summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2018-08-11 16:47:43 +0300
committerLars Wirzenius <liw@liw.fi>2018-08-11 16:47:43 +0300
commit0882ed2136c95a015735d3dcb44ff066f1016119 (patch)
tree1c6e09ebe19e0c264500996208d5aae414192511
downloadick-helpers-0882ed2136c95a015735d3dcb44ff066f1016119.tar.gz
Add: initial commit
-rw-r--r--ick_helpers.py231
1 files changed, 231 insertions, 0 deletions
diff --git a/ick_helpers.py b/ick_helpers.py
new file mode 100644
index 0000000..731d4fd
--- /dev/null
+++ b/ick_helpers.py
@@ -0,0 +1,231 @@
+import glob
+import os
+import re
+import sys
+import subprocess
+
+
+verbose = True
+
+def debug(*args):
+ if verbose:
+ print('DEBUG:', *args)
+
+
+class Exec:
+
+ def __init__(self, dirname):
+ self.dirname = dirname
+
+ def run(self, *args, **kwargs):
+ if 'cwd' not in kwargs:
+ kwargs['cwd'] = self.dirname
+ if 'check' not in kwargs:
+ kwargs['check'] = True
+ if 'stdout' not in kwargs:
+ kwargs['stdout'] = subprocess.PIPE
+ if 'stderr' not in kwargs:
+ kwargs['stderr'] = subprocess.STDOUT
+
+ debug('RUN:', args, kwargs)
+ x = subprocess.run(args, **kwargs)
+ if kwargs['stdout'] == subprocess.PIPE:
+ if x.stdout:
+ sys.stdout.write(x.stdout.decode('UTF-8'))
+ return x
+
+ def get_stdout(self, *args, **kwargs):
+ kwargs['check'] = True
+ kwargs['stdout'] = subprocess.PIPE
+ x = self.run(*args, **kwargs)
+ return x.stdout.decode('UTF-8')
+
+ def run_silently(self, *args, **kwargs):
+ kwargs['stdout'] = kwargs['stderr'] = subprocess.DEVNULL
+ kwargs['check'] = False
+ return self.run(*args, **kwargs)
+
+ def is_signed_tag(self, tag):
+ x = self.run_silently('git', 'tag', '--verify', tag)
+ return x.returncode == 0
+
+ def is_named_as_release_tag(self, tag, project):
+ prefix = tag[:len(project)]
+ suffix = tag[len(prefix):]
+ return prefix == project and re.match(r'^-\d+\.\d+(\.\d+)*$', suffix)
+
+ def is_release_tag(self, tag, project):
+ if not self.is_signed_tag(tag):
+ debug('tag is not signed:', tag)
+ return False
+ if not self.is_named_as_release_tag(tag, project):
+ debug('tag is not named correctly for a release tag:', tag)
+ return False
+ debug('seems to be a release tag:', tag)
+ return True
+
+ def get_debian_source_package(self):
+ output = self.get_stdout('dpkg-parsechangelog', '-S', 'Source')
+ return output.strip()
+
+ def get_version_from_tag(self, tag):
+ parts = tag.split('-', 1)
+ debug('tag parts:', parts)
+ assert len(parts) == 2
+ return parts[1]
+
+ def find_all_tags(self):
+ output = self.get_stdout('git', 'tag', '-l')
+ return output.splitlines()
+
+ def find_release_tags(self, project):
+ tags = self.find_all_tags()
+ return [
+ tag
+ for tag in tags
+ if self.is_release_tag(tag, project)
+ ]
+
+ def create_tarball_from_tag(self, tag, filename):
+ self.run('git', 'archive', '-o', 'temp.tar', tag)
+ self.run('xz', '-9', 'temp.tar')
+ self.run('mv', 'temp.tar.xz', filename)
+
+
+class Version:
+
+ def __init__(self, full_version):
+ self._full_version = full_version
+
+ @property
+ def full(self):
+ return self._full_version
+
+ @property
+ def upstream(self):
+ parts = self._full_version.split('-', 1)
+ return parts[0]
+
+ @property
+ def debian(self):
+ parts = self._full_version.split('-', 1)
+ if len(parts) == 1:
+ return None
+ return parts[1]
+
+
+class DebianReleaseBuilder:
+
+ def __init__(self, ex, resultsdir):
+ self.ex = ex
+ self.results = resultsdir
+
+ def build(self, tag):
+ debug('Building release from tag', tag)
+ cwd = os.getcwd()
+
+ self.checkout(tag)
+
+ upstream_tarball = self.create_upstream_tarball(tag)
+ debug('upstream_tarball:', upstream_tarball)
+ self.stash(upstream_tarball)
+
+ source = self.get_source_package()
+ version = self.get_version()
+ debug('Source package:', source)
+ debug('Version:', version)
+
+ orig_tarball = self.create_debian_orig_tarball(
+ upstream_tarball, source, version)
+ self.create_dsc()
+ self.build_deb()
+
+ debian_files = glob.glob('{}_{}*'.format(source, version.upstream))
+ debug('DEBIAN:', debian_files)
+ self.stash(*debian_files)
+
+ filenames = glob.glob('{}_{}*'.format(source, version.upstream))
+ filenames.append(upstream_tarball)
+ self.cleanup(filenames)
+
+ debug()
+
+ def checkout(self, tag):
+ self.ex.run('git', 'checkout', 'master', check=False)
+ self.ex.run('git', 'branch', '-d', '__ickbuild', check=False)
+ self.ex.run('git', 'checkout', '-b', '__ickbuild', tag)
+
+ def create_upstream_tarball(self, tag):
+ basename = '{}.tar.xz'.format(tag)
+ tarball = os.path.abspath(basename)
+ self.ex.create_tarball_from_tag(tag, tarball)
+ return basename
+
+ def create_debian_orig_tarball(self, upstream_tarball, source, version):
+ tarball = '{}_{}.orig.tar.xz'.format(source, version.upstream)
+ os.link(upstream_tarball, tarball)
+ return tarball
+
+ def get_source_package(self):
+ output = self.ex.get_stdout('dpkg-parsechangelog', '-S', 'Source')
+ return output.strip()
+
+ def get_version(self):
+ output = self.ex.get_stdout('dpkg-parsechangelog', '-S', 'Version')
+ return Version(output.strip())
+
+ def create_dsc(self):
+ self.ex.run('dpkg-buildpackage', '-S', '--no-sign')
+
+ def build_deb(self):
+ self.ex.run('dpkg-buildpackage', '-b', '--no-sign')
+
+ def stash(self, *filenames):
+ if not os.path.exists(self.results):
+ os.mkdir(self.results)
+ for filename in filenames:
+ dst = os.path.join(self.results, filename)
+ debug('STASH:', filename, '->', dst)
+ os.link(filename, dst)
+
+ def cleanup(self, filenames):
+ for filename in filenames:
+ debug('DELETE', filename)
+ os.remove(filename)
+
+
+known_tags = '.known_tags'
+
+def get_known_tags():
+ if os.path.exists(known_tags):
+ with open(known_tags) as f:
+ return [line.strip() for line in f.readlines()]
+ return []
+
+
+def remember_tag(tag):
+ with open(known_tags, 'a') as f:
+ f.write('{}\n'.format(tag))
+
+
+def find_upstream_dirs(sources):
+ for source in sources:
+ dirname = source['location']
+ control = os.path.join(dirname, 'debian', 'control')
+ if os.path.exists(control):
+ yield dirname
+
+
+def build_debian_releases(sources, resultsdir):
+ known_tags = get_known_tags()
+ debug('KNOWN:', known_tags)
+ dirnames = find_upstream_dirs(sources)
+ for dirname in dirnames:
+ ex = Exec(dirname)
+ project = ex.get_debian_source_package()
+ tags = ex.find_release_tags(project)
+ builder = DebianReleaseBuilder(ex, resultsdir)
+ for tag in tags:
+ if tag not in known_tags:
+ builder.build(tag)
+ remember_tag(tag)