Created
March 3, 2019 10:33
-
-
Save VarunBarad/c291e98dd426b0da1322171290d7bbd0 to your computer and use it in GitHub Desktop.
Script to create a single-file backup of a git repository
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
import os | |
import sys | |
import re | |
import shutil | |
from git import Repo | |
from zipfile import ZipFile | |
def create_backup_zip(directory_to_backup): | |
parent_directory, directory_name = os.path.split(directory_to_backup) | |
repository = Repo(directory_to_backup) | |
git_handle = repository.git | |
git_bundle_file_name = os.path.join(parent_directory, (directory_name + '.bundle')) | |
git_handle.bundle('create', git_bundle_file_name, '--all') | |
pattern_for_untracked_files_flag = re.compile(r'^\?+$') | |
non_staged_files_raw_output = git_handle.status('--porcelain') | |
if len(non_staged_files_raw_output.strip()) > 0: | |
non_staged_files = list(filter( | |
lambda x: pattern_for_untracked_files_flag.match(x[0]) is None, | |
list(map(lambda _: _.strip().split(), non_staged_files_raw_output.split(os.linesep))) | |
)) | |
else: | |
non_staged_files = [] | |
if len(non_staged_files) > 0: | |
git_handle.stash('push', '-m', 'git-backup-stash') | |
stashes = git_handle.stash('list').strip() | |
stash_list = stashes.split(os.linesep) | |
patch_files = [] | |
if (len(stashes) > 0) and (len(stash_list) > 0): | |
patch_files_directory = os.path.join(parent_directory, 'patch-files') | |
os.makedirs(patch_files_directory, exist_ok=True) | |
for stash in stash_list: | |
stash_name = stash.split(': ')[0] | |
stash_branch_name = stash.split(': ')[1].split()[1] | |
stash_message = ': '.join(stash.split(': ')[2:]) | |
patch_file_name = ':'.join([stash_name, stash_branch_name, stash_message]) + '.txt' | |
patch_file_path = os.path.join(patch_files_directory, patch_file_name) | |
patch_contents = git_handle.stash('show', '-p', stash_name) | |
with open(patch_file_path, 'x') as f: | |
f.write(patch_contents) | |
patch_files.append(patch_file_path) | |
zip_file_name = directory_name + '.zip' | |
zip_file_path = os.path.join(parent_directory, zip_file_name) | |
with ZipFile(zip_file_path, 'x') as z: | |
z.write(git_bundle_file_name, arcname=os.path.split(git_bundle_file_name)[1]) | |
for patch_file in patch_files: | |
z.write(patch_file, arcname=os.path.join('patch-files', os.path.split(patch_file)[1])) | |
os.remove(git_bundle_file_name) | |
if len(patch_files) > 0: | |
shutil.rmtree(patch_files_directory) | |
print(zip_file_name + ' created') | |
if __name__ == "__main__": | |
arguments = sys.argv[1:] | |
if len(arguments) == 0: | |
directory_to_backup = os.getcwd() | |
else: | |
directory_to_backup = arguments[0] | |
directory_to_backup = os.path.abspath(directory_to_backup) | |
git_directory = os.path.join(directory_to_backup, '.git') | |
if os.path.exists(git_directory) and os.path.isdir(git_directory): | |
create_backup_zip(directory_to_backup) | |
else: | |
print(directory_to_backup + ' is not a git repository') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks @flandersen
I really liked how you have put the documentation at the top of the script in comments 💯