From ca3a3e4a2af69ded62a7ccb9f92d342ea0bd2af9 Mon Sep 17 00:00:00 2001 From: Ein Anderssono Date: Thu, 11 Jun 2026 20:29:06 +0200 Subject: [PATCH] rename applephotos to photoscli, update module path to gitea.k3s.k0.nu/tools/photocli --- Makefile | 6 +-- README.md | 53 +++++++++++---------- cmd/{applephotos => photoscli}/main.go | 14 +++--- cmd/{applephotos => photoscli}/main_main.go | 2 +- cmd/{applephotos => photoscli}/main_test.go | 6 +-- go.mod | 2 +- 6 files changed, 43 insertions(+), 40 deletions(-) rename cmd/{applephotos => photoscli}/main.go (96%) rename cmd/{applephotos => photoscli}/main_main.go (90%) rename cmd/{applephotos => photoscli}/main_test.go (99%) diff --git a/Makefile b/Makefile index 0fa127d..bef5b21 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -BINARY := ./bin/applephotos -MODULE := github.com/einand/applephotos +BINARY := ./bin/photoscli +MODULE := gitea.k3s.k0.nu/tools/photocli BRIDGE_DIR := bridge OBJ := $(BRIDGE_DIR)/photokit_bridge.o LIB := $(BRIDGE_DIR)/libphotokit_bridge.a @@ -21,7 +21,7 @@ $(STUB_OBJ): $(BRIDGE_DIR)/photokit_bridge_stub.c $(BRIDGE_DIR)/photokit_bridge. cc -c -o $@ $< build: $(LIB) - go build -o $(BINARY) $(MODULE)/cmd/applephotos + go build -o $(BINARY) $(MODULE)/cmd/photoscli test: $(STUB_LIB) go test -tags=test -coverprofile=coverage.out -covermode=atomic -coverpkg=./... ./... diff --git a/README.md b/README.md index 2f5822d..d95ab04 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,26 @@ -# applephotos +# photoscli -`applephotos` is a small macOS-only CLI written in Go that reads data from Apple Photos through a PhotoKit bridge. +`photoscli` is a small macOS-only CLI written in Go that reads data from Apple Photos through a PhotoKit bridge. It supports five tasks: - listing albums -- listing asset IDs and filenames in an album +- listing asset IDs, filenames, and cloud status in an album - showing the folder and album tree - backing up all albums into the Photos folder tree - exporting resized JPEG previews or original files from an album ## What The Code Does -The executable lives in `cmd/applephotos` and calls into `internal/photos`, which wraps an Objective-C bridge in `bridge/`. +The executable lives in `cmd/photoscli` and calls into `internal/photos`, which wraps an Objective-C bridge in `bridge/`. Current behavior: - `albums` prints one line per album as `\t` -- `photos --album-id <id-or-title>` prints one asset local identifier and filename per line; accepts either a PhotoKit local identifier or an album title +- `photos --album-id <id-or-title>` prints one asset per line as `<id>\t<filename>\t<cloud>`; accepts either a PhotoKit local identifier or an album title - `tree` prints the human-readable folder and album hierarchy from Apple Photos -- `backup-all --out <dir> [--size <px>] [--originals]` exports every album into a matching folder tree under the output directory -- `export --album-id <id-or-title> --out <dir> [--size <px>] [--originals]` exports either JPEG previews or original files and reports the number exported on stderr; `--album-id` accepts either a PhotoKit local identifier or an album title +- `backup-all --out <dir> [--size <px>] [--originals]` exports every album into a matching folder tree, showing per-asset progress with filename, size, and cloud status +- `export --album-id <id-or-title> --out <dir> [--size <px>] [--originals]` exports either JPEG previews or original files with a progress bar showing filename, size, and cloud status; `--album-id` accepts either a PhotoKit local identifier or an album title The bridge uses PhotoKit to: @@ -48,7 +48,7 @@ make build Output binary: ```bash -./bin/applephotos +./bin/photoscli ``` ## Test @@ -62,16 +62,16 @@ Tests run against a stub bridge, so they do not require real Photos access. ## Usage ```bash -./bin/applephotos albums -./bin/applephotos photos --album-id "<album-local-identifier>" -./bin/applephotos photos --album-id "Vacation" -./bin/applephotos tree -./bin/applephotos backup-all --out ./backup -./bin/applephotos backup-all --out ./backup --originals -./bin/applephotos export --album-id "<album-local-identifier>" --out ./export -./bin/applephotos export --album-id "Vacation" --out ./export -./bin/applephotos export --album-id "<album-local-identifier>" --out ./export --size 2048 -./bin/applephotos export --album-id "<album-local-identifier>" --out ./export --originals +./bin/photoscli albums +./bin/photoscli photos --album-id "<album-local-identifier>" +./bin/photoscli photos --album-id "Vacation" +./bin/photoscli tree +./bin/photoscli backup-all --out ./backup +./bin/photoscli backup-all --out ./backup --originals +./bin/photoscli export --album-id "<album-local-identifier>" --out ./export +./bin/photoscli export --album-id "Vacation" --out ./export +./bin/photoscli export --album-id "<album-local-identifier>" --out ./export --size 2048 +./bin/photoscli export --album-id "<album-local-identifier>" --out ./export --originals ``` ### Commands @@ -93,13 +93,13 @@ Example output: - Requests Photos access - If the value looks like a PhotoKit local identifier, uses it directly - Otherwise searches album titles for a match and resolves the identifier -- Lists asset local identifiers for the given album +- Lists asset local identifiers and cloud status for the given album Example output: ```text -1F2A.../L0/001 IMG_0001.JPG -9C4D.../L0/001 IMG_0002.JPG +1F2A.../L0/001 IMG_0001.JPG local +9C4D.../L0/001 IMG_0002.JPG cloud ``` `backup-all --out <dir> [--size <px>] [--originals]` @@ -107,8 +107,8 @@ Example output: - Requests Photos access - Walks the Photos folder and album hierarchy - Creates directories as `out/folder/album/files` -- Exports previews by default -- Exports original files when `--originals` is present +- Exports previews by default, originals when `--originals` is present +- Shows per-asset progress bar with filename, file size, and cloud/local status - Uses `--size` only for preview export Example layout: @@ -128,6 +128,8 @@ backup/ - Requests Photos access - Resolves `--album-id` by local identifier first, then by album title if not found - Creates the output directory if needed +- Exports assets one at a time with a progress bar: `[=======---] 50% filename.jpg 1.2 MB cloud` +- Shows file size and cloud/local status for each exported asset - Exports resized JPEG previews by default - Exports original files when `--originals` is present - Writes a summary like `exported 10 photos to ./export` or `exported 10 original files to ./export` to stderr @@ -187,7 +189,9 @@ Sending `SIGINT` (Ctrl+C) or `SIGTERM` during export or backup triggers a gracef A second signal forces an immediate exit. -- `cmd/applephotos`: CLI entrypoint, argument parsing, and album name resolution +## Architecture + +- `cmd/photoscli`: CLI entrypoint, argument parsing, and album name resolution - `internal/photos`: Go bridge interface, JSON parsing, and error mapping - `bridge/`: Objective-C PhotoKit implementation plus a C test stub @@ -201,6 +205,5 @@ Data passed from Objective-C to Go is serialized as JSON and unmarshaled into Go - Preview export uses PhotoKit preview rendering, not original file export - Original export currently writes the first PhotoKit asset resource for each asset, which may not capture every related representation for complex assets - iCloud-backed assets may require network download during export -- Export is synchronous and has no progress output - A second interrupt signal forces an immediate exit without waiting for the current file - Partial export failures are not listed individually diff --git a/cmd/applephotos/main.go b/cmd/photoscli/main.go similarity index 96% rename from cmd/applephotos/main.go rename to cmd/photoscli/main.go index e163554..41a038d 100644 --- a/cmd/applephotos/main.go +++ b/cmd/photoscli/main.go @@ -5,7 +5,7 @@ import ( "io" "strings" - "github.com/einand/applephotos/internal/photos" + "gitea.k3s.k0.nu/tools/photocli/internal/photos" ) func run(args []string, stdout, stderr io.Writer, bridge photos.Bridge) int { @@ -37,14 +37,14 @@ func run(args []string, stdout, stderr io.Writer, bridge photos.Bridge) int { } func usage(w io.Writer) { - fmt.Fprintln(w, `applephotos — export optimized images from Apple Photos + fmt.Fprintln(w, `photoscli — export optimized images from Apple Photos Usage: - applephotos albums - applephotos photos --album-id <id> - applephotos tree - applephotos backup-all --out <dir> [--size <px>] [--originals] - applephotos export --album-id <id> --out <dir> [--size <px>] [--originals] + photoscli albums + photoscli photos --album-id <id> + photoscli tree + photoscli backup-all --out <dir> [--size <px>] [--originals] + photoscli export --album-id <id> --out <dir> [--size <px>] [--originals] Commands: albums List user-created albums diff --git a/cmd/applephotos/main_main.go b/cmd/photoscli/main_main.go similarity index 90% rename from cmd/applephotos/main_main.go rename to cmd/photoscli/main_main.go index cb03bba..b13f8d2 100644 --- a/cmd/applephotos/main_main.go +++ b/cmd/photoscli/main_main.go @@ -5,7 +5,7 @@ import ( "os/signal" "syscall" - "github.com/einand/applephotos/internal/photos" + "gitea.k3s.k0.nu/tools/photocli/internal/photos" ) func main() { diff --git a/cmd/applephotos/main_test.go b/cmd/photoscli/main_test.go similarity index 99% rename from cmd/applephotos/main_test.go rename to cmd/photoscli/main_test.go index e8770fb..954248f 100644 --- a/cmd/applephotos/main_test.go +++ b/cmd/photoscli/main_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "github.com/einand/applephotos/internal/photos" + "gitea.k3s.k0.nu/tools/photocli/internal/photos" ) type mockBridge struct { @@ -89,7 +89,7 @@ func TestRunNoArgs(t *testing.T) { if rc != 1 { t.Errorf("rc = %d, want 1", rc) } - if !strings.Contains(stderr, "applephotos") { + if !strings.Contains(stderr, "photoscli") { t.Errorf("stderr should contain usage, got: %s", stderr) } } @@ -100,7 +100,7 @@ func TestRunHelp(t *testing.T) { if rc != 0 { t.Errorf("%s: rc = %d, want 0", cmd, rc) } - if !strings.Contains(stderr, "applephotos") { + if !strings.Contains(stderr, "photoscli") { t.Errorf("%s: stderr should contain usage", cmd) } } diff --git a/go.mod b/go.mod index 51a1445..ee49136 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/einand/applephotos +module gitea.k3s.k0.nu/tools/photocli go 1.22 \ No newline at end of file