chiark / gitweb /
Test suite: mismatch: New test
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 836e19d4257173a9fe046781500e3cef0c2f0855..fa926dd0096d4db23a4a5af959030f6f4ccef7f2 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -1414,10 +1414,13 @@ sub mktree_in_ud_from_only_subdir (;$) {
     return ($tree,$dir);
 }
 
+our @files_csum_info_fields = 
+    (['Checksums-Sha256','Digest::SHA', 'new(256)'],
+     ['Checksums-Sha1',  'Digest::SHA', 'new(1)'],
+     ['Files',           'Digest::MD5', 'new()']);
+
 sub dsc_files_info () {
-    foreach my $csumi (['Checksums-Sha256','Digest::SHA', 'new(256)'],
-                      ['Checksums-Sha1',  'Digest::SHA', 'new(1)'],
-                      ['Files',           'Digest::MD5', 'new()']) {
+    foreach my $csumi (@files_csum_info_fields) {
        my ($fname, $module, $method) = @$csumi;
        my $field = $dsc->{$fname};
        next unless defined $field;
@@ -1445,6 +1448,65 @@ sub dsc_files () {
     map { $_->{Filename} } dsc_files_info();
 }
 
+sub files_compare_inputs (@) {
+    my $inputs = \@_;
+    my %record;
+    my %fchecked;
+
+    my $showinputs = sub {
+       return join "; ", map { $_->get_option('name') } @$inputs;
+    };
+
+    foreach my $in (@$inputs) {
+       my $expected_files;
+       my $in_name = $in->get_option('name');
+
+       printdebug "files_compare_inputs $in_name\n";
+
+       foreach my $csumi (@files_csum_info_fields) {
+           my ($fname) = @$csumi;
+           printdebug "files_compare_inputs $in_name $fname\n";
+
+           my $field = $in->{$fname};
+           next unless defined $field;
+
+           my @files;
+           foreach (split /\n/, $field) {
+               next unless m/\S/;
+
+               my ($info, $f) = m/^(\w+ \d+) (?:\S+ \S+ )?(\S+)$/ or
+                   fail "could not parse $in_name $fname line \`$_'";
+
+               printdebug "files_compare_inputs $in_name $fname $f\n";
+
+               push @files, $f;
+
+               my $re = \ $record{$f}{$fname};
+               if (defined $$re) {
+                   $fchecked{$f}{$in_name} = 1;
+                   $$re eq $info or
+                       fail "hash or size of $f varies in $fname fields".
+                       " (between: ".$showinputs->().")";
+               } else {
+                   $$re = $info;
+               }
+           }
+           @files = sort @files;
+           $expected_files //= \@files;
+           "@$expected_files" eq "@files" or
+               fail "file list in $in_name varies between hash fields!";
+       }
+       $expected_files or
+           fail "$in_name has no files list field(s)";
+    }
+    printdebug "files_compare_inputs ".Dumper(\%fchecked, \%record)
+       if $debuglevel>=2;
+
+    grep { keys %$_ == @$inputs-1 } values %fchecked
+       or fail "no file appears in all file lists".
+       " (looked in: ".$showinputs->().")";
+}
+
 sub is_orig_file_in_dsc ($$) {
     my ($f, $dsc_files_info) = @_;
     return 0 if @$dsc_files_info <= 1;
@@ -2136,6 +2198,8 @@ sub mergeinfo_version ($) {
 }
 
 sub fetch_from_archive () {
+    ensure_setup_existing_tree();
+
     # Ensures that lrref() is what is actually in the archive, one way
     # or another, according to us - ie this client's
     # appropritaely-updated archive view.  Also returns the commit id.
@@ -2535,6 +2599,13 @@ sub setup_useremail (;$) {
     $setup->('name', 'DEBFULLNAME');
 }
 
+sub ensure_setup_existing_tree () {
+    my $k = "remote.$remotename.skipdefaultupdate";
+    my $c = git_get_config $k;
+    return if defined $c;
+    set_local_git_config $k, 'true';
+}
+
 sub setup_new_tree () {
     setup_mergechangelogs();
     setup_useremail();
@@ -2630,7 +2701,11 @@ sub commit_quilty_patch () {
     }
     my @adds = map { s/[][*?\\]/\\$&/g; $_; } sort keys %adds;
     runcmd_ordryrun_local @git, qw(add -f), @adds;
-    commit_admin "Commit Debian 3.0 (quilt) metadata";
+    commit_admin <<END
+Commit Debian 3.0 (quilt) metadata
+
+[dgit ($our_version) quilt-fixup]
+END
 }
 
 sub get_source_format () {
@@ -3150,6 +3225,10 @@ END
        $changesfile = "$buildproductsdir/$changesfile";
     }
 
+    # Check that changes and .dsc agree enough
+    $changesfile =~ m{[^/]*$};
+    files_compare_inputs($dsc, parsecontrol($changesfile,$&));
+
     # Checks complete, we're going to try and go ahead:
 
     responder_send_file('changes',$changesfile);
@@ -3217,7 +3296,8 @@ END
        push @pushrefs, $forceflag."refs/tags/$tw->{Tag}";
     }
 
-    runcmd_ordryrun @git, qw(push),access_giturl(), @pushrefs;
+    runcmd_ordryrun @git,
+       qw(-c push.followTags=false push), access_giturl(), @pushrefs;
     runcmd_ordryrun @git, qw(update-ref -m), 'dgit push', lrref(), $dgithead;
 
     supplementary_message(<<'END');
@@ -3778,7 +3858,11 @@ END
        print SERIES "auto-gitignore\n" or die $!;
        close SERIES or die  $!;
         runcmd @git, qw(add -- debian/patches/series), $gipatch;
-        commit_admin "Commit patch to update .gitignore";
+        commit_admin <<END
+Commit patch to update .gitignore
+
+[dgit ($our_version) update-gitignore-quilt-fixup]
+END
     }
 
     my $dgitview = git_rev_parse 'refs/heads/dgit-view';
@@ -3973,15 +4057,65 @@ sub quiltify ($$$$) {
        $commitdata =~ m/^author (.*) \d+ [-+0-9]+$/m or die "$cc ?";
        my $author = $1;
 
+       my $commitdate = cmdoutput
+           @git, qw(log -n1 --pretty=format:%aD), $cc;
+
        $msg =~ s/^(.*)\n*/$1\n/ or die "$cc $msg ?";
 
+       my $strip_nls = sub { $msg =~ s/\n+$//; $msg .= "\n"; };
+       $strip_nls->();
+
        my $title = $1;
-       my $patchname = $title;
-       $patchname =~ s/[.:]$//;
-       $patchname =~ y/ A-Z/-a-z/;
-       $patchname =~ y/-a-z0-9_.+=~//cd;
-       $patchname =~ s/^\W/x-$&/;
-       $patchname = substr($patchname,0,40);
+       my $patchname;
+       my $patchdir;
+
+       my $gbp_check_suitable = sub {
+           $_ = shift;
+           my ($what) = @_;
+
+           eval {
+               die "contains unexpected slashes\n" if m{//} || m{/$};
+               die "contains leading punctuation\n" if m{^\W} || m{/\W};
+               die "contains bad character(s)\n" if m{[^-a-z0-9_.+=~/]}i;
+               die "too long" if length > 200;
+           };
+           return $_ unless $@;
+           print STDERR "quiltifying commit $cc:".
+               " ignoring/dropping Gbp-Pq $what: $@";
+           return undef;
+       };
+
+       if ($msg =~ s/^ (?: gbp(?:-pq)? : \s* name \s+ |
+                          gbp-pq-name: \s* )
+                      (\S+) \s* \n //ixm) {
+           $patchname = $gbp_check_suitable->($1, 'Name');
+       }
+       if ($msg =~ s/^ (?: gbp(?:-pq)? : \s* topic \s+ |
+                          gbp-pq-topic: \s* )
+                      (\S+) \s* \n //ixm) {
+           $patchdir = $gbp_check_suitable->($1, 'Topic');
+       }
+
+       $strip_nls->();
+
+       if (!defined $patchname) {
+           $patchname = $title;
+           $patchname =~ s/[.:]$//;
+           $patchname =~ y/ A-Z/-a-z/;
+           $patchname =~ y/-a-z0-9_.+=~//cd;
+           $patchname =~ s/^\W/x-$&/;
+           $patchname = substr($patchname,0,40);
+       }
+       if (!defined $patchdir) {
+           $patchdir = '';
+       }
+       if (length $patchdir) {
+           $patchname = "$patchdir/$patchname";
+       }
+       if ($patchname =~ m{^(.*)/}) {
+           mkpath "debian/patches/$1";
+       }
+
        my $index;
        for ($index='';
             stat "debian/patches/$patchname$index";
@@ -3999,6 +4133,7 @@ sub quiltify ($$$$) {
        runcmd @git, qw(checkout -q), $target, qw(debian/changelog);
 
        quiltify_dpkg_commit "$patchname$index", $author, $msg,
+           "Date: $commitdate\n".
            "X-Dgit-Generated: $clogp->{Version} $cc\n";
 
        runcmd @git, qw(checkout -q), $cc, qw(debian/changelog);
@@ -4074,7 +4209,11 @@ sub quilt_fixup_linkorigs ($$) {
 
 sub quilt_fixup_delete_pc () {
     runcmd @git, qw(rm -rqf .pc);
-    commit_admin "Commit removal of .pc (quilt series tracking data)";
+    commit_admin <<END
+Commit removal of .pc (quilt series tracking data)
+
+[dgit ($our_version) upgrade quilt-remove-pc]
+END
 }
 
 sub quilt_fixup_singlepatch ($$$) {
@@ -4608,6 +4747,10 @@ sub cmd_build {
     printdone "build successful\n";
 }
 
+sub pre_gbp_build {
+    $quilt_mode //= 'gbp';
+}
+
 sub cmd_gbp_build {
     my @dbp = @dpkgbuildpackage;
 
@@ -5038,6 +5181,9 @@ if (!@ARGV) {
 my $cmd = shift @ARGV;
 $cmd =~ y/-/_/;
 
+my $pre_fn = ${*::}{"pre_$cmd"};
+$pre_fn->() if $pre_fn;
+
 if (!defined $rmchanges) {
     local $access_forpush;
     $rmchanges = access_cfg_bool(0, 'rm-old-changes');