summaryrefslogtreecommitdiff
path: root/repository.py
diff options
context:
space:
mode:
Diffstat (limited to 'repository.py')
-rw-r--r--repository.py81
1 files changed, 81 insertions, 0 deletions
diff --git a/repository.py b/repository.py
new file mode 100644
index 0000000..98a4984
--- /dev/null
+++ b/repository.py
@@ -0,0 +1,81 @@
+import fcntl
+import os
+import os.path
+import subprocess
+
+class StepResult:
+ retcode = None
+ output = None
+ def __init__(self, retcode = 0, output = None):
+ self.retcode = retcode
+ self.output = output
+
+class BackupResult:
+ target_results = None
+ par2_result = None
+
+ def __init__(self):
+ self.target_results = []
+ self.par2_result = StepResult()
+
+ @property
+ def all_ok(self):
+ return (all(map(lambda tgtres: tgtres.retcode == 0, self.target_results)) and
+ self.par2_result.retcode == 0)
+
+
+class Repo:
+ """
+ A single Bup repository into which the data will be backed up, plus a
+ separate directory for extra runtime data.
+
+ :param str bup_dir: path to the bup repository, defaults to BUP_DIR or ~/.bup
+ :param str data_dir: path to the directory for storing the runtime data,
+ defaults to ~/.local/var/bupper
+ """
+ bup_dir = None
+ data_dir = None
+ lock_name = 'lock'
+
+ def __init__(self, bup_dir = None, data_dir = None):
+ if bup_dir is None:
+ if 'BUP_DIR' in os.environ:
+ bup_dir = os.environ['BUP_DIR']
+ else:
+ bup_dir = os.path.expanduser('~/.bup')
+
+ if data_dir is None:
+ data_dir = os.path.expanduser('~/.local/var/bupper/')
+
+ # create the data dir, if it does not already exist
+ os.makedirs(data_dir, 0o700, exist_ok = True)
+
+ self.bup_dir = bup_dir
+ self.data_dir = data_dir
+
+ def backup(self, tgts, gen_par2 = True):
+ """
+ Backup the supplied targets.
+
+ :param list of Target tgts: List of targets to back up.
+ :param bool gen_par2: Whether to generate par2 recovery information
+ after the backup concludes'
+ """
+ with open(os.path.join(self.data_dir, self.lock_name), 'w') as lockfile:
+ result = BackupResult()
+
+ fcntl.lockf(lockfile, fcntl.LOCK_EX)
+ try:
+ for tgt in tgts:
+ res = tgt.save(self.data_dir)
+ result.target_results.append(res)
+
+ if gen_par2:
+ res = subprocess.run(['bup', 'fsck', '-g'],
+ capture_output = True)
+ result.par2_result = StepResult(res.returncode,
+ res.stderr + res.stdout)
+ finally:
+ fcntl.lockf(lockfile, fcntl.LOCK_UN)
+
+ return result