Explorar el Código

Apply patches before building source packages when needed

* 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.
Raphael Hertzog hace 18 años
padre
commit
25298d2cef
Se han modificado 5 ficheros con 111 adiciones y 8 borrados
  1. 13 0
      ChangeLog
  2. 10 0
      debian/changelog
  3. 17 3
      man/dpkg-source.1
  4. 24 4
      scripts/Dpkg/Source/Package/V2_0.pm
  5. 47 1
      scripts/Dpkg/Source/Package/V3_0/quilt.pm

+ 13 - 0
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>
 2008-04-01  Raphael Hertzog  <hertzog@debian.org>
 
 
 	* scripts/Dpkg/IPC.pm (fork_and_exec): Handle redirection
 	* scripts/Dpkg/IPC.pm (fork_and_exec): Handle redirection

+ 10 - 0
debian/changelog

@@ -1,9 +1,19 @@
 dpkg (1.14.18) UNRELEASED; urgency=low
 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
   * 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
     in original man pages was causing build failures. Closes: #473498
   * Add triggers documentation to dpkg-dev. Closes: #473449
   * 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 ]
   [ Updated dselect translations ]
   * German. (Sven Joachim).
   * German. (Sven Joachim).
 
 

+ 17 - 3
man/dpkg-source.1

@@ -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
 is meant to simplify usage of quilt to manage the set of patches. The
 patches can remove files.
 patches can remove files.
 .PP
 .PP
+The file \fBdebian/patches/.dpkg-source-applied\fP is created if some
+patches have been applied during the extraction.
+.PP
 .B Building
 .B Building
 .PP
 .PP
 All original tarballs found in the current directory are extracted in a
 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
 \fB.pc\fP directory used by quilt is ignored during generation of the
 automatic patch.
 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
 .PP
 .B Build options
 .B Build options
 .TP
 .TP
@@ -396,6 +406,10 @@ Include timestamp in the automatically generated patch.
 Add all modified binaries in the debian tarball. Also add them to
 Add all modified binaries in the debian tarball. Also add them to
 \fBdebian/source/include-binaries\fP: they will be added by default
 \fBdebian/source/include-binaries\fP: they will be added by default
 in subsequent builds and this option is thus no more needed.
 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
 .PP
 .B Extract options
 .B Extract options
 .TP
 .TP

+ 24 - 4
scripts/Dpkg/Source/Package/V2_0.pm

@@ -47,6 +47,8 @@ sub init_options {
         unless exists $self->{'options'}{'include_timestamp'};
         unless exists $self->{'options'}{'include_timestamp'};
     $self->{'options'}{'include_binaries'} = 0
     $self->{'options'}{'include_binaries'} = 0
         unless exists $self->{'options'}{'include_binaries'};
         unless exists $self->{'options'}{'include_binaries'};
+    $self->{'options'}{'preparation'} = 1
+        unless exists $self->{'options'}{'preparation'};
 }
 }
 
 
 sub parse_cmdline_option {
 sub parse_cmdline_option {
@@ -60,6 +62,9 @@ sub parse_cmdline_option {
     } elsif ($opt =~ /^--include-binaries$/) {
     } elsif ($opt =~ /^--include-binaries$/) {
         $self->{'options'}{'include_binaries'} = 1;
         $self->{'options'}{'include_binaries'} = 1;
         return 1;
         return 1;
+    } elsif ($opt =~ /^--no-preparation$/) {
+        $self->{'options'}{'preparation'} = 0;
+        return 1;
     }
     }
     return 0;
     return 0;
 }
 }
@@ -163,6 +168,8 @@ sub get_patches {
 sub apply_patches {
 sub apply_patches {
     my ($self, $dir, $skip_auto) = @_;
     my ($self, $dir, $skip_auto) = @_;
     my $timestamp = time();
     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)) {
     foreach my $patch ($self->get_patches($dir, $skip_auto)) {
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
         info(_g("applying %s"), $patch) unless $skip_auto;
         info(_g("applying %s"), $patch) unless $skip_auto;
@@ -170,7 +177,9 @@ sub apply_patches {
         $patch_obj->apply($dir, force_timestamp => 1,
         $patch_obj->apply($dir, force_timestamp => 1,
                           timestamp => $timestamp,
                           timestamp => $timestamp,
                           add_options => [ '-E' ]);
                           add_options => [ '-E' ]);
+        print APPLIED "$patch\n";
     }
     }
+    close(APPLIED);
 }
 }
 
 
 sub can_build {
 sub can_build {
@@ -188,21 +197,32 @@ sub prepare_build {
         include_removal => $self->{'options'}{'include_removal'},
         include_removal => $self->{'options'}{'include_removal'},
         include_timestamp => $self->{'options'}{'include_timestamp'},
         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 ($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 ($dirname, $updir) = fileparse($dir);
+    my @argv = @{$self->{'options'}{'ARGV'}};
     if (scalar(@argv)) {
     if (scalar(@argv)) {
         usageerr(_g("-b takes only one parameter with format `%s'"),
         usageerr(_g("-b takes only one parameter with format `%s'"),
                  $self->{'fields'}{'Format'});
                  $self->{'fields'}{'Format'});
     }
     }
     $self->prepare_build($dir);
     $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 $sourcepackage = $self->{'fields'}{'Source'};
     my $basenamerev = $self->get_basename(1);
     my $basenamerev = $self->get_basename(1);
     my $basename = $self->get_basename();
     my $basename = $self->get_basename();

+ 47 - 1
scripts/Dpkg/Source/Package/V3_0/quilt.pm

@@ -105,6 +105,8 @@ sub apply_patches {
     }
     }
 
 
     # 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();
     my $now = time();
     foreach my $patch ($self->get_patches($dir, $skip_auto)) {
     foreach my $patch ($self->get_patches($dir, $skip_auto)) {
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
         my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
@@ -135,16 +137,20 @@ sub apply_patches {
                     force_timestamp => 1, create_dirs => 1,
                     force_timestamp => 1, create_dirs => 1,
                     add_options => [ '-E' ]);
                     add_options => [ '-E' ]);
         }
         }
+        print APPLIED "$patch\n";
     }
     }
+    close(APPLIED);
 }
 }
 
 
 sub prepare_build {
 sub prepare_build {
     my ($self, $dir) = @_;
     my ($self, $dir) = @_;
     $self->SUPER::prepare_build($dir);
     $self->SUPER::prepare_build($dir);
     # Skip .pc directories of quilt by default and ignore difference
     # 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 {
     my $func = sub {
         return 1 if $_[0] =~ m{^debian/patches/series$} and -l $_[0];
         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] =~ /^.pc(\/|$)/;
         return 1 if $_[0] =~ /$self->{'options'}{'diff_ignore_regexp'}/;
         return 1 if $_[0] =~ /$self->{'options'}{'diff_ignore_regexp'}/;
         return 0;
         return 0;
@@ -152,6 +158,46 @@ sub prepare_build {
     $self->{'diff_options'}{'diff_ignore_func'} = $func;
     $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 {
 sub register_autopatch {
     my ($self, $dir) = @_;
     my ($self, $dir) = @_;
     my $auto_patch = $self->get_autopatch_name();
     my $auto_patch = $self->get_autopatch_name();