git.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. # -*- coding: utf-8 -*-
  2. import collections
  3. import subprocess
  4. import re
  5. from . import sphinx
  6. VersionRef = collections.namedtuple('VersionRef', [
  7. 'name',
  8. 'commit',
  9. 'source',
  10. 'is_remote',
  11. 'refname',
  12. 'version',
  13. 'release',
  14. ])
  15. def get_refs(gitroot):
  16. cmd = ("git", "for-each-ref", "--format", "%(objectname) %(refname)", "refs")
  17. output = subprocess.check_output(cmd, cwd=gitroot).decode()
  18. for line in output.splitlines():
  19. line = line.strip()
  20. # Parse refname
  21. matchobj = re.match(r"^(\w+) refs/(heads|tags|remotes/[^/]+)/(\S+)$", line)
  22. if not matchobj:
  23. continue
  24. commit = matchobj.group(1)
  25. source = matchobj.group(2)
  26. name = matchobj.group(3)
  27. refname = line.partition(' ')[2]
  28. yield (name, commit, source, refname)
  29. def get_conf(gitroot, refname, confpath):
  30. objectname = "{}:{}".format(refname, confpath)
  31. cmd = ("git", "show", objectname)
  32. return subprocess.check_output(cmd, cwd=gitroot).decode()
  33. def find_versions(gitroot, confpath, tag_whitelist, branch_whitelist, remote_whitelist):
  34. for name, commit, source, refname in get_refs(gitroot):
  35. is_remote = False
  36. if source == 'tags':
  37. if tag_whitelist is None or not re.match(tag_whitelist, name):
  38. continue
  39. elif source == 'heads':
  40. if branch_whitelist is None or not re.match(branch_whitelist, name):
  41. continue
  42. elif source.startswith('remotes/') and remote_whitelist is not None:
  43. is_remote = True
  44. remote_name = source.partition('/')[2]
  45. if not re.match(remote_whitelist, remote_name):
  46. continue
  47. if branch_whitelist is None or not re.match(branch_whitelist, name):
  48. continue
  49. else:
  50. continue
  51. conf = get_conf(gitroot, refname, confpath)
  52. config = sphinx.parse_conf(conf)
  53. version = config['version']
  54. release = config['release']
  55. yield VersionRef(name, commit, source, is_remote, refname, version, release)
  56. def shallow_clone(src, dst, branch):
  57. cmd = ("git", "clone", "--no-hardlinks", "--single-branch", "--depth", "1",
  58. "--branch", branch, src, dst)
  59. subprocess.check_call(cmd)