From: Ian Jackson Date: Sat, 4 Aug 2018 11:01:50 +0000 (+0100) Subject: git-debrebase: Provide new convert-from-dgit-view operation. X-Git-Tag: archive/debian/6.5~10 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=commitdiff_plain;h=485a61ef66da7ad675e0495355b1f9f1df952bf5 git-debrebase: Provide new convert-from-dgit-view operation. The output is, unavoidably, not very pretty. Closes:#905322. Signed-off-by: Ian Jackson --- diff --git a/debian/changelog b/debian/changelog index a64a06d9..fd3f102f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,8 @@ dgit (6.5~) unstable; urgency=medium * git-debrebase: Properly reject bare dgit dsc imports * git-debrebase: Improve some error message formatting. * test suite: gdr-import-dgitview: New test for dgit dsc imports. + * git-debrebase: Provide new convert-from-dgit-view operation. + The output is, unavoidably, not very pretty. Closes:#905322. -- diff --git a/git-debrebase b/git-debrebase index b51c7148..98e645a4 100755 --- a/git-debrebase +++ b/git-debrebase @@ -1788,6 +1788,194 @@ git-debrebase: WARNING: doing so would drop all upstream patches! END } +sub cmd_convert_from_dgit_view () { + my $clogp = parsechangelog(); + + my $bpd = (cfg 'dgit.default.build-products-dir',1) // '..'; + my $do_origs = 1; + my $do_tags = 1; + my $always = 0; + my $diagnose = 0; + + getoptions("convert-from-dgit-view", + 'diagnose!', \$diagnose, + 'build-products-dir:s', \$bpd, + 'origs!', \$do_origs, + 'tags!', \$do_tags, + 'always-convert-anyway!', \$always); + fail "takes 1 optional argument, the upstream commitish" if @ARGV>1; + + my @upstreams; + + if (@ARGV) { + my $spec = shift @ARGV; + my $commit = git_rev_parse "$spec^{commit}"; + push @upstreams, { Commit => $commit, + Source => "$ARGV[0], from command line", + Only => 1, + }; + } + + my $head = get_head(); + + if (!$always) { + my $troubles = 0; + my $trouble = sub { $troubles++; }; + keycommits $head, sub{}, sub{}, $trouble, $trouble; + printdebug "troubles=$troubles\n"; + if (!$troubles) { + print STDERR <{Version}; + 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]"; + push @upstreams, { Commit => $ups_tag, + Source => $this, + }; + } else { + printf STDERR + " git tag: no suitable tag found (tried %s)\n", + "@tried"; + } + } + if ($do_origs) { + my $p = $clogp->{'Source'}; + # we do a quick check to see if there are plausible origs + my $something=0; + if (!opendir BPD, $bpd) { + die "$bpd: opendir: $!" unless $!==ENOENT; + } else { + while ($!=0, my $f = readdir BPD) { + next unless is_orig_file_of_p_v $f, $p, $version; + printf STDERR + " orig: found what looks like a .orig, %s\n", + "$bpd/$f"; + $something=1; + last; + } + die "read $bpd: $!" if $!; + closedir BPD; + } + if ($something) { + my $tree = cmdoutput + @dgit, qw(--build-products-dir), $bpd, + qw(print-unapplied-treeish); + fresh_workarea(); + in_workarea sub { + runcmd @git, qw(reset --quiet), $tree, qw(-- .); + rm_subdir_cached 'debian'; + $tree = cmdoutput @git, qw(write-tree); + my $ups_synth = make_commit [], [ < $ups_synth, + Source => "orig(s) imported via dgit", + }; + } + } else { + printf STDERR + " orig: no suitable origs found (looked for %s in %s)\n", + "${p}_".(stripeoch $version)."...", $bpd; + } + } + } + + my $some_patches = stat_exists 'debian/patches/series'; + + print STDERR "Evaluating possible commits corresponding to upstream:\n"; + + my $result; + foreach my $u (@upstreams) { + my $work = $head; + fresh_workarea(); + in_workarea sub { + runcmd @git, qw(reset --quiet), $u->{Commit}, qw(-- .); + runcmd @git, qw(checkout), $u->{Commit}, qw(-- .); + runcmd @git, qw(clean -xdff); + runcmd @git, qw(checkout), $head, qw(-- debian); + if ($some_patches) { + rm_subdir_cached 'debian/patches'; + $work = make_commit [ $work ], [ + 'git-debrebase convert-from-dgit-view: drop upstream changes from breakwater', + "Drop upstream changes, and delete debian/patches, as part of converting\n". + "to git-debrebase format. Upstream changes will appear as commits.", + '[git-debrebase convert-from-dgit-view: drop patches from tree]' + ]; + } + $work = make_commit [ $work, $u->{Commit} ], [ + 'git-debrebase convert-from-dgit-view: declare upstream', + '(Re)constructed breakwater merge.', + '[git-debrebase anchor: declare upstream]' + ]; + runcmd @git, qw(checkout --quiet -b mk), $work; + if ($some_patches) { + runcmd @git, qw(checkout), $head, qw(-- debian/patches); + runcmd @git, qw(reset --quiet); + my @gbp_cmd = (qw(gbp pq import)); + if (!$diagnose) { + my $gbp_err = "../gbp-pq-err"; + @gbp_cmd = shell_cmd "exec >$gbp_err 2>&1", @gbp_cmd; + } + my $r = system @gbp_cmd; + if ($r) { + printf STDERR + " %s: couldn't apply patches: gbp pq %s", + $u->{Source}, waitstatusmsg(); + return; + } + } + 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 $diffout if $diagnose; + return; + } + # OMG! + $u->{Result} = $work; + $result = $u; + }; + last if $result; + } + + if (!$result) { + fail <{Source}; + + ffq_check $result->{Result}; + snags_maybe_bail(); + update_head_checkout $head, $result->{Result}, + 'convert-from-dgit-view'; +} + sub cmd_downstream_rebase_launder_v0 () { badusage "needs 1 argument, the baseline" unless @ARGV==1; my ($base) = @ARGV; diff --git a/git-debrebase.1.pod b/git-debrebase.1.pod index eb85c6c4..e544a8c0 100644 --- a/git-debrebase.1.pod +++ b/git-debrebase.1.pod @@ -343,6 +343,72 @@ Be sure to not accidentally treat the result as a git-debrebase branch, or you will drop all the patches! +=item git-debrebase convert-from-dgit-view [] [upstream] + +Converts any dgit-compatible git branch +corresponding to a (possibly hypothetical) 3.0 quilt dsc source package +into a git-debrebase-compatible branch. + +This operation should not be used +if the branch is already in git-debrebase form. +Normally git-debrebase will refuse to continue in this case +(or silently do nothing if the global --noop-ok option is used). + +Some representation of the original upstream source code will be needed. +If I is supplied, that must be a suitable upstream commit. +By default, +git-debrebase will look first for git tags (as for new-upstream), +and then for orig tarballs which it will ask dgit to process. + +The upstream source must be exactly right and +all the patches in debian/patches must be up to date. +Applying the patches from debian/patches to the upstream source +must result in exactly your HEAD. + +The output is laundered and stitched. +The resulting history is not particularly pretty, +especially if orig tarball(s) were imported +to produce a synthetic upstream commit. + +The available convert-options are as follows. +(These must come after convert-from-dgit-view.) + +=over + +=item --[no-]diagnose + +Print additional error messages to help diagnose +failure to find an appropriate upstream. +--no-diagnose is the default. + +=item --build-products-dir + +Directory to look in for orig tarballs. +The default is the git config option +dgit.default.build-products-dir +or failing that, C<..>. +Passed on to dgit, if git-debrebase invokes dgit. + +=item --[no-]origs + +Whether to try to look for or use any orig tarballs. +--origs is the default. + +=item --[no-]tags + +Whether to try to look for or use any upstream git tags. +--tags is the default. + +=item --always-convert-anyway + +Perform the conversion operation, +producing unpleasant extra history, +even if the branch seems to be in git-debrebase form already. +This should not be done unless necessary, +and it should not be necessary. + +=back + =back =head1 OPTIONS