sphinx-multiversion/sphinx_multiversion/git.py
2020-02-23 17:10:33 +01:00

63 lines
2 KiB
Python

# -*- coding: utf-8 -*-
import collections
import tempfile
import subprocess
import re
import tarfile
GitRef = collections.namedtuple('VersionRef', [
'name',
'commit',
'source',
'is_remote',
'refname',
])
def get_all_refs(gitroot):
cmd = ("git", "for-each-ref", "--format", "%(objectname) %(refname)", "refs")
output = subprocess.check_output(cmd, cwd=gitroot).decode()
for line in output.splitlines():
is_remote = False
line = line.strip()
# Parse refname
matchobj = re.match(r"^(\w+) refs/(heads|tags|remotes/[^/]+)/(\S+)$", line)
if not matchobj:
continue
commit = matchobj.group(1)
source = matchobj.group(2)
name = matchobj.group(3)
refname = line.partition(' ')[2]
if source.startswith('remotes/'):
is_remote = True
yield GitRef(name, commit, source, is_remote, refname)
def get_refs(gitroot, tag_whitelist, branch_whitelist, remote_whitelist):
for ref in get_all_refs(gitroot):
if ref.source == 'tags':
if tag_whitelist is None or not re.match(tag_whitelist, ref.name):
continue
elif ref.source == 'heads':
if branch_whitelist is None or not re.match(branch_whitelist, ref.name):
continue
elif ref.is_remote and remote_whitelist is not None:
remote_name = ref.source.partition('/')[2]
if not re.match(remote_whitelist, remote_name):
continue
if branch_whitelist is None or not re.match(branch_whitelist, ref.name):
continue
else:
continue
yield ref
def copy_tree(src, dst, reference, sourcepath='.'):
with tempfile.SpooledTemporaryFile() as fp:
cmd = ("git", "archive", "--format", "tar", reference.commit, "--", sourcepath)
subprocess.check_call(cmd, stdout=fp)
fp.seek(0)
with tarfile.TarFile(fileobj=fp) as tarfp:
tarfp.extractall(dst)