v0.8.7: add JSON sidecars
This commit is contained in:
@@ -4385,6 +4385,52 @@ func TestWriteXMPSidecar(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteJSONSidecar(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "photo.json")
|
||||
if got := jsonSidecarPath(filepath.Join(dir, "photo.jpg")); got != path {
|
||||
t.Fatalf("json sidecar path=%q", got)
|
||||
}
|
||||
if !sidecarEnabled("xmp,json", "json") || sidecarEnabled("xmp", "json") {
|
||||
t.Fatal("sidecarEnabled mismatch")
|
||||
}
|
||||
if err := writeJSONSidecar(path, xmpSidecarData{AssetID: "x1", ExportedFilename: "photo.jpg"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(data), `"AssetID": "x1"`) {
|
||||
t.Fatalf("unexpected json sidecar: %s", string(data))
|
||||
}
|
||||
badParent := filepath.Join(t.TempDir(), "file")
|
||||
if err := os.WriteFile(badParent, []byte("x"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := writeJSONSidecar(filepath.Join(badParent, "bad.json"), xmpSidecarData{}); err == nil {
|
||||
t.Fatal("expected mkdir error")
|
||||
}
|
||||
oldCreate := createTempFunc
|
||||
createTempFunc = func(string, string) (*os.File, error) { return nil, fmt.Errorf("create") }
|
||||
if err := writeJSONSidecar(path, xmpSidecarData{}); err == nil {
|
||||
t.Fatal("expected create temp error")
|
||||
}
|
||||
createTempFunc = oldCreate
|
||||
oldWrite := writeFileFunc
|
||||
writeFileFunc = func(string, []byte, os.FileMode) error { return fmt.Errorf("write") }
|
||||
if err := writeJSONSidecar(path, xmpSidecarData{}); err == nil {
|
||||
t.Fatal("expected write error")
|
||||
}
|
||||
writeFileFunc = oldWrite
|
||||
oldRename := renameFunc
|
||||
renameFunc = func(string, string) error { return fmt.Errorf("rename") }
|
||||
if err := writeJSONSidecar(path, xmpSidecarData{}); err == nil {
|
||||
t.Fatal("expected rename error")
|
||||
}
|
||||
renameFunc = oldRename
|
||||
}
|
||||
|
||||
func TestSidecarExportIntegration(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
date := "2024-01-02T03:04:05Z"
|
||||
@@ -4395,7 +4441,7 @@ func TestSidecarExportIntegration(t *testing.T) {
|
||||
}
|
||||
return photos.ExportResult{Filename: "photo.jpg", Size: 4, Cloud: "local"}, nil
|
||||
}
|
||||
exported, failed := exportAssets(b.assets, dir, 1024, 85, 3, false, 1, io.Discard, b, "Album", false, manifest.FormatJSONL, false, exportOptions{sidecar: "xmp"})
|
||||
exported, failed := exportAssets(b.assets, dir, 1024, 85, 3, false, 1, io.Discard, b, "Album", false, manifest.FormatJSONL, false, exportOptions{sidecar: "xmp,json"})
|
||||
if exported != 1 || failed != 0 {
|
||||
t.Fatalf("exported=%d failed=%d", exported, failed)
|
||||
}
|
||||
@@ -4412,6 +4458,13 @@ func TestSidecarExportIntegration(t *testing.T) {
|
||||
if _, err := os.Stat(filepath.Join(dir, "photo.jpg.xmp")); !os.IsNotExist(err) {
|
||||
t.Fatal("sidecar should use basename, not double extension")
|
||||
}
|
||||
jsonData, err := os.ReadFile(filepath.Join(dir, "photo.json"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(string(jsonData), `"AssetID": "x1"`) {
|
||||
t.Fatalf("json sidecar missing asset ID: %s", string(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSidecarReverseGeocodeCache(t *testing.T) {
|
||||
@@ -4585,6 +4638,14 @@ func TestSidecarConfigAndErrors(t *testing.T) {
|
||||
t.Fatalf("expected sidecar validation error, stderr=%q", stderr.String())
|
||||
}
|
||||
stderr.Reset()
|
||||
if opts, ok := parseExportOptions([]string{"--sidecar", "json"}, &stderr); !ok || opts.sidecar != "json" || stderr.Len() != 0 {
|
||||
t.Fatalf("expected json sidecar option, opts=%+v ok=%v stderr=%q", opts, ok, stderr.String())
|
||||
}
|
||||
stderr.Reset()
|
||||
if _, ok := parseExportOptions([]string{"--sidecar", "xmp,bad"}, &stderr); ok || !strings.Contains(stderr.String(), "--sidecar") {
|
||||
t.Fatalf("expected mixed sidecar validation error, stderr=%q", stderr.String())
|
||||
}
|
||||
stderr.Reset()
|
||||
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())
|
||||
}
|
||||
@@ -4603,10 +4664,14 @@ func TestSidecarConfigAndErrors(t *testing.T) {
|
||||
}
|
||||
oldRename := renameFunc
|
||||
renameFunc = func(string, string) error { return fmt.Errorf("sidecar rename") }
|
||||
exported, failed := exportAssets(b.assets, dir, 1024, 85, 3, false, 1, io.Discard, b, "", false, manifest.FormatJSONL, false, exportOptions{sidecar: "xmp"})
|
||||
exported, failed := exportAssets(b.assets, dir, 1024, 85, 3, false, 1, io.Discard, b, "", false, manifest.FormatJSONL, false, exportOptions{sidecar: "json"})
|
||||
if exported != 0 || failed != 1 {
|
||||
t.Fatalf("expected json sidecar failure, exported=%d failed=%d", exported, failed)
|
||||
}
|
||||
exported, failed = exportAssets(b.assets, dir, 1024, 85, 3, false, 1, io.Discard, b, "", false, manifest.FormatJSONL, false, exportOptions{sidecar: "xmp"})
|
||||
renameFunc = oldRename
|
||||
if exported != 0 || failed != 1 {
|
||||
t.Fatalf("expected sidecar failure, exported=%d failed=%d", exported, failed)
|
||||
t.Fatalf("expected xmp sidecar failure, exported=%d failed=%d", exported, failed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4725,7 +4790,7 @@ func TestMetadataOnlyExportErrors(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
b := &mockBridge{assets: []photos.Asset{{ID: "x1", Filename: "photo.jpg"}}}
|
||||
_, stderr, rc := runWith([]string{"export", "--album-id", "x", "--out", dir, "--metadata-only"}, b)
|
||||
if rc != exitErr || !strings.Contains(stderr, "--metadata-only requires --sidecar xmp") {
|
||||
if rc != exitErr || !strings.Contains(stderr, "--metadata-only requires --sidecar") {
|
||||
t.Fatalf("expected sidecar requirement rc=%d stderr=%q", rc, stderr)
|
||||
}
|
||||
_, stderr, rc = runWith([]string{"export", "--album-id", "x", "--out", dir, "--sidecar", "xmp", "--metadata-only", "--no-manifest"}, b)
|
||||
|
||||
Reference in New Issue
Block a user