chiark / gitweb /
FIX
[dgit.git] / git-debrebase
index 2fa8cf479cf147be232acbbc91764b0384d0f575..f0cd2c88630375e89fcf00b4051346494cead12c 100755 (executable)
@@ -40,14 +40,14 @@ use File::Copy;
 
 $debugcmd_when_debuglevel = 2;
 
-our ($usage_message) = <<'END';
+our ($usage_message) = i_ <<'END';
 usages:
   git-debrebase [<options>] [--|-i <git rebase options...>]
   git-debrebase [<options>] status
   git-debrebase [<options>] prepush [--prose=...]
   git-debrebase [<options>] quick|conclude
   git-debrebase [<options>] new-upstream <new-version> [<details ...>]
-  git-debrebase [<options>] convert-from-gbp [<upstream-commitish>]
+  git-debrebase [<options>] convert-from-* ...
   ...
 See git-debrebase(1), git-debrebase(5), dgit-maint-debrebase(7) (in dgit).
 END
@@ -64,7 +64,7 @@ $|=1;
 
 sub badusage ($) {
     my ($m) = @_;
-    print STDERR "$us: bad usage: $m\n";
+    print STDERR f_ "%s: bad usage: %s\n", $us, $m;
     finish 8;
 }
 
@@ -75,7 +75,7 @@ sub getoptions_main {
 }
 sub getoptions {
     my $sc = shift;
-    getoptions_main "bad options follow \`git-debrebase $sc'", @_;
+    getoptions_main +(f_ "bad options follow \`git-debrebase %s'", $sc), @_;
 }
 
 sub cfg ($;$) {
@@ -86,7 +86,7 @@ sub cfg ($;$) {
     push @cmd, $k;
     my $out = cmdoutput_errok @cmd;
     if (!defined $out) {
-       fail "missing required git config $k" unless $optional;
+       fail f_ "missing required git config %s", $k unless $optional;
        return ();
     }
     my @l = split /\0/, $out;
@@ -173,7 +173,8 @@ sub all_snags_summarised () {
 sub run_deferred_updates ($) {
     my ($mrest) = @_;
 
-    confess 'dangerous internal error' unless all_snags_summarised();
+    my $m = 'dangerous internal error';
+    confess $m.' - '.__ $m unless all_snags_summarised();
 
     merge_wreckage_cleaning \@deferred_updates;
     run_ref_updates_now $mrest, \@deferred_updates;
@@ -397,10 +398,10 @@ sub snag ($$;@) {
     my ($tag,$msg) = @_; # ignores extra args, for benefit of keycommits
     if (grep { $_ eq $tag } @snag_force_opts) {
        $snags_forced++;
-       print STDERR "$us: snag ignored (-f$tag): $msg\n";
+       print STDERR f_ "%s: snag ignored (-f%s): %s\n", $us, $tag, $msg;
     } else {
        $snags_tripped++;
-       print STDERR "$us: snag detected (-f$tag): $msg\n";
+       print STDERR f_ "%s: snag detected (-f%s): %s\n", $us, $tag, $msg;
     }
 }
 
@@ -412,17 +413,17 @@ sub snag ($$;@) {
 sub snags_maybe_bail () {
     return if all_snags_summarised();
     if ($snags_forced) {
-       printf STDERR
+       print STDERR f_
            "%s: snags: %d overriden by individual -f options\n",
            $us, $snags_forced;
     }
     if ($snags_tripped) {
        if ($opt_force) {
-           printf STDERR
+           print STDERR f_
                "%s: snags: %d overriden by global --force\n",
                $us, $snags_tripped;
        } else {
-           fail sprintf
+           fail f_
   "%s: snags: %d blocker(s) (you could -f<tag>, or --force)",
                $us, $snags_tripped;
        }
@@ -454,26 +455,26 @@ sub fail_unprocessable ($) {
     changedir $maindir;
     my ($ffqs, $ffqm, $symref, $ffq_prev, $gdrlast) = ffq_prev_branchinfo();
 
-    my $mangled = <<END;
+    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
+       fail f_ <<END, $msg, $ffqm;
+%s
+Is this meant to be a gdr branch?  %s
 END
     } elsif (git_get_ref $ffq_prev) {
-       fail <<END;
-$msg
-$mangled
+       fail f_ <<END, $msg, $mangled;
+%s
+%s
 Consider git-debrebase scrap, to throw away your recent work.
 END
     } elsif (!git_get_ref $gdrlast) {
-       fail <<END;
-$msg
+       fail f_ <<END, $msg;
+%s
 Branch does not seem to be meant to be a git-debrebase branch?
 Wrong branch, or maybe you needed git-debrebase convert-from-*.
 END
@@ -483,8 +484,8 @@ $msg
 $mangled
 END
     } else {
-       fail <<END;
-$msg
+       fail f_ <<END, $msg;
+%s
 Branch/history mangled, and diverged since last git-debrebase.
 Maybe you reset to, or rebased from, somewhere inappropriate.
 END
@@ -930,9 +931,11 @@ sub classify ($) {
        # reject it here then we avoid making the pseudomerge which
        # would be needed to push it.
 
-       my $badanchor = sub { $unknown->("git-debrebase \`anchor' but @_"); };
-       @p == 2 or return $badanchor->("has other than two parents");
-       $haspatches and return $badanchor->("contains debian/patches");
+       my $badanchor = sub {
+           $unknown->(f_ "git-debrebase \`anchor' but %s", "@_");
+       };
+       @p == 2 or return $badanchor->(__ "has other than two parents");
+       $haspatches and return $badanchor->(__ "contains debian/patches");
 
        # How to decide about l/r ordering of anchors ?  git
        # --topo-order prefers to expand 2nd parent first.  There's
@@ -958,11 +961,11 @@ sub classify ($) {
        # parents from left to right, in order, so it's easy to see
        # which way round a pseudomerge is.
 
-       $p[0]{IsOrigin} and $badanchor->("is an origin commit");
+       $p[0]{IsOrigin} and $badanchor->(__ "is an origin commit");
        $p[1]{Differs} & ~DS_DEB and
-           $badanchor->("upstream files differ from left parent");
+           $badanchor->(__ "upstream files differ from left parent");
        $p[0]{Differs} & ~D_UPS and
-           $badanchor->("debian/ differs from right parent");
+           $badanchor->(__ "debian/ differs from right parent");
 
        return $classify->(qw(Anchor),
                           OrigParents => [ $p[1] ]);
@@ -973,7 +976,7 @@ sub classify ($) {
        if ($d == D_PAT_ADD) {
            return $classify->(qw(AddPatches));
        } elsif ($d & (D_PAT_ADD|D_PAT_OTH)) {
-           return $unknown->("edits debian/patches");
+           return $unknown->(__ "edits debian/patches");
        } elsif ($d & DS_DEB and !($d & ~DS_DEB)) {
            my ($ty,$dummy) = git_cat_file "$p[0]{CommitId}:debian";
            if ($ty eq 'tree') {
@@ -985,20 +988,20 @@ sub classify ($) {
            } elsif ($ty eq 'missing') {
                return $classify->(qw(BreakwaterStart));
            } else {
-               return $unknown->("parent's debian is not a directory");
+               return $unknown->(__ "parent's debian is not a directory");
            }
        } elsif ($d == D_UPS) {
            return $classify->(qw(Upstream));
        } elsif ($d & DS_DEB and $d & D_UPS and !($d & ~(DS_DEB|D_UPS))) {
            return $classify->(qw(Mixed));
        } elsif ($d == 0) {
-           return $unknown->("no changes");
+           return $unknown->(__ "no changes");
        } else {
            confess "internal error $objid ?";
        }
     }
     if (!@p) {
-       return $unknown->("origin commit");
+       return $unknown->(__ "origin commit");
     }
 
     if (@p == 2 && @identical == 1) {
@@ -1049,14 +1052,14 @@ sub classify ($) {
        return $classify->("MergedBreakwaters");
     }
     if ($r->{Msg} =~ m{^\[(git-debrebase|dgit)[: ].*\]$}m) {
-       return $unknown->("unknown kind of merge from $1");
+       return $unknown->(f_ "unknown kind of merge from %s", $1);
     }
     if (@p > 2) {
-       return $unknown->("octopus merge");
+       return $unknown->(__ "octopus merge");
     }
 
     if (!$opt_merges) {
-       return $unknown->("general two-parent merge");
+       return $unknown->(__ "general two-parent merge");
     }
 
     return $classify->("VanillaMerge");
@@ -1073,7 +1076,8 @@ sub mergedbreakwaters_anchor ($) {
        $best_anchor = $panchor
            if !defined $best_anchor
            or is_fast_fwd $best_anchor, $panchor;
-       fail "inconsistent anchors in merged-breakwaters $p->{CommitId}"
+       fail f_ "inconsistent anchors in merged-breakwaters %s",
+           $p->{CommitId}
            unless is_fast_fwd $panchor, $best_anchor;
     }
     return $best_anchor;
@@ -1112,7 +1116,7 @@ sub keycommits ($;$$$$$) {
     my $x = sub {
        my ($cb, $tagsfx, $mainwhy, $xwhy) = @_;
        my $why = $mainwhy.$xwhy;
-       my $m = "branch needs laundering (run git-debrebase): $why";
+       my $m = f_ "branch needs laundering (run git-debrebase): %s", $why;
        fail $m unless defined $cb;
        return unless $cb;
        $cb->("unclean-$tagsfx", $why, $cl, $mainwhy);
@@ -1140,41 +1144,47 @@ sub keycommits ($;$$$$$) {
            $found_anchor->($head);
        } elsif ($ty eq 'Upstream') {
            $x->($unclean, 'ordering',
- "packaging change ($breakwater) follows upstream change"," (eg $head)")
+ (f_ "packaging change (%s) follows upstream change", $breakwater),
+                (f_ " (eg %s)", $head))
                if defined $breakwater;
            $clogonly = undef;
            $breakwater = undef;
        } elsif ($ty eq 'Mixed') {
            $x->($unclean, 'mixed',
-                "found mixed upstream/packaging commit"," ($head)");
+                (__ "found mixed upstream/packaging commit"),
+                (f_ " (%s)", $head));
            $clogonly = undef;
            $breakwater = undef;
        } elsif ($ty eq 'Pseudomerge' or
                 $ty eq 'AddPatches') {
            my $found_pm = 1;
            $x->($furniture, (lc $ty),
-                "found interchange bureaucracy commit ($ty)"," ($head)");
+                (f_ "found interchange bureaucracy commit (%s)", $ty),
+                (f_ " (%s)", $head));
        } elsif ($ty eq 'DgitImportUnpatched') {
            if ($found_pm) {
                $x->($trouble, 'dgitimport',
-                    "found dgit dsc import"," ($head)");
+                    (__ "found dgit dsc import"),
+                    (f_ " (%s)", $head));
                return (undef,undef);
            } else {
                $x->($fatal, 'unprocessable',
-                    "found bare dgit dsc import with no prior history",
-                    " ($head)");
+                    (__ "found bare dgit dsc import with no prior history"),
+                    (f_ " (%s)", $head));
                return (undef,undef);
            }
        } elsif ($ty eq 'VanillaMerge') {
            $x->($trouble, 'vanillamerge',
-                "found vanilla merge"," ($head)");
+                (__ "found vanilla merge"),
+                (f_ " (%s)", $head));
            return (undef,undef);
        } elsif ($ty eq 'MergedBreakwaters') {
            $found_anchor->(mergedbreakwaters_anchor $cl);
        } else {
            $x->($fatal, 'unprocessable',
-                "found unprocessable commit, cannot cope: $cl->{Why}",
-                " ($head)");
+                (f_ "found unprocessable commit, cannot cope: %s",
+                    $cl->{Why}),
+                (f_ " (%s)", $head));
            return (undef,undef);
        }
        $head = $cl->{Parents}[0]{CommitId};
@@ -1203,6 +1213,8 @@ sub walk ($;$$$) {
     my $cl;
     my $xmsg = sub {
        my ($prose, $info) = @_;
+       # We deliberately do not translate $prose, since this mostly
+       # appears in commits in Debian and they should be in English.
        my $ms = $cl->{Msg};
        chomp $ms;
        confess unless defined $info;
@@ -1233,12 +1245,14 @@ sub walk ($;$$$) {
        if ($nogenerate) {
            return (undef,undef);
        }
-       fail_unprocessable "found unprocessable commit, cannot cope".
-           (defined $cl->{Why} ? "; $cl->{Why}:": ':').
-           " (commit $cur) (d.".
-           (join ' ', map { sprintf "%#x", $_->{Differs} }
-            @{ $cl->{Parents} }).
-                ")";
+       my $d =
+           join ' ',
+           map { sprintf "%#x", $_->{Differs} }
+           @{ $cl->{Parents} };
+       fail_unprocessable f_ +(defined $cl->{Why}
+ ? i_ 'found unprocessable commit, cannot cope; %3$s: (commit %1$s) (d.%2$s)'
+ : i_ 'found unprocessable commit, cannot cope: (commit %1$s) (d.%2$s)'),
+                                   $cur, $d, $cl->{Why};
     };
 
     my $build;
@@ -1358,7 +1372,7 @@ sub walk ($;$$$) {
                # patches as commits.  Unfortunately it contains
                # debian/patches/.
                printdebug "*** WALK BOMB bare dgit import\n";
-               $cl->{Why} = "bare dgit dsc import";
+               $cl->{Why} = __ "bare dgit dsc import";
                return $bomb->();
            }
            confess "$ty ?";
@@ -1569,7 +1583,7 @@ sub walk ($;$$$) {
 
     printdebug "WALK REBUILD $build ".(scalar @processed)."\n";
 
-    confess "internal error" unless $build eq (pop @processed)->{CommitId};
+    confess __ "internal error" unless $build eq (pop @processed)->{CommitId};
 
     in_workarea sub {
        mkdir $rd or $!==EEXIST or confess $!;
@@ -1698,13 +1712,13 @@ sub walk ($;$$$) {
                    my ($n) = @_;
                    no warnings qw(exiting);
                    next if $n eq 'debian/';
-                   confess "mismatch @_ ?";
+                   confess f_ "mismatch %s ?", "@_";
                };
                trees_diff_walk "$want_debian:debian", "$build:debian", sub {
-                   confess "mismatch @_ ?";
+                   confess f_ "mismatch %s ?", "@_";
                };
                my @old_parents = map { $_->{CommitId} } @{ $cl->{Parents} };
-               confess "mismatch @parents != @old_parents ?"
+               confess f_ "mismatch %s != %s ?", "@parents", "@old_parents"
                    unless "@parents" eq "@old_parents";
            }
             if (grep { $method eq $_ } qw(DgitImportUpstreamUpdate)) {
@@ -1714,7 +1728,7 @@ sub walk ($;$$$) {
     };
 
     my $final_check = get_differs $build, $input;
-    confess sprintf "internal error %#x %s %s", $final_check, $input, $build
+    confess f_ "internal error %#x %s %s", $final_check, $input, $build
        if $final_check & ~D_PAT_ADD;
 
     my @r = ($build, $breakwater, $last_anchor);
@@ -1742,7 +1756,7 @@ sub update_head_checkout ($$$) {
 sub update_head_postlaunder ($$$) {
     my ($old, $tip, $reflogmsg) = @_;
     return if $tip eq $old && !@deferred_updates;
-    print "$us: laundered (head was $old)\n";
+    print f_ "%s: laundered (head was %s)\n", $us, $old;
     update_head $old, $tip, $reflogmsg;
     # no tree changes except debian/patches
     runcmd @git, qw(rm --quiet --ignore-unmatch -rf debian/patches);
@@ -1756,7 +1770,7 @@ sub currently_rebasing() {
 }
 
 sub bail_if_rebasing() {
-    fail "you are in the middle of a git-rebase already"
+    fail __ "you are in the middle of a git-rebase already"
        if currently_rebasing();
 }
 
@@ -1782,14 +1796,14 @@ sub cmd_launder_v0 () {
 
 sub defaultcmd_rebase () {
     push @ARGV, @{ $opt_defaultcmd_interactive // [] };
-    my ($tip,$breakwater) = do_launder_head 'launder for rebase';
+    my ($tip,$breakwater) = do_launder_head __ 'launder for rebase';
     runcmd @git, qw(rebase), @ARGV, $breakwater if @ARGV;
 }
 
 sub cmd_analyse () {
-    badusage "analyse does not support any options"
+    badusage __ "analyse does not support any options"
        if @ARGV and $ARGV[0] =~ m/^-/;
-    badusage "too many arguments to analyse" if @ARGV>1;
+    badusage __ "too many arguments to analyse" if @ARGV>1;
     my ($old) = @ARGV;
     if (defined $old) {
        $old = git_rev_parse $old;
@@ -1822,9 +1836,9 @@ sub ffq_check ($;$$) {
     return ($status, $message) unless $status eq 'branch';
 
     my $exists = git_get_ref $ffq_prev;
-    return ('exists',"$ffq_prev already exists") if $exists;
+    return ('exists', f_ "%s already exists", $ffq_prev) if $exists;
 
-    return ('not-branch', 'HEAD symref is not to refs/heads/')
+    return ('not-branch', __ 'HEAD symref is not to refs/heads/')
        unless $current =~ m{^refs/heads/};
     my $branch = $';
 
@@ -1847,14 +1861,15 @@ sub ffq_check ($;$$) {
        return unless length $lrval;
 
        if (is_fast_fwd $lrval, $currentval) {
-           $ff->("OK, you are ahead of $lrref\n");
+           $ff->(f_ "OK, you are ahead of %s\n", $lrref);
            $checked{$lrref} = 1;
        } elsif (is_fast_fwd $currentval, $lrval) {
            $checked{$lrref} = -1;
-           $notff->('behind', "you are behind $lrref, divergence risk");
+           $notff->('behind', f_ "you are behind %s, divergence risk",
+                                 $lrref);
        } else {
            $checked{$lrref} = -1;
-           $notff->('diverged', "you have diverged from $lrref");
+           $notff->('diverged', f_ "you have diverged from %s", $lrref);
        }
     };
 
@@ -1875,9 +1890,11 @@ sub ffq_check ($;$$) {
                        'remote push branch');
     }
     if ($branch =~ m{^dgit/}) {
-       $check->("refs/remotes/dgit/$branch", 'remote dgit branch');
+       $check->("refs/remotes/dgit/$branch",
+                __ 'remote dgit branch');
     } elsif ($branch =~ m{^master$}) {
-       $check->("refs/remotes/dgit/dgit/sid", 'remote dgit branch for sid');
+       $check->("refs/remotes/dgit/dgit/sid",
+                __ 'remote dgit branch for sid');
     }
     return (undef, undef, $ffq_prev, $gdrlast);
 }
@@ -1904,7 +1921,8 @@ sub record_ffq_prev_deferred () {
 
     push @deferred_updates, "update $ffq_prev $currentval $git_null_obj";
     push @deferred_updates, "delete $gdrlast";
-    push @deferred_update_messages, "Recorded previous head for preservation";
+    push @deferred_update_messages,
+       __ "Recorded previous head for preservation";
     return ('deferred', undef);
 }
 
@@ -1912,7 +1930,7 @@ sub record_ffq_auto () {
     my ($status, $message) = record_ffq_prev_deferred();
     if ($status eq 'deferred' || $status eq 'exists') {
     } else {
-       snag $status, "could not record ffq-prev: $message";
+       snag $status, f_ "could not record ffq-prev: %s", $message;
        snags_maybe_bail();
     }
 }
@@ -1923,7 +1941,7 @@ sub ffq_prev_info () {
     my ($status, $message, $current, $ffq_prev, $gdrlast)
        = ffq_prev_branchinfo();
     if ($status ne 'branch') {
-       snag $status, "could not check ffq-prev: $message";
+       snag $status, f_ "could not check ffq-prev: %s", $message;
        snags_maybe_bail();
     }
     my $ffq_prev_commitish = $ffq_prev && git_get_ref $ffq_prev;
@@ -1943,7 +1961,7 @@ sub stitch ($$$$$) {
            # Just wind forwards rather than making a pointless pseudomerge.
            record_gdrlast $gdrlast, $ffq_prev_commitish;
            update_head_checkout $old_head, $ffq_prev_commitish,
-               "stitch (fast forward)";
+               sprintf "stitch (%s)", __ 'fast forward';
            return;
        }
     }
@@ -1951,7 +1969,9 @@ sub stitch ($$$$$) {
     # We make pseudomerges with L as the contributing parent.
     # This makes git rev-list --first-parent work properly.
     my $new_head = make_commit [ $old_head, $ffq_prev ], [
-       'Declare fast forward / record previous work',
+        # we translate this against the time when this same code is
+        # used outside Debian, for downstreams and users
+       (__ 'Declare fast forward / record previous work'),
         "[git-debrebase pseudomerge: $prose]",
     ];
     record_gdrlast $gdrlast, $new_head;
@@ -1963,7 +1983,7 @@ sub do_stitch ($;$) {
 
     my ($ffq_prev, $gdrlast, $ffq_prev_commitish) = ffq_prev_info();
     if (!$ffq_prev_commitish) {
-       fail "No ffq-prev to stitch." unless $opt_noop_ok;
+       fail __ "No ffq-prev to stitch." unless $opt_noop_ok;
        return;
     }
     my $dangling_head = get_head();
@@ -1992,9 +2012,11 @@ sub resolve_upstream_version ($$) {
        my @tried;
        $new_upstream = upstream_commitish_search $upstream_version, \@tried;
        if (!length $new_upstream) {
-           fail "Could not determine appropriate upstream commitish.\n".
-               " (Tried these tags: @tried)\n".
-               " Check version, and specify upstream commitish explicitly.";
+           fail f_
+               "Could not determine appropriate upstream commitish.\n".
+               " (Tried these tags: %s)\n".
+               " Check version, and specify upstream commitish explicitly.",
+               "@tried";
        }
     }
     $new_upstream = git_rev_parse $new_upstream;
@@ -2008,12 +2030,13 @@ sub cmd_new_upstream () {
 
     my %pieces;
 
-    badusage "need NEW-VERSION [UPS-COMMITTISH]" unless @ARGV >= 1;
+    badusage __ "need NEW-VERSION [UPS-COMMITTISH]" unless @ARGV >= 1;
 
     # parse args - low commitment
     my $spec_version = shift @ARGV;
     my $new_version = (new Dpkg::Version $spec_version, check => 1);
-    fail "bad version number \`$spec_version'" unless defined $new_version;
+    fail f_ "bad version number \`%s'", $spec_version
+       unless defined $new_version;
     if ($new_version->is_native()) {
        $new_version = (new Dpkg::Version "$spec_version-1", check => 1);
     }
@@ -2029,7 +2052,8 @@ sub cmd_new_upstream () {
         my ($n, @x) = @_; # may be ''
         my $pc = $pieces{$n} //= {
            Name => $n,
-           Desc => ($n ? "upstream piece \`$n'" : "upstream (main piece"),
+           Desc => ($n ? (f_ "upstream piece \`%s'", $n)
+                       : (__ "upstream (main piece")),
        };
        while (my $k = shift @x) { $pc->{$k} = shift @x; }
         $pc;
@@ -2049,7 +2073,7 @@ sub cmd_new_upstream () {
     while (@ARGV && $ARGV[0] !~ m{^-}) {
        my $n = shift @ARGV;
 
-        badusage "for each EXTRA-UPS-NAME need EXTRA-UPS-COMMITISH"
+        badusage __ "for each EXTRA-UPS-NAME need EXTRA-UPS-COMMITISH"
             unless @ARGV && $ARGV[0] !~ m{^-};
 
        my $c = git_rev_parse shift @ARGV;
@@ -2082,7 +2106,7 @@ sub cmd_new_upstream () {
            my $old_n_parents = scalar @{ $old_upstream->{Parents} };
            if ($old_n_parents != @oldpieces &&
                $old_n_parents != @oldpieces + 1) {
-               snag 'upstream-confusing', sprintf
+               snag 'upstream-confusing', f_
                    "previous upstream combine %s".
                    " mentions %d pieces (each implying one parent)".
                    " but has %d parents".
@@ -2091,7 +2115,7 @@ sub cmd_new_upstream () {
                    (scalar @oldpieces),
                    $old_n_parents;
            } elsif ($oldpieces[0] ne '.') {
-               snag 'upstream-confusing', sprintf
+               snag 'upstream-confusing', f_
                    "previous upstream combine %s".
                    " first piece is not \`.'",
                    $oldpieces[0];
@@ -2104,9 +2128,10 @@ sub cmd_new_upstream () {
                }
            }
        } else {
-           snag 'upstream-confusing',
-               "previous upstream $old_upstream->{CommitId} is from".
-               " git-debrebase but not an \`upstream-combine' commit";
+           snag 'upstream-confusing', f_
+               "previous upstream %s is from".
+               " git-debrebase but not an \`upstream-combine' commit",
+              $old_upstream->{CommitId};
        }
     }
 
@@ -2115,13 +2140,14 @@ sub cmd_new_upstream () {
            # we have complained already
        } elsif (!$pc->{Old}) {
            snag 'upstream-new-piece',
-               "introducing upstream piece \`$pc->{Name}'";
+               f_ "introducing upstream piece \`%s'", $pc->{Name};
        } elsif (!$pc->{New}) {
            snag 'upstream-rm-piece',
-               "dropping upstream piece \`$pc->{Name}'";
+               f_ "dropping upstream piece \`%s'", $pc->{Name};
        } elsif (!is_fast_fwd $pc->{Old}, $pc->{New}) {
            snag 'upstream-not-ff',
-               "not fast forward: $pc->{Name} $pc->{Old}..$pc->{New}";
+               f_ "not fast forward: %s %s",
+                  $pc->{Name}, "$pc->{Old}..$pc->{New}";
        }
     }
 
@@ -2191,8 +2217,6 @@ sub cmd_new_upstream () {
        $usetup->('DEBEMAIL',    'user.email');
        $usetup->('DEBFULLNAME', 'user.name');
 
-sleep 2;
-
        my @dch = (qw(debchange
                      --allow-lower-version .*
                      --no-auto-nmu
@@ -2233,28 +2257,28 @@ sub cmd_record_ffq_prev () {
     badusage "no arguments allowed" if @ARGV;
     my ($status, $msg) = record_ffq_prev_deferred();
     if ($status eq 'exists' && $opt_noop_ok) {
-       print "Previous head already recorded\n" or confess $!;
+       print __ "Previous head already recorded\n" or confess $!;
     } elsif ($status eq 'deferred') {
        run_deferred_updates 'record-ffq-prev';
     } else {
-       fail "Could not preserve: $msg";
+       fail f_ "Could not preserve: %s", $msg;
     }
 }
 
 sub cmd_anchor () {
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
     my ($anchor, $bw) = keycommits +(git_rev_parse 'HEAD'), 0,0;
-    print "$bw\n" or confess $!;
+    print "$anchor\n" or confess $!;
 }
 
 sub cmd_breakwater () {
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
     my ($anchor, $bw) = keycommits +(git_rev_parse 'HEAD'), 0,0;
     print "$bw\n" or confess $!;
 }
 
 sub cmd_status () {
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
 
     # todo: gdr status should print divergence info
     # todo: gdr status should print upstream component(s) info
@@ -2276,10 +2300,10 @@ sub cmd_status () {
        $newest //= $oldest;
     };
     my ($anchor, $bw) = keycommits +(git_rev_parse 'HEAD'),
-       sub { $note->(1, 'branch contains furniture (not laundered)', @_); },
-       sub { $note->(2, 'branch is unlaundered', @_); },
-       sub { $note->(3, 'branch needs laundering', @_); },
-       sub { $note->(4, 'branch not in git-debrebase form', @_); };
+       sub { $note->(1, __ 'branch contains furniture (not laundered)',@_); },
+       sub { $note->(2, __ 'branch is unlaundered', @_); },
+       sub { $note->(3, __ 'branch needs laundering', @_); },
+       sub { $note->(4, __ 'branch not in git-debrebase form', @_); };
 
     my $prcommitinfo = sub {
        my ($cid) = @_;
@@ -2289,9 +2313,9 @@ sub cmd_status () {
            $cid;
     };
 
-    print "current branch contents, in git-debrebase terms:\n";
+    print __ "current branch contents, in git-debrebase terms:\n";
     if (!$oldest->{Badness}) {
-       print "  branch is laundered\n";
+       print __ "  branch is laundered\n";
     } else {
        print "  $oldest->{OurMsg}\n";
        my $printed = '';
@@ -2307,44 +2331,44 @@ sub cmd_status () {
     my $prab = sub {
        my ($cid, $what) = @_;
        if (!defined $cid) {
-           print "  $what is not well-defined\n";
+           print f_ "  %s is not well-defined\n", $what;
        } else {
            print "  $what\n";
            $prcommitinfo->($cid);
        }
     };
-    print "key git-debrebase commits:\n";
-    $prab->($anchor, 'anchor');
-    $prab->($bw, 'breakwater');
+    print __ "key git-debrebase commits:\n";
+    $prab->($anchor, __ 'anchor');
+    $prab->($bw, __ 'breakwater');
 
     my ($ffqstatus, $ffq_msg, $current, $ffq_prev, $gdrlast) =
        ffq_prev_branchinfo();
 
-    print "branch and ref status, in git-debrebase terms:\n";
+    print __ "branch and ref status, in git-debrebase terms:\n";
     if ($ffq_msg) {
        print "  $ffq_msg\n";
     } else {
        $ffq_prev = git_get_ref $ffq_prev;
        $gdrlast = git_get_ref $gdrlast;
        if ($ffq_prev) {
-           print "  unstitched; previous tip was:\n";
+           print __ "  unstitched; previous tip was:\n";
            $prcommitinfo->($ffq_prev);
        } elsif (!$gdrlast) {
-           print "  stitched? (no record of git-debrebase work)\n";
+           print __ "  stitched? (no record of git-debrebase work)\n";
        } elsif (is_fast_fwd $gdrlast, 'HEAD') {
-           print "  stitched\n";
+           print __ "  stitched\n";
        } else {
-           print "  not git-debrebase (diverged since last stitch)\n"
+           print __ "  not git-debrebase (diverged since last stitch)\n"
        }
     }
-    print "you are currently rebasing\n" if currently_rebasing();
+    print __ "you are currently rebasing\n" if currently_rebasing();
 }
 
 sub cmd_stitch () {
     my $prose = 'stitch';
     getoptions("stitch",
               'prose=s', \$prose);
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
     do_stitch $prose, 0;
 }
 sub cmd_prepush () {
@@ -2353,21 +2377,21 @@ sub cmd_prepush () {
 }
 
 sub cmd_quick () {
-    badusage "no arguments allowed" if @ARGV;
-    do_launder_head 'launder for git-debrebase quick';
+    badusage __ "no arguments allowed" if @ARGV;
+    do_launder_head __ 'launder for git-debrebase quick';
     do_stitch 'quick';
 }
 
 sub cmd_conclude () {
     my ($ffq_prev, $gdrlast, $ffq_prev_commitish) = ffq_prev_info();
     if (!$ffq_prev_commitish) {
-       fail "No ongoing git-debrebase session." unless $opt_noop_ok;
+       fail __ "No ongoing git-debrebase session." unless $opt_noop_ok;
        return;
     }
     my $dangling_head = get_head();
     
     badusage "no arguments allowed" if @ARGV;
-    do_launder_head 'launder for git-debrebase quick';
+    do_launder_head __ 'launder for git-debrebase quick';
     do_stitch 'quick';
 }
 
@@ -2377,7 +2401,7 @@ sub cmd_scrap () {
        push @deferred_updates, 'verify HEAD HEAD';
        # noop, but stops us complaining that scrap was a noop
     }
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
     my ($ffq_prev, $gdrlast, $ffq_prev_commitish) = ffq_prev_info();
     my $scrapping_head;
     if ($ffq_prev_commitish) {
@@ -2391,7 +2415,7 @@ sub cmd_scrap () {
            "delete $merge_cache_ref";
     }
     if (!@deferred_updates) {
-       fail "No ongoing git-debrebase session." unless $opt_noop_ok;
+       fail __ "No ongoing git-debrebase session." unless $opt_noop_ok;
        finish 0;
     }
     snags_maybe_bail();
@@ -2430,7 +2454,7 @@ sub make_patches ($) {
            rm_subdir_cached 'debian/patches';
        }
        $out = make_commit [$head], [
-            'Commit patch queue (exported by git-debrebase)',
+            (__ 'Commit patch queue (exported by git-debrebase)'),
             '[git-debrebase make-patches: export and commit patches]',
         ];
     };
@@ -2441,22 +2465,23 @@ sub cmd_make_patches () {
     my $opt_quiet_would_amend;
     getoptions("make-patches",
               'quiet-would-amend!', \$opt_quiet_would_amend);
-    badusage "no arguments allowed" if @ARGV;
+    badusage __ "no arguments allowed" if @ARGV;
     bail_if_rebasing();
     my $old_head = get_head();
     my $new = make_patches $old_head;
     my $d = get_differs $old_head, $new;
     if ($d == 0) {
-       fail "No (more) patches to export." unless $opt_noop_ok;
+       fail __ "No (more) patches to export." unless $opt_noop_ok;
        return;
     } elsif ($d == D_PAT_ADD) {
        snags_maybe_bail();
        update_head_checkout $old_head, $new, 'make-patches';
     } else {
-       print STDERR failmsg
+       print STDERR failmsg f_
            "Patch export produced patch amendments".
-           " (abandoned output commit $new).".
-           "  Try laundering first."
+           " (abandoned output commit %s).".
+           "  Try laundering first.",
+           $new
            unless $opt_quiet_would_amend;
        finish 7;
     }
@@ -2472,18 +2497,20 @@ sub check_series_has_all_patches ($) {
     our $comments_snagged;
     foreach my $f (grep /\S/, grep {!m/^\s\#/} split /\n/, $series) {
        if ($f =~ m/^\s*\#/) {
-           snag 'series-comments',
-               "$seriesfn contains comments, which will be discarded"
+           snag 'series-comments', f_
+               "%s contains comments, which will be discarded",
+               $seriesfn
                unless $comments_snagged++;
            next;
        }
-       fail "patch $f repeated in $seriesfn !" if $series{$f}++;
+       fail f_ "patch %s repeated in %s !", $f, $seriesfn if $series{$f}++;
     }
     foreach my $patchfile (get_tree "$head:debian/patches", 1,1) {
        my ($f,$i) = @$patchfile;
        next if $series{$f};
        next if $f eq 'series';
-       snag 'unused-patches', "Unused patch file $f will be discarded";
+       snag 'unused-patches', f_
+           "Unused patch file %s will be discarded", $f;
     }
 }
 
@@ -2491,11 +2518,11 @@ 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!"
+    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',
+    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 });
@@ -2510,13 +2537,18 @@ sub complete_convert_from ($$$$) {
     update_head_checkout $old_head, $new_head, $mrest;
 }
 
-sub cmd_convert_from_gbp () {
-    badusage "want only 1 optional argument, the upstream git commitish"
+sub cmd_convert_from_unapplied () { convert_from_some_unapplied(0); }
+sub cmd_convert_from_gbp () { convert_from_some_unapplied(0); }
+sub cmd_convert_from_bare_debian () { convert_from_some_unapplied(1); }
+
+sub convert_from_some_unapplied ($) {
+    my ($bare) = @_;
+    badusage __ "want only 1 optional argument, the upstream git commitish"
        unless @ARGV<=1;
 
     my $clogp = parsechangelog();
     my $version = $clogp->{'Version'}
-       // die "missing Version from changelog\n";
+       // fail __ "missing Version from changelog\n";
 
     my ($upstream_spec) = @ARGV;
 
@@ -2526,35 +2558,45 @@ sub cmd_convert_from_gbp () {
 
     my ($old_head, $gdrlastinfo) = begin_convert_from();
 
-    my $upsdiff = get_differs $upstream, $old_head;
-    if ($upsdiff & D_UPS) {
-       runcmd @git, qw(--no-pager diff --stat),
-           $upstream, $old_head,
-           qw( -- :!/debian :/);
-       fail <<END;
-upstream ($upstream_spec) and HEAD are not
-identical in upstream files.  See diffstat above, or run
-  git diff $upstream_spec HEAD -- :!/debian :/
+    if ($bare) {
+       snag 'unfinished-conversion-mode', <<END
+The convert-from-bare-debian mode is not very finished.  In particular it does not check that the input branch was in fact bare.  Nor does it check that the upstream branch you provided was correct (not sure how it could).  So on your head be it.
 END
     }
 
-    if (!is_fast_fwd $upstream, $old_head) {
-       snag 'upstream-not-ancestor',
-           "upstream ($upstream) is not an ancestor of HEAD";
-    } else {
-       my $wrong = cmdoutput
-           (@git, qw(rev-list --ancestry-path), "$upstream..HEAD",
-            qw(-- :/ :!/debian));
-       if (length $wrong) {
-           snag 'unexpected-upstream-changes',
-               "history between upstream ($upstream) and HEAD contains direct changes to upstream files - are you sure this is a gbp (patches-unapplied) branch?";
-           print STDERR "list expected changes with:  git log --stat --ancestry-path $upstream_spec..HEAD -- :/ ':!/debian'\n";
+    if (!$bare) {
+       my $upsdiff = get_differs $upstream, $old_head;
+       if ($upsdiff & D_UPS) {
+           runcmd @git, qw(--no-pager diff --stat),
+               $upstream, $old_head,
+               qw( -- :!/debian :/);
+           fail f_ <<END, $upstream_spec, $upstream_spec;
+upstream (%s) and HEAD are not
+identical in upstream files.  See diffstat above, or run
+  git diff %s HEAD -- :!/debian :/
+END
+       }
+
+       if (!is_fast_fwd $upstream, $old_head) {
+           snag 'upstream-not-ancestor',
+               f_ "upstream (%s) is not an ancestor of HEAD", $upstream;
+       } else {
+           my $wrong = cmdoutput
+               (@git, qw(rev-list --ancestry-path), "$upstream..HEAD",
+                qw(-- :/ :!/debian));
+           if (length $wrong) {
+               snag 'unexpected-upstream-changes', f_
+                   "history between upstream (%s) and HEAD contains direct changes to upstream files - are you sure this is a gbp (patches-unapplied) branch?",
+                   $upstream;
+               print STDERR f_ "list expected changes with:  %s\n", 
+                   "git log --stat --ancestry-path $upstream_spec..HEAD -- :/ ':!/debian'";
+           }
        }
     }
 
     if ((git_cat_file "$upstream:debian")[0] ne 'missing') {
        snag 'upstream-has-debian',
-           "upstream ($upstream) contains debian/ directory";
+           f_ "upstream (%s) contains debian/ directory", $upstream;
     }
 
     check_series_has_all_patches $old_head;
@@ -2572,29 +2614,30 @@ END
            $suite = $stz->{Distribution};
            last;
        };
-       die "neither of the first two changelog entries are released\n"
+       die __ "neither of the first two changelog entries are released\n"
            unless defined $lvsn;
        print "last finished-looking changelog entry: ($lvsn) $suite\n";
        my $mtag_pat = debiantag_maintview $lvsn, '*';
        my $mtag = cmdoutput @git, qw(describe --always --abbrev=0 --match),
            $mtag_pat;
-       die "could not find suitable maintainer view tag $mtag_pat\n"
+       die f_ "could not find suitable maintainer view tag %s\n", $mtag_pat
            unless $mtag =~ m{/};
        is_fast_fwd $mtag, 'HEAD' or
-           die "HEAD is not FF from maintainer tag $mtag!";
+           die f_ "HEAD is not FF from maintainer tag %s!", $mtag;
        my $dtag = "archive/$mtag";
        git_get_ref "refs/tags/$dtag" or
-           die "dgit view tag $dtag not found\n";
+           die f_ "dgit view tag %s not found\n", $dtag;
        is_fast_fwd $mtag, $dtag or
-           die "dgit view tag $dtag is not FF from maintainer tag $mtag\n";
-       print "will stitch in dgit view, $dtag\n";
+           die f_ "dgit view tag %s is not FF from maintainer tag %s\n",
+                  $dtag, $mtag;
+       print f_ "will stitch in dgit view, %s\n", $dtag;
        git_rev_parse $dtag;
     };
     if (!$previous_dgit_view) {
        $@ =~ s/^\n+//;
        chomp $@;
-       print STDERR <<END;
-Cannot confirm dgit view: $@
+       print STDERR f_ <<END, "$@";
+Cannot confirm dgit view: %s
 Failed to stitch in dgit view (see messages above).
 dgit --overwrite will be needed on the first dgit push after conversion.
 END
@@ -2606,11 +2649,18 @@ END
 
     fresh_workarea();
     in_workarea sub {
-       runcmd @git, qw(checkout -q -b gdr-internal), $old_head;
+       if ($bare) {
+           runcmd @git, qw(checkout -q -b gdr-internal), $upstream;
+           runcmd @git, qw(rm --quiet -rf --ignore-unmatch debian);
+           runcmd @git, qw(checkout -q), $old_head, qw(debian);
+           runcmd @git, qw(commit --allow-empty -q -m ADD-DEBIAN);
+       } else {
+           runcmd @git, qw(checkout -q -b gdr-internal), $old_head;
+       }
        # make a branch out of the patch queue - we'll want this in a mo
        runcmd qw(gbp pq import);
        # strip the patches out
-       runcmd @git, qw(checkout -q gdr-internal~0);
+       runcmd @git, qw(checkout -q), $old_head;
        rm_subdir_cached 'debian/patches';
        $work = make_commit ['HEAD'], [
  'git-debrebase convert-from-gbp: drop patches from tree',
@@ -2619,6 +2669,9 @@ END
                              ];
        # make the anchor merge
        # the tree is already exactly right
+       if ($bare) {
+           runcmd @git, qw(reset -q), $upstream, qw(-- :/ :!/debian);
+       }
        $work = make_commit [$work, $upstream], [
  'git-debrebase import: declare upstream',
  'First breakwater merge.',
@@ -2639,8 +2692,8 @@ END
     };
 
     complete_convert_from $old_head, $work, $gdrlastinfo, 'convert-from-gbp';
-    print <<END or confess $!;
-$us: converted from patched-unapplied (gbp) branch format, OK
+    print f_ <<END, $us or confess $!;
+%s: converted from patched-unapplied (gbp) branch format, OK
 END
 }
 
@@ -2668,10 +2721,10 @@ sub cmd_convert_to_gbp () {
     }
     snags_maybe_bail();
     update_head_checkout $head, $out, "convert to gbp (v0)";
-    print <<END or confess $!;
-$us: converted to git-buildpackage branch format
-$us: WARNING: do not now run "git-debrebase" any more
-$us: WARNING: doing so would drop all upstream patches!
+    print f_ <<END, $us,$us,$us or confess $!;
+%s: converted to git-buildpackage branch format
+%s: WARNING: do not now run "git-debrebase" any more
+%s: WARNING: doing so would drop all upstream patches!
 END
 }
 
@@ -2690,7 +2743,7 @@ sub cmd_convert_from_dgit_view () {
               'origs!', \$do_origs,
               'tags!', \$do_tags,
               'always-convert-anyway!', \$always);
-    fail "takes 1 optional argument, the upstream commitish" if @ARGV>1;
+    fail __ "takes 1 optional argument, the upstream commitish" if @ARGV>1;
 
     my @upstreams;
 
@@ -2698,7 +2751,7 @@ sub cmd_convert_from_dgit_view () {
        my $spec = shift @ARGV;
        my $commit = git_rev_parse "$spec^{commit}";
        push @upstreams, { Commit => $commit,
-                          Source => "$ARGV[0], from command line",
+                          Source => (f_ "%s, from command line", $ARGV[0]),
                           Only => 1,
                         };
     }
@@ -2711,12 +2764,13 @@ sub cmd_convert_from_dgit_view () {
        keycommits $head, sub{}, sub{}, $trouble, $trouble;
        printdebug "troubles=$troubles\n";
        if (!$troubles) {
-           print STDERR <<END;
-$us: Branch already seems to be in git-debrebase format!
-$us: --always-convert-anyway would do the conversion operation anyway
-$us: but is probably a bad idea.  Probably, you wanted to do nothing.
+           print STDERR f_ <<END, $us,$us,$us;
+%s: Branch already seems to be in git-debrebase format!
+%s: --always-convert-anyway would do the conversion operation anyway
+%s: but is probably a bad idea.  Probably, you wanted to do nothing.
 END
-           fail "Branch already in git-debrebase format." unless $opt_noop_ok;
+           fail __ "Branch already in git-debrebase format."
+               unless $opt_noop_ok;
            finish 0;
        }
     }
@@ -2726,19 +2780,20 @@ END
     snags_maybe_bail_early();
 
     my $version = upstreamversion $clogp->{Version};
-    print STDERR "Considering possible commits corresponding to upstream:\n";
+    print STDERR __
+       "Considering possible commits corresponding to upstream:\n";
 
     if (!@upstreams) {
        if ($do_tags) {
            my @tried;
            my $ups_tag = upstream_commitish_search $version, \@tried;
            if ($ups_tag) {
-               my $this = "git tag $tried[-1]";
+               my $this = f_ "git tag %s", $tried[-1];
                push @upstreams, { Commit => $ups_tag,
                                   Source => $this,
                                 };
            } else {
-               printf STDERR
+               print STDERR f_
                    " git tag: no suitable tag found (tried %s)\n",
                    "@tried";
            }
@@ -2748,11 +2803,12 @@ END
            # we do a quick check to see if there are plausible origs
            my $something=0;
            if (!opendir BPD, $bpd) {
-               die "opendir build-products-dir $bpd: $!" unless $!==ENOENT;
+               die f_ "opendir build-products-dir %s: %s", $bpd, $!
+                   unless $!==ENOENT;
            } else {
                while ($!=0, my $f = readdir BPD) {
                    next unless is_orig_file_of_p_v $f, $p, $version;
-                   printf STDERR
+                   print STDERR f_
                        " orig: found what looks like a .orig, %s\n",
                        "$bpd/$f";
                    $something=1;
@@ -2783,7 +2839,7 @@ END
                                     };
                }
            } else {
-               printf STDERR
+               print STDERR f_
                    " orig: no suitable origs found (looked for %s in %s)\n",
                    "${p}_".(stripeoch $version)."...", $bpd;
            }
@@ -2792,7 +2848,8 @@ END
 
     my $some_patches = stat_exists 'debian/patches/series';
 
-    print STDERR "Evaluating possible commits corresponding to upstream:\n";
+    print STDERR __
+       "Evaluating possible commits corresponding to upstream:\n";
 
     my $result;
     foreach my $u (@upstreams) {
@@ -2828,7 +2885,7 @@ END
                }
                my $r = system @gbp_cmd;
                if ($r) {
-                   printf STDERR
+                   print STDERR f_
                        " %s: couldn't apply patches: gbp pq %s",
                        $u->{Source}, waitstatusmsg();
                    return;
@@ -2837,8 +2894,9 @@ END
            my $work = git_rev_parse qw(HEAD);
            my $diffout = cmdoutput @git, qw(diff-tree --stat HEAD), $work;
            if (length $diffout) {
-               print STDERR
-                   " $u->{Source}: applying patches gives different tree\n";
+               print STDERR f_
+                   " %s: applying patches gives different tree\n",
+                   $u->{Source};
                print STDERR $diffout if $diagnose;
                return;
            }
@@ -2850,24 +2908,26 @@ END
     }
 
     if (!$result) {
-       fail <<END;
+       fail __ <<END;
 Could not find or construct a suitable upstream commit.
 Rerun adding --diagnose after convert-from-dgit-view, or pass a
 upstream commmit explicitly or provide suitable origs.
 END
     }
 
-    printf STDERR "Yes, will base new branch on %s\n", $result->{Source};
+    print STDERR f_ "Yes, will base new branch on %s\n", $result->{Source};
 
     complete_convert_from $head, $result->{Result}, $gdrlastinfo,
        'convert-from-dgit-view';
 }
 
 sub cmd_forget_was_ever_debrebase () {
-    badusage "forget-was-ever-debrebase takes no further arguments" if @ARGV;
+    badusage __ "forget-was-ever-debrebase takes no further arguments"
+       if @ARGV;
     my ($ffqstatus, $ffq_msg, $current, $ffq_prev, $gdrlast) =
        ffq_prev_branchinfo();
-    fail "Not suitable for recording git-debrebaseness anyway: $ffq_msg"
+    fail f_ "Not suitable for recording git-debrebaseness anyway: %s",
+           $ffq_msg
        if defined $ffq_msg;
     push @deferred_updates, "delete $ffq_prev";
     push @deferred_updates, "delete $gdrlast";
@@ -2968,7 +3028,7 @@ setlocale(LC_MESSAGES, "");
 textdomain("git-debrebase");
 
 getoptions_main
-          ("bad options\n",
+          (__ "bad options\n",
           "D+" => \$debuglevel,
           'noop-ok', => \$opt_noop_ok,
           'f=s' => \@snag_force_opts,
@@ -2978,7 +3038,7 @@ getoptions_main
           'experimental-merge-resolution!', \$opt_merges,
           '-i:s' => sub {
               my ($opt,$val) = @_;
-              badusage __ "git-debrebase: no cuddling to -i for git-rebase"
+              badusage f_ "%s: no cuddling to -i for git-rebase", $us
                   if length $val;
               confess if $opt_defaultcmd_interactive; # should not happen
               $opt_defaultcmd_interactive = [ qw(-i) ];
@@ -2988,14 +3048,13 @@ getoptions_main
               push @$opt_defaultcmd_interactive, @ARGV;
               @ARGV=();
           },
-          'help' => sub { print $usage_message or die $!; finish 0; },
+          'help' => sub { print __ $usage_message or confess $!; finish 0; },
           );
 
 initdebug('git-debrebase ');
 enabledebug if $debuglevel;
 
-my $toplevel = cmdoutput @git, qw(rev-parse --show-toplevel);
-chdir $toplevel or fail "chdir toplevel $toplevel: $!\n";
+changedir_git_toplevel();
 
 $rd = fresh_playground "$playprefix/misc";