diff --git a/PBuild/OBS.pm b/PBuild/OBS.pm index 871b7ce5c..640d14da3 100644 --- a/PBuild/OBS.pm +++ b/PBuild/OBS.pm @@ -83,6 +83,7 @@ my $dtd_proj = [ my $dtd_packagebinaryversionlist = [ 'packagebinaryversionlist' => + 'cookie', [[ 'binaryversionlist' => 'package', 'code', @@ -414,6 +415,25 @@ sub fetch_gbininfo { return $gbininfo; } +sub fetch_gbininfo_cookie { + my ($url, $arch, $opts) = @_; + die("bad obs: reference\n") unless $url =~ /^obs:\/{1,3}([^\/]+\/[^\/]+)(?:\/([^\/]*))?$/; + my $prp = $1; + $arch = $2 if $2; + die("please specify the build service url with the --obs option\n") unless $opts->{'obs'}; + my $baseurl = $opts->{'obs'}; + $baseurl .= '/' unless $baseurl =~ /\/$/; + my $requrl .= "${baseurl}build/$prp/$arch?view=binaryversionscookie"; + my $cookie; + my $ua = create_ua(); + eval { + my ($data) = Build::Download::fetch($requrl, 'ua' => $ua, 'retry' => 3); + my $packagebinaryversionlist = PBuild::Structured::fromxml($data, $dtd_packagebinaryversionlist, 0, 1); + $cookie = $packagebinaryversionlist->{'cookie'} + }; + return $@ ? undef : $cookie; +} + sub fetch_productbinaries_cpioextract { my ($ent, $xfile, $repodir, $packid, $files) = @_; return undef unless $ent->{'cpiotype'} == 8; diff --git a/PBuild/RemoteRepo.pm b/PBuild/RemoteRepo.pm index 6a0a5fbf0..efed8ae75 100644 --- a/PBuild/RemoteRepo.pm +++ b/PBuild/RemoteRepo.pm @@ -261,18 +261,20 @@ sub replace_with_local { next if $bin->{'name'} eq 'moduleinfo:'; my $file = $bin->{'filename'}; if (defined $file) { - if (!$files{$file}) { + if (!$files{$file} || $files{$file} == 2) { $bad = 1; - next; + } else { + $files{$file} = 2; } - $files{$file} = 2; next; } $file = calc_binname($bin); next unless $files{$file}; + $bad = 1 if $files{$file} == 2; if ($bin->{'name'} =~ /^container:/) { delete $bin->{'id'}; $bin->{'filename'} = $file; + $files{$file} = 2; next; } my $oldbin = $oldbins{$file}; @@ -380,7 +382,9 @@ sub fetchrepo { } $repo = { 'bins' => $repo } if $repo && ref($repo) ne 'HASH'; die unless $repo && $repo->{'bins'}; - replace_with_local($repodir, $repo->{'bins'}, $oldrepo ? $oldrepo->{'bins'} : undef) unless $oldrepo && $repo == $oldrepo; + if (!($oldrepo && $repo == $oldrepo)) { + replace_with_local($repodir, $repo->{'bins'}, $oldrepo ? $oldrepo->{'bins'} : undef) || die("replace_with_local failed\n"); + } PBuild::Util::store("$repodir/._metadata.$$", $repofile, $repo); return $repo->{'bins'}; } @@ -522,6 +526,7 @@ sub fetchproductbinaries { sub replace_with_local_gbininfo { my ($repodir, $gbininfo, $oldgbininfo) = @_; + my $bad = 0; my %files = map {$_ => 1} PBuild::Util::ls("$repodir/_gbins"); for my $packid (sort keys %$gbininfo) { my $bins = $gbininfo->{$packid}; @@ -530,15 +535,16 @@ sub replace_with_local_gbininfo { my $bin = $bins->{$name}; my $file = $bin->{'filename'}; if (defined $file) { - if ($files{$file}) { - $files{$file} = 2; + if (!$files{$file} || $files{$file} == 2) { + $bad = 1; } else { - delete $bin->{'filename'}; + $files{$file} = 2; } next; } $file = "$packid-$name"; next unless $files{$file}; + $bad = 1 if $files{$file} == 2; my $oldbin = $oldbins ? $oldbins->{$name} : undef; if ($oldbin && $oldbin->{'filename'} eq $file) { if ($bin->{'md5sum'} && $bin->{'md5sum'} eq ($oldbin->{'md5sum'} || '')) { @@ -577,11 +583,16 @@ sub replace_with_local_gbininfo { } } } + # cannot verify, so download again + unlink("$repodir/_gbins/$file"); + delete $files{$file}; + next; } } for my $file (grep {$files{$_} == 1} sort keys %files) { unlink("$repodir/_gbins/$file"); } + return $bad ? 0 : 1; } @@ -592,9 +603,18 @@ sub get_gbininfo { die("get_gbininfo is not supported for $url\n") unless $url =~ /^obs:/; my $repodir = $repo->{'dir'}; my $oldgbininfo = PBuild::Util::retrieve("$repodir/_gbininfo", 1); + my $oldcookie = $oldgbininfo ? delete $oldgbininfo->{'.cookie'} : undef; + return $oldgbininfo if $oldgbininfo && $repo->{'no-repo-refresh'}; + my $cookie = PBuild::OBS::fetch_gbininfo_cookie($url, $repo->{'arch'}, { 'obs' => $repo->{'obs'} }); + if ($oldgbininfo && $oldcookie && $cookie && $oldcookie eq $cookie) { + return $oldgbininfo if replace_with_local_gbininfo($repodir, $oldgbininfo); + undef $oldgbininfo; + } my $gbininfo = PBuild::OBS::fetch_gbininfo($url, $repo->{'arch'}, { 'obs' => $repo->{'obs'} }); - replace_with_local_gbininfo($repodir, $gbininfo, $oldgbininfo); + replace_with_local_gbininfo($repodir, $gbininfo, $oldgbininfo) || die("replace_with_local_gbininfo failed\n"); + $gbininfo->{'.cookie'} = $cookie if $cookie; PBuild::Util::store("$repodir/._gbininfo.$$", "$repodir/_gbininfo", $gbininfo); + delete $gbininfo->{'.cookie'}; return $gbininfo; } diff --git a/PBuild/RepoMgr.pm b/PBuild/RepoMgr.pm index 36b7cb1e7..b3aa9870b 100644 --- a/PBuild/RepoMgr.pm +++ b/PBuild/RepoMgr.pm @@ -47,6 +47,7 @@ sub addremoterepo { $_->{'repoid'} = $id for @$bins; my $repo = { 'dir' => $repodir, 'bins' => $bins, 'url' => $repourl, 'arch' => $myarch, 'type' => 'repo', 'repoid' => $id }; $repo->{'obs'} = $opts->{'obs'} if $repourl =~ /^obs:/; + $repo->{'no-repo-refresh'} = $opts->{'no-repo-refresh'} if $opts->{'no-repo-refresh'}; $repos->{$id} = $repo; return $repo; } diff --git a/pbuild b/pbuild index d95dae29b..f56f3c461 100755 --- a/pbuild +++ b/pbuild @@ -571,6 +571,7 @@ while (1) { # if the build was successful, update artifact information and the local repo if ($bininfo) { PBuild::LocalRepo::update_gbininfo($builddir, $p->{'pkg'}, $bininfo); + delete $repos[0]->{'gbininfo'}; if ($p->{'useforbuildenabled'}) { # update with new local bin information if ($p->{'native'}) {