]> err.no Git - dpkg/commitdiff
Apply patches before building source packages when needed
authorRaphael Hertzog <hertzog@debian.org>
Sun, 30 Mar 2008 16:03:38 +0000 (18:03 +0200)
committerRaphael Hertzog <hertzog@debian.org>
Tue, 1 Apr 2008 17:36:16 +0000 (19:36 +0200)
* scripts/Dpkg/Source/Package/V2_0.pm (do_extract): Create
debian/patches/.dpkg-source-applied containing the list of patches
applied during extraction.
(prepare_build): apply patches before trying to build a source package
when it's clear that they have not been applied because
debian/patches/.dpkg-source-applied doesn't exist.
* scripts/Dpkg/Source/Package/V3_0/quilt.pm: Likewise. If a .pc directory
is present, then use "quilt unapplied" to check if all patches have been
applied.
* man/dpkg-source.1: Document the above changes.

ChangeLog
debian/changelog
man/dpkg-source.1
scripts/Dpkg/Source/Package/V2_0.pm
scripts/Dpkg/Source/Package/V3_0/quilt.pm

index cea7d6f9f393459551b91c291b472635c1eed8b4..5d6b6d1946373fb125c53acecc011c4c6af95866 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2008-04-01  Raphael Hertzog  <hertzog@debian.org>
+
+       * scripts/Dpkg/Source/Package/V2_0.pm (do_extract): Create
+       debian/patches/.dpkg-source-applied containing the list of patches
+       applied during extraction.
+       (prepare_build): apply patches before trying to build a source package
+       when it's clear that they have not been applied because
+       debian/patches/.dpkg-source-applied doesn't exist.
+       * scripts/Dpkg/Source/Package/V3_0/quilt.pm: Likewise. If a .pc directory
+       is present, then use "quilt unapplied" to check if all patches have been
+       applied.
+       * man/dpkg-source.1: Document the above changes.
+
 2008-04-01  Raphael Hertzog  <hertzog@debian.org>
 
        * scripts/Dpkg/IPC.pm (fork_and_exec): Handle redirection
index 78a7d837eaa459b314464759e0d0d91b1406a072..5fda86a5257791f0290ac004ad4b7f201b620db5 100644 (file)
@@ -1,9 +1,19 @@
 dpkg (1.14.18) UNRELEASED; urgency=low
 
+  [ Guillem Jover ]
   * Bump po4a version in Build-Depends to 0.33.1-1, as usage of UTF-8
     in original man pages was causing build failures. Closes: #473498
   * Add triggers documentation to dpkg-dev. Closes: #473449
 
+  [ Raphael Hertzog ]
+  * When dpkg-source builds a source package of Format: 2.0 or 3.0 (quilt) it
+    applies the patches before the build if
+    debian/patches/.dpkg-source-applied doesn't exist. This file is created
+    during extraction if patches are applied, and is auto-excluded from the
+    debian tarball. This enables on-the-fly conversion of source packages from
+    Format: 1.0 to Format: 3.0 (quilt) without manual intervention of the
+    user. This feature can be disabled with the option --no-preparation.
+
   [ Updated dselect translations ]
   * German. (Sven Joachim).
 
index c8cd8027c93e58066ad99c6153ff3c124dc42976..fa29a0e381dd51ba0cbfd909c782387297b68732 100644 (file)
@@ -356,6 +356,9 @@ symlink), then the latter is replaced with a symlink to the former. This
 is meant to simplify usage of quilt to manage the set of patches. The
 patches can remove files.
 .PP
+The file \fBdebian/patches/.dpkg-source-applied\fP is created if some
+patches have been applied during the extraction.
+.PP
 .B Building
 .PP
 All original tarballs found in the current directory are extracted in a
@@ -379,9 +382,16 @@ files as well as many temporary files (see default value associated to
 \fB.pc\fP directory used by quilt is ignored during generation of the
 automatic patch.
 
-Note: it's very important to generate the source package with all
-patches applied, otherwise the generation of the automatic patch will lead to
-a patch that reverts the patches which were not applied.
+Note: \fBdpkg\-source\fP expects the source tree to have all patches
+applied when you generate the source package. This is not the case
+when the source tree has been obtained by unpacking a source package using
+the Format: 1.0 for instance. To mitigate the problem, \fBdpkg\-source\fP
+will apply patches before building unless it finds
+\fBdebian/patches/.dpkg-source-applied\fP. The presence of a \fB.pc\fP
+subdirectory is also interpreted as a sign that some patches have been
+applied and in this case \fBquilt unapplied\fP is called to verify that
+all patches are applied. The option \fB\-\-no\-preparation\fP can be used
+to disable this behaviour.
 .PP
 .B Build options
 .TP
@@ -396,6 +406,10 @@ Include timestamp in the automatically generated patch.
 Add all modified binaries in the debian tarball. Also add them to
 \fBdebian/source/include-binaries\fP: they will be added by default
 in subsequent builds and this option is thus no more needed.
+.TP
+.B \-\-no\-preparation
+Do not try to prepare the build tree by applying patches which are
+apparently unapplied.
 .PP
 .B Extract options
 .TP
index a25636145d0bfe3b71b0510276890b79538d785e..d3b34bcf7dbf20b2174111c78f1fff39e007410b 100644 (file)
@@ -47,6 +47,8 @@ sub init_options {
         unless exists $self->{'options'}{'include_timestamp'};
     $self->{'options'}{'include_binaries'} = 0
         unless exists $self->{'options'}{'include_binaries'};
+    $self->{'options'}{'preparation'} = 1
+        unless exists $self->{'options'}{'preparation'};
 }
 
 sub parse_cmdline_option {
@@ -60,6 +62,9 @@ sub parse_cmdline_option {
     } elsif ($opt =~ /^--include-binaries$/) {
         $self->{'options'}{'include_binaries'} = 1;
         return 1;
+    } elsif ($opt =~ /^--no-preparation$/) {
+        $self->{'options'}{'preparation'} = 0;
+        return 1;
     }
     return 0;
 }
@@ -163,6 +168,8 @@ sub get_patches {
 sub apply_patches {
     my ($self, $dir, $skip_auto) = @_;
     my $timestamp = time();
+    my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
+    open(APPLIED, '>', $applied) || syserr(_g("cannot write %s"), $applied);
     foreach my $patch ($self->get_patches($dir, $skip_auto)) {
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
         info(_g("applying %s"), $patch) unless $skip_auto;
@@ -170,7 +177,9 @@ sub apply_patches {
         $patch_obj->apply($dir, force_timestamp => 1,
                           timestamp => $timestamp,
                           add_options => [ '-E' ]);
+        print APPLIED "$patch\n";
     }
+    close(APPLIED);
 }
 
 sub can_build {
@@ -188,21 +197,32 @@ sub prepare_build {
         include_removal => $self->{'options'}{'include_removal'},
         include_timestamp => $self->{'options'}{'include_timestamp'},
     };
+    push @{$self->{'options'}{'tar_ignore'}}, "debian/patches/.dpkg-source-applied";
+    $self->check_patches_applied($dir) if $self->{'options'}{'preparation'};
 }
 
-sub do_build {
+sub check_patches_applied {
     my ($self, $dir) = @_;
-    my @argv = @{$self->{'options'}{'ARGV'}};
-    my @tar_ignore = map { "--exclude=$_" } @{$self->{'options'}{'tar_ignore'}};
-    my $include_binaries = $self->{'options'}{'include_binaries'};
+    my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
+    unless (-e $applied) {
+        warning(_g("patches have not been applied, applying them now (use --no-preparation to override)"));
+        $self->apply_patches($dir);
+    }
+}
 
+sub do_build {
+    my ($self, $dir) = @_;
     my ($dirname, $updir) = fileparse($dir);
+    my @argv = @{$self->{'options'}{'ARGV'}};
     if (scalar(@argv)) {
         usageerr(_g("-b takes only one parameter with format `%s'"),
                  $self->{'fields'}{'Format'});
     }
     $self->prepare_build($dir);
 
+    my $include_binaries = $self->{'options'}{'include_binaries'};
+    my @tar_ignore = map { "--exclude=$_" } @{$self->{'options'}{'tar_ignore'}};
+
     my $sourcepackage = $self->{'fields'}{'Source'};
     my $basenamerev = $self->get_basename(1);
     my $basename = $self->get_basename();
index 1229feda094c7e68e8f0d25d017b98eca90c305d..d66c0e8cb67c691d32ab61eb757e0d8c99f1a4d6 100644 (file)
@@ -105,6 +105,8 @@ sub apply_patches {
     }
 
     # Apply patches
+    my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
+    open(APPLIED, '>', $applied) || syserr(_g("cannot write %s"), $applied);
     my $now = time();
     foreach my $patch ($self->get_patches($dir, $skip_auto)) {
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
@@ -135,16 +137,20 @@ sub apply_patches {
                     force_timestamp => 1, create_dirs => 1,
                     add_options => [ '-E' ]);
         }
+        print APPLIED "$patch\n";
     }
+    close(APPLIED);
 }
 
 sub prepare_build {
     my ($self, $dir) = @_;
     $self->SUPER::prepare_build($dir);
     # Skip .pc directories of quilt by default and ignore difference
-    # on debian/patches/series symlinks
+    # on debian/patches/series symlinks and d/p/.dpkg-source-applied
+    # stamp file created by ourselves
     my $func = sub {
         return 1 if $_[0] =~ m{^debian/patches/series$} and -l $_[0];
+        return 1 if $_[0] =~ m{^debian/patches/.dpkg-source-applied$};
         return 1 if $_[0] =~ /^.pc(\/|$)/;
         return 1 if $_[0] =~ /$self->{'options'}{'diff_ignore_regexp'}/;
         return 0;
@@ -152,6 +158,46 @@ sub prepare_build {
     $self->{'diff_options'}{'diff_ignore_func'} = $func;
 }
 
+sub check_patches_applied {
+    my ($self, $dir) = @_;
+    my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
+    my $quiltdir = File::Spec->catdir($dir, ".pc");
+    if (-d $quiltdir) {
+        my $auto_patch = $self->get_autopatch_name();
+        my $pipe;
+        my %opts = (env => { QUILT_PATCHES => 'debian/patches' },
+                    delete_env => [ 'QUILT_PATCH_OPTS' ],
+                    'chdir' => $dir,
+                    'exec' => [ 'quilt', '--quiltrc', '/dev/null', 'unapplied' ],
+                    error_to_file => "/dev/null",
+                    to_pipe => \$pipe);
+        my $pid = fork_and_exec(%opts);
+        # We skip auto_patch as this one might be applied but not by
+        # quilt... but by the user who made changes live in the tree
+        # and whose changes lead to this patch addition by a previous
+        # dpkg-source run.
+        my @patches = grep { chomp; $_ ne $auto_patch } (<$pipe>);
+        close ($pipe) || syserr("close on 'quilt unapplied' pipe");
+        wait_child($pid, cmdline => "quilt unapplied", nocheck => 1);
+        if (@patches) {
+            warning(_g("patches have not been applied, applying them now (use --no-preparation to override)"));
+            $opts{'wait_child'} = 1;
+            $opts{'to_file'} = "/dev/null";
+            delete $opts{'to_pipe'};
+            foreach my $patch (@patches) {
+                info(_g("applying %s with quilt"), $patch);
+                $opts{'exec'} = [ 'quilt', '--quiltrc', '/dev/null', 'push', $patch ];
+                fork_and_exec(%opts);
+            }
+        }
+        return;
+    }
+    unless (-e $applied) {
+        warning(_g("patches have not been applied, applying them now (use --no-preparation to override)"));
+        $self->apply_patches($dir);
+    }
+}
+
 sub register_autopatch {
     my ($self, $dir) = @_;
     my $auto_patch = $self->get_autopatch_name();