X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=dgit;h=c23ffa65758362c83b031e09474a75d59dbd8342;hb=acb8139b0c7f4de6287ab2c347170c88da8c89ad;hp=fb64dc2da8fc967051ce948eb6e8bd44d4c8dcf1;hpb=585cfef168061d0728969c7d9db7e0f04cfc4efa;p=dgit.git diff --git a/dgit b/dgit index fb64dc2d..c23ffa65 100755 --- a/dgit +++ b/dgit @@ -80,7 +80,10 @@ our $rmchanges; our $overwrite_version; # undef: not specified; '': check changelog our $quilt_mode; our $quilt_upstream_commitish; -our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied'; +our $quilt_upstream_commitish_used; +our $quilt_upstream_commitish_message; +our $quilt_options_re = 'gbp|dpm|baredebian(?:\+tarball|\+git)?'; +our $quilt_modes_re = "linear|smash|auto|nofix|nocheck|unapplied|$quilt_options_re"; our $splitview_mode; our $splitview_modes_re = qr{auto|always|never}; our $dodep14tag; @@ -295,7 +298,7 @@ sub deliberately_not_fast_forward () { } sub quiltmode_splitting () { - $quilt_mode =~ m/gbp|dpm|unapplied/; + $quilt_mode =~ m/gbp|dpm|unapplied|baredebian/; } sub do_split_brain () { !!($do_split_brain // confess) } @@ -2268,62 +2271,9 @@ sub dotdot_bpd_transfer_origs ($$$) { closedir DD; } -sub generate_commits_from_dsc () { - # See big comment in fetch_from_archive, below. - # See also README.dsc-import. - prep_ud(); - changedir $playground; - - my $bpd_abs = bpd_abs(); - my $upstreamv = upstreamversion $dsc->{version}; - my @dfi = dsc_files_info(); - - dotdot_bpd_transfer_origs $bpd_abs, $upstreamv, - sub { grep { $_->{Filename} eq $_[0] } @dfi }; - - foreach my $fi (@dfi) { - my $f = $fi->{Filename}; - die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#; - my $upper_f = "$bpd_abs/$f"; - - printdebug "considering reusing $f: "; - - if (link_ltarget "$upper_f,fetch", $f) { - printdebug "linked (using ...,fetch).\n"; - } elsif ((printdebug "($!) "), - $! != ENOENT) { - fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!; - } elsif (link_ltarget $upper_f, $f) { - printdebug "linked.\n"; - } elsif ((printdebug "($!) "), - $! != ENOENT) { - fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!; - } else { - printdebug "absent.\n"; - } - - my $refetched; - complete_file_from_dsc('.', $fi, \$refetched) - or next; - - printdebug "considering saving $f: "; - - if (rename_link_xf 1, $f, $upper_f) { - printdebug "linked.\n"; - } elsif ((printdebug "($@) "), - $! != EEXIST) { - fail f_ "saving %s: %s", "$buildproductsdir/$f", $@; - } elsif (!$refetched) { - printdebug "no need.\n"; - } elsif (rename_link_xf 1, $f, "$upper_f,fetch") { - printdebug "linked (using ...,fetch).\n"; - } elsif ((printdebug "($@) "), - $! != EEXIST) { - fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@; - } else { - printdebug "cannot.\n"; - } - } +sub import_tarball_tartrees ($$) { + my ($upstreamv, $dfi) = @_; + # cwd should be the playground # We unpack and record the orig tarballs first, so that we only # need disk space for one private copy of the unpacked source. @@ -2333,14 +2283,13 @@ sub generate_commits_from_dsc () { my @tartrees; my $orig_f_base = srcfn $upstreamv, ''; - foreach my $fi (@dfi) { + foreach my $fi (@$dfi) { # We actually import, and record as a commit, every tarball # (unless there is only one file, in which case there seems # little point. my $f = $fi->{Filename}; printdebug "import considering $f "; - (printdebug "only one dfi\n"), next if @dfi == 1; (printdebug "not tar\n"), next unless $f =~ m/\.tar(\.\w+)?$/; (printdebug "signature\n"), next if $f =~ m/$orig_f_sig_re$/o; my $compr_ext = $1; @@ -2352,6 +2301,7 @@ sub generate_commits_from_dsc () { $compr_ext, $orig_f_part ), "\n"; + my $path = $fi->{Path} // $f; my $input = new IO::File $f, '<' or die "$f $!"; my $compr_pid; my @compr_cmd; @@ -2417,6 +2367,7 @@ sub generate_commits_from_dsc () { Sort => (!$orig_f_part ? 2 : $orig_f_part =~ m/-/g ? 1 : 0), + OrigPart => $orig_f_part, # 'orig', 'orig-XXX', or undef F => $f, Tree => $tree, }; @@ -2430,36 +2381,15 @@ sub generate_commits_from_dsc () { $a->{F} cmp $b->{F} } @tartrees; - my $any_orig = grep { $_->{Orig} } @tartrees; + @tartrees; +} - my $dscfn = "$package.dsc"; +sub import_tarball_commits ($$) { + my ($tartrees, $upstreamv) = @_; + # cwd should be a playtree which has a relevant debian/changelog + # fills in $tt->{Commit} for each one - my $treeimporthow = 'package'; - - open D, ">", $dscfn or die "$dscfn: $!"; - print D $dscdata or die "$dscfn: $!"; - close D or die "$dscfn: $!"; - my @cmd = qw(dpkg-source); - push @cmd, '--no-check' if $dsc_checked; - if (madformat $dsc->{format}) { - push @cmd, '--skip-patches'; - $treeimporthow = 'unpatched'; - } - push @cmd, qw(-x --), $dscfn; - runcmd @cmd; - - my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package"); - if (madformat $dsc->{format}) { - check_for_vendor_patches(); - } - - my $dappliedtree; - if (madformat $dsc->{format}) { - my @pcmd = qw(dpkg-source --before-build .); - runcmd shell_cmd 'exec >/dev/null', @pcmd; - rmtree '.pc'; - $dappliedtree = git_add_write_tree(); - } + my $any_orig = grep { $_->{Orig} } @$tartrees; my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all); my $clogp; @@ -2513,19 +2443,21 @@ sub generate_commits_from_dsc () { $changes =~ s/^\n//; # Changes: \n my $cversion = getfield $clogp, 'Version'; - if (@tartrees) { + my $r1authline; + if (@$tartrees) { $r1clogp //= $clogp; # maybe there's only one entry; - my $r1authline = clogp_authline $r1clogp; + $r1authline = clogp_authline $r1clogp; # Strictly, r1authline might now be wrong if it's going to be # unused because !$any_orig. Whatever. printdebug "import tartrees authline $authline\n"; printdebug "import tartrees r1authline $r1authline\n"; - foreach my $tt (@tartrees) { + foreach my $tt (@$tartrees) { printdebug "import tartree $tt->{F} $tt->{Tree}\n"; - my $mbody = f_ "Import %s", $tt->{F}; + # untranslated so that different people's imports are identical + my $mbody = sprintf "Import %s", $tt->{F}; $tt->{Commit} = hash_commit_text($tt->{Orig} ? <{Tree} author $r1authline @@ -2546,6 +2478,104 @@ END_T } } + return ($authline, $r1authline, $clogp, $changes); +} + +sub generate_commits_from_dsc () { + # See big comment in fetch_from_archive, below. + # See also README.dsc-import. + prep_ud(); + changedir $playground; + + my $bpd_abs = bpd_abs(); + my $upstreamv = upstreamversion $dsc->{version}; + my @dfi = dsc_files_info(); + + dotdot_bpd_transfer_origs $bpd_abs, $upstreamv, + sub { grep { $_->{Filename} eq $_[0] } @dfi }; + + foreach my $fi (@dfi) { + my $f = $fi->{Filename}; + die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#; + my $upper_f = "$bpd_abs/$f"; + + printdebug "considering reusing $f: "; + + if (link_ltarget "$upper_f,fetch", $f) { + printdebug "linked (using ...,fetch).\n"; + } elsif ((printdebug "($!) "), + $! != ENOENT) { + fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!; + } elsif (link_ltarget $upper_f, $f) { + printdebug "linked.\n"; + } elsif ((printdebug "($!) "), + $! != ENOENT) { + fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!; + } else { + printdebug "absent.\n"; + } + + my $refetched; + complete_file_from_dsc('.', $fi, \$refetched) + or next; + + printdebug "considering saving $f: "; + + if (rename_link_xf 1, $f, $upper_f) { + printdebug "linked.\n"; + } elsif ((printdebug "($@) "), + $! != EEXIST) { + fail f_ "saving %s: %s", "$buildproductsdir/$f", $@; + } elsif (!$refetched) { + printdebug "no need.\n"; + } elsif (rename_link_xf 1, $f, "$upper_f,fetch") { + printdebug "linked (using ...,fetch).\n"; + } elsif ((printdebug "($@) "), + $! != EEXIST) { + fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@; + } else { + printdebug "cannot.\n"; + } + } + + my @tartrees; + @tartrees = import_tarball_tartrees($upstreamv, \@dfi) + unless @dfi == 1; # only one file in .dsc + + my $dscfn = "$package.dsc"; + + my $treeimporthow = 'package'; + + open D, ">", $dscfn or die "$dscfn: $!"; + print D $dscdata or die "$dscfn: $!"; + close D or die "$dscfn: $!"; + my @cmd = qw(dpkg-source); + push @cmd, '--no-check' if $dsc_checked; + if (madformat $dsc->{format}) { + push @cmd, '--skip-patches'; + $treeimporthow = 'unpatched'; + } + push @cmd, qw(-x --), $dscfn; + runcmd @cmd; + + my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package"); + if (madformat $dsc->{format}) { + check_for_vendor_patches(); + } + + my $dappliedtree; + if (madformat $dsc->{format}) { + my @pcmd = qw(dpkg-source --before-build .); + runcmd shell_cmd 'exec >/dev/null', @pcmd; + rmtree '.pc'; + $dappliedtree = git_add_write_tree(); + } + + my ($authline, $r1authline, $clogp, $changes) = + import_tarball_commits(\@tartrees, $upstreamv); + + my $cversion = getfield $clogp, 'Version'; + printdebug "import main commit\n"; open C, ">../commit.tmp" or confess "$!"; @@ -2665,7 +2695,10 @@ END if ($vcmp < 0) { @output = ($rawimport_mergeinput, $lastpush_mergeinput, { ReverseParents => 1, - Message => (f_ < (sprintf < 0) { @@ -4328,7 +4361,7 @@ sub push_mktags ($$ $$ $) { # We make the git tag by hand because (a) that makes it easier # to control the "tagger" (b) we can do remote signing my $authline = clogp_authline $clogp; - my $delibs = join(" ", "",@deliberatelies); + my @dtxinfo = @deliberatelies; my $mktag = sub { my ($tw) = @_; @@ -4349,8 +4382,9 @@ END %s release %s for %s (%s) [dgit] ENDT or confess "$!"; + my $dtxinfo = join(" ", "",@dtxinfo); print TO <{O2H} & 01)) { my $msg = f_ "--quilt=%s specified, implying patches-unapplied git tree\n". " but git tree differs from orig in upstream files.", $quilt_mode; $msg .= $fulldiffhint->($unapplied, 'HEAD'); - if (!stat_exists "debian/patches") { + if (!stat_exists "debian/patches" and $quilt_mode !~ m/baredebian/) { $msg .= __ "\n ... debian/patches is missing; perhaps this is a patch queue branch?"; } @@ -5404,7 +5438,23 @@ sub quiltify_splitting ($$$$$$$) { but git tree differs from result of applying debian/patches to upstream END } - if ($quilt_mode =~ m/gbp|unapplied/ && + if ($quilt_mode =~ m/baredebian/) { + # We need to construct a merge which has upstream files from + # upstream and debian/ files from HEAD. + + read_tree_upstream $quilt_upstream_commitish, 1, $headref; + my $version = getfield $clogp, 'Version'; + my $upsversion = upstreamversion $version; + my $merge = make_commit + [ $headref, $quilt_upstream_commitish ], + [ +(f_ <{O2A} & 01)) { # some patches progress __ "dgit view: creating patches-applied version using gbp pq"; runcmd shell_cmd 'exec >/dev/null', gbp_pq, qw(import); @@ -6022,6 +6072,30 @@ sub quilt_check_splitbrain_cache ($$) { return (undef, $splitbrain_cachekey); } +sub baredebian_origtarballs_scan ($$$) { + my ($fakedfi, $upstreamversion, $dir) = @_; + if (!opendir OD, $dir) { + return if $! == ENOENT; + fail "opendir $dir (origs): $!"; + } + + while ($!=0, defined(my $leaf = readdir OD)) { + { + local ($debuglevel) = $debuglevel-1; + printdebug "BDOS $dir $leaf ?\n"; + } + next unless is_orig_file_of_vsn $leaf, $upstreamversion; + next if grep { $_->{Filename} eq $leaf } @$fakedfi; + push @$fakedfi, { + Filename => $leaf, + Path => "$dir/$leaf", + }; + } + + die "$dir; $!" if $!; + closedir OD; +} + sub quilt_fixup_multipatch ($$$) { my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_; @@ -6169,9 +6243,88 @@ END # We calculate some guesswork now about what kind of tree this might # be. This is mostly for error reporting. + my $tentries = cmdoutput @git, qw(ls-tree --name-only -z), $headref; + my $onlydebian = $tentries eq "debian\0"; + my $uheadref = $headref; my $uhead_whatshort = 'HEAD'; + if ($quilt_mode =~ m/baredebian\+tarball/) { + # We need to make a tarball import. Yuk. + # We want to do this here so that we have a $uheadref value + + my @fakedfi; + baredebian_origtarballs_scan \@fakedfi, $upstreamversion, bpd_abs(); + baredebian_origtarballs_scan \@fakedfi, $upstreamversion, + "$maindir/.." unless $buildproductsdir eq '..'; + changedir '..'; + + my @tartrees = import_tarball_tartrees $upstreamversion, \@fakedfi; + + fail __ "baredebian quilt fixup: could not find any origs" + unless @tartrees; + + changedir 'work'; + my ($authline, $r1authline, $clogp,) = + import_tarball_commits \@tartrees, $upstreamversion; + + if (@tartrees == 1) { + $uheadref = $tartrees[0]{Commit}; + # TRANSLATORS: this translation must fit in the ASCII art + # quilt differences display. The untranslated display + # says %9.9s, so with that display it must be at most 9 + # characters. + $uhead_whatshort = __ 'tarball'; + } else { + # on .dsc import we do not make a separate commit, but + # here we need to do so + rm_subdir_cached '.'; + my $parents; + foreach my $ti (@tartrees) { + my $c = $ti->{Commit}; + if ($ti->{OrigPart} eq 'orig') { + runcmd qw(git read-tree), $c; + } elsif ($ti->{OrigPart} =~ m/orig-/) { + read_tree_subdir $', $c; + } else { + confess "$ti->OrigPart} ?" + } + $parents .= "parent $c\n"; + } + my $tree = git_write_tree(); + my $mbody = f_ 'Combine orig tarballs for %s %s', + $package, $upstreamversion; + $uheadref = hash_commit_text <[1], $_->[0] foreach @unrepres; @@ -6211,7 +6374,11 @@ END } my @failsuggestion; - if (!($diffbits->{O2H} & $diffbits->{O2A})) { + if ($onlydebian) { + push @failsuggestion, [ 'onlydebian', __ + "This has only a debian/ directory; you probably want --quilt=bare debian." ] + unless $quilt_mode =~ m/baredebian/; + } elsif (!($diffbits->{O2H} & $diffbits->{O2A})) { push @failsuggestion, [ 'unapplied', __ "This might be a patches-unapplied branch." ]; } elsif (!($diffbits->{H2A} & $diffbits->{O2A})) { @@ -6226,7 +6393,9 @@ END if stat_exists '.gitattributes'; push @failsuggestion, [ 'origs', __ - "Maybe orig tarball(s) are not identical to git representation?" ]; + "Maybe orig tarball(s) are not identical to git representation?" ] + unless $onlydebian && $quilt_mode !~ m/baredebian/; + # ^ in that case, we didn't really look properly if (quiltmode_splitting()) { quiltify_splitting($clogp, $unapplied, $headref, $oldtiptree, @@ -6272,7 +6441,7 @@ sub quilt_fixup_editor () { } sub maybe_apply_patches_dirtily () { - return unless $quilt_mode =~ m/gbp|unapplied/; + return unless $quilt_mode =~ m/gbp|unapplied|baredebian/; print STDERR __ <