sphinx-multiversion/sphinx_multiversion/git.py
2020-03-11 13:42:49 +01:00

89 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
import collections
import datetime
import tempfile
import subprocess
import re
import tarfile
GitRef = collections.namedtuple(
"VersionRef",
["name", "commit", "source", "is_remote", "refname", "creatordate",],
)
def get_all_refs(gitroot):
cmd = (
"git",
"for-each-ref",
"--format",
"%(objectname)\t%(refname)\t%(creatordate:iso)",
"refs",
)
output = subprocess.check_output(cmd, cwd=gitroot).decode()
for line in output.splitlines():
is_remote = False
fields = line.strip().split("\t")
if len(fields) != 3:
continue
commit = fields[0]
refname = fields[1]
creatordate = datetime.datetime.strptime(
fields[2], "%Y-%m-%d %H:%M:%S %z"
)
# Parse refname
matchobj = re.match(
r"^refs/(heads|tags|remotes/[^/]+)/(\S+)$", refname
)
if not matchobj:
continue
source = matchobj.group(1)
name = matchobj.group(2)
if source.startswith("remotes/"):
is_remote = True
yield GitRef(name, commit, source, is_remote, refname, creatordate)
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)