#!/usr/bin/env python3 ## Copyright 2005-2015 Linus Torvalds and others ## Copyright 2015, 2019, 2020 Codethink Limited ## ## Based on git's contrib/fast-import/import-zips.py; modified for Lorry. ## zip archive frontend for git-fast-import ## ## For example: ## ## mkdir project; cd project; git init ## python import-zips.py *.zip ## git log --stat import-zips import calendar import os.path import struct import subprocess import sys from zipfile import ZipFile branch_name = 'master' branch_ref = 'refs/heads/%s' % branch_name committer_name = 'Lorry Zip Importer' committer_email = 'lorry-zip-importer@lorry' # File header 'extra' field tags EXT_TAG_UNIX0 = 0x000d # PKWARE Unix, aka Unix type 0 EXT_TAG_TIME = 0x5455 # Extended Timestamp EXT_TIME_FLAG_MTIME = 1 # mtime present (and first) EXT_TAG_UNIX1 = 0x5855 # Info-ZIP Unix type 1 # Iterate over fields within a file header 'extra' block def zip_extra_fields(extra): pos = 0 while len(extra) >= pos + 4: tag, size = struct.unpack('= 1 and data[0] & EXT_TIME_FLAG_MTIME: format = '= min_len: return struct.unpack(format, data[:min_len])[0] # Timestamps in the main header are in local time, but the time # zone offset is unspecified. We choose to interpret them as UTC. return calendar.timegm(info.date_time + (0, 0, 0)) def export(zipfile, fast_import): def printlines(list): for str in list: fast_import.write(str.encode('utf-8') + b"\n") commit_time = 0 next_mark = 1 common_prefix = None mark = dict() zip = ZipFile(zipfile, 'r') for name in zip.namelist(): if name.endswith('/'): continue info = zip.getinfo(name) commit_time = max(commit_time, zip_info_mtime(info)) if common_prefix == None: common_prefix = name[:name.rfind('/') + 1] else: while not name.startswith(common_prefix): last_slash = common_prefix[:-1].rfind('/') + 1 common_prefix = common_prefix[:last_slash] mark[name] = ':' + str(next_mark) next_mark += 1 printlines(('blob', 'mark ' + mark[name], \ 'data ' + str(info.file_size))) fast_import.write(zip.read(name) + b"\n") committer = committer_name + ' <' + committer_email + '> %d +0000' % \ commit_time zipfile_basename = os.path.basename(zipfile) printlines(('commit ' + branch_ref, 'committer ' + committer, \ 'data <...') sys.exit(1) with subprocess.Popen('git fast-import --quiet', shell=True, stdin=subprocess.PIPE) as import_proc: for zipfile in sys.argv[1:]: export(zipfile, import_proc.stdin) import_proc.stdin.close() if import_proc.wait() != 0: sys.exit(1) main()