X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=git-debrebase;h=50f5e1674c6574afa7d42c8e7d04a33c31b99867;hb=528ff0071b6e9d1db499b48897a4a13f581f254f;hp=85cf331835002b313fc761f13acc537aee93e56a;hpb=880af0a90f1b02db4607e94d38555f2e86af47a3;p=dgit.git diff --git a/git-debrebase b/git-debrebase index 85cf3318..50f5e167 100755 --- a/git-debrebase +++ b/git-debrebase @@ -22,14 +22,17 @@ # usages: # # git-debrebase [] new-upstream-v0 \ -# -# [ ...] +# \ +# [ ...] \ # [...] # # git-debrebase [ --] [] # git-debrebase [] analyse # git-debrebase [] launder # prints breakwater tip etc. # git-debrebase [] downstream-rebase-launder-v0 # experimental +# +# git-debrebase [] gbp2debrebase-v0 \ +# # problems / outstanding questions: # @@ -113,7 +116,7 @@ sub dd ($) { sub get_commit ($) { my ($objid) = @_; - my $data = git_cat_file $objid, 'commit'; + my $data = (git_cat_file $objid, 'commit'); $data =~ m/(?<=\n)\n/ or die "$objid ($data) ?"; return ($`,$'); } @@ -197,8 +200,8 @@ sub get_differs ($$) { if ($mode eq 'A' && !m/\.series$/s) { $ok = 1; } elsif ($mode eq 'M' && $_ eq 'series') { - my $x_s = git_cat_file "$x:debian/patches/series", 'blob'; - my $y_s = git_cat_file "$y:debian/patches/series", 'blob'; + my $x_s = (git_cat_file "$x:debian/patches/series", 'blob'); + my $y_s = (git_cat_file "$y:debian/patches/series", 'blob'); chomp $x_s; $x_s .= "\n"; $ok = $x_s eq substr($y_s, 0, length $x_s); } else { @@ -249,6 +252,26 @@ sub make_commit ($$) { return cmdoutput @cmd; } +our $fproblems; +sub fproblem ($) { + my ($msg) = @_; + $fproblems++; + print STDERR "git-debrebase: safety catch tripped: $msg\n"; +} +sub fproblems_maybe_bail () { + if ($fproblems) { + if ($opt_force) { + printf STDERR + "safety catch trips (%d) overriden by --force\n", + $fproblems; + } else { + fail sprintf + "safety catch trips (%d) (you could --force)", + $fproblems; + } + } +} + # classify returns an info hash like this # CommitId => $objid # Hdr => # commit headers, including 1 final newline @@ -850,18 +873,11 @@ sub cmd_new_upstream_v0 () { my $old_upstream = parsecommit $old_upstream_update_cl->{OrigParents}[0]{CommitId}; - my $problems = 0; - my $problem = sub { - my ($msg) = @_; - $problems++; - print STDERR "preflight check failed: $msg\n"; - }; - $piece->('', Old => $old_upstream->{CommitId}); if ($old_upstream->{Msg} =~ m{^\[git-debrebase }m) { if ($old_upstream->{Msg} =~ - m{^\[git-debrebase new-upstream combine \.((?: $extra_orig_namepart_re)+)\]} + m{^\[git-debrebase (?:\w*-)?upstream combine \.((?: $extra_orig_namepart_re)+)\]} ) { my @oldpieces = ('', split / /, $1); my $parentix = -1 + scalar @{ $old_upstream->{Parents} }; @@ -870,35 +886,25 @@ sub cmd_new_upstream_v0 () { $piece->($n, Old => $old_upstream->{CommitId}.'^'.$parentix); } } else { - $problem->("previous upstream $old_upstream->{CommitId} is from". - " git-debrebase but not a \`new-upstream combine' commit"); + fproblem "previous upstream $old_upstream->{CommitId} is from". + " git-debrebase but not an \`upstream combine' commit"; } } foreach my $pc (values %pieces) { if (!$pc->{Old}) { - $problem->("introducing upstream piece \`$pc->{Name}'"); + fproblem "introducing upstream piece \`$pc->{Name}'"; } elsif (!$pc->{New}) { - $problem->("dropping upstream piece \`$pc->{Name}'"); + fproblem "dropping upstream piece \`$pc->{Name}'"; } elsif (!is_fast_fwd $pc->{Old}, $pc->{New}) { - $problem->("not fast forward: $pc->{Name} $pc->{Old}..$pc->{New}"); + fproblem "not fast forward: $pc->{Name} $pc->{Old}..$pc->{New}"; } } printdebug "%pieces = ", (dd \%pieces), "\n"; printdebug "\@newpieces = ", (dd \@newpieces), "\n"; - if ($problems) { - if ($opt_force) { - printf STDERR - "preflight check failures (%d) overriden by --force\n", - $problems; - } else { - fail sprintf - "preflight check failures (%d) (you could --force)", - $problems; - } - } + fproblems_maybe_bail(); my $new_bw; @@ -906,7 +912,7 @@ sub cmd_new_upstream_v0 () { in_workarea sub { my @upstream_merge_parents; - if (!$problems) { + if (!$fproblems) { push @upstream_merge_parents, $old_upstream->{CommitId}; } @@ -984,6 +990,45 @@ END # now it's for the user to sort out } +sub cmd_gbp2debrebase () { + badusage "needs 1 optional argument, the upstream" unless @ARGV<=1; + my ($upstream_spec) = @ARGV; + $upstream_spec //= 'refs/heads/upstream'; + my $upstream = git_rev_parse $upstream_spec; + my $old_head = get_head(); + + my $upsdiff = get_differs $upstream, $old_head; + if ($upsdiff & D_UPS) { + runcmd @git, qw(--no-pager diff), + $upstream, $old_head, + qw( -- :!/debian :/); + fail "upstream ($upstream_spec) and HEAD are not identical in upstream files"; + } + + if (!is_fast_fwd $upstream, $old_head) { + fproblem "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) { + fproblem "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 ((git_cat_file "$upstream:debian")[0] ne 'missing') { + fproblem "upstream ($upstream) contains debian/ directory"; + } + die; + + fresh_workarea(); + in_workarea sub { + runcmd @git, qw(checkout -b work), $old_head; + + }; +} + sub cmd_downstream_rebase_launder_v0 () { badusage "needs 1 argument, the baseline" unless @ARGV==1; my ($base) = @ARGV;