Package: dpkg-dev
Version: 1.16.3
Severity: wishlist
Tags: patch
User: [email protected]
Usertags: dpkg-buildpackage

The attached patch adds option to build package multiple times in a row. This is useful for testing correctness of the clean target.

The patch looks noisy, because I had to indent a few dozen of lines; but other than that, it adds just a few lines.

If case you wonder why can't I just call dpkg-buildpackage in a loop: I can't if run it through a wrapper like sbuild or $VCS-buildpackage.

--
Jakub Wilk
diff --git a/man/dpkg-buildpackage.1 b/man/dpkg-buildpackage.1
--- a/man/dpkg-buildpackage.1
+++ b/man/dpkg-buildpackage.1
@@ -68,6 +68,9 @@
 .IP \fB9.\fP 3
 If \fB\-tc\fP is specified, it will call \fBfakeroot debian/rules clean\fP
 again. Finally it calls \fBdpkg\-source \-\-after\-build\fP.
+.P
+If \fB\-l\fP\fIN\fP is specified, steps 1-9 are repeated \fIN\fP times, with
+the exception that steps 6 and 8 are only executed in the last iteration.
 .
 .SH OPTIONS
 .TP
@@ -90,6 +93,10 @@
 .B \-F
 Specifies a normal full build, binary and source packages will be built.
 This is the same as the default case when no build option is specified.
+.TP
+.BI \-l N
+Build the package \fIN\fP times in a row.  This is useful for testing the
+clean target.
 .P
 .BI \-\-target= target
 .br
diff --git a/scripts/dpkg-buildpackage.pl b/scripts/dpkg-buildpackage.pl
--- a/scripts/dpkg-buildpackage.pl
+++ b/scripts/dpkg-buildpackage.pl
@@ -73,6 +73,7 @@
   -A             binary-only, only arch-indep files. }
   -S             source only, no binary files.     }
   -F             normal full build (binaries and sources).
+  -l<n>          build <n> times in a row
   -t<system>     set GNU system type.           } passed to dpkg-architecture
   -v<version>    changes since version <version>.      }
   -m<maint>      maintainer for package is <maint>.    }
@@ -123,6 +124,7 @@
 my $targetarch = my $targetgnusystem = '';
 my $call_target = '';
 my $call_target_as_root = 0;
+my $nloops = 1;
 my (@checkbuilddep_opts, @changes_opts, @source_opts);
 
 use constant BUILD_DEFAULT    => 1;
@@ -229,6 +231,8 @@
 	!build_normal && usageerr(_g("cannot combine %s and %s"), $_, build_opt);
 	$include = BUILD_ALL;
 	@checkbuilddep_opts = ();
+    } elsif (/^-l(\d+)$/) {
+	$nloops = int($1);
     } elsif (/^-v(.*)$/) {
 	$since = $1;
     } elsif (/^-m(.*)$/) {
@@ -352,162 +356,172 @@
     chmod(0755, "debian/rules"); # No checks of failures, non fatal
 }
 
-unless ($call_target) {
+for my $iter (1 .. $nloops) {
+
+    unless ($call_target) {
+	chdir('..') or syserr('chdir ..');
+	withecho('dpkg-source', @source_opts, '--before-build', $dir);
+	chdir($dir) or syserr("chdir $dir");
+    }
+
+    if ($checkbuilddep) {
+	if ($admindir) {
+	    push @checkbuilddep_opts, "--admindir=$admindir";
+	}
+
+	system('dpkg-checkbuilddeps', @checkbuilddep_opts);
+	if (not WIFEXITED($?)) {
+	    subprocerr('dpkg-checkbuilddeps');
+	} elsif (WEXITSTATUS($?)) {
+	    warning(_g("Build dependencies/conflicts unsatisfied; aborting."));
+	    warning(_g("(Use -d flag to override.)"));
+
+	    if (build_sourceonly) {
+		warning(_g("This is currently a non-fatal warning with -S, but"));
+		warning(_g("will probably become fatal in the future."));
+	    } else {
+		exit 3;
+	    }
+	}
+    }
+
+    if ($call_target) {
+	if ($call_target_as_root or
+	    $call_target =~ /^(clean|binary(|-arch|-indep))$/)
+	{
+	    withecho(@rootcommand, @debian_rules, $call_target);
+	} else {
+	    withecho(@debian_rules, $call_target);
+	}
+	exit 0;
+    }
+
+    unless ($noclean) {
+	withecho(@rootcommand, @debian_rules, 'clean');
+    }
+    unless (build_binaryonly) {
+	warning(_g("it is a bad idea to generate a source package " .
+		   "without cleaning up first, it might contain undesired " .
+		   "files.")) if $noclean;
+	chdir('..') or syserr('chdir ..');
+	withecho('dpkg-source', @source_opts, '-b', $dir);
+	chdir($dir) or syserr("chdir $dir");
+    }
+
+    unless ($buildtarget eq "build" or scalar(@debian_rules) > 1) {
+	# Verify that build-{arch,indep} are supported. If not, fallback to build.
+	# This is a temporary measure to not break too many packages on a flag day.
+	my $pid = spawn(exec => [ "make", "-f", @debian_rules, "-qn", $buildtarget ],
+			from_file => "/dev/null", to_file => "/dev/null",
+			error_to_file => "/dev/null");
+	my $cmdline = "make -f @debian_rules -qn $buildtarget";
+	wait_child($pid, nocheck => 1, cmdline => $cmdline);
+	my $exitcode = WEXITSTATUS($?);
+	subprocerr($cmdline) unless WIFEXITED($?);
+	if ($exitcode == 2) {
+	    warning(_g("%s must be updated to support the 'build-arch' and " .
+		       "'build-indep' targets (at least '%s' seems to be " .
+		       "missing)"), "@debian_rules", $buildtarget);
+	    $buildtarget = "build";
+	}
+    }
+
+    unless (build_sourceonly) {
+	withecho(@debian_rules, $buildtarget);
+	withecho(@rootcommand, @debian_rules, $binarytarget);
+    }
+
+    my $signerrors;
+    if ($iter == $nloops) {
+	if ($usepause &&
+	    ($signchanges || (!build_binaryonly && $signsource))) {
+	    print _g("Press the return key to start signing process\n");
+	    getc();
+	}
+
+	unless (build_binaryonly) {
+	    if ($signsource && signfile("$pv.dsc")) {
+		$signerrors = _g("Failed to sign .dsc and .changes file");
+		$signchanges = 0;
+	    }
+	}
+    }
+
+    if (defined($maint)) { push @changes_opts, "-m$maint" }
+    if (defined($changedby)) { push @changes_opts, "-e$changedby" }
+    if (defined($since)) { push @changes_opts, "-v$since" }
+    if (defined($desc)) { push @changes_opts, "-C$desc" }
+
+    my $chg = "../$pva.changes";
+    print STDERR " dpkg-genchanges @changes_opts >$chg\n";
+    open CHANGES, '-|', 'dpkg-genchanges', @changes_opts
+	or subprocerr('dpkg-genchanges');
+
+    open OUT, '>', $chg or syserr(_g('write changes file'));
+
+    my $infiles = my $files = '';
+    while ($_ = <CHANGES>) {
+	print OUT $_ or syserr(_g('write changes file'));
+	chomp;
+
+	if (/^Files:/i) {
+	    $infiles = 1;
+	} elsif ($infiles && /^\s+(.*)$/) {
+	    $files .= " $1 ";
+	} elsif ($infiles && /^\S/) {
+	    $infiles = 0;
+	}
+    }
+
+    close CHANGES or subprocerr(_g('dpkg-genchanges'));
+    close OUT or syserr(_g('write changes file'));
+
+    my $srcmsg;
+    sub fileomitted($) { return $files !~ /$_[0]/ }
+    my $ext = $compression_re_file_ext;
+    if (fileomitted '\.deb') {
+	# source only upload
+	if (fileomitted "\.diff\.$ext" and fileomitted "\.debian\.tar\.$ext") {
+	    $srcmsg = _g('source only upload: Debian-native package');
+	} elsif (fileomitted "\.orig\.tar\.$ext") {
+	    $srcmsg = _g('source only, diff-only upload (original source NOT included)');
+	} else {
+	    $srcmsg = _g('source only upload (original source is included)');
+	}
+    } else {
+	$srcmsg = _g('full upload (original source is included)');
+	if (fileomitted '\.dsc') {
+	    $srcmsg = _g('binary only upload (no source included)');
+	} elsif (fileomitted "\.diff\.$ext" and fileomitted "\.debian\.tar\.$ext") {
+	    $srcmsg = _g('full upload; Debian-native package (full source is included)');
+	} elsif (fileomitted "\.orig\.tar\.$ext") {
+	    $srcmsg = _g('binary and diff upload (original source NOT included)');
+	} else {
+	    $srcmsg = _g('full upload (original source is included)');
+	}
+    }
+
+    if ($iter == $nloops) {
+	if ($signchanges && signfile("$pva.changes")) {
+	    $signerrors = _g("Failed to sign .changes file");
+	}
+    }
+
+    if ($cleansource) {
+	withecho(@rootcommand, @debian_rules, 'clean');
+    }
     chdir('..') or syserr('chdir ..');
-    withecho('dpkg-source', @source_opts, '--before-build', $dir);
+    withecho('dpkg-source', @source_opts, '--after-build', $dir);
     chdir($dir) or syserr("chdir $dir");
+
+    print "$progname: $srcmsg\n";
+    if ($signerrors) {
+	warning($signerrors);
+	exit 1;
+    }
+
 }
 
-if ($checkbuilddep) {
-    if ($admindir) {
-	push @checkbuilddep_opts, "--admindir=$admindir";
-    }
-
-    system('dpkg-checkbuilddeps', @checkbuilddep_opts);
-    if (not WIFEXITED($?)) {
-        subprocerr('dpkg-checkbuilddeps');
-    } elsif (WEXITSTATUS($?)) {
-	warning(_g("Build dependencies/conflicts unsatisfied; aborting."));
-	warning(_g("(Use -d flag to override.)"));
-
-	if (build_sourceonly) {
-	    warning(_g("This is currently a non-fatal warning with -S, but"));
-	    warning(_g("will probably become fatal in the future."));
-	} else {
-	    exit 3;
-	}
-    }
-}
-
-if ($call_target) {
-    if ($call_target_as_root or
-        $call_target =~ /^(clean|binary(|-arch|-indep))$/)
-    {
-        withecho(@rootcommand, @debian_rules, $call_target);
-    } else {
-        withecho(@debian_rules, $call_target);
-    }
-    exit 0;
-}
-
-unless ($noclean) {
-    withecho(@rootcommand, @debian_rules, 'clean');
-}
-unless (build_binaryonly) {
-    warning(_g("it is a bad idea to generate a source package " .
-               "without cleaning up first, it might contain undesired " .
-               "files.")) if $noclean;
-    chdir('..') or syserr('chdir ..');
-    withecho('dpkg-source', @source_opts, '-b', $dir);
-    chdir($dir) or syserr("chdir $dir");
-}
-
-unless ($buildtarget eq "build" or scalar(@debian_rules) > 1) {
-    # Verify that build-{arch,indep} are supported. If not, fallback to build.
-    # This is a temporary measure to not break too many packages on a flag day.
-    my $pid = spawn(exec => [ "make", "-f", @debian_rules, "-qn", $buildtarget ],
-                    from_file => "/dev/null", to_file => "/dev/null",
-                    error_to_file => "/dev/null");
-    my $cmdline = "make -f @debian_rules -qn $buildtarget";
-    wait_child($pid, nocheck => 1, cmdline => $cmdline);
-    my $exitcode = WEXITSTATUS($?);
-    subprocerr($cmdline) unless WIFEXITED($?);
-    if ($exitcode == 2) {
-        warning(_g("%s must be updated to support the 'build-arch' and " .
-                   "'build-indep' targets (at least '%s' seems to be " .
-                   "missing)"), "@debian_rules", $buildtarget);
-        $buildtarget = "build";
-    }
-}
-
-unless (build_sourceonly) {
-    withecho(@debian_rules, $buildtarget);
-    withecho(@rootcommand, @debian_rules, $binarytarget);
-}
-if ($usepause &&
-    ($signchanges || (!build_binaryonly && $signsource))) {
-    print _g("Press the return key to start signing process\n");
-    getc();
-}
-
-my $signerrors;
-unless (build_binaryonly) {
-    if ($signsource && signfile("$pv.dsc")) {
-	$signerrors = _g("Failed to sign .dsc and .changes file");
-	$signchanges = 0;
-    }
-}
-
-if (defined($maint)) { push @changes_opts, "-m$maint" }
-if (defined($changedby)) { push @changes_opts, "-e$changedby" }
-if (defined($since)) { push @changes_opts, "-v$since" }
-if (defined($desc)) { push @changes_opts, "-C$desc" }
-
-my $chg = "../$pva.changes";
-print STDERR " dpkg-genchanges @changes_opts >$chg\n";
-open CHANGES, '-|', 'dpkg-genchanges', @changes_opts
-    or subprocerr('dpkg-genchanges');
-
-open OUT, '>', $chg or syserr(_g('write changes file'));
-
-my $infiles = my $files = '';
-while ($_ = <CHANGES>) {
-    print OUT $_ or syserr(_g('write changes file'));
-    chomp;
-
-    if (/^Files:/i) {
-	$infiles = 1;
-    } elsif ($infiles && /^\s+(.*)$/) {
-	$files .= " $1 ";
-    } elsif ($infiles && /^\S/) {
-	$infiles = 0;
-    }
-}
-
-close CHANGES or subprocerr(_g('dpkg-genchanges'));
-close OUT or syserr(_g('write changes file'));
-
-my $srcmsg;
-sub fileomitted($) { return $files !~ /$_[0]/ }
-my $ext = $compression_re_file_ext;
-if (fileomitted '\.deb') {
-    # source only upload
-    if (fileomitted "\.diff\.$ext" and fileomitted "\.debian\.tar\.$ext") {
-	$srcmsg = _g('source only upload: Debian-native package');
-    } elsif (fileomitted "\.orig\.tar\.$ext") {
-	$srcmsg = _g('source only, diff-only upload (original source NOT included)');
-    } else {
-	$srcmsg = _g('source only upload (original source is included)');
-    }
-} else {
-    $srcmsg = _g('full upload (original source is included)');
-    if (fileomitted '\.dsc') {
-	$srcmsg = _g('binary only upload (no source included)');
-    } elsif (fileomitted "\.diff\.$ext" and fileomitted "\.debian\.tar\.$ext") {
-	$srcmsg = _g('full upload; Debian-native package (full source is included)');
-    } elsif (fileomitted "\.orig\.tar\.$ext") {
-	$srcmsg = _g('binary and diff upload (original source NOT included)');
-    } else {
-	$srcmsg = _g('full upload (original source is included)');
-    }
-}
-
-if ($signchanges && signfile("$pva.changes")) {
-    $signerrors = _g("Failed to sign .changes file");
-}
-
-if ($cleansource) {
-    withecho(@rootcommand, @debian_rules, 'clean');
-}
-chdir('..') or syserr('chdir ..');
-withecho('dpkg-source', @source_opts, '--after-build', $dir);
-chdir($dir) or syserr("chdir $dir");
-
-print "$progname: $srcmsg\n";
-if ($signerrors) {
-    warning($signerrors);
-    exit 1;
-}
 
 sub mustsetvar {
     my ($var, $text) = @_;

Reply via email to