2020-02-19 17:18:09 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import collections
|
2020-02-25 15:22:10 +01:00
|
|
|
import datetime
|
2020-02-21 14:01:09 +01:00
|
|
|
import tempfile
|
2020-02-19 17:18:09 +01:00
|
|
|
import subprocess
|
|
|
|
import re
|
2020-02-21 14:01:09 +01:00
|
|
|
import tarfile
|
2020-02-19 17:18:09 +01:00
|
|
|
|
2020-02-23 17:10:33 +01:00
|
|
|
GitRef = collections.namedtuple('VersionRef', [
|
2020-02-19 17:18:09 +01:00
|
|
|
'name',
|
2020-02-21 13:58:30 +01:00
|
|
|
'commit',
|
2020-02-19 17:18:09 +01:00
|
|
|
'source',
|
2020-02-21 13:58:30 +01:00
|
|
|
'is_remote',
|
2020-02-19 17:18:09 +01:00
|
|
|
'refname',
|
2020-02-25 15:22:10 +01:00
|
|
|
'creatordate',
|
2020-02-19 17:18:09 +01:00
|
|
|
])
|
|
|
|
|
|
|
|
|
2020-02-23 17:10:33 +01:00
|
|
|
def get_all_refs(gitroot):
|
2020-02-25 15:22:10 +01:00
|
|
|
cmd = ("git", "for-each-ref", "--format",
|
2020-02-26 11:42:37 +01:00
|
|
|
"%(objectname)\t%(refname)\t%(creatordate:iso)", "refs")
|
2020-02-19 17:18:09 +01:00
|
|
|
output = subprocess.check_output(cmd, cwd=gitroot).decode()
|
|
|
|
for line in output.splitlines():
|
2020-02-23 17:10:33 +01:00
|
|
|
is_remote = False
|
2020-02-25 15:22:10 +01:00
|
|
|
fields = line.strip().split("\t")
|
|
|
|
if len(fields) != 3:
|
|
|
|
continue
|
|
|
|
|
|
|
|
commit = fields[0]
|
|
|
|
refname = fields[1]
|
2020-02-26 11:42:37 +01:00
|
|
|
creatordate = datetime.datetime.strptime(fields[2], "%Y-%m-%d %H:%M:%S %z")
|
2020-02-25 15:22:10 +01:00
|
|
|
|
2020-02-19 17:18:09 +01:00
|
|
|
# Parse refname
|
2020-02-25 15:22:10 +01:00
|
|
|
matchobj = re.match(r"^refs/(heads|tags|remotes/[^/]+)/(\S+)$", refname)
|
2020-02-19 17:18:09 +01:00
|
|
|
if not matchobj:
|
|
|
|
continue
|
2020-02-25 15:22:10 +01:00
|
|
|
source = matchobj.group(1)
|
|
|
|
name = matchobj.group(2)
|
|
|
|
|
2020-02-23 17:10:33 +01:00
|
|
|
if source.startswith('remotes/'):
|
|
|
|
is_remote = True
|
2020-02-21 13:58:30 +01:00
|
|
|
|
2020-02-25 15:22:10 +01:00
|
|
|
yield GitRef(name, commit, source, is_remote, refname, creatordate)
|
2020-02-19 17:18:09 +01:00
|
|
|
|
|
|
|
|
2020-02-23 17:10:33 +01:00
|
|
|
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):
|
2020-02-19 17:18:09 +01:00
|
|
|
continue
|
2020-02-23 17:10:33 +01:00
|
|
|
elif ref.source == 'heads':
|
|
|
|
if branch_whitelist is None or not re.match(branch_whitelist, ref.name):
|
2020-02-19 17:18:09 +01:00
|
|
|
continue
|
2020-02-23 17:10:33 +01:00
|
|
|
elif ref.is_remote and remote_whitelist is not None:
|
|
|
|
remote_name = ref.source.partition('/')[2]
|
2020-02-21 13:58:30 +01:00
|
|
|
if not re.match(remote_whitelist, remote_name):
|
|
|
|
continue
|
2020-02-23 17:10:33 +01:00
|
|
|
if branch_whitelist is None or not re.match(branch_whitelist, ref.name):
|
2020-02-19 17:18:09 +01:00
|
|
|
continue
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
|
2020-02-23 17:10:33 +01:00
|
|
|
yield ref
|
2020-02-19 17:18:09 +01:00
|
|
|
|
|
|
|
|
2020-02-21 14:01:09 +01:00
|
|
|
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)
|