diff -Nru sbuild-0.67.0/bin/sbuild sbuild-0.69.0/bin/sbuild --- sbuild-0.67.0/bin/sbuild 2015-12-26 10:32:21.684607753 +0000 +++ sbuild-0.69.0/bin/sbuild 2016-04-28 05:04:00.686602490 +0000 @@ -165,6 +165,7 @@ # reported to the admin as failure: exit 1; } + debug("Error main(): $@") if $@; exit 1; } diff -Nru sbuild-0.67.0/bin/sbuild-adduser sbuild-0.69.0/bin/sbuild-adduser --- sbuild-0.67.0/bin/sbuild-adduser 2015-10-08 06:19:30.644049662 +0000 +++ sbuild-0.69.0/bin/sbuild-adduser 2016-05-02 17:26:38.474086495 +0000 @@ -41,7 +41,7 @@ my $user = getpwnam($_); if (defined $user) { - $status += system("/usr/sbin/adduser", "$_", "sbuild"); + $status += system(qw(/usr/sbin/adduser --), $_, 'sbuild'); } else { print STDERR "W: User \"$_\" does not exist\n"; $status++; diff -Nru sbuild-0.67.0/bin/sbuild-createchroot sbuild-0.69.0/bin/sbuild-createchroot --- sbuild-0.67.0/bin/sbuild-createchroot 2015-12-26 10:32:21.548607329 +0000 +++ sbuild-0.69.0/bin/sbuild-createchroot 2016-05-02 17:26:38.474086495 +0000 @@ -148,6 +148,7 @@ use Sbuild::ChrootRoot; use Sbuild::Sysconfig; use Sbuild::Conf qw(); +use File::Basename qw(dirname); use File::Path qw(mkpath rmtree); use File::Temp qw(tempfile); use File::Copy; @@ -210,7 +211,7 @@ push @args, "--components=" . $conf->get('COMPONENTS') if $conf->get('COMPONENTS'); push @args, "--keyring=" . $conf->get('KEYRING') if $conf->get('KEYRING'); -push @args, "--no-check-gpg" if $conf->get('KEYRING') eq ""; +push @args, "--no-check-gpg" if defined $conf->get('KEYRING') && $conf->get('KEYRING') eq ""; push @args, $conf->get('RESOLVE_DEPS') ? "--resolve-deps" : "--no-resolve-deps"; push @args, "$suite", "$target", "$mirror"; @@ -255,9 +256,10 @@ close POLICY_RC_D or die "Can't close $policy_rc_d"; -!system("chown", "root:", "$policy_rc_d") +my (undef, undef, $uid, undef) = getpwnam('root'); +!chown($uid, -1, $policy_rc_d) or die "E: Failed to set root: ownership on $policy_rc_d"; -!system("chmod", "0775", "$policy_rc_d") +!chmod(0775, $policy_rc_d) or die "E: Failed to set 0755 permissions on $policy_rc_d"; # Display /usr/sbin/policy-rc.d. @@ -306,10 +308,22 @@ profile=sbuild EOF } else { + # Determine whether system has overlayfs capability + my $uniontype = "union-type=none"; + if (lc("$^O") =~ /linux/) { + system(qw(/sbin/modprobe overlay)); + if (open(FILE, "/proc/filesystems")) { + if (grep {/\soverlay$/} ) { + $uniontype = "union-type=overlay"; + } + close(FILE); + } + } + $config_entry = <<"EOF"; [$chrootname] type=directory -union-type=overlay +$uniontype description=Debian $suite/$arch autobuilder directory=$target groups=root,sbuild @@ -442,6 +456,7 @@ system(@program_list) == 0 or die "Could not create chroot tarball: $?\n"; + makedir(dirname($conf->get('MAKE_SBUILD_TARBALL')), 0755); move("$tmpfile", $conf->get('MAKE_SBUILD_TARBALL')); chmod 0644, $conf->get('MAKE_SBUILD_TARBALL'); if (! $conf->get('KEEP_SBUILD_CHROOT_DIR')) { diff -Nru sbuild-0.67.0/bin/sbuild-debuild sbuild-0.69.0/bin/sbuild-debuild --- sbuild-0.67.0/bin/sbuild-debuild 2015-08-21 07:54:09.636952246 +0000 +++ sbuild-0.69.0/bin/sbuild-debuild 2016-05-02 17:26:38.478086496 +0000 @@ -362,7 +362,7 @@ if ((!$conf->get('NO_LINTIAN')) && (-x '/usr/bin/lintian')) { print "Running lintian.\n"; - system('/usr/bin/lintian', @{$conf->get('LINTIAN_OPTS')}, $bin_changes); + system('/usr/bin/lintian', @{$conf->get('LINTIAN_OPTS')}, '--', $bin_changes); if (($? >> 8) != 0) { print "Running lintian failed: $?"; chdir($currentdir); diff -Nru sbuild-0.67.0/ChangeLog sbuild-0.69.0/ChangeLog --- sbuild-0.67.0/ChangeLog 2015-12-26 13:36:24.345760221 +0000 +++ sbuild-0.69.0/ChangeLog 2016-05-08 12:14:54.886819330 +0000 @@ -1,3 +1,565 @@ +commit d4c3cc43b4d8d169f4fec6dac560a63c9c8f6640 +Author: Johannes 'josch' Schauer +Date: Sun May 8 11:01:42 2016 +0200 + + Bump version to 0.69.0 + +commit 6b64cd824c95d0634ef6c56af5a8487639f526ca +Author: Johannes 'josch' Schauer +Date: Sun May 8 13:21:09 2016 +0200 + + lib/Sbuild/Build.pm: fetch_source_files(): apt-cache does not support pkg=version syntax + +commit eb54277e2e1ad087aaf4c0443ece88427021e22a +Author: Johannes 'josch' Schauer +Date: Sun May 8 10:37:21 2016 +0200 + + lib/Sbuild/Conf.pm: Move configuration options that can be set via command line options from __INTERNAL to other groups and document changes in sbuild.1 + +commit 7ce5b665506278e0d00d837d5315215c7f871a59 +Author: Johannes 'josch' Schauer +Date: Sun May 8 08:58:15 2016 +0200 + + lib/Sbuild/Conf.pm: Refine the documentation for the ASPCUD_CRITERIA configuration option + +commit b317c3cbf0b927c99009e757ddc1887284c1dba3 +Author: Johannes 'josch' Schauer +Date: Sun May 8 08:57:40 2016 +0200 + + man/sbuild.1.in: Refine the documentation for the aspcud --build-dep-resolver option + +commit de4ecb6361d6c38a6d946502aa939933db2d4c06 +Author: Johannes 'josch' Schauer +Date: Sun May 8 08:57:08 2016 +0200 + + man/sbuild.1.in: document the --aspcud-criteria and --stats-dir options + +commit c19ed07dfc3fee9d29e318b5fc52b1592520a872 +Author: Johannes 'josch' Schauer +Date: Sun May 8 08:17:49 2016 +0200 + + Reference command line options in sbuild.conf.5 and configuration values in sbuild.1 + +commit 5380d29981487ca558759bf5377f9dfc8c0c6170 +Author: Johannes 'josch' Schauer +Date: Sun May 8 08:01:28 2016 +0200 + + lib/Sbuild/Conf.pm: move ADT_VIRT_SERVER from group __INTERNAL to Programs + +commit b45020adfb85ca5487295a3bbd4edce3257ddcc4 +Author: Paul Wise +Date: Mon May 2 17:39:13 2016 +0800 + + Improve sbuild's use of the perl system() function. + + Replace with perl-native functions where possible. + + Avoid shell meta-character injection where possible. + + Avoid extra forks due to shell where possible. + + Avoid manually running shell where possible. + + Avoid option injection where possible. + +commit 1cf828b179400227000cbd883c35b9ce964e589e +Author: Johannes 'josch' Schauer +Date: Sun May 1 21:12:29 2016 +0200 + + man/sbuild.1.in: Extend documentation of --*-opt and --*-opts options + +commit a8ba7bebf8f36da99d5263cc57327290d8959f93 +Author: Johannes 'josch' Schauer +Date: Sat Apr 30 08:50:15 2016 +0200 + + Add --adt-virt-server-opts option for convenience + +commit 1f57fb1b42efb21b9b8e3f708f247f363c2e7391 +Author: Johannes 'josch' Schauer +Date: Sat Apr 30 08:36:58 2016 +0200 + + Move the shellescape function to the Sbuild module and use it to escape the directory string in the adt backend + +commit 6f432bde9c72d564a2ef0dfe62f8c3e4bec08e81 +Author: Johannes 'josch' Schauer +Date: Sat Apr 30 08:35:55 2016 +0200 + + man/sbuild.1.in: Improve documentation for adt-virt options + +commit 21a28c2a19b5b47c8847aea25ef4ec34f406d0b9 +Author: Johannes 'josch' Schauer +Date: Sun Jan 3 14:33:35 2016 +0100 + + make different command line options modifying the same configuration parameter incompatible with each other and remove --arch-all-only in the process (its behaviour can be replicated by using --arch-all --no-arch-any) + +commit c6b228e443bbdc761b9da46524ba1c8aa99df6e2 +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 14:41:51 2016 +0100 + + Add new sbuild backend: adt + + - New value for CHROOT_MODE config option: adt. + - Added lib/Sbuild/ChrootADT.pm and lib/Sbuild/ChrootInfoADT.pm. + - Added new configuration variables: + - ADT_VIRT_SERVER to select the adt-virt-* backend + - ADT_VIRT_SERVER_OPTIONS to pass custom options to the backend + - Add command line options: + - --chroot-mode to select between schroot, sudo and adt on the + command line (controls CHROOT_MODE) + - --adt-virt-server which controls (ADT_VIRT_SERVER) + - --adt-virt-server-opt which controls (ADT_VIRT_SERVER_OPTIONS) + +commit 668e86dbfe5d14defe54926cf58dec2dc39d876f +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 14:04:33 2016 +0100 + + Decouple chroot from host in terms of filesystem access (closes: #798835) + + This is useful to allow sbuild backends where the chroot filesystem + cannot be directly accessed by the host, either because the host has no + permission to access the chroot or because the chroot is inside a + virtual machine, a container or on a remote system accessed via ssh. + This in turn allows backends like adt-virt-qemu, adt-virt-ssh, + adt-virt-lxc or backends based on Linux user namespaces to be added. + + In course of the decoupling all pieces of code where: + + - the test operators (-d, -f, -s) were used + - perl modules like File::Temp or File::Copy were used + - perl functions like mkdir, open, close, opendir, readdir were used + - external commands pointing to paths inside the chroot were used like + apt-ftparchive + + had to be replaced by invocations of a program that knows how to execute + processes inside the chroot. + + To make this easier, many new convenience functions have been added to + lib/Sbuild/Chroot.pm like: + + - mktemp + - copy_to_chroot + - copy_from_chroot + - get_read_file_handle + - read_file + - get_write_file_handle + - read_command + - write_file + - write_command + - rename + - mkdir + - test_directory + - test_regular_file + - test_regular_file_readable + - test_symlink + - unlink + - chmod + - chown + + Since this also means that nothing in Build.pm or ResolverBase.pm needs + to know about the chroot path anymore (because all modifications of the + chroot content have to go through Chroot.pm) the function + strip_chroot_path is not necessary anymore and with it the 'Location' + and 'Chroot Dir' configuration variables are only very rarely used. + + Another consequence is, that since it cannot be relied upon anymore that + the root filesystem of the chroot backend is mounted on the machine that + runs sbuild, that the %SBUILD_CHROOT_DIR percentage escape for external + commands is not useful anymore for all backends. Thus, this escape is + now deprecated. Instead, the percentage escape %SBUILD_CHROOT_EXEC + should be used in external commands. With that escape, the same external + command script can then be used irrespective of which chroot backend is + used. + + Also, with this commit, we create the Packages, Sources and Release file + inside the chroot. We cannot use apt-ftparchive as this is not + available inside the chroot. Apt-ftparchive outside the chroot might + not have access to the files inside the chroot for reasons explained + above. The only alternative would've been to set up the archive outside + the chroot using apt-ftparchive and to then copy Packages, Sources and + Release into the chroot. We do not do this to avoid copying files from + and to the chroot. At the same time doing it like this has the + advantage to have less dependencies of sbuild itself (no apt-ftparchive + needed). The disadvantage of doing it this way is that we now have to + maintain our own code creating the Release file which might break in the + future. + +commit 49dd7ee4bc28fba899fc2b178c2f64f0c136ca59 +Author: Luca Falavigna +Date: Thu Apr 28 06:48:58 2016 +0200 + + bin/sbuild-createchroot: check for overlayfs support (closes: #813360) + +commit 8e91ef0b7e1c99ab2cc354a09235f017e297dc2b +Author: Johannes 'josch' Schauer +Date: Fri Apr 22 13:10:04 2016 +0200 + + add --aspcud-criteria command line option and ASPCUD_CRITERIA configuration option to customize the optimization criteria of the aspcud resolver + +commit 05b39349632635177284bf7c5ed6b7678078aaeb +Author: Johannes 'josch' Schauer +Date: Wed Apr 20 13:07:12 2016 +0200 + + lib/Sbuild/Conf.pm: clarify aspcud resolver help message and fix typo (thanks cbmuser) + +commit 80bc910adb63e349a5c1c34dfacc7082278e77d0 +Author: Johannes 'josch' Schauer +Date: Sun Apr 3 07:53:44 2016 +0200 + + lib/Sbuild/ResolverBase.pm: stop apt from downloading translations + +commit 5cfa09c51a9167c8748330ba40206ec468fc8b47 +Author: Colin Watson +Date: Thu Apr 7 12:45:41 2016 +0100 + + Sbuild::ResolverBase: sign dummy archive with SHA-512 + + Recent versions of apt complain about gpg's default of SHA-1. + +commit 063ce0de64d2e66d597cf548c3145be536eaf3da +Author: Johannes 'josch' Schauer +Date: Sun Apr 3 06:27:35 2016 +0200 + + Add cron script to periodically update sbuild chroots (closes: #776438) + +commit f8efb79c6b70912af19e1e3507e721dd9630606a +Author: Adam Conrad +Date: Mon Mar 28 03:08:23 2016 -0600 + + lib/Sbuild/Build.pm: Fix "W: Stripped single quote from command for security" (closes: #816493) + +commit 60960c41210b5d01cf50bd320f4885a27c4c0fc8 +Author: Adam Conrad +Date: Mon Mar 28 02:17:57 2016 -0600 + + lib/Sbuild/ResolverBase.pm: Fix quoting in apt.conf to conform to spec. + +commit decfd14c80d633c19fdcd3846481f505a111d14d +Author: Johannes 'josch' Schauer +Date: Thu Feb 18 21:43:08 2016 +0100 + + lib/Sbuild/ResolverBase.pm: add code comment further explaining the reason behind commit e2d63ebc + +commit e2d63ebc20c8d2ef5d96db83828087505928895f +Author: Colin Watson +Date: Thu Feb 18 14:22:15 2016 +0000 + + Sbuild::ResolverBase: use copy: for dummy archive + + We used to use file: URIs for sbuild's dummy archive, but recent + versions of apt put symlinks in /var/lib/apt/lists/ if we do that, which + means that those symlinks become broken as soon as we remove the dummy + archive. sbuild itself is OK with this, but launchpad-buildd tries to + read /var/lib/apt/lists/*_Packages in order to do dep-wait analysis + after failures, and that fails if there are broken symlinks there. It's + easy enough to avoid this problem by using copy: URIs instead, so let's + do that. + +commit e18205251843f916f5593bf52436104b29346139 +Author: Johannes 'josch' Schauer +Date: Tue Jan 26 09:04:47 2016 +0100 + + lib/Sbuild/Build.pm: fix some more uses of the package version if build fails early + +commit cdf04b4e2d78151eb29c468ffc37ec1da26b462f +Author: Johannes 'josch' Schauer +Date: Tue Jan 26 08:58:14 2016 +0100 + + lib/Sbuild/Build.pm: and keys() being used on a reference is experimental - so dereference it first + +commit 5fd41dfc734bc7103b99159a90529e0410e1a92a +Author: Johannes 'josch' Schauer +Date: Tue Jan 26 08:52:49 2016 +0100 + + lib/Sbuild/Build.pm: turns out empty hashes evaluate to true in Perl + +commit cdf124142b70df446af938a5d19fc13cc01d36fa +Author: Johannes 'josch' Schauer +Date: Tue Jan 26 08:30:26 2016 +0100 + + Allow to build by only passing source package name without version (closes: #693928) + + The packagename_version format was a handy way to fulfill the assumption + sbuild makes that the source package version is available right from the + start. Sbuild then uses the version for things like log filtering, + status output, external command percentage escapes or the build log file + name. + + This patch makes it optional that the version is known from the start. + In case it is not known it will: + + - not print version information in the build log + - not let external command percentage escapes be defined + - use only the package name for the build log filename + - set up log filtering much later when the version is definitely known + + To not break existing setups, all the old behavior is kept if the + version is known from the start. To distinguish the version being known + from not being known, the user-supplied argument is checked for the + presence of an underscore. If an underscore exists, then either a dsc is + passed or the pkgname_version format was used and in both cases, the old + behavior can be executed. If no underscore can be found, then it is a + bare package name and the different behavior explained above will kick + in. + + The man page has been adapted to document the new behavior. + + While I was at it, I also rewrote the code downloading the source + package: + + - The old code triggered an "apt-get update" if the source package + could not be found. This is not necessary because the source package + is fetched after the chroot is updated. Furthermore it allows to + "apt-get update" to be run without eventual failures be caught by the + respective external command hooks. Lastly, this would ignore the + --no-apt-update command line option. + + - "apt-cache showsrc" was run without --only-source + + - The "apt-cache showsrc" output was parsed using Perl regexes. + Dpkg::Index is used now. + + - The Files field is now parsed using Dpkg::Checksums instead of using + perl regexes. + + - the @fetched array was only filled but never used by anybody + +commit 29a4c42c5190bd83dce4ebc600124c0227d0b453 +Author: Johannes 'josch' Schauer +Date: Mon Jan 25 16:22:54 2016 +0100 + + lib/Sbuild/ResolverBase.pm: do not remove architectures when cloned chroot is in use (closes: #811558) + +commit 4df31d9221ef86ba9b83c9cd8f2ae2c231a92dbd +Author: Johannes 'josch' Schauer +Date: Mon Jan 25 15:49:31 2016 +0100 + + lib/Sbuild/ResolverBase.pm: improve debugging output when adding architectures + +commit 7c94edf16fdfd4ec88122720873a4507b930d776 +Author: Johannes 'josch' Schauer +Date: Mon Jan 25 15:47:57 2016 +0100 + + lib/Sbuild/Build.pm: use log_error() for error messages + +commit 6bca9627085655f4877465e89ef42109ccb87cc0 +Author: Johannes 'josch' Schauer +Date: Mon Jan 25 15:36:52 2016 +0100 + + lib/Sbuild/Build.pm: issue a warning if it was requested not to apt update but a foreign arch was added + +commit 495228671184a4e46ffc1c9147e4157cf2c29876 +Author: Dima Kogan +Date: Fri Dec 25 18:01:08 2015 +0100 + + added another -failed external command: chroot-update-failed (closes: #803505) + +commit 75d0b5bc9593a0a8917b0376611914d4b92566a8 +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 10:10:23 2016 +0100 + + Bump version to 0.68.0 + +commit 0928b3b77e197eeb178f71fd558655eac7120b78 +Author: Johannes 'josch' Schauer +Date: Sun Jan 3 12:17:23 2016 +0100 + + Add documentation related to generated build artifacts (closes: #782553) + + - deprecated --arch-all-only + - throw an error if no artifacts are to be created + - add references to the command line options to config variables + BUILD_ARCH_AND, BUILD_ARCH_ALL and BUILD_SOURCE + - add a new section in sbuild man page explaining the + --arch-all/no--arch-all, --arch-any/--no-arch-any and + --source/--no-source options + +commit d6d2db3610fc4d63457dfe223e4a74f23b975e7a +Author: Johannes 'josch' Schauer +Date: Sun Jan 3 11:06:39 2016 +0100 + + Extend explanation of --source and --no-source options (closes: #700317) + +commit ac866706fbb633478140ddd175a9c04820eeb596 +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 09:24:15 2016 +0100 + + lib/Sbuild/ChrootInfoSchroot.pm: check if get_info_from_stream() was successful and don't check if closing the pipe was successful if not (closes: #811041) + +commit 36ca4ba6b6cb1a6064ddfc79f28ed1c6d0b2c38e +Author: Martin Michlmayr +Date: Thu Jan 14 21:57:25 2016 -0800 + + Create directory where tarball is stored (closes: #811040) + + At the moment, sbuild-createchroot silently fails when the directory + where the tarball is to be created doesn't exist. Avoid this by + creating the directory. + +commit 0a55459f98ededc5ba7c65bab49ef2f9fd8264e1 +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 09:08:23 2016 +0100 + + Some error message, status message and return code cleanup + + - some new log subsections + - update_archive() now returns 0 on failure and 1 on success + - check_architectures() doesn't throw an exception anymore but just + returns 0 + - the resolver show an appropriate error message in the log if setting + up the apt archive or updating it fails, respectively + - make some error message log_error() instead of log() + +commit 98f9e0225aac0dec3d8beea3d84364c7072e9c43 +Author: Johannes 'josch' Schauer +Date: Fri Jan 15 09:00:23 2016 +0100 + + Do architecture check after build-essential is installed (closes: #700317) + + The architecture check is done inside the chroot to not make the + architecture check dependent on a possibly outdated libdpkg-perl on the + host (useful for porters of new architectures). But this means that + libdpkg-perl has to be installed inside the chroot. Thus, the + architecture check can only be done after build-essential has been + installed. + +commit e227c8f3e10edd78bc71350380f559c481634b79 +Author: Johannes 'josch' Schauer +Date: Wed Jan 6 10:10:39 2016 +0100 + + When cross compiling, install dummy binary package instead of using 'apt-get build-dep' (closes: #809730) + + Three decisions are to be considered: + + a) does sbuild need to use an internal dummy repository? + + b) will sbuild use 'apt-get install' or 'apt-get build-dep' or both? + + c) can advanced apt features like 'apt-get build-dep foo.dsc' not be + used? + + Maintaining an internal dummy repository instead of offloading all the + complexity to apt results in complex code required to reside in sbuild + itself. The justification is as follows: + + Moving complexity to apt makes sbuild depend on apt *inside* the chroot. + This can have negative effects if building packages in a very old chroot + (like old-old-stable). Mangling build dependencies allows us to take + care of new features introduced in the archive (like the :native + qualifier or build profiles) while the apt inside the chroot does not + need to understand them. This means that sbuild is able to build for + example a build profile enabled binary package on Squeeze or Wheezy + because a newer libdpkg-perl from the host system takes care of mangling + the build dependencies correctly. This is for example useful for + backports. Apt 1.1 has the feature of being able to call "apt-get + build-dep foo.dsc" but this feature cannot be used by sbuild until that + apt version is in old-old-stable or otherwise sbuild would not be able + to use old chroots. We cannot control the apt that is used inside the + chroot but we can control sbuild by doing new uploads to unstable. So by + using sbuild to do the heavy lifting we can make sure that new + dependency features (like :native and build profiles) can used even with + chroots with an apt version that doesn't support them. + + Package dependency mangling is required. It is necessary to filter build + dependency alternatives as well as support for injecting additional + build dependencies via --add-depends and other command line options. So + the complexity of using Dpkg::Dep::deps_parse to parse the build + dependencies cannot go away. A nice side effect is that as explained + above we can take care of newly introduced dependency features so that + apt inside the chroot doesn't have to. One disadvantage of maintaining + an internal dummy repository used to be that it requires keys to be + generated (which would be too slow on some virtualized machines or + containers) but this has been solved with commit aea9a4d9 or closing of + bug #801798 using apt-get's feature of [trusted=yes] in sources.list, + making key generation optional and only required for chroots of squeeze + or older. + + Building dummy binary packages has been tested for a long time and seems + to be a reliable way to install build dependencies. Unless there is a + shortcoming of this method, there is no reason to switch to "apt-get + build-dep" to install dependencies from a mangled dummy Sources file. + If the "apt-get build-dep" method was to be introduced it would have had + to be tested with all apt versions down to old-old-stable. The risk of + breaking things is too great for little gain. The only gain would be the + decreased complexity from not needing to build a dummy binary package. + But I do not think this gain is worth the risk of breaking working + setups. + + Maintaining both code paths "apt-get install" as well as "apt-get + build-dep" would be too complex because we need to correctly mangle + build dependencies for both. Thus we unify build dependency installation + using only one method. As explained above we are using the "apt-get + install" method to install a dummy binary package because this method + has been tried and tested for a long time. + + In this commit we switch the method of installing cross build + dependencies from using "apt-get build-dep" to installing a dummy binary + package of the host architecture as it is used for the native case + already. Using "apt-get build-dep" to install cross build dependencies + should not be necessary because cross build dependency resolution should + not be different from cross architecture binary dependency resolution as + far as multiarch is concerned. Build-Depends specific constructs are + taken care of either by Dpkg::Dep::deps_parse (architecture qualifiers, + build profile restriction lists) or by rewriting the ':native' qualifier + to the correct architecture in course of commit d4c137190 or fixing of + bug #777216. + + In summary, answering the initial questions: + + a) we need to keep using an internal dummy repository because we need + to mangle dependencies. + + b) sbuild will continue creating a dummy binary package instead of + creating a Sources file because that has been tried and tested with apt + versions down to old-old-stable. Only that method will be maintained + because having support for "apt-get install" as well as "apt-get + build-dep" would add complexity with no reason. + + c) apt features can only be relied upon once they are part of + old-old-stable + +commit 1f4b6462610468b6c61eae5608a8ae0c2c9dbac1 +Author: Johannes 'josch' Schauer +Date: Sun Jan 3 14:31:58 2016 +0100 + + man/sbuild.1.in: clarify options that can be specified multiple times and how argument options are split by whitespace + +commit a5489dadb1fe07824290571a071d91afa31abbf7 +Author: Johannes 'josch' Schauer +Date: Wed Dec 30 09:47:18 2015 +0100 + + bin/sbuild-createchroot: check for defined-ness first before using eq + +commit 1a54381f6dbaa6e92aa0cd6027df30b7ca11b20a +Author: Aurelien Jarno +Date: Sat Jan 2 17:27:23 2016 +0100 + + lib/Buildd/Daemon.pm: remove existing .upload file when moving a .changes + + Signed-off-by: Aurelien Jarno + +commit fb6b27d04b07e03739e9e35047b0d7cc6f6ed4a6 +Author: Jakub Wilk +Date: Tue Dec 29 16:22:16 2015 +0100 + + lib/Sbuild/Build.pm: fix typo s/forein/foreign/ + +commit 7ebdf89ff4bf040d8d300ed2847501c855b45145 +Author: Johannes 'josch' Schauer +Date: Sun Dec 27 09:48:14 2015 +0100 + + sbuild-update: Add apt options that make sure that packages that are only recommended or suggested by still installed packages are also autoremoved. + +commit 2deb0b121d8ca5dffcdf3b50cefd4a59bbc4554d +Author: Niko Tyni +Date: Mon Dec 28 00:30:49 2015 +0200 + + Fix quoting when checking architectures (closes: #809175) + + The variables got interpolated into $command without any quoting, + essentially becoming barewords. + + Regression introduced in 9162dd0d727facb2ebab0ab7008603c5fa8c36a1 + commit 12582197079aaed20c5bac626333b4d328e45be5 Author: Johannes 'josch' Schauer Date: Sat Dec 26 14:32:59 2015 +0100 diff -Nru sbuild-0.67.0/configure sbuild-0.69.0/configure --- sbuild-0.67.0/configure 2015-12-26 13:35:48.793713320 +0000 +++ sbuild-0.69.0/configure 2016-05-08 12:14:35.354784280 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for sbuild 0.67.0. +# Generated by GNU Autoconf 2.69 for sbuild 0.69.0. # # Report bugs to . # @@ -597,8 +597,8 @@ # Identity of this package. PACKAGE_NAME='sbuild' PACKAGE_TARNAME='sbuild' -PACKAGE_VERSION='0.67.0' -PACKAGE_STRING='sbuild 0.67.0' +PACKAGE_VERSION='0.69.0' +PACKAGE_STRING='sbuild 0.69.0' PACKAGE_BUGREPORT='buildd-tools-devel@lists.alioth.debian.org' PACKAGE_URL='' @@ -1278,7 +1278,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sbuild 0.67.0 to adapt to many kinds of systems. +\`configure' configures sbuild 0.69.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1348,7 +1348,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sbuild 0.67.0:";; + short | recursive ) echo "Configuration of sbuild 0.69.0:";; esac cat <<\_ACEOF @@ -1443,7 +1443,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sbuild configure 0.67.0 +sbuild configure 0.69.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1516,7 +1516,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sbuild $as_me 0.67.0, which was +It was created by sbuild $as_me 0.69.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2385,7 +2385,7 @@ # Define the identity of the package. PACKAGE='sbuild' - VERSION='0.67.0' + VERSION='0.69.0' cat >>confdefs.h <<_ACEOF @@ -2602,8 +2602,8 @@ fi AM_BACKSLASH='\' -RELEASE_DATE='26 Dec 2015' -RELEASE_DATE_S='1451084400' +RELEASE_DATE='08 May 2016' +RELEASE_DATE_S='1462658400' cat >>confdefs.h <<_ACEOF #define RELEASE_DATE "$RELEASE_DATE_S" @@ -4323,7 +4323,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sbuild $as_me 0.67.0, which was +This file was extended by sbuild $as_me 0.69.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -4389,7 +4389,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sbuild config.status 0.67.0 +sbuild config.status 0.69.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru sbuild-0.67.0/debian/changelog sbuild-0.69.0/debian/changelog --- sbuild-0.67.0/debian/changelog 2016-04-19 13:52:52.000000000 +0000 +++ sbuild-0.69.0/debian/changelog 2016-07-01 08:28:37.000000000 +0000 @@ -1,3 +1,101 @@ +sbuild (0.69.0-2ubuntu1) yakkety; urgency=low + + * Merge from Debian unstable (LP: #1591674). Remaining changes: + - no-pkg-mangle-deps.patch: Set NO_PKG_MANGLE=1 when building dummy + packages, as pkgbinarymangler's dpkg-deb expects to be run from a source + package. + - Set APT::Sandbox::User=root when running apt-get source in the + build-procenv autopkgtest, to avoid stderr noise from current apt. + - Silence a couple of warnings from sbuild-createchroot which caused some + autopkgtest runs to fail. + - utf-8-by-default.patch: Switch to C.UTF-8 by default (LP: #1566590) + - abs-path-revert.patch: Revert upstream commit that breaks lp-buildd by + causing symlinks to files not ending in .dsc to no longer be buildable. + * Drop patches included/applied in Debian: apt-conf-quotes.patch, + copy-dummy-archive.patch, dummy-archive-sha512.patch, + fix-quoting-harder.patch + + -- Gianfranco Costamagna Sun, 12 Jun 2016 12:48:21 +0200 + +sbuild (0.69.0-2) unstable; urgency=medium + + * add patch 0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch + to make sbuild not print on stderr during sbuild-update unless it is an + error (closes: #823788) + * 0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch which + fixes error checking of chown and chmod calls in sbuild-createchroot + (closes: #823897) + + -- Johannes Schauer Thu, 12 May 2016 07:36:32 +0200 + +sbuild (0.69.0-1) unstable; urgency=medium + + * new upstream version + - Decouple chroot from host in terms of filesystem access to allow + chroot backends like qemu, ssh or lxc. Deprecate external command + percentage escape %SBUILD_CHROOT_DIR in favour of %SBUILD_CHROOT_EXEC. + - Experimental adt backend. Enable with --chroot-mode=adt. Choose the + virtualization server with --adt-virt-server and add options with + --adt-virt-server-opt. This allows sbuild to use qemu, ssh and lxc + chroots. + - Build packages without specifying a version. Earlier it was possible to + let sbuild "apt-get download" a dsc by specifying "package_version" as a + command line argument. The version part is not necessary anymore. No + manual version lookup by the user is required anymore. (closes: #693928) + - Disallow conflicting command line options, thus making command line + switches position independent and remove the deprecated --arch-all-only + option in the process. + - The aspcud resolver criteria is not hardcoded anymore but can be chosen + with --aspcud-criteria. The default criteria is -removed,-changed,-new. + To minimize the number of packages from experimental, use: + -count(solution,APT-Release:=/a=experimental/),-removed,-changed,-new + (closes: #821376) + - Apt doesn't download translations anymore. + - Dummy archive is now signed with SHA-512 + - Cron script etc/sbuild-update-all allows one to periodically update all + sbuild chroots. (closes: #776438) + - Add another --*-failed-commands external command: + --chroot-update-failed-commands (closes: #803505) + - Documentation of configuration options in sbuild.conf(5) and in + /etc/sbuild/sbuild.conf now reference related command line options from + sbuild(1). + - Documentation of command line options in sbuild(1) now references the + respective configuration options from sbuild.conf(5). + - Remove configuration options which can be set on the command line from + the __INTERNAL group, thus exposing them in sbuild.conf as well and + referencing them in sbuild(1). + - Replace single by double quotes in external command (closes: #816493) + - Parse "apt-cache showsrc" output using Dpkg::Index (closes: #818579) + - Fix permissions of temporary directories (closes: #798835) + - Fix signing of build results (closes: #817121) + - do not remove architectures when cloned chroot is in use + (closes: #811558) + - check for overlayfs support (closes: #813360) + + -- Johannes Schauer Sun, 08 May 2016 14:43:04 +0200 + +sbuild (0.68.0-1) unstable; urgency=medium + + * new upstream version + - Fix quoting when checking architectures (closes: #809175) + - bin/sbuild-createchroot: check for defined-ness first before using eq + (closes: #811042) + - When cross compiling, install dummy binary package instead of using + 'apt-get build-dep'. See upstream commit #e227c8f3 for an extensive + rationale. (closes: #809730) + - Do architecture check after build-essential is installed (closes: #700317) + - Create directory where tarball is stored (closes: #811040) + - lib/Sbuild/ChrootInfoSchroot.pm: check if get_info_from_stream() was + successful and don't check if closing the pipe was successful if not + (closes: #811041) + - Extend explanation of --source and --no-source options (closes: #700317) + - Add documentation related to generated build artifacts (closes: #782553) + - Deprecate command line option --arch-all-only in favour of --arch-all + --no-arch-any. This option will be removed in the next upstream release. + * drop patch fix-quoting.patch as it has been applied upstream + + -- Johannes Schauer Fri, 15 Jan 2016 10:18:53 +0100 + sbuild (0.67.0-2ubuntu7) xenial; urgency=medium * utf-8-by-default.patch: Switch to C.UTF-8 by default (LP: #1566590) diff -Nru sbuild-0.67.0/debian/patches/0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch sbuild-0.69.0/debian/patches/0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch --- sbuild-0.67.0/debian/patches/0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch 1970-01-01 00:00:00.000000000 +0000 +++ sbuild-0.69.0/debian/patches/0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch 2016-05-12 05:29:57.000000000 +0000 @@ -0,0 +1,29 @@ +From d3d2663b51fdd627155cee3b0fe8555ac81ddaf4 Mon Sep 17 00:00:00 2001 +From: Johannes 'josch' Schauer +Date: Wed, 11 May 2016 06:45:53 +0200 +Subject: [PATCH] bin/sbuild-createchroot: fix chown/chmod error checks + (closes: #823897) + +--- + bin/sbuild-createchroot | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/bin/sbuild-createchroot b/bin/sbuild-createchroot +index 6216371..efcfe04 100755 +--- a/bin/sbuild-createchroot ++++ b/bin/sbuild-createchroot +@@ -257,9 +257,9 @@ EOF + close POLICY_RC_D or die "Can't close $policy_rc_d"; + + my (undef, undef, $uid, undef) = getpwnam('root'); +-!chown($uid, -1, $policy_rc_d) ++chown($uid, -1, $policy_rc_d) == 1 + or die "E: Failed to set root: ownership on $policy_rc_d"; +-!chmod(0775, $policy_rc_d) ++chmod(0775, $policy_rc_d) == 1 + or die "E: Failed to set 0755 permissions on $policy_rc_d"; + + # Display /usr/sbin/policy-rc.d. +-- +2.5.1 + diff -Nru sbuild-0.67.0/debian/patches/0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch sbuild-0.69.0/debian/patches/0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch --- sbuild-0.67.0/debian/patches/0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch 1970-01-01 00:00:00.000000000 +0000 +++ sbuild-0.69.0/debian/patches/0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch 2016-05-12 05:29:40.000000000 +0000 @@ -0,0 +1,39 @@ +From dd66734ba7f24f41d72d5f465dd6fff02598087e Mon Sep 17 00:00:00 2001 +From: Johannes 'josch' Schauer +Date: Tue, 10 May 2016 07:36:38 +0200 +Subject: [PATCH] lib/Sbuild/ResolverBase.pm: do not produce non-error output + in architecture setup + +sbuild-update setups up the resolver but not the logger. Hence, all +messages from the resolver will plainly go to stderr. This should not +happen as stderr for sbuild-update should be empty unless there really +is an error. We thus demote the messages to debug level. (closes: #823788) +--- + lib/Sbuild/ResolverBase.pm | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/Sbuild/ResolverBase.pm b/lib/Sbuild/ResolverBase.pm +index b480cd2..86c48bf 100644 +--- a/lib/Sbuild/ResolverBase.pm ++++ b/lib/Sbuild/ResolverBase.pm +@@ -183,7 +183,7 @@ sub get_foreign_architectures { + + if (!$foreignarchs) + { +- $self->log("There are no foreign architectures configured\n"); ++ debug("There are no foreign architectures configured\n"); + return {}; + } + +@@ -252,7 +252,7 @@ sub cleanup_foreign_architectures { + my $session = $self->get('Session'); + + if (defined ($session->get('Session Purged')) && $session->get('Session Purged') == 1) { +- $self->log("Not removing foreign architectures: cloned chroot in use\n"); ++ debug("Not removing foreign architectures: cloned chroot in use\n"); + return; + } + +-- +2.5.1 + diff -Nru sbuild-0.67.0/debian/patches/abs-path-revert.patch sbuild-0.69.0/debian/patches/abs-path-revert.patch --- sbuild-0.67.0/debian/patches/abs-path-revert.patch 2016-01-21 10:46:07.000000000 +0000 +++ sbuild-0.69.0/debian/patches/abs-path-revert.patch 2016-07-01 08:28:37.000000000 +0000 @@ -1,4 +1,5 @@ Revert d15d5ea67b81cde811207ff6853b381c3ebe4b41 +Last-Update: 2016-06-28 --- x/bin/sbuild 2016-01-06 11:23:00.000000000 +0000 +++ x/bin/sbuild 2016-01-21 10:09:57.609600750 +0000 @@ -13,7 +14,7 @@ if (-d $jobname) { $jobname = create_source_package($jobname); if ($jobname eq '.') { -@@ -170,6 +166,7 @@ +@@ -171,6 +167,7 @@ sub create_source_package ($) { my $dsc = shift; diff -Nru sbuild-0.67.0/debian/patches/apt-conf-quotes.patch sbuild-0.69.0/debian/patches/apt-conf-quotes.patch --- sbuild-0.67.0/debian/patches/apt-conf-quotes.patch 2016-03-28 08:20:00.000000000 +0000 +++ sbuild-0.69.0/debian/patches/apt-conf-quotes.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -commit 60960c41210b5d01cf50bd320f4885a27c4c0fc8 -Author: Adam Conrad -Date: Mon Mar 28 02:17:57 2016 -0600 - - lib/Sbuild/ResolverBase.pm: Fix quoting in apt.conf to conform to spec. - -diff --git a/lib/Sbuild/ResolverBase.pm b/lib/Sbuild/ResolverBase.pm -index 5ffe848..093fd75 100644 ---- a/lib/Sbuild/ResolverBase.pm -+++ b/lib/Sbuild/ResolverBase.pm -@@ -94,9 +94,9 @@ sub setup { - DIR => $session->get('Location'), - UNLINK => 0) } ) { - if ($self->get_conf('APT_ALLOW_UNAUTHENTICATED')) { -- print $F "APT::Get::AllowUnauthenticated true;\n"; -+ print $F qq(APT::Get::AllowUnauthenticated "true";\n); - } -- print $F "APT::Install-Recommends false;\n"; -+ print $F qq(APT::Install-Recommends "false";\n); - - if ($self->get('Split')) { - print $F "Dir \"$chroot_dir\";\n"; diff -Nru sbuild-0.67.0/debian/patches/copy-dummy-archive.patch sbuild-0.69.0/debian/patches/copy-dummy-archive.patch --- sbuild-0.67.0/debian/patches/copy-dummy-archive.patch 2016-02-18 14:31:49.000000000 +0000 +++ sbuild-0.69.0/debian/patches/copy-dummy-archive.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -Description: Sbuild::ResolverBase: use copy: for dummy archive - We used to use file: URIs for sbuild's dummy archive, but recent versions - of apt put symlinks in /var/lib/apt/lists/ if we do that, which means that - those symlinks become broken as soon as we remove the dummy archive. - sbuild itself is OK with this, but launchpad-buildd tries to read - /var/lib/apt/lists/*_Packages in order to do dep-wait analysis after - failures, and that fails if there are broken symlinks there. It's easy - enough to avoid this problem by using copy: URIs instead, so let's do that. -Origin: upstream, https://anonscm.debian.org/cgit/buildd-tools/sbuild.git/commit/?id=e2d63ebc20c8d2ef5d96db83828087505928895f -Last-Update: 2016-02-18 - -Index: b/lib/Sbuild/ResolverBase.pm -=================================================================== ---- a/lib/Sbuild/ResolverBase.pm -+++ b/lib/Sbuild/ResolverBase.pm -@@ -1093,8 +1093,8 @@ - # Older apt from squeeze will still require keys to be generated as it - # ignores the trusted=yes. Older apt ignoring this is also why we can add - # this unconditionally. -- print $tmpfh 'deb [trusted=yes] file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; -- print $tmpfh 'deb-src [trusted=yes] file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; -+ print $tmpfh 'deb [trusted=yes] copy://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; -+ print $tmpfh 'deb-src [trusted=yes] copy://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; - - for my $repospec (@{$self->get_conf('EXTRA_REPOSITORIES')}) { - print $tmpfh "$repospec\n"; diff -Nru sbuild-0.67.0/debian/patches/do-not-install-debfoster-into-chroots.patch sbuild-0.69.0/debian/patches/do-not-install-debfoster-into-chroots.patch --- sbuild-0.67.0/debian/patches/do-not-install-debfoster-into-chroots.patch 2015-12-28 00:08:54.000000000 +0000 +++ sbuild-0.69.0/debian/patches/do-not-install-debfoster-into-chroots.patch 2016-07-01 08:28:37.000000000 +0000 @@ -3,13 +3,13 @@ Forwarded: not-needed (Ubuntu specific) Origin: vendor Author: Philipp Kern -Last-Update: 2015-12-28 +Last-Update: 2016-06-28 Index: b/bin/sbuild-createchroot =================================================================== --- a/bin/sbuild-createchroot +++ b/bin/sbuild-createchroot -@@ -169,8 +169,7 @@ +@@ -170,8 +170,7 @@ # Make sure fakeroot and build-essential are installed $conf->set('INCLUDE', add_items($conf->get('INCLUDE'), "fakeroot", diff -Nru sbuild-0.67.0/debian/patches/dummy-archive-sha512.patch sbuild-0.69.0/debian/patches/dummy-archive-sha512.patch --- sbuild-0.67.0/debian/patches/dummy-archive-sha512.patch 2016-04-07 11:47:40.000000000 +0000 +++ sbuild-0.69.0/debian/patches/dummy-archive-sha512.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -Description: Sbuild::ResolverBase: sign dummy archive with SHA-512 - Recent versions of apt complain about gpg's default of SHA-1. -Author: Colin Watson -Origin: upstream, https://anonscm.debian.org/cgit/buildd-tools/sbuild.git/commit/?id=5cfa09c51a9167c8748330ba40206ec468fc8b47 -Last-Update: 2016-04-07 - -Index: b/lib/Sbuild/ResolverBase.pm -=================================================================== ---- a/lib/Sbuild/ResolverBase.pm -+++ b/lib/Sbuild/ResolverBase.pm -@@ -1017,6 +1017,7 @@ - '--keyring', - $session->strip_chroot_path($dummy_archive_pubkey), - '--default-key', 'Sbuild Signer', '-abs', -+ '--digest-algo', 'SHA512', - '-o', $session->strip_chroot_path($dummy_release_file) . '.gpg', - $session->strip_chroot_path($dummy_release_file)); - $session->run_command( diff -Nru sbuild-0.67.0/debian/patches/fix-quoting-harder.patch sbuild-0.69.0/debian/patches/fix-quoting-harder.patch --- sbuild-0.67.0/debian/patches/fix-quoting-harder.patch 2016-01-21 10:48:11.000000000 +0000 +++ sbuild-0.69.0/debian/patches/fix-quoting-harder.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,14 +0,0 @@ -Description: Fix for 'W: Stripped single quote from command for security' -Author: Adam Conrad - ---- sbuild-0.67.0.orig/lib/Sbuild/Build.pm -+++ sbuild-0.67.0/lib/Sbuild/Build.pm -@@ -1139,7 +1139,7 @@ sub fetch_source_files { - use strict; - use warnings; - use Dpkg::Arch; -- if (Dpkg::Arch::debarch_is('$host_arch', '$a')) { -+ if (Dpkg::Arch::debarch_is("$host_arch", "$a")) { - exit 0; - } - exit 1; diff -Nru sbuild-0.67.0/debian/patches/fix-quoting.patch sbuild-0.69.0/debian/patches/fix-quoting.patch --- sbuild-0.67.0/debian/patches/fix-quoting.patch 2015-12-28 02:03:08.000000000 +0000 +++ sbuild-0.69.0/debian/patches/fix-quoting.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -From 2deb0b121d8ca5dffcdf3b50cefd4a59bbc4554d Mon Sep 17 00:00:00 2001 -From: Niko Tyni -Date: Mon, 28 Dec 2015 00:30:49 +0200 -Subject: [PATCH] Fix quoting when checking architectures (closes: #809175) - -The variables got interpolated into $command without any quoting, -essentially becoming barewords. - -Regression introduced in 9162dd0d727facb2ebab0ab7008603c5fa8c36a1 ---- - lib/Sbuild/Build.pm | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/lib/Sbuild/Build.pm b/lib/Sbuild/Build.pm -index a6ac74c..95245ca 100644 ---- a/lib/Sbuild/Build.pm -+++ b/lib/Sbuild/Build.pm -@@ -1139,7 +1139,7 @@ sub fetch_source_files { - use strict; - use warnings; - use Dpkg::Arch; -- if (Dpkg::Arch::debarch_is($host_arch, $a)) { -+ if (Dpkg::Arch::debarch_is('$host_arch', '$a')) { - exit 0; - } - exit 1; --- -2.5.1 - diff -Nru sbuild-0.67.0/debian/patches/no-pkg-mangle-deps.patch sbuild-0.69.0/debian/patches/no-pkg-mangle-deps.patch --- sbuild-0.67.0/debian/patches/no-pkg-mangle-deps.patch 2015-12-28 00:08:25.000000000 +0000 +++ sbuild-0.69.0/debian/patches/no-pkg-mangle-deps.patch 2016-07-01 08:28:37.000000000 +0000 @@ -2,18 +2,18 @@ pkgbinarymangler's dpkg-deb expects to be run from a source package. Author: Colin Watson Forwarded: not-needed -Last-Update: 2015-11-03 +Last-Update: 2016-06-28 Index: b/lib/Sbuild/ResolverBase.pm =================================================================== --- a/lib/Sbuild/ResolverBase.pm +++ b/lib/Sbuild/ResolverBase.pm -@@ -939,7 +939,7 @@ +@@ -966,7 +966,7 @@ #Now build the package: $session->run_command( -- { COMMAND => ['dpkg-deb', '--build', $session->strip_chroot_path($dummy_pkg_dir), $session->strip_chroot_path($dummy_deb)], -+ { COMMAND => ['env', 'NO_PKG_MANGLE=1', 'dpkg-deb', '--build', $session->strip_chroot_path($dummy_pkg_dir), $session->strip_chroot_path($dummy_deb)], +- { COMMAND => ['dpkg-deb', '--build', $dummy_pkg_dir, $dummy_deb], ++ { COMMAND => ['env', 'NO_PKG_MANGLE=1', 'dpkg-deb', '--build', $dummy_pkg_dir, $dummy_deb], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0}); if ($?) { diff -Nru sbuild-0.67.0/debian/patches/quieten-createchroot-warnings.patch sbuild-0.69.0/debian/patches/quieten-createchroot-warnings.patch --- sbuild-0.67.0/debian/patches/quieten-createchroot-warnings.patch 2015-12-28 13:59:36.000000000 +0000 +++ sbuild-0.69.0/debian/patches/quieten-createchroot-warnings.patch 2016-07-01 08:28:37.000000000 +0000 @@ -1,13 +1,13 @@ Description: Silence a couple of warnings from sbuild-createchroot Author: Colin Watson Forwarded: no -Last-Update: 2015-12-28 +Last-Update: 2016-06-28 Index: b/bin/sbuild-createchroot =================================================================== --- a/bin/sbuild-createchroot +++ b/bin/sbuild-createchroot -@@ -177,7 +177,7 @@ +@@ -179,7 +179,7 @@ my $chrootname = "${suite}-" . $conf->get('BUILD_ARCH') . $conf->get('CHROOT_SUFFIX'); @@ -16,12 +16,3 @@ while (my $line = <$pipe>) { $line ne "source:$chrootname\n" or die "chroot with name $chrootname already exists"; } -@@ -209,7 +209,7 @@ - push @args, "--components=" . $conf->get('COMPONENTS') - if $conf->get('COMPONENTS'); - push @args, "--keyring=" . $conf->get('KEYRING') if $conf->get('KEYRING'); --push @args, "--no-check-gpg" if $conf->get('KEYRING') eq ""; -+push @args, "--no-check-gpg" if ($conf->get('KEYRING') // "") eq ""; - push @args, $conf->get('RESOLVE_DEPS') ? - "--resolve-deps" : "--no-resolve-deps"; - push @args, "$suite", "$target", "$mirror"; diff -Nru sbuild-0.67.0/debian/patches/series sbuild-0.69.0/debian/patches/series --- sbuild-0.67.0/debian/patches/series 2016-04-19 14:12:56.000000000 +0000 +++ sbuild-0.69.0/debian/patches/series 2016-07-01 08:28:37.000000000 +0000 @@ -1,10 +1,7 @@ -fix-quoting.patch -do-not-install-debfoster-into-chroots.patch +0001-lib-Sbuild-ResolverBase.pm-do-not-produce-non-error-.patch +0001-bin-sbuild-createchroot-fix-chown-chmod-error-checks.patch no-pkg-mangle-deps.patch quieten-createchroot-warnings.patch abs-path-revert.patch -fix-quoting-harder.patch -copy-dummy-archive.patch -apt-conf-quotes.patch -dummy-archive-sha512.patch utf-8-by-default.patch +do-not-install-debfoster-into-chroots.patch diff -Nru sbuild-0.67.0/debian/patches/utf-8-by-default.patch sbuild-0.69.0/debian/patches/utf-8-by-default.patch --- sbuild-0.67.0/debian/patches/utf-8-by-default.patch 2016-04-19 14:13:18.000000000 +0000 +++ sbuild-0.69.0/debian/patches/utf-8-by-default.patch 2016-07-01 08:28:37.000000000 +0000 @@ -1,10 +1,11 @@ Description: utf-8-by-default.patch: Switch to C.UTF-8 by default (LP: #1566590) Author: Adam Conrad Bug-Ubuntu: https://bugs.launchpad.net/bugs/1566590 +Last-Update: 2016-06-28 --- sbuild-0.67.0.orig/lib/Sbuild/Build.pm +++ sbuild-0.67.0/lib/Sbuild/Build.pm -@@ -100,7 +100,7 @@ sub new { +@@ -99,7 +99,7 @@ sub new { $host_defaults->{'USER'} = $self->get_conf('USERNAME'); $host_defaults->{'DIR'} = $self->get_conf('HOME'); $host_defaults->{'STREAMIN'} = $devnull; @@ -13,7 +14,7 @@ $host_defaults->{'ENV'}->{'SHELL'} = '/bin/sh'; $host_defaults->{'ENV_FILTER'} = $self->get_conf('ENVIRONMENT_FILTER'); # Note, this should never fail. But, we should handle failure anyway. -@@ -506,7 +506,7 @@ sub run_chroot_session { +@@ -501,7 +501,7 @@ sub run_chroot_session { $chroot_defaults->{'STREAMIN'} = $devnull; $chroot_defaults->{'STREAMOUT'} = $self->get('Log Stream'); $chroot_defaults->{'STREAMERR'} = $self->get('Log Stream'); diff -Nru sbuild-0.67.0/etc/Makefile.am sbuild-0.69.0/etc/Makefile.am --- sbuild-0.67.0/etc/Makefile.am 2015-12-01 21:29:48.459402735 +0000 +++ sbuild-0.69.0/etc/Makefile.am 2016-04-22 12:05:06.794808726 +0000 @@ -28,7 +28,7 @@ builddsysconf_DATA = buildd.conf exampleconfdir = $(docdir)/examples -exampleconf_DATA = example.sbuildrc +exampleconf_DATA = example.sbuildrc sbuild-update-all COMPAT_SETUP = 99builddsourceslist SETUP = diff -Nru sbuild-0.67.0/etc/Makefile.in sbuild-0.69.0/etc/Makefile.in --- sbuild-0.67.0/etc/Makefile.in 2015-12-26 13:35:49.421714146 +0000 +++ sbuild-0.69.0/etc/Makefile.in 2016-05-08 12:14:36.118785653 +0000 @@ -298,7 +298,7 @@ builddsysconfdir = $(BUILDD_SYSCONF_DIR) builddsysconf_DATA = buildd.conf exampleconfdir = $(docdir)/examples -exampleconf_DATA = example.sbuildrc +exampleconf_DATA = example.sbuildrc sbuild-update-all COMPAT_SETUP = 99builddsourceslist SETUP = schrootsetupdir = $(SCHROOT_SYSCONF_DIR)/setup.d diff -Nru sbuild-0.67.0/etc/sbuild-update-all sbuild-0.69.0/etc/sbuild-update-all --- sbuild-0.67.0/etc/sbuild-update-all 1970-01-01 00:00:00.000000000 +0000 +++ sbuild-0.69.0/etc/sbuild-update-all 2016-04-22 12:05:06.794808726 +0000 @@ -0,0 +1,106 @@ +#!/bin/sh +# Example script for automatically updating sbuild chroots +# +# Simply create a crontab /etc/cron.d/sbuild-update-all and specify the +# schedule that you want to use. The behaviour of this script can be influenced +# by the following evironment variables: +# +# PATTERN glob pattern to match the chroot config name against, in +# directory /etc/schroot/chroot.d/. +# +# Default: *-sbuild +# +# UPDATEARGS The arguments with which sbuild-update will be invoked. +# +# Default: --update --dist-upgrade --autoclean --autoremove +# +# LOGFILE Log file to write to. These files are not rotated, you must set +# this up yourself. See logrotate(8) +# +# Default: /var/log/sbuild-update-all.log +# +# This script will refuse to run if another instance of it is running. In fact, +# it will refuse to run if there is an active chroot session (regardless of +# whether it is related to the matched patterns or not). Care for this must be +# taken when scheduling cron jobs, as crontabs are processed sequentially (with +# regards to variable assignment), but jobs are executed in parallel. +# +# Examples +# ======== +# +# 1. Update all sbuild chroots four times a day (at 00:15/06:15/12:15/18:15): +# +# 15 */6 * * * root /usr/share/doc/sbuild/examples/sbuild-update-all +# +# 2. Update all sid sbuild chroots daily, and all jessie sbuild chroots weekly, +# and log the latter to a separate file: +# +# PATTERN = sid-*-sbuild +# @daily root /usr/share/doc/sbuild/examples/sbuild-update-all +# +# PATTERN = jessie-*-sbuild +# LOGFILE = /var/log/wheezy-chroot-update.log +# @weekly root /usr/share/doc/sbuild/examples/sbuild-update-all +# +# The following will NOT work. Both of these jobs are executed at 00:15, so +# the second one will refuse to run: +# +# PATTERN = foo-* +# 15 0 * * * root /usr/share/doc/sbuild/examples/sbuild-update-all +# +# PATTERN = bar-* +# 15 0 * * * root /usr/share/doc/sbuild/examples/sbuild-update-all + + +# Output of sbuild-update invocations will be written to this file +LOGFILE=${LOGFILE:-/var/log/sbuild-update-all.log} + +# Arguments passed to sbuild-update +UPDATEARGS=${UPDATEARGS:-"--update --dist-upgrade --autoclean --autoremove"} + +# chroot config names are identified by this pattern +PATTERN=${PATTERN:-*-sbuild-*} + + +# Open logfile for output, make sure we're the only instance active +exec 8>>$LOGFILE +if ! flock -x -n 8 +then + echo "$0: another instance is already running" + exit 1 +fi +# Redirect stdout to logfile +exec 9>&1 +exec 1>&8 + +if ! ls /etc/schroot/chroot.d/$PATTERN >/dev/null 2>&1 +then + echo "No chroots defined" + break +fi + +for fullname in /etc/schroot/chroot.d/$PATTERN +do + confname=`basename $fullname | sed -e "s/-sbuild-.*//"` + + # Check for *any* active session and skip if there is one. + # chroots can share common factors, for example an LVM volume, so it's + # better to be safe than sorry. + if [ -n "`schroot -l --all-sessions`" ] + then + echo "Active schroot session, will not continue" + break + fi + + echo "****** `date` ******" + echo "Action: sbuild-update $UPDATEARGS $confname" + + if ! sbuild-update $UPDATEARGS $confname + then + echo "ERROR: failed to update $confname" + continue + fi +done + +# Release lock and undo redirections +exec 8>&- 1>&9 9>&- diff -Nru sbuild-0.67.0/lib/Buildd/Daemon.pm sbuild-0.69.0/lib/Buildd/Daemon.pm --- sbuild-0.67.0/lib/Buildd/Daemon.pm 2015-12-01 21:29:48.459402735 +0000 +++ sbuild-0.69.0/lib/Buildd/Daemon.pm 2016-05-08 10:31:16.418015118 +0000 @@ -543,7 +543,7 @@ } if ($dist_config->get('BUILT_ARCHITECTURE')) { if ($dist_config->get('BUILT_ARCHITECTURE') eq 'all') { - push ( @sbuild_args, "--arch-all-only" ); + push ( @sbuild_args, "--arch-all", "--no-arch-any" ); } else { push ( @sbuild_args, "--arch=" . $dist_config->get('BUILT_ARCHITECTURE') ); } @@ -694,13 +694,17 @@ $pkg_noepoch =~ s/_\d*:/_/; my $changes_name = $pkg_noepoch . '_' . $arch . '.changes'; + my $upload_path = $self->get_conf('HOME') . '/' . $dist_config->get('DUPLOAD_LOCAL_QUEUE_DIR') . '/' . $pkg_noepoch . '_' . $arch . '.upload'; $self->log("$pv is autosigned, moving to '$upload_dir'\n"); - system sprintf('dcmd mv %s/build/%s %s/%s/', - $self->get_conf('HOME'), - $changes_name, - $self->get_conf('HOME'), - $dist_config->get('DUPLOAD_LOCAL_QUEUE_DIR')); + if ( -f $upload_path ) { + unlink( $upload_path ); + $self->log("'$upload_path' removed.\n"); + } + system(qw(dcmd mv --), + sprintf('%s/build/%s', $self->get_conf('HOME'), $changes_name), + sprintf('%s/%s/', $self->get_conf('HOME'), $dist_config->get('DUPLOAD_LOCAL_QUEUE_DIR')) + ); $self->log("$pv moved to '$upload_dir'\n"); } diff -Nru sbuild-0.67.0/lib/Buildd/Mail.pm sbuild-0.69.0/lib/Buildd/Mail.pm --- sbuild-0.67.0/lib/Buildd/Mail.pm 2015-12-01 21:29:48.459402735 +0000 +++ sbuild-0.69.0/lib/Buildd/Mail.pm 2016-05-02 17:26:38.478086496 +0000 @@ -381,9 +381,9 @@ # that only has build-depends in it. # if that's too much cpu, have buildd use perl-apt if avail to export the # build-depends list, which could then be read in at this point - if (system "mv $upload_dir/$_ " . + if (system (qw(mv --), "$upload_dir/$_", $self->get_conf('HOME') . - "/build/chroot-$dist/var/cache/apt/archives/") { + "/build/chroot-$dist/var/cache/apt/archives/")) { $self->log("Cannot move $upload_dir/$_ to cache dir\n"); } else { next FILE; @@ -591,7 +591,7 @@ for my $upload_dir (@upload_dirs) { lock_file( $upload_dir ); foreach (@files) { - if (system "cp " . $self->get_conf('HOME') . "/build/$_ $upload_dir/$_") { + if (system('cp', '--', $self->get_conf('HOME')."/build/$_", "$upload_dir/$_")) { $self->log("Cannot copy $_ to $upload_dir/\n"); ++$errs; } @@ -605,7 +605,7 @@ } foreach (@files) { - if (system "rm " . $self->get_conf('HOME') . "/build/$_") { + if (!unlink($self->get_conf('HOME') . "/build/$_")) { $self->log("Cannot remove build/$_\n"); ++$errs; } diff -Nru sbuild-0.67.0/lib/Buildd/Watcher.pm sbuild-0.69.0/lib/Buildd/Watcher.pm --- sbuild-0.67.0/lib/Buildd/Watcher.pm 2015-08-21 07:54:09.640952212 +0000 +++ sbuild-0.69.0/lib/Buildd/Watcher.pm 2016-05-08 10:31:16.422015123 +0000 @@ -121,7 +121,7 @@ foreach (@to_purge) { next if ! -d $_; - system "sudo rm -rf $_"; + system(qw(sudo rm -rf --), $_); $self->log("Purged $_\n"); } @@ -227,18 +227,18 @@ -M "old-logs/daemon-stamp" > $self->get_conf('DAEMON_LOG_ROTATE')-$self->get('Fudge')) { $self->log("Rotating daemon log file\n"); - system "touch old-logs/daemon-stamp"; + system(qw(touch old-logs/daemon-stamp)); my $d = $self->format_time(time); if (-f $self->get_conf('DAEMON_LOG_FILE') . ".old") { - system "mv " . $self->get_conf('DAEMON_LOG_FILE') . ".old old-logs/daemon-$d.log"; - system "gzip -9 old-logs/daemon-$d.log"; + system(qw(mv --), $self->get_conf('DAEMON_LOG_FILE') . '.old', "old-logs/daemon-$d.log"); + system(qw(gzip -9), "old-logs/daemon-$d.log"); } rename( $self->get_conf('DAEMON_LOG_FILE'), $self->get_conf('DAEMON_LOG_FILE') . ".old" ); my $old_umask = umask 0007; - system "touch " . $self->get_conf('DAEMON_LOG_FILE'); + system(qw(touch --), $self->get_conf('DAEMON_LOG_FILE')); umask $old_umask; kill( 1, $daemon_pid ) if $daemon_pid; $self->reopen_log(); @@ -306,7 +306,7 @@ return if -f "$destpat-stamp" && -M "$destpat-stamp" < $minage-$self->get('Fudge'); $self->log("Archiving logs in $dir:\n"); - system "touch $destpat-stamp"; + system(qw(touch --), "$destpat-stamp"); $olddir = cwd; chdir( $dir ); @@ -326,8 +326,8 @@ $newt = $self->format_time($newest); $file = $self->get_conf('HOME') . "/$destpat-$oldt-$newt.tar"; - system "tar cf $file @todo"; - system "gzip -9 $file"; + system(qw(tar cf), $file, '--', @todo); + system(qw(gzip -9 --), $file); if ($dir eq "logs") { local (*F); diff -Nru sbuild-0.67.0/lib/Sbuild/AptitudeResolver.pm sbuild-0.69.0/lib/Sbuild/AptitudeResolver.pm --- sbuild-0.67.0/lib/Sbuild/AptitudeResolver.pm 2015-12-01 21:29:48.463402744 +0000 +++ sbuild-0.69.0/lib/Sbuild/AptitudeResolver.pm 2016-04-20 11:06:05.417529872 +0000 @@ -53,7 +53,6 @@ sub install_deps { my $self = shift; my $name = shift; - my $cross = shift; my @pkgs = @_; @@ -62,8 +61,17 @@ my $dummy_pkg_name = 'sbuild-build-depends-' . $name. '-dummy'; # Call functions to setup an archive to install dummy package. - return 0 unless ($self->setup_apt_archive($dummy_pkg_name, @pkgs)); - return 0 unless (!$self->update_archive()); + $self->log_subsubsection("Setup apt archive"); + + if (!$self->setup_apt_archive($dummy_pkg_name, @pkgs)) { + $self->log_error("Setting up apt archive failed"); + return 0; + } + + if (!$self->update_archive()) { + $self->log_error("Updating apt archive failed"); + return 0; + } $self->log_subsection("Install $name build dependencies (aptitude-based resolver)"); diff -Nru sbuild-0.67.0/lib/Sbuild/AptResolver.pm sbuild-0.69.0/lib/Sbuild/AptResolver.pm --- sbuild-0.67.0/lib/Sbuild/AptResolver.pm 2015-12-02 09:47:30.251449646 +0000 +++ sbuild-0.69.0/lib/Sbuild/AptResolver.pm 2016-04-24 13:18:49.311692713 +0000 @@ -52,7 +52,6 @@ sub install_deps { my $self = shift; my $name = shift; - my $cross = shift; my @pkgs = @_; my $status = 0; @@ -60,27 +59,27 @@ my $dummy_pkg_name = 'sbuild-build-depends-' . $name. '-dummy'; # Call functions to setup an archive to install dummy package. - return 0 unless ($self->setup_apt_archive($dummy_pkg_name, @pkgs)); - return 0 unless (!$self->update_archive()); + $self->log_subsubsection("Setup apt archive"); + if (!$self->setup_apt_archive($dummy_pkg_name, @pkgs)) { + $self->log_error("Setting up apt archive failed"); + return 0; + } + + if (!$self->update_archive()) { + $self->log_error("Updating apt archive failed"); + return 0; + } - $self->log_subsection("Install $name build dependencies (apt-based resolver)"); + $self->log_subsubsection("Install $name build dependencies (apt-based resolver)"); # Install the dummy package my (@instd, @rmvd); $self->log("Installing build dependencies\n"); - my @apt_args = ("-yf", \@instd, \@rmvd); - if ($cross) { - # Cross-building: 'apt-get build-dep' knows how to get the multiarch - # details right. - push @apt_args, - '-a' . $self->get('Host Arch'), 'build-dep', $dummy_pkg_name; - } else { - push @apt_args, 'install', $dummy_pkg_name; - } + my @apt_args = ("-yf", \@instd, \@rmvd, 'install', $dummy_pkg_name); if (!$self->run_apt(@apt_args)) { - $self->log("Package installation failed\n"); + $self->log_error("Package installation failed\n"); if (defined ($self->get('Session')->get('Session Purged')) && $self->get('Session')->get('Session Purged') == 1) { $self->log("Not removing build depends: cloned chroot in use\n"); diff -Nru sbuild-0.67.0/lib/Sbuild/AspcudResolver.pm sbuild-0.69.0/lib/Sbuild/AspcudResolver.pm --- sbuild-0.67.0/lib/Sbuild/AspcudResolver.pm 2015-12-01 21:29:48.463402744 +0000 +++ sbuild-0.69.0/lib/Sbuild/AspcudResolver.pm 2016-04-22 12:05:06.794808726 +0000 @@ -51,7 +51,6 @@ sub install_deps { my $self = shift; my $name = shift; - my $cross = shift; my @pkgs = @_; my $status = 0; @@ -59,8 +58,17 @@ my $dummy_pkg_name = 'sbuild-build-depends-' . $name. '-dummy'; # Call functions to setup an archive to install dummy package. - return 0 unless ($self->setup_apt_archive($dummy_pkg_name, @pkgs)); - return 0 unless (!$self->update_archive()); + $self->log_subsubsection("Setup apt archive"); + + if (!$self->setup_apt_archive($dummy_pkg_name, @pkgs)) { + $self->log_error("Setting up apt archive failed"); + return 0; + } + + if (!$self->update_archive()) { + $self->log_error("Updating apt archive failed"); + return 0; + } $self->log_subsection("Install $name build dependencies (aspcud-based resolver)"); #install aspcud first: @@ -78,31 +86,9 @@ my @apt_args = ("-yf", \@instd, \@rmvd); push @apt_args, 'install', $dummy_pkg_name; - # It follows an explanation of the choice of the - # APT::Solver::aspcud::Preferences setting - # - # Since it is assumed that the chroot only contains a base system and - # build-essential, from which we assume that no package shall be removed, - # we first minimize the number of removed packages. This means that if - # there exist solutions that do not remove any packages, then those will - # be evaluated further. The second optimization criteria is to minimize - # the number of changed packages. This will take care that no packages of - # the base system are unnecessarily upgraded to their versions from - # experimental. It will also avoid any solutions that do need upgrades to - # the experimental versions and keep the upgrades to a minimum if an - # upgrade is strictly required. The third criteria minimizes the number of - # new packages the solution installs. Here it can happen that installing a - # dependency from experimental instead of unstable will lead to less new - # packages. But this should only happen if the package in unstable depends - # on more additional packages compared to the same package in - # experimental. If the solutions are otherwise equal then as the last - # criteria, the number of packages from experimental will be minimized by - # maximizing the sum of the apt-pin values. Since packages from unstable - # have a higher pin value than those in experimental, this should prefer - # packages from unstable except if the solution from unstable is so large - # compared to the one in experimental that their sum of pin values is - # larger in which case the solution in experimental will be preferred. - push @apt_args, '--solver', 'aspcud', '-o', 'APT::Solver::Strict-Pinning=false', '-o', 'APT::Solver::aspcud::Preferences=-removed,-changed,-new,+sum(solution,apt-pin)'; + push @apt_args, '--solver', 'aspcud', + '-o', 'APT::Solver::Strict-Pinning=false', + '-o', 'APT::Solver::aspcud::Preferences='.$self->get_conf('ASPCUD_CRITERIA'); if (!$self->run_apt(@apt_args)) { $self->log("Package installation failed\n"); diff -Nru sbuild-0.67.0/lib/Sbuild/Build.pm sbuild-0.69.0/lib/Sbuild/Build.pm --- sbuild-0.67.0/lib/Sbuild/Build.pm 2015-12-26 10:32:21.876608352 +0000 +++ sbuild-0.69.0/lib/Sbuild/Build.pm 2016-05-08 11:21:18.505932271 +0000 @@ -30,13 +30,13 @@ use Errno qw(:POSIX); use Fcntl; use File::Basename qw(basename dirname); -use File::Temp qw(tempdir); use File::Path qw(make_path); use FileHandle; use File::Copy qw(); # copy is already exported from Sbuild, so don't export # anything. use Dpkg::Arch; use Dpkg::Control; +use Dpkg::Index; use Dpkg::Version; use Dpkg::Deps qw(deps_concat deps_parse); use Scalar::Util 'refaddr'; @@ -44,11 +44,12 @@ use MIME::Lite; use Term::ANSIColor; -use Sbuild qw($devnull binNMU_version copy isin debug df send_mail +use Sbuild qw($devnull binNMU_version copy isin debug send_mail dsc_files dsc_pkgver); use Sbuild::Base; use Sbuild::ChrootInfoSchroot; use Sbuild::ChrootInfoSudo; +use Sbuild::ChrootInfoADT; use Sbuild::ChrootRoot; use Sbuild::Sysconfig qw($version $release_date); use Sbuild::Sysconfig; @@ -77,8 +78,6 @@ $self->set('ABORT', undef); $self->set('Job', $dsc); - $self->set('Chroot Dir', ''); - $self->set('Chroot Build Dir', ''); $self->set('Build Dir', ''); $self->set('Max Lock Trys', 120); $self->set('Lock Interval', 5); @@ -114,15 +113,16 @@ # DSC, package and version information: $self->set_dsc($dsc); - # Note, will be overwritten by Version: in DSC. - $self->set_version($dsc); - # Can sources be obtained? - $self->set('Invalid Source', 0); - $self->set('Invalid Source', 1) - if (!defined $self->get('Version')); - - debug("Invalid Source = " . $self->get('Invalid Source') . "\n"); + # If the job name contains an underscore then it is either the filename of + # a dsc or a pkgname_version string. In both cases we can already extract + # the version number. Otherwise it is a bare source package name and the + # version will initially be unknown. + if ($dsc =~ m/_/) { + $self->set_version($dsc); + } else { + $self->set('Package', $dsc); + } return $self; } @@ -270,14 +270,16 @@ $self->set('Build Arch', $self->get_conf('BUILD_ARCH')); $self->set('Build Profiles', $self->get_conf('BUILD_PROFILES')); - my $dist = $self->get_conf('DISTRIBUTION'); - if (!defined($dist) || !$dist) { - Sbuild::Exception::Build->throw(error => "No distribution defined", + if (!$self->get_conf('BUILD_ARCH_ANY') && + !$self->get_conf('BUILD_ARCH_ALL') && + !$self->get_conf('BUILD_SOURCE')) { + Sbuild::Exception::Build->throw(error => "Neither architecture specific nor architecture independent or source package specified to be built.", failstage => "init"); } - if ($self->get('Invalid Source')) { - Sbuild::Exception::Build->throw(error => "Invalid source " . $self->get('DSC'), + my $dist = $self->get_conf('DISTRIBUTION'); + if (!defined($dist) || !$dist) { + Sbuild::Exception::Build->throw(error => "No distribution defined", failstage => "init"); } @@ -324,6 +326,8 @@ $self->run_chroot_session(); }; + debug("Error run_chroot(): $@") if $@; + # Log exception info and set status and fail stage prior to # closing build log. my $e; @@ -357,6 +361,8 @@ my $chroot_info; if ($self->get_conf('CHROOT_MODE') eq 'schroot') { $chroot_info = Sbuild::ChrootInfoSchroot->new($self->get('Config')); + } elsif ($self->get_conf('CHROOT_MODE') eq 'adt') { + $chroot_info = Sbuild::ChrootInfoADT->new($self->get('Config')); } else { $chroot_info = Sbuild::ChrootInfoSudo->new($self->get('Config')); } @@ -393,58 +399,62 @@ failstage => "create-session"); } - $self->set('Chroot Dir', $session->get('Location')); if (defined($self->get_conf('BUILD_PATH')) && $self->get_conf('BUILD_PATH')) { - my $build_path = $session->get('Location') . "/" . $self->get_conf('BUILD_PATH'); - $self->set('Chroot Build Dir', $build_path); - if (!(-d "$build_path")) { - make_path($build_path, {error => \my $err} ); - if (@$err) { - my $error; - for my $diag (@$err) { - my ($file, $message) = %$diag; - $error .= "mkdir $file: $message\n"; - } - Sbuild::Exception::Build->throw( - error => $error, - failstage => "create-session"); - } - } else { - my $empty = isEmpty($build_path); - if ($empty == 1) { - Sbuild::Exception::Build->throw( - error => "Buildpath: " . $build_path . " is not empty", - failstage => "create-session"); - } - elsif ($empty == 2) { - Sbuild::Exception::Build->throw( - error => "Buildpath: " . $build_path . " cannot be read. Insufficient permissions?", - failstage => "create-session"); - } + my $build_path = $self->get_conf('BUILD_PATH'); + $self->set('Build Dir', $build_path); + if (!($session->test_directory($build_path))) { + if (!$session->mkdir($build_path, { PARENTS => 1})) { + Sbuild::Exception::Build->throw( + error => "Buildpath: " . $build_path . " cannot be created", + failstage => "create-session"); + } + } else { + my $isempty = <run_command({ + COMMAND => ['perl', '-e', $isempty], + USER => 'root', + DIR => '/' + }); + if ($? == 1) { + Sbuild::Exception::Build->throw( + error => "Buildpath: " . $build_path . " is not empty", + failstage => "create-session"); + } + elsif ($? == 2) { + Sbuild::Exception::Build->throw( + error => "Buildpath: " . $build_path . " cannot be read. Insufficient permissions?", + failstage => "create-session"); } + } } else { - $self->set('Chroot Build Dir', - tempdir($self->get('Package') . '-XXXXXX', - DIR => $session->get('Location') . "/build")); - } - sub isEmpty{ - my ($dirpath) = @_; - my $file; - if ( opendir my $dfh, $dirpath){ - while (defined($file = readdir $dfh)){ - next if $file eq '.' or $file eq '..'; - closedir $dfh; - return 1; - } - closedir $dfh; - return 0; + # we run mktemp within the chroot instead of using File::Temp::tempdir because the user + # running sbuild might not have permissions creating a directory in /build. This happens + # when the chroot was extracted in a different user namespace than the outer user + $self->check_abort(); + my $tmpdir = $session->mktemp({ + TEMPLATE => "/build/" . $self->get('Package') . '-XXXXXX', + DIRECTORY => 1}); + if (!$tmpdir) { + $self->log_error("unable to mktemp\n"); + Sbuild::Exception::Build->throw(error => "unable to mktemp", + failstage => "create-build-dir"); } - return 2; + $self->check_abort(); + $self->set('Build Dir', $tmpdir); } - $self->set('Build Dir', $session->strip_chroot_path($self->get('Chroot Build Dir'))); - # Run pre build external commands $self->check_abort(); if(!$self->run_external_commands("pre-build-commands")) { @@ -464,33 +474,18 @@ # Log filtering my $filter; - $filter = $self->get('Build Dir') . '/' . $self->get('DSC Dir'); - $filter =~ s;^/;;; - $self->build_log_filter($filter, 'PKGBUILDDIR'); - $filter = $self->get('Build Dir'); - $filter =~ s;^/;;; - $self->build_log_filter($filter, 'BUILDDIR'); $filter = $session->get('Location'); $filter =~ s;^/;;; $self->build_log_filter($filter , 'CHROOT'); # Need tempdir to be writable and readable by sbuild group. $self->check_abort(); - $session->run_command( - { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild', - $self->get('Build Dir')], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chown($self->get('Build Dir'), $self->get_conf('BUILD_USER'), 'sbuild')) { Sbuild::Exception::Build->throw(error => "Failed to set sbuild group ownership on chroot build dir", failstage => "create-build-dir"); } $self->check_abort(); - $session->run_command( - { COMMAND => ['chmod', '0770', $self->get('Build Dir')], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chmod($self->get('Build Dir'), "ug=rwx,o=,a-s")) { Sbuild::Exception::Build->throw(error => "Failed to set sbuild group ownership on chroot build dir", failstage => "create-build-dir"); } @@ -517,12 +512,20 @@ $resolver->set('Host Arch', $self->get_conf('HOST_ARCH')); $resolver->set('Build Arch', $self->get_conf('BUILD_ARCH')); $resolver->set('Build Profiles', $self->get_conf('BUILD_PROFILES')); - $resolver->set('Chroot Build Dir', $self->get('Chroot Build Dir')); + $resolver->set('Build Dir', $self->get('Build Dir')); $self->set('Dependency Resolver', $resolver); # Lock chroot so it won't be tampered with during the build. $self->check_abort(); - if (!$session->lock_chroot($self->get('Package_SVersion'), $$, $self->get_conf('USERNAME'))) { + my $jobname; + # the version might not yet be known if the user only passed a package + # name without a version to sbuild + if ($self->get('Package_SVersion')) { + $jobname = $self->get('Package_SVersion'); + } else { + $jobname = $self->get('Package'); + } + if (!$session->lock_chroot($jobname, $$, $self->get_conf('USERNAME'))) { Sbuild::Exception::Build->throw(error => "Error locking chroot session: skipping " . $self->get('Package'), failstage => "lock-session"); @@ -607,58 +610,82 @@ my $self = shift; my $resolver = $self->get('Dependency Resolver'); - if ($self->get_conf('APT_CLEAN') || $self->get_conf('APT_UPDATE') || - $self->get_conf('APT_DISTUPGRADE') || $self->get_conf('APT_UPGRADE')) { - $self->log_subsection('Update chroot'); - } + eval { + if ($self->get_conf('APT_CLEAN') || $self->get_conf('APT_UPDATE') || + $self->get_conf('APT_DISTUPGRADE') || $self->get_conf('APT_UPGRADE')) { + $self->log_subsection('Update chroot'); + } - # Clean APT cache. - $self->check_abort(); - if ($self->get_conf('APT_CLEAN')) { - if ($resolver->clean()) { - # Since apt-clean was requested specifically, fail on - # error when not in buildd mode. - $self->log("apt-get clean failed\n"); - if ($self->get_conf('SBUILD_MODE') ne 'buildd') { - Sbuild::Exception::Build->throw(error => "apt-get clean failed", - failstage => "apt-get-clean"); + # Clean APT cache. + $self->check_abort(); + if ($self->get_conf('APT_CLEAN')) { + if ($resolver->clean()) { + # Since apt-clean was requested specifically, fail on + # error when not in buildd mode. + $self->log_error("apt-get clean failed\n"); + if ($self->get_conf('SBUILD_MODE') ne 'buildd') { + Sbuild::Exception::Build->throw(error => "apt-get clean failed", + failstage => "apt-get-clean"); + } } } - } - # Update APT cache. - $self->check_abort(); - if ($self->get_conf('APT_UPDATE')) { - if ($resolver->update()) { - # Since apt-update was requested specifically, fail on - # error when not in buildd mode. - if ($self->get_conf('SBUILD_MODE') ne 'buildd') { - Sbuild::Exception::Build->throw(error => "apt-get update failed", - failstage => "apt-get-update"); + # Update APT cache. + $self->check_abort(); + if ($self->get_conf('APT_UPDATE')) { + if ($resolver->update()) { + # Since apt-update was requested specifically, fail on + # error when not in buildd mode. + if ($self->get_conf('SBUILD_MODE') ne 'buildd') { + Sbuild::Exception::Build->throw(error => "apt-get update failed", + failstage => "apt-get-update"); + } + } + } else { + # If it was requested not to do an apt update, the build and host + # architecture must already be part of the chroot. If they are not + # and thus added during the sbuild run, issue a warning because + # then the package build dependencies will likely fail to be + # installable. + # + # The logic which checks which architectures are needed is in + # ResolverBase.pm, so we just check whether any architectures + # where added with 'dpkg --add-architecture' because if any were + # added an update is most likely needed. + if (keys %{$resolver->get('Added Foreign Arches')}) { + $self->log_warning("Additional architectures were added but apt update was disabled. Build dependencies might not be satisfiable.\n"); } } - } - # Upgrade using APT. - $self->check_abort(); - if ($self->get_conf('APT_DISTUPGRADE')) { - if ($resolver->distupgrade()) { - # Since apt-distupgrade was requested specifically, fail on - # error when not in buildd mode. - if ($self->get_conf('SBUILD_MODE') ne 'buildd') { - Sbuild::Exception::Build->throw(error => "apt-get dist-upgrade failed", - failstage => "apt-get-dist-upgrade"); - } - } - } elsif ($self->get_conf('APT_UPGRADE')) { - if ($resolver->upgrade()) { - # Since apt-upgrade was requested specifically, fail on - # error when not in buildd mode. - if ($self->get_conf('SBUILD_MODE') ne 'buildd') { - Sbuild::Exception::Build->throw(error => "apt-get upgrade failed", - failstage => "apt-get-upgrade"); + # Upgrade using APT. + $self->check_abort(); + if ($self->get_conf('APT_DISTUPGRADE')) { + if ($resolver->distupgrade()) { + # Since apt-distupgrade was requested specifically, fail on + # error when not in buildd mode. + if ($self->get_conf('SBUILD_MODE') ne 'buildd') { + Sbuild::Exception::Build->throw(error => "apt-get dist-upgrade failed", + failstage => "apt-get-dist-upgrade"); + } + } + } elsif ($self->get_conf('APT_UPGRADE')) { + if ($resolver->upgrade()) { + # Since apt-upgrade was requested specifically, fail on + # error when not in buildd mode. + if ($self->get_conf('SBUILD_MODE') ne 'buildd') { + Sbuild::Exception::Build->throw(error => "apt-get upgrade failed", + failstage => "apt-get-upgrade"); + } } } + }; + + debug("Error run_chroot_update(): $@") if $@; + + my $e = Exception::Class->caught('Sbuild::Exception::Build'); + if ($e) { + $self->run_external_commands("chroot-update-failed-commands"); + $e->rethrow(); } } @@ -687,6 +714,12 @@ $self->log_warning($msg); } + if ($self->get('Host Arch') ne $self->get('Build Arch')) { + $self->log_subsection("Install crossbuild-essential"); + } else { + $self->log_subsection("Install build-essential"); + } + $self->check_abort(); $self->set('Install Start Time', time); $self->set('Install End Time', $self->get('Install Start Time')); @@ -706,6 +739,16 @@ failstage => "install-deps"); } + # the architecture check has to be done *after* build-essential is + # installed because as part of the architecture check a perl script is + # run inside the chroot which requires the Dpkg::Arch module which is + # in libdpkg-perl which might not exist in the chroot but will get + # installed by the build-essential package + if(!$self->check_architectures()) { + Sbuild::Exception::Build->throw(error => "Architecture check failed", + failstage => "check-architecture"); + } + my $snapshot = ""; $snapshot = "gcc-snapshot" if ($self->get_conf('GCC_SNAPSHOT')); $resolver->add_dependencies('GCC_SNAPSHOT', $snapshot , "", "", "", "", ""); @@ -743,6 +786,8 @@ @build_deps = ('MANUAL', $self->get('Package')); } + $self->log_subsection("Install package build dependencies"); + $self->check_abort(); if (!$resolver->install_main_deps($self->get('Package'), @build_deps)) { @@ -827,11 +872,9 @@ if ($purge_build_directory) { # Purge package build directory $self->log("Purging " . $self->get('Build Dir') . "\n"); - $self->get('Session')->run_command( - { COMMAND => ['rm', '-rf', $self->get('Build Dir')], - USER => 'root', - PRIORITY => 0, - DIR => '/' }); + if (!$self->get('Session')->unlink($self->get('Build Dir'), { RECURSIVE => 1 })) { + $self->log_error("unable to remove build directory\n"); + } } # Purge non-cloned session @@ -856,30 +899,22 @@ sub copy_to_chroot { my $self = shift; my $source = shift; - my $dest = shift; + my $chrootdest = shift; + + my $session = $self->get('Session'); $self->check_abort(); - if (! File::Copy::copy($source, $dest)) { - $self->log_error("E: Failed to copy '$source' to '$dest': $!\n"); + if(!$session->copy_to_chroot($source, $chrootdest)) { + $self->log_error("E: Failed to copy $source to $chrootdest\n"); return 0; } - $self->get('Session')->run_command( - { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild', - $self->get('Session')->strip_chroot_path($dest)], - USER => 'root', - DIR => '/' }); - if ($?) { - $self->log_error("E: Failed to set sbuild group ownership on $dest\n"); + if (!$session->chown($chrootdest, $self->get_conf('BUILD_USER'), 'sbuild')) { + $self->log_error("E: Failed to set sbuild group ownership on $chrootdest\n"); return 0; } - $self->get('Session')->run_command( - { COMMAND => ['chmod', '0664', - $self->get('Session')->strip_chroot_path($dest)], - USER => 'root', - DIR => '/' }); - if ($?) { - $self->log_error("E: Failed to set 0644 permissions on $dest\n"); + if (!$session->chmod($chrootdest, "ug=rw,o=r,a-s")) { + $self->log_error("E: Failed to set 0644 permissions on $chrootdest\n"); return 0; } @@ -888,15 +923,11 @@ sub fetch_source_files { my $self = shift; - my $dir = $self->get('Source Dir'); - my $dsc = $self->get('DSC File'); - my $build_dir = $self->get('Chroot Build Dir'); - my $pkg = $self->get('Package'); - my $ver = $self->get('OVersion'); + my $build_dir = $self->get('Build Dir'); my $host_arch = $self->get('Host Arch'); my $resolver = $self->get('Dependency Resolver'); - my ($dscarchs, $dscpkg, $dscver, @fetched); + my ($dscarchs, $dscpkg, $dscver, $dsc); my $build_depends = ""; my $build_depends_arch = ""; @@ -908,17 +939,13 @@ $self->log_subsection("Fetch source files"); - if (!defined($self->get('Package')) || - !defined($self->get('OVersion')) || - !defined($self->get('Source Dir'))) { - $self->log("Invalid source: $self->get('DSC')\n"); - return 0; - } - $self->check_abort(); if ($self->get('DSC Base') =~ m/\.dsc$/) { + my $dir = $self->get('Source Dir'); + # Work with a .dsc file. my $file = $self->get('DSC'); + $dsc = $self->get('DSC File'); if (! -f $file || ! -r $file) { $self->log_error("Could not find $file\n"); return 0; @@ -931,89 +958,107 @@ if (! $self->copy_to_chroot("$file", "$build_dir/$dsc")) { return 0; } - push(@fetched, "$build_dir/$dsc"); foreach (@cwd_files) { if (! $self->copy_to_chroot("$dir/$_", "$build_dir/$_")) { return 0; } - push(@fetched, "$build_dir/$_"); } } else { + my $pkg = $self->get('DSC'); + my $ver; + + if ($pkg =~ m/_/) { + ($pkg, $ver) = split /_/, $pkg; + } + # Use apt to download the source files $self->log_subsubsection("Check APT"); my %entries = (); - my $retried = $self->get_conf('APT_UPDATE'); # Already updated if set - retry: $self->log("Checking available source versions...\n"); my $pipe = $self->get('Dependency Resolver')->pipe_apt_command( { COMMAND => [$self->get_conf('APT_CACHE'), - '-q', 'showsrc', "$pkg"], + '-q', '--only-source', 'showsrc', $pkg], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0, DIR => '/'}); if (!$pipe) { - $self->log("Can't open pipe to ".$self->get_conf('APT_UPDATE').": $!\n"); + $self->log_error("Can't open pipe to ".$self->get_conf('APT_CACHE').": $!\n"); return 0; } - { - local($/) = ""; - my $package; - my $ver; - my $tfile; - while( <$pipe> ) { - $package = $1 if /^Package:\s+(\S+)\s*$/mi; - $ver = $1 if /^Version:\s+(\S+)\s*$/mi; - $tfile = $1 if /^Files:\s*\n((\s+.*\s*\n)+)/mi; - if (defined $package && defined $ver && defined $tfile) { - @{$entries{"$package $ver"}} = map { (split( /\s+/, $_ ))[3] } - split( "\n", $tfile ); - undef($package); - undef($ver); - undef($tfile); - } - } + my $key_func = sub { + return $_[0]->{Package} . '_' . $_[0]->{Version}; + }; - if (! scalar keys %entries) { - $self->log($self->get_conf('APT_CACHE') . - " returned no information about $pkg source\n"); - $self->log("Are there any deb-src lines in your /etc/apt/sources.list?\n"); - return 0; + my $index = Dpkg::Index->new(get_key_func=>$key_func); - } + if (!$index->parse($pipe, 'apt-cache showsrc')) { + $self->log_error("Cannot parse output of apt-cache showsrc: $!\n"); + return 0; } + close($pipe); if ($?) { - $self->log($self->get_conf('APT_CACHE') . " exit status $?: $!\n"); + $self->log_error($self->get_conf('APT_CACHE') . " exit status $?: $!\n"); return 0; } - if (!defined($entries{"$pkg $ver"})) { - if (!$retried) { - $self->log_subsubsection("Update APT"); - # try to update apt's cache if nothing found - $self->get('Dependency Resolver')->update(); - $retried = 1; - goto retry; - } - $self->log("Can't find source for " . - $self->get('Package_OVersion') . "\n"); - $self->log("(only different version(s) ", - join( ", ", sort keys %entries), " found)\n") - if %entries; + my $highestversion; + my $highestdsc; + + foreach my $key ($index->get_keys()) { + my $cdata = $index->get_by_key($key); + my $pkgname = $cdata->{"Package"}; + if (not defined($pkgname)) { + $self->log_warning("apt-cache output without Package field\n"); + next; + } + if ($pkg ne $pkgname) { + $self->log_warning("apt-cache output for different package\n"); + next; + } + my $pkgversion = $cdata->{"Version"}; + if (not defined($pkgversion)) { + $self->log_warning("apt-cache output without Version field\n"); + next; + } + if (defined($ver) and $ver ne $pkgversion) { + next; + } + my $checksums = Dpkg::Checksums->new(); + $checksums->add_from_control($cdata, use_files_for_md5 => 1); + my @files = grep {/\.dsc$/} $checksums->get_files(); + if (scalar @files != 1) { + $self->log_warning("apt-cache output with more than one .dsc\n"); + next; + } + if (!defined $highestdsc) { + $highestdsc = $files[0]; + $highestversion = $pkgversion; + } else { + if (version_compare($highestversion, $pkgversion) < 0) { + $highestdsc = $files[0]; + $highestversion = $pkgversion; + } + } + } + + if (!defined $highestdsc) { + $self->log_error($self->get_conf('APT_CACHE') . + " returned no information about $pkg source\n"); + $self->log_error("Are there any deb-src lines in your /etc/apt/sources.list?\n"); return 0; } - $self->log_subsubsection("Download source files with APT"); + $self->set_dsc($highestdsc); + $dsc = $highestdsc; - foreach (@{$entries{"$pkg $ver"}}) { - push(@fetched, "$build_dir/$_"); - } + $self->log_subsubsection("Download source files with APT"); my $pipe2 = $self->get('Dependency Resolver')->pipe_apt_command( - { COMMAND => [$self->get_conf('APT_GET'), '--only-source', '-q', '-d', 'source', "$pkg=$ver"], + { COMMAND => [$self->get_conf('APT_GET'), '--only-source', '-q', '-d', 'source', "$pkg=$highestversion"], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0}) || return 0; @@ -1022,19 +1067,26 @@ } close($pipe2); if ($?) { - $self->log($self->get_conf('APT_GET') . " for sources failed\n"); + $self->log_error($self->get_conf('APT_GET') . " for sources failed\n"); return 0; } - $self->set_dsc((grep { /\.dsc$/ } @fetched)[0]); + } + + my $pipe = $self->get('Session')->get_read_file_handle("$build_dir/$dsc"); + if (!$pipe) { + $self->log_error("unable to open pipe\n"); + return 0; } my $pdsc = Dpkg::Control->new(type => CTRL_PKG_SRC); $pdsc->set_options(allow_pgp => 1); - if (!$pdsc->load("$build_dir/$dsc")) { - $self->log("Error parsing $build_dir/$dsc"); + if (!$pdsc->parse($pipe, "$build_dir/$dsc")) { + $self->log_error("Error parsing $build_dir/$dsc"); return 0; } + close($pipe); + $build_depends = $pdsc->{'Build-Depends'}; $build_depends_arch = $pdsc->{'Build-Depends-Arch'}; $build_depends_indep = $pdsc->{'Build-Depends-Indep'}; @@ -1054,8 +1106,36 @@ $build_conflicts_arch =~ s/\n\s+/ /g if defined $build_conflicts_arch; $build_conflicts_indep =~ s/\n\s+/ /g if defined $build_conflicts_indep; + $self->set('Build Depends', $build_depends); + $self->set('Build Depends Arch', $build_depends_arch); + $self->set('Build Depends Indep', $build_depends_indep); + $self->set('Build Conflicts', $build_conflicts); + $self->set('Build Conflicts Arch', $build_conflicts_arch); + $self->set('Build Conflicts Indep', $build_conflicts_indep); - $self->log_subsubsection("Check architectures"); + $self->set('Dsc Architectures', $dscarchs); + + # we set up the following filters this late because the user might only + # have specified a source package name to build without a version in which + # case we only get to know the final build directory now + my $filter; + $filter = $self->get('Build Dir') . '/' . $self->get('DSC Dir'); + $filter =~ s;^/;;; + $self->build_log_filter($filter, 'PKGBUILDDIR'); + $filter = $self->get('Build Dir'); + $filter =~ s;^/;;; + $self->build_log_filter($filter, 'BUILDDIR'); + + return 1; +} + +sub check_architectures { + my $self = shift; + my $resolver = $self->get('Dependency Resolver'); + my $dscarchs = $self->get('Dsc Architectures'); + my $host_arch = $self->get('Host Arch'); + + $self->log_subsection("Check architectures"); # Check for cross-arch dependencies # parse $build_depends* for explicit :arch and add the foreign arches, as needed sub get_explicit_arches @@ -1091,10 +1171,13 @@ return keys %set; } + # we don't need to look at build conflicts here because conflicting with a + # package of an explicit architecture does not mean that we need to enable + # that architecture in the chroot my $build_depends_concat = - deps_concat( grep {defined $_} ($build_depends, - $build_depends_arch, - $build_depends_indep)); + deps_concat( grep {defined $_} ($self->get('Build Depends'), + $self->get('Build Depends Arch'), + $self->get('Build Depends Indep'))); my $merged_depends = deps_parse( $build_depends_concat, reduce_arch => 1, host_arch => $self->get('Host Arch'), @@ -1104,10 +1187,7 @@ build_profiles => [ split / /, $self->get('Build Profiles') ]); if( !defined $merged_depends ) { my $msg = "Error! deps_parse() couldn't parse the Build-Depends '$build_depends_concat'"; - $self->log("$msg\n"); - Sbuild::Exception::Build->throw(error => $msg, - status => "skipped", - failstage => "add-forein-architecture"); + $self->log_error("$msg\n"); return 0; } @@ -1131,7 +1211,7 @@ # Check package arch makes sense to build if (!$dscarchs) { - $self->log("$dsc has no Architecture: field -- skipping arch check!\n"); + $self->log_warning("dsc has no Architecture: field -- skipping arch check!\n"); } else { my $valid_arch; for my $a (split(/\s+/, $dscarchs)) { @@ -1139,7 +1219,7 @@ use strict; use warnings; use Dpkg::Arch; - if (Dpkg::Arch::debarch_is($host_arch, $a)) { + if (Dpkg::Arch::debarch_is("$host_arch", "$a")) { exit 0; } exit 1; @@ -1158,25 +1238,16 @@ } if ($dscarchs ne "any" && !($valid_arch) && !($dscarchs =~ /\ball\b/ && $self->get_conf('BUILD_ARCH_ALL')) ) { - my $msg = "$dsc: $host_arch not in arch list or does not match any arch wildcards: $dscarchs -- skipping\n"; - $self->log($msg); - Sbuild::Exception::Build->throw(error => "$dsc: $host_arch not in arch list or does not match any arch wildcards: $dscarchs -- skipping", + my $msg = "dsc: $host_arch not in arch list or does not match any arch wildcards: $dscarchs -- skipping\n"; + $self->log_error($msg); + Sbuild::Exception::Build->throw(error => "dsc: $host_arch not in arch list or does not match any arch wildcards: $dscarchs -- skipping", status => "skipped", failstage => "arch-check"); return 0; } } - debug("Arch check ok ($host_arch included in $dscarchs)\n"); - - $self->log_subsubsection("Check dependencies"); - - $self->set('Build Depends', $build_depends); - $self->set('Build Depends Arch', $build_depends_arch); - $self->set('Build Depends Indep', $build_depends_indep); - $self->set('Build Conflicts', $build_conflicts); - $self->set('Build Conflicts Arch', $build_conflicts_arch); - $self->set('Build Conflicts Indep', $build_conflicts_indep); + $self->log("Arch check ok ($host_arch included in $dscarchs)\n"); return 1; } @@ -1267,6 +1338,10 @@ } elsif ($stage eq "chroot-setup-commands") { $self->log_subsection("Chroot Setup Commands"); $chroot = 1; + } elsif ($stage eq "chroot-update-failed-commands") { + $self->log_subsection("Chroot-update Install Failed Commands"); + $chroot = 1; + $rootuser = 1; } elsif ($stage eq "build-deps-failed-commands") { $self->log_subsection("Build-Deps Install Failed Commands"); $chroot = 1; @@ -1292,25 +1367,40 @@ # Run each command, substituting the various percent escapes (like # %SBUILD_DSC) from the commands to run with the appropriate subsitutions. - my $dsc = $self->get('DSC'); - my $changes = $self->get('Changes File') if ($self->get('Changes File')); - my $hostarch = $self->get('Host Arch') if ($self->get('Host Arch')); + my $hostarch = $self->get('Host Arch'); my $build_dir = $self->get('Build Dir'); - my $pkgbuild_dir = $build_dir . '/' . $self->get('DSC Dir'); my $shell_cmd = "bash -i /dev/tty 2>/dev/tty"; my %percent = ( "%" => "%", - "d" => $dsc, "SBUILD_DSC" => $dsc, - "c" => $changes, "SBUILD_CHANGES" => $changes, "a" => $hostarch, "SBUILD_HOST_ARCH" => $hostarch, "b" => $build_dir, "SBUILD_BUILD_DIR" => $build_dir, - "p" => $pkgbuild_dir, "SBUILD_PKGBUILD_DIR" => $pkgbuild_dir, "s" => $shell_cmd, "SBUILD_SHELL" => $shell_cmd, ); + if ($self->get('Changes File')) { + my $changes = $self->get('Changes File'); + $percent{c} = $changes; + $percent{SBUILD_CHANGES} = $changes; + } + # In case set_version has not been run yet, we do not know the dsc file or + # directory yet. This can happen if the user only specified a source + # package name without a version on the command line. + if ($self->get('DSC Dir')) { + my $dsc = $self->get('DSC'); + $percent{d} = $dsc; + $percent{SBUILD_DSC} = $dsc; + my $pkgbuild_dir = $build_dir . '/' . $self->get('DSC Dir'); + $percent{p} = $pkgbuild_dir; + $percent{SBUILD_PKGBUILD_DIR} = $pkgbuild_dir; + } if ($chroot == 0) { - my $chroot_dir = $self->get('Chroot Dir'); + my $chroot_dir = $self->get('Session')->get('Location'); $percent{r} = $chroot_dir; $percent{SBUILD_CHROOT_DIR} = $chroot_dir; + # the %SBUILD_CHROOT_EXEC escape is only defined when the command is + # to be run outside the chroot + my $exec_string = $self->get('Session')->get_internal_exec_string(); + $percent{e} = $exec_string; + $percent{SBUILD_CHROOT_EXEC} = $exec_string; } # Our escapes pattern, with longer escapes first, then sorted lexically. my $keyword_pat = join("|", @@ -1320,6 +1410,9 @@ my $substitute = sub { foreach(@_) { + if (/\%SBUILD_CHROOT_DIR/ || /\%r/) { + $self->log_warning("The %SBUILD_CHROOT_DIR and %r percentage escapes are deprecated and should not be used anymore. Please use %SBUILD_CHROOT_EXEC or %e instead."); + } s{ # Match a percent followed by a valid keyword \%($keyword_pat) @@ -1359,23 +1452,35 @@ sub run_lintian { my $self = shift; + my $session = $self->get('Session'); return 1 unless ($self->get_conf('RUN_LINTIAN')); + if (!defined($session)) { + $self->log_error("Session is undef. Cannot run lintian.\n"); + return 0; + } + $self->log_subsubsection("lintian"); - my $build_dir = $self->get('Chroot Build Dir'); + my $build_dir = $self->get('Build Dir'); my $resolver = $self->get('Dependency Resolver'); my $lintian = $self->get_conf('LINTIAN'); + my $changes = $self->get_changes($build_dir); + if (!defined($changes)) { + $self->log_error(".changes is undef. Cannot run lintian.\n"); + return 0; + } + my @lintian_command = ($lintian); push @lintian_command, @{$self->get_conf('LINTIAN_OPTIONS')} if ($self->get_conf('LINTIAN_OPTIONS')); - push @lintian_command, $self->get_changes($build_dir); + push @lintian_command, $changes; $resolver->add_dependencies('LINTIAN', 'lintian', "", "", "", "", ""); return 1 unless $resolver->install_core_deps('lintian', 'LINTIAN'); - $self->get('Session')->run_command( + $session->run_command( { COMMAND => \@lintian_command, PRIORITY => 0, DIR => $self->get('Build Dir') @@ -1442,9 +1547,10 @@ my $dscfile = $self->get('DSC File'); my $dscdir = $self->get('DSC Dir'); my $pkg = $self->get('Package'); - my $build_dir = $self->get('Chroot Build Dir'); + my $build_dir = $self->get('Build Dir'); my $host_arch = $self->get('Host Arch'); my $build_arch = $self->get('Build Arch'); + my $session = $self->get('Session'); my( $rv, $changes ); local( *PIPE, *F, *F2 ); @@ -1457,100 +1563,111 @@ $tmpunpackdir =~ s/_/-/; $tmpunpackdir = "$build_dir/$tmpunpackdir"; + $dscdir = "$build_dir/$dscdir"; + $self->log_subsubsection("Unpack source"); - if (-d "$build_dir/$dscdir" && -l "$build_dir/$dscdir") { + if ($session->test_directory($dscdir) && $session->test_symlink($dscdir)) { # if the package dir already exists but is a symlink, complain - $self->log("Cannot unpack source: a symlink to a directory with the\n". + $self->log_error("Cannot unpack source: a symlink to a directory with the\n". "same name already exists.\n"); return 0; } - if (! -d "$build_dir/$dscdir") { + if (!$session->test_directory($dscdir)) { $self->set('Sub Task', "dpkg-source"); - $self->get('Session')->run_command( - { COMMAND => [$self->get_conf('DPKG_SOURCE'), - '-x', $dscfile, $dscdir], - USER => $self->get_conf('BUILD_USER'), - PRIORITY => 0}); + $session->run_command({ + COMMAND => [$self->get_conf('DPKG_SOURCE'), + '-x', $dscfile, $dscdir], + USER => $self->get_conf('BUILD_USER'), + DIR => $build_dir, + PRIORITY => 0}); if ($?) { - $self->log("FAILED [dpkg-source died]\n"); + $self->log_error("FAILED [dpkg-source died]\n"); Sbuild::Exception::Build->throw(error => "FAILED [dpkg-source died]", failstage => "unpack"); } - $self->get('Session')->run_command( - { COMMAND => ['chmod', '-R', 'g-s,go+rX', $dscdir], - USER => $self->get_conf('BUILD_USER'), - PRIORITY => 0}); - if ($?) { - $self->log("chmod -R g-s,go+rX $dscdir failed.\n"); + if (!$session->chmod($dscdir, 'g-s,go+rX', { RECURSIVE => 1 })) { + $self->log_error("chmod -R g-s,go+rX $dscdir failed.\n"); Sbuild::Exception::Build->throw(error => "chmod -R g-s,go+rX $dscdir failed", failstage => "unpack"); } - - $dscdir = "$build_dir/$dscdir" } else { - $dscdir = "$build_dir/$dscdir"; - $self->log_subsubsection("Check unpacked source"); # check if the unpacked tree is really the version we need - $dscdir = $self->get('Session')->strip_chroot_path($dscdir); - my $pipe = $self->get('Session')->pipe_command( + my $clog = $session->read_command( { COMMAND => ['dpkg-parsechangelog'], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0, DIR => $dscdir}); - $self->set('Sub Task', "dpkg-parsechangelog"); - - my $clog = ""; - while(<$pipe>) { - $clog .= $_; - } - close($pipe); - if ($?) { - $self->log("FAILED [dpkg-parsechangelog died]\n"); - Sbuild::Exception::Build->throw(error => "FAILED [dpkg-parsechangelog died]", + if (!$clog) { + $self->log_error("unable to read from dpkg-parsechangelog"); + Sbuild::Exception::Build->throw(error => "unable to read from dpkg-parsechangelog", failstage => "check-unpacked-version"); } + $self->set('Sub Task', "dpkg-parsechangelog"); + if ($clog !~ /^Version:\s*(.+)\s*$/mi) { - $self->log("dpkg-parsechangelog didn't print Version:\n"); + $self->log_error("dpkg-parsechangelog didn't print Version:\n"); Sbuild::Exception::Build->throw(error => "dpkg-parsechangelog didn't print Version:", failstage => "check-unpacked-version"); } } $self->log_subsubsection("Check disc space"); - my $current_usage = `du -k -s "$dscdir"`; + chomp(my $current_usage = $session->read_command({ COMMAND => ["du", "-k", "-s", "$dscdir"]})); + if ($?) { + $self->log_error("du exited with non-zero exit status $?"); + Sbuild::Exception::Build->throw(error => "du exited with non-zero exit status $?", failstage => "check-space"); + } $current_usage =~ /^(\d+)/; $current_usage = $1; if ($current_usage) { - my $free = df($dscdir); + my $pipe = $session->pipe_command({ COMMAND => ["df", "-k", "$dscdir"]}); + my $free; + while (<$pipe>) { + $free = (split /\s+/)[3]; + } + close $pipe; + if ($?) { + $self->log_error("df exited with non-zero exit status $?"); + Sbuild::Exception::Build->throw(error => "df exited with non-zero exit status $?", failstage => "check-space"); + } if ($free < 2*$current_usage && $self->get_conf('CHECK_SPACE')) { Sbuild::Exception::Build->throw(error => "Disc space is probably not sufficient for building.", - info => "Source needs $current_usage KiB, while $free KiB is free.)", - failstage => "check-space"); + info => "Source needs $current_usage KiB, while $free KiB is free.)", + failstage => "check-space"); } else { $self->log("Sufficient free space for build\n"); } } - my $cpipe = $self->get('Session')->pipe_command( + my $clogpipe = $session->pipe_command( { COMMAND => ['dpkg-parsechangelog'], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0, - DIR => $self->get('Session')->strip_chroot_path($dscdir) }); - my $clog = do { local $/; <$cpipe> }; - close($cpipe); - if ($?) { - $self->log("FAILED [dpkg-parsechangelog died]\n"); - return 0; + DIR => $dscdir }); + if (!$clogpipe) { + $self->log_error("unable to read from dpkg-parsechangelog"); + Sbuild::Exception::Build->throw(error => "unable to read from dpkg-parsechangelog", + failstage => "check-unpacked-version"); + } + + my $clog = Dpkg::Control->new(type => CTRL_CHANGELOG); + if (!$clog->parse($clogpipe, "$dscdir/debian/changelog")) { + $self->log_error("unable to parse debian/changelog"); + Sbuild::Exception::Build->throw(error => "unable to parse debian/changelog", + failstage => "check-unpacked-version"); } - my ($name) = $clog =~ /^Source:\s*(.*)$/m; - my ($version) = $clog =~ /^Version:\s*(.*)$/m; - my ($dists) = $clog =~ /^Distribution:\s*(.*)$/m; - my ($urgency) = $clog =~ /^Urgency:\s*(.*)$/m; - my ($date) = $clog =~ /^Date:\s*(.*)$/m; + close($clogpipe); + + my $name = $clog->{Source}; + my $version = $clog->{Version}; + my $dists = $clog->{Distribution}; + my $urgency = $clog->{Urgency}; + my $date = $clog->{Date}; + if ($dists ne $self->get_conf('DISTRIBUTION')) { $self->build_log_colour('yellow', "^Distribution: " . $self->get_conf('DISTRIBUTION') . "\$"); @@ -1564,49 +1681,50 @@ } $self->log_subsubsection("Hack binNMU version"); - if (open( F, "<$dscdir/debian/changelog" )) { - my $text = do { local $/; }; - close( F ); + my $text = $session->read_file("$dscdir/debian/changelog"); - my $NMUversion = $self->get('Version'); - if (!open( F, ">$dscdir/debian/changelog" )) { - $self->log("Can't open debian/changelog for binNMU hack: $!\n"); - Sbuild::Exception::Build->throw(error => "Can't open debian/changelog for binNMU hack: $!", - failstage => "hack-binNMU"); - } - $dists = $self->get_conf('DISTRIBUTION'); - - print F "$name ($NMUversion) $dists; urgency=low, binary-only=yes\n\n"; - if ($self->get_conf('APPEND_TO_VERSION')) { - print F " * Append ", $self->get_conf('APPEND_TO_VERSION'), - " to version number; no source changes\n"; - } - if ($self->get_conf('BIN_NMU')) { - print F " * Binary-only non-maintainer upload for $host_arch; ", - "no source changes.\n"; - print F " * ", join( " ", split( "\n", $self->get_conf('BIN_NMU') )), "\n"; - } - print F "\n"; + if (!$text) { + $self->log_error("Can't open debian/changelog -- no binNMU hack!\n"); + Sbuild::Exception::Build->throw(error => "Can't open debian/changelog -- no binNMU hack: $!!", + failstage => "hack-binNMU"); + } - print F " -- " . $self->get_conf('MAINTAINER_NAME') . " $date\n\n"; - print F $text; - close( F ); - $self->log("Created changelog entry for binNMU version $NMUversion\n"); + my $NMUversion = $self->get('Version'); + + my $clogpipe = $session->get_write_file_handle("$dscdir/debian/changelog"); + + if (!$clogpipe) { + $self->log_error("Can't open debian/changelog for binNMU hack: $!\n"); + Sbuild::Exception::Build->throw(error => "Can't open debian/changelog for binNMU hack: $!", + failstage => "hack-binNMU"); } - else { - $self->log("Can't open debian/changelog -- no binNMU hack!\n"); - Sbuild::Exception::Build->throw(error => "Can't open debian/changelog -- no binNMU hack: $!!", - failstage => "hack-binNMU"); + $dists = $self->get_conf('DISTRIBUTION'); + + print $clogpipe "$name ($NMUversion) $dists; urgency=low, binary-only=yes\n\n"; + if ($self->get_conf('APPEND_TO_VERSION')) { + print $clogpipe " * Append ", $self->get_conf('APPEND_TO_VERSION'), + " to version number; no source changes\n"; + } + if ($self->get_conf('BIN_NMU')) { + print $clogpipe " * Binary-only non-maintainer upload for $host_arch; ", + "no source changes.\n"; + print $clogpipe " * ", join( " ", split( "\n", $self->get_conf('BIN_NMU') )), "\n"; } + print $clogpipe "\n"; + + print $clogpipe " -- " . $self->get_conf('MAINTAINER_NAME') . " $date\n\n"; + print $clogpipe $text; + close($clogpipe); + $self->log("Created changelog entry for binNMU version $NMUversion\n"); } - if (-f "$dscdir/debian/files") { + if ($session->test_regular_file("$dscdir/debian/files")) { local( *FILES ); my @lines; - open( FILES, "<$dscdir/debian/files" ); - chomp( @lines = ); - close( FILES ); + my $FILES = $session->get_read_file_handle("$dscdir/debian/files"); + chomp( @lines = <$FILES> ); + close( $FILES ); $self->log_warning("After unpacking, there exists a file debian/files with the contents:\n"); @@ -1625,12 +1743,8 @@ # Build tree not writable during build (except for the sbuild # user performing the build). - $self->get('Session')->run_command( - { COMMAND => ['chmod', '-R', 'go-w', $self->get('Build Dir')], - USER => 'root', - PRIORITY => 0}); - if ($?) { - $self->log("chmod og-w " . $self->get('Build Dir') . " failed.\n"); + if (!$session->chmod($self->get('Build Dir'), 'go-w', { RECURSIVE => 1 })) { + $self->log_error("chmod og-w " . $self->get('Build Dir') . " failed.\n"); return 0; } @@ -1642,14 +1756,9 @@ $self->set('Build Start Time', time); $self->set('Build End Time', $self->get('Build Start Time')); - my $bdir = $self->get('Session')->strip_chroot_path($dscdir); - if (-f "$self->{'Chroot Dir'}/etc/ld.so.conf" && - ! -r "$self->{'Chroot Dir'}/etc/ld.so.conf") { - $self->get('Session')->run_command( - { COMMAND => ['chmod', 'a+r', '/etc/ld.so.conf'], - USER => 'root', - PRIORITY => 0, - DIR => '/' }); + if ($session->test_regular_file("/etc/ld.so.conf") && + ! $session->test_regular_file_readable("/etc/ld.so.conf")) { + $session->chmod('/etc/ld.so.conf', 'a+r'); $self->log_subsubsection("Fix ld.so"); $self->log("ld.so.conf was not readable! Fixed.\n"); @@ -1729,23 +1838,24 @@ # Dump build environment $self->log_subsubsection("User Environment"); { - my $pipe = $self->get('Session')->pipe_command( + my $envcmd = $session->read_command( { COMMAND => ['env'], ENV => \%buildenv, ENV_FILTER => \@env_filter, USER => $self->get_conf('BUILD_USER'), SETSID => 1, PRIORITY => 0, - DIR => $bdir + DIR => $dscdir }); + if (!$envcmd) { + $self->log_error("unable to open pipe"); + Sbuild::Exception::Build->throw(error => "unable to open pipe", + failstage => "dump-build-env"); + } - my (@lines) = <$pipe>; - close($pipe); - - @lines=sort(@lines); + my @lines=sort(split /\n/, $envcmd); foreach my $line (@lines) { - # $line contains a trailing newline, so don't add one. - $self->log($line); + $self->log("$line\n"); } } @@ -1758,11 +1868,16 @@ USER => $self->get_conf('BUILD_USER'), SETSID => 1, PRIORITY => 0, - DIR => $bdir, + DIR => $dscdir, STREAMERR => \*STDOUT, }; - my $pipe = $self->get('Session')->pipe_command($command); + my $pipe = $session->pipe_command($command); + if (!$pipe) { + $self->log_error("unable to open pipe"); + Sbuild::Exception::Build->throw(error => "unable to open pipe", + failstage => "dpkg-buildpackage"); + } $self->set('Sub Task', "dpkg-buildpackage"); @@ -1779,7 +1894,7 @@ local $SIG{'ALRM'} = sub { my $pid = $command->{'PID'}; my $signal = ($timed_out > 0) ? "KILL" : "TERM"; - $self->get('Session')->run_command( + $session->run_command( { COMMAND => ['perl', '-e', "kill( \"$signal\", -$pid )"], @@ -1799,7 +1914,7 @@ $last_time = time; if ($self->get('ABORT')) { my $pid = $command->{'PID'}; - $self->get('Session')->run_command( + $session->run_command( { COMMAND => ['perl', '-e', "kill( \"TERM\", -$pid )"], @@ -1815,7 +1930,7 @@ my $i; for( $i = 0; $i < $timed_out; ++$i ) { - $self->log("Build killed with signal " . $timeout_sigs[$i] . + $self->log_error("Build killed with signal " . $timeout_sigs[$i] . " after " . int($timeout_times[$i]/60) . " minutes of inactivity\n"); } @@ -1835,7 +1950,7 @@ failstage => "run-finished-build-commands"); } - my @space_files = ("$dscdir"); + my @space_files = (); $self->log_subsubsection("Finished"); if ($rv) { @@ -1843,29 +1958,25 @@ } else { $self->log_info("Built successfully\n"); - if (-r "$dscdir/debian/files" && $self->get('Chroot Build Dir')) { + if ($session->test_regular_file_readable("$dscdir/debian/files")) { my @files = $self->debian_files_list("$dscdir/debian/files"); foreach (@files) { - if (! -f "$build_dir/$_") { + if (!$session->test_regular_file("$build_dir/$_")) { $self->log_error("Package claims to have built ".basename($_).", but did not. This is a bug in the packaging.\n"); next; } if (/_all.u?deb$/ and not $self->get_conf('BUILD_ARCH_ALL')) { $self->log_error("Package builds ".basename($_)." when binary-indep target is not called. This is a bug in the packaging.\n"); - unlink("$build_dir/$_"); + $session->unlink("$build_dir/$_"); next; } } } # Restore write access to build tree now build is complete. - $self->get('Session')->run_command( - { COMMAND => ['chmod', '-R', 'g+w', $self->get('Build Dir')], - USER => 'root', - PRIORITY => 0}); - if ($?) { - $self->log("chmod g+w " . $self->get('Build Dir') . " failed.\n"); + if (!$session->chmod($self->get('Build Dir'), 'g+w', { RECURSIVE => 1 })) { + $self->log_error("chmod g+w " . $self->get('Build Dir') . " failed.\n"); return 0; } @@ -1879,32 +1990,51 @@ $self->log_subsection("Changes"); $changes = $self->get_changes($build_dir); + if (!defined($changes)) { + $self->log_error(".changes is undef. Cannot copy build results.\n"); + return 0; + } my @cfiles; - if (-r "$build_dir/$changes") { + if ($session->test_regular_file_readable("$build_dir/$changes")) { my(@do_dists, @saved_dists); $self->log_subsubsection("$changes:"); - open( F, "<$build_dir/$changes" ); + my $F = $session->get_read_file_handle("$build_dir/$changes"); + if (!$F) { + $self->log_error("cannot get read file handle for $build_dir/$changes\n"); + Sbuild::Exception::Build->throw(error => "cannot get read file handle for $build_dir/$changes", + failstage => "parse-changes"); + } + my $pchanges = Dpkg::Control->new(type => CTRL_FILE_CHANGES); + if (!$pchanges->parse($F, "$build_dir/$changes")) { + $self->log_error("cannot parse $build_dir/$changes\n"); + Sbuild::Exception::Build->throw(error => "cannot parse $build_dir/$changes", + failstage => "parse-changes"); + } + close($F); + + + if ($self->get_conf('OVERRIDE_DISTRIBUTION')) { + $pchanges->{Distribution} = $self->get_conf('DISTRIBUTION'); + } + + my $checksums = Dpkg::Checksums->new(); + $checksums->add_from_control($pchanges); + + push(@cfiles, $checksums->get_files()); + my $sys_build_dir = $self->get_conf('BUILD_DIR'); - if (open( F2, ">$sys_build_dir/$changes.new" )) { - while( ) { - if (/^Distribution:\s*(.*)\s*$/ and $self->get_conf('OVERRIDE_DISTRIBUTION')) { - $self->log("Distribution: " . $self->get_conf('DISTRIBUTION') . "\n"); - print F2 "Distribution: " . $self->get_conf('DISTRIBUTION') . "\n"; - } - else { - print F2 $_; - while (length $_ > 989) - { - my $index = rindex($_,' ',989); - $self->log(substr ($_,0,$index) . "\n"); - $_ = ' ' . substr ($_,$index+1); - } - $self->log($_); - if (/^ [a-z0-9]{32} /) { - push(@cfiles, (split( /\s+/, $_ ))[5] ); - } + if (!open( F2, ">$sys_build_dir/$changes.new" )) { + $self->log("Cannot create $sys_build_dir/$changes.new: $!\n"); + $self->log("Distribution field may be wrong!!!\n"); + if ($build_dir) { + if(!$session->copy_from_chroot("$build_dir/$changes", ".")) { + $self->log_error("Could not copy $build_dir/$changes to .\n"); } } + } else { + $pchanges->output(\*STDOUT); + $pchanges->output(\*F2); + close( F2 ); rename("$sys_build_dir/$changes.new", "$sys_build_dir/$changes") or $self->log("$sys_build_dir/$changes.new could not be " . @@ -1913,18 +2043,9 @@ unlink("$build_dir/$changes") if $build_dir; } - else { - $self->log("Cannot create $sys_build_dir/$changes.new: $!\n"); - $self->log("Distribution field may be wrong!!!\n"); - if ($build_dir) { - system "mv", "-f", "$build_dir/$changes", "." - and $self->log_error("Could not move ".basename($_)." to .\n"); - } - } - close( F ); } else { - $self->log("Can't find $changes -- can't dump info\n"); + $self->log_error("Can't find $changes -- can't dump info\n"); } $self->log_subsection("Package contents"); @@ -1935,28 +2056,29 @@ next if $deb !~ /(\Q$host_arch\E|all)\.(udeb|deb)$/; $self->log_subsubsection("$_"); - if (!open( PIPE, "dpkg --info $deb 2>&1 |" )) { - $self->log("Can't spawn dpkg: $! -- can't dump info\n"); + my $dpkg_info = $session->read_command({COMMAND => ["dpkg", "--info", $deb]}); + if (!$dpkg_info) { + $self->log_error("Can't spawn dpkg: $! -- can't dump info\n"); } else { - $self->log($_) while( ); - close( PIPE ) or ($rv = 1); + $self->log($dpkg_info); } $self->log("\n"); - if (!open( PIPE, "dpkg --contents $deb 2>&1 | sort -k6 |" )) { - $self->log("Can't spawn dpkg: $! -- can't dump info\n"); + my $dpkg_contents = $session->read_command({COMMAND => ["sh", "-c", "dpkg --contents $deb 2>&1 | sort -k6"]}); + if (!$dpkg_contents) { + $self->log_error("Can't spawn dpkg: $! -- can't dump info\n"); } else { - $self->log($_) while( ); - close( PIPE ) or ($rv = 1); + $self->log($dpkg_contents); } $self->log("\n"); } foreach (@cfiles) { push( @space_files, $self->get_conf('BUILD_DIR') . "/$_"); - system "mv", "-f", "$build_dir/$_", $self->get_conf('BUILD_DIR') - and $self->log_error("Could not move $_ to .\n"); + if (!$session->copy_from_chroot("$build_dir/$_", $self->get_conf('BUILD_DIR'))) { + $self->log_error("Could not copy $build_dir/$_ to " . $self->get_conf('BUILD_DIR') . "\n"); + } } } @@ -1993,6 +2115,28 @@ my $self=shift; my $path=shift; my $changes; + my $session = $self->get('Session'); + + return if not defined($session); + + if ($session->test_regular_file_readable($path . '/' . $self->get('Package_SVersion') . "_source.changes")) { + $changes = $self->get('Package_SVersion') . "_source.changes"; + } + elsif ($session->test_regular_file_readable($path . '/' . $self->get('Package_SVersion') . "_all.changes")) { + $changes = $self->get('Package_SVersion') . "_all.changes"; + } + else { + $changes = $self->get('Package_SVersion') . '_' . $self->get('Host Arch') . '.changes'; + } + return $changes; +} + +# same as get_changes but checks for the .changes file on the host running +# sbuild instead of inside the chroot +sub get_changes_host { + my $self=shift; + my $path=shift; + my $changes; if ( -r $path . '/' . $self->get('Package_SVersion') . "_source.changes") { $changes = $self->get('Package_SVersion') . "_source.changes"; @@ -2011,22 +2155,39 @@ my @files = @_; my $sum = 0; + my $dscdir = $self->get('DSC Dir'); + my $build_dir = $self->get('Build Dir'); + my $pkgbuilddir = "$build_dir/$dscdir"; + + my $pkgbuilddirspc = $self->get('Session')->read_command( + { COMMAND => ['du', '-k', '-s', $pkgbuilddir], + USER => $self->get_conf('USERNAME'), + PRIORITY => 0, + DIR => '/'}); + + if (!$pkgbuilddirspc) { + $self->log_error("Cannot determine space needed (du failed)\n"); + } + if ($pkgbuilddirspc !~ /^(\d+)/) { + $self->log_error("Cannot determine space needed (unexpected du output): $pkgbuilddirspc\n"); + } + $sum += $1; + foreach (@files) { - my $pipe = $self->get('Host')->pipe_command( + my $space = $self->get('Host')->read_command( { COMMAND => ['du', '-k', '-s', $_], USER => $self->get_conf('USERNAME'), PRIORITY => 0, DIR => '/'}); - if (!$pipe) { - $self->log("Cannot determine space needed (du failed): $!\n"); - return; + if (!$space) { + $self->log_error("Cannot determine space needed (du failed): $!\n"); + next; } - while(<$pipe>) { - next if !/^(\d+)/; - $sum += $1; + if ($pkgbuilddirspc !~ /^(\d+)/) { + $self->log_error("Cannot determine space needed (unexpected du output): $space\n"); } - close($pipe); + $sum += $1; } $self->set('This Time', $self->get('Pkg End Time') - $self->get('Pkg Start Time')); @@ -2105,8 +2266,16 @@ $self->add_stat('Job', $self->get('Job')); $self->add_stat('Package', $self->get('Package')); - $self->add_stat('Version', $self->get('Version')); - $self->add_stat('Source-Version', $self->get('OVersion')); + # If the package fails early, then the version might not yet be known. + # This can happen if the user only specified a source package name on the + # command line and then the version will only be known after the source + # package was successfully downloaded. + if ($self->get('Version')) { + $self->add_stat('Version', $self->get('Version')); + } + if ($self->get('OVersion')) { + $self->add_stat('Source-Version', $self->get('OVersion')); + } $self->add_stat('Machine Architecture', $self->get_conf('ARCH')); $self->add_stat('Host Architecture', $self->get('Host Arch')); $self->add_stat('Build Architecture', $self->get('Build Arch')); @@ -2184,15 +2353,17 @@ my @list; debug("Parsing $files\n"); + my $session = $self->get('Session'); - if (-r $files && open( FILES, "<$files" )) { - while () { + my $pipe = $session->get_read_file_handle($files); + if ($pipe) { + while (<$pipe>) { chomp; my $f = (split( /\s+/, $_ ))[0]; push( @list, "$f" ); debug(" $f\n"); } - close( FILES ) or $self->log("Failed to close $files\n") && return 1; + close( $pipe ) or $self->log_error("Failed to close $files\n") && return 1; } return @list; @@ -2202,18 +2373,16 @@ sub chroot_arch { my $self = shift; - my $pipe = $self->get('Session')->pipe_command( + chomp(my $chroot_arch = $self->get('Session')->read_command( { COMMAND => ['dpkg', '--print-architecture'], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0, - DIR => '/' }) || return undef; - - chomp(my $chroot_arch = <$pipe>); - close($pipe); + DIR => '/' })); - Sbuild::Exception::Build->throw(error => "Can't determine architecture of chroot: $!", - failstage => "chroot-arch") - if ($? || !defined($chroot_arch)); + if (!$chroot_arch) { + Sbuild::Exception::Build->throw(error => "Can't determine architecture of chroot: $!", + failstage => "chroot-arch") + } return $chroot_arch; } @@ -2248,9 +2417,15 @@ my $colour_prefix = '__SBUILD_COLOUR_' . $$ . ':'; $self->set('COLOUR_PREFIX', $colour_prefix); - my $filename = $self->get_conf('LOG_DIR') . '/' . - $self->get('Package_SVersion') . '_' . - $self->get('Host Arch') . "-$date"; + my $filename = $self->get_conf('LOG_DIR') . '/'; + # we might not know the pkgname_ver string if the user only specified a + # package name without version + if ($self->get('Package_SVersion')) { + $filename .= $self->get('Package_SVersion'); + } else { + $filename .= $self->get('Package'); + } + $filename .= '_' . $self->get('Host Arch') . "-$date"; $filename .= ".build" if $self->get_conf('SBUILD_MODE') ne 'buildd'; open($saved_stdout, ">&STDOUT") or warn "Can't redirect stdout\n"; @@ -2268,8 +2443,6 @@ $SIG{'QUIT'} = 'IGNORE'; $SIG{'PIPE'} = 'IGNORE'; - $PROGRAM_NAME = 'package log for ' . $self->get('Package_SVersion') . '_' . $self->get('Host Arch'); - $saved_stdout->autoflush(1); if (!$self->get_conf('NOLOG') && $self->get_conf('LOG_DIR_AVAILABLE')) { @@ -2291,10 +2464,16 @@ if (Cwd::abs_path($self->get_conf('BUILD_DIR')) eq Cwd::abs_path(dirname($filename))) { $symlinktarget = basename($filename) } - $self->log_symlink($symlinktarget, - $self->get_conf('BUILD_DIR') . '/' . - $self->get('Package_SVersion') . '_' . - $self->get('Host Arch') . ".build"); + my $symlinkname = $self->get_conf('BUILD_DIR') . '/'; + # we might not know the pkgname_ver string if the user only specified a + # package name without version + if ($self->get('Package_SVersion')) { + $symlinkname .= $self->get('Package_SVersion'); + } else { + $symlinkname .= $self->get('Package'); + } + $symlinkname .= '_' . $self->get('Host Arch') . ".build"; + $self->log_symlink($symlinktarget, $symlinkname); } } @@ -2378,8 +2557,11 @@ $arch_string = 'CROSS host=' . $self->get('Host Arch') . '/build=' . $self->get('Build Arch') if ($self->get('Host Arch') ne $self->get('Build Arch')); - my $head1 = $self->get('Package') . ' ' . $self->get('Version') . - ' (' . $arch_string . ') '; + my $head1 = $self->get('Package'); + if ($self->get('Version')) { + $head1 .= ' ' . $self->get('Version'); + } + $head1 .= ' (' . $arch_string . ') '; my $head2 = strftime("%d %b %Y %H:%M", localtime($self->get('Pkg Start Time'))); my $head = $head1 . ' ' x (80 - 4 - length($head1) - length($head2)) . @@ -2387,8 +2569,10 @@ $self->log_section($head); $self->log("Package: " . $self->get('Package') . "\n"); - $self->log("Version: " . $self->get('Version') . "\n"); - $self->log("Source Version: " . $self->get('OVersion') . "\n"); + if ($self->get('Version') && $self->get('OVersion')) { + $self->log("Version: " . $self->get('Version') . "\n"); + $self->log("Source Version: " . $self->get('OVersion') . "\n"); + } $self->log("Distribution: " . $self->get_conf('DISTRIBUTION') . "\n"); $self->log("Machine Architecture: " . $self->get_conf('ARCH') . "\n"); $self->log("Host Architecture: " . $self->get('Host Arch') . "\n"); @@ -2433,13 +2617,21 @@ my $build_dir = $self->get_conf('BUILD_DIR'); my $changes; $self->log(sprintf("Signature with key '%s' requested:\n", $key_id)); - $changes = $self->get_changes($build_dir); - system "debsign", "-k$key_id", "$build_dir/$changes"; + $changes = $self->get_changes_host($build_dir); + if (!defined($changes)) { + $self->log_error(".changes is undef. Cannot sign .changes.\n"); + } else { + system('debsign', "-k$key_id", '--', "$build_dir/$changes"); + } } } - my $subject = "Log for " . $self->get_status() . - " build of " . $self->get('Package_Version'); + my $subject = "Log for " . $self->get_status() . " build of "; + if ($self->get('Package_Version')) { + $subject .= $self->get('Package_Version'); + } else { + $subject .= $self->get('Package'); + } if ($self->get_conf('BUILD_SOURCE') && !$self->get_conf('BUILD_ARCH_ALL') && !$self->get_conf('BUILD_ARCH_ANY')) { $subject .= " source"; @@ -2546,7 +2738,7 @@ ); } my $build_dir = $self->get_conf('BUILD_DIR'); - my $changes = $self->get_changes($build_dir); + my $changes = $self->get_changes_host($build_dir); if ($self->get_status() eq 'successful' && -r "$build_dir/$changes") { my $log_part = MIME::Lite->new( Type => 'text/plain', diff -Nru sbuild-0.67.0/lib/Sbuild/ChrootADT.pm sbuild-0.69.0/lib/Sbuild/ChrootADT.pm --- sbuild-0.67.0/lib/Sbuild/ChrootADT.pm 1970-01-01 00:00:00.000000000 +0000 +++ sbuild-0.69.0/lib/Sbuild/ChrootADT.pm 2016-04-30 05:45:34.097402104 +0000 @@ -0,0 +1,229 @@ +# +# Chroot.pm: chroot library for sbuild +# Copyright © 2005 Ryan Murray +# Copyright © 2005-2008 Roger Leigh +# Copyright © 2008 Simon McVittie +# +# 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, see +# . +# +####################################################################### + +package Sbuild::ChrootADT; + +use strict; +use warnings; + +use IPC::Open2; +use Sbuild qw(shellescape); + +BEGIN { + use Exporter (); + use Sbuild::Chroot; + our (@ISA, @EXPORT); + + @ISA = qw(Exporter Sbuild::Chroot); + + @EXPORT = qw(); +} + +sub new { + my $class = shift; + my $conf = shift; + my $chroot_id = shift; + + my $self = $class->SUPER::new($conf, $chroot_id); + bless($self, $class); + + return $self; +} + +sub begin_session { + my $self = shift; + my $chroot = $self->get('Chroot ID'); + + # Don't use namespaces in compat mode. + if ($Sbuild::Sysconfig::compat_mode) { + $chroot =~ s/^[^:]+://msx; + } + + my ($chld_out, $chld_in); + my $pid = open2( + $chld_out, $chld_in, + $self->get_conf('ADT_VIRT_SERVER'), + @{$self->get_conf('ADT_VIRT_SERVER_OPTIONS')}, + $chroot); + + if (!$pid) { + print STDERR "Chroot setup failed\n"; + return 0; + } + + chomp (my $status = <$chld_out>); + + if (! defined $status || $status ne "ok") { + print STDERR "adt-virt server returned unexpected value: $status\n"; + kill 'KILL', $pid; + return 0; + } + + print $chld_in "open\n"; + + chomp ($status = <$chld_out>); + + my $adt_session; + if ($status =~ /^ok (.*)$/) { + $adt_session = $1; + $self->set('Session ID', $adt_session); + } else { + print STDERR "adt-virt server: cannot open: $status\n"; + kill 'KILL', $pid; + return 0; + } + + print STDERR "Setting up chroot $chroot (session id $adt_session)\n" + if $self->get_conf('DEBUG'); + + print $chld_in "capabilities\n"; + + chomp ($status = <$chld_out>); + + my @capabilities; + if ($status =~ /^ok (.*)$/) { + @capabilities = split /\s+/, $1; + } else { + print STDERR "adt-virt server: cannot capabilities: $status\n"; + kill 'KILL', $pid; + return 0; + } + + if (! grep {$_ eq "root-on-testbed"} @capabilities) { + print STDERR "adt-virt server: capability root-on-testbed missing\n"; + kill 'KILL', $pid; + return 0; + } + + # TODO: also test "revert" capability + + print $chld_in "print-execute-command\n"; + + chomp ($status = <$chld_out>); + + my $exec_cmd; + if ($status =~ /^ok (.*)$/) { + $exec_cmd = $1; + } else { + print STDERR "adt-virt server: cannot print-execute-command: $status\n"; + kill 'KILL', $pid; + return 0; + } + + my @exec_args = split /,/, $exec_cmd; + + @exec_args = map { s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; $_ } @exec_args; + + $self->set('Location', '/adt-virt-dummy-location'); + $self->set('ADT Pipe In', $chld_in); + $self->set('ADT Pipe Out', $chld_out); + $self->set('ADT Virt PID', $pid); + $self->set('ADT Exec Command', \@exec_args); + + return 0 if !$self->_setup_options(); + + return 1; +} + +sub end_session { + my $self = shift; + + return if $self->get('Session ID') eq ""; + + print STDERR "Cleaning up chroot (session id " . $self->get('Session ID') . ")\n" + if $self->get_conf('DEBUG'); + + my $chld_in = $self->get('ADT Pipe In'); + my $chld_out = $self->get('ADT Pipe Out'); + my $pid = $self->get('ADT Virt PID'); + + print $chld_in "close\n"; + + chomp (my $status = <$chld_out>); + + if ($status ne "ok") { + print STDERR "adt-virt server: cannot close: $status\n"; + return 0; + } + + print $chld_in "quit\n"; + + waitpid $pid, 0; + + if ($?) { + my $child_exit_status = $? >> 8; + print STDERR "adt-virt quit with exit status $child_exit_status\n"; + return 0; + } + + return 1; +} + +sub get_command_internal { + my $self = shift; + my $options = shift; + + # Command to run. If I have a string, use it. Otherwise use the list-ref + my $command = $options->{'INTCOMMAND_STR'} // $options->{'INTCOMMAND'}; + + my $user = $options->{'USER'}; # User to run command under + my $dir; # Directory to use (optional) + $dir = $self->get('Defaults')->{'DIR'} if + (defined($self->get('Defaults')) && + defined($self->get('Defaults')->{'DIR'})); + $dir = $options->{'DIR'} if + defined($options->{'DIR'}) && $options->{'DIR'}; + + if (!defined $user || $user eq "") { + $user = $self->get_conf('USERNAME'); + } + + my @cmdline = (); + + @cmdline = @{$self->get('ADT Exec Command')}; + + if ($user ne "root") { + push @cmdline, "/sbin/runuser", '-u', $user, '--'; + } + + if (defined($dir)) { + my $shelldir = shellescape $dir; + push @cmdline, 'sh', '-c', "cd $shelldir && exec \"\$@\"", 'exec'; + } else { + $dir = '/'; + } + + if (ref $command) { + push @cmdline, @$command; + } else { + push @cmdline, ('/bin/sh', '-c', $command); + $command = [split(/\s+/, $command)]; + } + + $options->{'USER'} = $user; + $options->{'COMMAND'} = $command; + $options->{'EXPCOMMAND'} = \@cmdline; + $options->{'CHDIR'} = undef; + $options->{'DIR'} = $dir; +} + +1; diff -Nru sbuild-0.67.0/lib/Sbuild/ChrootInfoADT.pm sbuild-0.69.0/lib/Sbuild/ChrootInfoADT.pm --- sbuild-0.67.0/lib/Sbuild/ChrootInfoADT.pm 1970-01-01 00:00:00.000000000 +0000 +++ sbuild-0.69.0/lib/Sbuild/ChrootInfoADT.pm 2016-04-28 05:04:30.594584766 +0000 @@ -0,0 +1,69 @@ +# +# ChrootInfo.pm: chroot utility library for sbuild +# Copyright © 2005-2009 Roger Leigh +# +# 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, see +# . +# +####################################################################### + +package Sbuild::ChrootInfoADT; + +use Sbuild::ChrootInfo; +use Sbuild::ChrootADT; + +use strict; +use warnings; + +BEGIN { + use Exporter (); + our (@ISA, @EXPORT); + + @ISA = qw(Exporter Sbuild::ChrootInfo); + + @EXPORT = qw(); +} + +sub new { + my $class = shift; + my $conf = shift; + + my $self = $class->SUPER::new($conf); + bless($self, $class); + + return $self; +} + +sub get_info_all { + my $self = shift; + + my $chroots = {}; + + $self->set('Chroots', $chroots); +} + +sub _create { + my $self = shift; + my $chroot_id = shift; + + my $chroot = undef; + + if (defined($chroot_id)) { + $chroot = Sbuild::ChrootADT->new($self->get('Config'), $chroot_id); + } + + return $chroot; +} + +1; diff -Nru sbuild-0.67.0/lib/Sbuild/ChrootInfoSchroot.pm sbuild-0.69.0/lib/Sbuild/ChrootInfoSchroot.pm --- sbuild-0.67.0/lib/Sbuild/ChrootInfoSchroot.pm 2015-12-25 16:23:28.614723316 +0000 +++ sbuild-0.69.0/lib/Sbuild/ChrootInfoSchroot.pm 2016-04-20 11:06:05.421529866 +0000 @@ -131,6 +131,11 @@ my $tmp = $self->get_info_from_stream(\*CHROOT_DATA); + if (!$tmp) { + close CHROOT_DATA; + return undef; + } + close CHROOT_DATA or die "Can't close schroot pipe getting chroot data"; return $tmp; diff -Nru sbuild-0.67.0/lib/Sbuild/Chroot.pm sbuild-0.69.0/lib/Sbuild/Chroot.pm --- sbuild-0.67.0/lib/Sbuild/Chroot.pm 2015-12-26 10:32:21.796608102 +0000 +++ sbuild-0.69.0/lib/Sbuild/Chroot.pm 2016-04-28 05:04:00.686602490 +0000 @@ -32,6 +32,7 @@ use POSIX; use FileHandle; use File::Temp (); +use File::Basename qw(basename); BEGIN { use Exporter (); @@ -107,16 +108,6 @@ return $value; } -sub strip_chroot_path { - my $self = shift; - my $path = shift; - - my $location = $self->get('Location'); - $path =~ s/^\Q$location\E//; - - return $path; -} - sub log_command { my $self = shift; my $options = shift; @@ -135,6 +126,462 @@ } } +# create a temporary file or directory inside the chroot +sub mktemp { + my $self = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $mktempcmd = ['mktemp']; + + if (defined $options->{'DIRECTORY'} && $options->{'DIRECTORY'}) { + push(@{$mktempcmd}, "-d"); + } + + if (defined $options->{'TEMPLATE'}) { + push(@{$mktempcmd}, $options->{'TEMPLATE'}); + } + + my $pipe = $self->pipe_command({ COMMAND => $mktempcmd, USER => $user, DIR => $dir }); + if (!$pipe) { + $self->log_error("cannot open pipe\n"); + return; + } + chomp (my $tmpdir = do { local $/; <$pipe> }); + close $pipe; + if ($?) { + if (defined $options->{'TEMPLATE'}) { + $self->log_error("cannot run mktemp " . $options->{'TEMPLATE'} . ": $!\n"); + } else { + $self->log_error("cannot run mktemp: $!\n"); + } + return; + } + return $tmpdir; +} + +# copy a file from the outside into the chroot +sub copy_to_chroot { + my $self = shift; + my $source = shift; + my $dest = shift; + my $options = shift; + + # if the destination inside the chroot is a directory, then the file has + # to be copied into that directory with the same filename as outside + if($self->test_directory($dest)) { + $dest .= '/' . (basename $source); + } + + my $pipe = $self->get_write_file_handle($dest, $options); + if (!defined $pipe) { + $self->log_error("get_write_file_handle failed\n"); + return; + } + + local *INFILE; + if(!open(INFILE, "<", $source)) { + $self->log_error("cannot open $source\n"); + close $pipe; + return; + } + + while ( (read (INFILE, my $buffer, 65536)) != 0 ) { + print $pipe $buffer; + } + + close INFILE; + close $pipe; + + return 1; +} + +# copy a file inside the chroot to the outside +sub copy_from_chroot { + my $self = shift; + my $source = shift; + my $dest = shift; + my $options = shift; + + my $pipe = $self->get_read_file_handle($source, $options); + if (!defined $pipe) { + $self->log_error("get_read_file_handle failed\n"); + return; + } + + # if the destination outside the chroot is a directory, then the file has + # to be copied into that directory with the same filename as inside + if (-d $dest) { + $dest .= '/' . (basename $source); + } + + local *OUTFILE; + if(!open(OUTFILE, ">", $dest)) { + $self->log_error("cannot open $dest\n"); + close $pipe; + return; + } + + while ( (read ($pipe, my $buffer, 65536)) != 0 ) { + print OUTFILE $buffer; + } + + close OUTFILE; + close $pipe; + + return 1; +} + +# returns a file handle to read a file inside the chroot +sub get_read_file_handle { + my $self = shift; + my $source = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $pipe = $self->pipe_command({ + COMMAND => [ "sh", "-c", "cat \"$source\"" ], + DIR => $dir, + USER => $user, + PIPE => 'in' + }); + if (!$pipe) { + $self->log_error("cannot open pipe\n"); + return; + } + + return $pipe; +} + +# returns a string with the content of a file inside the chroot +sub read_file { + my $self = shift; + my $source = shift; + my $options = shift; + + my $pipe = $self->get_read_file_handle($source, $options); + if (!defined $pipe) { + $self->log_error("get_read_file_handle failed\n"); + return; + } + + my $content = do { local $/; <$pipe> }; + close $pipe; + + return $content; +} + +# returns a file handle to write to a file inside the chroot +sub get_write_file_handle { + my $self = shift; + my $dest = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $pipe = $self->pipe_command({ + COMMAND => [ "sh", "-c", "cat > \"$dest\"" ], + DIR => $dir, + USER => $user, + PIPE => 'out' + }); + if (!$pipe) { + $self->log_error("cannot open pipe\n"); + return; + } + + return $pipe; +} + +sub read_command { + my $self = shift; + my $options = shift; + + $options->{PIPE} = "in"; + + my $pipe = $self->pipe_command($options); + if (!$pipe) { + $self->log_error("cannot open pipe\n"); + return; + } + + my $content = do { local $/; <$pipe> }; + close $pipe; + + if ($?) { + $self->log_error("read_command failed to execute " . $options->{COMMAND} . "\n"); + return; + } + + return $content; +} + +# writes a string to a file inside the chroot +sub write_file { + my $self = shift; + my $dest = shift; + my $content = shift; + my $options = shift; + + my $pipe = $self->get_write_file_handle($dest, $options); + if (!defined $pipe) { + $self->log_error("get_read_file_handle failed\n"); + return; + } + + print $pipe $content; + close $pipe; + + return 1; +} + +sub write_command { + my $self = shift; + my $content = shift; + my $options = shift; + + $options->{PIPE} = "out"; + + my $pipe = $self->pipe_command($options); + if (!$pipe) { + $self->log_error("cannot open pipe\n"); + return; + } + + if(!print $pipe $content) { + $self->log_error("failed to print to file handle\n"); + close $pipe; + } + + close $pipe; + + if ($?) { + $self->log_error("read_command failed to execute " . $options->{COMMAND} . "\n"); + return; + } + + return 1; +} + +# rename a file inside the chroot +sub rename { + my $self = shift; + my $source = shift; + my $dest = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + $self->run_command({ COMMAND => ["mv", $source, $dest], USER => $user, DIR => $dir}); + if ($?) { + $self->log_error("Can't rename $source to $dest: $!\n"); + return 0; + } + + return 1; +} + +# create a directory inside the chroot +sub mkdir { + my $self = shift; + my $path = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $mkdircmd = [ "mkdir", $path ]; + + if (defined $options->{'PARENTS'} && $options->{'PARENTS'}) { + push(@{$mkdircmd}, "-p"); + } + + if (defined $options->{'MODE'}) { + push(@{$mkdircmd}, "--mode", $options->{'MODE'}); + } + + $self->run_command({ COMMAND => $mkdircmd, USER => $user, DIR => $dir}); + if ($?) { + $self->log_error("Can't mkdir $path: $!\n"); + return 0; + } + + return 1; +} + +sub test_internal { + my $self = shift; + my $path = shift; + my $arg = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + $self->run_command({ COMMAND => [ "test", $arg, $path ], USER => $user, DIR => $dir}); + if ($? eq 0) { + return 1; + } else { + return 0; + } +} + +# test if a path inside the chroot is a directory +sub test_directory { + my $self = shift; + my $path = shift; + my $options = shift; + + return $self->test_internal($path, "-d", $options); +} + +# test if a path inside the chroot is a regular file +sub test_regular_file { + my $self = shift; + my $path = shift; + my $options = shift; + + return $self->test_internal($path, "-f", $options); +} + +# test if a path inside the chroot is a regular readable file +sub test_regular_file_readable { + my $self = shift; + my $path = shift; + my $options = shift; + + return $self->test_internal($path, "-r", $options); +} + +# test if a path inside the chroot is a symlink +sub test_symlink { + my $self = shift; + my $path = shift; + my $options = shift; + + return $self->test_internal($path, "-L", $options); +} + +# remove a file inside the chroot +sub unlink { + my $self = shift; + my $path = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $rmcmd = [ "rm", $path ]; + + if (defined $options->{'RECURSIVE'} && $options->{'RECURSIVE'}) { + push(@{$rmcmd}, "-r"); + } + + if (defined $options->{'FORCE'} && $options->{'FORCE'}) { + push(@{$rmcmd}, "-f"); + } + + if (defined $options->{'DIRECTORY'} && $options->{'DIRECTORY'}) { + push(@{$rmcmd}, "-d"); + } + + $self->run_command({ COMMAND => $rmcmd, USER => $user, DIR => $dir}); + if ($?) { + $self->log_error("Can't unlink $path: $!\n"); + return 0; + } + + return 1; +} + +# chmod a path inside the chroot +sub chmod { + my $self = shift; + my $path = shift; + my $mode = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $chmodcmd = [ "chmod" ]; + + if (defined $options->{'RECURSIVE'} && $options->{'RECURSIVE'}) { + push(@{$chmodcmd}, "-R"); + } + + push(@{$chmodcmd}, $mode, $path); + + $self->run_command({ COMMAND => $chmodcmd, USER => $user, DIR => $dir}); + if ($?) { + $self->log_error("Can't chmod $path to $mode: $!\n"); + return 0; + } + + return 1; +} + +# chown a path inside the chroot +sub chown { + my $self = shift; + my $path = shift; + my $owner = shift; + my $group = shift; + my $options = shift; + + my $user = "root"; + $user = $options->{'USER'} if defined $options->{'USER'}; + + my $dir = "/"; + $dir = $options->{'DIR'} if defined $options->{'DIR'}; + + my $chowncmd = [ "chown" ]; + + if (defined $options->{'RECURSIVE'} && $options->{'RECURSIVE'}) { + push(@{$chowncmd}, "-R"); + } + + push(@{$chowncmd}, "$owner:$group", $path); + + $self->run_command({ COMMAND => $chowncmd, USER => $user, DIR => $dir}); + if ($?) { + $self->log_error("Can't chown $path to $owner:$group: $!\n"); + return 0; + } + + return 1; +} + # Note, do not run with $user="root", and $chroot=0, because root # access to the host system is not allowed by schroot, nor required # via sudo. @@ -260,12 +707,26 @@ return $self->pipe_command_internal($options); } +sub get_internal_exec_string { + my $self = shift; + return $self->get_internal_exec_string(); +} + +# This function must not print anything to standard output or standard error +# when it dies because its output will be treated as the output of the program +# it executes. So error handling can only happen with "die()". sub exec_command { my $self = shift; my $options = shift; $self->get_command_internal($options); + if (!defined($options->{'EXPCOMMAND'}) || $options->{'EXPCOMMAND'} eq '' + || !defined($options->{'COMMAND'}) || scalar(@{$options->{'COMMAND'}}) == 0 + || !defined($options->{'INTCOMMAND'}) || scalar(@{$options->{'INTCOMMAND'}}) == 0) { + die "get_command_internal failed during exec_command\n"; + } + $self->log_command($options); my $command = $options->{'EXPCOMMAND'}; diff -Nru sbuild-0.67.0/lib/Sbuild/ChrootSchroot.pm sbuild-0.69.0/lib/Sbuild/ChrootSchroot.pm --- sbuild-0.67.0/lib/Sbuild/ChrootSchroot.pm 2015-12-23 13:42:12.816497113 +0000 +++ sbuild-0.69.0/lib/Sbuild/ChrootSchroot.pm 2016-05-02 17:26:38.482086498 +0000 @@ -25,6 +25,8 @@ use strict; use warnings; +use Sbuild qw(shellescape); + BEGIN { use Exporter (); use Sbuild::Chroot; @@ -73,7 +75,8 @@ $self->set('Location', $info->{'Location'}); $self->set('Session Purged', $info->{'Session Purged'}); } else { - die $self->get('Chroot ID') . " chroot does not exist\n"; + print STDERR $self->get('Chroot ID') . " chroot does not exist\n"; + return 0; } return 0 if !$self->_setup_options(); @@ -88,7 +91,7 @@ print STDERR "Cleaning up chroot (session id " . $self->get('Session ID') . ")\n" if $self->get_conf('DEBUG'); - system($self->get_conf('SCHROOT') . ' -c ' . $self->get('Session ID') . ' --end-session'); + system($self->get_conf('SCHROOT'), '-c', $self->get('Session ID'), '--end-session'); $self->set('Session ID', ""); if ($?) { print STDERR "Chroot cleanup failed\n"; @@ -98,10 +101,28 @@ return 1; } +sub get_internal_exec_string { + my $self = shift; + + return if $self->get('Session ID') eq ""; + + my $dir = '/'; + my $user = 'root'; + my @cmdline = ($self->get_conf('SCHROOT'), + '-d', $dir, + '-c', $self->get('Session ID'), + '--run-session', + @{$self->get_conf('SCHROOT_OPTIONS')}, + '-u', "$user", '-p', '--'); + return join " ", (map { shellescape $_ } @cmdline); +} + sub get_command_internal { my $self = shift; my $options = shift; + return if $self->get('Session ID') eq ""; + # Command to run. If I have a string, use it. Otherwise use the list-ref my $command = $options->{'INTCOMMAND_STR'} // $options->{'INTCOMMAND'}; diff -Nru sbuild-0.67.0/lib/Sbuild/ChrootSetup.pm sbuild-0.69.0/lib/Sbuild/ChrootSetup.pm --- sbuild-0.67.0/lib/Sbuild/ChrootSetup.pm 2015-12-26 10:32:21.448607017 +0000 +++ sbuild-0.69.0/lib/Sbuild/ChrootSetup.pm 2016-05-02 17:26:38.482086498 +0000 @@ -59,7 +59,7 @@ # This will require root privileges. However, this should # only get run at initial chroot setup time. my $groupfile = $session->get('Location') . "/etc/group"; - system '/bin/sh', '-c', "getent group sbuild >> $groupfile"; + system("getent group sbuild >> $groupfile"); if ($?) { print STDERR "E: Failed to create group sbuild\n"; return $? diff -Nru sbuild-0.67.0/lib/Sbuild/ConfBase.pm sbuild-0.69.0/lib/Sbuild/ConfBase.pm --- sbuild-0.67.0/lib/Sbuild/ConfBase.pm 2015-12-26 10:32:21.320606618 +0000 +++ sbuild-0.69.0/lib/Sbuild/ConfBase.pm 2016-05-08 10:31:22.366021898 +0000 @@ -111,7 +111,8 @@ VARNAME => 'path', GROUP => 'Build environment', DEFAULT => "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games", - HELP => 'PATH to set when running dpkg-buildpackage.' + HELP => 'PATH to set when running dpkg-buildpackage.', + CLI_OPTIONS => ['--use-snapshot'] }, 'DISTRIBUTION' => { TYPE => 'STRING', @@ -119,7 +120,8 @@ GROUP => 'Build options', DEFAULT => undef, SET => $set_distribution, - HELP => 'Default distribution. By default, no distribution is defined, and the user must specify it with the -d option. However, a default may be configured here if desired. Users must take care not to upload to the wrong distribution when this option is set, for example experimental packages will be built for upload to unstable when this is not what is required.' + HELP => 'Default distribution. By default, no distribution is defined, and the user must specify it with the -d option. However, a default may be configured here if desired. Users must take care not to upload to the wrong distribution when this option is set, for example experimental packages will be built for upload to unstable when this is not what is required.', + CLI_OPTIONS => ['-d', '--dist'] }, 'OVERRIDE_DISTRIBUTION' => { TYPE => 'BOOL', @@ -174,7 +176,8 @@ # the architecture they are built on, so don't show the default for # example config and man page generation IGNORE_DEFAULT => 1, - HELP => 'Host architecture (Arch we are building for)' + HELP => 'Host architecture (Arch we are building for)', + CLI_OPTIONS => ['--arch', '--host'] }, 'BUILD_ARCH' => { TYPE => 'STRING', @@ -186,14 +189,16 @@ # the architecture they are built on, so don't show the default for # example config and man page generation IGNORE_DEFAULT => 1, - HELP => 'Build architecture (Arch we are building on).' + HELP => 'Build architecture (Arch we are building on).', + CLI_OPTIONS => ['--arch', '--build'] }, 'BUILD_PROFILES' => { TYPE => 'STRING', VARNAME => 'build_profiles', GROUP => 'Build options', DEFAULT => $ENV{'DEB_BUILD_PROFILES'} || '', - HELP => 'Build profiles. Separated by spaces.' + HELP => 'Build profiles. Separated by spaces.', + CLI_OPTIONS => ['--profiles'] }, 'HOSTNAME' => { TYPE => 'STRING', @@ -356,6 +361,13 @@ return $self->_get_property_value($key, 'IGNORE_DEFAULT'); } +sub _get_cli_options { + my $self = shift; + my $key = shift; + + return $self->_get_property_value($key, 'CLI_OPTIONS'); +} + sub _get { my $self = shift; my $key = shift; diff -Nru sbuild-0.67.0/lib/Sbuild/Conf.pm sbuild-0.69.0/lib/Sbuild/Conf.pm --- sbuild-0.67.0/lib/Sbuild/Conf.pm 2015-12-26 10:32:21.764608002 +0000 +++ sbuild-0.69.0/lib/Sbuild/Conf.pm 2016-05-08 10:31:22.478022025 +0000 @@ -130,27 +130,32 @@ VARNAME => 'chroot', GROUP => 'Chroot options', DEFAULT => undef, - HELP => 'Default chroot (defaults to distribution[-arch][-sbuild])' + HELP => 'Default chroot (defaults to distribution[-arch][-sbuild])', + CLI_OPTIONS => ['-c', '--chroot'] }, 'BUILD_ARCH_ALL' => { TYPE => 'BOOL', VARNAME => 'build_arch_all', GROUP => 'Build options', DEFAULT => 0, - HELP => 'Build architecture: all packages by default' + HELP => 'Build architecture: all packages by default.', + CLI_OPTIONS => ['--arch-all', '--no-arch-all'] }, 'BUILD_ARCH_ANY' => { TYPE => 'BOOL', VARNAME => 'build_arch_any', GROUP => 'Build options', DEFAULT => 1, - HELP => 'Build architecture: any packages by default' + HELP => 'Build architecture: any packages by default.', + CLI_OPTIONS => ['--arch-any', '--no-arch-any'] }, 'NOLOG' => { TYPE => 'BOOL', - GROUP => '__INTERNAL', + VARNAME => 'nolog', + GROUP => 'Logging options', DEFAULT => 0, - HELP => 'Disable use of log file' + HELP => 'Disable use of log file', + CLI_OPTIONS => ['-n', '--nolog'] }, 'SUDO' => { TYPE => 'STRING', @@ -220,6 +225,39 @@ DEFAULT => ['-q'], HELP => 'Additional command-line options for schroot' }, + 'ADT_VIRT_SERVER' => { + TYPE => 'STRING', + VARNAME => 'adt_virt_server', + GROUP => 'Programs', + CHECK => sub { + my $conf = shift; + my $entry = shift; + my $key = $entry->{'NAME'}; + my $program = $conf->get($key); + + # if the adt virtualization server name is only letters a-z + # then it is missing the adt-virt- prefix + if ($program =~ /^[a-z]+$/) { + $conf->set($key, "adt-virt-$program"); + } + + # Only validate if needed. + if ($conf->get('CHROOT_MODE') eq 'adt') { + $validate_program->($conf, $entry); + } + }, + DEFAULT => 'adt-virt-schroot', + HELP => 'Path to adt-virt-* binary, selecting the virtualization server.', + CLI_OPTIONS => ['--adt-virt-server'] + }, + 'ADT_VIRT_SERVER_OPTIONS' => { + TYPE => 'ARRAY:STRING', + VARNAME => 'adt_virt_server_options', + GROUP => 'Programs', + DEFAULT => [], + HELP => 'Additional command-line options for adt-virt-*', + CLI_OPTIONS => ['--adt-virt-server-opt', '--adt-virt-server-opts'] + }, 'FAKEROOT' => { TYPE => 'STRING', VARNAME => 'fakeroot', @@ -278,9 +316,11 @@ }, 'DPKG_BUILDPACKAGE_USER_OPTIONS' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'dpkg_buildpackage_user_options', + GROUP => 'Programs', DEFAULT => [], - HELP => 'Additional command-line options for dpkg-buildpackage. Not settable in config.' + HELP => 'Additional command-line options for dpkg-buildpackage.', + CLI_OPTIONS => ['--debbuildopt', '--debbuildopts', '--jobs'] }, 'DPKG_SOURCE' => { TYPE => 'STRING', @@ -295,7 +335,8 @@ VARNAME => 'dpkg_source_opts', GROUP => 'Programs', DEFAULT => [], - HELP => 'Additional command-line options for dpkg-source' + HELP => 'Additional command-line options for dpkg-source', + CLI_OPTIONS => ['--dpkg-source-opt', '--dpkg-source-opts'] }, 'DCMD' => { TYPE => 'STRING', @@ -318,7 +359,8 @@ VARNAME => 'stats_dir', GROUP => 'Statistics', DEFAULT => "$HOME/stats", - HELP => 'Directory for writing build statistics to' + HELP => 'Directory for writing build statistics to', + CLI_OPTIONS => ['--stats-dir'] }, 'PACKAGE_CHECKLIST' => { TYPE => 'STRING', @@ -448,7 +490,8 @@ return $retval; }, DEFAULT => "", - HELP => 'email address to mail build logs to' + HELP => 'email address to mail build logs to', + CLI_OPTIONS => ['--mail-log-to'] }, 'MAILTO_FORCED_BY_CLI' => { TYPE => 'BOOL', @@ -467,7 +510,8 @@ VARNAME => 'mailfrom', GROUP => 'Logging options', DEFAULT => "Source Builder ", - HELP => 'email address set in the From line of build logs' + HELP => 'email address set in the From line of build logs', + CLI_OPTIONS => ['--mailfrom'] }, 'COMPRESS_BUILD_LOG_MAILS' => { TYPE => 'BOOL', @@ -498,7 +542,8 @@ qw(always successful never)); }, DEFAULT => 'always', - HELP => 'When to purge the build dependencies after a build; possible values are "never", "successful", and "always"' + HELP => 'When to purge the build dependencies after a build; possible values are "never", "successful", and "always"', + CLI_OPTIONS => ['-p', '--purge', '--purge-deps'] }, 'PURGE_BUILD_DIRECTORY' => { TYPE => 'STRING', @@ -515,7 +560,8 @@ qw(always successful never)); }, DEFAULT => 'always', - HELP => 'When to purge the build directory after a build; possible values are "never", "successful", and "always"' + HELP => 'When to purge the build directory after a build; possible values are "never", "successful", and "always"', + CLI_OPTIONS => ['-p', '--purge', '--purge-build'] }, 'PURGE_SESSION' => { TYPE => 'STRING', @@ -532,7 +578,8 @@ qw(always successful never)); }, DEFAULT => 'always', - HELP => 'Purge the schroot session following a build. This is useful in conjunction with the --purge and --purge-deps options when using snapshot chroots, since by default the snapshot will be deleted. Possible values are "always" (default), "never", and "successful"' + HELP => 'Purge the schroot session following a build. This is useful in conjunction with the --purge and --purge-deps options when using snapshot chroots, since by default the snapshot will be deleted. Possible values are "always" (default), "never", and "successful"', + CLI_OPTIONS => ['-p', '--purge', '--purge-session'] }, 'TOOLCHAIN_REGEX' => { TYPE => 'ARRAY:STRING', @@ -584,10 +631,11 @@ die "Bad chroot mode \'" . $conf->get('CHROOT_MODE') . "\'" if !isin($conf->get('CHROOT_MODE'), - qw(schroot sudo)); + qw(schroot sudo adt)); }, DEFAULT => 'schroot', - HELP => 'Mechanism to use for chroot virtualisation. Possible value are "schroot" (default) and "sudo".' + HELP => 'Mechanism to use for chroot virtualisation. Possible value are "schroot" (default), "sudo" and "adt".', + CLI_OPTIONS => ['--chroot-mode'] }, 'CHROOT_SPLIT' => { TYPE => 'BOOL', @@ -618,28 +666,32 @@ VARNAME => 'build_path', GROUP => 'Build options', DEFAULT => undef, - HELP => 'By default the package is built in a path of the following format /build/packagename-XXXXXX/packagename-version/ where XXXXXX is a random ascii string. This option allows one to specify a custom path where the package is built inside the chroot. Notice that the sbuild user in the chroot must have permissions to create the path. Common writable locations are subdirectories of /tmp or /build. The buildpath must be an empty directory because the last component of the path will be removed after the build is finished. If you are running multiple sbuild instances with the same build path in parallel for the same package, make sure that your build path is not in a directory commonly mounted by all sbuild instances (like /tmp or /home). In that case, use for example /build instead. Otherwise, your builds will probably fail or contain wrong content.' + HELP => 'By default the package is built in a path of the following format /build/packagename-XXXXXX/packagename-version/ where XXXXXX is a random ascii string. This option allows one to specify a custom path where the package is built inside the chroot. Notice that the sbuild user in the chroot must have permissions to create the path. Common writable locations are subdirectories of /tmp or /build. The buildpath must be an empty directory because the last component of the path will be removed after the build is finished. If you are running multiple sbuild instances with the same build path in parallel for the same package, make sure that your build path is not in a directory commonly mounted by all sbuild instances (like /tmp or /home). In that case, use for example /build instead. Otherwise, your builds will probably fail or contain wrong content.', + CLI_OPTIONS => ['--build-path'] }, 'SBUILD_MODE' => { TYPE => 'STRING', VARNAME => 'sbuild_mode', GROUP => 'Core options', DEFAULT => 'user', - HELP => 'sbuild behaviour; possible values are "user" (exit status reports build failures) and "buildd" (exit status does not report build failures) for use in a buildd setup. "buildd" also currently implies enabling of "legacy features" such as chroot symlinks in the build directory and the creation of current symlinks in the build directory.' + HELP => 'sbuild behaviour; possible values are "user" (exit status reports build failures) and "buildd" (exit status does not report build failures) for use in a buildd setup. "buildd" also currently implies enabling of "legacy features" such as chroot symlinks in the build directory and the creation of current symlinks in the build directory.', + CLI_OPTIONS => ['--sbuild-mode'] }, 'CHROOT_SETUP_SCRIPT' => { TYPE => 'STRING', VARNAME => 'chroot_setup_script', GROUP => 'Chroot options', DEFAULT => undef, - HELP => 'Script to run to perform custom setup tasks in the chroot.' + HELP => 'Script to run to perform custom setup tasks in the chroot.', + CLI_OPTIONS => ['--setup-hook'] }, 'FORCE_ORIG_SOURCE' => { TYPE => 'BOOL', VARNAME => 'force_orig_source', GROUP => 'Build options', DEFAULT => 0, - HELP => 'By default, the -s option only includes the .orig.tar.gz when needed (i.e. when the Debian revision is 0 or 1). By setting this option to 1, the .orig.tar.gz will always be included when -s is used. This is equivalent to --force-orig-source.' + HELP => 'By default, the -s option only includes the .orig.tar.gz when needed (i.e. when the Debian revision is 0 or 1). By setting this option to 1, the .orig.tar.gz will always be included when -s is used.', + CLI_OPTIONS => ['--force-orig-source'] }, 'INDIVIDUAL_STALLED_PKG_TIMEOUT' => { TYPE => 'HASH:NUMERIC', @@ -685,7 +737,8 @@ VARNAME => 'ld_library_path', GROUP => 'Build environment', DEFAULT => undef, - HELP => 'Library search path to use inside the chroot.' + HELP => 'Library search path to use inside the chroot.', + CLI_OPTIONS => ['--use-snapshot'] }, 'MAINTAINER_NAME' => { TYPE => 'STRING', @@ -693,7 +746,8 @@ GROUP => 'Maintainer options', DEFAULT => undef, SET => $set_signing_option, - HELP => 'Name to use as override in .changes files for the Maintainer field. The Maintainer field will not be overridden unless set here.' + HELP => 'Name to use as override in .changes files for the Maintainer field. The Maintainer field will not be overridden unless set here.', + CLI_OPTIONS => ['-m', '--maintainer'] }, 'UPLOADER_NAME' => { VARNAME => 'uploader_name', @@ -701,14 +755,16 @@ GROUP => 'Maintainer options', DEFAULT => undef, SET => $set_signing_option, - HELP => 'Name to use as override in .changes file for the Changed-By: field.' + HELP => 'Name to use as override in .changes file for the Changed-By: field.', + CLI_OPTIONS => ['-e', '--uploader'] }, 'KEY_ID' => { TYPE => 'STRING', VARNAME => 'key_id', GROUP => 'Maintainer options', DEFAULT => undef, - HELP => 'Key ID to use in .changes for the current upload. It overrides both $maintainer_name and $uploader_name.' + HELP => 'Key ID to use in .changes for the current upload. It overrides both $maintainer_name and $uploader_name.', + CLI_OPTIONS => ['-k', '--keyid'] }, 'SIGNING_OPTIONS' => { TYPE => 'STRING', @@ -721,14 +777,16 @@ VARNAME => 'apt_clean', GROUP => 'Chroot options', DEFAULT => 0, - HELP => 'APT clean. 1 to enable running "apt-get clean" at the start of each build, or 0 to disable.' + HELP => 'APT clean. 1 to enable running "apt-get clean" at the start of each build, or 0 to disable.', + CLI_OPTIONS => ['--apt-clean', '--no-apt-clean'] }, 'APT_UPDATE' => { TYPE => 'BOOL', VARNAME => 'apt_update', GROUP => 'Chroot options', DEFAULT => 1, - HELP => 'APT update. 1 to enable running "apt-get update" at the start of each build, or 0 to disable.' + HELP => 'APT update. 1 to enable running "apt-get update" at the start of each build, or 0 to disable.', + CLI_OPTIONS => ['--apt-update', '--no-apt-update'] }, 'APT_UPDATE_ARCHIVE_ONLY' => { TYPE => 'BOOL', @@ -742,14 +800,16 @@ VARNAME => 'apt_upgrade', GROUP => 'Chroot options', DEFAULT => 0, - HELP => 'APT upgrade. 1 to enable running "apt-get upgrade" at the start of each build, or 0 to disable.' + HELP => 'APT upgrade. 1 to enable running "apt-get upgrade" at the start of each build, or 0 to disable.', + CLI_OPTIONS => ['--apt-upgrade', '--no-apt-upgrade'] }, 'APT_DISTUPGRADE' => { TYPE => 'BOOL', VARNAME => 'apt_distupgrade', GROUP => 'Chroot options', DEFAULT => 1, - HELP => 'APT distupgrade. 1 to enable running "apt-get dist-upgrade" at the start of each build, or 0 to disable.' + HELP => 'APT distupgrade. 1 to enable running "apt-get dist-upgrade" at the start of each build, or 0 to disable.', + CLI_OPTIONS => ['--apt-distupgrade', '--no-apt-distupgrade'] }, 'APT_ALLOW_UNAUTHENTICATED' => { TYPE => 'BOOL', @@ -760,9 +820,11 @@ }, 'BATCH_MODE' => { TYPE => 'BOOL', - GROUP => '__INTERNAL', + VARNAME => 'batch_mode', + GROUP => 'Core options', DEFAULT => 0, - HELP => 'Enable batch mode?' + HELP => 'Enable batch mode?', + CLI_OPTIONS => ['-b', '--batch'] }, 'CORE_DEPENDS' => { TYPE => 'ARRAY:STRING', @@ -773,39 +835,51 @@ }, 'MANUAL_DEPENDS' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_depends', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-depends'] }, 'MANUAL_CONFLICTS' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_conflicts', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-conflicts'] }, 'MANUAL_DEPENDS_ARCH' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_depends_arch', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-depends-arch'] }, 'MANUAL_CONFLICTS_ARCH' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_conflicts_arch', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-conflicts-arch'] }, 'MANUAL_DEPENDS_INDEP' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_depends_indep', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-depends-indep'] }, 'MANUAL_CONFLICTS_INDEP' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'manual_conflicts_indep', + GROUP => 'Core options', DEFAULT => [], - HELP => 'Additional per-build dependencies. Do not set by hand.' + HELP => 'Additional per-build dependencies.', + CLI_OPTIONS => ['--add-conflicts-indep'] }, 'CROSSBUILD_CORE_DEPENDS' => { TYPE => 'HASH:ARRAY:STRING', @@ -825,27 +899,33 @@ GROUP => 'Build options', DEFAULT => 0, CHECK => $validate_append_version, - HELP => 'By default, do not build a source package (binary only build). Set to 1 to force creation of a source package, but note that this is inappropriate for binary NMUs, where the option will always be disabled.' + HELP => 'By default, do not build a source package (binary only build). Set to 1 to force creation of a source package, but note that this is inappropriate for binary NMUs, where the option will always be disabled.', + CLI_OPTIONS => ['-s', '--source', '--no-source'] }, 'ARCHIVE' => { TYPE => 'STRING', VARNAME => 'archive', GROUP => 'Core options', DEFAULT => undef, - HELP => 'Archive being built. Only set in build log. This might be useful for derivative distributions.' + HELP => 'Archive being built. Only set in build log. This might be useful for derivative distributions.', + CLI_OPTIONS => ['--archive'] }, 'BIN_NMU' => { TYPE => 'STRING', - GROUP => '__INTERNAL', + VARNAME => 'bin_nmu', + GROUP => 'Build options', DEFAULT => undef, CHECK => $validate_append_version, - HELP => 'Binary NMU changelog entry. Do not set by hand.' + HELP => 'Binary NMU changelog entry.', + CLI_OPTIONS => ['--make-binNMU'] }, 'BIN_NMU_VERSION' => { TYPE => 'STRING', - GROUP => '__INTERNAL', + VARNAME => 'bin_nmu_version', + GROUP => 'Build options', DEFAULT => undef, - HELP => 'Binary NMU version number. Do not set by hand.' + HELP => 'Binary NMU version number.', + CLI_OPTIONS => ['--binNMU', '--make-binNMU'] }, 'APPEND_TO_VERSION' => { TYPE => 'STRING', @@ -853,14 +933,16 @@ GROUP => 'Build options', DEFAULT => undef, CHECK => $validate_append_version, - HELP => 'Suffix to append to version number. May be useful for derivative distributions.' + HELP => 'Suffix to append to version number. May be useful for derivative distributions.', + CLI_OPTIONS => ['--append-to-version'] }, 'GCC_SNAPSHOT' => { TYPE => 'BOOL', VARNAME => 'gcc_snapshot', GROUP => 'Build options', DEFAULT => 0, - HELP => 'Build using current GCC snapshot?' + HELP => 'Build using current GCC snapshot?', + CLI_OPTIONS => ['--use-snapshot'] }, 'JOB_FILE' => { TYPE => 'STRING', @@ -890,14 +972,24 @@ if !isin($conf->get($key), qw(apt aptitude aspcud xapt)); }, - HELP => 'Build dependency resolver. The \'apt\' resolver is currently the default, and recommended for most users. This resolver uses apt-get to resolve dependencies. Alternative resolvers are \'apt\', \'aptitude\' and \'aspcud\'. The \'apt\' resolver uses a built-in resolver module while the \'aptitude\' resolver uses aptitude to resolve build dependencies. The aptitude resolver is similar to apt, but is useful in more complex situations, such as where multiple distributions are required, for example when building from experimental, where packages are needed from both unstable and experimental, but defaulting to unstable. If the dependency situation is too complex for either apt or aptitude to solve it, you can use the \'aspcud\' resolver which is a real SAT solver and will thus alwyas find a solution if a solution exists.' + HELP => 'Build dependency resolver. The \'apt\' resolver is currently the default, and recommended for most users. This resolver uses apt-get to resolve dependencies. Alternative resolvers are \'apt\', \'aptitude\' and \'aspcud\'. The \'apt\' resolver uses a built-in resolver module while the \'aptitude\' resolver uses aptitude to resolve build dependencies. The aptitude resolver is similar to apt, but is useful in more complex situations, such as where multiple distributions are required, for example when building from experimental, where packages are needed from both unstable and experimental, but defaulting to unstable. If the dependency situation is too complex for either apt or aptitude to solve it, you can use the \'aspcud\' resolver which (in contrast to apt and aptitude) is a real solver (in the math sense) and will thus always find a solution if a solution exists.', + CLI_OPTIONS => ['--build-dep-resolver'] + }, + 'ASPCUD_CRITERIA' => { + TYPE => 'STRING', + VARNAME => 'aspcud_criteria', + GROUP => 'Dependency resolution', + DEFAULT => '-removed,-changed,-new', + HELP => 'Optimization criteria in extended MISC 2012 syntax passed to aspcud through apt-cudf. Optimization criteria are separated by commas, sorted by decreasing order of priority and are prefixed with a polarity (+ to maximize and - to minimize). The default criteria is \'-removed,-changed,-new\' which first minimizes the number of removed packages, then the number of changed packages (up or downgrades) and then the number of new packages. A common task is to minimize the number of packages from experimental. To do this you can add a criteria like \'-count(solution,APT-Release:=/a=experimental/)\' to the default criteria. This will then minimize the number of packages in the solution which contain the string \'a=experimental\' in the \'APT-Release\' field of the EDSP output created by apt. See the apt-cudf man page help on the --criteria option for more information.', + CLI_OPTIONS => ['--aspcud-criteria'] }, 'CLEAN_SOURCE' => { TYPE => 'BOOL', VARNAME => 'clean_source', GROUP => 'Build options', DEFAULT => 1, - HELP => 'When running sbuild from within an unpacked source tree, run the \'clean\' target before generating the source package. This might require some of the build dependencies necessary for running the \'clean\' target to be installed on the host machine. Only disable if you start from a clean checkout and you know what you are doing.' + HELP => 'When running sbuild from within an unpacked source tree, run the \'clean\' target before generating the source package. This might require some of the build dependencies necessary for running the \'clean\' target to be installed on the host machine. Only disable if you start from a clean checkout and you know what you are doing.', + CLI_OPTIONS => ['--clean-source', '--no-clean-source'] }, 'LINTIAN' => { TYPE => 'STRING', @@ -925,14 +1017,16 @@ $conf->check('LINTIAN'); }, DEFAULT => 0, - HELP => 'Run lintian?' + HELP => 'Run lintian?', + CLI_OPTIONS => ['--run-lintian', '--no-run-lintian'] }, 'LINTIAN_OPTIONS' => { TYPE => 'ARRAY:STRING', VARNAME => 'lintian_opts', GROUP => 'Build validation', DEFAULT => [], - HELP => 'Options to pass to lintian. Each option is a separate arrayref element. For example, [\'-i\', \'-v\'] to add -i and -v.' + HELP => 'Options to pass to lintian. Each option is a separate arrayref element. For example, [\'-i\', \'-v\'] to add -i and -v.', + CLI_OPTIONS => ['--lintian-opt', '--lintian-opts'] }, 'PIUPARTS' => { TYPE => 'STRING', @@ -949,7 +1043,8 @@ } }, DEFAULT => 'piuparts', - HELP => 'Path to piuparts binary' + HELP => 'Path to piuparts binary', + CLI_OPTIONS => ['--piuparts-opt', '--piuparts-opts'] }, 'RUN_PIUPARTS' => { TYPE => 'BOOL', @@ -960,7 +1055,8 @@ $conf->check('PIUPARTS'); }, DEFAULT => 0, - HELP => 'Run piuparts' + HELP => 'Run piuparts', + CLI_OPTIONS => ['--run-piuparts', '--no-run-piuparts'] }, 'PIUPARTS_OPTIONS' => { TYPE => 'ARRAY:STRING', @@ -974,7 +1070,8 @@ VARNAME => 'piuparts_root_args', GROUP => 'Build validation', DEFAULT => [], - HELP => 'Preceding arguments to launch piuparts as root. If no arguments are specified, piuparts will be launched via sudo.' + HELP => 'Preceding arguments to launch piuparts as root. If no arguments are specified, piuparts will be launched via sudo.', + CLI_OPTIONS => ['--piuparts-root-arg', '--piuparts-root-args'] }, 'EXTERNAL_COMMANDS' => { TYPE => 'HASH:ARRAY:STRING', @@ -983,6 +1080,7 @@ DEFAULT => { "pre-build-commands" => [], "chroot-setup-commands" => [], + "chroot-update-failed-commands" => [], "build-deps-failed-commands" => [], "build-failed-commands" => [], "starting-build-commands" => [], @@ -1001,6 +1099,10 @@ [\'foo\', \'arg1\', \'arg2\'], [\'bar\', \'arg1\', \'arg2\', \'arg3\'], ], + "chroot-update-failed-commands" => [ + [\'foo\', \'arg1\', \'arg2\'], + [\'bar\', \'arg1\', \'arg2\', \'arg3\'], + ], "build-deps-failed-commands" => [ [\'foo\', \'arg1\', \'arg2\'], [\'bar\', \'arg1\', \'arg2\', \'arg3\'], @@ -1025,21 +1127,24 @@ [\'foo\', \'arg1\', \'arg2\'], [\'bar\', \'arg1\', \'arg2\', \'arg3\'], ], -};' +};', + CLI_OPTIONS => ['--setup-hook', '--pre-build-commands', '--chroot-setup-commands', '--chroot-update-failed-commands', '--build-deps-failed-commands', '--build-failed-commands', '--anything-failed-commands', '--starting-build-commands', '--finished-build-commands', '--chroot-cleanup-commands', '--post-build-commands'] }, 'LOG_EXTERNAL_COMMAND_OUTPUT' => { TYPE => 'BOOL', VARNAME => 'log_external_command_output', GROUP => 'Chroot options', DEFAULT => 1, - HELP => 'Log standard output of commands run by sbuild?' + HELP => 'Log standard output of commands run by sbuild?', + CLI_OPTIONS => ['--log-external-command-output'] }, 'LOG_EXTERNAL_COMMAND_ERROR' => { TYPE => 'BOOL', VARNAME => 'log_external_command_error', GROUP => 'Chroot options', DEFAULT => 1, - HELP => 'Log standard error of commands run by sbuild?' + HELP => 'Log standard error of commands run by sbuild?', + CLI_OPTIONS => ['--log-external-command-error'] }, 'RESOLVE_ALTERNATIVES' => { TYPE => 'BOOL', @@ -1061,7 +1166,8 @@ return $retval; }, EXAMPLE => '$resolve_alternatives = 0;', - HELP => 'Should the dependency resolver use alternatives in Build-Depends, Build-Depends-Arch and Build-Depends-Indep? By default, using \'apt\' resolver, only the first alternative will be used; all other alternatives will be removed. When using the \'aptitude\' resolver, it will default to using all alternatives. Note that this does not include architecture-specific alternatives, which are reduced to the build architecture prior to alternatives removal. This should be left disabled when building for unstable; it may be useful when building for experimental or backports. Set to undef to use the default, 1 to enable, or 0 to disable.' + HELP => 'Should the dependency resolver use alternatives in Build-Depends, Build-Depends-Arch and Build-Depends-Indep? By default, using \'apt\' resolver, only the first alternative will be used; all other alternatives will be removed. When using the \'aptitude\' resolver, it will default to using all alternatives. Note that this does not include architecture-specific alternatives, which are reduced to the build architecture prior to alternatives removal. This should be left disabled when building for unstable; it may be useful when building for experimental or backports. Set to undef to use the default, 1 to enable, or 0 to disable.', + CLI_OPTIONS => ['--resolve-alternatives', '--no-resolve-alternatives'] }, 'SBUILD_BUILD_DEPENDS_SECRET_KEY' => { TYPE => 'STRING', @@ -1079,21 +1185,27 @@ }, 'EXTRA_PACKAGES' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'extra_packages', + GROUP => 'Dependency resolution', DEFAULT => [], - HELP => 'Additional per-build packages available as build dependencies. Do not set by hand.' + HELP => 'Additional per-build packages available as build dependencies.', + CLI_OPTIONS => ['--extra-package'] }, 'EXTRA_REPOSITORY_KEYS' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'extra_repository_keys', + GROUP => 'Dependency resolution', DEFAULT => [], - HELP => 'Additional per-build apt repository keys. Do not set by hand.' + HELP => 'Additional per-build apt repository keys.', + CLI_OPTIONS => ['--extra-repository-key'] }, 'EXTRA_REPOSITORIES' => { TYPE => 'ARRAY:STRING', - GROUP => '__INTERNAL', + VARNAME => 'extra_repositories', + GROUP => 'Dependency resolution', DEFAULT => [], - HELP => 'Additional per-build apt repositories. Do not set by hand.' + HELP => 'Additional per-build apt repositories.', + CLI_OPTIONS => ['--extra-repository'] }, ); diff -Nru sbuild-0.67.0/lib/Sbuild/Makefile.am sbuild-0.69.0/lib/Sbuild/Makefile.am --- sbuild-0.67.0/lib/Sbuild/Makefile.am 2015-12-01 21:29:48.463402744 +0000 +++ sbuild-0.69.0/lib/Sbuild/Makefile.am 2016-04-28 05:04:30.594584766 +0000 @@ -31,10 +31,12 @@ ChrootRoot.pm \ ChrootSchroot.pm \ ChrootSudo.pm \ + ChrootADT.pm \ ChrootSetup.pm \ ChrootInfo.pm \ ChrootInfoSchroot.pm \ ChrootInfoSudo.pm \ + ChrootInfoADT.pm \ Exception.pm \ ResolverBase.pm \ AptitudeResolver.pm \ diff -Nru sbuild-0.67.0/lib/Sbuild/Makefile.in sbuild-0.69.0/lib/Sbuild/Makefile.in --- sbuild-0.67.0/lib/Sbuild/Makefile.in 2015-12-26 13:35:49.493714241 +0000 +++ sbuild-0.69.0/lib/Sbuild/Makefile.in 2016-05-08 12:14:36.186785775 +0000 @@ -298,10 +298,12 @@ ChrootRoot.pm \ ChrootSchroot.pm \ ChrootSudo.pm \ + ChrootADT.pm \ ChrootSetup.pm \ ChrootInfo.pm \ ChrootInfoSchroot.pm \ ChrootInfoSudo.pm \ + ChrootInfoADT.pm \ Exception.pm \ ResolverBase.pm \ AptitudeResolver.pm \ diff -Nru sbuild-0.67.0/lib/Sbuild/Options.pm sbuild-0.69.0/lib/Sbuild/Options.pm --- sbuild-0.67.0/lib/Sbuild/Options.pm 2015-12-26 10:32:21.604607503 +0000 +++ sbuild-0.69.0/lib/Sbuild/Options.pm 2016-05-07 16:51:49.915120690 +0000 @@ -39,31 +39,79 @@ sub set_options { my $self = shift; + my ($opt_arch_all, $opt_no_arch_all); + my ($opt_build_arch, $opt_host_arch, $opt_arch); + my ($opt_arch_any, $opt_no_arch_any); + my ($opt_source, $opt_no_source); + my ($opt_apt_clean, $opt_no_apt_clean, $opt_apt_update, $opt_no_apt_update, + $opt_apt_upgrade, $opt_no_apt_upgrade, $opt_apt_distupgrade, $opt_no_apt_distupgrade); + my ($opt_purge, $opt_purge_build, $opt_purge_deps, $opt_purge_session); + my ($opt_resolve_alternatives, $opt_no_resolve_alternatives); + my ($opt_clean_source, $opt_no_clean_source); + my ($opt_run_lintian, $opt_no_run_lintian); + my ($opt_run_piuparts, $opt_no_run_piuparts); + $self->add_options("arch=s" => sub { + if (defined $opt_arch && $opt_arch ne $_[1]) { + die "cannot specify differing --arch multiple times"; + } + if (defined $opt_build_arch && $opt_build_arch ne $_[1]) { + die "cannot specify --arch together with differing --build-arch"; + } + if (defined $opt_host_arch && $opt_host_arch ne $_[1]) { + die "cannot specify --arch together with differing --host-arch"; + } $self->set_conf('HOST_ARCH', $_[1]); $self->set_conf('BUILD_ARCH', $_[1]); + $opt_arch = $_[1]; }, "build=s" => sub { + if (defined $opt_build_arch && $opt_build_arch ne $_[1]) { + die "cannot specify differing --build-arch multiple times"; + } + if (defined $opt_arch && $opt_arch ne $_[1]) { + die "cannot specify --build-arch together with differing --arch"; + } $self->set_conf('BUILD_ARCH', $_[1]); + $opt_build_arch = $_[1]; }, "host=s" => sub { + if (defined $opt_host_arch && $opt_host_arch ne $_[1]) { + die "cannot specify differing --host-arch multiple times"; + } + if (defined $opt_arch && $opt_arch ne $_[1]) { + die "cannot specify --host-arch together with differing --arch"; + } $self->set_conf('HOST_ARCH', $_[1]); + $opt_host_arch = $_[1]; }, "A|arch-all" => sub { + if ($opt_no_arch_all) { + die "--arch-all cannot be used together with --no-arch-all"; + } $self->set_conf('BUILD_ARCH_ALL', 1); + $opt_arch_all = 1; }, "no-arch-all" => sub { + if ($opt_arch_all) { + die "--no-arch-all cannot be used together with --arch-all"; + } $self->set_conf('BUILD_ARCH_ALL', 0); + $opt_no_arch_all = 1; }, "arch-any" => sub { + if ($opt_no_arch_any) { + die "--arch-any cannot be used together with --no-arch-any"; + } $self->set_conf('BUILD_ARCH_ANY', 1); + $opt_arch_any = 1; }, "no-arch-any" => sub { + if ($opt_arch_any) { + die "--no-arch-any cannot be used together with --arch-any"; + } $self->set_conf('BUILD_ARCH_ANY', 0); - }, - "arch-all-only" => sub { - $self->set_conf('BUILD_ARCH_ALL', 1); - $self->set_conf('BUILD_ARCH_ANY', 0); + $opt_no_arch_any = 1; }, "profiles=s" => sub { $_[1] =~ tr/,/ /; @@ -104,29 +152,74 @@ "c|chroot=s" => sub { $self->set_conf('CHROOT', $_[1]); }, + "chroot-mode=s" => sub { + $self->set_conf('CHROOT_MODE', $_[1]); + }, + "adt-virt-server=s" => sub { + $self->set_conf('ADT_VIRT_SERVER', $_[1]); + }, + "adt-virt-server-opts=s" => sub { + push(@{$self->get_conf('ADT_VIRT_SERVER_OPTIONS')}, + split(/\s+/, $_[1])); + }, + "adt-virt-server-opt=s" => sub { + push(@{$self->get_conf('ADT_VIRT_SERVER_OPTIONS')}, $_[1]); + }, "apt-clean" => sub { + if ($opt_no_apt_clean) { + die "--apt-clean cannot be used together with --no-apt-clean"; + } $self->set_conf('APT_CLEAN', 1); + $opt_apt_clean = 1; }, "apt-update" => sub { + if ($opt_no_apt_update) { + die "--apt-update cannot be used together with --no-apt-update"; + } $self->set_conf('APT_UPDATE', 1); + $opt_apt_update = 1; }, "apt-upgrade" => sub { + if ($opt_no_apt_upgrade) { + die "--apt-upgrade cannot be used together with --no-apt-upgrade"; + } $self->set_conf('APT_UPGRADE', 1); + $opt_apt_upgrade = 1; }, "apt-distupgrade" => sub { + if ($opt_no_apt_distupgrade) { + die "--apt-distupgrade cannot be used together with --no-apt-distupgrade"; + } $self->set_conf('APT_DISTUPGRADE', 1); + $opt_apt_distupgrade = 1; }, "no-apt-clean" => sub { + if ($opt_apt_clean) { + die "--no-apt-clean cannot be used together with --apt-clean"; + } $self->set_conf('APT_CLEAN', 0); + $opt_no_apt_clean = 1; }, "no-apt-update" => sub { + if ($opt_apt_update) { + die "--no-apt-update cannot be used together with --apt-update"; + } $self->set_conf('APT_UPDATE', 0); + $opt_no_apt_update = 1; }, "no-apt-upgrade" => sub { + if ($opt_apt_upgrade) { + die "--no-apt-upgrade cannot be used together with --apt-upgrade"; + } $self->set_conf('APT_UPGRADE', 0); + $opt_no_apt_upgrade = 1; }, "no-apt-distupgrade" => sub { + if ($opt_apt_distupgrade) { + die "--no-apt-distupgrade cannot be used together with --apt-distupgrade"; + } $self->set_conf('APT_DISTUPGRADE', 0); + $opt_no_apt_distupgrade = 1; }, "d|dist=s" => sub { $self->set_conf('DISTRIBUTION', $_[1]); @@ -188,24 +281,54 @@ $self->set_conf('NOLOG', 1); }, "p|purge=s" => sub { + if (defined $opt_purge_build) { + die "cannot specify --purge together with --purge-build"; + } + if (defined $opt_purge_deps) { + die "cannot specify --purge together with --purge-deps"; + } + if (defined $opt_purge_session) { + die "cannot specify --purge together with --purge-session"; + } $self->set_conf('PURGE_BUILD_DEPS', $_[1]); $self->set_conf('PURGE_BUILD_DIRECTORY', $_[1]); $self->set_conf('PURGE_SESSION', $_[1]); + $opt_purge = 1; }, "purge-build=s" => sub { + if (defined $opt_purge) { + die "cannot specify --purge-build together with --purge"; + } $self->set_conf('PURGE_BUILD_DIRECTORY', $_[1]); + $opt_purge_build = 1; }, "purge-deps=s" => sub { + if (defined $opt_purge) { + die "cannot specify --purge-deps together with --purge"; + } $self->set_conf('PURGE_BUILD_DEPS', $_[1]); + $opt_purge_deps = 1; }, "purge-session=s" => sub { + if (defined $opt_purge) { + die "cannot specify --purge-session together with --purge"; + } $self->set_conf('PURGE_SESSION', $_[1]); + $opt_purge_session = 1; }, "s|source" => sub { + if ($opt_no_source) { + die "--source cannot be used together with --no-source"; + } $self->set_conf('BUILD_SOURCE', 1); + $opt_source = 1; }, "no-source" => sub { + if ($opt_source) { + die "--no-source cannot be used together with --source"; + } $self->set_conf('BUILD_SOURCE', 0); + $opt_no_source = 1; }, "archive=s" => sub { $self->set_conf('ARCHIVE', $_[1]); @@ -234,23 +357,50 @@ "build-dep-resolver=s" => sub { $self->set_conf('BUILD_DEP_RESOLVER', $_[1]); }, + "aspcud-criteria=s" => sub { + $self->set_conf('ASPCUD_CRITERIA', $_[1]); + }, "resolve-alternatives" => sub { + if ($opt_no_resolve_alternatives) { + die "--resolve-alternatives cannot be used together with --no-resolve-alternatives"; + } $self->set_conf('RESOLVE_ALTERNATIVES', 1); + $opt_resolve_alternatives = 1; }, "no-resolve-alternatives" => sub { + if ($opt_resolve_alternatives) { + die "--no-resolve-alternatives cannot be used together with --resolve-alternatives"; + } $self->set_conf('RESOLVE_ALTERNATIVES', 0); + $opt_no_resolve_alternatives = 1; }, "clean-source" => sub { + if ($opt_no_clean_source) { + die "--clean-source cannot be used together with --no-clean-source"; + } $self->set_conf('CLEAN_SOURCE', 1); + $opt_clean_source = 1; }, "no-clean-source" => sub { + if ($opt_clean_source) { + die "--no-clean-source cannot be used together with --clean-source"; + } $self->set_conf('CLEAN_SOURCE', 0); + $opt_no_clean_source = 1; }, "run-lintian" => sub { + if ($opt_no_run_lintian) { + die "--run-lintian cannot be used together with --no-run-lintian"; + } $self->set_conf('RUN_LINTIAN', 1); + $opt_run_lintian = 1; }, "no-run-lintian" => sub { + if ($opt_run_lintian) { + die "--no-run-lintian cannot be used together with --run-lintian"; + } $self->set_conf('RUN_LINTIAN', 0); + $opt_no_run_lintian = 1; }, "lintian-opts=s" => sub { push(@{$self->get_conf('LINTIAN_OPTIONS')}, @@ -261,10 +411,18 @@ $_[1]); }, "run-piuparts" => sub { + if ($opt_no_run_piuparts) { + die "--run-piuparts cannot be used together with --no-run-piuparts"; + } $self->set_conf('RUN_PIUPARTS', 1); + $opt_run_piuparts = 1; }, "no-run-piuparts" => sub { + if ($opt_run_piuparts) { + die "--no-run-piuparts cannot be used together with --run-piuparts"; + } $self->set_conf('RUN_PIUPARTS', 0); + $opt_no_run_piuparts = 1; }, "piuparts-opts=s" => sub { push(@{$self->get_conf('PIUPARTS_OPTIONS')}, @@ -290,6 +448,10 @@ push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"chroot-setup-commands"}}, $_[1]); }, + "chroot-update-failed-commands=s" => sub { + push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"chroot-update-failed-commands"}}, + $_[1]); + }, "build-deps-failed-commands=s" => sub { push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"build-deps-failed-commands"}}, $_[1]); @@ -303,6 +465,8 @@ # --anything-failed-commands simply triggers all the # --xxx-failed-commands I know about + push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"chroot-update-failed-commands"}}, + $_[1]); push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"build-deps-failed-commands"}}, $_[1]); push(@{${$self->get_conf('EXTERNAL_COMMANDS')}{"build-failed-commands"}}, diff -Nru sbuild-0.67.0/lib/Sbuild/ResolverBase.pm sbuild-0.69.0/lib/Sbuild/ResolverBase.pm --- sbuild-0.67.0/lib/Sbuild/ResolverBase.pm 2015-12-26 10:32:21.712607841 +0000 +++ sbuild-0.69.0/lib/Sbuild/ResolverBase.pm 2016-04-28 05:04:00.686602490 +0000 @@ -25,7 +25,7 @@ use warnings; use POSIX; use Fcntl; -use File::Temp qw(tempdir tempfile); +use File::Temp qw(tempfile); use File::Copy; use Dpkg::Deps; @@ -63,11 +63,11 @@ $self->set('Initial Foreign Arches', {}); $self->set('Added Foreign Arches', {}); - my $dummy_archive_list_file = $session->get('Location') . + my $dummy_archive_list_file = '/etc/apt/sources.list.d/sbuild-build-depends-archive.list'; $self->set('Dummy archive list file', $dummy_archive_list_file); - my $dummy_archive_key_file = $session->get('Location') . + my $dummy_archive_key_file = '/etc/apt/trusted.gpg.d/sbuild-build-depends-archive.gpg'; $self->set('Dummy archive key file', $dummy_archive_key_file); @@ -89,25 +89,45 @@ my $chroot_aptconf = $session->get('Location') . "/$aptconf"; $self->set('Chroot APT Conf', $chroot_aptconf); + my $tmpaptconf = $session->mktemp({ TEMPLATE => "$aptconf.XXXXXX"}); + if (!$tmpaptconf) { + $self->log_error("Can't create $chroot_aptconf.XXXXXX: $!\n"); + return 0; + } + + my $F = $session->get_write_file_handle($tmpaptconf); + if (!$F) { + $self->log_error("Cannot open pipe: $!\n"); + return 0; + } + # Always write out apt.conf, because it may become outdated. - if (my $F = eval {new File::Temp( TEMPLATE => "$aptconf.XXXXXX", - DIR => $session->get('Location'), - UNLINK => 0) } ) { - if ($self->get_conf('APT_ALLOW_UNAUTHENTICATED')) { - print $F "APT::Get::AllowUnauthenticated true;\n"; - } - print $F "APT::Install-Recommends false;\n"; + if ($self->get_conf('APT_ALLOW_UNAUTHENTICATED')) { + print $F qq(APT::Get::AllowUnauthenticated "true";\n"); + } + print $F qq(APT::Install-Recommends "false";\n); + print $F qq(APT::AutoRemove::SuggestsImportant "false";\n); + print $F qq(APT::AutoRemove::RecommendsImportant "false";\n); + print $F qq(Acquire::Languages "none";\n); # do not download translations - if ($self->get('Split')) { - print $F "Dir \"$chroot_dir\";\n"; - } + if ($self->get('Split')) { + print $F "Dir \"$chroot_dir\";\n"; + } - if (! rename $F->filename, $chroot_aptconf) { - $self->log_error("Can't rename $F->filename to $chroot_aptconf: $!\n"); - return 0; - } - } else { - $self->log_error("Can't create $chroot_aptconf: $!\n"); + close $F; + + if (!$session->rename($tmpaptconf, $aptconf)) { + $self->log_error("Can't rename $tmpaptconf to $aptconf: $!\n"); + return 0; + } + + if (!$session->chown($aptconf, $self->get_conf('BUILD_USER'), 'sbuild')) { + $self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER') . + ":sbuild ownership on apt.conf at $aptconf\n"); + return 0; + } + if (!$session->chmod($aptconf, '0664')) { + $self->log_error("E: Failed to set 0664 permissions on apt.conf at $aptconf\n"); return 0; } @@ -153,31 +173,27 @@ return {}; } - my ($tmpfh, $tmpfilename) = tempfile(DIR => $session->get('Location') . "/tmp"); + my $foreignarchs = $session->read_command({ COMMAND => ['dpkg', '--print-foreign-architectures'], USER => 'root' }); - $session->run_command({ COMMAND => ['dpkg', '--print-foreign-architectures'], - USER => 'root', - STREAMOUT => $tmpfh}); - if ($?) - { + if (!defined($foreignarchs)) { $self->set('Multiarch Support', 0); - $self->log_error("Failed to get dpkg foreign-architecture config\n"); - close $tmpfh; - unlink $tmpfilename; + $self->log_error("dpkg does not support multi-arch\n"); return {}; - } # else dpkg has multiarch support - seek $tmpfh, 0, SEEK_SET; - my @existing_foreign_arches; - while(<$tmpfh>) + } + + if (!$foreignarchs) { - chomp; - next unless $_; - push @existing_foreign_arches, $_; + $self->log("There are no foreign architectures configured\n"); + return {}; } - close $tmpfh; - unlink $tmpfilename; + my %set; - foreach (@existing_foreign_arches) { $set{$_} = 1; } + foreach my $arch (split /\s+/, $foreignarchs) { + chomp; + next unless $_; + $set{$_} = 1; + } + return \%set; } @@ -187,12 +203,20 @@ my $arch = shift; # just skip if dpkg is to old for multiarch - if (! $self->get('Multiarch Support')) { return 1 }; + if (! $self->get('Multiarch Support')) { + debug("not adding $arch because of no multiarch support\n"); + return 1; + }; # if we already have this architecture, we're done - my $initial_foreign_arches = $self->get('Initial Foreign Arches'); - my $added_foreign_arches = $self->get('Added Foreign Arches'); - return if $initial_foreign_arches->{$arch} || $added_foreign_arches->{$arch}; + if ($self->get('Initial Foreign Arches')->{$arch}) { + debug("not adding $arch because it is an initial arch\n"); + return 1; + } + if ($self->get('Added Foreign Arches')->{$arch}) { + debug("not adding $arch because it has already been aded"); + return 1; + } my $session = $self->get('Session'); @@ -213,7 +237,7 @@ } debug("Added foreign arch: $arch\n") if $arch; - $added_foreign_arches->{$arch} = 1; + $self->get('Added Foreign Arches')->{$arch} = 1; return 1; } @@ -227,6 +251,11 @@ my $session = $self->get('Session'); + if (defined ($session->get('Session Purged')) && $session->get('Session Purged') == 1) { + $self->log("Not removing foreign architectures: cloned chroot in use\n"); + return; + } + foreach my $arch (keys %{$added_foreign_arches}) { $self->log("Removing foreign architecture $arch\n"); $session->run_command({ COMMAND => ['dpkg', '--remove-architecture', $arch], @@ -283,7 +312,6 @@ ENV => {'DEBIAN_FRONTEND' => 'noninteractive'}, USER => 'root', DIR => '/' }); - return $?; } else { my $session = $self->get('Session'); my $dummy_archive_list_file = $self->get('Dummy archive list file'); @@ -293,7 +321,7 @@ # 448eaf8 in apt 0.8.0 and af13d14 in apt 0.9.3). Since this # runs against the target chroot's apt, be conservative. my $dummy_sources_list_d = $self->get('Dummy package path') . '/sources.list.d'; - if (!(-d $dummy_sources_list_d || mkdir $dummy_sources_list_d, 0700)) { + if (!($session->test_directory($dummy_sources_list_d) || $session->mkdir($dummy_sources_list_d, { MODE => "00700"}))) { $self->log_warning('Could not create build-depends dummy sources.list directory ' . $dummy_sources_list_d . ': ' . $!); $self->cleanup_apt_archive(); return 0; @@ -309,21 +337,28 @@ # 872ed75 in apt 0.9.1.) $self->run_apt_command( { COMMAND => [$self->get_conf('APT_GET'), 'update', - '-o', 'Dir::Etc::sourcelist=' . $session->strip_chroot_path($dummy_archive_list_file), - '-o', 'Dir::Etc::sourceparts=' . $session->strip_chroot_path($dummy_sources_list_d), + '-o', 'Dir::Etc::sourcelist=' . $dummy_archive_list_file, + '-o', 'Dir::Etc::sourceparts=' . $dummy_sources_list_d, '--no-list-cleanup'], ENV => {'DEBIAN_FRONTEND' => 'noninteractive'}, USER => 'root', DIR => '/' }); - return $? if $?; + if ($? != 0) { + return 0; + } $self->run_apt_command( { COMMAND => [$self->get_conf('APT_CACHE'), 'gencaches'], ENV => {'DEBIAN_FRONTEND' => 'noninteractive'}, USER => 'root', DIR => '/' }); - return $?; } + + if ($? != 0) { + return 0; + } + + return 1; } sub upgrade { @@ -414,15 +449,14 @@ my $self = shift; my $name = shift; - return $self->install_deps($name, 0, @_); + return $self->install_deps($name, @_); } sub install_main_deps { my $self = shift; my $name = shift; - my $cross = $self->get('Host Arch') ne $self->get('Build Arch'); - return $self->install_deps($name, $cross, @_); + return $self->install_deps($name, @_); } sub uninstall_deps { @@ -539,6 +573,7 @@ '-o', 'DPkg::Options::=--force-confold', '-o', 'DPkg::Options::=--refuse-remove-essential', '-o', 'APT::Install-Recommends=false', + '-o', 'Dpkg::Use-Pty=false', '-q'); push @apt_command, '--allow-unauthenticated' if ($self->get_conf('APT_ALLOW_UNAUTHENTICATED')); @@ -704,27 +739,22 @@ my $session = $self->get('Session'); + #Prepare a path to build a dummy package containing our deps: if (! defined $self->get('Dummy package path')) { - $self->set('Dummy package path', - tempdir('resolver' . '-XXXXXX', - DIR => $self->get('Chroot Build Dir'))); + my $tmpdir = $session->mktemp({ TEMPLATE => $self->get('Build Dir') . '/resolver-XXXXXX', DIRECTORY => 1}); + if (!$tmpdir) { + $self->log_error("E: mktemp -d " . $self->get('Build Dir') . '/resolver-XXXXXX failed\n'); + return 0; + } + $self->set('Dummy package path', $tmpdir); } - $session->run_command( - { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild', - $session->strip_chroot_path($self->get('Dummy package path'))], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chown($self->get('Dummy package path'), $self->get_conf('BUILD_USER'), 'sbuild')) { $self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER') . ":sbuild ownership on dummy package dir\n"); return 0; } - $session->run_command( - { COMMAND => ['chmod', '0770', $session->strip_chroot_path($self->get('Dummy package path'))], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chmod($self->get('Dummy package path'), '0770')) { $self->log_error("E: Failed to set 0770 permissions on dummy package dir\n"); return 0; } @@ -739,27 +769,22 @@ $self->set('Dummy Release file', $dummy_release_file); my $dummy_archive_list_file = $self->get('Dummy archive list file'); - if (! -d $dummy_dir) { + if (!$session->test_directory($dummy_dir)) { $self->log_warning('Could not create build-depends dummy dir ' . $dummy_dir . ': ' . $!); $self->cleanup_apt_archive(); return 0; } - if (!(-d $dummy_gpghome || mkdir $dummy_gpghome, 0700)) { + if (!($session->test_directory($dummy_gpghome) || $session->mkdir($dummy_gpghome, { MODE => "00700"}))) { $self->log_warning('Could not create build-depends dummy gpg home dir ' . $dummy_gpghome . ': ' . $!); $self->cleanup_apt_archive(); return 0; } - $session->run_command( - { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild', - $session->strip_chroot_path($dummy_gpghome)], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chown($dummy_gpghome, $self->get_conf('BUILD_USER'), 'sbuild')) { $self->log_error('E: Failed to set ' . $self->get_conf('BUILD_USER') . ':sbuild ownership on $dummy_gpghome\n'); return 0; } - if (!(-d $dummy_archive_dir || mkdir $dummy_archive_dir, 0775)) { + if (!($session->test_directory($dummy_archive_dir) || $session->mkdir($dummy_archive_dir, { MODE => "00775"}))) { $self->log_warning('Could not create build-depends dummy archive dir ' . $dummy_archive_dir . ': ' . $!); $self->cleanup_apt_archive(); return 0; @@ -769,20 +794,27 @@ my $dummy_deb = $dummy_archive_dir . '/' . $dummy_pkg_name . '.deb'; my $dummy_dsc = $dummy_archive_dir . '/' . $dummy_pkg_name . '.dsc'; - if (!(mkdir($dummy_pkg_dir) && mkdir($dummy_pkg_dir . '/DEBIAN'))) { + if (!($session->mkdir("$dummy_pkg_dir", { MODE => "00775"}))) { + $self->log_warning('Could not create build-depends dummy dir ' . $dummy_pkg_dir . $!); + $self->cleanup_apt_archive(); + return 0; + } + + if (!($session->mkdir("$dummy_pkg_dir/DEBIAN", { MODE => "00775"}))) { $self->log_warning('Could not create build-depends dummy dir ' . $dummy_pkg_dir . '/DEBIAN: ' . $!); $self->cleanup_apt_archive(); return 0; } - if (!open(DUMMY_CONTROL, '>', $dummy_pkg_dir . '/DEBIAN/control')) { + my $DUMMY_CONTROL = $session->get_write_file_handle("$dummy_pkg_dir/DEBIAN/control"); + if (!$DUMMY_CONTROL) { $self->log_warning('Could not open ' . $dummy_pkg_dir . '/DEBIAN/control for writing: ' . $!); $self->cleanup_apt_archive(); return 0; } my $arch = $self->get('Host Arch'); - print DUMMY_CONTROL <<"EOF"; + print $DUMMY_CONTROL <<"EOF"; Package: $dummy_pkg_name Version: 0.invalid.0 Architecture: $arch @@ -904,33 +936,28 @@ } if ($positive ne "") { - print DUMMY_CONTROL 'Depends: ' . $positive . "\n"; + print $DUMMY_CONTROL 'Depends: ' . $positive . "\n"; } if ($negative ne "") { - print DUMMY_CONTROL 'Conflicts: ' . $negative . "\n"; + print $DUMMY_CONTROL 'Conflicts: ' . $negative . "\n"; } $self->log("Filtered Build-Depends: $positive\n") if $positive; $self->log("Filtered Build-Conflicts: $negative\n") if $negative; - print DUMMY_CONTROL <<"EOF"; + print $DUMMY_CONTROL <<"EOF"; Maintainer: Debian buildd-tools Developers Description: Dummy package to satisfy dependencies with apt - created by sbuild This package was created automatically by sbuild and should never appear on a real system. You can safely remove it. EOF - close (DUMMY_CONTROL); + close ($DUMMY_CONTROL); foreach my $path ($dummy_pkg_dir . '/DEBIAN/control', $dummy_pkg_dir . '/DEBIAN', $dummy_pkg_dir, $dummy_archive_dir) { - $session->run_command( - { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild', - $session->strip_chroot_path($path)], - USER => 'root', - DIR => '/' }); - if ($?) { + if (!$session->chown($path, $self->get_conf('BUILD_USER'), 'sbuild')) { $self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER') . ":sbuild ownership on $path\n"); return 0; @@ -939,7 +966,7 @@ #Now build the package: $session->run_command( - { COMMAND => ['dpkg-deb', '--build', $session->strip_chroot_path($dummy_pkg_dir), $session->strip_chroot_path($dummy_deb)], + { COMMAND => ['dpkg-deb', '--build', $dummy_pkg_dir, $dummy_deb], USER => $self->get_conf('BUILD_USER'), PRIORITY => 0}); if ($?) { @@ -949,8 +976,8 @@ } # Write the dummy dsc file. - my $dummy_dsc_fh; - if (!open($dummy_dsc_fh, '>', $dummy_dsc)) { + my $dummy_dsc_fh = $session->get_write_file_handle($dummy_dsc); + if (!$dummy_dsc_fh) { $self->log_warning('Could not open ' . $dummy_dsc . ' for writing: ' . $!); $self->cleanup_apt_archive(); return 0; @@ -1005,20 +1032,26 @@ $self->cleanup_apt_archive(); return 0; } - copy($self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY'), $dummy_archive_seckey) unless - (-f $dummy_archive_seckey); - copy($self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY'), $dummy_archive_pubkey) unless - (-f $dummy_archive_pubkey); + if (!$session->test_regular_file($dummy_archive_seckey)) { + if (!$session->copy_to_chroot($self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY'), $dummy_archive_seckey)) { + $self->log_error("Failed to copy secret key"); + return 0; + } + } + if (!$session->test_regular_file($dummy_archive_pubkey)) { + if (!$session->copy_to_chroot($self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY'), $dummy_archive_pubkey)) { + $self->log_error("Failed to copy public key"); + return 0; + } + } my @gpg_command = ('gpg', '--yes', '--no-default-keyring', - '--homedir', - $session->strip_chroot_path($dummy_gpghome), - '--secret-keyring', - $session->strip_chroot_path($dummy_archive_seckey), - '--keyring', - $session->strip_chroot_path($dummy_archive_pubkey), + '--homedir', $dummy_gpghome, + '--secret-keyring', $dummy_archive_seckey, + '--keyring', $dummy_archive_pubkey, '--default-key', 'Sbuild Signer', '-abs', - '-o', $session->strip_chroot_path($dummy_release_file) . '.gpg', - $session->strip_chroot_path($dummy_release_file)); + '--digest-algo', 'SHA512', + '-o', $dummy_release_file . '.gpg', + $dummy_release_file); $session->run_command( { COMMAND => \@gpg_command, USER => $self->get_conf('BUILD_USER'), @@ -1035,7 +1068,15 @@ # build. if (@{$self->get_conf('EXTRA_REPOSITORY_KEYS')}) { my $dummy_archive_key_file = $self->get('Dummy archive key file'); - my ($tmpfh, $tmpfilename) = tempfile(DIR => $session->get('Location') . "/tmp"); + + my $tmpfilename = $session->mktemp(); + + my $tmpfh = $session->get_write_file_handle($tmpfilename); + if (!$tmpfh) { + $self->log_error("Cannot open pipe: $!\n"); + return 0; + } + # Right, so, in order to copy the keys into the chroot (since we may have # a bunch of them), we'll append to a tempfile, and write *all* of the # given keys to the same tempfile. After we're clear, we'll move that file @@ -1047,10 +1088,24 @@ $self->log("Failed to add archive key '${repokey}' - it doesn't exist!\n"); $self->cleanup_apt_archive(); close($tmpfh); - unlink $tmpfilename; + $session->unlink($tmpfilename); return 0; } - copy($repokey, $tmpfh); + local *INFILE; + if(!open(INFILE, "<", $repokey)) { + $self->log("Failed to add archive key '${repokey}' - it cannot be opened for reading!\n"); + $self->cleanup_apt_archive(); + close($tmpfh); + $session->unlink($tmpfilename); + return 0; + } + + while ( (read (INFILE, my $buffer, 65536)) != 0 ) { + print $tmpfh $buffer; + } + + close INFILE; + print $tmpfh "\n"; } close($tmpfh); @@ -1060,14 +1115,18 @@ # out the secret ring and home to ensure we don't store anything # except for the public keyring. - my $tmpgpghome = tempdir('extra-repository-keys' . '-XXXXXX', - DIR => $session->get('Location') . "/tmp"); + + my $tmpgpghome = $session->mktemp({ TEMPLATE => '/tmp/extra-repository-keys-XXXXXX', DIRECTORY => 1}); + if (!$tmpgpghome) { + $self->log_error("mktemp /tmp/extra-repository-keys-XXXXXX failed\n"); + return 0; + } my @gpg_command = ('gpg', '--import', '--no-default-keyring', - '--homedir', $session->strip_chroot_path($tmpgpghome), + '--homedir', $tmpgpghome, '--secret-keyring', '/dev/null', - '--keyring', $session->strip_chroot_path($dummy_archive_key_file), - $session->strip_chroot_path($tmpfilename)); + '--keyring', $dummy_archive_key_file, + $tmpfilename); $session->run_command( { COMMAND => \@gpg_command, @@ -1076,15 +1135,27 @@ if ($?) { $self->log("Failed to import archive keys to the trusted keyring"); $self->cleanup_apt_archive(); - unlink $tmpfilename; + $session->unlink($tmpfilename); return 0; } - unlink $tmpfilename; + $session->unlink($tmpfilename); } # Write a list file for the dummy archive if one not create yet. - if (! -f $dummy_archive_list_file) { - my ($tmpfh, $tmpfilename) = tempfile(DIR => $session->get('Location') . "/tmp"); + if (!$session->test_regular_file($dummy_archive_list_file)) { + my $tmpfilename = $session->mktemp(); + + if (!$tmpfilename) { + $self->log_error("Can't create tempfile\n"); + return 0; + } + + my $tmpfh = $session->get_write_file_handle($tmpfilename); + if (!$tmpfh) { + $self->log_error("Cannot open pipe: $!\n"); + return 0; + } + # We always trust the dummy apt repositories. # This means that if SBUILD_BUILD_DEPENDS_{SECRET|PUBLIC}_KEY do not # exist and thus the dummy repositories do not get signed, apt will @@ -1093,8 +1164,15 @@ # Older apt from squeeze will still require keys to be generated as it # ignores the trusted=yes. Older apt ignoring this is also why we can add # this unconditionally. - print $tmpfh 'deb [trusted=yes] file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; - print $tmpfh 'deb-src [trusted=yes] file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n"; + # + # We use copy:// instead of file:// as URI because the latter will make + # apt use symlinks in /var/lib/apt/lists. These symlinks will become + # broken after the dummy archive is removed. This in turn confuses + # launchpad-buildd which directly tries to access + # /var/lib/apt/lists/*_Packages and cannot use `apt-get indextargets` as + # that apt feature is too new for it. + print $tmpfh 'deb [trusted=yes] copy://' . $dummy_archive_dir . " ./\n"; + print $tmpfh 'deb-src [trusted=yes] copy://' . $dummy_archive_dir . " ./\n"; for my $repospec (@{$self->get_conf('EXTRA_REPOSITORIES')}) { print $tmpfh "$repospec\n"; @@ -1102,28 +1180,18 @@ close($tmpfh); # List file needs to be moved with root. - $session->run_command( - { COMMAND => ['chmod', '0644', $session->strip_chroot_path($tmpfilename)], - USER => 'root', - PRIORITY => 0}); - if ($?) { + if (!$session->chmod($tmpfilename, '0644')) { $self->log("Failed to create apt list file for dummy archive.\n"); $self->cleanup_apt_archive(); - unlink $tmpfilename; + $session->unlink($tmpfilename); return 0; } - $session->run_command( - { COMMAND => ['mv', $session->strip_chroot_path($tmpfilename), - $session->strip_chroot_path($dummy_archive_list_file)], - USER => 'root', - PRIORITY => 0}); - if ($?) { + if (!$session->rename($tmpfilename, $dummy_archive_list_file)) { $self->log("Failed to create apt list file for dummy archive.\n"); $self->cleanup_apt_archive(); - unlink $tmpfilename; + $session->unlink($tmpfilename); return 0; } - unlink $tmpfilename; } if ((-f $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY')) && @@ -1131,7 +1199,7 @@ !$self->get_conf('APT_ALLOW_UNAUTHENTICATED')) { # Add the generated key $session->run_command( - { COMMAND => ['apt-key', 'add', $session->strip_chroot_path($dummy_archive_pubkey)], + { COMMAND => ['apt-key', 'add', $dummy_archive_pubkey], USER => 'root', PRIORITY => 0}); if ($?) { @@ -1151,23 +1219,12 @@ my $session = $self->get('Session'); if (defined $self->get('Dummy package path')) { - $session->run_command( - { COMMAND => ['rm', '-fr', $session->strip_chroot_path($self->get('Dummy package path'))], - USER => $self->get_conf('BUILD_USER'), - DIR => '/' }); + $session->unlink($self->get('Dummy package path'), { RECURSIVE => 1, FORCE => 1 }); } - $session->run_command( - { COMMAND => ['rm', '-f', $session->strip_chroot_path($self->get('Dummy archive list file'))], - USER => 'root', - DIR => '/', - PRIORITY => 0}); + $session->unlink($self->get('Dummy archive list file'), { FORCE => 1 }); - $session->run_command( - { COMMAND => ['rm', '-f', $session->strip_chroot_path($self->get('Dummy archive key file'))], - USER => 'root', - DIR => '/', - PRIORITY => 0}); + $session->unlink($self->get('Dummy archive key file'), { FORCE => 1 }); $self->set('Dummy package path', undef); $self->set('Dummy archive directory', undef); @@ -1199,86 +1256,128 @@ my $self = shift; my $session = $self->get('Session'); - my $host = $self->get('Host'); - - my ($tmpfh, $tmpfilename) = tempfile(); my $dummy_archive_dir = $self->get('Dummy archive directory'); for my $deb (@{$self->get_conf('EXTRA_PACKAGES')}) { - copy($deb, $dummy_archive_dir); + $session->copy_to_chroot($deb, $dummy_archive_dir); } - # Write the conf file. - print $tmpfh <<"EOF"; -Dir { - ArchiveDir "$dummy_archive_dir"; -}; - -Default { - Packages::Compress ". gzip"; - Sources::Compress ". gzip"; -}; - -BinDirectory "$dummy_archive_dir" { - Packages "Packages"; - Sources "Sources"; -}; - -APT::FTPArchive::Release::Origin "sbuild-build-depends-archive"; -APT::FTPArchive::Release::Label "sbuild-build-depends-archive"; -APT::FTPArchive::Release::Suite "invalid"; -APT::FTPArchive::Release::Codename "invalid"; -APT::FTPArchive::Release::Description "Sbuild Build Dependency Temporary Archive"; -EOF - close $tmpfh; - - # Remove APT_CONFIG environment variable here, restore it later. - my $env = $self->get('Session')->get('Defaults')->{'ENV'}; - my $apt_config_value = $env->{'APT_CONFIG'}; - delete $env->{'APT_CONFIG'}; - - # Run apt-ftparchive to generate Packages and Sources files. - $host->run_command( - { COMMAND => ['apt-ftparchive', '-q=2', 'generate', $tmpfilename], - USER => $self->get_conf('USERNAME'), - PRIORITY => 0, - DIR => '/'}); - if ($?) { - $env->{'APT_CONFIG'} = $apt_config_value; - unlink $tmpfilename; - return 0; - } + # We create the Packages, Sources and Release file inside the chroot. + # We cannot use apt-ftparchive as this is not available inside the chroot. + # Apt-ftparchive outside the chroot might not have access to the files + # inside the chroot (for example when using qemu or ssh backends). + # The only alternative would've been to set up the archive outside the + # chroot using apt-ftparchive and to then copy Packages, Sources and + # Release into the chroot. + # We do not do this to avoid copying files from and to the chroot. + # At the same time doing it like this has the advantage to have less + # dependencies of sbuild itself (no apt-ftparchive needed). + # The disadvantage of doing it this way is that we now have to maintain + # our own code creating the Release file which might break in the future. + my $packagessourcescmd = <<'SCRIPTEND'; +use strict; +use warnings; - # Get output for Release file - my $pipe = $host->pipe_command( - { COMMAND => ['apt-ftparchive', '-q=2', '-c', $tmpfilename, 'release', $dummy_archive_dir], - USER => $self->get_conf('USERNAME'), - PRIORITY => 0, - DIR => '/'}); - if (!defined($pipe)) { - $env->{'APT_CONFIG'} = $apt_config_value; - unlink $tmpfilename; - return 0; - } - $env->{'APT_CONFIG'} = $apt_config_value; +use IO::Compress::Gzip qw(gzip $GzipError); +use Digest::MD5; +use Digest::SHA; +use POSIX qw(strftime); + +# Execute a command without /bin/sh but plain execvp while redirecting its +# standard output to a file given as the first argument. +# Using "print $fh `my_command`" has the disadvantage that "my_command" might +# be executed through /bin/sh (depending on the characters used) or that the +# output of "my_command" is very long. +sub system_redir_stdout +{ + my ($filename, @args) = @_; + + open(my $saved_stdout, ">&STDOUT") or die "cannot save stdout: $!"; + open(my $packages, '>', $filename) or die "cannot open Packages for writing: $!"; + open(STDOUT, '>&', $packages) or die "cannot redirect stdout: $!"; + + system(@args) == 0 or die "system @args failed: $?"; + + open(STDOUT, '>&', $saved_stdout) or die "cannot restore stdout: $!"; + close $saved_stdout; + close $packages; +} + +sub hash_file($$) +{ + my ($filename, $hashobj) = @_; + open (my $handle, '<', $filename) or die "cannot open $filename for reading: $!"; + my $hash = $hashobj->addfile($handle)->hexdigest; + close $handle; + return $hash; +} + +system_redir_stdout('Packages', 'dpkg-scanpackages', '.', '/dev/null'); +system_redir_stdout('Sources', 'dpkg-scansources', '.', '/dev/null'); + +gzip 'Packages' => 'Packages.gz' or die "gzip failed: $GzipError\n"; +gzip 'Sources' => 'Sources.gz' or die "gzip failed: $GzipError\n"; + +my $packages_md5 = hash_file('Packages', Digest::MD5->new); +my $sources_md5 = hash_file('Sources', Digest::MD5->new); +my $packagesgz_md5 = hash_file('Packages.gz', Digest::MD5->new); +my $sourcesgz_md5 = hash_file('Sources.gz', Digest::MD5->new); + +my $packages_sha1 = hash_file('Packages', Digest::SHA->new(1)); +my $sources_sha1 = hash_file('Sources', Digest::SHA->new(1)); +my $packagesgz_sha1 = hash_file('Packages.gz', Digest::SHA->new(1)); +my $sourcesgz_sha1 = hash_file('Sources.gz', Digest::SHA->new(1)); + +my $packages_sha256 = hash_file('Packages', Digest::SHA->new(256)); +my $sources_sha256 = hash_file('Sources', Digest::SHA->new(256)); +my $packagesgz_sha256 = hash_file('Packages.gz', Digest::SHA->new(256)); +my $sourcesgz_sha256 = hash_file('Sources.gz', Digest::SHA->new(256)); + +my $packages_size = -s 'Packages'; +my $sources_size = -s 'Sources'; +my $packagesgz_size = -s 'Packages.gz'; +my $sourcesgz_size = -s 'Sources.gz'; + +# time format stolen from apt ftparchive/writer.cc +my $datestring = strftime "%a, %d %b %Y %H:%M:%S UTC", gmtime(); + +open(my $releasefh, '>', 'Release') or die "cannot open Release for writing: $!"; + +print $releasefh <<"END"; +Codename: invalid +Date: $datestring +Description: Sbuild Build Dependency Temporary Archive +Label: sbuild-build-depends-archive +Origin: sbuild-build-depends-archive +Suite: invalid +MD5Sum: + $packages_md5 $packages_size Packages + $sources_md5 $sources_size Sources + $packagesgz_md5 $packagesgz_size Packages.gz + $sourcesgz_md5 $sourcesgz_size Sources.gz +SHA1: + $packages_sha1 $packages_size Packages + $sources_sha1 $sources_size Sources + $packagesgz_sha1 $packagesgz_size Packages.gz + $sourcesgz_sha1 $sourcesgz_size Sources.gz +SHA256: + $packages_sha256 $packages_size Packages + $sources_sha256 $sources_size Sources + $packagesgz_sha256 $packagesgz_size Packages.gz + $sourcesgz_sha256 $sourcesgz_size Sources.gz +END +close $releasefh; - # Write output to Release file path. - my ($releasefh); - if (!open($releasefh, '>', $self->get('Dummy Release file'))) { - close $pipe; - unlink $tmpfilename; - return 0; - } +SCRIPTEND - while (<$pipe>) { - print $releasefh $_; + $session->run_command( + { COMMAND => ['perl', '-e', $packagessourcescmd], + USER => "root", DIR => $dummy_archive_dir}); + if ($? ne 0) { + $self->log_error("cannot create dummy archive"); + return 0; } - close $releasefh; - close $pipe; - - # Remove config file. Note also removed on failure paths above. - unlink $tmpfilename; return 1; } diff -Nru sbuild-0.67.0/lib/Sbuild/Utility.pm sbuild-0.69.0/lib/Sbuild/Utility.pm --- sbuild-0.67.0/lib/Sbuild/Utility.pm 2015-12-26 10:32:21.820608177 +0000 +++ sbuild-0.69.0/lib/Sbuild/Utility.pm 2016-04-30 05:39:28.632491183 +0000 @@ -88,6 +88,8 @@ my $chroot_info; if ($conf->get('CHROOT_MODE') eq 'schroot') { $chroot_info = Sbuild::ChrootInfoSchroot->new($conf); + } elsif ($conf->get('CHROOT_MODE') eq 'adt') { + $chroot_info = Sbuild::ChrootInfoADT->new($conf); } else { $chroot_info = Sbuild::ChrootInfoSudo->new($conf); } diff -Nru sbuild-0.67.0/lib/Sbuild/XaptResolver.pm sbuild-0.69.0/lib/Sbuild/XaptResolver.pm --- sbuild-0.67.0/lib/Sbuild/XaptResolver.pm 2015-12-01 21:29:48.463402744 +0000 +++ sbuild-0.69.0/lib/Sbuild/XaptResolver.pm 2016-04-20 11:06:05.425529859 +0000 @@ -52,7 +52,6 @@ sub install_deps { my $self = shift; my $name = shift; - my $cross = shift; my @pkgs = @_; my $status = 0; diff -Nru sbuild-0.67.0/lib/Sbuild.pm sbuild-0.69.0/lib/Sbuild.pm --- sbuild-0.67.0/lib/Sbuild.pm 2015-12-26 10:32:21.660607678 +0000 +++ sbuild-0.69.0/lib/Sbuild.pm 2016-05-03 05:36:20.470050360 +0000 @@ -43,7 +43,7 @@ @EXPORT = qw($debug_level $devnull binNMU_version parse_date isin copy dump_file check_packages help_text version_text usage_error send_mail debug debug2 df - check_group_membership dsc_files dsc_pkgver); + check_group_membership dsc_files dsc_pkgver shellescape); } our $devnull; @@ -69,6 +69,7 @@ sub debug2 (@); sub check_group_membership(); sub dsc_files ($); +sub shellescape ($); sub binNMU_version ($$$) { my $v = shift; @@ -249,7 +250,7 @@ my $section = shift; my $page = shift; - system("/usr/bin/man", "$section", "$page"); + system(qw('man --'), $section, $page); exit 0; } @@ -413,4 +414,22 @@ return ($pdsc->{'Source'}, $pdsc->{'Version'}); } +# avoid dependency on String::ShellQuote by implementing the mechanism +# from python's shlex.quote function +sub shellescape ($) { + my $string = shift; + if (length $string == 0) { + return "''"; + } + # search for occurrences of characters that are not safe + # the 'a' regex modifier makes sure that \w only matches ASCII + if ($string !~ m/[^\w@\%+=:,.\/-]/a) { + return $string; + } + # wrap the string in single quotes and handle existing single quotes by + # putting them outside of the single-quoted string + $string =~ s/'/'"'"'/g; + return "'$string'"; +}; + 1; diff -Nru sbuild-0.67.0/man/sbuild.1.in sbuild-0.69.0/man/sbuild.1.in --- sbuild-0.67.0/man/sbuild.1.in 2015-12-26 10:32:21.604607503 +0000 +++ sbuild-0.69.0/man/sbuild.1.in 2016-05-08 10:31:22.478022025 +0000 @@ -28,9 +28,9 @@ .RB [ \-\-archive=\fIarchive\fP ] .RB [ \-d \[or] \-\-dist=\fIdistribution\fP ] .RB [ \-c \[or] \-\-chroot=\fIchroot\fP ] +.RB [ \-\-chroot-mode=\fIschroot|sudo|adt\fP ] .RB [ \-\-arch=\fIarchitecture\fP ] .RB [ \-\-arch\-any " \[or] " \-\-no\-arch\-any ] -.RB [ \-\-arch\-all\-only ] .RB [ \-\-build=\fIarchitecture\fP ] .RB [ \-\-host=\fIarchitecture\fP ] .RB [ \-\-profiles=\fIprofile[,...]\fP ] @@ -73,6 +73,7 @@ .RB [ \-\-piuparts\-root\-args=\fIoptions\fP ] .RB [ \-\-pre\-build\-commands=\fIstring\fP ] .RB [ \-\-chroot\-setup\-commands=\fIstring\fP ] +.RB [ \-\-chroot\-update\-failed\-commands=\fIstring\fP ] .RB [ \-\-build\-deps\-failed\-commands=\fIstring\fP ] .RB [ \-\-starting\-build\-commands=\fIstring\fP ] .RB [ \-\-finished\-build\-commands=\fIstring\fP ] @@ -89,6 +90,9 @@ .RB [ \-\-extra\-repository=\fIspec\fP ] .RB [ \-\-extra\-repository\-key=\fIfile.asc\fP ] .RB [ \-\-build\-path=\fIstring\fP ] +.RB [ \-\-adt-virt-server=\fIschroot|lxc|chroot|qemu|ssh\fP ] +.RB [ \-\-adt\-virt\-server\-opt=\fIstring\fP ] +.RB [ \-\-adt\-virt\-server\-opts=\fIoptions\fP ] .RB [ PACKAGE [ .dsc ]] .SH DESCRIPTION \fBsbuild\fR rebuilds Debian binary packages from the corresponding Debian @@ -98,18 +102,18 @@ \fBsbuild\fR can fetch the Debian source over a network, or it can use locally available sources. .PP -sbuild is given a packages to process as the argument -\fBPACKAGE[.dsc]\fR. This argument is in the form of either a -debianized package source directory, a source package name along with a -version in the form \fIpackage_version\fP, or a .dsc file. If no arguments are -given, the current working directory is passed as an argument. -.PP -For arguments given as source directories, dpkg-source is first run to produce a -source .dsc file. Then, the package is built using the .dsc produced. For -arguments in the form \fIpackage_version\fP, apt is used to download the source -package. For arguments given as a .dsc file, sbuild builds the source packages -directly. For .dsc files in remote locations, the source packages are downloaded -first, then built. +sbuild is given a packages to process as the argument \fBPACKAGE[.dsc]\fR. +This argument is in the form of either a debianized package source directory, a +source package name along with a version in the form \fIpackage_version\fP, a +source package name, or a .dsc file. If no arguments are given, the current +working directory is passed as an argument. +.PP +For arguments given as source directories, dpkg-source is first run to produce +a source .dsc file. Then, the package is built using the .dsc produced. For +arguments in the form \fIpackage_version\fP or \fIpackage\fP, apt is used to +download the source package. For arguments given as a .dsc file, sbuild builds +the source packages directly. For .dsc files in remote locations, the source +packages are downloaded first, then built. .PP It is also possible to run external commands with sbuild. See the section \fBEXTERNAL COMMANDS\fR for more on this. @@ -136,6 +140,8 @@ must be run in a directory containing a \fIchroot\-$distribution\fP symlink to the chroot (not recommended, but done for backward compatibility). .SH OPTIONS +Options set on the command line overwrite settings made in the configuration +file. .TP .BR \-h ", " \-\-help Display this manual. @@ -161,6 +167,9 @@ and Build-Conflicts-Indep dependencies, respectively. The options may be used any number of times to add multiple dependencies. The format is identical to the format used in debian/control. +These command line options append to the \fBMANUAL_DEPENDS\fP, \fBMANUAL_CONFLICTS\fP, \fBMANUAL_DEPENDS_ARCH\fP, \fBMANUAL_CONFLICTS_ARCH\fP, \fBMANUAL_DEPENDS_INDEP\fP and \fBMANUAL_CONFLICTS_INDEP\fP configuration variables, respectively. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-arch=\fIarchitecture\fP" Build using the architecture specified. A chroot named @@ -169,6 +178,9 @@ appropriately to build as that architecture, e.g. using \fIpersonality=linux32\fP to build i386 packages on an amd64 system. Note that this option is equivalent to "\-\-host=architecture \-\-build=architecture". +This command line option sets the \fBHOST_ARCH\fP and \fBBUILD_ARCH\fP configuration variables. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-host=\fIarchitecture\fP" Build using the host architecture specified. If $host and $build don't match, a @@ -176,41 +188,82 @@ is searched for, falling back to \fI$distribution\-$build\-sbuild\fP or \fI$distribution\-$build\fP, in that order of preference. This option is only useful for cross-building when used together with \-\-build. +This command line option sets the \fBHOST_ARCH\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-build=\fIarchitecture\fP" Build using the build architecture specified. This option is only useful for cross-building when used together with \-\-host. If \-\-build is not specified, the default system architecture is assumed. +This command line option sets the \fBBUILD_ARCH\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-A ", " "\-\-arch\-all" -Also build Architecture: all packages, i.e. use dpkg\-buildpackage \-b -instead of \-B. +Also build Architecture: all packages. This option is the opposite of +\-\-no\-arch\-all. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_ARCH_ALL\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-no\-arch\-all" -Do not build Architecture: all packages, i.e. use dpkg\-buildpackage \-B -instead of \-b. This option is the opposite of \-\-arch\-all. +Do not build Architecture: all packages. This is the default behaviour. This +option is the opposite of \-\-arch\-all. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_ARCH_ALL\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-arch\-any" -Build Architecture: any packages. This is the default behavior. +Build Architecture: any packages. This is the default behavior. This option is +the opposite of \-\-no\-arch\-any. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_ARCH_ANY\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-no\-arch\-any" Do not build Architecture: any packages. This option is the opposite of \-\-arch\-any and only useful when used together with \-\-arch\-all or \-\-source. -.TP -.BR "\-\-arch\-all\-only" -Only build Architecture:all packages, i.e. use dpkg-buildpackage \-A -instead of \-B. The \-\-arch=\fIarchitecture\fP option can still be used to -specify the architecture used to build the package. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_ARCH_ANY\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-b ", " "\-\-batch" Operate in batchmode, i.e. write a build-progress file during execution and files on shutdown to facilitate a clean restart. +This command line option sets the \fBBATCH_MODE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-c ", " "\-\-chroot=\fIchroot\fP" Use the specified chroot. If not specified, the default is the first of \fI$distribution\-$arch\-sbuild\fP, \fI$distribution\-sbuild\fP, \fI$distribution\-$arch\fP or \fI$distribution\fP that exists. +This command line option sets the \fBCHROOT\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR "\-\-chroot-mode=\fIschroot|sudo|adt\fP" +Select the desired chroot mode. Four values are possible: schroot (the +default), sudo (which uses sudo to execute chroot in a directory from +/etc/sbuild/chroot or ./chroot) and adt which uses the adt-virt-* binaries +(selectable via the \-\-adt-virt-server option). +This command line option sets the \fBCHROOT_MODE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-d ", " "\-\-dist=\fIdistribution\fP" Explicitly set the distribution for the package build. This will be selecting @@ -218,9 +271,15 @@ the created .changes file. Setting this option is necessary when giving sbuild a .dsc file or a plain source package name to build. In the latter case it specifies the distribution the source package is fetched from. +This command line option sets the \fBDISTRIBUTION\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-archive=\fIarchive\fP Communicate with specified archive. +This command line option sets the \fBARCHIVE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-D ", " "\-\-debug" Enable debug output. @@ -230,110 +289,216 @@ .BR "\-\-no\-apt\-clean" Run (or do not run) apt-get clean in the chroot before executing the build, overriding the default setting. +This command line option sets the \fBAPT_CLEAN\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-apt\-update" .TQ .BR "\-\-no\-apt\-update" Run (or do not run) apt-get update in the chroot before executing the build, overriding the default setting. +This command line option sets the \fBAPT_UPDATE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-apt\-upgrade" .TQ .BR "\-\-no\-apt\-upgrade" Run (or do not run) apt-get upgrade in the chroot before executing the build, overriding the default setting. +This command line option sets the \fBAPT_UPGRADE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-apt\-distupgrade" .TQ .BR "\-\-no\-apt\-distupgrade" Run (or do not run) apt-get distupgrade in the chroot before executing the build, overriding the default setting. +This command line option sets the \fBAPT_DISTUPGRADE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-m ", " "\-\-maintainer=\fImaintainer\fP" Specify the identity to use for GPG signing packages, and also used as the maintainer for binary NMUs. This does not normally require setting (it defaults to the uploader). +This command line option sets the \fBMAINTAINER_NAME\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-e ", " "\-\-uploader=\fIuploader\fP" Passed to dpkg\-genchanges and is used to set the Changed\-by: field in the .changes file(s). +This command line option sets the \fBUPLOADER_NAME\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-k ", " "\-\-keyid=\fIkey-id\fP" Passed to dpkg\-genchanges and is used to set the key to sign the .changes file(s). Default is not using any key. +This command line option sets the \fBKEY_ID\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-j ", " "\-\-jobs=\fIn\fP" Number of jobs to run simultaneously. Passed through to dpkg\-buildpackage. +This command line option appends the appropriate \fB-j\fP option to the \fBDPKG_BUILDPACKAGE_USER_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-debbuildopt=\fIoption\fP -Pass the specified option directly to dpkg\-buildpackage. +Pass the specified option directly to dpkg\-buildpackage in addition to the +options already passed by sbuild. This option can be passed multiple times +(once per dpkg-buildpackage option) and can be freely mixed with the +\-\-debbuildopts option. Options will be passed to dpkg-buildpackage in the +order that the \-\-debbuildopt and \-\-debbuildopts options are given on the +command line. +This command line option appends to the \fBDPKG_BUILDPACKAGE_USER_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-debbuildopts=\fIoptions\fP -Pass the specified options directly to dpkg\-buildpackage. The options should -be separated by spaces. If any options contain spaces, use \-\-debbuildopt -instead. -.TP -.BR \-\-dpkg\-source\-opt=\fIoptions\fP -Pass the specified options directly to dpkg-source. This is only used when -creating a source package from a Debianized source directory. +Pass the specified options directly to dpkg\-buildpackage in addition to the +options already passed by sbuild. The argument will be split by whitespaces and +the resulting array passed to the dpkg\-buildpackage invocation. If any options +contain spaces, use \-\-debbuildopt for them. This option can be passed +multiple times and can be freely mixed with the \-\-debbuildopt option. Options +will be passed to dpkg\-buildpackage in the order that the \-\-debbuildopt and +\-\-debbuildopts options are given on the command line. +This command line option appends to the \fBDPKG_BUILDPACKAGE_USER_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-dpkg\-source\-opt=\fIoptions\f +Pass the specified option directly to dpkg-source in addition to the options +already passed by sbuild. This is only used when creating a source package from +a Debianized source directory. This option can be passed multiple times (once +per dpkg-source option) and can be freely mixed with the \-\-dpkg\-source\-opts +option. Options will be passed to dpkg-source in the order that the +\-\-dpkg\-source\-opt and \-\-dpkg\-source\-opts options are given on the +command line. +This command line option appends to the \fBDPKG_SOURCE_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .br \fBNOTE:\fR The '\fI-b\fP' option will always be passed to dpkg-source. .TP .BR \-\-dpkg\-source\-opts=\fIoptions\fP -Extra options to be appended to existing options passed to dpkg-source. +Pass the specified options directly to dpkg\-source in addition to the options +already passed by sbuild. The argument will be split by whitespaces and the +resulting array passed to the dpkg\-source invocation. This is only used when +creating a source package from a Debianized source directory. If any options +contain spaces, use \-\-dpkg\-source\-opt for them. This option can be passed +multiple times and can be freely mixed with the \-\-dpkg\-source\-opt option. +Options will be passed to dpkg\-source in the order that the +\-\-dpkg\-source\-opt and \-\-dpkg\-source\-opts options are given on the +command line. +This command line option appends to the \fBDPKG_SOURCE_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-mail\-log\-to=\fIemail-address\fP" -Send the build log to the specified email address. This overrides the -\fI$mailto\fP configuration option. +Send the build log to the specified email address. +This command line option sets the \fBMAILTO\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-mailfrom=\fIemail-address\fP" -Email address used as the sender address for build logs. This overrides the -\fI$mailfrom\fP configuration option. +Email address used as the sender address for build logs. +This command line option sets the \fBMAILFROM\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-n ", " "\-\-nolog" Do not create a package log file in the \fI$log_dir\fP directory and no build log file, but print everything to stdout. Also do not send any log mails. -.TP -.BR \-p ", " "\-\-purge=\fIpurge-mode\fP" -Convenience option to set \fIpurge-mode\fR for build directory, build -dependencies and session. +This command line option sets the \fBNOLOG\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-profiles=\fIprofile[,...]\fP" Specify the profile(s) we build, as a comma-separated list. Defaults to the space separated list of profiles in the \fBDEB_BUILD_PROFILES\fP environment variable. +This command line option sets the \fBBUILD_PROFILES\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-p ", " "\-\-purge=\fIpurge-mode\fP" +Convenience option to set \fIpurge-mode\fR for build directory, build +dependencies and session. +This command line option sets the \fBPURGE_BUILD_DEPS\fP, \fBPURGE_BUILD_DIRECTORY\fP and \fBPURGE_SESSION\fP configuration variables. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-purge\-build=\fIpurge-mode\fP" \fIpurge-mode\fR determines if the build directory will be deleted after a build. Possible values are \fBalways\fR (default), \fBnever\fR, and \fBsuccessful\fR. +This command line option sets the \fBPURGE_BUILD_DIRECTORY\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-purge\-deps=\fIpurge-mode\fP" \fIpurge-mode\fR determines if the build dependencies will be removed after a build. Possible values are \fBalways\fR (default), \fBnever\fR, and \fBsuccessful\fR. +This command line option sets the \fBPURGE_BUILD_DEPS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-purge\-session=\fIpurge-mode\fP" Purge the schroot session following a build. This is useful in conjunction with the \fI\-\-purge\-build\fP and \fI\-\-purge\-deps\fP options when using snapshot chroots, since by default the snapshot will be deleted. Possible values are \fBalways\fR (default), \fBnever\fR, and \fBsuccessful\fR. +This command line option sets the \fBPURGE_SESSION\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-s ", " "\-\-source" -Also build source package, i.e. use dpkg\-buildpackage without \-B. +Build the source package in addition to the other requested build artifacts. By +default, the dsc will not be rewritten because the source package is the input +to sbuild, not its output. Even when running from an unpacked source tree +sbuild will first build the source package using dpkg-source and then pass that +on to the sbuild machinery. Use this option only when you know what you are +doing. This will rewrite the original dsc passed to sbuild. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_SOURCE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-no-source" -Don't build source package, i.e. use dpkg\-buildpackage with \-B. This option -is the opposite of \-\-source. +Don't rebuild the source package. This is the default. It is the opposite of +\-\-source. +See the section +.BR "BUILD ARTIFACTS" +for more information. +This command line option sets the \fBBUILD_SOURCE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-force\-orig\-source" When used with in conjunction with \-s, this option forces the inclusion of the orig.tar.gz file in the generated .changes file, even in cases where it would not normally be included, i.e. use dpkg\-buildpackage \-sa. +This command line option sets the \fBFORCE_ORIG_SOURCE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-use\-snapshot" Installs the latest snapshot gcc compiler from the \fIgcc-snapshot\fP package, and alters the build environment to use the snapshot compiler for the build. +Specifically, this option appends \fI/usr/lib/gcc-snapshot/lib\fP to the value +of the \fBLD_LIBRARY_PATH\fP configuration variable and +\fI/usr/lib/gcc-snapshot/bin\fP to the value of the \fBPATH\fP configuration +variable. It also sets the \fBGCC_SNAPSHOT\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-v ", " "\-\-verbose" Be verbose, i.e. all information goes to stdout as well as to the log files. @@ -351,60 +516,128 @@ \fIPACKAGE_VERSION[.dsc]\fR arguments still have to be the unmodified (non-NMU ones) so that the sources can be found. The version number in log files and mails will be modified by \fBsbuild\fR automatically. +This command line option sets the \fBBIN_NMU\fP configuration variable and sets the \fBBIN_NMU_VERSION\fP configuration variable to 1 if it was not set yet, for example by the --binNMU option. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-binNMU=\fINMU-version\fP" The version number of the binary NMU. This should be used in conjunction with \-\-make\-binNMU. \fIversion\fP is a single number for the (+b\fIn\fR) format used for binary NMUs. +This command line option sets the \fBBIN_NMU_VERSION\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-append\-to\-version=\fIstring\fP" This option is similar to \-\-make\-binNMU except that it allows the user to specify an arbitrary string to be appended to the version number (immediately before the '+' in the Debian revision if \-\-make\-binNMU is also provided). +This command line option sets the \fBAPPEND_TO_VERSION\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-clean\-source When executing sbuild from within an unpacked source tree, execute the debian/rules clean target. This is the default and might require some of the build dependencies installed on the host. +This command line option sets the \fBCLEAN_SOURCE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-no\-clean\-source When executing sbuild from within an unpacked source tree, do not run the debian/rules clean target before building the source package. Only set this if you start from a clean checkout and you know what you are doing. +This command line option sets the \fBCLEAN_SOURCE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-run\-lintian Run lintian after a successful build. +This command line option sets the \fBRUN_LINTIAN\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-no\-run\-lintian Don't run lintian after a successful build. If sbuild is configured to run lintian by default, this option will prevent lintian being run. +This command line option sets the \fBRUN_LINTIAN\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-lintian\-opt=\fIoptions\fP -Run lintian with the specified options. +Pass the specified option directly to lintian in addition to the options +already passed by sbuild. This option can be passed multiple times (once per +lintian option) and can be freely mixed with the \-\-lintian\-opts option. +Options will be passed to lintian in the order that the \-\-lintian\-opt and +\-\-lintian\-opts options are given on the command line. +This command line option appends to the \fBLINTIAN_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-lintian\-opts=\fIoptions\fP -Append extra options to existing options passed to lintian. +Pass the specified options directly to lintian in addition to the options +already passed by sbuild. The argument will be split by whitespaces and the +resulting array passed to the lintian invocation. If any options contain +spaces, use \-\-lintian\-opt for them. This option can be passed multiple +times and can be freely mixed with the \-\-lintian\-opts option. Options will +be passed to lintian in the order that the \-\-lintian\-opt and +\-\-lintian\-opts options are given on the command line. +This command line option appends to the \fBLINTIAN_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-run\-piuparts Run piuparts after a successful build. +This command line option sets the \fBRUN_PIUPARTS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-no\-run\-piuparts Don't run piuparts after a successful build. If sbuild is configured to run piuparts by default, this option will prevent piuparts being run. +This command line option sets the \fBRUN_PIUPARTS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-piuparts\-opt=\fIoptions\fP -Run piuparts with the specified options. +Pass the specified option directly to piuparts in addition to the options +already passed by sbuild. This option can be passed multiple times (once per +piuparts option) and can be freely mixed with the \-\-piuparts\-opts option. +Options will be passed to piuparts in the order that the \-\-piuparts\-opt and +\-\-piuparts\-opts options are given on the command line. +This command line option appends to the \fBPIUPARTS_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-piuparts\-opts=\fIoptions\fP -Append extra options to existing options passed to piuparts. +Pass the specified options directly to piuparts in addition to the options +already passed by sbuild. The argument will be split by whitespaces and the +resulting array passed to the piuparts invocation. If any options contain +spaces, use \-\-piuparts\-opt for them. This option can be passed multiple +times and can be freely mixed with the \-\-piuparts\-opts option. Options will +be passed to piuparts in the order that the \-\-piuparts\-opt and +\-\-piuparts\-opts options are given on the command line. +This command line option appends to the \fBPIUPARTS_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-piuparts\-root\-arg=\fIoptions\fP Add an argument that is used to launch piuparts as root. If no arguments are -specified, piuparts will be launched via sudo. +specified, piuparts will be launched via sudo. This option can be specified +multiple times. +This command line option appends to the \fBPIUPARTS_ROOT_ARGS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-piuparts\-root\-args=\fIoptions\fP Add arguments that are used to launch piuparts as root. If no arguments are -specified, piuparts will be launched via sudo. +specified, piuparts will be launched via sudo. The argument will be split by +whitespaces. To pass options containing whitespaces use +the option \-\-piuparts\-root\-arg. +This command line option appends to the \fBPIUPARTS_ROOT_ARGS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-pre\-build\-commands=\fIstring\fP This is the earliest external command which is run right after the chroot @@ -413,6 +646,9 @@ option can be used multiple times to add multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-chroot\-setup\-commands=\fIstring\fP Run these commands after the chroot and variables have been setup but before @@ -421,6 +657,20 @@ section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-chroot\-update\-failed\-commands=\fIstring\fP +Run these commands after any of 'apt-get update', 'apt-get upgrade' or 'apt-get +dist-upgrade' failed. The environment is intact, and the failure can be +investigated. Especially %SBUILD_SHELL is useful here. This option can be used +multiple times to add multiple commands. See the section +.BR "EXTERNAL COMMANDS" +for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-build\-deps\-failed\-commands=\fIstring\fP These commands are run if installing the build dependencies has failed directly @@ -430,6 +680,9 @@ commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-starting\-build\-commands=\fIstring\fP Run these commands after dependencies are installed, just before the package @@ -438,6 +691,9 @@ multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-finished\-build\-commands=\fIstring\fP Run these commands immediately after the timed package build finishes. The @@ -445,6 +701,9 @@ option can be used multiple times to add multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-build\-failed\-commands=\fIstring\fP These commands are run if dpkg-buildpackage has failed directly after the @@ -454,6 +713,9 @@ to add multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-chroot\-cleanup\-commands=\fIstring\fP Run these commands when a chroot is cleaned up, before build directory is @@ -461,6 +723,9 @@ multiple times to add multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-post\-build\-commands=\fIstring\fP Run this command after a successful build. The command is run as root outside @@ -468,6 +733,9 @@ See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-anything\-failed\-commands=\fIstring\fP Run these commands for all the \fI\-\-xxx\-failed\-commands\fP options. @@ -475,48 +743,90 @@ to add multiple commands. See the section .BR "EXTERNAL COMMANDS" for more information. +This command line option appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-log\-external\-command\-output Write output from external commands to the build log. +This command line option sets the \fBLOG_EXTERNAL_COMMAND_OUTPUT\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-log\-external\-command\-error Write error output from external commands to the build log. +This command line option sets the \fBLOG_EXTERNAL_COMMAND_ERROR\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-setup\-hook=\fIhook-script\fP" " " \fBDEPRECATED\fP This option is deprecated. Use of this option will add \fIhook-script\fP to the external commands to run via \fIchroot-setup-commands\fP. +This command line option sets the \fBCHROOT_SETUP_SCRIPT\fP configuration variable and appends to the \fBEXTERNAL_COMMENDS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR "\-\-build\-dep\-resolver=\fIresolver\fP" Use the specified resolver to handle selecting the build dependencies. -Supported resolvers are \fIapt\fP (the default), \fIaptitude\fP, \fIaspcud\fP and \fIxapt\fP. -The apt resolver is the most appropriate resolver for most users, for building -for unstable, stable and other distributions. If alternative build -dependencies are used (excluding architecture restrictions), only the first -alternative will be used; the others will be ignored. The aptitude resolver is -very similar, but smarter and slower, and it will consider all alternatives by -default; it is suited to more complex situations, such as building packages for -the experimental distribution, where packages need installing from multiple -suites (\fIunstable\fP and \fIexperimental\fP). Due to performance and other -issues (bug #139615), aptitude is not recommended for use by default. -If the dependency situation is so complex that neither apt nor aptitude are -able to find a solution, then you can use the aspcud resolver. This resolver -uses apt-cudf to ask aspcud, a real SAT solver, for a solution to the -installation problem. Since aspcud is a real SAT solver it will always find -a solution if one exists. +Supported resolvers are \fIapt\fP (the default), \fIaptitude\fP, \fIaspcud\fP +and \fIxapt\fP. The apt resolver is the most appropriate resolver for most +users, for building for unstable, stable and other distributions. If +alternative build dependencies are used (excluding architecture restrictions), +only the first alternative will be used; the others will be ignored. The +aptitude resolver is very similar, but smarter and slower, and it will consider +all alternatives by default; it is suited to more complex situations, such as +building packages for the experimental distribution, where packages need +installing from multiple suites (\fIunstable\fP and \fIexperimental\fP). Due +to performance and other issues (bug #139615), aptitude is not recommended for +use by default. If the dependency situation is so complex that neither apt nor +aptitude are able to find a solution, then you can use the aspcud resolver. +This resolver uses apt-cudf to ask aspcud, a real solver (in the math sense), +to find a solution to the installation problem. Since aspcud uses a real solver +(an ASP solver) it will always find a solution if one exists. The solution +found by the aspcud resolver can be refined by changing the default +optimization criteria through the --aspcud-criteria option. The xapt resolver is intended only for cross-building, and is a temporary transitional feature which will be removed following the complete introduction of multi-arch support. +This command line option sets the \fBBUILD_DEP_RESOLVER\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-aspcud\-criteria=\fIcriteria\fP +Optimization criteria in extended MISC 2012 syntax passed to aspcud through +apt-cudf. Optimization criteria are separated by commas, sorted by decreasing +order of priority and are prefixed with a polarity (+ to maximize and - to +minimize). The default criteria is \fB-removed,-changed,-new\fP which first +minimizes the number of removed packages, then the number of changed packages +(up or downgrades) and then the number of new packages. A common task is to +minimize the number of packages from experimental. To do this you can add a +criteria like \fB-count(solution,APT-Release:=/a=experimental/)\fP to the +default criteria. This will then minimize the number of packages in the +solution which contain the string \fIa=experimental\fP in the \fIAPT-Release\fP +field of the EDSP output created by apt. For more help on how to write +optimization criteria, see the +.BR apt-cudf (1) +man page. Specifically the help on the --criteria option. +This command line option sets the \fBASPCUD_CRITERIA\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-resolve\-alternatives Allow the use of alternatives in Build-Depends, Build-Depends-Arch and Build-Depends-Indep. This is the default for the aptitude dependency resolver. +This command line option sets the \fBRESOLVE_ALTERNATIVES\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-no\-resolve\-alternatives Do not allow the use of alternatives in Build-Depends, Build-Depends-Arch and Build-Depends-Indep. Note that alternatives for the same package (e.g. different versions) are still allowed. This is the default for the apt and xapt dependency resolvers. +This command line option sets the \fBRESOLVE_ALTERNATIVES\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-extra\-package=\fIpackage.deb\fP Make \fIpackage.deb\fP available for build-dependency resolution, by @@ -526,6 +836,9 @@ through the hassle of maintaining a local archive and making it accessible inside the chroot. \fIpackage.deb\fP is copied into the chroot, so it can refer to any path on the host system. +This command line option appends to the \fBEXTRA_PACKAGES\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-extra\-repository=\fIspec\fP Add a repository to the list of apt sources during the package build. @@ -541,8 +854,11 @@ .nh .B \-\-extra\-repository-key .hy -flag. (see -.BR apt-secure (8)) +flag (see +.BR apt-secure (8)). +This command line option appends to the \fBEXTRA_REPOSITORIES\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-extra\-repository-key=\fIfile.asc\fP Add \fIfile.asc\fP to the list of trusted keys inside the chroot. The key is @@ -555,13 +871,117 @@ .hy is not signed with a key that's trusted by the base chroot. +This command line option appends to the \fBEXTRA_REPOSITORY_KEYS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-build\-path=\fIstring\fP By default the package is built in a path of the following format /build/packagename-XXXXXX/packagename-version/ where XXXXXX is a random ascii string. This option allows one to specify a custom path where the package is built inside the chroot. Notice that the sbuild user in the chroot must have permissions to create the path. Common writable locations are subdirectories of /tmp or /build. The buildpath must be an empty directory because the last component of the path will be removed after the build is finished. If you are running multiple sbuild instances with the same build path in parallel for the same package, make sure that your build path is not in a directory commonly mounted by all sbuild instances (like /tmp or /home). In that case, use for example /build instead. Otherwise, your builds will probably fail or contain wrong content. +This command line option sets the \fBBUILD_PATH\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-adt-virt-server=\fIschroot|lxc|chroot|qemu|ssh\fP +The adt virtualization server. Can be specified with or without the adt-virt- +prefix. For instance, the following set of command line options will use the +adt-virt-schroot backend for a package build: +.nh +.B \-\-chroot-mode=adt \-\-adt\-virt\-server=schroot \-\-chroot unstable-amd64-sbuild +.ny +The value of the \f[CB]--chroot\fP option will be passed as the last positional +argument to the adt-virt-* invocation. Thus, the value of the \f[CB]--chroot\fP +option becomes the image name of the virtual machine in case of adt-virt-qemu, +the lxc-container name in case of adt-virt-lxc, the path to the chroot in case +of adt-virt-chroot, the name of the schroot in case of adt-virt-schroot and so +on. +This command line option sets the \fBADT_VIRT_SERVER\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-adt-virt-server-opt=\fIstring\fP +Pass the specified option directly to the respective adt-virt-* virtualization +server in addition to the options already passed by sbuild. This option can be +passed multiple times (once per adt-virt-* option) and can be freely mixed with +the \-\-adt-virt-server\-opts option. Options will be passed to the respective +adt-virt-* virtualization server in the order that the \-\-adt-virt-server\-opt +and \-\-adt-virt-server\-opts options are given on the command line. See the +manual pages of the respective adt-virt-* commands for more information. +This command line option appends to the \fBADT_VIRT_SERVER_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\-adt\-virt\-server\-opts=\fIoptions\fP +Pass the specified options directly to the respective adt-virt-* virtualization +server in addition to the options already passed by sbuild. The argument will +be split by whitespaces and the resulting array passed to the adt-virt-* +invocation. If any options contain spaces, use \-\-adt\-virt\-server\-opt for +them. This option can be passed multiple times and can be freely mixed with +the \-\-adt\-virt\-server\-opts option. Options will be passed to the +respective adt-virt-* virtualization server in the order that the +\-\-adt\-virt\-server\-opt and \-\-adt\-virt\-server\-opts options are given on +the command line. See the manual pages of the respective adt\-virt\-* commands +for more information. +This command line option appends to the \fBADT_VIRT_SERVER_OPTIONS\fP configuration variable. See +.BR sbuild.conf (5) +for more information. .TP .BR \-\-sbuild-mode=\fImode\fP -Behaviour changes for use in a buildd environment. This overrides the -\fI$sbuild_mode\fP configuration option. +Behaviour changes for use in a buildd environment. +This command line option sets the \fBSBUILD_MODE\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.TP +.BR \-\tstats\-dir=\fIdirectory\fP +Directory for writing build statistics to. +This command line option sets the \fBSTATS_DIR\fP configuration variable. See +.BR sbuild.conf (5) +for more information. +.SH BUILD ARTIFACTS +Sbuild is meant to be used to build architecture specific binary packages from +a given source package. In addition, sbuild is also able to generate +architecture independent binary packages as well as to rebuild the original +source package that was used as input. In summary, sbuild is able to build +architecture specific binary packages, architecture independent binary packages +and source packages. What ends up being built is determined by the +configuration variables \fBBUILD_ARCH_ANY\fR, \fBBUILD_ARCH_ALL\fR and +\fBBUILD_SOURCE\fR, respectively. See +.BR sbuild.conf (5) +for a detailed explanation of these configuration variables. +.PP +By default, only \fBBUILD_ARCH_ANY\fR is set to true while \fBBUILD_ARCH_ALL\fR +and \fBBUILD_SOURCE\fR are set to false. So by default only architecture +specific binary packages will be built. This behaviour can be changed either by +using command line options or by modifying the configuration variables in your +\fI~/.sbuildrc\fP. The relevant command line options to change the values of +\fBBUILD_ARCH_ANY\fR, \fBBUILD_ARCH_ALL\fR and \fBBUILD_SOURCE\fR are +\f[CB]--arch-any/--no-arch-any\fP, \f[CB]--arch-all/--no-arch-all\fP and +\f[CB]--source/--no-source\fP, respectively. +.PP +The values of \fBBUILD_ARCH_ANY\fR, \fBBUILD_ARCH_ALL\fR and \fBBUILD_SOURCE\fR +change the parameter that dpkg-buildpackage is called with. The following table +displays the argument passed to dpkg-buildpackage in the last column depending +on the configuration options in the first three columns. +.PP +.if t \{\ +.ft CW +\} +.TS +l l l l. +\fBBUILD_ARCH_ANY\fR \fBBUILD_ARCH_ALL\fR \fBBUILD_SOURCE\fR dpkg-buildpackage flag +_ +false false false invalid +false false true -S +false true false -A +false true true -g +true false false -B +true false true -G +true true false -b +true true true no option +.TE +.if t \{\ +.in +.ft P +\} .SH EXTERNAL COMMANDS Support to run external commands during an sbuild run is provided. A set of external commands can be run at various stages of a build. Providing commands to @@ -574,9 +994,10 @@ run external to the chroot. The \fIchroot\-setup/cleanup\-\fP commands and \fIStarting/Finished\-Build\-\fP commands are run inside the chroot. They are all run as root except the \fIStarting/Finishing\-build-\fP commands, which are -run as the current sbuild user. \fIbuild\-deps\-failed\fP runs similarly to -\fIchroot\-setup\fP: in the chroot as root. \fIbuild\-failed\fP runs similarly -to \fIfinished\-build\fP: in the chroot as the user. +run as the current sbuild user. \fIchroot\-update\-failed\fP and +\fIbuild\-deps\-failed\fP runs similarly to \fIchroot\-setup\fP: in the chroot +as root. \fIbuild\-failed\fP runs similarly to \fIfinished\-build\fP: in the +chroot as the user. .PP Here is a summary of the ordering, user, internal/external to chroot for each command hook @@ -586,32 +1007,40 @@ or not (no). The column \fIchroot\fP shows whether the command is run inside our outside the chroot. The remaining columns show the percent escapes that are defined in each command. Percent escapes that are available in all commands -(\fB%%\fR, \fB%d\fR, \fB%a\fR, \fB%b\fR, \fB%p\fR, \fB%s\fR) are omitted. +(\fB%%\fR, \fB%a\fR, \fB%b\fR, \fB%s\fR) are omitted. The value \fImaybe\fP in +the column for the \fB%d\fR and \fB%p\fR escapes means that the value can not +relied upon to be defined in these stages. More specifically, these escapes +will not be defined at these points if the user specified a source package name +without a version on the command line. In that case, the version will only +become known after the source package has been retrieved in the "Fetch and +unpack source package" stage. .PP .if t \{\ .ft CW \} .TS -l l l l l. -command/action root chroot %c %r +l l l l l l. +command/action root chroot %c %e %d,%p _ Initialise chroot session -\f[CB]\-\-pre\-build\-commands\fP yes outside no yes +\f[CB]\-\-pre\-build\-commands\fP yes outside no yes maybe Setup the chroot and variables -\f[CB]\-\-chroot\-setup\-commands\fP yes inside no no +\f[CB]\-\-chroot\-setup\-commands\fP yes inside no no maybe Update and upgrade packages +\f[CB]\-\-chroot\-update\-failed\-commands\fP yes inside no no maybe +Fetch and unpack source package Install Dependencies -\f[CB]\-\-build\-deps\-failed\-commands\fP yes inside no no -\f[CB]\-\-starting\-build\-commands\fP no inside no no +\f[CB]\-\-build\-deps\-failed\-commands\fP yes inside no no yes +\f[CB]\-\-starting\-build\-commands\fP no inside no no yes Run dpkg-buildpackage -\f[CB]\-\-build\-failed\-commands\fP no inside no no -\f[CB]\-\-finished\-build\-commands\fP no inside no no +\f[CB]\-\-build\-failed\-commands\fP no inside no no yes +\f[CB]\-\-finished\-build\-commands\fP no inside no no yes Run lintian (if configured) Cleanup build files and dependencies -\f[CB]\-\-chroot\-cleanup\-commands\fP yes inside yes no +\f[CB]\-\-chroot\-cleanup\-commands\fP yes inside yes no yes Close schroot session Run piuparts (if configured) -\f[CB]\-\-post\-build\-commands\fP yes outside yes yes +\f[CB]\-\-post\-build\-commands\fP yes outside yes yes yes .TE .if t \{\ .in @@ -677,10 +1106,15 @@ These escapes are converted to the debian name of the architecture the build is being built for (e.g amd64, armhf). .TP -\fB%r\fR, \fB%SBUILD_CHROOT_DIR\fR -These escapes are converted to the absolute path on the host to the root -directory of the chroot. This variable is not set if the external command is -run inside the chroot. Thus this escape is only available for +\fB%e\fR, \fB%SBUILD_CHROOT_EXEC\fR +These escapes are converted to a command which can be executed on a host and +can be given arguments which will then be executed inside the chroot. Standard +input and output of the process started inside the chroot are connected to the +program executed on the host. Thus, this command can also be used to copy data +into the chroot and out of the chroot. The working directory of the process +started inside the chroot is the root directory of the chroot. The process is +started as the root user. This variable is not set if the external command is +run inside the chroot. Thus this escape is only available for \f[CB]\-\-pre\-build\-commands\fP and \f[CB]\-\-post\-build\-commands\fP. .TP \fB%b\fR, \fB%SBUILD_BUILD_DIR\fR @@ -697,7 +1131,7 @@ Percent escapes are only substituted when an appropriate value is defined for them. At other times, it is left unchanged. In practice this means that there are only two escapes that are not available in all external commands: \fB%c\fR -and \fB%r\fR. For example, a .changes file is only defined at the end of a +and \fB%e\fR. For example, a .changes file is only defined at the end of a build, so using \fI%c\fR will only be substituted for post-build-commands. .PP Here's an example of using an escape to run a program foo on a .changes file @@ -710,7 +1144,13 @@ And here's an example that will spawn an interactive shell to investigate the problem whenever the build failed: .PP -\f[CB]$ sbuild \-\-build\-failed\-commands '%s'\fP +\f[CB]$ sbuild \-\-build\-failed\-commands '%SBUILD_SHELL'\fP +.PP +The following example would copy a file from the host into the chroot: +.PP +\f[CB]$ sbuild \-\-pre\-build\-commands \\\fP +.br +\f[CB] 'cat blub.txt | %SBUILD_CHROOT_EXEC sh -c "cat > blub.txt"'\fP .PP One final note, external commands are processed in the order they are given. Also, the commands given in a configuration file are processed first, then the @@ -769,7 +1209,9 @@ chroot access; schroot access uses the schroot chroot configuration. .TP .I ~/.sbuildrc -User-specific configuration. +User-specific configuration. A custom path to a configuration file can also be +specified through setting the \fBSBUILD_CONFIG\fP environment variable to the +path of an additional configuration file. .TP .I /var/lib/sbuild Build trees, archive signing keys, build statistics and lock files. diff -Nru sbuild-0.67.0/NEWS sbuild-0.69.0/NEWS --- sbuild-0.67.0/NEWS 2015-12-26 13:32:23.533447317 +0000 +++ sbuild-0.69.0/NEWS 2016-05-08 11:21:18.533932310 +0000 @@ -1,12 +1,70 @@ NEWS -*- outline -*- ---- -Welcome to sbuild 0.67.0. Please read these release notes carefully. +Welcome to sbuild 0.69.0. Please read these release notes carefully. Full installation instructions are provided in the INSTALL file. The README file also contains more specific notes regarding building and configuration. + * Major changes in 0.69.0: + + 1) Decouple chroot from host in terms of filesystem access to allow + chroot backends like qemu, ssh or lxc. Deprecate external command + percentage escape %SBUILD_CHROOT_DIR in favour of %SBUILD_CHROOT_EXEC. + + 2) Experimental adt backend. Enable with --chroot-mode=adt. Choose the + virtualization server with --adt-virt-server and add options with + --adt-virt-server-opt. This allows sbuild to use qemu, ssh and lxc + chroots. + + 3) Allow to build packages without specifying a version. Earlier it was + possible to let sbuild "apt-get download" a dsc by specifying + "package_version" as a command line argument. The version part is not + necessary anymore. No manual version lookup by the user is required + anymore. + + 4) Disallow conflicting command line options, thus making command line + switches position independent and remove the deprecated --arch-all-only + option in the process. + + 5) The aspcud resolver criteria is not hardcoded anymore but can be chosen + with --aspcud-criteria. The default criteria is -removed,-changed,-new. + To minimize the number of packages from experimental, use: + -count(solution,APT-Release:=/a=experimental/),-removed,-changed,-new + + 6) Apt doesn't download translations anymore. + + 7) Dummy archive is now signed with SHA-512 + + 8) Cron script etc/sbuild-update-all allows one to periodically update all + sbuild chroots. + + 9) Add another --*-failed-commands external command: + --chroot-update-failed-commands + + 10) Documentation of configuration options in sbuild.conf(5) and in + /etc/sbuild/sbuild.conf now reference related command line options from + sbuild(1). + + 11) Documentation of command line options in sbuild(1) now references the + respective configuration options from sbuild.conf(5). + + 12) Remove configuration options which can be set on the command line from + the __INTERNAL group, thus exposing them in sbuild.conf as well and + referencing them in sbuild(1). + +* Major changes in 0.68.0: + + 1) Dummy binary packages are now used for native building *and* cross + building (apt-get build-dep was used for the latter so far). For an + extensive rationale for this choice, read the commit message of commit + e227c8f3. + + 2) Deprecate --arch-all-only option which was introduced two releases ago in + favour of --arch-all --no-arch-any. The option will be completely removed + in the next release to remove redundancy and for overall clarity. + * Major changes in 0.67.0: 1) add --clean-source and --no-clean-source to allow building a package from diff -Nru sbuild-0.67.0/tools/sbuild-dumpconfig sbuild-0.69.0/tools/sbuild-dumpconfig --- sbuild-0.67.0/tools/sbuild-dumpconfig 2015-12-25 16:23:28.614723316 +0000 +++ sbuild-0.69.0/tools/sbuild-dumpconfig 2016-05-08 10:31:22.366021898 +0000 @@ -104,13 +104,20 @@ my $help = $conf->_get_help($key); my $default = $conf->_get_default($key); my $ignore_default = $conf->_get_ignore_default($key); + my $cli_options = $conf->_get_cli_options($key); + my $example = $conf->_get_example($key); if ($output eq "config") { print "# $key\n"; print "# Type: $type\n"; if ($help) { print wrap("# ", "# ", "$help\n"); } - my $example = $conf->_get_example($key); + if ($cli_options) { + print "# See also related command line options in sbuild(1):\n"; + foreach my $opt (@{$cli_options}) { + print "# $opt\n"; + } + } if ($example) { foreach my $line (split("\n", $example)) { print "# $line\n"; @@ -132,7 +139,19 @@ print "$help\n"; # print wrap("", "", "$help\n"); } - my $example = $conf->_get_example($key); + if ($cli_options) { + print ".IP\n"; + print "Related\n"; + print ".BR sbuild (1)\n"; + print "command line options:\n"; + print ".PP\n"; + print ".RS\n"; + foreach my $opt (@{$cli_options}) { + print "\\f[CR]$opt\\fP\n"; + print ".br\n"; + } + print ".RE\n"; + } if ($example) { print "Example:\n"; print ".PP\n"; diff -Nru sbuild-0.67.0/VERSION sbuild-0.69.0/VERSION --- sbuild-0.67.0/VERSION 2015-12-26 13:35:46.757710641 +0000 +++ sbuild-0.69.0/VERSION 2016-05-08 12:14:33.262780522 +0000 @@ -1,5 +1,5 @@ Package: sbuild -Version: 0.67.0 -Release-Date: 26 Dec 2015 +Version: 0.69.0 +Release-Date: 08 May 2016 Released-By: Johannes 'josch' Schauer -Git-Tag: release/sbuild-0.67.0 +Git-Tag: release/sbuild-0.69.0