v0.2.0: semaphore timeouts, error logging, dead code removal, parallel exports

Critical:
- Replace DISPATCH_TIME_FOREVER with 120s/30s timeouts in ObjC
- Log failed asset IDs and error messages in cmdExport/backupTree
- Show failed count in export summaries

Cleanup:
- Remove legacy Bridge methods (ExportAlbumPreviews, ExportAlbumOriginals, BackupAll)
- Remove legacy ObjC functions and C stub equivalents
- Remove photos.go delegates (package-level pass-throughs)
- Remove InterpretExportResult (only used by legacy methods)
- Clean up mockBridge fields (rename Fn2 -> Fn)
- Fix rc race condition in main_main.go (atomic.Int32)
- Remove unused variables (_ = grandTotal, _ = sig)

Design:
- Fix resolveAlbumID: ListAlbums first (cheap), then direct ID
- Unify Cloud type: Asset.Cloud string (was bool)
- Extract shared export logic into exportAssets/exportOne
- Add worker pool for parallel exports (3 workers when assets >= 4)
- Fix backupTree progress bar counter and directory prefix

Robustness:
- Add nil checks for stringWithUTF8String: in ObjC
- Log directory creation errors in ensure_directory (ObjC)

Quality:
- Add go vet and -race flag to Makefile test target
- Add ADR for performSelector cloudIdentifier decision
- Add sync comments between Go/ObjC sanitizePathComponent
- Add package-level doc comment
- Add tests: partial failure, skipped album, album-not-found message
This commit is contained in:
Ein Anderssono
2026-06-11 21:12:47 +02:00
parent b460c68641
commit 85eaa3ea37
14 changed files with 274 additions and 651 deletions
-23
View File
@@ -10,11 +10,8 @@ type Bridge interface {
ListAlbums() ([]Album, error)
ListAssets(albumID string) ([]Asset, int, error)
ListTree() ([]CollectionNode, error)
ExportAlbumPreviews(albumID, outputDir string, targetSize int) (int, error)
ExportAlbumOriginals(albumID, outputDir string) (int, error)
ExportPreview(assetID, outputDir string, targetSize, index int) (ExportResult, error)
ExportOriginal(assetID, outputDir string, index int) (ExportResult, error)
BackupAll(outputDir string, targetSize int, originals bool) (int, error)
Cancel()
}
@@ -62,23 +59,3 @@ func ParseExportResultJSON(jsonStr string) (ExportResult, error) {
}
return resp.ExportResult, nil
}
func InterpretExportResult(rc int) (int, error) {
switch rc {
case -1:
return 0, fmt.Errorf("invalid arguments or directory creation failed")
case -2:
return 0, fmt.Errorf("could not create output directory")
case -3:
return 0, fmt.Errorf("album not found")
case -4:
return 0, fmt.Errorf("all exports failed")
case -5:
return 0, fmt.Errorf("cancelled")
default:
if rc < 0 {
return 0, fmt.Errorf("unknown error (code %d)", rc)
}
return rc, nil
}
}