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