chiark / gitweb /
changelog: Expand on explanation of #930922
[dgit.git] / dgit
diff --git a/dgit b/dgit
index cfd4f7ce2ca0681698d17715a4ee9887c352ac46..2d235a633fa9433d5febcf8b78ba2c9d7a62a4ec 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -82,7 +82,7 @@ our $quilt_mode;
 our $quilt_upstream_commitish;
 our $quilt_upstream_commitish_used;
 our $quilt_upstream_commitish_message;
-our $quilt_options_re = 'gbp|dpm|baredebian';
+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};
@@ -2290,7 +2290,6 @@ sub import_tarball_tartrees ($$) {
 
        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;
@@ -2302,6 +2301,7 @@ sub import_tarball_tartrees ($$) {
                          $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;
@@ -2367,6 +2367,7 @@ sub import_tarball_tartrees ($$) {
             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,
         };
@@ -2383,6 +2384,103 @@ sub import_tarball_tartrees ($$) {
     @tartrees;
 }
 
+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 $any_orig = grep { $_->{Orig} } @$tartrees;
+
+    my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
+    my $clogp;
+    my $r1clogp;
+
+    printdebug "import clog search...\n";
+    parsechangelog_loop \@clogcmd, (__ "package changelog"), sub {
+       my ($thisstanza, $desc) = @_;
+       no warnings qw(exiting);
+
+       $clogp //= $thisstanza;
+
+       printdebug "import clog $thisstanza->{version} $desc...\n";
+
+       last if !$any_orig; # we don't need $r1clogp
+
+       # We look for the first (most recent) changelog entry whose
+       # version number is lower than the upstream version of this
+       # package.  Then the last (least recent) previous changelog
+       # entry is treated as the one which introduced this upstream
+       # version and used for the synthetic commits for the upstream
+       # tarballs.
+
+       # One might think that a more sophisticated algorithm would be
+       # necessary.  But: we do not want to scan the whole changelog
+       # file.  Stopping when we see an earlier version, which
+       # necessarily then is an earlier upstream version, is the only
+       # realistic way to do that.  Then, either the earliest
+       # changelog entry we have seen so far is indeed the earliest
+       # upload of this upstream version; or there are only changelog
+       # entries relating to later upstream versions (which is not
+       # possible unless the changelog and .dsc disagree about the
+       # version).  Then it remains to choose between the physically
+       # last entry in the file, and the one with the lowest version
+       # number.  If these are not the same, we guess that the
+       # versions were created in a non-monotonic order rather than
+       # that the changelog entries have been misordered.
+
+       printdebug "import clog $thisstanza->{version} vs $upstreamv...\n";
+
+       last if version_compare($thisstanza->{version}, $upstreamv) < 0;
+       $r1clogp = $thisstanza;
+
+       printdebug "import clog $r1clogp->{version} becomes r1\n";
+    };
+
+    $clogp or fail __ "package changelog has no entries!";
+
+    my $authline = clogp_authline $clogp;
+    my $changes = getfield $clogp, 'Changes';
+    $changes =~ s/^\n//; # Changes: \n
+    my $cversion = getfield $clogp, 'Version';
+
+    my $r1authline;
+    if (@$tartrees) {
+       $r1clogp //= $clogp; # maybe there's only one entry;
+        $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) {
+           printdebug "import tartree $tt->{F} $tt->{Tree}\n";
+
+           # untranslated so that different people's imports are identical
+           my $mbody = sprintf "Import %s", $tt->{F};
+           $tt->{Commit} = hash_commit_text($tt->{Orig} ? <<END_O : <<END_T);
+tree $tt->{Tree}
+author $r1authline
+committer $r1authline
+
+$mbody
+
+[dgit import orig $tt->{F}]
+END_O
+tree $tt->{Tree}
+author $authline
+committer $authline
+
+$mbody
+
+[dgit import tarball $package $cversion $tt->{F}]
+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.
@@ -2440,9 +2538,9 @@ sub generate_commits_from_dsc () {
        }
     }
 
-    my @tartrees = import_tarball_tartrees($upstreamv, \@dfi);
-
-    my $any_orig = grep { $_->{Orig} } @tartrees;
+    my @tartrees;
+    @tartrees = import_tarball_tartrees($upstreamv, \@dfi)
+       unless @dfi == 1; # only one file in .dsc
 
     my $dscfn = "$package.dsc";
 
@@ -2473,91 +2571,11 @@ sub generate_commits_from_dsc () {
        $dappliedtree = git_add_write_tree();
     }
 
-    my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
-    my $clogp;
-    my $r1clogp;
-
-    printdebug "import clog search...\n";
-    parsechangelog_loop \@clogcmd, (__ "package changelog"), sub {
-       my ($thisstanza, $desc) = @_;
-       no warnings qw(exiting);
-
-       $clogp //= $thisstanza;
+    my ($authline, $r1authline, $clogp, $changes) =
+       import_tarball_commits(\@tartrees, $upstreamv);
 
-       printdebug "import clog $thisstanza->{version} $desc...\n";
-
-       last if !$any_orig; # we don't need $r1clogp
-
-       # We look for the first (most recent) changelog entry whose
-       # version number is lower than the upstream version of this
-       # package.  Then the last (least recent) previous changelog
-       # entry is treated as the one which introduced this upstream
-       # version and used for the synthetic commits for the upstream
-       # tarballs.
-
-       # One might think that a more sophisticated algorithm would be
-       # necessary.  But: we do not want to scan the whole changelog
-       # file.  Stopping when we see an earlier version, which
-       # necessarily then is an earlier upstream version, is the only
-       # realistic way to do that.  Then, either the earliest
-       # changelog entry we have seen so far is indeed the earliest
-       # upload of this upstream version; or there are only changelog
-       # entries relating to later upstream versions (which is not
-       # possible unless the changelog and .dsc disagree about the
-       # version).  Then it remains to choose between the physically
-       # last entry in the file, and the one with the lowest version
-       # number.  If these are not the same, we guess that the
-       # versions were created in a non-monotonic order rather than
-       # that the changelog entries have been misordered.
-
-       printdebug "import clog $thisstanza->{version} vs $upstreamv...\n";
-
-       last if version_compare($thisstanza->{version}, $upstreamv) < 0;
-       $r1clogp = $thisstanza;
-
-       printdebug "import clog $r1clogp->{version} becomes r1\n";
-    };
-
-    $clogp or fail __ "package changelog has no entries!";
-
-    my $authline = clogp_authline $clogp;
-    my $changes = getfield $clogp, 'Changes';
-    $changes =~ s/^\n//; # Changes: \n
     my $cversion = getfield $clogp, 'Version';
 
-    if (@tartrees) {
-       $r1clogp //= $clogp; # maybe there's only one entry;
-       my $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) {
-           printdebug "import tartree $tt->{F} $tt->{Tree}\n";
-
-           my $mbody = f_ "Import %s", $tt->{F};
-           $tt->{Commit} = hash_commit_text($tt->{Orig} ? <<END_O : <<END_T);
-tree $tt->{Tree}
-author $r1authline
-committer $r1authline
-
-$mbody
-
-[dgit import orig $tt->{F}]
-END_O
-tree $tt->{Tree}
-author $authline
-committer $authline
-
-$mbody
-
-[dgit import tarball $package $cversion $tt->{F}]
-END_T
-       }
-    }
-
     printdebug "import main commit\n";
 
     open C, ">../commit.tmp" or confess "$!";
@@ -2677,7 +2695,10 @@ END
        if ($vcmp < 0) {
            @output = ($rawimport_mergeinput, $lastpush_mergeinput,
                { ReverseParents => 1,
-                 Message => (f_ <<END, $package, $cversion, $csuite) });
+                 # untranslated so that different people's pseudomerges
+                 # are not needlessly different (although they will
+                 # still differ if the series of pulls is different)
+                 Message => (sprintf <<END, $package, $cversion, $csuite) });
 Record %s (%s) in archive suite %s
 END
        } elsif ($vcmp > 0) {
@@ -6050,6 +6071,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) = @_;
 
@@ -6203,7 +6248,74 @@ END
     my $uheadref = $headref;
     my $uhead_whatshort = 'HEAD';
 
-    if ($quilt_mode =~ m/baredebian/) {
+    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 <<END;
+tree $tree
+${parents}author $r1authline
+committer $r1authline
+
+$mbody
+
+[dgit import tarballs combine $package $upstreamversion]
+END
+           # 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.  This fragmentt is referring to multiple
+           # orig tarballs in a source package.
+           $uhead_whatshort = __ 'tarballs';
+
+           runcmd @git, qw(reset -q);
+       }
+       $quilt_upstream_commitish = $uheadref;
+       $quilt_upstream_commitish_used = '*orig*';
+       $quilt_upstream_commitish_message = '';
+    }
+    if ($quilt_mode =~ m/baredebian$/) {
        $uheadref = $quilt_upstream_commitish;
        # TRANSLATORS: this translation must fit in the ASCII art
        # quilt differences display.  The untranslated display
@@ -6238,9 +6350,10 @@ END
     # TRANSLATORS: Try to keep this ascii-art layout right.  The 0s in
     # %9.00009s will be ignored and are there to make the format the
     # same length (9 characters) as the output it generates.  If you
-    # change the value 9, your translation of "upstream" must fit into
-    # the new length, and you should change the number of 0s.  Do
-    # not reduce it below 4 as HEAD has to fit too.
+    # change the value 9, your translations of "upstream" and
+    # 'tarball' must fit into the new length, and you should change
+    # the number of 0s.  Do not reduce it below 4 as HEAD has to fit
+    # too.
     progress f_
 "%s: quilt differences: src:  %s orig %s     gitignores:  %s orig %s\n".
 "%s: quilt differences: %9.00009s %s o+d/p          %9.00009s %s o+d/p",
@@ -7603,6 +7716,7 @@ sub parseopts_late_defaults () {
            or badcfg f_ "unknown quilt-mode \`%s'", $quilt_mode;
        $quilt_mode = $1;
     }
+    $quilt_mode =~ s/^(baredebian)\+git$/$1/;
 
     foreach my $moc (@modeopt_cfgs) {
        local $access_forpush;