in_workarea sub { playtree_setup };
}
+our @deferred_updates;
+our @deferred_update_messages;
+
+sub run_deferred_updates ($) {
+ my ($mrest) = @_;
+
+ my @upd_cmd = (@git, qw(update-ref --stdin -m), "debrebase: $mrest");
+ debugcmd '>|', @upd_cmd;
+ open U, "|-", @upd_cmd or die $!;
+ foreach (@deferred_updates) {
+ printdebug ">= ", $_, "\n";
+ print U $_, "\n" or die $!;
+ }
+ printdebug ">\$\n";
+ close U or failedcmd @upd_cmd;
+
+ print $_, "\n" foreach @deferred_update_messages;
+
+ @deferred_updates = ();
+ @deferred_update_messages = ();
+}
+
sub get_differs ($$) {
my ($x,$y) = @_;
# This resembles quiltify_trees_differ, in dgit, a bit.
return (Msg => $ms);
};
my $rewrite_from_here = sub {
+ my ($cl) = @_;
my $sp_cl = { SpecialMethod => 'StartRewrite' };
- push @brw_cl, $sp_cl;
+ push @$cl, $sp_cl;
push @processed, $sp_cl;
};
my $cur = $input;
my $p0 = @{ $cl->{Parents} }==1 ? $cl->{Parents}[0]{CommitId} : undef;
if ($ty eq 'AddPatches') {
$cur = $p0;
- $rewrite_from_here->();
+ $rewrite_from_here->(\@upp_cl);
next;
} elsif ($ty eq 'Packaging' or $ty eq 'Changelog') {
push @brw_cl, $cl;
};
$queue->(\@brw_cl, "debian");
$queue->(\@upp_cl, "upstream");
- $rewrite_from_here->();
+ $rewrite_from_here->(\@brw_cl);
$cur = $p0;
next;
} elsif ($ty eq 'Pseudomerge') {
my $contrib = $cl->{Contributor}{CommitId};
print $report " Contributor=$contrib" if $report;
push @pseudomerges, $cl;
- $rewrite_from_here->();
+ $rewrite_from_here->(\@upp_cl);
$cur = $contrib;
next;
} elsif ($ty eq 'Anchor') {
" anchor")
};
$prline->(" Import");
- $rewrite_from_here->();
+ $rewrite_from_here->(\@brw_cl);
$upp_limit //= $#upp_cl; # further, deeper, patches discarded
$cur = $ovwr;
next;
sub update_head ($$$) {
my ($old, $new, $mrest) = @_;
- runcmd @git, qw(update-ref -m), "debrebase: $mrest", 'HEAD', $new, $old;
+ push @deferred_updates, "update HEAD $new $old";
+ run_deferred_updates $mrest;
}
sub update_head_checkout ($$$) {
sub defaultcmd_rebase () {
my $old = get_head();
- my ($status, $message) = record_ffq_prev();
- if ($status eq 'written' || $status eq 'exists') {
+ my ($status, $message) = record_ffq_prev_deferred();
+ if ($status eq 'deferred' || $status eq 'exists') {
} else {
fproblem $status, "could not record ffq-prev: $message";
fproblems_maybe_bail();
return ('branch', undef, $current, $ffq_prev);
}
-sub record_ffq_prev () {
+sub record_ffq_prev_deferred () {
# => ('status', "message")
# 'status' may be
- # written message is undef
+ # deferred message is undef
# exists
# detached
# weird-symref
# notbranch
# if not ff from some branch we should be ff from, is an fproblem
- # if "written", will have printed something about that to stdout,
- # and also some messages about ff checks
+ # if "deferred", will have added something about that to
+ # @deferred_update_messages, and also maybe printed (already)
+ # some messages about ff checks
my ($status, $message, $current, $ffq_prev) = ffq_prev_branchinfo();
return ($status, $message) unless $status eq 'branch';
}
fproblems_maybe_bail();
- runcmd @git, qw(update-ref -m), "record current head for preservation",
- $ffq_prev, $currentval, $git_null_obj;
- print "Recorded current head for preservation\n" or die $!;
- return ('written', undef);
+
+ push @deferred_updates, "update $ffq_prev $currentval $git_null_obj";
+ push @deferred_update_messages, "Recorded current head for preservation";
+ return ('deferred', undef);
}
sub cmd_new_upstream_v0 () {
sub cmd_record_ffq_prev () {
badusage "no arguments allowed" if @ARGV;
- my ($status, $msg) = record_ffq_prev();
+ my ($status, $msg) = record_ffq_prev_deferred();
if ($status eq 'exists' && $opt_noop_ok) {
print "Previous head already recorded\n" or die $!;
- } elsif ($status eq 'written') {
+ } elsif ($status eq 'deferred') {
+ run_deferred_updates 'record-ffq-prev';
} else {
fail "Could not preserve: $msg";
}
if (!$prev) {
fail "No ffq-prev to stitch." unless $opt_noop_ok;
}
- fresh_workarea();
+ push @deferred_updates, "delete $ffq_prev $prev";
+
my $old_head = get_head();
+ if (is_fast_fwd $old_head, $prev) {
+ my $differs = get_differs $old_head, $prev;
+ unless ($differs & ~D_PAT_ADD) {
+ # ffq-prev is ahead of us, and the only tree changes it has
+ # are possibly addition of things in debian/patches/.
+ # Just wind forwards rather than making a pointless pseudomerge.
+ update_head_checkout $old_head, $prev, "stitch (fast forward)";
+ return;
+ }
+ }
+ fresh_workarea();
my $new_head = make_commit [ $old_head, $ffq_prev ], [
'Declare fast forward / record previous work',
"[git-debrebase pseudomerge: stitch$prose]",
];
- my @upd_cmd = (@git, qw(update-ref --stdin));
- debugcmd '>|', @upd_cmd;
- open U, "|-", @upd_cmd or die $!;
- my $u = <<END;
-update HEAD $new_head $old_head
-delete $ffq_prev $prev
-END
- printdebug ">= ", $_, "\n" foreach split /\n/, $u;
- print U $u;
- printdebug ">\$\n";
- close U or failedcmd @upd_cmd;
+ update_head $old_head, $new_head, "stitch";
}
sub cmd_convert_from_gbp () {
];
};
if (defined $ffq) {
- runcmd @git, qw(update-ref -m),
- "debrebase: converting corresponding main branch to gbp format",
- $ffq, $git_null_obj;
+ push @deferred_updates, "delete $ffq";
}
update_head_checkout $head, $out, "convert to gbp (v0)";
print <<END or die $!;