+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
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).
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
\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
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
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 {
} elsif ($opt =~ /^--include-binaries$/) {
$self->{'options'}{'include_binaries'} = 1;
return 1;
+ } elsif ($opt =~ /^--no-preparation$/) {
+ $self->{'options'}{'preparation'} = 0;
+ return 1;
}
return 0;
}
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;
$patch_obj->apply($dir, force_timestamp => 1,
timestamp => $timestamp,
add_options => [ '-E' ]);
+ print APPLIED "$patch\n";
}
+ close(APPLIED);
}
sub can_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();
}
# 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);
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;
$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();