gitdist.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/env python3
  2. # Creates a source distribution package.
  3. from os import makedirs, remove
  4. from os.path import isdir
  5. from subprocess import CalledProcessError, PIPE, Popen, check_output
  6. from tarfile import TarError, TarFile
  7. import stat, sys
  8. verbose = False
  9. def archiveFromGit(versionedPackageName, committish):
  10. prefix = '%s/' % versionedPackageName
  11. distBase = 'derived/dist/'
  12. umask = (
  13. stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR |
  14. stat.S_IRGRP | stat.S_IXGRP |
  15. stat.S_IROTH | stat.S_IXOTH
  16. )
  17. def exclude(info):
  18. '''Returns True iff the given tar entry should be excluded.
  19. '''
  20. return any((
  21. info.name.endswith('/.gitignore'),
  22. info.name.startswith(prefix + 'doc/internal'),
  23. ))
  24. proc = Popen(
  25. ('git', 'archive', '--prefix=' + prefix, '--format=tar', committish),
  26. bufsize = -1,
  27. stdin = None, stdout = PIPE, stderr = sys.stderr,
  28. )
  29. try:
  30. outTarPath = distBase + versionedPackageName + '.tar.gz'
  31. print('archive:', outTarPath)
  32. if not isdir(distBase):
  33. makedirs(distBase)
  34. try:
  35. with TarFile.open(outTarPath, 'w:gz') as outTar:
  36. # Copy entries from "git archive" into output tarball,
  37. # except for excluded entries.
  38. numIncluded = numExcluded = 0
  39. with TarFile.open(mode='r|', fileobj=proc.stdout) as inTar:
  40. for info in inTar:
  41. if exclude(info):
  42. if verbose:
  43. print('EX', info.name)
  44. numExcluded += 1
  45. else:
  46. if verbose:
  47. print('IN', info.name)
  48. numIncluded += 1
  49. info.uid = info.gid = 1000
  50. info.uname = info.gname = 'openmsx'
  51. info.mode = info.mode & umask
  52. outTar.addfile(info, inTar.extractfile(info))
  53. print('entries: %d included, %d excluded' % (
  54. numIncluded, numExcluded))
  55. except:
  56. # Clean up partial output file.
  57. remove(outTarPath)
  58. raise
  59. except:
  60. proc.terminate()
  61. raise
  62. else:
  63. data, _ = proc.communicate()
  64. if len(data) != 0:
  65. print(
  66. 'WARNING: %d more bytes of data from "git archive" after '
  67. 'tar stream ended' % len(data),
  68. file=sys.stderr
  69. )
  70. def niceVersionFromGitDescription(description):
  71. '''Our release tag names are still based on naming limitations from CVS;
  72. convert them to something more pleasing to the eyes.
  73. '''
  74. parts = description.split('-')
  75. tag = parts[0]
  76. if tag.startswith('RELEASE_'):
  77. tagParts = tag.split('_')[1 : ]
  78. i = 0
  79. while i < len(tagParts) and tagParts[i].isdigit():
  80. i += 1
  81. version = '-'.join(
  82. ['.'.join(tagParts[ : i])] +
  83. [s.lower() for s in tagParts[i : ]]
  84. )
  85. else:
  86. version = tag
  87. if len(parts) >= 2:
  88. parts[1] = 'dev' + parts[1]
  89. return '-'.join([version] + parts[1 : ])
  90. def getDescription(committish):
  91. args = ['git', 'describe', '--abbrev=9']
  92. if committish is not None:
  93. args.append(committish)
  94. try:
  95. data = check_output(args)
  96. except CalledProcessError as ex:
  97. print(
  98. '"%s" returned %d' % (' '.join(args), ex.returncode),
  99. file=sys.stderr
  100. )
  101. raise
  102. else:
  103. return data.decode('utf-8', 'replace').rstrip('\n')
  104. def main(committish = None):
  105. try:
  106. description = getDescription(committish)
  107. except CalledProcessError:
  108. sys.exit(1)
  109. version = niceVersionFromGitDescription(description)
  110. try:
  111. archiveFromGit('openmsx-%s' % version, description)
  112. except (OSError, TarError) as ex:
  113. print('ERROR: %s' % ex, file=sys.stderr)
  114. sys.exit(1)
  115. if __name__ == '__main__':
  116. if len(sys.argv) == 1:
  117. main()
  118. elif len(sys.argv) == 2:
  119. main(sys.argv[1])
  120. else:
  121. print('Usage: gitdist.py [branch | tag]', file=sys.stderr)
  122. sys.exit(2)