our %forceopts = map { $_=>0 }
qw(unrepresentable unsupported-source-format
- dsc-changes-mismatch
+ dsc-changes-mismatch changes-origs-exactly
import-gitapply-absurd
import-gitapply-no-absurd);
'dgit-distro.test-dummy.git-url' => "$td/git",
'dgit-distro.test-dummy.git-host' => "git",
'dgit-distro.test-dummy.git-path' => "$td/git",
- 'dgit-distro.test-dummy.archive-query' => "ftpmasterapi:",
+ 'dgit-distro.test-dummy.archive-query' => "dummycatapi:",
'dgit-distro.test-dummy.archive-query-url' => "file://$td/aq/",
'dgit-distro.test-dummy.mirror' => "file://$td/mirror/",
'dgit-distro.test-dummy.upload-host' => 'test-dummy',
return $d;
}
+sub parse_dscdata () {
+ my $dscfh = new IO::File \$dscdata, '<' or die $!;
+ printdebug Dumper($dscdata) if $debuglevel>1;
+ $dsc = parsecontrolfh($dscfh,$dscurl,1);
+ printdebug Dumper($dsc) if $debuglevel>1;
+}
+
our %rmad;
-sub archive_query ($) {
- my ($method) = @_;
+sub archive_query ($;@) {
+ my ($method) = shift @_;
my $query = access_cfg('archive-query','RETURN-UNDEF');
$query =~ s/^(\w+):// or badcfg "invalid archive-query method \`$query'";
my $proto = $1;
my $data = $'; #';
- { no strict qw(refs); &{"${method}_${proto}"}($proto,$data); }
+ { no strict qw(refs); &{"${method}_${proto}"}($proto,$data,@_); }
}
sub pool_dsc_subpath ($$) {
return decode_json($json);
}
-sub canonicalise_suite_ftpmasterapi () {
+sub canonicalise_suite_ftpmasterapi {
my ($proto,$data) = @_;
my $suites = api_query($data, 'suites');
my @matched;
return $cn;
}
-sub archive_query_ftpmasterapi () {
+sub archive_query_ftpmasterapi {
my ($proto,$data) = @_;
my $info = api_query($data, "dsc_in_suite/$isuite/$package");
my @rows;
return @rows;
}
+sub file_in_archive_ftpmasterapi {
+ my ($proto,$data,$filename) = @_;
+ my $pat = $filename;
+ $pat =~ s/_/\\_/g;
+ $pat = "%/$pat";
+ $pat =~ s#[^-+_.0-9a-z/]# sprintf '%%%02x', ord $& #ge;
+ my $info = api_query($data, "file_in_archive/$pat", 1);
+}
+
+#---------- `dummyapicat' archive query method ----------
+
+sub archive_query_dummycatapi { archive_query_ftpmasterapi @_; }
+sub canonicalise_suite_dummycatapi { canonicalise_suite_ftpmasterapi @_; }
+
+sub file_in_archive_dummycatapi ($$$) {
+ my ($proto,$data,$filename) = @_;
+ my $mirror = access_cfg('mirror');
+ $mirror =~ s#^file://#/# or die "$mirror ?";
+ my @out;
+ my @cmd = (qw(sh -ec), '
+ cd "$1"
+ find -name "$2" -print0 |
+ xargs -0r sha256sum
+ ', qw(x), $mirror, $filename);
+ debugcmd "-|", @cmd;
+ open FIA, "-|", @cmd or die $!;
+ while (<FIA>) {
+ chomp or die;
+ printdebug "| $_\n";
+ m/^(\w+) (\S+)$/ or die "$_ ?";
+ push @out, { sha256sum => $1, filename => $2 };
+ }
+ close FIA or die failedcmd @cmd;
+ return \@out;
+}
+
#---------- `madison' archive query method ----------
sub archive_query_madison {
return $r[0][2];
}
+sub file_in_archive_madison { return undef; }
+
#---------- `sshpsql' archive query method ----------
sub sshpsql ($$$) {
return $rows[0];
}
+sub file_in_archive_sshpsql ($$$) { return undef; }
+
#---------- `dummycat' archive query method ----------
sub canonicalise_suite_dummycat ($$) {
return sort { -version_compare($a->[0],$b->[0]); } @rows;
}
+sub file_in_archive_dummycat () { return undef; }
+
#---------- tag format handling ----------
sub access_cfg_tagformats () {
fail "$dscurl has hash $got but".
" archive told us to expect $digest";
}
- my $dscfh = new IO::File \$dscdata, '<' or die $!;
- printdebug Dumper($dscdata) if $debuglevel>1;
- $dsc = parsecontrolfh($dscfh,$dscurl,1);
- printdebug Dumper($dsc) if $debuglevel>1;
+ parse_dscdata();
my $fmt = getfield $dsc, 'Format';
$format_ok{$fmt} or forceable_fail [qw(unsupported-source-format)],
"unsupported source format $fmt, sorry";
}
our @files_csum_info_fields =
- (['Checksums-Sha256','Digest::SHA', 'new(256)'],
- ['Checksums-Sha1', 'Digest::SHA', 'new(1)'],
- ['Files', 'Digest::MD5', 'new()']);
+ (['Checksums-Sha256','Digest::SHA', 'new(256)', 'sha256sum'],
+ ['Checksums-Sha1', 'Digest::SHA', 'new(1)', 'sha1sum'],
+ ['Files', 'Digest::MD5', 'new()', 'md5sum']);
sub dsc_files_info () {
foreach my $csumi (@files_csum_info_fields) {
return 1;
}
+sub changes_update_origs_from_dsc ($$$$) {
+ my ($dsc, $changes, $upstreamvsn, $changesfile) = @_;
+ my %changes_f;
+ printdebug "checking origs needed ($upstreamvsn)...\n";
+ $_ = getfield $changes, 'Files';
+ m/^\w+ \d+ (\S+ \S+) \S+$/m or
+ fail "cannot find section/priority from .changes Files field";
+ my $placementinfo = $1;
+ my %changed;
+ printdebug "checking origs needed placement '$placementinfo'...\n";
+ foreach my $l (split /\n/, getfield $dsc, 'Files') {
+ $l =~ m/\S+$/ or next;
+ my $file = $&;
+ printdebug "origs $file | $l\n";
+ next unless is_orig_file_of_vsn $file, $upstreamvsn;
+ printdebug "origs $file is_orig\n";
+ my $have = archive_query('file_in_archive', $file);
+ if (!defined $have) {
+ print STDERR <<END;
+archive does not support .orig check; hope you used --ch:--sa/-sd if needed
+END
+ return;
+ }
+ my $found_same = 0;
+ my @found_differ;
+ printdebug "origs $file \$#\$have=$#$have\n";
+ foreach my $h (@$have) {
+ my $same = 0;
+ my @differ;
+ foreach my $csumi (@files_csum_info_fields) {
+ my ($fname, $module, $method, $archivefield) = @$csumi;
+ next unless defined $h->{$archivefield};
+ $_ = $dsc->{$fname};
+ next unless defined;
+ m/^(\w+) .* \Q$file\E$/m or
+ fail ".dsc $fname missing entry for $file";
+ if ($h->{$archivefield} eq $1) {
+ $same++;
+ } else {
+ push @differ,
+ "$archivefield: $h->{$archivefield} (archive) != $1 (local .dsc)";
+ }
+ }
+ die "$file ".Dumper($h)." ?!" if $same && @differ;
+ $found_same++
+ if $same;
+ push @found_differ, "archive $h->{filename}: ".join "; ", @differ
+ if @differ;
+ }
+ print "origs $file f.same=$found_same #f._differ=$#found_differ\n";
+ if (@found_differ && !$found_same) {
+ fail join "\n",
+ "archive contains $file with different checksum",
+ @found_differ;
+ }
+ # Now we edit the changes file to add or remove it
+ foreach my $csumi (@files_csum_info_fields) {
+ my ($fname, $module, $method, $archivefield) = @$csumi;
+ next unless defined $changes->{$fname};
+ if ($found_same) {
+ # in archive, delete from .changes if it's there
+ $changed{$file} = "removed" if
+ $changes->{$fname} =~ s/^.* \Q$file\E$(?:)\n//m;
+ } elsif ($changes->{$fname} =~ m/^.* \Q$file\E$(?:)\n/m) {
+ # not in archive, but it's here in the .changes
+ } else {
+ my $dsc_data = getfield $dsc, $fname;
+ $dsc_data =~ m/^(.* \Q$file\E$)\n/m or die "$dsc_data $file ?";
+ my $extra = $1;
+ $extra =~ s/ \d+ /$&$placementinfo /
+ or die "$fname $extra >$dsc_data< ?"
+ if $fname eq 'Files';
+ $changes->{$fname} .= "\n". $extra;
+ $changed{$file} = "added";
+ }
+ }
+ }
+ if (%changed) {
+ foreach my $file (keys %changed) {
+ progress sprintf
+ "edited .changes for archive .orig contents: %s %s",
+ $changed{$file}, $file;
+ }
+ my $chtmp = "$changesfile.tmp";
+ $changes->save($chtmp);
+ if (act_local()) {
+ rename $chtmp,$changesfile or die "$changesfile $!";
+ } else {
+ progress "[new .changes left in $changesfile]";
+ }
+ } else {
+ progress "$changesfile already has appropriate .orig(s) (if any)";
+ }
+}
+
sub make_commit ($) {
my ($file) = @_;
return cmdoutput @git, qw(hash-object -w -t commit), $file;
my $f = $fi->{Filename};
die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
- link_ltarget "../../../$f", $f
+ printdebug "considering linking $f: ";
+
+ link_ltarget "../../../../$f", $f
+ or ((printdebug "($!) "), 0)
or $!==&ENOENT
or die "$f $!";
+ printdebug "linked.\n";
+
complete_file_from_dsc('.', $fi)
or next;
if (stat_exists $tf) {
progress "using existing $f";
} else {
+ printdebug "$tf does not exist, need to fetch\n";
my $furl = $dscurl;
$furl =~ s{/[^/]+$}{};
$furl .= "/$f";
my $dgithead = $actualhead;
my $maintviewhead = undef;
+ my $upstreamversion = $clogp->{Version};
+ $upstreamversion =~ s/-[^-]*$//;
+
if (madformat_wantfixup($format)) {
# user might have not used dgit build, so maybe do this now:
if (quiltmode_splitbrain()) {
- my $upstreamversion = $clogp->{Version};
- $upstreamversion =~ s/-[^-]*$//;
changedir $ud;
quilt_make_fake_dsc($upstreamversion);
my $cachekey;
# Check that changes and .dsc agree enough
$changesfile =~ m{[^/]*$};
- files_compare_inputs($dsc, parsecontrol($changesfile,$&))
+ my $changes = parsecontrol($changesfile,$&);
+ files_compare_inputs($dsc, $changes)
unless forceing [qw(dsc-changes-mismatch)];
+ # Perhaps adjust .dsc to contain right set of origs
+ changes_update_origs_from_dsc($dsc, $changes, $upstreamversion,
+ $changesfile)
+ unless forceing [qw(changes-origs-exactly)];
+
# Checks complete, we're going to try and go ahead:
responder_send_file('changes',$changesfile);