Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb5d15061c |
@@ -661,11 +661,17 @@ func collectAssetResources(p *project.Project, requireContent bool, allowed map[
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
assetsRelPath, err := filepath.Rel(p.Root, p.AssetsDir())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve assets dir relative path: %w", err)
|
||||
// A module-only project (consumes prebuilt HAKs, has no paths.assets) has no
|
||||
// asset files to collect — AssetFiles is empty and AssetsDir() is "". Skip the
|
||||
// relative-path resolve, which would otherwise fail with `Rel: can't make ""`.
|
||||
assetsRelPath := ""
|
||||
if p.AssetsDir() != "" {
|
||||
assetsRelPath, err = filepath.Rel(p.Root, p.AssetsDir())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve assets dir relative path: %w", err)
|
||||
}
|
||||
assetsRelPath = filepath.ToSlash(assetsRelPath)
|
||||
}
|
||||
assetsRelPath = filepath.ToSlash(assetsRelPath)
|
||||
|
||||
for _, rel := range p.Inventory.AssetFiles {
|
||||
if musicAssets != nil {
|
||||
|
||||
+30
-25
@@ -435,33 +435,38 @@ func writeCreditsArtifacts(p *project.Project, generated []musicCreditGroup) (cr
|
||||
}
|
||||
}
|
||||
|
||||
err := filepath.WalkDir(p.AssetsDir(), func(path string, d os.DirEntry, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
return walkErr
|
||||
}
|
||||
if d.IsDir() {
|
||||
// Authored credits.md files live under the assets tree. A project with no
|
||||
// configured assets dir (e.g. a module that consumes prebuilt HAKs) has none
|
||||
// to collect — walking "" would fail with `lstat : no such file or directory`.
|
||||
if assetsDir := p.AssetsDir(); assetsDir != "" {
|
||||
err := filepath.WalkDir(assetsDir, func(path string, d os.DirEntry, walkErr error) error {
|
||||
if walkErr != nil {
|
||||
return walkErr
|
||||
}
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if strings.ToLower(d.Name()) != "credits.md" {
|
||||
return nil
|
||||
}
|
||||
entries, err := music.ParseCreditsMarkdown(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse credits %s: %w", path, err)
|
||||
}
|
||||
rel, err := filepath.Rel(p.Root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sources = append(sources, music.CreditsSource{
|
||||
Path: filepath.ToSlash(rel),
|
||||
Kind: "authored",
|
||||
Entries: entries,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
if strings.ToLower(d.Name()) != "credits.md" {
|
||||
return nil
|
||||
}
|
||||
entries, err := music.ParseCreditsMarkdown(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parse credits %s: %w", path, err)
|
||||
}
|
||||
rel, err := filepath.Rel(p.Root, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sources = append(sources, music.CreditsSource{
|
||||
Path: filepath.ToSlash(rel),
|
||||
Kind: "authored",
|
||||
Entries: entries,
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return creditsArtifactWriteResult{}, err
|
||||
if err != nil {
|
||||
return creditsArtifactWriteResult{}, err
|
||||
}
|
||||
}
|
||||
|
||||
sort.Slice(sources, func(i, j int) bool { return sources[i].Path < sources[j].Path })
|
||||
|
||||
@@ -4084,3 +4084,62 @@ haks:
|
||||
t.Fatalf("plan-only should not stage music, stat err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// A module-only project (consumes prebuilt HAKs, no paths.assets) must build via
|
||||
// the full `crucible module build` (pipeline.Build) without an assets tree. The
|
||||
// HAK + music stages used to crash on the unset assets dir
|
||||
// (`lstat : no such file or directory` / `Rel: can't make "" relative`).
|
||||
func TestBuildModuleOnlyProjectWithoutAssetsDir(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mustMkdir(t, filepath.Join(root, "src", "module"))
|
||||
mustMkdir(t, filepath.Join(root, "build"))
|
||||
|
||||
mustWriteFile(t, filepath.Join(root, "nwn-tool.yaml"), `
|
||||
module:
|
||||
name: Test Module
|
||||
resref: testmod
|
||||
paths:
|
||||
source: src
|
||||
build: build
|
||||
`)
|
||||
mustWriteFile(t, filepath.Join(root, "src", "module", "module.ifo.json"), `{
|
||||
"file_type": "IFO ",
|
||||
"file_version": "V3.2",
|
||||
"root": {
|
||||
"struct_type": 0,
|
||||
"fields": [
|
||||
{
|
||||
"label": "Mod_Name",
|
||||
"type": "CExoString",
|
||||
"value": "Test Module"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
p, err := project.Load(root)
|
||||
if err != nil {
|
||||
t.Fatalf("load project: %v", err)
|
||||
}
|
||||
if err := p.ValidateLayout(); err != nil {
|
||||
t.Fatalf("validate layout: %v", err)
|
||||
}
|
||||
if err := p.Scan(); err != nil {
|
||||
t.Fatalf("scan: %v", err)
|
||||
}
|
||||
if p.AssetsDir() != "" {
|
||||
t.Fatalf("test precondition: expected unset assets dir, got %q", p.AssetsDir())
|
||||
}
|
||||
|
||||
result, err := Build(p)
|
||||
if err != nil {
|
||||
t.Fatalf("full build of module-only project: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(result.ModulePath); err != nil {
|
||||
t.Fatalf("expected built .mod at %s: %v", result.ModulePath, err)
|
||||
}
|
||||
if result.HAKAssets != 0 {
|
||||
t.Fatalf("module-only project has no assets, expected 0 HAK assets, got %d", result.HAKAssets)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user