Review: Approve
Diff comments: > === modified file 'debian/changelog' > --- debian/changelog 2015-05-11 11:00:44 +0000 > +++ debian/changelog 2015-05-11 11:00:44 +0000 > @@ -1,9 +1,15 @@ > launchpad-buildd (127) UNRELEASED; urgency=low > > + * Switch from an internal sbuild fork to the system package. > + - Dropped copy of sbuild. > + - Install ~buildd/.sbuildrc instead of ~buildd/.lp-sbuildrc. > + - Clean and update sbuildrc. > + - Write out /CurrentlyBuilding from Python. > + - Rewrite failure stage and depwait detection to cope with modern sbuild. > * Refactor lpbuildd.binarypackage tests to be readable. > * Drop duplicated paths from the config file. > > - -- William Grant <[email protected]> Sat, 18 Apr 2015 06:41:52 +1000 > + -- William Grant <[email protected]> Mon, 11 May 2015 20:55:37 +1000 > > launchpad-buildd (126) trusty; urgency=medium > > > === modified file 'debian/control' > --- debian/control 2014-06-25 01:50:28 +0000 > +++ debian/control 2015-05-11 11:00:44 +0000 > @@ -10,7 +10,7 @@ > Architecture: all > Depends: python-lpbuildd (=${source:Version}), python, debootstrap, dpkg-dev, > linux32, file, bzip2, sudo, ntpdate, adduser, apt-transport-https, > lsb-release, > - apache2, pristine-tar, python-apt, ${misc:Depends} > + apache2, pristine-tar, python-apt, sbuild, ${misc:Depends} > Recommends: qemu-user-static > Description: Launchpad buildd slave > This is the launchpad buildd slave package. It contains everything needed to > > === modified file 'debian/launchpad-buildd.install' > --- debian/launchpad-buildd.install 2014-06-25 01:50:28 +0000 > +++ debian/launchpad-buildd.install 2015-05-11 11:00:44 +0000 > @@ -1,4 +1,2 @@ > default/launchpad-buildd etc/default > -sbuild > usr/share/launchpad-buildd/slavebin > -sbuild.conf usr/share/launchpad-buildd > buildd-genconfig usr/share/launchpad-buildd > > === modified file 'debian/postinst' > --- debian/postinst 2014-07-10 10:20:31 +0000 > +++ debian/postinst 2015-05-11 11:00:44 +0000 > @@ -27,6 +27,7 @@ > getent passwd buildd >/dev/null 2>&1 || > adduser --ingroup buildd --disabled-login --gecos 'Buildd user' \ > --uid $BUILDDUID ${USER} > + adduser --quiet buildd sbuild > > SUDO_VERSION=$(sudo -V | sed -n '/^Sudo version/s/.* //p') > if dpkg --compare-versions $SUDO_VERSION lt 1.7 || > @@ -51,16 +52,21 @@ > > install -d -o${USER} -m0755 /home/${USER} > > - # Create ~buildd/.lp-sbuildrc if needed > - if [ ! -f /home/${USER}/.lp-sbuildrc ]; then > - cp /usr/share/launchpad-buildd/sbuildrc \ > - /home/${USER}/.lp-sbuildrc.tmp > - cd /home/${USER} > - sed -e's/@ARCHTAG@/'$(dpkg --print-architecture)'/g' \ > - < .lp-sbuildrc.tmp > .lp-sbuildrc > - chown $USER:buildd .lp-sbuildrc > - chmod 0644 .lp-sbuildrc > - rm .lp-sbuildrc.tmp > + if [ "x$2" != "x" ]; then > + if dpkg --compare-versions "$2" lt 127; then > + # .lp-sbuildrc is no longer used. > + rm -f /home/${USER}/.lp-sbuildrc > + # .sbuildrc used to be a normal file, but nowadays it's > a > + # symlink. > + rm -f /home/${USER}/.sbuildrc > + fi > + fi > + > + # Create ~buildd/.sbuildrc if needed > + if [ ! -f /home/${USER}/.sbuildrc ]; then > + ln -s /usr/share/launchpad-buildd/sbuildrc > /home/${USER}/.sbuildrc > + chown $USER:buildd /home/${USER}/.sbuildrc > + chmod 0644 /home/${USER}/.sbuildrc The chown and chmod really don't make much sense on a symlink. Without --dereference, they will affect the referent rather than the link, and the defaults in the package are probably fine anyway. > fi > > # Prepare a default buildd... > > === modified file 'debian/upgrade-config' > --- debian/upgrade-config 2015-05-11 11:00:44 +0000 > +++ debian/upgrade-config 2015-05-11 11:00:44 +0000 > @@ -181,11 +181,10 @@ > # all inside slavebin. > config.set('slave', 'sharepath', '/usr/share/launchpad-buildd') > deprecated_sections = [ > - 'allmanagers', 'debianmanager', 'sourcepackagerecipemanager', > - 'livefilesystemmanager'] > + 'allmanagers', 'binarypackagemanager', 'debianmanager', > + 'sourcepackagerecipemanager', 'livefilesystemmanager'] > for section in deprecated_sections: > config.remove_section(section) > - config.remove_option('binarypackagemanager', 'sbuildpath') > config.remove_option('translationtemplatesmanager', 'generatepath') > > out_file = open(conf_file, "w") > > === modified file 'lpbuildd/binarypackage.py' > --- lpbuildd/binarypackage.py 2015-05-11 11:00:44 +0000 > +++ lpbuildd/binarypackage.py 2015-05-11 11:00:44 +0000 > @@ -11,9 +11,9 @@ > class SBuildExitCodes: > """SBUILD process result codes.""" > OK = 0 > - DEPFAIL = 1 > - GIVENBACK = 2 > - PACKAGEFAIL = 3 > + FAILED = 1 > + ATTEMPTED = 2 > + GIVENBACK = 3 > BUILDERFAIL = 4 > > > @@ -23,11 +23,8 @@ > ("^E: There are problems and -y was used without --force-yes"), > ] > DEPFAIL = { > - "(?P<pk>[\-+.\w]+)\(inst [^ ]+ ! >> wanted (?P<v>[\-.+\w:~]+)\)": > "\g<pk> (>> \g<v>)", > - "(?P<pk>[\-+.\w]+)\(inst [^ ]+ ! >?= wanted (?P<v>[\-.+\w:~]+)\)": > "\g<pk> (>= \g<v>)", > - "(?s)^E: Couldn't find package (?P<pk>[\-+.\w]+)(?!.*^E: Couldn't > find package)": "\g<pk>", > - "(?s)^E: Package '?(?P<pk>[\-+.\w]+)'? has no installation > candidate(?!.*^E: Package)": "\g<pk>", > - "(?s)^E: Unable to locate package (?P<pk>[\-+.\w]+)(?!.*^E: Unable > to locate package)": "\g<pk>", > + 'The following packages have unmet dependencies:\n' > + '.*: Depends: (?P<p>[^ ]*( \([^)]*\))?)': "\g<p>", > } > > > @@ -43,8 +40,11 @@ > def __init__(self, slave, buildid, **kwargs): > DebianBuildManager.__init__(self, slave, buildid, **kwargs) > self._sbuildpath = os.path.join(self._slavebin, "sbuild-package") > - self._sbuildargs = slave._config.get("binarypackagemanager", > - "sbuildargs").split(" ") > + > + @property > + def chroot_path(self): > + return os.path.join( > + self.home, "build-" + self._buildid, 'chroot-autobuild') > > def initiate(self, files, chroot, extra_args): > """Initiate a build with a given set of files and chroot.""" > @@ -68,70 +68,36 @@ > > def doRunBuild(self): > """Run the sbuild process to build the package.""" > + currently_building_path = os.path.join( > + self.chroot_path, 'CurrentlyBuilding') > + currently_building_contents = ( > + 'Package: %s\n' > + 'Component: %s\n' > + 'Suite: %s\n' > + 'Purpose: %s\n' > + % (self._dscfile.split('_')[0], self.component, self.suite, > + self.archive_purpose)) > + if self.build_debug_symbols: > + currently_building_contents += 'Build-Debug-Symbols: yes\n' > + currently_building = open(currently_building_path, 'w') > + currently_building.write(currently_building_contents) > + currently_building.close() Here and elsewhere, we could use a context manager nowadays; any builders still on hardy are about to die and aren't going to be upgraded to this. > + > args = ["sbuild-package", self._buildid, self.arch_tag] > args.append(self.suite) > - args.extend(self._sbuildargs) > - args.append("--archive=" + self.distribution) > + args.extend(["-c", "chroot:autobuild"]) > + args.append("--arch=" + self.arch_tag) > args.append("--dist=" + self.suite) > + args.append("--purge=never") > + args.append("--nolog") > if self.arch_indep: > args.append("-A") > - if self.archive_purpose: > - args.append("--purpose=" + self.archive_purpose) > - if self.build_debug_symbols: > - args.append("--build-debug-symbols") > - args.append("--architecture=" + self.arch_tag) > - args.append("--comp=" + self.component) > args.append(self._dscfile) > - self.runSubProcess( self._sbuildpath, args ) > + self.runSubProcess(self._sbuildpath, args) > > def iterate_SBUILD(self, success): > """Finished the sbuild run.""" > - if success != SBuildExitCodes.OK: > - log_patterns = [] > - stop_patterns = [["^Toolchain package versions:", re.M]] > - > - if (success == SBuildExitCodes.DEPFAIL or > - success == SBuildExitCodes.PACKAGEFAIL): > - for rx in BuildLogRegexes.GIVENBACK: > - log_patterns.append([rx, re.M]) > - > - if success == SBuildExitCodes.DEPFAIL: > - for rx in BuildLogRegexes.DEPFAIL: > - log_patterns.append([rx, re.M]) > - > - if log_patterns: > - rx, mo = self.searchLogContents(log_patterns, stop_patterns) > - if mo: > - if rx in BuildLogRegexes.GIVENBACK: > - success = SBuildExitCodes.GIVENBACK > - elif rx in BuildLogRegexes.DEPFAIL: > - if not self.alreadyfailed: > - dep = BuildLogRegexes.DEPFAIL[rx] > - print("Returning build status: DEPFAIL") > - print("Dependencies: " + mo.expand(dep)) > - self._slave.depFail(mo.expand(dep)) > - success = SBuildExitCodes.DEPFAIL > - else: > - success = SBuildExitCodes.PACKAGEFAIL > - else: > - success = SBuildExitCodes.PACKAGEFAIL > - > - if success == SBuildExitCodes.GIVENBACK: > - if not self.alreadyfailed: > - print("Returning build status: GIVENBACK") > - self._slave.giveBack() > - elif success == SBuildExitCodes.PACKAGEFAIL: > - if not self.alreadyfailed: > - print("Returning build status: PACKAGEFAIL") > - self._slave.buildFail() > - elif success >= SBuildExitCodes.BUILDERFAIL: > - # anything else is assumed to be a buildd failure > - if not self.alreadyfailed: > - print("Returning build status: BUILDERFAIL") > - self._slave.builderFail() > - self.alreadyfailed = True > - self.doReapProcesses(self._state) > - else: > + if success == SBuildExitCodes.OK: > print("Returning build status: OK") > try: > self.gatherResults() > @@ -140,6 +106,64 @@ > self._slave.buildFail() > self.alreadyfailed = True > self.doReapProcesses(self._state) > + return > + > + log_patterns = [] > + stop_patterns = [["^Toolchain package versions:", re.M]] > + > + # We don't distinguish attempted and failed. > + if success == SBuildExitCodes.ATTEMPTED: > + success = SBuildExitCodes.FAILED > + > + if success == SBuildExitCodes.GIVENBACK: > + for rx in BuildLogRegexes.GIVENBACK: > + log_patterns.append([rx, re.M]) > + # Check the last 4KiB for the Fail-Stage. If it failed > + # during install-deps, search for the missing dependency > + # string. > + log = open(os.path.join(self._cachepath, "buildlog")) > + try: > + log.seek(-4096, os.SEEK_END) > + except IOError: > + pass > + tail = log.read(4096) > + log.close() > + if re.search("^Fail-Stage: install-deps$", tail, re.M): > + for rx in BuildLogRegexes.DEPFAIL: > + log_patterns.append([rx, re.M]) > + > + missing_dep = None > + if log_patterns: > + rx, mo = self.searchLogContents(log_patterns, stop_patterns) > + if mo is None: > + # It was givenback, but we can't see a valid reason. > + # Assume it failed. > + success = SBuildExitCodes.FAILED > + elif rx in BuildLogRegexes.DEPFAIL: > + # A depwait match forces depwait. > + missing_dep = mo.expand(BuildLogRegexes.DEPFAIL[rx]) > + else: > + # Otherwise it was a givenback pattern, so leave it > + # in givenback. > + pass > + > + if not self.alreadyfailed: > + if missing_dep is not None: > + print("Returning build status: DEPFAIL") > + print("Dependencies: " + missing_dep) > + self._slave.depFail(missing_dep) > + elif success == SBuildExitCodes.GIVENBACK: > + print("Returning build status: GIVENBACK") > + self._slave.giveBack() > + elif success == SBuildExitCodes.FAILED: > + print("Returning build status: PACKAGEFAIL") > + self._slave.buildFail() > + elif success >= SBuildExitCodes.BUILDERFAIL: > + # anything else is assumed to be a buildd failure > + print("Returning build status: BUILDERFAIL") > + self._slave.builderFail() > + self.alreadyfailed = True > + self.doReapProcesses(self._state) > > def iterateReap_SBUILD(self, success): > """Finished reaping after sbuild run.""" > > === modified file 'lpbuildd/check_implicit_pointer_functions.py' > --- lpbuildd/check_implicit_pointer_functions.py 2011-11-09 09:28:06 > +0000 > +++ lpbuildd/check_implicit_pointer_functions.py 2015-05-11 11:00:44 > +0000 > @@ -92,7 +92,7 @@ > errlist += err+"\n" > print err > if not warn_only: > - rv = 3 > + rv = 2 > > if len(errlist): > if in_line: > > === modified file 'lpbuildd/tests/buildd-slave-test.conf' > --- lpbuildd/tests/buildd-slave-test.conf 2015-05-11 11:00:44 +0000 > +++ lpbuildd/tests/buildd-slave-test.conf 2015-05-11 11:00:44 +0000 > @@ -6,6 +6,3 @@ > bindhost = localhost > bindport = 8221 > sharepath = /var/tmp/buildd > - > -[binarypackagemanager] > -sbuildargs = -dautobuild --nolog --batch > > === modified file 'lpbuildd/tests/test_binarypackage.py' > --- lpbuildd/tests/test_binarypackage.py 2015-05-11 11:00:44 +0000 > +++ lpbuildd/tests/test_binarypackage.py 2015-05-11 11:00:44 +0000 > @@ -14,6 +14,7 @@ > from lpbuildd.binarypackage import ( > BinaryPackageBuildManager, > BinaryPackageBuildState, > + SBuildExitCodes, > ) > from lpbuildd.tests.fakeslave import ( > FakeMethod, > @@ -85,6 +86,8 @@ > {'distribution': 'ubuntu', 'suite': 'warty', > 'ogrecomponent': 'main'}) > > + os.makedirs(self.chrootdir) > + > # Skip DebianBuildManager states to the state directly before > # SBUILD. > self.buildmanager._state = BinaryPackageBuildState.UPDATE > @@ -95,8 +98,9 @@ > BinaryPackageBuildState.SBUILD, > [ > 'sharepath/slavebin/sbuild-package', 'sbuild-package', > - self.buildid, 'i386', 'warty', 'sbuildargs', '--archive=ubuntu', > - '--dist=warty', '--architecture=i386', '--comp=main', > 'foo_1.dsc', > + self.buildid, 'i386', 'warty', '-c', 'chroot:autobuild', > + '--arch=i386', '--dist=warty', '--purge=never', '--nolog', > + 'foo_1.dsc', > ], True) > self.assertFalse(self.slave.wasCalled('chrootFail')) > > @@ -138,7 +142,7 @@ > write_file(changes_path, "I am a changes file.") > > # After building the package, reap processes. > - self.assertScansSanely(0) > + self.assertScansSanely(SBuildExitCodes.OK) > self.assertFalse(self.slave.wasCalled('buildFail')) > self.assertEqual( > [((changes_path,), {})], self.slave.addWaitingFile.calls) > @@ -236,7 +240,7 @@ > "I am a changes file.") > > # After building the package, reap processes. > - self.assertScansSanely(0) > + self.assertScansSanely(SBuildExitCodes.OK) > self.assertTrue(self.slave.wasCalled('buildFail')) > self.assertEqual( > [((os.path.join(build_dir, 'foo_1_i386.changes'),), {})], > @@ -251,12 +255,17 @@ > self.startBuild() > write_file( > os.path.join(self.buildmanager._cachepath, 'buildlog'), > - "E: Unable to locate package nonexistent\n") > + "The following packages have unmet dependencies:\n" > + + " sbuild-build-depends-hello-dummy : Depends: enoent but it is > " > + + "not installable\n" > + + "E: Unable to correct problems, you have held broken > packages.\n" > + + ("a" * 4096) + "\n" > + + "Fail-Stage: install-deps\n") > > # After building the package, reap processes. > - self.assertScansSanely(1) > + self.assertScansSanely(SBuildExitCodes.GIVENBACK) > self.assertFalse(self.slave.wasCalled('buildFail')) > - self.assertEqual([(("nonexistent",), {})], self.slave.depFail.calls) > + self.assertEqual([(("enoent",), {})], self.slave.depFail.calls) > > # Control returns to the DebianBuildManager in the UMOUNT state. > self.assertUnmountsSanely() > @@ -270,6 +279,6 @@ > os.path.join(self.buildmanager._cachepath, 'buildlog'), > "E: Everything is broken.\n") > > - self.assertScansSanely(1) > + self.assertScansSanely(SBuildExitCodes.GIVENBACK) > self.assertTrue(self.slave.wasCalled('buildFail')) > self.assertFalse(self.slave.wasCalled('depFail')) > > === removed file 'sbuild' > --- sbuild 2014-06-25 01:50:28 +0000 > +++ sbuild 1970-01-01 00:00:00 +0000 > @@ -1,3668 +0,0 @@ > -#! /usr/bin/perl > -# > -# sbuild: build packages, obeying source dependencies > -# Copyright (C) 1998-2000 Roman Hodek > <[email protected]> > -# > -# 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; either version 2 of the > -# License, or (at your option) any later version. > -# > -# 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, write to the Free Software > -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > -# > -# $Id: sbuild,v 1.170 2002/10/10 18:50:44 rnhodek Exp $ > -# > -# $Log: sbuild,v $ > -# Revision 1.170 2002/10/10 18:50:44 rnhodek > -# Security/accepted autobuilding patch by Ryan. > -# > -# Revision 1.169 2002/03/11 09:49:55 rnhodek > -# chroot_apt_options: don't just set Dir::Etc::sourcelist, but whole > -# Dir::Etc, to avoid new preferences. > -# > -# Revision 1.168 2002/02/07 09:12:25 rnhodek > -# Fixed sudo call for running scripts. > -# > -# Revision 1.167 2002/01/22 08:53:10 rnhodek > -# Use capitalized "Noninteractive" das DEBIAN_FRONTENT. > -# > -# Revision 1.166 2001/11/08 09:32:10 rnhodek > -# fetch_source_file: in case of apt, need to pass up a $dscfile with > -# epoch stripped. > -# > -# Revision 1.165 2001/11/07 18:04:31 rnhodek > -# Argl.. I should learn perl first :) > -# > -# Revision 1.164 2001/11/07 09:25:59 rnhodek > -# fetch_source_files: after apt-get, fix $dscfile not to contain epoch. > -# > -# Revision 1.163 2001/11/06 15:11:24 rnhodek > -# fetch_source_files: don't touch symlinks generated by apt-get. > -# > -# Revision 1.162 2001/11/06 12:29:22 rnhodek > -# New config var $use_FetchFile (default 0). > -# Integrated patches for using apt-get to download sources; modified so > -# that old code (using FetchFile.pm) still present. > -# run_apt: Fix parsing error of apt-output (\s matched ^M printed by > -# pre-configuring). > -# > -# Revision 1.161 2001/10/29 12:20:41 rnhodek > -# Added $fakeroot var. > -# > -# Revision 1.160 2001/10/29 08:27:53 rnhodek > -# Fix typo in message. > -# > -# Revision 1.159 2001/06/18 09:57:55 rnhodek > -# Use --database option when wanna_build_dbbase set in config. > -# > -# Revision 1.158 2001/06/01 09:54:36 rnhodek > -# Fix two typos. > -# > -# Revision 1.157 2001/05/31 08:08:08 rnhodek > -# Fixed thinko in conflicts checking (tnx James) > -# > -# Revision 1.156 2001/05/30 08:20:05 rnhodek > -# Use /var/lib/apt as Dir::State if exists (newer apt versions use that) > -# (tnx to Ryan Murray). > -# > -# Revision 1.155 2001/05/30 08:17:01 rnhodek > -# Print also architecture at start of log. > -# > -# Revision 1.154 2001/05/29 07:33:54 rnhodek > -# Also handle versioned Build-Conflicts. > -# (Tnx to David Schleef <[email protected]>) > -# > -# Revision 1.153 2001/03/13 08:45:17 rnhodek > -# Run chmod -R on source tree only after unpacking. > -# > -# Revision 1.152 2001/02/19 09:23:24 rnhodek > -# Fix typo. > -# > -# Revision 1.151 2001/02/19 08:43:22 rnhodek > -# Fix wrong arch logic. > -# > -# Revision 1.150 2001/01/22 12:56:16 rnhodek > -# Fix handling of arch-restricted build-deps (tnx to Ryan Murray). > -# > -# Revision 1.149 2001/01/15 11:17:36 rnhodek > -# Fixed typo. > -# > -# Revision 1.148 2001/01/15 10:59:18 rnhodek > -# Shortcut when looking for non-dsc files: first try to fetch from same > -# dir as .dsc and FF_search only if that fails. > -# > -# Revision 1.147 2001/01/10 16:16:48 rnhodek > -# Move all built files from chroot dir, not only *.deb. > -# > -# Revision 1.146 2000/10/23 10:39:24 rnhodek > -# Before doing chmod on /etc/ld.so.conf, test if it exists at all. > -# > -# Revision 1.145 2000/10/19 09:08:35 rnhodek > -# A couple of little fixes from Ben. > -# Checks and assures that /etc/ld.so.conf is readable. > -# Support for local overrides with $conf::srcdep_over. > -# > -# Revision 1.144 2000/06/27 12:34:00 rnhodek > -# Implemented new 'prepre' and 'unpack' sections for special targets; > -# the first is a script run before package installation, and the latter > -# can list source packages that should be unpacked in the build dir. > -# > -# Revision 1.143 2000/06/20 14:39:59 rnhodek > -# Call apt-get with some options for relocating various files instead of > -# chrooting it; this avoids that the archive must be available in chroot > -# environment; same is true for dpkg and apt-cache calls. > -# If chrooted, call dpkg with the chroot dir as cwd to avoid "cannot get > -# current directory" errors; same for apt option DPkg::Run-Directory. > -# > -# Revision 1.142 2000/06/19 14:09:00 rnhodek > -# Fix syntax error. > -# > -# Revision 1.141 2000/06/19 14:05:38 rnhodek > -# Call buildd-addpkg with --chroot=DIR options for each dist that is >= > -# the one building for (to run apt-get update in the chroot > -# environments). > -# > -# Revision 1.140 2000/06/19 09:10:24 rnhodek > -# Obey new config var @ignore_watches_no_build_deps, i.e. don't flag > -# watches that are listed there if the package doesn't have build deps. > -# In check_watches(), strip $chroot_dir instead of $chroot_build_dir > -# from pathname. > -# > -# Revision 1.139 2000/06/13 10:54:43 rnhodek > -# Also execute special dependency scripts in chroot environment. > -# > -# Revision 1.138 2000/06/09 12:47:52 rnhodek > -# File .dsc filename for rbuilder (with URL). > -# > -# Revision 1.137 2000/06/09 09:15:21 rnhodek > -# Always install built package (if already) when building chroot; i.e. > -# the $system_level test is not necessary when chrooted. > -# > -# Revision 1.136 2000/06/09 08:20:52 rnhodek > -# Fixed su usage in sub build. > -# > -# Revision 1.135 2000/06/08 14:02:11 rnhodek > -# After changing to chroot dir, change back to be the normal user again > -# and start dpkg-buildpackage with -rsudo again; some packages require > -# that the build target is executed as non-root. > -# > -# Revision 1.134 2000/06/08 13:01:54 rnhodek > -# apt-cache calls need sudo, too, when using chroot. > -# > -# Revision 1.133 2000/06/08 09:13:31 rnhodek > -# Implemented chroot builds; there are a few new global variables > -# $main::chroot_*; major changes are in build, where the source tree is > -# unpacked somewhere else, dpkg-buildpackage called under chroot and > -# built packages are moved back again; also all apt-get and dpkg calls > -# are chroot-ed and /var/lib/dpkg/status is accessed from the chroot > -# environment; also watches are checked under the new root dir. > -# > -# Revision 1.132 2000/06/06 14:37:05 rnhodek > -# New option --source (-s): Also build source package, i.e. don't pass > -# -b or -B to dpkg-buildpackage. > -# > -# Revision 1.131 2000/05/30 15:41:34 rnhodek > -# Call buildd-addpkg with --dist option. > -# Install freshly built packages only if $conf::system_level >= $dist. > -# > -# Revision 1.130 2000/05/16 12:34:20 rnhodek > -# Insert a chmod -R go+rX on the build tree to make files readable; it > -# happens sometimes that files in a .orig.tar.gz have restrictive > -# permissions and this can be inconvenient. > -# > -# Revision 1.129 2000/03/01 14:43:34 rnhodek > -# Also match error message "dpkg: status database area is locked" from > -# apt and retry call later. > -# > -# Revision 1.128 2000/02/16 15:21:33 rnhodek > -# Fix a print message in merge_pkg_build_deps. > -# > -# Revision 1.127 2000/02/16 15:20:38 rnhodek > -# Print version number of sbuild in package log. > -# > -# Revision 1.126 2000/02/16 15:15:15 rnhodek > -# Fix regexp for finding !needs-no-XXX packages. > -# Move !needs-no-XXX from central deps to $main::additional_deps so that > -# they can be found by prepare_watches later. > -# > -# Revision 1.125 2000/02/15 14:40:35 rnhodek > -# Remove forgotten debugging code. > -# > -# Revision 1.124 2000/02/15 11:12:43 rnhodek > -# Expand virtual packages in package build dependencies for comparing > -# with central deps. > -# > -# Revision 1.123 2000/02/11 11:17:07 rnhodek > -# Do not activate watches for packages XXX if a negative dependency > -# needs-no-XXX exists (used to be just a comment, now really processed > -# by sbuild.) > -# Also do not activate watches for dependencies of pkg build deps. > -# > -# Revision 1.122 2000/02/09 15:57:25 rnhodek > -# In merge_pkg_build_deps, do not show warnings about missing > -# !this-package-does-not-exist or !needs-no-xxx dependencies. > -# > -# Revision 1.121 2000/02/04 14:04:18 rnhodek > -# Use --no-down-propagation. > -# > -# Revision 1.120 2000/02/01 12:05:56 rnhodek > -# In binNMU mode, a '_' was missing in the job name. > -# > -# Revision 1.119 2000/01/28 14:54:43 rnhodek > -# Accept abbrevs for distribution options (-ds, -df, -du) here, too. > -# New option --make-binNMU=entry. > -# New binNMU hack to modify debian/changelog; it will add a new entry > -# for the NMU version. > -# New helper function binNMU_version to generate a new version number. > -# > -# Revision 1.118 2000/01/13 14:32:30 rnhodek > -# For compiling on slink systems, pass the --force-confold option to > -# dpkg only for versions < 1.4.1.18 (that don't understand it yet). > -# > -# Revision 1.117 1999/12/17 13:49:50 rnhodek > -# Improved output about missing central deps: build-essential (act. > -# policy) and dependencies of pkg build deps are filtered out and > -# printed separately. > -# New functions cmp_dep_lists, read_build_essential, > -# expand_dependencies, and get_dependencies for the above. > -# > -# Revision 1.116 1999/12/17 11:04:43 rnhodek > -# When pkg build-deps were read from debian/sbuild-build-deps, a wrong > -# package name was used. > -# > -# Revision 1.115 1999/12/09 09:54:42 rnhodek > -# Again fixed a fatal typo... > -# > -# Revision 1.114 1999/12/08 12:33:16 rnhodek > -# merge_pkg_build_deps: Fix printing of overrides. > -# > -# Revision 1.113 1999/12/08 12:25:34 rnhodek > -# Special dependencies are implicitly overrides, i.e. are added to the > -# package-provided build deps. > -# > -# Revision 1.112 1999/12/08 11:31:38 rnhodek > -# get_dpkg_status: don't reset $res{$pkg}->{Installed} to 0 if $pkg is > -# provided. > -# > -# Revision 1.111 1999/12/08 10:37:33 rnhodek > -# Change parsing of .dsc file so that multi-line build dependencies are > -# allowed. > -# Make warning about missing central deps a bit bigger. > -# > -# Revision 1.110 1999/12/06 15:00:33 rnhodek > -# Fix comparison with old deps (must copy them, not only the reference). > -# > -# Revision 1.109 1999/12/06 08:35:53 rnhodek > -# Fixed typo. > -# > -# Revision 1.108 1999/12/03 09:58:16 rnhodek > -# If a pkg has its own build deps, compare them with the central ones > -# and report missing ones. > -# > -# Revision 1.107 1999/11/30 13:54:38 rnhodek > -# Print a message if build deps from the .dsc are used (to avoid confusion). > -# If a pkg has build deps, store them in debian/.sbuild-build-deps to > -# have them available when rebuilding later (no .dsc anymore); also > -# check for this file and read deps from it if building without a .dsc > -# in unpacked source. > -# > -# Revision 1.106 1999/11/15 12:30:15 rnhodek > -# merge_pkg_build_deps: added missing if $main::debug. > -# > -# Revision 1.105 1999/11/03 14:56:32 rnhodek > -# When running apt, set env var DEBIAN_FRONTEND to noninteractive to > -# stop debconf from asking questions or complaining that /dev/tty can't > -# be opened. > -# > -# Revision 1.104 1999/11/02 16:43:51 rnhodek > -# check_inst_packages: also upgrade dependencies of src-deps (if they're > -# already installed); some -dev packages fail to correctly require an > -# identical versioned shlib pkg, so in some cases only the -dev pkg was > -# installed. > -# > -# Revision 1.103 1999/11/02 15:45:43 rnhodek > -# build: Use epoch-stripped version number for the .changes file. > -# check_inst_packages: forgot a if $main::debug. > -# > -# Revision 1.102 1999/10/29 13:07:49 rnhodek > -# New option --stats-dir=DIR; if used, a "1" is appended to > -# DIR/give-back each time a package is given back. > -# > -# Revision 1.101 1999/10/29 12:32:24 rnhodek > -# If using an already unpacked source tree, check (with > -# dpkg-parsechangelog) if it's really the requested version. > -# Make apt-get run dpkg with --force-confold, as the </dev/null trick > -# doesn't work anymore with dpkg >= 1.4.1.18. > -# > -# Revision 1.100 1999/10/25 12:12:21 rnhodek > -# check_inst_packages: Add packages to @deps_inst only if they're not > -# already to be installed. > -# > -# Revision 1.99 1999/10/22 09:01:36 rnhodek > -# Minor changes to output of check_inst_packages. > -# > -# Revision 1.98 1999/10/21 14:21:57 rnhodek > -# Oops... call check_inst_packages only if build was successful. > -# > -# Revision 1.97 1999/10/21 11:46:50 rnhodek > -# Deleted RCS logs for < 1.50. > -# New option --store-built-packages. > -# Fix package name parsing: \w also matches '_' which is unwanted; > -# replace by a-zA-Z. > -# Read reverse sourcedeps of $main::store_built_packages. > -# New sub check_inst_packages. > -# > -# Revision 1.96 1999/09/27 11:18:10 rnhodek > -# Added a missing PLOG. > -# > -# Revision 1.95 1999/09/15 09:10:25 rnhodek > -# Additionally print a warning if a special dep has a version relation. > -# > -# Revision 1.94 1999/09/15 09:08:12 rnhodek > -# Changed parsing of dependencies a bit so that special deps can have > -# arch restrictions, too. > -# > -# Revision 1.93 1999/08/30 09:44:35 rnhodek > -# get_dpkg_status: don't exit too early if a pkg isn't in the arg list, > -# as it might be provided only. > -# > -# Revision 1.92 1999/08/27 13:32:04 rnhodek > -# --auto-give-back has a new optional argument, the user and hostname > -# where to call wanna-build (like $conf::sshcmd); this is needed that > -# sbuild can do give-backs when there's no local wanna-build. > -# > -# Revision 1.91 1999/08/23 12:53:02 rnhodek > -# Support for alternatives. > -# Support for [ARCH1 !ARCH2] arch restriction on dependencies. > -# Parses only src-deps which are needed for packages to be built. > -# Reads Build-{Depends,Conflicts}{,-Indep}: fields from .dsc if present; > -# those override the central src-deps, except those marked as override > -# (& prefix). > -# Implemented abbrevs as kind of macros in src-deps. > -# New option --add-depends (-a). > -# New option --arch-all (-A). > -# > -# Revision 1.90 1999/08/11 15:28:11 rnhodek > -# Insert missing wait call in run_script to get correct return value. > -# > -# Revision 1.89 1999/08/10 14:01:49 rnhodek > -# Virtual packages as dependencies didn't work really yet -- the > -# consistency check didn't see them (dpkg --status doesn't know them) > -# and thus aborted the build; solution: get_dpkg_status now directly > -# reads the status file (which should be a bit faster, too) and extracts > -# Provides: fields of all installed packages and considers those virtual > -# packages installed, too. > -# Print "Source-dependencies not satisfied" message to package log, not > -# to sbuild log. > -# Same in run_apt for virtual package handling. > -# Fix stdout/stderr redirecting when running scripts. > -# > -# Revision 1.88 1999/07/13 07:23:55 rnhodek > -# Use GDBM for time/space databases, as perl-5.004 seems not to contain > -# DB_File anymore. > -# > -# Revision 1.87 1999/06/21 12:52:00 rnhodek > -# Seems apt has a new error message if a cached Packages file isn't > -# up-to-date anymore -- recognize this msg, too, and reun apt-get update. > -# > -# Revision 1.86 1999/06/09 15:05:38 rnhodek > -# Fix loop in apply_patches. > -# Don't fail due to failed patch if a global patch. > -# Global patches are no syntax error when parsing src-deps... > -# > -# Revision 1.85 1999/06/04 09:47:02 rnhodek > -# Add support for global patches, which will be tried on any package; > -# their names in source-dependencies start with "**". > -# > -# Revision 1.84 1999/06/04 08:17:17 rnhodek > -# When calling wanna-build --give-back, don't forget the --dist argument! > -# Added support for virtual packages as source dependencies: apt-get tells us > -# which alternatives are possible, and one of these is selected either by > -# %conf::alternatives or by random. > -# > -# Revision 1.83 1999/06/02 09:07:47 rnhodek > -# With --batch, write each finished job to SBUILD-FINISHED; buildd can pick > up > -# this file if sbuild crashes and needs not rebuild already done stuff. The > file > -# is removed on normal exit and if sbuild dumps to REDO during a shutdown. > -# > -# Revision 1.82 1999/06/02 08:47:39 rnhodek > -# Remove as many die's as possible -- the bad exit status can cause > -# buildd to retry all packages of an sbuild run; better let this one > -# package fail. > -# Make sure that after build() we're in the correct directory: some > -# chdir()s were missing; also don't chdir("..") because this can be > -# wrong if we followed a symlink, use $main::cwd instead. > -# If the package directory already exists as a symlink, abort the build. > -# > -# Revision 1.81 1999/05/31 12:59:41 rnhodek > -# Run du after build under sudo, to avoid error messages about > -# unreadable dirs. > -# > -# Revision 1.80 1999/05/27 13:28:04 rnhodek > -# Oops, missed an epoch fix (when constructing the .changes file name). > -# > -# Revision 1.79 1999/05/26 11:34:11 rnhodek > -# Ignore epochs for fetching files. > -# > -# Revision 1.78 1999/05/26 09:48:23 rnhodek > -# If dpkg-source fails, remove .tmp-nest dir. > -# > -# Revision 1.77 1999/05/05 07:56:51 rnhodek > -# Need to empty %main::this_watches before filling it for a new package; > -# otherwise we have some spurious reports :-) > -# > -# Revision 1.76 1999/05/04 14:51:40 rnhodek > -# Some more minor stuff for avg-build-space: Reset global > -# $main::this_space to 0 before each build to avoid using the figure of > -# the previous package in case of errors; don't write a 0 value into the > -# database. > -# > -# Revision 1.75 1999/05/04 14:43:01 rnhodek > -# Fix parsing of a single dependency: package name never should contain > -# a '('. > -# > -# Revision 1.74 1999/05/04 14:29:51 rnhodek > -# Determine how much space is required for a build (final build dir + > -# generated .debs) after dpkg-buildpackage is finished; display figure > -# in package log and also store it in $conf::avg_space_db (analogous to > -# avg_time_db). > -# > -# Revision 1.73 1999/05/03 12:53:25 rnhodek > -# After unpacking src dir, run "chmod -R g-s ." on it; some > -# .orig.tar.gz's are packed with the setgid bit, which causes the debian > -# dir and all subdirs to be created setgid, too, and later dpkg-deb > -# --build complains about this. > -# > -# Revision 1.72 1999/04/22 14:16:25 rnhodek > -# Don't kill tee process if verbose but --nolog set -- $pkg_tee_pid > -# undefined then! > -# > -# Revision 1.71 1999/04/21 14:54:10 rnhodek > -# Implemented watches if certain binaries have been used during a build > -# without a source dependency. > -# > -# Revision 1.70 1999/03/12 10:29:32 rnhodek > -# New option --force-depends (-f) to override src-deps of a package. > -# > - > -BEGIN { > - ($main::HOME = $ENV{'HOME'}) > - or die "HOME not defined in environment!\n"; > - push( @INC, "$main::HOME/lib" ); > -} > - > -chomp( $main::HOSTNAME = `hostname` ); > - > -package conf; > -$HOME = $main::HOME; > -# defaults: > -@dist_parts = qw(main contrib non-free); > -$source_dependencies = "/etc/source-dependencies"; > -$mailprog = "/usr/sbin/sendmail"; > -$dpkg = "/usr/bin/dpkg"; > -$sudo = "/usr/bin/sudo"; > -$su = "/bin/su"; > -$fakeroot = "/usr/bin/fakeroot"; > -$apt_get = "/usr/bin/apt-get"; > -$apt_cache = "/usr/bin/apt-cache"; > -$dpkg_source = "/usr/bin/dpkg-source"; > -$build_env_cmnd = ""; > -$pgp_options = "-us -uc"; > -$log_dir = "$main::HOME/logs"; > -$mailto = ""; > -$purge_build_directory = "successful"; > -@toolchain_regex = ( 'binutils$', 'gcc-[\d.]+$', 'g\+\+-[\d.]+$', > 'libstdc\+\+', 'libc[\d.]+-dev$', 'linux-kernel-headers$', 'dpkg-dev$', > 'make$' ); > -$stalled_pkg_timeout = 90; # minutes > -$srcdep_lock_wait = 1; # minutes > -%individual_stalled_pkg_timeout = (); > -$path = > "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin:/usr/games"; > -# read conf files > -require "/usr/share/launchpad-buildd/sbuild.conf" if -r > "/usr/share/launchpad-buildd/sbuild.conf"; > -require "$HOME/.lp-sbuildrc" if -r "$HOME/.lp-sbuildrc"; > -# some checks > -#die "mailprog binary $conf::mailprog does not exist or isn't executable\n" > -# if !-x $conf::mailprog; > -die "sudo binary $conf::sudo does not exist or isn't executable\n" > - if !-x $conf::sudo; > -die "apt-get binary $conf::apt_get does not exist or isn't executable\n" > - if !-x $conf::apt_get; > -die "apt-cache binary $conf::apt_cache does not exist or isn't executable\n" > - if !-x $conf::apt_cache; > -die "dpkg-source binary $conf::dpkg_source does not exist or isn't > executable\n" > - if !-x $conf::dpkg_source; > -#die "$conf::log_dir is not a directory\n" if ! -d $conf::log_dir; > -die "$conf::srcdep_lock_dir is not a directory\n" if ! -d > $conf::srcdep_lock_dir; > -die "conf::mailto not set\n" if !$conf::mailto; > -package main; > - > -use strict; > -use GDBM_File; > -use POSIX; > -use FileHandle; > -use Cwd; > - > -# avoid intermixing of stdout and stderr > -$| = 1; > - > -# We should not ignore HUP for our children - it breaks test suites. > -# in case the terminal disappears, the build should continue > -#$SIG{'HUP'} = 'IGNORE'; > - > -$main::distribution = ""; > -$main::distribution = $conf::default_distribution if > $conf::default_distribution; > - > -chomp( $main::arch = `$conf::dpkg --print-architecture` ); > -$main::username = (getpwuid($<))[0] || $ENV{'LOGNAME'} || $ENV{'USER'}; > -$main::debug = 0; > -$main::verbose = 0; > -$main::batchmode = 0; > -$main::auto_giveback = 0; > -$main::nomail = 0; > -$main::build_arch_all = 0; > -$main::build_source = 0; > -$main::jobs_file = cwd() . "/build-progress"; > -$main::max_lock_trys = 120; > -$main::lock_interval = 5; > -$main::cwd = cwd(); > -$main::ilock_file = "$conf::srcdep_lock_dir/install"; > -$main::srcdep_lock_cnt = 0; > -$main::chroot_dir = ""; > -$main::chroot_build_dir = ""; > -$main::chroot_apt_options = ""; > -@main::toolchain_pkgs = (); > -$main::component=""; > -$main::nr_processors = $ENV{'NR_PROCESSORS'} if $ENV{'NR_PROCESSORS'}; > - > -umask(022); > - > -$main::new_dpkg = 0; > -check_dpkg_version(); > - > -while( @ARGV && $ARGV[0] =~ /^-/ ) { > - $_ = shift @ARGV; > - if (/^-v$/ || /^--verbose$/) { > - $main::verbose++; > - } > - elsif (/^-D$/ || /^--debug$/) { > - $main::debug++; > - } > - elsif (/^-b$/ || /^--batch$/) { > - $main::batchmode = 1; > - } > - elsif (/^-n$/ || /^--nolog$/) { > - $main::nolog = 1; > - } > - elsif (/^-A$/ || /^--arch-all$/) { > - $main::build_arch_all++; > - } > - elsif (/^-s$/ || /^--source$/) { > - $main::build_source++; > - $conf::purge_build_directory = "never"; > - } > - elsif (/^--architecture=(.)/) { > - $conf::arch=$1.$'; > - } > - elsif (/^--archive=(.)/) { > - $main::archive=$1.$'; > - } > - elsif (/^--comp=(.)/) { > - $main::component=$1.$'; > - } > - elsif (/^--purpose=(.)/) { > - $main::purpose=$1.$'; > - } > - elsif (/^--build-debug-symbols$/) { > - $main::build_debug_symbols = 1; > - } > - elsif (/^-d/ || /^--dist/) { > - if (/^-d(.)/ || /^--dist=(.)/) { > - $main::distribution = $1.$'; > - } > - elsif (!@ARGV) { > - die "$_ option missing argument\n"; > - } > - else { > - $main::distribution = shift @ARGV; > - } > - $main::distribution = "stable" if $main::distribution eq "s"; > - $main::distribution = "testing" if $main::distribution eq "t"; > - $main::distribution = "unstable" if $main::distribution eq "u"; > - } > - elsif (/^-p/ || /^--purge/) { > - if (/^-p(.)/ || /^--purge=(.)/) { > - $conf::purge_build_directory = $1.$'; > - } > - elsif (!@ARGV) { > - die "$_ option missing argument\n"; > - } > - else { > - $conf::purge_build_directory = shift @ARGV; > - } > - die "Bad purge mode\n" > - if !isin($conf::purge_build_directory, qw(always > successful never)); > - } > - elsif (/^-m/ || /^--maintainer/) { > - if (/^-m(.)/ || /^--maintainer=(.)/) { > - $conf::maintainer_name = $1.$'; > - } > - elsif (!@ARGV) { > - die "$_ option missing argument\n"; > - } > - else { > - $conf::maintainer_name = shift @ARGV; > - } > - } > - elsif (/^-f/ || /^--force-depends/) { > - if (/^-f(.)/ || /^--force-depends=(.)/) { > - push( @main::manual_srcdeps, "f".$1.$' ); > - } > - elsif (!@ARGV) { > - die "$_ option missing argument\n"; > - } > - else { > - push( @main::manual_srcdeps, "f".(shift @ARGV) ); > - } > - } > - elsif (/^-a/ || /^--add-depends/) { > - if (/^-a(.)/ || /^--add-depends=(.)/) { > - push( @main::manual_srcdeps, "a".$1.$' ); > - } > - elsif (!@ARGV) { > - die "$_ option missing argument\n"; > - } > - else { > - push( @main::manual_srcdeps, "a".(shift @ARGV) ); > - } > - } > - elsif (/^--auto-give-back(=(.*))?$/) { > - $main::auto_giveback = 1; > - if ($2) { > - my @parts = split( '@', $2 ); > - $main::auto_giveback_socket = "$main::HOME/build" if > @parts > 3; > - $main::auto_giveback_socket .= $parts[$#parts-3] if > @parts > 3; > - $main::auto_giveback_wb_user = $parts[$#parts-2] if > @parts > 2; > - $main::auto_giveback_user = $parts[$#parts-1] if > @parts > 1; > - $main::auto_giveback_host = $parts[$#parts]; > - } > - } > - elsif (/^--database=(.+)$/) { > - $main::database = $1; > - } > - elsif (/^--stats-dir=(.+)$/) { > - $main::stats_dir = $1; > - } > - elsif (/^--make-binNMU=(.+)$/) { > - $main::binNMU = $1; > - $main::binNMUver ||= 1; > - } > - elsif (/^--binNMU=(\d+)$/) { > - $main::binNMUver = $1; > - } > - elsif (/^--use-snapshot$/) { > - $main::useSNAP = 1; > - $main::ld_library_path = "/usr/lib/gcc-snapshot/lib"; > - $conf::path = "/usr/lib/gcc-snapshot/bin:$conf::path"; > - } > - else { > - die "Unknown option: $_\n"; > - } > -} > - > -die "Need distribution\n" if $main::distribution eq ""; > - > -$conf::mailto = $conf::mailto{$main::distribution} > - if $conf::mailto{$main::distribution}; > - > -$main::arch = $conf::arch if $conf::arch; > - > -# variables for scripts: > -open_log(); > -$SIG{'INT'} = \&shutdown; > -$SIG{'TERM'} = \&shutdown; > -$SIG{'ALRM'} = \&shutdown; > -$SIG{'PIPE'} = \&shutdown; > -read_deps( map { m,(?:.*/)?([^_/]+)[^/]*, } @ARGV ); > -if (-d "chroot-autobuild") { > - $main::chroot_dir = "chroot-autobuild"; > - $main::chroot_build_dir = "$main::chroot_dir/build/$main::username/"; > - $conf::srcdep_lock_dir = "$main::chroot_dir/var/debbuild/srcdep-lock"; > - $main::ilock_file = "$conf::srcdep_lock_dir/install"; > - my $absroot = "$main::cwd/$main::chroot_dir"; > - $main::chroot_apt_options = > - "-o APT::Architecture=$main::arch ". > - "-o Dir::State=$absroot/var/". > - (-d "$absroot/var/lib/apt" ? "lib":"state")."/apt ". > - "-o Dir::State::status=$absroot/var/lib/dpkg/status ". > - "-o Dir::Cache=$absroot/var/cache/apt ". > - "-o Dir::Etc=$absroot/etc/apt ". > - "-o DPkg::Options::=--root=$absroot ". > - "-o DPkg::Options::=--force-architecture ". > - "-o DPkg::Run-Directory=$absroot"; > - $main::chroot_apt_op = '$CHROOT_OPTIONS'; > -} > -write_jobs_file(); > - > -my( $pkgv, $pkg ); > -foreach $pkgv (@ARGV) { > - my $urlbase; > - > - > - ($urlbase, $pkgv) = ($1, $3) if $pkgv =~ m,^(\w+://(\S+/)?)([^/]+)$,; > - $pkgv =~ s/\.dsc$//; > - next if !open_pkg_log( $pkgv ); > - (my $pkg = $pkgv) =~ s/_.*$//; > - $main::pkg_start_time = time; > - $main::this_space = 0; > - $main::pkg_status = "failed"; # assume for now > - $main::current_job = $main::binNMU_name || $pkgv; > - $main::additional_deps = []; > - write_jobs_file( "currently building" ); > - if (should_skip( $pkgv )) { > - $main::pkg_status = "skipped"; > - goto cleanup_close; > - } > - my $dscfile = $pkgv.".dsc"; > - $main::pkg_fail_stage = "fetch-src"; > - my @files_to_rm = fetch_source_files( \$dscfile ); > - if (@files_to_rm && $files_to_rm[0] eq "ERROR") { > - shift @files_to_rm; > - goto cleanup_symlinks; > - } > - > - $main::pkg_fail_stage = "install-deps"; > - if (!install_deps( $pkg )) { > - print PLOG "Source-dependencies not satisfied; skipping $pkg\n"; > - goto cleanup_packages; > - } > - > - my $dscbase = basename( $dscfile ); > - $main::pkg_status = "successful" if build( $dscbase, $pkgv ); > - chdir( $main::cwd ); > - write_jobs_file( $main::pkg_status ); > - append_to_FINISHED( $main::current_job ); > - > - cleanup_packages: > - undo_specials(); > - #uninstall_deps(); > - remove_srcdep_lock_file(); > - cleanup_symlinks: > - remove_files( @files_to_rm ); > - cleanup_close: > - analyze_fail_stage( $pkgv ); > - if( $main::pkg_status eq 'failed' ) { > - $main::pkg_status = 'failed ' . $main::pkg_fail_stage; > - } > - write_jobs_file( $main::pkg_status ); > - close_pkg_log( $pkgv ); > - $main::current_job = ""; > - if ( $main::batchmode and (-f "$main::HOME/EXIT-DAEMON-PLEASE") ) { > - main::shutdown("NONE (flag file exit)"); > - } > -} > -write_jobs_file(); > - > -close_log(); > -#unlink( $main::jobs_file ) if $main::batchmode; > -unlink( "SBUILD-FINISHED" ) if $main::batchmode; > -exit 0; > - > -sub fetch_source_files { > - my $dscfile_ref = shift; > - my $dscfile = $$dscfile_ref; > - my ($dir, $dscbase, $files, @other_files, $dscarchs, @made); > - my ($build_depends, $build_depends_indep, $build_conflicts, > - $build_conflicts_indep); > - local( *F ); > - > - $dscfile =~ m,^(.*)/([^/]+)$,; > - ($dir, $dscbase) = ($1, $2); > - my $urlbase; > - $urlbase = $1 if $dscfile =~ m,^(\w+://(\S+/)?)([^/]+)$,; > - (my $pkgv = $dscfile) =~ s,^(.*/)?([^/]+)\.dsc$,$2,; > - my ($pkg, $version) = split /_/, $pkgv; > - @main::have_dsc_build_deps = (); > - > - if (-d $dscfile) { > - if (-f "$dscfile/debian/.sbuild-build-deps") { > - open( F, "<$dscfile/debian/.sbuild-build-deps" ); > - my $pkg; > - while( <F> ) { > - /^Package:\s*(.*)\s*$/i and $pkg = $1; > - /^Build-Depends:\s*(.*)\s*$/i and > $build_depends = $1; > - /^Build-Depends-Indep:\s*(.*)\s*$/i and > $build_depends_indep = $1; > - /^Build-Conflicts:\s*(.*)\s*$/i and > $build_conflicts = $1; > - /^Build-Conflicts-Indep:\s*(.*)\s*$/i and > $build_conflicts_indep = $1; > - } > - close( F ); > - if ($build_depends || $build_depends_indep || > $build_conflicts || > - $build_conflicts_indep) { > - merge_pkg_build_deps( $pkg, $build_depends, > - > $build_depends_indep, $build_conflicts, > - > $build_conflicts_indep ); > - } > - } > - return; > - } > - > - if ($dir ne ".") { > - { > - if (-f "${pkgv}.dsc") { > - print PLOG "${pkgv}.dsc exists in cwd\n"; > - } > - else { > - my %entries; > - my $retried = 0; > - > - retry: > - print PLOG "Checking available source > versions...\n"; > - if (!open( PIPE, "$conf::sudo /usr/sbin/chroot > ". > - "$main::chroot_dir > $conf::apt_cache ". > - "-q showsrc $pkg 2>&1 > </dev/null |" )) { > - print PLOG "Can't open pipe to > apt-cache: $!\n"; > - return ("ERROR"); > - } > - { local($/) = ""; > - while( <PIPE> ) { > - my $ver = $1 if > /^Version:\s+(\S+)\s*$/mi; > - my $tfile = $1 if > /^Files:\s*\n((\s+.*\s*\n)+)/mi; > - @{$entries{$ver}} = map { (split( > /\s+/, $_ ))[3] } > - split( "\n", $tfile ); > - } > - } > - close( PIPE ); > - if ($?) { > - print PLOG "$conf::apt_cache failed\n"; > - return ("ERROR"); > - } > - > - if (!defined($entries{$version})) { > - if (!$retried) { > - # try to update apt's cache if > nothing found > - system "$conf::sudo > /usr/sbin/chroot ". > - "$main::chroot_dir > $conf::apt_get ". > - "update >/dev/null"; > - $retried = 1; > - goto retry; > - } > - print PLOG "Can't find source for > $pkgv\n"; > - print PLOG "(only different version(s) > ", > - join( ", ", sort > keys %entries), " found)\n" > - if %entries; > - return( "ERROR" ); > - } > - > - print PLOG "Fetching source files...\n"; > - @made = @{$entries{$version}}; > - if (!open( PIPE, "$conf::apt_get > $main::chroot_apt_options ". > - "--only-source -q -d source > $pkg=$version 2>&1 </dev/null |" )) { > - print PLOG "Can't open pipe to > $conf::apt_get: $!\n"; > - return ("ERROR", @made); > - } > - while( <PIPE> ) { > - print PLOG $_; > - } > - close( PIPE ); > - if ($?) { > - print PLOG "$conf::apt_get for sources > failed\n"; > - return( "ERROR", @made ); > - } > - # touch the downloaded files, otherwise > buildd-watcher > - # will complain that they're old :) > - $$dscfile_ref = $dscfile = (grep { /\.dsc$/ } > @made)[0]; > - } > - } > - } > - > - if (!open( F, "<$dscfile" )) { > - print PLOG "Can't open $dscfile: $!\n"; > - return( "ERROR", @made ); > - } > - my $dsctext; > - { local($/); $dsctext = <F>; } > - close( F ); > - > - $dsctext =~ /^Build-Depends:\s*((.|\n\s+)*)\s*$/mi > - and $build_depends = $1; > - $dsctext =~ /^Build-Depends-Indep:\s*((.|\n\s+)*)\s*$/mi > - and $build_depends_indep = $1; > - $dsctext =~ /^Build-Conflicts:\s*((.|\n\s+)*)\s*$/mi > - and $build_conflicts = $1; > - $dsctext =~ /^Build-Conflicts-Indep:\s*((.|\n\s+)*)\s*$/mi > - and $build_conflicts_indep = $1; > - $build_depends =~ s/\n\s+/ /g if defined $build_depends; > - $build_depends_indep =~ s/\n\s+/ /g if defined $build_depends_indep; > - $build_conflicts =~ s/\n\s+/ /g if defined $build_conflicts; > - $build_conflicts_indep =~ s/\n\s+/ /g if defined $build_conflicts_indep; > - > - $dsctext =~ /^Architecture:\s*(.*)$/mi and $dscarchs = $1; > - > - $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files = $1; > - @other_files = map { (split( /\s+/, $_ ))[3] } split( "\n", $files ); > - > - if (!$dscarchs) { > - print PLOG "$dscbase has no Architecture: field -- skipping > arch check!\n"; > - } > - else { > - my $valid_arch; > - for my $a (split(/\s+/, $dscarchs)) { > - if (system("$conf::sudo", "/usr/sbin/chroot", > - "$main::cwd/$main::chroot_dir", > - "dpkg-architecture", "-a".$main::arch, "-i".$a) eq > 0) { > - $valid_arch = 1; > - last; > - } > - } > - if ($dscarchs ne "any" && !($valid_arch) && > - !($dscarchs eq "all" && $main::build_arch_all) ) { > - my $msg = "$dscbase: $main::arch not in arch list or > does not match any arch "; > - $msg .= "wildcards: $dscarchs -- skipping\n"; > - print PLOG $msg; > - $main::pkg_fail_stage = "arch-check"; > - return( "ERROR", @made ); > - } > - } > - print "Arch check ok ($main::arch included in $dscarchs)\n" > - if $main::debug; > - > - if ($build_depends || $build_depends_indep || $build_conflicts || > - $build_conflicts_indep) { > - @main::have_dsc_build_deps = ($build_depends, > $build_depends_indep, > - > $build_conflicts,$build_conflicts_indep); > - merge_pkg_build_deps( $pkg, $build_depends, > $build_depends_indep, > - $build_conflicts, > $build_conflicts_indep ); > - } > - > - return @made; > -} > - > -sub build { > - my $dsc = shift; > - my $pkgv = shift; > - my( $dir, $rv, $changes ); > - my $do_apply_patches = 1; > - local( *PIPE, *F, *F2 ); > - > - fixup_pkgv( \$pkgv ); > - print PLOG "-"x78, "\n"; > - # count build time from now, ignoring the installation of source deps > - $main::pkg_start_time = time; > - $main::this_space = 0; > - $pkgv =~ /^([a-zA-Z\d.+-]+)_([a-zA-Z\d:.+~-]+)/; > - my ($pkg, $version) = ($1,$2); > - (my $sversion = $version) =~ s/^\d+://; > - my $tmpunpackdir = $dsc; > - $tmpunpackdir =~ s/-.*$/.orig.tmp-nest/; > - $tmpunpackdir =~ s/_/-/; > - $tmpunpackdir = "$main::chroot_build_dir$tmpunpackdir"; > - > - if (-d "$main::chroot_build_dir$dsc" && -l > "$main::chroot_build_dir$dsc") { > - # if the package dir already exists but is a symlink, complain > - print PLOG "Cannot unpack source: a symlink to a directory with > the\n", > - "same name already exists.\n"; > - return 0; > - } > - if (! -d "$main::chroot_build_dir$dsc") { > - $main::pkg_fail_stage = "unpack"; > - # dpkg-source refuses to remove the remanants of an > - # aborted dpkg-source extraction, so we will if necessary. > - if (-d $tmpunpackdir) { > - system ("rm -fr $tmpunpackdir"); > - } > - $main::sub_pid = open( PIPE, "-|" ); > - if (!defined $main::sub_pid) { > - print PLOG "Can't spawn dpkg-source: $!\n"; > - return 0; > - } > - if ($main::sub_pid == 0) { > - setpgrp( 0, $$ ); > - if ($main::chroot_build_dir && !chdir( > $main::chroot_build_dir )) { > - print PLOG "Couldn't cd to > $main::chroot_build_dir: $!\n"; > - system ("rm -fr $tmpunpackdir") if -d > $tmpunpackdir; > - exit 1; > - } > - > - my @files; > - push( @files, $dsc ); > - if (!open( F, "<$main::cwd/$dsc" )) { > - print PLOG "Can't open $main::cwd/$dsc: $!\n"; > - return 0; > - } > - my $dsctext; > - { local($/); $dsctext = <F>; } > - close( F ); > - my $files; > - $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files > = $1; > - push(@files, map { (split( /\s+/, $_ ))[3] } split( > "\n", $files )); > - > - my $file; > - foreach $file (@files) { > - system ("cp", "$main::cwd/$file", "$file"); > - } > - exec "$conf::sudo", "/usr/sbin/chroot", > "$main::cwd/$main::chroot_dir", > - "$conf::su", $main::username, "-s", "/bin/sh", > "-c", > - "cd /build/$main::username && > $conf::dpkg_source -sn -x $dsc 2>&1"; > - unlink @files; > - } > - $main::sub_task = "dpkg-source"; > - > - while( <PIPE> ) { > - print PLOG $_; > - $dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ > in (\S+)/; > - $main::pkg_fail_stage = "unpack-check" > - if /^dpkg-source: error: file.*instead of > expected/; > - } > - close( PIPE ); > - undef $main::sub_pid; > - if ($?) { > - print PLOG "FAILED [dpkg-source died]\n"; > - > - system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir; > - return 0; > - } > - if (!$dir) { > - print PLOG "Couldn't find directory of $dsc in > dpkg-source output\n"; > - system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir; > - return 0; > - } > - $dir = "$main::chroot_build_dir$dir"; > - > - if (system( "chmod -R g-s,go+rX $dir" ) != 0) { > - print PLOG "chmod -R g-s,go+rX $dir failed.\n"; > - return 0; > - } > - > - if (@main::have_dsc_build_deps && !defined $main::build_source) > { > - my ($d, $di, $c, $ci) = @main::have_dsc_build_deps; > - open( F, ">$dir/debian/.sbuild-build-deps" ); > - print F "Package: $pkg\n"; > - print F "Build-Depends: $d\n" if $d; > - print F "Build-Depends-Indep: $di\n" if $di; > - print F "Build-Conflicts: $c\n" if $c; > - print F "Build-Conflicts-Indep: $ci\n" if $ci; > - close( F ); > - } > - } > - else { > - $dir = "$main::chroot_build_dir$dsc"; > - $do_apply_patches = 0; > - > - $main::pkg_fail_stage = "check-unpacked-version"; > - # check if the unpacked tree is really the version we need > - $main::sub_pid = open( PIPE, "-|" ); > - if (!defined $main::sub_pid) { > - print PLOG "Can't spawn dpkg-parsechangelog: $!\n"; > - return 0; > - } > - if ($main::sub_pid == 0) { > - setpgrp( 0, $$ ); > - chdir( $dir ); > - exec "dpkg-parsechangelog 2>&1"; > - } > - $main::sub_task = "dpkg-parsechangelog"; > - > - my $clog = ""; > - while( <PIPE> ) { > - $clog .= $_; > - } > - close( PIPE ); > - undef $main::sub_pid; > - if ($?) { > - print PLOG "FAILED [dpkg-parsechangelog died]\n"; > - return 0; > - } > - if ($clog !~ /^Version:\s*(.+)\s*$/mi) { > - print PLOG "dpkg-parsechangelog didn't print > Version:\n"; > - return 0; > - } > - my $tree_version = $1; > - my $cmp_version = ($main::binNMU && -f > "$dir/debian/.sbuild-binNMU-done") ? > - binNMU_version($version) : $version; > - if ($tree_version ne $cmp_version) { > - print PLOG "The unpacked source tree $dir is version ". > - "$tree_version, not wanted > $cmp_version!\n"; > - return 0; > - } > - } > - > - if (!chdir( $dir )) { > - print PLOG "Couldn't cd to $dir: $!\n"; > - system ("rm -fr $tmpunpackdir") if -d $tmpunpackdir; > - return 0; > - } > - > - $main::pkg_fail_stage = "check-space"; > - my $current_usage = `/usr/bin/du -s .`; > - $current_usage =~ /^(\d+)/; > - $current_usage = $1; > - if ($current_usage) { > - my $free = df( "." ); > - if ($free < 2*$current_usage) { > - print PLOG "Disk space is propably not enough for > building.\n". > - "(Source needs $current_usage KB, > free are $free KB.)\n"; > - print PLOG "Purging $dir\n"; > - chdir( $main::cwd ); > - system "$conf::sudo rm -rf $dir"; > - return 0; > - } > - } > - > - $main::pkg_fail_stage = "hack-binNMU"; > - if ($main::binNMU && ! -f "debian/.sbuild-binNMU-done") { > - if (open( F, "<debian/changelog" )) { > - my($firstline, $text); > - $firstline = <F> while $firstline =~ /^$/; > - { local($/); undef $/; $text = <F>; } > - close( F ); > - $firstline =~ > /^(\S+)\s+\((\S+)\)\s+([^;]+)\s*;\s*urgency=(\S+)\s*$/; > - my ($name, $version, $dists, $urgent) = ($1, $2, $3, > $4); > - my $NMUversion = binNMU_version($version); > - chomp( my $date = `822-date` ); > - if (!open( F, ">debian/changelog" )) { > - print PLOG "Can't open debian/changelog for > binNMU hack: $!\n"; > - chdir( $main::cwd ); > - return 0; > - } > - $dists = $main::distribution; > - print F "$name ($NMUversion) $dists; urgency=low\n\n"; > - print F " * Binary-only non-maintainer upload for > $main::arch; ", > - "no source changes.\n"; > - print F " * ", join( " ", split( "\n", > $main::binNMU )), "\n\n"; > - print F " -- $conf::maintainer_name $date\n\n"; > - > - print F $firstline, $text; > - close( F ); > - system "touch debian/.sbuild-binNMU-done"; > - print PLOG "*** Created changelog entry for bin-NMU > version $NMUversion\n"; > - } > - else { > - print PLOG "Can't open debian/changelog -- no binNMU > hack!\n"; > - } > - } > - > - if ($do_apply_patches) { > - if (!apply_patches( $pkg )) { > - chdir( $main::cwd ); > - return 0; > - } > - } > - > - if (-f "debian/files") { > - local( *FILES ); > - my @lines; > - open( FILES, "<debian/files" ); > - chomp( @lines = <FILES> ); > - close( FILES ); > - @lines = map { my $ind = 68-length($_); > - $ind = 0 if $ind < 0; > - "| $_".(" " x $ind)." |\n"; } @lines; > - > - print PLOG <<"EOF"; > - > -+----------------------------------------------------------------------+ > -| sbuild Warning: | > -| --------------- | > -| After unpacking, there exists a file debian/files with the contents: | > -| | > -EOF > - print PLOG @lines; > - print PLOG <<"EOF"; > -| | > -| This should be reported as a bug. | > -| The file has been removed to avoid dpkg-genchanges errors. | > -+----------------------------------------------------------------------+ > - > -EOF > - unlink "debian/files"; > - } > - > - open CURRENT, ">$main::cwd/$main::chroot_dir/CurrentlyBuilding" or die > "$main::cwd/$main::chroot_dir/CurrentlyBuilding open failed"; > - # Package: must be first > - print CURRENT "Package: $pkg\nComponent: $main::component\n"; > - print CURRENT "Suite: $main::distribution\n" if $main::distribution; > - print CURRENT "Purpose: $main::purpose\n" if $main::purpose; > - print CURRENT "Build-Debug-Symbols: yes\n" if > $main::build_debug_symbols; > - close CURRENT; > - > - $main::build_start_time = time; > - $main::pkg_fail_stage = "build"; > - $main::sub_pid = open( PIPE, "-|" ); > - if (!defined $main::sub_pid) { > - print PLOG "Can't spawn dpkg-buildpackage: $!\n"; > - chdir( $main::cwd ); > - return 0; > - } > - if ($main::sub_pid == 0) { > - setpgrp( 0, $$ ); > - my $binopt = $main::build_source ? "" : > - $main::build_arch_all ? "-b" : "-B"; > - my $env_cmnd = $conf::build_env_cmnd; > - $env_cmnd = $conf::build_env_cmnd{$pkg} if > $conf::build_env_cmnd{$pkg}; > - if ($main::chroot_dir) { > - my $bdir = $dir; > - $bdir =~ s/^\Q$main::chroot_dir\E//; > - if (-f "$main::chroot_dir/etc/ld.so.conf" && > - ! -r "$main::chroot_dir/etc/ld.so.conf") { > - system "$conf::sudo chmod a+r > $main::chroot_dir/etc/ld.so.conf"; > - print PLOG "ld.so.conf was not readable! > Fixed.\n"; > - } > - exec "$conf::sudo", "/usr/sbin/chroot", > "$main::cwd/$main::chroot_dir", > - "$conf::su", $main::username, "-s", "/bin/sh", > "-c", > - "cd $bdir && PATH=$conf::path ". > - (defined($main::nr_processors) ? > - > "DEB_BUILD_OPTIONS=\"parallel=".$main::nr_processors."\" " : ""). > - (defined($main::ld_library_path) ? > - "LD_LIBRARY_PATH=".$main::ld_library_path." " : > ""). > - "exec $env_cmnd dpkg-buildpackage > $conf::pgp_options ". > - "$binopt -m'$conf::maintainer_name' > -r$conf::fakeroot 2>&1"; > - } > - else { > - if (-f "/etc/ld.so.conf" && ! -r "/etc/ld.so.conf") { > - system "$conf::sudo chmod a+r /etc/ld.so.conf"; > - print PLOG "ld.so.conf was not readable! > Fixed.\n"; > - } > - exec "$env_cmnd dpkg-buildpackage $conf::pgp_options > $binopt ". > - "-m'$conf::maintainer_name' -r$conf::fakeroot > 2>&1"; > - } > - } > - $main::sub_task = "dpkg-buildpackage"; > - > - # We must send the signal as root, because some subprocesses of > - # dpkg-buildpackage could run as root. So we have to use a shell > - # command to send the signal... but /bin/kill can't send to > - # process groups :-( So start another Perl :-) > - my $timeout = $conf::individual_stalled_pkg_timeout{$pkg} || > - $conf::stalled_pkg_timeout; > - $timeout *= 60; > - my $timed_out = 0; > - my(@timeout_times, @timeout_sigs, $last_time); > - $SIG{'ALRM'} = sub { > - my $signal = ($timed_out > 0) ? 9 : 15; > - system "$conf::sudo perl -e 'kill( -$signal, $main::sub_pid )'"; > - $timeout_times[$timed_out] = time - $last_time; > - $timeout_sigs[$timed_out] = $signal; > - $timed_out++; > - $timeout = 5*60; # only wait 5 minutes until next signal > - }; > - > - alarm( $timeout ); > - while( <PIPE> ) { > - alarm( $timeout ); > - $last_time = time; > - print PLOG $_; > - } > - close( PIPE ); > - undef $main::sub_pid; > - alarm( 0 ); > - $rv = $?; > - > - my $i; > - for( $i = 0; $i < $timed_out; ++$i ) { > - print PLOG "Build killed with signal ", $timeout_sigs[$i], > - " after ", int($timeout_times[$i]/60), > - " minutes of inactivity\n"; > - } > - $main::pkg_end_time = time; > - my $date = `date +%Y%m%d-%H%M`; > - print PLOG "*"x78, "\n"; > - print PLOG "Build finished at $date"; > - chdir( $main::cwd ); > - > - my @space_files = ("$dir"); > - if (!$main::nolog and defined $conf::exit_hook and open TMP, '-|', > "$conf::exit_hook <$main::pkg_logfile") { > - local $/ = undef; > - my $log = <TMP>; > - close TMP; > - $rv |= $?; > - print PLOG $log; > - } > - if ($rv) { > - print PLOG "FAILED [dpkg-buildpackage died]\n"; > - } > - else { > - my > $trans_oldfmt="$main::chroot_build_dir${pkg}_${version}_translations.tar.gz"; > - my > $trans_newfmt="$main::chroot_build_dir${pkg}_${version}_${main::arch}_translations.tar.gz"; > - my $translations=""; > - if (-r $trans_newfmt) { > - $translations = $trans_newfmt; > - } elsif (-r $trans_oldfmt) { > - $translations = $trans_oldfmt; > - } > - if ($translations) { > - print PLOG "Publishing $translations for rosetta.\n"; > - my $date = strftime '%Y%m%d',gmtime; > - my $target = > "$main::HOME/public_html/translations/$date/"; > - system "mkdir -p $target"; > - if (system("cp",$translations,$target) != 0) { > - print PLOG "ERROR: Could not move $translations > to $target\n"; > - } else { > - open TRANS, ">>$target/translations.txt"; > - print TRANS "File: " . > basename(${translations}) . "\n". > - "Distribution: > ${main::archive}\n". > - "Release: > ${main::distribution}\n". > - "Component: > ${main::component}\n". > - "Source: ${pkg}\n". > - "Version: ${version}\n\n"; > - close TRANS; > - system("chmod -R go+rX > $main::HOME/public_html/translations"); > - } > - } > - > - my $ddebtar = ""; > - my $ddebstring = ""; > - if (-r glob("$main::chroot_build_dir/*.ddeb")) { > - my @ddeblist = glob("$main::chroot_build_dir/*.ddeb"); > - $ddebtar="${pkg}_${version}_${main::arch}_ddebs.tar"; > - while (@ddeblist) { > - $ddebstring .= basename(@ddeblist[0]) . " "; > - shift @ddeblist; > - } > - } > - if ($ddebstring) { > - print PLOG "Publishing debug debs.\n"; > - my $date = strftime '%Y%m%d',gmtime; > - my $target = "$main::HOME/public_html/ddebs/$date/"; > - system "mkdir -p $target"; > - if (system("tar -C $main::chroot_build_dir -chf > $target/$ddebtar $ddebstring") != 0) { > - print PLOG "ERROR: Could not create $ddebtar in > $target\n"; > - } else { > - open TRANS, ">>$target/ddebs.txt"; > - print TRANS "File: " . basename(${ddebtar}) . "\n". > - "Distribution: ${main::archive}\n". > - "Release: ${main::distribution}\n". > - "Component: ${main::component}\n". > - "Source: ${pkg}\n". > - "Version: ${version}\n\n"; > - close TRANS; > - system("chmod -R go+rX $main::HOME/public_html/ddebs"); > - } > - } > - > - if (-r "$dir/debian/files") { > - my @debs; > - my @files; > - open( F, "<$dir/debian/files" ); > - while( <F> ) { > - my $f = (split( /\s+/, $_ ))[0]; > - push( @files, "$main::chroot_build_dir$f" ); > - if ($main::build_arch_all) { > - next if ($f !~ > /$main::arch\.[\w\d.-]*$/ && $f !~ /all\.[\w\d.-]*$/); > - } else { > - next if ($f !~ > /$main::arch\.[\w\d.-]*$/); > - } > - push( @debs, "$main::chroot_build_dir$f" ); > - push( @space_files, $f ); > - } > - close( F ); > - my @debs2 = @debs; > - foreach (@debs) { > - print PLOG "\n$_:\n"; > - if (!open( PIPE, "dpkg --info $_ 2>&1 |" )) { > - print PLOG "Can't spawn dpkg: $! -- > can't dump infos\n"; > - } > - else { > - print PLOG $_ while( <PIPE> ); > - close( PIPE ); > - } > - } > - foreach (@debs2) { > - print PLOG "\n$_:\n"; > - if (!open( PIPE, "dpkg --contents $_ 2>&1 |" )) > { > - print PLOG "Can't spawn dpkg: $! -- > can't dump infos\n"; > - } > - else { > - print PLOG $_ while( <PIPE> ); > - close( PIPE ); > - } > - } > - if ($main::chroot_build_dir) { > - foreach (@files) { > - system "mv", $_, "." > - and print PLOG "ERROR: Could > not move $_ to .\n"; > - } > - } > - } > - > - if (-r $translations) { > - system("rm",$translations); > - } > - > - $changes = "${pkg}_". > - ($main::binNMU ? binNMU_version($sversion) : $sversion). > - "_$main::arch.changes"; > - if (-r "$main::chroot_build_dir$changes") { > - my(@do_dists, @saved_dists); > - print PLOG "\n$changes:\n"; > - open( F, "<$main::chroot_build_dir$changes" ); > - if (open( F2, ">$changes.new" )) { > - while( <F> ) { > - if (/^Distribution:\s*(.*)\s*$/) { > - print PLOG "Distribution: > $main::distribution\n"; > - print F2 "Distribution: > $main::distribution\n"; > - } > - else { > - print F2 $_; > - while (length $_ > 989) > - { > - my $index = rindex($_,' > ',989); > - print PLOG substr > ($_,0,$index) . "\n"; > - $_ = ' ' . > substr ($_,$index+1); > - } > - print PLOG $_; > - } > - } > - close( F2 ); > - rename( "$changes.new", "$changes" ) > - or print PLOG "$changes.new could not > be renamed ". > - "to $changes: > $!\n"; > - unlink( "$main::chroot_build_dir$changes" ) > - if $main::chroot_build_dir; > - } > - else { > - print PLOG "Cannot create $changes.new: $!\n"; > - print PLOG "Distribution field may be > wrong!!!\n"; > - if ($main::chroot_build_dir) { > - system "mv", > "$main::chroot_build_dir$changes", "." > - and print PLOG "ERROR: Could > not move $_ to .\n"; > - } > - } > - close( F ); > - print PLOG "\n"; > - } > - else { > - print PLOG "Can't find $changes -- can't dump infos\n"; > - } > - > - print PLOG "*"x78, "\n"; > - print PLOG "Built successfully\n"; > - } > - > - check_watches(); > - check_space( @space_files ); > - > - #if ($conf::purge_build_directory eq "always" || > - # ($conf::purge_build_directory eq "successful" && $rv == 0)) { > - # print PLOG "Purging $dir\n"; > - # system "$conf::sudo rm -rf $dir"; > - #} > - # > - #print PLOG "-"x78, "\n"; > - return $rv == 0 ? 1 : 0; > -} > - > -sub apply_patches { > - my $pkg = shift; > - my $name; > - > - $main::pkg_fail_stage = "apply-patch"; > - foreach $name ((map { $_->{'Package'} } @{$main::deps{$pkg}}), > - @main::global_patches) { > - if ($name =~ /^\*/ && exists $main::specials{$name}->{'patch'}) > { > - if (exists $main::specials{$name}->{'patchcond'}) { > - print "Testing condition for $name patch:\n" > - if $main::debug; > - if > (run_script("+e",$main::specials{$name}->{'patchcond'})!=0){ > - print PLOG "Condition for $name patch > not true -- ", > - "not > applying\n" if $name !~ /^\*\*/; > - next; > - } > - print PLOG "Condition for $name patch ok\n"; > - } > - print PLOG "Applying $name patch\n"; > - $main::sub_pid = open( PIPE, "|-" ); > - if (!defined $main::sub_pid) { > - print PLOG "Can't spawn patch: $! -- can't > patch\n"; > - return 0; > - } > - if ($main::sub_pid == 0) { > - setpgrp( 0, $$ ); > - open( STDOUT, ">&PLOG" ); > - open( STDERR, ">&PLOG" ); > - exec "patch --batch --quiet -p1 -E -N > --no-backup-if-mismatch"; > - } > - $main::sub_task = "patch"; > - > - print PIPE $main::specials{$name}->{'patch'}; > - close( PIPE ); > - undef $main::sub_pid; > - if ($name !~ /^\*\*/ && $?) { > - print PLOG "FAILED [patch died]\n"; > - return 0; > - } > - } > - } > - return 1; > -} > - > -sub analyze_fail_stage { > - my $pkgv = shift; > - > - return if $main::pkg_status ne "failed"; > - return if !$main::auto_giveback; > - if (isin( $main::pkg_fail_stage, > - qw(find-dsc fetch-src unpack-check check-space > install-deps-env))) { > - $main::pkg_status = "given-back"; > - print PLOG "Giving back package $pkgv after failure in ". > - "$main::pkg_fail_stage stage.\n"; > - chdir( $main::cwd ); > - my $cmd = ""; > - $cmd = "ssh -l$main::auto_giveback_user > $main::auto_giveback_host " > - if $main::auto_giveback_host; > - $cmd .= "-S $main::auto_giveback_socket " > - if ($main::auto_giveback_socket and -S > "$main::auto_giveback_socket"); > - $cmd .= "wanna-build --give-back --no-down-propagation ". > - "--dist=$main::distribution"; > - $cmd .= " --database=$main::database" if $main::database; > - $cmd .= " --user=$main::auto_giveback_wb_user " > - if $main::auto_giveback_wb_user; > - $cmd .= " $pkgv"; > - system $cmd; > - if ($?) { > - print PLOG "wanna-build failed with status $?\n"; > - } > - else { > - add_givenback( $pkgv, time ); > - if ($main::stats_dir) { > - local( *F ); > - lock_file( "$main::stats_dir" ); > - open( F, ">>$main::stats_dir/give-back" ); > - print F "1\n"; > - close( F ); > - unlock_file( "$main::stats_dir" ); > - } > - } > - } > -} > - > -sub remove_files { > - > - foreach (@_) { > - unlink $_; > - print "Removed $_\n" if $main::debug; > - } > -} > - > - > -sub install_deps { > - my $pkg = shift; > - my( @positive, @negative, @special, @instd, @rmvd ); > - > - if (!exists $main::deps{$pkg}) { > - prepare_watches( [] ); > - return 1; > - } > - > - my $dep = $main::deps{$pkg}; > - if ($main::debug) { > - print "Source dependencies of $pkg: ", format_deps(@$dep), "\n"; > - } > - > - repeat: > - lock_file( "$main::ilock_file", 1 ); > - > - print "Filtering dependencies\n" if $main::debug; > - if (!filter_dependencies( $dep, \@positive, \@negative, \@special )) { > - print PLOG "Package installation not possible\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - > - print PLOG "Checking for source dependency conflicts...\n"; > - if (!run_apt( "-s", \@instd, \@rmvd, @positive )) { > - print PLOG "Test what should be installed failed.\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - # add negative deps as to be removed for checking srcdep conflicts > - push( @rmvd, @negative ); > - my @confl; > - if (@confl = check_srcdep_conflicts( \@instd, \@rmvd, \@special )) { > - print PLOG "Waiting for job(s) @confl to finish\n"; > - > - unlock_file( "$main::ilock_file" ); > - wait_for_srcdep_conflicts( @confl ); > - goto repeat; > - } > - > - write_srcdep_lock_file( $dep, \@special ); > - > - foreach my $sp (@special) { > - next if $sp !~ /^\*/ || !exists > $main::specials{$sp}->{'prepre'}; > - print PLOG "Running prepre script for $sp\n"; > - if (run_script( "-e", $main::specials{$sp}->{'prepre'} ) != 0) { > - print PLOG "prepre script of special dependency $sp > failed\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - } > - > - print "Installing positive dependencies: @positive\n" if $main::debug; > - if (!run_apt( "-y", \@instd, \@rmvd, @positive )) { > - print PLOG "Package installation failed\n"; > - # try to reinstall removed packages > - print PLOG "Trying to reinstall removed packages:\n"; > - print "Reinstalling removed packages: @rmvd\n" if $main::debug; > - my (@instd2, @rmvd2); > - print PLOG "Failed to reinstall removed packages!\n" > - if !run_apt( "-y", \@instd2, \@rmvd2, @rmvd ); > - print "Installed were: @instd2\n" if $main::debug; > - print "Removed were: @rmvd2\n" if $main::debug; > - # remove additional packages > - print PLOG "Trying to uninstall newly installed packages:\n"; > - uninstall_debs( $main::chroot_dir ? "purge" : "remove", @instd > ); > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - set_installed( @instd ); > - set_removed( @rmvd ); > - > - print "Removing negative dependencies: @negative\n" if $main::debug; > - if (!uninstall_debs( $main::chroot_dir ? "purge" : "remove", @negative > )) { > - print PLOG "Removal of packages failed\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - set_removed( @negative ); > - > - my $fail = check_dependencies( $dep ); > - if ($fail) { > - print PLOG "After installing, the following source dependencies > are ". > - "still unsatisfied:\n$fail\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - > - foreach my $sp (@special) { > - next if $sp !~ /^\*/ || > - (!exists $main::specials{$sp}->{'pre'} && > - !exists $main::specials{$sp}->{'post'} && > - !exists $main::specials{$sp}->{'unpack'}); > - if (exists $main::specials{$sp}->{'unpack'}) { > - my $s = $main::specials{$sp}->{'unpack'}; > - $s =~ s/^\s+//mg; > - $s =~ s/\s+$//mg; > - my @s = split( /\s+/, $s ); > - my @rem; > - print PLOG "Unpacking special sources $sp: @s\n"; > - if (!(@rem = unpack_special_source( @s ))) { > - print PLOG "unpacking of special dependency > sources for $sp failed\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - $main::changes->{'unpacked'}->{$sp} = \@rem; > - } > - if (exists $main::specials{$sp}->{'pre'}) { > - print PLOG "Running pre script for $sp\n"; > - $main::changes->{'specials'}->{$sp} = 1; > - if (run_script( "-e", $main::specials{$sp}->{'pre'} ) > != 0) { > - print PLOG "pre script of special dependency > $sp failed\n"; > - unlock_file( "$main::ilock_file" ); > - return 0; > - } > - } > - } > - > - local (*F); > - if (open( F, "| $conf::sudo /usr/sbin/chroot $main::chroot_dir > $conf::dpkg --set-selections")) { > - foreach my $tpkg (@instd) { > - print F $tpkg . " purge\n"; > - } > - close( F ); > - if ($?) { > - print PLOG "$conf::dpkg --set-selections failed"; > - } > - } > - > - unlock_file( "$main::ilock_file" ); > - > - prepare_watches( $dep, @instd ); > - return 1; > -} > - > -sub unpack_special_source { > - my @s = @_; > - my (@files, @dirs); > - local (*PIPE); > - > - foreach my $s (@s) { > - my $dsc; > - > - { > - if (!open( PIPE, "$conf::apt_get > $main::chroot_apt_options ". > - "--only-source -q -d source $s 2>&1 </dev/null |" )) { > - print PLOG "Can't open pipe to apt-get: $!\n"; > - goto failed; > - } > - while( <PIPE> ) { > - $dsc = "$1_$2.dsc" if /(\S+) (?:[^:]+:)?(\S+) > \(dsc\)/; > - print PLOG $_; > - } > - close( PIPE ); > - if ($?) { > - print PLOG "Apt-get of special unpack sources > failed\n"; > - goto failed; > - } > - push( @files, $dsc ); > - if (!open( F, "<$dsc" )) { > - print PLOG "Can't open $dsc: $!\n"; > - goto failed; > - } > - my $dsctext; > - { local($/); $dsctext = <F>; } > - close( F ); > - my $files; > - $dsctext =~ /^Files:\s*\n((\s+.*\s*\n)+)/mi and $files > = $1; > - push(@files, map { (split( /\s+/, $_ ))[3] } split( > "\n", $files )); > - } > - > - my $pid = open( PIPE, "-|" ); > - if (!defined $pid) { > - print PLOG "Can't spawn dpkg-source: $! -- special > unpack failed\n"; > - goto failed; > - } > - if ($pid == 0) { > - setpgrp( 0, $$ ); > - if ($main::chroot_build_dir && !chdir( > $main::chroot_build_dir )) { > - print PLOG "Couldn't cd to > $main::chroot_build_dir: $! -- special unpack failed\n"; > - exit 1; > - } > - exec "$conf::dpkg_source -sn -x $main::cwd/$dsc 2>&1"; > - } > - my $dir; > - while( <PIPE> ) { > - print PLOG $_; > - $dir = $1 if /^dpkg-source: (?:info: )?extracting \S+ > in (\S+)/; > - } > - close( PIPE ); > - if ($?) { > - print PLOG "dpkg-source failure -- special unpack > failed\n"; > - goto failed; > - } > - push( @dirs, "$main::chroot_build_dir$dir" ); > - unlink( @files ); > - } > - > - return @dirs; > - > - failed: > - unlink( @files ); > - system( "rm", "-rf", @dirs ); > - return (); > -} > - > -sub wait_for_srcdep_conflicts { > - my @confl = @_; > - > - for(;;) { > - sleep( $conf::srcdep_lock_wait*60 ); > - my $allgone = 1; > - for (@confl) { > - /^(\d+)-(\d+)$/; > - my $pid = $1; > - if (-f "$conf::srcdep_lock_dir/$_") { > - if (kill( 0, $pid ) == 0 && $! == ESRCH) { > - print PLOG "Ignoring stale src-dep lock > $_\n"; > - unlink( "$conf::srcdep_lock_dir/$_" ) or > - print PLOG "Cannot remove > $conf::srcdep_lock_dir/$_: $!\n"; > - } > - else { > - $allgone = 0; > - last; > - } > - } > - } > - last if $allgone; > - } > -} > - > -sub uninstall_deps { > - my( @pkgs, @instd, @rmvd ); > - > - lock_file( "$main::ilock_file", 1 ); > - > - @pkgs = keys %{$main::changes->{'removed'}}; > - print "Reinstalling removed packages: @pkgs\n" if $main::debug; > - print PLOG "Failed to reinstall removed packages!\n" > - if !run_apt( "-y", \@instd, \@rmvd, @pkgs ); > - print "Installed were: @instd\n" if $main::debug; > - print "Removed were: @rmvd\n" if $main::debug; > - unset_removed( @instd ); > - unset_installed( @rmvd ); > - > - @pkgs = keys %{$main::changes->{'installed'}}; > - print "Removing installed packages: @pkgs\n" if $main::debug; > - print PLOG "Failed to remove installed packages!\n" > - if !uninstall_debs( "purge", @pkgs ); > - unset_installed( @pkgs ); > - > - unlock_file( "$main::ilock_file" ); > -} > - > -sub uninstall_debs { > - my $mode = shift; > - local (*PIPE); > - > - return 1 if !@_; > - print "Uninstalling packages: @_\n" if $main::debug; > - print PLOG " $conf::sudo dpkg --$mode @_\n"; > - repeat: > - my $output; > - if (!open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir > $conf::dpkg --$mode @_ 2>&1 </dev/null |")) { > - print PLOG "Can't open pipe to dpkg: $!\n"; > - return 0; > - } > - while ( <PIPE> ) { > - $output .= $_; > - print PLOG $_; > - } > - close( PIPE ); > - > - if ($output =~ /status database area is locked/mi) { > - print PLOG "Another dpkg is running -- retrying later\n"; > - $output = ""; > - sleep( 2*60 ); > - goto repeat; > - } > - print PLOG "dpkg run to remove packages (@_) failed!\n" if $?; > - return $? == 0; > -} > - > -sub undo_specials { > - my $sp; > - > - print "Running post scripts of special dependencies:\n" if $main::debug; > - foreach $sp (keys %{$main::changes->{'specials'}}) { > - print PLOG "Running post script for $sp\n"; > - if (run_script( "-e", $main::specials{$sp}->{'post'} ) != 0) { > - print PLOG "post script of special dependency $sp > failed\n"; > - } > - delete $main::changes->{'specials'}->{$sp}; > - } > - foreach $sp (keys %{$main::changes->{'unpacked'}}) { > - my @dirs = @{$main::changes->{'unpacked'}->{$sp}}; > - print PLOG "Removing special unpacked sources for $sp: @dirs\n"; > - system "rm", "-rf", @dirs; > - delete $main::changes->{'unpacked'}->{$sp}; > - } > -} > - > - > -sub run_apt { > - my $mode = shift; > - my $inst_ret = shift; > - my $rem_ret = shift; > - my @to_install = @_; > - my( $msgs, $status, $pkgs, $rpkgs ); > - local (*PIPE); > - local (%ENV) = %ENV; # make local environment > - # hardwire frontend for debconf to non-interactive > - $ENV{'DEBIAN_FRONTEND'} = "noninteractive"; > - > - @$inst_ret = (); > - @$rem_ret = (); > - return 1 if !@to_install; > - repeat: > - print PLOG " $conf::sudo $conf::apt_get --purge $main::chroot_apt_op > -q $mode install @to_install\n" > - if $mode ne "-s"; > - $msgs = ""; > - # redirection of stdin from /dev/null so that conffile question are > - # treated as if RETURN was pressed. > - # dpkg since 1.4.1.18 issues an error on the conffile question if it > reads > - # EOF -- hardwire the new --force-confold option to avoid the questions. > - if (!open( PIPE, "$conf::sudo /usr/sbin/chroot ". > - "$main::chroot_dir $conf::apt_get --purge ". > - ($main::new_dpkg ? "-o > DPkg::Options::=--force-confold " : ""). > - "-q $mode install @to_install 2>&1 </dev/null |" )) { > - print PLOG "Can't open pipe to apt-get: $!\n"; > - return 0; > - } > - while( <PIPE> ) { > - $msgs .= $_; > - print PLOG $_ if $mode ne "-s" || $main::debug; > - } > - close( PIPE ); > - $status = $?; > - > - if ($status != 0 && $msgs =~ /^E: Packages file \S+ (has changed|is out > of sync)/mi) { > - print PLOG "$conf::sudo $conf::apt_get $main::chroot_apt_op -q > update\n"; > - if (!open( PIPE, "$conf::sudo /usr/sbin/chroot > $main::chroot_dir $conf::apt_get -q update 2>&1 |" )) { > - print PLOG "Can't open pipe to apt-get: $!\n"; > - return 0; > - } > - $msgs = ""; > - while( <PIPE> ) { > - $msgs .= $_; > - print PLOG $_; > - } > - close( PIPE ); > - print PLOG "apt-get update failed\n" if $?; > - $msgs = ""; > - goto repeat; > - } > - > - if ($status != 0 && $msgs =~ /^Package (\S+) is a virtual package > provided by:\n((^\s.*\n)*)/mi) { > - my $to_replace = $1; > - my @providers; > - foreach (split( "\n", $2 )) { > - s/^\s*//; > - push( @providers, (split( /\s+/, $_ ))[0] ); > - } > - print PLOG "$to_replace is a virtual package provided by: > @providers\n"; > - my $selected; > - if (@providers == 1) { > - $selected = $providers[0]; > - print PLOG "Using $selected (only possibility)\n"; > - } > - elsif (exists $conf::alternatives{$to_replace}) { > - $selected = $conf::alternatives{$to_replace}; > - print PLOG "Using $selected (selected in sbuildrc)\n"; > - } > - else { > - $selected = $providers[0]; > - print PLOG "Using $selected (no default, using first > one)\n"; > - } > - > - @to_install = grep { $_ ne $to_replace } @to_install; > - push( @to_install, $selected ); > - > - goto repeat; > - } > - > - if ($status != 0 && ($msgs =~ /^E: Could( not get lock|n.t lock)/mi || > - $msgs =~ /^dpkg: status > database area is locked/mi)) { > - print PLOG "Another apt-get or dpkg is running -- retrying > later\n"; > - sleep( 2*60 ); > - goto repeat; > - } > - > - # check for errors that are probably caused by something broken in > - # the build environment, and give back the packages. > - if ($status != 0 && $mode ne "-s" && > - (($msgs =~ /^E: dpkg was interrupted, you must manually run > 'dpkg --configure -a' to correct the problem./mi) || > - ($msgs =~ /^dpkg: parse error, in file > `\/.+\/var\/lib\/dpkg\/(?:available|status)' near line/mi) || > - ($msgs =~ /^E: Unmet dependencies. Try 'apt-get -f install' > with no packages \(or specify a solution\)\./mi))) { > - print PLOG "Build environment unusable, giving back\n"; > - $main::pkg_fail_stage = "install-deps-env"; > - } > - > - if ($status != 0 && $mode ne "-s" && > - (($msgs =~ /^E: Unable to fetch some archives, maybe run > apt-get update or try with/mi))) { > - print PLOG "Unable to fetch build-depends\n"; > - $main::pkg_fail_stage = "install-deps-env"; > - } > - > - $pkgs = $rpkgs = ""; > - if ($msgs =~ /NEW packages will be installed:\n((^[ ].*\n)*)/mi) { > - ($pkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m; > - $pkgs =~ s/\*//g; > - } > - if ($msgs =~ /packages will be REMOVED:\n((^[ ].*\n)*)/mi) { > - ($rpkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m; > - $rpkgs =~ s/\*//g; > - } > - @$inst_ret = split( /\s+/, $pkgs ); > - @$rem_ret = split( /\s+/, $rpkgs ); > - > - print PLOG "apt-get failed.\n" if $status && $mode ne "-s"; > - return $mode eq "-s" || $status == 0; > -} > - > -sub filter_dependencies { > - my $dependencies = shift; > - my $pos_list = shift; > - my $neg_list = shift; > - my $special_list = shift; > - my($dep, $d, $name, %names); > - > - print PLOG "Checking for already installed source dependencies...\n"; > - > - @$pos_list = @$neg_list = @$special_list = (); > - foreach $d (@$dependencies) { > - my $name = $d->{'Package'}; > - $names{$name} = 1 if $name !~ /^\*/; > - foreach (@{$d->{'Alternatives'}}) { > - my $name = $_->{'Package'}; > - $names{$name} = 1 if $name !~ /^\*/; > - } > - } > - my $status = get_dpkg_status( keys %names ); > - > - foreach $dep (@$dependencies) { > - $name = $dep->{'Package'}; > - next if !$name; > - if ($name =~ /^\*/) { > - my $doit = 1; > - if (exists $main::specials{$name}->{'condition'}) { > - print "Testing condition for special dependency > $name:\n" > - if $main::debug; > - if > (run_script("+e",$main::specials{$name}->{'condition'})!=0){ > - print "Condition false -> not running > scripts\n" > - if $main::debug; > - $doit = 0; > - } > - } > - push( @$special_list, $name ) if $doit; > - next; > - } > - my $stat = $status->{$name}; > - if ($dep->{'Neg'}) { > - if ($stat->{'Installed'}) { > - my ($rel, $vers) = ($dep->{'Rel'}, > $dep->{'Version'}); > - my $ivers = $stat->{'Version'}; > - if (!$rel || version_cmp( $ivers, $rel, $vers > )){ > - print "$name: neg dep, installed, not > versioned or ", > - "version relation satisfied > --> remove\n" if $main::debug; > - print PLOG "$name: installed (negative > dependency)"; > - print PLOG " (bad version $ivers $rel > $vers)" > - if $rel; > - print PLOG "\n"; > - push( @$neg_list, $name ); > - } > - else { > - print PLOG "$name: installed (negative > dependency)", > - "(but version ok > $ivers $rel $vers)\n"; > - } > - } > - else { > - print "$name: neg dep, not installed\n" if > $main::debug; > - print PLOG "$name: already deinstalled\n"; > - } > - next; > - } > - > - my $is_satisfied = 0; > - my $installable = ""; > - my $upgradeable = ""; > - my $downgradeable = ""; > - foreach $d ($dep, @{$dep->{'Alternatives'}}) { > - my ($name, $rel, $vers) = > - ($d->{'Package'}, $d->{'Rel'}, $d->{'Version'}); > - my $stat = $status->{$name}; > - if (!$stat->{'Installed'}) { > - print "$name: pos dep, not installed\n" if > $main::debug; > - print PLOG "$name: missing\n"; > - my $exists = package_exists($name); > - print PLOG "$name: does not exist\n" if not > $exists; > - $installable = $name if !$installable and > $exists; > - next; > - } > - my $ivers = $stat->{'Version'}; > - if (!$rel || version_cmp( $ivers, $rel, $vers )) { > - print "$name: pos dep, installed, no versioned > dep or ", > - "version ok\n" if $main::debug; > - print PLOG "$name: already installed ($ivers"; > - print PLOG " $rel $vers is satisfied" > - if $rel; > - print PLOG ")\n"; > - $is_satisfied = 1; > - last; > - } > - print "$name: vers dep, installed $ivers ! $rel $vers\n" > - if $main::debug; > - print PLOG "$name: non-matching version installed ", > - "($ivers ! $rel $vers)\n"; > - if ($rel =~ /^</ || > - ($rel eq '=' && version_cmp($ivers, '>>', > $vers))) { > - print "$name: would be a downgrade!\n" if > $main::debug; > - print PLOG "$name: would have to downgrade!\n"; > - $downgradeable = $name if !$downgradeable; > - } > - else { > - $upgradeable = $name if !$upgradeable; > - } > - } > - if (!$is_satisfied) { > - if ($upgradeable) { > - print "using $upgradeable for upgrade\n" if > $main::debug; > - push( @$pos_list, $upgradeable ); > - } > - elsif ($installable) { > - print "using $installable for install\n" if > $main::debug; > - push( @$pos_list, $installable ); > - } > - elsif ($downgradeable) { > - print PLOG "To satisfy this dependency the > package(s) would ", > - "have\n", > - "to be downgraded; this is > not implemented.\n"; > - return 0; > - } > - else { > - # None of the build-deps exist. Return the > - # first one so that we get a useful dep-wait. > - $installable = $dep->{'Package'}; > - print "using $installable for install (does not > exist)\n" if $main::debug; > - push( @$pos_list, $installable ); > - } > - } > - } > - > - return 1; > -} > - > -sub check_dependencies { > - my $dependencies = shift; > - my $fail = ""; > - my($dep, $d, $name, %names); > - > - print PLOG "Checking correctness of source dependencies...\n"; > - > - foreach $d (@$dependencies) { > - my $name = $d->{'Package'}; > - $names{$name} = 1 if $name !~ /^\*/; > - foreach (@{$d->{'Alternatives'}}) { > - my $name = $_->{'Package'}; > - $names{$name} = 1 if $name !~ /^\*/; > - } > - } > - foreach $name (@main::toolchain_pkgs) { > - $names{$name} = 1; > - } > - my $status = get_dpkg_status( keys %names ); > - > - foreach $dep (@$dependencies) { > - $name = $dep->{'Package'}; > - next if $name =~ /^\*/; > - my $stat = $status->{$name}; > - if ($dep->{'Neg'}) { > - if ($stat->{'Installed'}) { > - if (!$dep->{'Rel'}) { > - $fail .= "$name(still installed) "; > - } > - elsif (version_cmp($stat->{'Version'}, > $dep->{'Rel'}, > - > $dep->{'Version'})) { > - $fail .= "$name(inst $stat->{'Version'} > $dep->{'Rel'} ". > - "conflicted > $dep->{'Version'})\n"; > - } > - } > - } > - else { > - my $is_satisfied = 0; > - my $f = ""; > - foreach $d ($dep, @{$dep->{'Alternatives'}}) { > - my $name = $d->{'Package'}; > - my $stat = $status->{$name}; > - if (!$stat->{'Installed'}) { > - $f =~ s/ $/\|/ if $f; > - $f .= "$name(missing) "; > - } > - elsif ($d->{'Rel'} && > - !version_cmp( $stat->{'Version'}, > $d->{'Rel'}, > - > $d->{'Version'} )) { > - $f =~ s/ $/\|/ if $f; > - $f .= "$name(inst $stat->{'Version'} ! > $d->{'Rel'} ". > - "wanted $d->{'Version'}) "; > - } > - else { > - $is_satisfied = 1; > - } > - } > - if (!$is_satisfied) { > - $fail .= $f; > - } > - } > - } > - $fail =~ s/\s+$//; > - if (!$fail && @main::toolchain_pkgs) { > - print PLOG "Toolchain package versions:"; > - foreach $name (@main::toolchain_pkgs) { > - print PLOG ' ' . $name . '_' . > $status->{$name}->{'Version'}; > - } > - print PLOG "\n"; > - } > - > - return $fail; > -} > - > -sub get_dpkg_status { > - my @interest = @_; > - my %result; > - local( *STATUS ); > - > - return () if !@_; > - print "Requesting dpkg status for packages: @interest\n" > - if $main::debug; > - if (!open( STATUS, "<$main::chroot_dir/var/lib/dpkg/status" )) { > - print PLOG "Can't open $main::chroot_dir/var/lib/dpkg/status: > $!\n"; > - return (); > - } > - local( $/ ) = ""; > - while( <STATUS> ) { > - my( $pkg, $status, $version, $provides ); > - /^Package:\s*(.*)\s*$/mi and $pkg = $1; > - /^Status:\s*(.*)\s*$/mi and $status = $1; > - /^Version:\s*(.*)\s*$/mi and $version = $1; > - /^Provides:\s*(.*)\s*$/mi and $provides = $1; > - if (!$pkg) { > - print PLOG "sbuild: parse error in > $main::chroot_dir/var/lib/dpkg/status: ", > - "no Package: field\n"; > - next; > - } > - print "$pkg ($version) status: $status\n" if $main::debug >= 2; > - if (!$status) { > - print PLOG "sbuild: parse error in > $main::chroot_dir/var/lib/dpkg/status: ", > - "no Status: field for package > $pkg\n"; > - next; > - } > - if ($status !~ /\sinstalled$/) { > - $result{$pkg}->{'Installed'} = 0 > - if !(exists($result{$pkg}) && > - $result{$pkg}->{'Version'} eq > '=*=PROVIDED=*='); > - next; > - } > - if (!$version) { > - print PLOG "sbuild: parse error in > $main::chroot_dir/var/lib/dpkg/status: ", > - "no Version: field for package > $pkg\n"; > - next; > - } > - $result{$pkg} = { Installed => 1, Version => $version } > - if isin( $pkg, @interest ); > - if ($provides) { > - foreach (split( /\s*,\s*/, $provides )) { > - $result{$_} = { Installed => 1, Version => > '=*=PROVIDED=*=' } > - if (isin( $_, @interest ) && > - $result{$_}->{'Installed'} != > 1); > - } > - } > - } > - close( STATUS ); > - return \%result; > -} > - > -sub version_cmp { > - my $v1 = shift; > - my $rel = shift; > - my $v2 = shift; > - if ($v1 eq "=*=PROVIDED=*=") { > - return 0; > - } > - > - system "$conf::dpkg", "--compare-versions", $v1, $rel, $v2; > - return $? == 0; > -} > - > -sub run_script { > - my $e_mode = shift; > - my $x_mode = ""; > - my $script = shift; > - > - if ($main::debug >= 2) { > - $x_mode = "set -x -v\n"; > - } > - elsif ($main::debug) { > - print "Running script:\n ", > - join( "\n ", split( "\n", "set $e_mode\n$script" )), "\n"; > - } > - my $pid = fork(); > - if (!defined $pid) { > - print PLOG "Can't fork: $! -- can't execute script\n"; > - return 1; > - } > - if ($pid == 0) { > - setpgrp( 0, $$ ); > - open( STDOUT, ">&PLOG" ); > - open( STDERR, ">&PLOG" ); > - if ($main::chroot_dir) { > - exec "$conf::sudo", "/usr/sbin/chroot", > "$main::cwd/$main::chroot_dir", > - "$conf::su", $main::username, "-s", "/bin/sh", > "-c", > - "cd /build/$main::username\nset > $e_mode\n$x_mode$script"; > - } > - else { > - exec "/bin/sh", "-c", "set $e_mode\n$x_mode$script"; > - } > - die "Can't exec /bin/sh: $!\n"; > - } > - wait; > - print "Script return value: $?\n" if $main::debug; > - return $? > -} > - > - > -sub read_deps { > - my @for_pkgs = @_; > - my $fname; > - local( *F ); > - > - open( F, $fname = "<$conf::source_dependencies-$main::distribution" ) > - or open( F, $fname = "<$conf::source_dependencies" ) > - or die "Cannot open $conf::source_dependencies: $!\n"; > - $fname = substr( $fname, 1 ); > - print "Reading source dependencies from $fname\n" > - if $main::debug; > - while( <F> ) { > - chomp; > - next if /^\s*$/ || /^\s*#/; > - while( /\\$/ ) { > - chop; > - $_ .= <F>; > - chomp; > - } > - if (/^(\*\*?[\w\d.+-]+):\s*$/) { > - # is a special definition > - my $sp = $1; > - get_special( $fname, $sp, \*F ); > - next; > - } > - if (/^abbrev\s+([\w\d.+-]+)\s*=\s*(.*)\s*$/) { > - my ($abbrev, $def) = ($1, $2); > - parse_one_srcdep( $abbrev, $def, \%main::abbrevs ); > - next; > - } > - if (!/^([a-zA-Z\d.+-]+):\s*(.*)\s*$/) { > - warn "Syntax error in line $. in $fname\n"; > - next; > - } > - my( $pkg, $deps ) = ($1, $2); > - if (exists $main::deps{$pkg}) { > - warn "Ignoring double entry for package $pkg at line $. > ". > - "in $fname\n"; > - next; > - } > - next if !isin( $pkg, @for_pkgs ); > - parse_one_srcdep( $pkg, $deps, \%main::deps ); > - } > - close( F ); > - > - foreach (@main::manual_srcdeps) { > - if (!/^([fa])([a-zA-Z\d.+-]+):\s*(.*)\s*$/) { > - warn "Syntax error in manual source dependency: ", > - substr( $_, 1 ), "\n"; > - next; > - } > - my ($mode, $pkg, $deps) = ($1, $2, $3); > - next if !isin( $pkg, @for_pkgs ); > - @{$main::deps{$pkg}} = () if $mode eq 'f'; > - parse_one_srcdep( $pkg, $deps, \%main::deps ); > - } > - > - # substitute abbrevs and warn about undefined special deps > - my( $pkg, $i, %warned ); > - foreach $pkg (keys %main::deps) { > - repeat: > - my $dl = $main::deps{$pkg}; > - for( $i = 0; $i < @$dl; ++$i ) { > - my $dep = $dl->[$i]; > - my $name = $dep->{'Package'}; > - if ($name =~ /^\*/) { > - if (!$warned{$name} && !exists > $main::specials{$name}) { > - warn "Warning: $pkg: No definition for > special ", > - "dependency $name!\n"; > - $warned{$name}++; > - } > - } > - elsif (defined $main::abbrevs{$name}) { > - my @l = @{$main::abbrevs{$name}}; > - if (defined $dep->{'Alternatives'}) { > - warn "Warning: $pkg: abbrev $name not > allowed ", > - "in alternative\n"; > - @l = (); > - } > - if ($dep->{'Neg'}) { > - warn "Warning: $pkg: Negation of abbrev > $name ", > - "not allowed\n"; > - @l = (); > - } > - if ($dep->{'Rel'}) { > - warn "Warning: $pkg: No relation with > abbrev $name ", > - "allowed\n"; > - @l = (); > - } > - if (my $ov = $dep->{'Override'}) { > - @l = map { my $x = copy($_); > - $x->{'Override'} = > $ov; $x } @l; > - } > - splice @$dl, $i, 1, @l; > - goto repeat; > - } > - elsif (defined $dep->{'Alternatives'}) { > - my $alt; > - foreach $alt (@{$dep->{'Alternatives'}}) { > - if (defined > $main::abbrevs{$alt->{'Package'}}) { > - warn "Warning: $pkg: abbrev > $alt->{'Package'} not ", > - "allowed in > alternative\n"; > - splice @$dl, $i, 1; > - } > - } > - } > - } > - } > -} > - > -sub copy { > - my $r = shift; > - my $new; > - > - if (ref($r) eq "HASH") { > - $new = { }; > - foreach (keys %$r) { > - $new->{$_} = copy($r->{$_}); > - } > - } > - elsif (ref($r) eq "ARRAY") { > - my $i; > - $new = [ ]; > - for( $i = 0; $i < @$r; ++$i ) { > - $new->[$i] = copy($r->[$i]); > - } > - } > - elsif (!ref($r)) { > - $new = $r; > - } > - else { > - die "unknown ref type in copy\n"; > - } > - > - return $new; > -} > - > -sub merge_pkg_build_deps { > - my $pkg = shift; > - my $depends = shift; > - my $dependsi = shift; > - my $conflicts = shift; > - my $conflictsi = shift; > - my (@l, $dep); > - > - print PLOG "** Using build dependencies supplied by package:\n"; > - print PLOG "Build-Depends: $depends\n" if $depends; > - print PLOG "Build-Depends-Indep: $dependsi\n" if $dependsi; > - print PLOG "Build-Conflicts: $conflicts\n" if $conflicts; > - print PLOG "Build-Conflicts-Indep: $conflictsi\n" if $conflictsi; > - > - my $old_deps = copy($main::deps{$pkg}); > - # keep deps from the central file marked as overrides (& prefix) > - if ( $main::useSNAP ) { > - $dep->{'Package'} = "gcc-snapshot"; > - $dep->{'Override'} = 1; > - push( @{$main::deps{$pkg}}, $dep ); > - } > - foreach $dep (@{$main::deps{$pkg}}) { > - if ($dep->{'Override'}) { > - print PLOG "Added override: ", > - (map { ($_->{'Neg'} ? "!" : "") . > - $_->{'Package'} . > - ($_->{'Rel'} ? " ($_->{'Rel'} > $_->{'Version'})":"") } > - scalar($dep), > @{$dep->{'Alternatives'}}), "\n"; > - push( @l, $dep ); > - } > - } > - > - $conflicts = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflicts )); > - $conflictsi = join( ", ", map { "!$_" } split( /\s*,\s*/, $conflictsi > )); > - > - my $deps = $depends . ", " . $conflicts; > - $deps .= ", " . $dependsi . ", " . $conflictsi if $main::build_arch_all; > - # For the moment, we treat multiarch-annotated build-dependencies as > - # the same as any others because we're not implementing a > - # cross-buildd. > - $deps =~ s/:any//g; > - $deps =~ s/:native//g; > - > - @{$main::deps{$pkg}} = @l; > - print "Merging pkg deps: $deps\n" if $main::debug; > - parse_one_srcdep( $pkg, $deps, \%main::deps ); > - > - my $missing = (cmp_dep_lists( $old_deps, $main::deps{$pkg} ))[1]; > - > - # read list of build-essential packages (if not yet done) and expand > their > - # dependencies (those are implicitly essential) > - if (!defined($main::deps{'ESSENTIAL'})) { > - my $ess = read_build_essential(); > - parse_one_srcdep( 'ESSENTIAL', $ess, \%main::deps ); > - } > - my ($exp_essential, $exp_pkgdeps, $filt_essential, $filt_pkgdeps); > - $exp_essential = expand_dependencies( $main::deps{'ESSENTIAL'} ); > - print "Dependency-expanded build essential packages:\n", > - format_deps(@$exp_essential), "\n" if $main::debug; > - > - # populate toolchain_pkgs from toolchain_regexes and essential packages. > - @main::toolchain_pkgs = (); > - foreach my $tpkg (@$exp_essential) { > - foreach my $regex (@conf::toolchain_regex) { > - push @main::toolchain_pkgs,$tpkg->{'Package'} > - if $tpkg->{'Package'} =~ m,^$regex,; > - } > - } > - return if !@$missing; > - > - # remove missing central deps that are essential > - ($filt_essential, $missing) = cmp_dep_lists( $missing, $exp_essential ); > - print PLOG "** Filtered missing central deps that are > build-essential:\n", > - format_deps(@$filt_essential), "\n" > - if @$filt_essential; > - > - # if some build deps are virtual packages, replace them by an > alternative > - # over all providing packages > - $exp_pkgdeps = expand_virtuals( $main::deps{$pkg} ); > - print "Provided-expanded build deps:\n", > - format_deps(@$exp_pkgdeps), "\n" if $main::debug; > - > - # now expand dependencies of package build deps > - $exp_pkgdeps = expand_dependencies( $exp_pkgdeps ); > - print "Dependency-expanded build deps:\n", > - format_deps(@$exp_pkgdeps), "\n" if $main::debug; > - $main::additional_deps = $exp_pkgdeps; > - > - # remove missing central deps that are dependencies of build deps > - ($filt_pkgdeps, $missing) = cmp_dep_lists( $missing, $exp_pkgdeps ); > - print PLOG "** Filtered missing central deps that are dependencies of ", > - "or provide build-deps:\n", > - format_deps(@$filt_pkgdeps), "\n" > - if @$filt_pkgdeps; > - > - # remove comment package names > - push( @$main::additional_deps, > - grep { $_->{'Neg'} && $_->{'Package'} =~ /^needs-no-/ } > @$missing ); > - $missing = [ grep { !($_->{'Neg'} && > - ($_->{'Package'} =~ > /^this-package-does-not-exist/ || > - $_->{'Package'} =~ > /^needs-no-/)) } @$missing ]; > - > - print PLOG "**** Warning:\n", > - "**** The following central src deps are ", > - "(probably) missing:\n ", format_deps(@$missing), > "\n" > - if @$missing; > -} > - > -sub cmp_dep_lists { > - my $list1 = shift; > - my $list2 = shift; > - my ($dep, @common, @missing); > - > - foreach $dep (@$list1) { > - my $found = 0; > - > - if ($dep->{'Neg'}) { > - foreach (@$list2) { > - if ($dep->{'Package'} eq $_->{'Package'} && > $_->{'Neg'}) { > - $found = 1; > - last; > - } > - } > - } > - else { > - my $al = get_altlist($dep); > - foreach (@$list2) { > - if (is_superset( get_altlist($_), $al )) { > - $found = 1; > - last; > - } > - } > - } > - > - if ($found) { > - push( @common, $dep ); > - } > - else { > - push( @missing, $dep ); > - } > - } > - return (\@common, \@missing); > -} > - > -sub get_altlist { > - my $dep = shift; > - my %l; > - > - foreach (scalar($dep), @{$dep->{'Alternatives'}}) { > - $l{$_->{'Package'}} = 1 if !$_->{'Neg'}; > - } > - return \%l; > -} > - > -sub is_superset { > - my $l1 = shift; > - my $l2 = shift; > - > - foreach (keys %$l2) { > - return 0 if !exists $l1->{$_}; > - } > - return 1; > -} > - > -sub read_build_essential { > - my @essential; > - local (*F); > - > - if (open( F, > "$main::chroot_dir/usr/share/doc/build-essential/essential-packages-list" )) { > - while( <F> ) { > - last if $_ eq "\n"; > - } > - while( <F> ) { > - chomp; > - push( @essential, $_ ) if $_ !~ /^\s*$/; > - } > - close( F ); > - } > - else { > - warn "Cannot open > $main::chroot_dir/usr/share/doc/build-essential/essential-packages-list: > $!\n"; > - } > - > - if (open( F, "$main::chroot_dir/usr/share/doc/build-essential/list" )) { > - while( <F> ) { > - last if $_ eq "BEGIN LIST OF PACKAGES\n"; > - } > - while( <F> ) { > - chomp; > - last if $_ eq "END LIST OF PACKAGES"; > - next if /^\s/ || /^$/; > - push( @essential, $_ ); > - } > - close( F ); > - } > - else { > - warn "Cannot open > $main::chroot_dir/usr/share/doc/build-essential/list: $!\n"; > - } > - > - return join( ", ", @essential ); > -} > - > -sub expand_dependencies { > - my $dlist = shift; > - my (@to_check, @result, %seen, $check, $dep); > - > - foreach $dep (@$dlist) { > - next if $dep->{'Neg'} || $dep->{'Package'} =~ /^\*/; > - foreach (scalar($dep), @{$dep->{'Alternatives'}}) { > - my $name = $_->{'Package'}; > - push( @to_check, $name ); > - $seen{$name} = 1; > - } > - push( @result, copy($dep) ); > - } > - > - while( @to_check ) { > - my $deps = get_dependencies( @to_check ); > - my @check = @to_check; > - @to_check = (); > - foreach $check (@check) { > - foreach (split( /\s*,\s*/, $deps->{$check} )) { > - foreach (split( /\s*\|\s*/, $_ )) { > - my $pkg = (/^([^\s([]+)/)[0]; > - if (!$seen{$pkg}) { > - push( @to_check, $pkg ); > - push( @result, { Package => > $pkg, Neg => 0 } ); > - $seen{$pkg} = 1; > - } > - } > - } > - } > - } > - > - return \@result; > -} > - > -sub expand_virtuals { > - my $dlist = shift; > - my ($dep, %names, @new_dlist); > - > - foreach $dep (@$dlist) { > - foreach (scalar($dep), @{$dep->{'Alternatives'}}) { > - $names{$_->{'Package'}} = 1; > - } > - } > - my $provided_by = get_virtuals( keys %names ); > - > - foreach $dep (@$dlist) { > - my %seen; > - foreach (scalar($dep), @{$dep->{'Alternatives'}}) { > - my $name = $_->{'Package'}; > - $seen{$name} = 1; > - if (exists $provided_by->{$name}) { > - foreach( keys %{$provided_by->{$name}} ) { > - $seen{$_} = 1; > - } > - } > - } > - my @l = map { { Package => $_, Neg => 0 } } keys %seen; > - my $l = shift @l; > - foreach (@l) { > - push( @{$l->{'Alternatives'}}, $_ ); > - } > - push( @new_dlist, $l ); > - } > - > - return \@new_dlist; > -} > - > -sub get_dependencies { > - local(*PIPE); > - my %deps; > - > - open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir > $conf::apt_cache show @_ 2>&1 |" ) > - or die "Cannot start $conf::apt_cache $main::chroot_apt_op: > $!\n"; > - local($/) = ""; > - while( <PIPE> ) { > - my ($name, $dep, $predep); > - /^Package:\s*(.*)\s*$/mi and $name = $1; > - next if !$name || $deps{$name}; > - /^Depends:\s*(.*)\s*$/mi and $dep = $1; > - /^Pre-Depends:\s*(.*)\s*$/mi and $predep = $1; > - $dep .= ", " if $dep && $predep; > - $dep .= $predep; > - $deps{$name} = $dep; > - } > - close( PIPE ); > - die "$conf::apt_cache exit status $?\n" if $?; > - > - return \%deps; > -} > - > -sub get_virtuals { > - local(*PIPE); > - > - open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir > $conf::apt_cache showpkg @_ 2>&1 |" ) > - or die "Cannot start $conf::apt_cache $main::chroot_apt_op: > $!\n"; > - my $name; > - my $in_rprov = 0; > - my %provided_by; > - while( <PIPE> ) { > - if (/^Package:\s*(\S+)\s*$/) { > - $name = $1; > - } > - elsif (/^Reverse Provides: $/) { > - $in_rprov = 1; > - } > - elsif ($in_rprov && /^(\w+):\s/) { > - $in_rprov = 0; > - } > - elsif ($in_rprov && /^(\S+)\s*\S+\s*$/) { > - $provided_by{$name}->{$1} = 1; > - } > - } > - close( PIPE ); > - die "$conf::apt_cache exit status $?\n" if $?; > - > - return \%provided_by; > -} > - > -# Try to figure out if a package exists. We need to take account of virtual > -# packages, so showpkg is the best tool I can think of; but that shows > -# packages which only exist as (reverse) dependencies. As such, we make > -# sure that either Versions: or Reverse Provides: has some content. > -sub package_exists { > - local(*PIPE); > - > - open( PIPE, "$conf::sudo /usr/sbin/chroot $main::chroot_dir ". > - "$conf::apt_cache showpkg @_ 2>&1 |" ) > - or die "Cannot start $conf::apt_cache $main::chroot_apt_op: > $!\n"; > - my $name; > - my $in_versions = 0; > - my $in_rprov = 0; > - my $real = 0; > - while( <PIPE> ) { > - if (/^Package:\s*(\S+)\s*$/) { > - $name = $1; > - } > - elsif (/^Versions: $/) { > - $in_versions = 1; > - $in_rprov = 0; > - } > - elsif (/^Reverse Provides: $/) { > - $in_rprov = 1; > - $in_versions = 0; > - } > - elsif (($in_versions || $in_rprov) && /^(\w.*):\s/) { > - $in_versions = 0; > - $in_rprov = 0; > - } > - elsif (($in_versions || $in_rprov) && /^\S/) { > - $real = 1; > - } > - } > - close( PIPE ); > - if (defined $name and $real) { > - return 1; > - } else { > - return 0; > - } > -} > - > -sub parse_one_srcdep { > - my $pkg = shift; > - my $deps = shift; > - my $hash = shift; > - > - $deps =~ s/^\s*(.*)\s*$/$1/; > - foreach (split( /\s*,\s*/, $deps )) { > - my @l; > - my $override; > - if (/^\&/) { > - $override = 1; > - s/^\&\s+//; > - } > - my @alts = split( /\s*\|\s*/, $_ ); > - my $special_seen = 0; > - my $neg_seen = 0; > - foreach (@alts) { > - if > (!/^([^\s([]+)\s*(\(\s*([<=>]+)\s*(\S+)\s*\))?(\s*\[([^]]+)\])?/) { > - warn "Warning: syntax error in dependency '$_' > of $pkg\n"; > - next; > - } > - my( $dep, $rel, $relv, $archlist ) = ($1, $3, $4, $6); > - if ($archlist) { > - $archlist =~ s/^\s*(.*)\s*$/$1/; > - my @archs = split( /\s+/, $archlist ); > - my ($use_it, $ignore_it, $include) = (0, 0, 0); > - foreach (@archs) { > - # Use 'dpkg-architecture' to support > architecture > - # wildcards. > - if (/^!/) { > - if (system("$conf::sudo", > "/usr/sbin/chroot", > - > "$main::cwd/$main::chroot_dir", > - "dpkg-architecture", > "-a".$main::arch, "-i".substr($_, 1)) eq 0) { > - $ignore_it = 1 > - } > - } > - else { > - if (system("$conf::sudo", > "/usr/sbin/chroot", > - > "$main::cwd/$main::chroot_dir", > - "dpkg-architecture", > "-a".$main::arch, "-i".$_) eq 0) { > - $use_it = 1 > - } > - $include = 1; > - } > - } > - warn "Warning: inconsistent arch restriction on > ", > - "$pkg: $dep depedency\n" > - if $ignore_it && $use_it; > - next if $ignore_it || ($include && !$use_it); > - } > - if ($dep =~ /^\*/) { > - warn "Warning: $pkg: ignoring version relation > on ". > - "special dependency $dep\n" > - if $rel || $relv; > - push( @l, { Package => $dep, Override => 1 } ); > - $special_seen = 1; > - next; > - } > - my $neg = 0; > - if ($dep =~ /^!/) { > - $dep =~ s/^!\s*//; > - $neg = 1; > - $neg_seen = 1; > - } > - if ($conf::srcdep_over{$dep}) { > - if ($main::verbose) { > - print PLOG "Replacing source dep $dep"; > - print PLOG " ($rel $relv)" if $relv; > - print PLOG " with > $conf::srcdep_over{$dep}[0]"; > - print PLOG " > ($conf::srcdep_over{$dep}[1] $conf::srcdep_over{$dep}[2])" > - if $conf::srcdep_over{$dep}[1]; > - print PLOG ".\n"; > - } > - $dep = $conf::srcdep_over{$dep}[0]; > - $rel = $conf::srcdep_over{$dep}[1]; > - $relv = $conf::srcdep_over{$dep}[2]; > - } > - my $h = { Package => $dep, Neg => $neg }; > - if ($rel && $relv) { > - $h->{'Rel'} = $rel; > - $h->{'Version'} = $relv; > - } > - $h->{'Override'} = $override if $override; > - push( @l, $h ); > - } > - if (@alts > 1 && $special_seen) { > - warn "Warning: $pkg: alternatives with special > dependencies ", > - "forbidden -- skipped\n"; > - } > - elsif (@alts > 1 && $neg_seen) { > - warn "Warning: $pkg: alternatives with negative > dependencies ", > - "forbidden -- skipped\n"; > - } > - elsif (@l) { > - my $l = shift @l; > - foreach (@l) { > - push( @{$l->{'Alternatives'}}, $_ ); > - } > - push( @{$hash->{$pkg}}, $l ); > - } > - } > -} > - > -sub get_special { > - my $fname = shift; > - my $sp = shift; > - my $sub = ""; > - > - while( <F> ) { > - last if /^$/; > - if (/^\s*(\w+)\s*\{\s*$/) { > - if ($sub) { > - warn "Syntax error in line $. in $fname:\n"; > - warn " Start of special subsection inside ". > - "another one.\n"; > - } > - else { > - $sub = $1; > - $main::specials{$sp}->{$sub} = ""; > - } > - } > - elsif (/^\s*\}\s*$/) { > - if (!$sub) { > - warn "Syntax error in line $. in $fname:\n"; > - warn " } outside of special subsection\n"; > - } > - else { > - $sub = ""; > - } > - } > - elsif ($sub) { > - $main::specials{$sp}->{$sub} .= $_; > - } > - else { > - warn "Syntax error in line $. in $fname:\n"; > - warn " Subsection start expected\n"; > - } > - } > - if ($sub) { > - warn "Syntax error in line $. in $fname:\n"; > - warn " Subsection not finished with }\n"; > - } > - > - push( @main::global_patches, $sp ) if $sp =~ /^\*\*/; > -} > - > - > -sub open_log { > - my $date = `date +%Y%m%d-%H%M`; > - chomp( $date ); > - > - if ($main::nolog) { > - open( LOG, ">&STDOUT" ); > - open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n"; > - select( LOG ); > - return; > - } > - > - $main::main_logfile = "build-$date.log"; > - > - if ($main::verbose) { > - my $pid; > - ($pid = open( LOG, "|-")) || exec "tee $main::main_logfile"; > - if (!defined $pid) { > - warn "Cannot open pipe to 'tee $main::main_logfile': > $!\n"; > - } > - else { > - $main::tee_pid = $pid; > - } > - } > - else { > - open( LOG, ">$main::main_logfile" ) > - or warn "Cannot open log file $main::main_logfile: > $!\n"; > - } > - select( (select( LOG ), $| = 1)[0] ); > - open( STDOUT, ">&LOG" ) or warn "Can't redirect stdout\n"; > - open( STDERR, ">&LOG" ) or warn "Can't redirect stderr\n"; > - open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n"; > -} > - > -sub close_log { > - my $date = `date +%Y%m%d-%H%M`; > - chomp( $date ); > - > - kill( 15, $main::tee_pid ) if $main::verbose; > - close( LOG ); > - if (!$main::nolog && !$main::verbose && > - -s $main::main_logfile && $conf::mailto) { > - send_mail( $conf::mailto, "Log from sbuild $date", > - $main::main_logfile ) if $conf::mailto; > - } > - elsif (!$main::nolog && !$main::verbose && ! -s $main::main_logfile) { > - unlink( $main::main_logfile ); > - } > -} > - > -sub open_pkg_log { > - my $date = `date +%Y%m%d-%H%M`; > - my $pkg = shift; > - > - if ($main::nolog) { > - open( PLOG, ">&STDOUT" ); > - } > - else { > - $pkg = basename( $pkg ); > - if ($main::binNMU) { > - $pkg =~ /^([^_]+)_([^_]+)(.*)$/; > - $pkg = $1."_".binNMU_version($2); > - $main::binNMU_name = $pkg; > - $pkg .= $3; > - } > - $main::pkg_logfile = "$conf::log_dir/${pkg}_$date"; > - if ($main::verbose) { > - my $pid; > - ($pid = open( PLOG, "|-")) || exec "tee > $main::pkg_logfile"; > - if (!defined $pid) { > - warn "Cannot open pipe to 'tee > $main::pkg_logfile': $!\n"; > - } > - else { > - $main::pkg_tee_pid = $pid; > - } > - } > - else { > - if (!open( PLOG, ">$main::pkg_logfile" )) { > - warn "Can't open logfile $main::pkg_logfile: > $!\n"; > - return 0; > - } > - } > - } > - select( (select( PLOG ), $| = 1)[0] ); > - > - my $revision = '$Revision: 1.170.5 $'; > - $revision =~ /([\d.]+)/; > - $revision = $1; > - > - print PLOG "Automatic build of $pkg on $main::HOSTNAME by ". > - "sbuild/$main::arch $revision\n"; > - print PLOG "Build started at $date"; > - print PLOG "*"x78, "\n"; > - return 1; > -} > - > -sub close_pkg_log { > - my $date = `date +%Y%m%d-%H%M`; > - my $pkg = shift; > - my $t = $main::pkg_end_time - $main::pkg_start_time; > - > - $pkg = basename( $pkg ); > - $t = 0 if $t < 0; > - #if ($main::pkg_status eq "successful") { > - # add_time_entry( $pkg, $t ); > - # add_space_entry( $pkg, $main::this_space ); > - #} > - print PLOG "*"x78, "\n"; > - printf PLOG "Finished at ${date}Build needed %02d:%02d:%02d, %dk disk > space\n", > - int($t/3600), int(($t%3600)/60), int($t%60), > $main::this_space; > - kill( 15, $main::pkg_tee_pid ) if $main::verbose && !$main::nolog; > - close( PLOG ); > - open( PLOG, ">&LOG" ) or warn "Can't redirect PLOG\n"; > - send_mail( $conf::mailto, > - "Log for $main::pkg_status build of ". > - ($main::binNMU_name || $pkg)." > (dist=$main::distribution)", > - $main::pkg_logfile ) if !$main::nolog && > $conf::mailto; > -} > - > -sub add_time_entry { > - my $pkg = shift; > - my $t = shift; > - > - return if !$conf::avg_time_db; > - my %db; > - if (!tie %db, 'GDBM_File',$conf::avg_time_db,GDBM_WRCREAT,0664) { > - print "Can't open average time db $conf::avg_time_db\n"; > - return; > - } > - $pkg =~ s/_.*//; > - > - if (exists $db{$pkg}) { > - my @times = split( /\s+/, $db{$pkg} ); > - push( @times, $t ); > - my $sum = 0; > - foreach (@times[1..$#times]) { $sum += $_; } > - $times[0] = $sum / (@times-1); > - $db{$pkg} = join( ' ', @times ); > - } > - else { > - $db{$pkg} = "$t $t"; > - } > - untie %db; > -} > - > -sub check_space { > - my @files = @_; > - local( *PIPE ); > - > - if (!open( PIPE, "sudo /usr/bin/du -s @files 2>/dev/null |" )) { > - print PLOG "Cannot determine space needed (du failed): $!\n"; > - return; > - } > - my $sum = 0; > - while( <PIPE> ) { > - next if !/^(\d+)/; > - $sum += $1; > - } > - close( PIPE ); > - $main::this_space = $sum; > -} > - > -sub add_space_entry { > - my $pkg = shift; > - my $t = shift; > - > - my $keepvals = 4; > - > - return if !$conf::avg_space_db || $main::this_space == 0; > - my %db; > - if (!tie %db, 'GDBM_File',$conf::avg_space_db,GDBM_WRCREAT,0664) { > - print "Can't open average space db $conf::avg_space_db\n"; > - return; > - } > - $pkg =~ s/_.*//; > - > - if (exists $db{$pkg}) { > - my @values = split( /\s+/, $db{$pkg} ); > - shift @values; > - unshift( @values, $t ); > - pop @values if @values > $keepvals; > - my ($sum, $n, $weight, $i) = (0, 0, scalar(@values)); > - for( $i = 0; $i < @values; ++$i) { > - $sum += $values[$i] * $weight; > - $n += $weight; > - } > - unshift( @values, $sum/$n ); > - $db{$pkg} = join( ' ', @values ); > - } > - else { > - $db{$pkg} = "$t $t"; > - } > - untie %db; > -} > - > -sub file_for_name { > - my $name = shift; > - my @x = grep { /^\Q$name\E_/ } @_; > - return $x[0]; > -} > - > -sub write_jobs_file { > - my $news = shift; > - my $job; > - local( *F ); > - > - $main::job_state{$main::current_job} = $news > - if $news && $main::current_job; > - > - return if !$main::batchmode; > - > - return if !open( F, ">$main::jobs_file" ); > - foreach $job (@ARGV) { > - print F ($job eq $main::current_job) ? "" : " ", > - $job, > - ($main::job_state{$job} ? ": > $main::job_state{$job}" : ""), > - "\n"; > - } > - close( F ); > -} > - > -sub append_to_FINISHED { > - my $pkg = shift; > - local( *F ); > - > - return if !$main::batchmode; > - > - open( F, ">>SBUILD-FINISHED" ); > - print F "$pkg\n"; > - close( F ); > -} > - > -sub write_srcdep_lock_file { > - my $deps = shift; > - my $specials = shift; > - local( *F ); > - > - ++$main::srcdep_lock_cnt; > - my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt"; > - if (!open( F, ">$f" )) { > - print "Warning: cannot create srcdep lock file $f: $!"; > - return; > - } > - print "Writing srcdep lock file $f:\n" if $main::debug; > - > - chomp( my $user = `/usr/bin/whoami` ); > - print F "$main::current_job $$ $user\n"; > - print "Job $main::current_job pid $$ user $user\n" if $main::debug; > - foreach (@$deps) { > - my $name = $_->{'Package'}; > - # add special deps only if they affect global state ("global" > sub) > - next if $name =~ /^\*/ && > - (!isin( $name, @$specials ) || > - $main::specials{$name}->{'global'} !~ /yes/m); > - print F ($_->{'Neg'} ? "!" : ""), "$name\n"; > - print " ", ($_->{'Neg'} ? "!" : ""), "$name\n" if $main::debug; > - } > - close( F ); > -} > - > -sub check_srcdep_conflicts { > - my $to_inst = shift; > - my $to_remove = shift; > - my $special = shift; > - local( *F, *DIR ); > - my $mypid = $$; > - my %conflict_builds; > - > - if (!opendir( DIR, $conf::srcdep_lock_dir )) { > - print PLOG "Cannot opendir $conf::srcdep_lock_dir: $!\n"; > - return 1; > - } > - my @files = grep { !/^\.\.?$/ && !/^install\.lock/ && !/^$mypid-\d+$/ } > - readdir(DIR); > - closedir(DIR); > - > - my $file; > - foreach $file (@files) { > - if (!open( F, "<$conf::srcdep_lock_dir/$file" )) { > - print PLOG "Cannot open $conf::srcdep_lock_dir/$file: > $!\n"; > - next; > - } > - <F> =~ /^(\S+)\s+(\S+)\s+(\S+)/; > - my ($job, $pid, $user) = ($1, $2, $3); > - > - # ignore (and remove) a lock file if associated process doesn't > exist > - # anymore > - if (kill( 0, $pid ) == 0 && $! == ESRCH) { > - close( F ); > - print PLOG "Found stale srcdep lock file $file -- > removing it\n"; > - print PLOG "Cannot remove: $!\n" > - if !unlink( "$conf::srcdep_lock_dir/$file" ); > - next; > - } > - > - print "Reading srclock file $file by job $job user $user\n" > - if $main::debug; > - > - while( <F> ) { > - my ($neg, $pkg) = /^(!?)(\S+)/; > - print "Found ", ($neg ? "neg " : ""), "entry $pkg\n" > - if $main::debug; > - > - if ($pkg =~ /^\*/) { > - print PLOG "Build of $job by $user (pid $pid) > has ", > - "installed the global > special dependency $pkg.\n"; > - $conflict_builds{$file} = 1; > - } > - else { > - if (isin( $pkg, @$to_inst, @$to_remove )) { > - print PLOG "Source dependency conflict > with build of ", > - "$job by $user (pid > $pid):\n"; > - print PLOG " $job ", ($neg ? > "conflicts with" : "needs"), > - " $pkg\n"; > - print PLOG " $main::current_job wants > to ", > - (isin( $pkg, > @$to_inst ) ? "update" : "remove"), > - " $pkg\n"; > - $conflict_builds{$file} = 1; > - } > - } > - } > - close( F ); > - } > - > - foreach (@$special) { > - if ($main::specials{$_}->{'global'} =~ /yes/m) { > - print PLOG "$main::current_job wants to apply global ", > - "special dependency $_\n", > - "Must wait for other builds to > finish\n"; > - foreach (@files) { > - $conflict_builds{$_} = 1; > - } > - } > - } > - > - my @conflict_builds = keys %conflict_builds; > - if (@conflict_builds) { > - print "Srcdep conflicts with: @conflict_builds\n" if > $main::debug; > - } > - else { > - print "No srcdep conflicts\n" if $main::debug; > - } > - return @conflict_builds; > -} > - > -sub remove_srcdep_lock_file { > - my $f = "$conf::srcdep_lock_dir/$$-$main::srcdep_lock_cnt"; > - > - print "Removing srcdep lock file $f\n" if $main::debug; > - if (!unlink( $f )) { > - print "Warning: cannot remove srcdep lock file $f: $!\n" > - if $! != ENOENT; > - } > -} > - > -sub prepare_watches { > - my $dependencies = shift; > - my @instd = @_; > - my(@dep_on, $dep, $pkg, $prg); > - > - @dep_on = @instd; > - foreach $dep (@$dependencies, @$main::additional_deps) { > - if ($dep->{'Neg'} && $dep->{'Package'} =~ /^needs-no-(\S+)/) { > - push( @dep_on, $1 ); > - } > - elsif ($dep->{'Package'} !~ /^\*/ && !$dep->{'Neg'}) { > - foreach (scalar($dep), @{$dep->{'Alternatives'}}) { > - push( @dep_on, $_->{'Package'} ); > - } > - } > - } > - # init %this_watches to names of packages which have not been installed > as > - # source dependencies > - undef %main::this_watches; > - foreach $pkg (keys %conf::watches) { > - if (isin( $pkg, @dep_on )) { > - print "Excluding from watch: $pkg\n" if $main::debug; > - next; > - } > - foreach $prg (@{$conf::watches{$pkg}}) { > - $prg = "/usr/bin/$prg" if $prg !~ m,^/,; > - $main::this_watches{"$main::chroot_dir$prg"} = $pkg; > - print "Will watch for $prg ($pkg)\n" if $main::debug; > - } > - } > -} > - > -sub check_watches { > - my($prg, @st, %used); > - > - foreach $prg (keys %main::this_watches) { > - if (!(@st = stat( $prg ))) { > - print "Watch: $prg: stat failed\n" if $main::debug; > - next; > - } > - if ($st[8] > $main::build_start_time) { > - my $pkg = $main::this_watches{$prg}; > - my $prg2 = $prg; > - $prg2 =~ s/^\Q$main::chroot_dir\E// if > $main::chroot_dir; > - push( @{$used{$pkg}}, $prg2 ) > - if @main::have_dsc_build_deps || > - !isin( $pkg, > @conf::ignore_watches_no_build_deps ); > - } > - else { > - print "Watch: $prg: untouched\n" if $main::debug; > - } > - } > - return if !%used; > - > - print PLOG <<EOF; > - > -NOTE: The package could have used binaries from the following packages > -(access time changed) without a source dependency: > -EOF > - foreach (keys %used) { > - print PLOG " $_: @{$used{$_}}\n"; > - } > - print PLOG "\n"; > -} > - > -sub should_skip { > - my $pkgv = shift; > - > - fixup_pkgv( \$pkgv ); > - lock_file( "SKIP" ); > - goto unlock if !open( F, "SKIP" ); > - my @pkgs = <F>; > - close( F ); > - > - if (!open( F, ">SKIP" )) { > - print "Can't open SKIP for writing: $!\n", > - "Would write: @pkgs\nminus $pkgv\n"; > - goto unlock; > - } > - my $found = 0; > - foreach (@pkgs) { > - if (/^\Q$pkgv\E$/) { > - ++$found; > - print PLOG "$pkgv found in SKIP file -- skipping > building it\n"; > - } > - else { > - print F $_; > - } > - } > - close( F ); > - unlock: > - unlock_file( "SKIP" ); > - return $found; > -} > - > -sub add_givenback { > - my $pkgv = shift; > - my $time = shift; > - local( *F ); > - > - lock_file( "SBUILD-GIVEN-BACK" ); > - > - if (open( F, ">>SBUILD-GIVEN-BACK" )) { > - print F "$pkgv $time\n"; > - close( F ); > - } > - else { > - print PLOG "Can't open SBUILD-GIVEN-BACK: $!\n"; > - } > - > - unlock: > - unlock_file( "SBUILD-GIVEN-BACK" ); > -} > - > -sub send_mail { > - my $to = shift; > - my $subject = shift; > - my $file = shift; > - local( *MAIL, *F ); > - > - if (!open( F, "<$file" )) { > - warn "Cannot open $file for mailing: $!\n"; > - return 0; > - } > - local $SIG{'PIPE'} = 'IGNORE'; > - > - if (!open( MAIL, "|$conf::mailprog -oem $to" )) { > - warn "Could not open pipe to $conf::mailprog: $!\n"; > - close( F ); > - return 0; > - } > - > - print MAIL "Subject: $subject\n\n"; > - while( <F> ) { > - print MAIL "." if $_ eq ".\n"; > - print MAIL $_; > - } > - > - close( F ); > - if (!close( MAIL )) { > - warn "$conf::mailprog failed (exit status $?)\n"; > - return 0; > - } > - return 1; > -} > - > - > -sub set_installed { > - foreach (@_) { > - $main::changes->{'installed'}->{$_} = 1; > - } > - print "Added to installed list: @_\n" if $main::debug; > -} > - > -sub set_removed { > - foreach (@_) { > - $main::changes->{'removed'}->{$_} = 1; > - if (exists $main::changes->{'installed'}->{$_}) { > - delete $main::changes->{'installed'}->{$_}; > - $main::changes->{'auto-removed'}->{$_} = 1; > - print "Note: $_ was installed\n" if $main::debug; > - } > - } > - print "Added to removed list: @_\n" if $main::debug; > -} > - > -sub unset_installed { > - foreach (@_) { > - delete $main::changes->{'installed'}->{$_}; > - } > - print "Removed from installed list: @_\n" if $main::debug; > -} > - > -sub unset_removed { > - foreach (@_) { > - delete $main::changes->{'removed'}->{$_}; > - if (exists $main::changes->{'auto-removed'}->{$_}) { > - delete $main::changes->{'auto-removed'}->{$_}; > - $main::changes->{'installed'}->{$_} = 1; > - print "Note: revived $_ to installed list\n" if > $main::debug; > - } > - } > - print "Removed from removed list: @_\n" if $main::debug; > -} > - > -sub basename { > - my $b = $_[0]; > - $b =~ s,^.*/,,; > - return $b; > -} > - > -sub df { > - my $dir = shift; > - > - my $free = `/bin/df $dir | tail -1`; > - my @free = split( /\s+/, $free ); > - return $free[3]; > -} > - > -sub isin { > - my $val = shift; > - return grep( $_ eq $val, @_ ); > -} > - > -sub fixup_pkgv { > - my $pkgv = shift; > - > - $$pkgv =~ s,^.*/,,; # strip path > - $$pkgv =~ s/\.(dsc|diff\.gz|tar\.gz|deb)$//; # strip extension > - $$pkgv =~ s/_[a-zA-Z\d+~-]+\.(changes|deb)$//; # strip extension > -} > - > -sub format_deps { > - return join( ", ", > - map { join( "|", > - map { ($_->{'Neg'} ? "!" : "") . > - $_->{'Package'} . > - ($_->{'Rel'} ? " ($_->{'Rel'} > $_->{'Version'})":"")} > - scalar($_), @{$_->{'Alternatives'}}) } @_ ); > -} > - > -sub lock_file { > - my $file = shift; > - my $for_srcdep = shift; > - my $lockfile = "$file.lock"; > - my $try = 0; > - > - repeat: > - if (!sysopen( F, $lockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644 )){ > - if ($! == EEXIST) { > - # lock file exists, wait > - goto repeat if !open( F, "<$lockfile" ); > - my $line = <F>; > - my ($pid, $user); > - close( F ); > - if ($line !~ /^(\d+)\s+([\w\d.-]+)$/) { > - warn "Bad lock file contents ($lockfile) -- > still trying\n"; > - } > - else { > - ($pid, $user) = ($1, $2); > - if (kill( 0, $pid ) == 0 && $! == ESRCH) { > - # process doesn't exist anymore, remove > stale lock > - warn "Removing stale lock file > $lockfile ". > - " (pid $pid, user $user)\n"; > - unlink( $lockfile ); > - goto repeat; > - } > - } > - ++$try; > - if (!$for_srcdep && $try > $main::max_lock_trys) { > - warn "Lockfile $lockfile still present after ". > - $main::max_lock_trys*$main::lock_interval. > - " seconds -- giving up\n"; > - return; > - } > - print PLOG "Another sbuild process ($pid by $user) is > currently ", > - "installing or\n", > - "removing packages -- waiting...\n" > - if $for_srcdep && $try == 1; > - sleep $main::lock_interval; > - goto repeat; > - } > - warn "Can't create lock file $lockfile: $!\n"; > - } > - F->print("$$ $ENV{'LOGNAME'}\n"); > - F->close(); > -} > - > -sub unlock_file { > - my $file = shift; > - my $lockfile = "$file.lock"; > - > - unlink( $lockfile ); > -} > - > -sub check_dpkg_version { > - my $t = `$conf::dpkg --version`; > - my $version = ($t =~ /version\s+(\S+)/)[0]; > - > - $main::new_dpkg = 1 > - if 0 == system "$conf::dpkg --compare-versions '$version' ge > 1.4.1.18"; > -} > - > -sub binNMU_version { > - my $v = shift; > - > - if ($v =~ /^(.*)-([^-]+)$/) { > - my ($upstream, $debian) = ($1, $2); > - my @parts = split( /\./, $debian ); > - if (@parts == 1) { > - return "$upstream-$debian.0.$main::binNMUver"; > - } > - elsif (@parts == 2) { > - return "$upstream-$debian.$main::binNMUver"; > - } > - else { > - $parts[$#parts]+=$main::binNMUver; > - return "$upstream-".join( ".", @parts ); > - } > - } > - else { > - return "$v.0.$main::binNMUver"; > - } > -} > - > -sub shutdown { > - my $signame = shift; > - my($job,@npkgs,@pkgs); > - local( *F ); > - > - $SIG{'INT'} = 'IGNORE'; > - $SIG{'QUIT'} = 'IGNORE'; > - $SIG{'TERM'} = 'IGNORE'; > - $SIG{'ALRM'} = 'IGNORE'; > - $SIG{'PIPE'} = 'IGNORE'; > - print PLOG "sbuild received SIG$signame -- shutting down\n"; > - chdir( $main::cwd ); > - > - goto not_ni_shutdown if !$main::batchmode; > - > - # most important: dump out names of unfinished jobs to REDO > - foreach $job (@ARGV) { > - my $job2 = $job; > - fixup_pkgv( \$job2 ); > - push( @npkgs, $job2 ) > - if !$main::job_state{$job} || $job eq > $main::current_job; > - } > - print LOG "The following jobs were not finished: @npkgs\n"; > - > - my $f = "$main::HOME/build/REDO"; > - if (-f "$main::HOME/build/REDO.lock") { > - # if lock file exists, write to a different file -- timing may > - # be critical > - $f = "$main::HOME/build/REDO2"; > - } > - if (open( F, "<$f" )) { > - @pkgs = <F>; > - close( F ); > - } > - if (open( F, ">>$f" )) { > - foreach $job (@npkgs) { > - next if grep( /^\Q$job\E\s/, @pkgs ); > - print F "$job $main::distribution $main::component\n"; > - } > - close( F ); > - } > - else { > - print "Cannot open $f: $!\n"; > - } > - open( F, ">SBUILD-REDO-DUMPED" ); > - close( F ); > - print LOG "SBUILD-REDO-DUMPED created\n"; > - unlink( "SBUILD-FINISHED" ); > - > - # next: say which packages should be uninstalled > - @pkgs = keys %{$main::changes->{'installed'}}; > - if (@pkgs) { > - if (open( F, ">>NEED-TO-UNINSTALL" )) { > - print F "@pkgs\n"; > - close( F ); > - } > - print "The following packages still need to be uninstalled ", > - "(--purge):\n@pkgs\n"; > - } > - > - not_ni_shutdown: > - # next: kill currently running command (if one) > - if ($main::sub_pid) { > - print "Killing $main::sub_task subprocess $main::sub_pid\n"; > - system "$conf::sudo perl -e 'kill( -15, $main::sub_pid )'"; > - } > - remove_srcdep_lock_file(); > - > - # close logs and send mails > - if ( $main::current_job ) { > - fixup_pkgv( \$main::current_job ); > - close_pkg_log( $main::current_job ); > - } > - close_log(); > - unlink( $main::jobs_file ) if $main::batchmode; > - $? = 0; $! = 0; > - exit 0; > -} > > === modified file 'sbuild-package' > --- sbuild-package 2014-07-17 21:16:34 +0000 > +++ sbuild-package 2015-05-11 11:00:44 +0000 > @@ -1,4 +1,4 @@ > -#!/bin/sh > +#!/bin/bash > # > # Copyright 2009 Canonical Ltd. This software is licensed under the > # GNU Affero General Public License version 3 (see the file LICENSE). > @@ -13,6 +13,10 @@ > > # Needs SBUILD to be set to a sbuild instance with passwordless sudo ability > > +# We want a non-zero exit code from sbuild even if the implicit function > +# pointer check succeeds. > +set -o pipefail > + > exec 2>&1 > > # Keep this in sync with sbuild/lib/Buildd.pm. > @@ -43,15 +47,14 @@ > export V=1 > > # On multi-guest PPA hosts, the per-guest overlay sometimes gets out of > -# sync, and we notice this by way of a corrupted .lp-sbuildrc. We aren't > going > +# sync, and we notice this by way of a corrupted .sbuildrc. We aren't going > # to be able to build anything in this situation, so immediately return > # BUILDERFAIL. > -if ! perl -c "$HOME/.lp-sbuildrc" >/dev/null 2>&1; then > - echo "$HOME/.lp-sbuildrc is corrupt; builder needs repair work" 2>&1 > +if ! perl -c "$HOME/.sbuildrc" >/dev/null 2>&1; then > + echo "$HOME/.sbuildrc is corrupt; builder needs repair work" 2>&1 > exit 4 > fi > > -SBUILD=/usr/share/launchpad-buildd/slavebin/sbuild > BUILDID=$1 > ARCHITECTURETAG=$2 > SUITE=$3 > @@ -59,16 +62,22 @@ > shift 3 > > ACTUAL_NR_PROCESSORS=$(grep -c ^processor /proc/cpuinfo | sed 's/^0$/1/') > -export NR_PROCESSORS=$ACTUAL_NR_PROCESSORS > +NR_PROCESSORS=$ACTUAL_NR_PROCESSORS > > echo "Initiating build $BUILDID with $NR_PROCESSORS jobs across > $ACTUAL_NR_PROCESSORS processor cores." > > -if [ $NR_PROCESSORS -lt 2 ]; then > - unset NR_PROCESSORS > +if [ $NR_PROCESSORS -gt 1 ]; then > + export DEB_BUILD_OPTIONS=parallel=$NR_PROCESSORS > fi > > cd "$HOME/build-$BUILDID" > > +# sbuild tries to do this itself, but can end up trying to mkdir in > +# /build too early. > +getent group sbuild | sudo tee -a chroot-autobuild/etc/group > /dev/null || > exit 2 > +getent passwd sbuild | sudo tee -a chroot-autobuild/etc/passwd > /dev/null > || exit 2 > +sudo chown sbuild:sbuild chroot-autobuild/build || exit 2 > + > hostarch=$(dpkg --print-architecture) > > UNAME26="" > @@ -92,7 +101,7 @@ > esac > > echo "Kernel reported to sbuild: $($LINUX32 $UNAME26 uname -rvm)" > -SBUILD="$LINUX32 $UNAME26 $SBUILD" > +SBUILD="$LINUX32 $UNAME26 sbuild" > > case $SUITE in > warty*|hoary*|breezy*|dapper*|edgy*|feisty*|gutsy*|hardy*|karmic*) > @@ -101,31 +110,4 @@ > esac > > $SBUILD "$@" | > /usr/share/launchpad-buildd/slavebin/check-implicit-pointer-functions > --inline $WARN > -RET=$? > - > -# really successful returns > -[ $RET = 0 ] || exit $RET > - > -STATE=$(cat build-progress | awk '{print $2}') > -STEP=$(cat build-progress | awk '{print $3}') > - > -# If the build was successful; return 0 > -[ "$STATE" = "successful" ] && exit 0 > - > -# If we think it's a dep-wait problem, exit 1 > -[ "$STEP" = "install-deps" ] && exit 1 > - > -# Is this a state where auto-give-back should kick in; exit 2 > -[ "$STEP" = "find-dsc" ] && exit 2 > -[ "$STEP" = "fetch-src" ] && exit 2 > -[ "$STEP" = "unpack-check" ] && exit 2 > -[ "$STEP" = "check-space" ] && exit 2 > -[ "$STEP" = "install-deps-env" ] && exit 2 > - > -# Any other reason (which we'll treat as a build failure), exit 3 > -exit 3 > - > -# There is an exit code of "4" that means the builder itself is having > -# problems. Currently, we don't use it at all, except for the .lp-sbuildrc > -# check above. > -# exit 4 > +exit $? > > === removed file 'sbuild.conf' > --- sbuild.conf 2011-11-09 07:50:56 +0000 > +++ sbuild.conf 1970-01-01 00:00:00 +0000 > @@ -1,155 +0,0 @@ > -# > -# /etc/sbuild.conf: global sbuild configurations that are > -# supposed to be changed only by the sbuild author, not by the user. > -# Of course you're free to override values here in /etc/sbuild.conf.local > -# > -# commented out stuff are defaults > -# > -# $Id: sbuild.conf,v 1.54 2002/10/10 18:50:45 rnhodek Exp $ > -# > - > -# File with the source dependencies > -#$source_dependencies = "/etc/source-dependencies"; > - > -# Default distribution to build: > -#$default_distribution="unstable" > -#$default_distribution="" > - > -# Environment variables to set/override: > -%ENV_OVERRIDES = { > - 'LC_ALL' => 'C', > -}; > - > -# Directory for writing build logs to > -#$log_dir = "$HOME/logs"; > - > -# Name of a database for logging package build times (optional, no database > -# is written if empty) > -$avg_time_db = "/var/debbuild/avg-build-times"; > - > -# Name of a database for logging package space requirement (optional) > -$avg_space_db = "/var/debbuild/avg-build-space"; > - > -# Name for dir for source dependency lock files > -$srcdep_lock_dir = "/var/debbuild/srcdep-lock"; > - > -# When to purge the build directory afterwards; possible values are "never", > -# "successful", and "always" > -#$purge_build_directory="successful"; > - > -# PGP-related option to pass to dpkg-buildpackage. Usually neither .dsc > -# nor .changes files shall be signed automatically. > -#$pgp_options = "-us -uc"; > - > -# After that time (in minutes) of inactivity a build is terminated. Activity > -# is measured by output to the log file. > -$stalled_pkg_timeout = 150; > - > -# Some packages may exceed the general timeout (e.g. redirecting output to > -# a file) and need a different timeout. Below are some examples. > -#%individual_stalled_pkg_timeout = ( > -# smalleiffel => 300, > -# jade => 300, > -# atlas => 300, > -# glibc => 1000, > -# xfree86 => 1000, > -# 'gcc-3.3' => 300, > -# kwave => 600 > -#); > - > -# Binaries for which the access time is controlled if they're not listed as > -# source dependencies (note: /usr/bin is added if executable name doesn't > -# start with '/') > -%watches = ( > - # general utilities > - sharutils => [qw(uuencode uudecode)], > - emacs20 => ["emacs"], > - groff => ["groff"], > - bzip2 => [qw(bzip2 bunzip2 bzcat bz2cat)], > -# unfortunately, too much stuff uses the following, so there are much > -# false alarms :-( > -# perl => ["perl"], > -# diff => [qw(diff diff3 sdiff cmp)], > -# gzip => [qw(gzip gunzip zcat)], > - # development tools > - debhelper => [qw(dh_clean dh_testdir dh_testversion > dh_buildpackage)], > - debmake => ["debstd"], > - bison => ["bison"], > - flex => ["flex"], > - gettext => [qw(gettext msgfmt msgmerge xgettext > gettextize)], > - m4 => ["m4"], > - f2c => [qw(f2c fc)], > - g77 => ["g77"], > - libtool => [qw(/usr/share/aclocal/libtool.m4 > - > /usr/share/libtool/ltmain.sh)], > -# unfortunately, too much stuff uses the following in predefined autoconf > -# macros, but doesn't really need it. > -# automake => [qw(automake aclocal)], > -# autoconf => [qw(autoconf autoheader)], > - "python-dev" => [qw(python /usr/include/python/Python.h)], > - gperf => ["gperf"], > - rcs => [qw(ci co ident rcs rcsdiff rlog)], > - "netkit-rpc" => ["rpcgen"], > - # doc formatting stuff > - "sgml-tools" => ["sgmltools.v1"], > - "debiandoc-sgml" => [qw(debiandoc2html debiandoc2latex2e > debiandoc2texinfo > - debiandoc2text debiandoc2dvi > debiandoc2dvips > - debiandoc2info debiandoc2ps)], > - "jade" => ["jade"], > - "liburi-perl" => ["/usr/lib/perl5/URI/URL.pm"], > - "tetex-bin" => [qw(tex latex dvips)], > - texi2html => ["texi2html"], > - latex2html => ["latex2html"], > - # special stuff > - "apache-dev" => ["apxs"], > - > - # test for X libs > - "xlibs-dev" => [qw(/usr/X11R6/lib/libX11.a > /usr/X11R6/lib/libX11.so /usr/X11R6/lib/libICE.a /usr/X11R6/lib/libICE.so > /usr/X11R6/lib/libXp.a /usr/X11R6/lib/libXp.so)] > -); > - > -# Ignore watches on the following packages if the package doesn't have its > own > -# build dependencies in the .dsc > -@ignore_watches_no_build_deps = qw(); > - > -# If a source dependency is an alternative that is provided by more than one > -# package, this list can select which one will be installed (if nothing is > -# defined, a random provider will be used) > -%alternatives = ( > - "automaken" => "automake1.9", > - "info-browser" => "info", > - "httpd" => "apache2-mpm-worker", > - "postscript-viewer" => "gs-esp", > - "postscript-preview" => "psutils", > - "www-browser" => "lynx", > - "awk" => "gawk", > - "c-shell" => "tcsh", > - "wordlist" => "wbritish", > - "tclsh" => "tcl8.4", > - "wish" => "tk8.4", > - "c-compiler" => "gcc", > - "fortran77-compiler" => "g77", > - "java-compiler" => "gcj", > - "libc-dev" => "libc6-dev", > - "libgl-dev" => "libgl1-mesa-dev", > - "libglu-dev" => "libglu1-mesa-dev", > - "libncurses-dev" => "libncurses5-dev", > - "libreadline-dev" => "libreadline5-dev", > - "libz-dev" => "zlib1g-dev", > - "emacsen" => "emacs21", > - "mail-transport-agent" => "postfix", > - "mail-reader" => "mailx", > - "news-transport-system" => "inn", > - "news-reader" => "nn", # universe > - "pgp" => "pgp-i", > - "xserver" => "xserver-xorg", > - "libpng-dev" => "libpng12-dev", > - "mysql-dev" => "libmysqlclient-dev", > - "giflib-dev" => "libungif4-dev", > - "freetype2-dev" => "libttf-dev" > -); > - > -# read local config file > -# require '/etc/sbuild.conf.local'; > - > -# don't remove this, Perl needs it: > -1; > > === modified file 'sbuildrc' > --- sbuildrc 2014-07-10 10:20:31 +0000 > +++ sbuildrc 2015-05-11 11:00:44 +0000 > @@ -1,34 +1,20 @@ > # Mail address where logs are sent to (mandatory, no default!) > -$mailto = "[email protected]"; > - > -$srcdep_lock_dir = "/home/buildd/"; > - > -%mailto = ( > -); > - > -$arch="@ARCHTAG@"; > +$mailto = "buildd-maint\@canonical.com"; > > # Maintainer name to use in .changes files (mandatory, no default!) > -$fqdn=`hostname --fqdn`; > +my $fqdn=`hostname --fqdn`; > chomp $fqdn; > -$maintainer_name="Ubuntu Build Daemon <buildd\@$fqdn>"; > - > -# When to purge the build directory afterwards; possible values are > -# "never", "successful", and "always" > - $purge_build_directory="always"; > -#$purge_build_directory="successful"; > - > -# Hack a "frozen" into the Distribution: line if compiling for frozen > -#$hack_changes_for_frozen = 1; > +$maintainer_name="Launchpad Build Daemon <buildd\@$fqdn>"; > + > +# launchpad-buildd does this before sbuild. > +$apt_update = 0; > +$apt_distupgrade = 0; > +$apt_allow_unauthenticated = 1; > > # After that time (in minutes) of inactivity a build is terminated. > # Activity > # is measured by output to the log file. > $stalled_pkg_timeout = 150; > > -# Some packages may exceed the general timeout (e.g. redirecting output to > -# a file) and need a different timeout. Below are some examples. > -#%individual_stalled_pkg_timeout = ( > -# ivtools => 600, > -# smalleiffel => 600 > -#); > +$chroot_mode="sudo"; > +$sbuild_mode="buildd"; > > === modified file 'template-buildd-slave.conf' > --- template-buildd-slave.conf 2015-05-11 11:00:44 +0000 > +++ template-buildd-slave.conf 2015-05-11 11:00:44 +0000 > @@ -10,8 +10,5 @@ > ntphost = ntp.buildd > sharepath = /usr/share/launchpad-buildd > > -[binarypackagemanager] > -sbuildargs = --nolog --batch > - > [translationtemplatesmanager] > resultarchive = translation-templates.tar.gz > -- https://code.launchpad.net/~wgrant/launchpad-buildd/system-sbuild/+merge/258751 Your team Launchpad code reviewers is subscribed to branch lp:launchpad-buildd. _______________________________________________ Mailing list: https://launchpad.net/~launchpad-reviewers Post to : [email protected] Unsubscribe : https://launchpad.net/~launchpad-reviewers More help : https://help.launchpad.net/ListHelp

