#!/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')