v0.2.4: stop export loop on Ctrl+C instead of flooding failures
- Add IsCancelled() to Bridge interface - Check bridge.IsCancelled() before each export in serial/parallel/backupTree - Parallel workers mark remaining slots as 'cancelled' instead of exporting - Add photos_request_is_cancelled to ObjC and C stub
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
BINARY := ./bin/photoscli
|
||||
MODULE := gitea.k3s.k0.nu/tools/photocli
|
||||
VERSION := 0.2.3
|
||||
VERSION := 0.2.4
|
||||
BRIDGE_DIR := bridge
|
||||
LDFLAGS := -X main.version=$(VERSION)
|
||||
OBJ := $(BRIDGE_DIR)/photokit_bridge.o
|
||||
|
||||
@@ -28,6 +28,8 @@ char *photos_list_tree_json(void);
|
||||
|
||||
void photos_request_cancel(void);
|
||||
|
||||
int photos_request_is_cancelled(void);
|
||||
|
||||
void photos_free_string(char *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -415,3 +415,7 @@ void photos_free_string(char *value) {
|
||||
void photos_request_cancel(void) {
|
||||
photos_cancelled = 1;
|
||||
}
|
||||
|
||||
int photos_request_is_cancelled(void) {
|
||||
return photos_cancelled;
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@ void photos_request_cancel(void) {
|
||||
stub_cancelled = 1;
|
||||
}
|
||||
|
||||
int photos_request_is_cancelled(void) {
|
||||
return stub_cancelled;
|
||||
}
|
||||
|
||||
void photos_test_set_export_preview_json(const char *json) {
|
||||
stub_export_preview_json = json;
|
||||
}
|
||||
|
||||
@@ -263,6 +263,9 @@ func backupTree(nodes []photos.CollectionNode, outDir string, targetSize int, or
|
||||
total := 0
|
||||
failed := 0
|
||||
for _, node := range nodes {
|
||||
if bridge.IsCancelled() {
|
||||
break
|
||||
}
|
||||
path := outDir + "/" + sanitizePathComponent(node.Name)
|
||||
if node.Kind == "folder" {
|
||||
n, t, f, err := backupTree(node.Children, path, targetSize, originals, stderr, bridge)
|
||||
@@ -306,6 +309,9 @@ func exportAssetsSerial(assets []photos.Asset, outDir string, targetSize int, or
|
||||
exported := 0
|
||||
failed := 0
|
||||
for i, a := range assets {
|
||||
if bridge.IsCancelled() {
|
||||
break
|
||||
}
|
||||
result, exportErr := exportOne(bridge, a, outDir, targetSize, originals, i)
|
||||
progressBar(stderr, exported+failed+1, total, dirPrefix+result.Filename, result.Size, result.Cloud)
|
||||
if exportErr != nil {
|
||||
@@ -337,6 +343,11 @@ func exportAssetsParallel(assets []photos.Asset, outDir string, targetSize int,
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for i := range jobs {
|
||||
if bridge.IsCancelled() {
|
||||
slots[i].err = fmt.Errorf("cancelled")
|
||||
close(slots[i].done)
|
||||
continue
|
||||
}
|
||||
result, exportErr := exportOne(bridge, assets[i], outDir, targetSize, originals, i)
|
||||
slots[i].result = result
|
||||
slots[i].err = exportErr
|
||||
|
||||
@@ -50,6 +50,7 @@ func (m *mockBridge) ExportOriginal(assetID, out string, index int) (photos.Expo
|
||||
return photos.ExportResult{Filename: "test.jpg", Size: 2048, Cloud: "cloud"}, nil
|
||||
}
|
||||
func (m *mockBridge) Cancel() { m.cancelled = true }
|
||||
func (m *mockBridge) IsCancelled() bool { return m.cancelled }
|
||||
|
||||
func runWith(args []string, b photos.Bridge) (string, string, int) {
|
||||
var out, err bytes.Buffer
|
||||
|
||||
@@ -13,6 +13,7 @@ type Bridge interface {
|
||||
ExportPreview(assetID, outputDir string, targetSize, index int) (ExportResult, error)
|
||||
ExportOriginal(assetID, outputDir string, index int) (ExportResult, error)
|
||||
Cancel()
|
||||
IsCancelled() bool
|
||||
}
|
||||
|
||||
func ParseAlbumsJSON(jsonStr string) ([]Album, error) {
|
||||
|
||||
@@ -58,6 +58,10 @@ func (*CgoBridge) Cancel() {
|
||||
C.photos_request_cancel()
|
||||
}
|
||||
|
||||
func (*CgoBridge) IsCancelled() bool {
|
||||
return C.photos_request_is_cancelled() != 0
|
||||
}
|
||||
|
||||
func (*CgoBridge) ExportPreview(assetID, outputDir string, targetSize, index int) (ExportResult, error) {
|
||||
cid := C.CString(assetID)
|
||||
defer C.free(unsafe.Pointer(cid))
|
||||
|
||||
@@ -78,6 +78,10 @@ func (*CgoBridge) Cancel() {
|
||||
C.photos_request_cancel()
|
||||
}
|
||||
|
||||
func (*CgoBridge) IsCancelled() bool {
|
||||
return C.photos_request_is_cancelled() != 0
|
||||
}
|
||||
|
||||
func (*CgoBridge) ExportPreview(assetID, outputDir string, targetSize, index int) (ExportResult, error) {
|
||||
cid := C.CString(assetID)
|
||||
defer C.free(unsafe.Pointer(cid))
|
||||
|
||||
Reference in New Issue
Block a user