Here are a new set of patches for some debuild like functionality implemented 
directly in sbuild. Details of what's new is in the patch for the man page but 
in short, sbuild would now be able to build from a Debianized source package, 
run lintian after a build, and run external commands before and after a build.

With this, the sbuild-debuild script and manpage can be removed.

-- 
Regards,
Andres
From fcec5a689bd907f02d8fbd739dde66e13b7eb97c Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:04:28 -0400
Subject: [PATCH 1/6] Improve the parse_file() utility subroutine by being able to handle filehandles.
 This also provides better handling of placing the contents of fields in the
 hashes. Trailing newlines are removed as well as leading whitespace. Also, the
 first whitespace from multiline fields is removed.

---
 lib/Sbuild/Utility.pm |   23 +++++++++++++++++------
 1 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/lib/Sbuild/Utility.pm b/lib/Sbuild/Utility.pm
index 6ae6159..41ab9a3 100644
--- a/lib/Sbuild/Utility.pm
+++ b/lib/Sbuild/Utility.pm
@@ -356,7 +356,8 @@ sub _get_proxy {
 
 # Method to parse a rfc822 type file, like Debian changes or control files.
 # It can also be used on files like Packages or Sources files in a Debian
-# archive.
+# archive and can be used to parse output from tools such as dpkg-deb and
+# dpkg-parsechangelog.
 # This subroutine returns an array of hashes. Each hash is a stanza.
 sub parse_file {
     # Takes one parameter, the file to parse.
@@ -386,9 +387,14 @@ sub parse_file {
 
     # Enclose this in it's own block, since we change $/
     {
-        # Attempt to open and read the file
+        # Attempt to open and read the file or assign passed filehandle to $fh
         my $fh;
-        open $fh, '<', $file or die "Could not read $file: $!";
+	if (ref($file) eq "GLOB") {
+	    $fh = $file;
+	} elsif (! open $fh, '<', $file) {
+	    print "Could not read $file: $!";
+	    return 0;
+	}
 
         # Read paragraph by paragraph
         local $/ = "";
@@ -399,21 +405,26 @@ sub parse_file {
 
             # Chomp the paragraph and split by each field
             chomp;
-            my @matches = split /$split_pattern/, "$_\n";
+            my @matches = split /$split_pattern/, "$_";
 
             # Loop through the fields, placing them into a hash
             my %fields;
             foreach my $match (@matches) {
                 my ($field, $field_contents);
                 $field = $1 if ($match =~ /([^:]+?):/msx);
-                $field_contents = $1 if ($match =~ /[^:]+?:(.*)/msx);
+                $field_contents = $1 if ($match =~ /[^:]+?:\s*?\b(.*)/msx);
+                chomp $field_contents;
+                $field_contents =~ s/^\s//msxg;
                 $fields{$field} = $field_contents;
             }
 
             # Push each hash of fields as a ref onto our array
             push @array_of_fields, \%fields;
         }
-        close $fh or die "Problem encountered closing file $file: $!";
+        if ((ref($file) ne "GLOB") && (! close $fh)) {
+	    print "Problem encountered closing file $file: $!";
+	    return 0;
+	}
     }
 
     # Return a reference to the array
-- 
1.6.5

From 4011dc3dafba78c16d285c2b0bcb8616a8dd478a Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:16:37 -0400
Subject: [PATCH 2/6] Supply more options to be used with sbuild.
 Options are:
     Supporting options to pass to dpkg-source.
     Being able to run lintian.
     Supporting options to pass to lintian.
     Being able to run external commands before a build.
     Being able to run commands after a build.
     Whether to log stdout or stderr from external commands.

---
 etc/sbuild.conf            |   33 ++++++++++++++++++++++++
 lib/Sbuild/Conf.pm         |   59 ++++++++++++++++++++++++++++++++++++++++++-
 lib/Sbuild/Options.pm      |   45 ++++++++++++++++++++++++++++++++-
 lib/Sbuild/Sysconfig.pm.in |    1 +
 4 files changed, 135 insertions(+), 3 deletions(-)

diff --git a/etc/sbuild.conf b/etc/sbuild.conf
index 3d82caf..d7ed327 100644
--- a/etc/sbuild.conf
+++ b/etc/sbuild.conf
@@ -71,6 +71,14 @@
 #
 #$build_env_cmnd = "";
 
+##
+## DPKG-SOURCE OPTIONS
+##
+
+# Options to pass to dpkg-source
+#$dpkg_source_opt = "";
+# Options to be added with options passed to dpkg-source
+#$dpkg_source_opts = "";
 
 ##
 ## SBUILD BEHAVIOUR
@@ -244,6 +252,31 @@
 # Job status file (only used in batch mode)
 #$job_file = "build-progress";
 
+##
+## LINTIAN OPTIONS
+##
+
+# lintian binary
+#$lintian = "/usr/bin/lintian";
+# Whether to run lintian
+#$run_lintian = 0;
+# Options to pass to lintian
+#$lintian_opt = "";
+# Options to add into options passed to lintian
+#$lintian_opts = "";
+
+##
+## EXTERNAL COMMANDS
+##
+
+# pre build commands
+...@pre_build_commands = ();
+# post build commands
+...@post_build_commands = ();
+# Whether to log command output
+#$log_external_command_output = 0;
+# Whether to log command error
+#$log_external_command_error = 0;
 
 ##
 ## PROGRAMS USED BY SBUILD
diff --git a/lib/Sbuild/Conf.pm b/lib/Sbuild/Conf.pm
index 325c865..b0d0292 100644
--- a/lib/Sbuild/Conf.pm
+++ b/lib/Sbuild/Conf.pm
@@ -167,6 +167,9 @@ sub init_allowed_keys {
 	    CHECK => $validate_program,
 	    DEFAULT => $Sbuild::Sysconfig::programs{'DPKG_SOURCE'}
 	},
+	'DPKG_SOURCE_OPT'			=> {
+	    DEFAULT => undef
+	},
 	'DCMD'					=> {
 	    CHECK => $validate_program,
 	    DEFAULT => $Sbuild::Sysconfig::programs{'DCMD'}
@@ -438,7 +441,29 @@ sub init_allowed_keys {
 	},
 	'JOB_FILE'				=> {
 	    DEFAULT => 'build-progress'
-	}
+	},
+	'LINTIAN'				=> {
+	    CHECK => $validate_program,
+	    DEFAULT => $Sbuild::Sysconfig::programs{'LINTIAN'},
+	},
+	'RUN_LINTIAN'				=> {
+	    DEFAULT => 0
+	},
+	'LINTIAN_OPT'				=> {
+	    DEFAULT => undef
+	},
+	'PRE_BUILD_COMMANDS'			=> {
+	    DEFAULT => []
+	},
+	'POST_BUILD_COMMANDS'			=> {
+	    DEFAULT => []
+	},
+	'LOG_EXTERNAL_COMMAND_OUTPUT'		=> {
+	    DEFAULT => 0
+	},
+	'LOG_EXTERNAL_COMMAND_ERROR'		=> {
+	    DEFAULT => 0
+	},
     );
 
     $self->set_allowed_keys(\%sbuild_keys);
@@ -466,6 +491,8 @@ sub read_config {
     my $apt_get = undef;
     my $apt_cache = undef;
     my $dpkg_source = undef;
+    my $dpkg_source_opt = undef;
+    my $dpkg_source_opts = undef;
     my $dcmd = undef;
     my $md5sum = undef;
     my $avg_time_db = undef;
@@ -518,6 +545,16 @@ sub read_config {
     my $build_arch_all = undef;
     my $arch = undef;
     my $job_file = undef;
+    my $lintian = undef;
+    my $run_lintian = undef;
+    my $lintian_opt = undef;
+    my $lintian_opts = undef;
+    my @pre_build_commands;
+    undef @pre_build_commands;
+    my @post_build_commands;
+    undef @post_build_commands;
+    my $log_external_command_output = undef;
+    my $log_external_command_error = undef;
 
     foreach ($Sbuild::Sysconfig::paths{'SBUILD_CONF'}, "$HOME/.sbuildrc") {
 	if (-r $_) {
@@ -545,6 +582,10 @@ sub read_config {
     $self->set('APT_GET', $apt_get);
     $self->set('APT_CACHE', $apt_cache);
     $self->set('DPKG_SOURCE', $dpkg_source);
+    $self->set('DPKG_SOURCE_OPT', $dpkg_source_opt)
+	if ($dpkg_source_opt);
+    $self->set('DPKG_SOURCE_OPT', join(" ", $self->get('DPKG_SOURCE_OPT'),
+	$dpkg_source_opts)) if ($dpkg_source_opts);
     $self->set('DCMD', $dcmd);
     $self->set('MD5SUM', $md5sum);
     $self->set('AVG_TIME_DB', $avg_time_db);
@@ -614,7 +655,21 @@ sub read_config {
 	$self->get('BIN_NMU')) {
 	die "A maintainer name, uploader name or key ID must be specified in .sbuildrc,\nor use -m, -e or -k, when performing a binNMU\n";
     }
-
+    $self->set('LINTIAN', $lintian) if ($lintian);
+    $self->set('RUN_LINTIAN', $run_lintian)
+	if ($run_lintian);
+    $self->set('LINTIAN_OPT', $lintian_opt)
+	if ($lintian_opt);
+    $self->set('LINTIAN_OPT', join(" ", $self->get('LINTIAN_OPT'),
+	$lintian_opts)) if ($lintian_opts);
+    $self->set('PRE_BUILD_COMMANDS', \...@pre_build_commands)
+	if (@pre_build_commands);
+    $self->set('POST_BUILD_COMMANDS', \...@post_build_commands)
+	if (@post_build_commands);
+    $self->set('LOG_EXTERNAL_COMMAND_OUTPUT', $log_external_command_output)
+	if ($log_external_command_output);
+    $self->set('LOG_EXTERNAL_COMMAND_ERROR', $log_external_command_error)
+	if ($log_external_command_error);
 }
 
 sub check_group_membership ($) {
diff --git a/lib/Sbuild/Options.pm b/lib/Sbuild/Options.pm
index 811f946..425a5c3 100644
--- a/lib/Sbuild/Options.pm
+++ b/lib/Sbuild/Options.pm
@@ -135,6 +135,19 @@ sub set_options {
 			   push(@{$self->get_conf('DPKG_BUILDPACKAGE_USER_OPTIONS')},
 				$_[1]);
 		       },
+		       "dpkg-source-opt=s" => sub {
+			    $self->set_conf('DPKG_SOURCE_OPT', $_[1]);
+		       },
+		       "dpkg-source-opts=s" => sub {
+			    my $opt_values;
+			    if ($self->get_conf('DPKG_SOURCE_OPT')) {
+				$opt_values = join(" ",
+				    $self->get_conf('DPKG_SOURCE_OPT'),$_[1]);
+			    } else {
+				$opt_values = $_[1];
+			    }
+			    $self->set_conf('DPKG_SOURCE_OPT', $opt_values);
+		       },
 		       "mail-log-to=s" => sub {
 			   $self->set_conf('MAILTO', $_[1]);
 		       },
@@ -167,7 +180,37 @@ sub set_options {
 			   $self->set_conf('PATH',
 					   '/usr/lib/gcc-snapshot/bin' .
 					   $self->get_conf('PATH') ne '' ? ':' . $self->get_conf('PATH') : '');
-		       }
+		       },
+			"run-lintian" => sub {
+			    $self->set_conf('RUN_LINTIAN', 1);
+		       },
+			"lintian-opt=s" => sub {
+			    $self->set_conf('LINTIAN_OPT', $_[1]);
+		       },
+			"lintian-opts=s" => sub {
+			    my $opt_values;
+			    if ($self->get_conf('LINTIAN_OPT')) {
+				$opt_values = join(" ",
+				    $self->get_conf('LINTIAN_OPT'),$_[1]);
+			    } else {
+				$opt_values = $_[1];
+			    }
+			    $self->set_conf('LINTIAN_OPT', $opt_values);
+		       },
+			"pre-build-commands=s" => sub {
+			    push(@{$self->get_conf('PRE_BUILD_COMMANDS')},
+				$_[1]);
+		       },
+			"post-build-commands=s" => sub {
+			    push(@{$self->get_conf('POST_BUILD_COMMANDS')},
+				$_[1]);
+		       },
+			"log-external-command-output" => sub {
+			    $self->set_conf('LOG_EXTERNAL_COMMAND_OUTPUT', 1);
+		       },
+			"log-external-command-error" => sub {
+			    $self->set_conf('LOG_EXTERNAL_COMMAND_ERROR', 1);
+		       },
 	);
 }
 
diff --git a/lib/Sbuild/Sysconfig.pm.in b/lib/Sbuild/Sysconfig.pm.in
index d78f9ba..32d7b4c 100644
--- a/lib/Sbuild/Sysconfig.pm.in
+++ b/lib/Sbuild/Sysconfig.pm.in
@@ -95,6 +95,7 @@ our %programs = (
     'DPKG_BUILDPACKAGE' => '@DPKG_BUILDPACKAGE@',
     'DPKG_PARSECHANGELOG' => '@DPKG_PARSECHANGELOG@',
     'DPKG_SOURCE' => '@DPKG_SOURCE@',
+    'LINTIAN' => '@LINTIAN@',
     'DU' => '@DU@',
     'FAKEROOT' => '@FAKEROOT@',
     'GPG' => '@GPG@',
-- 
1.6.5

From a55e4961bb3ec57eddf74e578aaf4d5b42a01015 Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:46:41 -0400
Subject: [PATCH 3/6] Implement support for supplying directories as arguments, running lintian, and running pre and post build commands.

---
 lib/Sbuild/Build.pm |  229 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 218 insertions(+), 11 deletions(-)

diff --git a/lib/Sbuild/Build.pm b/lib/Sbuild/Build.pm
index 4469156..f6822c5 100644
--- a/lib/Sbuild/Build.pm
+++ b/lib/Sbuild/Build.pm
@@ -34,6 +34,7 @@ use FileHandle;
 use GDBM_File;
 use File::Copy qw(); # copy is already exported from Sbuild, so don't export
 		     # anything.
+use Cwd qw(:DEFAULT abs_path);
 
 use Sbuild qw($devnull binNMU_version version_compare split_version copy isin send_mail debug df);
 use Sbuild::Base;
@@ -74,7 +75,8 @@ sub new {
     $self->set('Download', 0);
     $self->set('Download', 1)
 	if (!($self->get('DSC Base') =~ m/\.dsc$/) || # Use apt to download
-	    check_url($self->get('DSC'))); # Valid URL
+	    check_url($self->get('DSC')) || # Valid URL
+	    ($self->get('Debian Source Dir'))); # Debianized source directory
 
     # Can sources be obtained?
     $self->set('Invalid Source', 0);
@@ -137,6 +139,36 @@ sub set_dsc {
     my $self = shift;
     my $dsc = shift;
 
+    # Check if argument given is a directory on the local system. This means
+    # we'll be building the source package via dpkg-source first.
+    if (-d $dsc) {
+	my $dpkg_parsechangelog =
+	    $Sbuild::Sysconfig::programs{'DPKG_PARSECHANGELOG'};
+	my $command = "$dpkg_parsechangelog -l$dsc/debian/changelog";
+	my $fh;
+	if (! open $fh, '-|', $command) {
+	    $self->log_error("Could not parse $dsc/debian/changelog: $!");
+	    return 0;
+	}
+	my $stanzas = parse_file($fh);
+	if (! close $fh) {
+	    $self->log_error("Could not close filehandle: $!");
+	    return 0;
+	}
+	my $stanza = @{$stanzas}[0];
+	my $package = ${$stanza}{'Source'};
+	my $version = $self->strip_epoch(${$stanza}{'Version'});
+	my $dir = getcwd();
+	if ($dir eq abs_path($dsc)) {
+	    # We won't attempt to build the source package from the source
+	    # directory so the source package files will go to the parent dir.
+	    $dir = abs_path("$dir/..");
+	    $self->set_conf('BUILD_DIR', $dir);
+	}
+	$self->set('Debian Source Dir', abs_path($dsc));
+	$dsc = "$dir/$package" . "_$version.dsc";
+    }
+
     debug("Setting DSC: $dsc\n");
 
     $self->set('DSC', $dsc);
@@ -208,6 +240,34 @@ sub run {
 	goto cleanup_skip;
     }
 
+    # Acquire the architecture we're building for.
+    $self->set('Arch', $self->get_conf('ARCH'));
+
+    # TODO: Get package name from build object
+    if (!$self->open_build_log()) {
+	goto cleanup_close;
+    }
+
+    # Run pre build external commands
+    $self->run_external_commands("pre-build-commands",
+	$self->get_conf('LOG_EXTERNAL_COMMAND_OUTPUT'),
+	$self->get_conf('LOG_EXTERNAL_COMMAND_ERROR'));
+
+    # Build the source package if given a Debianized source directory
+    if ($self->get('Debian Source Dir')) {
+	$self->log_subsection("Build Source Package");
+	my $dpkg_source = $self->get_conf('DPKG_SOURCE');
+	my $command = "$dpkg_source -b";
+	$command .= " " . $self->get_conf('DPKG_SOURCE_OPT')
+	    if ($self->get_conf('DPKG_SOURCE_OPT'));
+	$command .= " " . $self->get('Debian Source Dir');
+	$self->log_subsubsection("$command");
+	my $curdir = getcwd(); # In case we're inside the source dir
+	chdir($self->get_conf('BUILD_DIR'));
+	$self->run_command($command, 1, 1);
+	chdir($curdir);
+    }
+
     my $chroot_info;
     if ($self->get_conf('CHROOT_MODE') eq 'schroot') {
 	$chroot_info = Sbuild::ChrootInfoSchroot->new($self->get('Config'));
@@ -227,7 +287,6 @@ sub run {
     }
 
     $self->set('Session', $session);
-    $self->set('Arch', $self->chroot_arch());
 
     $self->set('Chroot Dir', $session->get('Location'));
     $self->set('Chroot Build Dir',
@@ -239,11 +298,6 @@ sub run {
     # the chroot directly.
     $session->set('Build Location', $self->get('Chroot Build Dir'));
 
-    # TODO: Get package name from build object
-    if (!$self->open_build_log()) {
-	goto cleanup_close;
-    }
-
     # Needed so chroot commands log to build log
     $session->set('Log Stream', $self->get('Log Stream'));
 
@@ -320,12 +374,40 @@ sub run {
 	    $self->log("Not removing build depends: as requested\n");
 	}
     }
+
     $self->remove_srcdep_lock_file();
   cleanup_close:
     $session->end_session();
     $session = undef;
     $self->set('Session', $session);
 
+    if ($self->get('Pkg Status') eq "successful") {
+	$self->log_subsection("Post Build");
+
+	# Run lintian.
+	my $lintian = $self->get_conf('LINTIAN');
+	if (($self->get_conf('RUN_LINTIAN')) && (-x $lintian)) {
+	    my $command = "$lintian";
+	    $command .= " " . $self->get_conf('LINTIAN_OPT')
+		if ($self->get_conf('LINTIAN_OPT'));
+	    $command .= " " . $self->get('Changes File');
+	    $self->log_subsubsection("$command");
+	    my $return = $self->run_command($command, 1, 1);
+	    $self->log("\n");
+	    if (!$return) {
+		$self->log_error("Lintian failed to run.\n");
+	    } else {
+		$self->log_info("Lintian run was successful.\n");
+	    }
+	}
+
+	# Run post build external commands
+	$self->run_external_commands("post-build-commands",
+	    $self->get_conf('LOG_EXTERNAL_COMMAND_OUTPUT'),
+	    $self->get_conf('LOG_EXTERNAL_COMMAND_ERROR'));
+
+    }
+
     $self->close_build_log();
 
   cleanup_skip:
@@ -607,6 +689,120 @@ sub fetch_source_files {
     return 1;
 }
 
+# Subroutine that runs any command through the system (i.e. not through the
+# chroot. It takes a string of a command with arguments to run along with
+# arguments whether to save STDOUT and/or STDERR to the log stream
+sub run_command {
+    my $self = shift;
+    my $command = shift;
+    my $log_output = shift;
+    my $log_error = shift;
+
+    # Duplicate output from our commands to the log stream if we are asked to
+    my ($out, $err);
+    if ($log_output) {
+	if (! open $out, ">&STDOUT") {
+	    $self->log_error("Could not duplicate STDOUT for $command: $!");
+	    return 0;
+	}
+	if (! open STDOUT, '>&', $self->get('Log Stream')) {
+	    $self->log_error("Could not duplicate STDOUT to log stream: $!");
+	    return 0;
+	}
+    }
+    if ($log_error) {
+	if (! open $err, ">&STDERR") {
+	    $self->log_error("Could not duplicate STDERR for $command: $!");
+	    return 0;
+	}
+	if (! open STDERR, '>&', $self->get('Log Stream')) {
+	    $self->log_error("Could not duplicate STDERR to log stream: $!");
+	    return 0;
+	}
+    }
+
+    # Run the command and save the exit status
+    my @args = split(/\s+/, $command);
+    system(@args);
+    my $status = ($? >> 8);
+
+    # Restore STDOUT and STDERR
+    if ($log_output) {
+	if (! open STDOUT, '>&', $out) {
+	    $self->log_error("Can't restore STDOUT: $!");
+	    return 0;
+	}
+	$out->close();
+    }
+    if ($log_error) {
+	if (! open STDERR, '>&', $err) {
+	    $self->log_error("Can't restore STDOUT: $!");
+	    return 0;
+	}
+	$err->close();
+    }
+
+    # Check if the command failed
+    if ($status != 0) {
+	return 0;
+    }
+    return 1;
+}
+
+# Subroutine that processes external commands to be run during various stages of
+# an sbuild run. We also ask if we want to log any output from the commands
+sub run_external_commands {
+    my $self = shift;
+    my $stage = shift;
+    my $log_output = shift;
+    my $log_error = shift;
+
+    # Determine which set of commands to run based on the string $commands
+    my @commands;
+    if ($stage eq "pre-build-commands") {
+	$self->log_subsection("Pre Build Commands");
+	@commands = @{$self->get_conf('PRE_BUILD_COMMANDS')};
+    } elsif ($stage eq "post-build-commands") {
+	$self->log_subsection("Post Build Commands");
+	@commands = @{$self->get_conf('POST_BUILD_COMMANDS')};
+    }
+
+    # 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;
+    $changes = $self->get('Changes File') if ($self->get('Changes File'));
+    my %percent = (
+	"%" => "%",
+	"d" => $dsc, "SBUILD_DSC" => $dsc,
+	"c" => $changes, "SBUILD_CHANGES" => $changes,
+    );
+    # Our escapes pattern, with longer escapes first, then sorted lexically.
+    my $keyword_pat = join("|",
+	sort {length $b <=> length $a || $a cmp $b} keys %percent);
+    my $returnval = 1;
+    foreach my $command (@commands) {
+	$command =~ s{
+	    # Match a percent followed by a valid keyword
+	    \%($keyword_pat)
+	}{
+	    # Substitute with the appropriate value only if it's defined
+	    $percent{$1} || $&
+	}msxge;
+	$self->log_subsubsection("$command");
+	$returnval = $self->run_command($command, $log_output, $log_error);
+	$self->log("\n");
+	if (!$returnval) {
+	    $self->log_error("Command '$command' failed to run.\n");
+	} else {
+	    $self->log_info("Finished running '$command'.\n");
+	}
+    }
+    $self->log("\nFinished processing commands.\n");
+    $self->log_sep();
+    return $returnval;
+}
+
 sub build {
     my $self = shift;
 
@@ -934,7 +1130,8 @@ sub build {
 	    my(@do_dists, @saved_dists);
 	    $self->log("\n$changes:\n");
 	    open( F, "<$build_dir/$changes" );
-	    if (open( F2, ">$changes.new" )) {
+	    my $sys_build_dir = $self->get_conf('BUILD_DIR');
+	    if (open( F2, ">$sys_build_dir/$changes.new" )) {
 		while( <F> ) {
 		    if (/^Distribution:\s*(.*)\s*$/ and $self->get_conf('OVERRIDE_DISTRIBUTION')) {
 			$self->log("Distribution: " . $self->get_conf('DISTRIBUTION') . "\n");
@@ -955,13 +1152,15 @@ sub build {
 		    }
 		}
 		close( F2 );
-		rename("$changes.new", "$changes")
-		    or $self->log("$changes.new could not be renamed to $changes: $!\n");
+		rename("$sys_build_dir/$changes.new", "$sys_build_dir/$changes")
+		    or $self->log("$sys_build_dir/$changes.new could not be " .
+		    "renamed to $sys_build_dir/$changes: $!\n");
+		$self->set('Changes File', "$sys_build_dir/$changes");
 		unlink("$build_dir/$changes")
 		    if $build_dir;
 	    }
 	    else {
-		$self->log("Cannot create $changes.new: $!\n");
+		$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", "."
@@ -2515,6 +2714,14 @@ sub dsc_files {
     return @files;
 }
 
+# This subroutine strips the epoch from a Debian package version.
+sub strip_epoch {
+    my $self = shift;
+    my $version = shift;
+    $version =~ s/^\d+?://;
+    return $version;
+}
+
 # Figure out chroot architecture
 sub chroot_arch {
     my $self = shift;
-- 
1.6.5

From eec5ca3d3a2005c5505baad54e4e2d00ceced37b Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:48:18 -0400
Subject: [PATCH 4/6] Have sbuild process current directory if no arguments are supplied.
 Also fix some issue where $_ is changed somewhere in the library code.

---
 bin/sbuild |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/bin/sbuild b/bin/sbuild
index ae7bf14..0052245 100755
--- a/bin/sbuild
+++ b/bin/sbuild
@@ -78,10 +78,13 @@ sub main () {
     $SIG{'ALRM'} = \&main::shutdown;
     $SIG{'PIPE'} = \&main::shutdown;
 
+    # If no arguments are supplied, assume we want to process the current dir.
+    push @ARGV, '.' unless (@ARGV);
+
     # Create jobs
-    foreach (@ARGV) {
-	$jobs{$_} = Sbuild::Build->new($_, $conf);
-	$jobs{$_}->set('Pkg Status Trigger', \&status_trigger)
+    foreach my $job (@ARGV) {
+	$jobs{$job} = Sbuild::Build->new($job, $conf);
+	$jobs{$job}->set('Pkg Status Trigger', \&status_trigger)
     }
     write_jobs_file(); # Will now update on trigger.
 
-- 
1.6.5

From 823498e8414773071ff6432b729f04c19364e8ea Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:49:47 -0400
Subject: [PATCH 5/6] Update sbuild man page for new features.

---
 man/sbuild.1.in |  118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 117 insertions(+), 1 deletions(-)

diff --git a/man/sbuild.1.in b/man/sbuild.1.in
index 2ce6394..53d63aa 100644
--- a/man/sbuild.1.in
+++ b/man/sbuild.1.in
@@ -41,12 +41,21 @@ sbuild \- build debian packages from source
 .RB [ \-k \[or] \-\-keyid=\fIkey-id\fP ]
 .RB [ \-\-debbuildopt=\fIoption\fP ]
 .RB [ \-\-debbuildopts=\fIoptions\fP ]
+.RB [ \-\-dpkg-source-opt=\fIoptions\fP ]
+.RB [ \-\-dpkg-source-opts=\fIoptions\fP ]
 .RB [ \-p \[or] \-\-purge=\fPpurge-mode\fP ]
 .RB [ \-\-purge\-deps=\fPpurge-mode\fP ]
 .RB [ \-b \[or] \-\-batch]
 .RB [ \-n \[or] \-\-nolog ]
+.RB [ \-\-run\-lintian ]
+.RB [ \-\-lintian\-opt=\fIoptions\fP ]
+.RB [ \-\-lintian\-opts=\fIoptions\fP ]
+.RB [ \-\-pre\-build\-commands=\fIstring\fP ]
+.RB [ \-\-post\-build\-commands=\fIstring\fP ]
+.RB [ \-\-log\-external\-command\-output ]
+.RB [ \-\-log\-external\-command\-error ]
 .RB [ \-\-setup\-hook=\fIhook-script\fP ]
-.BR PACKAGE1_VERSION[.dsc] " [" PACKAGE2_VERSION[.dsc] " [" PACKAGE\f[BI]n\fP_VERSION[.dsc] ]]
+.BR [PACKAGE1[.dsc] " [" PACKAGE2[.dsc] " [ " ... " " ]]]
 .SH VERSION
 This man page documents the packaged version of sbuild.  This version
 is maintained by the \fBbuildd-tools\fP project developers on Alioth
@@ -64,6 +73,22 @@ them, it knows about source dependencies.
 \fBsbuild\fR can fetch the Debian source over a network, or it can use
 locally available sources.
 .PP
+sbuild is given a list of packages to process as the arguments
+\fBPACKAGE\f[BI]i\fP[.dsc]\fR. These arguments are in the form of either
+debianized package source directories, 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.
+.PP
+It is also possible to run external commands with sbuild. See the section
+\fBEXTERNAL COMMANDS\fR for more on this.
+.PP
 \fBsbuild\fR mails the build logs to a user.  It is configured by the
 configuration files \fI/etc/sbuild/sbuild.conf\fP and \fI~/.sbuildrc\fP.  An
 example sbuildrc is available in
@@ -167,6 +192,15 @@ 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.
+.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.
+.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.
@@ -222,11 +256,93 @@ 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).
 .TP
+.BR \-\-run\-lintian
+Run lintian after a successful build.
+.TP
+.BR \-\-lintian\-opt=\fIoptions\fP
+Run lintian with the specified options.
+.TP
+.BR \-\-lintian\-opts=\fIoptions\fP
+Append extra options to existing options passed to lintian.
+.TP
+.BR \-\-pre\-build\-commands=\fIstring\fP
+Run this command before a build starts. This option can be used multiple times
+to add multiple commands.
+.TP
+.BR \-\-post\-build\-commands=\fIstring\fP
+Run this command after a successful build. This option can be used multiple
+times to add multiple commands.
+.TP
+.BR \-\-log\-external\-command\-output
+Write output from external commands to the build log.
+.TP
+.BR \-\-log\-external\-command\-error
+Write error output from external commands to the build log.
+.TP
 .BR "\-\-setup\-hook=\fIhook-script\fP"
 Run the specified script inside the chroot before building.  This script may
 perform any required actions to customise or configure the chroot.  Note that
 the script will be run inside the chroot, and so the script must exist inside
 the chroot rather than the host system.
+.SH EXTERNAL COMMANDS
+Support to run external commands during an sbuild run is provided. A set of
+external commands can be run before a build starts and after a successful build.
+Providing commands to run is done through the appropriate options given on the
+command line and through the use of the configuration files. In the
+configuration file, the list of commands to run are placed in an array of
+strings corresponding to the commands to run.
+.PP
+Here's an example of how to edit the configuration files to run "foo" and "bar"
+with arguments before a build starts.
+.PP
+\f[...@pre_build_commands = ('foo arg1 arg2',\fP
+.br
+\f[CB]    'bar arg1 arg2 arg3',\fP
+.br
+\f[CB]    );\fP
+.PP
+Here's an example of how to do the same with the previous example, except using
+the \fI\-\-pre\-build\-commands\fP option.
+.PP
+\f[CB]$ sbuild \\\fP
+.br
+\f[CB]      \-\-pre\-build\-commands='foo arg1 arg2' \\\fP
+.br
+\f[CB]      \-\-pre\-build\-commands=''bar arg1 arg2 arg3'\fP
+.PP
+Besides running external commands, sbuild can also detect the use of certain
+percent escapes given as arguments. These are used to allow for a command to be
+supplied with a certain argument depending on the escape given.
+For example, it could be possible to have an external command be given the
+path to a .changes file.
+.PP
+Here is a listing of keywords and a description of what it's converted to.
+.TP
+\fB%%\fR
+Used to escape a '\fI%\fP'.
+.TP
+\fB%d\fR, \fB%SBUILD_DSC\fR
+These escapes are converted to the absolute path to a package's .dsc file.
+.TP
+\fB%c\fR, \fB%SBUILD_CHANGES\fR
+These escapes are converted to the absolute path to a package's source .changes
+file.
+.PP
+Percent escapes are only substituted when an appropriate value is defined for
+them. At other times, it is left unchanged. 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 piuparts on a .changes file after
+a build is done.
+.PP
+\f[CB]$ sbuild \-\-post\-build\-commands \\\fP
+.br
+\f[CB]      'sudo piuparts %SBUILD_CHANGES'\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
+commands given through the command line options.
 .SH ENVIRONMENT VARIABLES
 The following environment variables are used by \fBsbuild\fR:
 .IP "DEBEMAIL"
-- 
1.6.5

From ed0221afb373ed621c6e2b3a0af8f9d49285aac8 Mon Sep 17 00:00:00 2001
From: Andres Mejia <mcita...@gmail.com>
Date: Fri, 23 Oct 2009 18:50:21 -0400
Subject: [PATCH 6/6] Update build system and Debian packaging.

---
 configure.ac |    1 +
 debian/rules |    3 ++-
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index f65c9cd..de0251d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,7 @@ AC_PATH_PROG([DPKG_ARCHITECTURE], [dpkg-architecture])
 AC_PATH_PROG([DPKG_BUILDPACKAGE], [dpkg-buildpackage])
 AC_PATH_PROG([DPKG_PARSECHANGELOG], [dpkg-parsechangelog])
 AC_PATH_PROG([DPKG_SOURCE], [dpkg-source])
+AC_PATH_PROG([LINTIAN], [lintian])
 AC_PATH_PROG([DU], [du])
 AC_PATH_PROG([FAKEROOT], [fakeroot])
 AC_PATH_PROG([FIND], [find])
diff --git a/debian/rules b/debian/rules
index 365469c..a62ca2f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -16,7 +16,8 @@ debian/build/config.status: configure
 	  DCMD=/usr/bin/dcmd \
 	  SCHROOT=/usr/bin/schroot \
 	  SSH=/usr/bin/ssh \
-	  SUDO=/usr/bin/sudo
+	  SUDO=/usr/bin/sudo \
+	  LINTIAN=/usr/bin/lintian
 
 build: debian/build/config.status debian/build-stamp
 debian/build-stamp:  debian/build/config.status
-- 
1.6.5

Reply via email to