@@ -253,6 +253,10 @@ sub setup ($) {
DEFAULT => 'aptitude',
HELP => 'Path to aptitude binary'
},
+ 'XAPT' => {
+ CHECK => $validate_program,
+ DEFAULT => 'xapt'
+ },
'DPKG_BUILDPACKAGE_USER_OPTIONS' => {
TYPE => 'ARRAY:STRING',
GROUP => '__INTERNAL',
@@ -873,9 +877,9 @@ sub setup ($) {
die '$key: Invalid build-dependency resolver \'' .
$conf->get($key) .
- "'\nValid algorthms are 'internal', 'apt' and 'aptitude'\n"
+ "'\nValid algorithms are 'internal', 'xapt', 'apt' and 'aptitude'\n"
if !isin($conf->get($key),
- qw(internal apt aptitude));
+ qw(internal xapt apt aptitude));
},
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\' and \'aptitude\', which use a built-in resolver module and aptitude to resolve build dependencies, respectively. The internal resolver is not capable of resolving complex alternative and virtual package dependencies, but is otherwise equivalent to apt. 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.'
},
@@ -46,6 +46,8 @@ sub get_resolver ($$$) {
my $resolver;
if ($conf->get('BUILD_DEP_RESOLVER') eq "apt") {
$resolver = Sbuild::AptResolver->new($conf, $session, $host);
+ } elsif ($conf->get('BUILD_DEP_RESOLVER') eq "xapt") {
+ $resolver = Sbuild::XaptResolver->new($conf, $session, $host);
} elsif ($conf->get('BUILD_DEP_RESOLVER') eq "aptitude") {
$resolver = Sbuild::AptitudeResolver->new($conf, $session, $host);
} else {
@@ -433,6 +433,60 @@ sub run_apt {
return $mode eq "-s" || $status == 0;
}
+sub run_xapt {
+ my $self = shift;
+ my $mode = shift;
+ my $inst_ret = shift;
+ my $rem_ret = shift;
+ my $action = shift;
+ my @packages = @_;
+ my( $msgs, $status, $pkgs, $rpkgs );
+
+ $msgs = "";
+ # redirection of stdin from /dev/null so that conffile question
+ # are treated as if RETURN was pressed.
+ # dpkg since 1.4.1.18 issues an error on the conffile question if
+ # it reads EOF -- hardwire the new --force-confold option to avoid
+ # the questions.
+ my @xapt_command = ($self->get_conf('XAPT'),
+ '-a', $self->get_conf('HOST_ARCH'));
+ # FIXME?:push @xapt_command, "$mode", $action, @packages;
+ push @xapt_command, @packages;
+ my $pipe =
+ $self->pipe_xapt_command(
+ { COMMAND => \@xapt_command,
+ ENV => {'DEBIAN_FRONTEND' => 'noninteractive'},
+ USER => 'root',
+ PRIORITY => 0,
+ DIR => '/' });
+ if (!$pipe) {
+ $self->log("Can't open pipe to xapt: $!\n");
+ return 0;
+ }
+
+ while(<$pipe>) {
+ $msgs .= $_;
+ $self->log($_) if $mode ne "-s" || debug($_);
+ }
+ close($pipe);
+ $status = $?;
+
+ $pkgs = $rpkgs = "";
+ if ($msgs =~ /NEW packages will be installed:\n((^[ ].*\n)*)/mi) {
+ ($pkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m;
+ $pkgs =~ s/\*//g;
+ }
+ if ($msgs =~ /packages will be REMOVED:\n((^[ ].*\n)*)/mi) {
+ ($rpkgs = $1) =~ s/^[ ]*((.|\n)*)\s*$/$1/m;
+ $rpkgs =~ s/\*//g;
+ }
+ @$inst_ret = split( /\s+/, $pkgs );
+ @$rem_ret = split( /\s+/, $rpkgs );
+
+ $self->log("xapt failed.\n") if $status && $mode ne "-s";
+ return $mode eq "-s" || $status == 0;
+}
+
sub format_deps {
my $self = shift;
new file mode 100644
@@ -0,0 +1,102 @@
+# ResolverBase.pm: build library for sbuild
+# Copyright © 2005 Ryan Murray <rmurray@debian.org>
+# Copyright © 2005-2008 Roger Leigh <rleigh@debian.org>
+# Copyright © 2008 Simon McVittie <smcv@debian.org>
+#
+# 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
+# <http://www.gnu.org/licenses/>.
+#
+#######################################################################
+
+package Sbuild::XaptResolver;
+
+use strict;
+use warnings;
+
+use Sbuild qw(debug);
+use Sbuild::Base;
+use Sbuild::ResolverBase;
+
+BEGIN {
+ use Exporter ();
+ our (@ISA, @EXPORT);
+
+ @ISA = qw(Exporter Sbuild::ResolverBase);
+
+ @EXPORT = qw();
+}
+
+sub new {
+ my $class = shift;
+ my $conf = shift;
+ my $session = shift;
+ my $host = shift;
+
+ my $self = $class->SUPER::new($conf, $session, $host);
+ bless($self, $class);
+
+ return $self;
+}
+
+sub install_deps {
+ my $self = shift;
+ my $name = shift;
+ my @pkgs = @_;
+
+ my $status = 0;
+ my $session = $self->get('Session');
+ 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_subsection("Install $name cross-build dependencies (xapt-based resolver)");
+
+ # Install the dummy package
+ my (@instd, @rmvd);
+ $self->log("Installing cross-build dependencies\n");
+ if (!$self->run_apt("-yf", \@instd, \@rmvd, 'install', $dummy_pkg_name)) {
+ $self->log("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");
+ } else {
+ $self->set_installed(@instd);
+ $self->set_removed(@rmvd);
+ goto package_cleanup;
+ }
+ return 0;
+ }
+ $self->set_installed(@instd);
+ $self->set_removed(@rmvd);
+ $status = 1;
+
+ package_cleanup:
+ if ($status == 0) {
+ if (defined ($session->get('Session Purged')) &&
+ $session->get('Session Purged') == 1) {
+ $self->log("Not removing installed packages: cloned chroot in use\n");
+ } else {
+ $self->uninstall_deps();
+ }
+ }
+
+ $self->cleanup_apt_archive();
+
+ return $status;
+}
+
+1;