v0.8.1: improve XMP sidecars
This commit is contained in:
@@ -3835,6 +3835,13 @@ func TestReportDiffVerifyRetryFailedAndConfig(t *testing.T) {
|
||||
if rc != exitOK || !strings.Contains(out, "verified") || stderr != "" {
|
||||
t.Fatalf("verify rc=%d out=%q stderr=%q", rc, out, stderr)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "file.xmp"), renderXMP(xmpSidecarData{AssetID: "x1", ExportedFilename: "file.jpg"}), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, stderr, rc = runWith([]string{"verify", "--out", dir, "--sidecar"}, &mockBridge{})
|
||||
if rc != exitOK || !strings.Contains(out, "verified") || stderr != "" {
|
||||
t.Fatalf("verify sidecar rc=%d out=%q stderr=%q", rc, out, stderr)
|
||||
}
|
||||
|
||||
b := &mockBridge{albums: []photos.Album{{ID: "a1", Title: "Album"}}, assets: []photos.Asset{{ID: "x1", Filename: "file.jpg"}, {ID: "x2", Filename: "missing.jpg"}}}
|
||||
out, _, rc = runWith([]string{"diff", "--album-id", "Album", "--out", dir}, b)
|
||||
@@ -4133,6 +4140,8 @@ func TestMoreIntegrityBranches(t *testing.T) {
|
||||
}
|
||||
m.AddEntry(manifest.Entry{ID: "zero", Filename: "zero.jpg", Path: "zero.jpg", Size: 1, Cloud: "local", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "mismatch", Filename: "mismatch.jpg", Path: "mismatch.jpg", Size: 10, Cloud: "local", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "nosidecar", Filename: "nosidecar.jpg", Path: "nosidecar.jpg", Size: 4, Cloud: "local", Exported: time.Now().Unix()})
|
||||
m.AddEntry(manifest.Entry{ID: "zerosidecar", Filename: "zerosidecar.jpg", Path: "zerosidecar.jpg", Size: 4, Cloud: "local", Exported: time.Now().Unix()})
|
||||
m.Close()
|
||||
if err := os.WriteFile(filepath.Join(dir, "zero.jpg"), nil, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -4140,10 +4149,30 @@ func TestMoreIntegrityBranches(t *testing.T) {
|
||||
if err := os.WriteFile(filepath.Join(dir, "mismatch.jpg"), []byte("bad"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "nosidecar.jpg"), []byte("data"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "zerosidecar.jpg"), []byte("data"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, _, rc := runWith([]string{"verify", "--out", dir}, &mockBridge{})
|
||||
if rc != exitPartial || !strings.Contains(out, "zero-byte") || !strings.Contains(out, "size-mismatch") {
|
||||
t.Fatalf("verify rc=%d out=%q", rc, out)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "mismatch.xmp"), []byte("wrong asset"), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, _, rc = runWith([]string{"verify", "--out", dir, "--sidecar"}, &mockBridge{})
|
||||
if rc != exitPartial || !strings.Contains(out, "sidecar-missing") || !strings.Contains(out, "sidecar-asset-mismatch") {
|
||||
t.Fatalf("verify sidecar failures rc=%d out=%q", rc, out)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "zerosidecar.xmp"), nil, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, _, rc = runWith([]string{"verify", "--out", dir, "--sidecar"}, &mockBridge{})
|
||||
if rc != exitPartial || !strings.Contains(out, "sidecar-zero-byte") {
|
||||
t.Fatalf("verify zero sidecar rc=%d out=%q", rc, out)
|
||||
}
|
||||
_, stderr, rc := runWith([]string{"status"}, &mockBridge{})
|
||||
if rc != exitErr || !strings.Contains(stderr, "--out") {
|
||||
t.Fatalf("status missing out rc=%d stderr=%q", rc, stderr)
|
||||
@@ -4162,6 +4191,25 @@ func TestMoreIntegrityBranches(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifySidecarBranches(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
subdir := filepath.Join(dir, "sub")
|
||||
if err := os.Mkdir(subdir, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
xmp := filepath.Join(dir, "asset.xmp")
|
||||
if err := os.WriteFile(xmp, []byte(`photoscli:assetID="x1"`), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oldRead := readFileFunc
|
||||
readFileFunc = func(string) ([]byte, error) { return nil, fmt.Errorf("read") }
|
||||
var out bytes.Buffer
|
||||
if got := verifySidecar(&out, subdir, "x1", "../asset.jpg"); got != 1 || !strings.Contains(out.String(), "sidecar-unreadable") {
|
||||
t.Fatalf("expected unreadable with rel fallback, got=%d out=%q", got, out.String())
|
||||
}
|
||||
readFileFunc = oldRead
|
||||
}
|
||||
|
||||
func TestXMPSidecarHelpers(t *testing.T) {
|
||||
if got := sidecarPath("/tmp/IMG_0001.HEIC"); got != "/tmp/IMG_0001.xmp" {
|
||||
t.Fatalf("sidecar path = %q", got)
|
||||
@@ -4172,6 +4220,7 @@ func TestXMPSidecarHelpers(t *testing.T) {
|
||||
ExportedFilename: "IMG_0001.jpg",
|
||||
Album: "A&B",
|
||||
AlbumPath: "/tmp/A&B",
|
||||
Keywords: []string{"A&B", "Trips"},
|
||||
ManifestPath: "A&B/IMG_0001.jpg",
|
||||
MediaType: "image",
|
||||
MediaSubtypes: []string{"photoLive", `hdr&<>"`},
|
||||
@@ -4198,13 +4247,29 @@ func TestXMPSidecarHelpers(t *testing.T) {
|
||||
AdjustmentInfo: &photos.AdjustmentInfo{FormatIdentifier: "com.apple", FormatVersion: "1.0", BaseFilename: "base.heic"},
|
||||
Resources: []photos.AssetResource{{Type: "photo", Filename: `res&.heic`, UTI: "public.heic", Local: true, Size: 99}},
|
||||
}))
|
||||
for _, want := range []string{"photoscli:assetID=\"id&<>"\"", "photoscli:isFavorite=\"true\"", "photoscli:hasAdjustments=\"true\"", "xmp:ModifyDate=\"2024-02-01T00:00:00Z\"", "photoscli:latitude=\"59.32930000\"", "photoscli:addressCountry=\"Sweden\"", "photoscli:adjustmentFormatIdentifier=\"com.apple\"", "<photoscli:resources><rdf:Seq>", "photoscli:resourceFilename=\"res&.heic\"", "<photoscli:mediaSubtypes><rdf:Seq>"} {
|
||||
for _, want := range []string{"photoscli:xmpSchemaVersion=\"2\"", "photoscli:assetID=\"id&<>"\"", "photoscli:isFavorite=\"true\"", "xmp:Rating=\"5\"", "photoscli:hasAdjustments=\"true\"", "xmp:ModifyDate=\"2024-02-01T00:00:00Z\"", "photoshop:DateCreated=\"2024-01-01T00:00:00Z\"", "exif:GPSLatitude=\"59.32930000\"", "photoscli:latitude=\"59.32930000\"", "photoscli:addressCountry=\"Sweden\"", "photoscli:adjustmentFormatIdentifier=\"com.apple\"", "<dc:subject><rdf:Seq>", "<rdf:li>A&B</rdf:li>", "<photoscli:resources><rdf:Seq>", "photoscli:resourceFilename=\"res&.heic\"", "<photoscli:mediaSubtypes><rdf:Seq>"} {
|
||||
if !strings.Contains(xmp, want) {
|
||||
t.Fatalf("XMP missing %q in %s", want, xmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeywordsFromAlbumPath(t *testing.T) {
|
||||
got := keywordsFromAlbumPath("Album", "Trips/Album/2024")
|
||||
want := []string{"Album", "Trips", "2024"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("keywords len=%d want=%d: %#v", len(got), len(want), got)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("keywords[%d]=%q want %q in %#v", i, got[i], want[i], got)
|
||||
}
|
||||
}
|
||||
if got := keywordsFromAlbumPath("", "."); len(got) != 0 {
|
||||
t.Fatalf("expected no dot keyword, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteXMPSidecar(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
path := filepath.Join(dir, "photo.xmp")
|
||||
|
||||
Reference in New Issue
Block a user