X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=dgit;h=08d07bec9190b600fac461f8ccb3bde037a593f2;hp=5910c778f2f7d0798150cd2ac89aaa15171ccbfe;hb=bd5e99ad04dc4eda140aca37840628118d1fa94d;hpb=fbb665eaf5e2ca9d027128dd8838adc15c934b30 diff --git a/dgit b/dgit index 5910c778..08d07bec 100755 --- a/dgit +++ b/dgit @@ -61,7 +61,7 @@ our $cleanmode; our $changes_since_version; our $rmchanges; our $quilt_mode; -our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck'; +our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|unapplied'; our $we_are_responder; our $initiator_tempdir; @@ -2510,17 +2510,24 @@ END } } -sub quiltify_trees_differ ($$) { - my ($x,$y) = @_; - # returns 1 iff the two tree objects differ other than in debian/ +sub quiltify_trees_differ ($$;$) { + my ($x,$y,$finegrained) = @_; + # returns true iff the two tree objects differ other than in debian/ + # with $finegrained, + # returns bitmask 01 - differ in upstream files except .gitignore + # 02 - differ in .gitignore local $/=undef; - my @cmd = (@git, qw(diff-tree --name-only -z), $x, $y); + my @cmd = (@git, qw(diff-tree --name-only -z)); + push @cmd, qw(-r) if $finegrained; + push @cmd, $x, $y; my $diffs= cmdoutput @cmd; + my $r = 0; foreach my $f (split /\0/, $diffs) { - next if $f eq 'debian'; - return 1; + next if $f =~ m#^debian(?:/.*)?$#s; + $r |= ($f =~ m#^(?:.*/)?.gitignore$#s) ? 02 : 01; } - return 0; + printdebug "quiltify_trees_differ $x $y => $r\n"; + return $r; } sub quiltify_tree_sentinelfiles ($) { @@ -2532,8 +2539,17 @@ sub quiltify_tree_sentinelfiles ($) { return $r; } -sub quiltify ($$$) { - my ($clogp,$target,$origtree) = @_; +sub quiltify_splitbrain ($) { + my ($diffbits) = @_; + # memoisation via git-reflog + my $may_apply = $quilt_mode =~ m/gbp|unapplied/; + die "xxx not yet implemented"; +# if ($may_apply && +# quiltify_trees_differ($userhead,)) {} +} + +sub quiltify ($$$$) { + my ($clogp,$target,$oldtiptree,$failsuggestion) = @_; # Quilt patchification algorithm # @@ -2559,12 +2575,6 @@ sub quiltify ($$$) { # After traversing PT, we git commit the changes which # should be contained within debian/patches. - changedir '../fake'; - rmtree '.pc'; - runcmd @git, qw(add -Af .); - my $oldtiptree=git_write_tree(); - changedir '../work'; - # The search for the path S..T is breadth-first. We maintain a # todo list containing search nodes. A search node identifies a # commit, and looks something like this: @@ -2677,6 +2687,7 @@ sub quiltify ($$$) { foreach my $notp (@nots) { print STDERR "$us: ", $reportnot->($notp), "\n"; } + print STDERR "$us: $_\n" foreach @$failsuggestion; fail "quilt fixup naive history linearisation failed.\n". "Use dpkg-source --commit by hand; or, --quilt=smash for one ugly patch"; } elsif ($quilt_mode eq 'smash') { @@ -2883,11 +2894,24 @@ sub quilt_fixup_multipatch ($$$) { # 6. Back in the main tree, fast forward to the new HEAD # Another situation we may have to cope with is gbp-style - # patches-unapplied trees. We want to detect these, so we know - # to escape into quilt_fixup_gbp. + # patches-unapplied trees. # - # A gbp-style tree is one which is not a clean patches-applied - # tree, but _is_ a clean patches-unapplied tree. + # We would want to detect these, so we know to escape into + # quilt_fixup_gbp. However, this is in general not possible. + # Consider a package with a one patch which the dgit user reverts + # (with git-revert or the moral equivalent). + # + # That is indistinguishable in contents from a patches-unapplied + # tree. And looking at the history to distinguish them is not + # useful because the user might have made a confusing-looking git + # history structure (which ought to produce an error if dgit can't + # cope, not a silent reintroduction of an unwanted patch). + # + # So gbp users will have to pass an option. But we can usually + # detect their failure to do so: if the tree is not a clean + # patches-applied tree, quilt linearisation fails, but the tree + # _is_ a clean patches-unapplied tree, we can suggest that maybe + # they want --quilt=unapplied. # # To help detect this, when we are extracting the fake dsc, we # first extract it with --skip-patches, and then apply the patches @@ -2921,7 +2945,8 @@ END my @files=qw(debian/source/format debian/rules debian/control debian/changelog); - foreach my $maybe (qw(debian/patches debian/source/options)) { + foreach my $maybe (qw(debian/patches debian/source/options + debian/tests/control)) { next unless stat_exists "../../../$maybe"; push @files, $maybe; } @@ -2940,18 +2965,22 @@ END changedir 'fake'; - ensuredir '.pc'; - remove_stray_gits(); mktree_in_ud_here(); + rmtree '.pc'; + + runcmd @git, qw(add -Af .); + my $unapplied=git_write_tree(); + printdebug "fake orig tree object $unapplied\n"; + + ensuredir '.pc'; + runcmd qw(sh -ec), 'exec dpkg-source --before-build . >/dev/null'; changedir '..'; - my $origtree=''; - quilt_fixup_mkwork($headref); my $mustdeletepc=0; @@ -2963,7 +2992,54 @@ END rename '../fake/.pc','.pc' or die $!; } - quiltify($clogp,$headref,$origtree); + changedir '../fake'; + rmtree '.pc'; + runcmd @git, qw(add -Af .); + my $oldtiptree=git_write_tree(); + changedir '../work'; + + + # We calculate some guesswork now about what kind of tree this might + # be. This is mostly for error reporting. + + my $diffbits = { + # H = user's HEAD + # O = orig, without patches applied + # A = "applied", ie orig with H's debian/patches applied + H2O => quiltify_trees_differ($headref, $unapplied, 1), + H2A => quiltify_trees_differ($headref, $oldtiptree,1), + O2A => quiltify_trees_differ($unapplied,$oldtiptree,1), + }; + + my @dl; + foreach my $b (qw(01 02)) { + foreach my $v (qw(H2O O2A H2A)) { + push @dl, ($diffbits->{$v} & $b) ? '##' : '=='; + } + } + printdebug "differences \@dl @dl.\n"; + + progress sprintf +"$us: quilt differences: src: %s orig %s gitignores: %s orig %s\n". +"$us: quilt differences: HEAD %s o+d/p HEAD %s o+d/p", + $dl[0], $dl[1], $dl[3], $dl[4], + $dl[2], $dl[5]; + + my @failsuggestion; + if (!($diffbits->{H2O} & $diffbits->{O2A})) { + push @failsuggestion, "This might be a patches-unapplied branch."; + } elsif (!($diffbits->{H2A} & $diffbits->{O2A})) { + push @failsuggestion, "This might be a patches-applied branch."; + } + push @failsuggestion, "Maybe you need to specify one of". + " --quilt=gbp --quilt=dpm --quilt=unapplied ?"; + + if ($quilt_mode =~ m/gbp|dpm|apply/) { + quiltify_splitbrain($diffbits); + return; + } + + quiltify($clogp,$headref,$oldtiptree,\@failsuggestion); if (!open P, '>>', ".pc/applied-patches") { $!==&ENOENT or die $!;