]> err.no Git - dpkg/commitdiff
dpkg-source/3.0 (quilt): improve reliability of check_patches_applied
authorRaphael Hertzog <hertzog@debian.org>
Wed, 28 May 2008 16:05:50 +0000 (18:05 +0200)
committerRaphael Hertzog <hertzog@debian.org>
Wed, 28 May 2008 20:38:31 +0000 (22:38 +0200)
* scripts/Dpkg/Source/Patch.pm (check_apply): New function to
verify if a patch will successfully apply on top of a given
directory.
* scripts/Dpkg/Source/Package/V3/quilt.pm (check_patches_applied):
Don't trust debian/patches/.dpkg-source-applied blindly. Get a
list of (supposedly unapplied) patches and verify if the first
patch applies or not. If yes, then apply the patch series,
otherwise do not (and assume that the patch series is already
applied).

ChangeLog
scripts/Dpkg/Source/Package/V3/quilt.pm
scripts/Dpkg/Source/Patch.pm

index d469819f855876f5abb1483b6e14c528752943b5..c816cca2658ad175fcf331f3cc35d2120090e0fd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-05-28  Raphael Hertzog  <hertzog@debian.org>
+
+       * scripts/Dpkg/Source/Patch.pm (check_apply): New function to
+       verify if a patch will successfully apply on top of a given
+       directory.
+       * scripts/Dpkg/Source/Package/V3/quilt.pm (check_patches_applied):
+       Don't trust debian/patches/.dpkg-source-applied blindly. Get a
+       list of (supposedly unapplied) patches and verify if the first
+       patch applies or not. If yes, then apply the patch series,
+       otherwise do not (and assume that the patch series is already
+       applied).
+
 2008-05-23  Raphael Hertzog  <hertzog@debian.org>
 
        * scripts/Dpkg/Source/Package/V2.pm (do_build): Display a
index 979d2074464730c246ce37189699bb8fb905e4c8..c02d0730878ade43b0d11e1fd7fed59c23f64d5e 100644 (file)
@@ -173,8 +173,9 @@ sub prepare_build {
 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 @patches ;
+    # First we try to get a list of patches that could be unapplied
+    if (-x "/usr/bin/quilt") {
         my $auto_patch = $self->get_autopatch_name();
         my $pipe;
         my %opts = (env => { QUILT_PATCHES => 'debian/patches' },
@@ -188,24 +189,18 @@ sub check_patches_applied {
         # 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>);
+        @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;
+    } else {
+        @patches = $self->get_patches($dir);
     }
-    unless (-e $applied) {
-        if (scalar($self->get_patches($dir))) {
+    # Then we check if it's applicable, and if yes, we make the
+    # assumption that patches are not applied and need to be applied
+    if (scalar(@patches)) {
+        my $first_patch = File::Spec->catfile($dir, "debian", "patches", $patches[0]);
+        my $patch_obj = Dpkg::Source::Patch->new(filename => $first_patch);
+        if ($patch_obj->check_apply($dir)) {
             warning(_g("patches have not been applied, applying them now (use --no-preparation to override)"));
             $self->apply_patches($dir);
         }
index 0ad407d0396415f4d7a9fced4e1e1caeeba9df4c..26cbe2a629da4087a3449d961c94e86ffa6a6c75 100644 (file)
@@ -377,6 +377,16 @@ sub analyze {
     return $self->{'analysis'}{$destdir};
 }
 
+sub prepare_apply {
+    my ($self, $analysis, %opts) = @_;
+    if ($opts{"create_dirs"}) {
+       foreach my $dir (keys %{$analysis->{'dirtocreate'}}) {
+           eval { mkpath($dir, 0, 0777); };
+           syserr(_g("cannot create directory %s"), $dir) if $@;
+       }
+    }
+}
+
 sub apply {
     my ($self, $destdir, %opts) = @_;
     # Set default values to options
@@ -389,12 +399,7 @@ sub apply {
     push @{$opts{"options"}}, @{$opts{"add_options"}};
     # Check the diff and create missing directories
     my $analysis = $self->analyze($destdir, %opts);
-    if ($opts{"create_dirs"}) {
-       foreach my $dir (keys %{$analysis->{'dirtocreate'}}) {
-           eval { mkpath($dir, 0, 0777); };
-           syserr(_g("cannot create directory %s"), $dir) if $@;
-       }
-    }
+    $self->prepare_apply($analysis, %opts);
     # Apply the patch
     my $diff_handle = $self->open_for_read();
     fork_and_exec(
@@ -421,6 +426,37 @@ sub apply {
     }
 }
 
+# Verify if check will work...
+sub check_apply {
+    my ($self, $destdir, %opts) = @_;
+    # Set default values to options
+    $opts{"create_dirs"} = 1 unless exists $opts{"create_dirs"};
+    $opts{"options"} ||= [ '--dry-run', '-s', '-t', '-F', '0', '-N', '-p1', '-u',
+            '-V', 'never', '-g0', '-b', '-z', '.dpkg-orig'];
+    $opts{"add_options"} ||= [];
+    push @{$opts{"options"}}, @{$opts{"add_options"}};
+    # Check the diff and create missing directories
+    my $analysis = $self->analyze($destdir, %opts);
+    $self->prepare_apply($analysis, %opts);
+    # Apply the patch
+    my $diff_handle = $self->open_for_read();
+    my $error;
+    my $patch_pid = fork_and_exec(
+       'exec' => [ 'patch', @{$opts{"options"}} ],
+       'chdir' => $destdir,
+       'env' => { LC_ALL => 'C', LANG => 'C' },
+       'delete_env' => [ 'POSIXLY_CORRECT' ], # ensure expected patch behaviour
+       'from_handle' => $diff_handle,
+        'to_file' => '/dev/null',
+        'error_to_file' => '/dev/null',
+    );
+    wait_child($patch_pid, nocheck => 1);
+    my $exit = WEXITSTATUS($?);
+    subprocerr("patch --dry-run") unless WIFEXITED($?);
+    $self->cleanup_after_open();
+    return ($exit == 0);
+}
+
 # Helper functions
 sub get_type {
     my $file = shift;