X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=dgit;h=769e48ee6ee50c7c7924cd9f0bbec02cec3d5840;hb=d7a62f56ca2269cd39b255f8397fd68adc4a16f0;hp=97557ce1c3e1c3a4042160a8c2ab99359184330b;hpb=9dd8836fb53b8d37db646b28d6ae94b052130736;p=dgit.git diff --git a/dgit b/dgit index 97557ce1..769e48ee 100755 --- a/dgit +++ b/dgit @@ -175,7 +175,31 @@ our $keyid; autoflush STDOUT 1; our $supplementary_message = ''; -our $split_brain = 0; +our $made_split_brain = 0; +our $do_split_brain = 0; + +# Interactions between quilt mode and split brain +# (currently, split brain only implemented iff +# madformat_wantfixup && quiltmode_splitbrain) +# +# source format sane `3.0 (quilt)' +# madformat_wantfixup() +# +# quilt mode normal quiltmode +# (eg linear) _splitbrain +# +# ------------ ------------------------------------------------ +# +# no split no q cache no q cache forbidden, +# brain PM on master q fixup on master prevented +# !$do_split_brain PM on master +# +# split brain no q cache q fixup cached, to dgit view +# PM in dgit view PM in dgit view +# +# PM = pseudomerge to make ff, due to overwrite (or split view) +# "no q cache" = do not record in cache on build, do not check cache +# `3.0 (quilt)' with --quilt=nocheck is treated as sane format END { local ($@, $?); @@ -919,6 +943,20 @@ sub access_forpush () { return $access_forpush; } +sub default_from_access_cfg ($$$;$) { + my ($var, $keybase, $defval, $permit_re) = @_; + return if defined $$var; + + $$var = access_cfg("$keybase-newer", 'RETURN-UNDEF'); + $$var = undef if $$var && $$var !~ m/^$permit_re$/; + + $$var //= access_cfg($keybase, 'RETURN-UNDEF'); + $$var //= $defval; + + badcfg f_ "unknown %s \`%s'", $keybase, $$var + if defined $permit_re and $$var !~ m/$permit_re/; +} + sub pushing () { confess +(__ 'internal error').' '.Dumper($access_forpush)," ?" if defined $access_forpush and !$access_forpush; @@ -4465,7 +4503,6 @@ END push_parse_dsc($dscpath, $dscfn, $cversion); my $format = getfield $dsc, 'Format'; - printdebug "format $format\n"; my $symref = git_get_symref(); my $actualhead = git_rev_parse('HEAD'); @@ -4491,9 +4528,8 @@ END if (madformat_wantfixup($format)) { # user might have not used dgit build, so maybe do this now: - if (quiltmode_splitbrain()) { + if ($do_split_brain) { changedir $playground; - quilt_make_fake_dsc($upstreamversion); my $cachekey; ($dgithead, $cachekey) = quilt_check_splitbrain_cache($actualhead, $upstreamversion); @@ -4501,17 +4537,22 @@ END "--quilt=%s but no cached dgit view: perhaps HEAD changed since dgit build[-source] ?", $quilt_mode; - $split_brain = 1; - $dgithead = splitbrain_pseudomerge($clogp, - $actualhead, $dgithead, - $archive_hash); - $maintviewhead = $actualhead; - changedir $maindir; - prep_ud(); # so _only_subdir() works, below - } else { + } + if (!$do_split_brain) { + # In split brain mode, do not attempt to incorporate dirty + # stuff from the user's working tree. That would be mad. commit_quilty_patch(); } } + if ($do_split_brain) { + $made_split_brain = 1; + $dgithead = splitbrain_pseudomerge($clogp, + $actualhead, $dgithead, + $archive_hash); + $maintviewhead = $actualhead; + changedir $maindir; + prep_ud(); # so _only_subdir() works, below + } if (defined $overwrite_version && !defined $maintviewhead && $archive_hash) { @@ -4538,6 +4579,8 @@ END } } + confess unless !!$made_split_brain == !!$do_split_brain; + changedir $playground; progress f_ "checking that %s corresponds to HEAD", $dscfn; runcmd qw(dpkg-source -x --), @@ -4551,7 +4594,7 @@ END my $r = system @diffcmd; if ($r) { if ($r==256) { - my $referent = $split_brain ? $dgithead : 'HEAD'; + my $referent = $made_split_brain ? $dgithead : 'HEAD'; my $diffs = cmdoutput @git, qw(diff --stat), $tree, $dgithead; my @mode_changes; @@ -4951,6 +4994,7 @@ sub prep_push () { parseopts(); build_or_push_prep_early(); pushing(); + build_or_push_prep_modes(); check_not_dirty(); my $specsuite; if (@ARGV==0) { @@ -5393,9 +5437,7 @@ sub quiltify_splitbrain ($$$$$$$) { local $ENV{GIT_AUTHOR_EMAIL} = $authline[1]; local $ENV{GIT_AUTHOR_DATE} = $authline[2]; - die if $split_brain; - runcmd @git, qw(checkout -q -b dgit-view); - $split_brain = 1; + confess unless $do_split_brain; my $fulldiffhint = sub { my ($x,$y) = @_; @@ -5783,55 +5825,47 @@ sub build_maybe_quilt_fixup () { check_for_vendor_patches(); - if (quiltmode_splitbrain) { - fail <{'single-debian-patch'} - && branch_is_gdr($headref)) { - # This is much faster. It also makes patches that gdr - # likes better for future updates without laundering. - # - # However, it can fail in some casses where we would - # succeed: if there are existing patches, which correspond - # to a prefix of the branch, but are not in gbp/gdr - # format, gdr will fail (exiting status 7), but we might - # be able to figure out where to start linearising. That - # will be slower so hopefully there's not much to do. - my @cmd = (@git_debrebase, - qw(--noop-ok -funclean-mixed -funclean-ordering - make-patches --quiet-would-amend)); - # We tolerate soe snags that gdr wouldn't, by default. - if (act_local()) { - debugcmd "+",@cmd; - $!=0; $?=-1; - failedcmd @cmd - if system @cmd - and not ($? == 7*256 or - $? == -1 && $!==ENOENT); - } else { - dryrun_report @cmd; - } - $headref = git_rev_parse('HEAD'); - } + my $upstreamversion = upstreamversion $version; prep_ud(); changedir $playground; - my $upstreamversion = upstreamversion $version; + my $splitbrain_cachekey; + + if ($do_split_brain) { + my $cachehit; + ($cachehit, $splitbrain_cachekey) = + quilt_check_splitbrain_cache($headref, $upstreamversion); + if ($cachehit) { + changedir $maindir; + return; + } + } + + unpack_playtree_need_cd_work($headref); + if ($do_split_brain) { + runcmd @git, qw(checkout -q -b dgit-view); + # so long as work is not deleted, its current branch will + # remain dgit-view, rather than master, so subsequent calls to + # unpack_playtree_need_cd_work + # will DTRT, resetting dgit-view. + confess if $made_split_brain; + $made_split_brain = 1; + } + chdir '..'; if ($fopts->{'single-debian-patch'}) { + fail f_ + "quilt mode %s does not make sense (or is not supported) with single-debian-patch", + $quilt_mode + if quiltmode_splitbrain(); quilt_fixup_singlepatch($clogp, $headref, $upstreamversion); } else { - quilt_fixup_multipatch($clogp, $headref, $upstreamversion); + quilt_fixup_multipatch($clogp, $headref, $upstreamversion, + $splitbrain_cachekey); } changedir $maindir; @@ -5839,12 +5873,29 @@ END @git, qw(pull --ff-only -q), "$playground/work", qw(master); } -sub unpack_playtree_mkwork ($) { +sub build_check_quilt_splitbrain () { + build_maybe_quilt_fixup(); + + if ($do_split_brain) { + fail <' or confess "$!"; @@ -5955,8 +6011,9 @@ END sub quilt_fakedsc2unapplied ($$) { my ($headref, $upstreamversion) = @_; # must be run in the playground - # quilt_make_fake_dsc must have been called + # quilt_need_fake_dsc must have been called + quilt_need_fake_dsc($upstreamversion); runcmd qw(sh -ec), 'exec dpkg-source --no-check --skip-patches -x fake.dsc >/dev/null'; @@ -5984,6 +6041,8 @@ sub quilt_check_splitbrain_cache ($$) { # Computes the cache key and looks in the cache. # Returns ($dgit_view_commitid, $cachekey) or (undef, $cachekey) + quilt_need_fake_dsc($upstreamversion); + my $splitbrain_cachekey; progress f_ @@ -6015,12 +6074,12 @@ sub quilt_check_splitbrain_cache ($$) { "refs/$splitbraincache", $splitbrain_cachekey; if ($cachehit) { - unpack_playtree_mkwork($headref); + unpack_playtree_need_cd_work($headref); my $saved = maybe_split_brain_save $headref, $cachehit, "cache-hit"; if ($cachehit ne $headref) { progress f_ "dgit view: found cached (%s)", $saved; runcmd @git, qw(checkout -q -b dgit-view), $cachehit; - $split_brain = 1; + $made_split_brain = 1; return ($cachehit, $splitbrain_cachekey); } progress __ "dgit view: found cached, no changes required"; @@ -6032,7 +6091,7 @@ sub quilt_check_splitbrain_cache ($$) { } sub quilt_fixup_multipatch ($$$) { - my ($clogp, $headref, $upstreamversion) = @_; + my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_; progress f_ "examining quilt state (multiple patches, %s mode)", $quilt_mode; @@ -6106,16 +6165,39 @@ sub quilt_fixup_multipatch ($$$) { # afterwards with dpkg-source --before-build. That lets us save a # tree object corresponding to .origs. - my $splitbrain_cachekey; + if ($quilt_mode eq 'linear' + && branch_is_gdr($headref)) { + # This is much faster. It also makes patches that gdr + # likes better for future updates without laundering. + # + # However, it can fail in some casses where we would + # succeed: if there are existing patches, which correspond + # to a prefix of the branch, but are not in gbp/gdr + # format, gdr will fail (exiting status 7), but we might + # be able to figure out where to start linearising. That + # will be slower so hopefully there's not much to do. - quilt_make_fake_dsc($upstreamversion); + unpack_playtree_need_cd_work $headref; - if (quiltmode_splitbrain()) { - my $cachehit; - ($cachehit, $splitbrain_cachekey) = - quilt_check_splitbrain_cache($headref, $upstreamversion); - return if $cachehit; + my @cmd = (@git_debrebase, + qw(--noop-ok -funclean-mixed -funclean-ordering + make-patches --quiet-would-amend)); + # We tolerate soe snags that gdr wouldn't, by default. + if (act_local()) { + debugcmd "+",@cmd; + $!=0; $?=-1; + failedcmd @cmd + if system @cmd + and not ($? == 7*256 or + $? == -1 && $!==ENOENT); + } else { + dryrun_report @cmd; + } + $headref = git_rev_parse('HEAD'); + + chdir '..'; } + my $unapplied=quilt_fakedsc2unapplied($headref, $upstreamversion); ensuredir '.pc'; @@ -6134,7 +6216,7 @@ END changedir '..'; - unpack_playtree_mkwork($headref); + unpack_playtree_need_cd_work($headref); my $mustdeletepc=0; if (stat_exists ".pc") { @@ -6369,9 +6451,20 @@ sub build_or_push_prep_early () { $dscfn = dscfn($version); } +sub build_or_push_prep_modes () { + my ($format,) = get_source_format(); + printdebug "format $format, quilt mode $quilt_mode\n"; + if (madformat_wantfixup($format) && quiltmode_splitbrain()) { + $do_split_brain = 1; + } + fail __ "dgit: --include-dirty is not supported in split view quilt mode" + if $do_split_brain && $includedirty; +} + sub build_prep_early () { build_or_push_prep_early(); notpushing(); + build_or_push_prep_modes(); check_not_dirty(); } @@ -6393,7 +6486,7 @@ sub build_prep ($) { # said -wc we should still do the check. clean_tree_check(); } - build_maybe_quilt_fixup(); + build_check_quilt_splitbrain(); if ($rmchanges) { my $pat = changespat $version; foreach my $f (glob "$buildproductsdir/$pat") { @@ -6682,7 +6775,7 @@ sub building_source_in_playtree { # # Note that if we are building a source package in split brain # mode we do not support including uncommitted changes, because - # that makes quilt fixup too hard. I.e. ($split_brain && (dgit is + # that makes quilt fixup too hard. I.e. ($made_split_brain && (dgit is # building a source package)) => !$includedirty return !$includedirty; } @@ -6693,6 +6786,8 @@ sub build_source { unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT or fail f_ "remove %s: %s", $sourcechanges, $!; } + confess unless !!$made_split_brain == !!$do_split_brain; + my @cmd = (@dpkgsource, qw(-b --)); my $leafdir; if (building_source_in_playtree()) { @@ -6701,12 +6796,12 @@ sub build_source { # If we are in split brain, there is already a playtree with # the thing we should package into a .dsc (thanks to quilt # fixup). If not, make a playtree - prep_ud() unless $split_brain; + prep_ud() unless $made_split_brain; changedir $playground; - unless ($split_brain) { + unless ($made_split_brain) { my $upstreamversion = upstreamversion $version; unpack_playtree_linkorigs($upstreamversion, sub { }); - unpack_playtree_mkwork($headref); + unpack_playtree_need_cd_work($headref); changedir '..'; } } else { @@ -6773,7 +6868,7 @@ sub cmd_push_source { "dgit push-source: --include-dirty/--ignore-dirty does not make". "sense with push-source!" if $includedirty; - build_maybe_quilt_fixup(); + build_check_quilt_splitbrain(); if ($changesfile) { my $changes = parsecontrol("$buildproductsdir/$changesfile", __ "source changes file"); @@ -6872,7 +6967,6 @@ sub cmd_print_unapplied_treeish { prep_ud(); changedir $playground; my $uv = upstreamversion $version; - quilt_make_fake_dsc($uv); my $u = quilt_fakedsc2unapplied($headref, $uv); print $u, "\n" or confess "$!"; } @@ -7504,19 +7598,10 @@ sub parseopts_late_defaults () { $$vr = $v; } - fail __ "dgit: --include-dirty is not supported in split view quilt mode" - if $split_brain && $includedirty; - - if (!defined $cleanmode) { + { local $access_forpush; - $cleanmode = access_cfg('clean-mode-newer', 'RETURN-UNDEF'); - $cleanmode = undef if $cleanmode && $cleanmode !~ m/^$cleanmode_re$/; - - $cleanmode //= access_cfg('clean-mode', 'RETURN-UNDEF'); - $cleanmode //= 'dpkg-source'; - - badcfg f_ "unknown clean-mode \`%s'", $cleanmode unless - $cleanmode =~ m/$cleanmode_re/; + default_from_access_cfg(\$cleanmode, 'clean-mode', 'dpkg-source', + $cleanmode_re); } $buildproductsdir //= access_cfg('build-products-dir', 'RETURN-UNDEF');