gitdist.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env python2
  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. outTar = TarFile.open(outTarPath, 'w:gz')
  35. try:
  36. # Copy entries from "git archive" into output tarball, except for
  37. # excluded entries.
  38. numIncluded = numExcluded = 0
  39. inTar = TarFile.open(mode = 'r|', fileobj = proc.stdout)
  40. try:
  41. for info in inTar:
  42. if exclude(info):
  43. if verbose:
  44. print 'EX', info.name
  45. numExcluded += 1
  46. else:
  47. if verbose:
  48. print 'IN', info.name
  49. numIncluded += 1
  50. info.uid = info.gid = 1000
  51. info.uname = info.gname = 'openmsx'
  52. info.mode = info.mode & umask
  53. outTar.addfile(info, inTar.extractfile(info))
  54. finally:
  55. inTar.close()
  56. print 'entries: %d included, %d excluded' % (
  57. numIncluded, numExcluded)
  58. except:
  59. # Clean up partial output file.
  60. outTar.close()
  61. remove(outTarPath)
  62. raise
  63. else:
  64. outTar.close()
  65. except:
  66. proc.terminate()
  67. raise
  68. else:
  69. data, _ = proc.communicate()
  70. if len(data) != 0:
  71. print >> sys.stderr, (
  72. 'WARNING: %d more bytes of data from "git archive" after '
  73. 'tar stream ended' % len(data))
  74. def niceVersionFromGitDescription(description):
  75. '''Our release tag names are still based on naming limitations from CVS;
  76. convert them to something more pleasing to the eyes.
  77. '''
  78. parts = description.split('-')
  79. tag = parts[0]
  80. if tag.startswith('RELEASE_'):
  81. tagParts = tag.split('_')[1 : ]
  82. i = 0
  83. while i < len(tagParts) and tagParts[i].isdigit():
  84. i += 1
  85. version = '-'.join(
  86. ['.'.join(tagParts[ : i])] +
  87. [s.lower() for s in tagParts[i : ]]
  88. )
  89. else:
  90. version = tag
  91. if len(parts) >= 2:
  92. parts[1] = 'dev' + parts[1]
  93. return '-'.join([version] + parts[1 : ])
  94. def getDescription(committish):
  95. args = ['git', 'describe', '--abbrev=9']
  96. if committish is not None:
  97. args.append(committish)
  98. try:
  99. return check_output(args).rstrip('\n')
  100. except CalledProcessError as ex:
  101. print >> sys.stderr, '"%s" returned %d' % (
  102. ' '.join(args), ex.returncode
  103. )
  104. raise
  105. def main(committish = None):
  106. try:
  107. description = getDescription(committish)
  108. except CalledProcessError:
  109. sys.exit(1)
  110. version = niceVersionFromGitDescription(description)
  111. try:
  112. archiveFromGit('openmsx-%s' % version, description)
  113. except (OSError, TarError) as ex:
  114. print >> sys.stderr, 'ERROR: %s' % ex
  115. sys.exit(1)
  116. if __name__ == '__main__':
  117. if len(sys.argv) == 1:
  118. main()
  119. elif len(sys.argv) == 2:
  120. main(sys.argv[1])
  121. else:
  122. print >> sys.stderr, 'Usage: gitdist.py [branch | tag]'
  123. sys.exit(2)