Bug#563546: pu: package dpkg/1.14.28
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: pu
I'd like to update dpkg in stable another time to include more
fixes/improvements made to new source formats in sid since the last time.
I expect this update to be the last one.
The reason that I want this update in stable is that dpkg-source now
creates quilt's .pc directory. This change has been requested by the
release team and several people and having this in stable will let people
use quilt in debian/rules. Up to now they could not because old buildd
extract the source package outside of the build chroot and thus would not
get the .pc directory required by quilt.
See #557667 mainly for some discussion.
You can review the individual commits here:
http://git.debian.org/?p=users/hertzog/dpkg.git;a=shortlog;h=refs/heads/pu/stable-update
This code is working fine in sid since several weeks and I tested the
updated dpkg on lenny as well.
I also attach a full git diff between 1.14.27 and the proposed 1.14.28.
If it's ok for you, I'll upload it. Thanks!
-- System Information:
Debian Release: squeeze/sid
APT prefers unstable
APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable'), (150, 'experimental')
Architecture: i386 (x86_64)
Kernel: Linux 2.6.32-trunk-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
--
Raphaël Hertzog
debian/changelog | 20 ++
man/dpkg-source.1 | 35 ++--
scripts/Dpkg/Source/Package/V2.pm | 50 ++++-
scripts/Dpkg/Source/Package/V3/quilt.pm | 326 ++++++++++++++++---------------
4 files changed, 250 insertions(+), 181 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 5b2d048..afa5980 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,23 @@
+dpkg (1.14.28) UNRELEASED; urgency=low
+
+ * Another round of updates concerning new source formats:
+ - fix dpkg-source to not complain on binary files that are ignored and are
+ not going to be included in the debian tarball of a "3.0 (quilt)" source
+ package. Closes: #524375
+ - let dpkg-source fail if several upstream orig.tar files are
+ available (using different compression scheme) since we don't know
+ which one to use.
+ - before accepting to build a 3.0 (quilt) source packages, ensure that
+ debian/patches is a directory (or non-existing) and that
+ debian/patches/series is a file (or non-existing). Closes: #557618
+ - modify implementation of "3.0 (quilt)" source format to not be
+ behave differently depending on whether quilt is installed or not.
+ The option --without-quilt is thus gone and dpkg-source creates and
+ relies on the .pc directory to know whether patches are applied or
+ not. Closes: #557667
+
+ -- Raphael Hertzog <hertzog@debian.org> Sun, 03 Jan 2010 18:21:35 +0100
+
dpkg (1.14.27) stable; urgency=low
* Cherry-pick some fixes from squeeze concerning new source formats:
diff --git a/man/dpkg-source.1 b/man/dpkg-source.1
index 2b5bf7d..838a8fd 100644
--- a/man/dpkg-source.1
+++ b/man/dpkg-source.1
@@ -371,7 +371,7 @@ such options, and the build is likely to fail.
.PP
Similarly to quilt's default behaviour, the patches can remove files too.
.PP
-The file \fBdebian/patches/.dpkg-source-applied\fP is created if some
+The file \fB.pc/applied-patches\fP is created if some
patches have been applied during the extraction.
.PP
.B Building
@@ -400,18 +400,28 @@ files as well as many temporary files (see default value associated to
automatic patch.
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.
+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 the patches by itself if it
+believes that they have not yet been applied. To detect this situation, it
+uses the following heuristic: it finds the list of supposedly unapplied
+patches (they are listed in the \fBseries\fP file but not in
+\fB.pc/applied-patches\fP), and if the first patch in that set can be
+applied without errors, it will apply them all.
+The option \fB\-\-no\-preparation\fP can be used to disable this
+behaviour.
.PP
.B Build options
.TP
+.BI \-\-allow\-version\-of\-quilt\-db= version
+Allow \fBdpkg\-source\fP to build the source package if the version of
+the quilt metadata is the one specified, even if \fBdpkg\-source\fP
+doesn't know about it. Effectively this says that the given version of the
+quilt metadata is compatible with the version 2 that \fBdpkg\-source\fP
+currently supports. The version of the quilt metadata is stored in
+\fB.pc/.version\fP.
+.TP
.B \-\-include\-removal
Do not ignore removed files and include them in the automatically
generated patch.
@@ -432,11 +442,6 @@ apparently unapplied.
.TP
.B \-\-skip\-patches
Do not apply patches at the end of the extraction.
-.TP
-.B \-\-without\-quilt
-Don't use quilt to apply patches but dpkg-source's own code. It won't be
-possible to use quilt directly on the unpacked directory but it will be
-free of quilt's temporary files as well.
.
.SS Format: 3.0 (custom)
This format is particular. It doesn't represent a real source package
diff --git a/scripts/Dpkg/Source/Package/V2.pm b/scripts/Dpkg/Source/Package/V2.pm
index a162f53..e7fb9d8 100644
--- a/scripts/Dpkg/Source/Package/V2.pm
+++ b/scripts/Dpkg/Source/Package/V2.pm
@@ -148,7 +148,8 @@ sub do_extract {
@exclude_symlinks ]);
# Apply patches (in a separate method as it might be overriden)
- $self->apply_patches($newdirectory) unless $self->{'options'}{'skip_patches'};
+ $self->apply_patches($newdirectory, usage => 'unpack')
+ unless $self->{'options'}{'skip_patches'};
}
sub get_autopatch_name {
@@ -156,7 +157,8 @@ sub get_autopatch_name {
}
sub get_patches {
- my ($self, $dir, $skip_auto) = @_;
+ my ($self, $dir, %opts) = @_;
+ $opts{"skip_auto"} = 0 unless defined($opts{"skip_auto"});
my @patches;
my $pd = "$dir/debian/patches";
my $auto_patch = $self->get_autopatch_name();
@@ -165,7 +167,7 @@ sub get_patches {
foreach my $patch (sort readdir(DIR)) {
# patches match same rules as run-parts
next unless $patch =~ /^[\w-]+$/ and -f "$pd/$patch";
- next if $skip_auto and $patch eq $auto_patch;
+ next if $opts{"skip_auto"} and $patch eq $auto_patch;
push @patches, $patch;
}
closedir(DIR);
@@ -174,15 +176,16 @@ sub get_patches {
}
sub apply_patches {
- my ($self, $dir, $skip_auto) = @_;
- my @patches = $self->get_patches($dir, $skip_auto);
+ my ($self, $dir, %opts) = @_;
+ $opts{"skip_auto"} = 0 unless defined($opts{"skip_auto"});
+ my @patches = $self->get_patches($dir, %opts);
return unless scalar(@patches);
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, %opts)) {
my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
- info(_g("applying %s"), $patch) unless $skip_auto;
+ info(_g("applying %s"), $patch) unless $opts{"skip_auto"};
my $patch_obj = Dpkg::Source::Patch->new(filename => $path);
$patch_obj->apply($dir, force_timestamp => 1,
timestamp => $timestamp,
@@ -217,7 +220,7 @@ sub check_patches_applied {
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);
+ $self->apply_patches($dir, usage => 'preparation');
}
}
@@ -245,6 +248,10 @@ sub do_build {
my @origtarballs;
foreach (sort $self->find_original_tarballs()) {
if (/\.orig\.tar\.$comp_regex$/) {
+ if (defined($tarfile)) {
+ error(_g("several orig.tar files found (%s and %s) but only " .
+ "one is allowed"), $tarfile, $_);
+ }
$tarfile = $_;
push @origtarballs, $_;
$self->add_file($_);
@@ -280,7 +287,7 @@ sub do_build {
subprocerr(_g("copy of the debian directory")) if $?;
# Apply all patches except the last automatic one
- $self->apply_patches($tmp, 1);
+ $self->apply_patches($tmp, skip_auto => 1, usage => 'build');
# Prepare handling of binary files
my %auth_bin_files;
@@ -324,7 +331,30 @@ sub do_build {
}
}
};
- find({ wanted => $check_binary, no_chdir => 1 }, File::Spec->catdir($dir, "debian"));
+ my $tar_ignore_glob = "{" . join(",",
+ map {
+ my $copy = $_;
+ $copy =~ s/,/\\,/g;
+ $copy;
+ } @{$self->{'options'}{'tar_ignore'}}) . "}";
+ my $filter_ignore = sub {
+ # Filter out files that are not going to be included in the debian
+ # tarball due to ignores.
+ my %exclude;
+ my $reldir = File::Spec->abs2rel($File::Find::dir, $dir);
+ foreach my $fn (glob($tar_ignore_glob)) {
+ $exclude{$fn} = 1;
+ }
+ my @result;
+ foreach my $fn (@_) {
+ unless (exists $exclude{$fn} or exists $exclude{"$reldir/$fn"}) {
+ push @result, $fn;
+ }
+ }
+ return @result;
+ };
+ find({ wanted => $check_binary, preprocess => $filter_ignore,
+ no_chdir => 1 }, File::Spec->catdir($dir, "debian"));
error(_g("detected %d unwanted binary file(s) " .
"(add them in debian/source/include-binaries to allow their " .
"inclusion)."), $unwanted_binaries) if $unwanted_binaries;
diff --git a/scripts/Dpkg/Source/Package/V3/quilt.pm b/scripts/Dpkg/Source/Package/V3/quilt.pm
index 5b45f6c..4ec79c3 100644
--- a/scripts/Dpkg/Source/Package/V3/quilt.pm
+++ b/scripts/Dpkg/Source/Package/V3/quilt.pm
@@ -1,5 +1,5 @@
-# Copyright 2008 Raphaël Hertzog <hertzog@debian.org>
-
+# Copyright © 2008-2009 Raphaël Hertzog <hertzog@debian.org>
+#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -26,6 +26,7 @@ use Dpkg;
use Dpkg::Gettext;
use Dpkg::ErrorHandling qw(error syserr warning usageerr subprocerr info);
use Dpkg::Source::Patch;
+use Dpkg::Source::Functions qw(erasedir);
use Dpkg::IPC;
use POSIX;
@@ -37,22 +38,40 @@ our $CURRENT_MINOR_VERSION = "0";
sub init_options {
my ($self) = @_;
+ $self->{'options'}{'allow-version-of-quilt-db'} = []
+ unless exists $self->{'options'}{'allow-version-of-quilt-db'};
+
$self->SUPER::init_options();
- # By default use quilt, unless it's not available
- $self->{'options'}{'without_quilt'} = (-x "/usr/bin/quilt") ? 0 : 1
- unless exists $self->{'options'}{'without_quilt'};
}
sub parse_cmdline_option {
my ($self, $opt) = @_;
return 1 if $self->SUPER::parse_cmdline_option($opt);
- if ($opt =~ /^--without-quilt$/) {
- $self->{'options'}{'without_quilt'} = 1;
+ if ($opt =~ /^--allow-version-of-quilt-db=(.*)$/) {
+ push @{$self->{'options'}{'allow-version-of-quilt-db'}}, $1;
return 1;
}
return 0;
}
+sub can_build {
+ my ($self, $dir) = @_;
+ my ($code, $msg) = $self->SUPER::can_build($dir);
+ return ($code, $msg) if $code eq 0;
+ my $pd = File::Spec->catdir($dir, "debian", "patches");
+ if (-e $pd and not -d _) {
+ return (0, sprintf(_g("%s should be a directory or non-existing"), $pd));
+ }
+ my $series_vendor = $self->get_series_file($dir);
+ my $series_main = File::Spec->catfile($pd, "series");
+ foreach my $series ($series_vendor, $series_main) {
+ if (defined($series) and -e $series and not -f _) {
+ return (0, sprintf(_g("%s should be a file or non-existing"), $series));
+ }
+ }
+ return (1, "");
+}
+
sub get_autopatch_name {
my ($self) = @_;
return "debian-changes-" . $self->{'fields'}{'Version'};
@@ -70,60 +89,80 @@ sub get_series_file {
return undef;
}
-sub get_patches {
- my ($self, $dir, $skip_auto) = @_;
+sub read_patch_list {
+ my ($self, $file, %opts) = @_;
+ return () if not defined $file or not -f $file;
+ $opts{"warn_options"} = 0 unless defined($opts{"warn_options"});
+ $opts{"skip_auto"} = 0 unless defined($opts{"skip_auto"});
my @patches;
my $auto_patch = $self->get_autopatch_name();
- my $series = $self->get_series_file($dir);
- if (defined($series)) {
- open(SERIES, "<" , $series) || syserr(_g("cannot read %s"), $series);
- while(defined($_ = <SERIES>)) {
- chomp; s/^\s+//; s/\s+$//; # Strip leading/trailing spaces
- s/(^|\s+)#.*$//; # Strip comment
- next unless $_;
- if (/^(\S+)\s+(.*)$/) {
- $_ = $1;
- if ($2 ne '-p1') {
- warning(_g("the series file (%s) contains unsupported " .
- "options ('%s', line %s), dpkg-source might " .
- "fail when applying patches."),
- $series, $2, $.) unless $skip_auto;
- }
+ open(SERIES, "<" , $file) || syserr(_g("cannot read %s"), $file);
+ while(defined($_ = <SERIES>)) {
+ chomp; s/^\s+//; s/\s+$//; # Strip leading/trailing spaces
+ s/(^|\s+)#.*$//; # Strip comment
+ next unless $_;
+ if (/^(\S+)\s+(.*)$/) {
+ $_ = $1;
+ if ($2 ne '-p1') {
+ warning(_g("the series file (%s) contains unsupported " .
+ "options ('%s', line %s), dpkg-source might " .
+ "fail when applying patches."),
+ $file, $2, $.) if $opts{"warn_options"};
}
- next if $skip_auto and $_ eq $auto_patch;
- push @patches, $_;
}
- close(SERIES);
+ next if $opts{"skip_auto"} and $_ eq $auto_patch;
+ push @patches, $_;
}
+ close(SERIES);
return @patches;
}
-sub run_quilt {
- my ($self, $dir, $params, %more_opts) = @_;
- $params = [ $params ] unless ref($params) eq "ARRAY";
- my $absdir = $dir;
- unless (File::Spec->file_name_is_absolute($absdir)) {
- $absdir = File::Spec->rel2abs($dir);
+sub create_quilt_db {
+ my ($self, $dir) = @_;
+ my $db_dir = File::Spec->catdir($dir, ".pc");
+ if (not -d $db_dir) {
+ mkdir $db_dir or syserr(_g("cannot mkdir %s"), $db_dir);
}
- my $series = $self->get_series_file($dir);
- # Use default name if no series files exist yet
- $series = "$absdir/debian/patches/series" unless defined $series;
- unless (File::Spec->file_name_is_absolute($series)) {
- $series = File::Spec->rel2abs($series);
+ my $version_file = File::Spec->catfile($db_dir, ".version");
+ if (not -e $version_file) {
+ open(VERSION, ">", $version_file);
+ print VERSION "2\n";
+ close(VERSION);
}
- my %opts = (
- env => { QUILT_PATCHES => "$absdir/debian/patches",
- QUILT_SERIES => $series },
- 'chdir' => $dir,
- 'exec' => [ 'quilt', '--quiltrc', '/dev/null', @$params ],
- %more_opts
- );
- my $pid = fork_and_exec(%opts);
- return $pid;
+}
+
+sub apply_quilt_patch {
+ my ($self, $dir, $patch, %opts) = @_;
+ $opts{"verbose"} = 0 unless defined($opts{"verbose"});
+ $opts{"timestamp"} = time() unless defined($opts{"timestamp"});
+ my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
+ my $obj = Dpkg::Source::Patch->new(filename => $path);
+
+ info(_g("applying %s"), $patch) if $opts{"verbose"};
+ $obj->apply($dir, timestamp => $opts{"timestamp"},
+ force_timestamp => 1, create_dirs => 1, remove_backup => 0,
+ options => [ '-s', '-t', '-F', '0', '-N', '-p1', '-u',
+ '-V', 'never', '-g0', '-E', '-b',
+ '-B', ".pc/$patch/" ]);
+}
+
+sub get_patches {
+ my ($self, $dir, %opts) = @_;
+ my $series = $self->get_series_file($dir);
+ return $self->read_patch_list($series, %opts);
}
sub apply_patches {
- my ($self, $dir, $skip_auto) = @_;
+ my ($self, $dir, %opts) = @_;
+
+ if ($opts{'usage'} eq 'unpack') {
+ $opts{'verbose'} = 1;
+ } elsif ($opts{'usage'} eq 'build') {
+ $opts{'warn_options'} = 1;
+ $opts{'verbose'} = 0;
+ }
+
+ my $patches = $opts{"patches"};
# Update debian/patches/series symlink if needed to allow quilt usage
my $series = $self->get_series_file($dir);
@@ -137,46 +176,22 @@ sub apply_patches {
syserr(_g("can't create symlink %s"), $dest);
}
}
- my @patches = $self->get_patches($dir, $skip_auto);
- return unless scalar(@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 $pobj = {};
- my $panalysis = {};
- foreach my $patch (@patches) {
- my $path = File::Spec->catfile($dir, "debian", "patches", $patch);
- $pobj->{$patch} = Dpkg::Source::Patch->new(filename => $path);
- if ($self->{'options'}{'without_quilt'}) {
- info(_g("applying %s"), $patch) unless $skip_auto;
- $pobj->{$patch}->apply($dir, timestamp => $now,
- force_timestamp => 1, create_dirs => 1,
- add_options => [ '-E' ]);
- print APPLIED "$patch\n";
- } else {
- $panalysis->{$patch} = $pobj->{$patch}->analyze($dir);
- foreach my $dir (keys %{$panalysis->{$patch}->{'dirtocreate'}}) {
- eval { mkpath($dir); };
- syserr(_g("cannot create directory %s"), $dir) if $@;
- }
- }
+ unless (defined($patches)) {
+ $patches = [ $self->get_patches($dir, %opts) ];
}
- if (not $self->{'options'}{'without_quilt'}) {
- my %opts;
- $opts{"to_file"} = "/dev/null" if $skip_auto;
- info(_g("applying all patches with %s"), "quilt push -q " . $patches[-1]) unless $skip_auto;
- $self->run_quilt($dir, ['push', '-q', $patches[-1]],
- delete_env => ['QUILT_PATCH_OPTS'],
- wait_child => 1, %opts);
- foreach my $patch (@patches) {
- foreach my $fn (keys %{$panalysis->{$patch}->{'filepatched'}}) {
- utime($now, $now, $fn) || $! == ENOENT ||
- syserr(_g("cannot change timestamp for %s"), $fn);
- }
- print APPLIED "$patch\n";
- }
+ return unless scalar(@$patches);
+
+ # Apply patches
+ $self->create_quilt_db($dir);
+ my $pc_applied = File::Spec->catfile($dir, ".pc", "applied-patches");
+ my @applied = $self->read_patch_list($pc_applied);
+ my @patches = $self->read_patch_list($self->get_series_file($dir));
+ open(APPLIED, '>>', $pc_applied) || syserr(_g("cannot write %s"), $pc_applied);
+ $opts{"timestamp"} = time();
+ foreach my $patch (@$patches) {
+ $self->apply_quilt_patch($dir, $patch, %opts);
+ print APPLIED "$patch\n";
}
close(APPLIED);
}
@@ -189,7 +204,6 @@ sub prepare_build {
# 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;
@@ -197,99 +211,99 @@ sub prepare_build {
$self->{'diff_options'}{'diff_ignore_func'} = $func;
}
+sub do_build {
+ my ($self, $dir) = @_;
+ my $pc_ver = File::Spec->catfile($dir, ".pc", ".version");
+ if (-f $pc_ver) {
+ open(VER, "<", $pc_ver) || syserr(_g("cannot read %s"), $pc_ver);
+ my $version = <VER>;
+ chomp $version;
+ close(VER);
+ if ($version != 2) {
+ if (scalar grep { $version eq $_ }
+ @{$self->{'options'}{'allow-version-of-quilt-db'}})
+ {
+ warning(_g("unsupported version of the quilt metadata: %s"),
+ $version);
+ } else {
+ error(_g("unsupported version of the quilt metadata: %s"),
+ $version);
+ }
+ }
+ }
+ $self->SUPER::do_build($dir);
+}
+
sub check_patches_applied {
my ($self, $dir) = @_;
- my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
- my $auto_patch = $self->get_autopatch_name();
- my @patches ;
- # First we try to get a list of patches that are probably not napplied
- if (not $self->{'options'}{'without_quilt'}) {
- my $pipe;
- my $pid = $self->run_quilt($dir, ['unapplied'], error_to_file => '/dev/null',
- to_pipe => \$pipe);
- @patches = map { chomp; $_ } (<$pipe>);
- close ($pipe) || syserr("close on 'quilt unapplied' pipe");
- wait_child($pid, cmdline => "quilt unapplied", nocheck => 1);
- subprocerr("quilt unapplied") unless WIFEXITED($?);
- } else {
- @patches = $self->get_patches($dir);
+ my $pc_applied = File::Spec->catfile($dir, ".pc", "applied-patches");
+ my @applied = $self->read_patch_list($pc_applied);
+ my @patches = $self->read_patch_list($self->get_series_file($dir));
+ my @to_apply;
+ foreach my $patch (@patches) {
+ next if scalar grep { $_ eq $patch } @applied;
+ push @to_apply, $patch;
}
- # 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]);
+ if (scalar(@to_apply)) {
+ my $first_patch = File::Spec->catfile($dir, "debian", "patches",
+ $to_apply[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);
+ warning(_g("patches have not been applied, applying them now " .
+ "(use --no-preparation to override)"));
+ $self->apply_patches($dir, usage => 'preparation', verbose => 1,
+ patches => \@to_apply);
}
}
}
sub register_autopatch {
my ($self, $dir) = @_;
+
+ sub add_line {
+ my ($file, $line) = @_;
+ open(FILE, ">>", $file) || syserr(_g("cannot write %s"), $file);
+ print FILE "$line\n";
+ close(FILE);
+ }
+
+ sub drop_line {
+ my ($file, $re) = @_;
+ open(FILE, "<", $file) || syserr(_g("cannot read %s"), $file);
+ my @lines = <FILE>;
+ close(FILE);
+ open(FILE, ">", $file) || syserr(_g("cannot write %s"), $file);
+ print(FILE $_) foreach grep { not /^\Q$re\E\s*$/ } @lines;
+ close(FILE);
+ }
+
my $auto_patch = $self->get_autopatch_name();
my @patches = $self->get_patches($dir);
my $has_patch = (grep { $_ eq $auto_patch } @patches) ? 1 : 0;
my $series = $self->get_series_file($dir);
$series ||= File::Spec->catfile($dir, "debian", "patches", "series");
- my $applied = File::Spec->catfile($dir, "debian", "patches", ".dpkg-source-applied");
+ my $applied = File::Spec->catfile($dir, ".pc", "applied-patches");
my $patch = File::Spec->catfile($dir, "debian", "patches", $auto_patch);
- my $absdir = $dir;
- unless (File::Spec->file_name_is_absolute($absdir)) {
- $absdir = File::Spec->rel2abs($dir);
- }
+
if (-e $patch) {
# Add auto_patch to series file
if (not $has_patch) {
- # Use quilt to register only if it's wanted/available AND :
- # - either we have patches and quilt has been used (.pc dir exists)
- # - or we don't have patches, hence quilt couldn't be used
- if ((-d "$dir/.pc" or not scalar(@patches)) and
- not $self->{'options'}{'without_quilt'})
- {
- # Registering the new patch with quilt requires some
- # trickery: reverse-apply the patch, create a new quilt patch,
- # fold the patch into the quilt-managed one
- my $patch_obj = Dpkg::Source::Patch->new(filename => $patch);
- $patch_obj->apply($dir, add_options => ['-R', '-E']);
- $self->run_quilt($dir, ['new', "$auto_patch"],
- wait_child => 1, to_file => '/dev/null');
- $self->run_quilt($dir, ['fold'],
- from_file => "$absdir/debian/patches/$auto_patch",
- wait_child => 1, to_file => '/dev/null');
- } else {
- open(SERIES, ">>", $series) || syserr(_g("cannot write %s"), $series);
- print SERIES "$auto_patch\n";
- close(SERIES);
- }
- } else {
- # If quilt was used, ensure its meta-information are
- # synchronized with the updated patch
- if (-d "$dir/.pc" and not $self->{'options'}{'without_quilt'}) {
- # Some trickery needed: reverse-apply the patch, fold the
- # new patch into the quilt-managed one
- my $patch_obj = Dpkg::Source::Patch->new(filename => $patch);
- $patch_obj->apply($dir, add_options => ['-R', '-E']);
- $self->run_quilt($dir, ['fold'],
- from_file => "$absdir/debian/patches/$auto_patch",
- wait_child => 1, to_file => '/dev/null');
- }
+ add_line($series, $auto_patch);
+ add_line($applied, $auto_patch);
}
+ # Ensure quilt meta-data are created and in sync with some trickery:
+ # reverse-apply the patch, drop .pc/$patch, re-apply it
+ # with the correct options to recreate the backup files
+ my $patch_obj = Dpkg::Source::Patch->new(filename => $patch);
+ $patch_obj->apply($dir, add_options => ['-R', '-E']);
+ erasedir(File::Spec->catdir($dir, ".pc", $auto_patch));
+ $self->apply_quilt_patch($dir, $auto_patch);
} else {
# Remove auto_patch from series
if ($has_patch) {
- if ($self->{'options'}{'without_quilt'}) {
- open(SERIES, "<", $series) || syserr(_g("cannot read %s"), $series);
- my @lines = <SERIES>;
- close(SERIES);
- open(SERIES, ">", $series) || syserr(_g("cannot write %s"), $series);
- print(SERIES $_) foreach grep { not /^\Q$auto_patch\E\s*$/ } @lines;
- close(SERIES);
- } else {
- $self->run_quilt($dir, ['delete', $auto_patch],
- wait_child => 1, to_file => '/dev/null');
- }
+ drop_line($series, $auto_patch);
+ drop_line($applied, $auto_patch);
+ erasedir(File::Spec->catdir($dir, ".pc", $auto_patch));
}
# Clean up empty series
unlink($series) if not -s $series;
Reply to: