Your message dated Fri, 17 Oct 2014 17:04:47 +0000
with message-id <[email protected]>
and subject line Bug#700522: fixed in sbuild 0.65.0-1
has caused the Debian Bug report #700522,
regarding sbuild: Let users push additional packages to the build dependencies 
dummy archive
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
700522: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=700522
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
Package: sbuild
Version: 0.64.0-1
Severity: wishlist
Tags: patch

When building related set of packages most people resort to set up a local
archive to enable the newly built packages to depend on locally built
dependencies for which the needed version has not hit the main archive yet.

Since sbuild already sets up a dummy archive for build dependencies, it could
also allow users to specify a list of packages that should be pushed there.

To do so I've added an --add-extra-package option that accepts a debfile and
can be used multiple times. It already allowed me to locally build packages
which depend on stuff not yet in the archive without any additional setup.

The git repo (`add-extra-package` branch) with the patches is at
http://cgit.collabora.com/git/user/em/sbuild/log/?h=add-extra-package

I also took the chance to refactor a bit the dummy archive handling and split
it out of the ResolverBase class. Even if not strictly needed it allowed me to
have a clear idea of the involved pieces and I think that the result is a bit
easier to understand and more flexible.

Comments and suggestions welcome, I'm not very proficient in Perl. :)



-- System Information:
Debian Release: jessie/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable'), (500, 
'oldstable'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.10-rc5-amd64 (SMP w/4 CPU cores)
Locale: LANG=it_IT.utf8, LC_CTYPE=it_IT.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages sbuild depends on:
ii  adduser         3.113+nmu3
ii  apt-utils       0.9.8.2
ii  libsbuild-perl  0.64.0-1
ii  perl            5.14.2-21
ii  perl-modules    5.14.2-21

Versions of packages sbuild recommends:
ii  debootstrap  1.0.52
ii  fakeroot     1.19-2

Versions of packages sbuild suggests:
pn  deborphan  <none>
ii  wget       1.14-2

-- no debconf information
>From 3746120a509778eb263ff9565ddf1de54bcedc2a Mon Sep 17 00:00:00 2001
From: Emanuele Aina <[email protected]>
Date: Fri, 31 May 2013 20:05:09 +0200
Subject: [PATCH 1/3] Sbuild::ResolverBase: Move the build-deps package
 building in its own method

---
 lib/Sbuild/ResolverBase.pm | 168 ++++++++++++++++++++++++++-------------------
 1 file changed, 99 insertions(+), 69 deletions(-)

diff --git a/lib/Sbuild/ResolverBase.pm b/lib/Sbuild/ResolverBase.pm
index efa6d9d..8048f16 100644
--- a/lib/Sbuild/ResolverBase.pm
+++ b/lib/Sbuild/ResolverBase.pm
@@ -607,79 +607,17 @@ sub get_dpkg_status {
     return \%result;
 }
 
-# Create an apt archive. Add to it if one exists.
-sub setup_apt_archive {
+sub build_dummy_package {
     my $self = shift;
+
     my $dummy_pkg_name = shift;
+    my $dummy_pkg_dir = shift;
+    my $dummy_deb = shift;
+    my $dummy_dsc = shift;
     my @pkgs = @_;
 
     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')));
-    }
-    $session->run_command(
-	{ COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
-		      $session->strip_chroot_path($self->get('Dummy package path'))],
-	  USER => 'root',
-	  DIR => '/' });
-    if ($?) {
-	$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 ($?) {
-	$self->log_error("E: Failed to set 0770 permissions on dummy package dir\n");
-	return 0;
-    }
-    my $dummy_dir = $self->get('Dummy package path');
-    my $dummy_gpghome = $dummy_dir . '/gpg';
-    my $dummy_archive_dir = $dummy_dir . '/apt_archive';
-    my $dummy_release_file = $dummy_archive_dir . '/Release';
-    my $dummy_archive_seckey = $dummy_archive_dir . '/sbuild-key.sec';
-    my $dummy_archive_pubkey = $dummy_archive_dir . '/sbuild-key.pub';
-
-    $self->set('Dummy archive directory', $dummy_archive_dir);
-    $self->set('Dummy Release file', $dummy_release_file);
-    my $dummy_archive_list_file = $self->get('Dummy archive list file');
-
-    if (! -d $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)) {
-        $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 ($?) {
-	$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)) {
-        $self->log_warning('Could not create build-depends dummy archive dir ' . $dummy_archive_dir . ': ' . $!);
-        $self->cleanup_apt_archive();
-        return 0;
-    }
-
-    my $dummy_pkg_dir = $dummy_dir . '/' . $dummy_pkg_name;
-    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'))) {
 	$self->log_warning('Could not create build-depends dummy dir ' . $dummy_pkg_dir . '/DEBIAN: ' . $!);
         $self->cleanup_apt_archive();
@@ -795,8 +733,7 @@ EOF
 
     foreach my $path ($dummy_pkg_dir . '/DEBIAN/control',
 		      $dummy_pkg_dir . '/DEBIAN',
-		      $dummy_pkg_dir,
-		      $dummy_archive_dir) {
+		      $dummy_pkg_dir) {
 	$session->run_command(
 	    { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
 			  $session->strip_chroot_path($path)],
@@ -857,6 +794,99 @@ EOF
     print $dummy_dsc_fh "\n";
     close $dummy_dsc_fh;
 
+    return 1;
+}
+
+# Create an apt archive. Add to it if one exists.
+sub setup_apt_archive {
+    my $self = shift;
+    my $dummy_pkg_name = shift;
+    my @pkgs = @_;
+
+    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')));
+    }
+    $session->run_command(
+	{ COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
+		      $session->strip_chroot_path($self->get('Dummy package path'))],
+	  USER => 'root',
+	  DIR => '/' });
+    if ($?) {
+	$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 ($?) {
+	$self->log_error("E: Failed to set 0770 permissions on dummy package dir\n");
+	return 0;
+    }
+    my $dummy_dir = $self->get('Dummy package path');
+    my $dummy_gpghome = $dummy_dir . '/gpg';
+    my $dummy_archive_dir = $dummy_dir . '/apt_archive';
+    my $dummy_release_file = $dummy_archive_dir . '/Release';
+    my $dummy_archive_seckey = $dummy_archive_dir . '/sbuild-key.sec';
+    my $dummy_archive_pubkey = $dummy_archive_dir . '/sbuild-key.pub';
+
+    $self->set('Dummy archive directory', $dummy_archive_dir);
+    $self->set('Dummy Release file', $dummy_release_file);
+    my $dummy_archive_list_file = $self->get('Dummy archive list file');
+
+    if (! -d $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)) {
+        $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 ($?) {
+	$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)) {
+        $self->log_warning('Could not create build-depends dummy archive dir ' . $dummy_archive_dir . ': ' . $!);
+        $self->cleanup_apt_archive();
+        return 0;
+    }
+
+    $session->run_command(
+        { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
+                      $session->strip_chroot_path($dummy_archive_dir)],
+          USER => 'root',
+          DIR => '/' });
+    if ($?) {
+        $self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER')
+                       . ":sbuild ownership on $dummy_archive_dir\n");
+        return 0;
+    }
+
+    my $dummy_pkg_dir = $dummy_dir . '/' . $dummy_pkg_name;
+    my $dummy_deb = $dummy_archive_dir . '/' . $dummy_pkg_name . '.deb';
+    my $dummy_dsc = $dummy_archive_dir . '/' . $dummy_pkg_name . '.dsc';
+
+    if (!$self->build_dummy_package ($dummy_pkg_name, $dummy_pkg_dir, $dummy_deb, $dummy_dsc, @pkgs)) {
+        $self->log("Failed to create build-depends dummy package.\n");
+        $self->cleanup_apt_archive();
+        return 0;
+    }
+
     # Do code to run apt-ftparchive
     if (!$self->run_apt_ftparchive()) {
         $self->log("Failed to run apt-ftparchive.\n");
-- 
1.8.3.1


>From da51ee83b51d89c17c2b874fcc95767f368a03a4 Mon Sep 17 00:00:00 2001
From: Emanuele Aina <[email protected]>
Date: Fri, 31 May 2013 20:09:05 +0200
Subject: [PATCH 2/3] Sbuild::DummyArchive: Move dummy archive management in
 its own class

---
 lib/Sbuild/DummyArchive.pm | 554 +++++++++++++++++++++++++++++++++++++++++++++
 lib/Sbuild/Makefile.am     |   1 +
 lib/Sbuild/ResolverBase.pm | 334 ++++-----------------------
 3 files changed, 602 insertions(+), 287 deletions(-)
 create mode 100644 lib/Sbuild/DummyArchive.pm

diff --git a/lib/Sbuild/DummyArchive.pm b/lib/Sbuild/DummyArchive.pm
new file mode 100644
index 0000000..afe2bc7
--- /dev/null
+++ b/lib/Sbuild/DummyArchive.pm
@@ -0,0 +1,554 @@
+# DummyArchive.pm: build library for sbuild
+# Copyright © 2005      Ryan Murray <[email protected]>
+# Copyright © 2005-2010 Roger Leigh <[email protected]>
+# Copyright © 2008      Simon McVittie <[email protected]>
+# Copyright © 2013      Emanuele Aina <[email protected]>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
+#######################################################################
+
+package Sbuild::DummyArchive;
+
+use strict;
+use warnings;
+use POSIX;
+use Fcntl;
+use File::Temp qw(tempdir tempfile);
+use File::Copy;
+
+use Dpkg::Deps;
+use Sbuild::Base;
+use Sbuild qw(isin debug debug2);
+
+BEGIN {
+    use Exporter ();
+    our (@ISA, @EXPORT);
+
+    @ISA = qw(Exporter Sbuild::Base);
+
+    @EXPORT = qw();
+}
+
+sub new {
+    my $class = shift;
+    my $conf = shift;
+    my $session = shift;
+    my $host = shift;
+    my $archive_shortname = shift;
+    my $archive_name = shift;
+    my $secret_key_file = shift;
+    my $public_key_file = shift;
+
+    my $self = $class->SUPER::new($conf);
+    bless($self, $class);
+
+    $self->set('Session', $session);
+    $self->set('Host', $host);
+    $self->set('Split', $self->get_conf('CHROOT_SPLIT'));
+    # Typically set by Sbuild::Build, but not outside a build context.
+    $self->set('Host Arch', $self->get_conf('HOST_ARCH'));
+    $self->set('Build Arch', $self->get_conf('BUILD_ARCH'));
+
+    $self->set('Shortname', $archive_shortname);
+    $self->set('Name', $archive_name);
+    $self->set('Dummy archive secret key file', $secret_key_file);
+    $self->set('Dummy archive public key file', $public_key_file);
+    $self->set('Debs', []);
+    $self->set('Dscs', []);
+
+    my $dummy_archive_list_file = $session->get('Location') .
+        "/etc/apt/sources.list.d/sbuild-${archive_shortname}-archive.list";
+    $self->set('Dummy archive list file', $dummy_archive_list_file);
+
+    return $self;
+}
+
+sub force_update_archive_list {
+    my $self = shift;
+
+	# Example archive list names:
+	#_tmp_resolver-XXXXXX_apt%5farchive_._Packages
+	#_tmp_resolver-XXXXXX_apt%5farchive_._Release
+	#_tmp_resolver-XXXXXX_apt%5farchive_._Release.gpg
+	#_tmp_resolver-XXXXXX_apt%5farchive_._Sources
+
+	# Update lists directly; only updates local archive
+
+	# Filename quoting for safety taken from apt URItoFileName and
+	# QuoteString.
+	my $session = $self->get('Session');
+	my $dummy_dir = $self->get('Dummy archive path');
+	my $dummy_archive_dir = $session->strip_chroot_path($dummy_dir.'/apt_archive/./');
+	my @chars = split('', $dummy_archive_dir);
+
+	foreach(@chars) {
+	    if (index('\\|{}[]<>"^~_=!@#$%^&*', $_) != -1 || # "Bad" characters
+		!m/[[:print:]]/ || # Not printable
+		ord($_) == 0x25 || # Percent '%' char
+		ord($_) <= 0x20 || # Control chars
+		ord($_) >= 0x7f) { # Control chars
+		$_ = sprintf("%%%02x", ord($_));
+	    }
+	}
+
+	my $uri = join('', @chars);
+	$uri =~ s;/;_;g; # Escape slashes
+
+	foreach my $file ("Packages", "Release", "Release.gpg", "Sources") {
+	    $session->run_command(
+		{ COMMAND => ['cp', $dummy_archive_dir . '/' . $file,
+			      '/var/lib/apt/lists/' . $uri . $file],
+		  USER => 'root',
+		  PRIORITY => 0 });
+		if ($?) {
+			$self->log("Failed to copy file from dummy archive to apt lists.\n");
+			return 1;
+		}
+	}
+
+	$self->run_apt_command(
+	    { COMMAND => [$self->get_conf('APT_CACHE'), 'gencaches'],
+	      ENV => {'DEBIAN_FRONTEND' => 'noninteractive'},
+	      USER => 'root',
+	      DIR => '/' });
+	return $?;
+}
+
+sub add_deb {
+    my $self = shift;
+    my $deb = shift;
+
+    my @debs = @{$self->get('Debs')};
+    push (@debs, $deb);
+    $self->set('Debs', \@debs);
+}
+
+sub add_dsc {
+    my $self = shift;
+    my $dsc = shift;
+
+    my @dscs = @{$self->get('Dscs')};
+    push (@dscs, $dsc);
+    $self->set('Dscs', \@dscs);
+}
+
+sub run_apt {
+    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 @apt_command = ($self->get_conf('APT_GET'), '--purge',
+	'-o', 'DPkg::Options::=--force-confold',
+	'-o', 'DPkg::Options::=--refuse-remove-essential',
+	'-o', 'APT::Install-Recommends=false',
+	'-q');
+    push @apt_command, '--allow-unauthenticated' if
+	($self->get_conf('APT_ALLOW_UNAUTHENTICATED'));
+    push @apt_command, "$mode", $action, @packages;
+    my $pipe =
+	$self->pipe_apt_command(
+	    { COMMAND => \@apt_command,
+	      ENV => {'DEBIAN_FRONTEND' => 'noninteractive'},
+	      USER => 'root',
+	      PRIORITY => 0,
+	      DIR => '/' });
+    if (!$pipe) {
+	$self->log("Can't open pipe to apt-get: $!\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("apt-get failed.\n") if $status && $mode ne "-s";
+    return $mode eq "-s" || $status == 0;
+}
+
+# Create an apt archive. Add to it if one exists.
+sub setup {
+    my $self = shift;
+
+    my $shortname = $self->get('Shortname');
+    my $session = $self->get('Session');
+
+    if (! defined $self->get('Dummy archive path')) {
+        my $archive_shortname = $self->get('Shortname');
+        $self->set('Dummy archive path',
+		   tempdir('dummy-archive-' . $shortname. '-XXXXXX',
+			   DIR => $self->get('Chroot Build Dir')));
+    }
+    $session->run_command(
+	{ COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
+		      $session->strip_chroot_path($self->get('Dummy archive path'))],
+	  USER => 'root',
+	  DIR => '/' });
+    if ($?) {
+	$self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER') .
+			 ":sbuild ownership on dummy archive dir\n");
+	return 0;
+    }
+    $session->run_command(
+	{ COMMAND => ['chmod', '0770', $session->strip_chroot_path($self->get('Dummy archive path'))],
+	  USER => 'root',
+	  DIR => '/' });
+    if ($?) {
+	$self->log_error("E: Failed to set 0770 permissions on dummy archive dir\n");
+	return 0;
+    }
+    my $dummy_dir = $self->get('Dummy archive path');
+    my $dummy_gpghome = $dummy_dir . '/gpg';
+    my $dummy_archive_dir = $dummy_dir . '/apt_archive';
+    my $dummy_release_file = $dummy_archive_dir . '/Release';
+
+    $self->set('Dummy archive directory', $dummy_archive_dir);
+    $self->set('Dummy Release file', $dummy_release_file);
+    $self->set('Dummy GPG home', $dummy_gpghome);
+
+    if (!(-d $dummy_gpghome || mkdir $dummy_gpghome, 0700)) {
+        $self->log_warning('Could not create gpg home dir ' . $dummy_gpghome .
+                           ' for dummy archive ' . $shortname . ': ' . $!);
+        $self->cleanup();
+        return 0;
+    }
+    $session->run_command(
+	{ COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
+		      $session->strip_chroot_path($dummy_gpghome)],
+	  USER => 'root',
+	  DIR => '/' });
+    if ($?) {
+	$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)) {
+        $self->log_warning('Could not create archive dir ' . $dummy_archive_dir .
+                           ' for dummy archive ' . $shortname . ': ' . $!);
+        $self->cleanup();
+        return 0;
+    }
+    return 1;
+}
+
+# Push files in the archive and add it to the APT sources
+sub populate {
+    my $self = shift;
+
+    my @debs = @{$self->get('Debs')};
+    my @dscs = @{$self->get('Dscs')};
+    my $dummy_archive_dir = $self->get('Dummy archive directory');
+    my $dummy_archive_list_file = $self->get('Dummy archive list file');
+    my $dummy_release_file= $self->get('Dummy Release file');
+    my $session = $self->get('Session');
+    my $dummy_gpghome = $self->get('Dummy GPG home');
+
+    my $dummy_archive_seckey = $dummy_archive_dir . '/sbuild-key.sec';
+    my $dummy_archive_pubkey = $dummy_archive_dir . '/sbuild-key.pub';
+
+    foreach my $file (@debs, @dscs) {
+        copy($file, $dummy_archive_dir);
+        if ($?) {
+            $self->log("Failed to copy ${file} to the dummy archive.\n");
+            $self->cleanup();
+            return 0;
+        }
+    }
+
+    # Do code to run apt-ftparchive
+    if (!$self->run_apt_ftparchive()) {
+        $self->log("Failed to run apt-ftparchive.\n");
+        $self->cleanup();
+        return 0;
+    }
+
+    if (! -f $dummy_archive_seckey) {
+        my $secret_key = $self->get('Dummy archive secret key file');
+        copy($secret_key, $dummy_archive_seckey);
+        if ($?) {
+            $self->log("Failed to copy the secret key ${secret_key} to the dummy archive.\n");
+            $self->cleanup();
+            return 0;
+        }
+    }
+
+    if (! -f $dummy_archive_pubkey) {
+        my $public_key = $self->get('Dummy archive public key file');
+        copy($public_key, $dummy_archive_pubkey);
+        if ($?) {
+            $self->log("Failed to copy the public key ${public_key} to the dummy archive.\n");
+            $self->cleanup();
+            return 0;
+        }
+    }
+
+    # Sign the release file
+    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),
+                       '--default-key', 'Sbuild Signer', '-abs',
+                       '-o', $session->strip_chroot_path($dummy_release_file) . '.gpg',
+                       $session->strip_chroot_path($dummy_release_file));
+    $session->run_command(
+	{ COMMAND => \@gpg_command,
+	  USER => $self->get_conf('BUILD_USER'),
+	  PRIORITY => 0});
+    if ($?) {
+	$self->log("Failed to sign dummy archive Release file.\n");
+        $self->cleanup();
+	return 0;
+    }
+
+    # 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");
+        print $tmpfh 'deb file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n";
+        print $tmpfh 'deb-src file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n";
+        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 ($?) {
+            $self->log("Failed to create apt list file for dummy archive.\n");
+            $self->cleanup();
+            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 ($?) {
+            $self->log("Failed to create apt list file for dummy archive.\n");
+            $self->cleanup();
+            return 0;
+        }
+    }
+
+    # Add the generated key
+    $session->run_command(
+        { COMMAND => ['apt-key', 'add', $session->strip_chroot_path($dummy_archive_pubkey)],
+          USER => 'root',
+          PRIORITY => 0});
+    if ($?) {
+        $self->log("Failed to add dummy archive key.\n");
+        $self->cleanup();
+        return 0;
+    }
+
+    return 1;
+}
+
+sub cleanup {
+    my $self = shift;
+
+    my $session = $self->get('Session');
+
+    if (defined $self->get('Dummy archive path')) {
+	$session->run_command(
+	    { COMMAND => ['rm', '-fr', $session->strip_chroot_path($self->get('Dummy archive path'))],
+	      USER => $self->get_conf('BUILD_USER'),
+	      DIR => '/' });
+    }
+
+    $session->run_command(
+	{ COMMAND => ['rm', '-f', $session->strip_chroot_path($self->get('Dummy archive list file'))],
+	  USER => 'root',
+	  DIR => '/',
+	  PRIORITY => 0});
+    $self->set('Dummy archive path', undef);
+    $self->set('Dummy archive directory', undef);
+    $self->set('Dummy Release file', undef);
+}
+
+# Function that runs apt-ftparchive
+sub run_apt_ftparchive {
+    my $self = shift;
+
+    my $session = $self->get('Session');
+    my $host = $self->get('Host');
+
+    my ($tmpfh, $tmpfilename) = tempfile();
+    my $dummy_archive_shortname = $self->get('Shortname');
+    my $dummy_archive_name = $self->get('Name');
+    my $dummy_archive_dir = $self->get('Dummy archive directory');
+
+    # 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-$dummy_archive_shortname-archive";
+APT::FTPArchive::Release::Label "sbuild-$dummy_archive_shortname-archive";
+APT::FTPArchive::Release::Suite "invalid";
+APT::FTPArchive::Release::Codename "invalid";
+APT::FTPArchive::Release::Description "Sbuild $dummy_archive_name 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;
+    }
+
+    # 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;
+
+
+    # Write output to Release file path.
+    my ($releasefh);
+    if (!open($releasefh, '>', $self->get('Dummy Release file'))) {
+        close $pipe;
+	unlink $tmpfilename;
+        return 0;
+    }
+
+    while (<$pipe>) {
+        print $releasefh $_;
+    }
+    close $releasefh;
+    close $pipe;
+
+    # Remove config file.  Note also removed on failure paths above.
+    unlink $tmpfilename;
+
+    return 1;
+}
+
+sub get_apt_command_internal {
+    my $self = shift;
+    my $options = shift;
+
+    my $command = $options->{'COMMAND'};
+    my $apt_options = $self->get('APT Options');
+
+    debug2("APT Options: ", join(" ", @$apt_options), "\n")
+	if defined($apt_options);
+
+    my @aptcommand = ();
+    if (defined($apt_options)) {
+	push(@aptcommand, @{$command}[0]);
+	push(@aptcommand, @$apt_options);
+	if ($#$command > 0) {
+	    push(@aptcommand, @{$command}[1 .. $#$command]);
+	}
+    } else {
+	@aptcommand = @$command;
+    }
+
+    debug2("APT Command: ", join(" ", @aptcommand), "\n");
+
+    $options->{'INTCOMMAND'} = \@aptcommand;
+}
+
+sub run_apt_command {
+    my $self = shift;
+    my $options = shift;
+
+    my $session = $self->get('Session');
+    my $host = $self->get('Host');
+
+    # Set modfied command
+    $self->get_apt_command_internal($options);
+
+    if ($self->get('Split')) {
+	return $host->run_command_internal($options);
+    } else {
+	return $session->run_command_internal($options);
+    }
+}
+
+sub pipe_apt_command {
+    my $self = shift;
+    my $options = shift;
+
+    my $session = $self->get('Session');
+    my $host = $self->get('Host');
+
+    # Set modfied command
+    $self->get_apt_command_internal($options);
+
+    if ($self->get('Split')) {
+	return $host->pipe_command_internal($options);
+    } else {
+	return $session->pipe_command_internal($options);
+    }
+}
+
+1;
diff --git a/lib/Sbuild/Makefile.am b/lib/Sbuild/Makefile.am
index 945645c..5897657 100644
--- a/lib/Sbuild/Makefile.am
+++ b/lib/Sbuild/Makefile.am
@@ -35,6 +35,7 @@ MODULES =			\
 	ChrootInfo.pm		\
 	ChrootInfoSchroot.pm	\
 	ChrootInfoSudo.pm	\
+	DummyArchive.pm		\
 	Exception.pm		\
 	ResolverBase.pm		\
 	AptitudeResolver.pm	\
diff --git a/lib/Sbuild/ResolverBase.pm b/lib/Sbuild/ResolverBase.pm
index 8048f16..c1dd9c3 100644
--- a/lib/Sbuild/ResolverBase.pm
+++ b/lib/Sbuild/ResolverBase.pm
@@ -30,6 +30,7 @@ use File::Copy;
 
 use Dpkg::Deps;
 use Sbuild::Base;
+use Sbuild::DummyArchive;
 use Sbuild qw(isin debug debug2);
 
 BEGIN {
@@ -59,10 +60,17 @@ sub new {
     $self->set('Host Arch', $self->get_conf('HOST_ARCH'));
     $self->set('Build Arch', $self->get_conf('BUILD_ARCH'));
 
-    my $dummy_archive_list_file = $session->get('Location') .
-        '/etc/apt/sources.list.d/sbuild-build-depends-archive.list';
-    $self->set('Dummy archive list file', $dummy_archive_list_file);
+    if (!$self->generate_keys()) {
+        $self->log("Failed to generate archive keys.\n");
+        $self->cleanup_apt_archive();
+        return 0;
+    }
 
+    my $dummy_archive = Sbuild::DummyArchive->new($conf, $session, $host,
+                                                  'build-depends', 'Build Dependencies',
+                                                  $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY'),
+                                                  $self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY'));
+    $self->set('Dummy archive', $dummy_archive);
 
     return $self;
 }
@@ -188,52 +196,8 @@ sub update_archive {
 	      DIR => '/' });
 	return $?;
     } else {
-	# Example archive list names:
-	#_tmp_resolver-XXXXXX_apt%5farchive_._Packages
-	#_tmp_resolver-XXXXXX_apt%5farchive_._Release
-	#_tmp_resolver-XXXXXX_apt%5farchive_._Release.gpg
-	#_tmp_resolver-XXXXXX_apt%5farchive_._Sources
-
-	# Update lists directly; only updates local archive
-
-	# Filename quoting for safety taken from apt URItoFileName and
-	# QuoteString.
-	my $session = $self->get('Session');
-	my $dummy_dir = $self->get('Dummy package path');
-	my $dummy_archive_dir = $session->strip_chroot_path($dummy_dir.'/apt_archive/./');
-	my @chars = split('', $dummy_archive_dir);
-
-	foreach(@chars) {
-	    if (index('\\|{}[]<>"^~_=!@#$%^&*', $_) != -1 || # "Bad" characters
-		!m/[[:print:]]/ || # Not printable
-		ord($_) == 0x25 || # Percent '%' char
-		ord($_) <= 0x20 || # Control chars
-		ord($_) >= 0x7f) { # Control chars
-		$_ = sprintf("%%%02x", ord($_));
-	    }
-	}
-
-	my $uri = join('', @chars);
-	$uri =~ s;/;_;g; # Escape slashes
-
-	foreach my $file ("Packages", "Release", "Release.gpg", "Sources") {
-	    $session->run_command(
-		{ COMMAND => ['cp', $dummy_archive_dir . '/' . $file,
-			      '/var/lib/apt/lists/' . $uri . $file],
-		  USER => 'root',
-		  PRIORITY => 0 });
-		if ($?) {
-			$self->log("Failed to copy file from dummy archive to apt lists.\n");
-			return 1;
-		}
-	}
-
-	$self->run_apt_command(
-	    { COMMAND => [$self->get_conf('APT_CACHE'), 'gencaches'],
-	      ENV => {'DEBIAN_FRONTEND' => 'noninteractive'},
-	      USER => 'root',
-	      DIR => '/' });
-	return $?;
+        my $dummy_archive = $self->get('Dummy archive');
+        $dummy_archive->force_update_archive_list();
     }
 }
 
@@ -797,7 +761,27 @@ EOF
     return 1;
 }
 
-# Create an apt archive. Add to it if one exists.
+# Generate a key pair if not already done.
+sub generate_keys {
+    my $self = shift;
+
+    if ((-f $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY')) &&
+        (-f $self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY'))) {
+        return 1;
+    }
+
+    $self->log_error("Local archive GPG signing key not found\n");
+    $self->log_info("Please generate a key with 'sbuild-update --keygen'\n");
+    $self->log_info("Note that on machines with scarce entropy, you may wish ".
+		    "to generate the key with this command on another machine ".
+		    "and copy the public and private keypair to '" .
+		    $self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY')
+		    ."' and '".
+		    $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY') ."'\n");
+    return 0;
+}
+
+# Create an apt archive with the dummy build-depends package.
 sub setup_apt_archive {
     my $self = shift;
     my $dummy_pkg_name = shift;
@@ -805,6 +789,9 @@ sub setup_apt_archive {
 
     my $session = $self->get('Session');
 
+    my $dummy_archive = $self->get('Dummy archive');
+    $dummy_archive->set('Chroot Build Dir', $self->get('Chroot Build Dir'));
+
     #Prepare a path to build a dummy package containing our deps:
     if (! defined $self->get('Dummy package path')) {
         $self->set('Dummy package path',
@@ -830,56 +817,9 @@ sub setup_apt_archive {
 	return 0;
     }
     my $dummy_dir = $self->get('Dummy package path');
-    my $dummy_gpghome = $dummy_dir . '/gpg';
-    my $dummy_archive_dir = $dummy_dir . '/apt_archive';
-    my $dummy_release_file = $dummy_archive_dir . '/Release';
-    my $dummy_archive_seckey = $dummy_archive_dir . '/sbuild-key.sec';
-    my $dummy_archive_pubkey = $dummy_archive_dir . '/sbuild-key.pub';
-
-    $self->set('Dummy archive directory', $dummy_archive_dir);
-    $self->set('Dummy Release file', $dummy_release_file);
-    my $dummy_archive_list_file = $self->get('Dummy archive list file');
-
-    if (! -d $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)) {
-        $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 ($?) {
-	$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)) {
-        $self->log_warning('Could not create build-depends dummy archive dir ' . $dummy_archive_dir . ': ' . $!);
-        $self->cleanup_apt_archive();
-        return 0;
-    }
-
-    $session->run_command(
-        { COMMAND => ['chown', $self->get_conf('BUILD_USER') . ':sbuild',
-                      $session->strip_chroot_path($dummy_archive_dir)],
-          USER => 'root',
-          DIR => '/' });
-    if ($?) {
-        $self->log_error("E: Failed to set " . $self->get_conf('BUILD_USER')
-                       . ":sbuild ownership on $dummy_archive_dir\n");
-        return 0;
-    }
-
     my $dummy_pkg_dir = $dummy_dir . '/' . $dummy_pkg_name;
-    my $dummy_deb = $dummy_archive_dir . '/' . $dummy_pkg_name . '.deb';
-    my $dummy_dsc = $dummy_archive_dir . '/' . $dummy_pkg_name . '.dsc';
+    my $dummy_deb = $dummy_dir . '/' . $dummy_pkg_name . '.deb';
+    my $dummy_dsc = $dummy_dir . '/' . $dummy_pkg_name . '.dsc';
 
     if (!$self->build_dummy_package ($dummy_pkg_name, $dummy_pkg_dir, $dummy_deb, $dummy_dsc, @pkgs)) {
         $self->log("Failed to create build-depends dummy package.\n");
@@ -887,78 +827,17 @@ sub setup_apt_archive {
         return 0;
     }
 
-    # Do code to run apt-ftparchive
-    if (!$self->run_apt_ftparchive()) {
-        $self->log("Failed to run apt-ftparchive.\n");
+    if (!$dummy_archive->setup()) {
+        $self->log("Failed to setup build-depends dummy archive.\n");
         $self->cleanup_apt_archive();
         return 0;
     }
 
-    # Sign the release file
-    if (!$self->generate_keys()) {
-        $self->log("Failed to generate archive keys.\n");
-        $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);
-    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),
-                       '--default-key', 'Sbuild Signer', '-abs',
-                       '-o', $session->strip_chroot_path($dummy_release_file) . '.gpg',
-                       $session->strip_chroot_path($dummy_release_file));
-    $session->run_command(
-	{ COMMAND => \@gpg_command,
-	  USER => $self->get_conf('BUILD_USER'),
-	  PRIORITY => 0});
-    if ($?) {
-	$self->log("Failed to sign dummy archive Release file.\n");
-        $self->cleanup_apt_archive();
-	return 0;
-    }
+    $dummy_archive->add_deb ($dummy_deb);
+    $dummy_archive->add_dsc ($dummy_dsc);
 
-    # 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");
-        print $tmpfh 'deb file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n";
-        print $tmpfh 'deb-src file://' . $session->strip_chroot_path($dummy_archive_dir) . " ./\n";
-        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 ($?) {
-            $self->log("Failed to create apt list file for dummy archive.\n");
-            $self->cleanup_apt_archive();
-            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 ($?) {
-            $self->log("Failed to create apt list file for dummy archive.\n");
-            $self->cleanup_apt_archive();
-            return 0;
-        }
-    }
-
-    # Add the generated key
-    $session->run_command(
-        { COMMAND => ['apt-key', 'add', $session->strip_chroot_path($dummy_archive_pubkey)],
-          USER => 'root',
-          PRIORITY => 0});
-    if ($?) {
-        $self->log("Failed to add dummy archive key.\n");
+    if (!$dummy_archive->populate()) {
+        $self->log("Failed to populate build-depends dummy archive.\n");
         $self->cleanup_apt_archive();
         return 0;
     }
@@ -970,129 +849,10 @@ sub setup_apt_archive {
 sub cleanup_apt_archive {
     my $self = shift;
 
-    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->run_command(
-	{ COMMAND => ['rm', '-f', $session->strip_chroot_path($self->get('Dummy archive list file'))],
-	  USER => 'root',
-	  DIR => '/',
-	  PRIORITY => 0});
-    $self->set('Dummy package path', undef);
-    $self->set('Dummy archive directory', undef);
-    $self->set('Dummy Release file', undef);
+    my $dummy_archive = $self->get('Dummy archive');
+    $dummy_archive->cleanup();
 }
 
-# Generate a key pair if not already done.
-sub generate_keys {
-    my $self = shift;
-
-    if ((-f $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY')) &&
-        (-f $self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY'))) {
-        return 1;
-    }
-
-    $self->log_error("Local archive GPG signing key not found\n");
-    $self->log_info("Please generate a key with 'sbuild-update --keygen'\n");
-    $self->log_info("Note that on machines with scarce entropy, you may wish ".
-		    "to generate the key with this command on another machine ".
-		    "and copy the public and private keypair to '" .
-		    $self->get_conf('SBUILD_BUILD_DEPENDS_PUBLIC_KEY')
-		    ."' and '".
-		    $self->get_conf('SBUILD_BUILD_DEPENDS_SECRET_KEY') ."'\n");
-    return 0;
-}
-
-# Function that runs apt-ftparchive
-sub run_apt_ftparchive {
-    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');
-
-    # 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;
-    }
-
-    # 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;
-
-
-    # Write output to Release file path.
-    my ($releasefh);
-    if (!open($releasefh, '>', $self->get('Dummy Release file'))) {
-        close $pipe;
-	unlink $tmpfilename;
-        return 0;
-    }
-
-    while (<$pipe>) {
-        print $releasefh $_;
-    }
-    close $releasefh;
-    close $pipe;
-
-    # Remove config file.  Note also removed on failure paths above.
-    unlink $tmpfilename;
-
-    return 1;
-}
 
 sub get_apt_command_internal {
     my $self = shift;
-- 
1.8.3.1


>From cccdc7803b8e0c8755b9bfbe9e60b8787ce524e9 Mon Sep 17 00:00:00 2001
From: Emanuele Aina <[email protected]>
Date: Mon, 3 Jun 2013 11:09:36 +0200
Subject: [PATCH 3/3] Sbuild::ResolverBase: Let users add custom packages to
 the build-deps archive

By letting users add custom packages to the dummy build-depends archive
with the --add-extra-package flags it should be easier to build packages
without waiting for their build dependencies to enter the main archive
and without going through the hassle of maintaining a local archive.
---
 lib/Sbuild/Build.pm        |  3 +++
 lib/Sbuild/Conf.pm         |  6 ++++++
 lib/Sbuild/Options.pm      |  3 +++
 lib/Sbuild/ResolverBase.pm | 14 ++++++++++++++
 man/sbuild.1.in            |  6 ++++++
 5 files changed, 32 insertions(+)

diff --git a/lib/Sbuild/Build.pm b/lib/Sbuild/Build.pm
index 0b2985c..fa8f749 100644
--- a/lib/Sbuild/Build.pm
+++ b/lib/Sbuild/Build.pm
@@ -659,6 +659,9 @@ sub run_fetch_install_packages {
 				    $self->get('Build Conflicts Arch'),
 				    $self->get('Build Conflicts Indep'));
 
+	$resolver->add_extra_packages(
+				    $self->get_conf('EXTRA_PACKAGES'));
+
 	my @build_deps;
 	if ($self->get('Host Arch') eq $self->get('Build Arch')) {
 	    @build_deps = ('ESSENTIAL', 'GCC_SNAPSHOT', 'MANUAL',
diff --git a/lib/Sbuild/Conf.pm b/lib/Sbuild/Conf.pm
index 27b035c..2b87484 100644
--- a/lib/Sbuild/Conf.pm
+++ b/lib/Sbuild/Conf.pm
@@ -803,6 +803,12 @@ sub setup ($) {
 	    DEFAULT => [],
 	    HELP => 'Additional per-build dependencies.  Do not set by hand.'
 	},
+	'EXTRA_PACKAGES'			=> {
+	    TYPE => 'ARRAY:STRING',
+	    GROUP => '__INTERNAL',
+	    DEFAULT => [],
+	    HELP => 'Extra packages to be made available for dependency resolution.'
+	},
 	'CROSSBUILD_CORE_DEPENDS'				=> {
 	    TYPE => 'HASH:ARRAY:STRING',
 	    VARNAME => 'crossbuild_core_depends',
diff --git a/lib/Sbuild/Options.pm b/lib/Sbuild/Options.pm
index 4a232bf..dcfb946 100644
--- a/lib/Sbuild/Options.pm
+++ b/lib/Sbuild/Options.pm
@@ -140,6 +140,9 @@ sub set_options {
 		       "e|uploader=s" => sub {
 			   $self->set_conf('UPLOADER_NAME', $_[1]);
 		       },
+		       "add-extra-package=s" => sub {
+			   push(@{$self->get_conf('EXTRA_PACKAGES')}, $_[1]);
+		       },
 		       "debbuildopts=s" => sub {
 			   push(@{$self->get_conf('DPKG_BUILDPACKAGE_USER_OPTIONS')},
 				split(/\s+/, $_[1]));
diff --git a/lib/Sbuild/ResolverBase.pm b/lib/Sbuild/ResolverBase.pm
index c1dd9c3..9be5b69 100644
--- a/lib/Sbuild/ResolverBase.pm
+++ b/lib/Sbuild/ResolverBase.pm
@@ -55,6 +55,7 @@ sub new {
     $self->set('Host', $host);
     $self->set('Changes', {});
     $self->set('AptDependencies', {});
+    $self->set('ExtraPackages', []);
     $self->set('Split', $self->get_conf('CHROOT_SPLIT'));
     # Typically set by Sbuild::Build, but not outside a build context.
     $self->set('Host Arch', $self->get_conf('HOST_ARCH'));
@@ -285,6 +286,14 @@ sub add_dependencies {
     $self->get('AptDependencies')->{$pkg} = $deps;
 }
 
+sub add_extra_packages {
+    my $self = shift;
+    my $pkgs = shift;
+    my @pkgs = @$pkgs;
+
+    $self->set('ExtraPackages', \@pkgs);
+}
+
 sub install_core_deps {
     my $self = shift;
     my $name = shift;
@@ -836,6 +845,11 @@ sub setup_apt_archive {
     $dummy_archive->add_deb ($dummy_deb);
     $dummy_archive->add_dsc ($dummy_dsc);
 
+    my @extra_debs = @{$self->get('ExtraPackages')};
+    foreach my $extra_deb (@extra_debs) {
+        $dummy_archive->add_deb ($extra_deb);
+    }
+
     if (!$dummy_archive->populate()) {
         $self->log("Failed to populate build-depends dummy archive.\n");
         $self->cleanup_apt_archive();
diff --git a/man/sbuild.1.in b/man/sbuild.1.in
index a91a064..f87f32c 100644
--- a/man/sbuild.1.in
+++ b/man/sbuild.1.in
@@ -42,6 +42,7 @@ sbuild \- build debian packages from source
 .RB [ \-\-add-conflicts\-arch=\fIdependency\fP ]
 .RB [ \-\-add-depends\-indep=\fIdependency\fP ]
 .RB [ \-\-add-conflicts\-indep=\fIdependency\fP ]
+.RB [ \-\-add-extra-package=\fIdebfile\fP ]
 .RB [ \-m \[or] \-\-maintainer=\fImaintainer\fP ]
 .RB [ \-e \[or] \-\-uploader=\fIuploader\fP ]
 .RB [ \-k \[or] \-\-keyid=\fIkey-id\fP ]
@@ -145,6 +146,11 @@ 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.
 .TP
+.BR \-\-add-extra-package=\fIdebfile\fP
+Inject additional packages into the build dependencies dummy archive.  This can
+be useful to build related packages before the depended-on ones hit the main
+archive.  The option may be used any number of times to add multiple packages.
+.TP
 .BR "\-\-arch=\fIarchitecture\fP"
 Build using the architecture specified.  A chroot named
 \fI$distribution\-$arch-sbuild\fP or \fI$distribution\-arch\fP is searched for,
-- 
1.8.3.1


--- End Message ---
--- Begin Message ---
Source: sbuild
Source-Version: 0.65.0-1

We believe that the bug you reported is fixed in the latest version of
sbuild, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Wookey <[email protected]> (supplier of updated sbuild package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Format: 1.8
Date: Fri, 17 Oct 2014 17:20:45 +0100
Source: sbuild
Binary: libsbuild-perl sbuild buildd
Architecture: source all
Version: 0.65.0-1
Distribution: unstable
Urgency: medium
Maintainer: Debian buildd-tools Developers 
<[email protected]>
Changed-By: Wookey <[email protected]>
Description:
 buildd     - Daemon for automatically building Debian binary packages from Deb
 libsbuild-perl - Tool for building Debian binary packages from Debian sources
 sbuild     - Tool for building Debian binary packages from Debian sources
Closes: 679574 700522 705926 712627 714883 722103 729012 731798 745221 756265
Changes:
 sbuild (0.65.0-1) unstable; urgency=medium
 .
   [ Benjamin Drung ]
   * Team upload.
   * Fix various issues found by Lintian:
     - Fix spelling mistake: indended -> intended
     - Fix hyphen-used-as-minus-sign
     - Fix debian-news-entry-uses-asterisk
     - Fix copyright-refers-to-symlink-license
     - Use canonical VCS fields
   * Export additional variables to external commands: %SBUILD_CHROOT_DIR,
     %SBUILD_BUILD_DIR, %SBUILD_PKGBUILD_DIR, and %SBUILD_HOST_ARCH
     (Closes: #756265)
   * Bump Standard-Version to 3.9.6
   * Unset typical desktop variables XDG_RUNTIME_DIR, XDG_SEAT,
     XDG_SESSION_COOKIE, XDG_SESSION_ID, and XDG_VTNR (Closes: #729012)
   * Fail if dpkg subcommands fail instead of silently ignoring failures.
     Thanks to Christoph Biedl for the patch (Closes: #745221)
   * Fix build failure if the package version ends with Debian revision 0.
     Thanks to Adam Borowski <[email protected]> (Closes: #679574)
   * Fix broken man page symlinks in buildd package
 .
   [ Geoffrey Thomas ]
   * Refactor temporary build-dep repository code to use apt-get update,
     instead of hacking /var/lib/apt/lists.
   * Add --extra-package (Closes: #700522) and --extra-repository (Closes:
     #714883).
   * Accept 0 as a source version number (Closes: #712627)
   * Add DEP-8 autopkgtest to build procenv. (Closes: #705926)
 .
   [ Johannes Schauer ]
   * sbuild:
     - Add build-profiles support (Closes: 731798)
 .
   [ Geoffrey Thomas ]
   * Sbuild::ChrootSetup: Pass --no-options to gpg (Closes: #722103)
Checksums-Sha1:
 e1a78947d0da569f61564366875b5f8216e71731 2211 sbuild_0.65.0-1.dsc
 56981eb635917ea1f25bef52a5fdac30604317c2 584238 sbuild_0.65.0.orig.tar.gz
 bf5fc61e1e2dd4983b529cbfa7c6fa6ae3244dde 50120 sbuild_0.65.0-1.debian.tar.xz
 27fce893c17ab4555bb02e90bc59a7bc14944dbc 291050 libsbuild-perl_0.65.0-1_all.deb
 d647e2eb7de5d0c3cf24c82a3f0bda08ac8cf112 312614 sbuild_0.65.0-1_all.deb
 c41442bca66b17de8971effd360fea3c42e3df7f 293378 buildd_0.65.0-1_all.deb
Checksums-Sha256:
 eac5afbb989d0eff6718dbff340e2b1dbec30e8f8e8564f07cab212053a16b41 2211 
sbuild_0.65.0-1.dsc
 2d78cae0a09c1d7334b87c45fb4a2de32d64d492600ca06be7d8eb43a88d7eab 584238 
sbuild_0.65.0.orig.tar.gz
 d67bfd434d0b4a83b1f14e8c5aa7579951d1c59c9076056757efd60ba821a3ab 50120 
sbuild_0.65.0-1.debian.tar.xz
 7cf376654b86fe7b597be0d29da3b67a1587cf1577f1837a7e44d90d4d60a1e3 291050 
libsbuild-perl_0.65.0-1_all.deb
 68281ef0d90b366285c9d04b497f14161c2ff602957b1589492cfc681b32d008 312614 
sbuild_0.65.0-1_all.deb
 38b41958c8677be17ccd448b79af312d2f68f9eb5d8b2f9b8ff6b28918a24134 293378 
buildd_0.65.0-1_all.deb
Files:
 f765239cba6dc9ecebe5ad9f3866b3ec 2211 devel extra sbuild_0.65.0-1.dsc
 a0e4806ff60418bac3ea31d4b964a532 584238 devel extra sbuild_0.65.0.orig.tar.gz
 9d693cac94f66ce1b2f9841fbfd68910 50120 devel extra 
sbuild_0.65.0-1.debian.tar.xz
 6336273bd515916d090ff631da413758 291050 perl extra 
libsbuild-perl_0.65.0-1_all.deb
 38237fcc180441e42c9f48bf47647c08 312614 devel extra sbuild_0.65.0-1_all.deb
 627fbc34a04a74e6fe2c42fc70e7f1fb 293378 devel extra buildd_0.65.0-1_all.deb

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iQIcBAEBAgAGBQJUQUhSAAoJEPuGMlGob55HiJoQALIg5wIhx8JGa5qgPkx9vBTD
X8aYNQEW3NwrB1IIqJW/nLm0ES2eD1nU7FoIPPV2eBxwwnPCm06F1Ew/o3XRKldP
/e2DnAr8IoIcn9ToGA/jNQTDpVH0alqz56c3oPgIWbgu0yGeYi31w1VUxQ50IHH0
8dWyWWXMe5a6iCYeiCZ/WT7U5Xd2RpFwrO8iq1jMcg132mQp6HriK5Kr7C2G5g9w
mt5QZ3BfaZVlZNZfNYj7BR3aCVHXtZKSLBwmtI6TZkMxC9pE4Xmx3mxxhTQNGhkR
QyhtlecRJY0Igp9JN1E5RBBc2d1OcWPYxZa+yD/RcvsXVMDnL7L/W7XZOBxrS+Tf
wQz33t7Pdls407DjyzSuVYhdfj6I4e5ILcbxjwZvRxRohLZJeWK5nLwcDOLVsdpO
uwjxzcVOL+1KaCREaLlr3o2+E2Sw89pI12kPENGIDZ0knRiBC0AvmpGNvsfJtggI
9glp6o7V9HpvLf4PaUN+qyw3clsVn3CXcljOzCrchXc5h+IuIAoOHKDkehK+UqLU
VtT5WjefspUwJcXdFL63go1TMm7cLAEmuiJUhW/cZh4pHpSUi2jVz+33mnO5y9Zy
75/GV4bwivQwN2Azqj7tv9ots/T+u45x0Ib1K9GgLq33jO1gSTyrEKgR4PLvwVXy
tkR5//uqf6qTCJdEvUjx
=YQM/
-----END PGP SIGNATURE-----

--- End Message ---

Reply via email to