use Data::Dumper;
use Getopt::Long qw(:config posix_default gnu_compat bundling);
use Dpkg::Version;
+use File::FnMatch qw(:fnmatch);
-our ($opt_force);
+our ($opt_force, $opt_noop_ok);
+
+our $us = qw(git-debrebase);
sub badusage ($) {
my ($m) = @_;
return cmdoutput @cmd;
}
-our $fproblems;
-sub fproblem ($) {
- my ($msg) = @_;
- $fproblems++;
- print STDERR "git-debrebase: safety catch tripped: $msg\n";
+our @fproblem_force_opts;
+our $fproblems_forced;
+our $fproblems_tripped;
+sub fproblem ($$) {
+ my ($tag,$msg) = @_;
+ if (grep { $_ eq $tag } @fproblem_force_opts) {
+ $fproblems_forced++;
+ print STDERR "git-debrebase: safety catch overridden (-f$tag): $msg\n";
+ } else {
+ $fproblems_tripped++;
+ print STDERR "git-debrebase: safety catch tripped (-f$tag): $msg\n";
+ }
}
+
sub fproblems_maybe_bail () {
- if ($fproblems) {
+ if ($fproblems_forced) {
+ printf STDERR
+ "%s: safety catch trips: %d overriden by individual -f options\n",
+ $us, $fproblems_forced;
+ }
+ if ($fproblems_tripped) {
if ($opt_force) {
printf STDERR
- "safety catch trips (%d) overriden by --force\n",
- $fproblems;
+ "%s: safety catch trips: %d overriden by global --force\n",
+ $us, $fproblems_tripped;
} else {
fail sprintf
- "safety catch trips (%d) (you could --force)",
- $fproblems;
+ "%s: safety catch trips: %d blockers (you could -f<tag>, or --force)",
+ $us, $fproblems_tripped;
}
}
}
+sub any_fproblems () {
+ return $fproblems_forced || $fproblems_tripped;
+}
# classify returns an info hash like this
# CommitId => $objid
$r->{Msg} =~ m{^\[git-debrebase breakwater.*\]$}m;
if (@p == 1) {
+ if ($claims_to_be_breakwater) {
+ return $unknown->("single-parent git-debrebase breakwater \`merge'");
+ }
my $d = $r->{Parents}[0]{Differs};
if ($d == D_PAT_ADD) {
return $classify->(qw(AddPatches));
$piece->($n, Old => $old_upstream->{CommitId}.'^'.$parentix);
}
} else {
- fproblem "previous upstream $old_upstream->{CommitId} is from".
- " git-debrebase but not an \`upstream-combine' commit";
+ fproblem 'upstream-confusing',
+ "previous upstream $old_upstream->{CommitId} is from".
+ " git-debrebase but not an \`upstream-combine' commit";
}
}
foreach my $pc (values %pieces) {
if (!$pc->{Old}) {
- fproblem "introducing upstream piece \`$pc->{Name}'";
+ fproblem 'upstream-new-piece',
+ "introducing upstream piece \`$pc->{Name}'";
} elsif (!$pc->{New}) {
- fproblem "dropping upstream piece \`$pc->{Name}'";
+ fproblem 'upstream-rm-piece',
+ "dropping upstream piece \`$pc->{Name}'";
} elsif (!is_fast_fwd $pc->{Old}, $pc->{New}) {
- fproblem "not fast forward: $pc->{Name} $pc->{Old}..$pc->{New}";
+ fproblem 'upstream-not-ff',
+ "not fast forward: $pc->{Name} $pc->{Old}..$pc->{New}";
}
}
in_workarea sub {
my @upstream_merge_parents;
- if (!$fproblems) {
+ if (!any_fproblems()) {
push @upstream_merge_parents, $old_upstream->{CommitId};
}
}
if (!is_fast_fwd $upstream, $old_head) {
- fproblem "upstream ($upstream) is not an ancestor of HEAD";
+ fproblem '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) {
- fproblem "history between upstream ($upstream) and HEAD contains direct changes to upstream files - are you sure this is a gbp (patches-unapplied) branch?";
+ fproblem '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 ((git_cat_file "$upstream:debian")[0] ne 'missing') {
- fproblem "upstream ($upstream) contains debian/ directory";
+ fproblem 'upstream-has-debian',
+ "upstream ($upstream) contains debian/ directory";
}
fproblems_maybe_bail();
}
GetOptions("D+" => \$debuglevel,
+ 'noop-ok', => \$opt_noop_ok,
+ 'f=s' => \@fproblem_force_opts,
'force!') or die badusage "bad options\n";
initdebug('git-debrebase ');
enabledebug if $debuglevel;