From 009c71e6bb0c134525059322cae20a36f7905441 Mon Sep 17 00:00:00 2001 From: Ein Anderssono Date: Thu, 11 Jun 2026 21:37:11 +0200 Subject: [PATCH] v0.2.3: fix export write failures and Ctrl+C cancellation - Add ensure_directory calls in both export functions (preview + original) - Include NSError.localizedDescription in write failed messages - Make semaphore_wait_with_timeout poll photos_cancelled every ~1s - Add status messages: auth, loading tree, per-album progress - Fix parallel export: slot-based progress shows results in order --- Makefile | 2 +- bridge/photokit_bridge.m | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index caf44cf..0069f45 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BINARY := ./bin/photoscli MODULE := gitea.k3s.k0.nu/tools/photocli -VERSION := 0.2.1 +VERSION := 0.2.3 BRIDGE_DIR := bridge LDFLAGS := -X main.version=$(VERSION) OBJ := $(BRIDGE_DIR)/photokit_bridge.o diff --git a/bridge/photokit_bridge.m b/bridge/photokit_bridge.m index 7a66ce2..3ed7b76 100644 --- a/bridge/photokit_bridge.m +++ b/bridge/photokit_bridge.m @@ -274,6 +274,10 @@ char *photos_export_preview_json(const char *asset_id, const char *output_dir, i NSString *nsOutputDir = [NSString stringWithUTF8String:output_dir]; if (!nsAssetId || !nsOutputDir) return json_from_object(make_error_dict(@"invalid UTF-8 in arguments")); + if (!ensure_directory(nsOutputDir)) { + return json_from_object(make_error_dict(@"failed to create output directory")); + } + PHFetchResult *fetch = [PHAsset fetchAssetsWithLocalIdentifiers:@[nsAssetId] options:nil]; if (fetch.count == 0) return json_from_object(make_error_dict(@"asset not found")); @@ -322,7 +326,8 @@ char *photos_export_preview_json(const char *asset_id, const char *output_dir, i NSError *writeErr = nil; if (![imageData writeToFile:filepath options:NSDataWritingAtomic error:&writeErr]) { - return json_from_object(@{@"error": @"write failed", @"cloud": asset_cloud_status_string(asset)}); + NSString *msg = writeErr ? writeErr.localizedDescription : @"unknown write error"; + return json_from_object(@{@"error": [NSString stringWithFormat:@"write failed: %@", msg], @"cloud": asset_cloud_status_string(asset)}); } NSNumber *fileSize = nil; @@ -345,6 +350,10 @@ char *photos_export_original_json(const char *asset_id, const char *output_dir, NSString *nsOutputDir = [NSString stringWithUTF8String:output_dir]; if (!nsAssetId || !nsOutputDir) return json_from_object(make_error_dict(@"invalid UTF-8 in arguments")); + if (!ensure_directory(nsOutputDir)) { + return json_from_object(make_error_dict(@"failed to create output directory")); + } + PHFetchResult *fetch = [PHAsset fetchAssetsWithLocalIdentifiers:@[nsAssetId] options:nil]; if (fetch.count == 0) return json_from_object(make_error_dict(@"asset not found")); @@ -382,7 +391,7 @@ char *photos_export_original_json(const char *asset_id, const char *output_dir, } if (writeErr) { - return json_from_object(@{@"error": @"write failed", @"cloud": asset_cloud_status_string(asset)}); + return json_from_object(@{@"error": [NSString stringWithFormat:@"write failed: %@", writeErr.localizedDescription], @"cloud": asset_cloud_status_string(asset)}); } NSString *writtenFilename = [filepath lastPathComponent];