borgmatic without arguments/parameters should show usage help instead of starting a backup (#262).

Reviewed-on: borgmatic-collective/borgmatic#1046
This commit is contained in:
2025-03-30 01:57:11 +00:00
4 changed files with 91 additions and 0 deletions

View File

@@ -954,6 +954,21 @@ def exit_with_help_link(): # pragma: no cover
sys.exit(1)
def check_and_show_help_on_no_args(configs):
"""
Check if the 'borgmatic' command is run without any arguments. If the configuration option
'default_actions' is set to False, show the help message. Otherwise, trigger the
default backup behavior.
"""
if len(sys.argv) == 1: # No arguments provided
default_actions = any(
config.get('default_actions', True) for config in configs.values()
)
if not default_actions:
parse_arguments('--help')
sys.exit(0)
def main(extra_summary_logs=[]): # pragma: no cover
configure_signals()
configure_delayed_logging()
@@ -989,6 +1004,10 @@ def main(extra_summary_logs=[]): # pragma: no cover
global_arguments.overrides,
resolve_env=global_arguments.resolve_env and not validate,
)
# Use the helper function to check and show help on no arguments, passing the preloaded configs
check_and_show_help_on_no_args(configs)
configuration_parse_errors = (
(max(log.levelno for log in parse_logs) >= logging.CRITICAL) if parse_logs else False
)

View File

@@ -2685,3 +2685,11 @@ properties:
example: /usr/local/bin/keepassxc-cli
description: |
Configuration for integration with the KeePassXC password manager.
default_actions:
type: boolean
description: |
Whether to apply default actions (e.g., backup) when no arguments
are supplied to the borgmatic command. If set to true, borgmatic
will trigger the default actions(create, prune, compact and check).
If set to false, borgmatic will display the help message instead.
example: true

View File

@@ -296,6 +296,20 @@ skip_actions:
- compact
```
### Disabling default actions
By default, running `borgmatic` without any arguments will perform the default
backup actions (create, prune, compact and check). If you want to disable this
behavior and require explicit actions to be specified, add the following to
your configuration:
```yaml
default_actions: false
```
With this setting, running `borgmatic` without arguments will show the help
message instead of performing any actions.
## Autopilot

View File

@@ -2120,3 +2120,53 @@ def test_collect_configuration_run_summary_logs_outputs_merged_json_results():
arguments=arguments,
)
)
def test_check_and_show_help_on_no_args_shows_help_when_no_args_and_default_actions_false():
flexmock(module.sys).should_receive('argv').and_return(['borgmatic'])
flexmock(module).should_receive('parse_arguments').with_args('--help').once()
flexmock(module.sys).should_receive('exit').with_args(0).once()
module.check_and_show_help_on_no_args({'test.yaml': {'default_actions': False}})
def test_check_and_show_help_on_no_args_does_not_show_help_when_no_args_and_default_actions_true():
flexmock(module.sys).should_receive('argv').and_return(['borgmatic'])
flexmock(module).should_receive('parse_arguments').never()
flexmock(module.sys).should_receive('exit').never()
module.check_and_show_help_on_no_args({'test.yaml': {'default_actions': True}})
def test_check_and_show_help_on_no_args_does_not_show_help_when_args_provided():
flexmock(module.sys).should_receive('argv').and_return(['borgmatic', '--create'])
flexmock(module).should_receive('parse_arguments').never()
flexmock(module.sys).should_receive('exit').never()
module.check_and_show_help_on_no_args({'test.yaml': {'default_actions': False}})
def test_check_and_show_help_on_no_args_with_no_default_actions_in_all_configs():
flexmock(module.sys).should_receive('argv').and_return(['borgmatic'])
# Both configs have default_actions set to False, so help should be shown
configs = {
'config1.yaml': {'default_actions': False},
'config2.yaml': {'default_actions': False}
}
# Expect help to be shown
flexmock(module).should_receive('parse_arguments').with_args('--help').once()
flexmock(module.sys).should_receive('exit').with_args(0).once()
module.check_and_show_help_on_no_args(configs)
def test_check_and_show_help_on_no_args_with_conflicting_configs():
flexmock(module.sys).should_receive('argv').and_return(['borgmatic'])
# Simulate two config files with conflicting 'default_actions' values
configs = {
'config1.yaml': {'default_actions': True},
'config2.yaml': {'default_actions': False}
}
# Expect help not to be shown because at least one config enables default actions
flexmock(module).should_receive('parse_arguments').never()
flexmock(module.sys).should_receive('exit').never()
module.check_and_show_help_on_no_args(configs)