return () if $type eq 'missing';
}
+ confess "get_tree needs object not $x ?" unless $x =~ m{^[0-9a-f]+\:};
+
our (@get_tree_memo, %get_tree_memo);
my $memo = $get_tree_memo{$x};
return @$memo if $memo;
return $snags_forced || $snags_tripped;
}
+sub ffq_prev_branchinfo () {
+ my $current = git_get_symref();
+ return gdr_ffq_prev_branchinfo($current);
+}
+
+sub record_gdrlast ($$;$) {
+ my ($gdrlast, $newvalue, $oldvalue) = @_;
+ $oldvalue ||= $git_null_obj;
+ push @deferred_updates, "update $gdrlast $newvalue $oldvalue";
+}
+
+sub fail_unprocessable ($) {
+ my ($msg) = @_;
+ changedir $maindir;
+ my ($ffqs, $ffqm, $symref, $ffq_prev, $gdrlast) = ffq_prev_branchinfo();
+
+ my $mangled = <<END;
+Branch/history seems mangled - no longer in gdr format.
+See ILLEGAL OPERATIONS in git-debrebase(5).
+END
+ chomp $mangled;
+
+ if (defined $ffqm) {
+ fail <<END;
+$msg
+Is this meant to be a gdr branch? $ffqm
+END
+ } elsif (git_get_ref $ffq_prev) {
+ fail <<END;
+$msg
+$mangled
+Consider git-debrebase scrap, to throw away your recent work.
+END
+ } elsif (!git_get_ref $gdrlast) {
+ fail <<END;
+$msg
+Branch does not seem to be meant to be a git-debrebase branch?
+Wrong branch, or maybe you needed git-debrebase convert-from-*.
+END
+ } elsif (is_fast_fwd $gdrlast, git_rev_parse 'HEAD') {
+ fail <<END;
+$msg
+$mangled
+END
+ } else {
+ fail <<END;
+$msg
+Branch/history mangled, and diverged since last git-debrebase.
+Maybe you reset to, or rebased from, somewhere inappropriate.
+END
+ }
+};
+
sub gbp_pq_export ($$$) {
my ($bname, $base, $tip) = @_;
# must be run in a workarea. $bname and patch-queue/$bname
runcmd @git, qw(checkout -q -b mergec), $merged_pq;
merge_attempt_cmd($wrecknotes, qw(gbp pq import));
+ # MERGE-TODO consider git-format-patch etc. instead,
+ # since gbp pq doesn't always round-trip :-/
# OK now we are on patch-queue/merge, and we need to rebase
# onto the intended parent and drop the patches from each one
my $clogonly;
my $cl;
my $found_pm;
- $fatal //= sub { fail $_[1]; };
+ $fatal //= sub { fail_unprocessable $_[1]; };
my $x = sub {
my ($cb, $tagsfx, $mainwhy, $xwhy) = @_;
my $why = $mainwhy.$xwhy;
if ($nogenerate) {
return (undef,undef);
}
- fail "found unprocessable commit, cannot cope".
+ fail_unprocessable "found unprocessable commit, cannot cope".
(defined $cl->{Why} ? "; $cl->{Why}:": ':').
" (commit $cur) (d.".
(join ' ', map { sprintf "%#x", $_->{Differs} }
STDOUT->error and die $!;
}
-sub ffq_prev_branchinfo () {
- my $current = git_get_symref();
- return gdr_ffq_prev_branchinfo($current);
-}
-
sub ffq_check ($;$$) {
# calls $ff and/or $notff zero or more times
# then returns either (status,message) where status is
# 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.
- push @deferred_updates,
- "update $gdrlast $ffq_prev_commitish $git_null_obj";
+ record_gdrlast $gdrlast, $ffq_prev_commitish;
update_head_checkout $old_head, $ffq_prev_commitish,
"stitch (fast forward)";
return;
'Declare fast forward / record previous work',
"[git-debrebase pseudomerge: $prose]",
];
- push @deferred_updates, "update $gdrlast $new_head $git_null_obj";
+ record_gdrlast $gdrlast, $new_head;
update_head $old_head, $new_head, "stitch: $prose";
}
}
}
+sub begin_convert_from () {
+ my $head = get_head();
+ my ($ffqs, $ffqm, $symref, $ffq_prev, $gdrlast) = ffq_prev_branchinfo();
+
+ fail "ffq-prev exists, this is already managed by git-debrebase!"
+ if $ffq_prev && git_get_ref $ffq_prev;
+
+ my $gdrlast_obj = $gdrlast && git_get_ref $gdrlast;
+ snag 'already-converted',
+ "ahead of debrebase-last, this is already managed by git-debrebase!"
+ if $gdrlast_obj && is_fast_fwd $gdrlast_obj, $head;
+ return ($head, { LastRef => $gdrlast, LastObj => $gdrlast_obj });
+}
+
+sub complete_convert_from ($$$$) {
+ my ($old_head, $new_head, $gi, $mrest) = @_;
+ ffq_check $new_head;
+ record_gdrlast $gi->{LastRef}, $new_head, $gi->{LastObj}
+ if $gi->{LastRef};
+ snags_maybe_bail();
+ update_head_checkout $old_head, $new_head, $mrest;
+}
+
sub cmd_convert_from_gbp () {
badusage "want only 1 optional argument, the upstream git commitish"
unless @ARGV<=1;
my $upstream =
resolve_upstream_version($upstream_spec, $upstream_version);
- my $old_head = get_head();
+ my ($old_head, $gdrlastinfo) = begin_convert_from();
my $upsdiff = get_differs $upstream, $old_head;
if ($upsdiff & D_UPS) {
}
};
- ffq_check $work;
- snags_maybe_bail();
- update_head_checkout $old_head, $work, 'convert-from-gbp';
+ complete_convert_from $old_head, $work, $gdrlastinfo, 'convert-from-gbp';
print <<END or die $!;
git-debrebase: converted from patched-unapplied (gbp) branch format, OK
END
};
}
- my $head = get_head();
+ my ($head, $gdrlastinfo) = begin_convert_from();
if (!$always) {
my $troubles = 0;
printf STDERR "Yes, will base new branch on %s\n", $result->{Source};
- ffq_check $result->{Result};
- snags_maybe_bail();
- update_head_checkout $head, $result->{Result},
+ complete_convert_from $head, $result->{Result}, $gdrlastinfo,
'convert-from-dgit-view';
}