Package: release.debian.org Severity: normal User: release.debian....@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 <hert...@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 <hert...@debian.org> - +# Copyright © 2008-2009 Raphaël Hertzog <hert...@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;