summaryrefslogtreecommitdiffstats
path: root/bin/sbuild-debuild
diff options
context:
space:
mode:
Diffstat (limited to 'bin/sbuild-debuild')
-rw-r--r--bin/sbuild-debuild391
1 files changed, 391 insertions, 0 deletions
diff --git a/bin/sbuild-debuild b/bin/sbuild-debuild
new file mode 100644
index 0000000..ca15a77
--- /dev/null
+++ b/bin/sbuild-debuild
@@ -0,0 +1,391 @@
+#!/usr/bin/perl -w
+#
+# Copyright © 2005-2009 Roger Leigh <rleigh@debian.org>
+# Copyright © 2009 Andres Mejia <mcitadel@gmail.com>
+#
+# 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/>.
+#
+#######################################################################
+
+use strict;
+use warnings;
+
+package Conf;
+
+sub setup {
+ my $conf = shift;
+
+ my %update_keys = (
+ 'DPKG_BUILDPACKAGE_OPTS' => {
+ DEFAULT => ['-S',
+ '-us',
+ '-uc',
+ ]
+ },
+ 'DPKG_BUILDPACKAGE_EXTRA_OPTS' => {
+ DEFAULT => []
+ },
+ 'SBUILD_OPTS' => {
+ DEFAULT => []
+ },
+ 'SBUILD_EXTRA_OPTS' => {
+ DEFAULT => []
+ },
+ 'LINTIAN_OPTS' => {
+ DEFAULT => []
+ },
+ 'LINTIAN_EXTRA_OPTS' => {
+ DEFAULT => []
+ },
+ 'NO_LINTIAN' => {
+ DEFAULT => 0
+ },
+ 'PRE_DPKG_BUILDPACKAGE_COMMANDS' => {
+ DEFAULT => []
+ },
+ 'PRE_SBUILD_COMMANDS' => {
+ DEFAULT => []
+ },
+ 'PRE_LINTIAN_COMMANDS' => {
+ DEFAULT => []
+ },
+ 'PRE_EXIT_COMMANDS' => {
+ DEFAULT => []
+ },
+ );
+
+ $conf->set_allowed_keys(\%update_keys);
+}
+
+# This subroutine is used to read a different set of config files for
+# sbuild-debuild
+sub read_sbuild_debuild_config {
+ my $self = shift;
+
+ # Our HOME environment variable.
+ my $HOME = $self->get('HOME');
+
+ # Variables are undefined, so config will default to DEFAULT if unset.
+ my $dpkg_buildpackage_opts = undef;
+ my $dpkg_buildpackage_extra_opts = undef;
+ my $sbuild_opts = undef;
+ my $sbuild_extra_opts = undef;
+ my $lintian_opts = undef;
+ my $lintian_extra_opts = undef;
+ my $no_lintian = undef;
+ my $pre_dpkg_buildpackage_commands = undef;
+ my $pre_sbuild_commands = undef;
+ my $pre_lintian_commands = undef;
+ my $pre_exit_commands = undef;
+
+ foreach ("/etc/sbuild/sbuild-debuild.conf", "$HOME/.sbuild-debuildrc") {
+ if (-r $_) {
+ my $e = eval `cat "$_"`;
+ if (!defined($e)) {
+ print STDERR "E: $_: Errors found in configuration file:\n$@";
+ exit(1);
+ }
+ }
+ }
+
+ $self->set('DPKG_BUILDPACKAGE_OPTS', $dpkg_buildpackage_opts)
+ if ($dpkg_buildpackage_opts);
+ push(@{$self->get('DPKG_BUILDPACKAGE_OPTS')},
+ @{$dpkg_buildpackage_extra_opts}) if ($dpkg_buildpackage_extra_opts);
+ $self->set('SBUILD_OPTS', $sbuild_opts)
+ if ($sbuild_opts);
+ push(@{$self->get('SBUILD_OPTS')}, @{$sbuild_extra_opts})
+ if ($sbuild_extra_opts);
+ $self->set('LINTIAN_OPTS', $lintian_opts)
+ if ($lintian_opts);
+ push(@{$self->get('LINTIAN_OPTS')}, @{$lintian_extra_opts})
+ if ($lintian_extra_opts);
+ $self->set('NO_LINTIAN', $no_lintian)
+ if ($no_lintian);
+ $self->set('PRE_DPKG_BUILDPACKAGE_COMMANDS',
+ $pre_dpkg_buildpackage_commands) if ($pre_dpkg_buildpackage_commands);
+ $self->set('PRE_SBUILD_COMMANDS', $pre_sbuild_commands)
+ if ($pre_sbuild_commands);
+ $self->set('PRE_LINTIAN_COMMANDS', $pre_lintian_commands)
+ if ($pre_lintian_commands);
+ $self->set('PRE_EXIT_COMMANDS', $pre_exit_commands)
+ if ($pre_exit_commands);
+}
+
+package Options;
+
+use Sbuild::OptionsBase;
+use Sbuild::Conf;
+
+BEGIN {
+ use Exporter ();
+ our (@ISA, @EXPORT);
+
+ @ISA = qw(Exporter Sbuild::OptionsBase);
+
+ @EXPORT = qw();
+}
+
+sub set_options {
+ my $self = shift;
+
+ $self->add_options(
+ "dpkg-buildpackage-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ $self->set_conf('DPKG_BUILDPACKAGE_OPTS', \@opt_values);
+ },
+ "dpkg-buildpackage-extra-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ push(@{$self->get_conf('DPKG_BUILDPACKAGE_OPTS')},
+ @opt_values);
+ },
+ "sbuild-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ $self->set_conf('SBUILD_OPTS', \@opt_values);
+ },
+ "sbuild-extra-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ push(@{$self->get_conf('SBUILD_OPTS')},
+ @opt_values);
+ },
+ "lintian-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ $self->set_conf('LINTIAN_OPTS', \@opt_values);
+ },
+ "lintian-extra-opts=s" => sub {
+ my @opt_values = split(/\s+/,$_[1]);
+ push(@{$self->get_conf('LINTIAN_OPTS')},
+ @opt_values);
+ },
+ "no-lintian" => sub {
+ $self->set_conf('NO_LINTIAN', 1);
+ },
+ "pre-dpkg-buildpackage-commands=s" => sub {
+ push(@{$self->get_conf('PRE_DPKG_BUILDPACKAGE_COMMANDS')}, $_[1]);
+ },
+ "pre-sbuild-commands=s" => sub {
+ push(@{$self->get_conf('PRE_SBUILD_COMMANDS')}, $_[1]);
+ },
+ "pre-lintian-commands=s" => sub {
+ push(@{$self->get_conf('PRE_LINTIAN_COMMANDS')}, $_[1]);
+ },
+ "pre-exit-commands=s" => sub {
+ push(@{$self->get_conf('PRE_EXIT_COMMANDS')}, $_[1]);
+ },
+ );
+}
+
+package main;
+
+use Getopt::Long;
+use Cwd;
+use File::Basename;
+use Sbuild qw(help_text version_text usage_error check_group_membership);
+
+my $conf = Sbuild::Conf::new();
+Conf::setup($conf);
+exit 1 if !defined($conf);
+$conf->read_sbuild_debuild_config();
+my $options = Options->new($conf, "sbuild-debuild", "1");
+exit 1 if !defined($options);
+check_group_membership();
+
+# This subroutine determines the architecture we're building for.
+sub detect_arch {
+ # Detect if we're building for another architecture
+ my @values = grep {/--arch=.+/} @{$conf->get('SBUILD_OPTS')};
+ my $arch_opt = $values[0];
+ $arch_opt =~ s/--arch=// if ($arch_opt);
+
+ # Determine the arch using dpkg-architecture
+ my $dpkg_arch_command = '/usr/bin/dpkg-architecture -qDEB_HOST_ARCH';
+ $dpkg_arch_command .= " -a$arch_opt" if ($arch_opt);
+
+ # Grab the architecture and return it. We discard output from STDERR
+ # to suppress the "Specified GNU system ... does not match" warning that
+ # may occur from dpkg-architecture
+ my $arch = qx($dpkg_arch_command 2>/dev/null);
+ chomp $arch;
+ return $arch;
+}
+
+# This subroutine determines the package and version we're building for
+sub detect_package_and_version {
+ my ($build_input) = @_;
+
+ # chdir into package directories, but not dsc files
+ chdir($build_input) unless ($build_input =~ /.*\.dsc$/);
+
+ my $output;
+ if ($build_input =~ m/.*\.dsc$/) {
+ # Read the dsc file directly.
+ open($output, '<', $build_input);
+ } else {
+ # Grab the output from dpkg-parsechangelog
+ my $dpkg_parsechangelog = '/usr/bin/dpkg-parsechangelog';
+ open($output, '-|', $dpkg_parsechangelog);
+ }
+
+ # Grab the package and version info
+ my ($package, $version);
+ while (<$output>) {
+ $package = $1 if ($_ =~ /^Source: (.*)$/);
+ $version = $1 if ($_ =~ /^Version: (.*)$/);
+ last if (($package) and ($version));
+ }
+ return ($package, $version);
+}
+
+# This subroutine strips the epoch from a Debian package version.
+sub strip_epoch {
+ my ($version) = @_;
+ $version =~ s/^[^:]*?://;
+ return $version;
+}
+
+# This subroutine processes the array external ommands to run at the various
+# stages of sbuild-debuild's run
+sub process_commands {
+ my ($commands, $dsc, $source_changes, $bin_changes) = @_;
+
+ # Determine which set of commands to run based on the string $commands
+ my @commands;
+ if ($commands eq "pre_dpkg_buildpackage_commands") {
+ @commands = @{$conf->get('PRE_DPKG_BUILDPACKAGE_COMMANDS')};
+ } elsif ($commands eq "pre_sbuild_commands") {
+ @commands = @{$conf->get('PRE_SBUILD_COMMANDS')};
+ } elsif ($commands eq "pre_lintian_commands") {
+ @commands = @{$conf->get('PRE_LINTIAN_COMMANDS')};
+ } elsif ($commands eq "pre_exit_commands") {
+ @commands = @{$conf->get('PRE_EXIT_COMMANDS')};
+ }
+
+ # Run each command, substituting the various @SBUILD_DEBUILD_*@ options from
+ # the commands to run with the appropriate subsitutions.
+ my $returnval = 1;
+ foreach my $command (@commands) {
+ $command =~ s/\@SBUILD_DEBUILD_DSC@/$dsc/;
+ $command =~ s/\@SBUILD_DEBUILD_SOURCE_CHANGES@/$source_changes/;
+ $command =~ s/\@SBUILD_DEBUILD_BIN_CHANGES@/$bin_changes/;
+ my @args = split(/\s+/, $command);
+ print "Running $command\n";
+ system(@args);
+ if (($? >> 8) != 0) {
+ print "Failed to run command ($command): $?";
+ $returnval = 0;
+ }
+ }
+ return $returnval;
+}
+
+# Subroutine to determine various files we'll be working with.
+sub detect_files {
+ my ($build_input) = @_;
+
+ # Determine the dsc and changes files that we'll use
+ my ($package, $version) = detect_package_and_version($build_input);
+ $version = strip_epoch($version);
+ my $arch = detect_arch();
+ my ($dsc, $dirname);
+ if ($build_input =~ /.*\.dsc$/) {
+ $dsc = Cwd::abs_path("$build_input");
+ $dirname = Cwd::abs_path(dirname($build_input));
+ } else {
+ $dirname = Cwd::abs_path("$build_input/..");
+ $dsc = "$dirname/" . $package . "_" . "$version.dsc";
+ }
+ my $source_changes = "$dirname/" . $package . "_$version" .
+ "_source.changes";
+ my $bin_changes = "$dirname/" . $package . "_$version" . "_$arch.changes";
+
+ return ($dsc, $source_changes, $bin_changes);
+}
+
+# Process a debianized package directory or .dsc file.
+sub process_package {
+ my ($build_input) = @_;
+
+ # We use this to determine if there was a problem processing the external
+ # commands.
+ my $returnval = 1;
+
+ # Save the current directory we're in.
+ my $currentdir = getcwd();
+
+ # Determine the dsc and changes files that we'll use
+ my ($dsc, $source_changes, $bin_changes) = detect_files($build_input);
+
+ print "Processing pre dpkg-buildpackage commands.\n";
+ $returnval = 0 unless process_commands("pre_dpkg_buildpackage_commands",
+ $dsc, $source_changes, $bin_changes);
+
+ if ($build_input !~ /.*\.dsc$/) {
+ chdir($build_input);
+ print "Running dpkg-buildpackage.\n";
+ system('/usr/bin/dpkg-buildpackage',
+ @{$conf->get('DPKG_BUILDPACKAGE_OPTS')});
+ if (($? >> 8) != 0) {
+ print "Running dpkg-buildpckage failed: $?";
+ chdir($currentdir);
+ return 0;
+ }
+ }
+
+ print "Processing pre sbuild commands.\n";
+ $returnval = 0 unless process_commands("pre_sbuild_commands", $dsc,
+ $source_changes, $bin_changes);
+
+ chdir(dirname($dsc));
+ print "Running sbuild.\n";
+ system('/usr/bin/sbuild', @{$conf->get('SBUILD_OPTS')}, $dsc);
+ if (($? >> 8) != 0) {
+ print "Running sbuild failed: $?";
+ chdir($currentdir);
+ return 0;
+ }
+
+ print "Processing pre lintian commands.\n";
+ $returnval = 0 unless process_commands("pre_lintian_commands", $dsc,
+ $source_changes, $bin_changes);
+
+ if ((!$conf->get('NO_LINTIAN')) && (-x '/usr/bin/lintian')) {
+ print "Running lintian.\n";
+ system('/usr/bin/lintian', @{$conf->get('LINTIAN_OPTS')}, '--', $bin_changes);
+ if (($? >> 8) != 0) {
+ print "Running lintian failed: $?";
+ chdir($currentdir);
+ return 0;
+ }
+ }
+
+ print "Processing commands run before exiting.\n";
+ $returnval = 0 unless process_commands("pre_exit_commands", $dsc,
+ $source_changes, $bin_changes);
+
+ # Go back to the directory we were in earlier
+ chdir($currentdir);
+ return $returnval;
+}
+
+# Process each package directory and .dsc file.
+my $status = 0;
+if (!@ARGV) {
+ $status = 1 unless process_package(getcwd());
+} else {
+ foreach my $arg (@ARGV) {
+ $status = 1 unless process_package($arg);
+ }
+}
+exit $status;