From 141474ff0761f76485b2ffd54d91168277617913 Mon Sep 17 00:00:00 2001 From: jetchirag Date: Sun, 26 Mar 2023 01:58:03 +0530 Subject: [PATCH 1/9] Added TIMESPAN flags to match archive in various commands (Borg2 feature) Signed-off-by: jetchirag --- borgmatic/actions/mount.py | 1 + borgmatic/actions/prune.py | 1 + borgmatic/borg/mount.py | 7 ++++ borgmatic/borg/prune.py | 5 +++ borgmatic/commands/arguments.py | 68 +++++++++++++++++++++++++++++++++ 5 files changed, 82 insertions(+) diff --git a/borgmatic/actions/mount.py b/borgmatic/actions/mount.py index e2703a5..2b661ec 100644 --- a/borgmatic/actions/mount.py +++ b/borgmatic/actions/mount.py @@ -35,6 +35,7 @@ def run_mount( mount_arguments.paths, mount_arguments.foreground, mount_arguments.options, + mount_arguments, storage, local_borg_version, local_path=local_path, diff --git a/borgmatic/actions/prune.py b/borgmatic/actions/prune.py index ca098ce..a89b717 100644 --- a/borgmatic/actions/prune.py +++ b/borgmatic/actions/prune.py @@ -44,6 +44,7 @@ def run_prune( storage, retention, local_borg_version, + prune_arguments, local_path=local_path, remote_path=remote_path, stats=prune_arguments.stats, diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 92d689b..d987ca4 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -13,6 +13,7 @@ def mount_archive( paths, foreground, options, + mount_arguments, storage_config, local_borg_version, local_path='borg', @@ -35,6 +36,12 @@ def mount_archive( + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + (('--foreground',) if foreground else ()) + + (flags.make_flags('first', mount_arguments.first) if mount_arguments.first else ()) + + (flags.make_flags('last', mount_arguments.last) if mount_arguments.last else ()) + + (flags.make_flags('newest', mount_arguments.newest) if mount_arguments.newest else ()) + + (flags.make_flags('oldest', mount_arguments.oldest) if mount_arguments.oldest else ()) + + (flags.make_flags('older', mount_arguments.older) if mount_arguments.older else ()) + + (flags.make_flags('newer', mount_arguments.newer) if mount_arguments.newer else ()) + (('-o', options) if options else ()) + ( ( diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index e53197f..aa81a7f 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -43,6 +43,7 @@ def prune_archives( storage_config, retention_config, local_borg_version, + prune_arguments, local_path='borg', remote_path=None, stats=False, @@ -71,6 +72,10 @@ def prune_archives( + (('--stats',) if stats and not dry_run else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--list',) if list_archives else ()) + + (flags.make_flags('newest', prune_arguments.newest) if prune_arguments.newest else ()) + + (flags.make_flags('oldest', prune_arguments.oldest) if prune_arguments.oldest else ()) + + (flags.make_flags('older', prune_arguments.older) if prune_arguments.older else ()) + + (flags.make_flags('newer', prune_arguments.newer) if prune_arguments.newer else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + (('--dry-run',) if dry_run else ()) + (tuple(extra_borg_options.split(' ')) if extra_borg_options else ()) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index d5dc6af..34ff804 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -321,6 +321,18 @@ def make_parsers(): transfer_group.add_argument( '--last', metavar='N', help='Only transfer last N archives after other filters are applied' ) + transfer_group.add_argument( + '--oldest', metavar='TIMESPAN', help='Transfer archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + transfer_group.add_argument( + '--newest', metavar='TIMESPAN', help='Transfer archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + transfer_group.add_argument( + '--older', metavar='TIMESPAN', help='Transfer archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) + transfer_group.add_argument( + '--newer', metavar='TIMESPAN', help='Transfer archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) transfer_group.add_argument( '-h', '--help', action='help', help='Show this help message and exit' ) @@ -347,6 +359,18 @@ def make_parsers(): prune_group.add_argument( '--list', dest='list_archives', action='store_true', help='List archives kept/pruned' ) + prune_group.add_argument( + '--oldest', metavar='TIMESPAN', help='Consider archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + prune_group.add_argument( + '--newest', metavar='TIMESPAN', help='Consider archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + prune_group.add_argument( + '--older', metavar='TIMESPAN', help='Consider archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) + prune_group.add_argument( + '--newer', metavar='TIMESPAN', help='Consider archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) prune_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') compact_parser = subparsers.add_parser( @@ -587,6 +611,26 @@ def make_parsers(): action='store_true', help='Stay in foreground until ctrl-C is pressed', ) + mount_group.add_argument( + '--first', + metavar='N', + help='Mount first N archives after other filters are applied', + ) + mount_group.add_argument( + '--last', metavar='N', help='Mount last N archives after other filters are applied' + ) + mount_group.add_argument( + '--oldest', metavar='TIMESPAN', help='Mount archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + mount_group.add_argument( + '--newest', metavar='TIMESPAN', help='Mount archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + mount_group.add_argument( + '--older', metavar='TIMESPAN', help='Mount archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) + mount_group.add_argument( + '--newer', metavar='TIMESPAN', help='Mount archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) mount_group.add_argument('--options', dest='options', help='Extra Borg mount options') mount_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') @@ -670,6 +714,18 @@ def make_parsers(): rlist_group.add_argument( '--last', metavar='N', help='List last N archives after other filters are applied' ) + rlist_group.add_argument( + '--oldest', metavar='TIMESPAN', help='List archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + rlist_group.add_argument( + '--newest', metavar='TIMESPAN', help='List archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + rlist_group.add_argument( + '--older', metavar='TIMESPAN', help='List archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) + rlist_group.add_argument( + '--newer', metavar='TIMESPAN', help='List archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) rlist_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') list_parser = subparsers.add_parser( @@ -799,6 +855,18 @@ def make_parsers(): info_group.add_argument( '--last', metavar='N', help='Show info for last N archives after other filters are applied' ) + info_group.add_argument( + '--oldest', metavar='TIMESPAN', help='Show info for archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + info_group.add_argument( + '--newest', metavar='TIMESPAN', help='Show info for archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + ) + info_group.add_argument( + '--older', metavar='TIMESPAN', help='Show info for archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) + info_group.add_argument( + '--newer', metavar='TIMESPAN', help='Show info for archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + ) info_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') break_lock_parser = subparsers.add_parser( From ff1f4dc09c9c38def4bfad4f528e5ced4eff779f Mon Sep 17 00:00:00 2001 From: jetchirag Date: Sun, 26 Mar 2023 02:06:46 +0530 Subject: [PATCH 2/9] minor fixes to prune argument help text --- borgmatic/commands/arguments.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 34ff804..b7ee94a 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -360,16 +360,16 @@ def make_parsers(): '--list', dest='list_archives', action='store_true', help='List archives kept/pruned' ) prune_group.add_argument( - '--oldest', metavar='TIMESPAN', help='Consider archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', metavar='TIMESPAN', help='Prune archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) prune_group.add_argument( - '--newest', metavar='TIMESPAN', help='Consider archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='Prune archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) prune_group.add_argument( - '--older', metavar='TIMESPAN', help='Consider archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', metavar='TIMESPAN', help='Prune archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' ) prune_group.add_argument( - '--newer', metavar='TIMESPAN', help='Consider archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', metavar='TIMESPAN', help='Prune archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' ) prune_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') From 4fa4fccab7b186522648a2d78c9098937e86d8b6 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 27 Mar 2023 23:24:17 +0530 Subject: [PATCH 3/9] Use make_flags_from_arguments on mount; Pending test fixes Signed-off-by: Chirag Aggarwal --- borgmatic/borg/mount.py | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index d987ca4..2797534 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -9,10 +9,6 @@ logger = logging.getLogger(__name__) def mount_archive( repository, archive, - mount_point, - paths, - foreground, - options, mount_arguments, storage_config, local_borg_version, @@ -35,14 +31,13 @@ def mount_archive( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) - + (('--foreground',) if foreground else ()) - + (flags.make_flags('first', mount_arguments.first) if mount_arguments.first else ()) - + (flags.make_flags('last', mount_arguments.last) if mount_arguments.last else ()) - + (flags.make_flags('newest', mount_arguments.newest) if mount_arguments.newest else ()) - + (flags.make_flags('oldest', mount_arguments.oldest) if mount_arguments.oldest else ()) - + (flags.make_flags('older', mount_arguments.older) if mount_arguments.older else ()) - + (flags.make_flags('newer', mount_arguments.newer) if mount_arguments.newer else ()) - + (('-o', options) if options else ()) + + + flags.make_flags_from_arguments( + mount_arguments, + excludes=('repository', 'archive', 'mount_point', 'path', 'options'), + ) + + + (('-o', mount_arguments.options) if mount_arguments.options else ()) + ( ( flags.make_repository_flags(repository, local_borg_version) @@ -59,14 +54,14 @@ def mount_archive( else flags.make_repository_flags(repository, local_borg_version) ) ) - + (mount_point,) - + (tuple(paths) if paths else ()) + + (mount_arguments.mount_point,) + + (tuple(mount_arguments.paths) if mount_arguments.paths else ()) ) borg_environment = environment.make_environment(storage_config) # Don't capture the output when foreground mode is used so that ctrl-C can work properly. - if foreground: + if mount_arguments.foreground: execute_command( full_command, output_file=DO_NOT_CAPTURE, From edd79ed86cca097216741363151deebe35839e25 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Mar 2023 18:10:42 +0530 Subject: [PATCH 4/9] removed individual action parameters, and used make_flags_from_arguments Signed-off-by: Chirag Aggarwal --- borgmatic/actions/mount.py | 4 ---- borgmatic/actions/prune.py | 2 -- borgmatic/borg/prune.py | 19 +++++++++---------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/borgmatic/actions/mount.py b/borgmatic/actions/mount.py index 2b661ec..b1a1132 100644 --- a/borgmatic/actions/mount.py +++ b/borgmatic/actions/mount.py @@ -31,10 +31,6 @@ def run_mount( local_path, remote_path, ), - mount_arguments.mount_point, - mount_arguments.paths, - mount_arguments.foreground, - mount_arguments.options, mount_arguments, storage, local_borg_version, diff --git a/borgmatic/actions/prune.py b/borgmatic/actions/prune.py index a89b717..09666ee 100644 --- a/borgmatic/actions/prune.py +++ b/borgmatic/actions/prune.py @@ -47,8 +47,6 @@ def run_prune( prune_arguments, local_path=local_path, remote_path=remote_path, - stats=prune_arguments.stats, - list_archives=prune_arguments.list_archives, ) borgmatic.hooks.command.execute_hook( hooks.get('after_prune'), diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index aa81a7f..b8b1d6b 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -46,8 +46,6 @@ def prune_archives( prune_arguments, local_path='borg', remote_path=None, - stats=False, - list_archives=False, ): ''' Given dry-run flag, a local or remote repository path, a storage config dict, and a @@ -69,20 +67,21 @@ def prune_archives( + (('--remote-path', remote_path) if remote_path else ()) + (('--umask', str(umask)) if umask else ()) + (('--lock-wait', str(lock_wait)) if lock_wait else ()) - + (('--stats',) if stats and not dry_run else ()) + + (('--stats',) if prune_arguments.stats and not dry_run else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) - + (('--list',) if list_archives else ()) - + (flags.make_flags('newest', prune_arguments.newest) if prune_arguments.newest else ()) - + (flags.make_flags('oldest', prune_arguments.oldest) if prune_arguments.oldest else ()) - + (flags.make_flags('older', prune_arguments.older) if prune_arguments.older else ()) - + (flags.make_flags('newer', prune_arguments.newer) if prune_arguments.newer else ()) + + + flags.make_flags_from_arguments( + prune_arguments, + excludes=('repository', 'stats'), + ) + + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) - + (('--dry-run',) if dry_run else ()) + + (tuple(extra_borg_options.split(' ')) if extra_borg_options else ()) + flags.make_repository_flags(repository, local_borg_version) ) - if stats or list_archives: + if prune_arguments.stats or prune_arguments.list_archives: output_log_level = logging.ANSWER else: output_log_level = logging.INFO From 98c6aa644379dee2c1d89ee30d2f2c9588c978fe Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 28 Mar 2023 18:15:49 +0530 Subject: [PATCH 5/9] Use Square brackets to denote version specific flag Signed-off-by: Chirag Aggarwal --- borgmatic/commands/arguments.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index b7ee94a..db743dc 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -246,7 +246,7 @@ def make_parsers(): '--source-repository', '--other-repo', metavar='KEY_REPOSITORY', - help='Path to an existing Borg repository whose key material should be reused (Borg 2.x+ only)', + help='Path to an existing Borg repository whose key material should be reused [Borg 2.x+ only]', ) rcreate_group.add_argument( '--repository', @@ -255,7 +255,7 @@ def make_parsers(): rcreate_group.add_argument( '--copy-crypt-key', action='store_true', - help='Copy the crypt key used for authenticated encryption from the source repository, defaults to a new random key (Borg 2.x+ only)', + help='Copy the crypt key used for authenticated encryption from the source repository, defaults to a new random key [Borg 2.x+ only]', ) rcreate_group.add_argument( '--append-only', action='store_true', help='Create an append-only repository', @@ -275,8 +275,8 @@ def make_parsers(): transfer_parser = subparsers.add_parser( 'transfer', aliases=SUBPARSER_ALIASES['transfer'], - help='Transfer archives from one repository to another, optionally upgrading the transferred data (Borg 2.0+ only)', - description='Transfer archives from one repository to another, optionally upgrading the transferred data (Borg 2.0+ only)', + help='Transfer archives from one repository to another, optionally upgrading the transferred data [Borg 2.0+ only]', + description='Transfer archives from one repository to another, optionally upgrading the transferred data [Borg 2.0+ only]', add_help=False, ) transfer_group = transfer_parser.add_argument_group('transfer arguments') @@ -325,7 +325,7 @@ def make_parsers(): '--oldest', metavar='TIMESPAN', help='Transfer archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) transfer_group.add_argument( - '--newest', metavar='TIMESPAN', help='Transfer archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='Transfer archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) transfer_group.add_argument( '--older', metavar='TIMESPAN', help='Transfer archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' @@ -363,7 +363,7 @@ def make_parsers(): '--oldest', metavar='TIMESPAN', help='Prune archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) prune_group.add_argument( - '--newest', metavar='TIMESPAN', help='Prune archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='Prune archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) prune_group.add_argument( '--older', metavar='TIMESPAN', help='Prune archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' @@ -376,8 +376,8 @@ def make_parsers(): compact_parser = subparsers.add_parser( 'compact', aliases=SUBPARSER_ALIASES['compact'], - help='Compact segments to free space (Borg 1.2+, borgmatic 1.5.23+ only)', - description='Compact segments to free space (Borg 1.2+, borgmatic 1.5.23+ only)', + help='Compact segments to free space [Borg 1.2+, borgmatic 1.5.23+ only]', + description='Compact segments to free space [Borg 1.2+, borgmatic 1.5.23+ only]', add_help=False, ) compact_group = compact_parser.add_argument_group('compact arguments') @@ -397,7 +397,7 @@ def make_parsers(): dest='cleanup_commits', default=False, action='store_true', - help='Cleanup commit-only 17-byte segment files left behind by Borg 1.1 (flag in Borg 1.2 only)', + help='Cleanup commit-only 17-byte segment files left behind by Borg 1.1 [flag in Borg 1.2 only]', ) compact_group.add_argument( '--threshold', @@ -623,7 +623,7 @@ def make_parsers(): '--oldest', metavar='TIMESPAN', help='Mount archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) mount_group.add_argument( - '--newest', metavar='TIMESPAN', help='Mount archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='Mount archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) mount_group.add_argument( '--older', metavar='TIMESPAN', help='Mount archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' @@ -718,7 +718,7 @@ def make_parsers(): '--oldest', metavar='TIMESPAN', help='List archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) rlist_group.add_argument( - '--newest', metavar='TIMESPAN', help='List archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='List archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) rlist_group.add_argument( '--older', metavar='TIMESPAN', help='List archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' @@ -859,7 +859,7 @@ def make_parsers(): '--oldest', metavar='TIMESPAN', help='Show info for archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' ) info_group.add_argument( - '--newest', metavar='TIMESPAN', help='Show info for archives within a time range that ends at newest archive\'s timestamp and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', metavar='TIMESPAN', help='Show info for archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' ) info_group.add_argument( '--older', metavar='TIMESPAN', help='Show info for archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' From 96aca4f446c427eb8cce4212e5e3f7df1e5f9744 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 24 Apr 2023 20:24:41 +0530 Subject: [PATCH 6/9] Updated existing tests to use new parameters Signed-off-by: Chirag Aggarwal --- borgmatic/borg/mount.py | 2 +- borgmatic/borg/prune.py | 4 ++- tests/unit/borg/test_mount.py | 66 ++++++++++++----------------------- tests/unit/borg/test_prune.py | 41 ++++++++++++++++++++-- 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 2f6132d..764f72e 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -34,7 +34,7 @@ def mount_archive( + flags.make_flags_from_arguments( mount_arguments, - excludes=('repository', 'archive', 'mount_point', 'path', 'options'), + excludes=('repository', 'archive', 'mount_point', 'paths', 'options'), ) + (('-o', mount_arguments.options) if mount_arguments.options else ()) diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index c9a4635..ba41fba 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -78,10 +78,12 @@ def prune_archives( + flags.make_flags_from_arguments( prune_arguments, - excludes=('repository', 'stats'), + excludes=('repository', 'stats', 'list_archives'), ) + + (('--list',) if prune_arguments.list_archives else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + + (('--dry-run',) if dry_run else ()) + (tuple(extra_borg_options.split(' ')) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index 658b2e5..1438ebe 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -21,13 +21,11 @@ def test_mount_archive_calls_borg_with_required_flags(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(('borg', 'mount', 'repo', '/mnt')) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive=None, - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -45,13 +43,11 @@ def test_mount_archive_with_borg_features_calls_borg_with_repository_and_match_a ('borg', 'mount', '--repo', 'repo', '--match-archives', 'archive', '/mnt') ) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -64,13 +60,11 @@ def test_mount_archive_without_archive_calls_borg_with_repository_flags_only(): ) insert_execute_command_mock(('borg', 'mount', 'repo::archive', '/mnt')) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -83,13 +77,11 @@ def test_mount_archive_calls_borg_with_path_flags(): ) insert_execute_command_mock(('borg', 'mount', 'repo::archive', '/mnt', 'path1', 'path2')) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=['path1', 'path2'], foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=['path1', 'path2'], - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -104,13 +96,11 @@ def test_mount_archive_calls_borg_with_remote_path_flags(): ('borg', 'mount', '--remote-path', 'borg1', 'repo::archive', '/mnt') ) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', remote_path='borg1', @@ -124,13 +114,11 @@ def test_mount_archive_calls_borg_with_umask_flags(): ) insert_execute_command_mock(('borg', 'mount', '--umask', '0770', 'repo::archive', '/mnt')) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={'umask': '0770'}, local_borg_version='1.2.3', ) @@ -143,13 +131,11 @@ def test_mount_archive_calls_borg_with_lock_wait_flags(): ) insert_execute_command_mock(('borg', 'mount', '--lock-wait', '5', 'repo::archive', '/mnt')) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={'lock_wait': '5'}, local_borg_version='1.2.3', ) @@ -163,13 +149,11 @@ def test_mount_archive_with_log_info_calls_borg_with_info_parameter(): insert_execute_command_mock(('borg', 'mount', '--info', 'repo::archive', '/mnt')) insert_logging_mock(logging.INFO) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -183,13 +167,11 @@ def test_mount_archive_with_log_debug_calls_borg_with_debug_flags(): insert_execute_command_mock(('borg', 'mount', '--debug', '--show-rc', 'repo::archive', '/mnt')) insert_logging_mock(logging.DEBUG) + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -208,13 +190,11 @@ def test_mount_archive_calls_borg_with_foreground_parameter(): extra_environment=None, ).once() + mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=True) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=True, - options=None, + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) @@ -227,13 +207,11 @@ def test_mount_archive_calls_borg_with_options_flags(): ) insert_execute_command_mock(('borg', 'mount', '-o', 'super_mount', 'repo::archive', '/mnt')) + mount_arguments = flexmock(mount_point='/mnt', options='super_mount', paths=None, foreground=False) module.mount_archive( repository_path='repo', archive='archive', - mount_point='/mnt', - paths=None, - foreground=False, - options='super_mount', + mount_arguments=mount_arguments, storage_config={}, local_borg_version='1.2.3', ) diff --git a/tests/unit/borg/test_prune.py b/tests/unit/borg/test_prune.py index 128bdc0..2ed9c90 100644 --- a/tests/unit/borg/test_prune.py +++ b/tests/unit/borg/test_prune.py @@ -117,12 +117,14 @@ def test_prune_archives_calls_borg_with_parameters(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('repo',), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) @@ -134,12 +136,14 @@ def test_prune_archives_with_log_info_calls_borg_with_info_parameter(): insert_execute_command_mock(PRUNE_COMMAND + ('--info', 'repo'), logging.INFO) insert_logging_mock(logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( repository_path='repo', storage_config={}, dry_run=False, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) @@ -151,15 +155,34 @@ def test_prune_archives_with_log_debug_calls_borg_with_debug_parameter(): insert_execute_command_mock(PRUNE_COMMAND + ('--debug', '--show-rc', 'repo'), logging.INFO) insert_logging_mock(logging.DEBUG) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( repository_path='repo', storage_config={}, dry_run=False, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) +# def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): +# flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') +# flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER +# flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) +# flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) +# insert_execute_command_mock(PRUNE_COMMAND + ('--dry-run', 'repo'), logging.INFO) + +# prune_arguments = flexmock(stats=False, list_archives=False) +# module.prune_archives( +# repository_path='repo', +# storage_config={}, +# dry_run=True, +# retention_config=flexmock(), +# local_borg_version='1.2.3', +# prune_arguments=prune_arguments, +# ) + def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER @@ -167,12 +190,14 @@ def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--dry-run', 'repo'), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( repository_path='repo', storage_config={}, dry_run=True, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) @@ -183,6 +208,7 @@ def test_prune_archives_with_local_path_calls_borg_via_local_path(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(('borg1',) + PRUNE_COMMAND[1:] + ('repo',), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', @@ -190,6 +216,7 @@ def test_prune_archives_with_local_path_calls_borg_via_local_path(): retention_config=flexmock(), local_borg_version='1.2.3', local_path='borg1', + prune_arguments=prune_arguments, ) @@ -200,6 +227,7 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_parameters( flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--remote-path', 'borg1', 'repo'), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', @@ -207,6 +235,7 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_parameters( retention_config=flexmock(), local_borg_version='1.2.3', remote_path='borg1', + prune_arguments=prune_arguments, ) @@ -217,13 +246,14 @@ def test_prune_archives_with_stats_calls_borg_with_stats_parameter_and_answer_ou flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--stats', 'repo'), module.borgmatic.logger.ANSWER) + prune_arguments = flexmock(stats=True, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', - stats=True, + prune_arguments=prune_arguments, ) @@ -234,13 +264,14 @@ def test_prune_archives_with_files_calls_borg_with_list_parameter_and_answer_out flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--list', 'repo'), module.borgmatic.logger.ANSWER) + prune_arguments = flexmock(stats=False, list_archives=True) module.prune_archives( dry_run=False, repository_path='repo', storage_config={}, retention_config=flexmock(), local_borg_version='1.2.3', - list_archives=True, + prune_arguments=prune_arguments, ) @@ -252,12 +283,14 @@ def test_prune_archives_with_umask_calls_borg_with_umask_parameters(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--umask', '077', 'repo'), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', storage_config=storage_config, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) @@ -269,12 +302,14 @@ def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_parameters(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--lock-wait', '5', 'repo'), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', storage_config=storage_config, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) @@ -285,10 +320,12 @@ def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options(): flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) insert_execute_command_mock(PRUNE_COMMAND + ('--extra', '--options', 'repo'), logging.INFO) + prune_arguments = flexmock(stats=False, list_archives=False) module.prune_archives( dry_run=False, repository_path='repo', storage_config={'extra_borg_options': {'prune': '--extra --options'}}, retention_config=flexmock(), local_borg_version='1.2.3', + prune_arguments=prune_arguments, ) From 8aaba9bb0ade4f765c42206e076c36dcb56f245e Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 24 Apr 2023 20:43:34 +0530 Subject: [PATCH 7/9] Added new flags to prune test for review Signed-off-by: Chirag Aggarwal --- tests/unit/borg/test_prune.py | 41 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tests/unit/borg/test_prune.py b/tests/unit/borg/test_prune.py index 2ed9c90..66cb7cd 100644 --- a/tests/unit/borg/test_prune.py +++ b/tests/unit/borg/test_prune.py @@ -166,23 +166,6 @@ def test_prune_archives_with_log_debug_calls_borg_with_debug_parameter(): ) -# def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): -# flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') -# flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER -# flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) -# flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) -# insert_execute_command_mock(PRUNE_COMMAND + ('--dry-run', 'repo'), logging.INFO) - -# prune_arguments = flexmock(stats=False, list_archives=False) -# module.prune_archives( -# repository_path='repo', -# storage_config={}, -# dry_run=True, -# retention_config=flexmock(), -# local_borg_version='1.2.3', -# prune_arguments=prune_arguments, -# ) - def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter(): flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER @@ -329,3 +312,27 @@ def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options(): local_borg_version='1.2.3', prune_arguments=prune_arguments, ) + + +def test_prune_archives_with_date_based_matching_calls_borg_with_date_based_flags(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + insert_execute_command_mock( + PRUNE_COMMAND + + ('--newer', '1d', '--newest', '1y', '--older', '1m', '--oldest', '1w', 'repo'), + logging.INFO, + ) + + prune_arguments = flexmock( + stats=False, list_archives=False, newer='1d', newest='1y', older='1m', oldest='1w' + ) + module.prune_archives( + dry_run=False, + repository_path='repo', + storage_config={}, + retention_config=flexmock(), + local_borg_version='1.2.3', + prune_arguments=prune_arguments, + ) From 32395e47f91b503f61aef592f26b2c4370b52938 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 24 Apr 2023 20:49:41 +0530 Subject: [PATCH 8/9] Added duplicate flags test for prune Signed-off-by: Chirag Aggarwal --- tests/integration/borg/test_commands.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/integration/borg/test_commands.py b/tests/integration/borg/test_commands.py index 1afb0e0..6049a26 100644 --- a/tests/integration/borg/test_commands.py +++ b/tests/integration/borg/test_commands.py @@ -106,3 +106,17 @@ def test_display_archives_info_command_does_not_duplicate_flags_or_raise(): borgmatic.borg.info.display_archives_info( 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) ) + +def test_prune_archives_command_does_not_duplicate_flags_or_raise(): + arguments = borgmatic.commands.arguments.parse_arguments('prune')['prune'] + flexmock(borgmatic.borg.prune).should_receive('execute_command').replace_with( + assert_command_does_not_duplicate_flags + ) + + for argument_name in dir(arguments): + if argument_name.startswith('_'): + continue + + borgmatic.borg.prune.prune_archives( + False, 'repo', {}, {}, '2.3.4', fuzz_argument(arguments, argument_name) + ) From 68ee9687f5e01bd5abbedb43e88f8fb02d1bcd5d Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 27 Apr 2023 22:27:23 +0530 Subject: [PATCH 9/9] Added tests for all subcommands and used black formatter Signed-off-by: Chirag Aggarwal --- borgmatic/borg/mount.py | 2 - borgmatic/borg/prune.py | 3 - borgmatic/commands/arguments.py | 80 ++++++++++++++++++------- tests/integration/borg/test_commands.py | 1 + tests/unit/borg/test_info.py | 49 +++++++++++++++ tests/unit/borg/test_mount.py | 55 ++++++++++++++++- tests/unit/borg/test_rlist.py | 42 +++++++++++++ tests/unit/borg/test_transfer.py | 47 +++++++++++++++ 8 files changed, 252 insertions(+), 27 deletions(-) diff --git a/borgmatic/borg/mount.py b/borgmatic/borg/mount.py index 764f72e..3302617 100644 --- a/borgmatic/borg/mount.py +++ b/borgmatic/borg/mount.py @@ -31,12 +31,10 @@ def mount_archive( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) - + flags.make_flags_from_arguments( mount_arguments, excludes=('repository', 'archive', 'mount_point', 'paths', 'options'), ) - + (('-o', mount_arguments.options) if mount_arguments.options else ()) + ( ( diff --git a/borgmatic/borg/prune.py b/borgmatic/borg/prune.py index ba41fba..c7d1393 100644 --- a/borgmatic/borg/prune.py +++ b/borgmatic/borg/prune.py @@ -75,16 +75,13 @@ def prune_archives( + (('--lock-wait', str(lock_wait)) if lock_wait else ()) + (('--stats',) if prune_arguments.stats and not dry_run else ()) + (('--info',) if logger.getEffectiveLevel() == logging.INFO else ()) - + flags.make_flags_from_arguments( prune_arguments, excludes=('repository', 'stats', 'list_archives'), ) + (('--list',) if prune_arguments.list_archives else ()) - + (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) else ()) + (('--dry-run',) if dry_run else ()) - + (tuple(extra_borg_options.split(' ')) if extra_borg_options else ()) + flags.make_repository_flags(repository_path, local_borg_version) ) diff --git a/borgmatic/commands/arguments.py b/borgmatic/commands/arguments.py index 7711958..4b19135 100644 --- a/borgmatic/commands/arguments.py +++ b/borgmatic/commands/arguments.py @@ -327,16 +327,24 @@ def make_parsers(): '--last', metavar='N', help='Only transfer last N archives after other filters are applied' ) transfer_group.add_argument( - '--oldest', metavar='TIMESPAN', help='Transfer archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', + metavar='TIMESPAN', + help='Transfer archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]', ) transfer_group.add_argument( - '--newest', metavar='TIMESPAN', help='Transfer archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', + metavar='TIMESPAN', + help='Transfer archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]', ) transfer_group.add_argument( - '--older', metavar='TIMESPAN', help='Transfer archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', + metavar='TIMESPAN', + help='Transfer archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) transfer_group.add_argument( - '--newer', metavar='TIMESPAN', help='Transfer archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', + metavar='TIMESPAN', + help='Transfer archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) transfer_group.add_argument( '-h', '--help', action='help', help='Show this help message and exit' @@ -365,16 +373,24 @@ def make_parsers(): '--list', dest='list_archives', action='store_true', help='List archives kept/pruned' ) prune_group.add_argument( - '--oldest', metavar='TIMESPAN', help='Prune archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', + metavar='TIMESPAN', + help='Prune archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]', ) prune_group.add_argument( - '--newest', metavar='TIMESPAN', help='Prune archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', + metavar='TIMESPAN', + help='Prune archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]', ) prune_group.add_argument( - '--older', metavar='TIMESPAN', help='Prune archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', + metavar='TIMESPAN', + help='Prune archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) prune_group.add_argument( - '--newer', metavar='TIMESPAN', help='Prune archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', + metavar='TIMESPAN', + help='Prune archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) prune_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') @@ -625,16 +641,24 @@ def make_parsers(): '--last', metavar='N', help='Mount last N archives after other filters are applied' ) mount_group.add_argument( - '--oldest', metavar='TIMESPAN', help='Mount archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', + metavar='TIMESPAN', + help='Mount archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]', ) mount_group.add_argument( - '--newest', metavar='TIMESPAN', help='Mount archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', + metavar='TIMESPAN', + help='Mount archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]', ) mount_group.add_argument( - '--older', metavar='TIMESPAN', help='Mount archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', + metavar='TIMESPAN', + help='Mount archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) mount_group.add_argument( - '--newer', metavar='TIMESPAN', help='Mount archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', + metavar='TIMESPAN', + help='Mount archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) mount_group.add_argument('--options', dest='options', help='Extra Borg mount options') mount_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') @@ -728,16 +752,24 @@ def make_parsers(): '--last', metavar='N', help='List last N archives after other filters are applied' ) rlist_group.add_argument( - '--oldest', metavar='TIMESPAN', help='List archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', + metavar='TIMESPAN', + help='List archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]', ) rlist_group.add_argument( - '--newest', metavar='TIMESPAN', help='List archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', + metavar='TIMESPAN', + help='List archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]', ) rlist_group.add_argument( - '--older', metavar='TIMESPAN', help='List archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', + metavar='TIMESPAN', + help='List archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) rlist_group.add_argument( - '--newer', metavar='TIMESPAN', help='List archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', + metavar='TIMESPAN', + help='List archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) rlist_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') @@ -871,16 +903,24 @@ def make_parsers(): '--last', metavar='N', help='Show info for last N archives after other filters are applied' ) info_group.add_argument( - '--oldest', metavar='TIMESPAN', help='Show info for archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]' + '--oldest', + metavar='TIMESPAN', + help='Show info for archives within a specified time range starting from the timestamp of the oldest archive (e.g. 7d or 12m) [Borg 2.x+ only]', ) info_group.add_argument( - '--newest', metavar='TIMESPAN', help='Show info for archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]' + '--newest', + metavar='TIMESPAN', + help='Show info for archives within a time range that ends at timestamp of the newest archive and starts a specified time range ago (e.g. 7d or 12m) [Borg 2.x+ only]', ) info_group.add_argument( - '--older', metavar='TIMESPAN', help='Show info for archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--older', + metavar='TIMESPAN', + help='Show info for archives that are older than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) info_group.add_argument( - '--newer', metavar='TIMESPAN', help='Show info for archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]' + '--newer', + metavar='TIMESPAN', + help='Show info for archives that are newer than the specified time range (e.g. 7d or 12m) from the current time [Borg 2.x+ only]', ) info_group.add_argument('-h', '--help', action='help', help='Show this help message and exit') diff --git a/tests/integration/borg/test_commands.py b/tests/integration/borg/test_commands.py index 6049a26..6c330d6 100644 --- a/tests/integration/borg/test_commands.py +++ b/tests/integration/borg/test_commands.py @@ -107,6 +107,7 @@ def test_display_archives_info_command_does_not_duplicate_flags_or_raise(): 'repo', {}, '2.3.4', fuzz_argument(arguments, argument_name) ) + def test_prune_archives_command_does_not_duplicate_flags_or_raise(): arguments = borgmatic.commands.arguments.parse_arguments('prune')['prune'] flexmock(borgmatic.borg.prune).should_receive('execute_command').replace_with( diff --git a/tests/unit/borg/test_info.py b/tests/unit/borg/test_info.py index 2eed4fe..d7bf731 100644 --- a/tests/unit/borg/test_info.py +++ b/tests/unit/borg/test_info.py @@ -433,3 +433,52 @@ def test_display_archives_info_passes_through_arguments_to_borg(argument_name): archive=None, json=False, prefix=None, match_archives=None, **{argument_name: 'value'} ), ) + + +def test_display_archives_info_with_date_based_matching_calls_borg_with_date_based_flags(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, None, '2.3.4' + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return( + ('--newer', '1d', '--newest', '1y', '--older', '1m', '--oldest', '1w') + ) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ( + 'borg', + 'info', + '--newer', + '1d', + '--newest', + '1y', + '--older', + '1m', + '--oldest', + '1w', + '--repo', + 'repo', + ), + output_log_level=module.borgmatic.logger.ANSWER, + borg_local_path='borg', + extra_environment=None, + ) + info_arguments = flexmock( + archive=None, + json=False, + prefix=None, + match_archives=None, + newer='1d', + newest='1y', + older='1m', + oldest='1w', + ) + module.display_archives_info( + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + info_arguments=info_arguments, + ) diff --git a/tests/unit/borg/test_mount.py b/tests/unit/borg/test_mount.py index 1438ebe..05ff72e 100644 --- a/tests/unit/borg/test_mount.py +++ b/tests/unit/borg/test_mount.py @@ -77,7 +77,9 @@ def test_mount_archive_calls_borg_with_path_flags(): ) insert_execute_command_mock(('borg', 'mount', 'repo::archive', '/mnt', 'path1', 'path2')) - mount_arguments = flexmock(mount_point='/mnt', options=None, paths=['path1', 'path2'], foreground=False) + mount_arguments = flexmock( + mount_point='/mnt', options=None, paths=['path1', 'path2'], foreground=False + ) module.mount_archive( repository_path='repo', archive='archive', @@ -207,7 +209,9 @@ def test_mount_archive_calls_borg_with_options_flags(): ) insert_execute_command_mock(('borg', 'mount', '-o', 'super_mount', 'repo::archive', '/mnt')) - mount_arguments = flexmock(mount_point='/mnt', options='super_mount', paths=None, foreground=False) + mount_arguments = flexmock( + mount_point='/mnt', options='super_mount', paths=None, foreground=False + ) module.mount_archive( repository_path='repo', archive='archive', @@ -215,3 +219,50 @@ def test_mount_archive_calls_borg_with_options_flags(): storage_config={}, local_borg_version='1.2.3', ) + + +def test_mount_archive_with_date_based_matching_calls_borg_with_date_based_flags(): + flexmock(module.feature).should_receive('available').and_return(True) + flexmock(module.flags).should_receive('make_repository_flags').and_return( + ( + '--repo', + 'repo', + ) + ) + insert_execute_command_mock( + ( + 'borg', + 'mount', + '--newer', + '1d', + '--newest', + '1y', + '--older', + '1m', + '--oldest', + '1w', + '--repo', + 'repo', + '--match-archives', + None, + '/mnt', + ) + ) + + mount_arguments = flexmock( + mount_point='/mnt', + options=None, + paths=None, + foreground=False, + newer='1d', + newest='1y', + older='1m', + oldest='1w', + ) + module.mount_archive( + repository_path='repo', + archive=None, + mount_arguments=mount_arguments, + storage_config={}, + local_borg_version='1.2.3', + ) diff --git a/tests/unit/borg/test_rlist.py b/tests/unit/borg/test_rlist.py index b83ba61..b6fadd1 100644 --- a/tests/unit/borg/test_rlist.py +++ b/tests/unit/borg/test_rlist.py @@ -506,3 +506,45 @@ def test_list_repository_with_json_returns_borg_output(): ) == json_output ) + + +def test_make_rlist_command_with_date_based_matching_calls_borg_with_date_based_flags(): + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').with_args( + None, None, '1.2.3' + ).and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return( + ('--newer', '1d', '--newest', '1y', '--older', '1m', '--oldest', '1w') + ) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',)) + + command = module.make_rlist_command( + repository_path='repo', + storage_config={}, + local_borg_version='1.2.3', + rlist_arguments=flexmock( + archive=None, + paths=None, + json=False, + prefix=None, + match_archives=None, + newer='1d', + newest='1y', + older='1m', + oldest='1w', + ), + ) + + assert command == ( + 'borg', + 'list', + '--newer', + '1d', + '--newest', + '1y', + '--older', + '1m', + '--oldest', + '1w', + 'repo', + ) diff --git a/tests/unit/borg/test_transfer.py b/tests/unit/borg/test_transfer.py index 8f41bf5..fd6cb19 100644 --- a/tests/unit/borg/test_transfer.py +++ b/tests/unit/borg/test_transfer.py @@ -386,3 +386,50 @@ def test_transfer_archives_with_source_repository_calls_borg_with_other_repo_fla archive=None, progress=None, match_archives=None, source_repository='other' ), ) + + +def test_transfer_archives_with_date_based_matching_calls_borg_with_date_based_flags(): + flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels') + flexmock(module.flags).should_receive('make_flags').and_return(()) + flexmock(module.flags).should_receive('make_match_archives_flags').and_return(()) + flexmock(module.flags).should_receive('make_flags_from_arguments').and_return( + ('--newer', '1d', '--newest', '1y', '--older', '1m', '--oldest', '1w') + ) + flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo')) + flexmock(module.environment).should_receive('make_environment') + flexmock(module).should_receive('execute_command').with_args( + ( + 'borg', + 'transfer', + '--newer', + '1d', + '--newest', + '1y', + '--older', + '1m', + '--oldest', + '1w', + '--repo', + 'repo', + ), + output_log_level=module.borgmatic.logger.ANSWER, + output_file=None, + borg_local_path='borg', + extra_environment=None, + ) + + module.transfer_archives( + dry_run=False, + repository_path='repo', + storage_config={}, + local_borg_version='2.3.4', + transfer_arguments=flexmock( + archive=None, + progress=None, + source_repository='other', + newer='1d', + newest='1y', + older='1m', + oldest='1w', + ), + )