import requests import json import sys import os import os.path import errno import subprocess import re import shutil from urlparse import urlparse, urljoin # Update or create the github mirror. def mirror_boostorg(root_dir): mirror_dir = os.path.join(root_dir, 'mirror') url = 'https://api.github.com/orgs/boostorg/repos' while (url) : r = requests.get(url) if (not r.ok): raise Exception("Error getting: " + url) for repo in json.loads(r.text or r.content): print "Downloading " + repo['name'] url = repo['clone_url'] # Not using os.path.join because url path is absolute. path = mirror_dir + urlparse(url).path mkdir_p(os.path.join(path, os.pardir)) # TODO: Check that path is actually a git repo? if os.path.isdir(path): subprocess.check_call(["git", "--git-dir=" + path, "fetch"]) else: subprocess.check_call(["git", "clone", "--mirror", url, path]) url = r.links['next']['url'] if 'next' in r.links else False # Export the full tree from the mirror def mirror_export(root_dir, dst_dir, branch = 'master', eol = 'lf'): git_flags = "-c core.autocrlf=false -c core.eol="+ eol boost_module_dir = os.path.join(root_dir, 'mirror/boostorg/boost.git') os.mkdir(dst_dir) export_single_repo(boost_module_dir, dst_dir, branch, eol) module_settings = get_submodule_settings(dst_dir) hashes = get_submodule_hashes(boost_module_dir, branch, [ module_settings[x]['path'] for x in module_settings ]) # Export child submodules for name, module in module_settings.iteritems(): print "Exporting submodule " + name if module['path'] not in hashes: raise Exception('No hash for module ' + name) export_single_repo( urljoin(boost_module_dir + '/', module['url']), os.path.join(dst_dir, module['path']), hashes[module['path']], eol) # Export from a single git repo def export_single_repo(git_dir, dst_dir, ref, eol): ps = subprocess.Popen( ["git", "-c", "core.autocrlf=false", "-c", "core.eol=" + eol, "--git-dir=" + git_dir, "archive", ref], stdout=subprocess.PIPE) subprocess.check_call(['tar', '-x', '-C', dst_dir], stdin=ps.stdout) # Load the submodule settings from an exported repo. def get_submodule_settings(dst_dir): module_settings = {} for line in subprocess.Popen( [ 'git', 'config', '-f', dst_dir + "/.gitmodules", "-l" ], stdout=subprocess.PIPE).stdout: result = re.match('submodule\.([^.]*)\.([^.]*)=(.*)', line) if result.group(1) not in module_settings: module_settings[result.group(1)] = { 'name': result.group(1) } module_settings[result.group(1)][result.group(2)] = result.group(3) return module_settings # Load the submodule hashes from the given paths def get_submodule_hashes(boost_module_dir, branch, paths): hashes = {} for line in subprocess.Popen( [ 'git', '--git-dir=' + boost_module_dir, 'ls-tree', branch ] + paths, stdout=subprocess.PIPE).stdout: result = re.match('160000 commit ([0-9a-zA-Z]+)\t(.*)', line) hashes[result.group(2)] = result.group(1) return hashes # Equivalent to mkdir -p # From http://stackoverflow.com/a/600612/2434 def mkdir_p(path): path = os.path.realpath(path) try: os.makedirs(path) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(path): pass else: raise ############################################################################### def export_boost(root_dir, branch, eol): dir = os.path.join(root_dir, branch + '-' + eol) if os.path.isdir(dir): shutil.rmtree(dir) mirror_export(root_dir, dir, branch, eol) root=os.path.dirname(sys.argv[0]) print "Update mirror" print mirror_boostorg(root) print "Export master-crlf" print export_boost(root, 'master', 'crlf') print "Export develop-lf" print export_boost(root, 'develop', 'lf')