Skip to content

Commit

Permalink
Added run_before_borg and run_after_borg settings; run_after* command…
Browse files Browse the repository at this point in the history
…s now always run.
  • Loading branch information
Ken Kundert authored and Ken Kundert committed Feb 10, 2022
1 parent 53b74cd commit aad5100
Show file tree
Hide file tree
Showing 13 changed files with 557 additions and 200 deletions.
4 changes: 2 additions & 2 deletions doc/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ here. Run ``emborg help <cmd>`` for the details.
.. _exit status:

Exit Status
----------
-----------

*Emborg* returns with an exit status of 0 if it completes without issue. It
returns with an exit status of 1 if was able to terminate normally but some
exceptional condition was encountered along the way. For example, if the
:ref:`compare <compare>` or :ref:`diff <diff>` detects a difference or if
:due:`due <due>` command detects the backups are overdue, a 1 is returned. In
:ref:`due <due>` command detects the backups are overdue, a 1 is returned. In
addition, 1 is returned if *Borg* detects an error but is able to complete
anyway. However, if *Emborg* or *Borg* suffers errors and cannot complete, 2 is
returned.
Expand Down
15 changes: 15 additions & 0 deletions doc/configuring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,21 @@ specifies identical commands to *run_before_first_backup* for each configuration
in a composite configuration with the intent that the commands will be run only
once regardless whether the configurations are run individually or as a group.


.. _run_before_borg:
.. _run_after_borg:

run_before_borg, run_after_borg
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Specifies commands that are to be run before the first *Borg* command is run or
after the last one is run. These can be used, for example, to mount and then
unmount a remote repository, if such a thing is needed.

May be specified as a list of strings or as a multi-line string with one command
per line (lines that begin with ``#`` are ignored).


.. _show_progress:

show_progress
Expand Down
3 changes: 3 additions & 0 deletions doc/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Latest development release
| Version: 1.30.0
| Released: 2022-01-04
- Added the :ref:`run_before_borg and run_after_borg <run_before_borg>`
settings.


1.30 (2022-01-04)
-----------------
Expand Down
71 changes: 35 additions & 36 deletions emborg/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ class CompareCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] compare [<path>]
emborg compare [options] [<path>]
Options:
-a <archive>, --archive <archive> name of the archive to mount
Expand Down Expand Up @@ -622,18 +622,18 @@ def run(cls, command, args, settings, options):
culprit = ("must_exist", path),
)

# run prerequisites
# run commands specified to be run before a backup
prerequisite_settings = []
if settings.is_first_config():
pre_script_settings = ["run_before_first_backup", "run_before_backup"]
else:
pre_script_settings = ["run_before_backup"]
for setting in pre_script_settings:
prerequisite_settings.append("run_before_first_backup")
prerequisite_settings.append("run_before_backup")
for setting in prerequisite_settings:
for i, cmd in enumerate(settings.values(setting)):
narrate(f"staging {setting}[{i}] pre-backup script")
try:
Run(cmd, "SoEW")
except Error as e:
e.reraise(culprit=(setting, cmd.split()[0]))
e.reraise(culprit=(setting, i, cmd.split()[0]))

# run borg
src_dirs = settings.src_dirs
Expand All @@ -653,25 +653,24 @@ def run(cls, command, args, settings, options):
e.reraise(codicil="Run 'emborg init' to initialize the repository.")
else:
raise
finally:
# run commands specified to be run after a backup
postrequisite_settings = ["run_after_backup"]
if settings.is_last_config():
postrequisite_settings.append("run_after_last_backup")
for setting in postrequisite_settings:
for i, cmd in enumerate(settings.values(setting)):
narrate(f"staging {setting}[{i}] post-backup script")
try:
Run(cmd, "SoEW")
except Error as e:
e.reraise(culprit=(setting, i, cmd.split()[0]))

# update the date files
narrate("update date file")
now = arrow.now()
settings.date_file.write_text(str(now))

# run scripts specified to be run after a backup
if settings.is_last_config():
post_script_settings = ["run_after_backup", "run_after_last_backup"]
else:
post_script_settings = ["run_after_backup"]
for setting in post_script_settings:
for i, cmd in enumerate(settings.values(setting)):
narrate(f"staging {setting}[{i}] post-backup script")
try:
Run(cmd, "SoEW")
except Error as e:
e.reraise(culprit=(setting, cmd.split()[0]))

if cmdline["--fast"]:
return create_status

Expand Down Expand Up @@ -725,7 +724,7 @@ class DeleteCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] delete [<archive>]
emborg delete [options] [<archive>]
Options:
-r, --repo delete entire repository
Expand Down Expand Up @@ -986,7 +985,7 @@ class ExtractCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] extract <path>...
emborg extract [options] <path>...
Options:
-a <archive>, --archive <archive> name of the archive to use
Expand Down Expand Up @@ -1129,7 +1128,7 @@ class InfoCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] info
emborg info [options]
Options:
-f, --fast only report local information
Expand Down Expand Up @@ -1220,9 +1219,9 @@ class ListCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] list
emborg [options] archives
emborg [options] lr
emborg list [options]
emborg archives [options]
emborg lr [options]
Options:
-e, --include-external list all archives in repository, not just
Expand Down Expand Up @@ -1285,11 +1284,11 @@ class ManifestCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] manifest [<path>]
emborg [options] m [<path>]
emborg [options] la [<path>]
emborg [options] files [<path>]
emborg [options] f [<path>]
emborg manifest [options] [<path>]
emborg m [options] [<path>]
emborg la [options] [<path>]
emborg files [options] [<path>]
emborg f [options] [<path>]
Options:
-a <archive>, --archive <archive> name of the archive to use
Expand Down Expand Up @@ -1530,7 +1529,7 @@ class MountCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] mount [<mount_point>]
emborg mount [options] [<mount_point>]
Options:
-a <archive>, --archive <archive> name of the archive to mount
Expand Down Expand Up @@ -1631,7 +1630,7 @@ class PruneCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] prune
emborg prune [options]
Options:
-e, --include-external prune all archives in repository, not just
Expand Down Expand Up @@ -1689,7 +1688,7 @@ class RestoreCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] restore <path>...
emborg restore [options] <path>...
Options:
-a <archive>, --archive <archive> name of the archive to use
Expand Down Expand Up @@ -1773,8 +1772,8 @@ class SettingsCommand(Command):
USAGE = dedent(
"""
Usage:
emborg [options] settings [<name>]
emborg [options] setting [<name>]
emborg settings [options] [<name>]
emborg setting [options] [<name>]
Options:
-a, --available list available settings
Expand Down
2 changes: 2 additions & 0 deletions emborg/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
run_before_backup="commands to run before archive is created",
run_after_last_backup="commands to run after last archive has been created",
run_before_first_backup="commands to run before first archive is created",
run_after_borg="commands to run after last Borg command has run",
run_before_borg="commands to run before first Borg command is run",
show_progress="show borg progress when running create command",
show_stats="show borg statistics when running create, delete, and prune commands",
src_dirs="the directories to archive",
Expand Down
27 changes: 27 additions & 0 deletions emborg/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
if "arg" in attrs and attrs["arg"]:
borg_options_arg_count[convert_name_to_option(name)] = 1


# ConfigQueue {{{2
class ConfigQueue:
def __init__(self, command=None):
Expand Down Expand Up @@ -213,6 +214,7 @@ def __init__(self, config=None, emborg_opts=(), _queue=None):
self.check()
set_shlib_prefs(encoding=self.encoding if self.encoding else DEFAULT_ENCODING)
self.hooks = Hooks(self)
self.borg_ran = False

# set colorscheme
if self.colorscheme:
Expand Down Expand Up @@ -637,6 +639,19 @@ def publish_passcode(self):
return
raise Error("Cannot determine the encryption passphrase.")

# run_user_commands() {{[2
def run_user_commands(self, setting):
for i, cmd in enumerate(self.values(setting)):
narrate(f"staging {setting}[{i}] command.")
try:
Run(cmd, "SoEW")
except Error as e:
e.reraise(culprit=(setting, i, cmd.split()[0]))

# the following two statements are only useful from run_before_borg
self.settings[setting] = [] # erase the setting so it is not run again
self.borg_ran = True # indicate that before has run so after should run

# run_borg() {{{2
def run_borg(
self,
Expand All @@ -648,6 +663,10 @@ def run_borg(
show_borg_output=False,
use_working_dir=False,
):

# run the run_before_borg commands
self.run_user_commands('run_before_borg')

# prepare the command
self.publish_passcode()
if "BORG_PASSPHRASE" in os.environ:
Expand Down Expand Up @@ -718,11 +737,15 @@ def run_borg(
if borg.stderr:
narrate("Borg stderr:")
narrate(indent(borg.stderr))

return borg

# run_borg_raw() {{{2
def run_borg_raw(self, args):

# run the run_before_borg commands
self.run_user_commands('run_before_borg')

# prepare the command
self.publish_passcode()
os.environ["BORG_DISPLAY_PASSPHRASE"] = "no"
Expand Down Expand Up @@ -918,6 +941,10 @@ def __enter__(self):
# exit {{{2
def __exit__(self, exc_type, exc_val, exc_tb):

# run the run_after_borg commands
if self.borg_ran:
self.run_user_commands('run_after_borg')

# delete lockfile
if self.requires_exclusivity:
self.lockfile.unlink()
15 changes: 15 additions & 0 deletions tests/CONFIGS/test0
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,18 @@ excludes = [
'sh:**/.*.swp',
'sh:**/.*.swo',
]

run_before_backup = """
# this line is ignored
echo run_before_backup on test0
"""
run_before_first_backup = "echo run_before_first_backup on test0"
run_before_borg = ["echo run_before_borg on test0"]
run_after_backup = """
# this line is ignored
echo run_after_backup on test0
"""
run_after_last_backup = [
"echo run_after_last_backup on test0",
]
run_after_borg = "echo run_after_borg on test0"
14 changes: 14 additions & 0 deletions tests/CONFIGS/test1
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,17 @@ excludes = '''
sh:**/.*.swo
'''

run_before_backup = """
# this line is ignored
echo run_before_backup on test1
"""
run_before_first_backup = "echo run_before_first_backup on test1"
run_before_borg = ["echo run_before_borg on test1"]
run_after_backup = """
# this line is ignored
echo run_after_backup on test1
"""
run_after_last_backup = [
"echo run_after_last_backup on test1",
]
run_after_borg = "echo run_after_borg on test1"
15 changes: 15 additions & 0 deletions tests/CONFIGS/test2
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,18 @@ passcommand = 'cat {config_dir}/test2passphrase'
src_dirs = '~'.split()

exclude_from = '{config_dir}/test2excludes'

run_before_backup = """
# this line is ignored
echo run_before_backup on test2
"""
run_before_first_backup = "echo run_before_first_backup on test2"
run_before_borg = ["echo run_before_borg on test2"]
run_after_backup = """
# this line is ignored
echo run_after_backup on test2
"""
run_after_last_backup = [
"echo run_after_last_backup on test2",
]
run_after_borg = "echo run_after_borg on test2"
15 changes: 15 additions & 0 deletions tests/CONFIGS/test3
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,18 @@ patterns = '''- ~/repositories
- **/.viminfo
- **/.*.swp
- **/.*.swo'''

run_before_backup = """
# this line is ignored
echo run_before_backup on test3
"""
run_before_first_backup = "echo run_before_first_backup on test3"
run_before_borg = ["echo run_before_borg on test3"]
run_after_backup = """
# this line is ignored
echo run_after_backup on test3
"""
run_after_last_backup = [
"echo run_after_last_backup on test3",
]
run_after_borg = "echo run_after_borg on test3"

0 comments on commit aad5100

Please sign in to comment.