diff options
| author | Max Resnick <max@ofmax.li> | 2020-01-18 12:15:27 -0800 |
|---|---|---|
| committer | Max Resnick <max@ofmax.li> | 2020-01-18 12:15:27 -0800 |
| commit | 1b8767584a41f3163293f890abc901c23e78dce2 (patch) | |
| tree | 06de6a43d2b856c7d2cf062e136f57bbd4ddf953 | |
| parent | ddf94e407ca1debfaf06cd7314a7922e31d029a8 (diff) | |
| download | git-snapshot-1b8767584a41f3163293f890abc901c23e78dce2.tar.gz | |
initial pass at snapshotter
| -rw-r--r-- | VERSION | 1 | ||||
| -rw-r--r-- | gitsnap/restore.py | 76 | ||||
| -rw-r--r-- | setup.py | 33 |
3 files changed, 110 insertions, 0 deletions
@@ -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']) + |