|
|
@@ -0,0 +1,155 @@
|
|
|
+# Copyright 2008 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
|
|
|
+# (at your option) any later version.
|
|
|
+
|
|
|
+# This program is distributed in the hope that it will be useful,
|
|
|
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+# GNU General Public License for more details.
|
|
|
+
|
|
|
+# You should have received a copy of the GNU General Public License along
|
|
|
+# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
+
|
|
|
+package Dpkg::Source::Package::V3_0::quilt;
|
|
|
+
|
|
|
+use strict;
|
|
|
+use warnings;
|
|
|
+
|
|
|
+# Based on wig&pen implementation
|
|
|
+use base 'Dpkg::Source::Package::V2_0';
|
|
|
+
|
|
|
+use Dpkg;
|
|
|
+use Dpkg::Gettext;
|
|
|
+use Dpkg::ErrorHandling qw(error syserr warning usageerr subprocerr info);
|
|
|
+use Dpkg::Source::Patch;
|
|
|
+use Dpkg::IPC;
|
|
|
+
|
|
|
+use File::Basename;
|
|
|
+use File::Spec;
|
|
|
+
|
|
|
+sub get_autopatch_name {
|
|
|
+ my ($self) = @_;
|
|
|
+ return "debian-changes-" . $self->{'fields'}{'Version'} . ".diff";
|
|
|
+}
|
|
|
+
|
|
|
+sub get_series_file {
|
|
|
+ my ($self, $dir) = @_;
|
|
|
+ my $pd = File::Spec->catdir($dir, "debian", "patches");
|
|
|
+ # TODO: replace "debian" with the current distro name once we have a
|
|
|
+ # way to figure it out
|
|
|
+ foreach (File::Spec->catfile($pd, "debian.series"),
|
|
|
+ File::Spec->catfile($pd, "series")) {
|
|
|
+ return $_ if -e $_;
|
|
|
+ }
|
|
|
+ return undef;
|
|
|
+}
|
|
|
+
|
|
|
+sub get_patches {
|
|
|
+ my ($self, $dir, $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 trailing comment
|
|
|
+ next unless $_;
|
|
|
+ next if $skip_auto and $_ eq $auto_patch;
|
|
|
+ push @patches, $_;
|
|
|
+ }
|
|
|
+ close(SERIES);
|
|
|
+ }
|
|
|
+ return @patches;
|
|
|
+}
|
|
|
+
|
|
|
+sub apply_patches {
|
|
|
+ my ($self, $dir, $skip_auto) = @_;
|
|
|
+
|
|
|
+ # Update debian/patches/series symlink if needed to allow quilt usage
|
|
|
+ my $series = $self->get_series_file($dir);
|
|
|
+ return unless $series; # No series, no patches
|
|
|
+ my $basename = basename($series);
|
|
|
+ if ($basename ne "series") {
|
|
|
+ my $dest = File::Spec->catfile($dir, "debian", "patches", "series");
|
|
|
+ unlink($dest) if -l $dest;
|
|
|
+ unless (-f _) { # Don't overwrite real files
|
|
|
+ symlink($basename, $dest) ||
|
|
|
+ syserr(_g("can't create symlink %s"), $dest);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # Apply patches
|
|
|
+ my $now = time();
|
|
|
+ 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;
|
|
|
+ my $patch_obj = Dpkg::Source::Patch->new(filename => $path);
|
|
|
+ my $analysis = $patch_obj->analyze($dir);
|
|
|
+ foreach my $dir (keys %{$analysis->{'dirtocreate'}}) {
|
|
|
+ eval { mkpath($dir); };
|
|
|
+ syserr(_g("cannot create directory %s"), $dir) if $@;
|
|
|
+ }
|
|
|
+ my %opts = (
|
|
|
+ env => { QUILT_PATCHES => 'debian/patches' },
|
|
|
+ delete_env => [ 'QUILT_PATCH_OPTS' ],
|
|
|
+ 'chdir' => $dir,
|
|
|
+ 'exec' => [ 'quilt', '--quiltrc', '/dev/null', 'push', $patch ],
|
|
|
+ wait_child => 1,
|
|
|
+ to_file => '/dev/null',
|
|
|
+ );
|
|
|
+ fork_and_exec(%opts);
|
|
|
+ foreach my $fn (keys %{$analysis->{'filepatched'}}) {
|
|
|
+ utime($now, $now, $fn) ||
|
|
|
+ syserr(_g("cannot change timestamp for %s"), $fn);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+sub prepare_build {
|
|
|
+ my ($self, $dir) = @_;
|
|
|
+ # Skip .pc directories of quilt by default and ignore difference
|
|
|
+ # on debian/patches/series symlinks
|
|
|
+ my $func = sub {
|
|
|
+ return 1 if $_[0] =~ m{^debian/patches/series$} and -l $_[0];
|
|
|
+ return 1 if $_[0] =~ /^.pc(\/|$)/;
|
|
|
+ return 1 if $_[0] =~ /$self->{'options'}{'diff_ignore_regexp'}/;
|
|
|
+ return 0;
|
|
|
+ };
|
|
|
+ $self->{'diff_options'} = {
|
|
|
+ diff_ignore_func => $func
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+sub register_autopatch {
|
|
|
+ my ($self, $dir) = @_;
|
|
|
+ my $auto_patch = $self->get_autopatch_name();
|
|
|
+ my $has_patch = grep(/\/\Q$auto_patch\E$/, $self->get_patches($dir)) ? 1 : 0;
|
|
|
+ my $series = $self->get_series_file($dir);
|
|
|
+ $series ||= File::Spec->catfile($dir, "debian", "patches", "series");
|
|
|
+ if (-e "$dir/debian/patches/$auto_patch") {
|
|
|
+ # Add auto_patch to series file
|
|
|
+ if (not $has_patch) {
|
|
|
+ open(SERIES, ">>", $series) || syserr(_g("cannot write %s"), $series);
|
|
|
+ print SERIES "$auto_patch\n";
|
|
|
+ close(SERIES);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ # Remove auto_patch from series
|
|
|
+ if ($has_patch) {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# vim:et:sw=4:ts=8
|
|
|
+1;
|