From ba7f70e0f8c408b6305c8333c1815aad51d84f55 Mon Sep 17 00:00:00 2001 From: Dillard Blom Date: Tue, 6 Oct 2026 03:51:35 +0200 Subject: [PATCH] Rename per-user backup/restore commands to backup:user:backup and backup:user:restore --- .github/workflows/ci.yml | 2 +- PLAN.md | 2 +- lib/Command/BackupUser.php | 6 +++--- lib/Command/RestoreUser.php | 10 +++++----- lib/Command/Retention.php | 2 +- lib/Service/PruneService.php | 4 ++-- tests/integration/user-roundtrip.sh | 14 +++++++------- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 44d9a35..8c37031 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,7 +62,7 @@ jobs: run: tests/integration/targets-matrix.sh integration-user: - # Per-user backup/restore via user_migration (occ backup:backup:user / backup:restore:user), + # Per-user backup/restore via user_migration (occ backup:user:backup / backup:user:restore), # an optional dependency installed from the app store. It calls user_migration's internal # UserMigrationService, whose API can change between Nextcloud versions, so this runs on every # supported version (not the database, which the main integration job already covers). diff --git a/PLAN.md b/PLAN.md index 3709d3d..d146e9a 100644 --- a/PLAN.md +++ b/PLAN.md @@ -276,7 +276,7 @@ onderdelen wel en niet terugkomen, op basis van de geregistreerde migrators. | `backup:list [--target=]` | herstelpunten | | `backup:verify [--deep]` | checksums controleren, optioneel alles ontsleutelen | | `backup:restore:file [--to=]` | bestand/map terugzetten | -| `backup:restore:user [--to-user=]` | gebruiker terugzetten via user_migration (fase 2) | +| `backup:user:restore [--to-user=]` | gebruiker terugzetten via user_migration (fase 2) | | `backup:restore:full ` | volledige restore (fase 2, verse installatie) | | `backup:target:add/list/remove/test` | opslagdoelen beheren en testen | | `backup:key:export / import` | herstelkit | diff --git a/lib/Command/BackupUser.php b/lib/Command/BackupUser.php index 75f0d35..a73c8ca 100644 --- a/lib/Command/BackupUser.php +++ b/lib/Command/BackupUser.php @@ -25,17 +25,17 @@ final class BackupUser extends Command { } protected function configure(): void { - $this->setName('backup:backup:user') + $this->setName('backup:user:backup') ->setDescription('Back up one user via user_migration (account, settings, files and everything else a migrator covers)') ->addArgument('target', InputArgument::REQUIRED, 'Location name or id') ->addArgument('user', InputArgument::REQUIRED, 'User id') ->setHelp(<<<'HELP' Streams a user_migration export straight into the encrypted repository: no zip, no copy in the user's own storage. Shares data with the regular backup; this needs the user_migration app -enabled. The manifest path this prints is what occ backup:restore:user expects. +enabled. The manifest path this prints is what occ backup:user:restore expects. Example: - occ backup:backup:user offsite alice + occ backup:user:backup offsite alice HELP); } diff --git a/lib/Command/RestoreUser.php b/lib/Command/RestoreUser.php index 90e2a95..198097a 100644 --- a/lib/Command/RestoreUser.php +++ b/lib/Command/RestoreUser.php @@ -24,10 +24,10 @@ final class RestoreUser extends Command { } protected function configure(): void { - $this->setName('backup:restore:user') - ->setDescription('Restore a user from a user_migration export (see backup:backup:user)') + $this->setName('backup:user:restore') + ->setDescription('Restore a user from a user_migration export (see backup:user:backup)') ->addArgument('target', InputArgument::REQUIRED, 'Location name or id') - ->addArgument('manifest', InputArgument::REQUIRED, 'Manifest path printed by backup:backup:user (users//)') + ->addArgument('manifest', InputArgument::REQUIRED, 'Manifest path printed by backup:user:backup (users//)') ->addOption('mode', 'm', InputOption::VALUE_REQUIRED, 'replace or as-backup', UserRestoreService::MODE_REPLACE) ->setHelp(<<<'HELP' Never imports over a live account. Modes: @@ -38,8 +38,8 @@ Never imports over a live account. Modes: the new name, never the existing account Example: - occ backup:restore:user offsite users/alice/20261005T120000Z-ab12cd34 - occ backup:restore:user offsite users/alice/20261005T120000Z-ab12cd34 --mode=as-backup + occ backup:user:restore offsite users/alice/20261005T120000Z-ab12cd34 + occ backup:user:restore offsite users/alice/20261005T120000Z-ab12cd34 --mode=as-backup HELP); } diff --git a/lib/Command/Retention.php b/lib/Command/Retention.php index 68c60c6..43eff92 100644 --- a/lib/Command/Retention.php +++ b/lib/Command/Retention.php @@ -28,7 +28,7 @@ final class Retention extends Command { ->addOption('daily', null, InputOption::VALUE_REQUIRED, 'Keep one per day for the last N days with a backup') ->addOption('weekly', null, InputOption::VALUE_REQUIRED, 'Keep one per week for N weeks') ->addOption('monthly', null, InputOption::VALUE_REQUIRED, 'Keep one per month for N months') - ->addOption('user-last', null, InputOption::VALUE_REQUIRED, 'Keep the newest N of each user\'s own exports (occ backup:backup:user)') + ->addOption('user-last', null, InputOption::VALUE_REQUIRED, 'Keep the newest N of each user\'s own exports (occ backup:user:backup)') ->setHelp("Example: occ backup:retention --last=3 --daily=7 --weekly=4 --monthly=12 --user-last=3"); } diff --git a/lib/Service/PruneService.php b/lib/Service/PruneService.php index 284de2c..68852b9 100644 --- a/lib/Service/PruneService.php +++ b/lib/Service/PruneService.php @@ -111,7 +111,7 @@ final class PruneService { return self::lockKey($target) . '/catalog'; } - /** How many of each user's own exports (occ backup:backup:user) to keep, newest first. */ + /** How many of each user's own exports (occ backup:user:backup) to keep, newest first. */ public function userExportRetention(): int { return $this->appConfig->getValueInt(Application::APP_ID, 'user_export_retention', 3); } @@ -129,7 +129,7 @@ final class PruneService { /** * Forgets a user's older exports once more than userExportRetention() exist for them, - * newest first; no trash, unlike a full snapshot (occ backup:backup:user is on-demand, not + * newest first; no trash, unlike a full snapshot (occ backup:user:backup is on-demand, not * yet the primary safety net the deletion delay protects). * * @return array{kept: array>, forgotten: list} diff --git a/tests/integration/user-roundtrip.sh b/tests/integration/user-roundtrip.sh index e6efe5a..73c2283 100755 --- a/tests/integration/user-roundtrip.sh +++ b/tests/integration/user-roundtrip.sh @@ -1,6 +1,6 @@ #!/bin/bash # Per-user backup/restore round trip via user_migration (optional dependency, see PLAN.md 3.8): -# occ backup:backup:user / occ backup:restore:user --mode=as-backup|replace. +# occ backup:user:backup / occ backup:user:restore --mode=as-backup|replace. # Usage: user-roundtrip.sh "" [target-args] # e.g. user-roundtrip.sh "docker exec -u www-data ngb-nc35-pgsql" /var/www/html/data set -euo pipefail @@ -32,12 +32,12 @@ $X sh -c "mkdir -p $DATA/$U/files/Docs && for i in 1 2 3; do head -c 100000 /dev occ files:scan "$U" >/dev/null SUM_BEFORE=$($X sh -c "cd $DATA/$U/files && find . -type f -print0 | sort -z | xargs -0 md5sum | md5sum") -MANIFEST=$(occ backup:backup:user ci "$U" | sed -n 's/.* to \(.*\)\.$/\1/p') -[ -n "$MANIFEST" ] || fail "backup:backup:user printed no manifest path" +MANIFEST=$(occ backup:user:backup ci "$U" | sed -n 's/.* to \(.*\)\.$/\1/p') +[ -n "$MANIFEST" ] || fail "backup:user:backup printed no manifest path" ok "backed up $U to $MANIFEST" # as-backup: restore into -bak; the original account must stay untouched. -occ backup:restore:user ci "$MANIFEST" --mode=as-backup >/dev/null || fail "restore as-backup" +occ backup:user:restore ci "$MANIFEST" --mode=as-backup >/dev/null || fail "restore as-backup" occ files:scan "$U-bak" >/dev/null SUM_BAK=$($X sh -c "cd $DATA/$U-bak/files && find . -type f -print0 | sort -z | xargs -0 md5sum | md5sum") [ "$SUM_BEFORE" = "$SUM_BAK" ] || fail "the -bak account's files differ from the original" @@ -48,7 +48,7 @@ ok "as-backup restores into -bak, byte-identical, original account untouche # replace: damage the account, then restore it in place under the same uid. $X sh -c "rm '$DATA/$U/files/Docs/f1.bin' && echo damaged > '$DATA/$U/files/Docs/f1.bin'" occ files:scan "$U" >/dev/null -occ backup:restore:user ci "$MANIFEST" --mode=replace >/dev/null || fail "restore replace" +occ backup:user:restore ci "$MANIFEST" --mode=replace >/dev/null || fail "restore replace" occ files:scan "$U" >/dev/null SUM_AFTER=$($X sh -c "cd $DATA/$U/files && find . -type f -print0 | sort -z | xargs -0 md5sum | md5sum") [ "$SUM_BEFORE" = "$SUM_AFTER" ] || fail "files differ after a replace restore" @@ -58,9 +58,9 @@ ok "replace restores the original content under the same uid, byte-identical" # restore made of it just before deleting it (4 total after these two more), then --user-last=2 # must forget exactly the 2 oldest. sleep 1.1 # exportId is time-based to the second; force each one to be distinct -occ backup:backup:user ci "$U" >/dev/null || fail "third backup:backup:user" +occ backup:user:backup ci "$U" >/dev/null || fail "third backup:user:backup" sleep 1.1 -occ backup:backup:user ci "$U" >/dev/null || fail "fourth backup:backup:user" +occ backup:user:backup ci "$U" >/dev/null || fail "fourth backup:user:backup" occ backup:retention --user-last=2 >/dev/null || fail "retention --user-last" PRUNE_OUT=$(occ backup:prune ci) echo "$PRUNE_OUT" | grep -q "forgot 2 user export(s) for 1 user(s)" || fail "prune did not forget the expected two user exports"