Log Refactor

This commit is contained in:
2026-05-07 13:33:25 +02:00
parent 13a615dbd7
commit 7abcbf1a38
6 changed files with 706 additions and 53 deletions
+41
View File
@@ -28,6 +28,8 @@ type BuildResult struct {
Manifest string
AutogenManifestPaths []string
CreditsArtifactPaths []string
CreditsSummary CreditsRefreshSummary
HAKSummary HAKArchiveSummary
Resources int
HAKAssets int
TopPackageHAK string
@@ -35,6 +37,35 @@ type BuildResult struct {
TopPackageFiles int
}
type CreditsRefreshSummary struct {
ScannedDirs []string
TrackCount int
ArtifactPaths []string
GeneratedPaths []string
InventoryPath string
ChangedFiles int
Mappings []MusicFileMapping
}
type MusicFileMapping struct {
Source string
Output string
}
type HAKArchiveSummary struct {
Total int
Reused int
Written int
Actions []HAKArchiveAction
}
type HAKArchiveAction struct {
Name string
AssetCount int
Reused bool
OutputPath string
}
type BuildManifest struct {
ModuleHAKs []string `json:"module_haks"`
HAKs []BuildManifestHAK `json:"haks"`
@@ -220,6 +251,7 @@ func planOrBuildHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
result = BuildResult{HAKAssets: len(assetResources)}
result.CreditsArtifactPaths = append(result.CreditsArtifactPaths, musicAssets.Artifacts...)
result.CreditsSummary = musicAssets.Summary
if err := writeAutogenManifestOutputs(progress, autogenManifests); err != nil {
return BuildResult{}, err
}
@@ -298,6 +330,7 @@ func planOrBuildHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
progressf(progress, "Reusing unchanged generated HAKs where possible...")
result.HAKSummary.Total = len(chunks)
result.HAKPaths = make([]string, 0, len(chunks))
for index, chunk := range chunks {
hakPath := p.HAKArchivePath(chunk.Name)
@@ -307,8 +340,10 @@ func planOrBuildHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
return BuildResult{}, err
}
if reused {
result.HAKSummary.Reused++
progressf(progress, fmt.Sprintf("Reusing HAK %d/%d: %s (%d assets)", index+1, len(chunks), chunk.Name, len(chunk.Assets)))
} else {
result.HAKSummary.Written++
progressf(progress, fmt.Sprintf("Writing HAK %d/%d: %s (%d assets)", index+1, len(chunks), chunk.Name, len(chunk.Assets)))
hakOutput, err := os.Create(hakPath)
if err != nil {
@@ -323,6 +358,12 @@ func planOrBuildHAKs(p *project.Project, progress ProgressFunc, writeArchives bo
}
}
result.HAKSummary.Actions = append(result.HAKSummary.Actions, HAKArchiveAction{
Name: chunk.Name,
AssetCount: len(chunk.Assets),
Reused: reused,
OutputPath: hakPath,
})
result.HAKPaths = append(result.HAKPaths, hakPath)
}
progressf(progress, "Cleaning stale generated HAKs...")
+92 -25
View File
@@ -49,6 +49,7 @@ type preparedMusicAssets struct {
SkipSourceRel map[string]struct{}
Artifacts []string
TempRoots []string
Summary CreditsRefreshSummary
}
type musicMetadata struct {
@@ -111,11 +112,12 @@ func prepareMusicAssets(p *project.Project) (*preparedMusicAssets, error) {
SkipSourceRel: make(map[string]struct{}),
}
if len(dirSources) == 0 {
artifactPaths, err := writeCreditsArtifacts(p, nil)
writeResult, err := writeCreditsArtifacts(p, nil)
if err != nil {
return nil, err
}
result.Artifacts = artifactPaths
result.Artifacts = writeResult.Artifacts
result.Summary = writeResult.Summary
return result, nil
}
@@ -217,28 +219,30 @@ func prepareMusicAssets(p *project.Project) (*preparedMusicAssets, error) {
generatedByDir[dir] = entries
}
artifactPaths, err := writeCreditsArtifacts(p, generatedByDir)
writeResult, err := writeCreditsArtifacts(p, generatedByDir)
if err != nil {
return nil, err
}
result.Artifacts = artifactPaths
writeResult.Summary.ScannedDirs = append(writeResult.Summary.ScannedDirs, dirs...)
writeResult.Summary.TrackCount = len(result.Generated)
result.Artifacts = writeResult.Artifacts
result.Summary = writeResult.Summary
sort.Slice(result.Generated, func(i, j int) bool {
return compareResourceKeys(result.Generated[i].Resource, result.Generated[j].Resource) < 0
})
return result, nil
}
func writeCreditsArtifacts(p *project.Project, generatedByDir map[string][]creditsEntry) ([]string, error) {
creditsRoot := filepath.Join(p.Root, ".cache", "credits")
if err := os.RemoveAll(creditsRoot); err != nil {
return nil, fmt.Errorf("reset credits dir: %w", err)
}
if err := os.MkdirAll(creditsRoot, 0o755); err != nil {
return nil, fmt.Errorf("create credits dir: %w", err)
}
type creditsArtifactWriteResult struct {
Artifacts []string
Summary CreditsRefreshSummary
}
func writeCreditsArtifacts(p *project.Project, generatedByDir map[string][]creditsEntry) (creditsArtifactWriteResult, error) {
creditsRoot := filepath.Join(p.Root, ".cache", "credits")
sources := make([]creditsSource, 0)
artifacts := make([]string, 0)
desiredFiles := make(map[string][]byte)
summary := CreditsRefreshSummary{}
if generatedByDir != nil {
dirs := make([]string, 0, len(generatedByDir))
for dir := range generatedByDir {
@@ -257,13 +261,14 @@ func writeCreditsArtifacts(p *project.Project, generatedByDir map[string][]credi
return strings.ToLower(entries[i].OutputFile) < strings.ToLower(entries[j].OutputFile)
})
outputPath := filepath.Join(creditsRoot, filepath.FromSlash(dir), "CREDITS.md")
if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil {
return nil, fmt.Errorf("create generated credits dir: %w", err)
desiredFiles[outputPath] = []byte(renderCreditsMarkdown(entries))
summary.GeneratedPaths = append(summary.GeneratedPaths, outputPath)
for _, entry := range entries {
summary.Mappings = append(summary.Mappings, MusicFileMapping{
Source: entry.OriginalFile,
Output: entry.OutputFile,
})
}
if err := os.WriteFile(outputPath, []byte(renderCreditsMarkdown(entries)), 0o644); err != nil {
return nil, fmt.Errorf("write generated credits %s: %w", outputPath, err)
}
artifacts = append(artifacts, outputPath)
sources = append(sources, creditsSource{
Path: filepath.ToSlash(outputPath),
Kind: "generated_music",
@@ -298,21 +303,83 @@ func writeCreditsArtifacts(p *project.Project, generatedByDir map[string][]credi
return nil
})
if err != nil {
return nil, err
return creditsArtifactWriteResult{}, err
}
sort.Slice(sources, func(i, j int) bool { return sources[i].Path < sources[j].Path })
inventoryPath := filepath.Join(creditsRoot, "credits.json")
payload, err := json.MarshalIndent(creditsInventory{Sources: sources}, "", " ")
if err != nil {
return nil, fmt.Errorf("marshal credits inventory: %w", err)
return creditsArtifactWriteResult{}, fmt.Errorf("marshal credits inventory: %w", err)
}
payload = append(payload, '\n')
if err := os.WriteFile(inventoryPath, payload, 0o644); err != nil {
return nil, fmt.Errorf("write credits inventory: %w", err)
desiredFiles[inventoryPath] = payload
if err := os.MkdirAll(creditsRoot, 0o755); err != nil {
return creditsArtifactWriteResult{}, fmt.Errorf("create credits dir: %w", err)
}
artifacts = append(artifacts, inventoryPath)
return artifacts, nil
changedFiles, err := syncGeneratedCreditsArtifacts(creditsRoot, desiredFiles)
if err != nil {
return creditsArtifactWriteResult{}, err
}
artifacts := make([]string, 0, len(desiredFiles))
for path := range desiredFiles {
artifacts = append(artifacts, path)
}
sort.Strings(artifacts)
summary.ArtifactPaths = append(summary.ArtifactPaths, artifacts...)
summary.InventoryPath = inventoryPath
summary.ChangedFiles = changedFiles
return creditsArtifactWriteResult{
Artifacts: artifacts,
Summary: summary,
}, nil
}
func syncGeneratedCreditsArtifacts(root string, desiredFiles map[string][]byte) (int, error) {
changedFiles := 0
existingFiles := make(map[string]struct{})
if err := filepath.WalkDir(root, func(path string, d os.DirEntry, walkErr error) error {
if walkErr != nil {
if os.IsNotExist(walkErr) {
return nil
}
return walkErr
}
if d.IsDir() {
return nil
}
existingFiles[path] = struct{}{}
return nil
}); err != nil {
return 0, fmt.Errorf("scan credits dir: %w", err)
}
for path, content := range desiredFiles {
current, err := os.ReadFile(path)
if err != nil && !os.IsNotExist(err) {
return 0, fmt.Errorf("read credits artifact %s: %w", path, err)
}
if err == nil && string(current) == string(content) {
delete(existingFiles, path)
continue
}
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return 0, fmt.Errorf("create generated credits dir: %w", err)
}
if err := os.WriteFile(path, content, 0o644); err != nil {
return 0, fmt.Errorf("write credits artifact %s: %w", path, err)
}
changedFiles++
delete(existingFiles, path)
}
for path := range existingFiles {
if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return 0, fmt.Errorf("remove stale credits artifact %s: %w", path, err)
}
changedFiles++
}
return changedFiles, nil
}
func cleanupPreparedMusicAssets(prepared *preparedMusicAssets) error {
+11
View File
@@ -2685,6 +2685,17 @@ func TestBuildHAKsConvertsMusicSourcesAndWritesCreditsArtifacts(t *testing.T) {
if _, err := os.Stat(filepath.Join(root, ".cache", "music")); !os.IsNotExist(err) {
t.Fatalf("expected temporary music staging to be cleaned, got err=%v", err)
}
secondResult, err := BuildHAKs(p)
if err != nil {
t.Fatalf("build haks second pass: %v", err)
}
if secondResult.CreditsSummary.ChangedFiles != 0 {
t.Fatalf("expected second credits refresh to be unchanged, got %d changed files", secondResult.CreditsSummary.ChangedFiles)
}
if secondResult.CreditsSummary.TrackCount != 1 {
t.Fatalf("expected one tracked music conversion, got %d", secondResult.CreditsSummary.TrackCount)
}
}
func TestUniqueMusicNameHandlesShortStemCollisions(t *testing.T) {