aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Resnick <max@ofmax.li>2020-01-18 12:15:27 -0800
committerMax Resnick <max@ofmax.li>2020-01-18 12:15:27 -0800
commit1b8767584a41f3163293f890abc901c23e78dce2 (patch)
tree06de6a43d2b856c7d2cf062e136f57bbd4ddf953
parentddf94e407ca1debfaf06cd7314a7922e31d029a8 (diff)
downloadgit-snapshot-1b8767584a41f3163293f890abc901c23e78dce2.tar.gz
initial pass at snapshotter
-rw-r--r--VERSION1
-rw-r--r--gitsnap/restore.py76
-rw-r--r--setup.py33
3 files changed, 110 insertions, 0 deletions
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..a4a32c3
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+v0.0.1-alpha.1
diff --git a/gitsnap/restore.py b/gitsnap/restore.py
new file mode 100644
index 0000000..186214b
--- /dev/null
+++ b/gitsnap/restore.py
@@ -0,0 +1,76 @@
+import os
+import argparse
+from pathlib import Path
+import datetime
+from functools import wraps
+
+from sh.contrib import git
+import boto3
+
+s3 = boto3.resource('s3')
+
+
+parser = argparse.ArgumentParser()
+subparsers = parser.add_subparsers(dest='cmd', help='sub-command help')
+
+parser_backup= subparsers.add_parser('backup', help='backup repositories')
+parser_backup.add_argument('repositories', help='directory with repos')
+
+# create the parser for the "b" command
+parser_b = subparsers.add_parser('b', help='b help')
+parser_b.add_argument('--baz', choices='XYZ', help='baz help')
+
+args = parser.parse_args()
+
+
+def logit(func):
+ @wraps(func)
+ def with_logging(*args, **kwargs):
+ print(func.__name__ + " was called")
+ return func(*args, **kwargs)
+ return with_logging
+
+def cloud_object(bundle, prefix, bucket):
+ obj = s3.Object(bucket, f'{prefix}/{bundle.name}')
+ obj.upload_file(str(bundle))
+ return obj
+
+def backup_repo(repo, repo_name):
+ # new repo or backup
+ ts = datetime.datetime.utcnow().timestamp()
+ bundle_path = Path(f'{repo_name}.{ts}.bundle')
+ repo.bundle('create', bundle_path, '--all')
+ return bundle_path
+
+def tag_checkpoint(repo):
+ last_hash = repo('rev-list', '-n', 1, '--all').strip()
+ repo.tag('-f', 'CHECKPOINT', last_hash)
+
+def requires_backup(repo):
+ last_hash = repo.rev_list('rev-list', '-n', 1, '--all').strip()
+ # empty repo
+ if not last_hash:
+ return False
+ try:
+ checkpoint = repo.rev_list('rev-list', '-n', 1, 'CHECKPOINT').strip()
+ # no checkpoint exists
+ except sh.ErrorReturnCode_1:
+ return True
+ return True ^ (last_hash == checkpoint)
+
+def run_restore(bundle):
+ pass
+
+def run_backup(base):
+ repo_base_path = Path(base)
+ for repo_path in repo_base_path.glob('*.git'):
+ repo = git.bake(f'--git-dir={repo_path}/')
+ if requires_backup:
+ bundle_path = backup_repo(repo, repo_path.name.split('.')[0])
+ obj = cloud_object(bundle_path, '2', 'privategit')
+ tag_checkpoint(repo)
+
+if args.cmd == 'backup':
+ run_backup(args.repositories)
+elif args.cmd == 'restore':
+ run_restore(args.bundle)
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..a284405
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,33 @@
+"""setup"""
+
+from setuptools import setup
+
+
+with open('VERSION', 'r') as version_file:
+ version = version_file.read().strip()
+
+setup(name='gitsnap',
+ version=version,
+ description='distributed observability of systemd',
+ long_description=" ".join("""
+ simple tools for snapshotting git repos
+ """.split()),
+ author='Max Resnick',
+ author_email='max@ofmax.li',
+ url='http://git.ofmax.li/gitsnap.git/',
+ license="MIT",
+ py_modules=['gitsnap'],
+ packages=[],
+ install_requires=[
+ 'sh',
+ 'boto3'
+ ],
+ keywords='',
+ classifiers=[
+ 'Development Status :: 3 - Alpha',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: Python',
+ 'Topic :: Software Development :: Libraries',
+ 'Topic :: Utilities'])
+