diff --git a/src/borg/archiver/delete_cmd.py b/src/borg/archiver/delete_cmd.py index 5ad81f95b..5ff05d33d 100644 --- a/src/borg/archiver/delete_cmd.py +++ b/src/borg/archiver/delete_cmd.py @@ -22,6 +22,7 @@ class DeleteMixIn: archive_infos = [manifest.archives.get_one([args.name])] else: archive_infos = manifest.archives.list_considering(args) + archive_infos = [ai for ai in archive_infos if "@PROT" not in ai.tags] count = len(archive_infos) if count == 0: return diff --git a/src/borg/archiver/prune_cmd.py b/src/borg/archiver/prune_cmd.py index 42a375c21..fd0f0fcfd 100644 --- a/src/borg/archiver/prune_cmd.py +++ b/src/borg/archiver/prune_cmd.py @@ -151,6 +151,7 @@ class PruneMixIn: match = args.name if args.name else args.match_archives archives = manifest.archives.list(match=match, sort_by=["ts"], reverse=True) + archives = [ai for ai in archives if "@PROT" not in ai.tags] keep = [] # collect the rule responsible for the keeping of each archive in this dict diff --git a/src/borg/testsuite/archiver/delete_cmd_test.py b/src/borg/testsuite/archiver/delete_cmd_test.py index e07ef2736..a163f3d71 100644 --- a/src/borg/testsuite/archiver/delete_cmd_test.py +++ b/src/borg/testsuite/archiver/delete_cmd_test.py @@ -32,3 +32,19 @@ def test_delete_multiple(archivers, request): cmd(archiver, "delete", "-a", "test1") cmd(archiver, "delete", "-a", "test2") assert not cmd(archiver, "repo-list") + + +def test_delete_ignore_protected(archivers, request): + archiver = request.getfixturevalue(archivers) + create_regular_file(archiver.input_path, "file1", size=1024 * 80) + cmd(archiver, "repo-create", RK_ENCRYPTION) + cmd(archiver, "create", "test1", "input") + cmd(archiver, "tag", "--add=@PROT", "test1") + cmd(archiver, "create", "test2", "input") + cmd(archiver, "delete", "-a", "test1") + cmd(archiver, "delete", "-a", "test2") + cmd(archiver, "delete", "-a", "sh:test*") + output = cmd(archiver, "repo-list") + assert "@PROT" in output + assert "test1" in output + assert "test2" not in output diff --git a/src/borg/testsuite/archiver/prune_cmd_test.py b/src/borg/testsuite/archiver/prune_cmd_test.py index 2c44064bf..207f2bdb7 100644 --- a/src/borg/testsuite/archiver/prune_cmd_test.py +++ b/src/borg/testsuite/archiver/prune_cmd_test.py @@ -241,3 +241,19 @@ def test_prune_repository_glob(archivers, request): assert "2015-08-12-20:00-foo" in output assert "2015-08-12-10:00-bar" in output assert "2015-08-12-20:00-bar" in output + + +def test_prune_ignore_protected(archivers, request): + archiver = request.getfixturevalue(archivers) + cmd(archiver, "repo-create", RK_ENCRYPTION) + cmd(archiver, "create", "archive1", archiver.input_path) + cmd(archiver, "tag", "--set=@PROT", "archive1") # do not delete archive1! + cmd(archiver, "create", "archive2", archiver.input_path) + cmd(archiver, "create", "archive3", archiver.input_path) + output = cmd(archiver, "prune", "--list", "--keep-last=1", "--match-archives=sh:archive*") + assert "archive1" not in output # @PROT archives are completely ignored. + assert re.search(r"Keeping archive \(rule: secondly #1\):\s+archive3", output) + assert re.search(r"Pruning archive \(.*?\):\s+archive2", output) + output = cmd(archiver, "repo-list") + assert "archive1" in output # @PROT protected archive1 from deletion + assert "archive3" in output # last one