Better new-pocket affordances in invirtibuilder and build submission script
[invirt/packages/invirt-dev.git] / invirtibuilder
index b4487b9..699ce07 100755 (executable)
@@ -56,6 +56,9 @@ def logAndRun(cmd, *args, **kwargs):
         del kwargs['stdout']
     kwargs['stderr'] = logfile
     logfile.write('---> Ran %s\n' % (cmd, ))
+    if 'stdin_str' in kwargs:
+        logfile.write('STDIN:\n')
+        logfile.write(kwargs['stdin_str'])
     logfile.write('STDERR:\n')
     output = c.captureOutput(cmd, *args, **kwargs)
     logfile.write('STDOUT:\n')
@@ -132,7 +135,7 @@ def sbuild(package, ref, distro, arch, workdir, arch_all=False):
     env['NMUTAG'] = nmutag
 
     # Run sbuild with a hack in place to append arbitrary versions
-    args = ['perl', '-I/usr/share/invirt-dev',
+    args = ['perl', '-I/usr/share/invirt-dev', '-MSbuildHack',
             '/usr/bin/sbuild',
             '--binNMU=171717', '--make-binNMU=Build with sbuild',
             '-v', '-d', distro, '--arch', arch]
@@ -199,8 +202,11 @@ def uploadBuild(pocket, workdir):
         except subprocess.CalledProcessError, e:
             if not force:
                 raise
-            package = deb822.Changes(open(changes).read())['Binary']
-            logAndRun(['reprepro-env', 'remove', apt, package])
+            changelog = deb822.Changes(open(changes).read())
+            packages = set(changelog['Binary'].split())
+            packages.add(changelog['Source'])
+            for package in packages:
+                logAndRun(['reprepro-env', 'remove', apt, package])
             logAndRun(upload)
 
 
@@ -214,23 +220,48 @@ def updateSuperproject(pocket, package, commit, principal, version, env):
     pushes to the superproject.
     """
     superproject = os.path.join(b._REPO_DIR, 'invirt/packages.git')
+    if not b.pocketExists(pocket, superproject):
+        raise Exception("Super-repository does not contain pocket branch '%s'.  Create it first." % pocket)
+
     branch = b.pocketToGit(pocket)
     tree = logAndRun(['git', 'ls-tree', branch],
                      cwd=superproject).strip()
 
-    new_tree = re.compile(
-        r'^(160000 commit )[0-9a-f]*(\t%s)$' % package, re.M).sub(
-        r'\g<1>%s\g<2>' % commit,
-        tree)
+    tree_items = dict((k, v) for (v, k) in (x.split("\t") for x in tree.split("\n")))
+
+    created = not (package in tree_items)
+
+    tree_items[package] = "160000 commit "+commit
+
+    # If "created" is true, we need to check if the package is
+    # mentioned in .gitmodules, and add it if not.
+    if created:
+        gitmodules = logAndRun(['git', 'cat-file', 'blob', '%s:.gitmodules' % (branch)],
+                               cwd=superproject)
+        if ('[submodule "%s"]' % (package)) not in gitmodules.split("\n"):
+            gitmodules += """[submodule "%s"]
+\tpath = %s
+\turl = ../packages/%s.git
+""" % (package, package, package)
+            gitmodules_hash = logAndRun(['git', 'hash-object', '-w', '--stdin'],
+                                        cwd=superproject,
+                                        stdin_str=gitmodules).strip()
+            tree_items[package] = "100644 blob "+gitmodules_hash
+
+    new_tree = "\n".join("%s\t%s" % (v, k) for (k, v) in tree_items.iteritems())
 
     new_tree_id = logAndRun(['git', 'mktree', '--missing'],
                             cwd=superproject,
                             stdin_str=new_tree).strip()
 
-    commit_msg = ('Update %s to version %s\n\n'
-                  'Requested by %s' % (package,
-                                       version.full_version,
-                                       principal))
+    if created:
+        commit_msg = 'Add %s at version %s'
+    else:
+        commit_msg = 'Update %s to version %s'
+    commit_msg = ((commit_msg + '\n\n'
+                   'Requested by %s') % (package,
+                                         version.full_version,
+                                         principal))
     new_commit = logAndRun(
         ['git', 'commit-tree', new_tree_id, '-p', branch],
         cwd=superproject,
@@ -246,7 +277,7 @@ def makeReadable(workdir):
     os.chmod(workdir, 0755)
 
 @contextlib.contextmanager
-def packageWorkdir(package, commit):
+def packageWorkdir(package, commit, build_id):
     """Checkout the package in a temporary working directory.
 
     This context manager returns that working directory. The requested
@@ -256,11 +287,11 @@ def packageWorkdir(package, commit):
     When the context wrapped with this context manager is exited, the
     working directory is automatically deleted.
     """
-    workdir = tempfile.mkdtemp()
+    workdir = tempfile.mkdtemp(prefix=("b%d-" % build_id))
     try:
         p_archive = subprocess.Popen(
-            ['git', 'archive',
-             '--remote=file://%s' % b.getRepo(package),
+            ['git', '--git-dir=%s' % (b.getRepo(package),),
+             'archive',
              '--prefix=%s/' % package,
              commit,
              ],
@@ -350,7 +381,7 @@ def build():
             # do the build ourselves
             else:
                 db.failed_stage = 'checking out package source'
-                with packageWorkdir(package, commit) as workdir:
+                with packageWorkdir(package, commit, db.build_id) as workdir:
                     db.failed_stage = 'preparing source package'
                     packagedir = os.path.join(workdir, package)
 
@@ -361,11 +392,13 @@ def build():
                     # If we were, we could use debuild and get nice
                     # environment scrubbing. Since we're not, debuild
                     # complains about not having an orig.tar.gz
-                    logAndRun(['dpkg-buildpackage', '-us', '-uc', '-S'],
+                    logAndRun(['schroot', '-c', 
+                               '%s-amd64-sbuild' % (b.pocketToDistro(pocket),), 
+                               '--', 'dpkg-buildpackage', '-us', '-uc', '-S'],
                               cwd=packagedir)
 
                     db.failed_stage = 'building binary packages'
-                    sbuildAll(package, commit, workdir)
+                    sbuildAll(package, commit, b.pocketToDistro(pocket), workdir)
                     db.failed_stage = 'tagging submodule'
                     tagSubmodule(pocket, package, commit, principal, version, env)
                     db.failed_stage = 'updating submodule branches'