v0.8.6: add XMP keyword and rating controls
pipeline / build (push) Has been cancelled
pipeline / test (push) Has been cancelled

This commit is contained in:
Ein Anderssono
2026-06-15 02:05:14 +02:00
parent 700d8ef05a
commit 5c40b1d3ba
7 changed files with 118 additions and 10 deletions
+52
View File
@@ -4588,6 +4588,14 @@ func TestSidecarConfigAndErrors(t *testing.T) {
if _, ok := parseExportOptions([]string{"--xmp-privacy", "bad"}, &stderr); ok || !strings.Contains(stderr.String(), "--xmp-privacy") {
t.Fatalf("expected xmp privacy validation error, stderr=%q", stderr.String())
}
stderr.Reset()
if _, ok := parseExportOptions([]string{"--xmp-keywords", "bad"}, &stderr); ok || !strings.Contains(stderr.String(), "--xmp-keywords") {
t.Fatalf("expected xmp keywords validation error, stderr=%q", stderr.String())
}
stderr.Reset()
if _, ok := parseExportOptions([]string{"--xmp-rating", "bad"}, &stderr); ok || !strings.Contains(stderr.String(), "--xmp-rating") {
t.Fatalf("expected xmp rating validation error, stderr=%q", stderr.String())
}
b := &mockBridge{assets: []photos.Asset{{ID: "x1", Filename: "photo.jpg"}}}
b.exportPreviewFn = func(assetID, out string, targetSize, quality, index int) (photos.ExportResult, error) {
@@ -4640,6 +4648,50 @@ func TestXMPSidecarPrivacy(t *testing.T) {
}
}
func TestXMPSidecarKeywordAndRatingOptions(t *testing.T) {
dir := t.TempDir()
asset := photos.Asset{ID: "x1", Filename: "photo.jpg", IsFavorite: true}
pa := pendingAsset{asset: asset, root: dir, path: filepath.Join(dir, "Trips", "Beach"), album: "Beach"}
if err := os.MkdirAll(pa.path, 0755); err != nil {
t.Fatal(err)
}
for _, tc := range []struct {
name string
keywords string
rating string
wantTrip bool
wantBeach bool
wantRate bool
}{
{name: "default", wantTrip: true, wantBeach: true, wantRate: true},
{name: "album", keywords: "album", wantTrip: false, wantBeach: true, wantRate: true},
{name: "none", keywords: "none", rating: "none", wantTrip: false, wantBeach: false, wantRate: false},
} {
filename := tc.name + ".jpg"
path := filepath.Join(pa.path, filename)
if err := os.WriteFile(path, []byte("data"), 0644); err != nil {
t.Fatal(err)
}
if err := writeSidecarIfNeeded(pa, photos.ExportResult{Filename: filename, Size: 4}, false, exportOptions{sidecar: "xmp", xmpKeywords: tc.keywords, xmpRating: tc.rating}, nil, &mockBridge{}); err != nil {
t.Fatalf("%s write sidecar: %v", tc.name, err)
}
data, err := os.ReadFile(sidecarPath(path))
if err != nil {
t.Fatal(err)
}
content := string(data)
if strings.Contains(content, "<rdf:li>Trips</rdf:li>") != tc.wantTrip {
t.Fatalf("%s Trips keyword mismatch in %s", tc.name, content)
}
if strings.Contains(content, "<rdf:li>Beach</rdf:li>") != tc.wantBeach {
t.Fatalf("%s Beach keyword mismatch in %s", tc.name, content)
}
if strings.Contains(content, "xmp:Rating=\"5\"") != tc.wantRate {
t.Fatalf("%s rating mismatch in %s", tc.name, content)
}
}
}
func TestMetadataOnlyExport(t *testing.T) {
dir := t.TempDir()
m := manifest.LoadJSONL(dir)