chiark / gitweb /
Import fix: Switch back to unpa branch on patch import iterations.
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 6a7430707ec0b3b1aa5ee9050d746ce5976d3ccc..1e7c923eea6e8070b3f2254af6f8a85570d05aa4 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -69,6 +69,8 @@ our $rmchanges;
 our $overwrite_version; # undef: not specified; '': check changelog
 our $quilt_mode;
 our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied';
+our $dodep14tag;
+our $dodep14tag_re = 'want|no|always';
 our $split_brain_save;
 our $we_are_responder;
 our $initiator_tempdir;
@@ -171,8 +173,7 @@ sub debiantag ($$) {
 
 sub debiantag_maintview ($$) { 
     my ($v,$distro) = @_;
-    $v =~ y/~:/_%/;
-    return "$distro/$v";
+    return "$distro/".dep14_version_mangle $v;
 }
 
 sub madformat ($) { $_[0] eq '3.0 (quilt)' }
@@ -1520,6 +1521,15 @@ sub access_cfg_tagformats () {
     split /\,/, access_cfg('dgit-tag-format');
 }
 
+sub access_cfg_tagformats_can_splitbrain () {
+    my %y = map { $_ => 1 } access_cfg_tagformats;
+    foreach my $needtf (qw(new maint)) {
+       next if $y{$needtf};
+       return 0;
+    }
+    return 1;
+}
+
 sub need_tagformat ($$) {
     my ($fmt, $why) = @_;
     fail "need to use tag format $fmt ($why) but also need".
@@ -1693,7 +1703,13 @@ sub git_write_tree () {
     return $tree;
 }
 
-sub remove_stray_gits () {
+sub git_add_write_tree () {
+    runcmd @git, qw(add -Af .);
+    return git_write_tree();
+}
+
+sub remove_stray_gits ($) {
+    my ($what) = @_;
     my @gitscmd = qw(find -name .git -prune -print0);
     debugcmd "|",@gitscmd;
     open GITS, "-|", @gitscmd or die $!;
@@ -1701,7 +1717,7 @@ sub remove_stray_gits () {
        local $/="\0";
        while (<GITS>) {
            chomp or die;
-           print STDERR "$us: warning: removing from source package: ",
+           print STDERR "$us: warning: removing from $what: ",
                (messagequote $_), "\n";
            rmtree $_;
        }
@@ -1709,8 +1725,8 @@ sub remove_stray_gits () {
     $!=0; $?=0; close GITS or failedcmd @gitscmd;
 }
 
-sub mktree_in_ud_from_only_subdir (;$) {
-    my ($raw) = @_;
+sub mktree_in_ud_from_only_subdir ($;$) {
+    my ($what,$raw) = @_;
 
     # changes into the subdir
     my (@dirs) = <*/.>;
@@ -1719,7 +1735,7 @@ sub mktree_in_ud_from_only_subdir (;$) {
     my $dir = $1;
     changedir $dir;
 
-    remove_stray_gits();
+    remove_stray_gits($what);
     mktree_in_ud_here();
     if (!$raw) {
        my ($format, $fopts) = get_source_format();
@@ -1728,8 +1744,7 @@ sub mktree_in_ud_from_only_subdir (;$) {
        }
     }
 
-    runcmd @git, qw(add -Af);
-    my $tree=git_write_tree();
+    my $tree=git_add_write_tree();
     return ($tree,$dir);
 }
 
@@ -2123,14 +2138,14 @@ sub generate_commits_from_dsc () {
            $input = $compr_fh;
        }
 
-       rmtree "../unpack-tar";
-       mkdir "../unpack-tar" or die $!;
+       rmtree "_unpack-tar";
+       mkdir "_unpack-tar" or die $!;
        my @tarcmd = qw(tar -x -f -
                        --no-same-owner --no-same-permissions
                        --no-acls --no-xattrs --no-selinux);
        my $tar_pid = fork // die $!;
        if (!$tar_pid) {
-           chdir "../unpack-tar" or die $!;
+           chdir "_unpack-tar" or die $!;
            open STDIN, "<&", $input or die $!;
            exec @tarcmd;
            die "dgit (child): exec $tarcmd[0]: $!";
@@ -2144,11 +2159,21 @@ sub generate_commits_from_dsc () {
        # finally, we have the results in "tarball", but maybe
        # with the wrong permissions
 
-       runcmd qw(chmod -R +rwX ../unpack-tar);
-       changedir "../unpack-tar";
-       my ($tree) = mktree_in_ud_from_only_subdir(1);
-       changedir "../../unpack";
-       rmtree "../unpack-tar";
+       runcmd qw(chmod -R +rwX _unpack-tar);
+       changedir "_unpack-tar";
+       remove_stray_gits($f);
+       mktree_in_ud_here();
+       
+       my ($tree) = git_add_write_tree();
+       my $tentries = cmdoutput @git, qw(ls-tree -z), $tree;
+       if ($tentries =~ m/^\d+ tree (\w+)\t[^\000]+\000$/s) {
+           $tree = $1;
+           printdebug "one subtree $1\n";
+       } else {
+           printdebug "multiple subtrees\n";
+       }
+       changedir "..";
+       rmtree "_unpack-tar";
 
        my $ent = [ $f, $tree ];
        push @tartrees, {
@@ -2187,7 +2212,7 @@ sub generate_commits_from_dsc () {
     push @cmd, qw(-x --), $dscfn;
     runcmd @cmd;
 
-    my ($tree,$dir) = mktree_in_ud_from_only_subdir();
+    my ($tree,$dir) = mktree_in_ud_from_only_subdir("source package");
     if (madformat $dsc->{format}) { 
        check_for_vendor_patches();
     }
@@ -2197,8 +2222,7 @@ sub generate_commits_from_dsc () {
        my @pcmd = qw(dpkg-source --before-build .);
        runcmd shell_cmd 'exec >/dev/null', @pcmd;
        rmtree '.pc';
-       runcmd @git, qw(add -Af);
-       $dappliedtree = git_write_tree();
+       $dappliedtree = git_add_write_tree();
     }
 
     my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
@@ -2343,6 +2367,8 @@ END
        my $path = $ENV{PATH} or die;
 
        foreach my $use_absurd (qw(0 1)) {
+           runcmd @git, qw(checkout -q unpa);
+           runcmd @git, qw(update-ref -d refs/heads/patch-queue/unpa);
            local $ENV{PATH} = $path;
            if ($use_absurd) {
                chomp $@;
@@ -2359,11 +2385,12 @@ END
                die "only absurd git-apply!\n" if !$use_absurd
                    && forceing [qw(import-gitapply-absurd)];
 
-               local $ENV{PATH} = $path if $use_absurd;
+               local $ENV{DGIT_ABSURD_DEBUG} = $debuglevel if $use_absurd;
+               local $ENV{PATH} = $path                    if $use_absurd;
 
                my @showcmd = (gbp_pq, qw(import));
                my @realcmd = shell_cmd
-                   'exec >/dev/null 2>../../gbp-pq-output', @showcmd;
+                   'exec >/dev/null 2>>../../gbp-pq-output', @showcmd;
                debugcmd "+",@realcmd;
                if (system @realcmd) {
                    die +(shellquote @showcmd).
@@ -3247,7 +3274,7 @@ sub clone_finish ($) {
     runcmd qw(bash -ec), <<'END';
         set -o pipefail
         git ls-tree -r --name-only -z HEAD | \
-        xargs -0r touch -r . --
+        xargs -0r touch -h -r . --
 END
     printdone "ready for work in $dstdir";
 }
@@ -3652,7 +3679,21 @@ sub push_tagwants ($$$$) {
            TfSuffix => '-maintview',
             View => 'maint',
         };
-    }
+    } elsif ($dodep14tag eq 'no' ? 0
+            : $dodep14tag eq 'want' ? access_cfg_tagformats_can_splitbrain
+            : $dodep14tag eq 'always'
+            ? (access_cfg_tagformats_can_splitbrain or fail <<END)
+--dep14tag-always (or equivalent in config) means server must support
+ both "new" and "maint" tag formats, but config says it doesn't.
+END
+           : die "$dodep14tag ?") {
+       push @tagwants, {
+           TagFn => \&debiantag_maintview,
+           Objid => $dgithead,
+           TfSuffix => '-dgit',
+           View => 'dgit',
+        };
+    };
     foreach my $tw (@tagwants) {
        $tw->{Tag} = $tw->{TagFn}($cversion, access_nomdistro);
        $tw->{Tfn} = sub { $tfbase.$tw->{TfSuffix}.$_[0]; };
@@ -3799,7 +3840,7 @@ END
 
     my $dscpath = "$buildproductsdir/$dscfn";
     stat_exists $dscpath or
-       fail "looked for .dsc $dscfn, but $!;".
+       fail "looked for .dsc $dscpath, but $!;".
            " maybe you forgot to build";
 
     responder_send_file('dsc', $dscpath);
@@ -3866,7 +3907,7 @@ END
     progress "checking that $dscfn corresponds to HEAD";
     runcmd qw(dpkg-source -x --),
         $dscpath =~ m#^/# ? $dscpath : "../../../$dscpath";
-    my ($tree,$dir) = mktree_in_ud_from_only_subdir();
+    my ($tree,$dir) = mktree_in_ud_from_only_subdir("source package");
     check_for_vendor_patches() if madformat($dsc->{format});
     changedir '../../../..';
     my @diffcmd = (@git, qw(diff --quiet), $tree, $dgithead);
@@ -3982,8 +4023,12 @@ END
     runcmd_ordryrun @git, qw(update-ref -m), 'dgit push', lrref(), $dgithead;
 
     supplementary_message(<<'END');
-Push failed, after updating the remote git repository.
-If you want to try again, you must use a new version number.
+Push failed, while obtaining signatures on the .changes and .dsc.
+If it was just that the signature failed, you may try again by using
+debsign by hand to sign the changes
+   $changesfile
+and then dput to complete the upload.
+If you need to change the package, you must use a new version number.
 END
     if ($we_are_responder) {
        my $dryrunsuffix = act_local() ? "" : ".tmp";
@@ -4417,7 +4462,7 @@ END
        local $ENV{'EDITOR'} = cmdoutput qw(realpath --), $0;
        local $ENV{'VISUAL'} = $ENV{'EDITOR'};
        local $ENV{$fakeeditorenv} = cmdoutput qw(realpath --), $descfn;
-       runcmd @dpkgsource, qw(--commit .), $patchname;
+       runcmd @dpkgsource, qw(--commit --include-removal .), $patchname;
     }
 }
 
@@ -4452,17 +4497,21 @@ sub quiltify_trees_differ ($$;$$$) {
 
        if ($unrepres) {
            eval {
-               die "deleted\n" unless $newmode =~ m/[^0]/;
-               die "not a plain file\n" unless $newmode =~ m/^10\d{4}$/;
-               if ($oldmode =~ m/[^0]/) {
+               die "not a plain file\n"
+                   unless $newmode =~ m/^10\d{4}$/ ||
+                          $oldmode =~ m/^10\d{4}$/;
+               if ($oldmode =~ m/[^0]/ &&
+                   $newmode =~ m/[^0]/) {
                    die "mode changed\n" if $oldmode ne $newmode;
                } else {
-                   die "non-default mode\n" unless $newmode =~ m/^100644$/;
+                   die "non-default mode\n"
+                       unless $newmode =~ m/^100644$/ ||
+                              $oldmode =~ m/^100644$/;
                }
            };
            if ($@) {
                local $/="\n"; chomp $@;
-               push @$unrepres, [ $f, $@ ];
+               push @$unrepres, [ $f, "$@ ($oldmode->$newmode)" ];
            }
        }
 
@@ -4895,13 +4944,10 @@ sub build_maybe_quilt_fixup () {
     check_for_vendor_patches();
 
     if (quiltmode_splitbrain) {
-       foreach my $needtf (qw(new maint)) {
-           next if grep { $_ eq $needtf } access_cfg_tagformats;
-           fail <<END
+       fail <<END unless access_cfg_tagformats_can_splitbrain;
 quilt mode $quilt_mode requires split view so server needs to support
  both "new" and "maint" tag formats, but config says it doesn't.
 END
-       }
     }
 
     my $clogp = parsechangelog();
@@ -5190,13 +5236,12 @@ sub quilt_fixup_multipatch ($$$) {
 
     changedir 'fake';
 
-    remove_stray_gits();
+    remove_stray_gits("source package");
     mktree_in_ud_here();
 
     rmtree '.pc';
 
-    runcmd @git, qw(add -Af .);
-    my $unapplied=git_write_tree();
+    my $unapplied=git_add_write_tree();
     printdebug "fake orig tree object $unapplied\n";
 
     ensuredir '.pc';
@@ -5228,8 +5273,7 @@ END
 
     changedir '../fake';
     rmtree '.pc';
-    runcmd @git, qw(add -Af .);
-    my $oldtiptree=git_write_tree();
+    my $oldtiptree=git_add_write_tree();
     printdebug "fake o+d/p tree object $unapplied\n";
     changedir '../work';
 
@@ -5886,7 +5930,7 @@ END
        $there .= "/$f";
        symlink $there, $here or fail "symlink $there to $here: $!";
        progress "made symlink $here -> $there";
-       print STDERR Dumper($fi);
+#      print STDERR Dumper($fi);
     }
     my @mergeinputs = generate_commits_from_dsc();
     die unless @mergeinputs == 1;
@@ -6074,6 +6118,15 @@ sub parseopts () {
            } elsif (m/^--overwrite=(.+)$/s) {
                push @ropts, $_;
                $overwrite_version = $1;
+           } elsif (m/^--dep14tag$/s) {
+               push @ropts, $_;
+               $dodep14tag= 'want';
+           } elsif (m/^--no-dep14tag$/s) {
+               push @ropts, $_;
+               $dodep14tag= 'no';
+           } elsif (m/^--always-dep14tag$/s) {
+               push @ropts, $_;
+               $dodep14tag= 'always';
            } elsif (m/^--delayed=(\d+)$/s) {
                push @ropts, $_;
                push @dput, $_;
@@ -6258,6 +6311,14 @@ if (!defined $quilt_mode) {
     $quilt_mode = $1;
 }
 
+if (!defined $dodep14tag) {
+    local $access_forpush;
+    $dodep14tag = access_cfg('dep14tag', 'RETURN-UNDEF') // 'want';
+    $dodep14tag =~ m/^($dodep14tag_re)$/ 
+       or badcfg "unknown dep14tag setting \`$dodep14tag'";
+    $dodep14tag = $1;
+}
+
 $need_split_build_invocation ||= quiltmode_splitbrain();
 
 if (!defined $cleanmode) {