remove -P (aka --prefix) option, fixes #6806

-a (aka --glob-archives) can be used for same purpose and is more powerful.
This commit is contained in:
Thomas Waldmann 2022-07-02 20:52:41 +02:00
parent 2ab254cea0
commit 6888d5dcb2
7 changed files with 26 additions and 38 deletions

View file

@ -402,11 +402,10 @@ different prefixes. For example, you could have a script that does::
Then you would have two different prune calls with different policies::
borg prune --verbose --list -d 30 --prefix main-
borg prune --verbose --list -d 7 --prefix logs-
borg prune --verbose --list -d 30 -a 'main-*'
borg prune --verbose --list -d 7 -a 'logs-*'
This will keep 7 days of logs and 30 days of everything else.
Borg also supports the ``--glob-archives`` parameter.
How do I remove files from an existing backup?
----------------------------------------------

View file

@ -195,13 +195,13 @@ backed up and that the ``prune`` command is keeping and deleting the correct bac
info "Pruning repository"
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
# archives of THIS machine. The '{hostname}-' prefix is very important to
# archives of THIS machine. The '{hostname}-*' globbing is very important to
# limit prune's operation to this machine's archives and not apply to
# other machines' archives also:
borg prune \
--list \
--prefix '{hostname}-' \
--glob-archives '{hostname}-*' \
--show-rc \
--keep-daily 7 \
--keep-weekly 4 \

View file

@ -10,7 +10,7 @@ Examples
$ borg compact
# delete all archives whose names begin with the machine's hostname followed by "-"
$ borg delete --prefix '{hostname}-'
$ borg delete -a '{hostname}-*'
# delete all archives whose names contain "-2012-"
$ borg delete -a '*-2012-*'

View file

@ -7,8 +7,8 @@ Be careful, prune is a potentially dangerous command, it will remove backup
archives.
The default of prune is to apply to **all archives in the repository** unless
you restrict its operation to a subset of the archives using ``--prefix``.
When using ``--prefix``, be careful to choose a good prefix - e.g. do not use a
you restrict its operation to a subset of the archives using ``-a`` / ``--glob-archives``.
When using ``-a``, be careful to choose a good pattern - e.g. do not use a
prefix "foo" if you do not also want to match "foobar".
It is strongly recommended to always run ``prune -v --list --dry-run ...``
@ -22,7 +22,7 @@ first so you will see what it would do without it actually doing anything.
# Same as above but only apply to archive names starting with the hostname
# of the machine followed by a "-" character:
$ borg prune -v --list --keep-daily=7 --keep-weekly=4 --prefix='{hostname}-'
$ borg prune -v --list --keep-daily=7 --keep-weekly=4 -a '{hostname}-*'
# actually free disk space:
$ borg compact

View file

@ -459,8 +459,8 @@ class Archiver:
env_var_override='BORG_CHECK_I_KNOW_WHAT_I_AM_DOING'):
return EXIT_ERROR
if args.repo_only and any(
(args.verify_data, args.first, args.last, args.prefix is not None, args.glob_archives)):
self.print_error("--repository-only contradicts --first, --last, --prefix, --glob-archives "
(args.verify_data, args.first, args.last, args.glob_archives)):
self.print_error("--repository-only contradicts --first, --last, -a / --glob-archives "
" and --verify-data arguments.")
return EXIT_ERROR
if args.repair and args.max_duration:
@ -476,8 +476,6 @@ class Archiver:
if not args.archives_only:
if not repository.check(repair=args.repair, save_space=args.save_space, max_duration=args.max_duration):
return EXIT_WARNING
if args.prefix is not None:
args.glob_archives = args.prefix + '*'
if not args.repo_only and not ArchiveChecker().check(repository, repair=args.repair,
first=args.first, last=args.last, sort_by=args.sort_by or 'ts', glob=args.glob_archives,
verify_data=args.verify_data, save_space=args.save_space):
@ -1757,8 +1755,6 @@ class Archiver:
'"keep-secondly", "keep-minutely", "keep-hourly", "keep-daily", '
'"keep-weekly", "keep-monthly" or "keep-yearly" settings must be specified.')
return self.exit_code
if args.prefix is not None:
args.glob_archives = args.prefix + '*'
checkpoint_re = r'\.checkpoint(\.\d+)?'
archives_checkpoints = manifest.archives.list(glob=args.glob_archives,
consider_checkpoints=True,
@ -2652,7 +2648,7 @@ class Archiver:
This allows you to share the same patterns between multiple repositories
without needing to specify them on the command line.\n\n''')
helptext['placeholders'] = textwrap.dedent('''
Repository URLs, ``--name``, ``--prefix``, ``--glob-archives``, ``--comment``
Repository URLs, ``--name``, ``-a`` / ``--glob-archives``, ``--comment``
and ``--remote-path`` values support these placeholders:
{hostname}
@ -2698,7 +2694,7 @@ class Archiver:
borg create /path/to/repo::{hostname}-{user}-{utcnow} ...
borg create /path/to/repo::{hostname}-{now:%Y-%m-%d_%H:%M:%S} ...
borg prune --prefix '{hostname}-' ...
borg prune -a '{hostname}-*' ...
.. note::
systemd uses a difficult, non-standard syntax for command lines in unit files (refer to
@ -3091,13 +3087,10 @@ class Archiver:
filters_group = subparser.add_argument_group('Archive filters',
'Archive filters can be applied to repository targets.')
group = filters_group.add_mutually_exclusive_group()
group.add_argument('-P', '--prefix', metavar='PREFIX', dest='prefix', type=PrefixSpec, action=Highlander,
help='only consider archive names starting with this prefix.')
group.add_argument('-a', '--glob-archives', metavar='GLOB', dest='glob_archives',
type=GlobSpec, action=Highlander,
help='only consider archive names matching the glob. '
'sh: rules apply, see "borg help patterns". '
'``--prefix`` and ``--glob-archives`` are mutually exclusive.')
'sh: rules apply, see "borg help patterns".')
if sort_by:
sort_by_default = 'timestamp'
@ -3971,11 +3964,9 @@ class Archiver:
that is how much your repository will shrink.
Please note that the "All archives" stats refer to the state after deletion.
You can delete multiple archives by specifying their common prefix, if they
have one, using the ``--prefix PREFIX`` option. You can also specify a shell
pattern to match multiple archives using the ``--glob-archives GLOB`` option
(for more info on these patterns, see :ref:`borg_patterns`). Note that these
two options are mutually exclusive.
You can delete multiple archives by specifying a matching shell pattern,
using the ``--glob-archives GLOB`` option (for more info on these patterns,
see :ref:`borg_patterns`).
Always first use ``--dry-run --list`` to see what would be deleted.
""")

View file

@ -106,9 +106,7 @@ class Archives(abc.MutableMapping):
name = getattr(args, 'name', None)
consider_checkpoints = getattr(args, 'consider_checkpoints', None)
if name is not None:
raise Error('Giving a specific name is incompatible with options --first, --last, --prefix, and --glob-archives, and --consider-checkpoints.')
if args.prefix is not None:
args.glob_archives = args.prefix + '*'
raise Error('Giving a specific name is incompatible with options --first, --last, -a / --glob-archives, and --consider-checkpoints.')
return self.list(sort_by=args.sort_by.split(','), consider_checkpoints=consider_checkpoints, glob=args.glob_archives, first=args.first, last=args.last)
def set_raw_dict(self, d):

View file

@ -1600,7 +1600,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.cmd(f'--repo={self.repository_location}', 'create', 'another_test.2', 'input')
self.cmd(f'--repo={self.repository_location}', 'extract', 'test', '--dry-run')
self.cmd(f'--repo={self.repository_location}', 'extract', 'test.2', '--dry-run')
self.cmd(f'--repo={self.repository_location}', 'delete', '--prefix', 'another_')
self.cmd(f'--repo={self.repository_location}', 'delete', '--glob-archives', 'another_*')
self.cmd(f'--repo={self.repository_location}', 'delete', '--last', '1')
self.cmd(f'--repo={self.repository_location}', 'delete', '-a', 'test')
self.cmd(f'--repo={self.repository_location}', 'extract', 'test.2', '--dry-run')
@ -2259,7 +2259,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.cmd(f'--repo={self.repository_location}', 'create', 'foo-2015-08-12-20:00', src_dir)
self.cmd(f'--repo={self.repository_location}', 'create', 'bar-2015-08-12-10:00', src_dir)
self.cmd(f'--repo={self.repository_location}', 'create', 'bar-2015-08-12-20:00', src_dir)
output = self.cmd(f'--repo={self.repository_location}', 'prune', '--list', '--dry-run', '--keep-daily=1', '--prefix=foo-')
output = self.cmd(f'--repo={self.repository_location}', 'prune', '--list', '--dry-run', '--keep-daily=1', '--glob-archives=foo-*')
assert re.search(r'Keeping archive \(rule: daily #1\):\s+foo-2015-08-12-20:00', output)
assert re.search(r'Would prune:\s+foo-2015-08-12-10:00', output)
output = self.cmd(f'--repo={self.repository_location}', 'rlist')
@ -2267,7 +2267,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.assert_in('foo-2015-08-12-20:00', output)
self.assert_in('bar-2015-08-12-10:00', output)
self.assert_in('bar-2015-08-12-20:00', output)
self.cmd(f'--repo={self.repository_location}', 'prune', '--keep-daily=1', '--prefix=foo-')
self.cmd(f'--repo={self.repository_location}', 'prune', '--keep-daily=1', '--glob-archives=foo-*')
output = self.cmd(f'--repo={self.repository_location}', 'rlist')
self.assert_not_in('foo-2015-08-12-10:00', output)
self.assert_in('foo-2015-08-12-20:00', output)
@ -2300,7 +2300,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.cmd(f'--repo={self.repository_location}', 'create', 'test-1', src_dir)
self.cmd(f'--repo={self.repository_location}', 'create', 'something-else-than-test-1', src_dir)
self.cmd(f'--repo={self.repository_location}', 'create', 'test-2', src_dir)
output = self.cmd(f'--repo={self.repository_location}', 'rlist', '--prefix=test-')
output = self.cmd(f'--repo={self.repository_location}', 'rlist', '--glob-archives=test-*')
self.assert_in('test-1', output)
self.assert_in('test-2', output)
self.assert_not_in('something-else', output)
@ -2664,13 +2664,13 @@ class ArchiverTestCase(ArchiverTestCaseBase):
assert sorted(os.listdir(os.path.join(mountpoint))) == ['arch11', 'arch12']
with self.fuse_mount(self.repository_location, mountpoint, '--last=2', '--sort=name'):
assert sorted(os.listdir(os.path.join(mountpoint))) == ['arch21', 'arch22']
with self.fuse_mount(self.repository_location, mountpoint, '--prefix=arch1'):
with self.fuse_mount(self.repository_location, mountpoint, '--glob-archives=arch1*'):
assert sorted(os.listdir(os.path.join(mountpoint))) == ['arch11', 'arch12']
with self.fuse_mount(self.repository_location, mountpoint, '--prefix=arch2'):
with self.fuse_mount(self.repository_location, mountpoint, '--glob-archives=arch2*'):
assert sorted(os.listdir(os.path.join(mountpoint))) == ['arch21', 'arch22']
with self.fuse_mount(self.repository_location, mountpoint, '--prefix=arch'):
with self.fuse_mount(self.repository_location, mountpoint, '--glob-archives=arch*'):
assert sorted(os.listdir(os.path.join(mountpoint))) == ['arch11', 'arch12', 'arch21', 'arch22']
with self.fuse_mount(self.repository_location, mountpoint, '--prefix=nope'):
with self.fuse_mount(self.repository_location, mountpoint, '--glob-archives=nope'):
assert sorted(os.listdir(os.path.join(mountpoint))) == []
@unittest.skipUnless(llfuse, 'llfuse not installed')
@ -3559,7 +3559,7 @@ class ArchiverCheckTestCase(ArchiverTestCaseBase):
output = self.cmd(f'--repo={self.repository_location}', 'check', '-v', '--archives-only', exit_code=0)
self.assert_not_in('Starting repository check', output)
self.assert_in('Starting archive consistency check', output)
output = self.cmd(f'--repo={self.repository_location}', 'check', '-v', '--archives-only', '--prefix=archive2', exit_code=0)
output = self.cmd(f'--repo={self.repository_location}', 'check', '-v', '--archives-only', '--glob-archives=archive2', exit_code=0)
self.assert_not_in('archive1', output)
output = self.cmd(f'--repo={self.repository_location}', 'check', '-v', '--archives-only', '--first=1', exit_code=0)
self.assert_in('archive1', output)