Packaging Fix
This commit is contained in:
+5
-1
@@ -565,7 +565,11 @@ func runBuildTopPackage(ctx context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := topdata.BuildAndPackageWithOptions(p, opts, func(message string) {
|
if opts.BuildWiki {
|
||||||
|
return fmt.Errorf("--wiki is not supported with build-top-package; use build-topdata when wiki generation is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := topdata.BuildPackage(p, func(message string) {
|
||||||
fmt.Fprintf(ctx.stdout, "[build-top-package] %s\n", message)
|
fmt.Fprintf(ctx.stdout, "[build-top-package] %s\n", message)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRunBuildTopPackageUsesCachedCompiledOutputs(t *testing.T) {
|
||||||
|
root := t.TempDir()
|
||||||
|
mkdirAll(t, filepath.Join(root, "build"))
|
||||||
|
mkdirAll(t, filepath.Join(root, ".cache", "2da"))
|
||||||
|
mkdirAll(t, filepath.Join(root, "topdata", "assets", "gui"))
|
||||||
|
mkdirAll(t, filepath.Join(root, "topdata", "data", "repadjust"))
|
||||||
|
|
||||||
|
writeFile(t, filepath.Join(root, "nwn-tool.json"), `{
|
||||||
|
"module": {
|
||||||
|
"name": "Test Module",
|
||||||
|
"resref": "test_module"
|
||||||
|
},
|
||||||
|
"topdata": {
|
||||||
|
"source": "topdata",
|
||||||
|
"build": ".cache",
|
||||||
|
"package_hak": "sow_top.hak",
|
||||||
|
"package_tlk": "sow_tlk.tlk"
|
||||||
|
}
|
||||||
|
}`+"\n")
|
||||||
|
writeFile(t, filepath.Join(root, ".cache", "2da", "repadjust.2da"), "2DA V2.0\n\n Label\n0 TEST_LABEL\n")
|
||||||
|
writeFile(t, filepath.Join(root, "build", "sow_tlk.tlk"), "compiled tlk")
|
||||||
|
writeFile(t, filepath.Join(root, "topdata", "assets", "gui", "testicon.png"), "icon-data")
|
||||||
|
writeFile(t, filepath.Join(root, "topdata", "data", "repadjust", "base.json"), "{ this is intentionally invalid json }\n")
|
||||||
|
|
||||||
|
sourceTime := time.Now().Add(-2 * time.Hour)
|
||||||
|
outputTime := time.Now().Add(-1 * time.Hour)
|
||||||
|
setFileTime(t, filepath.Join(root, "topdata", "assets", "gui", "testicon.png"), sourceTime)
|
||||||
|
setFileTime(t, filepath.Join(root, "topdata", "data", "repadjust", "base.json"), sourceTime)
|
||||||
|
setFileTime(t, filepath.Join(root, ".cache", "2da", "repadjust.2da"), outputTime)
|
||||||
|
setFileTime(t, filepath.Join(root, "build", "sow_tlk.tlk"), outputTime)
|
||||||
|
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
ctx := context{
|
||||||
|
stdout: &stdout,
|
||||||
|
stderr: &bytes.Buffer{},
|
||||||
|
cwd: root,
|
||||||
|
args: []string{"build-top-package"},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := runBuildTopPackage(ctx); err != nil {
|
||||||
|
t.Fatalf("runBuildTopPackage failed: %v", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stdout.String(), "top package hak:") {
|
||||||
|
t.Fatalf("expected build-top-package output, got %q", stdout.String())
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(filepath.Join(root, "build", "sow_top.hak")); err != nil {
|
||||||
|
t.Fatalf("expected packaged hak output: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mkdirAll(t *testing.T, path string) {
|
||||||
|
t.Helper()
|
||||||
|
if err := os.MkdirAll(path, 0o755); err != nil {
|
||||||
|
t.Fatalf("mkdir %s: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFile(t *testing.T, path, content string) {
|
||||||
|
t.Helper()
|
||||||
|
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||||
|
t.Fatalf("write %s: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFileTime(t *testing.T, path string, modTime time.Time) {
|
||||||
|
t.Helper()
|
||||||
|
if err := os.Chtimes(path, modTime, modTime); err != nil {
|
||||||
|
t.Fatalf("set file time %s: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -165,6 +165,7 @@ func packageBuiltTopData(p *project.Project, nativeResult BuildResult, progress
|
|||||||
|
|
||||||
func collectTopPackageResources(p *project.Project, compiled2DADir string) ([]erf.Resource, int, error) {
|
func collectTopPackageResources(p *project.Project, compiled2DADir string) ([]erf.Resource, int, error) {
|
||||||
resourceByKey := map[string]erf.Resource{}
|
resourceByKey := map[string]erf.Resource{}
|
||||||
|
resourceSourceByKey := map[string]string{}
|
||||||
|
|
||||||
entries, err := os.ReadDir(compiled2DADir)
|
entries, err := os.ReadDir(compiled2DADir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -179,7 +180,9 @@ func collectTopPackageResources(p *project.Project, compiled2DADir string) ([]er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
resourceByKey[topPackageResourceKey(resource)] = resource
|
key := topPackageResourceKey(resource)
|
||||||
|
resourceByKey[key] = resource
|
||||||
|
resourceSourceByKey[key] = path
|
||||||
}
|
}
|
||||||
|
|
||||||
assetFiles := 0
|
assetFiles := 0
|
||||||
@@ -210,10 +213,11 @@ func collectTopPackageResources(p *project.Project, compiled2DADir string) ([]er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
key := topPackageResourceKey(resource)
|
key := topPackageResourceKey(resource)
|
||||||
if _, ok := resourceByKey[key]; ok {
|
if existing, ok := resourceSourceByKey[key]; ok {
|
||||||
return fmt.Errorf("topdata asset %s collides with generated top package resource %s", path, key)
|
return fmt.Errorf("topdata asset %s collides with %s for top package resource %s", path, existing, key)
|
||||||
}
|
}
|
||||||
resourceByKey[key] = resource
|
resourceByKey[key] = resource
|
||||||
|
resourceSourceByKey[key] = path
|
||||||
assetFiles++
|
assetFiles++
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package topdata
|
package topdata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
@@ -9670,7 +9671,8 @@ func TestBuildAndPackageIncludesCompiled2DAAndTopAssets(t *testing.T) {
|
|||||||
"columns": ["Label"],
|
"columns": ["Label"],
|
||||||
"rows": [{"id": 0, "Label": "TEST_LABEL"}]
|
"rows": [{"id": 0, "Label": "TEST_LABEL"}]
|
||||||
}`+"\n")
|
}`+"\n")
|
||||||
writeFile(t, filepath.Join(root, "topdata", "assets", "gui", "testicon.png"), "icon-data")
|
pngPayload := bytes.Repeat([]byte("png-payload-"), 4096)
|
||||||
|
writeBytes(t, filepath.Join(root, "topdata", "assets", "gui", "testicon.png"), pngPayload)
|
||||||
|
|
||||||
proj := testProject(root)
|
proj := testProject(root)
|
||||||
proj.Config.TopData.ReferenceBuilder = ""
|
proj.Config.TopData.ReferenceBuilder = ""
|
||||||
@@ -9708,6 +9710,9 @@ func TestBuildAndPackageIncludesCompiled2DAAndTopAssets(t *testing.T) {
|
|||||||
found2DA = true
|
found2DA = true
|
||||||
}
|
}
|
||||||
if key == "testicon.png" {
|
if key == "testicon.png" {
|
||||||
|
if !bytes.Equal(resource.Data, pngPayload) {
|
||||||
|
t.Fatalf("expected testicon.png payload to be preserved, got %d bytes", len(resource.Data))
|
||||||
|
}
|
||||||
foundAsset = true
|
foundAsset = true
|
||||||
}
|
}
|
||||||
if ext == "tlk" {
|
if ext == "tlk" {
|
||||||
@@ -9728,6 +9733,22 @@ func TestBuildAndPackageIncludesCompiled2DAAndTopAssets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCollectTopPackageResourcesRejectsDuplicateTopAssetKeys(t *testing.T) {
|
||||||
|
root := testProjectRoot(t)
|
||||||
|
mkdirAll(t, filepath.Join(root, ".cache", "2da"))
|
||||||
|
mkdirAll(t, filepath.Join(root, "topdata", "assets", "gui", "icons"))
|
||||||
|
mkdirAll(t, filepath.Join(root, "topdata", "assets", "gui", "portraits"))
|
||||||
|
writeFile(t, filepath.Join(root, "topdata", "base_dialog.json"), "{}\n")
|
||||||
|
writeFile(t, filepath.Join(root, ".cache", "2da", "repadjust.2da"), "2DA V2.0\n\n Label\n0 TEST_LABEL\n")
|
||||||
|
writeFile(t, filepath.Join(root, "topdata", "assets", "gui", "icons", "duplicate.png"), "icon-a")
|
||||||
|
writeFile(t, filepath.Join(root, "topdata", "assets", "gui", "portraits", "duplicate.png"), "icon-b")
|
||||||
|
|
||||||
|
proj := testProject(root)
|
||||||
|
if _, _, err := collectTopPackageResources(proj, filepath.Join(root, ".cache", "2da")); err == nil || !strings.Contains(err.Error(), "collides with") {
|
||||||
|
t.Fatalf("expected duplicate topdata asset collision, got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildAndPackageHonorsConfiguredTopPackageOutputNames(t *testing.T) {
|
func TestBuildAndPackageHonorsConfiguredTopPackageOutputNames(t *testing.T) {
|
||||||
root := testProjectRoot(t)
|
root := testProjectRoot(t)
|
||||||
mkdirAll(t, filepath.Join(root, "topdata", "data", "repadjust"))
|
mkdirAll(t, filepath.Join(root, "topdata", "data", "repadjust"))
|
||||||
@@ -10214,3 +10235,10 @@ func writeFile(t *testing.T, path, content string) {
|
|||||||
t.Fatalf("write %s: %v", path, err)
|
t.Fatalf("write %s: %v", path, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func writeBytes(t *testing.T, path string, content []byte) {
|
||||||
|
t.Helper()
|
||||||
|
if err := os.WriteFile(path, content, 0o755); err != nil {
|
||||||
|
t.Fatalf("write %s: %v", path, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user