sbuild-launchpad-chroot-0.4/0000755000000000000000000000000012264632521012761 5ustar sbuild-launchpad-chroot-0.4/bin/0000755000000000000000000000000012264632521013531 5ustar sbuild-launchpad-chroot-0.4/bin/sbuild-launchpad-chroot0000755000000000000000000002046312264632355020204 0ustar #!/usr/bin/python -u # -*- coding: utf-8 -*- # Copyright (C) 2013 Stéphane Graber # Author: Stéphane Graber # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import argparse import fcntl import os import urllib import subprocess import shutil import tempfile from ConfigParser import ConfigParser def create_chroot(args): chroot = args.name print("[%s] Creating config" % chroot) config_path = os.path.join("/etc/schroot/chroot.d/", chroot) if os.path.exists(config_path): print("[%s] Chroot already exists!" % chroot) return # Generate alias list aliases = [] for pocket in ("security", "updates", "proposed"): aliases.append(args.name.replace(args.series, "%s-%s" % (args.series, pocket))) for component in ("main", "restricted", "universe", "multiverse"): aliases.append(args.name.replace(args.series, "%s-%s+%s" % (args.series, pocket, component))) # Generate config config = ConfigParser() config.add_section(args.name) config.set(args.name, "type", "directory") config.set(args.name, "description", "Ubuntu %s/%s sbuild" % (args.series, args.architecture)) config.set(args.name, "directory", os.path.join("/var/lib/schroot/chroot/", args.name)) config.set(args.name, "union-type", "overlayfs") config.set(args.name, "root-groups", "root,sbuild") config.set(args.name, "profile", "sbuild") config.set(args.name, "launchpad.dist", "ubuntu") config.set(args.name, "launchpad.series", args.series) config.set(args.name, "launchpad.arch", args.architecture) config.set(args.name, "launchpad.url", "") config.set(args.name, "apt.enable", "true") config.set(args.name, "aliases", ",".join(aliases)) with open(config_path, "w+") as fd: config.write(fd) fd.seek(0) content = fd.read() fd.truncate(0) fd.seek(0) fd.write(content.replace(" = ", "=")) print("[%s] Initial download" % chroot) update_chroot(args) print("[%s] Done creating" % chroot) def update_chroot(args): chroot = args.name # Lock file lock_file = "/run/lock/sbuild.%s" % chroot lock_fd = open(lock_file, 'w') try: fcntl.lockf(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError: print("[%s] Waiting for other process to release the lock" % chroot) fcntl.lockf(lock_fd, fcntl.LOCK_EX) # Authenticated login to Launchpad from launchpadlib.launchpad import Launchpad lp = Launchpad.login_anonymously('lp-sbuild', 'production') print("[%s] Processing config" % chroot) config_path = os.path.join("/etc/schroot/chroot.d/", chroot) # Parse the existing configuration config = ConfigParser() config.read(config_path) if not os.path.exists(config_path): print("[%s] Doesn't exist." % chroot) return if (set(['launchpad.dist', 'launchpad.series', 'launchpad.arch']) - set(config.options(chroot))): print("[%s] Skipping (missing launchpad.* options)." % chroot) return # Grab the chroot URL from Launchpad dist = lp.distributions[config.get(chroot, 'launchpad.dist')] series = dist.getSeries(name_or_version=config.get(chroot, 'launchpad.series')) arch = series.getDistroArchSeries(archtag=config.get(chroot, 'launchpad.arch')) chroot_url = arch.chroot_url old_chroot_url = None if config.has_option(chroot, 'launchpad.url'): old_chroot_url = config.get(chroot, 'launchpad.url') if chroot_url == old_chroot_url: print("[%s] Already up to date." % chroot) return if not chroot_url.endswith(".tar.bz2"): print("[%s] Remote tarball isn't .tar.bz2." % chroot) return print("[%s] Downloading new Launchpad chroot." % chroot) # Create tempfile for chroot download fd, tarball_path = tempfile.mkstemp(suffix=".tar.bz2") os.remove(tarball_path) os.close(fd) # Download the chroot urllib.urlretrieve(chroot_url, tarball_path) # Unpack the chroot chroot_path = config.get(chroot, 'directory') if os.path.exists(chroot_path): shutil.rmtree(chroot_path) os.makedirs(chroot_path) subprocess.call(['tar', 'xf', tarball_path, '-C', chroot_path, '--strip-components=1', 'chroot-autobuild']) os.remove(tarball_path) # Make the chroot sbuild compatible if os.path.exists(os.path.join(chroot_path, "CurrentlyBuilding")): os.remove(os.path.join(chroot_path, "CurrentlyBuilding")) if os.path.exists(os.path.join(chroot_path, "etc/apt/sources.list.d/bootstrap.list")): os.remove(os.path.join(chroot_path, "etc/apt/sources.list.d/" "bootstrap.list")) if not os.path.exists(os.path.join(chroot_path, "etc/schroot/setup.d")): os.makedirs(os.path.join(chroot_path, "etc/schroot/setup.d")) # Update the symlink to the chroot (just in case) if not os.path.exists("/etc/sbuild/chroot"): os.makedirs("/etc/sbuild/chroot") symlink_path = os.path.join("/etc/sbuild/chroot/", chroot) if os.path.exists(symlink_path): os.remove(symlink_path) os.symlink(chroot_path, symlink_path) # Set the chroot URL and save the config config.set(chroot, 'launchpad.url', chroot_url) with open(config_path, "w+") as fd: config.write(fd) fd.seek(0) content = fd.read() fd.truncate(0) fd.seek(0) fd.write(content.replace(" = ", "=")) print("[%s] Done updating from Launchpad" % chroot) # Remove lock file if os.path.exists(lock_file): os.remove(lock_file) def remove_chroot(args): chroot = args.name print("[%s] Beginning removal" % chroot) config_path = os.path.join("/etc/schroot/chroot.d/", chroot) # Parse the existing configuration config = ConfigParser() config.read(config_path) if not os.path.exists(config_path): print("[%s] Doesn't exist." % chroot) return if (set(['launchpad.dist', 'launchpad.series', 'launchpad.arch']) - set(config.options(chroot))): print("[%s] Skipping (missing launchpad.* options)." % chroot) return # Actually remove it chroot_path = config.get(chroot, 'directory') if os.path.exists(chroot_path): shutil.rmtree(chroot_path) os.remove(config_path) symlink_path = os.path.join("/etc/sbuild/chroot/", chroot) if os.path.exists(symlink_path): os.remove(symlink_path) print("[%s] Removed" % chroot) if __name__ == '__main__': parser = argparse.ArgumentParser(description="launchpad sbuild chroot") subparsers = parser.add_subparsers() # Create parser_create = subparsers.add_parser( 'create', help="Create a new Launchpad-based chroot") parser_create.add_argument("-n", "--name", required=True) parser_create.add_argument("-a", "--architecture", required=True) parser_create.add_argument("-s", "--series", required=True) parser_create.set_defaults(func=create_chroot) # Update parser_update = subparsers.add_parser( 'update', help="Update a Launchpad-based chroot") parser_update.add_argument("-n", "--name", required=True) parser_update.set_defaults(func=update_chroot) # Remove parser_remove = subparsers.add_parser( 'remove', help="Remove a Launchpad-based chroot") parser_remove.add_argument("-n", "--name", required=True) parser_remove.set_defaults(func=remove_chroot) args = parser.parse_args() # Some checks if not os.geteuid() == 0: parser.error("Sorry but you must be root.") args.func(args) sbuild-launchpad-chroot-0.4/debian/0000755000000000000000000000000012264632521014203 5ustar sbuild-launchpad-chroot-0.4/debian/control0000644000000000000000000000162112264623165015612 0ustar Source: sbuild-launchpad-chroot Section: misc Priority: optional Maintainer: Stéphane Graber Build-Depends: debhelper (>= 9), python, help2man Standards-Version: 3.9.4 Homepage: http://www.stgraber.org Package: sbuild-launchpad-chroot Architecture: all Depends: python, python-launchpadlib, sbuild, ${misc:Depends} Description: Launchpad integration for sbuild This includes two sbuild hooks and a command line tool to setup and maintain build chroots that are as close as possible to a standard Launchpad sbuild chroot. . The sbuild-launchpad-chroot command can be used to setup, update and destroy those chroots. A schroot hook will also automatically update them should an update be available at the start of a build. . Those chroots also come with a series of useful aliases allowing the user to easily choose which pockets and components should be available for the build. sbuild-launchpad-chroot-0.4/debian/changelog0000644000000000000000000000146412264632501016060 0ustar sbuild-launchpad-chroot (0.4) trusty; urgency=medium * Add locking to the update function to avoid the case where two builds using the same chroot are both trying to update the same path. -- Stéphane Graber Sun, 12 Jan 2014 19:37:20 -0500 sbuild-launchpad-chroot (0.3) trusty; urgency=low * Make sur both /var/lib/schroot/chroot and /etc/sbuild/chroot exist. -- Stéphane Graber Tue, 22 Oct 2013 12:28:29 -0400 sbuild-launchpad-chroot (0.2) trusty; urgency=low * Fix FTBFS due to help2man failing when launchpadlib is missing. -- Stéphane Graber Sun, 20 Oct 2013 11:31:18 -0400 sbuild-launchpad-chroot (0.1) trusty; urgency=low * Initial release. -- Stéphane Graber Sat, 19 Oct 2013 19:42:18 -0400 sbuild-launchpad-chroot-0.4/debian/compat0000644000000000000000000000000212264623165015405 0ustar 9 sbuild-launchpad-chroot-0.4/debian/bzr-builddeb.conf0000644000000000000000000000003112264623165017415 0ustar [BUILDDEB] native = True sbuild-launchpad-chroot-0.4/debian/install0000644000000000000000000000003412264623165015575 0ustar bin/* /usr/bin/ etc/* /etc/ sbuild-launchpad-chroot-0.4/debian/rules0000755000000000000000000000074312264623165015273 0ustar #!/usr/bin/make -f # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 VERSION=$(shell head -n1 debian/changelog |sed -e 's/.*(\(.*\)).*/\1/') %: dh $@ override_dh_installman: mkdir -p $(CURDIR)/debian/sbuild-launchpad-chroot/usr/share/man/man1/ help2man --name="Launchpad chroots for sbuild" --version-string=$(VERSION) -N $(CURDIR)/bin/sbuild-launchpad-chroot > $(CURDIR)/debian/sbuild-launchpad-chroot/usr/share/man/man1/sbuild-launchpad-chroot.1 dh_installman sbuild-launchpad-chroot-0.4/debian/copyright0000644000000000000000000000213012264623165016136 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: sbuild-launchpad-chroot Upstream-Contact: stgraber@ubuntu.com Source: http://code.launchpad.net/ubuntu/+source/sbuild-launchpad-chroot Files: * Copyright: 2013 Stéphane Graber License: GPL-3+ Files: etc/schroot/setup.d/90apt-sources Copyright: 2012 Andy Whitcroft License: GPL-3+ License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 3 of the License. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the full text of the GNU General Public License version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. sbuild-launchpad-chroot-0.4/debian/source/0000755000000000000000000000000012264632521015503 5ustar sbuild-launchpad-chroot-0.4/debian/source/format0000644000000000000000000000001512264623165016716 0ustar 3.0 (native) sbuild-launchpad-chroot-0.4/etc/0000755000000000000000000000000012264632521013534 5ustar sbuild-launchpad-chroot-0.4/etc/schroot/0000755000000000000000000000000012264632521015215 5ustar sbuild-launchpad-chroot-0.4/etc/schroot/setup.d/0000755000000000000000000000000012264632521016577 5ustar sbuild-launchpad-chroot-0.4/etc/schroot/setup.d/01launchpad-chroot0000755000000000000000000000160612264623165022130 0ustar #!/bin/sh # -*- coding: utf-8 -*- # Copyright (C) 2013 Stéphane Graber # Author: Stéphane Graber # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 3 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . . "$SETUP_DATA_DIR/common-data" . "$SETUP_DATA_DIR/common-functions" . "$SETUP_DATA_DIR/common-config" [ "$STAGE" != "setup-start" ] && exit 0 sbuild-launchpad-chroot update -n $CHROOT_NAME sbuild-launchpad-chroot-0.4/etc/schroot/setup.d/90apt-sources0000755000000000000000000001154512264623165021155 0ustar #!/bin/sh # Copyright © 2012 Andy Whitcroft # # schroot is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # schroot is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see # . # ##################################################################### set -e . "$SETUP_DATA_DIR/common-data" . "$SETUP_DATA_DIR/common-functions" if [ -f "$SETUP_DATA_DIR/common-config" ]; then . "$SETUP_DATA_DIR/common-config" else # handle precise where we cannot set variables, and do not get # alias information. desc="`schroot --config -c "$CHROOT_NAME" | \ awk -F= ' /^description/ { r=$2 for (n=3; n <= NF; n++) { r = r "=" $n } print r } '`" case "$desc" in *apt.enable=true*) APT_ENABLE=true CHROOT_ALIAS="$CHROOT_NAME" CHROOT_NAME=`echo "$desc" | sed -e 's/apt.enable=true//' -e 's/^ *//' -e 's/ *$//'` ;; esac fi changed=false if [ $STAGE = "setup-start" ] || [ $STAGE = "setup-recover" ]; then sources="${CHROOT_PATH}/etc/apt/sources.list" if [ "$CHROOT_SESSION_PURGE" = 'false' ]; then exit 0 fi # Alias driven mode. if [ -n "$APT_ENABLE" ]; then suite="proposed" comp="universe" [ -n "$APT_DEFAULT_SUITE" ] && suite="$APT_DEFAULT_SUITE" [ -n "$APT_DEFAULT_COMPONENT" ] && comp="$APT_DEFAULT_COMPONENT" # "Subtract" the CHROOT_NAME from the CHROOT_ALIAS to extract # the pocket/component information. suite_comp=`awk -v base="$CHROOT_NAME" -v name="$CHROOT_ALIAS" ' BEGIN { bbh = split(base, bb, "-") nbh = split(name, nb, "-") bbl = 1 nbl = 1 while (bbl <= bbh && bb[bbl] == nb[nbl]) { bbl++; nbl++; } while (bbh >= bbl && bb[bbh] == nb[nbh]) { bbh--; nbh--; } extra="" for (; nbl <= nbh; nbl++) { extra = extra "-" nb[nbl] } print(substr(extra, 2)) } '` case "$suite_comp" in '') ;; *+*) suite=`echo "$suite_comp" | sed -e 's/\+.*//'` comp=`echo "$suite_comp" | sed -e 's/[^\+]*+//'` ;; *) suite="$suite_comp" ;; esac case "$suite" in release) suites="" ;; security) suites="security" ;; updates) suites="security updates" ;; proposed) suites="security updates proposed" ;; *) echo "unknown suite $suite" 1>&2; exit 1 ;; esac case "$comp" in main) comps="main" ;; restricted) comps="main restricted" ;; universe) comps="main universe" ;; multiverse) comps="main restricted universe multiverse" ;; '') ;; *) echo "unknown component $comp" 1>&2; exit 1 ;; esac APT_POCKETS="$suites" APT_COMPONENTS="$comps" fi if [ -n "$APT_POCKETS" ]; then echo "setting apt pockets to 'release $APT_POCKETS' in sources.list" awk -v pockets="$APT_POCKETS" ' BEGIN { n = 0; split(pockets, plist); } /^#/ { print ; next } ($3 !~ /-/) { print; release = $3; for (m in plist) { $3 = release "-" plist[m]; new[n] = $0; n++; } next; } END { for (x = 0; x < n; x++) { print new[x] } } ' <"$sources" >"$sources.new" mv "$sources.new" "$sources" changed=true fi if [ -n "$APT_COMPONENTS" ]; then echo "setting apt components to '$APT_COMPONENTS' in sources.list" awk -v components="$APT_COMPONENTS" ' /^#/ { print ; next } { print $1 " " $2 " " $3 " " components } ' <"$sources" >"$sources.new" mv "$sources.new" "$sources" changed=true fi if [ "$VERBOSE" = 'verbose' -a "$changed" = 'true' ]; then echo "Resulting sources.list" cat "$sources" fi fi