[PATCH] New dpkg-source build option: --no-generate-diff

"Daniel Richard G." <[email protected]>
Newsgroups gmane.linux.debian.devel.dpkg.general
Message-ID <[email protected]>
I've rebased this patch against current Git.

To recap, this option enables (re)building a source package without cross-
checking against the orig tarball, in scenarios where the latter is
superfluous and expensive. Some benchmarks from a package I work with
basically tell the story. This is with my patch applied:

$ ls -l *.orig.tar.xz 
-rw-r--r-- 1 skunk users 843547668 May 16 19:08 ungoogled-chromium_125.0.6422.60.orig.tar.xz

$ time -p dpkg-source --no-preparation --abort-on-upstream-changes --build ungoogled-chromium-src
dpkg-source.pl: info: using source format '3.0 (quilt)'
dpkg-source.pl: info: building ungoogled-chromium using existing ./ungoogled-chromium_125.0.6422.60.orig.tar.xz
dpkg-source.pl: info: using patch list from debian/patches/series
dpkg-source.pl: info: building ungoogled-chromium in ungoogled-chromium_125.0.6422.60-1xtradeb1.2204.1.debian.tar.xz
dpkg-source.pl: info: building ungoogled-chromium in ungoogled-chromium_125.0.6422.60-1xtradeb1.2204.1.dsc
real 628.93
user 198.92
sys 88.00

$ time -p dpkg-source --no-generate-diff --no-preparation --abort-on-upstream-changes --build ungoogled-chromium-src
dpkg-source.pl: info: using source format '3.0 (quilt)'
dpkg-source.pl: info: building ungoogled-chromium using existing ./ungoogled-chromium_125.0.6422.60.orig.tar.xz
dpkg-source.pl: info: building ungoogled-chromium in ungoogled-chromium_125.0.6422.60-1xtradeb1.2204.1.debian.tar.xz
dpkg-source.pl: info: building ungoogled-chromium in ungoogled-chromium_125.0.6422.60-1xtradeb1.2204.1.dsc
real 11.62
user 10.86
sys 0.74


--Daniel


---
 man/dpkg-source.pod               | 11 ++++++++++-
 scripts/Dpkg/Source/Package/V2.pm | 32 +++++++++++++++++++++++++++++---
 2 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/man/dpkg-source.pod b/man/dpkg-source.pod
index 736f42fd2..4102fd986 100644
--- a/man/dpkg-source.pod
+++ b/man/dpkg-source.pod
@@ -647,7 +647,8 @@ patches have been applied during the extraction.
 
 B<Building>
 
-All original tarballs found in the current directory are extracted in a
+If B<--no-generate-diff> is not given, then
+all original tarballs found in the current directory are extracted in a
 temporary directory by following the same logic as for the unpack, the
 debian directory is copied over in the temporary directory, and all
 patches except the automatic patch (B<debian-changes->I<version>
@@ -791,6 +792,14 @@ Those options are only allowed
 in B<debian/source/local-options> so that all generated source
 packages have the same behavior by default.
 
+=item B<--no-generate-diff>
+
+Do not generate a diff against the upstream sources. This skips the process
+of extracting the original tarballs, and thus allows for a faster build.
+Not only is the source package directory not checked for any extraneous
+modifications, anything outside the debian subdirectory is ignored
+altogether. Use with caution.
+
 =item B<--abort-on-upstream-changes>
 
 The process fails if an automatic patch has been generated
diff --git a/scripts/Dpkg/Source/Package/V2.pm b/scripts/Dpkg/Source/Package/V2.pm
index 1f0946128..0eb9ba529 100644
--- a/scripts/Dpkg/Source/Package/V2.pm
+++ b/scripts/Dpkg/Source/Package/V2.pm
@@ -71,6 +71,7 @@ sub init_options {
     $self->{options}{unapply_patches} //= 'auto';
     $self->{options}{skip_debianization} //= 0;
     $self->{options}{create_empty_orig} //= 0;
+    $self->{options}{generate_diff} //= 1;
     $self->{options}{auto_commit} //= 0;
     $self->{options}{ignore_bad_version} //= 0;
 }
@@ -104,6 +105,10 @@ my @module_cmdline = (
         name => '--create-empty-orig',
         help => N_('create an empty original tarball if missing'),
         when => 'build',
+    }, {
+        name => '--no-generate-diff',
+        help => N_('do not generate diff against upstream sources'),
+        when => 'build',
     }, {
         name => '--abort-on-upstream-changes',
         help => N_('abort if generated diff has upstream files changes'),
@@ -156,6 +161,9 @@ sub parse_cmdline_option {
     } elsif ($opt eq '--create-empty-orig') {
         $self->{options}{create_empty_orig} = 1;
         return 1;
+    } elsif ($opt eq '--no-generate-diff') {
+        $self->{options}{generate_diff} = 0;
+        return 1;
     } elsif ($opt eq '--abort-on-upstream-changes') {
         $self->{options}{auto_commit} = 0;
         return 1;
@@ -460,6 +468,8 @@ sub _generate_patch {
         }
     }
 
+    return if !$opts{do_diff};
+
     # Unpack a second copy for comparison
     my $tmp = tempdir("$dirname.orig.XXXXXX", DIR => $updir);
     push_exit_handler(sub { erasedir($tmp) });
@@ -530,6 +540,21 @@ sub do_build {
         usageerr(g_("-b takes only one parameter with format '%s'"),
                  $self->{fields}{'Format'});
     }
+    if (!$self->{options}{generate_diff} &&
+        ($self->{options}{include_removal}   ||
+         $self->{options}{include_timestamp} ||
+         $self->{options}{include_binaries}  ||
+         $self->{options}{create_empty_orig} ||
+         $self->{options}{auto_commit})) {
+        my @incompat = (
+            "--include-removal",
+            "--include-timestamp",
+            "--include-binaries",
+            "--create-empty-orig",
+            "--auto-commit"
+        );
+        usageerr(g_("--no-generate-diff is incompatible with the following options: %s"), join(", ", @incompat));
+    }
     $self->prepare_build($dir);
 
     my $include_binaries = $self->{options}{include_binaries};
@@ -569,8 +594,9 @@ sub do_build {
                                         header_from => $autopatch,
                                         handle_binary => $handle_binary,
                                         skip_auto => $self->{options}{auto_commit},
+                                        do_diff => $self->{options}{generate_diff},
                                         usage => 'build');
-    unless (-z $tmpdiff or $self->{options}{auto_commit}) {
+    unless (!$tmpdiff or -z $tmpdiff or $self->{options}{auto_commit}) {
         info(g_('Hint: make sure the version in debian/changelog matches ' .
                 'the unpacked source tree'));
         info(g_('you can integrate the local changes with %s'),
@@ -578,7 +604,7 @@ sub do_build {
         error(g_('aborting due to unexpected upstream changes, see %s'),
               $tmpdiff);
     }
-    push_exit_handler(sub { unlink($tmpdiff) });
+    push_exit_handler(sub { !$tmpdiff or unlink($tmpdiff) });
     $binaryfiles->update_debian_source_include_binaries() if $include_binaries;
 
     # Install the diff as the new autopatch
@@ -590,7 +616,7 @@ sub do_build {
              $autopatch) if -e $autopatch;
         rmdir(File::Spec->catdir($dir, 'debian', 'patches')); # No check on purpose
     }
-    unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff);
+    !$tmpdiff or unlink($tmpdiff) or syserr(g_('cannot remove %s'), $tmpdiff);
     pop_exit_handler();
 
     # Create the debian.tar
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.