our $suite_re = '[-+.0-9a-z]+';
our $cleanmode_re = 'dpkg-source(?:-d)?|git|git-ff|check|none';
+our $git_authline_re = '^([^<>]+) \<(\S+)\> (\d+ [-+]\d+)$';
+
our (@git) = qw(git);
our (@dget) = qw(dget);
our (@curl) = qw(curl -f);
our (@dpkgsource) = qw(dpkg-source -i\.git/ -I.git);
our (@dpkggenchanges) = qw(dpkg-genchanges);
our (@mergechanges) = qw(mergechanges -f);
+our (@gbppq) = qw(gbp-pq);
our (@changesopts) = ('');
our %opts_opt_map = ('dget' => \@dget, # accept for compatibility
our $supplementary_message = '';
our $need_split_build_invocation = 0;
+our $split_brain = 0;
END {
local ($@, $?);
$author =~ s#,.*##ms;
my $date = cmdoutput qw(date), '+%s %z', qw(-d), getfield($clogp,'Date');
my $authline = "$author $date";
- $authline =~ m/^[^<>]+ \<\S+\> \d+ [-+]\d+$/ or
+ $authline =~ m/$git_authline_re/o or
fail "unexpected commit author line format \`$authline'".
" (was generated from changelog Maintainer field)";
+ return ($1,$2,$3) if wantarray;
return $authline;
}
}
}
-sub quiltify_trees_differ ($$;$) {
- my ($x,$y,$finegrained) = @_;
+sub quiltify_trees_differ ($$;$$) {
+ my ($x,$y,$finegrained,$ignorenamesr) = @_;
# returns true iff the two tree objects differ other than in debian/
# with $finegrained,
# returns bitmask 01 - differ in upstream files except .gitignore
# 02 - differ in .gitignore
+ # if $ignorenamesr is defined, $ingorenamesr->{$fn}
+ # is set for each modified .gitignore filename $fn
local $/=undef;
my @cmd = (@git, qw(diff-tree --name-only -z));
push @cmd, qw(-r) if $finegrained;
my $r = 0;
foreach my $f (split /\0/, $diffs) {
next if $f =~ m#^debian(?:/.*)?$#s;
- $r |= ($f =~ m#^(?:.*/)?.gitignore$#s) ? 02 : 01;
+ my $isignore = $f =~ m#^(?:.*/)?.gitignore$#s;
+ $r |= $isignore ? 02 : 01;
+ $ignorenamesr->{$f}=1 if $ignorenamesr && $isignore;
}
printdebug "quiltify_trees_differ $x $y => $r\n";
return $r;
qw(-- debian/rules debian/control);
$r =~ s/\n/,/g;
return $r;
-}
+ }
+
+sub quiltify_splitbrain_needed () {
+ if (!$split_brain) {
+ progress "creating dgit view";
+ runcmd @git, qw(checkout -q -b dgit-view);
+ $split_brain = 1;
+ }
+}
+
+sub quiltify_splitbrain ($$$$$) {
+ my ($clogp, $unapplied, $headref, $diffbits, $editedignores) = @_;
+ if ($quilt_mode !~ m/gbp|dpm/) {
+ # treat .gitignore just like any other upstream file
+ $diffbits = { %$diffbits };
+ $_ = !!$_ foreach values %$diffbits;
+ }
+ # We would like any commits we generate to be reproducible
+ my @authline = clogp_authline($clogp);
+ local $ENV{GIT_COMMITTER_NAME} = $authline[0];
+ local $ENV{GIT_COMMITTER_EMAIL} = $authline[1];
+ local $ENV{GIT_COMMITTER_DATE} = $authline[2];
+ if ($quilt_mode =~ m/gbp|unapplied/ &&
+ ($diffbits->{O2A} & 01) && # some patches
+ !($diffbits->{H2O} & 01)) { # but HEAD is like orig
+ quiltify_splitbrain_needed();
+ progress "creating patches-applied version using gbp-pq";
+ open STDOUT, ">/dev/null" or die $!;
+ runcmd shell_cmd 'exec >/dev/null', @gbppq, qw(import);
+ runcmd @git, qw(update-ref dgit-view HEAD);
+ runcmd @git, qw(checkout dgit-view);
+ }
+ if (($diffbits->{H2O} & 02) && # user has modified .gitignore
+ !($diffbits->{O2A} & 02)) { # patches do not change .gitignore
+ quiltify_splitbrain_needed();
+ progress "creating patch to represent .gitignore changes";
+ ensuredir "debian/patches";
+ my $gipatch = "debian/patches/auto-gitignore";
+ open GIPATCH, ">>", "$gipatch" or die "$gipatch: $!";
+ stat GIPATCH or die "$gipatch: $!";
+ fail "$gipatch already exists; but want to create it".
+ " to record .gitignore changes" if (stat _)[7];
+ print GIPATCH <<END or die "$gipatch: $!";
+Subject: Update .gitignore from Debian packaging branch
+
+The Debian packaging git branch contains these updates to the upstream
+.gitignore file(s). This patch is autogenerated, to provide these
+updates to users of the official Debian archive view of the package.
+
+[dgit version $our_version]
+---
+END
+ close GIPATCH or die "$gipatch: $!";
+ runcmd shell_cmd "exec >>$gipatch", @git, qw(diff),
+ $unapplied, $headref, "--", sort keys %$editedignores;
+ open SERIES, "+>>", "debian/patches/series" or die $!;
+ defined seek SERIES, -1, 2 or $!==EINVAL or die $!;
+ my $newline;
+ defined read SERIES, $newline, 1 or die $!;
+ print SERIES "\n" or die $! unless $newline eq "\n";
+ print SERIES "auto-gitignore\n" or die $!;
+ close SERIES or die $!;
+ runcmd @git, qw(add -- debian/patches/series), $gipatch;
+ commit_admin "Commit patch to update .gitignore";
+ }
-sub quiltify_splitbrain ($) {
- my ($diffbits) = @_;
- # memoisation via git-reflog
- my $may_apply = $quilt_mode =~ m/gbp|unapplied/;
- die "xxx not yet implemented";
-# if ($may_apply &&
-# quiltify_trees_differ($userhead,)) {}
+ die 'xxx memoisation via git-reflog';
+ die 'xxx fast forward (should not depend on quilt mode, but will always be needed if we did $split_brain)';
}
sub quiltify ($$$$) {
rmtree '.pc';
runcmd @git, qw(add -Af .);
my $oldtiptree=git_write_tree();
+ printdebug "fake o+d/p tree object $unapplied\n";
changedir '../work';
# We calculate some guesswork now about what kind of tree this might
# be. This is mostly for error reporting.
+ my %editedignores;
my $diffbits = {
# H = user's HEAD
# O = orig, without patches applied
# A = "applied", ie orig with H's debian/patches applied
- H2O => quiltify_trees_differ($headref, $unapplied, 1),
+ H2O => quiltify_trees_differ($headref, $unapplied, 1,\%editedignores),
H2A => quiltify_trees_differ($headref, $oldtiptree,1),
O2A => quiltify_trees_differ($unapplied,$oldtiptree,1),
};
push @failsuggestion, "Maybe you need to specify one of".
" --quilt=gbp --quilt=dpm --quilt=unapplied ?";
- if ($quilt_mode =~ m/gbp|dpm|apply/) {
- quiltify_splitbrain($diffbits);
+ if ($quilt_mode =~ m/gbp|dpm|unapplied/) {
+ quiltify_splitbrain($clogp, $unapplied, $headref,
+ $diffbits, \%editedignores);
return;
}