From 58702f8563a443a7c6e66253b259c2488b877290 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 19 May 2015 10:40:55 +0200 Subject: don't try other compressions on hashsum mismatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we e.g. fail on hash verification for Packages.xz its highly unlikely that it will be any better with Packages.gz, so we just waste download bandwidth and time. It also causes us always to fallback to the uncompressed Packages file for which the error will finally be reported, which in turn confuses users as the file usually doesn't exist on the mirrors, so a bug in apt is suspected for even trying it… --- test/integration/test-apt-update-not-modified | 23 +++++++++++++++++++++-- test/integration/test-apt-update-rollback | 4 ++-- test/integration/test-apt-update-transactions | 8 ++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/integration/test-apt-update-not-modified b/test/integration/test-apt-update-not-modified index b1d55c156..bac33d531 100755 --- a/test/integration/test-apt-update-not-modified +++ b/test/integration/test-apt-update-not-modified @@ -14,6 +14,7 @@ setupaptarchive --no-update methodtest() { msgmsg 'Test InRelease with' "$1" rm -rf rootdir/var/lib/apt/lists + cp -a aptarchive/dists aptarchive/dists.good # get our cache populated testsuccess aptget update listcurrentlistsdirectory > listsdir.lst @@ -30,8 +31,27 @@ Reading package lists..." aptget update Reading package lists..." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" - # readd arch so its downloaded again + # readd arch so its downloaded again… configarchitecture 'amd64' 'i386' + # … but oh noes, hashsum mismatch! + find aptarchive/dists/unstable/main/binary-amd64/ -type f -delete + cat >> aptarchive/dists/unstable/main/binary-amd64/Packages < "$1" < listsdir.lst redatereleasefiles '+1hour' testrun 'listsdir.lst' -- cgit v1.2.3-70-g09d2 From 448c38bdcd72b52f11ec5f326f822cf57653f81c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 6 Jun 2015 12:28:00 +0200 Subject: rework hashsum verification in the acquire system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having every item having its own code to verify the file(s) it handles is an errorprune process and easy to break, especially if items move through various stages (download, uncompress, patching, …). With a giant rework we centralize (most of) the verification to have a better enforcement rate and (hopefully) less chance for bugs, but it breaks the ABI bigtime in exchange – and as we break it anyway, it is broken even harder. It shouldn't effect most frontends as they don't deal with the acquire system at all or implement their own items, but some do and will need to be patched (might be an opportunity to use apt on-board material). The theory is simple: Items implement methods to decide if hashes need to be checked (in this stage) and to return the expected hashes for this item (in this stage). The verification itself is done in worker message passing which has the benefit that a hashsum error is now a proper error for the acquire system rather than a Done() which is later revised to a Failed(). --- apt-pkg/acquire-item.cc | 3750 ++++++++++---------- apt-pkg/acquire-item.h | 677 ++-- apt-pkg/acquire-method.cc | 5 +- apt-pkg/acquire-worker.cc | 189 +- apt-pkg/contrib/hashes.cc | 10 + apt-pkg/contrib/hashes.h | 9 + apt-pkg/deb/debindexfile.cc | 4 +- apt-pkg/deb/debmetaindex.cc | 78 +- apt-pkg/indexrecords.cc | 2 +- apt-pkg/pkgcache.h | 7 +- methods/file.cc | 6 +- test/integration/test-apt-get-source-authenticated | 2 +- test/integration/test-apt-sources-deb822 | 55 +- test/integration/test-apt-update-expected-size | 2 +- test/integration/test-apt-update-file | 4 + test/integration/test-apt-update-nofallback | 11 +- test/integration/test-apt-update-not-modified | 30 +- test/integration/test-apt-update-stale | 9 +- .../test-bug-595691-empty-and-broken-archive-files | 2 +- .../test-ubuntu-bug-1098738-apt-get-source-md5sum | 8 + test/libapt/acqprogress_test.cc | 6 +- test/libapt/hashsums_test.cc | 3 + 22 files changed, 2411 insertions(+), 2458 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index cf89717c4..ec6ec6e84 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -107,36 +107,296 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser } /*}}}*/ +// all ::HashesRequired and ::GetExpectedHashes implementations /*{{{*/ +/* ::GetExpectedHashes is abstract and has to be implemented by all subclasses. + It is best to implement it as broadly as possible, while ::HashesRequired defaults + to true and should be as restrictive as possible for false cases. Note that if + a hash is returned by ::GetExpectedHashes it must match. Only if it doesn't + ::HashesRequired is called to evaluate if its okay to have no hashes. */ +APT_CONST bool pkgAcqTransactionItem::HashesRequired() const +{ + /* signed repositories obviously have a parser and good hashes. + unsigned repositories, too, as even if we can't trust them for security, + we can at least trust them for integrity of the download itself. + Only repositories without a Release file can (obviously) not have + hashes – and they are very uncommon and strongly discouraged */ + return TransactionManager->MetaIndexParser != NULL; +} +HashStringList pkgAcqTransactionItem::GetExpectedHashes() const +{ + return GetExpectedHashesFor(GetMetaKey()); +} + +APT_CONST bool pkgAcqMetaBase::HashesRequired() const +{ + // Release and co have no hashes 'by design'. + return false; +} +HashStringList pkgAcqMetaBase::GetExpectedHashes() const +{ + return HashStringList(); +} + +APT_CONST bool pkgAcqIndexDiffs::HashesRequired() const +{ + /* FIXME: We have only hashes for uncompressed pdiffs. + rred uncompresses them on the fly while parsing. + In StateFetchDiff state we also uncompress on the fly for hash check. + Hashes are checked while searching for (next) patch to apply. */ + return false; +} +HashStringList pkgAcqIndexDiffs::GetExpectedHashes() const +{ + return HashStringList(); +} + +APT_CONST bool pkgAcqIndexMergeDiffs::HashesRequired() const +{ + /* @see #pkgAcqIndexDiffs::HashesRequired, with the difference that + we can check the rred result after all patches are applied as + we know the expected result rather than potentially apply more patches */ + return State == StateApplyDiff; +} +HashStringList pkgAcqIndexMergeDiffs::GetExpectedHashes() const +{ + if (State == StateApplyDiff) + return GetExpectedHashesFor(Target->MetaKey); + return HashStringList(); +} + +APT_CONST bool pkgAcqArchive::HashesRequired() const +{ + return LocalSource == false; +} +HashStringList pkgAcqArchive::GetExpectedHashes() const +{ + // figured out while parsing the records + return ExpectedHashes; +} + +APT_CONST bool pkgAcqFile::HashesRequired() const +{ + // supplied as parameter at creation time, so the caller decides + return ExpectedHashes.usable(); +} +HashStringList pkgAcqFile::GetExpectedHashes() const +{ + return ExpectedHashes; +} + /*}}}*/ +// Acquire::Item::QueueURI and specialisations from child classes /*{{{*/ +bool pkgAcquire::Item::QueueURI(pkgAcquire::ItemDesc &Item) +{ + Owner->Enqueue(Item); + return true; +} +/* The idea here is that an item isn't queued if it exists on disk and the + transition manager was a hit as this means that the files it contains + the checksums for can't be updated either (or they are and we are asking + for a hashsum mismatch to happen which helps nobody) */ +bool pkgAcqTransactionItem::QueueURI(pkgAcquire::ItemDesc &Item) +{ + std::string const FinalFile = GetFinalFilename(); + if (TransactionManager != NULL && TransactionManager->IMSHit == true && + FileExists(FinalFile) == true) + { + PartialFile = DestFile = FinalFile; + Status = StatDone; + return false; + } + return pkgAcquire::Item::QueueURI(Item); +} +/* The transition manager InRelease itself (or its older sisters-in-law + Release & Release.gpg) is always queued as this allows us to rerun gpgv + on it to verify that we aren't stalled with old files */ +bool pkgAcqMetaBase::QueueURI(pkgAcquire::ItemDesc &Item) +{ + return pkgAcquire::Item::QueueURI(Item); +} +/* the Diff/Index needs to queue also the up-to-date complete index file + to ensure that the list cleaner isn't eating it */ +bool pkgAcqDiffIndex::QueueURI(pkgAcquire::ItemDesc &Item) +{ + if (pkgAcqTransactionItem::QueueURI(Item) == true) + return true; + QueueOnIMSHit(); + return false; +} + /*}}}*/ +// Acquire::Item::GetFinalFilename and specialisations for child classes /*{{{*/ +std::string pkgAcquire::Item::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Desc.URI); +} +std::string pkgAcqDiffIndex::GetFinalFilename() const +{ + // the logic we inherent from pkgAcqBaseIndex isn't what we need here + return pkgAcquire::Item::GetFinalFilename(); +} +std::string pkgAcqIndex::GetFinalFilename() const +{ + std::string const FinalFile = GetFinalFileNameFromURI(Target->URI); + return GetCompressedFileName(Target->URI, FinalFile, CurrentCompressionExtension); +} +std::string pkgAcqMetaSig::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Target->URI); +} +std::string pkgAcqBaseIndex::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(Target->URI); +} +std::string pkgAcqMetaBase::GetFinalFilename() const +{ + return GetFinalFileNameFromURI(DataTarget.URI); +} +std::string pkgAcqArchive::GetFinalFilename() const +{ + return _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename); +} + /*}}}*/ +// pkgAcqTransactionItem::GetMetaKey and specialisations for child classes /*{{{*/ +std::string pkgAcqTransactionItem::GetMetaKey() const +{ + return Target->MetaKey; +} +std::string pkgAcqIndex::GetMetaKey() const +{ + if (Stage == STAGE_DECOMPRESS_AND_VERIFY || CurrentCompressionExtension == "uncompressed") + return Target->MetaKey; + return Target->MetaKey + "." + CurrentCompressionExtension; +} +std::string pkgAcqDiffIndex::GetMetaKey() const +{ + return Target->MetaKey + ".diff/Index"; +} + /*}}}*/ +//pkgAcqTransactionItem::TransactionState and specialisations for child classes /*{{{*/ +bool pkgAcqTransactionItem::TransactionState(TransactionStates const state) +{ + bool const Debug = _config->FindB("Debug::Acquire::Transaction", false); + switch(state) + { + case TransactionAbort: + if(Debug == true) + std::clog << " Cancel: " << DestFile << std::endl; + if (Status == pkgAcquire::Item::StatIdle) + { + Status = pkgAcquire::Item::StatDone; + Dequeue(); + } + break; + case TransactionCommit: + if(PartialFile != "") + { + if(Debug == true) + std::clog << "mv " << PartialFile << " -> "<< DestFile << " # " << DescURI() << std::endl; + + Rename(PartialFile, DestFile); + } else { + if(Debug == true) + std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; + unlink(DestFile.c_str()); + } + break; + } + return true; +} +bool pkgAcqMetaBase::TransactionState(TransactionStates const state) +{ + // Do not remove InRelease on IMSHit of Release.gpg [yes, this is very edgecasey] + if (TransactionManager->IMSHit == false) + return pkgAcqTransactionItem::TransactionState(state); + return true; +} +bool pkgAcqIndex::TransactionState(TransactionStates const state) +{ + if (pkgAcqTransactionItem::TransactionState(state) == false) + return false; + + switch (state) + { + case TransactionAbort: + if (Stage == STAGE_DECOMPRESS_AND_VERIFY) + { + // keep the compressed file, but drop the decompressed + EraseFileName.clear(); + if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp") + unlink(PartialFile.c_str()); + } + break; + case TransactionCommit: + if (EraseFileName.empty() == false) + unlink(EraseFileName.c_str()); + break; + } + return true; +} +bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) +{ + if (pkgAcqTransactionItem::TransactionState(state) == false) + return false; + + switch (state) + { + case TransactionCommit: + break; + case TransactionAbort: + std::string const Partial = GetPartialFileNameFromURI(Target->URI); + unlink(Partial.c_str()); + break; + } + + return true; +} + /*}}}*/ // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH -pkgAcquire::Item::Item(pkgAcquire *Owner, - HashStringList const &ExpectedHashes, - pkgAcqMetaBase *TransactionManager) - : Owner(Owner), FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), - Local(false), QueueCounter(0), TransactionManager(TransactionManager), - ExpectedAdditionalItems(0), ExpectedHashes(ExpectedHashes) +pkgAcquire::Item::Item(pkgAcquire * const Owner) : + FileSize(0), PartialSize(0), Mode(0), Complete(false), Local(false), + QueueCounter(0), ExpectedAdditionalItems(0), Owner(Owner) { Owner->Add(this); Status = StatIdle; - if(TransactionManager != NULL) - TransactionManager->Add(this); } APT_IGNORE_DEPRECATED_POP /*}}}*/ // Acquire::Item::~Item - Destructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgAcquire::Item::~Item() { Owner->Remove(this); } /*}}}*/ +std::string pkgAcquire::Item::Custom600Headers() const /*{{{*/ +{ + return std::string(); +} + /*}}}*/ +std::string pkgAcquire::Item::ShortDesc() const /*{{{*/ +{ + return DescURI(); +} + /*}}}*/ +APT_CONST void pkgAcquire::Item::Finished() /*{{{*/ +{ +} + /*}}}*/ +APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ +{ + return Owner; +} + /*}}}*/ +APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/ +{ + return false; +} + /*}}}*/ // Acquire::Item::Failed - Item failed to download /*{{{*/ // --------------------------------------------------------------------- /* We return to an idle state if there are still other queues that could fetch this object */ -void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { if(ErrorText.empty()) ErrorText = LookupTag(Message,"Message"); @@ -169,59 +429,28 @@ void pkgAcquire::Item::Failed(string Message,pkgAcquire::MethodConfig *Cnf) Complete = false; Dequeue(); } - else - Status = StatIdle; - // check fail reason string const FailReason = LookupTag(Message, "FailReason"); - if(FailReason == "MaximumSizeExceeded") + if (FailReason == "MaximumSizeExceeded") RenameOnError(MaximumSizeExceeded); + else if (Status == StatAuthError) + RenameOnError(HashSumMismatch); // report mirror failure back to LP if we actually use a mirror - if(FailReason.empty() == false) + if (FailReason.empty() == false) ReportMirrorFailure(FailReason); else ReportMirrorFailure(ErrorText); -} - /*}}}*/ -bool pkgAcquire::Item::TransactionState(TransactionStates const state) /*{{{*/ -{ - bool const Debug = _config->FindB("Debug::Acquire::Transaction", false); - switch(state) - { - case TransactionAbort: - if(Debug == true) - std::clog << " Cancel: " << DestFile << std::endl; - if (Status == pkgAcquire::Item::StatIdle) - { - Status = pkgAcquire::Item::StatDone; - Dequeue(); - } - break; - case TransactionCommit: - if(PartialFile != "") - { - if(Debug == true) - std::clog << "mv " << PartialFile << " -> "<< DestFile << " # " << DescURI() << std::endl; - Rename(PartialFile, DestFile); - } else { - if(Debug == true) - std::clog << "rm " << DestFile << " # " << DescURI() << std::endl; - unlink(DestFile.c_str()); - } - // mark that this transaction is finished - TransactionManager = 0; - break; - } - return true; + if (QueueCounter > 1) + Status = StatIdle; } /*}}}*/ // Acquire::Item::Start - Item has begun to download /*{{{*/ // --------------------------------------------------------------------- -/* Stash status and the file size. Note that setting Complete means +/* Stash status and the file size. Note that setting Complete means sub-phases of the acquire process such as decompresion are operating */ -void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) +void pkgAcquire::Item::Start(string const &/*Message*/, unsigned long long const Size) { Status = StatFetching; ErrorText.clear(); @@ -230,22 +459,24 @@ void pkgAcquire::Item::Start(string /*Message*/,unsigned long long Size) } /*}}}*/ // Acquire::Item::Done - Item downloaded OK /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringList const &/*Hash*/, - pkgAcquire::MethodConfig * /*Cnf*/) +void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const /*Cnf*/) { // We just downloaded something.. string FileName = LookupTag(Message,"Filename"); UsedMirror = LookupTag(Message,"UsedMirror"); - if (Complete == false && !Local && FileName == DestFile) + unsigned long long const downloadedSize = Hashes.FileSize(); + if (downloadedSize != 0) { - if (Owner->Log != 0) - Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str())); - } + if (Complete == false && !Local && FileName == DestFile) + { + if (Owner->Log != 0) + Owner->Log->Fetched(Hashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + } - if (FileSize == 0) - FileSize= Size; + if (FileSize == 0) + FileSize= downloadedSize; + } Status = StatDone; ErrorText = string(); Owner->Dequeue(this); @@ -255,7 +486,7 @@ void pkgAcquire::Item::Done(string Message,unsigned long long Size,HashStringLis // --------------------------------------------------------------------- /* This helper function is used by a lot of item methods as their final step */ -bool pkgAcquire::Item::Rename(string From,string To) +bool pkgAcquire::Item::Rename(string const &From,string const &To) { if (From == To || rename(From.c_str(),To.c_str()) == 0) return true; @@ -271,76 +502,40 @@ bool pkgAcquire::Item::Rename(string From,string To) return false; } /*}}}*/ -// Acquire::Item::QueueURI and specialisations from child classes /*{{{*/ -/* The idea here is that an item isn't queued if it exists on disk and the - transition manager was a hit as this means that the files it contains - the checksums for can't be updated either (or they are and we are asking - for a hashsum mismatch to happen which helps nobody) */ -bool pkgAcquire::Item::QueueURI(ItemDesc &Item) +void pkgAcquire::Item::Dequeue() /*{{{*/ { - std::string const FinalFile = GetFinalFilename(); - if (TransactionManager != NULL && TransactionManager->IMSHit == true && - FileExists(FinalFile) == true) - { - PartialFile = DestFile = FinalFile; - Status = StatDone; - return false; - } - - Owner->Enqueue(Item); - return true; + Owner->Dequeue(this); } -/* The transition manager InRelease itself (or its older sisters-in-law - Release & Release.gpg) is always queued as this allows us to rerun gpgv - on it to verify that we aren't stalled with old files */ -bool pkgAcqMetaBase::QueueURI(pkgAcquire::ItemDesc &Item) -{ - Owner->Enqueue(Item); - return true; -} -/* the Diff/Index needs to queue also the up-to-date complete index file - to ensure that the list cleaner isn't eating it */ -bool pkgAcqDiffIndex::QueueURI(pkgAcquire::ItemDesc &Item) -{ - if (pkgAcquire::Item::QueueURI(Item) == true) - return true; - QueueOnIMSHit(); - return false; -} - /*}}}*/ -void pkgAcquire::Item::Dequeue() /*{{{*/ -{ - Owner->Dequeue(this); -} - /*}}}*/ -bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/ + /*}}}*/ +bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const error)/*{{{*/ { if (RealFileExists(DestFile)) Rename(DestFile, DestFile + ".FAILED"); + std::string errtext; switch (error) { case HashSumMismatch: - ErrorText = _("Hash Sum mismatch"); + errtext = _("Hash Sum mismatch"); Status = StatAuthError; ReportMirrorFailure("HashChecksumFailure"); break; case SizeMismatch: - ErrorText = _("Size mismatch"); + errtext = _("Size mismatch"); Status = StatAuthError; ReportMirrorFailure("SizeFailure"); break; case InvalidFormat: - ErrorText = _("Invalid file format"); + errtext = _("Invalid file format"); Status = StatError; // do not report as usually its not the mirrors fault, but Portal/Proxy break; case SignatureError: - ErrorText = _("Signature error"); + errtext = _("Signature error"); Status = StatError; break; case NotClearsigned: - ErrorText = _("Does not start with a cleartext signature"); + errtext = _("Does not start with a cleartext signature"); Status = StatError; break; case MaximumSizeExceeded: @@ -351,6 +546,8 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const // no handling here, done by callers break; } + if (ErrorText.empty()) + ErrorText = errtext; return false; } /*}}}*/ @@ -360,15 +557,8 @@ void pkgAcquire::Item::SetActiveSubprocess(const std::string &subprocess)/*{{{*/ APT_IGNORE_DEPRECATED(Mode = ActiveSubprocess.c_str();) } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcquire::Item::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(Desc.URI); -} - /*}}}*/ // Acquire::Item::ReportMirrorFailure /*{{{*/ -// --------------------------------------------------------------------- -void pkgAcquire::Item::ReportMirrorFailure(string FailCode) +void pkgAcquire::Item::ReportMirrorFailure(string const &FailCode) { // we only act if a mirror was used at all if(UsedMirror.empty()) @@ -411,2083 +601,1897 @@ void pkgAcquire::Item::ReportMirrorFailure(string FailCode) } } /*}}}*/ -// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* Get the DiffIndex file first and see if there are patches available - * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the - * patches. If anything goes wrong in that process, it will fall back to - * the original packages file - */ -pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser) +std::string pkgAcquire::Item::HashSum() const /*{{{*/ { - - Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - - RealURI = Target->URI; - Desc.Owner = this; - Desc.Description = Target->Description + ".diff/Index"; - Desc.ShortDesc = Target->ShortDesc; - Desc.URI = Target->URI + ".diff/Index"; - - DestFile = GetPartialFileNameFromURI(Desc.URI); + HashStringList const hashes = GetExpectedHashes(); + HashString const * const hs = hashes.find(NULL); + return hs != NULL ? hs->toStr() : ""; +} + /*}}}*/ - if(Debug) - std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; +pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/ + pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target) : + pkgAcquire::Item(Owner), Target(Target), TransactionManager(TransactionManager) +{ + if (TransactionManager != this) + TransactionManager->Add(this); +} + /*}}}*/ +pkgAcqTransactionItem::~pkgAcqTransactionItem() /*{{{*/ +{ +} + /*}}}*/ +HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const MetaKey) const /*{{{*/ +{ + if (TransactionManager->MetaIndexParser == NULL) + return HashStringList(); + indexRecords::checkSum * const R = TransactionManager->MetaIndexParser->Lookup(MetaKey); + if (R == NULL) + return HashStringList(); + return R->Hashes; +} + /*}}}*/ - // look for the current package file - CurrentPackagesFile = GetFinalFileNameFromURI(RealURI); +// AcqMetaBase - Constructor /*{{{*/ +pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + std::vector const * const IndexTargets, + IndexTarget const &DataTarget, + indexRecords * const MetaIndexParser) +: pkgAcqTransactionItem(Owner, TransactionManager, NULL), DataTarget(DataTarget), + MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), + AuthPass(false), IMSHit(false) +{ +} + /*}}}*/ +// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/ +void pkgAcqMetaBase::Add(pkgAcqTransactionItem * const I) +{ + Transaction.push_back(I); +} + /*}}}*/ +// AcqMetaBase::AbortTransaction - Abort the current Transaction /*{{{*/ +void pkgAcqMetaBase::AbortTransaction() +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "AbortTransaction: " << TransactionManager << std::endl; - // FIXME: this file:/ check is a hack to prevent fetching - // from local sources. this is really silly, and - // should be fixed cleanly as soon as possible - if(!FileExists(CurrentPackagesFile) || - Desc.URI.substr(0,strlen("file:/")) == "file:/") + // ensure the toplevel is in error state too + for (std::vector::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) { - // we don't have a pkg file or we don't want to queue - Failed("No index file, local or canceld by user", NULL); - return; + (*I)->TransactionState(TransactionAbort); } + Transaction.clear(); +} + /*}}}*/ +// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/ +APT_PURE bool pkgAcqMetaBase::TransactionHasError() const +{ + for (std::vector::const_iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + switch((*I)->Status) { + case StatDone: break; + case StatIdle: break; + case StatAuthError: return true; + case StatError: return true; + case StatTransientNetworkError: return true; + case StatFetching: break; + } + } + return false; +} + /*}}}*/ +// AcqMetaBase::CommitTransaction - Commit a transaction /*{{{*/ +void pkgAcqMetaBase::CommitTransaction() +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "CommitTransaction: " << this << std::endl; - if(Debug) - std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): " - << CurrentPackagesFile << std::endl; - - QueueURI(Desc); - + // move new files into place *and* remove files that are not + // part of the transaction but are still on disk + for (std::vector::iterator I = Transaction.begin(); + I != Transaction.end(); ++I) + { + (*I)->TransactionState(TransactionCommit); + } + Transaction.clear(); } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqDiffIndex::GetFinalFilename() const +// AcqMetaBase::TransactionStageCopy - Stage a file for copying /*{{{*/ +void pkgAcqMetaBase::TransactionStageCopy(pkgAcqTransactionItem * const I, + const std::string &From, + const std::string &To) { - // the logic we inherent from pkgAcqBaseIndex isn't what we need here - return pkgAcquire::Item::GetFinalFilename(); + I->PartialFile = From; + I->DestFile = To; } /*}}}*/ -// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// AcqMetaBase::TransactionStageRemoval - Stage a file for removal /*{{{*/ +void pkgAcqMetaBase::TransactionStageRemoval(pkgAcqTransactionItem * const I, + const std::string &FinalFile) +{ + I->PartialFile = ""; + I->DestFile = FinalFile; +} + /*}}}*/ +// AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ +bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message) +{ + // FIXME: this entire function can do now that we disallow going to + // a unauthenticated state and can cleanly rollback + + string const Final = I->GetFinalFilename(); + if(FileExists(Final)) + { + I->Status = StatTransientNetworkError; + _error->Warning(_("An error occurred during the signature " + "verification. The repository is not updated " + "and the previous index files will be used. " + "GPG error: %s: %s\n"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); + RunScripts("APT::Update::Auth-Failure"); + return true; + } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) { + /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */ + _error->Error(_("GPG error: %s: %s"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); + I->Status = StatError; + return true; + } else { + _error->Warning(_("GPG error: %s: %s"), + Desc.Description.c_str(), + LookupTag(Message,"Message").c_str()); + } + // gpgv method failed + ReportMirrorFailure("GPGFailure"); + return false; +} + /*}}}*/ +// AcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ // --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 -string pkgAcqDiffIndex::Custom600Headers() const -#else -string pkgAcqDiffIndex::Custom600Headers() -#endif +string pkgAcqMetaBase::Custom600Headers() const { - string const Final = GetFinalFilename(); + std::string Header = "\nIndex-File: true"; + std::string MaximumSize; + strprintf(MaximumSize, "\nMaximum-Size: %i", + _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); + Header += MaximumSize; - if(Debug) - std::clog << "Custom600Header-IMS: " << Final << std::endl; + string const FinalFile = GetFinalFilename(); struct stat Buf; - if (stat(Final.c_str(),&Buf) != 0) - return "\nIndex-File: true"; - - return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + if (stat(FinalFile.c_str(),&Buf) == 0) + Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + + return Header; } /*}}}*/ -void pkgAcqDiffIndex::QueueOnIMSHit() const /*{{{*/ +// AcqMetaBase::QueueForSignatureVerify /*{{{*/ +void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature) { - // list cleanup needs to know that this file as well as the already - // present index is ours, so we create an empty diff to save it for us - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, - ExpectedHashes, MetaIndexParser); + AuthPass = true; + I->Desc.URI = "gpgv:" + Signature; + I->DestFile = File; + QueueURI(I->Desc); + I->SetActiveSubprocess("gpgv"); } /*}}}*/ -bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile) /*{{{*/ +// AcqMetaBase::CheckDownloadDone /*{{{*/ +bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const std::string &Message, HashStringList const &Hashes) const { - // failing here is fine: our caller will take care of trying to - // get the complete file if patching fails - if(Debug) - std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile - << std::endl; - - FileFd Fd(IndexDiffFile,FileFd::ReadOnly); - pkgTagFile TF(&Fd); - if (_error->PendingError() == true) - return false; - - pkgTagSection Tags; - if(unlikely(TF.Step(Tags) == false)) - return false; - - HashStringList ServerHashes; - unsigned long long ServerSize = 0; + // We have just finished downloading a Release file (it is not + // verified yet) - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + string const FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) { - std::string tagname = *type; - tagname.append("-Current"); - std::string const tmp = Tags.FindS(tagname.c_str()); - if (tmp.empty() == true) - continue; - - string hash; - unsigned long long size; - std::stringstream ss(tmp); - ss >> hash >> size; - if (unlikely(hash.empty() == true)) - continue; - if (unlikely(ServerSize != 0 && ServerSize != size)) - continue; - ServerHashes.push_back(HashString(*type, hash)); - ServerSize = size; + I->Status = StatError; + I->ErrorText = "Method gave a blank filename"; + return false; } - if (ServerHashes.usable() == false) + if (FileName != I->DestFile) { - if (Debug == true) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Did not find a good hashsum in the index" << std::endl; + I->Local = true; + I->Desc.URI = "copy:" + FileName; + I->QueueURI(I->Desc); return false; } - if (ServerHashes != HashSums()) + // make sure to verify against the right file on I-M-S hit + bool IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"), false); + if (IMSHit == false && Hashes.usable()) { - if (Debug == true) + // detect IMS-Hits servers haven't detected by Hash comparison + std::string const FinalFile = I->GetFinalFilename(); + if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) { - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl; - printHashSumComparision(CurrentPackagesFile, ServerHashes, HashSums()); + IMSHit = true; + unlink(I->DestFile.c_str()); } - return false; } - if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + if(IMSHit == true) { - // we have the same sha1 as the server so we are done here - if(Debug) - std::clog << "pkgAcqDiffIndex: Package file " << CurrentPackagesFile << " is up-to-date" << std::endl; - QueueOnIMSHit(); - return true; + // for simplicity, the transaction manager is always InRelease + // even if it doesn't exist. + if (TransactionManager != NULL) + TransactionManager->IMSHit = true; + I->PartialFile = I->DestFile = I->GetFinalFilename(); } - FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); - Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); + // set Item to complete as the remaining work is all local (verify etc) + I->Complete = true; - if(Debug) - std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at " - << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; + return true; +} + /*}}}*/ +bool pkgAcqMetaBase::CheckAuthDone(string const &Message) /*{{{*/ +{ + // At this point, the gpgv method has succeeded, so there is a + // valid signature from a key in the trusted keyring. We + // perform additional verification of its contents, and use them + // to verify the indexes we are about to download - // parse all of (provided) history - vector available_patches; - bool firstAcceptedHashes = true; - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + if (TransactionManager->IMSHit == false) { - if (LocalHashes.find(*type) == NULL) - continue; - - std::string tagname = *type; - tagname.append("-History"); - std::string const tmp = Tags.FindS(tagname.c_str()); - if (tmp.empty() == true) - continue; - - string hash, filename; - unsigned long long size; - std::stringstream ss(tmp); - - while (ss >> hash >> size >> filename) + // open the last (In)Release if we have it + std::string const FinalFile = GetFinalFilename(); + std::string FinalRelease; + std::string FinalInRelease; + if (APT::String::Endswith(FinalFile, "InRelease")) { - if (unlikely(hash.empty() == true || filename.empty() == true)) - continue; - - // see if we have a record for this file already - std::vector::iterator cur = available_patches.begin(); - for (; cur != available_patches.end(); ++cur) - { - if (cur->file != filename || unlikely(cur->result_size != size)) - continue; - cur->result_hashes.push_back(HashString(*type, hash)); - break; - } - if (cur != available_patches.end()) - continue; - if (firstAcceptedHashes == true) - { - DiffInfo next; - next.file = filename; - next.result_hashes.push_back(HashString(*type, hash)); - next.result_size = size; - next.patch_size = 0; - available_patches.push_back(next); - } + FinalInRelease = FinalFile; + FinalRelease = FinalFile.substr(0, FinalFile.length() - strlen("InRelease")) + "Release"; + } + else + { + FinalInRelease = FinalFile.substr(0, FinalFile.length() - strlen("Release")) + "InRelease"; + FinalRelease = FinalFile; + } + if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) + { + TransactionManager->LastMetaIndexParser = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) { - if (Debug == true) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename - << " wasn't in the list for the first parsed hash! (history)" << std::endl; - break; + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; } + _error->RevertToStack(); } - firstAcceptedHashes = false; } - if (unlikely(available_patches.empty() == true)) + if (TransactionManager->MetaIndexParser->Load(DestFile) == false) { - if (Debug) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " - << "Couldn't find any patches for the patch series." << std::endl; + Status = StatAuthError; + ErrorText = TransactionManager->MetaIndexParser->ErrorText; return false; } - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + if (!VerifyVendor(Message)) { - if (LocalHashes.find(*type) == NULL) - continue; + Status = StatAuthError; + return false; + } - std::string tagname = *type; - tagname.append("-Patches"); - std::string const tmp = Tags.FindS(tagname.c_str()); - if (tmp.empty() == true) - continue; + if (_config->FindB("Debug::pkgAcquire::Auth", false)) + std::cerr << "Signature verification succeeded: " + << DestFile << std::endl; - string hash, filename; - unsigned long long size; - std::stringstream ss(tmp); + // Download further indexes with verification + QueueIndexes(true); - while (ss >> hash >> size >> filename) + return true; +} + /*}}}*/ +void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ +{ + // at this point the real Items are loaded in the fetcher + ExpectedAdditionalItems = 0; + + vector ::const_iterator Target; + for (Target = IndexTargets->begin(); + Target != IndexTargets->end(); + ++Target) + { + if (verify == true && TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) { - if (unlikely(hash.empty() == true || filename.empty() == true)) + // optional target that we do not have in the Release file are skipped + if ((*Target)->IsOptional()) continue; - // see if we have a record for this file already - std::vector::iterator cur = available_patches.begin(); - for (; cur != available_patches.end(); ++cur) - { - if (cur->file != filename) - continue; - if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) - continue; - cur->patch_hashes.push_back(HashString(*type, hash)); - cur->patch_size = size; - break; - } - if (cur != available_patches.end()) - continue; - if (Debug == true) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename - << " wasn't in the list for the first parsed hash! (patches)" << std::endl; - break; + Status = StatAuthError; + strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); + return; } + + /* Queue the Index file (Packages, Sources, Translation-$foo + (either diff or full packages files, depending + on the users option) - we also check if the PDiff Index file is listed + in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this + instead, but passing the required info to it is to much hassle */ + if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false || + TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)) + new pkgAcqDiffIndex(Owner, TransactionManager, *Target); + else + new pkgAcqIndex(Owner, TransactionManager, *Target); } +} + /*}}}*/ +bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ +{ + string::size_type pos; - bool foundStart = false; - for (std::vector::iterator cur = available_patches.begin(); - cur != available_patches.end(); ++cur) + // check for missing sigs (that where not fatal because otherwise we had + // bombed earlier) + string missingkeys; + string msg = _("There is no public key available for the " + "following key IDs:\n"); + pos = Message.find("NO_PUBKEY "); + if (pos != std::string::npos) { - if (LocalHashes != cur->result_hashes) - continue; - - available_patches.erase(available_patches.begin(), cur); - foundStart = true; - break; + string::size_type start = pos+strlen("NO_PUBKEY "); + string Fingerprint = Message.substr(start, Message.find("\n")-start); + missingkeys += (Fingerprint); } + if(!missingkeys.empty()) + _error->Warning("%s", (msg + missingkeys).c_str()); - if (foundStart == false || unlikely(available_patches.empty() == true)) + string Transformed = TransactionManager->MetaIndexParser->GetExpectedDist(); + + if (Transformed == "../project/experimental") { - if (Debug) - std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " - << "Couldn't find the start of the patch series." << std::endl; - return false; + Transformed = "experimental"; } - // patching with too many files is rather slow compared to a fast download - unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); - if (fileLimit != 0 && fileLimit < available_patches.size()) + pos = Transformed.rfind('/'); + if (pos != string::npos) { - if (Debug) - std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit - << ") so fallback to complete download" << std::endl; - return false; + Transformed = Transformed.substr(0, pos); } - // calculate the size of all patches we have to get - // note that all sizes are uncompressed, while we download compressed files - unsigned long long patchesSize = 0; - for (std::vector::const_iterator cur = available_patches.begin(); - cur != available_patches.end(); ++cur) - patchesSize += cur->patch_size; - unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); - if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) + if (Transformed == ".") { - if (Debug) - std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 - << ") so fallback to complete download" << std::endl; - return false; + Transformed = ""; } - // we have something, queue the diffs - string::size_type const last_space = Description.rfind(" "); - if(last_space != string::npos) - Description.erase(last_space, Description.size()-last_space); + if (_config->FindB("Acquire::Check-Valid-Until", true) == true && + TransactionManager->MetaIndexParser->GetValidUntil() > 0) { + time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil(); + if (invalid_since > 0) + { + std::string errmsg; + strprintf(errmsg, + // TRANSLATOR: The first %s is the URL of the bad Release file, the second is + // the time since then the file is invalid - formated in the same way as in + // the download progress display (e.g. 7d 3h 42min 1s) + _("Release file for %s is expired (invalid since %s). " + "Updates for this repository will not be applied."), + DataTarget.URI.c_str(), TimeToStr(invalid_since).c_str()); + if (ErrorText.empty()) + ErrorText = errmsg; + return _error->Error("%s", errmsg.c_str()); + } + } - /* decide if we should download patches one by one or in one go: - The first is good if the server merges patches, but many don't so client - based merging can be attempt in which case the second is better. - "bad things" will happen if patches are merged on the server, - but client side merging is attempt as well */ - bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true); - if (pdiff_merge == true) + /* Did we get a file older than what we have? This is a last minute IMS hit and doubles + as a prevention of downgrading us to older (still valid) files */ + if (TransactionManager->IMSHit == false && TransactionManager->LastMetaIndexParser != NULL && + TransactionManager->LastMetaIndexParser->GetDate() > TransactionManager->MetaIndexParser->GetDate()) { - // reprepro adds this flag if it has merged patches on the server - std::string const precedence = Tags.FindS("X-Patch-Precedence"); - pdiff_merge = (precedence != "merged"); + TransactionManager->IMSHit = true; + unlink(DestFile.c_str()); + PartialFile = DestFile = GetFinalFilename(); + delete TransactionManager->MetaIndexParser; + TransactionManager->MetaIndexParser = TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; } - if (pdiff_merge == false) + if (_config->FindB("Debug::pkgAcquire::Auth", false)) { - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, ExpectedHashes, - MetaIndexParser, available_patches); + std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetDist() << std::endl; + std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl; + std::cerr << "Transformed Dist: " << Transformed << std::endl; } - else + + if (TransactionManager->MetaIndexParser->CheckDist(Transformed) == false) { - std::vector *diffs = new std::vector(available_patches.size()); - for(size_t i = 0; i < available_patches.size(); ++i) - (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager, - Target, - ExpectedHashes, - MetaIndexParser, - available_patches[i], - diffs); + // This might become fatal one day +// Status = StatAuthError; +// ErrorText = "Conflicting distribution; expected " +// + MetaIndexParser->GetExpectedDist() + " but got " +// + MetaIndexParser->GetDist(); +// return false; + if (!Transformed.empty()) + { + _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), + Desc.Description.c_str(), + Transformed.c_str(), + TransactionManager->MetaIndexParser->GetDist().c_str()); + } } - Complete = false; - Status = StatDone; - Dequeue(); return true; } /*}}}*/ -void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ -{ - Item::Failed(Message,Cnf); - Status = StatDone; - - if(Debug) - std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl - << "Falling back to normal index file acquire" << std::endl; - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); +pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, + const vector* const IndexTargets, + indexRecords * const MetaIndexParser) : + pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets, MetaIndexParser), + ClearsignedTarget(ClearsignedTarget), + DetachedDataTarget(DetachedDataTarget), DetachedSigTarget(DetachedSigTarget) +{ + // index targets + (worst case:) Release/Release.gpg + ExpectedAdditionalItems = IndexTargets->size() + 2; + TransactionManager->Add(this); } /*}}}*/ -bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) /*{{{*/ +pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ { - if (pkgAcquire::Item::TransactionState(state) == false) - return false; - - switch (state) - { - case TransactionCommit: - break; - case TransactionAbort: - std::string const Partial = GetPartialFileNameFromURI(RealURI); - unlink(Partial.c_str()); - break; - } - - return true; } /*}}}*/ -void pkgAcqDiffIndex::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ +string pkgAcqMetaClearSig::Custom600Headers() const { - if(Debug) - std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - - Item::Done(Message, Size, Hashes, Cnf); + string Header = pkgAcqMetaBase::Custom600Headers(); + Header += "\nFail-Ignore: true"; + return Header; +} + /*}}}*/ +// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ +class APT_HIDDEN DummyItem : public pkgAcquire::Item +{ + IndexTarget const * const Target; + public: + virtual std::string DescURI() const {return Target->URI;}; + virtual HashStringList GetExpectedHashes() const {return HashStringList();}; - // verify the index target - if(Target && Target->MetaKey != "" && MetaIndexParser && Hashes.usable()) + DummyItem(pkgAcquire * const Owner, IndexTarget const * const Target) : + pkgAcquire::Item(Owner), Target(Target) { - std::string IndexMetaKey = Target->MetaKey + ".diff/Index"; - indexRecords::checkSum *Record = MetaIndexParser->Lookup(IndexMetaKey); - if(Record && Record->Hashes.usable() && Hashes != Record->Hashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(RealURI, Record->Hashes, Hashes); - Failed(Message, Cnf); - return; - } - + Status = StatDone; + DestFile = GetFinalFileNameFromURI(Target->URI); } +}; +void pkgAcqMetaClearSig::Done(std::string const &Message, + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message, Hashes, Cnf); - string const FinalFile = GetFinalFilename(); - if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) - DestFile = FinalFile; - - if(ParseDiffIndex(DestFile) == false) + // if we expect a ClearTextSignature (InRelease), ensure that + // this is what we get and if not fail to queue a + // Release/Release.gpg, see #346386 + if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile)) { - Failed("Message: Couldn't parse pdiff index", Cnf); - // queue for final move - this should happen even if we fail - // while parsing (e.g. on sizelimit) and download the complete file. - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + pkgAcquire::Item::Failed(Message, Cnf); + RenameOnError(NotClearsigned); + TransactionManager->AbortTransaction(); return; } - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); - - Complete = true; - Status = StatDone; - Dequeue(); - - return; + if(AuthPass == false) + { + if(CheckDownloadDone(this, Message, Hashes) == true) + QueueForSignatureVerify(this, DestFile, DestFile); + return; + } + else if(CheckAuthDone(Message) == true) + { + if (TransactionManager->IMSHit == false) + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + else if (RealFileExists(GetFinalFilename()) == false) + { + // We got an InRelease file IMSHit, but we haven't one, which means + // we had a valid Release/Release.gpg combo stepping in, which we have + // to 'acquire' now to ensure list cleanup isn't removing them + new DummyItem(Owner, &DetachedDataTarget); + new DummyItem(Owner, &DetachedSigTarget); + } + } } /*}}}*/ -// AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* The package diff is added to the queue. one object is constructed - * for each diff and the index - */ -pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser, - vector diffs) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), - available_patches(diffs) +void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) /*{{{*/ { - DestFile = GetPartialFileNameFromURI(Target->URI); - - Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + Item::Failed(Message, Cnf); - RealURI = Target->URI; - Desc.Owner = this; - Description = Target->Description; - Desc.ShortDesc = Target->ShortDesc; + // we failed, we will not get additional items from this method + ExpectedAdditionalItems = 0; - if(available_patches.empty() == true) + if (AuthPass == false) { - // we are done (yeah!), check hashes against the final file - DestFile = GetFinalFileNameFromURI(Target->URI); - Finish(true); + // Queue the 'old' InRelease file for removal if we try Release.gpg + // as otherwise the file will stay around and gives a false-auth + // impression (CVE-2012-0214) + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); + Status = StatDone; + + new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets, TransactionManager->MetaIndexParser); } else { - // patching needs to be bootstrapped with the 'old' version - std::string const PartialFile = GetPartialFileNameFromURI(RealURI); - if (RealFileExists(PartialFile) == false) + if(CheckStopAuthentication(this, Message)) + return; + + _error->Warning(_("The data from '%s' is not signed. Packages " + "from that repository can not be authenticated."), + ClearsignedTarget.Description.c_str()); + + // No Release file was present, or verification failed, so fall + // back to queueing Packages files without verification + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) { - if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) + Status = StatDone; + + /* InRelease files become Release files, otherwise + * they would be considered as trusted later on */ + string const FinalRelease = GetFinalFileNameFromURI(DetachedDataTarget.URI); + string const PartialRelease = GetPartialFileNameFromURI(DetachedDataTarget.URI); + string const FinalReleasegpg = GetFinalFileNameFromURI(DetachedSigTarget.URI); + string const FinalInRelease = GetFinalFilename(); + Rename(DestFile, PartialRelease); + TransactionManager->TransactionStageCopy(this, PartialRelease, FinalRelease); + + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) { - Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL); - return; + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); + } } - } - // get the next diff - State = StateFetchDiff; - QueueNextDiff(); + // we parse the indexes here because at this point the user wanted + // a repository that may potentially harm him + if (TransactionManager->MetaIndexParser->Load(PartialRelease) == false || VerifyVendor(Message) == false) + /* expired Release files are still a problem you need extra force for */; + else + QueueIndexes(true); + } } } /*}}}*/ -void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ -{ - Item::Failed(Message,Cnf); - Status = StatDone; - if(Debug) - std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl - << "Falling back to normal index file acquire" << std::endl; - DestFile = GetPartialFileNameFromURI(Target->URI); - RenameOnError(PDiffError); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); - Finish(); -} - /*}}}*/ -// Finish - helper that cleans the item out of the fetcher queue /*{{{*/ -void pkgAcqIndexDiffs::Finish(bool allDone) +pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/ + pkgAcqMetaBase * const TransactionManager, + IndexTarget const &DataTarget, + IndexTarget const &DetachedSigTarget, + vector const * const IndexTargets, + indexRecords * const MetaIndexParser) : + pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget, MetaIndexParser), + DetachedSigTarget(DetachedSigTarget) { - if(Debug) - std::clog << "pkgAcqIndexDiffs::Finish(): " - << allDone << " " - << Desc.URI << std::endl; - - // we restore the original name, this is required, otherwise - // the file will be cleaned - if(allDone) - { - if(HashSums().usable() && !HashSums().VerifyFile(DestFile)) - { - RenameOnError(HashSumMismatch); - Dequeue(); - return; - } + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaIndex with TransactionManager " + << this->TransactionManager << std::endl; - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + DestFile = GetPartialFileNameFromURI(DataTarget.URI); - // this is for the "real" finish - Complete = true; - Status = StatDone; - Dequeue(); - if(Debug) - std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; - return; - } + // Create the item + Desc.Description = DataTarget.Description; + Desc.Owner = this; + Desc.ShortDesc = DataTarget.ShortDesc; + Desc.URI = DataTarget.URI; - if(Debug) - std::clog << "Finishing: " << Desc.URI << std::endl; - Complete = false; - Status = StatDone; - Dequeue(); - return; + // we expect more item + ExpectedAdditionalItems = IndexTargets->size(); + QueueURI(Desc); } /*}}}*/ -bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ +void pkgAcqMetaIndex::Done(string const &Message, /*{{{*/ + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - // calc sha1 of the just patched file - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); + Item::Done(Message,Hashes,Cfg); - if(!FileExists(FinalFile)) + if(CheckDownloadDone(this, Message, Hashes)) { - Failed("Message: No FinalFile " + FinalFile + " available", NULL); - return false; + // we have a Release file, now download the Signature, all further + // verify/queue for additional downloads will be done in the + // pkgAcqMetaSig::Done() code + new pkgAcqMetaSig(Owner, TransactionManager, &DetachedSigTarget, this); } +} + /*}}}*/ +// pkgAcqMetaIndex::Failed - no Release file present /*{{{*/ +void pkgAcqMetaIndex::Failed(string const &Message, + pkgAcquire::MethodConfig const * const Cnf) +{ + pkgAcquire::Item::Failed(Message, Cnf); + Status = StatDone; - FileFd fd(FinalFile, FileFd::ReadOnly); - Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if(Debug) - std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; + _error->Warning(_("The repository '%s' does not have a Release file. " + "This is deprecated, please contact the owner of the " + "repository."), DataTarget.Description.c_str()); - if (unlikely(LocalHashes.usable() == false || ExpectedHashes.usable() == false)) + // No Release file was present so fall + // back to queueing Packages files without verification + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) { - Failed("Local/Expected hashes are not usable", NULL); - return false; - } - + // ensure old Release files are removed + TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); + delete TransactionManager->MetaIndexParser; + TransactionManager->MetaIndexParser = NULL; - // final file reached before all patches are applied - if(LocalHashes == ExpectedHashes) - { - Finish(true); - return true; - } - - // remove all patches until the next matching patch is found - // this requires the Index file to be ordered - for(vector::iterator I = available_patches.begin(); - available_patches.empty() == false && - I != available_patches.end() && - I->result_hashes != LocalHashes; - ++I) - { - available_patches.erase(I); + // queue without any kind of hashsum support + QueueIndexes(false); } +} + /*}}}*/ +void pkgAcqMetaIndex::Finished() /*{{{*/ +{ + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "Finished: " << DestFile <TransactionHasError() == false) + TransactionManager->CommitTransaction(); +} + /*}}}*/ +std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ +{ + return DataTarget.URI; +} + /*}}}*/ - // error checking and falling back if no patch was found - if(available_patches.empty() == true) - { - Failed("No patches left to reach target", NULL); - return false; - } +// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ +pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + pkgAcqMetaIndex * const MetaIndex) : + pkgAcqTransactionItem(Owner, TransactionManager, Target), MetaIndex(MetaIndex) +{ + DestFile = GetPartialFileNameFromURI(Target->URI); - // queue the right diff - Desc.URI = RealURI + ".diff/" + available_patches[0].file + ".gz"; - Desc.Description = Description + " " + available_patches[0].file + string(".pdiff"); - DestFile = GetPartialFileNameFromURI(RealURI + ".diff/" + available_patches[0].file); + // remove any partial downloaded sig-file in partial/. + // it may confuse proxies and is too small to warrant a + // partial download anyway + unlink(DestFile.c_str()); - if(Debug) - std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + // set the TransactionManager + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgAcqMetaSig with TransactionManager " + << TransactionManager << std::endl; - QueueURI(Desc); + // Create the item + Desc.Description = Target->Description; + Desc.Owner = this; + Desc.ShortDesc = Target->ShortDesc; + Desc.URI = Target->URI; - return true; + // If we got a hit for Release, we will get one for Release.gpg too (or obscure errors), + // so we skip the download step and go instantly to verification + if (TransactionManager->IMSHit == true && RealFileExists(GetFinalFilename())) + { + Complete = true; + Status = StatDone; + PartialFile = DestFile = GetFinalFilename(); + MetaIndexFileSignature = DestFile; + MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + } + else + QueueURI(Desc); } /*}}}*/ -void pkgAcqIndexDiffs::Done(string Message,unsigned long long Size, HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ { - if(Debug) - std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - - Item::Done(Message, Size, Hashes, Cnf); - - // FIXME: verify this download too before feeding it to rred - std::string const FinalFile = GetPartialFileNameFromURI(RealURI); - - // success in downloading a diff, enter ApplyDiff state - if(State == StateFetchDiff) +} + /*}}}*/ +// AcqMetaSig::Done - The signature was downloaded/verified /*{{{*/ +void pkgAcqMetaSig::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) +{ + if (MetaIndexFileSignature.empty() == false) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); + DestFile = MetaIndexFileSignature; + MetaIndexFileSignature.clear(); + } + Item::Done(Message, Hashes, Cfg); - if (fd.Size() != available_patches[0].patch_size || - available_patches[0].patch_hashes != LocalHashes) + if(MetaIndex->AuthPass == false) + { + if(MetaIndex->CheckDownloadDone(this, Message, Hashes) == true) { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; + // destfile will be modified to point to MetaIndexFile for the + // gpgv method, so we need to save it here + MetaIndexFileSignature = DestFile; + MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + } + return; + } + else if(MetaIndex->CheckAuthDone(Message) == true) + { + if (TransactionManager->IMSHit == false) + { + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); } + } +} + /*}}}*/ +void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + Item::Failed(Message,Cnf); - // rred excepts the patch as $FinalFile.ed - Rename(DestFile,FinalFile+".ed"); + // check if we need to fail at this point + if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) + return; - if(Debug) - std::clog << "Sending to rred method: " << FinalFile << std::endl; + string const FinalRelease = MetaIndex->GetFinalFilename(); + string const FinalReleasegpg = GetFinalFilename(); + string const FinalInRelease = TransactionManager->GetFinalFilename(); - State = StateApplyDiff; - Local = true; - Desc.URI = "rred:" + FinalFile; - QueueURI(Desc); - SetActiveSubprocess("rred"); - return; - } + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + { + std::string downgrade_msg; + strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), + MetaIndex->DataTarget.Description.c_str()); + if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) + { + // meh, the users wants to take risks (we still mark the packages + // from this repository as unauthenticated) + _error->Warning("%s", downgrade_msg.c_str()); + _error->Warning(_("This is normally not allowed, but the option " + "Acquire::AllowDowngradeToInsecureRepositories was " + "given to override it.")); + Status = StatDone; + } else { + _error->Error("%s", downgrade_msg.c_str()); + if (TransactionManager->IMSHit == false) + Rename(MetaIndex->DestFile, MetaIndex->DestFile + ".FAILED"); + Item::Failed("Message: " + downgrade_msg, Cnf); + TransactionManager->AbortTransaction(); + return; + } + } + else + _error->Warning(_("The data from '%s' is not signed. Packages " + "from that repository can not be authenticated."), + MetaIndex->DataTarget.Description.c_str()); + // ensures that a Release.gpg file in the lists/ is removed by the transaction + TransactionManager->TransactionStageRemoval(this, DestFile); - // success in download/apply a diff, queue next (if needed) - if(State == StateApplyDiff) + // only allow going further if the users explicitely wants it + if(AllowInsecureRepositories(TransactionManager->MetaIndexParser, TransactionManager, this) == true) { - // remove the just applied patch - available_patches.erase(available_patches.begin()); - unlink((FinalFile + ".ed").c_str()); - - // move into place - if(Debug) + if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) { - std::clog << "Moving patched file in place: " << std::endl - << DestFile << " -> " << FinalFile << std::endl; + // open the last Release if we have it + if (TransactionManager->IMSHit == false) + { + TransactionManager->LastMetaIndexParser = new indexRecords; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); + } } - Rename(DestFile,FinalFile); - chmod(FinalFile.c_str(),0644); - // see if there is more to download - if(available_patches.empty() == false) { - new pkgAcqIndexDiffs(Owner, TransactionManager, Target, - ExpectedHashes, MetaIndexParser, - available_patches); - return Finish(); - } else - // update - DestFile = FinalFile; - return Finish(true); + // we parse the indexes here because at this point the user wanted + // a repository that may potentially harm him + if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile) == false || MetaIndex->VerifyVendor(Message) == false) + /* expired Release files are still a problem you need extra force for */; + else + MetaIndex->QueueIndexes(true); + + TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); + } + + // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor + if (Cnf->LocalOnly == true || + StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + { + // Ignore this + Status = StatDone; } } /*}}}*/ -// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ -pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser, - DiffInfo const &patch, - std::vector const * const allPatches) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser), - patch(patch), allPatches(allPatches), State(StateFetchDiff) + + +// AcqBaseIndex - Constructor /*{{{*/ +pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) +: pkgAcqTransactionItem(Owner, TransactionManager, Target) +{ +} + /*}}}*/ + +// AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Get the DiffIndex file first and see if there are patches available + * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the + * patches. If anything goes wrong in that process, it will fall back to + * the original packages file + */ +pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - RealURI = Target->URI; Desc.Owner = this; - Description = Target->Description; + Desc.Description = Target->Description + ".diff/Index"; Desc.ShortDesc = Target->ShortDesc; + Desc.URI = Target->URI + ".diff/Index"; - Desc.URI = RealURI + ".diff/" + patch.file + ".gz"; - Desc.Description = Description + " " + patch.file + string(".pdiff"); + DestFile = GetPartialFileNameFromURI(Desc.URI); + + if(Debug) + std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl; - DestFile = GetPartialFileNameFromURI(RealURI + ".diff/" + patch.file); + // look for the current package file + CurrentPackagesFile = GetFinalFileNameFromURI(Target->URI); + + // FIXME: this file:/ check is a hack to prevent fetching + // from local sources. this is really silly, and + // should be fixed cleanly as soon as possible + if(!FileExists(CurrentPackagesFile) || + Desc.URI.substr(0,strlen("file:/")) == "file:/") + { + // we don't have a pkg file or we don't want to queue + Failed("No index file, local or canceld by user", NULL); + return; + } if(Debug) - std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; + std::clog << "pkgAcqDiffIndex::pkgAcqDiffIndex(): " + << CurrentPackagesFile << std::endl; QueueURI(Desc); + } /*}}}*/ -void pkgAcqIndexMergeDiffs::Failed(string Message,pkgAcquire::MethodConfig * Cnf)/*{{{*/ +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqDiffIndex::Custom600Headers() const { - if(Debug) - std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; - - Item::Failed(Message,Cnf); - Status = StatDone; + string const Final = GetFinalFilename(); - // check if we are the first to fail, otherwise we are done here - State = StateDoneDiff; - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - if ((*I)->State == StateErrorDiff) - return; + if(Debug) + std::clog << "Custom600Header-IMS: " << Final << std::endl; - // first failure means we should fallback - State = StateErrorDiff; - if (Debug) - std::clog << "Falling back to normal index file acquire" << std::endl; - DestFile = GetPartialFileNameFromURI(Target->URI); - RenameOnError(PDiffError); - new pkgAcqIndex(Owner, TransactionManager, Target, ExpectedHashes, MetaIndexParser); + struct stat Buf; + if (stat(Final.c_str(),&Buf) != 0) + return "\nIndex-File: true"; + + return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); +} + /*}}}*/ +void pkgAcqDiffIndex::QueueOnIMSHit() const /*{{{*/ +{ + // list cleanup needs to know that this file as well as the already + // present index is ours, so we create an empty diff to save it for us + new pkgAcqIndexDiffs(Owner, TransactionManager, Target); } /*}}}*/ -void pkgAcqIndexMergeDiffs::Done(string Message,unsigned long long Size,HashStringList const &Hashes, /*{{{*/ - pkgAcquire::MethodConfig *Cnf) +bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ { + // failing here is fine: our caller will take care of trying to + // get the complete file if patching fails if(Debug) - std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl; - - Item::Done(Message,Size,Hashes,Cnf); - - // FIXME: verify download before feeding it to rred - string const FinalFile = GetPartialFileNameFromURI(RealURI); - - if (State == StateFetchDiff) - { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes) - { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; - } + std::clog << "pkgAcqDiffIndex::ParseIndexDiff() " << IndexDiffFile + << std::endl; - // rred expects the patch as $FinalFile.ed.$patchname.gz - Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + FileFd Fd(IndexDiffFile,FileFd::ReadOnly); + pkgTagFile TF(&Fd); + if (_error->PendingError() == true) + return false; - // check if this is the last completed diff - State = StateDoneDiff; - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - if ((*I)->State != StateDoneDiff) - { - if(Debug) - std::clog << "Not the last done diff in the batch: " << Desc.URI << std::endl; - return; - } + pkgTagSection Tags; + if(unlikely(TF.Step(Tags) == false)) + return false; - // this is the last completed diff, so we are ready to apply now - State = StateApplyDiff; + HashStringList ServerHashes; + unsigned long long ServerSize = 0; - // patching needs to be bootstrapped with the 'old' version - if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0) - { - Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL); - return; - } + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string tagname = *type; + tagname.append("-Current"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - if(Debug) - std::clog << "Sending to rred method: " << FinalFile << std::endl; + string hash; + unsigned long long size; + std::stringstream ss(tmp); + ss >> hash >> size; + if (unlikely(hash.empty() == true)) + continue; + if (unlikely(ServerSize != 0 && ServerSize != size)) + continue; + ServerHashes.push_back(HashString(*type, hash)); + ServerSize = size; + } - Local = true; - Desc.URI = "rred:" + FinalFile; - QueueURI(Desc); - SetActiveSubprocess("rred"); - return; + if (ServerHashes.usable() == false) + { + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Did not find a good hashsum in the index" << std::endl; + return false; } - // success in download/apply all diffs, clean up - else if (State == StateApplyDiff) + + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + if (TargetFileHashes.usable() == false || ServerHashes != TargetFileHashes) { - // see if we really got the expected file - if(ExpectedHashes.usable() && ExpectedHashes != Hashes) + if (Debug == true) { - RenameOnError(HashSumMismatch); - return; + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": Index has different hashes than parser, probably older, so fail pdiffing" << std::endl; + printHashSumComparision(CurrentPackagesFile, ServerHashes, TargetFileHashes); } + return false; + } - // move the result into place - std::string const Final = GetFinalFilename(); + if (ServerHashes.VerifyFile(CurrentPackagesFile) == true) + { + // we have the same sha1 as the server so we are done here if(Debug) - std::clog << "Queue patched file in place: " << std::endl - << DestFile << " -> " << Final << std::endl; + std::clog << "pkgAcqDiffIndex: Package file " << CurrentPackagesFile << " is up-to-date" << std::endl; + QueueOnIMSHit(); + return true; + } - // queue for copy by the transaction manager - TransactionManager->TransactionStageCopy(this, DestFile, Final); + FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); + Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - // ensure the ed's are gone regardless of list-cleanup - for (std::vector::const_iterator I = allPatches->begin(); - I != allPatches->end(); ++I) - { - std::string const PartialFile = GetPartialFileNameFromURI(RealURI); - std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; - unlink(patch.c_str()); - } - unlink(FinalFile.c_str()); + if(Debug) + std::clog << "Server-Current: " << ServerHashes.find(NULL)->toStr() << " and we start at " + << fd.Name() << " " << fd.FileSize() << " " << LocalHashes.find(NULL)->toStr() << std::endl; - // all set and done - Complete = true; - if(Debug) - std::clog << "allDone: " << DestFile << "\n" << std::endl; - } -} - /*}}}*/ -// AcqBaseIndex - Constructor /*{{{*/ -pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser) -: Item(Owner, ExpectedHashes, TransactionManager), Target(Target), - MetaIndexParser(MetaIndexParser) -{ -} - /*}}}*/ -// AcqBaseIndex::VerifyHashByMetaKey - verify hash for the given metakey /*{{{*/ -bool pkgAcqBaseIndex::VerifyHashByMetaKey(HashStringList const &Hashes) -{ - if(MetaKey != "" && Hashes.usable()) + // parse all of (provided) history + vector available_patches; + bool firstAcceptedHashes = true; + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record && Record->Hashes.usable() && Hashes != Record->Hashes) - { - printHashSumComparision(RealURI, Record->Hashes, Hashes); - return false; - } - } - return true; -} - /*}}}*/ -// AcqBaseIndex::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqBaseIndex::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(RealURI); -} - /*}}}*/ -// AcqIndex::AcqIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* The package file is added to the queue and a second class is - instantiated to fetch the revision file */ -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, - string URI,string URIDesc,string ShortDesc, - HashStringList const &ExpectedHash) - : pkgAcqBaseIndex(Owner, 0, NULL, ExpectedHash, NULL) -{ - RealURI = URI; - - AutoSelectCompression(); - Init(URI, URIDesc, ShortDesc); + if (LocalHashes.find(*type) == NULL) + continue; - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgIndex with TransactionManager " - << TransactionManager << std::endl; -} - /*}}}*/ -// AcqIndex::AcqIndex - Constructor /*{{{*/ -pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - IndexTarget const *Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser) - : pkgAcqBaseIndex(Owner, TransactionManager, Target, ExpectedHash, - MetaIndexParser) -{ - RealURI = Target->URI; + std::string tagname = *type; + tagname.append("-History"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - // autoselect the compression method - AutoSelectCompression(); - Init(Target->URI, Target->Description, Target->ShortDesc); + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgIndex with TransactionManager " - << TransactionManager << std::endl; -} - /*}}}*/ -// AcqIndex::AutoSelectCompression - Select compression /*{{{*/ -void pkgAcqIndex::AutoSelectCompression() -{ - std::vector types = APT::Configuration::getCompressionTypes(); - CompressionExtensions = ""; - if (ExpectedHashes.usable()) - { - for (std::vector::const_iterator t = types.begin(); - t != types.end(); ++t) + while (ss >> hash >> size >> filename) { - std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t); - if (*t == "uncompressed" || - MetaIndexParser->Exists(CompressedMetaKey) == true) - CompressionExtensions.append(*t).append(" "); + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; + + // see if we have a record for this file already + std::vector::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) + { + if (cur->file != filename || unlikely(cur->result_size != size)) + continue; + cur->result_hashes.push_back(HashString(*type, hash)); + break; + } + if (cur != available_patches.end()) + continue; + if (firstAcceptedHashes == true) + { + DiffInfo next; + next.file = filename; + next.result_hashes.push_back(HashString(*type, hash)); + next.result_size = size; + next.patch_size = 0; + available_patches.push_back(next); + } + else + { + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename + << " wasn't in the list for the first parsed hash! (history)" << std::endl; + break; + } } + firstAcceptedHashes = false; } - else + + if (unlikely(available_patches.empty() == true)) { - for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) - CompressionExtensions.append(*t).append(" "); + if (Debug) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " + << "Couldn't find any patches for the patch series." << std::endl; + return false; } - if (CompressionExtensions.empty() == false) - CompressionExtensions.erase(CompressionExtensions.end()-1); -} - /*}}}*/ -// AcqIndex::Init - defered Constructor /*{{{*/ -void pkgAcqIndex::Init(string const &URI, string const &URIDesc, - string const &ShortDesc) -{ - Stage = STAGE_DOWNLOAD; - - DestFile = GetPartialFileNameFromURI(URI); - CurrentCompressionExtension = CompressionExtensions.substr(0, CompressionExtensions.find(' ')); - if (CurrentCompressionExtension == "uncompressed") + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - Desc.URI = URI; - if(Target) - MetaKey = string(Target->MetaKey); - } - else - { - Desc.URI = URI + '.' + CurrentCompressionExtension; - DestFile = DestFile + '.' + CurrentCompressionExtension; - if(Target) - MetaKey = string(Target->MetaKey) + '.' + CurrentCompressionExtension; - } - - // load the filesize - if(MetaIndexParser) - { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record) - FileSize = Record->Size; - - InitByHashIfNeeded(MetaKey); - } - - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - - QueueURI(Desc); -} - /*}}}*/ -// AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/ -void pkgAcqIndex::InitByHashIfNeeded(const std::string MetaKey) -{ - // TODO: - // - (maybe?) add support for by-hash into the sources.list as flag - // - make apt-ftparchive generate the hashes (and expire?) - std::string HostKnob = "APT::Acquire::" + ::URI(Desc.URI).Host + "::By-Hash"; - if(_config->FindB("APT::Acquire::By-Hash", false) == true || - _config->FindB(HostKnob, false) == true || - MetaIndexParser->GetSupportsAcquireByHash()) - { - indexRecords::checkSum *Record = MetaIndexParser->Lookup(MetaKey); - if(Record) - { - // FIXME: should we really use the best hash here? or a fixed one? - const HashString *TargetHash = Record->Hashes.find(""); - std::string ByHash = "/by-hash/" + TargetHash->HashType() + "/" + TargetHash->HashValue(); - size_t trailing_slash = Desc.URI.find_last_of("/"); - Desc.URI = Desc.URI.replace( - trailing_slash, - Desc.URI.substr(trailing_slash+1).size()+1, - ByHash); - } else { - _error->Warning( - "Fetching ByHash requested but can not find record for %s", - MetaKey.c_str()); - } - } -} - /*}}}*/ -// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 -string pkgAcqIndex::Custom600Headers() const -#else -string pkgAcqIndex::Custom600Headers() -#endif -{ - string Final = GetFinalFilename(); - - string msg = "\nIndex-File: true"; - struct stat Buf; - if (stat(Final.c_str(),&Buf) == 0) - msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + if (LocalHashes.find(*type) == NULL) + continue; - if(Target->IsOptional()) - msg += "\nFail-Ignore: true"; + std::string tagname = *type; + tagname.append("-Patches"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; - return msg; -} - /*}}}*/ -// pkgAcqIndex::Failed - getting the indexfile failed /*{{{*/ -void pkgAcqIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf) -{ - Item::Failed(Message,Cnf); + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); - // authorisation matches will not be fixed by other compression types - if (Status != StatAuthError) - { - size_t const nextExt = CompressionExtensions.find(' '); - if (nextExt != std::string::npos) + while (ss >> hash >> size >> filename) { - CompressionExtensions = CompressionExtensions.substr(nextExt+1); - Init(RealURI, Desc.Description, Desc.ShortDesc); - Status = StatIdle; - return; - } - } - - if(Target->IsOptional() && ExpectedHashes.empty() && Stage == STAGE_DOWNLOAD) - Status = StatDone; - else - TransactionManager->AbortTransaction(); -} - /*}}}*/ -bool pkgAcqIndex::TransactionState(TransactionStates const state) /*{{{*/ -{ - if (pkgAcquire::Item::TransactionState(state) == false) - return false; + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; - switch (state) - { - case TransactionAbort: - if (Stage == STAGE_DECOMPRESS_AND_VERIFY) + // see if we have a record for this file already + std::vector::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) { - // keep the compressed file, but drop the decompressed - EraseFileName.clear(); - if (PartialFile.empty() == false && flExtension(PartialFile) == "decomp") - unlink(PartialFile.c_str()); + if (cur->file != filename) + continue; + if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) + continue; + cur->patch_hashes.push_back(HashString(*type, hash)); + cur->patch_size = size; + break; } + if (cur != available_patches.end()) + continue; + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename + << " wasn't in the list for the first parsed hash! (patches)" << std::endl; break; - case TransactionCommit: - if (EraseFileName.empty() == false) - unlink(EraseFileName.c_str()); - break; - } - return true; -} - /*}}}*/ -// pkgAcqIndex::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqIndex::GetFinalFilename() const -{ - std::string const FinalFile = GetFinalFileNameFromURI(RealURI); - return GetCompressedFileName(RealURI, FinalFile, CurrentCompressionExtension); -} - /*}}}*/ -// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ -void pkgAcqIndex::ReverifyAfterIMS() -{ - // update destfile to *not* include the compression extension when doing - // a reverify (as its uncompressed on disk already) - DestFile = GetCompressedFileName(RealURI, GetPartialFileNameFromURI(RealURI), CurrentCompressionExtension); - - // copy FinalFile into partial/ so that we check the hash again - string FinalFile = GetFinalFilename(); - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = "copy:" + FinalFile; - QueueURI(Desc); -} - /*}}}*/ -// AcqIndex::ValidateFile - Validate the content of the downloaded file /*{{{*/ -bool pkgAcqIndex::ValidateFile(const std::string &FileName) -{ - // FIXME: this can go away once we only ever download stuff that - // has a valid hash and we never do GET based probing - // FIXME2: this also leaks debian-isms into the code and should go therefore - - /* Always validate the index file for correctness (all indexes must - * have a Package field) (LP: #346386) (Closes: #627642) - */ - FileFd fd(FileName, FileFd::ReadOnly, FileFd::Extension); - // Only test for correctness if the content of the file is not empty - // (empty is ok) - if (fd.Size() > 0) - { - pkgTagSection sec; - pkgTagFile tag(&fd); - - // all our current indexes have a field 'Package' in each section - if (_error->PendingError() == true || - tag.Step(sec) == false || - sec.Exists("Package") == false) - return false; - } - return true; -} - /*}}}*/ -// AcqIndex::Done - Finished a fetch /*{{{*/ -// --------------------------------------------------------------------- -/* This goes through a number of states.. On the initial fetch the - method could possibly return an alternate filename which points - to the uncompressed version of the file. If this is so the file - is copied into the partial directory. In all other cases the file - is decompressed with a compressed uri. */ -void pkgAcqIndex::Done(string Message, - unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - Item::Done(Message,Size,Hashes,Cfg); - - switch(Stage) - { - case STAGE_DOWNLOAD: - StageDownloadDone(Message, Hashes, Cfg); - break; - case STAGE_DECOMPRESS_AND_VERIFY: - StageDecompressDone(Message, Hashes, Cfg); - break; - } -} - /*}}}*/ -// AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ -void pkgAcqIndex::StageDownloadDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - // First check if the calculcated Hash of the (compressed) downloaded - // file matches the hash we have in the MetaIndexRecords for this file - if(VerifyHashByMetaKey(Hashes) == false) - { - RenameOnError(HashSumMismatch); - Failed(Message, Cfg); - return; - } - - Complete = true; - - // Handle the unzipd case - string FileName = LookupTag(Message,"Alt-Filename"); - if (FileName.empty() == false) - { - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Local = true; - DestFile += ".decomp"; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); - SetActiveSubprocess("copy"); - return; - } - - FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - Status = StatError; - ErrorText = "Method gave a blank filename"; - } - - // Methods like e.g. "file:" will give us a (compressed) FileName that is - // not the "DestFile" we set, in this case we uncompress from the local file - if (FileName != DestFile) - Local = true; - else - EraseFileName = FileName; - - // we need to verify the file against the current Release file again - // on if-modfied-since hit to avoid a stale attack against us - if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) - { - // The files timestamp matches, reverify by copy into partial/ - EraseFileName = ""; - ReverifyAfterIMS(); - return; - } - - // If we have compressed indexes enabled, queue for hash verification - if (_config->FindB("Acquire::GzipIndexes",false)) - { - DestFile = GetPartialFileNameFromURI(RealURI + '.' + CurrentCompressionExtension); - EraseFileName = ""; - Stage = STAGE_DECOMPRESS_AND_VERIFY; - Desc.URI = "copy:" + FileName; - QueueURI(Desc); - SetActiveSubprocess("copy"); - return; - } - - // get the binary name for your used compression type - string decompProg; - if(CurrentCompressionExtension == "uncompressed") - decompProg = "copy"; - else - decompProg = _config->Find(string("Acquire::CompressionTypes::").append(CurrentCompressionExtension),""); - if(decompProg.empty() == true) - { - _error->Error("Unsupported extension: %s", CurrentCompressionExtension.c_str()); - return; - } - - // queue uri for the next stage - Stage = STAGE_DECOMPRESS_AND_VERIFY; - DestFile += ".decomp"; - Desc.URI = decompProg + ":" + FileName; - QueueURI(Desc); - SetActiveSubprocess(decompProg); -} - /*}}}*/ -// pkgAcqIndex::StageDecompressDone - Final verification /*{{{*/ -void pkgAcqIndex::StageDecompressDone(string Message, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - if (ExpectedHashes.usable() && ExpectedHashes != Hashes) - { - Desc.URI = RealURI; - RenameOnError(HashSumMismatch); - printHashSumComparision(RealURI, ExpectedHashes, Hashes); - Failed(Message, Cfg); - return; - } - - if(!ValidateFile(DestFile)) - { - RenameOnError(InvalidFormat); - Failed(Message, Cfg); - return; - } - - // Done, queue for rename on transaction finished - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - - return; -} - /*}}}*/ -// AcqMetaBase - Constructor /*{{{*/ -pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire *Owner, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser, - std::string const &RealURI, - HashStringList const &ExpectedHashes, - pkgAcqMetaBase *TransactionManager) -: Item(Owner, ExpectedHashes, TransactionManager), - MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), - AuthPass(false), RealURI(RealURI), IMSHit(false) -{ -} - /*}}}*/ -// AcqMetaBase::Add - Add a item to the current Transaction /*{{{*/ -void pkgAcqMetaBase::Add(Item *I) -{ - Transaction.push_back(I); -} - /*}}}*/ -// AcqMetaBase::AbortTransaction - Abort the current Transaction /*{{{*/ -void pkgAcqMetaBase::AbortTransaction() -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "AbortTransaction: " << TransactionManager << std::endl; - - // ensure the toplevel is in error state too - for (std::vector::iterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - (*I)->TransactionState(TransactionAbort); - } - Transaction.clear(); -} - /*}}}*/ -// AcqMetaBase::TransactionHasError - Check for errors in Transaction /*{{{*/ -bool pkgAcqMetaBase::TransactionHasError() -{ - for (pkgAcquire::ItemIterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - switch((*I)->Status) { - case StatDone: break; - case StatIdle: break; - case StatAuthError: return true; - case StatError: return true; - case StatTransientNetworkError: return true; - case StatFetching: break; } } - return false; -} - /*}}}*/ -// AcqMetaBase::CommitTransaction - Commit a transaction /*{{{*/ -void pkgAcqMetaBase::CommitTransaction() -{ - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "CommitTransaction: " << this << std::endl; - - // move new files into place *and* remove files that are not - // part of the transaction but are still on disk - for (std::vector::iterator I = Transaction.begin(); - I != Transaction.end(); ++I) - { - (*I)->TransactionState(TransactionCommit); - } - Transaction.clear(); -} - /*}}}*/ -bool pkgAcqMetaBase::TransactionState(TransactionStates const state) /*{{{*/ -{ - // Do not remove InRelease on IMSHit of Release.gpg [yes, this is very edgecasey] - if (TransactionManager->IMSHit == false) - return pkgAcquire::Item::TransactionState(state); - return true; -} - /*}}}*/ -// AcqMetaBase::TransactionStageCopy - Stage a file for copying /*{{{*/ -void pkgAcqMetaBase::TransactionStageCopy(Item *I, - const std::string &From, - const std::string &To) -{ - I->PartialFile = From; - I->DestFile = To; -} - /*}}}*/ -// AcqMetaBase::TransactionStageRemoval - Stage a file for removal /*{{{*/ -void pkgAcqMetaBase::TransactionStageRemoval(Item *I, - const std::string &FinalFile) -{ - I->PartialFile = ""; - I->DestFile = FinalFile; -} - /*}}}*/ -// AcqMetaBase::GenerateAuthWarning - Check gpg authentication error /*{{{*/ -bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message) -{ - // FIXME: this entire function can do now that we disallow going to - // a unauthenticated state and can cleanly rollback - string const Final = I->GetFinalFilename(); - if(FileExists(Final)) - { - I->Status = StatTransientNetworkError; - _error->Warning(_("An error occurred during the signature " - "verification. The repository is not updated " - "and the previous index files will be used. " - "GPG error: %s: %s\n"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); - RunScripts("APT::Update::Auth-Failure"); - return true; - } else if (LookupTag(Message,"Message").find("NODATA") != string::npos) { - /* Invalid signature file, reject (LP: #346386) (Closes: #627642) */ - _error->Error(_("GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); - I->Status = StatError; - return true; - } else { - _error->Warning(_("GPG error: %s: %s"), - Desc.Description.c_str(), - LookupTag(Message,"Message").c_str()); + bool foundStart = false; + for (std::vector::iterator cur = available_patches.begin(); + cur != available_patches.end(); ++cur) + { + if (LocalHashes != cur->result_hashes) + continue; + + available_patches.erase(available_patches.begin(), cur); + foundStart = true; + break; } - // gpgv method failed - ReportMirrorFailure("GPGFailure"); - return false; -} - /*}}}*/ -// AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ -pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - string const &URI, string const &URIDesc,string const &ShortDesc, - pkgAcqMetaIndex * const MetaIndex) : - pkgAcquire::Item(Owner, HashStringList(), TransactionManager), MetaIndex(MetaIndex), - URIDesc(URIDesc), RealURI(URI) -{ - DestFile = GetPartialFileNameFromURI(URI); - // remove any partial downloaded sig-file in partial/. - // it may confuse proxies and is too small to warrant a - // partial download anyway - unlink(DestFile.c_str()); + if (foundStart == false || unlikely(available_patches.empty() == true)) + { + if (Debug) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": " + << "Couldn't find the start of the patch series." << std::endl; + return false; + } - // set the TransactionManager - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgAcqMetaSig with TransactionManager " - << TransactionManager << std::endl; + // patching with too many files is rather slow compared to a fast download + unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0); + if (fileLimit != 0 && fileLimit < available_patches.size()) + { + if (Debug) + std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit + << ") so fallback to complete download" << std::endl; + return false; + } - // Create the item - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - Desc.URI = URI; + // calculate the size of all patches we have to get + // note that all sizes are uncompressed, while we download compressed files + unsigned long long patchesSize = 0; + for (std::vector::const_iterator cur = available_patches.begin(); + cur != available_patches.end(); ++cur) + patchesSize += cur->patch_size; + unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); + if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) + { + if (Debug) + std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100 + << ") so fallback to complete download" << std::endl; + return false; + } - // If we got a hit for Release, we will get one for Release.gpg too (or obscure errors), - // so we skip the download step and go instantly to verification - if (TransactionManager->IMSHit == true && RealFileExists(GetFinalFilename())) + // we have something, queue the diffs + string::size_type const last_space = Description.rfind(" "); + if(last_space != string::npos) + Description.erase(last_space, Description.size()-last_space); + + /* decide if we should download patches one by one or in one go: + The first is good if the server merges patches, but many don't so client + based merging can be attempt in which case the second is better. + "bad things" will happen if patches are merged on the server, + but client side merging is attempt as well */ + bool pdiff_merge = _config->FindB("Acquire::PDiffs::Merge", true); + if (pdiff_merge == true) { - Complete = true; - Status = StatDone; - PartialFile = DestFile = GetFinalFilename(); - MetaIndexFileSignature = DestFile; - MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); + // reprepro adds this flag if it has merged patches on the server + std::string const precedence = Tags.FindS("X-Patch-Precedence"); + pdiff_merge = (precedence != "merged"); } + + if (pdiff_merge == false) + new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches); else - QueueURI(Desc); -} - /*}}}*/ -pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ -{ + { + std::vector *diffs = new std::vector(available_patches.size()); + for(size_t i = 0; i < available_patches.size(); ++i) + (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager, + Target, + available_patches[i], + diffs); + } + + Complete = false; + Status = StatDone; + Dequeue(); + return true; } /*}}}*/ -// pkgAcqMetaSig::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqMetaSig::GetFinalFilename() const +void pkgAcqDiffIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ { - return GetFinalFileNameFromURI(RealURI); + Item::Failed(Message,Cnf); + Status = StatDone; + + if(Debug) + std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << " with " << Message << std::endl + << "Falling back to normal index file acquire" << std::endl; + + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -// pkgAcqMetaSig::Done - The signature was downloaded/verified /*{{{*/ -// --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -void pkgAcqMetaSig::Done(string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) +void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - if (MetaIndexFileSignature.empty() == false) - { - DestFile = MetaIndexFileSignature; - MetaIndexFileSignature.clear(); - } - Item::Done(Message, Size, Hashes, Cfg); + if(Debug) + std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl; - if(MetaIndex->AuthPass == false) + Item::Done(Message, Hashes, Cnf); + + string const FinalFile = GetFinalFilename(); + if(StringToBool(LookupTag(Message,"IMS-Hit"),false)) + DestFile = FinalFile; + + if(ParseDiffIndex(DestFile) == false) { - if(MetaIndex->CheckDownloadDone(this, Message, Hashes) == true) - { - // destfile will be modified to point to MetaIndexFile for the - // gpgv method, so we need to save it here - MetaIndexFileSignature = DestFile; - MetaIndex->QueueForSignatureVerify(this, MetaIndex->DestFile, DestFile); - } + Failed("Message: Couldn't parse pdiff index", Cnf); + // queue for final move - this should happen even if we fail + // while parsing (e.g. on sizelimit) and download the complete file. + TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); return; } - else if(MetaIndex->CheckAuthDone(Message) == true) - { - if (TransactionManager->IMSHit == false) - { - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); - } - } + + TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); + + Complete = true; + Status = StatDone; + Dequeue(); + + return; } /*}}}*/ -void pkgAcqMetaSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf)/*{{{*/ + +// AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* The package diff is added to the queue. one object is constructed + * for each diff and the index + */ +pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + vector const &diffs) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), + available_patches(diffs) { - Item::Failed(Message,Cnf); + DestFile = GetPartialFileNameFromURI(Target->URI); - // check if we need to fail at this point - if (MetaIndex->AuthPass == true && MetaIndex->CheckStopAuthentication(this, Message)) - return; + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); - string const FinalRelease = MetaIndex->GetFinalFilename(); - string const FinalReleasegpg = GetFinalFilename(); - string const FinalInRelease = TransactionManager->GetFinalFilename(); + Desc.Owner = this; + Description = Target->Description; + Desc.ShortDesc = Target->ShortDesc; - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + if(available_patches.empty() == true) { - std::string downgrade_msg; - strprintf(downgrade_msg, _("The repository '%s' is no longer signed."), - MetaIndex->URIDesc.c_str()); - if(_config->FindB("Acquire::AllowDowngradeToInsecureRepositories")) - { - // meh, the users wants to take risks (we still mark the packages - // from this repository as unauthenticated) - _error->Warning("%s", downgrade_msg.c_str()); - _error->Warning(_("This is normally not allowed, but the option " - "Acquire::AllowDowngradeToInsecureRepositories was " - "given to override it.")); - Status = StatDone; - } else { - _error->Error("%s", downgrade_msg.c_str()); - if (TransactionManager->IMSHit == false) - Rename(MetaIndex->DestFile, MetaIndex->DestFile + ".FAILED"); - Item::Failed("Message: " + downgrade_msg, Cnf); - TransactionManager->AbortTransaction(); - return; - } + // we are done (yeah!), check hashes against the final file + DestFile = GetFinalFileNameFromURI(Target->URI); + Finish(true); } else - _error->Warning(_("The data from '%s' is not signed. Packages " - "from that repository can not be authenticated."), - MetaIndex->URIDesc.c_str()); - - // ensures that a Release.gpg file in the lists/ is removed by the transaction - TransactionManager->TransactionStageRemoval(this, DestFile); - - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndex->MetaIndexParser, TransactionManager, this) == true) { - if (RealFileExists(FinalReleasegpg) || RealFileExists(FinalInRelease)) + // patching needs to be bootstrapped with the 'old' version + std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + if (RealFileExists(PartialFile) == false) { - // open the last Release if we have it - if (TransactionManager->IMSHit == false) + if (symlink(GetFinalFilename().c_str(), PartialFile.c_str()) != 0) { - MetaIndex->LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - MetaIndex->LastMetaIndexParser->Load(FinalInRelease); - else - MetaIndex->LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete MetaIndex->LastMetaIndexParser; - MetaIndex->LastMetaIndexParser = NULL; - } - _error->RevertToStack(); + Failed("Link creation of " + PartialFile + " to " + GetFinalFilename() + " failed", NULL); + return; } } - // we parse the indexes here because at this point the user wanted - // a repository that may potentially harm him - MetaIndex->MetaIndexParser->Load(MetaIndex->DestFile); - if (MetaIndex->VerifyVendor(Message) == false) - /* expired Release files are still a problem you need extra force for */; - else - MetaIndex->QueueIndexes(true); - - TransactionManager->TransactionStageCopy(MetaIndex, MetaIndex->DestFile, MetaIndex->GetFinalFilename()); + // get the next diff + State = StateFetchDiff; + QueueNextDiff(); } +} + /*}}}*/ +void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + Item::Failed(Message,Cnf); + Status = StatDone; - // FIXME: this is used often (e.g. in pkgAcqIndexTrans) so refactor - if (Cnf->LocalOnly == true || - StringToBool(LookupTag(Message,"Transient-Failure"),false) == false) + if(Debug) + std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << " with " << Message << std::endl + << "Falling back to normal index file acquire" << std::endl; + DestFile = GetPartialFileNameFromURI(Target->URI); + RenameOnError(PDiffError); + new pkgAcqIndex(Owner, TransactionManager, Target); + Finish(); +} + /*}}}*/ +// Finish - helper that cleans the item out of the fetcher queue /*{{{*/ +void pkgAcqIndexDiffs::Finish(bool allDone) +{ + if(Debug) + std::clog << "pkgAcqIndexDiffs::Finish(): " + << allDone << " " + << Desc.URI << std::endl; + + // we restore the original name, this is required, otherwise + // the file will be cleaned + if(allDone) { - // Ignore this + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + + // this is for the "real" finish + Complete = true; Status = StatDone; + Dequeue(); + if(Debug) + std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl; + return; } + + if(Debug) + std::clog << "Finishing: " << Desc.URI << std::endl; + Complete = false; + Status = StatDone; + Dequeue(); + return; } /*}}}*/ -pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire *Owner, /*{{{*/ - pkgAcqMetaBase *TransactionManager, - string URI,string URIDesc,string ShortDesc, - string MetaIndexSigURI,string MetaIndexSigURIDesc, string MetaIndexSigShortDesc, - const vector* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaBase(Owner, IndexTargets, MetaIndexParser, URI, HashStringList(), - TransactionManager), - URIDesc(URIDesc), ShortDesc(ShortDesc), - MetaIndexSigURI(MetaIndexSigURI), MetaIndexSigURIDesc(MetaIndexSigURIDesc), - MetaIndexSigShortDesc(MetaIndexSigShortDesc) +bool pkgAcqIndexDiffs::QueueNextDiff() /*{{{*/ { - if(TransactionManager == NULL) + // calc sha1 of the just patched file + std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); + + if(!FileExists(FinalFile)) { - this->TransactionManager = this; - this->TransactionManager->Add(this); + Failed("Message: No FinalFile " + FinalFile + " available", NULL); + return false; } - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "New pkgAcqMetaIndex with TransactionManager " - << this->TransactionManager << std::endl; - - - Init(URIDesc, ShortDesc); -} - /*}}}*/ -// pkgAcqMetaIndex::Init - Delayed constructor /*{{{*/ -void pkgAcqMetaIndex::Init(std::string URIDesc, std::string ShortDesc) -{ - DestFile = GetPartialFileNameFromURI(RealURI); - - // Create the item - Desc.Description = URIDesc; - Desc.Owner = this; - Desc.ShortDesc = ShortDesc; - Desc.URI = RealURI; + FileFd fd(FinalFile, FileFd::ReadOnly); + Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - // we expect more item - ExpectedAdditionalItems = IndexTargets->size(); - QueueURI(Desc); -} - /*}}}*/ -void pkgAcqMetaIndex::Done(string Message,unsigned long long Size, /*{{{*/ - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg) -{ - Item::Done(Message,Size,Hashes,Cfg); + if(Debug) + std::clog << "QueueNextDiff: " << FinalFile << " (" << LocalHashes.find(NULL)->toStr() << ")" << std::endl; - if(CheckDownloadDone(this, Message, Hashes)) + HashStringList const TargetFileHashes = GetExpectedHashesFor(Target->MetaKey); + if (unlikely(LocalHashes.usable() == false || TargetFileHashes.usable() == false)) { - // we have a Release file, now download the Signature, all further - // verify/queue for additional downloads will be done in the - // pkgAcqMetaSig::Done() code - new pkgAcqMetaSig(Owner, TransactionManager, - MetaIndexSigURI, MetaIndexSigURIDesc, - MetaIndexSigShortDesc, this); + Failed("Local/Expected hashes are not usable", NULL); + return false; } -} - /*}}}*/ -bool pkgAcqMetaBase::CheckAuthDone(string Message) /*{{{*/ -{ - // At this point, the gpgv method has succeeded, so there is a - // valid signature from a key in the trusted keyring. We - // perform additional verification of its contents, and use them - // to verify the indexes we are about to download - if (TransactionManager->IMSHit == false) + + // final file reached before all patches are applied + if(LocalHashes == TargetFileHashes) { - // open the last (In)Release if we have it - std::string const FinalFile = GetFinalFilename(); - std::string FinalRelease; - std::string FinalInRelease; - if (APT::String::Endswith(FinalFile, "InRelease")) - { - FinalInRelease = FinalFile; - FinalRelease = FinalFile.substr(0, FinalFile.length() - strlen("InRelease")) + "Release"; - } - else - { - FinalInRelease = FinalFile.substr(0, FinalFile.length() - strlen("Release")) + "InRelease"; - FinalRelease = FinalFile; - } - if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) - { - LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - LastMetaIndexParser->Load(FinalInRelease); - else - LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) - { - delete LastMetaIndexParser; - LastMetaIndexParser = NULL; - } - _error->RevertToStack(); - } + Finish(true); + return true; } - if (!MetaIndexParser->Load(DestFile)) + // remove all patches until the next matching patch is found + // this requires the Index file to be ordered + for(vector::iterator I = available_patches.begin(); + available_patches.empty() == false && + I != available_patches.end() && + I->result_hashes != LocalHashes; + ++I) { - Status = StatAuthError; - ErrorText = MetaIndexParser->ErrorText; - return false; + available_patches.erase(I); } - if (!VerifyVendor(Message)) + // error checking and falling back if no patch was found + if(available_patches.empty() == true) { - Status = StatAuthError; + Failed("No patches left to reach target", NULL); return false; } - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - std::cerr << "Signature verification succeeded: " - << DestFile << std::endl; + // queue the right diff + Desc.URI = Target->URI + ".diff/" + available_patches[0].file + ".gz"; + Desc.Description = Description + " " + available_patches[0].file + string(".pdiff"); + DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + available_patches[0].file); - // Download further indexes with verification - QueueIndexes(true); + if(Debug) + std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl; + + QueueURI(Desc); return true; } /*}}}*/ -// pkgAcqMetaBase::Custom600Headers - Get header for AcqMetaBase /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -string pkgAcqMetaBase::Custom600Headers() const -#else -string pkgAcqMetaBase::Custom600Headers() -#endif +void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - std::string Header = "\nIndex-File: true"; - std::string MaximumSize; - strprintf(MaximumSize, "\nMaximum-Size: %i", - _config->FindI("Acquire::MaxReleaseFileSize", 10*1000*1000)); - Header += MaximumSize; - - string const FinalFile = GetFinalFilename(); + if(Debug) + std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl; - struct stat Buf; - if (stat(FinalFile.c_str(),&Buf) == 0) - Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); + Item::Done(Message, Hashes, Cnf); - return Header; -} - /*}}}*/ -// pkgAcqMetaBase::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqMetaBase::GetFinalFilename() const -{ - return GetFinalFileNameFromURI(RealURI); -} - /*}}}*/ -// pkgAcqMetaBase::QueueForSignatureVerify /*{{{*/ -void pkgAcqMetaBase::QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature) -{ - AuthPass = true; - I->Desc.URI = "gpgv:" + Signature; - I->DestFile = File; - QueueURI(I->Desc); - I->SetActiveSubprocess("gpgv"); -} - /*}}}*/ -// pkgAcqMetaBase::CheckDownloadDone /*{{{*/ -bool pkgAcqMetaBase::CheckDownloadDone(pkgAcquire::Item * const I, const std::string &Message, HashStringList const &Hashes) const -{ - // We have just finished downloading a Release file (it is not - // verified yet) + // FIXME: verify this download too before feeding it to rred + std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); - string const FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) + // success in downloading a diff, enter ApplyDiff state + if(State == StateFetchDiff) { - I->Status = StatError; - I->ErrorText = "Method gave a blank filename"; - return false; - } + FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); + class Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - if (FileName != I->DestFile) - { - I->Local = true; - I->Desc.URI = "copy:" + FileName; - I->QueueURI(I->Desc); - return false; - } + if (fd.Size() != available_patches[0].patch_size || + available_patches[0].patch_hashes != LocalHashes) + { + // patchfiles are dated, so bad indicates a bad download, so kill it + unlink(DestFile.c_str()); + Failed("Patch has Size/Hashsum mismatch", NULL); + return; + } - // make sure to verify against the right file on I-M-S hit - bool IMSHit = StringToBool(LookupTag(Message,"IMS-Hit"), false); - if (IMSHit == false && Hashes.usable()) + // rred excepts the patch as $FinalFile.ed + Rename(DestFile,FinalFile+".ed"); + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + State = StateApplyDiff; + Local = true; + Desc.URI = "rred:" + FinalFile; + QueueURI(Desc); + SetActiveSubprocess("rred"); + return; + } + + + // success in download/apply a diff, queue next (if needed) + if(State == StateApplyDiff) { - // detect IMS-Hits servers haven't detected by Hash comparison - std::string const FinalFile = I->GetFinalFilename(); - if (RealFileExists(FinalFile) && Hashes.VerifyFile(FinalFile) == true) + // remove the just applied patch + available_patches.erase(available_patches.begin()); + unlink((FinalFile + ".ed").c_str()); + + // move into place + if(Debug) { - IMSHit = true; - unlink(I->DestFile.c_str()); + std::clog << "Moving patched file in place: " << std::endl + << DestFile << " -> " << FinalFile << std::endl; } - } + Rename(DestFile,FinalFile); + chmod(FinalFile.c_str(),0644); - if(IMSHit == true) - { - // for simplicity, the transaction manager is always InRelease - // even if it doesn't exist. - if (TransactionManager != NULL) - TransactionManager->IMSHit = true; - I->PartialFile = I->DestFile = I->GetFinalFilename(); + // see if there is more to download + if(available_patches.empty() == false) { + new pkgAcqIndexDiffs(Owner, TransactionManager, Target, + available_patches); + return Finish(); + } else + // update + DestFile = FinalFile; + return Finish(true); } +} + /*}}}*/ + +// AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ +pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + DiffInfo const &patch, + std::vector const * const allPatches) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), + patch(patch), allPatches(allPatches), State(StateFetchDiff) +{ + Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); + + Desc.Owner = this; + Description = Target->Description; + Desc.ShortDesc = Target->ShortDesc; + + Desc.URI = Target->URI + ".diff/" + patch.file + ".gz"; + Desc.Description = Description + " " + patch.file + string(".pdiff"); + + DestFile = GetPartialFileNameFromURI(Target->URI + ".diff/" + patch.file); + + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs: " << Desc.URI << std::endl; + + QueueURI(Desc); +} + /*}}}*/ +void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf)/*{{{*/ +{ + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs failed: " << Desc.URI << " with " << Message << std::endl; - // set Item to complete as the remaining work is all local (verify etc) - I->Complete = true; + Item::Failed(Message,Cnf); + Status = StatDone; - return true; + // check if we are the first to fail, otherwise we are done here + State = StateDoneDiff; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + if ((*I)->State == StateErrorDiff) + return; + + // first failure means we should fallback + State = StateErrorDiff; + if (Debug) + std::clog << "Falling back to normal index file acquire" << std::endl; + DestFile = GetPartialFileNameFromURI(Target->URI); + RenameOnError(PDiffError); + new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ -void pkgAcqMetaBase::QueueIndexes(bool verify) /*{{{*/ +void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Hashes, /*{{{*/ + pkgAcquire::MethodConfig const * const Cnf) { - // at this point the real Items are loaded in the fetcher - ExpectedAdditionalItems = 0; + if(Debug) + std::clog << "pkgAcqIndexMergeDiffs::Done(): " << Desc.URI << std::endl; - vector ::const_iterator Target; - for (Target = IndexTargets->begin(); - Target != IndexTargets->end(); - ++Target) - { - HashStringList ExpectedIndexHashes; - const indexRecords::checkSum *Record = MetaIndexParser->Lookup((*Target)->MetaKey); + Item::Done(Message, Hashes, Cnf); - // optional target that we do not have in the Release file are - // skipped - if (verify == true && Record == NULL && (*Target)->IsOptional()) - continue; + // FIXME: verify download before feeding it to rred + string const FinalFile = GetPartialFileNameFromURI(Target->URI); + + if (State == StateFetchDiff) + { + FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); + class Hashes LocalHashesCalc; + LocalHashesCalc.AddFD(fd); + HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - // targets without a hash record are a error when verify is required - if (verify == true && Record == NULL) + if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes) { - Status = StatAuthError; - strprintf(ErrorText, _("Unable to find expected entry '%s' in Release file (Wrong sources.list entry or malformed file)"), (*Target)->MetaKey.c_str()); - return; + // patchfiles are dated, so bad indicates a bad download, so kill it + unlink(DestFile.c_str()); + Failed("Patch has Size/Hashsum mismatch", NULL); + return; } - if (Record) - ExpectedIndexHashes = Record->Hashes; - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) - { - std::cerr << "Queueing: " << (*Target)->URI << std::endl - << "Expected Hash:" << std::endl; - for (HashStringList::const_iterator hs = ExpectedIndexHashes.begin(); hs != ExpectedIndexHashes.end(); ++hs) - std::cerr << "\t- " << hs->toStr() << std::endl; - std::cerr << "For: " << ((Record == NULL) ? "" : Record->MetaKeyFilename) << std::endl; + // rred expects the patch as $FinalFile.ed.$patchname.gz + Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + + // check if this is the last completed diff + State = StateDoneDiff; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + if ((*I)->State != StateDoneDiff) + { + if(Debug) + std::clog << "Not the last done diff in the batch: " << Desc.URI << std::endl; + return; + } + + // this is the last completed diff, so we are ready to apply now + State = StateApplyDiff; + // patching needs to be bootstrapped with the 'old' version + if (symlink(GetFinalFilename().c_str(), FinalFile.c_str()) != 0) + { + Failed("Link creation of " + FinalFile + " to " + GetFinalFilename() + " failed", NULL); + return; } - if (verify == true && ExpectedIndexHashes.empty() == true) + + if(Debug) + std::clog << "Sending to rred method: " << FinalFile << std::endl; + + Local = true; + Desc.URI = "rred:" + FinalFile; + QueueURI(Desc); + SetActiveSubprocess("rred"); + return; + } + // success in download/apply all diffs, clean up + else if (State == StateApplyDiff) + { + // move the result into place + std::string const Final = GetFinalFilename(); + if(Debug) + std::clog << "Queue patched file in place: " << std::endl + << DestFile << " -> " << Final << std::endl; + + // queue for copy by the transaction manager + TransactionManager->TransactionStageCopy(this, DestFile, Final); + + // ensure the ed's are gone regardless of list-cleanup + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) { - Status = StatAuthError; - strprintf(ErrorText, _("Unable to find hash sum for '%s' in Release file"), (*Target)->MetaKey.c_str()); - return; + std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); + std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; + unlink(patch.c_str()); } + unlink(FinalFile.c_str()); - /* Queue the Index file (Packages, Sources, Translation-$foo - (either diff or full packages files, depending - on the users option) - we also check if the PDiff Index file is listed - in the Meta-Index file. Ideal would be if pkgAcqDiffIndex would test this - instead, but passing the required info to it is to much hassle */ - if(_config->FindB("Acquire::PDiffs",true) == true && (verify == false || - MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index") == true)) - new pkgAcqDiffIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser); - else - new pkgAcqIndex(Owner, TransactionManager, *Target, ExpectedIndexHashes, MetaIndexParser); + // all set and done + Complete = true; + if(Debug) + std::clog << "allDone: " << DestFile << "\n" << std::endl; } } /*}}}*/ -bool pkgAcqMetaBase::VerifyVendor(string Message) /*{{{*/ + +// AcqIndex::AcqIndex - Constructor /*{{{*/ +pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, + pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target) + : pkgAcqBaseIndex(Owner, TransactionManager, Target) { - string::size_type pos; + // autoselect the compression method + AutoSelectCompression(); + Init(Target->URI, Target->Description, Target->ShortDesc); - // check for missing sigs (that where not fatal because otherwise we had - // bombed earlier) - string missingkeys; - string msg = _("There is no public key available for the " - "following key IDs:\n"); - pos = Message.find("NO_PUBKEY "); - if (pos != std::string::npos) + if(_config->FindB("Debug::Acquire::Transaction", false) == true) + std::clog << "New pkgIndex with TransactionManager " + << TransactionManager << std::endl; +} + /*}}}*/ +// AcqIndex::AutoSelectCompression - Select compression /*{{{*/ +void pkgAcqIndex::AutoSelectCompression() +{ + std::vector types = APT::Configuration::getCompressionTypes(); + CompressionExtensions = ""; + if (TransactionManager->MetaIndexParser != NULL && TransactionManager->MetaIndexParser->Exists(Target->MetaKey)) { - string::size_type start = pos+strlen("NO_PUBKEY "); - string Fingerprint = Message.substr(start, Message.find("\n")-start); - missingkeys += (Fingerprint); + for (std::vector::const_iterator t = types.begin(); + t != types.end(); ++t) + { + std::string CompressedMetaKey = string(Target->MetaKey).append(".").append(*t); + if (*t == "uncompressed" || + TransactionManager->MetaIndexParser->Exists(CompressedMetaKey) == true) + CompressionExtensions.append(*t).append(" "); + } } - if(!missingkeys.empty()) - _error->Warning("%s", (msg + missingkeys).c_str()); - - string Transformed = MetaIndexParser->GetExpectedDist(); - - if (Transformed == "../project/experimental") + else { - Transformed = "experimental"; + for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) + CompressionExtensions.append(*t).append(" "); } + if (CompressionExtensions.empty() == false) + CompressionExtensions.erase(CompressionExtensions.end()-1); +} + /*}}}*/ +// AcqIndex::Init - defered Constructor /*{{{*/ +void pkgAcqIndex::Init(string const &URI, string const &URIDesc, + string const &ShortDesc) +{ + Stage = STAGE_DOWNLOAD; - pos = Transformed.rfind('/'); - if (pos != string::npos) - { - Transformed = Transformed.substr(0, pos); - } + DestFile = GetPartialFileNameFromURI(URI); - if (Transformed == ".") + size_t const nextExt = CompressionExtensions.find(' '); + if (nextExt == std::string::npos) { - Transformed = ""; + CurrentCompressionExtension = CompressionExtensions; + CompressionExtensions.clear(); } - - if (_config->FindB("Acquire::Check-Valid-Until", true) == true && - MetaIndexParser->GetValidUntil() > 0) { - time_t const invalid_since = time(NULL) - MetaIndexParser->GetValidUntil(); - if (invalid_since > 0) - { - std::string errmsg; - strprintf(errmsg, - // TRANSLATOR: The first %s is the URL of the bad Release file, the second is - // the time since then the file is invalid - formated in the same way as in - // the download progress display (e.g. 7d 3h 42min 1s) - _("Release file for %s is expired (invalid since %s). " - "Updates for this repository will not be applied."), - RealURI.c_str(), TimeToStr(invalid_since).c_str()); - if (ErrorText.empty()) - ErrorText = errmsg; - return _error->Error("%s", errmsg.c_str()); - } + else + { + CurrentCompressionExtension = CompressionExtensions.substr(0, nextExt); + CompressionExtensions = CompressionExtensions.substr(nextExt+1); } - /* Did we get a file older than what we have? This is a last minute IMS hit and doubles - as a prevention of downgrading us to older (still valid) files */ - if (TransactionManager->IMSHit == false && LastMetaIndexParser != NULL && - LastMetaIndexParser->GetDate() > MetaIndexParser->GetDate()) + if (CurrentCompressionExtension == "uncompressed") { - TransactionManager->IMSHit = true; - unlink(DestFile.c_str()); - PartialFile = DestFile = GetFinalFilename(); - delete MetaIndexParser; - MetaIndexParser = LastMetaIndexParser; - LastMetaIndexParser = NULL; + Desc.URI = URI; } - - if (_config->FindB("Debug::pkgAcquire::Auth", false)) + else if (unlikely(CurrentCompressionExtension.empty())) + return; + else { - std::cerr << "Got Codename: " << MetaIndexParser->GetDist() << std::endl; - std::cerr << "Expecting Dist: " << MetaIndexParser->GetExpectedDist() << std::endl; - std::cerr << "Transformed Dist: " << Transformed << std::endl; + Desc.URI = URI + '.' + CurrentCompressionExtension; + DestFile = DestFile + '.' + CurrentCompressionExtension; } - if (MetaIndexParser->CheckDist(Transformed) == false) + if(TransactionManager->MetaIndexParser != NULL) + InitByHashIfNeeded(); + + Desc.Description = URIDesc; + Desc.Owner = this; + Desc.ShortDesc = ShortDesc; + + QueueURI(Desc); +} + /*}}}*/ +// AcqIndex::AdjustForByHash - modify URI for by-hash support /*{{{*/ +void pkgAcqIndex::InitByHashIfNeeded() +{ + // TODO: + // - (maybe?) add support for by-hash into the sources.list as flag + // - make apt-ftparchive generate the hashes (and expire?) + std::string HostKnob = "APT::Acquire::" + ::URI(Desc.URI).Host + "::By-Hash"; + if(_config->FindB("APT::Acquire::By-Hash", false) == true || + _config->FindB(HostKnob, false) == true || + TransactionManager->MetaIndexParser->GetSupportsAcquireByHash()) { - // This might become fatal one day -// Status = StatAuthError; -// ErrorText = "Conflicting distribution; expected " -// + MetaIndexParser->GetExpectedDist() + " but got " -// + MetaIndexParser->GetDist(); -// return false; - if (!Transformed.empty()) + HashStringList const Hashes = GetExpectedHashes(); + if(Hashes.usable()) { - _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), - Desc.Description.c_str(), - Transformed.c_str(), - MetaIndexParser->GetDist().c_str()); + // FIXME: should we really use the best hash here? or a fixed one? + HashString const * const TargetHash = Hashes.find(""); + std::string const ByHash = "/by-hash/" + TargetHash->HashType() + "/" + TargetHash->HashValue(); + size_t const trailing_slash = Desc.URI.find_last_of("/"); + Desc.URI = Desc.URI.replace( + trailing_slash, + Desc.URI.substr(trailing_slash+1).size()+1, + ByHash); + } else { + _error->Warning( + "Fetching ByHash requested but can not find record for %s", + GetMetaKey().c_str()); } } - - return true; } /*}}}*/ -// pkgAcqMetaIndex::Failed - no Release file present /*{{{*/ -void pkgAcqMetaIndex::Failed(string Message, - pkgAcquire::MethodConfig * Cnf) +// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ +// --------------------------------------------------------------------- +/* The only header we use is the last-modified header. */ +string pkgAcqIndex::Custom600Headers() const { - pkgAcquire::Item::Failed(Message, Cnf); - Status = StatDone; - - _error->Warning(_("The repository '%s' does not have a Release file. " - "This is deprecated, please contact the owner of the " - "repository."), URIDesc.c_str()); + string Final = GetFinalFilename(); - // No Release file was present so fall - // back to queueing Packages files without verification - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true) - { - // Done, queue for rename on transaction finished - if (FileExists(DestFile)) - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); + string msg = "\nIndex-File: true"; + struct stat Buf; + if (stat(Final.c_str(),&Buf) == 0) + msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); - // queue without any kind of hashsum support - QueueIndexes(false); - } + if(Target->IsOptional()) + msg += "\nFail-Ignore: true"; + + return msg; } /*}}}*/ -void pkgAcqMetaIndex::Finished() /*{{{*/ +// AcqIndex::Failed - getting the indexfile failed /*{{{*/ +void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { - if(_config->FindB("Debug::Acquire::Transaction", false) == true) - std::clog << "Finished: " << DestFile <TransactionHasError() == false) - TransactionManager->CommitTransaction(); + Item::Failed(Message,Cnf); + + // authorisation matches will not be fixed by other compression types + if (Status != StatAuthError) + { + if (CompressionExtensions.empty() == false) + { + Init(Target->URI, Desc.Description, Desc.ShortDesc); + Status = StatIdle; + return; + } + } + + if(Target->IsOptional() && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) + Status = StatDone; + else + TransactionManager->AbortTransaction(); } /*}}}*/ -pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire *Owner, /*{{{*/ - string const &URI, string const &URIDesc, string const &ShortDesc, - string const &MetaIndexURI, string const &MetaIndexURIDesc, string const &MetaIndexShortDesc, - string const &MetaSigURI, string const &MetaSigURIDesc, string const &MetaSigShortDesc, - const vector* IndexTargets, - indexRecords* MetaIndexParser) : - pkgAcqMetaIndex(Owner, NULL, URI, URIDesc, ShortDesc, MetaSigURI, MetaSigURIDesc,MetaSigShortDesc, IndexTargets, MetaIndexParser), - MetaIndexURI(MetaIndexURI), MetaIndexURIDesc(MetaIndexURIDesc), MetaIndexShortDesc(MetaIndexShortDesc), - MetaSigURI(MetaSigURI), MetaSigURIDesc(MetaSigURIDesc), MetaSigShortDesc(MetaSigShortDesc) +// AcqIndex::ReverifyAfterIMS - Reverify index after an ims-hit /*{{{*/ +void pkgAcqIndex::ReverifyAfterIMS() { - // index targets + (worst case:) Release/Release.gpg - ExpectedAdditionalItems = IndexTargets->size() + 2; + // update destfile to *not* include the compression extension when doing + // a reverify (as its uncompressed on disk already) + DestFile = GetCompressedFileName(Target->URI, GetPartialFileNameFromURI(Target->URI), CurrentCompressionExtension); + + // copy FinalFile into partial/ so that we check the hash again + string FinalFile = GetFinalFilename(); + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Desc.URI = "copy:" + FinalFile; + QueueURI(Desc); } /*}}}*/ -pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ +// AcqIndex::ValidateFile - Validate the content of the downloaded file /*{{{*/ +bool pkgAcqIndex::ValidateFile(const std::string &FileName) { + // FIXME: this can go away once we only ever download stuff that + // has a valid hash and we never do GET based probing + // FIXME2: this also leaks debian-isms into the code and should go therefore + + /* Always validate the index file for correctness (all indexes must + * have a Package field) (LP: #346386) (Closes: #627642) + */ + FileFd fd(FileName, FileFd::ReadOnly, FileFd::Extension); + // Only test for correctness if the content of the file is not empty + // (empty is ok) + if (fd.Size() > 0) + { + pkgTagSection sec; + pkgTagFile tag(&fd); + + // all our current indexes have a field 'Package' in each section + if (_error->PendingError() == true || + tag.Step(sec) == false || + sec.Exists("Package") == false) + return false; + } + return true; } /*}}}*/ -// pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ -#if APT_PKG_ABI >= 413 -string pkgAcqMetaClearSig::Custom600Headers() const -#else -string pkgAcqMetaClearSig::Custom600Headers() -#endif +// AcqIndex::Done - Finished a fetch /*{{{*/ +// --------------------------------------------------------------------- +/* This goes through a number of states.. On the initial fetch the + method could possibly return an alternate filename which points + to the uncompressed version of the file. If this is so the file + is copied into the partial directory. In all other cases the file + is decompressed with a compressed uri. */ +void pkgAcqIndex::Done(string const &Message, + HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - string Header = pkgAcqMetaBase::Custom600Headers(); - Header += "\nFail-Ignore: true"; - return Header; + Item::Done(Message,Hashes,Cfg); + + switch(Stage) + { + case STAGE_DOWNLOAD: + StageDownloadDone(Message, Hashes, Cfg); + break; + case STAGE_DECOMPRESS_AND_VERIFY: + StageDecompressDone(Message, Hashes, Cfg); + break; + } } /*}}}*/ -// pkgAcqMetaClearSig::Done - We got a file /*{{{*/ -class APT_HIDDEN DummyItem : public pkgAcquire::Item +// AcqIndex::StageDownloadDone - Queue for decompress and verify /*{{{*/ +void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const &, + pkgAcquire::MethodConfig const * const) { - std::string URI; - public: - virtual std::string DescURI() {return URI;}; + Complete = true; - DummyItem(pkgAcquire *Owner, std::string const &URI) : pkgAcquire::Item(Owner), URI(URI) + // Handle the unzipd case + string FileName = LookupTag(Message,"Alt-Filename"); + if (FileName.empty() == false) { - Status = StatDone; - DestFile = GetFinalFileNameFromURI(URI); + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Local = true; + DestFile += ".decomp"; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); + SetActiveSubprocess("copy"); + return; } -}; -void pkgAcqMetaClearSig::Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf) -{ - Item::Done(Message, Size, Hashes, Cnf); - // if we expect a ClearTextSignature (InRelease), ensure that - // this is what we get and if not fail to queue a - // Release/Release.gpg, see #346386 - if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile)) + FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) { - pkgAcquire::Item::Failed(Message, Cnf); - RenameOnError(NotClearsigned); - TransactionManager->AbortTransaction(); - return; + Status = StatError; + ErrorText = "Method gave a blank filename"; } - if(AuthPass == false) + // Methods like e.g. "file:" will give us a (compressed) FileName that is + // not the "DestFile" we set, in this case we uncompress from the local file + if (FileName != DestFile) + Local = true; + else + EraseFileName = FileName; + + // we need to verify the file against the current Release file again + // on if-modfied-since hit to avoid a stale attack against us + if(StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) { - if(CheckDownloadDone(this, Message, Hashes) == true) - QueueForSignatureVerify(this, DestFile, DestFile); + // The files timestamp matches, reverify by copy into partial/ + EraseFileName = ""; + ReverifyAfterIMS(); return; } - else if(CheckAuthDone(Message) == true) + + // If we have compressed indexes enabled, queue for hash verification + if (_config->FindB("Acquire::GzipIndexes",false)) { - if (TransactionManager->IMSHit == false) - TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - else if (RealFileExists(GetFinalFilename()) == false) - { - // We got an InRelease file IMSHit, but we haven't one, which means - // we had a valid Release/Release.gpg combo stepping in, which we have - // to 'acquire' now to ensure list cleanup isn't removing them - new DummyItem(Owner, MetaIndexURI); - new DummyItem(Owner, MetaSigURI); - } + DestFile = GetPartialFileNameFromURI(Target->URI + '.' + CurrentCompressionExtension); + EraseFileName = ""; + Stage = STAGE_DECOMPRESS_AND_VERIFY; + Desc.URI = "copy:" + FileName; + QueueURI(Desc); + SetActiveSubprocess("copy"); + return; + } + + // get the binary name for your used compression type + string decompProg; + if(CurrentCompressionExtension == "uncompressed") + decompProg = "copy"; + else + decompProg = _config->Find(string("Acquire::CompressionTypes::").append(CurrentCompressionExtension),""); + if(decompProg.empty() == true) + { + _error->Error("Unsupported extension: %s", CurrentCompressionExtension.c_str()); + return; } + + // queue uri for the next stage + Stage = STAGE_DECOMPRESS_AND_VERIFY; + DestFile += ".decomp"; + Desc.URI = decompProg + ":" + FileName; + QueueURI(Desc); + SetActiveSubprocess(decompProg); } /*}}}*/ -void pkgAcqMetaClearSig::Failed(string Message,pkgAcquire::MethodConfig *Cnf) /*{{{*/ +// AcqIndex::StageDecompressDone - Final verification /*{{{*/ +void pkgAcqIndex::StageDecompressDone(string const &Message, + HashStringList const &, + pkgAcquire::MethodConfig const * const Cfg) { - Item::Failed(Message, Cnf); - - // we failed, we will not get additional items from this method - ExpectedAdditionalItems = 0; - - if (AuthPass == false) + if(!ValidateFile(DestFile)) { - // Queue the 'old' InRelease file for removal if we try Release.gpg - // as otherwise the file will stay around and gives a false-auth - // impression (CVE-2012-0214) - TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); - Status = StatDone; - - new pkgAcqMetaIndex(Owner, TransactionManager, - MetaIndexURI, MetaIndexURIDesc, MetaIndexShortDesc, - MetaSigURI, MetaSigURIDesc, MetaSigShortDesc, - IndexTargets, MetaIndexParser); + RenameOnError(InvalidFormat); + Failed(Message, Cfg); + return; } - else - { - if(CheckStopAuthentication(this, Message)) - return; - _error->Warning(_("The data from '%s' is not signed. Packages " - "from that repository can not be authenticated."), - URIDesc.c_str()); - - // No Release file was present, or verification failed, so fall - // back to queueing Packages files without verification - // only allow going further if the users explicitely wants it - if(AllowInsecureRepositories(MetaIndexParser, TransactionManager, this) == true) - { - Status = StatDone; + // Done, queue for rename on transaction finished + TransactionManager->TransactionStageCopy(this, DestFile, GetFinalFilename()); - /* Always move the meta index, even if gpgv failed. This ensures - * that PackageFile objects are correctly filled in */ - if (FileExists(DestFile)) - { - string FinalFile = GetFinalFilename(); - /* InRelease files become Release files, otherwise - * they would be considered as trusted later on */ - RealURI = RealURI.replace(RealURI.rfind("InRelease"), 9, - "Release"); - FinalFile = FinalFile.replace(FinalFile.rfind("InRelease"), 9, - "Release"); - - // Done, queue for rename on transaction finished - TransactionManager->TransactionStageCopy(this, DestFile, FinalFile); - } - QueueIndexes(false); - } - } + return; } /*}}}*/ + + // AcqArchive::AcqArchive - Constructor /*{{{*/ // --------------------------------------------------------------------- /* This just sets up the initial fetch environment and queues the first possibilitiy */ -pkgAcqArchive::pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, - pkgRecords *Recs,pkgCache::VerIterator const &Version, +pkgAcqArchive::pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources, + pkgRecords * const Recs,pkgCache::VerIterator const &Version, string &StoreFilename) : - Item(Owner, HashStringList()), Version(Version), Sources(Sources), Recs(Recs), - StoreFilename(StoreFilename), Vf(Version.FileList()), + Item(Owner), LocalSource(false), Version(Version), Sources(Sources), Recs(Recs), + StoreFilename(StoreFilename), Vf(Version.FileList()), Trusted(false) { Retries = _config->FindI("Acquire::Retries",0); @@ -2573,15 +2577,17 @@ bool pkgAcqArchive::QueueNext() { for (; Vf.end() == false; ++Vf) { + pkgCache::PkgFileIterator const PkgF = Vf.File(); // Ignore not source sources - if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0) + if ((PkgF->Flags & pkgCache::Flag::NotSource) != 0) continue; // Try to cross match against the source list pkgIndexFile *Index; - if (Sources->FindIndex(Vf.File(),Index) == false) + if (Sources->FindIndex(PkgF, Index) == false) continue; - + LocalSource = (PkgF->Flags & pkgCache::Flag::LocalSource) == pkgCache::Flag::LocalSource; + // only try to get a trusted package from another source if that source // is also trusted if(Trusted && !Index->IsTrusted()) @@ -2681,25 +2687,10 @@ bool pkgAcqArchive::QueueNext() // AcqArchive::Done - Finished fetching /*{{{*/ // --------------------------------------------------------------------- /* */ -void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cfg) +void pkgAcqArchive::Done(string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cfg) { - Item::Done(Message, Size, CalcHashes, Cfg); - - // Check the size - if (Size != Version->Size) - { - RenameOnError(SizeMismatch); - return; - } - - // FIXME: could this empty() check impose *any* sort of security issue? - if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); - return; - } + Item::Done(Message, Hashes, Cfg); // Grab the output filename string FileName = LookupTag(Message,"Filename"); @@ -2726,23 +2717,17 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size, HashStringList Complete = true; } /*}}}*/ -// Acquire::Item::GetFinalFilename - Return the full final file path /*{{{*/ -std::string pkgAcqArchive::GetFinalFilename() const -{ - return _config->FindDir("Dir::Cache::Archives") + flNotDir(StoreFilename); -} - /*}}}*/ // AcqArchive::Failed - Failure handler /*{{{*/ // --------------------------------------------------------------------- /* Here we try other sources */ -void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcqArchive::Failed(string const &Message,pkgAcquire::MethodConfig const * const Cnf) { Item::Failed(Message,Cnf); - /* We don't really want to retry on failed media swaps, this prevents + /* We don't really want to retry on failed media swaps, this prevents that. An interesting observation is that permanent failures are not recorded. */ - if (Cnf->Removable == true && + if (Cnf->Removable == true && StringToBool(LookupTag(Message,"Transient-Failure"),false) == true) { // Vf = Version.FileList(); @@ -2770,21 +2755,12 @@ void pkgAcqArchive::Failed(string Message,pkgAcquire::MethodConfig *Cnf) } } /*}}}*/ -// AcqArchive::IsTrusted - Determine whether this archive comes from a trusted source /*{{{*/ -// --------------------------------------------------------------------- -#if APT_PKG_ABI >= 413 -APT_PURE bool pkgAcqArchive::IsTrusted() const -#else -APT_PURE bool pkgAcqArchive::IsTrusted() -#endif +APT_PURE bool pkgAcqArchive::IsTrusted() const /*{{{*/ { return Trusted; } /*}}}*/ -// AcqArchive::Finished - Fetching has finished, tidy up /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcqArchive::Finished() +void pkgAcqArchive::Finished() /*{{{*/ { if (Status == pkgAcquire::Item::StatDone && Complete == true) @@ -2792,17 +2768,26 @@ void pkgAcqArchive::Finished() StoreFilename = string(); } /*}}}*/ +std::string pkgAcqArchive::DescURI() const /*{{{*/ +{ + return Desc.URI; +} + /*}}}*/ +std::string pkgAcqArchive::ShortDesc() const /*{{{*/ +{ + return Desc.ShortDesc; +} + /*}}}*/ + // AcqFile::pkgAcqFile - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* The file is added to the queue */ -pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashes, - unsigned long long Size,string Dsc,string ShortDesc, +pkgAcqFile::pkgAcqFile(pkgAcquire * const Owner,string const &URI, HashStringList const &Hashes, + unsigned long long const Size,string const &Dsc,string const &ShortDesc, const string &DestDir, const string &DestFilename, - bool IsIndexFile) : - Item(Owner, Hashes), IsIndexFile(IsIndexFile) + bool const IsIndexFile) : + Item(Owner), IsIndexFile(IsIndexFile), ExpectedHashes(Hashes) { Retries = _config->FindI("Acquire::Retries",0); - + if(!DestFilename.empty()) DestFile = DestFilename; else if(!DestDir.empty()) @@ -2817,7 +2802,7 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashe // Set the short description to the archive component Desc.ShortDesc = ShortDesc; - + // Get the transfer sizes FileSize = Size; struct stat Buf; @@ -2834,21 +2819,11 @@ pkgAcqFile::pkgAcqFile(pkgAcquire *Owner,string URI, HashStringList const &Hashe } /*}}}*/ // AcqFile::Done - Item downloaded OK /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cnf) +void pkgAcqFile::Done(string const &Message,HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) { - Item::Done(Message,Size,CalcHashes,Cnf); + Item::Done(Message,CalcHashes,Cnf); - // Check the hash - if(ExpectedHashes.usable() && ExpectedHashes != CalcHashes) - { - RenameOnError(HashSumMismatch); - printHashSumComparision(DestFile, ExpectedHashes, CalcHashes); - return; - } - string FileName = LookupTag(Message,"Filename"); if (FileName.empty() == true) { @@ -2858,11 +2833,11 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons } Complete = true; - + // The files timestamp matches if (StringToBool(LookupTag(Message,"IMS-Hit"),false) == true) return; - + // We have to copy it into place if (FileName != DestFile) { @@ -2874,7 +2849,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons QueueURI(Desc); return; } - + // Erase the file if it is a symlink so we can overwrite it struct stat St; if (lstat(DestFile.c_str(),&St) == 0) @@ -2882,7 +2857,7 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons if (S_ISLNK(St.st_mode) != 0) unlink(DestFile.c_str()); } - + // Symlink the file if (symlink(FileName.c_str(),DestFile.c_str()) != 0) { @@ -2894,14 +2869,14 @@ void pkgAcqFile::Done(string Message,unsigned long long Size,HashStringList cons ErrorText = msg.str(); Status = StatError; Complete = false; - } + } } } /*}}}*/ // AcqFile::Failed - Failure handler /*{{{*/ // --------------------------------------------------------------------- /* Here we try other sources */ -void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf) +void pkgAcqFile::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf) { Item::Failed(Message,Cnf); @@ -2918,14 +2893,7 @@ void pkgAcqFile::Failed(string Message,pkgAcquire::MethodConfig *Cnf) } /*}}}*/ -// AcqIndex::Custom600Headers - Insert custom request headers /*{{{*/ -// --------------------------------------------------------------------- -/* The only header we use is the last-modified header. */ -#if APT_PKG_ABI >= 413 -string pkgAcqFile::Custom600Headers() const -#else -string pkgAcqFile::Custom600Headers() -#endif +string pkgAcqFile::Custom600Headers() const /*{{{*/ { if (IsIndexFile) return "\nIndex-File: true"; diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 07c86f31b..97d5ea1dd 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -6,15 +6,15 @@ Acquire Item - Item to acquire When an item is instantiated it will add it self to the local list in - the Owner Acquire class. Derived classes will then call QueueURI to - register all the URI's they wish to fetch at the initial moment. - + the Owner Acquire class. Derived classes will then call QueueURI to + register all the URI's they wish to fetch at the initial moment. + Three item classes are provided to provide functionality for downloading of Index, Translation and Packages files. - + A Archive class is provided for downloading .deb files. It does Hash checking and source location as well as a retry algorithm. - + ##################################################################### */ /*}}}*/ #ifndef PKGLIB_ACQUIRE_ITEM_H @@ -49,7 +49,48 @@ class pkgSourceList; class IndexTarget; class pkgAcqMetaBase; -/** \brief Represents the process by which a pkgAcquire object should {{{ +class APT_HIDDEN IndexTarget /*{{{*/ +/** \brief Information about an index file. */ +{ + public: + /** \brief A URI from which the index file can be downloaded. */ + std::string const URI; + + /** \brief A description of the index file. */ + std::string const Description; + + /** \brief A shorter description of the index file. */ + std::string const ShortDesc; + + /** \brief The key by which this index file should be + * looked up within the meta signature file. + */ + std::string const MetaKey; + + virtual bool IsOptional() const { + return false; + } + + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey) {} +}; + /*}}}*/ +class APT_HIDDEN OptionalIndexTarget : public IndexTarget /*{{{*/ +/** \brief Information about an optional index file. */ +{ + public: + virtual bool IsOptional() const { + return true; + } + + OptionalIndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI) : + IndexTarget(MetaKey, ShortDesc, LongDesc, URI) {} +}; + /*}}}*/ +class pkgAcquire::Item : public WeakPointable /*{{{*/ +/** \brief Represents the process by which a pkgAcquire object should * retrieve a file or a collection of files. * * By convention, Item subclasses should insert themselves into the @@ -61,46 +102,7 @@ class pkgAcqMetaBase; * * \see pkgAcquire */ -class pkgAcquire::Item : public WeakPointable -{ - friend class pkgAcqMetaBase; - - void *d; - - protected: - - /** \brief The acquire object with which this item is associated. */ - pkgAcquire *Owner; - - /** \brief Insert this item into its owner's queue. - * - * The method is designed to check if the request would end - * in an IMSHit and if it determines that it would, it isn't - * queueing the Item and instead sets it to completion instantly. - * - * \param Item Metadata about this item (its URI and - * description). - * \return true if the item was inserted, false if IMSHit was detected - */ - virtual bool QueueURI(ItemDesc &Item); - - /** \brief Remove this item from its owner's queue. */ - void Dequeue(); - - /** \brief Rename a file without modifying its timestamp. - * - * Many item methods call this as their final action. - * - * \param From The file to be renamed. - * - * \param To The new name of \a From. If \a To exists it will be - * overwritten. - */ - bool Rename(std::string From,std::string To); - - /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; - +{ public: /** \brief The current status of this item. */ @@ -125,7 +127,7 @@ class pkgAcquire::Item : public WeakPointable */ StatAuthError, - /** \brief The item was could not be downloaded because of + /** \brief The item was could not be downloaded because of * a transient network error (e.g. network down) */ StatTransientNetworkError, @@ -153,11 +155,11 @@ class pkgAcquire::Item : public WeakPointable std::string ActiveSubprocess; /** \brief A client-supplied unique identifier. - * + * * This field is initalized to 0; it is meant to be filled in by * clients that wish to use it to uniquely identify items. * - * \todo it's unused in apt itself + * APT progress reporting will store an ID there as shown in "Get:42 …" */ unsigned long ID; @@ -173,6 +175,7 @@ class pkgAcquire::Item : public WeakPointable * download progress indicator's overall statistics. */ bool Local; + std::string UsedMirror; /** \brief The number of fetch queues into which this item has been @@ -185,9 +188,6 @@ class pkgAcquire::Item : public WeakPointable */ unsigned int QueueCounter; - /** \brief TransactionManager */ - pkgAcqMetaBase *TransactionManager; - /** \brief The number of additional fetch items that are expected * once this item is done. * @@ -197,15 +197,12 @@ class pkgAcquire::Item : public WeakPointable * progress. */ unsigned int ExpectedAdditionalItems; - + /** \brief The name of the file into which the retrieved object * will be written. */ std::string DestFile; - /** \brief storge name until a transaction is finished */ - std::string PartialFile; - /** \brief Invoked by the acquire worker when the object couldn't * be fetched. * @@ -219,7 +216,7 @@ class pkgAcquire::Item : public WeakPointable * * \sa pkgAcqMethod */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); /** \brief Invoked by the acquire worker when the object was * fetched successfully. @@ -234,25 +231,24 @@ class pkgAcquire::Item : public WeakPointable * * \param Message Data from the acquire method. Use LookupTag() * to parse it. - * \param Size The size of the object that was fetched. * \param Hashes The HashSums of the object that was fetched. * \param Cnf The method via which the object was fetched. * * \sa pkgAcqMethod */ - virtual void Done(std::string Message, unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \brief Invoked when the worker starts to fetch this object. * * \param Message RFC822-formatted data from the worker process. * Use LookupTag() to parse it. * - * \param Size The size of the object being fetched. + * \param Hashes The expected hashes of the object being fetched. * * \sa pkgAcqMethod */ - virtual void Start(std::string Message,unsigned long long Size); + virtual void Start(std::string const &Message, unsigned long long const Size); /** \brief Custom headers to be sent to the fetch process. * @@ -262,61 +258,55 @@ class pkgAcquire::Item : public WeakPointable * line, so they should (if nonempty) have a leading newline and * no trailing newline. */ -#if APT_PKG_ABI >= 413 - virtual std::string Custom600Headers() const {return std::string();}; -#else - virtual std::string Custom600Headers() {return std::string();}; -#endif + virtual std::string Custom600Headers() const; /** \brief A "descriptive" URI-like string. * * \return a URI that should be used to describe what is being fetched. */ - virtual std::string DescURI() = 0; + virtual std::string DescURI() const = 0; /** \brief Short item description. * * \return a brief description of the object being fetched. */ - virtual std::string ShortDesc() {return DescURI();} + virtual std::string ShortDesc() const; /** \brief Invoked by the worker when the download is completely done. */ - virtual void Finished() {}; - - /** \brief HashSums + virtual void Finished(); + + /** \return HashSums the DestFile is supposed to have in this stage */ + virtual HashStringList GetExpectedHashes() const = 0; + /** \return the 'best' hash for display proposes like --print-uris */ + std::string HashSum() const; + + /** \return if having no hashes is a hard failure or not * - * \return the HashSums of this object, if applicable; otherwise, an - * empty list. + * Idealy this is always \b true for every subclass, but thanks to + * historical grow we don't have hashes for all files in all cases + * in all steps, so it is slightly more complicated than it should be. */ - HashStringList HashSums() const {return ExpectedHashes;}; - std::string HashSum() const {HashStringList const hashes = HashSums(); HashString const * const hs = hashes.find(NULL); return hs != NULL ? hs->toStr() : ""; }; + virtual bool HashesRequired() const { return true; } /** \return the acquire process with which this item is associated. */ - pkgAcquire *GetOwner() const {return Owner;}; -#if APT_PKG_ABI < 413 - pkgAcquire *GetOwner() {return Owner;}; -#endif + pkgAcquire *GetOwner() const; /** \return \b true if this object is being fetched from a trusted source. */ -#if APT_PKG_ABI >= 413 - virtual bool IsTrusted() const {return false;}; -#else - virtual bool IsTrusted() {return false;}; -#endif - + virtual bool IsTrusted() const; + /** \brief Report mirror problem - * + * * This allows reporting mirror failures back to a centralized * server. The apt-report-mirror-failure script is called for this - * + * * \param FailCode A short failure string that is send */ - void ReportMirrorFailure(std::string FailCode); + void ReportMirrorFailure(std::string const &FailCode); /** \brief Set the name of the current active subprocess * * See also #ActiveSubprocess */ - void SetActiveSubprocess(const std::string &subprocess); + void SetActiveSubprocess(std::string const &subprocess); /** \brief Initialize an item. * @@ -325,11 +315,8 @@ class pkgAcquire::Item : public WeakPointable * manually invoke QueueURI() to do so). * * \param Owner The new owner of this item. - * \param ExpectedHashes of the file represented by this item */ - Item(pkgAcquire *Owner, - HashStringList const &ExpectedHashes=HashStringList(), - pkgAcqMetaBase *TransactionManager=NULL); + Item(pkgAcquire * const Owner); /** \brief Remove this item from its owner's queue by invoking * pkgAcquire::Remove. @@ -337,6 +324,11 @@ class pkgAcquire::Item : public WeakPointable virtual ~Item(); protected: + /** \brief The acquire object with which this item is associated. */ + pkgAcquire * const Owner; + + /** \brief The item that is currently being downloaded. */ + pkgAcquire::ItemDesc Desc; enum RenameOnErrorState { HashSumMismatch, @@ -354,63 +346,99 @@ class pkgAcquire::Item : public WeakPointable */ bool RenameOnError(RenameOnErrorState const state); + /** \brief Insert this item into its owner's queue. + * + * The method is designed to check if the request would end + * in an IMSHit and if it determines that it would, it isn't + * queueing the Item and instead sets it to completion instantly. + * + * \param Item Metadata about this item (its URI and + * description). + * \return true if the item was inserted, false if IMSHit was detected + */ + virtual bool QueueURI(ItemDesc &Item); + + /** \brief Remove this item from its owner's queue. */ + void Dequeue(); + + /** \brief Rename a file without modifying its timestamp. + * + * Many item methods call this as their final action. + * + * \param From The file to be renamed. + * + * \param To The new name of \a From. If \a To exists it will be + * overwritten. If \a From and \a To are equal nothing happens. + */ + bool Rename(std::string const &From, std::string const &To); + + /** \brief Get the full pathname of the final file for the current URI */ + virtual std::string GetFinalFilename() const; + + private: + void *d; + + friend class pkgAcqMetaBase; +}; + /*}}}*/ +class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ +/** \brief baseclass for the indexes files to manage them all together */ +{ + protected: + IndexTarget const * const Target; + HashStringList GetExpectedHashesFor(std::string const MetaKey) const; + + bool QueueURI(pkgAcquire::ItemDesc &Item); + + public: + /** \brief storge name until a transaction is finished */ + std::string PartialFile; + + /** \brief TransactionManager */ + pkgAcqMetaBase * const TransactionManager; + enum TransactionStates { TransactionCommit, TransactionAbort, }; virtual bool TransactionState(TransactionStates const state); - /** \brief The HashSums of the item is supposed to have than done */ - HashStringList ExpectedHashes; + virtual std::string DescURI() const { return Target->URI; } + virtual HashStringList GetExpectedHashes() const; + virtual std::string GetMetaKey() const; + virtual bool HashesRequired() const; - /** \brief The item that is currently being downloaded. */ - pkgAcquire::ItemDesc Desc; -}; - /*}}}*/ -/** \brief Information about an index patch (aka diff). */ /*{{{*/ -struct APT_HIDDEN DiffInfo { - /** The filename of the diff. */ - std::string file; - /** The hashes of the diff */ - HashStringList result_hashes; - - /** The hashes of the file after the diff is applied */ - HashStringList patch_hashes; + pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target); + virtual ~pkgAcqTransactionItem(); - /** The size of the file after the diff is applied */ - unsigned long long result_size; - - /** The size of the diff itself */ - unsigned long long patch_size; + friend class pkgAcqMetaBase; }; /*}}}*/ -class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ +class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ +/** \brief the manager of a transaction */ { void *d; protected: - std::vector Transaction; + std::vector Transaction; + IndexTarget const DataTarget; + public: /** \brief A package-system-specific parser for the meta-index file. */ indexRecords *MetaIndexParser; indexRecords *LastMetaIndexParser; + protected: /** \brief The index files which should be looked up in the meta-index * and then downloaded. */ - const std::vector* IndexTargets; + const std::vector* const IndexTargets; /** \brief If \b true, the index's signature is currently being verified. */ bool AuthPass; - /** \brief The URI of the signature file. Unlike Desc.URI, this is - * never modified; it is used to determine the file that is being - * downloaded. - */ - std::string RealURI; - /** \brief Starts downloading the individual index files. * * \param verify If \b true, only indices whose expected hashsum @@ -419,7 +447,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * #StatAuthError if there is a mismatch). If verify is \b false, * no hashsum checking will be performed. */ - void QueueIndexes(bool verify); + void QueueIndexes(bool const verify); /** \brief Called when a file is finished being retrieved. * @@ -430,16 +458,12 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckDownloadDone(pkgAcquire::Item * const I, const std::string &Message, HashStringList const &Hashes) const; + bool CheckDownloadDone(pkgAcqTransactionItem * const I, const std::string &Message, HashStringList const &Hashes) const; /** \brief Queue the downloaded Signature for verification */ - void QueueForSignatureVerify(pkgAcquire::Item * const I, std::string const &File, std::string const &Signature); + void QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature); -#if APT_PKG_ABI >= 413 virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif /** \brief Called when authentication succeeded. * @@ -450,7 +474,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * \param Message The message block received from the fetch * subprocess. */ - bool CheckAuthDone(std::string Message); + bool CheckAuthDone(std::string const &Message); /** Check if the current item should fail at this point */ bool CheckStopAuthentication(pkgAcquire::Item * const I, const std::string &Message); @@ -460,7 +484,7 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ * * \return \b true if no fatal errors were encountered. */ - bool VerifyVendor(std::string Message); + bool VerifyVendor(std::string const &Message); virtual bool TransactionState(TransactionStates const state); @@ -468,33 +492,32 @@ class pkgAcqMetaBase : public pkgAcquire::Item /*{{{*/ // This refers more to the Transaction-Manager than the actual file bool IMSHit; - virtual std::string DescURI() {return RealURI; }; virtual bool QueueURI(pkgAcquire::ItemDesc &Item); + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; // transaction code - void Add(Item *I); + void Add(pkgAcqTransactionItem * const I); void AbortTransaction(); - bool TransactionHasError() APT_PURE; + bool TransactionHasError() const; void CommitTransaction(); /** \brief Stage (queue) a copy action when the transaction is committed */ - void TransactionStageCopy(Item *I, - const std::string &From, + void TransactionStageCopy(pkgAcqTransactionItem * const I, + const std::string &From, const std::string &To); /** \brief Stage (queue) a removal action when the transaction is committed */ - void TransactionStageRemoval(Item *I, const std::string &FinalFile); + void TransactionStageRemoval(pkgAcqTransactionItem * const I, const std::string &FinalFile); /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; - pkgAcqMetaBase(pkgAcquire *Owner, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser, - std::string const &RealURI, - HashStringList const &ExpectedHashes=HashStringList(), - pkgAcqMetaBase *TransactionManager=NULL); + pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + std::vector const * const IndexTargets, + IndexTarget const &DataTarget, + indexRecords* const MetaIndexParser); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -512,36 +535,24 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase void *d; protected: - std::string URIDesc; - std::string ShortDesc; - - /** \brief The URI of the meta-index file for the detached signature */ - std::string MetaIndexSigURI; - - /** \brief A "URI-style" description of the meta-index file */ - std::string MetaIndexSigURIDesc; - - /** \brief A brief description of the meta-index file */ - std::string MetaIndexSigShortDesc; + IndexTarget const DetachedSigTarget; /** \brief delayed constructor */ - void Init(std::string URIDesc, std::string ShortDesc); - + void Init(std::string const &URIDesc, std::string const &ShortDesc); + public: + virtual std::string DescURI() const; // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); virtual void Finished(); /** \brief Create a new pkgAcqMetaIndex. */ - pkgAcqMetaIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - std::string URI,std::string URIDesc, std::string ShortDesc, - std::string MetaIndexSigURI, std::string MetaIndexSigURIDesc, std::string MetaIndexSigShortDesc, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, + const std::vector* const IndexTargets, indexRecords * const MetaIndexParser); friend class pkgAcqMetaSig; }; @@ -554,7 +565,7 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase * * \sa pkgAcqMetaIndex */ -class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item +class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem { void *d; @@ -565,29 +576,20 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcquire::Item protected: - /** \brief Long URI description used in the acquire system */ - std::string URIDesc; - - /** \brief URI used to get the file */ - std::string RealURI; - /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; public: - virtual std::string DescURI() {return RealURI;}; + virtual bool HashesRequired() const { return false; } // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \brief Create a new pkgAcqMetaSig. */ - pkgAcqMetaSig(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - std::string const &URI,std::string const &URIDesc, - std::string const &ShortDesc, pkgAcqMetaIndex * const MetaIndex); + pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const * const Target, + pkgAcqMetaIndex * const MetaIndex); virtual ~pkgAcqMetaSig(); }; /*}}}*/ @@ -596,78 +598,37 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex { void *d; - /** \brief The URI of the meta-index file for the detached signature */ - std::string MetaIndexURI; - - /** \brief A "URI-style" description of the meta-index file */ - std::string MetaIndexURIDesc; - - /** \brief A brief description of the meta-index file */ - std::string MetaIndexShortDesc; - - /** \brief The URI of the detached meta-signature file if the clearsigned one failed. */ - std::string MetaSigURI; - - /** \brief A "URI-style" description of the meta-signature file */ - std::string MetaSigURIDesc; - - /** \brief A brief description of the meta-signature file */ - std::string MetaSigShortDesc; + IndexTarget const ClearsignedTarget; + IndexTarget const DetachedDataTarget; + IndexTarget const DetachedSigTarget; public: - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); -#if APT_PKG_ABI >= 413 + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); /** \brief Create a new pkgAcqMetaClearSig. */ - pkgAcqMetaClearSig(pkgAcquire *Owner, - std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc, - std::string const &MetaIndexURI, std::string const &MetaIndexURIDesc, std::string const &MetaIndexShortDesc, - std::string const &MetaSigURI, std::string const &MetaSigURIDesc, std::string const &MetaSigShortDesc, - const std::vector* IndexTargets, - indexRecords* MetaIndexParser); + pkgAcqMetaClearSig(pkgAcquire * const Owner, + IndexTarget const &ClearsignedTarget, + IndexTarget const &DetachedDataTarget, + IndexTarget const &DetachedSigTarget, + std::vector const * const IndexTargets, + indexRecords * const MetaIndexParser); virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ -/** \brief Common base class for all classes that deal with fetching {{{ - indexes - */ -class pkgAcqBaseIndex : public pkgAcquire::Item +/** \brief Common base class for all classes that deal with fetching indexes {{{*/ +class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem { void *d; - protected: - /** \brief Pointer to the IndexTarget data - */ - const struct IndexTarget * Target; - - /** \brief Pointer to the indexRecords parser */ - indexRecords *MetaIndexParser; - - /** \brief The MetaIndex Key */ - std::string MetaKey; - - /** \brief The URI of the index file to recreate at our end (either - * by downloading it or by applying partial patches). - */ - std::string RealURI; - - bool VerifyHashByMetaKey(HashStringList const &Hashes); - + public: /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; - pkgAcqBaseIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser); + pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -705,15 +666,12 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex virtual bool TransactionState(TransactionStates const state); public: // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; -#if APT_PKG_ABI >= 413 + virtual void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Target->URI + "Index";}; virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif + virtual std::string GetMetaKey() const; /** \brief Parse the Index file for a set of Packages diffs. * @@ -725,7 +683,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * \return \b true if the Index file was successfully parsed, \b * false otherwise. */ - bool ParseDiffIndex(std::string IndexDiffFile); + bool ParseDiffIndex(std::string const &IndexDiffFile); /** \brief Create a new pkgAcqDiffIndex. * @@ -736,18 +694,30 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * \param URIDesc A long description of the list file to download. * * \param ShortDesc A short description of the list file to download. - * - * \param ExpectedHashes The list file's hashsums which are expected. */ - pkgAcqDiffIndex(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHashes, - indexRecords *MetaIndexParser); + pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); private: APT_HIDDEN void QueueOnIMSHit() const; }; /*}}}*/ +struct APT_HIDDEN DiffInfo { /*{{{*/ + /** The filename of the diff. */ + std::string file; + + /** The hashes of the diff */ + HashStringList result_hashes; + + /** The hashes of the file after the diff is applied */ + HashStringList patch_hashes; + + /** The size of the file after the diff is applied */ + unsigned long long result_size; + + /** The size of the diff itself */ + unsigned long long patch_size; +}; + /*}}}*/ /** \brief An item that is responsible for fetching client-merge patches {{{ * that need to be applied to a given package index file. * @@ -801,10 +771,12 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "Index";}; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Target->URI + "Index";}; + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create an index merge-diff item. * @@ -817,22 +789,15 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * * \param ShortDesc A brief description of this item. * - * \param ExpectedHashes The expected md5sum of the completely - * reconstructed package index file; the index file will be tested - * against this value when it is entirely reconstructed. - * * \param patch contains infos about the patch this item is supposed * to download which were read from the index * * \param allPatches contains all related items so that each item can * check if it was the last one to complete the download step */ - pkgAcqIndexMergeDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser, - DiffInfo const &patch, + pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + DiffInfo const &patch, std::vector const * const allPatches); }; /*}}}*/ @@ -875,7 +840,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * \param allDone If \b true, the file was entirely reconstructed, * and its md5sum is verified. */ - APT_HIDDEN void Finish(bool allDone=false); + APT_HIDDEN void Finish(bool const allDone=false); protected: @@ -905,26 +870,25 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex /** \brief The diff is currently being fetched. */ StateFetchDiff, - - /** \brief The diff is currently being uncompressed. */ - StateUnzipDiff, // FIXME: No longer used /** \brief The diff is currently being applied. */ StateApplyDiff } State; public: - + /** \brief Called when the patch file failed to be downloaded. * * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return RealURI + "IndexDiffs";}; + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Target->URI + "IndexDiffs";}; + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create an index diff item. * @@ -940,20 +904,13 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * * \param ShortDesc A brief description of this item. * - * \param ExpectedHashes The expected hashsums of the completely - * reconstructed package index file; the index file will be tested - * against this value when it is entirely reconstructed. - * * \param diffs The remaining diffs from the index of diffs. They * should be ordered so that each diff appears before any diff * that depends on it. */ - pkgAcqIndexDiffs(pkgAcquire *Owner, - pkgAcqMetaBase *TransactionManager, - struct IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser, - std::vector diffs=std::vector()); + pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target, + std::vector const &diffs=std::vector()); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching an index {{{ @@ -981,16 +938,16 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex AllStages Stage; /** \brief Handle what needs to be done when the download is done */ - void StageDownloadDone(std::string Message, + void StageDownloadDone(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg); + pkgAcquire::MethodConfig const * const Cfg); /** \brief Handle what needs to be done when the decompression/copy is * done */ - void StageDecompressDone(std::string Message, + void StageDecompressDone(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cfg); + pkgAcquire::MethodConfig const * const Cfg); /** \brief If \b set, this partially downloaded file will be * removed when the download completes. @@ -1006,7 +963,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex std::string CurrentCompressionExtension; /** \brief Do the changes needed to fetch via AptByHash (if needed) */ - void InitByHashIfNeeded(const std::string MetaKey); + void InitByHashIfNeeded(); /** \brief Auto select the right compression to use */ void AutoSelectCompression(); @@ -1015,7 +972,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex void ReverifyAfterIMS(); /** \brief Validate the downloaded index file */ - bool ValidateFile(const std::string &FileName); + bool ValidateFile(std::string const &FileName); /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; @@ -1024,82 +981,20 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex public: // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, - HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); -#if APT_PKG_ABI >= 413 + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif - virtual std::string DescURI() {return Desc.URI;}; + virtual std::string DescURI() const {return Desc.URI;}; + virtual std::string GetMetaKey() const; + + pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + IndexTarget const * const Target); - /** \brief Create a pkgAcqIndex. - * - * \param Owner The pkgAcquire object with which this item is - * associated. - * - * \param URI The URI of the index file that is to be downloaded. - * - * \param URIDesc A "URI-style" description of this index file. - * - * \param ShortDesc A brief description of this index file. - * - * \param ExpectedHashes The expected hashsum of this index file. - * - * \param compressExt The compression-related extension with which - * this index file should be downloaded, or "" to autodetect - * Compression types can be set with config Acquire::CompressionTypes, - * default is ".lzma" or ".bz2" (if the needed binaries are present) - * fallback is ".gz" or none. - */ - pkgAcqIndex(pkgAcquire *Owner,std::string URI,std::string URIDesc, - std::string ShortDesc, HashStringList const &ExpectedHashes); - pkgAcqIndex(pkgAcquire *Owner, pkgAcqMetaBase *TransactionManager, - IndexTarget const * const Target, - HashStringList const &ExpectedHash, - indexRecords *MetaIndexParser); - void Init(std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc); }; /*}}}*/ -/** \brief Information about an index file. */ /*{{{*/ -class APT_HIDDEN IndexTarget -{ - void *d; - - public: - /** \brief A URI from which the index file can be downloaded. */ - std::string URI; - - /** \brief A description of the index file. */ - std::string Description; - - /** \brief A shorter description of the index file. */ - std::string ShortDesc; - - /** \brief The key by which this index file should be - * looked up within the meta signature file. - */ - std::string MetaKey; - - virtual bool IsOptional() const { - return false; - } -}; - /*}}}*/ -/** \brief Information about an optional index file. */ /*{{{*/ -class APT_HIDDEN OptionalIndexTarget : public IndexTarget -{ - void *d; - - virtual bool IsOptional() const { - return true; - } -}; - /*}}}*/ /** \brief An item that is responsible for fetching a package file. {{{ * * If the package file already exists in the cache, nothing will be @@ -1109,6 +1004,9 @@ class pkgAcqArchive : public pkgAcquire::Item { void *d; + bool LocalSource; + HashStringList ExpectedHashes; + protected: /** \brief The package version being fetched. */ pkgCache::VerIterator Version; @@ -1141,7 +1039,7 @@ class pkgAcqArchive : public pkgAcquire::Item /** \brief \b true if this version file is being downloaded from a * trusted source. */ - bool Trusted; + bool Trusted; /** \brief Queue up the next available file for this version. */ bool QueueNext(); @@ -1151,17 +1049,15 @@ class pkgAcqArchive : public pkgAcquire::Item public: - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &Hashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; - virtual std::string ShortDesc() {return Desc.ShortDesc;}; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &Hashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const; + virtual std::string ShortDesc() const; virtual void Finished(); -#if APT_PKG_ABI >= 413 virtual bool IsTrusted() const; -#else - virtual bool IsTrusted(); -#endif + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; /** \brief Create a new pkgAcqArchive. * @@ -1181,8 +1077,8 @@ class pkgAcqArchive : public pkgAcquire::Item * basename in the constructor, and filled in with a fully * qualified filename once the download finishes. */ - pkgAcqArchive(pkgAcquire *Owner,pkgSourceList *Sources, - pkgRecords *Recs,pkgCache::VerIterator const &Version, + pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources, + pkgRecords * const Recs,pkgCache::VerIterator const &Version, std::string &StoreFilename); }; /*}}}*/ @@ -1200,22 +1096,21 @@ class pkgAcqFile : public pkgAcquire::Item * Acquire::Retries. */ unsigned int Retries; - + /** \brief Should this file be considered a index file */ bool IsIndexFile; + HashStringList const ExpectedHashes; public: - + virtual HashStringList GetExpectedHashes() const; + virtual bool HashesRequired() const; + // Specialized action members - virtual void Failed(std::string Message,pkgAcquire::MethodConfig *Cnf); - virtual void Done(std::string Message,unsigned long long Size, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig *Cnf); - virtual std::string DescURI() {return Desc.URI;}; -#if APT_PKG_ABI >= 413 + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Desc.URI;}; virtual std::string Custom600Headers() const; -#else - virtual std::string Custom600Headers(); -#endif /** \brief Create a new pkgAcqFile object. * @@ -1248,10 +1143,10 @@ class pkgAcqFile : public pkgAcquire::Item * is the absolute name to which the file should be downloaded. */ - pkgAcqFile(pkgAcquire *Owner, std::string URI, HashStringList const &Hashes, unsigned long long Size, - std::string Desc, std::string ShortDesc, - const std::string &DestDir="", const std::string &DestFilename="", - bool IsIndexFile=false); + pkgAcqFile(pkgAcquire * const Owner, std::string const &URI, HashStringList const &Hashes, unsigned long long const Size, + std::string const &Desc, std::string const &ShortDesc, + std::string const &DestDir="", std::string const &DestFilename="", + bool const IsIndexFile=false); }; /*}}}*/ /** @} */ diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index c29ef469e..b77096efd 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -376,7 +376,10 @@ int pkgAcqMethod::Run(bool Single) Tmp->ExpectedHashes.push_back(HashString(*t, hash)); } char *End; - Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10); + if (Tmp->ExpectedHashes.FileSize() > 0) + Tmp->MaximumSize = Tmp->ExpectedHashes.FileSize(); + else + Tmp->MaximumSize = strtoll(LookupTag(Message, "Maximum-Size", "0").c_str(), &End, 10); Tmp->Next = 0; // Append it to the list diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 9254e20a3..099a1f87d 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -55,8 +55,8 @@ pkgAcquire::Worker::Worker(Queue *Q,MethodConfig *Cnf, CurrentItem = 0; TotalSize = 0; CurrentSize = 0; - - Construct(); + + Construct(); } /*}}}*/ // Worker::Worker - Constructor for method config startup /*{{{*/ @@ -70,8 +70,8 @@ pkgAcquire::Worker::Worker(MethodConfig *Cnf) CurrentItem = 0; TotalSize = 0; CurrentSize = 0; - - Construct(); + + Construct(); } /*}}}*/ // Worker::Construct - Constructor helper /*{{{*/ @@ -136,7 +136,7 @@ bool pkgAcquire::Worker::Start() } for (int I = 0; I != 4; I++) SetCloseExec(Pipes[I],true); - + // Fork off the process Process = ExecFork(); if (Process == 0) @@ -145,9 +145,9 @@ bool pkgAcquire::Worker::Start() dup2(Pipes[1],STDOUT_FILENO); dup2(Pipes[2],STDIN_FILENO); SetCloseExec(STDOUT_FILENO,false); - SetCloseExec(STDIN_FILENO,false); + SetCloseExec(STDIN_FILENO,false); SetCloseExec(STDERR_FILENO,false); - + const char *Args[2]; Args[0] = Method.c_str(); Args[1] = 0; @@ -165,7 +165,7 @@ bool pkgAcquire::Worker::Start() close(Pipes[2]); OutReady = false; InReady = true; - + // Read the configuration data if (WaitFd(InFd) == false || ReadMessages() == false) @@ -174,7 +174,7 @@ bool pkgAcquire::Worker::Start() RunMessages(); if (OwnerQ != 0) SendConfiguration(); - + return true; } /*}}}*/ @@ -201,7 +201,7 @@ bool pkgAcquire::Worker::RunMessages() if (Debug == true) clog << " <- " << Access << ':' << QuoteString(Message,"\n") << endl; - + // Fetch the message number char *End; int Number = strtol(Message.c_str(),&End,10); @@ -215,15 +215,15 @@ bool pkgAcquire::Worker::RunMessages() // update used mirror string UsedMirror = LookupTag(Message,"UsedMirror", ""); - if (!UsedMirror.empty() && + if (!UsedMirror.empty() && Itm && - Itm->Description.find(" ") != string::npos) + Itm->Description.find(" ") != string::npos) { Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); // FIXME: will we need this as well? //Itm->ShortDesc = UsedMirror; } - + // Determine the message number and dispatch switch (Number) { @@ -232,18 +232,18 @@ bool pkgAcquire::Worker::RunMessages() if (Capabilities(Message) == false) return _error->Error("Unable to process Capabilities message from %s",Access.c_str()); break; - + // 101 Log case 101: if (Debug == true) clog << " <- (log) " << LookupTag(Message,"Message") << endl; break; - + // 102 Status case 102: Status = LookupTag(Message,"Message"); break; - + // 103 Redirect case 103: { @@ -252,7 +252,7 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 103 Redirect message"); break; } - + string NewURI = LookupTag(Message,"New-URI",URI.c_str()); Itm->URI = NewURI; @@ -272,7 +272,7 @@ bool pkgAcquire::Worker::RunMessages() Log->Done(Desc); break; } - + // 200 URI Start case 200: { @@ -281,23 +281,23 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 200 URI Start message"); break; } - + CurrentItem = Itm; CurrentSize = 0; TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10); - Itm->Owner->Start(Message,strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10)); + Itm->Owner->Start(Message, TotalSize); // Display update before completion if (Log != 0 && Log->MorePulses == true) Log->Pulse(Itm->Owner->GetOwner()); - + if (Log != 0) Log->Fetch(*Itm); break; } - + // 201 URI Done case 201: { @@ -306,7 +306,7 @@ bool pkgAcquire::Worker::RunMessages() _error->Error("Method gave invalid 201 URI Done message"); break; } - + pkgAcquire::Item *Owner = Itm->Owner; pkgAcquire::ItemDesc Desc = *Itm; @@ -316,22 +316,11 @@ bool pkgAcquire::Worker::RunMessages() // Display update before completion if (Log != 0 && Log->MorePulses == true) Log->Pulse(Owner->GetOwner()); - + OwnerQ->ItemDone(Itm); - unsigned long long const ServerSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); - bool isHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || - StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); - // Using the https method the server might return 200, but the - // If-Modified-Since condition is not satsified, libcurl will - // discard the download. In this case, however, TotalSize will be - // set to the actual size of the file, while ServerSize will be set - // to 0. Therefore, if the item is marked as a hit and the - // downloaded size (ServerSize) is 0, we ignore TotalSize. - if (TotalSize != 0 && (!isHit || ServerSize != 0) && ServerSize != TotalSize) - _error->Warning("Size of file %s is not what the server reported %s %llu", - Owner->DestFile.c_str(), LookupTag(Message,"Size","0").c_str(),TotalSize); - - // see if there is a hash to verify + + HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); + // see if we got hashes to verify HashStringList ReceivedHashes; for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { @@ -340,6 +329,18 @@ bool pkgAcquire::Worker::RunMessages() if (hashsum.empty() == false) ReceivedHashes.push_back(HashString(*type, hashsum)); } + // not all methods always sent Hashes our way + if (ExpectedHashes.usable() == true && ReceivedHashes.usable() == false) + { + std::string const filename = LookupTag(Message, "Filename", Owner->DestFile.c_str()); + if (filename.empty() == false && RealFileExists(filename)) + { + Hashes calc(ExpectedHashes); + FileFd file(filename, FileFd::ReadOnly, FileFd::None); + calc.AddFD(file); + ReceivedHashes = calc.GetHashStringList(); + } + } if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) { @@ -348,30 +349,66 @@ bool pkgAcquire::Worker::RunMessages() for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) std::clog << "\t- " << hs->toStr() << std::endl; std::clog << "ExpectedHash:" << endl; - HashStringList expectedHashes = Owner->HashSums(); - for (HashStringList::const_iterator hs = expectedHashes.begin(); hs != expectedHashes.end(); ++hs) + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) std::clog << "\t- " << hs->toStr() << std::endl; std::clog << endl; } - Owner->Done(Message, ServerSize, ReceivedHashes, Config); - ItemDone(); - // Log that we are done - if (Log != 0) + // decide if what we got is what we expected + bool consideredOkay = false; + bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || + StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); + if (ExpectedHashes.usable()) { - if (isHit) + if (ReceivedHashes.usable() == false) { - /* Hide 'hits' for local only sources - we also manage to - hide gets */ - if (Config->LocalOnly == false) - Log->IMSHit(Desc); - } + /* IMS-Hits can't be checked here as we will have uncompressed file, + but the hashes for the compressed file. What we have was good through + so all we have to ensure later is that we are not stalled. */ + consideredOkay = isIMSHit; + } + else if (ReceivedHashes == ExpectedHashes) + consideredOkay = true; else - Log->Done(Desc); + consideredOkay = false; + + } + else if (Owner->HashesRequired() == true) + consideredOkay = false; + else + consideredOkay = true; + + if (consideredOkay == true) + { + Owner->Done(Message, ReceivedHashes, Config); + ItemDone(); + + // Log that we are done + if (Log != 0) + { + if (isIMSHit) + { + /* Hide 'hits' for local only sources - we also manage to + hide gets */ + if (Config->LocalOnly == false) + Log->IMSHit(Desc); + } + else + Log->Done(Desc); + } + } + else + { + Owner->Status = pkgAcquire::Item::StatAuthError; + Owner->Failed(Message,Config); + ItemDone(); + + if (Log != 0) + Log->Fail(Desc); } break; - } - + } + // 400 URI Failure case 400: { @@ -408,18 +445,18 @@ bool pkgAcquire::Worker::RunMessages() Log->Fail(Desc); break; - } - + } + // 401 General Failure case 401: _error->Error("Method %s General failure: %s",Access.c_str(),LookupTag(Message,"Message").c_str()); break; - + // 403 Media Change case 403: - MediaChange(Message); + MediaChange(Message); break; - } + } } return true; } @@ -432,7 +469,7 @@ bool pkgAcquire::Worker::Capabilities(string Message) { if (Config == 0) return true; - + Config->Version = LookupTag(Message,"Version"); Config->SingleInstance = StringToBool(LookupTag(Message,"Single-Instance"),false); Config->Pipeline = StringToBool(LookupTag(Message,"Pipeline"),false); @@ -447,13 +484,13 @@ bool pkgAcquire::Worker::Capabilities(string Message) clog << "Configured access method " << Config->Access << endl; clog << "Version:" << Config->Version << " SingleInstance:" << Config->SingleInstance << - " Pipeline:" << Config->Pipeline << - " SendConfig:" << Config->SendConfig << - " LocalOnly: " << Config->LocalOnly << - " NeedsCleanup: " << Config->NeedsCleanup << + " Pipeline:" << Config->Pipeline << + " SendConfig:" << Config->SendConfig << + " LocalOnly: " << Config->LocalOnly << + " NeedsCleanup: " << Config->NeedsCleanup << " Removable: " << Config->Removable << endl; } - + return true; } /*}}}*/ @@ -463,10 +500,10 @@ bool pkgAcquire::Worker::Capabilities(string Message) bool pkgAcquire::Worker::MediaChange(string Message) { int status_fd = _config->FindI("APT::Status-Fd",-1); - if(status_fd > 0) + if(status_fd > 0) { string Media = LookupTag(Message,"Media"); - string Drive = LookupTag(Message,"Drive"); + string Drive = LookupTag(Message,"Drive"); ostringstream msg,status; ioprintf(msg,_("Please insert the disc labeled: " "'%s' " @@ -536,12 +573,12 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) { if (OutFd == -1) return false; - + string Message = "600 URI Acquire\n"; Message.reserve(300); Message += "URI: " + Item->URI; Message += "\nFilename: " + Item->Owner->DestFile; - HashStringList const hsl = Item->Owner->HashSums(); + HashStringList const hsl = Item->Owner->GetExpectedHashes(); for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); if(Item->Owner->FileSize > 0) @@ -564,7 +601,7 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) clog << " -> " << Access << ':' << QuoteString(Message,"\n") << endl; OutQueue += Message; OutReady = true; - + return true; } /*}}}*/ @@ -586,7 +623,7 @@ bool pkgAcquire::Worker::OutFdReady() OutQueue.erase(0,Res); if (OutQueue.empty() == true) OutReady = false; - + return true; } /*}}}*/ @@ -608,7 +645,7 @@ bool pkgAcquire::Worker::InFdReady() bool pkgAcquire::Worker::MethodFailure() { _error->Error("Method %s has died unexpectedly!",Access.c_str()); - + // do not reap the child here to show meaningfull error to the user ExecWait(Process,Access.c_str(),false); Process = -1; @@ -620,26 +657,22 @@ bool pkgAcquire::Worker::MethodFailure() InReady = false; OutQueue = string(); MessageQueue.erase(MessageQueue.begin(),MessageQueue.end()); - + return false; } /*}}}*/ -// Worker::Pulse - Called periodically /*{{{*/ +// Worker::Pulse - Called periodically /*{{{*/ // --------------------------------------------------------------------- /* */ void pkgAcquire::Worker::Pulse() { if (CurrentItem == 0) return; - + struct stat Buf; if (stat(CurrentItem->Owner->DestFile.c_str(),&Buf) != 0) return; CurrentSize = Buf.st_size; - - // Hmm? Should not happen... - if (CurrentSize > TotalSize && TotalSize != 0) - TotalSize = CurrentSize; } /*}}}*/ // Worker::ItemDone - Called when the current item is finished /*{{{*/ diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 0fa443b4a..11a7e479b 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include /*}}}*/ @@ -178,6 +179,15 @@ HashString const * HashStringList::find(char const * const type) const /*{{{*/ return NULL; } /*}}}*/ +unsigned long long HashStringList::FileSize() const /*{{{*/ +{ + HashString const * const hsf = find("Checksum-FileSize"); + if (hsf == NULL) + return 0; + std::string const hv = hsf->HashValue(); + return strtoull(hv.c_str(), NULL, 10); +} + /*}}}*/ bool HashStringList::supported(char const * const type) /*{{{*/ { for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index ac13c8ace..176ce4faa 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -87,6 +87,15 @@ class HashStringList */ HashString const * find(char const * const type) const; HashString const * find(std::string const &type) const { return find(type.c_str()); } + + /** finds the filesize hash and returns it as number + * + * @return beware: if the size isn't known we return \b 0 here, + * just like we would do for an empty file. If that is a problem + * for you have to get the size manually out of the list. + */ + unsigned long long FileSize() const; + /** check if the given hash type is supported * * @param type to check diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index d672b4fd8..185248619 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -742,13 +742,13 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // and give it to the list parser debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, "local", *this) == false) + if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == false) return _error->Error("Problem with SelectFile %s", DebFile.c_str()); pkgCache::PkgFileIterator File = Gen.GetCurFile(); File->Size = DebControl->Size(); File->mtime = DebControl->ModificationTime(); - + if (Gen.MergeList(Parser) == false) return _error->Error("Problem with MergeLister for %s", DebFile.c_str()); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index aa2db8149..eb5e78e3b 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -192,11 +192,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { vector const SectionEntries = src->second; for (vector::const_iterator I = SectionEntries.begin(); I != SectionEntries.end(); ++I) { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = "Sources"; - Target->MetaKey = SourceIndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section); - Target->URI = SourceIndexURI(Target->ShortDesc.c_str(), (*I)->Section); - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section); + char const * const ShortDesc = "Sources"; + IndexTarget * const Target = new IndexTarget( + SourceIndexURISuffix(ShortDesc, (*I)->Section), + ShortDesc, + Info(ShortDesc, (*I)->Section), + SourceIndexURI(ShortDesc, (*I)->Section) + ); IndexTargets->push_back (Target); } } @@ -212,11 +214,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { continue; for (vector ::const_iterator I = a->second.begin(); I != a->second.end(); ++I) { - IndexTarget * Target = new IndexTarget(); - Target->ShortDesc = "Packages"; - Target->MetaKey = IndexURISuffix(Target->ShortDesc.c_str(), (*I)->Section, a->first); - Target->URI = IndexURI(Target->ShortDesc.c_str(), (*I)->Section, a->first); - Target->Description = Info (Target->ShortDesc.c_str(), (*I)->Section, a->first); + char const * const ShortDesc = "Packages"; + IndexTarget * const Target = new IndexTarget( + IndexURISuffix(ShortDesc, (*I)->Section, a->first), + ShortDesc, + Info (ShortDesc, (*I)->Section, a->first), + IndexURI(ShortDesc, (*I)->Section, a->first) + ); IndexTargets->push_back (Target); sections.insert((*I)->Section); } @@ -235,11 +239,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const { s != sections.end(); ++s) { for (std::vector::const_iterator l = lang.begin(); l != lang.end(); ++l) { - IndexTarget * Target = new OptionalIndexTarget(); - Target->ShortDesc = "Translation-" + *l; - Target->MetaKey = TranslationIndexURISuffix(l->c_str(), *s); - Target->URI = TranslationIndexURI(l->c_str(), *s); - Target->Description = Info (Target->ShortDesc.c_str(), *s); + std::string const ShortDesc = "Translation-" + *l; + IndexTarget * const Target = new OptionalIndexTarget( + TranslationIndexURISuffix(l->c_str(), *s), + ShortDesc, + Info (ShortDesc.c_str(), *s), + TranslationIndexURI(l->c_str(), *s) + ); IndexTargets->push_back(Target); } } @@ -249,8 +255,6 @@ vector * debReleaseIndex::ComputeIndexTargets() const { /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { - bool const tryInRelease = _config->FindB("Acquire::TryInRelease", true); - indexRecords * const iR = new indexRecords(Dist); if (Trusted == ALWAYS_TRUSTED) iR->SetTrusted(true); @@ -258,37 +262,17 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const iR->SetTrusted(false); // special case for --print-uris - if (GetAll) { - vector *targets = ComputeIndexTargets(); - for (vector ::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) { - new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, - (*Target)->ShortDesc, HashStringList()); - } - delete targets; - - // this is normally created in pkgAcqMetaSig, but if we run - // in --print-uris mode, we add it here - if (tryInRelease == false) - new pkgAcqMetaIndex(Owner, NULL, - MetaIndexURI("Release"), - MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); + vector const * const targets = ComputeIndexTargets(); +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X)) + pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, + APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), + targets, iR); +#undef APT_TARGET + if (GetAll) + { + for (vector ::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) + new pkgAcqIndex(Owner, TransactionManager, *Target); } - if (tryInRelease == true) - new pkgAcqMetaClearSig(Owner, - MetaIndexURI("InRelease"), MetaIndexInfo("InRelease"), "InRelease", - MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); - else - new pkgAcqMetaIndex(Owner, NULL, - MetaIndexURI("Release"), MetaIndexInfo("Release"), "Release", - MetaIndexURI("Release.gpg"), MetaIndexInfo("Release.gpg"), "Release.gpg", - ComputeIndexTargets(), - iR); return true; } diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index de2617833..c26868cac 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -73,7 +73,7 @@ APT_PURE indexRecords::checkSum *indexRecords::Lookup(const string MetaKey) APT_PURE bool indexRecords::Exists(string const &MetaKey) const { - return Entries.count(MetaKey) == 1; + return Entries.find(MetaKey) != Entries.end(); } bool indexRecords::Load(const string Filename) /*{{{*/ diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 2ba23c5c0..b4d56611a 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -190,7 +190,12 @@ class pkgCache /*{{{*/ struct Flag { enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)}; - enum PkgFFlags {NotSource=(1<<0),NotAutomatic=(1<<1),ButAutomaticUpgrades=(1<<2)}; + enum PkgFFlags { + NotSource=(1<<0), /*!< packages can't be fetched from here, e.g. dpkg/status file */ + NotAutomatic=(1<<1), /*!< archive has a default pin of 1 */ + ButAutomaticUpgrades=(1<<2), /*!< (together with the previous) archive has a default pin of 100 */ + LocalSource=(1<<3), /*!< local sources can't and will not be verified by hashes */ + }; }; protected: diff --git a/methods/file.cc b/methods/file.cc index 043ab04b8..353e54bd5 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -57,7 +57,11 @@ bool FileMethod::Fetch(FetchItem *Itm) Res.LastModified = Buf.st_mtime; Res.IMSHit = false; if (Itm->LastModified == Buf.st_mtime && Itm->LastModified != 0) - Res.IMSHit = true; + { + unsigned long long const filesize = Itm->ExpectedHashes.FileSize(); + if (filesize != 0 && filesize == Res.Size) + Res.IMSHit = true; + } } // See if the uncompressed file exists and reuse it diff --git a/test/integration/test-apt-get-source-authenticated b/test/integration/test-apt-get-source-authenticated index 685bc566b..da63f7cb3 100755 --- a/test/integration/test-apt-get-source-authenticated +++ b/test/integration/test-apt-get-source-authenticated @@ -1,7 +1,7 @@ #!/bin/sh # # Regression test for debian bug #749795. Ensure that we fail with -# a error if apt-get source foo will download a source that comes +# an error if apt-get source foo will download a source that comes # from a unauthenticated repository # set -e diff --git a/test/integration/test-apt-sources-deb822 b/test/integration/test-apt-sources-deb822 index d8b2334ad..51fe7bcfe 100755 --- a/test/integration/test-apt-sources-deb822 +++ b/test/integration/test-apt-sources-deb822 @@ -23,46 +23,45 @@ Description: summay msgtest 'Test sources.list' 'old style' echo "deb http://ftp.debian.org/debian stable main" > $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris msgtest 'Test sources.list' 'simple deb822' echo "$BASE" > $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris - +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris msgtest 'Test deb822 with' 'two entries' # Two entries echo "$BASE" > $SOURCES echo "" >> $SOURCES echo "$BASE" | sed s/stable/unstable/ >> $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 " aptget update --print-uris +'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris # two suite entries msgtest 'Test deb822 with' 'two Suite entries' echo "$BASE" | sed -e "s/stable/stable unstable/" > $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/unstable/InRelease' ftp.debian.org_debian_dists_unstable_InRelease 0 " aptget update --print-uris +'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris msgtest 'Test deb822' 'architecture option' echo "$BASE" > $SOURCES echo "Architectures: amd64 armel" >> $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0 +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-amd64/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-amd64_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 -'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris msgtest 'Test old-style sources.list file which has' 'malformed dist' @@ -85,20 +84,20 @@ testempty aptget update --print-uris # multiple URIs msgtest 'Test deb822 sources.list file which has' 'Multiple URIs work' echo "$BASE" | sed -e 's#http://ftp.debian.org/debian#http://ftp.debian.org/debian http://ftp.de.debian.org/debian#' > $SOURCES -testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 'http://ftp.de.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.de.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris # multiple Type in one field msgtest 'Test deb822 sources.list file which has' 'Multiple Types work' echo "$BASE" | sed -e 's#Types: deb#Types: deb deb-src#' > $SOURCES -testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 -'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 -'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 " aptget update --print-uris +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris # a Suite msgtest 'Test deb822 sources.list file which has' 'a exact path and no sections' @@ -107,6 +106,6 @@ Types: deb URIs: http://emacs.naquadah.org Suites: stable/ EOF -testequal --nomsg "'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0 -'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0 -'http://emacs.naquadah.org/stable/InRelease' emacs.naquadah.org_stable_InRelease 0 " aptget update --print-uris +testequal --nomsg "'http://emacs.naquadah.org/stable/InRelease' emacs.naquadah.org_stable_InRelease 0 +'http://emacs.naquadah.org/stable/Packages.bz2' emacs.naquadah.org_stable_Packages 0 +'http://emacs.naquadah.org/stable/en.bz2' emacs.naquadah.org_stable_en 0 " aptget update --print-uris diff --git a/test/integration/test-apt-update-expected-size b/test/integration/test-apt-update-expected-size index 55a5da848..55bba8188 100755 --- a/test/integration/test-apt-update-expected-size +++ b/test/integration/test-apt-update-expected-size @@ -35,7 +35,7 @@ test_packagestoobig() { done NEW_SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" testfailuremsg "W: Failed to fetch ${1}/dists/unstable/main/binary-i386/Packages Writing more data than expected ($NEW_SIZE > $SIZE) -E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -o Debug::pkgAcquire::Worker=0 -o Debug::Acquire::Transaction=0 +E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::Transaction=0 } methodtest() { diff --git a/test/integration/test-apt-update-file b/test/integration/test-apt-update-file index 1ecf9a38a..665f94fa5 100755 --- a/test/integration/test-apt-update-file +++ b/test/integration/test-apt-update-file @@ -22,6 +22,10 @@ addtrap 'prefix' 'chmod 750 aptarchive/dists/unstable/main/binary-amd64;' chmod 550 aptarchive/dists/unstable/main/binary-amd64 testsuccess aptget update + +# the release files aren't an IMS-hit, but the indexes are +redatereleasefiles '+1 hour' + testsuccess aptget update -o Debug::pkgAcquire::Auth=1 cp -a rootdir/tmp/testsuccess.output rootdir/tmp/update.output diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index db4430ea3..f132bcf8e 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -28,6 +28,7 @@ Description: an autogenerated evil package EOF # avoid ims hit touch -d '+1hour' aptarchive/dists/unstable/main/binary-i386/Packages + compressfile aptarchive/dists/unstable/main/binary-i386/Packages } assert_update_is_refused_and_last_good_state_used() @@ -87,16 +88,16 @@ test_from_inrelease_to_unsigned_with_override() { # setup archive with InRelease file setupaptarchive_with_lists_clean - # FIXME: is not what the server reported 4104 4106 - testsuccess aptget update #-o Debug::pkgAcquire::Worker=1 + testsuccess aptget update # simulate moving to a unsigned but otherwise valid repo simulate_mitm_and_inject_evil_package - generatereleasefiles + generatereleasefiles '+2 hours' + find $APTARCHIVE -name '*Packages*' -exec touch -d '+2 hours' {} \; # and ensure we can update to it (with enough force) testwarning aptget update --allow-insecure-repositories \ - -o Acquire::AllowDowngradeToInsecureRepositories=1 + -o Acquire::AllowDowngradeToInsecureRepositories=1 -o Debug::pkgAcquire::Worker=1 -o Debug::pkgAcquire::Auth=1 # but that the individual packages are still considered untrusted testfailureequal "WARNING: The following packages cannot be authenticated! evil @@ -167,7 +168,7 @@ test_inrelease_to_invalid_inrelease() listcurrentlistsdirectory > lists.before # now remove InRelease and subvert Release do no longer verify - sed -i 's/Codename.*/Codename: evil!'/ $APTARCHIVE/dists/unstable/InRelease + sed -i 's/^Codename:.*/Codename: evil!/' $APTARCHIVE/dists/unstable/InRelease inject_evil_package testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) diff --git a/test/integration/test-apt-update-not-modified b/test/integration/test-apt-update-not-modified index bac33d531..a490f00de 100755 --- a/test/integration/test-apt-update-not-modified +++ b/test/integration/test-apt-update-not-modified @@ -43,7 +43,9 @@ Version: 1 EOF compressfile aptarchive/dists/unstable/main/binary-amd64/Packages testfailureequal "Hit $1 unstable InRelease -Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists.good/unstable/main/binary-amd64/Packages.gz') B] +Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] +Err $1 unstable/main amd64 Packages + Hash Sum mismatch W: Failed to fetch $1/dists/unstable/main/binary-amd64/Packages.gz Hash Sum mismatch E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update @@ -87,8 +89,32 @@ Hit $1 unstable Release Reading package lists..." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" - # readd arch so its downloaded again + # readd arch so its downloaded again… configarchitecture 'amd64' 'i386' + # … but oh noes, hashsum mismatch! + find aptarchive/dists/unstable/main/binary-amd64/ -type f -delete + cat >> aptarchive/dists/unstable/main/binary-amd64/Packages < rootdir/etc/apt/apt.conf.d/00nolanguages -testsuccess aptget update +testsuccess aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::http=1 listcurrentlistsdirectory > lists.before # insert new version @@ -26,7 +26,7 @@ mkdir aptarchive/dists/unstable/main/binary-i386/saved cp -p aptarchive/dists/unstable/main/binary-i386/Packages* \ aptarchive/dists/unstable/main/binary-i386/saved insertpackage 'unstable' 'foo' 'all' '2.0' - +touch -d '+1 hour' aptarchive/dists/unstable/main/binary-i386/Packages compressfile aptarchive/dists/unstable/main/binary-i386/Packages # ensure that we do not get a I-M-S hit for the Release file @@ -39,7 +39,6 @@ cp -p aptarchive/dists/unstable/main/binary-i386/saved/Packages* \ aptarchive/dists/unstable/main/binary-i386/ # ensure this raises an error -testfailureequal "W: Failed to fetch http://localhost:8080/dists/unstable/main/binary-i386/Packages Hash Sum mismatch - -E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq +testfailuremsg "W: Failed to fetch copy:$(readlink -f ./rootdir)/var/lib/apt/lists/localhost:8080_dists_unstable_main_binary-i386_Packages Hash Sum mismatch +E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::http=1 testfileequal lists.before "$(listcurrentlistsdirectory)" diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index bca07268c..486b8ba02 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -12,7 +12,7 @@ setupflataptarchive testaptgetupdate() { rm -rf rootdir/var/lib/apt - aptget update 2>> testaptgetupdate.diff >> testaptgetupdate.diff || true + aptget update >testaptgetupdate.diff 2>&1 || true sed -i -e '/Ign /,+1d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff GIVEN="$1" shift diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum index ec74a750b..555d8fcaa 100755 --- a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum +++ b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum @@ -176,7 +176,11 @@ testmismatch() { Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B] +Err http://localhost:8080/ $1 1.0 (dsc) + Hash Sum mismatch Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B] +Err http://localhost:8080/ $1 1.0 (tar) + Hash Sum mismatch E: Failed to fetch http://localhost:8080/${1}_1.0.dsc Hash Sum mismatch E: Failed to fetch http://localhost:8080/${1}_1.0.tar.gz Hash Sum mismatch @@ -238,6 +242,8 @@ Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (tar) [3 B] Get:2 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc) [3 B] +Err http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc) + Hash Sum mismatch E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc Hash Sum mismatch E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha1-bad @@ -247,6 +253,8 @@ testfailureequal 'Reading package lists... Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar) [3 B] +Err http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar) + Hash Sum mismatch Get:2 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (dsc) [3 B] E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz Hash Sum mismatch diff --git a/test/libapt/acqprogress_test.cc b/test/libapt/acqprogress_test.cc index 288e05aca..c634733d4 100644 --- a/test/libapt/acqprogress_test.cc +++ b/test/libapt/acqprogress_test.cc @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -10,9 +11,10 @@ class TestItem: public pkgAcquire::Item { public: - TestItem(pkgAcquire * const Acq) : pkgAcquire::Item(Acq, "", NULL) {} + TestItem(pkgAcquire * const Acq) : pkgAcquire::Item(Acq) {} - virtual std::string DescURI() { return ""; } + virtual std::string DescURI() const { return ""; } + virtual HashStringList GetExpectedHashes() const { return HashStringList(); } }; diff --git a/test/libapt/hashsums_test.cc b/test/libapt/hashsums_test.cc index edcd8a11a..63c63ecd3 100644 --- a/test/libapt/hashsums_test.cc +++ b/test/libapt/hashsums_test.cc @@ -306,6 +306,7 @@ TEST(HashSumsTest, HashStringList) EXPECT_EQ(NULL, list.find(NULL)); EXPECT_EQ(NULL, list.find("")); EXPECT_EQ(NULL, list.find("MD5Sum")); + EXPECT_EQ(0, list.FileSize()); // empty lists aren't equal HashStringList list2; @@ -316,6 +317,8 @@ TEST(HashSumsTest, HashStringList) list.push_back(HashString("Checksum-FileSize", "29")); EXPECT_FALSE(list.empty()); EXPECT_FALSE(list.usable()); + EXPECT_EQ(1, list.size()); + EXPECT_EQ(29, list.FileSize()); Hashes hashes; hashes.Add("The quick brown fox jumps over the lazy dog"); -- cgit v1.2.3-70-g09d2 From 3679515479136179e0d95325a6559fcc6d0af7f8 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 6 Jun 2015 19:16:45 +0200 Subject: check patch hashes in rred worker instead of in the handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rred is responsible for unpacking and reading the patch files in one go, but we currently only have hashes for the uncompressed patch files, so the handler read the entire patch file before dispatching it to the worker which would read it again – both with an implicit uncompress. Worse, while the workers operate in parallel the handler is the central orchestration unit, so having it busy with work means the workers do (potentially) nothing. This means rred is working with 'untrusted' data, which is bad. Yet, having the unpack in the handler meant that the untrusted uncompress was done as root which isn't better either. Now, we have it at least contained in a binary which we can harden a bit better. In the long run, we want hashes for the compressed patch files through to be safe. --- apt-pkg/acquire-item.cc | 95 +++++++++++++++++++++++---------------- apt-pkg/acquire-item.h | 2 + apt-pkg/acquire-method.cc | 14 +++--- apt-pkg/acquire-method.h | 5 ++- methods/rred.cc | 62 ++++++++++++++++++++----- test/integration/test-pdiff-usage | 2 + 6 files changed, 121 insertions(+), 59 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index ec6ec6e84..7b69ee993 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -95,6 +95,19 @@ static std::string GetCompressedFileName(std::string const &URI, std::string con return Name; } /*}}}*/ +static std::string GetMergeDiffsPatchFileName(std::string const &Final, std::string const &Patch)/*{{{*/ +{ + // rred expects the patch as $FinalFile.ed.$patchname.gz + return Final + ".ed." + Patch + ".gz"; +} + /*}}}*/ +static std::string GetDiffsPatchFileName(std::string const &Final) /*{{{*/ +{ + // rred expects the patch as $FinalFile.ed + return Final + ".ed"; +} + /*}}}*/ + static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaBase * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ { if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true) @@ -1860,6 +1873,9 @@ void pkgAcqIndexDiffs::Failed(string const &Message,pkgAcquire::MethodConfig con << "Falling back to normal index file acquire" << std::endl; DestFile = GetPartialFileNameFromURI(Target->URI); RenameOnError(PDiffError); + std::string const patchname = GetDiffsPatchFileName(DestFile); + if (RealFileExists(patchname)) + rename(patchname.c_str(), std::string(patchname + ".FAILED").c_str()); new pkgAcqIndex(Owner, TransactionManager, Target); Finish(); } @@ -1968,28 +1984,13 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, Item::Done(Message, Hashes, Cnf); - // FIXME: verify this download too before feeding it to rred std::string const FinalFile = GetPartialFileNameFromURI(Target->URI); + std::string const PatchFile = GetDiffsPatchFileName(FinalFile); // success in downloading a diff, enter ApplyDiff state if(State == StateFetchDiff) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if (fd.Size() != available_patches[0].patch_size || - available_patches[0].patch_hashes != LocalHashes) - { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; - } - - // rred excepts the patch as $FinalFile.ed - Rename(DestFile,FinalFile+".ed"); + Rename(DestFile, PatchFile); if(Debug) std::clog << "Sending to rred method: " << FinalFile << std::endl; @@ -2000,18 +2001,17 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, QueueURI(Desc); SetActiveSubprocess("rred"); return; - } - + } // success in download/apply a diff, queue next (if needed) if(State == StateApplyDiff) { // remove the just applied patch available_patches.erase(available_patches.begin()); - unlink((FinalFile + ".ed").c_str()); + unlink(PatchFile.c_str()); // move into place - if(Debug) + if(Debug) { std::clog << "Moving patched file in place: " << std::endl << DestFile << " -> " << FinalFile << std::endl; @@ -2031,6 +2031,18 @@ void pkgAcqIndexDiffs::Done(string const &Message, HashStringList const &Hashes, } } /*}}}*/ +std::string pkgAcqIndexDiffs::Custom600Headers() const /*{{{*/ +{ + if(State != StateApplyDiff) + return pkgAcqBaseIndex::Custom600Headers(); + std::ostringstream patchhashes; + HashStringList const ExpectedHashes = available_patches[0].patch_hashes; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + patchhashes << "\nPatch-0-" << hs->HashType() << "-Hash: " << hs->HashValue(); + patchhashes << pkgAcqBaseIndex::Custom600Headers(); + return patchhashes.str(); +} + /*}}}*/ // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, @@ -2079,6 +2091,9 @@ void pkgAcqIndexMergeDiffs::Failed(string const &Message,pkgAcquire::MethodConfi std::clog << "Falling back to normal index file acquire" << std::endl; DestFile = GetPartialFileNameFromURI(Target->URI); RenameOnError(PDiffError); + std::string const patchname = GetMergeDiffsPatchFileName(DestFile, patch.file); + if (RealFileExists(patchname)) + rename(patchname.c_str(), std::string(patchname + ".FAILED").c_str()); new pkgAcqIndex(Owner, TransactionManager, Target); } /*}}}*/ @@ -2090,26 +2105,10 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha Item::Done(Message, Hashes, Cnf); - // FIXME: verify download before feeding it to rred string const FinalFile = GetPartialFileNameFromURI(Target->URI); - if (State == StateFetchDiff) { - FileFd fd(DestFile, FileFd::ReadOnly, FileFd::Gzip); - class Hashes LocalHashesCalc; - LocalHashesCalc.AddFD(fd); - HashStringList const LocalHashes = LocalHashesCalc.GetHashStringList(); - - if (fd.Size() != patch.patch_size || patch.patch_hashes != LocalHashes) - { - // patchfiles are dated, so bad indicates a bad download, so kill it - unlink(DestFile.c_str()); - Failed("Patch has Size/Hashsum mismatch", NULL); - return; - } - - // rred expects the patch as $FinalFile.ed.$patchname.gz - Rename(DestFile, FinalFile + ".ed." + patch.file + ".gz"); + Rename(DestFile, GetMergeDiffsPatchFileName(FinalFile, patch.file)); // check if this is the last completed diff State = StateDoneDiff; @@ -2158,7 +2157,7 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha I != allPatches->end(); ++I) { std::string const PartialFile = GetPartialFileNameFromURI(Target->URI); - std::string patch = PartialFile + ".ed." + (*I)->patch.file + ".gz"; + std::string const patch = GetMergeDiffsPatchFileName(PartialFile, (*I)->patch.file); unlink(patch.c_str()); } unlink(FinalFile.c_str()); @@ -2170,6 +2169,24 @@ void pkgAcqIndexMergeDiffs::Done(string const &Message, HashStringList const &Ha } } /*}}}*/ +std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ +{ + if(State != StateApplyDiff) + return pkgAcqBaseIndex::Custom600Headers(); + std::ostringstream patchhashes; + unsigned int seen_patches = 0; + for (std::vector::const_iterator I = allPatches->begin(); + I != allPatches->end(); ++I) + { + HashStringList const ExpectedHashes = (*I)->patch.patch_hashes; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + patchhashes << "\nPatch-" << seen_patches << "-" << hs->HashType() << "-Hash: " << hs->HashValue(); + ++seen_patches; + } + patchhashes << pkgAcqBaseIndex::Custom600Headers(); + return patchhashes.str(); +} + /*}}}*/ // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 97d5ea1dd..f24af1aec 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -774,6 +774,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); + virtual std::string Custom600Headers() const; virtual std::string DescURI() const {return Target->URI + "Index";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; @@ -886,6 +887,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); + virtual std::string Custom600Headers() const; virtual std::string DescURI() const {return Target->URI + "IndexDiffs";}; virtual HashStringList GetExpectedHashes() const; virtual bool HashesRequired() const; diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index b77096efd..a8fc75f8e 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -388,14 +388,14 @@ int pkgAcqMethod::Run(bool Single) *I = Tmp; if (QueueBack == 0) QueueBack = Tmp; - + // Notify that this item is to be fetched. - if (Fetch(Tmp) == false) + if (URIAcquire(Message, Tmp) == false) Fail(); - - break; - } - } + + break; + } + } } Exit(); @@ -403,8 +403,6 @@ int pkgAcqMethod::Run(bool Single) } /*}}}*/ // AcqMethod::PrintStatus - privately really send a log/status message /*{{{*/ -// --------------------------------------------------------------------- -/* */ void pkgAcqMethod::PrintStatus(char const * const header, const char* Format, va_list &args) const { diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 399454892..6480eb4b5 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -76,11 +76,12 @@ class pkgAcqMethod std::string FailReason; std::string UsedMirror; std::string IP; - + // Handlers for messages virtual bool Configuration(std::string Message); virtual bool Fetch(FetchItem * /*Item*/) {return true;}; - + virtual bool URIAcquire(std::string const &/*Message*/, FetchItem *Itm) { return Fetch(Itm); }; + // Outgoing messages void Fail(bool Transient = false); inline void Fail(const char *Why, bool Transient = false) {Fail(std::string(Why),Transient);}; diff --git a/methods/rred.cc b/methods/rred.cc index 554ac99b4..3da33c126 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -388,7 +388,7 @@ class Patch { public: - void read_diff(FileFd &f) + void read_diff(FileFd &f, Hashes * const h) { char buffer[BLOCK_SIZE]; bool cmdwanted = true; @@ -396,6 +396,8 @@ class Patch { Change ch(0); while(f.ReadLine(buffer, sizeof(buffer))) { + if (h != NULL) + h->Add(buffer); if (cmdwanted) { char *m, *c; size_t s, e; @@ -519,8 +521,29 @@ class RredMethod : public pkgAcqMethod { private: bool Debug; + struct PDiffFile { + std::string FileName; + HashStringList ExpectedHashes; + PDiffFile(std::string const &FileName, HashStringList const &ExpectedHashes) : + FileName(FileName), ExpectedHashes(ExpectedHashes) {} + }; + + HashStringList ReadExpectedHashesForPatch(unsigned int const patch, std::string const &Message) + { + HashStringList ExpectedHashes; + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string tagname; + strprintf(tagname, "Patch-%d-%s-Hash", patch, *type); + std::string const hashsum = LookupTag(Message, tagname.c_str()); + if (hashsum.empty() == false) + ExpectedHashes.push_back(HashString(*type, hashsum)); + } + return ExpectedHashes; + } + protected: - virtual bool Fetch(FetchItem *Itm) { + virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) { Debug = _config->FindB("Debug::pkgAcquire::RRed", false); URI Get = Itm->Uri; std::string Path = Get.Host + Get.Path; // rred:/path - no host @@ -534,11 +557,17 @@ class RredMethod : public pkgAcqMethod { } else URIStart(Res); - std::vector patchpaths; + std::vector patchfiles; Patch patch; if (FileExists(Path + ".ed") == true) - patchpaths.push_back(Path + ".ed"); + { + HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(0, Message); + std::string const FileName = Path + ".ed"; + if (ExpectedHashes.usable() == false) + return _error->Error("No hashes found for uncompressed patch: %s", FileName.c_str()); + patchfiles.push_back(PDiffFile(FileName, ExpectedHashes)); + } else { _error->PushToStack(); @@ -546,18 +575,27 @@ class RredMethod : public pkgAcqMethod { _error->RevertToStack(); std::string const baseName = Path + ".ed."; + unsigned int seen_patches = 0; for (std::vector::const_iterator p = patches.begin(); p != patches.end(); ++p) + { if (p->compare(0, baseName.length(), baseName) == 0) - patchpaths.push_back(*p); + { + HashStringList const ExpectedHashes = ReadExpectedHashesForPatch(seen_patches, Message); + if (ExpectedHashes.usable() == false) + return _error->Error("No hashes found for uncompressed patch %d: %s", seen_patches, p->c_str()); + patchfiles.push_back(PDiffFile(*p, ExpectedHashes)); + ++seen_patches; + } + } } std::string patch_name; - for (std::vector::iterator I = patchpaths.begin(); - I != patchpaths.end(); + for (std::vector::iterator I = patchfiles.begin(); + I != patchfiles.end(); ++I) { - patch_name = *I; + patch_name = I->FileName; if (Debug == true) std::clog << "Patching " << Path << " with " << patch_name << std::endl; @@ -569,8 +607,12 @@ class RredMethod : public pkgAcqMethod { _error->DumpErrors(std::cerr); abort(); } - patch.read_diff(p); + Hashes patch_hash(I->ExpectedHashes); + patch.read_diff(p, &patch_hash); p.Close(); + HashStringList const hsl = patch_hash.GetHashStringList(); + if (hsl != I->ExpectedHashes) + return _error->Error("Patch %s doesn't have the expected hashsum", patch_name.c_str()); } if (Debug == true) @@ -643,7 +685,7 @@ int main(int argc, char **argv) _error->DumpErrors(std::cerr); exit(1); } - patch.read_diff(p); + patch.read_diff(p, NULL); } if (just_diff) { diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index 7d72a6944..73df61895 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -170,6 +170,8 @@ SHA256-Patches: generatereleasefiles '+1hour' signreleasefiles testsuccess aptget update "$@" + cp -f rootdir/tmp/testsuccess.output rootdir/tmp/aptgetupdate.output + testsuccess grep 'have the expected hashsum' rootdir/tmp/aptgetupdate.output testnopackage oldstuff testsuccessequal "$(cat ${PKGFILE}-new) " aptcache show apt newstuff -- cgit v1.2.3-70-g09d2 From 6d3e5bd8e08564c5eb12ecd869de5bd71e25f59d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 7 Jun 2015 02:17:15 +0200 Subject: add more parsing error checking for rred The rred parser is very accepting regarding 'invalid' files. Given that we can't trust the input it might be a bit too relaxed. In any case, checking for more errors can't hurt given that we support only a very specific subset of ed commands. --- methods/rred.cc | 70 +++++++++----- test/integration/test-method-rred | 194 ++++++++++++++++++++++++++++++++++++++ test/integration/test-pdiff-usage | 3 +- 3 files changed, 245 insertions(+), 22 deletions(-) create mode 100755 test/integration/test-method-rred (limited to 'test') diff --git a/methods/rred.cc b/methods/rred.cc index 3da33c126..81ecf8553 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,7 @@ class MemBlock { char *start; size_t size; char *free; - struct MemBlock *next; + MemBlock *next; MemBlock(size_t size) : size(size), next(NULL) { @@ -116,7 +117,7 @@ struct Change { size_t add_len; /* bytes */ char *add; - Change(int off) + Change(size_t off) { offset = off; del_cnt = add_cnt = add_len = 0; @@ -388,30 +389,37 @@ class Patch { public: - void read_diff(FileFd &f, Hashes * const h) + bool read_diff(FileFd &f, Hashes * const h) { char buffer[BLOCK_SIZE]; bool cmdwanted = true; - Change ch(0); - while(f.ReadLine(buffer, sizeof(buffer))) - { + Change ch(std::numeric_limits::max()); + if (f.ReadLine(buffer, sizeof(buffer)) == NULL) + return _error->Error("Reading first line of patchfile %s failed", f.Name().c_str()); + do { if (h != NULL) h->Add(buffer); if (cmdwanted) { char *m, *c; size_t s, e; - s = strtol(buffer, &m, 10); - if (m == buffer) { - s = e = ch.offset + ch.add_cnt; - c = buffer; - } else if (*m == ',') { - m++; + errno = 0; + s = strtoul(buffer, &m, 10); + if (unlikely(m == buffer || s == ULONG_MAX || errno != 0)) + return _error->Error("Parsing patchfile %s failed: Expected an effected line start", f.Name().c_str()); + else if (*m == ',') { + ++m; e = strtol(m, &c, 10); + if (unlikely(m == c || e == ULONG_MAX || errno != 0)) + return _error->Error("Parsing patchfile %s failed: Expected an effected line end", f.Name().c_str()); + if (unlikely(e < s)) + return _error->Error("Parsing patchfile %s failed: Effected lines end %lu is before start %lu", f.Name().c_str(), e, s); } else { e = s; c = m; } + if (s > ch.offset) + return _error->Error("Parsing patchfile %s failed: Effected line is after previous effected line", f.Name().c_str()); switch(*c) { case 'a': cmdwanted = false; @@ -422,6 +430,8 @@ class Patch { ch.del_cnt = 0; break; case 'c': + if (unlikely(s == 0)) + return _error->Error("Parsing patchfile %s failed: Change command can't effect line zero", f.Name().c_str()); cmdwanted = false; ch.add = NULL; ch.add_cnt = 0; @@ -430,6 +440,8 @@ class Patch { ch.del_cnt = e - s + 1; break; case 'd': + if (unlikely(s == 0)) + return _error->Error("Parsing patchfile %s failed: Delete command can't effect line zero", f.Name().c_str()); ch.offset = s - 1; ch.del_cnt = e - s + 1; ch.add = NULL; @@ -437,9 +449,11 @@ class Patch { ch.add_len = 0; filechanges.add_change(ch); break; + default: + return _error->Error("Parsing patchfile %s failed: Unknown command", f.Name().c_str()); } } else { /* !cmdwanted */ - if (buffer[0] == '.' && buffer[1] == '\n') { + if (strcmp(buffer, ".\n") == 0) { cmdwanted = true; filechanges.add_change(ch); } else { @@ -465,7 +479,8 @@ class Patch { } } } - } + } while(f.ReadLine(buffer, sizeof(buffer))); + return true; } void write_diff(FILE *f) @@ -601,14 +616,14 @@ class RredMethod : public pkgAcqMethod { << std::endl; FileFd p; + Hashes patch_hash(I->ExpectedHashes); // all patches are compressed, even if the name doesn't reflect it - if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false) { - std::cerr << "Could not open patch file " << patch_name << std::endl; + if (p.Open(patch_name, FileFd::ReadOnly, FileFd::Gzip) == false || + patch.read_diff(p, &patch_hash) == false) + { _error->DumpErrors(std::cerr); - abort(); + return false; } - Hashes patch_hash(I->ExpectedHashes); - patch.read_diff(p, &patch_hash); p.Close(); HashStringList const hsl = patch_hash.GetHashStringList(); if (hsl != I->ExpectedHashes) @@ -624,7 +639,6 @@ class RredMethod : public pkgAcqMethod { FILE *out = fopen(Itm->DestFile.c_str(), "w"); Hashes hash(Itm->ExpectedHashes); - patch.apply_against_file(out, inp, &hash); fclose(out); @@ -657,6 +671,16 @@ class RredMethod : public pkgAcqMethod { return true; } + bool Configuration(std::string Message) + { + if (pkgAcqMethod::Configuration(Message) == false) + return false; + + DropPrivsOrDie(); + + return true; + } + public: RredMethod() : pkgAcqMethod("2.0",SingleInstance | SendConfig), Debug(false) {} }; @@ -685,7 +709,11 @@ int main(int argc, char **argv) _error->DumpErrors(std::cerr); exit(1); } - patch.read_diff(p, NULL); + if (patch.read_diff(p, NULL) == false) + { + _error->DumpErrors(std::cerr); + exit(2); + } } if (just_diff) { diff --git a/test/integration/test-method-rred b/test/integration/test-method-rred new file mode 100755 index 000000000..a8de3ea28 --- /dev/null +++ b/test/integration/test-method-rred @@ -0,0 +1,194 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'i386' + +echo 'Package: coolstuff +Version: 0.8.15 +Description: collection of stuff + A lot, too much to iterate all, but at least this: + - stuff + - more stuff + - even more stuff + . + And a cow. + +Package: oldstuff +Version: 0-1 +Description: collection of outdated stuff + A lot, but of no use nowadays, but at least this: + - stuff + - more stuff + - even more stuff + . + And a dog.' > Packages + +testrred() { + msgtest "$1" "$2" + if [ -z "$3" ]; then + echo -n '' > Packages.ed + else + echo "$3" > Packages.ed + fi + rred() { + cat Packages | runapt "${METHODSDIR}/rred" "$@" + } + testsuccessequal "$4" --nomsg rred -f Packages.ed +} + +testrred 'Remove' 'first line' '1d' "$(tail -n +2 ./Packages)" +testrred 'Remove' 'empty line' '10d' "$(head -n 9 ./Packages) +$(tail -n 9 ./Packages)" +testrred 'Remove' 'line in a paragraph' '5d' "$(head -n 4 ./Packages) +$(tail -n 14 ./Packages)" +testrred 'Remove' 'last line' '19d' "$(head -n -1 ./Packages)" +testrred 'Remove' 'multiple single lines' '17d +7d' "$(sed -e '/^ - even more stuff$/ d' ./Packages)" +testrred 'Remove' 'first paragraph' '1,10d' "$(tail -n 9 ./Packages)" +testrred 'Remove' 'a few lines in the middle' '5,14d' "$(head -n 4 ./Packages) +$(tail -n 5 ./Packages)" +testrred 'Remove' 'second paragraph' '10,19d' "$(head -n 9 ./Packages)" +testrred 'Mass Remove' 'all stuff lines' '15,17d +13d +11d +5,7d +3d +1d' "$(sed '/stuff/ d' ./Packages)" + +testrred 'Single line add' 'first line' '0a +Format: 3.0 (native) +.' "Format: 3.0 (native) +$(cat ./Packages)" +testrred 'Single line add' 'last line' '19a +Multi-Arch: foreign +.' "$(cat ./Packages) +Multi-Arch: foreign" +testrred 'Single line add' 'middle' '9a +Multi-Arch: foreign +.' "$(head -n 9 ./Packages) +Multi-Arch: foreign +$(tail -n 10 ./Packages)" + +testrred 'Multi line add' 'first line' '0a +Format: 3.0 (native) +Source: apt +.' "Format: 3.0 (native) +Source: apt +$(cat ./Packages)" +testrred 'Multi line add' 'last line' '19a +Multi-Arch: foreign +Homepage: https://debian.org +.' "$(cat ./Packages) +Multi-Arch: foreign +Homepage: https://debian.org" +testrred 'Multi line add' 'middle' '9a +Multi-Arch: foreign +Homepage: https://debian.org +.' "$(head -n 9 ./Packages) +Multi-Arch: foreign +Homepage: https://debian.org +$(tail -n 10 ./Packages)" + +testrred 'Single line change' 'first line' '1c +Package: supercoolstuff +.' "Package: supercoolstuff +$(tail -n +2 ./Packages)" +testrred 'Single line change' 'in the middle' '9c + And a super cow. +.' "$(head -n 8 ./Packages) + And a super cow. +$(tail -n 10 ./Packages)" +testrred 'Single line change' 'an empty line' '10c + +.' "$(head -n 9 ./Packages) + +$(tail -n 9 ./Packages)" +testrred 'Single line change' 'a spacy line' '10c + +.' "$(head -n 9 ./Packages) + +$(tail -n 9 ./Packages)" +testrred 'Single line change' 'last line' '19c + And a cat. +.' "$(head -n -1 ./Packages) + And a cat." + +testrred 'Multi line change' 'exchange' '5,7c + - good stuff + - more good stuff + - even more good stuff +.' "$(head -n 4 ./Packages) + - good stuff + - more good stuff + - even more good stuff +$(tail -n 12 ./Packages)" +testrred 'Multi line change' 'less' '5,7c + - good stuff + - more good stuff +.' "$(head -n 4 ./Packages) + - good stuff + - more good stuff +$(tail -n 12 ./Packages)" +testrred 'Multi line change' 'more' '5,7c + - good stuff + - more good stuff + - even more good stuff + - bonus good stuff +.' "$(head -n 4 ./Packages) + - good stuff + - more good stuff + - even more good stuff + - bonus good stuff +$(tail -n 12 ./Packages)" + +failrred() { + msgtest 'Failure caused by' "$1" + echo "$2" > Packages.ed + rred() { + cat Packages | runapt "${METHODSDIR}/rred" "$@" + } + testfailure --nomsg rred -f Packages.ed +} + +failrred 'Bogus content' ' +' + +# not a problem per-se, but we want our parser to be really strict +failrred 'Empty patch file' '' +failrred 'Empty line patch file' ' +' +failrred 'Empty line before command' ' +1d' +failrred 'Empty line after command' '1d +' +failrred 'Empty line between commands' '17d + +7d' +failrred 'Empty spaces lines before command' ' +1d' +failrred 'Empty spaces lines after command' '1d + ' +failrred 'Empty spaces lines between commands' '17d + +7d' + +# the line before the first one can't be deleted/changed +failrred 'zero line delete' '0d' +failrred 'zero line change' '0c +Package: supercoolstuff +.' +# and this makes no sense at all +failrred 'negative line delete' '-1d' +failrred 'negative line change' '-1c +Package: supercoolstuff +.' +failrred 'negative line add' '-1a +Package: supercoolstuff +.' +failrred 'Wrong order of commands' '7d +17d' +failrred 'End before start' '7,6d' diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index 73df61895..7a9f6496b 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -165,7 +165,8 @@ SHA256-History: SHA256-Patches: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 19722 2010-08-18-2013.28 $(sha256sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX - echo 'I am Mallory and I change files' >> $PATCHFILE + # needs to look like a valid command, otherwise the parser will fail before hashes are checked + echo '1d' >> $PATCHFILE cat $PATCHFILE | gzip > ${PATCHFILE}.gz generatereleasefiles '+1hour' signreleasefiles -- cgit v1.2.3-70-g09d2 From fec55559451dc1c440c4770ee3faa116522fc59c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 7 Jun 2015 09:35:37 +0200 Subject: fix download-file using testcases to run as root Git-Dch: Ignore --- test/integration/test-apt-download-progress | 7 ++++--- test/integration/test-apt-helper | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/test/integration/test-apt-download-progress b/test/integration/test-apt-download-progress index 65c438e8f..7caeca971 100755 --- a/test/integration/test-apt-download-progress +++ b/test/integration/test-apt-download-progress @@ -24,18 +24,19 @@ assertprogress() { # actually report progress - but not too big to ensure its not delaying the # test too much TESTFILE=testfile.big -testsuccess dd if=/dev/zero of=./aptarchive/$TESTFILE bs=800k count=1 +testsuccess dd if=/dev/zero of=./aptarchive/$TESTFILE bs=800k count=1 OPT='-o APT::Status-Fd=3 -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::http=1 -o Debug::Acquire::https=1' msgtest 'download progress works via' 'http' exec 3> apt-progress.log -testsuccess --nomsg apthelper download-file "http://localhost:8080/$TESTFILE" http-$TESTFILE $OPT -o Acquire::http::Dl-Limit=800 +testsuccess --nomsg apthelper download-file "http://localhost:8080/$TESTFILE" ./downloaded/http-$TESTFILE $OPT -o Acquire::http::Dl-Limit=800 assertprogress apt-progress.log msgtest 'download progress works via' 'https' exec 3> apt-progress.log -testsuccess --nomsg apthelper download-file "https://localhost:4433/$TESTFILE" https-$TESTFILE $OPT -o Acquire::https::Dl-Limit=800 +testsuccess --nomsg apthelper download-file "https://localhost:4433/$TESTFILE" ./downloaded/https-$TESTFILE $OPT -o Acquire::https::Dl-Limit=800 +assertprogress apt-progress.log # cleanup rm -f apt-progress*.log diff --git a/test/integration/test-apt-helper b/test/integration/test-apt-helper index 431210797..00d859ad5 100755 --- a/test/integration/test-apt-helper +++ b/test/integration/test-apt-helper @@ -14,32 +14,32 @@ test_apt_helper_download() { echo 'bar' > aptarchive/foo2 msgtest 'apt-file download-file md5sum' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 - testfileequal foo2 'foo' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo2 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 + testfileequal ./downloaded/foo2 'foo' msgtest 'apt-file download-file sha1' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 - testfileequal foo1 'foo' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo1 SHA1:f1d2d2f924e986ac86fdf7b36c94bcdf32beec15 + testfileequal ./downloaded/foo1 'foo' msgtest 'apt-file download-file sha256' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c - testfileequal foo3 'foo' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo3 SHA256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c + testfileequal ./downloaded/foo3 'foo' msgtest 'apt-file download-file no-hash' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo4 - testfileequal foo4 'foo' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo4 + testfileequal ./downloaded/foo4 'foo' msgtest 'apt-file download-file wrong hash' - testfailure --nomsg apthelper -qq download-file http://localhost:8080/foo foo5 MD5Sum:aabbcc + testfailure --nomsg apthelper -qq download-file http://localhost:8080/foo ./downloaded/foo5 MD5Sum:aabbcc testfileequal rootdir/tmp/testfailure.output 'E: Failed to fetch http://localhost:8080/foo Hash Sum mismatch E: Download Failed' - testfileequal foo5.FAILED 'foo' + testfileequal ./downloaded/foo5.FAILED 'foo' msgtest 'apt-file download-file md5sum sha1' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo foo6 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 http://localhost:8080/foo2 foo7 SHA1:e242ed3bffccdf271b7fbaf34ed72d089537b42f - testfileequal foo6 'foo' - testfileequal foo7 'bar' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo6 MD5Sum:d3b07384d113edec49eaa6238ad5ff00 http://localhost:8080/foo2 ./downloaded/foo7 SHA1:e242ed3bffccdf271b7fbaf34ed72d089537b42f + testfileequal ./downloaded/foo6 'foo' + testfileequal ./downloaded/foo7 'bar' } test_apt_helper_detect_proxy() { -- cgit v1.2.3-70-g09d2 From 4f51fd8636592a96aecf17c8bf4cfdb3ea2207cc Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 00:06:41 +0200 Subject: support hashes for compressed pdiff files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At the moment we only have hashes for the uncompressed pdiff files, but via the new '$HASH-Download' field in the .diff/Index hashes can be provided for the .gz compressed pdiff file, which apt will pick up now and use to verify the download. Now, we "just" need a buy in from the creators of repositories… --- apt-pkg/acquire-item.cc | 72 ++++++++++++++++++++++++++++++++------- apt-pkg/acquire-item.h | 11 +++--- apt-pkg/contrib/hashes.cc | 11 ++++-- apt-pkg/contrib/hashes.h | 7 ++++ apt-pkg/indexrecords.cc | 4 +-- methods/rred.cc | 2 +- test/integration/test-pdiff-usage | 46 +++++++++++++++++++++++-- 7 files changed, 125 insertions(+), 28 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 7b69ee993..a3f47242f 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -152,14 +152,18 @@ HashStringList pkgAcqMetaBase::GetExpectedHashes() const APT_CONST bool pkgAcqIndexDiffs::HashesRequired() const { - /* FIXME: We have only hashes for uncompressed pdiffs. - rred uncompresses them on the fly while parsing. - In StateFetchDiff state we also uncompress on the fly for hash check. - Hashes are checked while searching for (next) patch to apply. */ + /* We don't always have the diff of the downloaded pdiff file. + What we have for sure is hashes for the uncompressed file, + but rred uncompresses them on the fly while parsing, so not handled here. + Hashes are (also) checked while searching for (next) patch to apply. */ + if (State == StateFetchDiff) + return available_patches[0].download_hashes.empty() == false; return false; } HashStringList pkgAcqIndexDiffs::GetExpectedHashes() const { + if (State == StateFetchDiff) + return available_patches[0].download_hashes; return HashStringList(); } @@ -168,11 +172,15 @@ APT_CONST bool pkgAcqIndexMergeDiffs::HashesRequired() const /* @see #pkgAcqIndexDiffs::HashesRequired, with the difference that we can check the rred result after all patches are applied as we know the expected result rather than potentially apply more patches */ + if (State == StateFetchDiff) + return patch.download_hashes.empty() == false; return State == StateApplyDiff; } HashStringList pkgAcqIndexMergeDiffs::GetExpectedHashes() const { - if (State == StateApplyDiff) + if (State == StateFetchDiff) + return patch.download_hashes; + else if (State == StateApplyDiff) return GetExpectedHashesFor(Target->MetaKey); return HashStringList(); } @@ -1618,7 +1626,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ std::vector::iterator cur = available_patches.begin(); for (; cur != available_patches.end(); ++cur) { - if (cur->file != filename || unlikely(cur->result_size != size)) + if (cur->file != filename) continue; cur->result_hashes.push_back(HashString(*type, hash)); break; @@ -1630,8 +1638,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ DiffInfo next; next.file = filename; next.result_hashes.push_back(HashString(*type, hash)); - next.result_size = size; - next.patch_size = 0; + next.result_hashes.FileSize(size); available_patches.push_back(next); } else @@ -1679,10 +1686,9 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ { if (cur->file != filename) continue; - if (unlikely(cur->patch_size != 0 && cur->patch_size != size)) - continue; + if (cur->patch_hashes.empty()) + cur->patch_hashes.FileSize(size); cur->patch_hashes.push_back(HashString(*type, hash)); - cur->patch_size = size; break; } if (cur != available_patches.end()) @@ -1694,6 +1700,48 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ } } + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) + { + std::string tagname = *type; + tagname.append("-Download"); + std::string const tmp = Tags.FindS(tagname.c_str()); + if (tmp.empty() == true) + continue; + + string hash, filename; + unsigned long long size; + std::stringstream ss(tmp); + + // FIXME: all of pdiff supports only .gz compressed patches + while (ss >> hash >> size >> filename) + { + if (unlikely(hash.empty() == true || filename.empty() == true)) + continue; + if (unlikely(APT::String::Endswith(filename, ".gz") == false)) + continue; + filename.erase(filename.length() - 3); + + // see if we have a record for this file already + std::vector::iterator cur = available_patches.begin(); + for (; cur != available_patches.end(); ++cur) + { + if (cur->file != filename) + continue; + if (cur->download_hashes.empty()) + cur->download_hashes.FileSize(size); + cur->download_hashes.push_back(HashString(*type, hash)); + break; + } + if (cur != available_patches.end()) + continue; + if (Debug == true) + std::clog << "pkgAcqDiffIndex: " << IndexDiffFile << ": File " << filename + << " wasn't in the list for the first parsed hash! (download)" << std::endl; + break; + } + } + + bool foundStart = false; for (std::vector::iterator cur = available_patches.begin(); cur != available_patches.end(); ++cur) @@ -1729,7 +1777,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ unsigned long long patchesSize = 0; for (std::vector::const_iterator cur = available_patches.begin(); cur != available_patches.end(); ++cur) - patchesSize += cur->patch_size; + patchesSize += cur->patch_hashes.FileSize(); unsigned long long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100); if (sizeLimit > 0 && (sizeLimit/100) < patchesSize) { diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index f24af1aec..910e4131b 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -705,17 +705,14 @@ struct APT_HIDDEN DiffInfo { /*{{{*/ /** The filename of the diff. */ std::string file; - /** The hashes of the diff */ + /** The hashes of the file after the diff is applied */ HashStringList result_hashes; - /** The hashes of the file after the diff is applied */ + /** The hashes of the diff */ HashStringList patch_hashes; - /** The size of the file after the diff is applied */ - unsigned long long result_size; - - /** The size of the diff itself */ - unsigned long long patch_size; + /** The hashes of the compressed diff */ + HashStringList download_hashes; }; /*}}}*/ /** \brief An item that is responsible for fetching client-merge patches {{{ diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 11a7e479b..46cf0ba08 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -188,6 +188,13 @@ unsigned long long HashStringList::FileSize() const /*{{{*/ return strtoull(hv.c_str(), NULL, 10); } /*}}}*/ +bool HashStringList::FileSize(unsigned long long const Size) /*{{{*/ +{ + std::string size; + strprintf(size, "%llu", Size); + return push_back(HashString("Checksum-FileSize", size)); +} + /*}}}*/ bool HashStringList::supported(char const * const type) /*{{{*/ { for (char const * const * t = HashString::SupportedHashes(); *t != NULL; ++t) @@ -361,9 +368,7 @@ APT_IGNORE_DEPRECATED_PUSH if ((d->CalcHashes & SHA512SUM) == SHA512SUM) hashes.push_back(HashString("SHA512", SHA512.Result().Value())); APT_IGNORE_DEPRECATED_POP - std::string SizeStr; - strprintf(SizeStr, "%llu", d->FileSize); - hashes.push_back(HashString("Checksum-FileSize", SizeStr)); + hashes.FileSize(d->FileSize); return hashes; } APT_IGNORE_DEPRECATED_PUSH diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index 176ce4faa..e8d84da9e 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -96,6 +96,13 @@ class HashStringList */ unsigned long long FileSize() const; + /** sets the filesize hash + * + * @param Size of the file + * @return @see #push_back + */ + bool FileSize(unsigned long long const Size); + /** check if the given hash type is supported * * @param type to check diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index c26868cac..7e6da9558 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -121,9 +121,7 @@ bool indexRecords::Load(const string Filename) /*{{{*/ indexRecords::checkSum *Sum = new indexRecords::checkSum; Sum->MetaKeyFilename = Name; Sum->Size = Size; - std::string SizeStr; - strprintf(SizeStr, "%llu", Size); - Sum->Hashes.push_back(HashString("Checksum-FileSize", SizeStr)); + Sum->Hashes.FileSize(Size); APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) Entries[Name] = Sum; } diff --git a/methods/rred.cc b/methods/rred.cc index 81ecf8553..12cf2b4a5 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -627,7 +627,7 @@ class RredMethod : public pkgAcqMethod { p.Close(); HashStringList const hsl = patch_hash.GetHashStringList(); if (hsl != I->ExpectedHashes) - return _error->Error("Patch %s doesn't have the expected hashsum", patch_name.c_str()); + return _error->Error("Hash Sum mismatch for uncompressed patch %s", patch_name.c_str()); } if (Debug == true) diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index 7a9f6496b..3295d5497 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -42,6 +42,8 @@ wasmergeused() { testrun() { msgmsg "Testcase: setup the base with: $*" + local DOWNLOADHASH=true + if [ "$1" = 'nohash' ]; then DOWNLOADHASH=false; shift; fi find aptarchive -name 'Packages*' -type f -delete cp ${PKGFILE} aptarchive/Packages compressfile 'aptarchive/Packages' @@ -76,6 +78,15 @@ SHA256-History: SHA256-Patches: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 19722 2010-08-18-2013.28 $(sha256sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX + if $DOWNLOADHASH; then + echo "SHA1-Download: + 2365ac0ac57cde3d43c63145e8251a3bd5410213 197 2010-08-18-2013.28.gz + $(sha1sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz) +SHA256-Download: + d2a1b33187ed2d248eeae3b1223ea71791ea35f2138a713ed371332a6421f467 197 2010-08-18-2013.28.gz + $(sha256sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz)" >> $PATCHINDEX + fi + generatereleasefiles '+1hour' signreleasefiles find aptarchive -name 'Packages*' -type f -delete @@ -131,6 +142,17 @@ SHA256-Patches: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 19722 2010-08-18-2013.28 $(sha256sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE) $(sha256sum ${PATCHFILE2} | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE2}) $(basename ${PATCHFILE2})" > $PATCHINDEX + if $DOWNLOADHASH; then + echo "SHA1-Download: + 2365ac0ac57cde3d43c63145e8251a3bd5410213 197 2010-08-18-2013.28.gz + $(sha1sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz) + $(sha1sum ${PATCHFILE2}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE2}.gz) $(basename ${PATCHFILE2}.gz) +SHA256-Download: + d2a1b33187ed2d248eeae3b1223ea71791ea35f2138a713ed371332a6421f467 197 2010-08-18-2013.28.gz + $(sha256sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz) + $(sha256sum ${PATCHFILE2}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE2}.gz) $(basename ${PATCHFILE2}.gz)" >> $PATCHINDEX + fi + generatereleasefiles '+2hour' signreleasefiles cp -a aptarchive/Packages Packages-future @@ -150,6 +172,7 @@ SHA256-Patches: mkdir -p aptarchive/Packages.diff PATCHFILE="aptarchive/Packages.diff/$(date +%Y-%m-%d-%H%M.%S)" diff -e ${PKGFILE} ${PKGFILE}-new > ${PATCHFILE} || true + cat $PATCHFILE | gzip > ${PATCHFILE}.gz PATCHINDEX='aptarchive/Packages.diff/Index' echo "SHA1-Current: $(sha1sum ${PKGFILE}-new | cut -d' ' -f 1) $(stat -c%s ${PKGFILE}-new) SHA1-History: @@ -165,14 +188,22 @@ SHA256-History: SHA256-Patches: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 19722 2010-08-18-2013.28 $(sha256sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE) $(basename $PATCHFILE)" > $PATCHINDEX + if $DOWNLOADHASH; then + echo "SHA1-Download: + 2365ac0ac57cde3d43c63145e8251a3bd5410213 197 2010-08-18-2013.28.gz + $(sha1sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz) +SHA256-Download: + d2a1b33187ed2d248eeae3b1223ea71791ea35f2138a713ed371332a6421f467 197 2010-08-18-2013.28.gz + $(sha256sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz) $(basename ${PATCHFILE}.gz)" >> $PATCHINDEX + fi # needs to look like a valid command, otherwise the parser will fail before hashes are checked - echo '1d' >> $PATCHFILE + echo '1d' > $PATCHFILE cat $PATCHFILE | gzip > ${PATCHFILE}.gz generatereleasefiles '+1hour' signreleasefiles testsuccess aptget update "$@" cp -f rootdir/tmp/testsuccess.output rootdir/tmp/aptgetupdate.output - testsuccess grep 'have the expected hashsum' rootdir/tmp/aptgetupdate.output + testsuccess grep 'Hash Sum mismatch' rootdir/tmp/aptgetupdate.output testnopackage oldstuff testsuccessequal "$(cat ${PKGFILE}-new) " aptcache show apt newstuff @@ -201,6 +232,14 @@ SHA256-History: SHA256-Patches: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 19722 2010-08-18-2013.28 $(sha256sum $PATCHFILE | cut -d' ' -f 1) $(stat -c%s $PATCHFILE)000 $(basename $PATCHFILE)" > $PATCHINDEX + if $DOWNLOADHASH; then + echo "SHA1-Download: + 2365ac0ac57cde3d43c63145e8251a3bd5410213 197 2010-08-18-2013.28.gz + $(sha1sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz)000 $(basename ${PATCHFILE}.gz) +SHA256-Download: + d2a1b33187ed2d248eeae3b1223ea71791ea35f2138a713ed371332a6421f467 197 2010-08-18-2013.28.gz + $(sha256sum ${PATCHFILE}.gz | cut -d' ' -f 1) $(stat -c%s ${PATCHFILE}.gz)000 $(basename ${PATCHFILE}.gz)" >> $PATCHINDEX + fi generatereleasefiles '+1hour' signreleasefiles #find aptarchive -name 'Packages*' -type f -delete @@ -215,6 +254,9 @@ echo 'Debug::pkgAcquire::Diffs "true"; Debug::Acquire::Transaction "true"; Debug::pkgAcquire::rred "true";' > rootdir/etc/apt/apt.conf.d/rreddebug.conf +testrun nohash -o Acquire::PDiffs::Merge=0 -o APT::Get::List-Cleanup=1 +testrun nohash -o Acquire::PDiffs::Merge=1 -o APT::Get::List-Cleanup=1 + testrun -o Acquire::PDiffs::Merge=0 -o APT::Get::List-Cleanup=1 testrun -o Acquire::PDiffs::Merge=1 -o APT::Get::List-Cleanup=1 testrun -o Acquire::PDiffs::Merge=0 -o APT::Get::List-Cleanup=0 -- cgit v1.2.3-70-g09d2 From 8d041b4f4f353079268039dcbfd8b5e575196b66 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 8 Jun 2015 15:22:01 +0200 Subject: do not request files if we expect an IMS hit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have a file on disk and the hashes are the same in the new Release file and the old one we have on disk we know that if we ask the server for the file, we will at best get an IMS hit – at worse the server doesn't support this and sends us the (unchanged) file and we have to run all our checks on it again for nothing. So, we can save ourselves (and the servers) some unneeded requests if we figure this out on our own. --- apt-pkg/acquire-item.cc | 77 ++++++++++++++-------- test/integration/framework | 4 +- test/integration/test-apt-update-expected-size | 4 +- test/integration/test-apt-update-file | 25 +++++-- test/integration/test-apt-update-not-modified | 19 ++++++ test/integration/test-apt-update-rollback | 6 +- test/integration/test-apt-update-transactions | 24 +++++-- .../test-cve-2013-1051-InRelease-parsing | 13 ++-- 8 files changed, 127 insertions(+), 45 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 13e971e9f..511bbbc64 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -119,6 +119,16 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser return false; } /*}}}*/ +static HashStringList GetExpectedHashesFromFor(indexRecords * const Parser, std::string const MetaKey)/*{{{*/ +{ + if (Parser == NULL) + return HashStringList(); + indexRecords::checkSum * const R = Parser->Lookup(MetaKey); + if (R == NULL) + return HashStringList(); + return R->Hashes; +} + /*}}}*/ // all ::HashesRequired and ::GetExpectedHashes implementations /*{{{*/ /* ::GetExpectedHashes is abstract and has to be implemented by all subclasses. @@ -372,6 +382,25 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) } /*}}}*/ +class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ +/* The sole purpose of this class is having an item which does nothing to + reach its done state to prevent cleanup deleting the mentioned file. + Handy in cases in which we know we have the file already, like IMS-Hits. */ +{ + IndexTarget const * const Target; + public: + virtual std::string DescURI() const {return Target->URI;}; + virtual HashStringList GetExpectedHashes() const {return HashStringList();}; + + NoActionItem(pkgAcquire * const Owner, IndexTarget const * const Target) : + pkgAcquire::Item(Owner), Target(Target) + { + Status = StatDone; + DestFile = GetFinalFileNameFromURI(Target->URI); + } +}; + /*}}}*/ + // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH pkgAcquire::Item::Item(pkgAcquire * const Owner) : @@ -644,12 +673,7 @@ pkgAcqTransactionItem::~pkgAcqTransactionItem() /*{{{*/ /*}}}*/ HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const MetaKey) const /*{{{*/ { - if (TransactionManager->MetaIndexParser == NULL) - return HashStringList(); - indexRecords::checkSum * const R = TransactionManager->MetaIndexParser->Lookup(MetaKey); - if (R == NULL) - return HashStringList(); - return R->Hashes; + return GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, MetaKey); } /*}}}*/ @@ -939,6 +963,23 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ return; } + if (RealFileExists(GetFinalFileNameFromURI((*Target)->URI))) + { + if (TransactionManager->LastMetaIndexParser != NULL) + { + HashStringList const newFile = GetExpectedHashesFromFor(TransactionManager->MetaIndexParser, (*Target)->MetaKey); + HashStringList const oldFile = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, (*Target)->MetaKey); + if (newFile == oldFile) + { + // we have the file already, no point in trying to acquire it again + new NoActionItem(Owner, *Target); + continue; + } + } + } + else + trypdiff = false; // no file to patch + // check if we have patches available trypdiff &= TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey + ".diff/Index"); } @@ -1085,20 +1126,6 @@ string pkgAcqMetaClearSig::Custom600Headers() const } /*}}}*/ // pkgAcqMetaClearSig::Done - We got a file /*{{{*/ -class APT_HIDDEN DummyItem : public pkgAcquire::Item -{ - IndexTarget const * const Target; - public: - virtual std::string DescURI() const {return Target->URI;}; - virtual HashStringList GetExpectedHashes() const {return HashStringList();}; - - DummyItem(pkgAcquire * const Owner, IndexTarget const * const Target) : - pkgAcquire::Item(Owner), Target(Target) - { - Status = StatDone; - DestFile = GetFinalFileNameFromURI(Target->URI); - } -}; void pkgAcqMetaClearSig::Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf) @@ -1131,8 +1158,8 @@ void pkgAcqMetaClearSig::Done(std::string const &Message, // We got an InRelease file IMSHit, but we haven't one, which means // we had a valid Release/Release.gpg combo stepping in, which we have // to 'acquire' now to ensure list cleanup isn't removing them - new DummyItem(Owner, &DetachedDataTarget); - new DummyItem(Owner, &DetachedSigTarget); + new NoActionItem(Owner, &DetachedDataTarget); + new NoActionItem(Owner, &DetachedSigTarget); } } } @@ -1578,11 +1605,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ HashStringList LocalHashes; // try avoiding calculating the hash here as this is costly if (TransactionManager->LastMetaIndexParser != NULL) - { - indexRecords::checkSum * const R = TransactionManager->LastMetaIndexParser->Lookup(Target->MetaKey); - if (R != NULL) - LocalHashes = R->Hashes; - } + LocalHashes = GetExpectedHashesFromFor(TransactionManager->LastMetaIndexParser, Target->MetaKey); if (LocalHashes.usable() == false) { FileFd fd(CurrentPackagesFile, FileFd::ReadOnly); diff --git a/test/integration/framework b/test/integration/framework index b253deb91..56c4a1216 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -835,7 +835,9 @@ buildaptarchivefromincoming() { buildaptarchivefromfiles() { msginfo "Build APT archive for ${CCMD}$(basename $0)${CINFO} based on prebuild files…" - find aptarchive -name 'Packages' -o -name 'Sources' -o -name 'Translation-*' | while read line; do + local DIR='aptarchive' + if [ -d "${DIR}/dists" ]; then DIR="${DIR}/dists"; fi + find "$DIR" -name 'Packages' -o -name 'Sources' -o -name 'Translation-*' | while read line; do msgninfo "\t${line} file… " compressfile "$line" "$1" msgdone "info" diff --git a/test/integration/test-apt-update-expected-size b/test/integration/test-apt-update-expected-size index 55bba8188..24ca85133 100755 --- a/test/integration/test-apt-update-expected-size +++ b/test/integration/test-apt-update-expected-size @@ -26,7 +26,9 @@ test_inreleasetoobig() { } test_packagestoobig() { - redatereleasefiles '+1hour' + insertpackage 'unstable' 'foo' 'all' '1.0' + buildaptarchivefromfiles '+1 hour' + signreleasefiles # append junk at the end of the Packages.gz/Packages SIZE="$(stat --printf=%s aptarchive/dists/unstable/main/binary-i386/Packages)" find aptarchive/dists -name 'Packages*' | while read pkg; do diff --git a/test/integration/test-apt-update-file b/test/integration/test-apt-update-file index 665f94fa5..94b604f0e 100755 --- a/test/integration/test-apt-update-file +++ b/test/integration/test-apt-update-file @@ -26,14 +26,29 @@ testsuccess aptget update # the release files aren't an IMS-hit, but the indexes are redatereleasefiles '+1 hour' +# we don't download the index if it isn't updated testsuccess aptget update -o Debug::pkgAcquire::Auth=1 +# file:/ isn't shown in the log, so see if it was downloaded anyhow cp -a rootdir/tmp/testsuccess.output rootdir/tmp/update.output +canary="SHA512:$(bzcat aptarchive/dists/unstable/main/binary-amd64/Packages.bz2 | sha512sum |cut -f1 -d' ')" +testfailure grep -- "$canary" rootdir/tmp/update.output + +testfoo() { + # foo is still available + testsuccess aptget install -s foo + testsuccess aptcache showsrc foo + testsuccess aptget source foo --print-uris +} +testfoo + +# the release file is new again, the index still isn't, but it is somehow gone now from disk +redatereleasefiles '+2 hour' +find rootdir/var/lib/apt/lists -name '*_Packages*' -delete -# ensure that the hash of the uncompressed file was verified even on a local ims hit +testsuccess aptget update -o Debug::pkgAcquire::Auth=1 +# file:/ isn't shown in the log, so see if it was downloaded anyhow +cp -a rootdir/tmp/testsuccess.output rootdir/tmp/update.output canary="SHA512:$(bzcat aptarchive/dists/unstable/main/binary-amd64/Packages.bz2 | sha512sum |cut -f1 -d' ')" testsuccess grep -- "$canary" rootdir/tmp/update.output -# foo is still available -testsuccess aptget install -s foo -testsuccess aptcache showsrc foo -testsuccess aptget source foo --print-uris +testfoo diff --git a/test/integration/test-apt-update-not-modified b/test/integration/test-apt-update-not-modified index a490f00de..32818658f 100755 --- a/test/integration/test-apt-update-not-modified +++ b/test/integration/test-apt-update-not-modified @@ -133,6 +133,25 @@ Reading package lists..." aptget update rm -rf aptarchive/dists cp -a aptarchive/dists.good aptarchive/dists + + # new release file, but the indexes are the same + redatereleasefiles '+2 hours' + + rm -rf rootdir/var/lib/apt/lists.good + cp -a rootdir/var/lib/apt/lists rootdir/var/lib/apt/lists.good + testsuccessequal "Get:1 $1 unstable InRelease [$(stat -c '%s' 'aptarchive/dists/unstable/InRelease') B] +Reading package lists..." aptget update + + rm -rf rootdir/var/lib/apt/lists + cp -a rootdir/var/lib/apt/lists.good rootdir/var/lib/apt/lists + find rootdir/var/lib/apt/lists -name '*_Packages*' -delete + testsuccessequal "Get:1 $1 unstable InRelease [$(stat -c '%s' 'aptarchive/dists/unstable/InRelease') B] +Get:2 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] +Get:3 $1 unstable/main i386 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-i386/Packages.gz') B] +Reading package lists..." aptget update + + rm -rf aptarchive/dists + cp -a aptarchive/dists.good aptarchive/dists } changetowebserver diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback index 6fd901715..6ecf322b2 100755 --- a/test/integration/test-apt-update-rollback +++ b/test/integration/test-apt-update-rollback @@ -158,7 +158,10 @@ test_inrelease_to_broken_gzip() { msgmsg "Test InRelease to broken gzip" start_with_good_inrelease - redatereleasefiles '+2hours' + break_repository_sources_index '+1hour' + generatereleasefiles '+2hours' + signreleasefiles + # append junk at the end of the compressed file echo "lala" >> $APTARCHIVE/dists/unstable/main/source/Sources.gz touch -d '+2min' $APTARCHIVE/dists/unstable/main/source/Sources.gz @@ -166,6 +169,7 @@ test_inrelease_to_broken_gzip() { rm $APTARCHIVE/dists/unstable/main/source/Sources testfailure aptget update + testsuccess grep 'Hash Sum mismatch' rootdir/tmp/testfailure.output testfileequal lists.before "$(listcurrentlistsdirectory)" } diff --git a/test/integration/test-apt-update-transactions b/test/integration/test-apt-update-transactions index 152e1617a..a5dac1737 100755 --- a/test/integration/test-apt-update-transactions +++ b/test/integration/test-apt-update-transactions @@ -29,6 +29,12 @@ restorefile() { } testrun() { + rm -rf aptarchive/dists.good + cp -a aptarchive/dists aptarchive/dists.good + insertpackage 'unstable' 'bar' 'all' '1.0' + insertsource 'unstable' 'bar' 'all' '1.0' + buildaptarchivefromfiles '+1 hour' + # produce an unsigned repository find aptarchive \( -name 'Release.gpg' -o -name 'InRelease' \) -delete testfailure aptget update --no-allow-insecure-repositories @@ -37,20 +43,27 @@ testrun() { # signed but broken signreleasefiles + onehashbroken() { + testfailure aptget update + # each file generates two messages with this string + testequal '2' grep --count 'Hash Sum mismatch' rootdir/tmp/testfailure.output + testfileequal "$1" "$(listcurrentlistsdirectory)" + } + breakfile aptarchive/dists/unstable/main/binary-i386/Packages - testfailure aptget update - testfileequal "$1" "$(listcurrentlistsdirectory)" + onehashbroken "$1" restorefile aptarchive/dists/unstable/main/binary-i386/Packages breakfile aptarchive/dists/unstable/main/source/Sources - testfailure aptget update - testfileequal "$1" "$(listcurrentlistsdirectory)" + onehashbroken "$1" restorefile aptarchive/dists/unstable/main/source/Sources + + rm -rf aptarchive/dists + cp -a aptarchive/dists.good aptarchive/dists } testsetup() { msgmsg 'Test with no initial data over' "$1" - redatereleasefiles 'now' rm -rf rootdir/var/lib/apt/lists mkdir -p rootdir/var/lib/apt/lists/partial listcurrentlistsdirectory > listsdir.lst @@ -60,7 +73,6 @@ testsetup() { rm -rf rootdir/var/lib/apt/lists testsuccess aptget update -o Debug::pkgAcquire::Worker=1 listcurrentlistsdirectory > listsdir.lst - redatereleasefiles '+1hour' testrun 'listsdir.lst' } diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing index e38e40cc9..d99174553 100755 --- a/test/integration/test-cve-2013-1051-InRelease-parsing +++ b/test/integration/test-cve-2013-1051-InRelease-parsing @@ -39,10 +39,15 @@ sed -i '/^-----BEGIN PGP SIGNATURE-----/,/^-----END PGP SIGNATURE-----/ s/^$/ / cat aptarchive/dists/stable/Release >> aptarchive/dists/stable/InRelease touch -d '+1hour' aptarchive/dists/stable/InRelease -# ensure the update fails -# useful for debugging to add "-o Debug::pkgAcquire::auth=true" -msgtest 'apt-get update for should fail with the modified' 'InRelease' -aptget update 2>&1 | grep -E -q '(Writing more data than expected|Hash Sum mismatch)' > /dev/null && msgpass || msgfail +# ensure the update doesn't load bad data as good data +# Note that we will pick up the InRelease itself as we download no other +# indexes which would trigger a hashsum mismatch, but we ignore the 'bad' +# part of the InRelease +listcurrentlistsdirectory | sed '/_InRelease/ d' > listsdir.lst +msgtest 'apt-get update should ignore unsigned data in the' 'InRelease' +testsuccessequal "Get:1 http://localhost:8080 stable InRelease [$(stat -c%s aptarchive/dists/stable/InRelease) B] +Reading package lists..." --nomsg aptget update +testfileequal './listsdir.lst' "$(listcurrentlistsdirectory | sed '/_InRelease/ d')" # ensure there is no package testfailureequal 'Reading package lists... -- cgit v1.2.3-70-g09d2 From 1e0f0f28e1025f42a8172eb72f3e87984eb2b939 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 9 Jun 2015 11:59:22 +0200 Subject: configureable acquire targets to download additional files First pass at making the acquire system capable of downloading files based on configuration rather than hardcoded entries. It is now possible to instruct 'deb' and 'deb-src' sources.list lines to download more than just Packages/Translation-* and Sources files. Details on how to do that can be found in the included documentation file. --- apt-pkg/contrib/configuration.cc | 4 +- apt-pkg/contrib/configuration.h | 11 +- apt-pkg/deb/debmetaindex.cc | 317 ++++++++++----------- apt-pkg/deb/debmetaindex.h | 8 - apt-pkg/init.cc | 20 +- doc/acquire-additional-files.txt | 142 +++++++++ test/integration/test-apt-acquire-additional-files | 54 ++++ test/integration/test-apt-by-hash-update | 12 +- 8 files changed, 376 insertions(+), 192 deletions(-) create mode 100644 doc/acquire-additional-files.txt create mode 100755 test/integration/test-apt-acquire-additional-files (limited to 'test') diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc index 42e35d32a..2500ab631 100644 --- a/apt-pkg/contrib/configuration.cc +++ b/apt-pkg/contrib/configuration.cc @@ -259,7 +259,7 @@ vector Configuration::FindVector(const char *Name) const return FindVector(Name, ""); } #endif -vector Configuration::FindVector(const char *Name, std::string const &Default) const +vector Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const { vector Vec; const Item *Top = Lookup(Name); @@ -272,7 +272,7 @@ vector Configuration::FindVector(const char *Name, std::string const &De Item *I = Top->Child; while(I != NULL) { - Vec.push_back(I->Value); + Vec.push_back(Keys ? I->Tag : I->Value); I = I->Next; } if (Vec.empty() == true) diff --git a/apt-pkg/contrib/configuration.h b/apt-pkg/contrib/configuration.h index 8d7d51037..eacc26fda 100644 --- a/apt-pkg/contrib/configuration.h +++ b/apt-pkg/contrib/configuration.h @@ -84,15 +84,8 @@ class Configuration * * \param Name of the parent node * \param Default list of values separated by commas */ -#if APT_PKG_ABI >= 413 - std::vector FindVector(const char *Name, std::string const &Default = "") const; - std::vector FindVector(std::string const &Name, std::string const &Default = "") const { return FindVector(Name.c_str(), Default); }; -#else - std::vector FindVector(const char *Name, std::string const &Default) const; - std::vector FindVector(std::string const &Name, std::string const &Default) const { return FindVector(Name.c_str(), Default); }; - std::vector FindVector(const char *Name) const; - std::vector FindVector(std::string const &Name) const { return FindVector(Name.c_str(), ""); }; -#endif + std::vector FindVector(const char *Name, std::string const &Default = "", bool const Keys = false) const; + std::vector FindVector(std::string const &Name, std::string const &Default = "", bool const Keys = false) const { return FindVector(Name.c_str(), Default, Keys); }; int FindI(const char *Name,int const &Default = 0) const; int FindI(std::string const &Name,int const &Default = 0) const {return FindI(Name.c_str(),Default);}; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index eb5e78e3b..8fef05ab0 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -23,25 +23,6 @@ using namespace std; -string debReleaseIndex::Info(const char *Type, string const &Section, string const &Arch) const -{ - string Info = ::URI::SiteOnly(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - { - Info += Dist + '/' + Section; - if (Arch.empty() != true) - Info += " " + Arch; - } - Info += " "; - Info += Type; - return Info; -} - string debReleaseIndex::MetaIndexInfo(const char *Type) const { string Info = ::URI::SiteOnly(URI) + ' '; @@ -92,81 +73,6 @@ std::string debReleaseIndex::LocalFileName() const return ""; } -string debReleaseIndex::IndexURISuffix(const char *Type, string const &Section, string const &Arch) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - { - if (Arch == "native") - Res += Section + "/binary-" + _config->Find("APT::Architecture") + '/'; - else - Res += Section + "/binary-" + Arch + '/'; - } - return Res + Type; -} - - -string debReleaseIndex::IndexURI(const char *Type, string const &Section, string const &Arch) const -{ - if (Dist[Dist.size() - 1] == '/') - { - string Res; - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + '/' + IndexURISuffix(Type, Section, Arch); - } - -string debReleaseIndex::SourceIndexURISuffix(const char *Type, const string &Section) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/source/"; - return Res + Type; -} - -string debReleaseIndex::SourceIndexURI(const char *Type, const string &Section) const -{ - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + "/" + SourceIndexURISuffix(Type, Section); -} - -string debReleaseIndex::TranslationIndexURISuffix(const char *Type, const string &Section) const -{ - string Res =""; - if (Dist[Dist.size() - 1] != '/') - Res += Section + "/i18n/Translation-"; - return Res + Type; -} - -string debReleaseIndex::TranslationIndexURI(const char *Type, const string &Section) const -{ - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - return Res + Type; - } - else - return URI + "dists/" + Dist + "/" + TranslationIndexURISuffix(Type, Section); -} - debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) : metaIndex(URI, Dist, "deb"), Trusted(CHECK_TRUST) {} @@ -184,73 +90,161 @@ debReleaseIndex::~debReleaseIndex() { delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const { - vector * IndexTargets = new vector ; +vector * debReleaseIndex::ComputeIndexTargets() const +{ + vector * IndexTargets = new vector ; - map >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) { - char const * const ShortDesc = "Sources"; - IndexTarget * const Target = new IndexTarget( - SourceIndexURISuffix(ShortDesc, (*I)->Section), - ShortDesc, - Info(ShortDesc, (*I)->Section), - SourceIndexURI(ShortDesc, (*I)->Section) - ); - IndexTargets->push_back (Target); - } - } + bool const flatArchive = (Dist[Dist.length() - 1] == '/'); + std::string baseURI = URI; + if (flatArchive) + { + if (Dist != "/") + baseURI += Dist; + } + else + baseURI += "dists/" + Dist + "/"; + std::string const Release = (Dist == "/") ? "" : Dist; + std::string const Site = ::URI::SiteOnly(URI); + std::vector lang = APT::Configuration::getLanguages(true); + if (lang.empty()) + lang.push_back("none"); + map >::const_iterator const src = ArchEntries.find("source"); + if (src != ArchEntries.end()) + { + std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true); + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + { +#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X)) + std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); +#undef APT_T_CONFIG + if (URI.empty()) + continue; - // Only source release - if (IndexTargets->empty() == false && ArchEntries.size() == 1) - return IndexTargets; + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); + I != SectionEntries.end(); ++I) + { + for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) + { + if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + continue; + + struct SubstVar subst[] = { + { "$(SITE)", &Site }, + { "$(RELEASE)", &Release }, + { "$(COMPONENT)", &((*I)->Section) }, + { "$(LANGUAGE)", &(*l) }, + { NULL, NULL } + }; + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + + if (URI.find("$(LANGUAGE)") == std::string::npos) + break; + } - std::set sections; - for (map >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector ::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - char const * const ShortDesc = "Packages"; - IndexTarget * const Target = new IndexTarget( - IndexURISuffix(ShortDesc, (*I)->Section, a->first), - ShortDesc, - Info (ShortDesc, (*I)->Section, a->first), - IndexURI(ShortDesc, (*I)->Section, a->first) - ); - IndexTargets->push_back (Target); - sections.insert((*I)->Section); - } - } + if (URI.find("$(COMPONENT)") == std::string::npos) + break; + } + } + } - std::vector lang = APT::Configuration::getLanguages(true); - std::vector::iterator lend = std::remove(lang.begin(), lang.end(), "none"); - if (lend != lang.end()) - lang.erase(lend); - - if (lang.empty() == true) - return IndexTargets; - - // get the Translation-* files, later we will skip download of non-existent if we have an index - for (std::set::const_iterator s = sections.begin(); - s != sections.end(); ++s) { - for (std::vector::const_iterator l = lang.begin(); - l != lang.end(); ++l) { - std::string const ShortDesc = "Translation-" + *l; - IndexTarget * const Target = new OptionalIndexTarget( - TranslationIndexURISuffix(l->c_str(), *s), - ShortDesc, - Info (ShortDesc.c_str(), *s), - TranslationIndexURI(l->c_str(), *s) - ); - IndexTargets->push_back(Target); - } - } + // Only source release + if (IndexTargets->empty() == false && ArchEntries.size() == 1) + return IndexTargets; - return IndexTargets; + std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true); + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + { +#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X)) + std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true); +#undef APT_T_CONFIG + if (URI.empty()) + continue; + + for (map >::const_iterator a = ArchEntries.begin(); + a != ArchEntries.end(); ++a) + { + if (a->first == "source") + continue; + + for (vector ::const_iterator I = a->second.begin(); + I != a->second.end(); ++I) { + + for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) + { + if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + continue; + + struct SubstVar subst[] = { + { "$(SITE)", &Site }, + { "$(RELEASE)", &Release }, + { "$(COMPONENT)", &((*I)->Section) }, + { "$(LANGUAGE)", &(*l) }, + { "$(ARCHITECTURE)", &(a->first) }, + { NULL, NULL } + }; + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + + if (URI.find("$(LANGUAGE)") == std::string::npos) + break; + } + + if (URI.find("$(COMPONENT)") == std::string::npos) + break; + } + + if (URI.find("$(ARCHITECTURE)") == std::string::npos) + break; + } + } + + return IndexTargets; } /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const @@ -361,17 +355,6 @@ void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry ArchEntries[Arch].push_back(Entry); } -void debReleaseIndex::PushSectionEntry(const debSectionEntry *Entry) { - if (Entry->IsSrc == true) - PushSectionEntry("source", Entry); - else { - for (map >::iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - a->second.push_back(Entry); - } - } -} - debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, bool const &IsSrc): Section(Section), IsSrc(IsSrc) {} diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 94d005760..e1c1d91ef 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -47,7 +47,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; std::vector * ComputeIndexTargets() const; - std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const; std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; @@ -58,12 +57,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { #endif std::string LocalFileName() const; - std::string IndexURI(const char *Type, std::string const &Section, std::string const &Arch="native") const; - std::string IndexURISuffix(const char *Type, std::string const &Section, std::string const &Arch="native") const; - std::string SourceIndexURI(const char *Type, const std::string &Section) const; - std::string SourceIndexURISuffix(const char *Type, const std::string &Section) const; - std::string TranslationIndexURI(const char *Type, const std::string &Section) const; - std::string TranslationIndexURISuffix(const char *Type, const std::string &Section) const; virtual std::vector *GetIndexFiles(); void SetTrusted(bool const Trusted); @@ -71,7 +64,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { void PushSectionEntry(std::vector const &Archs, const debSectionEntry *Entry); void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry); - void PushSectionEntry(const debSectionEntry *Entry); }; class APT_HIDDEN debDebFileMetaIndex : public metaIndex diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index f756eab26..50ea2b49e 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -101,8 +101,26 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::URI", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatURI", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::URI", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatURI", "$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::URI", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatURI", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + bool Res = true; - + // Read an alternate config file const char *Cfg = getenv("APT_CONFIG"); if (Cfg != 0 && strlen(Cfg) != 0) diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt new file mode 100644 index 000000000..5a07c2bec --- /dev/null +++ b/doc/acquire-additional-files.txt @@ -0,0 +1,142 @@ +# Acquire additional files in 'update' operations + +The download and verification of data from multiple sources in different +compression formats, with partial downloads and patches is an involved +process which is hard to implement correctly and securely. + +APT frontends share the code and binaries to make this happen in libapt +with the Acquire system, supported by helpers shipped in the apt package +itself and additional transports in individual packages like +apt-transport-https. + +For its own operation libapt needs or can make use of Packages, Sources +and Translation-* files, which it will acquire by default, but +a repository might contain more data files (e.g. Contents) a frontend +might want to use and would therefore need to be downloaded as well +(e.g. apt-file). + +This file describes the configuration scheme such a frontend can use to +instruct the Acquire system to download those additional files. + +Note that you can't download files from other sources. It must be files +in the same repository and below the Release file. The Release file must +also contain hashes for the file itself as well as for the compressed +file if wanted, otherwise a download isn't even tried! + + +# The Configuration Stanza + +The Acquire system uses the same configuration settings to implement the +files it downloads by default. These settings are the default, but if +they would be written in a configuration file the configuration +instructing the Acquire system to download the Packages files would look +like this (see also apt.conf(5) manpage for configuration file syntax): + + APT::Acquire::Targets::deb::Packages { + URI "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"; + ShortDescription "Packages"; + Description "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"; + + flatURI "Packages"; + flatDescription "$(SITE) $(RELEASE) Packages"; + + Optional "false"; + }; + +All files which should be downloaded (nicknamed 'Targets') are mentioned +below the APT::Acquire::Targets scope. 'deb' is here the type of the +sources.list entry the file should be acquired for. The only other +supported value is hence 'deb-src'. Beware: You can't specify multiple +types here and you can't download the same URI for multiple types! + +After the type you can pick any valid and unique string which preferable +refers to the file it downloads (In the example we picked 'Packages'). +This string is never shown or used. + +All targets have three main properties you can define: +* URI: The identifier of the file to be downloaded as used in the + Release file. It is also the relative location of the file from the + Release file. You can neither download from a different server + entirely (absolute URI) nor should you try to access directories above + the Release file (e.g. "../../"). +* ShortDescription: Very short string intended to be displayed to the + user e.g. while reporting progress. apt will e.g. use this string in + the last line to indicate progress of e.g. the download of a specific + item. +* Description: A preferable human understandable and readable identifier + of which file is acquired exactly. Mainly used for progress reporting + and error messages. apt will e.g. use this string in the Get/Hit/Err + progress lines. + +Additional optional properties: +* flat{URI,Description}: APT supports two types of repositories: + dists-style repositories which are the default and by far the most + common which are named after the fact that the files are in an + elaborated directory structure. In contrast a flat-style repositories + lumps all files together in one directory. Support for these flat + repositories exists mainly for legacy purposes only. It is therefore + recommend to not set these values. +* Optional: The default value is 'true' and should be kept at this + value. If enabled the acquire system will skip the download if the + file isn't mentioned in the Release file. Otherwise this is treated as + a hard error and the update process fails. + + +Note that the acquire system will automatically choose to download +a compressed file if it is available and uncompress it for you, just as +it will also use pdiff patching if provided by the repository and +enabled by the user. You only have to ensure that the Release file +contains the information about the compressed files/pdiffs to make this +happen. NO properties have to be set to enable this. + +# More examples + +The stanzas for Translation-* files as well as for Sources files would +look like this: + +APT::Acquire::Targets { + deb::Translations { + URI "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"; + ShortDescription "Translation-$(LANGUAGE)"; + Description "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"; + + flatURI "$(LANGUAGE)"; + flatDescription "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"; + }; + + deb-src::Sources { + URI "$(COMPONENT)/source/Sources"; + ShortDescription "Sources"; + Description "$(SITE) $(RELEASE)/$(COMPONENT) Sources"; + + flatURI "Sources"; + flatDescription "$(SITE) $(RELEASE) Sources"; + + Optional "false"; + }; +}; + +# Substitution variables + +As seen in the examples, properties can contain placeholders filled in +by the acquire system. The following variables are known; note that +unknown variables have no default value nor are they touched: They are +printed literally. + +* $(SITE): An identifier of the site we access, e.g. + "http://example.org/". +* $(RELEASE): This is usually an archive- or codename, e.g. "stable" or + "stretch". Note that flat-style repositories do not have a archive- + or codename per-se, so the value might very well be just "/" or so. +* $(COMPONENT): as given in the sources.list, e.g. "main", "non-free" or + "universe". Note that flat-style repositories again do not really + have a meaningful value here. +* $(LANGUAGE): Values are all entries (expect "none") of configuration + option Acquire::Languages, e.g. "en", "de" or "de_AT". + +These values are defined both for 'deb' as well as 'deb-src' targets. +'deb' targets additional have the variable: + +* $(ARCHITECTURE): Values are all entries of configuration option + APT::Architectures (potentially modified by sources.list options), + e.g. "amd64", "i386" or "armel". diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files new file mode 100755 index 000000000..150a50980 --- /dev/null +++ b/test/integration/test-apt-acquire-additional-files @@ -0,0 +1,54 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'amd64' +configcompression '.' 'gz' + +buildsimplenativepackage 'foo' 'amd64' '1' 'unstable' + +setupaptarchive --no-update +changetowebserver + +testsuccessequal "Get:1 http://localhost:8080 unstable InRelease [$(stat -c%s aptarchive/dists/unstable/InRelease) B] +Get:2 http://localhost:8080 unstable/main Sources [$(stat -c%s aptarchive/dists/unstable/main/source/Sources.gz) B] +Get:3 http://localhost:8080 unstable/main amd64 Packages [$(stat -c%s aptarchive/dists/unstable/main/binary-amd64/Packages.gz) B] +Get:4 http://localhost:8080 unstable/main Translation-en [$(stat -c%s aptarchive/dists/unstable/main/i18n/Translation-en.gz) B] +Reading package lists..." aptget update + +testempty find rootdir/var/lib/apt/lists -name '*Contents*' + +cat > rootdir/etc/apt/apt.conf.d/content-target.conf < rootdir/etc/apt/apt.conf.d/content-target.conf < Date: Wed, 10 Jun 2015 19:22:41 +0200 Subject: abstract the code to iterate over all targets a bit We have two places in the code which need to iterate over targets and do certain things with it. The first one is actually creating these targets for download and the second instance pepares certain targets for reading. Git-Dch: Ignore --- apt-pkg/deb/debmetaindex.cc | 197 +++++++++++---------- test/integration/framework | 7 +- test/integration/test-apt-acquire-additional-files | 33 ++++ 3 files changed, 142 insertions(+), 95 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8fef05ab0..c35f3b0a4 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -90,10 +90,11 @@ debReleaseIndex::~debReleaseIndex() { delete *S; } -vector * debReleaseIndex::ComputeIndexTargets() const +template +void foreachTarget(std::string const URI, std::string const Dist, + std::map > const &ArchEntries, + CallC Call) { - vector * IndexTargets = new vector ; - bool const flatArchive = (Dist[Dist.length() - 1] == '/'); std::string baseURI = URI; if (flatArchive) @@ -108,7 +109,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const std::vector lang = APT::Configuration::getLanguages(true); if (lang.empty()) lang.push_back("none"); - map >::const_iterator const src = ArchEntries.find("source"); + map >::const_iterator const src = ArchEntries.find("source"); if (src != ArchEntries.end()) { std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true); @@ -123,8 +124,8 @@ vector * debReleaseIndex::ComputeIndexTargets() const if (URI.empty()) continue; - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); + vector const SectionEntries = src->second; + for (vector::const_iterator I = SectionEntries.begin(); I != SectionEntries.end(); ++I) { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) @@ -139,27 +140,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const { "$(LANGUAGE)", &(*l) }, { NULL, NULL } }; - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else - { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - IndexTargets->push_back(Target); + Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); if (URI.find("$(LANGUAGE)") == std::string::npos) break; @@ -171,10 +152,6 @@ vector * debReleaseIndex::ComputeIndexTargets() const } } - // Only source release - if (IndexTargets->empty() == false && ArchEntries.size() == 1) - return IndexTargets; - std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true); for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { @@ -187,13 +164,13 @@ vector * debReleaseIndex::ComputeIndexTargets() const if (URI.empty()) continue; - for (map >::const_iterator a = ArchEntries.begin(); + for (map >::const_iterator a = ArchEntries.begin(); a != ArchEntries.end(); ++a) { if (a->first == "source") continue; - for (vector ::const_iterator I = a->second.begin(); + for (vector ::const_iterator I = a->second.begin(); I != a->second.end(); ++I) { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) @@ -209,27 +186,7 @@ vector * debReleaseIndex::ComputeIndexTargets() const { "$(ARCHITECTURE)", &(a->first) }, { NULL, NULL } }; - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else - { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - IndexTargets->push_back(Target); + Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); if (URI.find("$(LANGUAGE)") == std::string::npos) break; @@ -243,9 +200,51 @@ vector * debReleaseIndex::ComputeIndexTargets() const break; } } +} + + +struct ComputeIndexTargetsClass +{ + vector * const IndexTargets; + + void operator()(std::string const &baseURI, std::string const &/*TargetName*/, + std::string const &URI, std::string const &ShortDesc, std::string const &LongDesc, + bool const IsOptional, struct SubstVar const * const subst) + { + std::string const name = SubstVar(URI, subst); + IndexTarget * Target; + if (IsOptional == true) + { + Target = new OptionalIndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + else + { + Target = new IndexTarget( + name, + SubstVar(ShortDesc, subst), + SubstVar(LongDesc, subst), + baseURI + name + ); + } + IndexTargets->push_back(Target); + } - return IndexTargets; + ComputeIndexTargetsClass() : IndexTargets(new vector ) {} +}; + +vector * debReleaseIndex::ComputeIndexTargets() const +{ + ComputeIndexTargetsClass comp; + foreachTarget(URI, Dist, ArchEntries, comp); + return comp.IndexTargets; } + + /*}}}*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const { @@ -303,45 +302,55 @@ bool debReleaseIndex::IsTrusted() const return FileExists(VerifiedSigFile); } -vector *debReleaseIndex::GetIndexFiles() { - if (Indexes != NULL) - return Indexes; - - Indexes = new vector ; - map >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) { - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) - Indexes->push_back(new debSourcesIndex (URI, Dist, (*I)->Section, IsTrusted())); - } - - // Only source release - if (Indexes->empty() == false && ArchEntries.size() == 1) - return Indexes; - - std::vector const lang = APT::Configuration::getLanguages(true); - map > sections; - for (map >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) { - if (a->first == "source") - continue; - for (vector::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - Indexes->push_back(new debPackagesIndex (URI, Dist, (*I)->Section, IsTrusted(), a->first)); - sections[(*I)->Section].insert(lang.begin(), lang.end()); - } - } - - for (map >::const_iterator s = sections.begin(); - s != sections.end(); ++s) - for (set::const_iterator l = s->second.begin(); - l != s->second.end(); ++l) { - if (*l == "none") continue; - Indexes->push_back(new debTranslationsIndex(URI,Dist,s->first,(*l).c_str())); - } - - return Indexes; +struct GetIndexFilesClass +{ + vector * const Indexes; + std::string const URI; + std::string const Release; + bool const IsTrusted; + + void operator()(std::string const &/*baseURI*/, std::string const &TargetName, + std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, + bool const /*IsOptional*/, struct SubstVar const * const subst) + { + if (TargetName == "Packages") + { + Indexes->push_back(new debPackagesIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + IsTrusted, + SubstVar("$(ARCHITECTURE)", subst) + )); + } + else if (TargetName == "Sources") + Indexes->push_back(new debSourcesIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + IsTrusted + )); + else if (TargetName == "Translations") + Indexes->push_back(new debTranslationsIndex( + URI, + Release, + SubstVar("$(COMPONENT)", subst), + SubstVar("$(LANGUAGE)", subst) + )); + } + + GetIndexFilesClass(std::string const &URI, std::string const &Release, bool const IsTrusted) : + Indexes(new vector ), URI(URI), Release(Release), IsTrusted(IsTrusted) {} +}; + +std::vector *debReleaseIndex::GetIndexFiles() +{ + if (Indexes != NULL) + return Indexes; + + GetIndexFilesClass comp(URI, Dist, IsTrusted()); + foreachTarget(URI, Dist, ArchEntries, comp); + return Indexes = comp.Indexes; } void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { diff --git a/test/integration/framework b/test/integration/framework index 56c4a1216..110758e82 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1531,6 +1531,11 @@ aptautotest() { } aptautotest_aptget_update() { + local TESTCALL="$1" + while [ -n "$2" ]; do + if [ "$2" = '--print-uris' ]; then return; fi # simulation mode + shift + done if ! test -d "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists"; then return; fi testfilestats "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:755" testfilestats "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:755" @@ -1538,7 +1543,7 @@ aptautotest_aptget_update() { for file in $(find "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists" -type f ! -name 'lock'); do testfilestats "$file" '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" done - if [ "$1" = 'testsuccess' ]; then + if [ "$TESTCALL" = 'testsuccess' ]; then # failure cases can retain partial files and such testempty find "${TMPWORKINGDIRECTORY}/rootdir/var/lib/apt/lists/partial" -mindepth 1 ! \( -name 'lock' -o -name '*.FAILED' \) fi diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index 150a50980..0e59233e9 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -6,6 +6,9 @@ TESTDIR=$(readlink -f $(dirname $0)) setupenvironment configarchitecture 'amd64' + +# note that in --print-uri we talk about .bz2 because that is the default. +# This doesn't mean it is actually attempt to download it. configcompression '.' 'gz' buildsimplenativepackage 'foo' 'amd64' '1' 'unstable' @@ -13,6 +16,11 @@ buildsimplenativepackage 'foo' 'amd64' '1' 'unstable' setupaptarchive --no-update changetowebserver +testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists_unstable_InRelease 0 +'http://localhost:8080/dists/unstable/main/source/Sources.bz2' localhost:8080_dists_unstable_main_source_Sources 0 +'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 +'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris + testsuccessequal "Get:1 http://localhost:8080 unstable InRelease [$(stat -c%s aptarchive/dists/unstable/InRelease) B] Get:2 http://localhost:8080 unstable/main Sources [$(stat -c%s aptarchive/dists/unstable/main/source/Sources.gz) B] Get:3 http://localhost:8080 unstable/main amd64 Packages [$(stat -c%s aptarchive/dists/unstable/main/binary-amd64/Packages.gz) B] @@ -29,6 +37,12 @@ APT::Acquire::Targets::deb::Contents { }; EOF +testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists_unstable_InRelease 0 +'http://localhost:8080/dists/unstable/main/source/Sources.bz2' localhost:8080_dists_unstable_main_source_Sources 0 +'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 +'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 +'http://localhost:8080/dists/unstable/main/Contents-amd64.bz2' localhost:8080_dists_unstable_main_Contents-amd64 0 " aptget update --print-uris + testsuccessequal "Hit http://localhost:8080 unstable InRelease Get:1 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update @@ -46,9 +60,28 @@ APT::Acquire::Targets::deb::Contents { }; EOF +# the last line is utter bogus of course, but how should apt know… +testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists_unstable_InRelease 0 +'http://localhost:8080/dists/unstable/main/source/Sources.bz2' localhost:8080_dists_unstable_main_source_Sources 0 +'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 +'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 +'http://localhost:8080/dists/unstable/main/Contents-amd64.gz.bz2' localhost:8080_dists_unstable_main_Contents-amd64.gz 0 " aptget update --print-uris + testsuccessequal "Hit http://localhost:8080 unstable InRelease Get:1 http://localhost:8080 unstable/main amd64 Contents.gz [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' 'aptarchive/dists/unstable/main/Contents-amd64.gz' + +rm -f rootdir/etc/apt/apt.conf.d/content-target.conf + +testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists_unstable_InRelease 0 +'http://localhost:8080/dists/unstable/main/source/Sources.bz2' localhost:8080_dists_unstable_main_source_Sources 0 +'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 +'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris + +testsuccessequal "Hit http://localhost:8080 unstable InRelease +Reading package lists..." aptget update + +testempty find rootdir/var/lib/apt/lists -name '*Contents*' -- cgit v1.2.3-70-g09d2 From d3a869e35503638e3483228fbfc95b7143568ad0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 10 Jun 2015 21:24:47 +0200 Subject: store all targets data in IndexTarget struct We still need an API for the targets, so slowly prepare the IndexTargets to let them take this job. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 15 ++- apt-pkg/acquire-item.h | 31 ++---- apt-pkg/deb/debmetaindex.cc | 114 ++++++++++----------- apt-pkg/init.cc | 12 +-- doc/acquire-additional-files.txt | 29 +++--- test/integration/test-apt-acquire-additional-files | 4 +- 6 files changed, 97 insertions(+), 108 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index a1357fb15..e92ccc08b 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -382,6 +382,15 @@ bool pkgAcqDiffIndex::TransactionState(TransactionStates const state) } /*}}}*/ +// IndexTarget - Constructor /*{{{*/ +IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + std::map const &Options) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options) +{ +} + /*}}}*/ + class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ /* The sole purpose of this class is having an item which does nothing to reach its done state to prevent cleanup deleting the mentioned file. @@ -955,7 +964,7 @@ void pkgAcqMetaBase::QueueIndexes(bool const verify) /*{{{*/ if (TransactionManager->MetaIndexParser->Exists((*Target)->MetaKey) == false) { // optional targets that we do not have in the Release file are skipped - if ((*Target)->IsOptional()) + if ((*Target)->IsOptional) continue; Status = StatAuthError; @@ -2388,7 +2397,7 @@ string pkgAcqIndex::Custom600Headers() const if (stat(Final.c_str(),&Buf) == 0) msg += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); - if(Target->IsOptional()) + if(Target->IsOptional) msg += "\nFail-Ignore: true"; return msg; @@ -2410,7 +2419,7 @@ void pkgAcqIndex::Failed(string const &Message,pkgAcquire::MethodConfig const * } } - if(Target->IsOptional() && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) + if(Target->IsOptional && GetExpectedHashes().empty() && Stage == STAGE_DOWNLOAD) Status = StatDone; else TransactionManager->AbortTransaction(); diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 38a7a8662..a2571e1cd 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -28,6 +28,7 @@ #include #include +#include #ifndef APT_8_CLEANER_HEADERS #include @@ -49,7 +50,7 @@ class pkgSourceList; class IndexTarget; class pkgAcqMetaBase; -class APT_HIDDEN IndexTarget /*{{{*/ +class IndexTarget /*{{{*/ /** \brief Information about an index file. */ { public: @@ -63,30 +64,18 @@ class APT_HIDDEN IndexTarget /*{{{*/ std::string const ShortDesc; /** \brief The key by which this index file should be - * looked up within the meta signature file. - */ + looked up within the meta index file. */ std::string const MetaKey; - virtual bool IsOptional() const { - return false; - } + /** \brief Is it okay if the file isn't found in the meta index */ + bool const IsOptional; - IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI) : - URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey) {} -}; - /*}}}*/ -class APT_HIDDEN OptionalIndexTarget : public IndexTarget /*{{{*/ -/** \brief Information about an optional index file. */ -{ - public: - virtual bool IsOptional() const { - return true; - } + /** \brief Target specific options defined by the implementation */ + std::map const Options; - OptionalIndexTarget(std::string const &MetaKey, std::string const &ShortDesc, - std::string const &LongDesc, std::string const &URI) : - IndexTarget(MetaKey, ShortDesc, LongDesc, URI) {} + IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, + std::string const &LongDesc, std::string const &URI, bool const IsOptional, + std::map const &Options); }; /*}}}*/ class pkgAcquire::Item : public WeakPointable /*{{{*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index c35f3b0a4..f038f12f5 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -116,12 +116,12 @@ void foreachTarget(std::string const URI, std::string const Dist, for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { #define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X)) - std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); #undef APT_T_CONFIG - if (URI.empty()) + if (MetaKey.empty()) continue; vector const SectionEntries = src->second; @@ -130,23 +130,24 @@ void foreachTarget(std::string const URI, std::string const Dist, { for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) { - if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) continue; - struct SubstVar subst[] = { - { "$(SITE)", &Site }, - { "$(RELEASE)", &Release }, - { "$(COMPONENT)", &((*I)->Section) }, - { "$(LANGUAGE)", &(*l) }, - { NULL, NULL } - }; - Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); - - if (URI.find("$(LANGUAGE)") == std::string::npos) + std::map Options; + Options.insert(std::make_pair("SITE", Site)); + Options.insert(std::make_pair("RELEASE", Release)); + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + Options.insert(std::make_pair("LANGUAGE", *l)); + Options.insert(std::make_pair("ARCHITECTURE", "source")); + Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("CREATED_BY", *T)); + Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); + + if (MetaKey.find("$(LANGUAGE)") == std::string::npos) break; } - if (URI.find("$(COMPONENT)") == std::string::npos) + if (MetaKey.find("$(COMPONENT)") == std::string::npos) break; } } @@ -156,12 +157,12 @@ void foreachTarget(std::string const URI, std::string const Dist, for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { #define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X)) - std::string const URI = APT_T_CONFIG(flatArchive ? "flatURI" : "URI"); + std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true); #undef APT_T_CONFIG - if (URI.empty()) + if (MetaKey.empty()) continue; for (map >::const_iterator a = ArchEntries.begin(); @@ -175,28 +176,28 @@ void foreachTarget(std::string const URI, std::string const Dist, for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) { - if (*l == "none" && URI.find("$(LANGUAGE)") != std::string::npos) + if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) continue; - struct SubstVar subst[] = { - { "$(SITE)", &Site }, - { "$(RELEASE)", &Release }, - { "$(COMPONENT)", &((*I)->Section) }, - { "$(LANGUAGE)", &(*l) }, - { "$(ARCHITECTURE)", &(a->first) }, - { NULL, NULL } - }; - Call(baseURI, *T, URI, ShortDesc, LongDesc, IsOptional, subst); - - if (URI.find("$(LANGUAGE)") == std::string::npos) + std::map Options; + Options.insert(std::make_pair("SITE", Site)); + Options.insert(std::make_pair("RELEASE", Release)); + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + Options.insert(std::make_pair("LANGUAGE", *l)); + Options.insert(std::make_pair("ARCHITECTURE", a->first)); + Options.insert(std::make_pair("BASE_URI", baseURI)); + Options.insert(std::make_pair("CREATED_BY", *T)); + Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); + + if (MetaKey.find("$(LANGUAGE)") == std::string::npos) break; } - if (URI.find("$(COMPONENT)") == std::string::npos) + if (MetaKey.find("$(COMPONENT)") == std::string::npos) break; } - if (URI.find("$(ARCHITECTURE)") == std::string::npos) + if (MetaKey.find("$(ARCHITECTURE)") == std::string::npos) break; } } @@ -207,30 +208,23 @@ struct ComputeIndexTargetsClass { vector * const IndexTargets; - void operator()(std::string const &baseURI, std::string const &/*TargetName*/, - std::string const &URI, std::string const &ShortDesc, std::string const &LongDesc, - bool const IsOptional, struct SubstVar const * const subst) + void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc, + bool const IsOptional, std::map Options) { - std::string const name = SubstVar(URI, subst); - IndexTarget * Target; - if (IsOptional == true) - { - Target = new OptionalIndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); - } - else + for (std::map::const_iterator O = Options.begin(); O != Options.end(); ++O) { - Target = new IndexTarget( - name, - SubstVar(ShortDesc, subst), - SubstVar(LongDesc, subst), - baseURI + name - ); + MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second); + ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second); + LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second); } + IndexTarget * Target = new IndexTarget( + MetaKey, + ShortDesc, + LongDesc, + Options.find("BASE_URI")->second + MetaKey, + IsOptional, + Options + ); IndexTargets->push_back(Target); } @@ -256,7 +250,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const // special case for --print-uris vector const * const targets = ComputeIndexTargets(); -#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X)) +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), targets, iR); @@ -309,33 +303,33 @@ struct GetIndexFilesClass std::string const Release; bool const IsTrusted; - void operator()(std::string const &/*baseURI*/, std::string const &TargetName, - std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, - bool const /*IsOptional*/, struct SubstVar const * const subst) + void operator()(std::string const &/*URI*/, std::string const &/*ShortDesc*/, std::string const &/*LongDesc*/, + bool const /*IsOptional*/, std::map Options) { + std::string const TargetName = Options.find("CREATED_BY")->second; if (TargetName == "Packages") { Indexes->push_back(new debPackagesIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), + Options.find("COMPONENT")->second, IsTrusted, - SubstVar("$(ARCHITECTURE)", subst) + Options.find("ARCHITECTURE")->second )); } else if (TargetName == "Sources") Indexes->push_back(new debSourcesIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), + Options.find("COMPONENT")->second, IsTrusted )); else if (TargetName == "Translations") Indexes->push_back(new debTranslationsIndex( URI, Release, - SubstVar("$(COMPONENT)", subst), - SubstVar("$(LANGUAGE)", subst) + Options.find("COMPONENT")->second, + Options.find("LANGUAGE")->second )); } diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 50ea2b49e..e2239a906 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -101,19 +101,19 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::URI", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatURI", "Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatMetaKey", "Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::URI", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatURI", "$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::URI", "$(COMPONENT)/source/Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatURI", "Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatMetaKey", "Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt index 5a07c2bec..ab833440b 100644 --- a/doc/acquire-additional-files.txt +++ b/doc/acquire-additional-files.txt @@ -33,11 +33,11 @@ instructing the Acquire system to download the Packages files would look like this (see also apt.conf(5) manpage for configuration file syntax): APT::Acquire::Targets::deb::Packages { - URI "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"; + MetaKey "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"; ShortDescription "Packages"; Description "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"; - flatURI "Packages"; + flatMetaKey "Packages"; flatDescription "$(SITE) $(RELEASE) Packages"; Optional "false"; @@ -47,18 +47,18 @@ All files which should be downloaded (nicknamed 'Targets') are mentioned below the APT::Acquire::Targets scope. 'deb' is here the type of the sources.list entry the file should be acquired for. The only other supported value is hence 'deb-src'. Beware: You can't specify multiple -types here and you can't download the same URI for multiple types! +types here and you can't download the same MetaKey form multiple types! After the type you can pick any valid and unique string which preferable refers to the file it downloads (In the example we picked 'Packages'). This string is never shown or used. All targets have three main properties you can define: -* URI: The identifier of the file to be downloaded as used in the +* MetaKey: The identifier of the file to be downloaded as used in the Release file. It is also the relative location of the file from the Release file. You can neither download from a different server - entirely (absolute URI) nor should you try to access directories above - the Release file (e.g. "../../"). + entirely (absolute URI) nor access directories above the Release file + (e.g. "../../"). * ShortDescription: Very short string intended to be displayed to the user e.g. while reporting progress. apt will e.g. use this string in the last line to indicate progress of e.g. the download of a specific @@ -69,7 +69,7 @@ All targets have three main properties you can define: progress lines. Additional optional properties: -* flat{URI,Description}: APT supports two types of repositories: +* flat{MetaKey,Description}: APT supports two types of repositories: dists-style repositories which are the default and by far the most common which are named after the fact that the files are in an elaborated directory structure. In contrast a flat-style repositories @@ -96,20 +96,20 @@ look like this: APT::Acquire::Targets { deb::Translations { - URI "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"; + MetaKey "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"; ShortDescription "Translation-$(LANGUAGE)"; Description "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"; - flatURI "$(LANGUAGE)"; + flatMetaKey "$(LANGUAGE)"; flatDescription "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"; }; deb-src::Sources { - URI "$(COMPONENT)/source/Sources"; + MetaKey "$(COMPONENT)/source/Sources"; ShortDescription "Sources"; Description "$(SITE) $(RELEASE)/$(COMPONENT) Sources"; - flatURI "Sources"; + flatMetaKey "Sources"; flatDescription "$(SITE) $(RELEASE) Sources"; Optional "false"; @@ -133,10 +133,7 @@ printed literally. have a meaningful value here. * $(LANGUAGE): Values are all entries (expect "none") of configuration option Acquire::Languages, e.g. "en", "de" or "de_AT". - -These values are defined both for 'deb' as well as 'deb-src' targets. -'deb' targets additional have the variable: - * $(ARCHITECTURE): Values are all entries of configuration option APT::Architectures (potentially modified by sources.list options), - e.g. "amd64", "i386" or "armel". + e.g. "amd64", "i386" or "armel" for the 'deb' type. In type 'deb-src' + this variable has the value "source". diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index 0e59233e9..4a6845f40 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -31,7 +31,7 @@ testempty find rootdir/var/lib/apt/lists -name '*Contents*' cat > rootdir/etc/apt/apt.conf.d/content-target.conf < rootdir/etc/apt/apt.conf.d/content-target.conf < Date: Thu, 11 Jun 2015 10:56:31 +0200 Subject: show URI.Path in all acquire item descriptions It is a rather strange sight that index items use SiteOnly which strips the Path, while e.g. deb files are downloaded with NoUserPassword which does not. Important to note here is that for the file transport Path is pretty important as there is no Host which would be displayed by Site, which always resulted in "interesting" unspecific errors for "file:". Adding a 'middle' ground between the two which does show the Path but potentially modifies it (it strips a pending / at the end if existing) solves this "file:" issue, syncs the output and in the end helps to identify which file is meant exactly in progress output and co as a single site can have multiple repositories in different paths. --- apt-pkg/contrib/strutl.cc | 15 ++++++--- apt-pkg/contrib/strutl.h | 1 + apt-pkg/deb/debindexfile.cc | 10 +++--- apt-pkg/deb/debmetaindex.cc | 4 +-- test/integration/test-apt-cache | 2 +- test/integration/test-apt-cli-show | 2 +- .../integration/test-apt-get-update-unauth-warning | 12 +++---- .../test-apt-translation-has-no-packages | 2 +- test/integration/test-apt-update-nofallback | 6 ++-- test/integration/test-apt-update-rollback | 6 ++-- .../test-bug-543966-downgrade-below-1000-pin | 2 +- .../test-bug-595691-empty-and-broken-archive-files | 5 +-- .../test-cve-2013-1051-InRelease-parsing | 2 +- test/integration/test-policy-pinning | 8 ++--- test/integration/test-releasefile-verification | 4 +-- .../test-ubuntu-bug-1098738-apt-get-source-md5sum | 28 ++++++++-------- test/libapt/uri_test.cc | 39 ++++++++++++++++++++++ 17 files changed, 98 insertions(+), 50 deletions(-) (limited to 'test') diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index 0db4c57b2..5731b5a2b 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -1637,8 +1637,6 @@ URI::operator string() } /*}}}*/ // URI::SiteOnly - Return the schema and site for the URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ string URI::SiteOnly(const string &URI) { ::URI U(URI); @@ -1648,9 +1646,18 @@ string URI::SiteOnly(const string &URI) return U; } /*}}}*/ +// URI::ArchiveOnly - Return the schema, site and cleaned path for the URI /*{{{*/ +string URI::ArchiveOnly(const string &URI) +{ + ::URI U(URI); + U.User.clear(); + U.Password.clear(); + if (U.Path.empty() == false && U.Path[U.Path.length() - 1] == '/') + U.Path.erase(U.Path.length() - 1); + return U; +} + /*}}}*/ // URI::NoUserPassword - Return the schema, site and path for the URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ string URI::NoUserPassword(const string &URI) { ::URI U(URI); diff --git a/apt-pkg/contrib/strutl.h b/apt-pkg/contrib/strutl.h index d64270aaf..01bbfef72 100644 --- a/apt-pkg/contrib/strutl.h +++ b/apt-pkg/contrib/strutl.h @@ -167,6 +167,7 @@ class URI inline void operator =(const std::string &From) {CopyFrom(From);} inline bool empty() {return Access.empty();}; static std::string SiteOnly(const std::string &URI); + static std::string ArchiveOnly(const std::string &URI); static std::string NoUserPassword(const std::string &URI); URI(std::string Path) {CopyFrom(Path);} diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 185248619..20bf5ae50 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -57,7 +57,7 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { string Res; - Res = ::URI::NoUserPassword(URI) + ' '; + Res = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -116,7 +116,7 @@ string debSourcesIndex::Describe(bool Short) const /* */ string debSourcesIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -210,7 +210,7 @@ debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string /* This is a shorter version that is designed to be < 60 chars or so */ string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const { - string Res = ::URI::NoUserPassword(URI) + ' '; + string Res = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -248,7 +248,7 @@ string debPackagesIndex::Describe(bool Short) const /* */ string debPackagesIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -473,7 +473,7 @@ string debTranslationsIndex::Describe(bool Short) const /* */ string debTranslationsIndex::Info(const char *Type) const { - string Info = ::URI::NoUserPassword(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index e1f86d20f..d4e340be0 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -25,7 +25,7 @@ using namespace std; string debReleaseIndex::MetaIndexInfo(const char *Type) const { - string Info = ::URI::SiteOnly(URI) + ' '; + string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -105,7 +105,7 @@ void foreachTarget(std::string const URI, std::string const Dist, else baseURI += "dists/" + Dist + "/"; std::string const Release = (Dist == "/") ? "" : Dist; - std::string const Site = ::URI::SiteOnly(URI); + std::string const Site = ::URI::ArchiveOnly(URI); std::vector lang = APT::Configuration::getLanguages(true); if (lang.empty()) lang.push_back("none"); diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index f3db8024f..97dc0f939 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -50,7 +50,7 @@ testsuccessequal 'bar' aptcache pkgnames bar testsuccessequal 'fancy foo' aptcache pkgnames f -testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive/ unstable/main amd64 Packages" aptcache madison foo +testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive unstable/main amd64 Packages" aptcache madison foo ### depends diff --git a/test/integration/test-apt-cli-show b/test/integration/test-apt-cli-show index 43072cf03..5f4ef1b48 100755 --- a/test/integration/test-apt-cli-show +++ b/test/integration/test-apt-cli-show @@ -32,7 +32,7 @@ Maintainer: Joe Sixpack Installed-Size: 43.0 kB Download-Size: unknown APT-Manual-Installed: yes -APT-Sources: file:$APTARCHIVE/ unstable/main i386 Packages +APT-Sources: file:$APTARCHIVE unstable/main i386 Packages Description: Some description That has multiple lines " apt show foo diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index 81c01ba3e..ada7f7a26 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -19,11 +19,11 @@ APTARCHIVE=$(readlink -f ./aptarchive) rm -f $APTARCHIVE/dists/unstable/*Release* # update without authenticated files leads to warning -testfailureequal "Ign file: unstable InRelease +testfailureequal "Ign file:$APTARCHIVE unstable InRelease File not found -Err file: unstable Release +Err file:$APTARCHIVE unstable Release File not found -W: The repository 'file: unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository. +W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository. E: Use --allow-insecure-repositories to force the update" aptget update --no-allow-insecure-repositories # no package foo @@ -32,12 +32,12 @@ testequal 'lock partial' ls rootdir/var/lib/apt/lists # allow override -testwarningequal "Ign file: unstable InRelease +testwarningequal "Ign file:$APTARCHIVE unstable InRelease File not found -Ign file: unstable Release +Ign file:$APTARCHIVE unstable Release File not found Reading package lists... -W: The repository 'file: unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." aptget update --allow-insecure-repositories +W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." aptget update --allow-insecure-repositories # ensure we can not install the package testfailureequal "WARNING: The following packages cannot be authenticated! foo diff --git a/test/integration/test-apt-translation-has-no-packages b/test/integration/test-apt-translation-has-no-packages index 440fd30cf..cf5b56243 100755 --- a/test/integration/test-apt-translation-has-no-packages +++ b/test/integration/test-apt-translation-has-no-packages @@ -38,4 +38,4 @@ testsuccessequal "foo: Candidate: 1.0 Version table: 1.0 0 - 500 file:$APTARCHIVE/ unstable/main amd64 Packages" aptcache policy foo + 500 file:$APTARCHIVE unstable/main amd64 Packages" aptcache policy foo diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index f132bcf8e..2ded73122 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -33,7 +33,7 @@ EOF assert_update_is_refused_and_last_good_state_used() { - testfailuremsg "E: The repository 'file: unstable Release' is no longer signed." aptget update + testfailuremsg "E: The repository 'file:${APTARCHIVE} unstable Release' is no longer signed." aptget update assert_repo_is_intact } @@ -171,7 +171,7 @@ test_inrelease_to_invalid_inrelease() sed -i 's/^Codename:.*/Codename: evil!/' $APTARCHIVE/dists/unstable/InRelease inject_evil_package - testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) + testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) @@ -195,7 +195,7 @@ test_release_gpg_to_invalid_release_release_gpg() echo "Some evil data" >> $APTARCHIVE/dists/unstable/Release inject_evil_package - testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable Release: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) + testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable Release: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) W: Failed to fetch file:${APTARCHIVE}/dists/unstable/Release.gpg The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback index 6ecf322b2..70619dd08 100755 --- a/test/integration/test-apt-update-rollback +++ b/test/integration/test-apt-update-rollback @@ -78,7 +78,7 @@ test_inrelease_to_valid_release() { rm $APTARCHIVE/dists/unstable/Release.gpg # update fails - testfailureequal "E: The repository 'file: unstable Release' is no longer signed." aptget update -qq + testfailureequal "E: The repository 'file:${APTARCHIVE} unstable Release' is no longer signed." aptget update -qq # test that security downgrade was not successful testfileequal lists.before "$(listcurrentlistsdirectory)" @@ -101,7 +101,7 @@ test_inrelease_to_release_reverts_all() { break_repository_sources_index '+1hour' # ensure error - testfailureequal "E: The repository 'file: unstable Release' is no longer signed." aptget update -qq # -o Debug::acquire::transaction=1 + testfailureequal "E: The repository 'file:${APTARCHIVE} unstable Release' is no longer signed." aptget update -qq # -o Debug::acquire::transaction=1 # ensure that the Packages file is also rolled back testfileequal lists.before "$(listcurrentlistsdirectory)" @@ -144,7 +144,7 @@ test_inrelease_to_unauth_inrelease() { signreleasefiles 'Marvin Paranoid' - testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file: unstable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2 + testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2 W: Failed to fetch file:$APTARCHIVE/dists/unstable/InRelease The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2 diff --git a/test/integration/test-bug-543966-downgrade-below-1000-pin b/test/integration/test-bug-543966-downgrade-below-1000-pin index e59231608..180393867 100755 --- a/test/integration/test-bug-543966-downgrade-below-1000-pin +++ b/test/integration/test-bug-543966-downgrade-below-1000-pin @@ -13,7 +13,7 @@ insertinstalledpackage 'base-files' 'all' '5.0.0-1' setupaptarchive STATUS=$(readlink -f rootdir/var/lib/dpkg/status) -APTARCHIVE="$(readlink -f aptarchive)/" +APTARCHIVE="$(readlink -f aptarchive)" testsuccessequal "base-files: Installed: 5.0.0-1 diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index 486b8ba02..b42212f5e 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -49,6 +49,7 @@ createemptyfile() { } testoverfile() { + local APTARCHIVE="$(readlink -f ./aptarchive)" forcecompressor "$1" createemptyfile 'en' @@ -63,9 +64,9 @@ testoverfile() { testaptgetupdate 'Reading package lists...' "empty archive Packages.$COMPRESS over file" createemptyfile 'Packages' - testaptgetupdate "Err file: Packages + testaptgetupdate "Err file:$APTARCHIVE Packages Empty files can't be valid archives -W: Failed to fetch ${COMPRESSOR}:$(readlink -f aptarchive/Packages.$COMPRESS) Empty files can't be valid archives +W: Failed to fetch ${COMPRESSOR}:${APTARCHIVE}/Packages.$COMPRESS Empty files can't be valid archives E: Some index files failed to download. They have been ignored, or old ones used instead." "empty file Packages.$COMPRESS over file" } diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing index d99174553..933cbbd92 100755 --- a/test/integration/test-cve-2013-1051-InRelease-parsing +++ b/test/integration/test-cve-2013-1051-InRelease-parsing @@ -12,7 +12,7 @@ insertpackage 'stable' 'good-pkg' 'all' '1.0' setupaptarchive changetowebserver -ARCHIVE='http://localhost:8080/' +ARCHIVE='http://localhost:8080' msgtest 'Initial apt-get update should work with' 'InRelease' testsuccess --nomsg aptget update diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 2675b51bc..9cd54264b 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -20,7 +20,7 @@ testequalpolicy() { testsuccessequal "Package files: $(echo "$SP" | awk '{ printf("%3s\n",$0) }') ${STATUS} release a=now - $(echo "$AP" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE}/ Packages + $(echo "$AP" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} Packages release c= Pinned packages:" aptcache policy $* } @@ -105,11 +105,11 @@ testequalpolicycoolstuff() { local BPO1ARCHIVE="" local BPO2ARCHIVE="" if [ ! "$7" = "2.0~bpo2" ]; then - BPO1ARCHIVE=" $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE}/ backports/main i386 Packages" + BPO1ARCHIVE=" $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} backports/main i386 Packages" else BPO2ARCHIVE=" 2.0~bpo2 $PB - $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE}/ backports/main i386 Packages" + $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} backports/main i386 Packages" SB="$(echo "$SB" | tail -n 1)" shift fi @@ -121,7 +121,7 @@ testequalpolicycoolstuff() { $IB 2.0~bpo1 $PB ${BPO1ARCHIVE}$SB $IS 1.0 $PB - $(echo "$AS" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE}/ stable/main i386 Packages$SS" \ + $(echo "$AS" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} stable/main i386 Packages$SS" \ aptcache policy coolstuff -o Policy=${INSTALLED}-${CANDIDATE}-${AB}-${AS}-${PB} $* } diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 469ed34d2..e8419524c 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -41,7 +41,7 @@ The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. After this operation, 5370 kB of additional disk space will be used. -Get:1 http://localhost:8080/ apt 0.7.25.3 +Get:1 http://localhost:8080 apt 0.7.25.3 Download complete and in download only mode' aptget install apt -dy } @@ -54,7 +54,7 @@ The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. After this operation, 5808 kB of additional disk space will be used. -Get:1 http://localhost:8080/ apt 0.8.0~pre1 +Get:1 http://localhost:8080 apt 0.8.0~pre1 Download complete and in download only mode' aptget install apt -dy } diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum index 555d8fcaa..6abb5d12a 100755 --- a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum +++ b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum @@ -148,8 +148,8 @@ testok() { testsuccessequal "Reading package lists... Building dependency tree... Need to get 6 B of source archives. -Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B] -Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B] +Get:1 http://localhost:8080 $1 1.0 (dsc) [3 B] +Get:2 http://localhost:8080 $1 1.0 (tar) [3 B] Download complete and in download only mode" aptget source -d "$@" msgtest 'Files were successfully downloaded for' "$1" testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz @@ -175,11 +175,11 @@ testmismatch() { testfailureequal "Reading package lists... Building dependency tree... Need to get 6 B of source archives. -Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B] -Err http://localhost:8080/ $1 1.0 (dsc) +Get:1 http://localhost:8080 $1 1.0 (dsc) [3 B] +Err http://localhost:8080 $1 1.0 (dsc) Hash Sum mismatch -Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B] -Err http://localhost:8080/ $1 1.0 (tar) +Get:2 http://localhost:8080 $1 1.0 (tar) [3 B] +Err http://localhost:8080 $1 1.0 (tar) Hash Sum mismatch E: Failed to fetch http://localhost:8080/${1}_1.0.dsc Hash Sum mismatch @@ -203,8 +203,8 @@ Download complete and in download only mode" aptget source -d "$@" -o Acquire::F testsuccessequal "Reading package lists... Building dependency tree... Need to get 6 B of source archives. -Get:1 http://localhost:8080/ $1 1.0 (dsc) [3 B] -Get:2 http://localhost:8080/ $1 1.0 (tar) [3 B] +Get:1 http://localhost:8080 $1 1.0 (dsc) [3 B] +Get:2 http://localhost:8080 $1 1.0 (tar) [3 B] Download complete and in download only mode" aptget source --allow-unauthenticated -d "$@" -o Acquire::ForceHash=ROT26 msgtest 'Files were downloaded unauthenticated as user allowed it' "$1" testsuccess --nomsg test -e ${1}_1.0.dsc -a -e ${1}_1.0.tar.gz @@ -240,9 +240,9 @@ testok pkg-mixed-ok testfailureequal 'Reading package lists... Building dependency tree... Need to get 6 B of source archives. -Get:1 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (tar) [3 B] -Get:2 http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc) [3 B] -Err http://localhost:8080/ pkg-mixed-sha1-bad 1.0 (dsc) +Get:1 http://localhost:8080 pkg-mixed-sha1-bad 1.0 (tar) [3 B] +Get:2 http://localhost:8080 pkg-mixed-sha1-bad 1.0 (dsc) [3 B] +Err http://localhost:8080 pkg-mixed-sha1-bad 1.0 (dsc) Hash Sum mismatch E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc Hash Sum mismatch @@ -252,10 +252,10 @@ testsuccess --nomsg test ! -e pkg-mixed-sha1-bad_1.0.dsc -a -e pkg-mixed-sha1-ba testfailureequal 'Reading package lists... Building dependency tree... Need to get 6 B of source archives. -Get:1 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar) [3 B] -Err http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (tar) +Get:1 http://localhost:8080 pkg-mixed-sha2-bad 1.0 (tar) [3 B] +Err http://localhost:8080 pkg-mixed-sha2-bad 1.0 (tar) Hash Sum mismatch -Get:2 http://localhost:8080/ pkg-mixed-sha2-bad 1.0 (dsc) [3 B] +Get:2 http://localhost:8080 pkg-mixed-sha2-bad 1.0 (dsc) [3 B] E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz Hash Sum mismatch E: Failed to fetch some archives.' aptget source -d pkg-mixed-sha2-bad diff --git a/test/libapt/uri_test.cc b/test/libapt/uri_test.cc index 5d5ae9679..fe6015e65 100644 --- a/test/libapt/uri_test.cc +++ b/test/libapt/uri_test.cc @@ -13,6 +13,9 @@ TEST(URITest, BasicHTTP) EXPECT_EQ("www.debian.org", U.Host); EXPECT_EQ("/temp/test", U.Path); EXPECT_EQ("http://www.debian.org:90/temp/test", (std::string)U); + EXPECT_EQ("http://www.debian.org:90", URI::SiteOnly(U)); + EXPECT_EQ("http://www.debian.org:90/temp/test", URI::ArchiveOnly(U)); + EXPECT_EQ("http://www.debian.org:90/temp/test", URI::NoUserPassword(U)); // Login data U = URI("http://jgg:foo@ualberta.ca/blah"); EXPECT_EQ("http", U.Access); @@ -22,6 +25,9 @@ TEST(URITest, BasicHTTP) EXPECT_EQ("ualberta.ca", U.Host); EXPECT_EQ("/blah", U.Path); EXPECT_EQ("http://jgg:foo@ualberta.ca/blah", (std::string)U); + EXPECT_EQ("http://ualberta.ca", URI::SiteOnly(U)); + EXPECT_EQ("http://ualberta.ca/blah", URI::ArchiveOnly(U)); + EXPECT_EQ("http://ualberta.ca/blah", URI::NoUserPassword(U)); } TEST(URITest, SingeSlashFile) { @@ -33,6 +39,9 @@ TEST(URITest, SingeSlashFile) EXPECT_EQ("", U.Host); EXPECT_EQ("/usr/bin/foo", U.Path); EXPECT_EQ("file:/usr/bin/foo", (std::string)U); + EXPECT_EQ("file:", URI::SiteOnly(U)); + EXPECT_EQ("file:/usr/bin/foo", URI::ArchiveOnly(U)); + EXPECT_EQ("file:/usr/bin/foo", URI::NoUserPassword(U)); } TEST(URITest, BasicCDROM) { @@ -44,6 +53,9 @@ TEST(URITest, BasicCDROM) EXPECT_EQ("Moo Cow Rom", U.Host); EXPECT_EQ("/debian", U.Path); EXPECT_EQ("cdrom://Moo Cow Rom/debian", (std::string)U); + EXPECT_EQ("cdrom://Moo Cow Rom", URI::SiteOnly(U)); + EXPECT_EQ("cdrom://Moo Cow Rom/debian", URI::ArchiveOnly(U)); + EXPECT_EQ("cdrom://Moo Cow Rom/debian", URI::NoUserPassword(U)); } TEST(URITest, RelativeGzip) { @@ -55,6 +67,9 @@ TEST(URITest, RelativeGzip) EXPECT_EQ(".", U.Host); EXPECT_EQ("/bar/cow", U.Path); EXPECT_EQ("gzip://./bar/cow", (std::string)U); + EXPECT_EQ("gzip://.", URI::SiteOnly(U)); + EXPECT_EQ("gzip://./bar/cow", URI::ArchiveOnly(U)); + EXPECT_EQ("gzip://./bar/cow", URI::NoUserPassword(U)); } TEST(URITest, NoSlashFTP) { @@ -66,6 +81,9 @@ TEST(URITest, NoSlashFTP) EXPECT_EQ("ftp.fr.debian.org", U.Host); EXPECT_EQ("/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", U.Path); EXPECT_EQ("ftp://ftp.fr.debian.org/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", (std::string)U); + EXPECT_EQ("ftp://ftp.fr.debian.org", URI::SiteOnly(U)); + EXPECT_EQ("ftp://ftp.fr.debian.org/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", URI::ArchiveOnly(U)); + EXPECT_EQ("ftp://ftp.fr.debian.org/debian/pool/main/x/xtel/xtel_3.2.1-15_i386.deb", URI::NoUserPassword(U)); } TEST(URITest, RFC2732) { @@ -77,6 +95,9 @@ TEST(URITest, RFC2732) EXPECT_EQ("1080::8:800:200C:417A", U.Host); EXPECT_EQ("/foo", U.Path); EXPECT_EQ("http://[1080::8:800:200C:417A]/foo", (std::string)U); + EXPECT_EQ("http://[1080::8:800:200C:417A]", URI::SiteOnly(U)); + EXPECT_EQ("http://[1080::8:800:200C:417A]/foo", URI::ArchiveOnly(U)); + EXPECT_EQ("http://[1080::8:800:200C:417A]/foo", URI::NoUserPassword(U)); // with port U = URI("http://[::FFFF:129.144.52.38]:80/index.html"); EXPECT_EQ("http", U.Access); @@ -86,6 +107,9 @@ TEST(URITest, RFC2732) EXPECT_EQ("::FFFF:129.144.52.38", U.Host); EXPECT_EQ("/index.html", U.Path); EXPECT_EQ("http://[::FFFF:129.144.52.38]:80/index.html", (std::string)U); + EXPECT_EQ("http://[::FFFF:129.144.52.38]:80", URI::SiteOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38]:80/index.html", URI::ArchiveOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38]:80/index.html", URI::NoUserPassword(U)); // extra colon U = URI("http://[::FFFF:129.144.52.38:]:80/index.html"); EXPECT_EQ("http", U.Access); @@ -95,6 +119,9 @@ TEST(URITest, RFC2732) EXPECT_EQ("::FFFF:129.144.52.38:", U.Host); EXPECT_EQ("/index.html", U.Path); EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80/index.html", (std::string)U); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80", URI::SiteOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80/index.html", URI::ArchiveOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]:80/index.html", URI::NoUserPassword(U)); // extra colon port U = URI("http://[::FFFF:129.144.52.38:]/index.html"); EXPECT_EQ("http", U.Access); @@ -104,6 +131,9 @@ TEST(URITest, RFC2732) EXPECT_EQ("::FFFF:129.144.52.38:", U.Host); EXPECT_EQ("/index.html", U.Path); EXPECT_EQ("http://[::FFFF:129.144.52.38:]/index.html", (std::string)U); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]", URI::SiteOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]/index.html", URI::ArchiveOnly(U)); + EXPECT_EQ("http://[::FFFF:129.144.52.38:]/index.html", URI::NoUserPassword(U)); // My Evil Corruption of RFC 2732 to handle CDROM names! // Fun for the whole family! */ U = URI("cdrom:[The Debian 1.2 disk, 1/2 R1:6]/debian/"); @@ -114,6 +144,9 @@ TEST(URITest, RFC2732) EXPECT_EQ("The Debian 1.2 disk, 1/2 R1:6", U.Host); EXPECT_EQ("/debian/", U.Path); EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]/debian/", (std::string)U); + EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]", URI::SiteOnly(U)); + EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]/debian", URI::ArchiveOnly(U)); + EXPECT_EQ("cdrom://[The Debian 1.2 disk, 1/2 R1:6]/debian/", URI::NoUserPassword(U)); // no brackets U = URI("cdrom:Foo Bar Cow/debian/"); EXPECT_EQ("cdrom", U.Access); @@ -123,9 +156,15 @@ TEST(URITest, RFC2732) EXPECT_EQ("Foo Bar Cow", U.Host); EXPECT_EQ("/debian/", U.Path); EXPECT_EQ("cdrom://Foo Bar Cow/debian/", (std::string)U); + EXPECT_EQ("cdrom://Foo Bar Cow", URI::SiteOnly(U)); + EXPECT_EQ("cdrom://Foo Bar Cow/debian", URI::ArchiveOnly(U)); + EXPECT_EQ("cdrom://Foo Bar Cow/debian/", URI::NoUserPassword(U)); // percent encoded U = URI("ftp://foo:b%40r@example.org"); EXPECT_EQ("foo", U.User); EXPECT_EQ("b@r", U.Password); EXPECT_EQ("ftp://foo:b%40r@example.org/", (std::string) U); + EXPECT_EQ("ftp://example.org", URI::SiteOnly(U)); + EXPECT_EQ("ftp://example.org", URI::ArchiveOnly(U)); + EXPECT_EQ("ftp://example.org/", URI::NoUserPassword(U)); } -- cgit v1.2.3-70-g09d2 From 8881b11eacd735148d087c8c0f53827cb537b582 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 11 Jun 2015 16:40:45 +0200 Subject: implement 'apt-get files' to access index targets Downloading additional files is only half the job. We still need a way to allow external tools to know where the files are they requested for download given that we don't want them to choose their own location. 'apt-get files' is our answer to this showing by default in a deb822 format information about each IndexTarget with the potential to filter the records based on lines and an option to change the output format. The command serves also as an example on how to get to this information via libapt. --- apt-pkg/deb/debmetaindex.cc | 17 +++-- apt-pkg/indexfile.cc | 18 ++++- apt-pkg/indexfile.h | 3 + apt-private/private-cmndline.cc | 4 + cmdline/apt-get.cc | 87 ++++++++++++++++++++++ doc/acquire-additional-files.txt | 87 +++++++++++++++++++++- doc/apt-get.8.xml | 15 ++++ test/integration/test-apt-acquire-additional-files | 2 + 8 files changed, 223 insertions(+), 10 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index c05e7cdae..8e4c2be2d 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -136,11 +136,14 @@ void foreachTarget(std::string const URI, std::string const Dist, std::map Options; Options.insert(std::make_pair("SITE", Site)); Options.insert(std::make_pair("RELEASE", Release)); - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - Options.insert(std::make_pair("LANGUAGE", *l)); + if (MetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + if (MetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *l)); Options.insert(std::make_pair("ARCHITECTURE", "source")); Options.insert(std::make_pair("BASE_URI", baseURI)); Options.insert(std::make_pair("REPO_URI", URI)); + Options.insert(std::make_pair("TARGET_OF", "deb-src")); Options.insert(std::make_pair("CREATED_BY", *T)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); @@ -183,11 +186,15 @@ void foreachTarget(std::string const URI, std::string const Dist, std::map Options; Options.insert(std::make_pair("SITE", Site)); Options.insert(std::make_pair("RELEASE", Release)); - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - Options.insert(std::make_pair("LANGUAGE", *l)); - Options.insert(std::make_pair("ARCHITECTURE", a->first)); + if (MetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", (*I)->Section)); + if (MetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *l)); + if (MetaKey.find("$(ARCHITECTURE)") != std::string::npos) + Options.insert(std::make_pair("ARCHITECTURE", a->first)); Options.insert(std::make_pair("BASE_URI", baseURI)); Options.insert(std::make_pair("REPO_URI", URI)); + Options.insert(std::make_pair("TARGET_OF", "deb")); Options.insert(std::make_pair("CREATED_BY", *T)); Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 72d35ddcc..33fb48e35 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -133,8 +133,10 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ APT_CASE(ARCHITECTURE); APT_CASE(BASE_URI); APT_CASE(REPO_URI); + APT_CASE(TARGET_OF); APT_CASE(CREATED_BY); #undef APT_CASE + case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI); } std::map::const_iterator const M = Options.find(Key); if (M == Options.end()) @@ -142,6 +144,20 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ return M->second; } /*}}}*/ +std::string IndexTarget::Format(std::string format) const /*{{{*/ +{ + for (std::map::const_iterator O = Options.begin(); O != Options.end(); ++O) + { + format = SubstVar(format, std::string("$(") + O->first + ")", O->second); + } + format = SubstVar(format, "$(METAKEY)", MetaKey); + format = SubstVar(format, "$(SHORTDESC)", ShortDesc); + format = SubstVar(format, "$(DESCRIPTION)", Description); + format = SubstVar(format, "$(URI)", URI); + format = SubstVar(format, "$(FILENAME)", Option(IndexTarget::FILENAME)); + return format; +} + /*}}}*/ pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ pkgIndexFile(Trusted), Target(Target) @@ -162,7 +178,7 @@ std::string pkgIndexTargetFile::Describe(bool Short) const /*{{{*/ /*}}}*/ std::string pkgIndexTargetFile::IndexFileName() const /*{{{*/ { - std::string const s =_config->FindDir("Dir::State::lists") + URItoFileName(Target.URI); + std::string const s = Target.Option(IndexTarget::FILENAME); if (FileExists(s)) return s; diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index c38cf0bf0..220c415ac 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -79,8 +79,11 @@ class IndexTarget /*{{{*/ BASE_URI, REPO_URI, CREATED_BY, + TARGET_OF, + FILENAME, }; std::string Option(OptionKeys const Key) const; + std::string Format(std::string format) const; }; /*}}}*/ diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 41aab81f6..458051bf2 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -163,6 +163,10 @@ static bool addArgumentsAPTGet(std::vector &Args, char const // once sbuild is fixed, this option can be removed addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0); } + else if (CmdMatches("files")) + { + addArg(0,"format","APT::Get::Files::Format", CommandLine::HasArg); + } else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands ; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index c1f78523c..0fff2db58 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include @@ -1602,6 +1603,91 @@ static bool DoChangelog(CommandLine &CmdL) return true; } /*}}}*/ +// DoFiles - Lists all IndexTargets /*{{{*/ +static std::string format_key(std::string key) +{ + // deb822 is case-insensitive, but the human eye prefers candy + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + key[0] = ::toupper(key[0]); + size_t found = key.find("_uri"); + if (found != std::string::npos) + key.replace(found, 4, "-URI"); + while ((found = key.find('_')) != std::string::npos) + { + key[found] = '-'; + key[found + 1] = ::toupper(key[found + 1]); + } + return key; +} +static bool DoFiles(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgSourceList *SrcList = CacheFile.GetSourceList(); + + if (SrcList == NULL) + return false; + + std::string const Format = _config->Find("APT::Get::Files::Format"); + bool Filtered = CmdL.FileSize() > 1; + for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S) + { + std::vector const targets = (*S)->GetIndexTargets(); + std::map AddOptions; + AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no"))); + + for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + { + std::ostringstream stanza; + if (Filtered || Format.empty()) + { + stanza << "MetaKey: " << T->MetaKey << "\n" + << "ShortDesc: " << T->ShortDesc << "\n" + << "Description: " << T->Description << "\n" + << "URI: " << T->URI << "\n" + << "Filename: " << T->Option(IndexTarget::FILENAME) << "\n" + << "Optional: " << (T->IsOptional ? "yes" : "no") << "\n"; + for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + stanza << format_key(O->first) << ": " << O->second << "\n"; + for (std::map::const_iterator O = T->Options.begin(); O != T->Options.end(); ++O) + stanza << format_key(O->first) << ": " << O->second << "\n"; + stanza << "\n"; + + if (Filtered) + { + // that is a bit crude, but good enough for now + bool found = true; + std::string haystack = std::string("\n") + stanza.str() + "\n"; + std::transform(haystack.begin(), haystack.end(), haystack.begin(), ::tolower); + size_t const filesize = CmdL.FileSize() - 1; + for (size_t i = 0; i != filesize; ++i) + { + std::string needle = std::string("\n") + CmdL.FileList[i + 1] + "\n"; + std::transform(needle.begin(), needle.end(), needle.begin(), ::tolower); + if (haystack.find(needle) != std::string::npos) + continue; + found = false; + break; + } + if (found == false) + continue; + } + } + + if (Format.empty()) + cout << stanza.str(); + else + { + std::string out = T->Format(Format); + for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) + out = SubstVar(out, std::string("$(") + O->first + ")", O->second); + cout << out << std::endl; + } + } + } + + return true; +} + /*}}}*/ // ShowHelp - Show a help screen /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1716,6 +1802,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {"source",&DoSource}, {"download",&DoDownload}, {"changelog",&DoChangelog}, + {"files",&DoFiles}, {"moo",&DoMoo}, {"help",&ShowHelp}, {0,0}}; diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt index ab833440b..a47dac2d4 100644 --- a/doc/acquire-additional-files.txt +++ b/doc/acquire-additional-files.txt @@ -47,11 +47,13 @@ All files which should be downloaded (nicknamed 'Targets') are mentioned below the APT::Acquire::Targets scope. 'deb' is here the type of the sources.list entry the file should be acquired for. The only other supported value is hence 'deb-src'. Beware: You can't specify multiple -types here and you can't download the same MetaKey form multiple types! +types here and you can't download the same (evaluated) MetaKey from +multiple types! After the type you can pick any valid and unique string which preferable refers to the file it downloads (In the example we picked 'Packages'). -This string is never shown or used. +This string is used as identifier for the target class and accessible as +'Created-By' e.g. in the "apt-get files" output as detailed below. All targets have three main properties you can define: * MetaKey: The identifier of the file to be downloaded as used in the @@ -123,11 +125,12 @@ by the acquire system. The following variables are known; note that unknown variables have no default value nor are they touched: They are printed literally. -* $(SITE): An identifier of the site we access, e.g. - "http://example.org/". +* $(SITE): An identifier of the site we access as seen in sources.list, + e.g. "http://example.org/debian" or "file:/path/to/a/repository". * $(RELEASE): This is usually an archive- or codename, e.g. "stable" or "stretch". Note that flat-style repositories do not have a archive- or codename per-se, so the value might very well be just "/" or so. + Again, as seen in the sources.list. * $(COMPONENT): as given in the sources.list, e.g. "main", "non-free" or "universe". Note that flat-style repositories again do not really have a meaningful value here. @@ -137,3 +140,79 @@ printed literally. APT::Architectures (potentially modified by sources.list options), e.g. "amd64", "i386" or "armel" for the 'deb' type. In type 'deb-src' this variable has the value "source". + +Note that while more variables might exist in the implementation, these +are to be considered undefined and their usage strongly discouraged. If +you have a need for another variable contact us instead. + +# Accessing files + +Do NOT hardcode specific file locations, names or compression types in +your application! You will notice that the configuration options give +you no choice over where the downloaded files will be stored. This is by +design so multiple applications can download and use the same file +rather than each and every one of them potentially downloads and uses +its own copy somewhere on disk. + +"apt-get files" can be used to get the location as well as other +information about all files downloaded (aka: you will see Packages, +Sources and Translation-* files here as well). Provide a line of the +default output format as parameter to filter out all entries which do +not have such a line. With --format, you can further more define your +own output style. The variables are what you see in the output, just all +uppercase and wrapped in $(), as in the configuration file. + +To get all the filenames of all Translation-en files you can e.g. call: + apt-get files --format '$(FILENAME)' "Created-By: Translations" "Language: en" + +Accessing this information via libapt is done by reading the +sources.lists (pkgSourceList), iterating over the metaIndex objects this +creates and calling GetIndexTargets() on them. See the sourcecode of +"apt-get files" for a complete example. + +Remarks on the available fields: +* MetaKey, ShortDesc, Description, Site, Release: as defined + by the configuration and described further above. +* Created-By: configuration entity responsible for this target +* Target-Of: type of the sources.list entry +* URI, Repo-URI: avoid using. Contains potentially username/password. + Prefer 'Site', especially for display. +* Filename: The mentioned file doesn't need to exist, e.g. because the + file wasn't downloaded yet – or it does exist compressed. libapt users + are encouraged to use FileFd to open such files as it can handle + decompression transparently. +* Trusted: As of the last 'apt-get update' call denoting if e.g. apt-get + would print the unauthenticated warning while installing packages + mentioned in this file (example assumes Packages file) [Not really + a property of the target itself, but of the metaIndex]. +* Optional: Decodes the option of the same name from the configuration. + Note that it is using 'yes' and 'no' instead of 'true' and 'false'. +* Language, Architecture, Component: as defined further above, but with + the catch that they might be missing if they don't effect the target + (aka: They weren't used while evaluating the MetaKey template). + +Again, additional fields might be visible in certain implementation, but +you should avoid using them and instead talk to us about a portable +implementation. + +# Multiple application requiring the same files + +It is highly encouraged that applications talk to each other and to us +about which files they require. It is usually best to have a common +package ship the configuration needed to get the files, but specific +needs might require specific solutions. Again: talk to us. + +# Acquiring files not mentioned in the Release file + +You can't. This is by design as these files couldn't be verified to not +be modified in transit, corrupted by the download process or simple if +they are present at all on the server, which would require apt to probe +for them. APT did this in the past for legacy reasons, we do not intend +to go back to these dark times. + +This is also why you can't request files from a different server. It +would have the additional problem that this server might not even be +accessible (e.g. proxy settings) or that local sources (file:/, cdrom:/) +start requesting online files… + +In other words: We would be opening Pandora's box. diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index a372a0d30..da077afa7 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -243,6 +243,21 @@ + + Displays by default a deb822 formatted listing of + information about all data files apt-get + update would download. Supports a + option to modify the output format as + well as accepts lines of the default output to filter the records + by. The command is mainly used as an interface for external tools + working with APT to get information as well as filenames for + downloaded files so they can use them as well instead of + downloading them again on their own. Detailed documentation is + omitted here and can instead be found in the source tree in + doc/acquire-additional-files.txt. + + + diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index 4a6845f40..971cfac2e 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -48,6 +48,7 @@ Get:1 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64' find rootdir/var/lib/apt/lists -name '*Contents*' +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64)" aptget files --format '$(FILENAME)' 'Created-By: Contents' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64' 'aptarchive/dists/unstable/main/Contents-amd64' # no automatic uncompress based on the name please, @@ -72,6 +73,7 @@ Get:1 http://localhost:8080 unstable/main amd64 Contents.gz [$(stat -c%s aptarch Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget files --format '$(FILENAME)' 'Created-By: Contents' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' 'aptarchive/dists/unstable/main/Contents-amd64.gz' rm -f rootdir/etc/apt/apt.conf.d/content-target.conf -- cgit v1.2.3-70-g09d2 From b07aeb1a6e24825e534167a737043441e871de9f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 02:08:53 +0200 Subject: store Release files data in the Cache We used to read the Release file for each Packages file and store the data in the PackageFile struct even through potentially many Packages (and Translation-*) files could use the same data. The point of the exercise isn't the duplicated data through. Having the Release files as first-class citizens in the Cache allows us to properly track their state as well as allows us to use the information also for files which aren't in the cache, but where we know to which Release file they belong (Sources are an example for this). This modifies the pkgCache structs, especially the PackagesFile struct which depending on how libapt users access the data in these structs can mean huge breakage or no visible change. As a single data point: aptitude seems to be fine with this. Even if there is breakage it is trivial to fix in a backportable way while avoiding breakage for everyone would be a huge pain for us. Note that not all PackageFile structs have a corresponding ReleaseFile. In particular the dpkg/status file as well as *.deb files have not. As these have only a Archive property need, the Component property takes over this duty and the ReleaseFile remains zero. This is also the reason why it isn't needed nor particularily recommended to change from PackagesFile to ReleaseFile blindly. Sticking with the earlier is usually the better option. --- apt-pkg/acquire-item.cc | 6 +- apt-pkg/cacheiterators.h | 46 ++++++- apt-pkg/clean.cc | 2 +- apt-pkg/deb/debindexfile.cc | 42 ++----- apt-pkg/deb/debindexfile.h | 1 - apt-pkg/deb/deblistparser.cc | 37 ------ apt-pkg/deb/deblistparser.h | 6 +- apt-pkg/deb/debmetaindex.cc | 124 ++++++++++++++++++- apt-pkg/deb/debmetaindex.h | 6 + apt-pkg/deb/dpkgpm.cc | 4 +- apt-pkg/depcache.cc | 6 +- apt-pkg/edsp.cc | 2 +- apt-pkg/edsp/edspindexfile.cc | 5 +- apt-pkg/edsp/edsplistparser.cc | 4 +- apt-pkg/edsp/edsplistparser.h | 4 +- apt-pkg/metaindex.cc | 17 +++ apt-pkg/metaindex.h | 6 + apt-pkg/pkgcache.cc | 77 ++++++++---- apt-pkg/pkgcache.h | 75 ++++++++++-- apt-pkg/pkgcachegen.cc | 226 +++++++++++++++++++++++++++-------- apt-pkg/pkgcachegen.h | 10 +- apt-pkg/policy.cc | 15 ++- apt-pkg/versionmatch.cc | 45 +++---- apt-pkg/versionmatch.h | 4 +- cmdline/apt-cache.cc | 11 +- test/integration/framework | 9 +- test/integration/test-policy-pinning | 2 +- 27 files changed, 573 insertions(+), 219 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index d4191f00e..d6e9ccbe0 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -2568,7 +2568,7 @@ pkgAcqArchive::pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sour // Skip not source sources, they do not have file fields. for (; Vf.end() == false; ++Vf) { - if ((Vf.File()->Flags & pkgCache::Flag::NotSource) != 0) + if (Vf.File().Flagged(pkgCache::Flag::NotSource)) continue; break; } @@ -2636,14 +2636,14 @@ bool pkgAcqArchive::QueueNext() { pkgCache::PkgFileIterator const PkgF = Vf.File(); // Ignore not source sources - if ((PkgF->Flags & pkgCache::Flag::NotSource) != 0) + if (PkgF.Flagged(pkgCache::Flag::NotSource)) continue; // Try to cross match against the source list pkgIndexFile *Index; if (Sources->FindIndex(PkgF, Index) == false) continue; - LocalSource = (PkgF->Flags & pkgCache::Flag::LocalSource) == pkgCache::Flag::LocalSource; + LocalSource = PkgF.Flagged(pkgCache::Flag::LocalSource); // only try to get a trusted package from another source if that source // is also trusted diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index fe798799c..301da6fc4 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -367,27 +367,61 @@ class pkgCache::PrvIterator : public Iterator { } }; /*}}}*/ -// Package file /*{{{*/ -class pkgCache::PkgFileIterator : public Iterator { +// Release file /*{{{*/ +class pkgCache::RlsFileIterator : public Iterator { protected: - inline PackageFile* OwnerPointer() const { - return (Owner != 0) ? Owner->PkgFileP : 0; + inline ReleaseFile* OwnerPointer() const { + return (Owner != 0) ? Owner->RlsFileP : 0; } public: // Iteration - void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;} + void operator ++(int) {if (S != Owner->RlsFileP) S = Owner->RlsFileP + S->NextFile;} inline void operator ++() {operator ++(0);} // Accessors inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;} inline const char *Archive() const {return S->Archive == 0?0:Owner->StrP + S->Archive;} - inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;} inline const char *Version() const {return S->Version == 0?0:Owner->StrP + S->Version;} inline const char *Origin() const {return S->Origin == 0?0:Owner->StrP + S->Origin;} inline const char *Codename() const {return S->Codename ==0?0:Owner->StrP + S->Codename;} inline const char *Label() const {return S->Label == 0?0:Owner->StrP + S->Label;} inline const char *Site() const {return S->Site == 0?0:Owner->StrP + S->Site;} + inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return (S->Flags & flag) == flag; } + + bool IsOk(); + std::string RelStr(); + + // Constructors + inline RlsFileIterator() : Iterator() {} + inline RlsFileIterator(pkgCache &Owner) : Iterator(Owner, Owner.RlsFileP) {} + inline RlsFileIterator(pkgCache &Owner,ReleaseFile *Trg) : Iterator(Owner, Trg) {} +}; + /*}}}*/ +// Package file /*{{{*/ +class pkgCache::PkgFileIterator : public Iterator { + protected: + inline PackageFile* OwnerPointer() const { + return (Owner != 0) ? Owner->PkgFileP : 0; + } + + public: + // Iteration + void operator ++(int) {if (S != Owner->PkgFileP) S = Owner->PkgFileP + S->NextFile;} + inline void operator ++() {operator ++(0);} + + // Accessors + inline const char *FileName() const {return S->FileName == 0?0:Owner->StrP + S->FileName;} + inline pkgCache::RlsFileIterator ReleaseFile() const {return RlsFileIterator(*Owner, Owner->RlsFileP + S->Release);} + inline const char *Archive() const {return S->Release == 0 ? Component() : ReleaseFile().Archive();} + inline const char *Version() const {return S->Release == 0 ? NULL : ReleaseFile().Version();} + inline const char *Origin() const {return S->Release == 0 ? NULL : ReleaseFile().Origin();} + inline const char *Codename() const {return S->Release == 0 ? NULL : ReleaseFile().Codename();} + inline const char *Label() const {return S->Release == 0 ? NULL : ReleaseFile().Label();} + inline const char *Site() const {return S->Release == 0 ? NULL : ReleaseFile().Site();} + inline bool Flagged(pkgCache::Flag::ReleaseFileFlags const flag) const {return S->Release== 0 ? false : ReleaseFile().Flagged(flag);} + inline bool Flagged(pkgCache::Flag::PkgFFlags const flag) const {return (S->Flags & flag) == flag;} + inline const char *Component() const {return S->Component == 0?0:Owner->StrP + S->Component;} inline const char *Architecture() const {return S->Architecture == 0?0:Owner->StrP + S->Architecture;} inline const char *IndexType() const {return S->IndexType == 0?0:Owner->StrP + S->IndexType;} diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 6edce5b6d..0fca60ba9 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -106,7 +106,7 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) J.end() == false; ++J) { if (CleanInstalled == true && - (J.File()->Flags & pkgCache::Flag::NotSource) != 0) + J.File().Flagged(pkgCache::Flag::NotSource)) continue; IsFetchable = true; break; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 7aad65c0e..3a79cbc58 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -128,7 +128,7 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Dist.empty()) Dist = "/"; ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) + if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::COMPONENT)) == false) return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); // Store the IMS information @@ -136,31 +136,10 @@ bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const pkgCacheGenerator::Dynamic DynFile(File); File->Size = Pkg.FileSize(); File->mtime = Pkg.ModificationTime(); - + if (Gen.MergeList(Parser) == false) return _error->Error("Problem with MergeList %s",PackageFile.c_str()); - // Check the release file - string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease"); - bool releaseExists = false; - if (FileExists(ReleaseFile) == true) - releaseExists = true; - else - ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release"); - - if (releaseExists == true || FileExists(ReleaseFile) == true) - { - FileFd Rel; - // Beware: The 'Release' file might be clearsigned in case the - // signature for an 'InRelease' file couldn't be checked - if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) - return false; - - if (_error->PendingError() == true) - return false; - Parser.LoadReleaseInfo(File, Rel, Target.Option(IndexTarget::COMPONENT)); - } - return true; } /*}}}*/ @@ -221,17 +200,17 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const debTranslationsParser TransParser(&Trans); if (_error->PendingError() == true) return false; - + if (Prog != NULL) Prog->SubProgress(0, Target.Description); - if (Gen.SelectFile(TranslationFile,string(),*this) == false) + if (Gen.SelectFile(TranslationFile, *this, Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource) == false) return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); // Store the IMS information pkgCache::PkgFileIterator TransFile = Gen.GetCurFile(); TransFile->Size = Trans.FileSize(); TransFile->mtime = Trans.ModificationTime(); - + if (Gen.MergeList(TransParser) == false) return _error->Error("Problem with MergeList %s",TranslationFile.c_str()); } @@ -305,18 +284,17 @@ bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false) + if (Gen.SelectFile(File, *this, "now", pkgCache::Flag::NotSource) == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(CFile); CFile->Size = Pkg.FileSize(); CFile->mtime = Pkg.ModificationTime(); - map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now"); - CFile->Archive = storage; - + if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); + return _error->Error("Problem with MergeList %s",File.c_str()); return true; } /*}}}*/ @@ -431,7 +409,7 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // and give it to the list parser debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == false) + if(Gen.SelectFile(DebFile, *this, "now", pkgCache::Flag::LocalSource) == false) return _error->Error("Problem with SelectFile %s", DebFile.c_str()); pkgCache::PkgFileIterator File = Gen.GetCurFile(); diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index dd3f212b2..6b8c78e5a 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -45,7 +45,6 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile virtual bool HasPackages() const {return true;}; virtual unsigned long Size() const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog, unsigned long const Flag) const; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; debStatusIndex(std::string File); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b80b57bc4..c5e77b0ff 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -951,43 +951,6 @@ bool debListParser::Step() return false; } /*}}}*/ -// ListParser::LoadReleaseInfo - Load the release information /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debListParser::LoadReleaseInfo(pkgCache::PkgFileIterator &FileI, - FileFd &File, string component) -{ - // apt-secure does no longer download individual (per-section) Release - // file. to provide Component pinning we use the section name now - map_stringitem_t const storage = StoreString(pkgCacheGenerator::MIXED, component); - FileI->Component = storage; - - pkgTagFile TagFile(&File, File.Size()); - pkgTagSection Section; - if (_error->PendingError() == true || TagFile.Step(Section) == false) - return false; - - std::string data; - #define APT_INRELEASE(TYPE, TAG, STORE) \ - data = Section.FindS(TAG); \ - if (data.empty() == false) \ - { \ - map_stringitem_t const storage = StoreString(pkgCacheGenerator::TYPE, data); \ - STORE = storage; \ - } - APT_INRELEASE(MIXED, "Suite", FileI->Archive) - APT_INRELEASE(MIXED, "Component", FileI->Component) - APT_INRELEASE(VERSIONNUMBER, "Version", FileI->Version) - APT_INRELEASE(MIXED, "Origin", FileI->Origin) - APT_INRELEASE(MIXED, "Codename", FileI->Codename) - APT_INRELEASE(MIXED, "Label", FileI->Label) - #undef APT_INRELEASE - Section.FindFlag("NotAutomatic", FileI->Flags, pkgCache::Flag::NotAutomatic); - Section.FindFlag("ButAutomaticUpgrades", FileI->Flags, pkgCache::Flag::ButAutomaticUpgrades); - - return !_error->PendingError(); -} - /*}}}*/ // ListParser::GetPrio - Convert the priority from a string /*{{{*/ // --------------------------------------------------------------------- /* */ diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 6279d8399..420d5ff08 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -80,9 +80,9 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser virtual map_filesize_t Size() {return Section.size();}; virtual bool Step(); - - bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, - std::string section); + + bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, + std::string const §ion); APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, std::string &Package,std::string &Ver,unsigned int &Op); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 8e4c2be2d..994b95849 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -10,10 +11,12 @@ #include #include #include -#include #include +#include +#include +#include +#include -#include #include #include #include @@ -21,6 +24,11 @@ #include #include +#include +#include +#include +#include + using namespace std; string debReleaseIndex::MetaIndexInfo(const char *Type) const @@ -37,6 +45,10 @@ string debReleaseIndex::MetaIndexInfo(const char *Type) const Info += Type; return Info; } +std::string debReleaseIndex::Describe() const +{ + return MetaIndexInfo("Release"); +} string debReleaseIndex::MetaIndexFile(const char *Type) const { @@ -339,6 +351,114 @@ debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, bool const &IsSrc): Section(Section), IsSrc(IsSrc) {} +static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile) +{ + ReleaseFile = That->MetaIndexFile("InRelease"); + bool releaseExists = false; + if (FileExists(ReleaseFile) == true) + releaseExists = true; + else + { + ReleaseFile = That->MetaIndexFile("Release"); + if (FileExists(ReleaseFile)) + releaseExists = true; + } + return releaseExists; +} + +bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/ +{ + std::string ReleaseFile; + bool const releaseExists = ReleaseFileName(this, ReleaseFile); + + ::URI Tmp(URI); + if (Gen.SelectReleaseFile(ReleaseFile, Tmp.Host) == false) + return _error->Error("Problem with SelectReleaseFile %s", ReleaseFile.c_str()); + + if (releaseExists == false) + return true; + + FileFd Rel; + // Beware: The 'Release' file might be clearsigned in case the + // signature for an 'InRelease' file couldn't be checked + if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) + return false; + if (_error->PendingError() == true) + return false; + + // Store the IMS information + pkgCache::RlsFileIterator File = Gen.GetCurRlsFile(); + pkgCacheGenerator::Dynamic DynFile(File); + // Rel can't be used as this is potentially a temporary file + struct stat Buf; + if (stat(ReleaseFile.c_str(), &Buf) != 0) + return _error->Errno("fstat", "Unable to stat file %s", ReleaseFile.c_str()); + File->Size = Buf.st_size; + File->mtime = Buf.st_mtime; + + pkgTagFile TagFile(&Rel, Rel.Size()); + pkgTagSection Section; + if (_error->PendingError() == true || TagFile.Step(Section) == false) + return false; + + std::string data; + #define APT_INRELEASE(TYPE, TAG, STORE) \ + data = Section.FindS(TAG); \ + if (data.empty() == false) \ + { \ + map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::TYPE, data); \ + STORE = storage; \ + } + APT_INRELEASE(MIXED, "Suite", File->Archive) + APT_INRELEASE(VERSIONNUMBER, "Version", File->Version) + APT_INRELEASE(MIXED, "Origin", File->Origin) + APT_INRELEASE(MIXED, "Codename", File->Codename) + APT_INRELEASE(MIXED, "Label", File->Label) + #undef APT_INRELEASE + Section.FindFlag("NotAutomatic", File->Flags, pkgCache::Flag::NotAutomatic); + Section.FindFlag("ButAutomaticUpgrades", File->Flags, pkgCache::Flag::ButAutomaticUpgrades); + + return !_error->PendingError(); +} + /*}}}*/ +// ReleaseIndex::FindInCache - Find this index /*{{{*/ +pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache) const +{ + std::string ReleaseFile; + bool const releaseExists = ReleaseFileName(this, ReleaseFile); + + pkgCache::RlsFileIterator File = Cache.RlsFileBegin(); + for (; File.end() == false; ++File) + { + if (File->FileName == 0 || ReleaseFile != File.FileName()) + continue; + + // empty means the file does not exist by "design" + if (releaseExists == false && File->Size == 0) + return File; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "ReleaseIndex::FindInCache - stat failed on " << File.FileName() << std::endl; + return pkgCache::RlsFileIterator(Cache); + } + if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "ReleaseIndex::FindInCache - size (" << St.st_size << " <> " << File->Size + << ") or mtime (" << St.st_mtime << " <> " << File->mtime + << ") doesn't match for " << File.FileName() << std::endl; + return pkgCache::RlsFileIterator(Cache); + } + return File; + } + + return File; +} + /*}}}*/ + class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { protected: diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 0b1b08432..7e9942710 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -20,6 +20,8 @@ class pkgAcquire; class pkgIndexFile; class debDebPkgFileIndex; class IndexTarget; +class pkgCacheGenerator; +class OpProgress; class APT_HIDDEN debReleaseIndex : public metaIndex { public: @@ -48,6 +50,10 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; virtual std::vector GetIndexTargets() const; + virtual std::string Describe() const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + std::string MetaIndexInfo(const char *Type) const; std::string MetaIndexFile(const char *Types) const; std::string MetaIndexURI(const char *Type) const; diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index a7a66c75d..6ee939edd 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -205,8 +205,10 @@ pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) for (pkgCache::VerFileIterator Vf = Ver.FileList(); Vf.end() == false; ++Vf) for (pkgCache::PkgFileIterator F = Vf.File(); F.end() == false; ++F) - if (F->Archive != 0 && strcmp(F.Archive(), "now") == 0) + { + if (F.Archive() != 0 && strcmp(F.Archive(), "now") == 0) return Ver; + } return Ver; } /*}}}*/ diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index b73c336db..36e1ac9ec 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1685,13 +1685,13 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk for (VerFileIterator J = I.FileList(); J.end() == false; ++J) { - if ((J.File()->Flags & Flag::NotSource) != 0) + if (J.File().Flagged(Flag::NotSource)) continue; /* Stash the highest version of a not-automatic source, we use it if there is nothing better */ - if ((J.File()->Flags & Flag::NotAutomatic) != 0 || - (J.File()->Flags & Flag::ButAutomaticUpgrades) != 0) + if (J.File().Flagged(Flag::NotAutomatic) || + J.File().Flagged(Flag::ButAutomaticUpgrades)) { if (Last.end() == true) Last = I; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 3c6a7e30f..41cc2cdfe 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -129,7 +129,7 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI signed short const p = Cache.GetPolicy().GetPriority(File); if (Pin < p) Pin = p; - if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) { + if (File.Flagged(pkgCache::Flag::NotSource) == false) { string Release = File.RelStr(); if (!Release.empty()) Releases.insert(Release); diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index d00536362..43dd44a79 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -49,15 +49,14 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (Prog != NULL) Prog->SubProgress(0,File); - if (Gen.SelectFile(File,std::string(),*this) == false) + if (Gen.SelectFile(File, *this, "edsp") == false) return _error->Error("Problem with SelectFile %s",File.c_str()); // Store the IMS information pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(CFile); CFile->Size = Pkg.FileSize(); CFile->mtime = Pkg.ModificationTime(); - map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "edsp::scenario"); - CFile->Archive = storage; if (Gen.MergeList(Parser) == false) return _error->Error("Problem with MergeList %s",File.c_str()); diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 212dc7840..d62abe709 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -86,8 +86,8 @@ bool edspListParser::ParseStatus(pkgCache::PkgIterator &Pkg, } /*}}}*/ // ListParser::LoadReleaseInfo - Load the release information /*{{{*/ -APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::PkgFileIterator & /*FileI*/, - FileFd & /*File*/, std::string /*component*/) +APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::RlsFileIterator & /*FileI*/, + FileFd & /*File*/, std::string const &/*component*/) { return true; } diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 86cd77606..abe2ef139 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -34,8 +34,8 @@ class APT_HIDDEN edspListParser : public debListParser virtual MD5SumValue Description_md5(); virtual unsigned short VersionHash(); - bool LoadReleaseInfo(pkgCache::PkgFileIterator &FileI,FileFd &File, - std::string section); + bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, + std::string const §ion); edspListParser(FileFd *File, std::string const &Arch = ""); diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 31a8ec009..35ab6c53b 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -1,4 +1,5 @@ // Include Files /*{{{*/ +#include #include #include @@ -22,6 +23,22 @@ std::string metaIndex::LocalFileName() const } #endif +std::string metaIndex::Describe() const +{ + return "Release"; +} + +pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache) const +{ + return pkgCache::RlsFileIterator(Cache); +} + +bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const +{ + return Gen.SelectReleaseFile("", ""); +} + + metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) : Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false) diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 4e5de8be0..20c879a89 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -23,6 +23,8 @@ using std::string; class pkgAcquire; class IndexTarget; +class pkgCacheGenerator; +class OpProgress; class metaIndex { @@ -51,6 +53,10 @@ class metaIndex virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; + virtual std::string Describe() const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + metaIndex(std::string const &URI, std::string const &Dist, char const * const Type); virtual ~metaIndex(); diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 864ae0f60..9fe382108 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -61,6 +61,7 @@ pkgCache::Header::Header() HeaderSz = sizeof(pkgCache::Header); GroupSz = sizeof(pkgCache::Group); PackageSz = sizeof(pkgCache::Package); + ReleaseFileSz = sizeof(pkgCache::ReleaseFile); PackageFileSz = sizeof(pkgCache::PackageFile); VersionSz = sizeof(pkgCache::Version); DescriptionSz = sizeof(pkgCache::Description); @@ -74,6 +75,7 @@ pkgCache::Header::Header() VersionCount = 0; DescriptionCount = 0; DependsCount = 0; + ReleaseFileCount = 0; PackageFileCount = 0; VerFileCount = 0; DescFileCount = 0; @@ -82,6 +84,7 @@ pkgCache::Header::Header() MaxDescFileSize = 0; FileList = 0; + RlsFileList = 0; #if APT_PKG_ABI < 413 APT_IGNORE_DEPRECATED(StringList = 0;) #endif @@ -102,6 +105,7 @@ bool pkgCache::Header::CheckSizes(Header &Against) const if (HeaderSz == Against.HeaderSz && GroupSz == Against.GroupSz && PackageSz == Against.PackageSz && + ReleaseFileSz == Against.ReleaseFileSz && PackageFileSz == Against.PackageFileSz && VersionSz == Against.VersionSz && DescriptionSz == Against.DescriptionSz && @@ -140,6 +144,7 @@ bool pkgCache::ReMap(bool const &Errorchecks) PkgP = (Package *)Map.Data(); VerFileP = (VerFile *)Map.Data(); DescFileP = (DescFile *)Map.Data(); + RlsFileP = (ReleaseFile *)Map.Data(); PkgFileP = (PackageFile *)Map.Data(); VerP = (Version *)Map.Data(); DescP = (Description *)Map.Data(); @@ -814,7 +819,7 @@ APT_PURE bool pkgCache::VerIterator::Downloadable() const { VerFileIterator Files = FileList(); for (; Files.end() == false; ++Files) - if ((Files.File()->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) + if (Files.File().Flagged(pkgCache::Flag::NotSource) == false) return true; return false; } @@ -828,7 +833,7 @@ APT_PURE bool pkgCache::VerIterator::Automatic() const VerFileIterator Files = FileList(); for (; Files.end() == false; ++Files) // Do not check ButAutomaticUpgrades here as it is kind of automatic… - if ((Files.File()->Flags & pkgCache::Flag::NotAutomatic) != pkgCache::Flag::NotAutomatic) + if (Files.File().Flagged(pkgCache::Flag::NotAutomatic) == false) return true; return false; } @@ -861,27 +866,27 @@ string pkgCache::VerIterator::RelStr() const for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I) { // Do not print 'not source' entries' - pkgCache::PkgFileIterator File = I.File(); - if ((File->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) + pkgCache::PkgFileIterator const File = I.File(); + if (File.Flagged(pkgCache::Flag::NotSource)) continue; // See if we have already printed this out.. bool Seen = false; for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J) { - pkgCache::PkgFileIterator File2 = J.File(); - if (File2->Label == 0 || File->Label == 0) + pkgCache::PkgFileIterator const File2 = J.File(); + if (File2.Label() == 0 || File.Label() == 0) continue; if (strcmp(File.Label(),File2.Label()) != 0) continue; - if (File2->Version == File->Version) + if (File2.Version() == File.Version()) { Seen = true; break; } - if (File2->Version == 0 || File->Version == 0) + if (File2.Version() == 0 || File.Version() == 0) break; if (strcmp(File.Version(),File2.Version()) == 0) Seen = true; @@ -895,12 +900,12 @@ string pkgCache::VerIterator::RelStr() const else First = false; - if (File->Label != 0) + if (File.Label() != 0) Res = Res + File.Label() + ':'; - if (File->Archive != 0) + if (File.Archive() != 0) { - if (File->Version == 0) + if (File.Version() == 0) Res += File.Archive(); else Res = Res + File.Version() + '/' + File.Archive(); @@ -908,7 +913,7 @@ string pkgCache::VerIterator::RelStr() const else { // No release file, print the host name that this came from - if (File->Site == 0 || File.Site()[0] == 0) + if (File.Site() == 0 || File.Site()[0] == 0) Res += "localhost"; else Res += File.Site(); @@ -931,12 +936,12 @@ const char * pkgCache::VerIterator::MultiArchType() const return "none"; } /*}}}*/ -// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ +// RlsFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ // --------------------------------------------------------------------- /* This stats the file and compares its stats with the ones that were - stored during generation. Date checks should probably also be + stored during generation. Date checks should probably also be included here. */ -bool pkgCache::PkgFileIterator::IsOk() +bool pkgCache::RlsFileIterator::IsOk() { struct stat Buf; if (stat(FileName(),&Buf) != 0) @@ -948,10 +953,8 @@ bool pkgCache::PkgFileIterator::IsOk() return true; } /*}}}*/ -// PkgFileIterator::RelStr - Return the release string /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string pkgCache::PkgFileIterator::RelStr() +// RlsFileIterator::RelStr - Return the release string /*{{{*/ +string pkgCache::RlsFileIterator::RelStr() { string Res; if (Version() != 0) @@ -964,8 +967,40 @@ string pkgCache::PkgFileIterator::RelStr() Res = Res + (Res.empty() == true?"n=":",n=") + Codename(); if (Label() != 0) Res = Res + (Res.empty() == true?"l=":",l=") + Label(); - if (Component() != 0) - Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + return Res; +} + /*}}}*/ +// PkgFileIterator::IsOk - Checks if the cache is in sync with the file /*{{{*/ +// --------------------------------------------------------------------- +/* This stats the file and compares its stats with the ones that were + stored during generation. Date checks should probably also be + included here. */ +bool pkgCache::PkgFileIterator::IsOk() +{ + struct stat Buf; + if (stat(FileName(),&Buf) != 0) + return false; + + if (Buf.st_size != (signed)S->Size || Buf.st_mtime != S->mtime) + return false; + + return true; +} + /*}}}*/ +string pkgCache::PkgFileIterator::RelStr() /*{{{*/ +{ + std::string Res; + if (ReleaseFile() == 0) + { + if (Component() != 0) + Res = Res + (Res.empty() == true?"a=":",a=") + Component(); + } + else + { + Res = ReleaseFile().RelStr(); + if (Component() != 0) + Res = Res + (Res.empty() == true?"c=":",c=") + Component(); + } if (Architecture() != 0) Res = Res + (Res.empty() == true?"b=":",b=") + Architecture(); return Res; diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index b4d56611a..696b3b94d 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -133,6 +133,7 @@ class pkgCache /*{{{*/ struct Header; struct Group; struct Package; + struct ReleaseFile; struct PackageFile; struct Version; struct Description; @@ -150,6 +151,7 @@ class pkgCache /*{{{*/ class DescIterator; class DepIterator; class PrvIterator; + class RlsFileIterator; class PkgFileIterator; class VerFileIterator; class DescFileIterator; @@ -192,9 +194,11 @@ class pkgCache /*{{{*/ enum PkgFlags {Auto=(1<<0),Essential=(1<<3),Important=(1<<4)}; enum PkgFFlags { NotSource=(1<<0), /*!< packages can't be fetched from here, e.g. dpkg/status file */ - NotAutomatic=(1<<1), /*!< archive has a default pin of 1 */ - ButAutomaticUpgrades=(1<<2), /*!< (together with the previous) archive has a default pin of 100 */ - LocalSource=(1<<3), /*!< local sources can't and will not be verified by hashes */ + LocalSource=(1<<1), /*!< local sources can't and will not be verified by hashes */ + }; + enum ReleaseFileFlags { + NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */ + ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */ }; }; @@ -215,6 +219,7 @@ class pkgCache /*{{{*/ Package *PkgP; VerFile *VerFileP; DescFile *DescFileP; + ReleaseFile *RlsFileP; PackageFile *PkgFileP; Version *VerP; Description *DescP; @@ -247,6 +252,8 @@ class pkgCache /*{{{*/ inline PkgIterator PkgEnd(); inline PkgFileIterator FileBegin(); inline PkgFileIterator FileEnd(); + inline RlsFileIterator RlsFileBegin(); + inline RlsFileIterator RlsFileEnd(); inline bool MultiArchCache() const { return MultiArchEnabled; } inline char const * NativeArch(); @@ -296,6 +303,7 @@ struct pkgCache::Header unsigned short HeaderSz; unsigned short GroupSz; unsigned short PackageSz; + unsigned short ReleaseFileSz; unsigned short PackageFileSz; unsigned short VersionSz; unsigned short DescriptionSz; @@ -314,6 +322,7 @@ struct pkgCache::Header map_id_t VersionCount; map_id_t DescriptionCount; map_id_t DependsCount; + map_fileid_t ReleaseFileCount; map_fileid_t PackageFileCount; map_fileid_t VerFileCount; map_fileid_t DescFileCount; @@ -324,6 +333,9 @@ struct pkgCache::Header The PackageFile structures are singly linked lists that represent all package files that have been merged into the cache. */ map_pointer_t FileList; + /** \brief index of the first ReleaseFile structure */ + map_pointer_t RlsFileList; + #if APT_PKG_ABI < 413 APT_DEPRECATED map_pointer_t StringList; #endif @@ -482,15 +494,14 @@ struct pkgCache::Package unsigned long Flags; }; /*}}}*/ -// Package File structure /*{{{*/ -/** \brief stores information about the files used to generate the cache +// Release File structure /*{{{*/ +/** \brief stores information about the release files used to generate the cache - Package files are referenced by Version structures to be able to know - after the generation still from which Packages file includes this Version - as we need this information later on e.g. for pinning. */ -struct pkgCache::PackageFile + PackageFiles reference ReleaseFiles as we need to keep record of which + version belongs to which release e.g. for pinning. */ +struct pkgCache::ReleaseFile { - /** \brief physical disk file that this PackageFile represents */ + /** \brief physical disk file that this ReleaseFile represents */ map_stringitem_t FileName; /** \brief the release information @@ -498,13 +509,47 @@ struct pkgCache::PackageFile release information means. */ map_stringitem_t Archive; map_stringitem_t Codename; - map_stringitem_t Component; map_stringitem_t Version; map_stringitem_t Origin; map_stringitem_t Label; - map_stringitem_t Architecture; /** \brief The site the index file was fetched from */ map_stringitem_t Site; + + /** \brief Size of the file + + Used together with the modification time as a + simple check to ensure that the Packages + file has not been altered since Cache generation. */ + map_filesize_t Size; + /** \brief Modification time for the file */ + time_t mtime; + + /** @TODO document PackageFile::Flags */ + unsigned long Flags; + + // Linked list + /** \brief Link to the next ReleaseFile in the Cache */ + map_pointer_t NextFile; + /** \brief unique sequel ID */ + should_be_map_fileid_t ID; +}; + /*}}}*/ +// Package File structure /*{{{*/ +/** \brief stores information about the files used to generate the cache + + Package files are referenced by Version structures to be able to know + after the generation still from which Packages file includes this Version + as we need this information later on e.g. for pinning. */ +struct pkgCache::PackageFile +{ + /** \brief physical disk file that this PackageFile represents */ + map_stringitem_t FileName; + /** \brief the release information */ + map_pointer_t Release; + + map_stringitem_t Component; + map_stringitem_t Architecture; + /** \brief indicates what sort of index file this is @TODO enumerate at least the possible indexes */ @@ -744,6 +789,11 @@ inline pkgCache::PkgFileIterator pkgCache::FileBegin() {return PkgFileIterator(*this,PkgFileP + HeaderP->FileList);} inline pkgCache::PkgFileIterator pkgCache::FileEnd() {return PkgFileIterator(*this,PkgFileP);} +inline pkgCache::RlsFileIterator pkgCache::RlsFileBegin() + {return RlsFileIterator(*this,RlsFileP + HeaderP->RlsFileList);} +inline pkgCache::RlsFileIterator pkgCache::RlsFileEnd() + {return RlsFileIterator(*this,RlsFileP);} + // Oh I wish for Real Name Space Support class pkgCache::Namespace /*{{{*/ @@ -755,6 +805,7 @@ class pkgCache::Namespace /*{{{*/ typedef pkgCache::DescIterator DescIterator; typedef pkgCache::DepIterator DepIterator; typedef pkgCache::PrvIterator PrvIterator; + typedef pkgCache::RlsFileIterator RlsFileIterator; typedef pkgCache::PkgFileIterator PkgFileIterator; typedef pkgCache::VerFileIterator VerFileIterator; typedef pkgCache::Version Version; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ba454f057..2d0e3960d 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -54,10 +54,8 @@ using std::string; /* We set the dirty flag and make sure that is written to the disk */ pkgCacheGenerator::pkgCacheGenerator(DynamicMMap *pMap,OpProgress *Prog) : Map(*pMap), Cache(pMap,false), Progress(Prog), - FoundFileDeps(0) + CurrentRlsFile(NULL), CurrentFile(NULL), FoundFileDeps(0) { - CurrentFile = 0; - if (_error->PendingError() == true) return; @@ -145,6 +143,7 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM Cache.ReMap(false); CurrentFile += (pkgCache::PackageFile const * const) newMap - (pkgCache::PackageFile const * const) oldMap; + CurrentRlsFile += (pkgCache::ReleaseFile const * const) newMap - (pkgCache::ReleaseFile const * const) oldMap; for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) @@ -167,6 +166,9 @@ void pkgCacheGenerator::ReMap(void const * const oldMap, void const * const newM for (std::vector::const_iterator i = Dynamic::toReMap.begin(); i != Dynamic::toReMap.end(); ++i) (*i)->ReMap(oldMap, newMap); + for (std::vector::const_iterator i = Dynamic::toReMap.begin(); + i != Dynamic::toReMap.end(); ++i) + (*i)->ReMap(oldMap, newMap); } /*}}}*/ // CacheGenerator::WriteStringInMap /*{{{*/ map_stringitem_t pkgCacheGenerator::WriteStringInMap(const char *String, @@ -1072,13 +1074,47 @@ bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{* return Hash == Ver->Hash; } /*}}}*/ +// CacheGenerator::SelectReleaseFile - Select the current release file the indexes belong to /*{{{*/ +bool pkgCacheGenerator::SelectReleaseFile(const string &File,const string &Site, + unsigned long Flags) +{ + if (File.empty() && Site.empty()) + { + CurrentRlsFile = NULL; + return true; + } + + // Get some space for the structure + map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentRlsFile)); + if (unlikely(idxFile == 0)) + return false; + CurrentRlsFile = Cache.RlsFileP + idxFile; + + // Fill it in + map_stringitem_t const idxFileName = WriteStringInMap(File); + map_stringitem_t const idxSite = StoreString(MIXED, Site); + if (unlikely(idxFileName == 0 || idxSite == 0)) + return false; + CurrentRlsFile->FileName = idxFileName; + CurrentRlsFile->Site = idxSite; + CurrentRlsFile->NextFile = Cache.HeaderP->RlsFileList; + CurrentRlsFile->Flags = Flags; + CurrentRlsFile->ID = Cache.HeaderP->ReleaseFileCount; + RlsFileName = File; + Cache.HeaderP->RlsFileList = CurrentRlsFile - Cache.RlsFileP; + Cache.HeaderP->ReleaseFileCount++; + + return true; +} + /*}}}*/ // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/ // --------------------------------------------------------------------- /* This is used to select which file is to be associated with all newly added versions. The caller is responsible for setting the IMS fields. */ -bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, - const pkgIndexFile &Index, - unsigned long Flags) +bool pkgCacheGenerator::SelectFile(std::string const &File, + pkgIndexFile const &Index, + std::string const &Component, + unsigned long const Flags) { // Get some space for the structure map_pointer_t const idxFile = AllocateInMap(sizeof(*CurrentFile)); @@ -1088,18 +1124,24 @@ bool pkgCacheGenerator::SelectFile(const string &File,const string &Site, // Fill it in map_stringitem_t const idxFileName = WriteStringInMap(File); - map_stringitem_t const idxSite = StoreString(MIXED, Site); - if (unlikely(idxFileName == 0 || idxSite == 0)) + if (unlikely(idxFileName == 0)) return false; CurrentFile->FileName = idxFileName; - CurrentFile->Site = idxSite; CurrentFile->NextFile = Cache.HeaderP->FileList; - CurrentFile->Flags = Flags; CurrentFile->ID = Cache.HeaderP->PackageFileCount; map_stringitem_t const idxIndexType = StoreString(MIXED, Index.GetType()->Label); if (unlikely(idxIndexType == 0)) return false; CurrentFile->IndexType = idxIndexType; + map_stringitem_t const component = StoreString(pkgCacheGenerator::MIXED, Component); + if (unlikely(component == 0)) + return false; + CurrentFile->Component = component; + CurrentFile->Flags = Flags; + if (CurrentRlsFile != NULL) + CurrentFile->Release = CurrentRlsFile - Cache.RlsFileP; + else + CurrentFile->Release = 0; PkgFileName = File; Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP; Cache.HeaderP->PackageFileCount++; @@ -1174,35 +1216,59 @@ static bool CheckValidity(const string &CacheFile, _error->Discard(); return false; } - + + SPtrArray RlsVisited = new bool[Cache.HeaderP->ReleaseFileCount]; + memset(RlsVisited,0,sizeof(*RlsVisited)*Cache.HeaderP->ReleaseFileCount); + std::vector Files; + for (pkgSourceList::const_iterator i = List.begin(); i != List.end(); ++i) + { + if (Debug == true) + std::clog << "Checking RlsFile " << (*i)->Describe() << ": "; + pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache); + if (RlsFile.end() == true) + { + if (Debug == true) + std::clog << "FindInCache returned end-Pointer" << std::endl; + return false; + } + + RlsVisited[RlsFile->ID] = true; + if (Debug == true) + std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl; + + std::vector *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) + if ((*j)->HasPackages()) + Files.push_back (*j); + } + for (unsigned I = 0; I != Cache.HeaderP->ReleaseFileCount; ++I) + if (RlsVisited[I] == false) + { + if (Debug == true) + std::clog << "RlsFile with ID" << I << " wasn't visited" << std::endl; + return false; + } + + for (; Start != End; ++Start) + Files.push_back(*Start); + /* Now we check every index file, see if it is in the cache, verify the IMS data and check that it is on the disk too.. */ SPtrArray Visited = new bool[Cache.HeaderP->PackageFileCount]; memset(Visited,0,sizeof(*Visited)*Cache.HeaderP->PackageFileCount); - for (; Start != End; ++Start) + for (std::vector::const_reverse_iterator PkgFile = Files.rbegin(); PkgFile != Files.rend(); ++PkgFile) { if (Debug == true) - std::clog << "Checking PkgFile " << (*Start)->Describe() << ": "; - if ((*Start)->HasPackages() == false) - { - if (Debug == true) - std::clog << "Has NO packages" << std::endl; - continue; - } - - if ((*Start)->Exists() == false) + std::clog << "Checking PkgFile " << (*PkgFile)->Describe() << ": "; + if ((*PkgFile)->Exists() == false) { -#if 0 // mvo: we no longer give a message here (Default Sources spec) - _error->WarningE("stat",_("Couldn't stat source package list %s"), - (*Start)->Describe().c_str()); -#endif if (Debug == true) std::clog << "file doesn't exist" << std::endl; continue; } // FindInCache is also expected to do an IMS check. - pkgCache::PkgFileIterator File = (*Start)->FindInCache(Cache); + pkgCache::PkgFileIterator File = (*PkgFile)->FindInCache(Cache); if (File.end() == true) { if (Debug == true) @@ -1214,15 +1280,15 @@ static bool CheckValidity(const string &CacheFile, if (Debug == true) std::clog << "with ID " << File->ID << " is valid" << std::endl; } - + for (unsigned I = 0; I != Cache.HeaderP->PackageFileCount; I++) if (Visited[I] == false) { if (Debug == true) - std::clog << "File with ID" << I << " wasn't visited" << std::endl; + std::clog << "PkgFile with ID" << I << " wasn't visited" << std::endl; return false; } - + if (_error->PendingError() == true) { if (Debug == true) @@ -1243,9 +1309,20 @@ static bool CheckValidity(const string &CacheFile, // --------------------------------------------------------------------- /* Size is kind of an abstract notion that is only used for the progress meter */ -static map_filesize_t ComputeSize(FileIterator Start,FileIterator End) +static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator Start,FileIterator End) { map_filesize_t TotalSize = 0; + if (List != NULL) + { + for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) + { + std::vector *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) + if ((*j)->HasPackages() == true) + TotalSize += (*j)->Size(); + } + } + for (; Start < End; ++Start) { if ((*Start)->HasPackages() == false) @@ -1261,11 +1338,63 @@ static map_filesize_t ComputeSize(FileIterator Start,FileIterator End) static bool BuildCache(pkgCacheGenerator &Gen, OpProgress *Progress, map_filesize_t &CurrentSize,map_filesize_t TotalSize, + pkgSourceList const * const List, FileIterator Start, FileIterator End) { + std::vector Files; + bool const HasFileDeps = Gen.HasFileDeps(); + + if (List != NULL) + { + for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) + { + if ((*i)->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*i)->Describe().c_str()); + continue; + } + + if ((*i)->Merge(Gen, Progress) == false) + return false; + + std::vector *Indexes = (*i)->GetIndexFiles(); + for (std::vector::const_iterator I = Indexes->begin(); I != Indexes->end(); ++I) + { + if (HasFileDeps) + Files.push_back(*I); + + if ((*I)->HasPackages() == false) + continue; + + if ((*I)->Exists() == false) + continue; + + if ((*I)->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + (*I)->Describe().c_str()); + continue; + } + + map_filesize_t Size = (*I)->Size(); + if (Progress != NULL) + Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); + CurrentSize += Size; + + if ((*I)->Merge(Gen,Progress) == false) + return false; + } + } + } + + Gen.SelectReleaseFile("", ""); FileIterator I; for (I = Start; I != End; ++I) { + if (HasFileDeps) + Files.push_back(*I); + if ((*I)->HasPackages() == false) continue; @@ -1288,13 +1417,13 @@ static bool BuildCache(pkgCacheGenerator &Gen, return false; } - if (Gen.HasFileDeps() == true) + if (HasFileDeps == true) { if (Progress != NULL) Progress->Done(); - TotalSize = ComputeSize(Start, End); + TotalSize = ComputeSize(List, Start, End); CurrentSize = 0; - for (I = Start; I != End; ++I) + for (std::vector::const_iterator I = Files.begin(); I != Files.end(); ++I) { map_filesize_t Size = (*I)->Size(); if (Progress != NULL) @@ -1339,6 +1468,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress bool const Debug = _config->FindB("Debug::pkgCacheGen", false); std::vector Files; + /* for (std::vector::const_iterator i = List.begin(); i != List.end(); ++i) @@ -1349,8 +1479,7 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress ++j) Files.push_back (*j); } - - map_filesize_t const EndOfSource = Files.size(); +*/ if (_system->AddStatusFiles(Files) == false) return false; @@ -1442,8 +1571,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress // Lets try the source cache. map_filesize_t CurrentSize = 0; map_filesize_t TotalSize = 0; - if (CheckValidity(SrcCacheFile, List, Files.begin(), - Files.begin()+EndOfSource) == true) + if (CheckValidity(SrcCacheFile, List, Files.end(), + Files.end()) == true) { if (Debug == true) std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl; @@ -1455,28 +1584,28 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress SCacheF.Size()) == false) return false; - TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); + TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); // Build the status cache pkgCacheGenerator Gen(Map.Get(),Progress); if (_error->PendingError() == true) return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(),Files.end()) == false) return false; } else { if (Debug == true) std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl; - TotalSize = ComputeSize(Files.begin(),Files.end()); + TotalSize = ComputeSize(&List, Files.begin(),Files.end()); // Build the source cache pkgCacheGenerator Gen(Map.Get(),Progress); if (_error->PendingError() == true) return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin(),Files.begin()+EndOfSource) == false) + if (BuildCache(Gen, Progress, CurrentSize, TotalSize, &List, + Files.end(),Files.end()) == false) return false; // Write it back @@ -1503,8 +1632,8 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress } // Build the status cache - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(), Files.end()) == false) return false; } if (Debug == true) @@ -1536,7 +1665,6 @@ APT_DEPRECATED bool pkgMakeOnlyStatusCache(OpProgress &Progress,DynamicMMap **Ou bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap) { std::vector Files; - map_filesize_t EndOfSource = Files.size(); if (_system->AddStatusFiles(Files) == false) return false; @@ -1544,7 +1672,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O map_filesize_t CurrentSize = 0; map_filesize_t TotalSize = 0; - TotalSize = ComputeSize(Files.begin()+EndOfSource,Files.end()); + TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); // Build the status cache if (Progress != NULL) @@ -1552,8 +1680,8 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O pkgCacheGenerator Gen(Map.Get(),Progress); if (_error->PendingError() == true) return false; - if (BuildCache(Gen,Progress,CurrentSize,TotalSize, - Files.begin()+EndOfSource,Files.end()) == false) + if (BuildCache(Gen,Progress,CurrentSize,TotalSize, NULL, + Files.begin(), Files.end()) == false) return false; if (_error->PendingError() == true) diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index c4ace713d..2795d09d6 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -69,7 +69,9 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ DynamicMMap ⤅ pkgCache Cache; OpProgress *Progress; - + + std::string RlsFileName; + pkgCache::ReleaseFile *CurrentRlsFile; std::string PkgFileName; pkgCache::PackageFile *CurrentFile; @@ -100,12 +102,14 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ inline map_stringitem_t StoreString(enum StringType const type, const std::string &S) {return StoreString(type, S.c_str(),S.length());}; void DropProgress() {Progress = 0;}; - bool SelectFile(const std::string &File,const std::string &Site,pkgIndexFile const &Index, - unsigned long Flags = 0); + bool SelectFile(const std::string &File,pkgIndexFile const &Index, std::string const &Component, unsigned long Flags = 0); + bool SelectReleaseFile(const std::string &File, const std::string &Site, unsigned long Flags = 0); bool MergeList(ListParser &List,pkgCache::VerIterator *Ver = 0); inline pkgCache &GetCache() {return Cache;}; inline pkgCache::PkgFileIterator GetCurFile() {return pkgCache::PkgFileIterator(Cache,CurrentFile);}; + inline pkgCache::RlsFileIterator GetCurRlsFile() + {return pkgCache::RlsFileIterator(Cache,CurrentRlsFile);}; bool HasFileDeps() {return FoundFileDeps;}; bool MergeFileProvides(ListParser &List); diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index 00693ce54..bd40ad2d9 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -63,9 +63,9 @@ pkgPolicy::pkgPolicy(pkgCache *Owner) : Pins(0), PFPriority(0), Cache(Owner) pkgVersionMatch vm("", pkgVersionMatch::None); for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) { - if ((F->Archive != 0 && vm.ExpressionMatches(DefRel, F.Archive()) == true) || - (F->Codename != 0 && vm.ExpressionMatches(DefRel, F.Codename()) == true) || - (F->Version != 0 && vm.ExpressionMatches(DefRel, F.Version()) == true) || + if (vm.ExpressionMatches(DefRel, F.Archive()) || + vm.ExpressionMatches(DefRel, F.Codename()) || + vm.ExpressionMatches(DefRel, F.Version()) || (DefRel.length() > 2 && DefRel[1] == '=')) found = true; } @@ -86,11 +86,11 @@ bool pkgPolicy::InitDefaults() for (pkgCache::PkgFileIterator I = Cache->FileBegin(); I != Cache->FileEnd(); ++I) { PFPriority[I->ID] = 500; - if ((I->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource) + if (I.Flagged(pkgCache::Flag::NotSource)) PFPriority[I->ID] = 100; - else if ((I->Flags & pkgCache::Flag::ButAutomaticUpgrades) == pkgCache::Flag::ButAutomaticUpgrades) + else if (I.Flagged(pkgCache::Flag::ButAutomaticUpgrades)) PFPriority[I->ID] = 100; - else if ((I->Flags & pkgCache::Flag::NotAutomatic) == pkgCache::Flag::NotAutomatic) + else if (I.Flagged(pkgCache::Flag::NotAutomatic)) PFPriority[I->ID] = 1; } @@ -170,8 +170,7 @@ pkgCache::VerIterator pkgPolicy::GetCandidateVer(pkgCache::PkgIterator const &Pk then it is not a candidate for installation, ever. This weeds out bogus entries that may be due to config-file states, or other. */ - if ((VF.File()->Flags & pkgCache::Flag::NotSource) == pkgCache::Flag::NotSource && - instVer == false) + if (VF.File().Flagged(pkgCache::Flag::NotSource) && instVer == false) continue; signed Prio = PFPriority[VF.File()->ID]; diff --git a/apt-pkg/versionmatch.cc b/apt-pkg/versionmatch.cc index 284098bdf..86c1b7d4a 100644 --- a/apt-pkg/versionmatch.cc +++ b/apt-pkg/versionmatch.cc @@ -137,7 +137,10 @@ pkgVersionMatch::pkgVersionMatch(string Data,MatchType Type) : Type(Type) // --------------------------------------------------------------------- /* */ bool pkgVersionMatch::MatchVer(const char *A,string B,bool Prefix) -{ +{ + if (A == NULL) + return false; + const char *Ab = A; const char *Ae = Ab + strlen(A); @@ -178,13 +181,16 @@ pkgCache::VerIterator pkgVersionMatch::Find(pkgCache::PkgIterator Pkg) // This will be Ended by now. return Ver; } + /*}}}*/ #ifndef FNM_CASEFOLD #define FNM_CASEFOLD 0 #endif -bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string) +bool pkgVersionMatch::ExpressionMatches(const char *pattern, const char *string)/*{{{*/ { + if (pattern == NULL || string == NULL) + return false; if (pattern[0] == '/') { size_t length = strlen(pattern); if (pattern[length - 1] == '/') { @@ -230,38 +236,30 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) return false; if (RelVerStr.empty() == false) - if (File->Version == 0 || - (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false && - ExpressionMatches(RelVerStr, File.Version()) == false)) + if (MatchVer(File.Version(),RelVerStr,RelVerPrefixMatch) == false && + ExpressionMatches(RelVerStr, File.Version()) == false) return false; if (RelOrigin.empty() == false) - if (File->Origin == 0 || !ExpressionMatches(RelOrigin,File.Origin())) + if (!ExpressionMatches(RelOrigin,File.Origin())) return false; if (RelArchive.empty() == false) - if (File->Archive == 0 || - !ExpressionMatches(RelArchive,File.Archive())) + if (!ExpressionMatches(RelArchive,File.Archive())) return false; if (RelCodename.empty() == false) - if (File->Codename == 0 || - !ExpressionMatches(RelCodename,File.Codename())) + if (!ExpressionMatches(RelCodename,File.Codename())) return false; if (RelRelease.empty() == false) - if ((File->Archive == 0 || - !ExpressionMatches(RelRelease,File.Archive())) && - (File->Codename == 0 || - !ExpressionMatches(RelRelease,File.Codename()))) + if (!ExpressionMatches(RelRelease,File.Archive()) && + !ExpressionMatches(RelRelease,File.Codename())) return false; if (RelLabel.empty() == false) - if (File->Label == 0 || - !ExpressionMatches(RelLabel,File.Label())) + if (!ExpressionMatches(RelLabel,File.Label())) return false; if (RelComponent.empty() == false) - if (File->Component == 0 || - !ExpressionMatches(RelComponent,File.Component())) + if (!ExpressionMatches(RelComponent,File.Component())) return false; if (RelArchitecture.empty() == false) - if (File->Architecture == 0 || - !ExpressionMatches(RelArchitecture,File.Architecture())) + if (!ExpressionMatches(RelArchitecture,File.Architecture())) return false; return true; } @@ -269,11 +267,14 @@ bool pkgVersionMatch::FileMatch(pkgCache::PkgFileIterator File) if (Type == Origin) { if (OrSite.empty() == false) { - if (File->Site == 0) + if (File.Site() == NULL) return false; } else // so we are talking about file:// or status file - if (strcmp(File.Site(),"") == 0 && File->Archive != 0 && strcmp(File.Archive(),"now") == 0) // skip the status file + { + pkgCache::RlsFileIterator const RlsFile = File.ReleaseFile(); + if (strcmp(File.Site(),"") == 0 && RlsFile->Archive != 0 && strcmp(RlsFile.Archive(),"now") == 0) // skip the status file return false; + } return (ExpressionMatches(OrSite, File.Site())); /* both strings match */ } diff --git a/apt-pkg/versionmatch.h b/apt-pkg/versionmatch.h index 4c8f704c8..bb950b9c7 100644 --- a/apt-pkg/versionmatch.h +++ b/apt-pkg/versionmatch.h @@ -70,8 +70,8 @@ class pkgVersionMatch enum MatchType {None = 0,Version,Release,Origin} Type; bool MatchVer(const char *A,std::string B,bool Prefix) APT_PURE; - bool ExpressionMatches(const char *pattern, const char *string); - bool ExpressionMatches(const std::string& pattern, const char *string); + static bool ExpressionMatches(const char *pattern, const char *string); + static bool ExpressionMatches(const std::string& pattern, const char *string); bool FileMatch(pkgCache::PkgFileIterator File); pkgCache::VerIterator Find(pkgCache::PkgIterator Pkg); diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 690b03bcc..3b8ebc96d 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -413,17 +413,21 @@ static bool Stats(CommandLine &) stritems.insert(Prv->ProvideVersion); } } - for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) + for (pkgCache::RlsFileIterator F = Cache->RlsFileBegin(); F != Cache->RlsFileEnd(); ++F) { stritems.insert(F->FileName); stritems.insert(F->Archive); stritems.insert(F->Codename); - stritems.insert(F->Component); stritems.insert(F->Version); stritems.insert(F->Origin); stritems.insert(F->Label); - stritems.insert(F->Architecture); stritems.insert(F->Site); + } + for (pkgCache::PkgFileIterator F = Cache->FileBegin(); F != Cache->FileEnd(); ++F) + { + stritems.insert(F->FileName); + stritems.insert(F->Architecture); + stritems.insert(F->Component); stritems.insert(F->IndexType); } unsigned long Size = 0; @@ -446,6 +450,7 @@ static bool Stats(CommandLine &) APT_CACHESIZE(VersionCount, VersionSz) + APT_CACHESIZE(DescriptionCount, DescriptionSz) + APT_CACHESIZE(DependsCount, DependencySz) + + APT_CACHESIZE(ReleaseFileCount, ReleaseFileSz) + APT_CACHESIZE(PackageFileCount, PackageFileSz) + APT_CACHESIZE(VerFileCount, VerFileSz) + APT_CACHESIZE(DescFileCount, DescFileSz) + diff --git a/test/integration/framework b/test/integration/framework index 110758e82..7b03c09ef 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -137,7 +137,14 @@ dpkgcheckbuilddeps() { command dpkg-checkbuilddeps --admindir=${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg "$@" } gdb() { - local CMD="$1" + local CMD + case "$1" in + aptget) CMD="apt-get";; + aptcache) CMD="apt-cache";; + aptmark) CMD="apt-mark";; + apthelper) CMD="apt-helper";; + *) CMD="$1";; + esac shift runapt command gdb --quiet -ex run "${BUILDDIRECTORY}/$CMD" --args "${BUILDDIRECTORY}/$CMD" "$@" } diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 9cd54264b..9f7f457ae 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -22,7 +22,7 @@ testequalpolicy() { release a=now $(echo "$AP" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} Packages release c= -Pinned packages:" aptcache policy $* +Pinned packages:" aptcache policy "$@" } testglobalpolicy() { -- cgit v1.2.3-70-g09d2 From 3fd89e62e985c89b1f9a545ab72c20987b756aff Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 12 Jun 2015 12:06:29 +0200 Subject: implement default apt-get file --release-info mode Selecting targets based on the Release they belong to isn't to unrealistic. In fact, it is assumed to be the most used case so it is made the default especially as this allows to bundle another thing we have to be careful with: Filenames and only showing targets we have acquired. Closes: 752702 --- apt-pkg/deb/debmetaindex.cc | 4 +- apt-pkg/deb/debmetaindex.h | 2 +- apt-pkg/indexfile.cc | 12 ++++ apt-pkg/indexfile.h | 1 + apt-pkg/metaindex.cc | 2 +- apt-pkg/metaindex.h | 2 +- apt-pkg/pkgcachegen.cc | 4 +- apt-private/private-cmndline.cc | 1 + cmdline/apt-get.cc | 26 ++++++++- doc/acquire-additional-files.txt | 65 +++++++++++++--------- test/integration/test-apt-acquire-additional-files | 6 ++ 11 files changed, 88 insertions(+), 37 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 994b95849..b328fcea8 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -422,7 +422,7 @@ bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/ } /*}}}*/ // ReleaseIndex::FindInCache - Find this index /*{{{*/ -pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache) const +pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool const ModifyCheck) const { std::string ReleaseFile; bool const releaseExists = ReleaseFileName(this, ReleaseFile); @@ -434,7 +434,7 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache) const continue; // empty means the file does not exist by "design" - if (releaseExists == false && File->Size == 0) + if (ModifyCheck == false || (releaseExists == false && File->Size == 0)) return File; struct stat St; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 7e9942710..b448ecc53 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -51,7 +51,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual std::vector GetIndexTargets() const; virtual std::string Describe() const; - virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; std::string MetaIndexInfo(const char *Type) const; diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 33fb48e35..605bbeb47 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -137,6 +137,18 @@ std::string IndexTarget::Option(OptionKeys const EnumKey) const /*{{{*/ APT_CASE(CREATED_BY); #undef APT_CASE case FILENAME: return _config->FindDir("Dir::State::lists") + URItoFileName(URI); + case EXISTING_FILENAME: + std::string const filename = Option(FILENAME); + std::vector const types = APT::Configuration::getCompressionTypes(); + for (std::vector::const_iterator t = types.begin(); t != types.end(); ++t) + { + if (t->empty()) + continue; + std::string const file = (*t == "uncompressed") ? filename : (filename + "." + *t); + if (FileExists(file)) + return file; + } + return ""; } std::map::const_iterator const M = Options.find(Key); if (M == Options.end()) diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 220c415ac..042e5c2f7 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -81,6 +81,7 @@ class IndexTarget /*{{{*/ CREATED_BY, TARGET_OF, FILENAME, + EXISTING_FILENAME, }; std::string Option(OptionKeys const Key) const; std::string Format(std::string format) const; diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 35ab6c53b..3c1b696bd 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -28,7 +28,7 @@ std::string metaIndex::Describe() const return "Release"; } -pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache) const +pkgCache::RlsFileIterator metaIndex::FindInCache(pkgCache &Cache, bool const) const { return pkgCache::RlsFileIterator(Cache); } diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 20c879a89..e1810fb27 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -54,7 +54,7 @@ class metaIndex virtual bool IsTrusted() const = 0; virtual std::string Describe() const; - virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache) const; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; metaIndex(std::string const &URI, std::string const &Dist, diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 2d0e3960d..9db4ef41f 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1224,7 +1224,7 @@ static bool CheckValidity(const string &CacheFile, { if (Debug == true) std::clog << "Checking RlsFile " << (*i)->Describe() << ": "; - pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache); + pkgCache::RlsFileIterator const RlsFile = (*i)->FindInCache(Cache, true); if (RlsFile.end() == true) { if (Debug == true) @@ -1348,7 +1348,7 @@ static bool BuildCache(pkgCacheGenerator &Gen, { for (pkgSourceList::const_iterator i = List->begin(); i != List->end(); ++i) { - if ((*i)->FindInCache(Gen.GetCache()).end() == false) + if ((*i)->FindInCache(Gen.GetCache(), false).end() == false) { _error->Warning("Duplicate sources.list entry %s", (*i)->Describe().c_str()); diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 458051bf2..11e88b1e7 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -166,6 +166,7 @@ static bool addArgumentsAPTGet(std::vector &Args, char const else if (CmdMatches("files")) { addArg(0,"format","APT::Get::Files::Format", CommandLine::HasArg); + addArg(0,"release-info","APT::Get::Files::ReleaseInfo", 0); } else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 0fff2db58..a4cd3c377 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1628,15 +1628,34 @@ static bool DoFiles(CommandLine &CmdL) return false; std::string const Format = _config->Find("APT::Get::Files::Format"); + bool const ReleaseInfo = _config->FindB("APT::Get::Files::ReleaseInfo", true); bool Filtered = CmdL.FileSize() > 1; for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S) { std::vector const targets = (*S)->GetIndexTargets(); std::map AddOptions; - AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no"))); + if (ReleaseInfo) + { + AddOptions.insert(std::make_pair("TRUSTED", ((*S)->IsTrusted() ? "yes" : "no"))); + pkgCache &Cache = *CacheFile.GetPkgCache(); + pkgCache::RlsFileIterator const RlsFile = (*S)->FindInCache(Cache, false); + if (RlsFile.end()) + continue; +#define APT_RELEASE(X,Y) if (RlsFile.Y() != NULL) AddOptions.insert(std::make_pair(X, RlsFile.Y())) + APT_RELEASE("CODENAME", Codename); + APT_RELEASE("SUITE", Archive); + APT_RELEASE("VERSION", Version); + APT_RELEASE("ORIGIN", Origin); + APT_RELEASE("LABEL", Label); +#undef APT_RELEASE + } for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) { + std::string filename = T->Option(ReleaseInfo ? IndexTarget::EXISTING_FILENAME : IndexTarget::FILENAME); + if (filename.empty()) + continue; + std::ostringstream stanza; if (Filtered || Format.empty()) { @@ -1644,7 +1663,7 @@ static bool DoFiles(CommandLine &CmdL) << "ShortDesc: " << T->ShortDesc << "\n" << "Description: " << T->Description << "\n" << "URI: " << T->URI << "\n" - << "Filename: " << T->Option(IndexTarget::FILENAME) << "\n" + << "Filename: " << filename << "\n" << "Optional: " << (T->IsOptional ? "yes" : "no") << "\n"; for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) stanza << format_key(O->first) << ": " << O->second << "\n"; @@ -1677,7 +1696,8 @@ static bool DoFiles(CommandLine &CmdL) cout << stanza.str(); else { - std::string out = T->Format(Format); + std::string out = SubstVar(Format, "$(FILENAME)", filename); + out = T->Format(out); for (std::map::const_iterator O = AddOptions.begin(); O != AddOptions.end(); ++O) out = SubstVar(out, std::string("$(") + O->first + ")", O->second); cout << out << std::endl; diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt index a47dac2d4..f9a16318d 100644 --- a/doc/acquire-additional-files.txt +++ b/doc/acquire-additional-files.txt @@ -18,12 +18,6 @@ might want to use and would therefore need to be downloaded as well This file describes the configuration scheme such a frontend can use to instruct the Acquire system to download those additional files. -Note that you can't download files from other sources. It must be files -in the same repository and below the Release file. The Release file must -also contain hashes for the file itself as well as for the compressed -file if wanted, otherwise a download isn't even tried! - - # The Configuration Stanza The Acquire system uses the same configuration settings to implement the @@ -81,15 +75,17 @@ Additional optional properties: * Optional: The default value is 'true' and should be kept at this value. If enabled the acquire system will skip the download if the file isn't mentioned in the Release file. Otherwise this is treated as - a hard error and the update process fails. + a hard error and the update process fails. Note that failures while + downloading (e.g. 404 or hash verification errors) are failures, + regardless of this setting. -Note that the acquire system will automatically choose to download -a compressed file if it is available and uncompress it for you, just as -it will also use pdiff patching if provided by the repository and -enabled by the user. You only have to ensure that the Release file -contains the information about the compressed files/pdiffs to make this -happen. NO properties have to be set to enable this. +The acquire system will automatically choose to download a compressed +file if it is available and uncompress it for you, just as it will also +use pdiff patching if provided by the repository and enabled by the +user. You only have to ensure that the Release file contains the +information about the compressed files/pdiffs to make this happen. +NO properties have to be set to enable this. # More examples @@ -123,10 +119,12 @@ APT::Acquire::Targets { As seen in the examples, properties can contain placeholders filled in by the acquire system. The following variables are known; note that unknown variables have no default value nor are they touched: They are -printed literally. +printed as-is. * $(SITE): An identifier of the site we access as seen in sources.list, - e.g. "http://example.org/debian" or "file:/path/to/a/repository". + e.g. "http://example.org/debian" or "file:/path/to/a/repository". You + can't use this field in {,flat}MetaKey, it is for description proposes + only. * $(RELEASE): This is usually an archive- or codename, e.g. "stable" or "stretch". Note that flat-style repositories do not have a archive- or codename per-se, so the value might very well be just "/" or so. @@ -143,7 +141,7 @@ printed literally. Note that while more variables might exist in the implementation, these are to be considered undefined and their usage strongly discouraged. If -you have a need for another variable contact us instead. +you have a need for other variables contact us. # Accessing files @@ -170,29 +168,42 @@ sources.lists (pkgSourceList), iterating over the metaIndex objects this creates and calling GetIndexTargets() on them. See the sourcecode of "apt-get files" for a complete example. -Remarks on the available fields: +Note that by default targets are not listed if they weren't downloaded. +If you want to see all targets, you can use the --no-release-info, which +also removes the Codename, Suite, Version, Origin, Label and Trusted +fields from the output as these also display data which needs to be +downloaded first and could hence be inaccurate [on the pro-side: This +mode is faster as it doesn't require a valid binary cache to operate]. +The most notable difference perhaps is in the Filename field through: By +default it indicates an existing file, potentially compressed (Hint: +libapt users can use FileFd to open compressed files transparently). In +the --no-release-info mode the indicated file doesn't need to exist and +it will always refer to an uncompressed file, even if the index would be +(or is) stored compressed. + +Remarks on fields only available in (default) --release-info mode: +* Trusted: Denotes with a 'yes' or 'no' if the data in this file is + authenticated by a trustchain rooted in a trusted gpg key. You should + be careful with untrusted data and warn the user if you use it. +* Codename, Suite, Version, Origin and Label are fields from the Release + file, are only present if they are present in the Release file and + contain the same data. + +Remarks on other available fields: * MetaKey, ShortDesc, Description, Site, Release: as defined by the configuration and described further above. * Created-By: configuration entity responsible for this target * Target-Of: type of the sources.list entry * URI, Repo-URI: avoid using. Contains potentially username/password. Prefer 'Site', especially for display. -* Filename: The mentioned file doesn't need to exist, e.g. because the - file wasn't downloaded yet – or it does exist compressed. libapt users - are encouraged to use FileFd to open such files as it can handle - decompression transparently. -* Trusted: As of the last 'apt-get update' call denoting if e.g. apt-get - would print the unauthenticated warning while installing packages - mentioned in this file (example assumes Packages file) [Not really - a property of the target itself, but of the metaIndex]. * Optional: Decodes the option of the same name from the configuration. Note that it is using 'yes' and 'no' instead of 'true' and 'false'. * Language, Architecture, Component: as defined further above, but with the catch that they might be missing if they don't effect the target (aka: They weren't used while evaluating the MetaKey template). -Again, additional fields might be visible in certain implementation, but -you should avoid using them and instead talk to us about a portable +Again, additional fields might be visible in certain implementations, +but you should avoid using them and instead talk to us about a portable implementation. # Multiple application requiring the same files diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index 971cfac2e..ffb9f3135 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -37,6 +37,12 @@ APT::Acquire::Targets::deb::Contents { }; EOF +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64)" aptget files --no-release-info --format '$(FILENAME)' 'Created-By: Contents' +testempty aptget files --format '$(FILENAME)' 'Created-By: Contents' +# lets fake the existence of a compressed Contents file +touch ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget files --format '$(FILENAME)' 'Created-By: Contents' + testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists_unstable_InRelease 0 'http://localhost:8080/dists/unstable/main/source/Sources.bz2' localhost:8080_dists_unstable_main_source_Sources 0 'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 -- cgit v1.2.3-70-g09d2 From d56e2917f27a722b54685de13aeb1bb7592fc61b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 13 Jun 2015 11:13:45 +0200 Subject: provide a public interface for acquiring changelogs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provided is a specialized acquire item which given a version can figure out the correct URI to try by itself and if not provides an error message alongside with static methods to get just the URI it would try to download if it should just be displayed or similar such. The URI is constructed as follows: Release files can provide an URI template in the "Changelogs" field, otherwise we lookup a configuration item based on the "Label" or "Origin" of the Release file to get a (hopefully known) default value for now. This template should contain the string CHANGEPATH which is replaced with the information about the version we want the changelog for (e.g. main/a/apt/apt_1.1). This middleway was choosen as this path part was consistent over the three known implementations (+1 defunct), while the rest of the URI varies widely between them. The benefit of this construct is that it is now easy to get changelogs for Debian packages on Ubuntu and vice versa – even at the moment where the Changelogs field is present nowhere. Strictly better than what apt-get had before as it would even fail to get changelogs from security… Now it will notice that security identifies as Origin: Debian and pick this setting (assuming again that no Changelogs field exists). If on the other hand security would ship its changelogs in a different location we could set it via the Label option overruling Origin. Closes: 687147, 739854, 784027, 787190 --- apt-pkg/acquire-item.cc | 211 +++++++++++++++++++++ apt-pkg/acquire-item.h | 114 +++++++++++ apt-pkg/init.cc | 4 + cmdline/apt-get.cc | 204 ++++---------------- doc/apt-get.8.xml | 16 +- doc/apt.conf.5.xml | 27 +++ doc/examples/configure-index | 11 +- test/integration/framework | 24 ++- test/integration/test-apt-get-changelog | 104 +++++++--- .../test-bug-722207-print-uris-even-if-very-quiet | 3 +- test/integration/test-bug-738785-switch-protocol | 7 +- vendor/ubuntu/apt.conf-01-vendor-ubuntu | 6 - 12 files changed, 507 insertions(+), 224 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index d6e9ccbe0..4bf4e62f8 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -2836,6 +2837,216 @@ std::string pkgAcqArchive::ShortDesc() const /*{{{*/ } /*}}}*/ +// AcqChangelog::pkgAcqChangelog - Constructors /*{{{*/ +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, + std::string const &DestDir, std::string const &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(Ver.SourcePkgName()), SrcVersion(Ver.SourceVerStr()) +{ + Desc.URI = URI(Ver); + Init(DestDir, DestFilename); +} +// some parameters are char* here as they come likely from char* interfaces – which can also return NULL +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &RlsFile, + char const * const Component, char const * const SrcName, char const * const SrcVersion, + const string &DestDir, const string &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion) +{ + Desc.URI = URI(RlsFile, Component, SrcName, SrcVersion); + Init(DestDir, DestFilename); +} +pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, + std::string const &URI, char const * const SrcName, char const * const SrcVersion, + const string &DestDir, const string &DestFilename) : + pkgAcquire::Item(Owner), d(NULL), SrcName(SrcName), SrcVersion(SrcVersion) +{ + Desc.URI = URI; + Init(DestDir, DestFilename); +} +void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFilename) +{ + if (Desc.URI.empty()) + { + Status = StatError; + // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1 + strprintf(ErrorText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str()); + // Let the error message print something sensible rather than "Failed to fetch /" + if (DestFilename.empty()) + DestFile = SrcName + ".changelog"; + else + DestFile = DestFilename; + Desc.URI = "changelog:/" + DestFile; + return; + } + + if (DestDir.empty()) + { + std::string const systemTemp = GetTempDir(); + char tmpname[100]; + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", systemTemp.c_str()); + if (NULL == mkdtemp(tmpname)) + { + _error->Errno("mkdtemp", "mkdtemp failed in changelog acquire of %s %s", SrcName.c_str(), SrcVersion.c_str()); + Status = StatError; + return; + } + DestFile = TemporaryDirectory = tmpname; + } + else + DestFile = DestDir; + + if (DestFilename.empty()) + DestFile = flCombine(DestFile, SrcName + ".changelog"); + else + DestFile = flCombine(DestFile, DestFilename); + + Desc.ShortDesc = "Changelog"; + strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str()); + Desc.Owner = this; + QueueURI(Desc); + + if (Status == StatDone) // this happens if we queue the same changelog two times + { + Complete = true; + for (pkgAcquire::UriIterator I = Owner->UriBegin(); I != Owner->UriEnd(); ++I) + if (I->URI == Desc.URI) + if (DestFile != I->Owner->DestFile) + if (symlink(I->Owner->DestFile.c_str(), DestFile.c_str()) != 0) + { + ; // ignore error, there isn't anthing we could do to handle the edgecase of an edgecase + } + } +} + /*}}}*/ +std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/ +{ + char const * const SrcName = Ver.SourcePkgName(); + char const * const SrcVersion = Ver.SourceVerStr(); + pkgCache::PkgFileIterator PkgFile; + // find the first source for this version which promises a changelog + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; ++VF) + { + pkgCache::PkgFileIterator const PF = VF.File(); + if (PF.Flagged(pkgCache::Flag::NotSource) || PF->Release == 0) + continue; + PkgFile = PF; + pkgCache::RlsFileIterator const RF = PF.ReleaseFile(); + std::string const uri = URI(RF, PF.Component(), SrcName, SrcVersion); + if (uri.empty()) + continue; + return uri; + } + return ""; +} +std::string pkgAcqChangelog::URITemplate(pkgCache::RlsFileIterator const &Rls) +{ + if (Rls.end() == true || (Rls->Label == 0 && Rls->Origin == 0)) + return ""; + std::string const serverConfig = "Acquire::Changelogs::URI"; + std::string server; +#define APT_EMPTY_SERVER \ + if (server.empty() == false) \ + { \ + if (server != "no") \ + return server; \ + return ""; \ + } +#define APT_CHECK_SERVER(X, Y) \ + if (Rls->X != 0) \ + { \ + std::string const specialServerConfig = serverConfig + "::" + Y + #X + "::" + Rls.X(); \ + server = _config->Find(specialServerConfig); \ + APT_EMPTY_SERVER \ + } + // this way e.g. Debian-Security can fallback to Debian + APT_CHECK_SERVER(Label, "Override::") + APT_CHECK_SERVER(Origin, "Override::") + + if (RealFileExists(Rls.FileName())) + { + _error->PushToStack(); + FileFd rf; + /* This can be costly. A caller wanting to get millions of URIs might + want to do this on its own once and use Override settings. + We don't do this here as Origin/Label are not as unique as they + should be so this could produce request order-dependent anomalies */ + if (OpenMaybeClearSignedFile(Rls.FileName(), rf) == true) + { + pkgTagFile TagFile(&rf, rf.Size()); + pkgTagSection Section; + if (TagFile.Step(Section) == true) + server = Section.FindS("Changelogs"); + } + _error->RevertToStack(); + APT_EMPTY_SERVER + } + + APT_CHECK_SERVER(Label, "") + APT_CHECK_SERVER(Origin, "") +#undef APT_CHECK_SERVER +#undef APT_EMPTY_SERVER + return ""; +} +std::string pkgAcqChangelog::URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + return URI(URITemplate(Rls), Component, SrcName, SrcVersion); +} +std::string pkgAcqChangelog::URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion) +{ + if (Template.find("CHANGEPATH") == std::string::npos) + return ""; + + // the path is: COMPONENT/SRC/SRCNAME/SRCNAME_SRCVER, e.g. main/a/apt/1.1 or contrib/liba/libapt/2.0 + std::string Src = SrcName; + std::string path = APT::String::Startswith(SrcName, "lib") ? Src.substr(0, 4) : Src.substr(0,1); + path.append("/").append(Src).append("/"); + path.append(Src).append("_").append(StripEpoch(SrcVersion)); + // we omit component for releases without one (= flat-style repositories) + if (Component != NULL && strlen(Component) != 0) + path = std::string(Component) + "/" + path; + + return SubstVar(Template, "CHANGEPATH", path); +} + /*}}}*/ +// AcqChangelog::Failed - Failure handler /*{{{*/ +void pkgAcqChangelog::Failed(string const &Message, pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Failed(Message,Cnf); + + std::string errText; + // TRANSLATOR: %s=%s is sourcename=sourceversion, e.g. apt=1.1 + strprintf(errText, _("Changelog unavailable for %s=%s"), SrcName.c_str(), SrcVersion.c_str()); + + // Error is probably something techy like 404 Not Found + if (ErrorText.empty()) + ErrorText = errText; + else + ErrorText = errText + " (" + ErrorText + ")"; + return; +} + /*}}}*/ +// AcqChangelog::Done - Item downloaded OK /*{{{*/ +void pkgAcqChangelog::Done(string const &Message,HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::Done(Message,CalcHashes,Cnf); + + Complete = true; +} + /*}}}*/ +pkgAcqChangelog::~pkgAcqChangelog() /*{{{*/ +{ + if (TemporaryDirectory.empty() == false) + { + unlink(DestFile.c_str()); + rmdir(TemporaryDirectory.c_str()); + } +} + /*}}}*/ + // AcqFile::pkgAcqFile - Constructor /*{{{*/ pkgAcqFile::pkgAcqFile(pkgAcquire * const Owner,string const &URI, HashStringList const &Hashes, unsigned long long const Size,string const &Dsc,string const &ShortDesc, diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index b6d569737..606fd4173 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1031,6 +1031,120 @@ class pkgAcqArchive : public pkgAcquire::Item std::string &StoreFilename); }; /*}}}*/ +/** \brief Retrieve the changelog for the given version {{{ + * + * Downloads the changelog to a temporary file it will also remove again + * while it is deconstructed or downloads it to a named location. + */ +class pkgAcqChangelog : public pkgAcquire::Item +{ + void *d; + std::string TemporaryDirectory; + std::string const SrcName; + std::string const SrcVersion; + + public: + // we will never have hashes for changelogs. + // If you need verified ones, download the deb and extract the changelog. + virtual HashStringList GetExpectedHashes() const { return HashStringList(); } + virtual bool HashesRequired() const { return false; } + + // Specialized action members + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Done(std::string const &Message, HashStringList const &CalcHashes, + pkgAcquire::MethodConfig const * const Cnf); + virtual std::string DescURI() const {return Desc.URI;}; + + /** returns the URI to the changelog of this version + * + * @param Ver is the version to get the changelog for + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::VerIterator const &Ver); + + /** returns the URI to the changelog of this version + * + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI to the changelog of this version + * + * \param Template URI where CHANGEPATH has to be filled in + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * @return the URI which will be used to acquire the changelog + */ + static std::string URI(std::string const &Template, + char const * const Component, char const * const SrcName, + char const * const SrcVersion); + + /** returns the URI template for this release file + * + * \param Rls is a Release file + * @return the URI template to use for this release file + */ + static std::string URITemplate(pkgCache::RlsFileIterator const &Rls); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Ver is the version to get the changelog for + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param Rls is the Release file the package comes from + * \param Component in which the package resides, can be empty + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::RlsFileIterator const &Rls, + char const * const Component, char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + /** \brief Create a new pkgAcqChangelog object. + * + * \param Owner The pkgAcquire object with which this object is + * associated. + * \param URI is to be used to get the changelog + * \param SrcName is the source package name + * \param SrcVersion is the source package version + * \param DestDir The directory the file should be downloaded into. + * Will be an autocreated (and cleaned up) temporary directory if not set. + * \param DestFilename The filename the file should have in #DestDir + * Defaults to sourcepackagename.changelog if not set. + */ + pkgAcqChangelog(pkgAcquire * const Owner, std::string const &URI, + char const * const SrcName, char const * const SrcVersion, + std::string const &DestDir="", std::string const &DestFilename=""); + + virtual ~pkgAcqChangelog(); + +private: + APT_HIDDEN void Init(std::string const &DestDir, std::string const &DestFilename); +}; + /*}}}*/ /** \brief Retrieve an arbitrary file to the current directory. {{{ * * The file is retrieved even if it is accessed via a URL type that diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index e2239a906..96966b249 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -119,6 +119,10 @@ bool pkgInitConfig(Configuration &Cnf) Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog"); + Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ultimedia", "http://packages.ultimediaos.com/changelogs/pool/CHANGEPATH/changelog.txt"); + bool Res = true; // Read an alternate config file diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index a4cd3c377..184b51d23 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1410,196 +1410,70 @@ static bool DoBuildDep(CommandLine &CmdL) return true; } /*}}}*/ -// GetChangelogPath - return a path pointing to a changelog file or dir /*{{{*/ -// --------------------------------------------------------------------- -/* This returns a "path" string for the changelog url construction. - * Please note that its not complete, it either needs a "/changelog" - * appended (for the packages.debian.org/changelogs site) or a - * ".changelog" (for third party sites that store the changelog in the - * pool/ next to the deb itself) - * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3" - */ -static string GetChangelogPath(CacheFile &Cache, - pkgCache::VerIterator Ver) -{ - pkgRecords Recs(Cache); - pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList()); - string path = flNotFile(rec.FileName()); -#if APT_PKG_ABI >= 413 - path.append(Ver.SourcePkgName()); - path.append("_"); - path.append(StripEpoch(Ver.SourceVerStr())); -#else - string srcpkg = rec.SourcePkg().empty() ? Ver.ParentPkg().Name() : rec.SourcePkg(); - string ver = Ver.VerStr(); - // if there is a source version it always wins - if (rec.SourceVer() != "") - ver = rec.SourceVer(); - path += srcpkg + "_" + StripEpoch(ver); -#endif - return path; -} - /*}}}*/ -// GuessThirdPartyChangelogUri - return url /*{{{*/ -// --------------------------------------------------------------------- -/* Contruct a changelog file path for third party sites that do not use - * packages.debian.org/changelogs - * This simply uses the ArchiveURI() of the source pkg and looks for - * a .changelog file there, Example for "mediabuntu": - * apt-get changelog mplayer-doc: - * http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog - */ -static bool GuessThirdPartyChangelogUri(CacheFile &Cache, - pkgCache::VerIterator Ver, - string &out_uri) -{ - // get the binary deb server path - pkgCache::VerFileIterator Vf = Ver.FileList(); - if (Vf.end() == true) - return false; - pkgCache::PkgFileIterator F = Vf.File(); - pkgIndexFile *index; - pkgSourceList *SrcList = Cache.GetSourceList(); - if(SrcList->FindIndex(F, index) == false) - return false; - - // get archive uri for the binary deb - string path_without_dot_changelog = GetChangelogPath(Cache, Ver); - out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog"); - - // now strip away the filename and add srcpkg_srcver.changelog - return true; -} - /*}}}*/ -// DownloadChangelog - Download the changelog /*{{{*/ -// --------------------------------------------------------------------- -static bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, - pkgCache::VerIterator Ver, string targetfile) -/* Download a changelog file for the given package version to - * targetfile. This will first try the server from Apt::Changelogs::Server - * (http://packages.debian.org/changelogs by default) and if that gives - * a 404 tries to get it from the archive directly (see - * GuessThirdPartyChangelogUri for details how) - */ -{ - // make the server root configurable - string const server = _config->Find("Apt::Changelogs::Server", - "http://packages.debian.org/changelogs"); - string const path = GetChangelogPath(CacheFile, Ver); - string changelog_uri; - if (APT::String::Endswith(server, "/") == true) - strprintf(changelog_uri, "%s%s/changelog", server.c_str(), path.c_str()); - else - strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str()); - if (_config->FindB("APT::Get::Print-URIs", false) == true) - { - std::cout << '\'' << changelog_uri << '\'' << std::endl; - return true; - } - pkgCache::PkgIterator const Pkg = Ver.ParentPkg(); - - string descr; - strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str()); - // queue it - pkgAcquire::Item const * itm = new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - - // Disable drop-privs if "_apt" can not write to the target dir - CheckDropPrivsMustBeDisabled(Fetcher); - - // try downloading it, if that fails, try third-party-changelogs location - // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!? - Fetcher.Run(); - if (itm->Status != pkgAcquire::Item::StatDone) - { - string third_party_uri; - if (GuessThirdPartyChangelogUri(CacheFile, Ver, third_party_uri)) - { - strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str()); - itm = new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - Fetcher.Run(); - } - } - - if (itm->Status == pkgAcquire::Item::StatDone) - return true; - - // error - return _error->Error("changelog download failed"); -} - /*}}}*/ // DoChangelog - Get changelog from the command line /*{{{*/ -// --------------------------------------------------------------------- static bool DoChangelog(CommandLine &CmdL) { CacheFile Cache; if (Cache.ReadOnlyOpen() == false) return false; - + APT::CacheSetHelper helper; APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, CmdL.FileList + 1, APT::CacheSetHelper::CANDIDATE, helper); if (verset.empty() == true) return false; pkgAcquire Fetcher; + AcqTextStatus Stat(std::cout, ScreenWidth,_config->FindI("quiet",0)); + Fetcher.SetLog(&Stat); - if (_config->FindB("APT::Get::Print-URIs", false) == true) + bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + bool const printOnly = _config->FindB("APT::Get::Print-URIs", false); + + for (APT::VersionList::const_iterator Ver = verset.begin(); + Ver != verset.end(); + ++Ver) { - bool Success = true; - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); ++Ver) - Success &= DownloadChangelog(Cache, Fetcher, Ver, ""); - return Success; + if (printOnly) + new pkgAcqChangelog(&Fetcher, Ver, "/dev/null"); + else if (downOnly) + new pkgAcqChangelog(&Fetcher, Ver, "."); + else + new pkgAcqChangelog(&Fetcher, Ver); } - AcqTextStatus Stat(std::cout, ScreenWidth,_config->FindI("quiet",0)); - Fetcher.SetLog(&Stat); + if (printOnly == false) + { + // Disable drop-privs if "_apt" can not write to the target dir + CheckDropPrivsMustBeDisabled(Fetcher); + if (_error->PendingError() == true) + return false; - bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + bool Failed = false; + if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true) + return false; + } - char tmpname[100]; - const char* tmpdir = NULL; - if (downOnly == false) + if (downOnly == false || printOnly == true) { - std::string systemTemp = GetTempDir(); - snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", - systemTemp.c_str()); - tmpdir = mkdtemp(tmpname); - if (tmpdir == NULL) - return _error->Errno("mkdtemp", "mkdtemp failed"); - - std::string const SandboxUser = _config->Find("APT::Sandbox::User"); - if (getuid() == 0 && SandboxUser.empty() == false) // if we aren't root, we can't chown, so don't try it + bool Failed = false; + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) { - struct passwd const * const pw = getpwnam(SandboxUser.c_str()); - struct group const * const gr = getgrnam("root"); - if (pw != NULL && gr != NULL) + if (printOnly) { - // chown the tmp dir directory we use to the sandbox user - if(chown(tmpdir, pw->pw_uid, gr->gr_gid) != 0) - _error->WarningE("DoChangelog", "chown to %s:%s of directory %s failed", SandboxUser.c_str(), "root", tmpdir); + if ((*I)->ErrorText.empty() == false) + { + Failed = true; + _error->Error("%s", (*I)->ErrorText.c_str()); + } + else + cout << '\'' << (*I)->DescURI() << "' " << flNotDir((*I)->DestFile) << std::endl; } + else + DisplayFileInPager((*I)->DestFile); } + return Failed == false; } - for (APT::VersionList::const_iterator Ver = verset.begin(); - Ver != verset.end(); - ++Ver) - { - string changelogfile; - if (downOnly == false) - changelogfile.append(tmpname).append("/changelog"); - else - changelogfile.append(Ver.ParentPkg().Name()).append(".changelog"); - if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false) - { - DisplayFileInPager(changelogfile); - // cleanup temp file - unlink(changelogfile.c_str()); - } - } - // clenaup tmp dir - if (tmpdir != NULL) - rmdir(tmpdir); return true; } /*}}}*/ diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index da077afa7..5b6788ed4 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -230,16 +230,12 @@ - changelog downloads a package changelog and displays - it through sensible-pager. The server name and base - directory is defined in the APT::Changelogs::Server - variable (e.g. packages.debian.org/changelogs for - Debian or changelogs.ubuntu.com/changelogs for - Ubuntu). - By default it displays the changelog for the version that is - installed. However, you can specify the same options as for - the command. - + changelog tries to download the + changelog of a package and displays it through + sensible-pager. By default it + displays the changelog for the version that is installed. + However, you can specify the same options as for the + command. diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index efe986ea8..7d5f7e9b3 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -618,6 +618,33 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; + scope + + Acquiring changelogs can only be done if an URI is known from where to get them. + Preferable the Release file indicates this in a 'Changelogs' field. If this isn't + available the Label/Origin field of the Release file is used to check if a + Acquire::Changelogs::URI::Label::LABEL or + Acquire::Changelogs::URI::Origin::ORIGIN option + exists and if so this value is taken. The value in the Release file can be overridden + with Acquire::Changelogs::URI::Override::Label::LABEL + or Acquire::Changelogs::URI::Override::Origin::ORIGIN. + + The value should be a normal URI to a text file, expect that package specific data is + replaced with the placeholder CHANGEPATH. The + value for it is: 1. if the package is from a component (e.g. main) + this is the first part otherwise it is omitted, 2. the first letter of source package name, + expect if the source package name starts with 'lib' in which case it will + be the first four letters. 3. The complete source package name. 4. the complete name again and + 5. the source version. + The first (if present), second, third and fourth part are separated by a slash ('/') + and between the fourth and fifth part is an underscore ('_'). + + The special value 'no' is available for this option indicating that + this source can't be used to acquire changelog files from. Another source will be tried + if available in this case. + + + diff --git a/doc/examples/configure-index b/doc/examples/configure-index index ef1ae056d..1339335fa 100644 --- a/doc/examples/configure-index +++ b/doc/examples/configure-index @@ -117,14 +117,6 @@ APT // does a ExecFork) Keep-Fds {}; - Changelogs - { - // server the provides the changelogs, the code will assume - // the changlogs are in the pool/ under a srcpkg_ver directory - // with the name "changelog" - Server "http://packages.debian.org/changelogs"; - }: - // control parameters for cron jobs by /etc/cron.daily/apt Periodic { @@ -305,6 +297,9 @@ Acquire "none"; "fr"; }; + + // Location of the changelogs with the placeholder CHANGEPATH (e.g. "main/a/apt/apt_1.1") + Changelogs::URI::Origin::Debian "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"; }; // Directory layout diff --git a/test/integration/framework b/test/integration/framework index 7b03c09ef..1b99929e2 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -520,6 +520,12 @@ Package: $NAME" > debian/control buildsimplenativepackage() { local NAME="$1" + local NM + if [ "$(echo "$NAME" | cut -c 1-3)" = 'lib' ]; then + NM="$(echo "$NAME" | cut -c 1-4)" + else + NM="$(echo "$NAME" | cut -c 1)" + fi local ARCH="$2" local VERSION="$3" local RELEASE="${4:-unstable}" @@ -600,15 +606,15 @@ Package: $NAME" >> ${BUILDDIR}/debian/control (cd ${BUILDDIR}; dpkg-gencontrol -DArchitecture=$arch) (cd ${BUILDDIR}/debian/tmp; md5sum $(find usr/ -type f) > DEBIAN/md5sums) local LOG="${BUILDDIR}/../${NAME}_${VERSION}_${arch}.dpkg-deb.log" - # ensure the right permissions as dpkg-deb ensists + # ensure the right permissions as dpkg-deb insists chmod 755 ${BUILDDIR}/debian/tmp/DEBIAN testsuccess --nomsg dpkg-deb -Z${COMPRESS_TYPE} --build ${BUILDDIR}/debian/tmp ${BUILDDIR}/.. echo "pool/${NAME}_${VERSION}_${arch}.deb" >> ${BUILDDIR}/../${RELEASE}.${DISTSECTION}.pkglist done - mkdir -p ${BUILDDIR}/../${NAME}_${VERSION} - cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}/ - cp ${BUILDDIR}/debian/changelog ${BUILDDIR}/../${NAME}_${VERSION}.changelog + local CHANGEPATH="${BUILDDIR}/../${DISTSECTION}/${NM}/${NAME}/${NAME}_${VERSION}" + mkdir -p $CHANGEPATH + cp ${BUILDDIR}/debian/changelog $CHANGEPATH rm -rf "${BUILDDIR}" msgdone "info" } @@ -876,6 +882,7 @@ getcodenamefromsuite() { } getreleaseversionfromsuite() { true; } getlabelfromsuite() { true; } +getoriginfromsuite() { true; } generatereleasefiles() { # $1 is the Date header and $2 is the ValidUntil header to be set @@ -887,16 +894,21 @@ generatereleasefiles() { local CODENAME="$(getcodenamefromsuite $SUITE)" local VERSION="$(getreleaseversionfromsuite $SUITE)" local LABEL="$(getlabelfromsuite $SUITE)" + local ORIGIN="$(getoriginfromsuite $SUITE)" if [ -n "$VERSION" ]; then VERSION="-o APT::FTPArchive::Release::Version=${VERSION}" fi if [ -n "$LABEL" ]; then LABEL="-o APT::FTPArchive::Release::Label=${LABEL}" fi + if [ -n "$ORIGIN" ]; then + ORIGIN="-o APT::FTPArchive::Release::Origin=${ORIGIN}" + fi aptftparchive -qq release $dir \ -o APT::FTPArchive::Release::Suite="${SUITE}" \ -o APT::FTPArchive::Release::Codename="${CODENAME}" \ ${LABEL} \ + ${ORIGIN} \ ${VERSION} \ | sed -e '/0 Release$/ d' > $dir/Release # remove the self reference if [ "$SUITE" = "experimental" -o "$SUITE" = "experimental2" ]; then @@ -1450,9 +1462,9 @@ testfilestats() { msgpass else echo >&2 - ls -ld >&2 "$1" + ls -ld >&2 "$1" || true echo -n >&2 "stat(1) reports for $2: " - stat --format "$2" "$1" + stat --format "$2" "$1" || true msgfail fi } diff --git a/test/integration/test-apt-get-changelog b/test/integration/test-apt-get-changelog index 7e81c71b6..5fa8543b9 100755 --- a/test/integration/test-apt-get-changelog +++ b/test/integration/test-apt-get-changelog @@ -5,44 +5,98 @@ TESTDIR=$(readlink -f $(dirname $0)) . $TESTDIR/framework setupenvironment -configarchitecture "i386" +configarchitecture 'native' -buildsimplenativepackage 'apt' 'all' '1.0' 'stable' +buildsimplenativepackage 'foo' 'all' '1.0' 'stable' +buildsimplenativepackage 'libbar' 'all' '1.0' 'stable' + +getlabelfromsuite() { echo 'Testcases'; } +getoriginfromsuite() { echo 'Debian'; } setupaptarchive --no-update changetowebserver testsuccess aptget update -# simulate normal user with non-existent root-owned directories -rm -rf rootdir/var/cache/apt/archives/ -mkdir rootdir/var/cache/apt/archives/ -addtrap 'prefix' "chmod -f -R +w $PWD/rootdir/var/cache/apt/archives || true;" -chmod -R -w rootdir/var/cache/apt/archives +testsuccessequal "'http://metadata.ftp-master.debian.org/changelogs/main/f/foo/foo_1.0_changelog' foo.changelog +'http://metadata.ftp-master.debian.org/changelogs/main/libb/libbar/libbar_1.0_changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +releasechanger() { + # modifying the Release files in lists… bad stuff. Good that this is only a test… + sed -i "s#^${1}: .*#${1}: ${2}#" $(find rootdir/var/lib/apt/lists -name '*Release') + rm -f rootdir/var/cache/apt/*.bin +} +releasechanger 'Origin' 'Ubuntu' +testsuccessequal "'http://changelogs.ubuntu.com/changelogs/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://changelogs.ubuntu.com/changelogs/pool/main/libb/libbar/libbar_1.0/changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +releasechanger 'Label' 'Debian' +testsuccessequal "'http://changelogs.ubuntu.com/changelogs/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://changelogs.ubuntu.com/changelogs/pool/main/libb/libbar/libbar_1.0/changelog' libbar.changelog" aptget changelog foo libbar --print-uris + +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0.changelog' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0.changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' + +sed -i '/^Origin: / a\ +Changelogs: http://example.org/CHANGEPATH-changelog' $(find rootdir/var/lib/apt/lists -name '*Release') +rm -f rootdir/var/cache/apt/*.bin -echo 'Apt::Changelogs::Server "http://localhost:8080/";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://example.org/main/f/foo/foo_1.0-changelog' foo.changelog +'http://example.org/main/libb/libbar/libbar_1.0-changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' -testsuccessequal "'http://localhost:8080/pool/apt_1.0/changelog'" aptget changelog apt --print-uris +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0.changelog' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0.changelog' libbar.changelog" aptget changelog foo libbar --print-uris -o Acquire::Changelogs::URI::Override::Label::Debian='http://localhost:8080/CHANGEPATH.changelog' -testsuccessequal "'http://localhost:8080/pool/apt_1.0/changelog' -'http://localhost:8080/pool/apt_1.0/changelog'" aptget changelog apt apt --print-uris +releasechanger 'Changelogs' 'no' +testequal 'E: Failed to fetch changelog:/foo.changelog Changelog unavailable for foo=1.0 +' aptget changelog foo -qq -d + +sed -i '/^Changelogs: / d' $(find rootdir/var/lib/apt/lists -name '*Release') +releasechanger 'Label' 'Testcases' + +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/CHANGEPATH/change.txt";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/main/f/foo/foo_1.0/change.txt' foo.changelog +'http://localhost:8080/main/libb/libbar/libbar_1.0/change.txt' libbar.changelog" aptget changelog foo libbar --print-uris + +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/pool/CHANGEPATH/changelog";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog" aptget changelog foo --print-uris cd downloaded -testsuccess aptget changelog apt -qq -testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/apt_1.0/changelog)" +testsuccess aptget changelog foo -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" + +testsuccess aptget changelog foo libbar -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog) +$(cat ../aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)" + +testsuccess aptget changelog foo -d +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f foo.changelog -testsuccess aptget changelog apt -d -testfileequal 'apt.changelog' "$(cat ../aptarchive/pool/apt_1.0/changelog)" -testfilestats 'apt.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" -rm -f apt.changelog ../aptarchive/pool/apt_1.0/changelog +testsuccess aptget changelog libbar foo -d +testfilestats 'libbar.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'libbar.changelog' "$(cat ../aptarchive/pool/main/libb/libbar/libbar_1.0/changelog)" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f libbar.changelog foo.changelog -testequal "$(cat ../aptarchive/pool/apt_1.0.changelog)" aptget changelog apt \ - -qq -o APT::Changelogs::Server='http://not-on-the-main-server:8080/' +# as such bogus, but can happen with multiple binaries from the same source +testsuccessequal "'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog +'http://localhost:8080/pool/main/f/foo/foo_1.0/changelog' foo.changelog" aptget changelog foo foo --print-uris +testsuccess aptget changelog foo foo -qq +testfileequal '../rootdir/tmp/testsuccess.output' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog) +$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +testsuccess aptget changelog foo foo -d +testfilestats 'foo.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" +testfileequal 'foo.changelog' "$(cat ../aptarchive/pool/main/f/foo/foo_1.0/changelog)" +rm -f foo.changelog -testsuccess aptget changelog apt -d -testfileequal 'apt.changelog' "$(cat ../aptarchive/pool/apt_1.0.changelog)" -testfilestats 'apt.changelog' '%U:%G:%a' '=' "${TEST_DEFAULT_USER}:${TEST_DEFAULT_GROUP}:644" -rm -f apt.changelog ../aptarchive/pool/apt_1.0.changelog +# no CHANGEPATH in the URI +testequal 'E: Failed to fetch changelog:/foo.changelog Changelog unavailable for foo=1.0 +' aptget changelog foo -qq -d -o Acquire::Changelogs::URI::Label::Testcases='http://localhost:8080/change.txt' +testfailure test -e foo.changelog -testequal 'E: changelog download failed' aptget changelog apt -qq -d -o APT::Changelogs::Server='http://not-on-the-main-server:8080/' -testfailure test -e apt.changelog +testequal 'E: Failed to fetch http://localhost:8080/does/not/exist/main/f/foo/foo_1.0/change.txt Changelog unavailable for foo=1.0 (404 Not Found) +' aptget changelog foo -qq -d -o Acquire::Changelogs::URI::Label::Testcases='http://localhost:8080/does/not/exist/CHANGEPATH/change.txt' +testfailure test -e foo.changelog diff --git a/test/integration/test-bug-722207-print-uris-even-if-very-quiet b/test/integration/test-bug-722207-print-uris-even-if-very-quiet index 2cad929cc..e51d72ccd 100755 --- a/test/integration/test-bug-722207-print-uris-even-if-very-quiet +++ b/test/integration/test-bug-722207-print-uris-even-if-very-quiet @@ -12,6 +12,7 @@ insertpackage 'unstable' 'apt' 'all' '2' insertsource 'unstable' 'apt' 'all' '2' insertsource 'unstable' 'apt2' 'all' '1' +getoriginfromsuite() { echo 'Debian'; } setupaptarchive APTARCHIVE=$(readlink -f ./aptarchive) @@ -22,7 +23,7 @@ testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.d testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget download apt -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris -testsuccessequal "'http://packages.debian.org/changelogs/pool/main/apt/apt_2/changelog'" aptget changelog apt -qq --print-uris +testsuccessequal "'http://metadata.ftp-master.debian.org/changelogs/main/a/apt/apt_2_changelog' apt.changelog" aptget changelog apt -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e 'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e diff --git a/test/integration/test-bug-738785-switch-protocol b/test/integration/test-bug-738785-switch-protocol index f6336ffe3..539080200 100755 --- a/test/integration/test-bug-738785-switch-protocol +++ b/test/integration/test-bug-738785-switch-protocol @@ -10,6 +10,7 @@ configarchitecture "i386" buildsimplenativepackage 'apt' 'all' '1.0' 'stable' # setup http redirecting to https +getlabelfromsuite() { echo 'Testcases'; } setupaptarchive --no-update changetowebserver -o 'aptwebserver::redirect::replace::/redirectme/=https://localhost:4433/' \ -o 'aptwebserver::redirect::replace::/downgrademe/=http://localhost:8080/' \ @@ -20,10 +21,10 @@ sed -i -e 's#:4433/#:8080/redirectme#' -e 's# https:# http:#' rootdir/etc/apt/so testsuccess aptget update -o Debug::Acquire::http=1 -o Debug::Acquire::https=1 -o Debug::pkgAcquire::Worker=1 msgtest 'Test that the webserver does not answer' 'http requests' -downloadfile 'http://localhost:8080/pool/apt_1.0/changelog' changelog >/dev/null 2>&1 && msgfail || msgpass +downloadfile 'http://localhost:8080/pool/main/a/apt/apt_1.0/changelog' changelog >/dev/null 2>&1 && msgfail || msgpass -echo 'Apt::Changelogs::Server "http://localhost:8080/redirectme";' > rootdir/etc/apt/apt.conf.d/changelog.conf -testsuccessequal "'http://localhost:8080/redirectme/pool/apt_1.0/changelog'" aptget changelog apt --print-uris +echo 'Acquire::Changelogs::URI::Label::Testcases "http://localhost:8080/redirectme/pool/CHANGEPATH/changelog";' > rootdir/etc/apt/apt.conf.d/changelog.conf +testsuccessequal "'http://localhost:8080/redirectme/pool/main/a/apt/apt_1.0/changelog' apt.changelog" aptget changelog apt --print-uris cd downloaded testsuccess aptget changelog apt -d diff --git a/vendor/ubuntu/apt.conf-01-vendor-ubuntu b/vendor/ubuntu/apt.conf-01-vendor-ubuntu index c4092ff44..e69de29bb 100644 --- a/vendor/ubuntu/apt.conf-01-vendor-ubuntu +++ b/vendor/ubuntu/apt.conf-01-vendor-ubuntu @@ -1,6 +0,0 @@ -// Server information for apt-changelog -APT { - Changelogs { - Server "http://changelogs.ubuntu.com/changelogs"; - }; -}; -- cgit v1.2.3-70-g09d2 From 08ea7806458de0995414eaae852e0a5985875642 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 13:16:43 +0200 Subject: deal better with acquiring the same URI multiple times This is an unlikely event for indexes and co, but it can happen quiet easily e.g. for changelogs where you want to get the changelogs for multiple binary package(version)s which happen to all be built from a single source. The interesting part is that the Acquire system actually detected this already and set the item requesting the URI again to StatDone - expect that this is hardly sufficient: an Item must be Complete=true as well to be considered truely done and that is only the tip of the ::Done handling iceberg. So instead of this StatDone hack we allow QItems to be owned by multiple items and notify all owners about everything now, so that for the point of each item they got it downloaded just for them. --- apt-pkg/acquire-item.cc | 25 +- apt-pkg/acquire-item.h | 1 + apt-pkg/acquire-worker.cc | 280 +++++++++++++-------- apt-pkg/acquire-worker.h | 3 + apt-pkg/acquire.cc | 126 ++++++++-- apt-pkg/acquire.h | 44 +++- .../test-acquire-same-file-multiple-times | 80 ++++++ test/integration/test-apt-get-download | 2 +- 8 files changed, 409 insertions(+), 152 deletions(-) create mode 100755 test/integration/test-acquire-same-file-multiple-times (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 4bf4e62f8..dc4f61b56 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -438,6 +438,11 @@ APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ return Owner; } /*}}}*/ +pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ +{ + return Desc; +} + /*}}}*/ APT_CONST bool pkgAcquire::Item::IsTrusted() const /*{{{*/ { return false; @@ -840,7 +845,7 @@ bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const st return false; } - if (FileName != I->DestFile) + if (FileName != I->DestFile && RealFileExists(I->DestFile) == false) { I->Local = true; I->Desc.URI = "copy:" + FileName; @@ -2482,7 +2487,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const // Methods like e.g. "file:" will give us a (compressed) FileName that is // not the "DestFile" we set, in this case we uncompress from the local file - if (FileName != DestFile) + if (FileName != DestFile && RealFileExists(DestFile) == false) Local = true; else EraseFileName = FileName; @@ -2760,7 +2765,7 @@ void pkgAcqArchive::Done(string const &Message, HashStringList const &Hashes, } // Reference filename - if (FileName != DestFile) + if (DestFile != FileName && RealFileExists(DestFile) == false) { StoreFilename = DestFile = FileName; Local = true; @@ -2903,18 +2908,6 @@ void pkgAcqChangelog::Init(std::string const &DestDir, std::string const &DestFi strprintf(Desc.Description, "%s %s %s Changelog", URI::SiteOnly(Desc.URI).c_str(), SrcName.c_str(), SrcVersion.c_str()); Desc.Owner = this; QueueURI(Desc); - - if (Status == StatDone) // this happens if we queue the same changelog two times - { - Complete = true; - for (pkgAcquire::UriIterator I = Owner->UriBegin(); I != Owner->UriEnd(); ++I) - if (I->URI == Desc.URI) - if (DestFile != I->Owner->DestFile) - if (symlink(I->Owner->DestFile.c_str(), DestFile.c_str()) != 0) - { - ; // ignore error, there isn't anthing we could do to handle the edgecase of an edgecase - } - } } /*}}}*/ std::string pkgAcqChangelog::URI(pkgCache::VerIterator const &Ver) /*{{{*/ @@ -3107,7 +3100,7 @@ void pkgAcqFile::Done(string const &Message,HashStringList const &CalcHashes, return; // We have to copy it into place - if (FileName != DestFile) + if (RealFileExists(DestFile.c_str()) == false) { Local = true; if (_config->FindB("Acquire::Source-Symlinks",true) == false || diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 606fd4173..9dbacc1ea 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -249,6 +249,7 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ /** \return the acquire process with which this item is associated. */ pkgAcquire *GetOwner() const; + pkgAcquire::ItemDesc &GetItemDesc(); /** \return \b true if this object is being fetched from a trusted source. */ virtual bool IsTrusted() const; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 099a1f87d..d6318a21b 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -258,18 +258,27 @@ bool pkgAcquire::Worker::RunMessages() ItemDone(); - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - // Change the status so that it can be dequeued - Owner->Status = pkgAcquire::Item::StatIdle; + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + pkgAcquire::Item *Owner = *O; + Owner->Status = pkgAcquire::Item::StatIdle; + } // Mark the item as done (taking care of all queues) // and then put it in the main queue again + std::vector const ItmOwners = Itm->Owners; OwnerQ->ItemDone(Itm); - OwnerQ->Owner->Enqueue(Desc); + Itm = NULL; + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) + { + pkgAcquire::Item *Owner = *O; + pkgAcquire::ItemDesc desc = Owner->GetItemDesc(); + desc.URI = NewURI; + OwnerQ->Owner->Enqueue(desc); - if (Log != 0) - Log->Done(Desc); + if (Log != 0) + Log->Done(Owner->GetItemDesc()); + } break; } @@ -286,14 +295,18 @@ bool pkgAcquire::Worker::RunMessages() CurrentSize = 0; TotalSize = strtoull(LookupTag(Message,"Size","0").c_str(), NULL, 10); ResumePoint = strtoull(LookupTag(Message,"Resume-Point","0").c_str(), NULL, 10); - Itm->Owner->Start(Message, TotalSize); - - // Display update before completion - if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Itm->Owner->GetOwner()); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + (*O)->Start(Message, TotalSize); - if (Log != 0) - Log->Fetch(*Itm); + // Display update before completion + if (Log != 0) + { + if (Log->MorePulses == true) + Log->Pulse((*O)->GetOwner()); + Log->Fetch((*O)->GetItemDesc()); + } + } break; } @@ -307,105 +320,110 @@ bool pkgAcquire::Worker::RunMessages() break; } - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - - if (RealFileExists(Owner->DestFile)) - ChangeOwnerAndPermissionOfFile("201::URIDone", Owner->DestFile.c_str(), "root", "root", 0644); + PrepareFiles("201::URIDone", Itm); // Display update before completion if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Owner->GetOwner()); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + Log->Pulse((*O)->GetOwner()); - OwnerQ->ItemDone(Itm); - - HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); - // see if we got hashes to verify + std::string const filename = LookupTag(Message, "Filename", Itm->Owner->DestFile.c_str()); HashStringList ReceivedHashes; - for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - std::string const tagname = std::string(*type) + "-Hash"; - std::string const hashsum = LookupTag(Message, tagname.c_str()); - if (hashsum.empty() == false) - ReceivedHashes.push_back(HashString(*type, hashsum)); - } - // not all methods always sent Hashes our way - if (ExpectedHashes.usable() == true && ReceivedHashes.usable() == false) - { - std::string const filename = LookupTag(Message, "Filename", Owner->DestFile.c_str()); - if (filename.empty() == false && RealFileExists(filename)) + // see if we got hashes to verify + for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type) { - Hashes calc(ExpectedHashes); - FileFd file(filename, FileFd::ReadOnly, FileFd::None); - calc.AddFD(file); - ReceivedHashes = calc.GetHashStringList(); + std::string const tagname = std::string(*type) + "-Hash"; + std::string const hashsum = LookupTag(Message, tagname.c_str()); + if (hashsum.empty() == false) + ReceivedHashes.push_back(HashString(*type, hashsum)); + } + // not all methods always sent Hashes our way + if (ReceivedHashes.usable() == false) + { + HashStringList const ExpectedHashes = Itm->GetExpectedHashes(); + if (ExpectedHashes.usable() == true && RealFileExists(filename)) + { + Hashes calc(ExpectedHashes); + FileFd file(filename, FileFd::ReadOnly, FileFd::None); + calc.AddFD(file); + ReceivedHashes = calc.GetHashStringList(); + } } } - if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) - { - std::clog << "201 URI Done: " << Owner->DescURI() << endl - << "ReceivedHash:" << endl; - for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) - std::clog << "\t- " << hs->toStr() << std::endl; - std::clog << "ExpectedHash:" << endl; - for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) - std::clog << "\t- " << hs->toStr() << std::endl; - std::clog << endl; - } + // only local files can refer other filenames and counting them as fetched would be unfair + if (Log != NULL && filename != Itm->Owner->DestFile) + Log->Fetched(ReceivedHashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + + std::vector const ItmOwners = Itm->Owners; + OwnerQ->ItemDone(Itm); + Itm = NULL; - // decide if what we got is what we expected - bool consideredOkay = false; bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); - if (ExpectedHashes.usable()) + + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) { - if (ReceivedHashes.usable() == false) + pkgAcquire::Item * const Owner = *O; + HashStringList const ExpectedHashes = Owner->GetExpectedHashes(); + if(_config->FindB("Debug::pkgAcquire::Auth", false) == true) { - /* IMS-Hits can't be checked here as we will have uncompressed file, - but the hashes for the compressed file. What we have was good through - so all we have to ensure later is that we are not stalled. */ - consideredOkay = isIMSHit; + std::clog << "201 URI Done: " << Owner->DescURI() << endl + << "ReceivedHash:" << endl; + for (HashStringList::const_iterator hs = ReceivedHashes.begin(); hs != ReceivedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << "ExpectedHash:" << endl; + for (HashStringList::const_iterator hs = ExpectedHashes.begin(); hs != ExpectedHashes.end(); ++hs) + std::clog << "\t- " << hs->toStr() << std::endl; + std::clog << endl; } - else if (ReceivedHashes == ExpectedHashes) - consideredOkay = true; - else - consideredOkay = false; - } - else if (Owner->HashesRequired() == true) - consideredOkay = false; - else - consideredOkay = true; + // decide if what we got is what we expected + bool consideredOkay = false; + if (ExpectedHashes.usable()) + { + if (ReceivedHashes.usable() == false) + { + /* IMS-Hits can't be checked here as we will have uncompressed file, + but the hashes for the compressed file. What we have was good through + so all we have to ensure later is that we are not stalled. */ + consideredOkay = isIMSHit; + } + else if (ReceivedHashes == ExpectedHashes) + consideredOkay = true; + else + consideredOkay = false; - if (consideredOkay == true) - { - Owner->Done(Message, ReceivedHashes, Config); - ItemDone(); + } + else if (Owner->HashesRequired() == true) + consideredOkay = false; + else + consideredOkay = true; - // Log that we are done - if (Log != 0) + if (consideredOkay == true) { - if (isIMSHit) + Owner->Done(Message, ReceivedHashes, Config); + + // Log that we are done + if (Log != 0) { - /* Hide 'hits' for local only sources - we also manage to - hide gets */ - if (Config->LocalOnly == false) - Log->IMSHit(Desc); + if (isIMSHit) + Log->IMSHit(Owner->GetItemDesc()); + else + Log->Done(Owner->GetItemDesc()); } - else - Log->Done(Desc); } - } - else - { - Owner->Status = pkgAcquire::Item::StatAuthError; - Owner->Failed(Message,Config); - ItemDone(); + else + { + Owner->Status = pkgAcquire::Item::StatAuthError; + Owner->Failed(Message,Config); - if (Log != 0) - Log->Fail(Desc); + if (Log != 0) + Log->Fail(Owner->GetItemDesc()); + } } + ItemDone(); break; } @@ -419,30 +437,32 @@ bool pkgAcquire::Worker::RunMessages() break; } + PrepareFiles("400::URIFailure", Itm); + // Display update before completion if (Log != 0 && Log->MorePulses == true) - Log->Pulse(Itm->Owner->GetOwner()); - - pkgAcquire::Item *Owner = Itm->Owner; - pkgAcquire::ItemDesc Desc = *Itm; - - if (RealFileExists(Owner->DestFile)) - ChangeOwnerAndPermissionOfFile("400::URIFailure", Owner->DestFile.c_str(), "root", "root", 0644); + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + Log->Pulse((*O)->GetOwner()); + std::vector const ItmOwners = Itm->Owners; OwnerQ->ItemDone(Itm); + Itm = NULL; - // set some status - if(LookupTag(Message,"FailReason") == "Timeout" || - LookupTag(Message,"FailReason") == "TmpResolveFailure" || - LookupTag(Message,"FailReason") == "ResolveFailure" || - LookupTag(Message,"FailReason") == "ConnectionRefused") - Owner->Status = pkgAcquire::Item::StatTransientNetworkError; + for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) + { + // set some status + if(LookupTag(Message,"FailReason") == "Timeout" || + LookupTag(Message,"FailReason") == "TmpResolveFailure" || + LookupTag(Message,"FailReason") == "ResolveFailure" || + LookupTag(Message,"FailReason") == "ConnectionRefused") + (*O)->Status = pkgAcquire::Item::StatTransientNetworkError; - Owner->Failed(Message,Config); - ItemDone(); + (*O)->Failed(Message,Config); - if (Log != 0) - Log->Fail(Desc); + if (Log != 0) + Log->Fail((*O)->GetItemDesc()); + } + ItemDone(); break; } @@ -578,16 +598,24 @@ bool pkgAcquire::Worker::QueueItem(pkgAcquire::Queue::QItem *Item) Message.reserve(300); Message += "URI: " + Item->URI; Message += "\nFilename: " + Item->Owner->DestFile; - HashStringList const hsl = Item->Owner->GetExpectedHashes(); + + HashStringList const hsl = Item->GetExpectedHashes(); for (HashStringList::const_iterator hs = hsl.begin(); hs != hsl.end(); ++hs) Message += "\nExpected-" + hs->HashType() + ": " + hs->HashValue(); - if(Item->Owner->FileSize > 0) + + if (hsl.FileSize() == 0) { - string MaximumSize; - strprintf(MaximumSize, "%llu", Item->Owner->FileSize); - Message += "\nMaximum-Size: " + MaximumSize; + unsigned long long FileSize = Item->GetMaximumSize(); + if(FileSize > 0) + { + string MaximumSize; + strprintf(MaximumSize, "%llu", FileSize); + Message += "\nMaximum-Size: " + MaximumSize; + } } - Message += Item->Owner->Custom600Headers(); + + Item->SyncDestinationFiles(); + Message += Item->Custom600Headers(); Message += "\n\n"; if (RealFileExists(Item->Owner->DestFile)) @@ -686,3 +714,33 @@ void pkgAcquire::Worker::ItemDone() Status = string(); } /*}}}*/ +void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm)/*{{{*/ +{ + if (RealFileExists(Itm->Owner->DestFile)) + { + ChangeOwnerAndPermissionOfFile(caller, Itm->Owner->DestFile.c_str(), "root", "root", 0644); + std::string const filename = Itm->Owner->DestFile; + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + pkgAcquire::Item const * const Owner = *O; + if (Owner->DestFile == filename) + continue; + unlink(Owner->DestFile.c_str()); + if (link(filename.c_str(), Owner->DestFile.c_str()) != 0) + { + // diferent mounts can't happen for us as we download to lists/ by default, + // but if the system is reused by others the locations can potentially be on + // different disks, so use symlink as poor-men replacement. + // FIXME: Real copying as last fallback, but that is costly, so offload to a method preferable + if (symlink(filename.c_str(), Owner->DestFile.c_str()) != 0) + _error->Error("Can't create (sym)link of file %s to %s", filename.c_str(), Owner->DestFile.c_str()); + } + } + } + else + { + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + unlink((*O)->DestFile.c_str()); + } +} + /*}}}*/ diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index db8889c8e..3a3ef706d 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -326,6 +326,9 @@ class pkgAcquire::Worker : public WeakPointable * \b false, also rudely interrupts the worker with a SIGINT. */ virtual ~Worker(); + +private: + APT_HIDDEN void PrepareFiles(char const * const caller, pkgAcquire::Queue::QItem const * const Itm); }; /** @} */ diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 0c815c005..14c8863dc 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -682,7 +683,8 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item) for (; *I != 0; I = &(*I)->Next) if (Item.URI == (*I)->URI) { - Item.Owner->Status = Item::StatDone; + (*I)->Owners.push_back(Item.Owner); + Item.Owner->Status = (*I)->Owner->Status; return false; } @@ -705,13 +707,13 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner) { if (Owner->Status == pkgAcquire::Item::StatFetching) return _error->Error("Tried to dequeue a fetching object"); - + bool Res = false; - + QItem **I = &Items; for (; *I != 0;) { - if ((*I)->Owner == Owner) + if (Owner == (*I)->Owner) { QItem *Jnk= *I; *I = (*I)->Next; @@ -722,7 +724,7 @@ bool pkgAcquire::Queue::Dequeue(Item *Owner) else I = &(*I)->Next; } - + return Res; } /*}}}*/ @@ -799,9 +801,12 @@ pkgAcquire::Queue::QItem *pkgAcquire::Queue::FindItem(string URI,pkgAcquire::Wor bool pkgAcquire::Queue::ItemDone(QItem *Itm) { PipeDepth--; - if (Itm->Owner->Status == pkgAcquire::Item::StatFetching) - Itm->Owner->Status = pkgAcquire::Item::StatDone; - + for (QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + { + if ((*O)->Status == pkgAcquire::Item::StatFetching) + (*O)->Status = pkgAcquire::Item::StatDone; + } + if (Itm->Owner->QueueCounter <= 1) Owner->Dequeue(Itm->Owner); else @@ -809,7 +814,7 @@ bool pkgAcquire::Queue::ItemDone(QItem *Itm) Dequeue(Itm->Owner); Owner->Bump(); } - + return Cycle(); } /*}}}*/ @@ -824,7 +829,7 @@ bool pkgAcquire::Queue::Cycle() if (PipeDepth < 0) return _error->Error("Pipedepth failure"); - + // Look for a queable item QItem *I = Items; while (PipeDepth < (signed)MaxPipeDepth) @@ -832,18 +837,19 @@ bool pkgAcquire::Queue::Cycle() for (; I != 0; I = I->Next) if (I->Owner->Status == pkgAcquire::Item::StatIdle) break; - + // Nothing to do, queue is idle. if (I == 0) return true; - + I->Worker = Workers; - I->Owner->Status = pkgAcquire::Item::StatFetching; + for (QItem::owner_iterator O = I->Owners.begin(); O != I->Owners.end(); ++O) + (*O)->Status = pkgAcquire::Item::StatFetching; PipeDepth++; if (Workers->QueueItem(I) == false) return false; } - + return true; } /*}}}*/ @@ -855,6 +861,94 @@ void pkgAcquire::Queue::Bump() Cycle(); } /*}}}*/ +HashStringList pkgAcquire::Queue::QItem::GetExpectedHashes() const /*{{{*/ +{ + /* each Item can have multiple owners and each owner might have different + hashes, even if that is unlikely in practice and if so at least some + owners will later fail. There is one situation through which is not a + failure and still needs this handling: Two owners who expect the same + file, but one owner only knows the SHA1 while the other only knows SHA256. */ + HashStringList superhsl; + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + HashStringList const hsl = (*O)->GetExpectedHashes(); + if (hsl.usable() == false) + continue; + if (superhsl.usable() == false) + superhsl = hsl; + else + { + // we merge both lists - if we find disagreement send no hashes + HashStringList::const_iterator hs = hsl.begin(); + for (; hs != hsl.end(); ++hs) + if (superhsl.push_back(*hs) == false) + break; + if (hs != hsl.end()) + { + superhsl.clear(); + break; + } + } + } + return superhsl; +} + /*}}}*/ +APT_PURE unsigned long long pkgAcquire::Queue::QItem::GetMaximumSize() const /*{{{*/ +{ + unsigned long long Maximum = std::numeric_limits::max(); + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + if ((*O)->FileSize == 0) + continue; + Maximum = std::min(Maximum, (*O)->FileSize); + } + if (Maximum == std::numeric_limits::max()) + return 0; + return Maximum; +} + /*}}}*/ +void pkgAcquire::Queue::QItem::SyncDestinationFiles() const /*{{{*/ +{ + /* ensure that the first owner has the best partial file of all and + the rest have (potentially dangling) symlinks to it so that + everything (like progress reporting) finds it easily */ + std::string superfile = Owner->DestFile; + off_t supersize = 0; + for (pkgAcquire::Queue::QItem::owner_iterator O = Owners.begin(); O != Owners.end(); ++O) + { + if ((*O)->DestFile == superfile) + continue; + struct stat file; + if (lstat((*O)->DestFile.c_str(),&file) == 0) + { + if ((file.st_mode & S_IFREG) == 0) + unlink((*O)->DestFile.c_str()); + else if (supersize < file.st_size) + { + supersize = file.st_size; + unlink(superfile.c_str()); + rename((*O)->DestFile.c_str(), superfile.c_str()); + } + else + unlink((*O)->DestFile.c_str()); + if (symlink(superfile.c_str(), (*O)->DestFile.c_str()) != 0) + { + ; // not a problem per-se and no real alternative + } + } + } +} + /*}}}*/ +std::string pkgAcquire::Queue::QItem::Custom600Headers() const /*{{{*/ +{ + /* The others are relatively easy to merge, but this one? + Lets not merge and see how far we can run with it… + Likely, nobody will ever notice as all the items will + be of the same class and hence generate the same headers. */ + return Owner->Custom600Headers(); +} + /*}}}*/ + // AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -914,9 +1008,9 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) { CurrentBytes += I->CurrentSize; ResumeSize += I->ResumePoint; - + // Files with unknown size always have 100% completion - if (I->CurrentItem->Owner->FileSize == 0 && + if (I->CurrentItem->Owner->FileSize == 0 && I->CurrentItem->Owner->Complete == false) TotalBytes += I->CurrentSize; } diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index fc90624e1..02031dafd 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -68,9 +68,10 @@ #include #include +#include -#include #include +#include #include #include @@ -390,13 +391,13 @@ class pkgAcquire */ struct pkgAcquire::ItemDesc : public WeakPointable { - /** \brief The URI from which to download this item. */ + /** \brief URI from which to download this item. */ std::string URI; - /** brief A description of this item. */ + /** \brief description of this item. */ std::string Description; - /** brief A shorter description of this item. */ + /** \brief shorter description of this item. */ std::string ShortDesc; - /** brief The underlying item which is to be downloaded. */ + /** \brief underlying item which is to be downloaded. */ Item *Owner; }; /*}}}*/ @@ -419,13 +420,26 @@ class pkgAcquire::Queue protected: /** \brief A single item placed in this queue. */ - struct QItem : pkgAcquire::ItemDesc + struct QItem : public WeakPointable { /** \brief The next item in the queue. */ QItem *Next; /** \brief The worker associated with this item, if any. */ pkgAcquire::Worker *Worker; + /** \brief The URI from which to download this item. */ + std::string URI; + /** \brief A description of this item. */ + std::string Description; + /** \brief A shorter description of this item. */ + std::string ShortDesc; + /** \brief The underlying items interested in the download */ + std::vector Owners; + // both, backward compatibility and easy access as syncing is interal + Item * Owner; + + typedef std::vector::const_iterator owner_iterator; + /** \brief Assign the ItemDesc portion of this QItem from * another ItemDesc */ @@ -434,10 +448,24 @@ class pkgAcquire::Queue URI = I.URI; Description = I.Description; ShortDesc = I.ShortDesc; + Owners.clear(); + Owners.push_back(I.Owner); Owner = I.Owner; }; + + /** @return the sum of all expected hashes by all owners */ + HashStringList GetExpectedHashes() const; + + /** @return smallest maximum size of all owners */ + unsigned long long GetMaximumSize() const; + + /** \brief get partial files in order */ + void SyncDestinationFiles() const; + + /** @return the custom headers to use for this item */ + std::string Custom600Headers() const; }; - + /** \brief The name of this queue. */ std::string Name; @@ -590,7 +618,7 @@ class pkgAcquire::UriIterator } }; - inline pkgAcquire::ItemDesc const *operator ->() const {return CurItem;}; + inline pkgAcquire::Queue::QItem const *operator ->() const {return CurItem;}; inline bool operator !=(UriIterator const &rhs) const {return rhs.CurQ != CurQ || rhs.CurItem != CurItem;}; inline bool operator ==(UriIterator const &rhs) const {return rhs.CurQ == CurQ && rhs.CurItem == CurItem;}; diff --git a/test/integration/test-acquire-same-file-multiple-times b/test/integration/test-acquire-same-file-multiple-times new file mode 100755 index 000000000..d329a39cb --- /dev/null +++ b/test/integration/test-acquire-same-file-multiple-times @@ -0,0 +1,80 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +TESTFILE="$TESTDIR/framework" +cp $TESTFILE aptarchive/foo +APTARCHIVE="$(readlink -f ./aptarchive)" + +filedown() { + msgtest 'Downloading the same URI twice over file' "$1" + testsuccess --nomsg apthelper download-file file:///$APTARCHIVE/foo ./downloaded/foo1 '' file:///$APTARCHIVE/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 + cp rootdir/tmp/testsuccess.output download.log + #cat download.log + testsuccess cmp $TESTFILE ./downloaded/foo1 + testsuccess cmp ./downloaded/foo1 ./downloaded/foo2 + #testequal '1' grep -c '200%20URI%20Start' ./download.log + testequal '1' grep -c '201%20URI%20Done' ./download.log + rm -f ./downloaded/foo1 ./downloaded/foo2 +} + +testrun() { + $1 'no partial' + cp $TESTFILE ./downloaded/foo1 + $1 'complete partial 1' + cp $TESTFILE ./downloaded/foo2 + $1 'complete partial 2' + cp $TESTFILE ./downloaded/foo1 + cp $TESTFILE ./downloaded/foo2 + $1 'complete partial 1+2' + dd if=$TESTFILE of=./downloaded/foo1 bs=500 count=1 2>/dev/null + $1 'partial partial 1' + dd if=$TESTFILE of=./downloaded/foo2 bs=500 count=1 2>/dev/null + $1 'partial partial 2' + dd if=$TESTFILE of=./downloaded/foo1 bs=500 count=1 2>/dev/null + dd if=$TESTFILE of=./downloaded/foo2 bs=500 count=1 2>/dev/null + $1 'partial partial 1+2' +} +testrun 'filedown' + +changetowebserver -o aptwebserver::redirect::replace::/foo2=/foo + +httpdown() { + msgtest 'Downloading the same URI to different files' 'twice over http' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 + cp rootdir/tmp/testsuccess.output download.log + testsuccess cmp $TESTDIR/framework ./downloaded/foo1 + testsuccess cmp ./downloaded/foo1 ./downloaded/foo2 + testequal '1' grep -c '200%20URI%20Start' ./download.log + testequal '1' grep -c '201%20URI%20Done' ./download.log + rm -f ./downloaded/foo1 ./downloaded/foo2 +} +testrun 'httpdown' + +httpredirectdown() { + msgtest 'Redirect leads' 'first URI to the second URI' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo2 ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 + cp rootdir/tmp/testsuccess.output download.log + testsuccess cmp $TESTDIR/framework ./downloaded/foo1 + testsuccess cmp ./downloaded/foo1 ./downloaded/foo2 + testequal '1' grep -c '200%20URI%20Start' ./download.log + testequal '1' grep -c '103%20Redirect' ./download.log + testequal '1' grep -c '201%20URI%20Done' ./download.log + rm -f ./downloaded/foo1 ./downloaded/foo2 +} +testrun 'httpredirectdown' + +httpsamedown() { + msgtest 'Downloading two files via the same URI to' 'the same file' + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo1 '' -o Debug::pkgAcquire::Worker=1 + cp rootdir/tmp/testsuccess.output download.log + testsuccess cmp $TESTDIR/framework ./downloaded/foo1 + testequal '1' grep -c '200%20URI%20Start' ./download.log + testequal '1' grep -c '201%20URI%20Done' ./download.log + rm -f ./downloaded/foo1 +} +testrun 'httpsamedown' diff --git a/test/integration/test-apt-get-download b/test/integration/test-apt-get-download index 6503bbd1c..fa0b65672 100755 --- a/test/integration/test-apt-get-download +++ b/test/integration/test-apt-get-download @@ -38,7 +38,7 @@ testdownload() { APT="${APT}/${3}" fi msgtest "Test download of package file $1 with" "$APT" - testsuccess --nomsg aptget download ${APT} + testsuccess --nomsg aptget download ${APT} -o Debug::pkgAcquire::Worker=1 -o Debug::pkgAcquire::Auth=1 testsuccess test -f "$1" rm -f "$1" } -- cgit v1.2.3-70-g09d2 From ff86d7df6a53ff6283de4b9a858c1dad98ed887f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 13:36:11 +0200 Subject: call URIStart in cdrom and file method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All other methods call it, so they should follow along even if the work they do afterwards is hardly breathtaking and usually results in a URIDone pretty soon, but the acquire system tells the individual item about this via a virtual method call, so even through none of our existing items contains any critical code in these, maybe one day they might. Consistency at least once… Which is also why this has a good sideeffect: file: and cdrom: requests appear now in the 'apt-get update' output. Finally - it never made sense to hide them for me. Okay, I guess it made before the new hit behavior, but now that you can actually see the difference in an update it makes sense to see if a file: repository changed or not as well. --- apt-pkg/acquire-item.cc | 13 ++++--------- apt-pkg/acquire-worker.cc | 1 - methods/cdrom.cc | 3 ++- methods/file.cc | 18 ++++++++++-------- test/integration/test-apt-cdrom | 6 ++++-- test/integration/test-apt-get-update-unauth-warning | 7 +++++++ test/integration/test-apt-progress-fd | 6 ++++-- .../test-bug-595691-empty-and-broken-archive-files | 20 ++++---------------- .../test-bug-596498-trusted-unsigned-repo | 8 +++++++- 9 files changed, 42 insertions(+), 40 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index dc4f61b56..50936b627 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -519,19 +519,14 @@ void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const /*Cnf*/) { // We just downloaded something.. - string FileName = LookupTag(Message,"Filename"); UsedMirror = LookupTag(Message,"UsedMirror"); - unsigned long long const downloadedSize = Hashes.FileSize(); - if (downloadedSize != 0) + if (FileSize == 0) { - if (Complete == false && !Local && FileName == DestFile) + unsigned long long const downloadedSize = Hashes.FileSize(); + if (downloadedSize != 0) { - if (Owner->Log != 0) - Owner->Log->Fetched(Hashes.FileSize(),atoi(LookupTag(Message,"Resume-Point","0").c_str())); + FileSize = downloadedSize; } - - if (FileSize == 0) - FileSize= downloadedSize; } Status = StatDone; ErrorText = string(); diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index d6318a21b..ef195d44b 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -362,7 +362,6 @@ bool pkgAcquire::Worker::RunMessages() bool const isIMSHit = StringToBool(LookupTag(Message,"IMS-Hit"),false) || StringToBool(LookupTag(Message,"Alt-IMS-Hit"),false); - for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) { pkgAcquire::Item * const Owner = *O; diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 10cb29f66..67265cfa3 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -260,7 +260,8 @@ bool CDROMMethod::Fetch(FetchItem *Itm) struct stat Buf; if (stat(Res.Filename.c_str(),&Buf) != 0) return _error->Error(_("File not found")); - + + URIStart(Res); if (NewID.empty() == false) CurrentID = NewID; Res.LastModified = Buf.st_mtime; diff --git a/methods/file.cc b/methods/file.cc index 5d5fffa67..5c76ec122 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -58,7 +58,10 @@ bool FileMethod::Fetch(FetchItem *Itm) { HashStringList const hsl = Itm->ExpectedHashes; if (Itm->ExpectedHashes.VerifyFile(File)) + { + Res.Filename = Itm->DestFile; Res.IMSHit = true; + } } } } @@ -78,7 +81,14 @@ bool FileMethod::Fetch(FetchItem *Itm) if (filesize != 0 && filesize == Res.Size) Res.IMSHit = true; } + + Hashes Hash(Itm->ExpectedHashes); + FileFd Fd(File, FileFd::ReadOnly); + Hash.AddFD(Fd); + Res.TakeHashes(Hash); } + if (Res.IMSHit == false) + URIStart(Res); // See if the uncompressed file exists and reuse it FetchResult AltRes; @@ -103,14 +113,6 @@ bool FileMethod::Fetch(FetchItem *Itm) } } - if (Res.Filename.empty() == false) - { - Hashes Hash(Itm->ExpectedHashes); - FileFd Fd(Res.Filename, FileFd::ReadOnly); - Hash.AddFD(Fd); - Res.TakeHashes(Hash); - } - if (AltRes.Filename.empty() == false) URIDone(Res,&AltRes); else if (Res.Filename.empty() == false) diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom index 34b35f745..6a218ffb8 100755 --- a/test/integration/test-apt-cdrom +++ b/test/integration/test-apt-cdrom @@ -136,13 +136,15 @@ aptcache show testing -o Acquire::Languages=en | grep -q '^Description-en: ' && mv rootdir/media/cdrom-unmounted rootdir/media/cdrom-ejected msgmsg "ensure an update doesn't mess with cdrom sources" testsuccess aptget update -testfileequal rootdir/tmp/testsuccess.output 'Reading package lists...' +testfileequal rootdir/tmp/testsuccess.output 'Hit cdrom://Debian APT Testdisk 0.8.15 stable InRelease +Reading package lists...' mv rootdir/media/cdrom-ejected rootdir/media/cdrom-unmounted testcdromusage msgmsg 'and again to check that it withstands the temptation even if it could mount' testsuccess aptget update -testfileequal rootdir/tmp/testsuccess.output 'Reading package lists...' +testfileequal rootdir/tmp/testsuccess.output 'Hit cdrom://Debian APT Testdisk 0.8.15 stable InRelease +Reading package lists...' testcdromusage msgmsg 'Check that nothing touched our' 'CD-ROM' diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index ada7f7a26..1f4a14e23 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -9,6 +9,7 @@ TESTDIR=$(readlink -f $(dirname $0)) setupenvironment configarchitecture "i386" +configcompression '.' 'gz' # a "normal" package with source and binary buildsimplenativepackage 'foo' 'all' '2.0' @@ -31,11 +32,17 @@ testsuccessequal 'Listing...' apt list foo testequal 'lock partial' ls rootdir/var/lib/apt/lists +filesize() { + stat -c%s "$(aptget files --no-release-info --format '$(URI)' "Created-By: $1" | cut -d'/' -f 3- ).gz" +} # allow override testwarningequal "Ign file:$APTARCHIVE unstable InRelease File not found Ign file:$APTARCHIVE unstable Release File not found +Get:1 file:$APTARCHIVE unstable/main Sources [$(filesize 'Sources') B] +Get:2 file:$APTARCHIVE unstable/main i386 Packages [$(filesize 'Packages') B] +Get:3 file:$APTARCHIVE unstable/main Translation-en [$(filesize 'Translations') B] Reading package lists... W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." aptget update --allow-insecure-repositories # ensure we can not install the package diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 0c11aba7e..99b4ea050 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -16,6 +16,7 @@ setupaptarchive exec 3> apt-progress.log testsuccess aptget install testing=0.1 -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -32,6 +33,7 @@ pmstatus:dpkg-exec:83.3333:Running dpkg' exec 3> apt-progress.log testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -48,6 +50,7 @@ pmstatus:dpkg-exec:83.3333:Running dpkg' exec 3> apt-progress.log testsuccess aptget install testing=0.8.15 --reinstall -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -73,9 +76,8 @@ pmstatus:dpkg-exec:75:Running dpkg' # install non-native and ensure we get proper progress info exec 3> apt-progress.log testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 - -# and compare testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 +dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing2:0:Installing testing2 (i386) diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index b42212f5e..3042d116d 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -27,9 +27,6 @@ testaptgetupdate() { createemptyarchive() { find aptarchive/ \( -name "Packages*" -o -name "en*" \) -type f -delete - if [ "en" = "$1" ]; then - echo -n "" | $COMPRESSOR_CMD > aptarchive/Packages.$COMPRESS - fi touch aptarchive/Packages echo -n "" | $COMPRESSOR_CMD > aptarchive/${1}.$COMPRESS generatereleasefiles @@ -39,9 +36,6 @@ createemptyarchive() { createemptyfile() { find aptarchive/ \( -name "Packages*" -o -name "en*" \) -type f -delete - if [ "en" = "$1" ]; then - echo -n "" | $COMPRESSOR_CMD > aptarchive/Packages.$COMPRESS - fi touch aptarchive/Packages aptarchive/${1}.$COMPRESS generatereleasefiles signreleasefiles @@ -52,19 +46,13 @@ testoverfile() { local APTARCHIVE="$(readlink -f ./aptarchive)" forcecompressor "$1" - createemptyfile 'en' - testaptgetupdate 'Reading package lists...' "empty file en.$COMPRESS over file" - - createemptyarchive 'en' - testaptgetupdate 'Reading package lists...' "empty archive en.$COMPRESS over file" - createemptyarchive 'Packages' - # FIXME: Why omits the file transport the Packages Get line? - #Get:3 file: Packages [] - testaptgetupdate 'Reading package lists...' "empty archive Packages.$COMPRESS over file" + testaptgetupdate "Get: file:$APTARCHIVE Packages [] +Reading package lists..." "empty archive Packages.$COMPRESS over file" createemptyfile 'Packages' - testaptgetupdate "Err file:$APTARCHIVE Packages + testaptgetupdate "Get: file:$APTARCHIVE Packages +Err file:$APTARCHIVE Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:${APTARCHIVE}/Packages.$COMPRESS Empty files can't be valid archives diff --git a/test/integration/test-bug-596498-trusted-unsigned-repo b/test/integration/test-bug-596498-trusted-unsigned-repo index 4eb77b9a4..1ff0f1d8d 100755 --- a/test/integration/test-bug-596498-trusted-unsigned-repo +++ b/test/integration/test-bug-596498-trusted-unsigned-repo @@ -15,13 +15,17 @@ aptgetupdate() { ${1:-testwarning} aptget update --allow-insecure-repositories } -PKGTEXT="$(aptget install cool --assume-no -d | head -n 7)" +PKGTEXT="$(aptget install cool --assume-no -d | head -n 8)" +DOWNLOG="$(echo "$PKGTEXT" | tail -n 1)" +PKGTEXT="$(echo "$PKGTEXT" | head -n 7)" DEBFILE='rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.list' testsuccessequal "$PKGTEXT +$DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d testsuccessequal "$PKGTEXT +$DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated sed -i -e 's#deb#deb [trusted=no]#' $DEBFILE @@ -47,10 +51,12 @@ testsuccessequal "$PKGTEXT WARNING: The following packages cannot be authenticated! cool Authentication warning overridden. +$DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated sed -i -e 's#deb#deb [trusted=yes]#' $DEBFILE aptgetupdate testsuccessequal "$PKGTEXT +$DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d -- cgit v1.2.3-70-g09d2 From 1eb1836f4b5397497bd34f0cf516e6e4e73117bf Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 16:41:43 +0200 Subject: show item ID in Hit, Ign and Err lines as well Again, consistency is the main sellingpoint here, but this way it is now also easier to explain that some files move through different stages and lines are printed for them hence multiple times: That is a bit hard to believe if the number is changing all the time, but now that it keeps consistent. --- apt-pkg/acquire-item.cc | 2 +- apt-private/acqprogress.cc | 38 +++++++++++++++----- apt-private/acqprogress.h | 3 +- po/apt-all.pot | 12 ++++--- po/ar.po | 18 ++++++---- po/ast.po | 20 ++++++----- po/bg.po | 20 ++++++----- po/bs.po | 8 ++--- po/ca.po | 20 ++++++----- po/cs.po | 20 ++++++----- po/cy.po | 20 ++++++----- po/da.po | 20 ++++++----- po/de.po | 20 ++++++----- po/dz.po | 20 ++++++----- po/el.po | 20 ++++++----- po/es.po | 20 ++++++----- po/eu.po | 20 ++++++----- po/fi.po | 20 ++++++----- po/fr.po | 20 ++++++----- po/gl.po | 20 ++++++----- po/he.po | 12 ++++--- po/hu.po | 20 ++++++----- po/it.po | 21 +++++++----- po/ja.po | 20 ++++++----- po/km.po | 20 ++++++----- po/ko.po | 20 ++++++----- po/ku.po | 16 +++++---- po/lt.po | 20 ++++++----- po/mr.po | 20 ++++++----- po/nb.po | 20 ++++++----- po/ne.po | 20 ++++++----- po/nl.po | 20 ++++++----- po/nn.po | 20 ++++++----- po/pl.po | 20 ++++++----- po/pt.po | 20 ++++++----- po/pt_BR.po | 20 ++++++----- po/ro.po | 20 ++++++----- po/ru.po | 20 ++++++----- po/sk.po | 20 ++++++----- po/sl.po | 20 ++++++----- po/sv.po | 20 ++++++----- po/th.po | 20 ++++++----- po/tl.po | 20 ++++++----- po/tr.po | 20 ++++++----- po/uk.po | 20 ++++++----- po/vi.po | 20 ++++++----- po/zh_CN.po | 20 ++++++----- po/zh_TW.po | 20 ++++++----- test/integration/test-apt-acquire-additional-files | 10 +++--- test/integration/test-apt-cdrom | 4 +-- .../integration/test-apt-get-update-unauth-warning | 14 ++++---- test/integration/test-apt-update-ims | 36 +++++++++---------- test/integration/test-apt-update-not-modified | 40 +++++++++++----------- .../test-bug-595691-empty-and-broken-archive-files | 14 ++++---- test/integration/test-bug-602412-dequote-redirect | 2 +- test/integration/test-pdiff-usage | 2 +- .../test-ubuntu-bug-1098738-apt-get-source-md5sum | 8 ++--- 57 files changed, 618 insertions(+), 422 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 50936b627..5460280ec 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -405,7 +405,7 @@ class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ // Acquire::Item::Item - Constructor /*{{{*/ APT_IGNORE_DEPRECATED_PUSH pkgAcquire::Item::Item(pkgAcquire * const Owner) : - FileSize(0), PartialSize(0), Mode(0), Complete(false), Local(false), + FileSize(0), PartialSize(0), Mode(0), ID(0), Complete(false), Local(false), QueueCounter(0), ExpectedAdditionalItems(0), Owner(Owner) { Owner->Add(this); diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index 0c606e48e..dc92e3b2a 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -49,6 +49,16 @@ void AcqTextStatus::Start() ID = 1; } /*}}}*/ +void AcqTextStatus::AssignItemID(pkgAcquire::ItemDesc &Itm) /*{{{*/ +{ + /* In theory calling it from Fetch() would be enough, but to be + safe we call it from IMSHit and Fail as well. + Also, an Item can pass through multiple stages, so ensure + that it keeps the same number */ + if (Itm.Owner->ID == 0) + Itm.Owner->ID = ID++; +} + /*}}}*/ // AcqTextStatus::IMSHit - Called when an item got a HIT response /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -57,9 +67,11 @@ void AcqTextStatus::IMSHit(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; + AssignItemID(Itm); clearLastLine(); - out << _("Hit ") << Itm.Description; + // TRANSLATOR: Very short word to be displayed before unchanged files in 'apt-get update' + ioprintf(out, _("Hit:%lu %s"), Itm.Owner->ID, Itm.Description.c_str()); out << std::endl; Update = true; } @@ -72,15 +84,16 @@ void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) Update = true; if (Itm.Owner->Complete == true) return; - - Itm.Owner->ID = ID++; + AssignItemID(Itm); if (Quiet > 1) return; clearLastLine(); - out << _("Get:") << Itm.Owner->ID << ' ' << Itm.Description; + // TRANSLATOR: Very short word to be displayed for files processed in 'apt-get update' + // Potentially replaced later by "Hit:", "Ign:" or "Err:" if something (bad) happens + ioprintf(out, _("Get:%lu %s"), Itm.Owner->ID, Itm.Description.c_str()); if (Itm.Owner->FileSize != 0) out << " [" << SizeToStr(Itm.Owner->FileSize) << "B]"; out << std::endl; @@ -89,9 +102,10 @@ void AcqTextStatus::Fetch(pkgAcquire::ItemDesc &Itm) // AcqTextStatus::Done - Completed a download /*{{{*/ // --------------------------------------------------------------------- /* We don't display anything... */ -void AcqTextStatus::Done(pkgAcquire::ItemDesc &/*Itm*/) +void AcqTextStatus::Done(pkgAcquire::ItemDesc &Itm) { Update = true; + AssignItemID(Itm); } /*}}}*/ // AcqTextStatus::Fail - Called when an item fails to download /*{{{*/ @@ -106,19 +120,25 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) return; + AssignItemID(Itm); clearLastLine(); if (Itm.Owner->Status == pkgAcquire::Item::StatDone) { - out << _("Ign ") << Itm.Description << std::endl; + // TRANSLATOR: Very short word to be displayed for files in 'apt-get update' + // which failed to download, but the error is ignored (compare "Err:") + ioprintf(out, _("Ign:%lu %s"), Itm.Owner->ID, Itm.Description.c_str()); if (Itm.Owner->ErrorText.empty() == false && _config->FindB("Acquire::Progress::Ignore::ShowErrorText", false) == true) - out << " " << Itm.Owner->ErrorText << std::endl; + out << std::endl << " " << Itm.Owner->ErrorText; + out << std::endl; } else { - out << _("Err ") << Itm.Description << std::endl; - out << " " << Itm.Owner->ErrorText << std::endl; + // TRANSLATOR: Very short word to be displayed for files in 'apt-get update' + // which failed to download and the error is critical (compare "Ign:") + ioprintf(out, _("Err:%lu %s"), Itm.Owner->ID, Itm.Description.c_str()); + out << std::endl << " " << Itm.Owner->ErrorText << std::endl; } Update = true; diff --git a/apt-private/acqprogress.h b/apt-private/acqprogress.h index 7cf990c65..cbb06fbec 100644 --- a/apt-private/acqprogress.h +++ b/apt-private/acqprogress.h @@ -23,7 +23,8 @@ class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus unsigned long ID; unsigned long Quiet; - void clearLastLine(); + APT_HIDDEN void clearLastLine(); + APT_HIDDEN void AssignItemID(pkgAcquire::ItemDesc &Itm); public: diff --git a/po/apt-all.pot b/po/apt-all.pot index b68d801ea..73b033876 100644 --- a/po/apt-all.pot +++ b/po/apt-all.pot @@ -1529,19 +1529,23 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " +#, c-format +msgid "Hit:%lu %s" msgstr "" #: apt-private/acqprogress.cc:88 -msgid "Get:" +#, c-format +msgid "Get:%lu %s" msgstr "" #: apt-private/acqprogress.cc:119 -msgid "Ign " +#, c-format +msgid "Ign:%lu %s" msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " +#, c-format +msgid "Err:%lu %s" msgstr "" #: apt-private/acqprogress.cc:150 diff --git a/po/ar.po b/po/ar.po index e2b179d0e..3e71fef80 100644 --- a/po/ar.po +++ b/po/ar.po @@ -1555,20 +1555,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " +#, c-format +msgid "Hit:%lu %s" msgstr "" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "جلب:" +#, c-format +msgid "Get:%lu %s" +msgstr "جلب:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "تجاهل" +#, c-format +msgid "Ign:%lu %s" +msgstr "تجاهل:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "خطأ" +#, c-format +msgid "Err:%lu %s" +msgstr "خطأ:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ast.po b/po/ast.po index 1efbbc1d2..1995c12f6 100644 --- a/po/ast.po +++ b/po/ast.po @@ -1684,20 +1684,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Oxe " +#, c-format +msgid "Hit:%lu %s" +msgstr "Oxe:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Des:" +#, c-format +msgid "Get:%lu %s" +msgstr "Des:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/bg.po b/po/bg.po index bbe6df3ae..7dff005e6 100644 --- a/po/bg.po +++ b/po/bg.po @@ -1720,20 +1720,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Поп " +#, c-format +msgid "Hit:%lu %s" +msgstr "Поп:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Изт:" +#, c-format +msgid "Get:%lu %s" +msgstr "Изт:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Игн " +#, c-format +msgid "Ign:%lu %s" +msgstr "Игн:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Грш " +#, c-format +msgid "Err:%lu %s" +msgstr "Грш:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/bs.po b/po/bs.po index 9cd1adc85..abb9a570a 100644 --- a/po/bs.po +++ b/po/bs.po @@ -1555,19 +1555,19 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " +msgid "Hit:%lu %s" msgstr "" #: apt-private/acqprogress.cc:88 -msgid "Get:" +msgid "Get:%lu %s" msgstr "" #: apt-private/acqprogress.cc:119 -msgid "Ign " +msgid "Ign:%lu %s" msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " +msgid "Err:%lu %s" msgstr "" #: apt-private/acqprogress.cc:150 diff --git a/po/ca.po b/po/ca.po index cdb3ceeb8..065ad0ea7 100644 --- a/po/ca.po +++ b/po/ca.po @@ -1708,20 +1708,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Obj " +#, c-format +msgid "Hit:%lu %s" +msgstr "Obj:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Bai:" +#, c-format +msgid "Get:%lu %s" +msgstr "Bai:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/cs.po b/po/cs.po index 76fc37b6b..3f6bcb4a7 100644 --- a/po/cs.po +++ b/po/cs.po @@ -1734,20 +1734,24 @@ msgid "Full Text Search" msgstr "Fulltextové hledání" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Cíl " +#, c-format +msgid "Hit:%lu %s" +msgstr "Cíl:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Mám:" +#, c-format +msgid "Get:%lu %s" +msgstr "Mám:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/cy.po b/po/cy.po index e29221cd1..b05bc7c59 100644 --- a/po/cy.po +++ b/po/cy.po @@ -1706,20 +1706,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Presennol " +#, c-format +msgid "Hit:%lu %s" +msgstr "Presennol:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Cyrchu:" +#, c-format +msgid "Get:%lu %s" +msgstr "Cyrchu:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Anwybyddu " +#, c-format +msgid "Ign:%lu %s" +msgstr "Anwybyddu:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Gwall " +#, c-format +msgid "Err:%lu %s" +msgstr "Gwall:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/da.po b/po/da.po index 53d3de059..d6b8e07a1 100644 --- a/po/da.po +++ b/po/da.po @@ -1749,20 +1749,24 @@ msgid "Full Text Search" msgstr "Fuldtekst-søgning" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Havde " +#, c-format +msgid "Hit:%lu %s" +msgstr "Havde:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Henter:" +#, c-format +msgid "Get:%lu %s" +msgstr "Henter:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ignorerer " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ignorerer:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Fejl " +#, c-format +msgid "Err:%lu %s" +msgstr "Fejl:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/de.po b/po/de.po index 85b0cb7ac..d4ca0d5a0 100644 --- a/po/de.po +++ b/po/de.po @@ -1810,20 +1810,24 @@ msgid "Full Text Search" msgstr "Volltextsuche" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "OK " +#, c-format +msgid "Hit:%lu %s" +msgstr "OK:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Holen: " +#, c-format +msgid "Get:%lu %s" +msgstr "Holen:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ign:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Fehl " +#, c-format +msgid "Err:%lu %s" +msgstr "Fehl:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/dz.po b/po/dz.po index 8d1e57b35..a4c50d245 100644 --- a/po/dz.po +++ b/po/dz.po @@ -1674,20 +1674,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "ཨེབ།" +#, c-format +msgid "Hit:%lu %s" +msgstr "ཨེབ།:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "ལེན:" +#, c-format +msgid "Get:%lu %s" +msgstr "ལེན:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "ཨེལ་ཇི་ཨེན:" +#, c-format +msgid "Ign:%lu %s" +msgstr "ཨེལ་ཇི་ཨེན:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "ཨི་ཨར་ཨར།" +#, c-format +msgid "Err:%lu %s" +msgstr "ཨི་ཨར་ཨར།:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/el.po b/po/el.po index e0750b61e..98e1f31c9 100644 --- a/po/el.po +++ b/po/el.po @@ -1695,20 +1695,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Hit " +#, c-format +msgid "Hit:%lu %s" +msgstr "Hit:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Φέρε:" +#, c-format +msgid "Get:%lu %s" +msgstr "Φέρε:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Αγνόησε " +#, c-format +msgid "Ign:%lu %s" +msgstr "Αγνόησε:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Σφάλμα " +#, c-format +msgid "Err:%lu %s" +msgstr "Σφάλμα:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/es.po b/po/es.po index e094ccafa..a2a9a71e9 100644 --- a/po/es.po +++ b/po/es.po @@ -1820,20 +1820,24 @@ msgid "Full Text Search" msgstr "Buscar en todo el texto" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Obj " +#, c-format +msgid "Hit:%lu %s" +msgstr "Obj:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Des:" +#, c-format +msgid "Get:%lu %s" +msgstr "Des:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/eu.po b/po/eu.po index e268f6059..f1e90411a 100644 --- a/po/eu.po +++ b/po/eu.po @@ -1678,20 +1678,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Atzituta " +#, c-format +msgid "Hit:%lu %s" +msgstr "Atzituta:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Hartu:" +#, c-format +msgid "Get:%lu %s" +msgstr "Hartu:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ez ikusi " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ez ikusi:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/fi.po b/po/fi.po index d58fb9b04..c40ed8e9e 100644 --- a/po/fi.po +++ b/po/fi.po @@ -1669,20 +1669,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Löytyi " +#, c-format +msgid "Hit:%lu %s" +msgstr "Löytyi:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Nouda:" +#, c-format +msgid "Get:%lu %s" +msgstr "Nouda:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Siv " +#, c-format +msgid "Ign:%lu %s" +msgstr "Siv:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Vrhe " +#, c-format +msgid "Err:%lu %s" +msgstr "Vrhe:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/fr.po b/po/fr.po index cb9d82856..ecb752f5e 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1774,20 +1774,24 @@ msgid "Full Text Search" msgstr "Recherche en texte intégral" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Atteint " +#, c-format +msgid "Hit:%lu %s" +msgstr "Atteint:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Réception de : " +#, c-format +msgid "Get:%lu %s" +msgstr "Réception de:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ign:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "Err:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/gl.po b/po/gl.po index d6bb1e92e..2adaa302a 100644 --- a/po/gl.po +++ b/po/gl.po @@ -1706,20 +1706,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Teño " +#, c-format +msgid "Hit:%lu %s" +msgstr "Teño:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Rcb:" +#, c-format +msgid "Get:%lu %s" +msgstr "Rcb:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/he.po b/po/he.po index b3ef8f831..ab7b50745 100644 --- a/po/he.po +++ b/po/he.po @@ -1188,19 +1188,23 @@ msgid "" msgstr "" #: cmdline/acqprogress.cc:55 -msgid "Hit " +#, c-format +msgid "Hit:%lu %s" msgstr "" #: cmdline/acqprogress.cc:79 -msgid "Get:" +#, c-format +msgid "Get:%lu %s" msgstr "" #: cmdline/acqprogress.cc:110 -msgid "Ign " +#, c-format +msgid "Ign:%lu %s" msgstr "" #: cmdline/acqprogress.cc:114 -msgid "Err " +#, c-format +msgid "Err:%lu %s" msgstr "" #: cmdline/acqprogress.cc:135 diff --git a/po/hu.po b/po/hu.po index 313f3a492..635184c75 100644 --- a/po/hu.po +++ b/po/hu.po @@ -1714,20 +1714,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Találat " +#, c-format +msgid "Hit:%lu %s" +msgstr "Találat:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Letöltés:" +#, c-format +msgid "Get:%lu %s" +msgstr "Letöltés:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Mellőz " +#, c-format +msgid "Ign:%lu %s" +msgstr "Mellőz:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Hiba " +#, c-format +msgid "Err:%lu %s" +msgstr "Hiba:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/it.po b/po/it.po index 36173e92c..178754c52 100644 --- a/po/it.po +++ b/po/it.po @@ -1766,21 +1766,24 @@ msgid "Full Text Search" msgstr "Ricerca sul testo" #: apt-private/acqprogress.cc:62 -msgid "Hit " -msgstr "Trovato " +#, c-format +msgid "Hit:%lu %s" +msgstr "Trovato:%lu %s" #: apt-private/acqprogress.cc:83 -msgid "Get:" -msgstr "Scaricamento di:" +#, c-format +msgid "Get:%lu %s" +msgstr "Scaricamento di:%lu %s" -# (ndt) questa non so cosa voglia dire #: apt-private/acqprogress.cc:113 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:120 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:143 #, c-format diff --git a/po/ja.po b/po/ja.po index 6c49f2608..f8f55f8aa 100644 --- a/po/ja.po +++ b/po/ja.po @@ -1750,20 +1750,24 @@ msgid "Full Text Search" msgstr "全文検索" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "ヒット " +#, c-format +msgid "Hit:%lu %s" +msgstr "ヒット:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "取得:" +#, c-format +msgid "Get:%lu %s" +msgstr "取得:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "無視 " +#, c-format +msgid "Ign:%lu %s" +msgstr "無視:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "エラー " +#, c-format +msgid "Err:%lu %s" +msgstr "エラー:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/km.po b/po/km.po index 26bfe4361..8c72865f8 100644 --- a/po/km.po +++ b/po/km.po @@ -1652,20 +1652,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "វាយ​" +#, c-format +msgid "Hit:%lu %s" +msgstr "វាយ​:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "យក​ ៖" +#, c-format +msgid "Get:%lu %s" +msgstr "យក​ ៖:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ko.po b/po/ko.po index 5479ab790..51cc27d61 100644 --- a/po/ko.po +++ b/po/ko.po @@ -1666,20 +1666,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "기존 " +#, c-format +msgid "Hit:%lu %s" +msgstr "기존:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "받기:" +#, c-format +msgid "Get:%lu %s" +msgstr "받기:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "무시" +#, c-format +msgid "Ign:%lu %s" +msgstr "무시:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "오류 " +#, c-format +msgid "Err:%lu %s" +msgstr "오류:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ku.po b/po/ku.po index c14ca94bd..540307937 100644 --- a/po/ku.po +++ b/po/ku.po @@ -1558,20 +1558,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " +#, c-format +msgid "Hit:%lu %s" msgstr "" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Anîn:" +#, c-format +msgid "Get:%lu %s" +msgstr "Anîn:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " +#, c-format +msgid "Ign:%lu %s" msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Çewt" +#, c-format +msgid "Err:%lu %s" +msgstr "Çewt:%lu %s" #: apt-private/acqprogress.cc:150 #, fuzzy, c-format diff --git a/po/lt.po b/po/lt.po index b85a0fbe1..1f485b28d 100644 --- a/po/lt.po +++ b/po/lt.po @@ -1577,20 +1577,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Imamas " +#, c-format +msgid "Hit:%lu %s" +msgstr "Imamas:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Gauti:" +#, c-format +msgid "Get:%lu %s" +msgstr "Gauti:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ignoruotas " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ignoruotas:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Klaida " +#, c-format +msgid "Err:%lu %s" +msgstr "Klaida:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/mr.po b/po/mr.po index 286c5d859..24e470cef 100644 --- a/po/mr.po +++ b/po/mr.po @@ -1656,20 +1656,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "दाबा" +#, c-format +msgid "Hit:%lu %s" +msgstr "दाबा:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "मिळवा:" +#, c-format +msgid "Get:%lu %s" +msgstr "मिळवा:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "आय.जी.एन." +#, c-format +msgid "Ign:%lu %s" +msgstr "आय.जी.एन.:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "दोष इ.आर.आर." +#, c-format +msgid "Err:%lu %s" +msgstr "दोष इ.आर.आर.:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/nb.po b/po/nb.po index 07247be4f..433e33909 100644 --- a/po/nb.po +++ b/po/nb.po @@ -1684,20 +1684,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Funnet " +#, c-format +msgid "Hit:%lu %s" +msgstr "Funnet:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Hent:" +#, c-format +msgid "Get:%lu %s" +msgstr "Hent:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ign:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Feil " +#, c-format +msgid "Err:%lu %s" +msgstr "Feil:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ne.po b/po/ne.po index 54dd771b4..4c6f2d098 100644 --- a/po/ne.po +++ b/po/ne.po @@ -1652,20 +1652,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "हान्नुहोस्" +#, c-format +msgid "Hit:%lu %s" +msgstr "हान्नुहोस्:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "प्राप्त गर्नुहोस्:" +#, c-format +msgid "Get:%lu %s" +msgstr "प्राप्त गर्नुहोस्:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/nl.po b/po/nl.po index 8d226dfef..5c774fe8d 100644 --- a/po/nl.po +++ b/po/nl.po @@ -1776,20 +1776,24 @@ msgid "Full Text Search" msgstr "Volledige tekst doorzoeken" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Geraakt " +#, c-format +msgid "Hit:%lu %s" +msgstr "Geraakt:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Ophalen:" +#, c-format +msgid "Get:%lu %s" +msgstr "Ophalen:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Genegeerd " +#, c-format +msgid "Ign:%lu %s" +msgstr "Genegeerd:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Fout " +#, c-format +msgid "Err:%lu %s" +msgstr "Fout:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/nn.po b/po/nn.po index b3622b6cd..0886c266a 100644 --- a/po/nn.po +++ b/po/nn.po @@ -1668,20 +1668,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Treff " +#, c-format +msgid "Hit:%lu %s" +msgstr "Treff:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Hent:" +#, c-format +msgid "Get:%lu %s" +msgstr "Hent:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ign:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Feil " +#, c-format +msgid "Err:%lu %s" +msgstr "Feil:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/pl.po b/po/pl.po index 0dda22a47..1851fa805 100644 --- a/po/pl.po +++ b/po/pl.po @@ -1749,22 +1749,26 @@ msgstr "" # Ujednolicono z aptitude #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Stary " +#, c-format +msgid "Hit:%lu %s" +msgstr "Stary:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Pobieranie:" +#, c-format +msgid "Get:%lu %s" +msgstr "Pobieranie:%lu %s" # Wyrównane do Hit i Err. #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign. " +#, c-format +msgid "Ign:%lu %s" +msgstr "" # Wyrównane do Hit i Ign. #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Błąd " +#, c-format +msgid "Err:%lu %s" +msgstr "Błąd:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/pt.po b/po/pt.po index a4b1105f8..4f05ada82 100644 --- a/po/pt.po +++ b/po/pt.po @@ -1718,20 +1718,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Hit " +#, c-format +msgid "Hit:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Obter:" +#, c-format +msgid "Get:%lu %s" +msgstr "Obter:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/pt_BR.po b/po/pt_BR.po index 0c4d92d02..5e2abd988 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -1687,20 +1687,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Atingido " +#, c-format +msgid "Hit:%lu %s" +msgstr "Atingido:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Obter:" +#, c-format +msgid "Get:%lu %s" +msgstr "Obter:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ro.po b/po/ro.po index 63df026ab..9b0a1494a 100644 --- a/po/ro.po +++ b/po/ro.po @@ -1695,20 +1695,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Atins " +#, c-format +msgid "Hit:%lu %s" +msgstr "Atins:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Luat:" +#, c-format +msgid "Get:%lu %s" +msgstr "Luat:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ignorat " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ignorat:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Eroare" +#, c-format +msgid "Err:%lu %s" +msgstr "Eroare:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/ru.po b/po/ru.po index 260bdd513..2028e5420 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1742,20 +1742,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "В кэше " +#, c-format +msgid "Hit:%lu %s" +msgstr "В кэше:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Получено:" +#, c-format +msgid "Get:%lu %s" +msgstr "Получено:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Игн " +#, c-format +msgid "Ign:%lu %s" +msgstr "Игн:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Ош " +#, c-format +msgid "Err:%lu %s" +msgstr "Ош:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/sk.po b/po/sk.po index 912d1fcf7..631ddd826 100644 --- a/po/sk.po +++ b/po/sk.po @@ -1716,20 +1716,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Už existuje " +#, c-format +msgid "Hit:%lu %s" +msgstr "Už existuje:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Získava sa:" +#, c-format +msgid "Get:%lu %s" +msgstr "Získava sa:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Chyba " +#, c-format +msgid "Err:%lu %s" +msgstr "Chyba:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/sl.po b/po/sl.po index 3210fa504..845fe3c5f 100644 --- a/po/sl.po +++ b/po/sl.po @@ -1717,20 +1717,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Zadetek " +#, c-format +msgid "Hit:%lu %s" +msgstr "Zadetek:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Dobi:" +#, c-format +msgid "Get:%lu %s" +msgstr "Dobi:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Prezr " +#, c-format +msgid "Ign:%lu %s" +msgstr "Prezr:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Nap " +#, c-format +msgid "Err:%lu %s" +msgstr "Nap:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/sv.po b/po/sv.po index 70f4b2d2d..52f65b598 100644 --- a/po/sv.po +++ b/po/sv.po @@ -1698,23 +1698,27 @@ msgstr "" # Måste vara tre bokstäver(?) # "Hit" = aktuell version är fortfarande giltig #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Bra " +#, c-format +msgid "Hit:%lu %s" +msgstr "Bra:%lu %s" # "Get:" = hämtar ny version #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Läs:" +#, c-format +msgid "Get:%lu %s" +msgstr "Läs:%lu %s" # "Ign" = hoppar över #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ign " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ign:%lu %s" # "Err" = fel vid hämtning #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Fel " +#, c-format +msgid "Err:%lu %s" +msgstr "Fel:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/th.po b/po/th.po index 147c3b8b8..60a468ea4 100644 --- a/po/th.po +++ b/po/th.po @@ -1696,20 +1696,24 @@ msgid "Full Text Search" msgstr "ค้นทั่วทั้งเนื้อความ" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "เจอ " +#, c-format +msgid "Hit:%lu %s" +msgstr "เจอ:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "ดึง:" +#, c-format +msgid "Get:%lu %s" +msgstr "ดึง:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "ข้าม " +#, c-format +msgid "Ign:%lu %s" +msgstr "ข้าม:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "ปัญหา " +#, c-format +msgid "Err:%lu %s" +msgstr "ปัญหา:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/tl.po b/po/tl.po index e3da79c8a..970b0b387 100644 --- a/po/tl.po +++ b/po/tl.po @@ -1677,20 +1677,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Tumama " +#, c-format +msgid "Hit:%lu %s" +msgstr "Tumama:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Kunin: " +#, c-format +msgid "Get:%lu %s" +msgstr "Kunin:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "DiPansin " +#, c-format +msgid "Ign:%lu %s" +msgstr "DiPansin:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Err " +#, c-format +msgid "Err:%lu %s" +msgstr "Err:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/tr.po b/po/tr.po index 5d9c3cee3..1e6f38903 100644 --- a/po/tr.po +++ b/po/tr.po @@ -1753,20 +1753,24 @@ msgid "Full Text Search" msgstr "Tam Metin Arama" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Bağlandı " +#, c-format +msgid "Hit:%lu %s" +msgstr "Bağlandı:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Alınıyor: " +#, c-format +msgid "Get:%lu %s" +msgstr "Alınıyor:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Yoksay " +#, c-format +msgid "Ign:%lu %s" +msgstr "Yoksay:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Hata " +#, c-format +msgid "Err:%lu %s" +msgstr "Hata:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/uk.po b/po/uk.po index faeedf941..47976d39c 100644 --- a/po/uk.po +++ b/po/uk.po @@ -1736,20 +1736,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "В кеші " +#, c-format +msgid "Hit:%lu %s" +msgstr "В кеші:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Отр:" +#, c-format +msgid "Get:%lu %s" +msgstr "Отр:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Ігн " +#, c-format +msgid "Ign:%lu %s" +msgstr "Ігн:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Пом " +#, c-format +msgid "Err:%lu %s" +msgstr "Пом:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/vi.po b/po/vi.po index 089d8461a..2edb52f22 100644 --- a/po/vi.po +++ b/po/vi.po @@ -1752,20 +1752,24 @@ msgid "Full Text Search" msgstr "Tìm kiếm toàn văn" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "Tìm thấy " +#, c-format +msgid "Hit:%lu %s" +msgstr "Tìm thấy:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "Lấy:" +#, c-format +msgid "Get:%lu %s" +msgstr "Lấy:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "Bỏq " +#, c-format +msgid "Ign:%lu %s" +msgstr "Bỏq:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "Lỗi " +#, c-format +msgid "Err:%lu %s" +msgstr "Lỗi:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/zh_CN.po b/po/zh_CN.po index 2ff5bcf01..6e9610ac9 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -1693,20 +1693,24 @@ msgid "Full Text Search" msgstr "全文搜索" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "命中 " +#, c-format +msgid "Hit:%lu %s" +msgstr "命中:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "获取:" +#, c-format +msgid "Get:%lu %s" +msgstr "获取:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "忽略 " +#, c-format +msgid "Ign:%lu %s" +msgstr "忽略:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "错误 " +#, c-format +msgid "Err:%lu %s" +msgstr "错误:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/po/zh_TW.po b/po/zh_TW.po index e35910df2..201d9d675 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -1646,20 +1646,24 @@ msgid "Full Text Search" msgstr "" #: apt-private/acqprogress.cc:66 -msgid "Hit " -msgstr "已有 " +#, c-format +msgid "Hit:%lu %s" +msgstr "已有:%lu %s" #: apt-private/acqprogress.cc:88 -msgid "Get:" -msgstr "下載:" +#, c-format +msgid "Get:%lu %s" +msgstr "下載:%lu %s" #: apt-private/acqprogress.cc:119 -msgid "Ign " -msgstr "略過 " +#, c-format +msgid "Ign:%lu %s" +msgstr "略過:%lu %s" #: apt-private/acqprogress.cc:126 -msgid "Err " -msgstr "錯誤 " +#, c-format +msgid "Err:%lu %s" +msgstr "錯誤:%lu %s" #: apt-private/acqprogress.cc:150 #, c-format diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index ffb9f3135..3465c0a16 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -49,8 +49,8 @@ testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists 'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 'http://localhost:8080/dists/unstable/main/Contents-amd64.bz2' localhost:8080_dists_unstable_main_Contents-amd64 0 " aptget update --print-uris -testsuccessequal "Hit http://localhost:8080 unstable InRelease -Get:1 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] +testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease +Get:2 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64' find rootdir/var/lib/apt/lists -name '*Contents*' @@ -74,8 +74,8 @@ testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists 'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 'http://localhost:8080/dists/unstable/main/Contents-amd64.gz.bz2' localhost:8080_dists_unstable_main_Contents-amd64.gz 0 " aptget update --print-uris -testsuccessequal "Hit http://localhost:8080 unstable InRelease -Get:1 http://localhost:8080 unstable/main amd64 Contents.gz [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] +testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease +Get:2 http://localhost:8080 unstable/main amd64 Contents.gz [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' @@ -89,7 +89,7 @@ testequal "'http://localhost:8080/dists/unstable/InRelease' localhost:8080_dists 'http://localhost:8080/dists/unstable/main/binary-amd64/Packages.bz2' localhost:8080_dists_unstable_main_binary-amd64_Packages 0 'http://localhost:8080/dists/unstable/main/i18n/Translation-en.bz2' localhost:8080_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris -testsuccessequal "Hit http://localhost:8080 unstable InRelease +testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease Reading package lists..." aptget update testempty find rootdir/var/lib/apt/lists -name '*Contents*' diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom index 6a218ffb8..108805daa 100755 --- a/test/integration/test-apt-cdrom +++ b/test/integration/test-apt-cdrom @@ -136,14 +136,14 @@ aptcache show testing -o Acquire::Languages=en | grep -q '^Description-en: ' && mv rootdir/media/cdrom-unmounted rootdir/media/cdrom-ejected msgmsg "ensure an update doesn't mess with cdrom sources" testsuccess aptget update -testfileequal rootdir/tmp/testsuccess.output 'Hit cdrom://Debian APT Testdisk 0.8.15 stable InRelease +testfileequal rootdir/tmp/testsuccess.output 'Hit:1 cdrom://Debian APT Testdisk 0.8.15 stable InRelease Reading package lists...' mv rootdir/media/cdrom-ejected rootdir/media/cdrom-unmounted testcdromusage msgmsg 'and again to check that it withstands the temptation even if it could mount' testsuccess aptget update -testfileequal rootdir/tmp/testsuccess.output 'Hit cdrom://Debian APT Testdisk 0.8.15 stable InRelease +testfileequal rootdir/tmp/testsuccess.output 'Hit:1 cdrom://Debian APT Testdisk 0.8.15 stable InRelease Reading package lists...' testcdromusage diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index 1f4a14e23..5b81d56d2 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -20,9 +20,9 @@ APTARCHIVE=$(readlink -f ./aptarchive) rm -f $APTARCHIVE/dists/unstable/*Release* # update without authenticated files leads to warning -testfailureequal "Ign file:$APTARCHIVE unstable InRelease +testfailureequal "Ign:1 file:$APTARCHIVE unstable InRelease File not found -Err file:$APTARCHIVE unstable Release +Err:2 file:$APTARCHIVE unstable Release File not found W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository. E: Use --allow-insecure-repositories to force the update" aptget update --no-allow-insecure-repositories @@ -36,13 +36,13 @@ filesize() { stat -c%s "$(aptget files --no-release-info --format '$(URI)' "Created-By: $1" | cut -d'/' -f 3- ).gz" } # allow override -testwarningequal "Ign file:$APTARCHIVE unstable InRelease +testwarningequal "Ign:1 file:$APTARCHIVE unstable InRelease File not found -Ign file:$APTARCHIVE unstable Release +Ign:2 file:$APTARCHIVE unstable Release File not found -Get:1 file:$APTARCHIVE unstable/main Sources [$(filesize 'Sources') B] -Get:2 file:$APTARCHIVE unstable/main i386 Packages [$(filesize 'Packages') B] -Get:3 file:$APTARCHIVE unstable/main Translation-en [$(filesize 'Translations') B] +Get:3 file:$APTARCHIVE unstable/main Sources [$(filesize 'Sources') B] +Get:4 file:$APTARCHIVE unstable/main i386 Packages [$(filesize 'Packages') B] +Get:5 file:$APTARCHIVE unstable/main Translation-en [$(filesize 'Translations') B] Reading package lists... W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." aptget update --allow-insecure-repositories # ensure we can not install the package diff --git a/test/integration/test-apt-update-ims b/test/integration/test-apt-update-ims index 7385e701a..2b662171c 100755 --- a/test/integration/test-apt-update-ims +++ b/test/integration/test-apt-update-ims @@ -43,7 +43,7 @@ runtest() { testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" # ensure that we still do a hash check for other files on ims hit of Release - if grep -q '^Hit .* InRelease$' expected.output || ! grep -q '^Ign .* Release\(\.gpg\)\?$' expected.output; then + if grep -q '^Hit:[0-9]\+ .* InRelease$' expected.output || ! grep -q '^Ign:[0-9]\+ .* Release\(\.gpg\)\?$' expected.output; then $TEST aptget update -o Debug::Acquire::gpgv=1 cp rootdir/tmp/${TEST}.output goodsign.output testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" @@ -55,7 +55,7 @@ runtest() { } msgmsg 'InRelease' -EXPECT='Hit http://localhost:8080 unstable InRelease +EXPECT='Hit:1 http://localhost:8080 unstable InRelease Reading package lists...' echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest @@ -63,9 +63,9 @@ echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest msgmsg 'Release/Release.gpg' -EXPECT='Ign http://localhost:8080 unstable InRelease +EXPECT='Ign:1 http://localhost:8080 unstable InRelease 404 Not Found -Hit http://localhost:8080 unstable Release +Hit:2 http://localhost:8080 unstable Release Reading package lists...' find aptarchive -name 'InRelease' -delete echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -74,10 +74,10 @@ echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest msgmsg 'Release only' -EXPECT="Ign http://localhost:8080 unstable InRelease +EXPECT="Ign:1 http://localhost:8080 unstable InRelease 404 Not Found -Hit http://localhost:8080 unstable Release -Ign http://localhost:8080 unstable Release.gpg +Hit:2 http://localhost:8080 unstable Release +Ign:3 http://localhost:8080 unstable Release.gpg 404 Not Found Reading package lists... W: The data from 'http://localhost:8080 unstable Release' is not signed. Packages from that repository can not be authenticated." @@ -96,7 +96,7 @@ Valid-Until: $(date -d '-1 weeks' '+%a, %d %b %Y %H:%M:%S %Z')" '{}' \; signreleasefiles msgmsg 'expired InRelease' -EXPECT='Hit http://localhost:8080 unstable InRelease +EXPECT='Hit:1 http://localhost:8080 unstable InRelease E: Release file for http://localhost:8080/dists/unstable/InRelease is expired (invalid since). Updates for this repository will not be applied.' echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'failure' @@ -104,9 +104,9 @@ echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'failure' msgmsg 'expired Release/Release.gpg' -EXPECT='Ign http://localhost:8080 unstable InRelease +EXPECT='Ign:1 http://localhost:8080 unstable InRelease 404 Not Found -Hit http://localhost:8080 unstable Release +Hit:2 http://localhost:8080 unstable Release E: Release file for http://localhost:8080/dists/unstable/Release is expired (invalid since). Updates for this repository will not be applied.' find aptarchive -name 'InRelease' -delete echo 'Acquire::GzipIndexes "0";' > rootdir/etc/apt/apt.conf.d/02compressindex @@ -115,10 +115,10 @@ echo 'Acquire::GzipIndexes "1";' > rootdir/etc/apt/apt.conf.d/02compressindex runtest 'failure' msgmsg 'expired Release only' -EXPECT="Ign http://localhost:8080 unstable InRelease +EXPECT="Ign:1 http://localhost:8080 unstable InRelease 404 Not Found -Hit http://localhost:8080 unstable Release -Ign http://localhost:8080 unstable Release.gpg +Hit:2 http://localhost:8080 unstable Release +Ign:3 http://localhost:8080 unstable Release.gpg 404 Not Found W: The data from 'http://localhost:8080 unstable Release' is not signed. Packages from that repository can not be authenticated. E: Release file for http://localhost:8080/dists/unstable/Release is expired (invalid since). Updates for this repository will not be applied." @@ -130,13 +130,13 @@ runtest 'failure' 'warning' msgmsg 'no Release at all' -EXPECT="Ign http://localhost:8080 unstable InRelease +EXPECT="Ign:1 http://localhost:8080 unstable InRelease 404 Not Found -Ign http://localhost:8080 unstable Release +Ign:2 http://localhost:8080 unstable Release 404 Not Found -Hit http://localhost:8080 unstable/main Sources -Hit http://localhost:8080 unstable/main amd64 Packages -Hit http://localhost:8080 unstable/main Translation-en +Hit:3 http://localhost:8080 unstable/main Sources +Hit:4 http://localhost:8080 unstable/main amd64 Packages +Hit:5 http://localhost:8080 unstable/main Translation-en Reading package lists... W: The repository 'http://localhost:8080 unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository." find aptarchive -name '*Release*' -delete diff --git a/test/integration/test-apt-update-not-modified b/test/integration/test-apt-update-not-modified index 32818658f..6d176a655 100755 --- a/test/integration/test-apt-update-not-modified +++ b/test/integration/test-apt-update-not-modified @@ -20,14 +20,14 @@ methodtest() { listcurrentlistsdirectory > listsdir.lst # hit again with a good cache - testsuccessequal "Hit $1 unstable InRelease + testsuccessequal "Hit:1 $1 unstable InRelease Reading package lists..." aptget update testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" # drop an architecture, which means the file should be gone now configarchitecture 'i386' sed '/_binary-amd64_Packages/ d' listsdir.lst > listsdir-without-amd64.lst - testsuccessequal "Hit $1 unstable InRelease + testsuccessequal "Hit:1 $1 unstable InRelease Reading package lists..." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" @@ -42,9 +42,9 @@ Architecture: amd64 Version: 1 EOF compressfile aptarchive/dists/unstable/main/binary-amd64/Packages - testfailureequal "Hit $1 unstable InRelease -Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] -Err $1 unstable/main amd64 Packages + testfailureequal "Hit:1 $1 unstable InRelease +Get:2 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] +Err:2 $1 unstable/main amd64 Packages Hash Sum mismatch W: Failed to fetch $1/dists/unstable/main/binary-amd64/Packages.gz Hash Sum mismatch @@ -54,8 +54,8 @@ E: Some index files failed to download. They have been ignored, or old ones used cp -a aptarchive/dists.good aptarchive/dists # … now everything is fine again - testsuccessequal "Hit $1 unstable InRelease -Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] + testsuccessequal "Hit:1 $1 unstable InRelease +Get:2 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] Reading package lists..." aptget update testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" @@ -74,18 +74,18 @@ Reading package lists..." aptget update listcurrentlistsdirectory > listsdir.lst # hit again with a good cache - testsuccessequal "Ign $1 unstable InRelease + testsuccessequal "Ign:1 $1 unstable InRelease 404 Not Found -Hit $1 unstable Release +Hit:2 $1 unstable Release Reading package lists..." aptget update testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" # drop an architecture, which means the file should be gone now configarchitecture 'i386' sed '/_binary-amd64_Packages/ d' listsdir.lst > listsdir-without-amd64.lst - testsuccessequal "Ign $1 unstable InRelease + testsuccessequal "Ign:1 $1 unstable InRelease 404 Not Found -Hit $1 unstable Release +Hit:2 $1 unstable Release Reading package lists..." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" @@ -100,11 +100,11 @@ Architecture: amd64 Version: 1 EOF compressfile aptarchive/dists/unstable/main/binary-amd64/Packages - testfailureequal "Ign $1 unstable InRelease + testfailureequal "Ign:1 $1 unstable InRelease 404 Not Found -Hit $1 unstable Release -Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] -Err $1 unstable/main amd64 Packages +Hit:2 $1 unstable Release +Get:4 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] +Err:4 $1 unstable/main amd64 Packages Hash Sum mismatch W: Failed to fetch $1/dists/unstable/main/binary-amd64/Packages.gz Hash Sum mismatch @@ -115,18 +115,18 @@ E: Some index files failed to download. They have been ignored, or old ones used find aptarchive/dists -name 'InRelease' -delete # … now everything is fine again - testsuccessequal "Ign $1 unstable InRelease + testsuccessequal "Ign:1 $1 unstable InRelease 404 Not Found -Hit $1 unstable Release -Get:1 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] +Hit:2 $1 unstable Release +Get:4 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable/main/binary-amd64/Packages.gz') B] Reading package lists..." aptget update testfileequal 'listsdir.lst' "$(listcurrentlistsdirectory)" webserverconfig 'aptwebserver::support::modified-since' 'false' webserverconfig 'aptwebserver::support::last-modified' 'false' - testsuccessequal "Ign $1 unstable InRelease + testsuccessequal "Ign:1 $1 unstable InRelease 404 Not Found -Get:1 $1 unstable Release [$(stat -c '%s' 'aptarchive/dists/unstable/Release') B] +Get:2 $1 unstable Release [$(stat -c '%s' 'aptarchive/dists/unstable/Release') B] Reading package lists..." aptget update webserverconfig 'aptwebserver::support::modified-since' 'true' webserverconfig 'aptwebserver::support::last-modified' 'true' diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index 3042d116d..47dd62712 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -13,7 +13,7 @@ setupflataptarchive testaptgetupdate() { rm -rf rootdir/var/lib/apt aptget update >testaptgetupdate.diff 2>&1 || true - sed -i -e '/Ign /,+1d' -e '/Release/ d' -e 's#Get:[0-9]\+ #Get: #' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff + sed -i -e '/Ign /,+1d' -e '/Release/ d' -e 's#\[[0-9]* [kMGTPY]*B\]#\[\]#' testaptgetupdate.diff GIVEN="$1" shift msgtest "Test for correctness of" "apt-get update with $*" @@ -47,12 +47,12 @@ testoverfile() { forcecompressor "$1" createemptyarchive 'Packages' - testaptgetupdate "Get: file:$APTARCHIVE Packages [] + testaptgetupdate "Get:2 file:$APTARCHIVE Packages [] Reading package lists..." "empty archive Packages.$COMPRESS over file" createemptyfile 'Packages' - testaptgetupdate "Get: file:$APTARCHIVE Packages -Err file:$APTARCHIVE Packages + testaptgetupdate "Get:2 file:$APTARCHIVE Packages +Err:2 file:$APTARCHIVE Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:${APTARCHIVE}/Packages.$COMPRESS Empty files can't be valid archives @@ -63,13 +63,13 @@ testoverhttp() { forcecompressor "$1" createemptyarchive 'Packages' - testaptgetupdate "Get: http://localhost:8080 Packages [] + testaptgetupdate "Get:2 http://localhost:8080 Packages [] Reading package lists..." "empty archive Packages.$COMPRESS over http" createemptyfile 'Packages' #FIXME: we should response with a good error message instead - testaptgetupdate "Get: http://localhost:8080 Packages -Err http://localhost:8080 Packages + testaptgetupdate "Get:2 http://localhost:8080 Packages +Err:2 http://localhost:8080 Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:$(readlink -f rootdir/var/lib/apt/lists/partial/localhost:8080_Packages.${COMPRESS}) Empty files can't be valid archives diff --git a/test/integration/test-bug-602412-dequote-redirect b/test/integration/test-bug-602412-dequote-redirect index ca2378c19..b9d232f90 100755 --- a/test/integration/test-bug-602412-dequote-redirect +++ b/test/integration/test-bug-602412-dequote-redirect @@ -21,7 +21,7 @@ testrun() { testsuccess --nomsg aptget update # check that I-M-S header is kept in redirections - testsuccessequal "Hit $1 unstable InRelease + testsuccessequal "Hit:1 $1 unstable InRelease Reading package lists..." aptget update msgtest 'Test redirection works in' 'package download' diff --git a/test/integration/test-pdiff-usage b/test/integration/test-pdiff-usage index 3295d5497..e5fe21e0f 100755 --- a/test/integration/test-pdiff-usage +++ b/test/integration/test-pdiff-usage @@ -98,7 +98,7 @@ SHA256-Download: msgmsg "Testcase: index is already up-to-date: $*" find rootdir/var/lib/apt/lists -name '*diff_Index' -type f -delete testsuccess aptget update "$@" - testequal 'Hit http://localhost:8080 InRelease + testequal 'Hit:1 http://localhost:8080 InRelease Reading package lists...' aptget update "$@" -o Debug::Acquire::Transaction=0 -o Debug::pkgAcquire::Diffs=0 testsuccessequal "$(cat ${PKGFILE}-new) " aptcache show apt newstuff diff --git a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum index 6abb5d12a..48a7f0562 100755 --- a/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum +++ b/test/integration/test-ubuntu-bug-1098738-apt-get-source-md5sum @@ -176,10 +176,10 @@ testmismatch() { Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080 $1 1.0 (dsc) [3 B] -Err http://localhost:8080 $1 1.0 (dsc) +Err:1 http://localhost:8080 $1 1.0 (dsc) Hash Sum mismatch Get:2 http://localhost:8080 $1 1.0 (tar) [3 B] -Err http://localhost:8080 $1 1.0 (tar) +Err:2 http://localhost:8080 $1 1.0 (tar) Hash Sum mismatch E: Failed to fetch http://localhost:8080/${1}_1.0.dsc Hash Sum mismatch @@ -242,7 +242,7 @@ Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080 pkg-mixed-sha1-bad 1.0 (tar) [3 B] Get:2 http://localhost:8080 pkg-mixed-sha1-bad 1.0 (dsc) [3 B] -Err http://localhost:8080 pkg-mixed-sha1-bad 1.0 (dsc) +Err:2 http://localhost:8080 pkg-mixed-sha1-bad 1.0 (dsc) Hash Sum mismatch E: Failed to fetch http://localhost:8080/pkg-mixed-sha1-bad_1.0.dsc Hash Sum mismatch @@ -253,7 +253,7 @@ testfailureequal 'Reading package lists... Building dependency tree... Need to get 6 B of source archives. Get:1 http://localhost:8080 pkg-mixed-sha2-bad 1.0 (tar) [3 B] -Err http://localhost:8080 pkg-mixed-sha2-bad 1.0 (tar) +Err:1 http://localhost:8080 pkg-mixed-sha2-bad 1.0 (tar) Hash Sum mismatch Get:2 http://localhost:8080 pkg-mixed-sha2-bad 1.0 (dsc) [3 B] E: Failed to fetch http://localhost:8080/pkg-mixed-sha2-bad_1.0.tar.gz Hash Sum mismatch -- cgit v1.2.3-70-g09d2 From 9d2a8a7388cf3b0bbbe92f6b0b30a533e1167f40 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 23:06:56 +0200 Subject: condense parallel requests with the same hashes to one It shouldn't be too common, but sometimes people have multiple mirrors in the sources or otherwise repositories with the same content. Now that we gracefully can handle multiple requests to the same URI, we can also fold multiple requests with the same expected hashes into one. Note that this isn't trying to find oppertunities for merging, but just merges if it happens to encounter the oppertunity for it. This is most obvious in the new testcase actually as it needs to delay the action to give the acquire system enough time to figure out that they can be merged. --- apt-pkg/acquire.cc | 5 +- apt-private/acqprogress.cc | 6 +- test/integration/framework | 8 ++- test/integration/skip-aptwebserver | 25 ------- .../test-acquire-same-file-multiple-times | 4 +- .../test-acquire-same-repository-multiple-times | 81 ++++++++++++++++++++++ test/integration/test-apt-get-source | 42 ++++++----- test/integration/test-apt-get-source-arch | 23 +++--- test/integration/test-apt-get-source-multisources | 12 ++-- .../integration/test-apt-get-update-unauth-warning | 37 +++++++++- test/integration/test-apt-progress-fd | 4 -- test/integration/test-apt-update-ims | 18 +++++ .../test-bug-722207-print-uris-even-if-very-quiet | 12 ++-- test/integration/test-bug-738785-switch-protocol | 22 +++--- 14 files changed, 198 insertions(+), 101 deletions(-) delete mode 100755 test/integration/skip-aptwebserver create mode 100755 test/integration/test-acquire-same-repository-multiple-times (limited to 'test') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 14c8863dc..34afab181 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -680,9 +680,12 @@ bool pkgAcquire::Queue::Enqueue(ItemDesc &Item) { QItem **I = &Items; // move to the end of the queue and check for duplicates here + HashStringList const hsl = Item.Owner->GetExpectedHashes(); for (; *I != 0; I = &(*I)->Next) - if (Item.URI == (*I)->URI) + if (Item.URI == (*I)->URI || hsl == (*I)->Owner->GetExpectedHashes()) { + if (_config->FindB("Debug::pkgAcquire::Worker",false) == true) + std::cerr << " @ Queue: Action combined for " << Item.URI << " and " << (*I)->URI << std::endl; (*I)->Owners.push_back(Item.Owner); Item.Owner->Status = (*I)->Owner->Status; return false; diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index dc92e3b2a..f6c3d1204 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -116,14 +116,10 @@ void AcqTextStatus::Fail(pkgAcquire::ItemDesc &Itm) if (Quiet > 1) return; - // Ignore certain kinds of transient failures (bad code) - if (Itm.Owner->Status == pkgAcquire::Item::StatIdle) - return; - AssignItemID(Itm); clearLastLine(); - if (Itm.Owner->Status == pkgAcquire::Item::StatDone) + if (Itm.Owner->Status == pkgAcquire::Item::StatDone || Itm.Owner->Status == pkgAcquire::Item::StatIdle) { // TRANSLATOR: Very short word to be displayed for files in 'apt-get update' // which failed to download, but the error is ignored (compare "Err:") diff --git a/test/integration/framework b/test/integration/framework index 1b99929e2..d8f7567d9 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -245,7 +245,7 @@ setupenvironment() { echo "Dir \"${TMPWORKINGDIRECTORY}/rootdir\";" > aptconfig.conf echo "Dir::state::status \"${TMPWORKINGDIRECTORY}/rootdir/var/lib/dpkg/status\";" >> aptconfig.conf echo "APT::Get::Show-User-Simulation-Note \"false\";" >> aptconfig.conf - echo "Dir::Bin::Methods \"${METHODSDIR}\";" >> aptconfig.conf + echo "Dir::Bin::Methods \"${TMPWORKINGDIRECTORY}/rootdir/usr/lib/apt/methods\";" >> aptconfig.conf # store apt-key were we can access it, even if we run it as a different user # destroys coverage reporting though, so just do it for root for now if [ "$(id -u)" = '0' ]; then @@ -786,6 +786,8 @@ insertsource() { local SPATH="aptarchive/dists/${RELEASE}/main/source" mkdir -p $SPATH local FILE="${SPATH}/Sources" + local DSCFILE="${NAME}_${VERSION}.dsc" + local TARFILE="${NAME}_${VERSION}.tar.gz" echo "Package: $NAME Binary: $NAME Version: $VERSION @@ -793,8 +795,8 @@ Maintainer: Joe Sixpack Architecture: $ARCH" >> $FILE test -z "$DEPENDENCIES" || echo "$DEPENDENCIES" >> $FILE echo "Files: - d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.dsc - d41d8cd98f00b204e9800998ecf8427e 0 ${NAME}_${VERSION}.tar.gz + $(echo -n "$DSCFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$DSCFILE" | wc -c) $DSCFILE + $(echo -n "$TARFILE" | md5sum | cut -d' ' -f 1) $(echo -n "$TARFILE" | wc -c) $TARFILE " >> $FILE } diff --git a/test/integration/skip-aptwebserver b/test/integration/skip-aptwebserver deleted file mode 100755 index 0622941ce..000000000 --- a/test/integration/skip-aptwebserver +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -set -e - -TESTDIR=$(readlink -f $(dirname $0)) -. $TESTDIR/framework - -setupenvironment -configarchitecture 'amd64' - -buildsimplenativepackage 'apt' 'all' '1.0' 'stable' - -setupaptarchive -changetowebserver - -rm -rf rootdir/var/lib/apt/lists -aptget update -qq -testequal 'Hit http://localhost stable InRelease -Hit http://localhost stable/main Sources -Hit http://localhost stable/main amd64 Packages -Hit http://localhost stable/main Translation-en -Reading package lists...' aptget update - -mv rootdir/var/lib/apt/lists/localhost* rootdir/var/lib/apt/lists/partial -aptget update - diff --git a/test/integration/test-acquire-same-file-multiple-times b/test/integration/test-acquire-same-file-multiple-times index d329a39cb..526765521 100755 --- a/test/integration/test-acquire-same-file-multiple-times +++ b/test/integration/test-acquire-same-file-multiple-times @@ -45,7 +45,7 @@ changetowebserver -o aptwebserver::redirect::replace::/foo2=/foo httpdown() { msgtest 'Downloading the same URI to different files' 'twice over http' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 + testsuccess --nomsg apthelper download-file http://localhost:8080/foo ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::http=1 cp rootdir/tmp/testsuccess.output download.log testsuccess cmp $TESTDIR/framework ./downloaded/foo1 testsuccess cmp ./downloaded/foo1 ./downloaded/foo2 @@ -57,7 +57,7 @@ testrun 'httpdown' httpredirectdown() { msgtest 'Redirect leads' 'first URI to the second URI' - testsuccess --nomsg apthelper download-file http://localhost:8080/foo2 ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 + testsuccess --nomsg apthelper download-file http://localhost:8080/foo2 ./downloaded/foo1 '' http://localhost:8080/foo ./downloaded/foo2 '' -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::http=1 cp rootdir/tmp/testsuccess.output download.log testsuccess cmp $TESTDIR/framework ./downloaded/foo1 testsuccess cmp ./downloaded/foo1 ./downloaded/foo2 diff --git a/test/integration/test-acquire-same-repository-multiple-times b/test/integration/test-acquire-same-repository-multiple-times new file mode 100755 index 000000000..bfeaf88db --- /dev/null +++ b/test/integration/test-acquire-same-repository-multiple-times @@ -0,0 +1,81 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +TESTFILE="$TESTDIR/framework" +cp $TESTFILE aptarchive/foo +APTARCHIVE="$(readlink -f ./aptarchive)" + +getcodenamefromsuite() { echo "jessie"; } +buildsimplenativepackage 'foo' 'all' '1.0' 'stable' +setupaptarchive --no-update +ln -s "${APTARCHIVE}/dists/stable" "${APTARCHIVE}/dists/jessie" +for FILE in rootdir/etc/apt/sources.list.d/*-stable-* ; do + sed 's#stable#jessie#g' $FILE > $(echo "$FILE" | sed 's#stable#jessie#g') +done + +# install a slowed down file: otherwise its to fast to reproduce combining +NEWMETHODS="$(readlink -f rootdir)/usr/lib/apt/methods" +OLDMETHODS="$(readlink -f rootdir/usr/lib/apt/methods)" +rm $NEWMETHODS +mkdir $NEWMETHODS +for METH in $(find $OLDMETHODS ! -type d); do + ln -s $OLDMETHODS/$(basename $METH) $NEWMETHODS +done +rm $NEWMETHODS/file +cat >$NEWMETHODS/file < file.lst + testequal "$(find $(readlink -f ./rootdir/var/lib/apt/lists) -name '*_dists_*' \( ! -name '*InRelease' \) -type f | sort)" cat file.lst + testsuccess aptcache policy + testequal "foo: + Installed: (none) + Candidate: 1.0 + Version table: + 1.0 0 + 500 $1:$2 jessie/main amd64 Packages + 500 $1:$2 stable/main amd64 Packages" aptcache policy foo + testfailure aptcache show foo/unstable + testsuccess aptcache show foo/stable + testsuccess aptcache show foo/jessie +} + +tworepos 'file' "$APTARCHIVE" 'no partial' +testequal '12' grep -c '200%20URI%20Start' ./download.log +testequal '12' grep -c '201%20URI%20Done' ./download.log +testequal '6' grep -c '^ @ Queue: Action combined' ./download.log +tworepos 'file' "$APTARCHIVE" 'hit' +testequal '6' grep -c '200%20URI%20Start' ./download.log +testequal '6' grep -c '201%20URI%20Done' ./download.log +testequal '0' grep -c '^ @ Queue: Action combined' ./download.log +rm -rf rootdir/var/lib/apt/lists + +changetowebserver + +tworepos 'http' '//localhost:8080' 'no partial' +testequal '10' grep -c '200%20URI%20Start' ./download.log +testequal '10' grep -c '201%20URI%20Done' ./download.log +testequal '6' grep -c '^ @ Queue: Action combined' ./download.log +tworepos 'http' '//localhost:8080' 'hit' +testequal '2' grep -c '200%20URI%20Start' ./download.log +testequal '4' grep -c '201%20URI%20Done' ./download.log +testequal '0' grep -c '^ @ Queue: Action combined' ./download.log +rm -rf rootdir/var/lib/apt/lists diff --git a/test/integration/test-apt-get-source b/test/integration/test-apt-get-source index 9db24370f..22f01b997 100755 --- a/test/integration/test-apt-get-source +++ b/test/integration/test-apt-get-source @@ -34,43 +34,40 @@ APTARCHIVE=$(readlink -f ./aptarchive) # normal operation gets highest version number HEADER="Reading package lists... Building dependency tree..." +DOWNLOAD1="Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 11 MD5Sum:b998e085e36cf162e6a33c2801318fef +'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 14 MD5Sum:d46b9a02af8487cbeb49165540c88184" +DOWNLOAD2="Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 11 MD5Sum:c0de572c6f8aa576c8ff78c81132ed55 +'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 14 MD5Sum:e10bb487c375b2b938d27bd31c2d1f5f" testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo +$DOWNLOAD2" aptget source -q --print-uris foo # select by release: suite testsuccessequal "$HEADER Selected version '1.0' (stable) for foo -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/stable +$DOWNLOAD1" aptget source -q --print-uris foo/stable testsuccessequal "$HEADER Selected version '2.0' (unstable) for foo -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/unstable +$DOWNLOAD2" aptget source -q --print-uris foo/unstable # select by release: codename testsuccessequal "$HEADER Selected version '2.0' (sid) for foo -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/sid +$DOWNLOAD2" aptget source -q --print-uris foo/sid # select by version testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo=1.0 +$DOWNLOAD1" aptget source -q --print-uris foo=1.0 # select by release with no binary package (Bug#731102) but ensure to get # highest version +DOWNLOAD01="Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 11 MD5Sum:0811a4d85238056c613ea897f49f01af +'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 14 MD5Sum:fa1ecb7a1a53e8e6f6551ca7db888a61" testsuccessequal "$HEADER Selected version '0.1' (wheezy) for foo -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo/wheezy +$DOWNLOAD01" aptget source -q --print-uris foo/wheezy # unavailable one testfailureequal "$HEADER @@ -78,11 +75,12 @@ E: Can not find version '9.9-not-there' of package 'foo' E: Unable to find a source package for foo" aptget source -q --print-uris foo=9.9-not-there # version and release +DOWNLOAD001="Need to get 0 B/29 B of source archives. +'file://${APTARCHIVE}/foo_0.0.1.dsc' foo_0.0.1.dsc 13 MD5Sum:6c819ebf0a21b1a480e1dbf6b8edfebd +'file://${APTARCHIVE}/foo_0.0.1.tar.gz' foo_0.0.1.tar.gz 16 MD5Sum:a3c7e1ac2159fc0faf522e110d6906fd" testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_0.0.1.dsc' foo_0.0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_0.0.1.tar.gz' foo_0.0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris -t unstable foo=0.0.1 +$DOWNLOAD001" aptget source -q --print-uris -t unstable foo=0.0.1 testsuccessequal "$HEADER -Need to get 0 B of source archives. +Need to get 0 B/25 B of source archives. Fetch source foo" aptget source -q -s foo diff --git a/test/integration/test-apt-get-source-arch b/test/integration/test-apt-get-source-arch index c75798209..f54bb6012 100755 --- a/test/integration/test-apt-get-source-arch +++ b/test/integration/test-apt-get-source-arch @@ -28,31 +28,30 @@ APTARCHIVE=$(readlink -f ./aptarchive) HEADER="Reading package lists... Building dependency tree..." +DOWNLOAD10="Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 11 MD5Sum:b998e085e36cf162e6a33c2801318fef +'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 14 MD5Sum:d46b9a02af8487cbeb49165540c88184" # pick :amd64 testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:amd64 +$DOWNLOAD10" aptget source -q --print-uris foo:amd64 # pick :i386 testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386 +Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_2.0.dsc' foo_2.0.dsc 11 MD5Sum:c0de572c6f8aa576c8ff78c81132ed55 +'file://${APTARCHIVE}/foo_2.0.tar.gz' foo_2.0.tar.gz 14 MD5Sum:e10bb487c375b2b938d27bd31c2d1f5f" aptget source -q --print-uris foo:i386 # pick :i386 by release testsuccessequal "$HEADER Selected version '0.1' (oldstable) for foo -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386/oldstable +Need to get 0 B/25 B of source archives. +'file://${APTARCHIVE}/foo_0.1.dsc' foo_0.1.dsc 11 MD5Sum:0811a4d85238056c613ea897f49f01af +'file://${APTARCHIVE}/foo_0.1.tar.gz' foo_0.1.tar.gz 14 MD5Sum:fa1ecb7a1a53e8e6f6551ca7db888a61" aptget source -q --print-uris foo:i386/oldstable # pick :i386 by version testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/foo_1.0.dsc' foo_1.0.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/foo_1.0.tar.gz' foo_1.0.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -q --print-uris foo:i386=1.0 +$DOWNLOAD10" aptget source -q --print-uris foo:i386=1.0 # error on unknown arch testfailureequal "$HEADER diff --git a/test/integration/test-apt-get-source-multisources b/test/integration/test-apt-get-source-multisources index 03d0400a0..887a30685 100755 --- a/test/integration/test-apt-get-source-multisources +++ b/test/integration/test-apt-get-source-multisources @@ -20,11 +20,11 @@ APTARCHIVE=$(readlink -f ./aptarchive) HEADER="Reading package lists... Building dependency tree..." testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/adduser_3.113+nmu3.dsc' adduser_3.113+nmu3.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/python-fll_0.9.11.dsc' python-fll_0.9.11.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -qdy --print-uris --dsc-only adduser=3.113 python-fll=0.9.11 +Need to get 0 B/43 B of source archives. +'file://${APTARCHIVE}/adduser_3.113+nmu3.dsc' adduser_3.113+nmu3.dsc 22 MD5Sum:255405ab5af211238ef53b7a1dd8ca4b +'file://${APTARCHIVE}/python-fll_0.9.11.dsc' python-fll_0.9.11.dsc 21 MD5Sum:740a9dbf02a295932f15b1415d0dc0df" aptget source -qdy --print-uris --dsc-only adduser=3.113 python-fll=0.9.11 testsuccessequal "$HEADER -Need to get 0 B of source archives. -'file://${APTARCHIVE}/python-fll_0.9.11.dsc' python-fll_0.9.11.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/adduser_3.113+nmu3.dsc' adduser_3.113+nmu3.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source -qdy --print-uris --dsc-only python-fll=0.9.11 adduser=3.113 +Need to get 0 B/43 B of source archives. +'file://${APTARCHIVE}/python-fll_0.9.11.dsc' python-fll_0.9.11.dsc 21 MD5Sum:740a9dbf02a295932f15b1415d0dc0df +'file://${APTARCHIVE}/adduser_3.113+nmu3.dsc' adduser_3.113+nmu3.dsc 22 MD5Sum:255405ab5af211238ef53b7a1dd8ca4b" aptget source -qdy --print-uris --dsc-only python-fll=0.9.11 adduser=3.113 diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index 5b81d56d2..fcabf244a 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -20,8 +20,10 @@ APTARCHIVE=$(readlink -f ./aptarchive) rm -f $APTARCHIVE/dists/unstable/*Release* # update without authenticated files leads to warning -testfailureequal "Ign:1 file:$APTARCHIVE unstable InRelease +testfailureequal "Get:1 file:$APTARCHIVE unstable InRelease +Ign:1 file:$APTARCHIVE unstable InRelease File not found +Get:2 file:$APTARCHIVE unstable Release Err:2 file:$APTARCHIVE unstable Release File not found W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release file. This is deprecated, please contact the owner of the repository. @@ -36,10 +38,41 @@ filesize() { stat -c%s "$(aptget files --no-release-info --format '$(URI)' "Created-By: $1" | cut -d'/' -f 3- ).gz" } # allow override -testwarningequal "Ign:1 file:$APTARCHIVE unstable InRelease +#aptget update --allow-insecure-repositories -o Debug::pkgAcquire::worker=1 +#exit +testwarningequal "Get:1 file:$APTARCHIVE unstable InRelease +Ign:1 file:$APTARCHIVE unstable InRelease File not found +Get:2 file:$APTARCHIVE unstable Release Ign:2 file:$APTARCHIVE unstable Release File not found +Get:3 file:$APTARCHIVE unstable/main Sources +Ign:3 file:$APTARCHIVE unstable/main Sources + File not found +Get:4 file:$APTARCHIVE unstable/main i386 Packages +Ign:4 file:$APTARCHIVE unstable/main i386 Packages + File not found +Get:5 file:$APTARCHIVE unstable/main Translation-en +Ign:5 file:$APTARCHIVE unstable/main Translation-en + File not found +Get:3 file:$APTARCHIVE unstable/main Sources +Ign:3 file:$APTARCHIVE unstable/main Sources + File not found +Get:4 file:$APTARCHIVE unstable/main i386 Packages +Ign:4 file:$APTARCHIVE unstable/main i386 Packages + File not found +Get:5 file:$APTARCHIVE unstable/main Translation-en +Ign:5 file:$APTARCHIVE unstable/main Translation-en + File not found +Get:3 file:$APTARCHIVE unstable/main Sources +Ign:3 file:$APTARCHIVE unstable/main Sources + File not found +Get:4 file:$APTARCHIVE unstable/main i386 Packages +Ign:4 file:$APTARCHIVE unstable/main i386 Packages + File not found +Get:5 file:$APTARCHIVE unstable/main Translation-en +Ign:5 file:$APTARCHIVE unstable/main Translation-en + File not found Get:3 file:$APTARCHIVE unstable/main Sources [$(filesize 'Sources') B] Get:4 file:$APTARCHIVE unstable/main i386 Packages [$(filesize 'Packages') B] Get:5 file:$APTARCHIVE unstable/main Translation-en [$(filesize 'Translations') B] diff --git a/test/integration/test-apt-progress-fd b/test/integration/test-apt-progress-fd index 99b4ea050..e30d503cb 100755 --- a/test/integration/test-apt-progress-fd +++ b/test/integration/test-apt-progress-fd @@ -16,7 +16,6 @@ setupaptarchive exec 3> apt-progress.log testsuccess aptget install testing=0.1 -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 -dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -33,7 +32,6 @@ pmstatus:dpkg-exec:83.3333:Running dpkg' exec 3> apt-progress.log testsuccess aptget install testing=0.8.15 -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 -dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -50,7 +48,6 @@ pmstatus:dpkg-exec:83.3333:Running dpkg' exec 3> apt-progress.log testsuccess aptget install testing=0.8.15 --reinstall -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 -dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing:0:Installing testing (amd64) @@ -77,7 +74,6 @@ pmstatus:dpkg-exec:75:Running dpkg' exec 3> apt-progress.log testsuccess aptget install testing2:i386 -y -o APT::Status-Fd=3 testfileequal './apt-progress.log' 'dlstatus:1:0:Retrieving file 1 of 1 -dlstatus:1:0:Retrieving file 1 of 1 dlstatus:1:20:Retrieving file 1 of 1 pmstatus:dpkg-exec:0:Running dpkg pmstatus:testing2:0:Installing testing2 (i386) diff --git a/test/integration/test-apt-update-ims b/test/integration/test-apt-update-ims index 2b662171c..33b4ed1b9 100755 --- a/test/integration/test-apt-update-ims +++ b/test/integration/test-apt-update-ims @@ -134,6 +134,24 @@ EXPECT="Ign:1 http://localhost:8080 unstable InRelease 404 Not Found Ign:2 http://localhost:8080 unstable Release 404 Not Found +Ign:3 http://localhost:8080 unstable/main Sources + 404 Not Found +Ign:4 http://localhost:8080 unstable/main amd64 Packages + 404 Not Found +Ign:5 http://localhost:8080 unstable/main Translation-en + 404 Not Found +Ign:3 http://localhost:8080 unstable/main Sources + 404 Not Found +Ign:4 http://localhost:8080 unstable/main amd64 Packages + 404 Not Found +Ign:5 http://localhost:8080 unstable/main Translation-en + 404 Not Found +Ign:3 http://localhost:8080 unstable/main Sources + 404 Not Found +Ign:4 http://localhost:8080 unstable/main amd64 Packages + 404 Not Found +Ign:5 http://localhost:8080 unstable/main Translation-en + 404 Not Found Hit:3 http://localhost:8080 unstable/main Sources Hit:4 http://localhost:8080 unstable/main amd64 Packages Hit:5 http://localhost:8080 unstable/main Translation-en diff --git a/test/integration/test-bug-722207-print-uris-even-if-very-quiet b/test/integration/test-bug-722207-print-uris-even-if-very-quiet index e51d72ccd..1fa94de7d 100755 --- a/test/integration/test-bug-722207-print-uris-even-if-very-quiet +++ b/test/integration/test-bug-722207-print-uris-even-if-very-quiet @@ -21,11 +21,11 @@ testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.d testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget dist-upgrade -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget install apt -qq --print-uris testsuccessequal "'file://${APTARCHIVE}/pool/main/apt/apt_2_all.deb' apt_2_all.deb 0 " aptget download apt -qq --print-uris -testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt -qq --print-uris +testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 9 MD5Sum:16ff470aaedad0f06fb951ed89ffdd3a +'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 12 MD5Sum:ab2b546f59ff9e8f5cc7a2d987ff3373" aptget source apt -qq --print-uris testsuccessequal "'http://metadata.ftp-master.debian.org/changelogs/main/a/apt/apt_2_changelog' apt.changelog" aptget changelog apt -qq --print-uris -testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/apt2_1.dsc' apt2_1.dsc 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e -'file://${APTARCHIVE}/apt2_1.tar.gz' apt2_1.tar.gz 0 MD5Sum:d41d8cd98f00b204e9800998ecf8427e" aptget source apt apt2 -qq --print-uris +testsuccessequal "'file://${APTARCHIVE}/apt_2.dsc' apt_2.dsc 9 MD5Sum:16ff470aaedad0f06fb951ed89ffdd3a +'file://${APTARCHIVE}/apt_2.tar.gz' apt_2.tar.gz 12 MD5Sum:ab2b546f59ff9e8f5cc7a2d987ff3373 +'file://${APTARCHIVE}/apt2_1.dsc' apt2_1.dsc 10 MD5Sum:4c572ce45f1e2bedbb30da7f5e1c241c +'file://${APTARCHIVE}/apt2_1.tar.gz' apt2_1.tar.gz 13 MD5Sum:2a96fec139f8722d93312a1ff8281232" aptget source apt apt2 -qq --print-uris diff --git a/test/integration/test-bug-738785-switch-protocol b/test/integration/test-bug-738785-switch-protocol index 539080200..e86f28824 100755 --- a/test/integration/test-bug-738785-switch-protocol +++ b/test/integration/test-bug-738785-switch-protocol @@ -39,18 +39,15 @@ cd - >/dev/null testsuccess aptget install apt -y testdpkginstalled 'apt' -# create a copy of all methods, expect https -eval `aptconfig shell METHODS Dir::Bin::Methods/d` -COPYMETHODS='usr/lib/apt/methods' -mv rootdir/${COPYMETHODS} rootdir/${COPYMETHODS}.bak -mkdir -p rootdir/$COPYMETHODS -cd rootdir/$COPYMETHODS -find $METHODS \! -type d | while read meth; do - ln -s $meth +# install a slowed down file: otherwise its to fast to reproduce combining +NEWMETHODS="$(readlink -f rootdir)/usr/lib/apt/methods" +OLDMETHODS="$(readlink -f rootdir/usr/lib/apt/methods)" +rm $NEWMETHODS +mkdir $NEWMETHODS +for METH in $(find $OLDMETHODS ! -type d); do + ln -s $OLDMETHODS/$(basename $METH) $NEWMETHODS done -rm https -cd - >/dev/null -echo "Dir::Bin::Methods \"${COPYMETHODS}\";" >> aptconfig.conf +rm $NEWMETHODS/https cd downloaded testfailureequal "E: The method driver $(readlink -f './../')/rootdir/usr/lib/apt/methods/https could not be found. @@ -59,8 +56,7 @@ testfailure test -e apt_1.0_all.deb cd - >/dev/null # revert to all methods -rm -rf rootdir/$COPYMETHODS -mv rootdir/${COPYMETHODS}.bak rootdir/${COPYMETHODS} +ln -s $OLDMETHODS/https $NEWMETHODS # check that downgrades from https to http are not allowed webserverconfig 'aptwebserver::support::http' 'true' -- cgit v1.2.3-70-g09d2 From 533fe3d13927798c17bdef84eba60ed9441d9608 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 15 Jun 2015 23:59:14 +0200 Subject: allow ratelimiting progress reporting for testcases Progress reports once in a while which is a bit to unpredictable for testcases, so we enforce a steady progress for them in the hope that this makes the tests (mostly test-apt-progress-fd) a bit more stable. Git-Dch: Ignore --- apt-pkg/acquire.cc | 14 ++++++++----- test/integration/framework | 23 ++++++++++++---------- .../test-acquire-same-repository-multiple-times | 2 +- 3 files changed, 23 insertions(+), 16 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 34afab181..5e5bec95c 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -955,7 +955,7 @@ std::string pkgAcquire::Queue::QItem::Custom600Headers() const /*{{{*/ // AcquireStatus::pkgAcquireStatus - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(0), Update(true), MorePulses(false) +pkgAcquireStatus::pkgAcquireStatus() : d(NULL), Percent(-1), Update(true), MorePulses(false) { Start(); } @@ -1054,13 +1054,17 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) Time = NewTime; } + double const OldPercent = Percent; // calculate the percentage, if we have too little data assume 1% if (TotalBytes > 0 && UnfetchedReleaseFiles) Percent = 0; - else + else // use both files and bytes because bytes can be unreliable - Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) + + Percent = (0.8 * (CurrentBytes/float(TotalBytes)*100.0) + 0.2 * (CurrentItems/float(TotalItems)*100.0)); + double const DiffPercent = Percent - OldPercent; + if (DiffPercent < 0.001 && _config->FindB("Acquire::Progress::Diffpercent", false) == true) + return true; int fd = _config->FindI("APT::Status-Fd",-1); if(fd > 0) @@ -1078,11 +1082,11 @@ bool pkgAcquireStatus::Pulse(pkgAcquire *Owner) snprintf(msg,sizeof(msg), _("Retrieving file %li of %li (%s remaining)"), i, TotalItems, TimeToStr(ETA).c_str()); else snprintf(msg,sizeof(msg), _("Retrieving file %li of %li"), i, TotalItems); - + // build the status str status << "dlstatus:" << i << ":" << std::setprecision(3) << Percent - << ":" << msg + << ":" << msg << endl; std::string const dlstatus = status.str(); diff --git a/test/integration/framework b/test/integration/framework index d8f7567d9..5d949009f 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -273,16 +273,19 @@ EOF chmod +x "${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg" echo "Dir::Bin::dpkg \"${TMPWORKINGDIRECTORY}/rootdir/usr/bin/dpkg\";" > rootdir/etc/apt/apt.conf.d/99dpkg - if ! command dpkg --assert-multi-arch >/dev/null 2>&1; then - echo "DPKG::options:: \"--force-architecture\";" >> aptconfig.conf # Added to test multiarch before dpkg is ready for it… - fi - echo 'quiet::NoUpdate "true";' >> aptconfig.conf - echo 'quiet::NoStatistic "true";' >> aptconfig.conf - # too distracting for users, but helpful to detect changes - echo 'Acquire::Progress::Ignore::ShowErrorText "true";' >> aptconfig.conf - # in testcases, it can appear as if localhost has a rotation setup, - # hide this as we can't really deal with it properly - echo 'Acquire::Failure::ShowIP "false";' >> aptconfig.conf + { + if ! command dpkg --assert-multi-arch >/dev/null 2>&1; then + echo "DPKG::options:: \"--force-architecture\";" # Added to test multiarch before dpkg is ready for it… + fi + echo 'quiet::NoUpdate "true";' + echo 'quiet::NoStatistic "true";' + # too distracting for users, but helpful to detect changes + echo 'Acquire::Progress::Ignore::ShowErrorText "true";' + echo 'Acquire::Progress::Diffpercent "true";' + # in testcases, it can appear as if localhost has a rotation setup, + # hide this as we can't really deal with it properly + echo 'Acquire::Failure::ShowIP "false";' + } >> aptconfig.conf cp "${TESTDIRECTORY}/apt.pem" "${TMPWORKINGDIRECTORY}/rootdir/etc/webserver.pem" if [ "$(id -u)" = '0' ]; then diff --git a/test/integration/test-acquire-same-repository-multiple-times b/test/integration/test-acquire-same-repository-multiple-times index bfeaf88db..a46e0d73c 100755 --- a/test/integration/test-acquire-same-repository-multiple-times +++ b/test/integration/test-acquire-same-repository-multiple-times @@ -32,7 +32,7 @@ cat >$NEWMETHODS/file < Date: Tue, 16 Jun 2015 16:22:46 +0200 Subject: add d-pointer, virtual destructors and de-inline de/constructors To have a chance to keep the ABI for a while we need all three to team up. One of them missing and we might loose, so ensuring that they are available is a very tedious but needed task once in a while. Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 11 +++- apt-pkg/acquire-item.h | 16 ++++-- apt-pkg/acquire-method.cc | 6 +- apt-pkg/acquire-method.h | 9 ++- apt-pkg/acquire-worker.h | 1 - apt-pkg/acquire.cc | 9 +++ apt-pkg/acquire.h | 10 +--- apt-pkg/algorithms.h | 6 +- apt-pkg/aptconfiguration.h | 21 ++++--- apt-pkg/cachefile.h | 1 - apt-pkg/cacheset.cc | 15 ++++- apt-pkg/cacheset.h | 24 +++++--- apt-pkg/cdrom.cc | 6 ++ apt-pkg/cdrom.h | 11 +++- apt-pkg/clean.cc | 1 + apt-pkg/clean.h | 2 + apt-pkg/deb/debindexfile.cc | 1 + apt-pkg/deb/debindexfile.h | 8 ++- apt-pkg/deb/debmetaindex.cc | 2 + apt-pkg/deb/debmetaindex.h | 3 +- apt-pkg/deb/debrecords.cc | 7 +++ apt-pkg/deb/debrecords.h | 15 +++-- apt-pkg/deb/debsrcrecords.cc | 4 ++ apt-pkg/deb/debsrcrecords.h | 4 +- apt-pkg/deb/debversion.h | 1 - apt-pkg/depcache.h | 6 +- apt-pkg/edsp.cc | 123 ++++++++++++++++++++-------------------- apt-pkg/edsp.h | 42 +++++--------- apt-pkg/edsp/edspindexfile.cc | 2 + apt-pkg/edsp/edspindexfile.h | 1 + apt-pkg/edsp/edsplistparser.cc | 2 + apt-pkg/edsp/edsplistparser.h | 2 + apt-pkg/edsp/edspsystem.h | 2 +- apt-pkg/indexcopy.cc | 10 ++++ apt-pkg/indexcopy.h | 23 ++++++-- apt-pkg/indexfile.cc | 3 + apt-pkg/indexfile.h | 6 +- apt-pkg/indexrecords.h | 3 - apt-pkg/install-progress.cc | 6 ++ apt-pkg/install-progress.h | 11 +++- apt-pkg/metaindex.h | 1 + apt-pkg/orderlist.h | 4 +- apt-pkg/packagemanager.h | 2 +- apt-pkg/pkgcache.cc | 2 + apt-pkg/pkgcache.h | 5 +- apt-pkg/pkgcachegen.cc | 3 + apt-pkg/pkgcachegen.h | 17 +++--- apt-pkg/pkgrecords.cc | 3 + apt-pkg/pkgrecords.h | 8 ++- apt-pkg/pkgsystem.cc | 2 + apt-pkg/pkgsystem.h | 5 +- apt-pkg/policy.cc | 2 + apt-pkg/policy.h | 5 +- apt-pkg/sourcelist.h | 4 +- apt-pkg/srcrecords.h | 1 - apt-pkg/tagfile.h | 2 - apt-pkg/version.cc | 3 + apt-pkg/version.h | 2 +- test/libapt/acqprogress_test.cc | 46 ++++++++------- 59 files changed, 348 insertions(+), 205 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 5460280ec..3313aaabc 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -438,7 +438,7 @@ APT_PURE pkgAcquire * pkgAcquire::Item::GetOwner() const /*{{{*/ return Owner; } /*}}}*/ -pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ +APT_CONST pkgAcquire::ItemDesc &pkgAcquire::Item::GetItemDesc() /*{{{*/ { return Desc; } @@ -1098,6 +1098,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ return true; } /*}}}*/ +pkgAcqMetaBase::~pkgAcqMetaBase() {} pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ IndexTarget const &ClearsignedTarget, @@ -1319,6 +1320,7 @@ std::string pkgAcqMetaIndex::DescURI() const /*{{{*/ return Target.URI; } /*}}}*/ +pkgAcqMetaIndex::~pkgAcqMetaIndex() {} // AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, @@ -1491,6 +1493,7 @@ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, { } /*}}}*/ +pkgAcqBaseIndex::~pkgAcqBaseIndex() {} // AcqDiffIndex::AcqDiffIndex - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -1893,6 +1896,7 @@ void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, / return; } /*}}}*/ +pkgAcqDiffIndex::~pkgAcqDiffIndex() {} // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -2119,6 +2123,7 @@ std::string pkgAcqIndexDiffs::Custom600Headers() const /*{{{*/ return patchhashes.str(); } /*}}}*/ +pkgAcqIndexDiffs::~pkgAcqIndexDiffs() {} // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, @@ -2263,6 +2268,7 @@ std::string pkgAcqIndexMergeDiffs::Custom600Headers() const /*{{{*/ return patchhashes.str(); } /*}}}*/ +pkgAcqIndexMergeDiffs::~pkgAcqIndexMergeDiffs() {} // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, @@ -2539,6 +2545,7 @@ void pkgAcqIndex::StageDecompressDone(string const &, return; } /*}}}*/ +pkgAcqIndex::~pkgAcqIndex() {} // AcqArchive::AcqArchive - Constructor /*{{{*/ @@ -2836,6 +2843,7 @@ std::string pkgAcqArchive::ShortDesc() const /*{{{*/ return Desc.ShortDesc; } /*}}}*/ +pkgAcqArchive::~pkgAcqArchive() {} // AcqChangelog::pkgAcqChangelog - Constructors /*{{{*/ pkgAcqChangelog::pkgAcqChangelog(pkgAcquire * const Owner, pkgCache::VerIterator const &Ver, @@ -3156,3 +3164,4 @@ string pkgAcqFile::Custom600Headers() const /*{{{*/ return ""; } /*}}}*/ +pkgAcqFile::~pkgAcqFile() {} diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 9dbacc1ea..df1380b5e 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-item.h,v 1.26.2.3 2004/01/02 18:51:00 mdz Exp $ /* ###################################################################### Acquire Item - Item to acquire @@ -345,6 +344,7 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ /** \brief baseclass for the indexes files to manage them all together */ { + void *d; protected: IndexTarget const Target; HashStringList GetExpectedHashesFor(std::string const MetaKey) const; @@ -380,7 +380,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ /** \brief the manager of a transaction */ { void *d; - protected: std::vector Transaction; @@ -478,6 +477,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ std::vector const IndexTargets, IndexTarget const &DataTarget, indexRecords* const MetaIndexParser); + virtual ~pkgAcqMetaBase(); }; /*}}}*/ /** \brief An item that is responsible for downloading the meta-index {{{ @@ -493,7 +493,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase { void *d; - protected: IndexTarget const DetachedSigTarget; @@ -513,6 +512,7 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, std::vector const IndexTargets, indexRecords * const MetaIndexParser); + virtual ~pkgAcqMetaIndex(); friend class pkgAcqMetaSig; }; @@ -589,6 +589,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqBaseIndex(); }; /*}}}*/ /** \brief An item that is responsible for fetching an index file of {{{ @@ -652,6 +653,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex */ pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqDiffIndex(); private: APT_HIDDEN void QueueOnIMSHit() const; }; @@ -751,6 +753,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target, DiffInfo const &patch, std::vector const * const allPatches); + virtual ~pkgAcqIndexMergeDiffs(); }; /*}}}*/ /** \brief An item that is responsible for fetching server-merge patches {{{ @@ -864,6 +867,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target, std::vector const &diffs=std::vector()); + virtual ~pkgAcqIndexDiffs(); }; /*}}}*/ /** \brief An acquire item that is responsible for fetching an index {{{ @@ -940,8 +944,10 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const Target); + virtual ~pkgAcqIndex(); - void Init(std::string const &URI, std::string const &URIDesc, + private: + APT_HIDDEN void Init(std::string const &URI, std::string const &URIDesc, std::string const &ShortDesc); }; /*}}}*/ @@ -1030,6 +1036,7 @@ class pkgAcqArchive : public pkgAcquire::Item pkgAcqArchive(pkgAcquire * const Owner,pkgSourceList * const Sources, pkgRecords * const Recs,pkgCache::VerIterator const &Version, std::string &StoreFilename); + virtual ~pkgAcqArchive(); }; /*}}}*/ /** \brief Retrieve the changelog for the given version {{{ @@ -1211,6 +1218,7 @@ class pkgAcqFile : public pkgAcquire::Item std::string const &Desc, std::string const &ShortDesc, std::string const &DestDir="", std::string const &DestFilename="", bool const IsIndexFile=false); + virtual ~pkgAcqFile(); }; /*}}}*/ /** @} */ diff --git a/apt-pkg/acquire-method.cc b/apt-pkg/acquire-method.cc index a8fc75f8e..d3aff4d5e 100644 --- a/apt-pkg/acquire-method.cc +++ b/apt-pkg/acquire-method.cc @@ -478,5 +478,9 @@ void pkgAcqMethod::Dequeue() { /*{{{*/ delete Tmp; } /*}}}*/ - pkgAcqMethod::~pkgAcqMethod() {} + +pkgAcqMethod::FetchItem::FetchItem() {} +pkgAcqMethod::FetchItem::~FetchItem() {} + +pkgAcqMethod::FetchResult::~FetchResult() {} diff --git a/apt-pkg/acquire-method.h b/apt-pkg/acquire-method.h index 6480eb4b5..f6659ef1f 100644 --- a/apt-pkg/acquire-method.h +++ b/apt-pkg/acquire-method.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-method.h,v 1.15.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Acquire Method - Method helper class + functions @@ -53,6 +52,11 @@ class pkgAcqMethod // for when we know it or a arbitrary limit when we don't know the // filesize (like a InRelease file) unsigned long long MaximumSize; + + FetchItem(); + virtual ~FetchItem(); + private: + void *d; }; struct FetchResult @@ -67,6 +71,9 @@ class pkgAcqMethod void TakeHashes(class Hashes &Hash); FetchResult(); + virtual ~FetchResult(); + private: + void *d; }; // State diff --git a/apt-pkg/acquire-worker.h b/apt-pkg/acquire-worker.h index 3a3ef706d..b8e8fefed 100644 --- a/apt-pkg/acquire-worker.h +++ b/apt-pkg/acquire-worker.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire-worker.h,v 1.12 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Acquire Worker - Worker process manager diff --git a/apt-pkg/acquire.cc b/apt-pkg/acquire.cc index 5e5bec95c..75df858a8 100644 --- a/apt-pkg/acquire.cc +++ b/apt-pkg/acquire.cc @@ -1143,6 +1143,15 @@ void pkgAcquireStatus::Fetched(unsigned long long Size,unsigned long long Resume } /*}}}*/ +pkgAcquire::UriIterator::UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0) +{ + while (CurItem == 0 && CurQ != 0) + { + CurItem = CurQ->Items; + CurQ = CurQ->Next; + } +} + APT_CONST pkgAcquire::UriIterator::~UriIterator() {} APT_CONST pkgAcquire::MethodConfig::~MethodConfig() {} APT_CONST pkgAcquireStatus::~pkgAcquireStatus() {} diff --git a/apt-pkg/acquire.h b/apt-pkg/acquire.h index 02031dafd..b7e6c68f1 100644 --- a/apt-pkg/acquire.h +++ b/apt-pkg/acquire.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: acquire.h,v 1.29.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Acquire - File Acquiration @@ -626,14 +625,7 @@ class pkgAcquire::UriIterator * * \param Q The queue over which this UriIterator should iterate. */ - UriIterator(pkgAcquire::Queue *Q) : d(NULL), CurQ(Q), CurItem(0) - { - while (CurItem == 0 && CurQ != 0) - { - CurItem = CurQ->Items; - CurQ = CurQ->Next; - } - } + UriIterator(pkgAcquire::Queue *Q); virtual ~UriIterator(); }; /*}}}*/ diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index 2ac28c0d7..dab844220 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: algorithms.h,v 1.10 2001/05/22 04:17:41 jgg Exp $ /* ###################################################################### Algorithms - A set of misc algorithms @@ -55,6 +54,7 @@ using std::ostream; class pkgSimulate : public pkgPackageManager /*{{{*/ { + void *d; protected: class Policy : public pkgDepCache::Policy @@ -88,7 +88,7 @@ private: public: pkgSimulate(pkgDepCache *Cache); - ~pkgSimulate(); + virtual ~pkgSimulate(); }; /*}}}*/ class pkgProblemResolver /*{{{*/ @@ -156,7 +156,7 @@ class pkgProblemResolver /*{{{*/ APT_DEPRECATED void InstallProtect(); pkgProblemResolver(pkgDepCache *Cache); - ~pkgProblemResolver(); + virtual ~pkgProblemResolver(); }; /*}}}*/ bool pkgApplyStatus(pkgDepCache &Cache); diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index c7b8d2d73..353843c3e 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -16,8 +16,7 @@ #include /*}}}*/ namespace APT { -class Configuration { /*{{{*/ -public: /*{{{*/ +namespace Configuration { /*{{{*/ /** \brief Returns a vector of usable Compression Types * * Files can be compressed in various ways to decrease the size of the @@ -39,7 +38,7 @@ public: /*{{{*/ * * \return a vector of the compression types in the preferred usage order */ - std::vector static const getCompressionTypes(bool const &Cached = true); + std::vector const getCompressionTypes(bool const &Cached = true); /** \brief Returns a vector of Language Codes * @@ -64,7 +63,7 @@ public: /*{{{*/ * * \return a vector of (all) Language Codes in the preferred usage order */ - std::vector static const getLanguages(bool const &All = false, + std::vector const getLanguages(bool const &All = false, bool const &Cached = true, char const ** const Locale = 0); /** \brief Are we interested in the given Language? @@ -73,7 +72,7 @@ public: /*{{{*/ * \param All defines if we check against all codes or only against used codes * \return true if we are interested, false otherwise */ - bool static checkLanguage(std::string Lang, bool const All = false); + bool checkLanguage(std::string Lang, bool const All = false); /** \brief Returns a vector of Architectures we support * @@ -82,14 +81,14 @@ public: /*{{{*/ * * \return a vector of Architectures in preferred order */ - std::vector static const getArchitectures(bool const &Cached = true); + std::vector const getArchitectures(bool const &Cached = true); /** \brief Are we interested in the given Architecture? * * \param Arch we want to check * \return true if we are interested, false otherwise */ - bool static checkArchitecture(std::string const &Arch); + bool checkArchitecture(std::string const &Arch); /** \brief Representation of supported compressors */ struct Compressor { @@ -113,15 +112,15 @@ public: /*{{{*/ * * \return a vector of Compressors */ - std::vector static const getCompressors(bool const Cached = true); + std::vector const getCompressors(bool const Cached = true); /** \brief Return a vector of extensions supported for data.tar's */ - std::vector static const getCompressorExtensions(); + std::vector const getCompressorExtensions(); /** \return Return a vector of enabled build profile specifications */ - std::vector static const getBuildProfiles(); + std::vector const getBuildProfiles(); /** \return Return a comma-separated list of enabled build profile specifications */ - std::string static const getBuildProfilesString(); + std::string const getBuildProfilesString(); /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h index 36b20893a..74a092593 100644 --- a/apt-pkg/cachefile.h +++ b/apt-pkg/cachefile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: cachefile.h,v 1.5 2002/04/27 04:28:04 jgg Exp $ /* ###################################################################### CacheFile - Simple wrapper class for opening, generating and whatnot diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index 0ad99713a..c42f76112 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -37,7 +37,6 @@ #include /*}}}*/ namespace APT { - // PackageFrom - selecting the appropriate method for package selection /*{{{*/ bool CacheSetHelper::PackageFrom(enum PkgSelector const select, PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern) { @@ -812,4 +811,18 @@ APT_CONST void CacheSetHelper::showSelectedVersion(pkgCache::PkgIterator const & bool const /*verIsRel*/) { } /*}}}*/ + +CacheSetHelper::CacheSetHelper(bool const ShowError, GlobalError::MsgType ErrorType) : + ShowError(ShowError), ErrorType(ErrorType) {} +CacheSetHelper::~CacheSetHelper() {} + +PackageContainerInterface::PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {} +PackageContainerInterface::PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {} +PackageContainerInterface::~PackageContainerInterface() {} + +PackageUniverse::PackageUniverse(pkgCache * const Owner) : _cont(Owner) { } +PackageUniverse::~PackageUniverse() {} + +VersionContainerInterface::VersionContainerInterface() {} +VersionContainerInterface::~VersionContainerInterface() {} } diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 97aee8c2d..1a6feb5f7 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -50,9 +50,8 @@ class CacheSetHelper { /*{{{*/ */ public: /*{{{*/ CacheSetHelper(bool const ShowError = true, - GlobalError::MsgType ErrorType = GlobalError::ERROR) : - ShowError(ShowError), ErrorType(ErrorType) {} - virtual ~CacheSetHelper() {} + GlobalError::MsgType ErrorType = GlobalError::ERROR); + virtual ~CacheSetHelper(); enum PkgSelector { UNKNOWN, REGEX, TASK, FNMATCH, PACKAGENAME, STRING }; @@ -203,6 +202,8 @@ protected: bool PackageFromFnmatch(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromPackageName(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern); bool PackageFromString(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string const &pattern); +private: + void *d; }; /*}}}*/ class PackageContainerInterface { /*{{{*/ @@ -263,8 +264,9 @@ APT_IGNORE_DEPRECATED_POP void setConstructor(CacheSetHelper::PkgSelector const by) { ConstructedBy = by; } CacheSetHelper::PkgSelector getConstructor() const { return ConstructedBy; } - PackageContainerInterface() : ConstructedBy(CacheSetHelper::UNKNOWN) {} - PackageContainerInterface(CacheSetHelper::PkgSelector const by) : ConstructedBy(by) {} + PackageContainerInterface(); + PackageContainerInterface(CacheSetHelper::PkgSelector const by); + virtual ~PackageContainerInterface(); APT_DEPRECATED static bool FromTask(PackageContainerInterface * const pci, pkgCacheFile &Cache, std::string pattern, CacheSetHelper &helper) { return helper.PackageFrom(CacheSetHelper::TASK, pci, Cache, pattern); } @@ -292,6 +294,7 @@ APT_IGNORE_DEPRECATED_POP private: CacheSetHelper::PkgSelector ConstructedBy; + void *d; }; /*}}}*/ template class PackageContainer : public PackageContainerInterface {/*{{{*/ @@ -355,7 +358,7 @@ public: /*{{{*/ iterator end() { return iterator(_cont.end()); } const_iterator find(pkgCache::PkgIterator const &P) const { return const_iterator(_cont.find(P)); } - PackageContainer() : PackageContainerInterface() {} + PackageContainer() : PackageContainerInterface(CacheSetHelper::UNKNOWN) {} PackageContainer(CacheSetHelper::PkgSelector const &by) : PackageContainerInterface(by) {} APT_IGNORE_DEPRECATED_PUSH APT_DEPRECATED PackageContainer(Constructor const &by) : PackageContainerInterface((CacheSetHelper::PkgSelector)by) {} @@ -552,6 +555,7 @@ template<> template inline bool PackageContainerPkgBegin(); } APT_PUBLIC iterator end() { return _cont->PkgEnd(); } - APT_PUBLIC PackageUniverse(pkgCache * const Owner) : _cont(Owner) { } + APT_PUBLIC PackageUniverse(pkgCache * const Owner); + APT_PUBLIC virtual ~PackageUniverse(); private: bool insert(pkgCache::PkgIterator const &) { return true; } @@ -701,6 +706,11 @@ APT_IGNORE_DEPRECATED_PUSH } APT_IGNORE_DEPRECATED_POP + VersionContainerInterface(); + virtual ~VersionContainerInterface(); +private: + void *d; + protected: /*{{{*/ /** \brief returns the candidate version of the package diff --git a/apt-pkg/cdrom.cc b/apt-pkg/cdrom.cc index 8cec4b78e..de5cd0657 100644 --- a/apt-pkg/cdrom.cc +++ b/apt-pkg/cdrom.cc @@ -1022,3 +1022,9 @@ pkgUdevCdromDevices::~pkgUdevCdromDevices() /*{{{*/ dlclose(libudev_handle); } /*}}}*/ + +pkgCdromStatus::pkgCdromStatus() : totalSteps(0) {} +pkgCdromStatus::~pkgCdromStatus() {} + +pkgCdrom::pkgCdrom() {} +pkgCdrom::~pkgCdrom() {} diff --git a/apt-pkg/cdrom.h b/apt-pkg/cdrom.h index bd0902176..5626b5059 100644 --- a/apt-pkg/cdrom.h +++ b/apt-pkg/cdrom.h @@ -18,12 +18,13 @@ class OpProgress; class pkgCdromStatus /*{{{*/ { + void *d; protected: int totalSteps; public: - pkgCdromStatus() : totalSteps(0) {}; - virtual ~pkgCdromStatus() {}; + pkgCdromStatus(); + virtual ~pkgCdromStatus(); // total steps virtual void SetTotal(int total) { totalSteps = total; }; @@ -74,7 +75,12 @@ class pkgCdrom /*{{{*/ bool Ident(std::string &ident, pkgCdromStatus *log); bool Add(pkgCdromStatus *log); + pkgCdrom(); + virtual ~pkgCdrom(); + private: + void *d; + APT_HIDDEN bool MountAndIdentCDROM(Configuration &Database, std::string &CDROM, std::string &ident, pkgCdromStatus * const log, bool const interactive); APT_HIDDEN bool UnmountCDROM(std::string const &CDROM, pkgCdromStatus * const log); @@ -92,6 +98,7 @@ struct CdromDevice /*{{{*/ /*}}}*/ class pkgUdevCdromDevices /*{{{*/ { + void *d; protected: // libudev dlopen structure void *libudev_handle; diff --git a/apt-pkg/clean.cc b/apt-pkg/clean.cc index 0fca60ba9..d05ae83b9 100644 --- a/apt-pkg/clean.cc +++ b/apt-pkg/clean.cc @@ -132,4 +132,5 @@ bool pkgArchiveCleaner::Go(std::string Dir,pkgCache &Cache) } /*}}}*/ +pkgArchiveCleaner::pkgArchiveCleaner() {} APT_CONST pkgArchiveCleaner::~pkgArchiveCleaner() {} diff --git a/apt-pkg/clean.h b/apt-pkg/clean.h index 466cb67a9..a1495702b 100644 --- a/apt-pkg/clean.h +++ b/apt-pkg/clean.h @@ -30,6 +30,8 @@ class pkgArchiveCleaner public: bool Go(std::string Dir,pkgCache &Cache); + + pkgArchiveCleaner(); virtual ~pkgArchiveCleaner(); }; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 944cbe0bf..0fffa52b0 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -576,3 +576,4 @@ debTranslationsIndex::~debTranslationsIndex() {} debSourcesIndex::~debSourcesIndex() {} debDebPkgFileIndex::~debDebPkgFileIndex() {} +debDscFileIndex::~debDscFileIndex() {} diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 6b8c78e5a..6285a9e5c 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debindexfile.h,v 1.3.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Debian Index Files @@ -30,6 +29,7 @@ class pkgCacheGenerator; class APT_HIDDEN debStatusIndex : public pkgIndexFile { + void *d; protected: std::string File; @@ -53,6 +53,7 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -71,6 +72,7 @@ class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -86,6 +88,7 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile { + void *d; public: virtual const Type *GetType() const APT_CONST; @@ -145,6 +148,7 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile class APT_HIDDEN debDscFileIndex : public pkgIndexFile { private: + void *d; std::string DscFile; public: virtual const Type *GetType() const APT_CONST; @@ -157,7 +161,7 @@ class APT_HIDDEN debDscFileIndex : public pkgIndexFile }; debDscFileIndex(std::string &DscFile); - virtual ~debDscFileIndex() {}; + virtual ~debDscFileIndex(); }; class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index b328fcea8..34fc98838 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -459,6 +459,8 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool con } /*}}}*/ +debDebFileMetaIndex::~debDebFileMetaIndex() {} + class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type { protected: diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index b448ecc53..f2706e08a 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -75,6 +75,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { class APT_HIDDEN debDebFileMetaIndex : public metaIndex { private: + void *d; std::string DebFile; debDebPkgFileIndex *DebIndex; public: @@ -94,7 +95,7 @@ class APT_HIDDEN debDebFileMetaIndex : public metaIndex return true; } debDebFileMetaIndex(std::string const &DebFile); - virtual ~debDebFileMetaIndex() {}; + virtual ~debDebFileMetaIndex(); }; diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 335bcfda0..f527042e4 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -51,6 +51,7 @@ bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) /*}}}*/ debRecordParser::~debRecordParser() {} +debRecordParserBase::debRecordParserBase() : Parser() {} // RecordParserBase::FileName - Return the archive filename on the site /*{{{*/ string debRecordParserBase::FileName() { @@ -207,3 +208,9 @@ bool debDebFileRecordParser::LoadContent() return _error->Error(_("Unable to parse package file %s (%d)"), debFileName.c_str(), 3); return true; } +bool debDebFileRecordParser::Jump(pkgCache::VerFileIterator const &) { return LoadContent(); } +bool debDebFileRecordParser::Jump(pkgCache::DescFileIterator const &) { return LoadContent(); } +std::string debDebFileRecordParser::FileName() { return debFileName; } + +debDebFileRecordParser::debDebFileRecordParser(std::string FileName) : debRecordParserBase(), debFileName(FileName) {} +debDebFileRecordParser::~debDebFileRecordParser() {} diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 38e071940..8efcec8cd 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -27,6 +27,7 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser { + void *d; protected: pkgTagSection Section; @@ -50,12 +51,13 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser virtual void GetRec(const char *&Start,const char *&Stop); - debRecordParserBase() : Parser() {} + debRecordParserBase(); virtual ~debRecordParserBase(); }; class APT_HIDDEN debRecordParser : public debRecordParserBase { + void *d; protected: FileFd File; pkgTagFile Tags; @@ -71,20 +73,21 @@ class APT_HIDDEN debRecordParser : public debRecordParserBase // custom record parser that reads deb files directly class APT_HIDDEN debDebFileRecordParser : public debRecordParserBase { + void *d; std::string debFileName; std::string controlContent; APT_HIDDEN bool LoadContent(); protected: // single file files, so no jumping whatsoever - bool Jump(pkgCache::VerFileIterator const &) { return LoadContent(); } - bool Jump(pkgCache::DescFileIterator const &) { return LoadContent(); } + bool Jump(pkgCache::VerFileIterator const &); + bool Jump(pkgCache::DescFileIterator const &); public: - virtual std::string FileName() { return debFileName; } + virtual std::string FileName(); - debDebFileRecordParser(std::string FileName) - : debRecordParserBase(), debFileName(FileName) {}; + debDebFileRecordParser(std::string FileName); + virtual ~debDebFileRecordParser(); }; #endif diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index ca6d09896..21a4ff8ea 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -32,6 +32,10 @@ using std::max; using std::string; +debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) + : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), + iOffset(0), Buffer(NULL) {} + // SrcRecordParser::Binaries - Return the binaries field /*{{{*/ // --------------------------------------------------------------------- /* This member parses the binaries field into a pair of class arrays and diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index cd246d624..7aeb2db88 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -56,9 +56,7 @@ class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser virtual bool Files(std::vector &F); bool Files2(std::vector &F); - debSrcRecordParser(std::string const &File,pkgIndexFile const *Index) - : Parser(Index), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400), - iOffset(0), Buffer(NULL) {} + debSrcRecordParser(std::string const &File,pkgIndexFile const *Index); virtual ~debSrcRecordParser(); }; diff --git a/apt-pkg/deb/debversion.h b/apt-pkg/deb/debversion.h index 434ff4a2e..7befe6372 100644 --- a/apt-pkg/deb/debversion.h +++ b/apt-pkg/deb/debversion.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: debversion.h,v 1.3 2001/05/03 05:25:04 jgg Exp $ /* ###################################################################### Debian Version - Versioning system for Debian diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 20d263c67..94c1088f2 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -1,6 +1,5 @@ // -*- mode: c++; mode: fold -*- // Description /*{{{*/ -// $Id: depcache.h,v 1.14 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### DepCache - Dependency Extension data for the cache @@ -164,6 +163,7 @@ class pkgDepCache : protected pkgCache::Namespace */ class ActionGroup { + void *d; pkgDepCache &cache; bool released; @@ -192,7 +192,7 @@ class pkgDepCache : protected pkgCache::Namespace * If this is the last action group, the automatic cache * cleanup operations will be undertaken. */ - ~ActionGroup(); + virtual ~ActionGroup(); }; /** \brief Returns \b true for packages matching a regular @@ -503,6 +503,8 @@ class pkgDepCache : protected pkgCache::Namespace bool const rPurge, unsigned long const Depth, bool const FromUser); private: + void *d; + APT_HIDDEN bool IsModeChangeOk(ModeList const mode, PkgIterator const &Pkg, unsigned long const Depth, bool const FromUser); }; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 41cc2cdfe..25d53747c 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -39,60 +39,15 @@ using std::string; // we could use pkgCache::DepType and ::Priority, but these would be localized strings… -const char * const EDSP::PrioMap[] = {0, "important", "required", "standard", +const char * const PrioMap[] = {0, "important", "required", "standard", "optional", "extra"}; -const char * const EDSP::DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", +const char * const DepMap[] = {"", "Depends", "Pre-Depends", "Suggests", "Recommends" , "Conflicts", "Replaces", "Obsoletes", "Breaks", "Enhances"}; -// EDSP::WriteScenario - to the given file descriptor /*{{{*/ -bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) -{ - if (Progress != NULL) - Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); - unsigned long p = 0; - std::vector archs = APT::Configuration::getArchitectures(); - for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) - { - std::string const arch = Pkg.Arch(); - if (std::find(archs.begin(), archs.end(), arch) == archs.end()) - continue; - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) - { - WriteScenarioVersion(Cache, output, Pkg, Ver); - WriteScenarioDependency(output, Ver); - fprintf(output, "\n"); - if (Progress != NULL && p % 100 == 0) - Progress->Progress(p); - } - } - return true; -} - /*}}}*/ -// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ -bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, - APT::PackageSet const &pkgset, - OpProgress *Progress) -{ - if (Progress != NULL) - Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); - unsigned long p = 0; - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p) - for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) - { - WriteScenarioVersion(Cache, output, Pkg, Ver); - WriteScenarioLimitedDependency(output, Ver, pkgset); - fprintf(output, "\n"); - if (Progress != NULL && p % 100 == 0) - Progress->Progress(p); - } - if (Progress != NULL) - Progress->Done(); - return true; -} - /*}}}*/ -// EDSP::WriteScenarioVersion /*{{{*/ -void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, + +// WriteScenarioVersion /*{{{*/ +static void WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { fprintf(output, "Package: %s\n", Pkg.Name()); @@ -147,8 +102,8 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI fprintf(output, "APT-Automatic: yes\n"); } /*}}}*/ -// EDSP::WriteScenarioDependency /*{{{*/ -void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver) +// WriteScenarioDependency /*{{{*/ +static void WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &Ver) { std::string dependencies[pkgCache::Dep::Enhances + 1]; bool orGroup = false; @@ -183,8 +138,8 @@ void EDSP::WriteScenarioDependency( FILE* output, pkgCache::VerIterator const &V fprintf(output, "Provides: %s\n", provides.c_str()+2); } /*}}}*/ -// EDSP::WriteScenarioLimitedDependency /*{{{*/ -void EDSP::WriteScenarioLimitedDependency(FILE* output, +// WriteScenarioLimitedDependency /*{{{*/ +static void WriteScenarioLimitedDependency(FILE* output, pkgCache::VerIterator const &Ver, APT::PackageSet const &pkgset) { @@ -235,6 +190,52 @@ void EDSP::WriteScenarioLimitedDependency(FILE* output, fprintf(output, "Provides: %s\n", provides.c_str()+2); } /*}}}*/ +// EDSP::WriteScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress) +{ + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; + std::vector archs = APT::Configuration::getArchitectures(); + for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg) + { + std::string const arch = Pkg.Arch(); + if (std::find(archs.begin(), archs.end(), arch) == archs.end()) + continue; + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver, ++p) + { + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioDependency(output, Ver); + fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); + } + } + return true; +} + /*}}}*/ +// EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/ +bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + APT::PackageSet const &pkgset, + OpProgress *Progress) +{ + if (Progress != NULL) + Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to solver")); + unsigned long p = 0; + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg, ++p) + for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + WriteScenarioVersion(Cache, output, Pkg, Ver); + WriteScenarioLimitedDependency(output, Ver, pkgset); + fprintf(output, "\n"); + if (Progress != NULL && p % 100 == 0) + Progress->Progress(p); + } + if (Progress != NULL) + Progress->Done(); + return true; +} + /*}}}*/ // EDSP::WriteRequest - to the given file descriptor /*{{{*/ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, bool const DistUpgrade, bool const AutoRemove, @@ -365,13 +366,13 @@ bool EDSP::ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progres return true; } /*}}}*/ -// EDSP::ReadLine - first line from the given file descriptor /*{{{*/ +// ReadLine - first line from the given file descriptor /*{{{*/ // --------------------------------------------------------------------- /* Little helper method to read a complete line into a string. Similar to fgets but we need to use the low-level read() here as otherwise the listparser will be confused later on as mixing of fgets and read isn't a supported action according to the manpages and results are undefined */ -bool EDSP::ReadLine(int const input, std::string &line) { +static bool ReadLine(int const input, std::string &line) { char one; ssize_t data = 0; line.erase(); @@ -390,11 +391,11 @@ bool EDSP::ReadLine(int const input, std::string &line) { return false; } /*}}}*/ -// EDSP::StringToBool - convert yes/no to bool /*{{{*/ +// StringToBool - convert yes/no to bool /*{{{*/ // --------------------------------------------------------------------- /* we are not as lazy as we are in the global StringToBool as we really only accept yes/no here - but we will ignore leading spaces */ -bool EDSP::StringToBool(char const *answer, bool const defValue) { +static bool StringToBool(char const *answer, bool const defValue) { for (; isspace(*answer) != 0; ++answer); if (strncasecmp(answer, "yes", 3) == 0) return true; @@ -443,11 +444,11 @@ bool EDSP::ReadRequest(int const input, std::list &install, request = &remove; } else if (line.compare(0, 8, "Upgrade:") == 0) - upgrade = EDSP::StringToBool(line.c_str() + 9, false); + upgrade = StringToBool(line.c_str() + 9, false); else if (line.compare(0, 13, "Dist-Upgrade:") == 0) - distUpgrade = EDSP::StringToBool(line.c_str() + 14, false); + distUpgrade = StringToBool(line.c_str() + 14, false); else if (line.compare(0, 11, "Autoremove:") == 0) - autoRemove = EDSP::StringToBool(line.c_str() + 12, false); + autoRemove = StringToBool(line.c_str() + 12, false); else if (line.compare(0, 13, "Architecture:") == 0) _config->Set("APT::Architecture", line.c_str() + 14); else if (line.compare(0, 14, "Architectures:") == 0) diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 9e833556a..72b886a31 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -27,24 +27,8 @@ class pkgDepCache; class OpProgress; -class EDSP /*{{{*/ +namespace EDSP /*{{{*/ { - // we could use pkgCache::DepType and ::Priority, but these would be localized strings… - static const char * const PrioMap[]; - static const char * const DepMap[]; - - APT_HIDDEN bool static ReadLine(int const input, std::string &line); - APT_HIDDEN bool static StringToBool(char const *answer, bool const defValue); - - APT_HIDDEN void static WriteScenarioVersion(pkgDepCache &Cache, FILE* output, - pkgCache::PkgIterator const &Pkg, - pkgCache::VerIterator const &Ver); - APT_HIDDEN void static WriteScenarioDependency(FILE* output, - pkgCache::VerIterator const &Ver); - APT_HIDDEN void static WriteScenarioLimitedDependency(FILE* output, - pkgCache::VerIterator const &Ver, - APT::PackageSet const &pkgset); -public: /** \brief creates the EDSP request stanza * * In the EDSP protocol the first thing send to the resolver is a stanza @@ -61,7 +45,7 @@ public: * * \return true if request was composed successfully, otherwise false */ - bool static WriteRequest(pkgDepCache &Cache, FILE* output, + bool WriteRequest(pkgDepCache &Cache, FILE* output, bool const upgrade = false, bool const distUpgrade = false, bool const autoRemove = false, @@ -84,7 +68,7 @@ public: * * \return true if universe was composed successfully, otherwise false */ - bool static WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL); + bool WriteScenario(pkgDepCache &Cache, FILE* output, OpProgress *Progress = NULL); /** \brief creates a limited scenario representing the package universe * @@ -101,7 +85,7 @@ public: * * \return true if universe was composed successfully, otherwise false */ - bool static WriteLimitedScenario(pkgDepCache &Cache, FILE* output, + bool WriteLimitedScenario(pkgDepCache &Cache, FILE* output, APT::PackageSet const &pkgset, OpProgress *Progress = NULL); @@ -118,7 +102,7 @@ public: * * \return true if a solution is found and applied correctly, otherwise false */ - bool static ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); + bool ReadResponse(int const input, pkgDepCache &Cache, OpProgress *Progress = NULL); /** \brief search and read the request stanza for action later * @@ -136,7 +120,7 @@ public: * * \return true if the request could be found and worked on, otherwise false */ - bool static ReadRequest(int const input, std::list &install, + bool ReadRequest(int const input, std::list &install, std::list &remove, bool &upgrade, bool &distUpgrade, bool &autoRemove); @@ -152,7 +136,7 @@ public: * * \return false if the request couldn't be applied, true otherwise */ - bool static ApplyRequest(std::list const &install, + bool ApplyRequest(std::list const &install, std::list const &remove, pkgDepCache &Cache); @@ -168,7 +152,7 @@ public: * * \return true if solution could be written, otherwise false */ - bool static WriteSolution(pkgDepCache &Cache, FILE* output); + bool WriteSolution(pkgDepCache &Cache, FILE* output); /** \brief sends a progress report * @@ -176,7 +160,7 @@ public: * \param message the solver wants the user to see * \param output the front-end listens for progress report */ - bool static WriteProgress(unsigned short const percent, const char* const message, FILE* output); + bool WriteProgress(unsigned short const percent, const char* const message, FILE* output); /** \brief sends an error report * @@ -193,7 +177,7 @@ public: * \param message is free form text to describe the error * \param output the front-end listens for error messages */ - bool static WriteError(char const * const uuid, std::string const &message, FILE* output); + bool WriteError(char const * const uuid, std::string const &message, FILE* output); /** \brief executes the given solver and returns the pipe ends @@ -207,8 +191,8 @@ public: * * \return PID of the started solver or 0 if failure occurred */ - pid_t static ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); - APT_DEPRECATED bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + pid_t ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool /*overload*/); + APT_DEPRECATED bool ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); /** \brief call an external resolver to handle the request * @@ -224,7 +208,7 @@ public: * \return true if the solver has successfully solved the problem, * otherwise false */ - bool static ResolveExternal(const char* const solver, pkgDepCache &Cache, + bool ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove, OpProgress *Progress = NULL); }; diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index a2ec0a19b..5d9383e94 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -81,3 +81,5 @@ const pkgIndexFile::Type *edspIndex::GetType() const return &_apt_Universe; } /*}}}*/ + +edspIndex::~edspIndex() {} diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 8c18d8cbd..0f63b7b2a 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -30,6 +30,7 @@ class APT_HIDDEN edspIndex : public debStatusIndex virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; edspIndex(std::string File); + virtual ~edspIndex(); }; #endif diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index d62abe709..d1c0cf7e8 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -92,3 +92,5 @@ APT_CONST bool edspListParser::LoadReleaseInfo(pkgCache::RlsFileIterator & /*Fil return true; } /*}}}*/ + +edspListParser::~edspListParser() {} diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index abe2ef139..ef5179e68 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -27,6 +27,7 @@ class FileFd; class APT_HIDDEN edspListParser : public debListParser { + void *d; public: virtual bool NewVersion(pkgCache::VerIterator &Ver); virtual std::string Description(); @@ -38,6 +39,7 @@ class APT_HIDDEN edspListParser : public debListParser std::string const §ion); edspListParser(FileFd *File, std::string const &Arch = ""); + virtual ~edspListParser(); protected: virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 06a63f40c..1e27d2cb0 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -42,7 +42,7 @@ class APT_HIDDEN edspSystem : public pkgSystem pkgIndexFile *&Found) const; edspSystem(); - ~edspSystem(); + virtual ~edspSystem(); }; #endif diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 461aa4217..120d061ad 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -770,4 +770,14 @@ bool TranslationsCopy::CopyTranslations(string CDROM,string Name, /*{{{*/ } /*}}}*/ +IndexCopy::IndexCopy() {} APT_CONST IndexCopy::~IndexCopy() {} + +PackageCopy::PackageCopy() : IndexCopy() {} +APT_CONST PackageCopy::~PackageCopy() {} +SourceCopy::SourceCopy() : IndexCopy() {} +APT_CONST SourceCopy::~SourceCopy() {} +TranslationsCopy::TranslationsCopy() {} +APT_CONST TranslationsCopy::~TranslationsCopy() {} +SigVerify::SigVerify() {} +APT_CONST SigVerify::~SigVerify() {} diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 729b0c8cb..7ee162542 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: indexcopy.h,v 1.3 2001/05/27 04:46:54 jgg Exp $ /* ###################################################################### Index Copying - Aid for copying and verifying the index files @@ -54,39 +53,52 @@ class IndexCopy /*{{{*/ bool CopyPackages(std::string CDROM,std::string Name,std::vector &List, pkgCdromStatus *log); + IndexCopy(); virtual ~IndexCopy(); }; /*}}}*/ class PackageCopy : public IndexCopy /*{{{*/ { + void *d; protected: - + virtual bool GetFile(std::string &Filename,unsigned long long &Size); virtual bool RewriteEntry(FileFd &Target, std::string const &File); virtual const char *GetFileName() {return "Packages";}; virtual const char *Type() {return "Package";}; - + + public: + PackageCopy(); + virtual ~PackageCopy(); }; /*}}}*/ class SourceCopy : public IndexCopy /*{{{*/ { + void *d; protected: virtual bool GetFile(std::string &Filename,unsigned long long &Size); virtual bool RewriteEntry(FileFd &Target, std::string const &File); virtual const char *GetFileName() {return "Sources";}; virtual const char *Type() {return "Source";}; - + + public: + SourceCopy(); + virtual ~SourceCopy(); }; /*}}}*/ class TranslationsCopy /*{{{*/ { + void *d; protected: pkgTagSection *Section; public: bool CopyTranslations(std::string CDROM,std::string Name,std::vector &List, pkgCdromStatus *log); + + TranslationsCopy(); + virtual ~TranslationsCopy(); }; /*}}}*/ class SigVerify /*{{{*/ @@ -106,6 +118,9 @@ class SigVerify /*{{{*/ int const &statusfd, int fd[2]); APT_DEPRECATED static bool RunGPGV(std::string const &File, std::string const &FileOut, int const &statusfd = -1); + + SigVerify(); + virtual ~SigVerify(); }; /*}}}*/ diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index 605bbeb47..b3c5cf229 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -227,3 +227,6 @@ bool pkgIndexTargetFile::Exists() const /*{{{*/ return FileExists(IndexFileName()); } /*}}}*/ + +APT_CONST pkgIndexFile::~pkgIndexFile() {} +APT_CONST pkgIndexTargetFile::~pkgIndexTargetFile() {} diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 042e5c2f7..c51879bb8 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: indexfile.h,v 1.6.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### Index File - Abstraction for an index of archive/source file. @@ -90,6 +89,7 @@ class IndexTarget /*{{{*/ class pkgIndexFile { + void *d; protected: bool Trusted; @@ -145,11 +145,12 @@ class pkgIndexFile bool IsTrusted() const { return Trusted; }; pkgIndexFile(bool Trusted); - virtual ~pkgIndexFile() {}; + virtual ~pkgIndexFile(); }; class pkgIndexTargetFile : public pkgIndexFile { + void *d; protected: IndexTarget const Target; @@ -162,6 +163,7 @@ public: virtual unsigned long Size() const; pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted); + virtual ~pkgIndexTargetFile(); }; #endif diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h index 6ed5f0c2b..f7dfa3235 100644 --- a/apt-pkg/indexrecords.h +++ b/apt-pkg/indexrecords.h @@ -1,7 +1,4 @@ // -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: indexrecords.h,v 1.1.2.1 2003/12/24 23:09:17 mdz Exp $ - /*}}}*/ #ifndef PKGLIB_INDEXRECORDS_H #define PKGLIB_INDEXRECORDS_H diff --git a/apt-pkg/install-progress.cc b/apt-pkg/install-progress.cc index 5ea8bf4d0..ee2ef683f 100644 --- a/apt-pkg/install-progress.cc +++ b/apt-pkg/install-progress.cc @@ -69,6 +69,7 @@ PackageManagerProgressFd::PackageManagerProgressFd(int progress_fd) { OutStatusFd = progress_fd; } +PackageManagerProgressFd::~PackageManagerProgressFd() {} void PackageManagerProgressFd::WriteToStatusFd(std::string s) { @@ -157,6 +158,7 @@ PackageManagerProgressDeb822Fd::PackageManagerProgressDeb822Fd(int progress_fd) { OutStatusFd = progress_fd; } +PackageManagerProgressDeb822Fd::~PackageManagerProgressDeb822Fd() {} void PackageManagerProgressDeb822Fd::WriteToStatusFd(std::string s) { @@ -433,6 +435,10 @@ bool PackageManagerText::StatusChanged(std::string PackageName, return true; } +PackageManagerText::PackageManagerText() : PackageManager() {} +PackageManagerText::~PackageManagerText() {} + + } // namespace progress diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index d8b4a5c82..a4c5daf7f 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -61,6 +61,7 @@ namespace Progress { class PackageManagerProgressFd : public PackageManager { + void *d; protected: int OutStatusFd; int StepsDone; @@ -69,6 +70,7 @@ namespace Progress { public: PackageManagerProgressFd(int progress_fd); + virtual ~PackageManagerProgressFd(); virtual void StartDpkg(); virtual void Stop(); @@ -90,6 +92,7 @@ namespace Progress { class PackageManagerProgressDeb822Fd : public PackageManager { + void *d; protected: int OutStatusFd; int StepsDone; @@ -98,6 +101,7 @@ namespace Progress { public: PackageManagerProgressDeb822Fd(int progress_fd); + virtual ~PackageManagerProgressDeb822Fd(); virtual void StartDpkg(); virtual void Stop(); @@ -118,6 +122,7 @@ namespace Progress { class PackageManagerFancy : public PackageManager { + void *d; private: APT_HIDDEN static void staticSIGWINCH(int); static std::vector instances; @@ -138,7 +143,7 @@ namespace Progress { public: PackageManagerFancy(); - ~PackageManagerFancy(); + virtual ~PackageManagerFancy(); virtual void Start(int child_pty=-1); virtual void Stop(); virtual bool StatusChanged(std::string PackageName, @@ -153,11 +158,15 @@ namespace Progress { class PackageManagerText : public PackageManager { + void *d; public: virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, std::string HumanReadableAction); + + PackageManagerText(); + virtual ~PackageManagerText(); }; diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index e1810fb27..760c7dd15 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -28,6 +28,7 @@ class OpProgress; class metaIndex { + void *d; protected: std::vector *Indexes; const char *Type; diff --git a/apt-pkg/orderlist.h b/apt-pkg/orderlist.h index b8bad81b3..29ef79b84 100644 --- a/apt-pkg/orderlist.h +++ b/apt-pkg/orderlist.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: orderlist.h,v 1.9 2001/02/20 07:03:17 jgg Exp $ /* ###################################################################### Order List - Represents and Manipulates an ordered list of packages. @@ -25,6 +24,7 @@ class pkgDepCache; class pkgOrderList : protected pkgCache::Namespace { + void *d; protected: pkgDepCache &Cache; @@ -123,7 +123,7 @@ class pkgOrderList : protected pkgCache::Namespace int Score(PkgIterator Pkg); pkgOrderList(pkgDepCache *Cache); - ~pkgOrderList(); + virtual ~pkgOrderList(); }; #endif diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index fce0ad301..60414ae1c 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: packagemanager.h,v 1.14 2001/05/07 04:24:08 jgg Exp $ /* ###################################################################### Package Manager - Abstacts the package manager @@ -146,6 +145,7 @@ class pkgPackageManager : protected pkgCache::Namespace virtual ~pkgPackageManager(); private: + void *d; enum APT_HIDDEN SmartAction { UNPACK_IMMEDIATE, UNPACK, CONFIGURE }; APT_HIDDEN bool NonLoopingSmart(SmartAction const action, pkgCache::PkgIterator &Pkg, pkgCache::PkgIterator DepPkg, int const Depth, bool const PkgLoop, diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 9fe382108..dc7698edd 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -1059,3 +1059,5 @@ bool pkgCache::PrvIterator::IsMultiArchImplicit() const return false; } /*}}}*/ + +pkgCache::~pkgCache() {} diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 3cc85f1e8..b7bf26c2a 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -266,11 +266,12 @@ class pkgCache /*{{{*/ static const char *CompTypeDeb(unsigned char Comp) APT_CONST; static const char *CompType(unsigned char Comp) APT_CONST; static const char *DepType(unsigned char Dep); - + pkgCache(MMap *Map,bool DoMap = true); - virtual ~pkgCache() {} + virtual ~pkgCache(); private: + void *d; bool MultiArchEnabled; APT_HIDDEN PkgIterator SingleArchFindPkg(const std::string &Name); }; diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ea0205944..54e2ef19c 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1720,3 +1720,6 @@ bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/) return true; } /*}}}*/ + +pkgCacheGenerator::ListParser::ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {} +pkgCacheGenerator::ListParser::~ListParser() {} diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index ade93795b..3c1a40972 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgcachegen.h,v 1.19 2002/07/08 03:13:30 jgg Exp $ /* ###################################################################### Package Cache Generator - Generator for the cache structure. @@ -123,9 +122,10 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ void ReMap(void const * const oldMap, void const * const newMap); pkgCacheGenerator(DynamicMMap *Map,OpProgress *Progress); - ~pkgCacheGenerator(); + virtual ~pkgCacheGenerator(); private: + void *d; APT_HIDDEN bool MergeListGroup(ListParser &List, std::string const &GrpName); APT_HIDDEN bool MergeListPackage(ListParser &List, pkgCache::PkgIterator &Pkg); APT_HIDDEN bool MergeListVersion(ListParser &List, pkgCache::PkgIterator &Pkg, @@ -151,7 +151,9 @@ class APT_HIDDEN pkgCacheGenerator::ListParser // Flag file dependencies bool FoundFileDeps; - + + void *d; + protected: inline map_stringitem_t StoreString(pkgCacheGenerator::StringType const type, std::string const &S) {return Owner->StoreString(type, S);}; @@ -182,10 +184,7 @@ class APT_HIDDEN pkgCacheGenerator::ListParser * \param Hash of the currently parsed version * \param Ver to compare with */ -#if APT_PKG_ABI >= 413 - virtual -#endif - APT_PURE bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); + virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); virtual bool UsePackage(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver) = 0; virtual map_filesize_t Offset() = 0; @@ -197,8 +196,8 @@ class APT_HIDDEN pkgCacheGenerator::ListParser virtual bool CollectFileProvides(pkgCache &/*Cache*/, pkgCache::VerIterator &/*Ver*/) {return true;}; - ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false) {}; - virtual ~ListParser() {}; + ListParser(); + virtual ~ListParser(); }; /*}}}*/ diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc index 859af3a09..87c965f87 100644 --- a/apt-pkg/pkgrecords.cc +++ b/apt-pkg/pkgrecords.cc @@ -76,3 +76,6 @@ pkgRecords::Parser &pkgRecords::Lookup(pkgCache::DescFileIterator const &Desc) return *Files[Desc.File()->ID]; } /*}}}*/ + +pkgRecords::Parser::Parser() {} +pkgRecords::Parser::~Parser() {} diff --git a/apt-pkg/pkgrecords.h b/apt-pkg/pkgrecords.h index bcc05baba..66eb17857 100644 --- a/apt-pkg/pkgrecords.h +++ b/apt-pkg/pkgrecords.h @@ -43,7 +43,7 @@ class pkgRecords /*{{{*/ // Construct destruct pkgRecords(pkgCache &Cache); - ~pkgRecords(); + virtual ~pkgRecords(); }; /*}}}*/ class pkgRecords::Parser /*{{{*/ @@ -106,10 +106,12 @@ class pkgRecords::Parser /*{{{*/ // The record in binary form virtual void GetRec(const char *&Start,const char *&Stop) {Start = Stop = 0;}; - - virtual ~Parser() {}; + + Parser(); + virtual ~Parser(); private: + void *d; APT_HIDDEN std::string GetHashFromHashes(char const * const type) const { HashStringList const hashes = Hashes(); diff --git a/apt-pkg/pkgsystem.cc b/apt-pkg/pkgsystem.cc index 14d090c7a..98daeb2b9 100644 --- a/apt-pkg/pkgsystem.cc +++ b/apt-pkg/pkgsystem.cc @@ -45,3 +45,5 @@ APT_PURE pkgSystem *pkgSystem::GetSystem(const char *Label) return 0; } /*}}}*/ + +pkgSystem::~pkgSystem() {} diff --git a/apt-pkg/pkgsystem.h b/apt-pkg/pkgsystem.h index f88ffa7c8..3a447da8b 100644 --- a/apt-pkg/pkgsystem.h +++ b/apt-pkg/pkgsystem.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: pkgsystem.h,v 1.6 2002/11/11 06:55:50 doogie Exp $ /* ###################################################################### System - Abstraction for running on different systems. @@ -93,7 +92,9 @@ class pkgSystem }; pkgSystem(); - virtual ~pkgSystem() {}; + virtual ~pkgSystem(); + private: + void *d; }; // The environment we are operating in. diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index bd40ad2d9..6da6ed606 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -439,3 +439,5 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) return true; } /*}}}*/ + +pkgPolicy::~pkgPolicy() {delete [] PFPriority; delete [] Pins;} diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index f15d8c0a0..c4b1cbadd 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: policy.h,v 1.4 2001/05/07 04:24:08 jgg Exp $ /* ###################################################################### Package Version Policy implementation @@ -85,7 +84,9 @@ class pkgPolicy : public pkgDepCache::Policy bool InitDefaults(); pkgPolicy(pkgCache *Owner); - virtual ~pkgPolicy() {delete [] PFPriority; delete [] Pins;}; + virtual ~pkgPolicy(); + private: + void *d; }; bool ReadPinFile(pkgPolicy &Plcy, std::string File = ""); diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index 998357509..c92643829 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: sourcelist.h,v 1.12.2.1 2003/12/24 23:09:17 mdz Exp $ /* ###################################################################### SourceList - Manage a list of sources @@ -54,6 +53,7 @@ class metaIndex; class pkgSourceList { + void *d; public: // List of supported source list types @@ -118,7 +118,7 @@ class pkgSourceList pkgSourceList(); pkgSourceList(std::string File); - ~pkgSourceList(); + virtual ~pkgSourceList(); }; #endif diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index c931e17b7..dda66ce48 100644 --- a/apt-pkg/srcrecords.h +++ b/apt-pkg/srcrecords.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: srcrecords.h,v 1.8.2.1 2003/12/26 16:27:34 mdz Exp $ /* ###################################################################### Source Package Records - Allows access to source package records diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 118954541..24eda02f7 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -1,6 +1,5 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: tagfile.h,v 1.20 2003/05/19 17:13:57 doogie Exp $ /* ###################################################################### Fast scanner for RFC-822 type header information @@ -47,7 +46,6 @@ class pkgTagSection APT_DEPRECATED unsigned int TagCount; #endif - // dpointer placeholder (for later in case we need it) pkgTagSectionPrivate *d; protected: diff --git a/apt-pkg/version.cc b/apt-pkg/version.cc index 29bee46da..f32d39a69 100644 --- a/apt-pkg/version.cc +++ b/apt-pkg/version.cc @@ -40,3 +40,6 @@ pkgVersioningSystem *pkgVersioningSystem::GetVS(const char *Label) return 0; } /*}}}*/ + + +pkgVersioningSystem::~pkgVersioningSystem() {} diff --git a/apt-pkg/version.h b/apt-pkg/version.h index d98809f7e..5110ecaa7 100644 --- a/apt-pkg/version.h +++ b/apt-pkg/version.h @@ -55,7 +55,7 @@ class pkgVersioningSystem APT_MKSTRCMP(CmpReleaseVer,DoCmpReleaseVer); pkgVersioningSystem(); - virtual ~pkgVersioningSystem() {}; + virtual ~pkgVersioningSystem(); }; #endif diff --git a/test/libapt/acqprogress_test.cc b/test/libapt/acqprogress_test.cc index c634733d4..dc31423fc 100644 --- a/test/libapt/acqprogress_test.cc +++ b/test/libapt/acqprogress_test.cc @@ -25,21 +25,23 @@ TEST(AcqProgress, IMSHit) AcqTextStatus Stat(out, width, 0); Stat.Start(); + pkgAcquire Acq(&Stat); pkgAcquire::ItemDesc hit; hit.URI = "http://example.org/file"; hit.Description = "Example File from example.org"; hit.ShortDesc = "Example File"; - hit.Owner = NULL; + TestItem hitO(&Acq); + hit.Owner = &hitO; EXPECT_EQ("", out.str()); Stat.IMSHit(hit); - EXPECT_EQ("Hit Example File from example.org\n", out.str()); + EXPECT_EQ("Hit:1 Example File from example.org\n", out.str()); Stat.IMSHit(hit); - EXPECT_EQ("Hit Example File from example.org\n" - "Hit Example File from example.org\n", out.str()); + EXPECT_EQ("Hit:1 Example File from example.org\n" + "Hit:1 Example File from example.org\n", out.str()); Stat.Stop(); - EXPECT_EQ("Hit Example File from example.org\n" - "Hit Example File from example.org\n", out.str()); + EXPECT_EQ("Hit:1 Example File from example.org\n" + "Hit:1 Example File from example.org\n", out.str()); } TEST(AcqProgress, FetchNoFileSize) { @@ -61,10 +63,10 @@ TEST(AcqProgress, FetchNoFileSize) EXPECT_EQ("Get:1 Example File from example.org\n", out.str()); Stat.Fetch(fetch); EXPECT_EQ("Get:1 Example File from example.org\n" - "Get:2 Example File from example.org\n", out.str()); + "Get:1 Example File from example.org\n", out.str()); Stat.Stop(); EXPECT_EQ("Get:1 Example File from example.org\n" - "Get:2 Example File from example.org\n", out.str()); + "Get:1 Example File from example.org\n", out.str()); } TEST(AcqProgress, FetchFileSize) { @@ -88,10 +90,10 @@ TEST(AcqProgress, FetchFileSize) fetchO.FileSize = 42; Stat.Fetch(fetch); EXPECT_EQ("Get:1 Example File from example.org [100 B]\n" - "Get:2 Example File from example.org [42 B]\n", out.str()); + "Get:1 Example File from example.org [42 B]\n", out.str()); Stat.Stop(); EXPECT_EQ("Get:1 Example File from example.org [100 B]\n" - "Get:2 Example File from example.org [42 B]\n", out.str()); + "Get:1 Example File from example.org [42 B]\n", out.str()); } TEST(AcqProgress, Fail) { @@ -112,30 +114,34 @@ TEST(AcqProgress, Fail) EXPECT_EQ("", out.str()); Stat.Fail(fetch); - EXPECT_EQ("", out.str()); + EXPECT_EQ("Ign:1 Example File from example.org\n", out.str()); fetchO.Status = pkgAcquire::Item::StatDone; Stat.Fail(fetch); - EXPECT_EQ("Ign Example File from example.org\n", out.str()); + EXPECT_EQ("Ign:1 Example File from example.org\n" + "Ign:1 Example File from example.org\n", out.str()); fetchO.Status = pkgAcquire::Item::StatError; fetchO.ErrorText = "An error test!"; Stat.Fail(fetch); - EXPECT_EQ("Ign Example File from example.org\n" - "Err Example File from example.org\n" + EXPECT_EQ("Ign:1 Example File from example.org\n" + "Ign:1 Example File from example.org\n" + "Err:1 Example File from example.org\n" " An error test!\n", out.str()); _config->Set("Acquire::Progress::Ignore::ShowErrorText", true); fetchO.Status = pkgAcquire::Item::StatDone; Stat.Fail(fetch); - EXPECT_EQ("Ign Example File from example.org\n" - "Err Example File from example.org\n" + EXPECT_EQ("Ign:1 Example File from example.org\n" + "Ign:1 Example File from example.org\n" + "Err:1 Example File from example.org\n" " An error test!\n" - "Ign Example File from example.org\n" + "Ign:1 Example File from example.org\n" " An error test!\n", out.str()); _config->Set("Acquire::Progress::Ignore::ShowErrorText", true); Stat.Stop(); - EXPECT_EQ("Ign Example File from example.org\n" - "Err Example File from example.org\n" + EXPECT_EQ("Ign:1 Example File from example.org\n" + "Ign:1 Example File from example.org\n" + "Err:1 Example File from example.org\n" " An error test!\n" - "Ign Example File from example.org\n" + "Ign:1 Example File from example.org\n" " An error test!\n", out.str()); } TEST(AcqProgress, Pulse) -- cgit v1.2.3-70-g09d2 From 20cf708a62df5e4aa45a506819db425c6cc975fe Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 10 Aug 2015 11:42:34 +0200 Subject: fileutl_test.cc: Check for /etc/passwd instead of /bin/sh This fixes the tests on systems where usrmerge is installed. Gbp-dch: ignore --- test/libapt/fileutl_test.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/libapt/fileutl_test.cc b/test/libapt/fileutl_test.cc index a2c303768..b42261716 100644 --- a/test/libapt/fileutl_test.cc +++ b/test/libapt/fileutl_test.cc @@ -290,10 +290,10 @@ TEST(FileUtlTest, Popen) TEST(FileUtlTest, flAbsPath) { std::string cwd = SafeGetCWD(); - int res = chdir("/bin/"); + int res = chdir("/etc/"); EXPECT_EQ(res, 0); - std::string p = flAbsPath("ls"); - EXPECT_EQ(p, "/bin/ls"); + std::string p = flAbsPath("passwd"); + EXPECT_EQ(p, "/etc/passwd"); res = chdir(cwd.c_str()); EXPECT_EQ(res, 0); -- cgit v1.2.3-70-g09d2 From 76b004d1a2122206925abc1a412e055430cef283 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 10 Aug 2015 15:36:51 +0200 Subject: Fix test case breakage from the new policy implementation Everything's working now. --- .../test-acquire-same-repository-multiple-times | 2 +- .../test-apt-translation-has-no-packages | 2 +- .../test-bug-543966-downgrade-below-1000-pin | 14 ++--- .../test-cve-2013-1051-InRelease-parsing | 4 +- test/integration/test-policy-pinning | 73 +++++++++++----------- 5 files changed, 48 insertions(+), 47 deletions(-) (limited to 'test') diff --git a/test/integration/test-acquire-same-repository-multiple-times b/test/integration/test-acquire-same-repository-multiple-times index a46e0d73c..ad9cd6d7e 100755 --- a/test/integration/test-acquire-same-repository-multiple-times +++ b/test/integration/test-acquire-same-repository-multiple-times @@ -50,7 +50,7 @@ tworepos() { Installed: (none) Candidate: 1.0 Version table: - 1.0 0 + 1.0 500 500 $1:$2 jessie/main amd64 Packages 500 $1:$2 stable/main amd64 Packages" aptcache policy foo testfailure aptcache show foo/unstable diff --git a/test/integration/test-apt-translation-has-no-packages b/test/integration/test-apt-translation-has-no-packages index cf5b56243..ec2e1e43b 100755 --- a/test/integration/test-apt-translation-has-no-packages +++ b/test/integration/test-apt-translation-has-no-packages @@ -37,5 +37,5 @@ testsuccessequal "foo: Installed: (none) Candidate: 1.0 Version table: - 1.0 0 + 1.0 500 500 file:$APTARCHIVE unstable/main amd64 Packages" aptcache policy foo diff --git a/test/integration/test-bug-543966-downgrade-below-1000-pin b/test/integration/test-bug-543966-downgrade-below-1000-pin index 180393867..ede9ad6aa 100755 --- a/test/integration/test-bug-543966-downgrade-below-1000-pin +++ b/test/integration/test-bug-543966-downgrade-below-1000-pin @@ -19,9 +19,9 @@ testsuccessequal "base-files: Installed: 5.0.0-1 Candidate: 5.0.0-1 Version table: - *** 5.0.0-1 0 + *** 5.0.0-1 100 100 $STATUS - 5.0.0 0 + 5.0.0 500 500 file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=0 writepin() { @@ -34,7 +34,7 @@ Pin-Priority: $2" > rootdir/etc/apt/preferences testpinning() { local PKGPIN='' - local PKGPINPRIO='0' + local PKGPINPRIO='' local REPPINPRIO='' if [ "$1" != '*' ]; then PKGPINPRIO='' @@ -47,7 +47,7 @@ testpinning() { Installed: 5.0.0-1 Candidate: 5.0.0-1 ${PKGPIN}Version table: - *** 5.0.0-1 ${PKGPINPRIO:-99} + *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-99} ${REPPINPRIO:- 99} file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=99 @@ -57,7 +57,7 @@ testpinning() { Installed: 5.0.0-1 Candidate: 5.0.0-1 ${PKGPIN}Version table: - *** 5.0.0-1 ${PKGPINPRIO:-100} + *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-100} ${REPPINPRIO:- 100} file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=100 @@ -67,7 +67,7 @@ testpinning() { Installed: 5.0.0-1 Candidate: 5.0.0-1 ${PKGPIN}Version table: - *** 5.0.0-1 ${PKGPINPRIO:-999} + *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-999} ${REPPINPRIO:- 999} file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=999 @@ -77,7 +77,7 @@ testpinning() { Installed: 5.0.0-1 Candidate: 5.0.0 ${PKGPIN}Version table: - *** 5.0.0-1 ${PKGPINPRIO:-1000} + *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-1000} ${REPPINPRIO:-1000} file:${APTARCHIVE} unstable/main i386 Packages" aptcache policy base-files -o apt::pin=1000 diff --git a/test/integration/test-cve-2013-1051-InRelease-parsing b/test/integration/test-cve-2013-1051-InRelease-parsing index 933cbbd92..a503ad0fe 100755 --- a/test/integration/test-cve-2013-1051-InRelease-parsing +++ b/test/integration/test-cve-2013-1051-InRelease-parsing @@ -21,7 +21,7 @@ testsuccessequal "good-pkg: Installed: (none) Candidate: 1.0 Version table: - 1.0 0 + 1.0 500 500 ${ARCHIVE} stable/main i386 Packages" aptcache policy good-pkg # now exchange to the Packages file, note that this could be @@ -62,5 +62,5 @@ testsuccessequal "good-pkg: Installed: (none) Candidate: 1.0 Version table: - 1.0 0 + 1.0 500 500 ${ARCHIVE} stable/main i386 Packages" aptcache policy good-pkg diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 9f7f457ae..c4f478efc 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -105,10 +105,11 @@ testequalpolicycoolstuff() { local BPO1ARCHIVE="" local BPO2ARCHIVE="" if [ ! "$7" = "2.0~bpo2" ]; then + BPO1PIN="$AB" BPO1ARCHIVE=" $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} backports/main i386 Packages" else BPO2ARCHIVE=" - 2.0~bpo2 $PB + 2.0~bpo2 $AB $(echo "$AB" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} backports/main i386 Packages" SB="$(echo "$SB" | tail -n 1)" shift @@ -120,25 +121,25 @@ testequalpolicycoolstuff() { ${PINVERSION}Version table:${BPO2ARCHIVE} $IB 2.0~bpo1 $PB ${BPO1ARCHIVE}$SB - $IS 1.0 $PB + $IS 1.0 $AS $(echo "$AS" | awk '{ printf("%3s\n",$0) }') file:${APTARCHIVE} stable/main i386 Packages$SS" \ aptcache policy coolstuff -o Policy=${INSTALLED}-${CANDIDATE}-${AB}-${AS}-${PB} $* } -testequalpolicycoolstuff "" "2.0~bpo1" 500 500 0 "" -testequalpolicycoolstuff "" "1.0" 500 990 0 "" -t stable -testequalpolicycoolstuff "" "2.0~bpo1" 990 500 0 "" -t backports +testequalpolicycoolstuff "" "2.0~bpo1" 500 500 500 "" +testequalpolicycoolstuff "" "1.0" 500 990 500 "" -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 990 500 990 "" -t backports echo "Package: * Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "1.0" 200 500 0 "" -o Test=GlobalPin -testequalpolicycoolstuff "" "1.0" 200 990 0 "" -o Test=GlobalPin -t stable -testequalpolicycoolstuff "" "2.0~bpo1" 990 500 0 "" -o Test=GlobalPin -t backports +testequalpolicycoolstuff "" "1.0" 200 500 200 "" -o Test=GlobalPin +testequalpolicycoolstuff "" "1.0" 200 990 200 "" -o Test=GlobalPin -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 990 500 990 "" -o Test=GlobalPin -t backports echo "Package: * Pin: release n=backports Pin-Priority: 600" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "2.0~bpo1" 600 500 0 "" -o Test=GlobalPin -testequalpolicycoolstuff "" "1.0" 600 990 0 "" -o Test=GlobalPin -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 600 500 600 "" -o Test=GlobalPin +testequalpolicycoolstuff "" "1.0" 600 990 600 "" -o Test=GlobalPin -t stable echo "Package: coolstuff Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences @@ -165,18 +166,18 @@ sed -i aptarchive/dists/backports/Release -e 1i"NotAutomatic: yes" signreleasefiles aptgetupdate -testequalpolicycoolstuff "" "1.0" 1 500 0 "" -o Test=NotAutomatic -testequalpolicycoolstuff "" "1.0" 1 990 0 "" -o Test=NotAutomatic -t stable -testequalpolicycoolstuff "" "2.0~bpo1" 990 500 0 "" -o Test=NotAutomatic -t backports +testequalpolicycoolstuff "" "1.0" 1 500 1 "" -o Test=NotAutomatic +testequalpolicycoolstuff "" "1.0" 1 990 1 "" -o Test=NotAutomatic -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 990 500 990 "" -o Test=NotAutomatic -t backports echo "Package: * Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "1.0" 200 500 0 "" -o Test=NotAutomatic +testequalpolicycoolstuff "" "1.0" 200 500 200 "" -o Test=NotAutomatic echo "Package: * Pin: release n=backports Pin-Priority: 600" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "2.0~bpo1" 600 500 0 "" -o Test=NotAutomatic -testequalpolicycoolstuff "" "1.0" 600 990 0 "" -o Test=NotAutomatic -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 600 500 600 "" -o Test=NotAutomatic +testequalpolicycoolstuff "" "1.0" 600 990 600 "" -o Test=NotAutomatic -t stable echo "Package: coolstuff Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences @@ -193,18 +194,18 @@ sed -i aptarchive/dists/backports/Release -e 1i"ButAutomaticUpgrades: yes" signreleasefiles aptgetupdate -testequalpolicycoolstuff "" "1.0" 100 500 0 "" -o Test=ButAutomaticUpgrades -testequalpolicycoolstuff "" "1.0" 100 990 0 "" -o Test=ButAutomaticUpgrades -t stable -testequalpolicycoolstuff "" "2.0~bpo1" 990 500 0 "" -o Test=ButAutomaticUpgrades -t backports +testequalpolicycoolstuff "" "1.0" 100 500 100 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "" "1.0" 100 990 100 "" -o Test=ButAutomaticUpgrades -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 990 500 990 "" -o Test=ButAutomaticUpgrades -t backports echo "Package: * Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "1.0" 200 500 0 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "" "1.0" 200 500 200 "" -o Test=ButAutomaticUpgrades echo "Package: * Pin: release n=backports Pin-Priority: 600" > rootdir/etc/apt/preferences -testequalpolicycoolstuff "" "2.0~bpo1" 600 500 0 "" -o Test=ButAutomaticUpgrades -testequalpolicycoolstuff "" "1.0" 600 990 0 "" -o Test=ButAutomaticUpgrades -t stable +testequalpolicycoolstuff "" "2.0~bpo1" 600 500 600 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "" "1.0" 600 990 600 "" -o Test=ButAutomaticUpgrades -t stable echo "Package: coolstuff Pin: release n=backports Pin-Priority: 200" > rootdir/etc/apt/preferences @@ -218,18 +219,18 @@ testequalpolicycoolstuff "" "1.0" 100 990 600 "2.0~bpo1" -o Test=ButAutomaticUpg rm rootdir/etc/apt/preferences testsuccess aptget install coolstuff -y -testequalpolicycoolstuff "1.0" "1.0" 100 500 0 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "1.0" "1.0" 100 500 100 "" -o Test=ButAutomaticUpgrades testsuccess aptget dist-upgrade -y -testequalpolicycoolstuff "1.0" "1.0" 100 500 0 "" -o Test=ButAutomaticUpgrades -testequalpolicycoolstuff "1.0" "1.0" 100 990 0 "" -o Test=ButAutomaticUpgrades -t stable -testequalpolicycoolstuff "1.0" "2.0~bpo1" 990 500 0 "" -o Test=ButAutomaticUpgrades -t backports +testequalpolicycoolstuff "1.0" "1.0" 100 500 100 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "1.0" "1.0" 100 990 100 "" -o Test=ButAutomaticUpgrades -t stable +testequalpolicycoolstuff "1.0" "2.0~bpo1" 990 500 990 "" -o Test=ButAutomaticUpgrades -t backports testsuccess aptget install coolstuff -t backports -y -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 0 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 100 "" -o Test=ButAutomaticUpgrades testsuccess aptget dist-upgrade -y -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 0 "" -o Test=ButAutomaticUpgrades -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 990 0 "" -o Test=ButAutomaticUpgrades -t stable -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 990 500 0 "" -o Test=ButAutomaticUpgrades -t backports +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 500 100 "" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 100 990 100 "" -o Test=ButAutomaticUpgrades -t stable +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 990 500 990 "" -o Test=ButAutomaticUpgrades -t backports rm incoming/backports.main.pkglist incoming/backports.main.srclist buildsimplenativepackage "coolstuff" "all" "2.0~bpo2" "backports" @@ -239,14 +240,14 @@ sed -i aptarchive/dists/backports/Release -e 1i"NotAutomatic: yes" signreleasefiles aptgetupdate -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 1 500 0 "" "2.0~bpo2" -o Test=NotAutomatic -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 1 990 0 "" "2.0~bpo2" -o Test=NotAutomatic -t stable -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 0 "" "2.0~bpo2" -o Test=NotAutomatic -t backports +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 1 500 100 "" "2.0~bpo2" -o Test=NotAutomatic +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo1" 1 990 100 "" "2.0~bpo2" -o Test=NotAutomatic -t stable +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 100 "" "2.0~bpo2" -o Test=NotAutomatic -t backports sed -i aptarchive/dists/backports/Release -e 1i"ButAutomaticUpgrades: yes" signreleasefiles aptgetupdate -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 500 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 990 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t stable -testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 0 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t backports +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 500 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 990 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t stable +testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t backports -- cgit v1.2.3-70-g09d2 From c3392a9fccc04129816057b1184c651171034376 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 17 Jun 2015 22:15:01 +0200 Subject: some CXXFLAGS housekeeping More warnings are always better. Git-Dch: Ignore --- apt-pkg/aptconfiguration.h | 2 +- apt-pkg/contrib/sptr.h | 8 ++++++++ apt-pkg/edsp.h | 2 +- buildlib/environment.mak.in | 6 +++++- test/libapt/makefile | 3 ++- 5 files changed, 17 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/apt-pkg/aptconfiguration.h b/apt-pkg/aptconfiguration.h index 353843c3e..fbd9b02e6 100644 --- a/apt-pkg/aptconfiguration.h +++ b/apt-pkg/aptconfiguration.h @@ -122,7 +122,7 @@ namespace Configuration { /*{{{*/ /** \return Return a comma-separated list of enabled build profile specifications */ std::string const getBuildProfilesString(); /*}}}*/ -}; +} /*}}}*/ } #endif diff --git a/apt-pkg/contrib/sptr.h b/apt-pkg/contrib/sptr.h index 9df0e44a7..e2e811b1d 100644 --- a/apt-pkg/contrib/sptr.h +++ b/apt-pkg/contrib/sptr.h @@ -60,7 +60,15 @@ class SPtrArray inline SPtrArray(T *Ptr) : Ptr(Ptr) {}; inline SPtrArray() : Ptr(0) {}; +#if __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" + // gcc warns about this, but we can do nothing here… +#endif inline ~SPtrArray() {delete [] Ptr;}; +#if __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif }; #endif diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index 72b886a31..4f5f500a1 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -211,6 +211,6 @@ namespace EDSP /*{{{*/ bool ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove, OpProgress *Progress = NULL); -}; +} /*}}}*/ #endif diff --git a/buildlib/environment.mak.in b/buildlib/environment.mak.in index b0a8d9d35..0dff02e69 100644 --- a/buildlib/environment.mak.in +++ b/buildlib/environment.mak.in @@ -11,7 +11,11 @@ CPPFLAGS+= @CPPFLAGS@ @DEFS@ -D_REENTRANT -D_FORTIFY_SOURCE=2 CXX = @CXX@ CXXFLAGS+= @CXXFLAGS@ -Wall -Wextra CXXFLAGS+= -Wcast-align -Wlogical-op -Wredundant-decls -Wmissing-declarations -Wunsafe-loop-optimizations -CXXFLAGS+= -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=noreturn +CXXFLAGS+= -Wctor-dtor-privacy -Wdisabled-optimization -Winit-self -Wmissing-include-dirs -Wnoexcept -Wsign-promo -Wundef +# suggests methods which already have such an attribute +#CXXFLAGS+= -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=noreturn +# gcc reports currently lots of them at the end of file - unknown reason +CXXFLAGS+= -Wno-deprecated-declarations # a bit too pedantic to be run by default #CXXFLAGS+= -Wpedantic -Wno-long-long -Wno-vla -Wno-variadic-macros NUM_PROCS = @NUM_PROCS@ diff --git a/test/libapt/makefile b/test/libapt/makefile index 61a8aaf31..c078cc568 100644 --- a/test/libapt/makefile +++ b/test/libapt/makefile @@ -33,7 +33,7 @@ GTEST_DIR = /usr/src/gtest # Flags passed to the preprocessor. # Set Google Test's header directory as a system directory, such that # the compiler doesn't generate warnings in Google Test headers. -CPPFLAGS += -isystem $(GTEST_DIR)/include +#CPPFLAGS += -isystem $(GTEST_DIR)/include # Flags passed to the C++ compiler. CXXFLAGS += -pthread @@ -41,6 +41,7 @@ CXXFLAGS += -pthread CXXFLAGS+= -Wno-missing-declarations CXXFLAGS+= -Wno-missing-field-initializers CXXFLAGS+= -Wno-suggest-attribute=pure -Wno-suggest-attribute=const -Wno-suggest-attribute=noreturn +CXXFLAGS+= -Wno-undef # All Google Test headers. Usually you shouldn't change this definition. GTEST_HEADERS = /usr/include/gtest/*.h \ -- cgit v1.2.3-70-g09d2 From 3d8232bf97ce11818fb07813a71136484ea1a44a Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 18 Jun 2015 17:33:15 +0200 Subject: fix memory leaks reported by -fsanitize Various small leaks here and there. Nothing particularily big, but still good to fix. Found by the sanitizers while running our testcases. Reported-By: gcc -fsanitize Git-Dch: Ignore --- apt-pkg/acquire-item.cc | 57 +++++++++++++++++++--------------- apt-pkg/acquire-item.h | 45 +++++++++++++-------------- apt-pkg/acquire-worker.cc | 2 +- apt-pkg/cachefile.cc | 4 +-- apt-pkg/contrib/cdromutl.cc | 2 ++ apt-pkg/contrib/gpgv.cc | 2 ++ apt-pkg/deb/debmetaindex.cc | 2 +- apt-pkg/deb/debrecords.cc | 4 +++ apt-pkg/deb/dpkgpm.cc | 4 +++ apt-pkg/indexrecords.cc | 5 ++- apt-pkg/tagfile.cc | 13 ++++++-- apt-pkg/tagfile.h | 2 +- apt-private/private-cacheset.h | 13 +++++--- apt-private/private-output.cc | 23 ++++++++------ buildlib/environment.mak.in | 2 ++ cmdline/apt-cache.cc | 1 + cmdline/apt-get.cc | 8 ++--- ftparchive/apt-ftparchive.cc | 69 +++++++++++++++++++++--------------------- ftparchive/cachedb.cc | 1 + ftparchive/writer.cc | 31 ++++++++++++------- ftparchive/writer.h | 14 +++------ test/integration/framework | 3 ++ test/libapt/cdrom_test.cc | 7 ++--- test/libapt/file-helpers.cc | 7 ++--- test/libapt/file-helpers.h | 2 +- test/libapt/sourcelist_test.cc | 5 +-- 26 files changed, 190 insertions(+), 138 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 222ca8931..0ab52a0cd 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -109,7 +109,7 @@ static std::string GetDiffsPatchFileName(std::string const &Final) /*{{{*/ } /*}}}*/ -static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaBase * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ +static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaClearSig * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ { if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true) return true; @@ -661,7 +661,7 @@ std::string pkgAcquire::Item::HashSum() const /*{{{*/ /*}}}*/ pkgAcqTransactionItem::pkgAcqTransactionItem(pkgAcquire * const Owner, /*{{{*/ - pkgAcqMetaBase * const transactionManager, IndexTarget const &target) : + pkgAcqMetaClearSig * const transactionManager, IndexTarget const &target) : pkgAcquire::Item(Owner), d(NULL), Target(target), TransactionManager(transactionManager) { if (TransactionManager != this) @@ -680,12 +680,11 @@ HashStringList pkgAcqTransactionItem::GetExpectedHashesFor(std::string const &Me // AcqMetaBase - Constructor /*{{{*/ pkgAcqMetaBase::pkgAcqMetaBase(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, std::vector const &IndexTargets, - IndexTarget const &DataTarget, - indexRecords * const MetaIndexParser) + IndexTarget const &DataTarget) : pkgAcqTransactionItem(Owner, TransactionManager, DataTarget), d(NULL), - MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL), IndexTargets(IndexTargets), + IndexTargets(IndexTargets), AuthPass(false), IMSHit(false) { } @@ -1047,7 +1046,7 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ std::string errmsg; strprintf(errmsg, // TRANSLATOR: The first %s is the URL of the bad Release file, the second is - // the time since then the file is invalid - formated in the same way as in + // the time since then the file is invalid - formatted in the same way as in // the download progress display (e.g. 7d 3h 42min 1s) _("Release file for %s is expired (invalid since %s). " "Updates for this repository will not be applied."), @@ -1098,16 +1097,19 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ return true; } /*}}}*/ -pkgAcqMetaBase::~pkgAcqMetaBase() {} +pkgAcqMetaBase::~pkgAcqMetaBase() +{ +} pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ IndexTarget const &ClearsignedTarget, IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, std::vector const &IndexTargets, indexRecords * const MetaIndexParser) : - pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets, MetaIndexParser), + pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets), d(NULL), ClearsignedTarget(ClearsignedTarget), - DetachedDataTarget(DetachedDataTarget) + DetachedDataTarget(DetachedDataTarget), + MetaIndexParser(MetaIndexParser), LastMetaIndexParser(NULL) { // index targets + (worst case:) Release/Release.gpg ExpectedAdditionalItems = IndexTargets.size() + 2; @@ -1116,6 +1118,10 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ /*}}}*/ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ { + if (MetaIndexParser != NULL) + delete MetaIndexParser; + if (LastMetaIndexParser != NULL) + delete LastMetaIndexParser; } /*}}}*/ // pkgAcqMetaClearSig::Custom600Headers - Insert custom request headers /*{{{*/ @@ -1180,7 +1186,7 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); Status = StatDone; - new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets, TransactionManager->MetaIndexParser); + new pkgAcqMetaIndex(Owner, TransactionManager, DetachedDataTarget, DetachedSigTarget, IndexTargets); } else { @@ -1240,12 +1246,11 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c /*}}}*/ pkgAcqMetaIndex::pkgAcqMetaIndex(pkgAcquire * const Owner, /*{{{*/ - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, - vector const &IndexTargets, - indexRecords * const MetaIndexParser) : - pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget, MetaIndexParser), d(NULL), + vector const &IndexTargets) : + pkgAcqMetaBase(Owner, TransactionManager, IndexTargets, DataTarget), d(NULL), DetachedSigTarget(DetachedSigTarget) { if(_config->FindB("Debug::Acquire::Transaction", false) == true) @@ -1324,7 +1329,7 @@ pkgAcqMetaIndex::~pkgAcqMetaIndex() {} // AcqMetaSig::AcqMetaSig - Constructor /*{{{*/ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target, pkgAcqMetaIndex * const MetaIndex) : pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL), MetaIndex(MetaIndex) @@ -1487,7 +1492,7 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const // AcqBaseIndex - Constructor /*{{{*/ pkgAcqBaseIndex::pkgAcqBaseIndex(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target) : pkgAcqTransactionItem(Owner, TransactionManager, Target), d(NULL) { @@ -1503,9 +1508,9 @@ pkgAcqBaseIndex::~pkgAcqBaseIndex() {} * the original packages file */ pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target) - : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL) + : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), diffs(NULL) { Debug = _config->FindB("Debug::pkgAcquire::Diffs",false); @@ -1840,7 +1845,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string const &IndexDiffFile) /*{{{*/ new pkgAcqIndexDiffs(Owner, TransactionManager, Target, available_patches); else { - std::vector *diffs = new std::vector(available_patches.size()); + diffs = new std::vector(available_patches.size()); for(size_t i = 0; i < available_patches.size(); ++i) (*diffs)[i] = new pkgAcqIndexMergeDiffs(Owner, TransactionManager, Target, @@ -1896,7 +1901,11 @@ void pkgAcqDiffIndex::Done(string const &Message,HashStringList const &Hashes, / return; } /*}}}*/ -pkgAcqDiffIndex::~pkgAcqDiffIndex() {} +pkgAcqDiffIndex::~pkgAcqDiffIndex() +{ + if (diffs != NULL) + delete diffs; +} // AcqIndexDiffs::AcqIndexDiffs - Constructor /*{{{*/ // --------------------------------------------------------------------- @@ -1904,7 +1913,7 @@ pkgAcqDiffIndex::~pkgAcqDiffIndex() {} * for each diff and the index */ pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target, vector const &diffs) : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), @@ -2127,7 +2136,7 @@ pkgAcqIndexDiffs::~pkgAcqIndexDiffs() {} // AcqIndexMergeDiffs::AcqIndexMergeDiffs - Constructor /*{{{*/ pkgAcqIndexMergeDiffs::pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target, DiffInfo const &patch, std::vector const * const allPatches) @@ -2272,7 +2281,7 @@ pkgAcqIndexMergeDiffs::~pkgAcqIndexMergeDiffs() {} // AcqIndex::AcqIndex - Constructor /*{{{*/ pkgAcqIndex::pkgAcqIndex(pkgAcquire * const Owner, - pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target) : pkgAcqBaseIndex(Owner, TransactionManager, Target), d(NULL), Stage(STAGE_DOWNLOAD) { diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index c4bbfc7a1..4d235dce2 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -46,7 +46,8 @@ class indexRecords; class pkgRecords; class pkgSourceList; -class pkgAcqMetaBase; +class pkgAcqMetaClearSig; +class pkgAcqIndexMergeDiffs; class pkgAcquire::Item : public WeakPointable /*{{{*/ /** \brief Represents the process by which a pkgAcquire object should @@ -339,6 +340,7 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ void * const d; friend class pkgAcqMetaBase; + friend class pkgAcqMetaClearSig; }; /*}}}*/ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ @@ -356,7 +358,7 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ std::string PartialFile; /** \brief TransactionManager */ - pkgAcqMetaBase * const TransactionManager; + pkgAcqMetaClearSig * const TransactionManager; enum TransactionStates { TransactionCommit, @@ -370,10 +372,11 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ virtual bool HashesRequired() const; - pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const &Target); + pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); virtual ~pkgAcqTransactionItem(); friend class pkgAcqMetaBase; + friend class pkgAcqMetaClearSig; }; /*}}}*/ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ @@ -383,12 +386,6 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ protected: std::vector Transaction; - public: - /** \brief A package-system-specific parser for the meta-index file. */ - indexRecords *MetaIndexParser; - indexRecords *LastMetaIndexParser; - protected: - /** \brief The index files which should be looked up in the meta-index * and then downloaded. */ @@ -473,10 +470,9 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; - pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, std::vector const &IndexTargets, - IndexTarget const &DataTarget, - indexRecords* const MetaIndexParser); + IndexTarget const &DataTarget); virtual ~pkgAcqMetaBase(); }; /*}}}*/ @@ -509,9 +505,9 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase virtual void Finished(); /** \brief Create a new pkgAcqMetaIndex. */ - pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &DataTarget, IndexTarget const &DetachedSigTarget, - std::vector const &IndexTargets, indexRecords * const MetaIndexParser); + std::vector const &IndexTargets); virtual ~pkgAcqMetaIndex(); friend class pkgAcqMetaSig; @@ -548,8 +544,8 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem pkgAcquire::MethodConfig const * const Cnf); /** \brief Create a new pkgAcqMetaSig. */ - pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, IndexTarget const &Target, - pkgAcqMetaIndex * const MetaIndex); + pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, + IndexTarget const &Target, pkgAcqMetaIndex * const MetaIndex); virtual ~pkgAcqMetaSig(); }; /*}}}*/ @@ -561,7 +557,11 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex IndexTarget const ClearsignedTarget; IndexTarget const DetachedDataTarget; -public: + public: + /** \brief A package-system-specific parser for the meta-index file. */ + indexRecords *MetaIndexParser; + indexRecords *LastMetaIndexParser; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; virtual void Done(std::string const &Message, HashStringList const &Hashes, @@ -586,7 +586,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem /** \brief Get the full pathname of the final file for the current URI */ virtual std::string GetFinalFilename() const; - pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); virtual ~pkgAcqBaseIndex(); }; @@ -603,6 +603,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex { void * const d; + std::vector * diffs; protected: /** \brief If \b true, debugging information will be written to std::clog. */ @@ -650,7 +651,7 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex * * \param ShortDesc A short description of the list file to download. */ - pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqDiffIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); virtual ~pkgAcqDiffIndex(); private: @@ -749,7 +750,7 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * \param allPatches contains all related items so that each item can * check if it was the last one to complete the download step */ - pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqIndexMergeDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target, DiffInfo const &patch, std::vector const * const allPatches); virtual ~pkgAcqIndexMergeDiffs(); @@ -863,7 +864,7 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * should be ordered so that each diff appears before any diff * that depends on it. */ - pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqIndexDiffs(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target, std::vector const &diffs=std::vector()); virtual ~pkgAcqIndexDiffs(); @@ -941,7 +942,7 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex virtual std::string DescURI() const {return Desc.URI;}; virtual std::string GetMetaKey() const; - pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaBase * const TransactionManager, + pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); virtual ~pkgAcqIndex(); diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 8d619e96d..c0f93f9ce 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -722,7 +722,7 @@ void pkgAcquire::Worker::PrepareFiles(char const * const caller, pkgAcquire::Que unlink(Owner->DestFile.c_str()); if (link(filename.c_str(), Owner->DestFile.c_str()) != 0) { - // diferent mounts can't happen for us as we download to lists/ by default, + // different mounts can't happen for us as we download to lists/ by default, // but if the system is reused by others the locations can potentially be on // different disks, so use symlink as poor-men replacement. // FIXME: Real copying as last fallback, but that is costly, so offload to a method preferable diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index ea3d45480..690776266 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -65,8 +65,8 @@ bool pkgCacheFile::BuildCaches(OpProgress *Progress, bool WithLock) if (_config->FindB("pkgCacheFile::Generate", true) == false) { - Map = new MMap(*new FileFd(_config->FindFile("Dir::Cache::pkgcache"), - FileFd::ReadOnly),MMap::Public|MMap::ReadOnly); + FileFd file(_config->FindFile("Dir::Cache::pkgcache"), FileFd::ReadOnly); + Map = new MMap(file, MMap::Public|MMap::ReadOnly); Cache = new pkgCache(Map); if (_error->PendingError() == true) return false; diff --git a/apt-pkg/contrib/cdromutl.cc b/apt-pkg/contrib/cdromutl.cc index 6eb917457..428ef0161 100644 --- a/apt-pkg/contrib/cdromutl.cc +++ b/apt-pkg/contrib/cdromutl.cc @@ -287,9 +287,11 @@ string FindMountPointForDevice(const char *devnode) fclose(f); // unescape the \0XXX chars in the path string mount_point = out[1]; + free(line); return DeEscapeString(mount_point); } fclose(f); + free(line); } return string(); diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index 9d798cca9..a01e319eb 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -296,6 +296,8 @@ bool SplitClearSignedFile(std::string const &InFile, FileFd * const ContentFile, // all the rest is whitespace, unsigned garbage or additional message blocks we ignore } fclose(in); + if (buf != NULL) + free(buf); if (found_signature == true) return _error->Error("Signature in file %s wasn't closed", InFile.c_str()); diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 026af077f..5a517b290 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -270,7 +270,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const // special case for --print-uris std::vector const targets = GetIndexTargets(); #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) - pkgAcqMetaBase * const TransactionManager = new pkgAcqMetaClearSig(Owner, + pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), targets, iR); #undef APT_TARGET diff --git a/apt-pkg/deb/debrecords.cc b/apt-pkg/deb/debrecords.cc index 326102d08..d78a7e2e0 100644 --- a/apt-pkg/deb/debrecords.cc +++ b/apt-pkg/deb/debrecords.cc @@ -42,10 +42,14 @@ debRecordParser::debRecordParser(string FileName,pkgCache &Cache) : // RecordParser::Jump - Jump to a specific record /*{{{*/ bool debRecordParser::Jump(pkgCache::VerFileIterator const &Ver) { + if (Ver.end() == true) + return false; return Tags.Jump(Section,Ver->Offset); } bool debRecordParser::Jump(pkgCache::DescFileIterator const &Desc) { + if (Desc.end() == true) + return false; return Tags.Jump(Section,Desc->Offset); } /*}}}*/ diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 1991a4a66..3594a6efe 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1484,6 +1484,10 @@ bool pkgDPkgPM::Go(APT::Progress::PackageManager *progress) a != Args.end(); ++a) clog << *a << ' '; clog << endl; + for (std::vector::const_iterator p = Packages.begin(); + p != Packages.end(); ++p) + free(*p); + Packages.clear(); continue; } Args.push_back(NULL); diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc index 5a93d826f..03ba59460 100644 --- a/apt-pkg/indexrecords.cc +++ b/apt-pkg/indexrecords.cc @@ -278,4 +278,7 @@ indexRecords::indexRecords(const string &ExpectedDist) : { } -indexRecords::~indexRecords() {} +indexRecords::~indexRecords() { + for (std::map::const_iterator S = Entries.begin(); S != Entries.end(); ++S) + delete S->second; +} diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 4c5505bf3..6d7d8185b 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -34,8 +34,10 @@ class pkgTagFilePrivate public: void Reset(FileFd * const pFd, unsigned long long const pSize) { - Fd = pFd; + if (Buffer != NULL) + free(Buffer); Buffer = NULL; + Fd = pFd; Start = NULL; End = NULL; Done = false; @@ -43,7 +45,7 @@ public: Size = pSize; } - pkgTagFilePrivate(FileFd * const pFd, unsigned long long const Size) + pkgTagFilePrivate(FileFd * const pFd, unsigned long long const Size) : Buffer(NULL) { Reset(pFd, Size); } @@ -54,6 +56,12 @@ public: bool Done; unsigned long long iOffset; unsigned long long Size; + + ~pkgTagFilePrivate() + { + if (Buffer != NULL) + free(Buffer); + } }; class pkgTagSectionPrivate @@ -127,7 +135,6 @@ void pkgTagFile::Init(FileFd * const pFd,unsigned long long Size) /* */ pkgTagFile::~pkgTagFile() { - free(d->Buffer); delete d; } /*}}}*/ diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 23238d979..d0d0c7a84 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -136,7 +136,7 @@ class pkgTagSection * * @param File to write the section to * @param Order in which tags should appear in the file - * @param Rewrite is a set of tags to be renamed, rewitten and/or removed + * @param Rewrite is a set of tags to be renamed, rewritten and/or removed * @return \b true if successful, otherwise \b false */ bool Write(FileFd &File, char const * const * const Order = NULL, std::vector const &Rewrite = std::vector()) const; diff --git a/apt-private/private-cacheset.h b/apt-private/private-cacheset.h index 059c7637e..0eb22b788 100644 --- a/apt-private/private-cacheset.h +++ b/apt-private/private-cacheset.h @@ -32,10 +32,15 @@ struct VersionSortDescriptionLocality bool operator () (const pkgCache::VerIterator &v_lhs, const pkgCache::VerIterator &v_rhs) { - pkgCache::DescFile *A = v_lhs.TranslatedDescription().FileList(); - pkgCache::DescFile *B = v_rhs.TranslatedDescription().FileList(); - if (A == 0 && B == 0) - return false; + pkgCache::DescFile const *A = NULL; + pkgCache::DescFile const *B = NULL; + if (v_lhs->DescriptionList != 0) + A = v_lhs.TranslatedDescription().FileList(); + if (v_rhs->DescriptionList != 0) + B = v_rhs.TranslatedDescription().FileList(); + + if (A == 0 && B == 0) + return false; if (A == 0) return true; diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 4e18030ab..9944ab002 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -199,10 +199,12 @@ static std::string GetShortDescription(pkgCacheFile &CacheFile, pkgRecords &reco std::string ShortDescription = "(none)"; if(ver) { - pkgCache::DescIterator Desc = ver.TranslatedDescription(); - pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); - - ShortDescription = parser.ShortDesc(); + pkgCache::DescIterator const Desc = ver.TranslatedDescription(); + if (Desc.end() == false) + { + pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); + ShortDescription = parser.ShortDesc(); + } } return ShortDescription; } @@ -222,11 +224,14 @@ static std::string GetLongDescription(pkgCacheFile &CacheFile, pkgRecords &recor return EmptyDescription; pkgCache::DescIterator const Desc = ver.TranslatedDescription(); - pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); - std::string const longdesc = parser.LongDesc(); - if (longdesc.empty() == true) - return EmptyDescription; - return SubstVar(longdesc, "\n ", "\n "); + if (Desc.end() == false) + { + pkgRecords::Parser & parser = records.Lookup(Desc.FileList()); + std::string const longdesc = parser.LongDesc(); + if (longdesc.empty() == false) + return SubstVar(longdesc, "\n ", "\n "); + } + return EmptyDescription; } /*}}}*/ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ diff --git a/buildlib/environment.mak.in b/buildlib/environment.mak.in index 0dff02e69..8ea7a05ba 100644 --- a/buildlib/environment.mak.in +++ b/buildlib/environment.mak.in @@ -16,6 +16,8 @@ CXXFLAGS+= -Wctor-dtor-privacy -Wdisabled-optimization -Winit-self -Wmissing-inc #CXXFLAGS+= -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=noreturn # gcc reports currently lots of them at the end of file - unknown reason CXXFLAGS+= -Wno-deprecated-declarations +# sanitize options to be enabled for testing +#CXXFLAGS+= -fsanitize=address -fsanitize=undefined -fno-sanitize=vptr # a bit too pedantic to be run by default #CXXFLAGS+= -Wpedantic -Wno-long-long -Wno-vla -Wno-variadic-macros NUM_PROCS = @NUM_PROCS@ diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 303605f70..9c884433c 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1484,6 +1484,7 @@ static bool Search(CommandLine &CmdL) delete [] PatternMatch; for (unsigned I = 0; I != NumPatterns; I++) regfree(&Patterns[I]); + delete [] Patterns; if (ferror(stdout)) return _error->Error("Write to stdout failed"); return true; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 184b51d23..632c7cfea 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1015,9 +1015,6 @@ static bool DoBuildDep(CommandLine &CmdL) pkgSourceList *List = Cache.GetSourceList(); // Create the text record parsers -#if APT_PKG_ABI < 413 - pkgRecords Recs(Cache); -#endif pkgSrcRecords SrcRecs(*List); if (_error->PendingError() == true) return false; @@ -1039,6 +1036,7 @@ static bool DoBuildDep(CommandLine &CmdL) { string Src; pkgSrcRecords::Parser *Last = 0; + SPtr LastOwner; // an unpacked debian source tree using APT::String::Startswith; @@ -1050,7 +1048,7 @@ static bool DoBuildDep(CommandLine &CmdL) std::string TypeName = "debian/control File Source Index"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) - Last = Type->CreateSrcPkgParser(*I); + LastOwner = Last = Type->CreateSrcPkgParser(*I); } // if its a local file (e.g. .dsc) use this else if (FileExists(*I)) @@ -1061,7 +1059,7 @@ static bool DoBuildDep(CommandLine &CmdL) string TypeName = flExtension(*I) + " File Source Index"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) - Last = Type->CreateSrcPkgParser(*I); + LastOwner = Last = Type->CreateSrcPkgParser(*I); } else { // normal case, search the cache for the source file #if APT_PKG_ABI >= 413 diff --git a/ftparchive/apt-ftparchive.cc b/ftparchive/apt-ftparchive.cc index 62108f7ca..cf667483c 100644 --- a/ftparchive/apt-ftparchive.cc +++ b/ftparchive/apt-ftparchive.cc @@ -180,7 +180,7 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats) // Create a package writer object. MultiCompress Comp(flCombine(ArchiveDir,PkgFile), PkgCompress,Permissions); - PackagesWriter Packages(&Comp.Input, flCombine(CacheDir,BinCacheDB), + PackagesWriter Packages(&Comp.Input, TransWriter, flCombine(CacheDir,BinCacheDB), flCombine(OverrideDir,BinOverride), flCombine(OverrideDir,ExtraOverride), Arch); @@ -193,7 +193,6 @@ bool PackageMap::GenPackages(Configuration &Setup,struct CacheDB::Stats &Stats) Packages.DirStrip = ArchiveDir; Packages.InternalPrefix = flCombine(ArchiveDir,InternalPrefix); - Packages.TransWriter = TransWriter; Packages.LongDescription = LongDesc; Packages.Stats.DeLinkBytes = Stats.DeLinkBytes; @@ -457,7 +456,7 @@ bool PackageMap::GenContents(Configuration &Setup, // --------------------------------------------------------------------- /* This populates the PkgList with all the possible permutations of the section/arch lists. */ -static void LoadTree(vector &PkgList,Configuration &Setup) +static void LoadTree(vector &PkgList, std::vector &TransList, Configuration &Setup) { // Load the defaults string DDir = Setup.Find("TreeDefault::Directory", @@ -508,16 +507,7 @@ static void LoadTree(vector &PkgList,Configuration &Setup) {NULL, NULL}}; mode_t const Perms = Block.FindI("FileMode", Permissions); bool const LongDesc = Block.FindB("LongDescription", LongDescription); - TranslationWriter *TransWriter; - if (DTrans.empty() == false && LongDesc == false) - { - string const TranslationFile = flCombine(Setup.FindDir("Dir::ArchiveDir"), - SubstVar(Block.Find("Translation", DTrans.c_str()), Vars)); - string const TransCompress = Block.Find("Translation::Compress", TranslationCompress); - TransWriter = new TranslationWriter(TranslationFile, TransCompress, Perms); - } - else - TransWriter = NULL; + TranslationWriter *TransWriter = NULL; string const Tmp2 = Block.Find("Architectures"); const char *Archs = Tmp2.c_str(); @@ -546,27 +536,34 @@ static void LoadTree(vector &PkgList,Configuration &Setup) Itm.Tag = SubstVar("$(DIST)/$(SECTION)/$(ARCH)",Vars); Itm.Arch = Arch; Itm.LongDesc = LongDesc; - if (TransWriter != NULL) + if (TransWriter == NULL && DTrans.empty() == false && LongDesc == false && DTrans != "/dev/null") { - TransWriter->IncreaseRefCounter(); - Itm.TransWriter = TransWriter; + string const TranslationFile = flCombine(Setup.FindDir("Dir::ArchiveDir"), + SubstVar(Block.Find("Translation", DTrans.c_str()), Vars)); + string const TransCompress = Block.Find("Translation::Compress", TranslationCompress); + TransWriter = new TranslationWriter(TranslationFile, TransCompress, Perms); + TransList.push_back(TransWriter); } + Itm.TransWriter = TransWriter; Itm.Contents = SubstVar(Block.Find("Contents",DContents.c_str()),Vars); Itm.ContentsHead = SubstVar(Block.Find("Contents::Header",DContentsH.c_str()),Vars); Itm.FLFile = SubstVar(Block.Find("FileList",DFLFile.c_str()),Vars); Itm.ExtraOverride = SubstVar(Block.Find("ExtraOverride"),Vars); } - Itm.GetGeneral(Setup,Block); + Itm.GetGeneral(Setup,Block); PkgList.push_back(Itm); } - // we didn't use this TransWriter, so we can release it - if (TransWriter != NULL && TransWriter->GetRefCounter() == 0) - delete TransWriter; } - + Top = Top->Next; - } + } +} + /*}}}*/ +static void UnloadTree(std::vector const &Trans) /*{{{*/ +{ + for (std::vector::const_reverse_iterator T = Trans.rbegin(); T != Trans.rend(); ++T) + delete *T; } /*}}}*/ // LoadBinDir - Load a 'bindirectory' section from the Generate Config /*{{{*/ @@ -671,7 +668,7 @@ static bool SimpleGenPackages(CommandLine &CmdL) Override = CmdL.FileList[2]; // Create a package writer object. - PackagesWriter Packages(NULL, _config->Find("APT::FTPArchive::DB"), + PackagesWriter Packages(NULL, NULL, _config->Find("APT::FTPArchive::DB"), Override, "", _config->Find("APT::FTPArchive::Architecture")); if (_error->PendingError() == true) return false; @@ -844,12 +841,6 @@ static bool DoGeneratePackagesAndSources(Configuration &Setup, delete [] List; } - - // close the Translation master files - for (vector::reverse_iterator I = PkgList.rbegin(); I != PkgList.rend(); ++I) - if (I->TransWriter != NULL && I->TransWriter->DecreaseRefCounter() == 0) - delete I->TransWriter; - return true; } @@ -940,7 +931,8 @@ static bool Generate(CommandLine &CmdL) return false; vector PkgList; - LoadTree(PkgList,Setup); + std::vector TransList; + LoadTree(PkgList, TransList, Setup); LoadBinDir(PkgList,Setup); // Sort by cache DB to improve IO locality. @@ -951,7 +943,10 @@ static bool Generate(CommandLine &CmdL) if (_config->FindB("APT::FTPArchive::ContentsOnly", false) == false) { if(DoGeneratePackagesAndSources(Setup, PkgList, SrcStats, Stats, CmdL) == false) + { + UnloadTree(TransList); return false; + } } else { c1out << "Skipping Packages/Sources generation" << endl; } @@ -959,7 +954,10 @@ static bool Generate(CommandLine &CmdL) // do Contents if needed if (_config->FindB("APT::FTPArchive::Contents", true) == true) if (DoGenerateContents(Setup, PkgList, CmdL) == false) - return false; + { + UnloadTree(TransList); + return false; + } struct timeval NewTime; gettimeofday(&NewTime,0); @@ -968,6 +966,7 @@ static bool Generate(CommandLine &CmdL) c1out << "Done. " << SizeToStr(Stats.Bytes) << "B in " << Stats.Packages << " archives. Took " << TimeToStr((long)Delta) << endl; + UnloadTree(TransList); return true; } @@ -984,9 +983,12 @@ static bool Clean(CommandLine &CmdL) Configuration Setup; if (ReadConfigFile(Setup,CmdL.FileList[1],true) == false) return false; + // we don't need translation creation here + Setup.Set("TreeDefault::Translation", "/dev/null"); vector PkgList; - LoadTree(PkgList,Setup); + std::vector TransList; + LoadTree(PkgList, TransList, Setup); LoadBinDir(PkgList,Setup); // Sort by cache DB to improve IO locality. @@ -1007,14 +1009,13 @@ static bool Clean(CommandLine &CmdL) _error->DumpErrors(); if (DB_SRC.Clean() == false) _error->DumpErrors(); - + string CacheDB = I->BinCacheDB; string SrcCacheDB = I->SrcCacheDB; while(I != PkgList.end() && I->BinCacheDB == CacheDB && I->SrcCacheDB == SrcCacheDB) ++I; - } diff --git a/ftparchive/cachedb.cc b/ftparchive/cachedb.cc index cc3527ea4..ce6c865f3 100644 --- a/ftparchive/cachedb.cc +++ b/ftparchive/cachedb.cc @@ -45,6 +45,7 @@ CacheDB::~CacheDB() { ReadyDB(); delete DebFile; + CloseFile(); } // CacheDB::ReadyDB - Ready the DB2 /*{{{*/ diff --git a/ftparchive/writer.cc b/ftparchive/writer.cc index 7cf7e6efc..1bc926d21 100644 --- a/ftparchive/writer.cc +++ b/ftparchive/writer.cc @@ -69,22 +69,29 @@ static void ConfigToDoHashes(unsigned int &DoHashes, std::string const &Conf) /*}}}*/ // FTWScanner::FTWScanner - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ FTWScanner::FTWScanner(FileFd * const GivenOutput, string const &Arch): Arch(Arch), DoHashes(~0) { if (GivenOutput == NULL) { Output = new FileFd; + OwnsOutput = true; Output->OpenDescriptor(STDOUT_FILENO, FileFd::WriteOnly, false); } else + { Output = GivenOutput; + OwnsOutput = false; + } ErrorPrinted = false; NoLinkAct = !_config->FindB("APT::FTPArchive::DeLinkAct",true); ConfigToDoHashes(DoHashes, "APT::FTPArchive"); } /*}}}*/ +FTWScanner::~FTWScanner() +{ + if (Output != NULL && OwnsOutput) + delete Output; +} // FTWScanner::Scanner - FTW Scanner /*{{{*/ // --------------------------------------------------------------------- /* This is the FTW scanner, it processes each directory element in the @@ -324,9 +331,10 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath, // PackagesWriter::PackagesWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ -PackagesWriter::PackagesWriter(FileFd * const GivenOutput, string const &DB,string const &Overrides,string const &ExtOverrides, - string const &Arch) : - FTWScanner(GivenOutput, Arch), Db(DB), Stats(Db.Stats), TransWriter(NULL) +PackagesWriter::PackagesWriter(FileFd * const GivenOutput, TranslationWriter * const transWriter, + string const &DB,string const &Overrides,string const &ExtOverrides, + string const &Arch) : + FTWScanner(GivenOutput, Arch), Db(DB), Stats(Db.Stats), TransWriter(transWriter) { SetExts(".deb .udeb"); DeLinkLimit = 0; @@ -377,7 +385,6 @@ bool FTWScanner::SetExts(string const &Vals) return true; } - /*}}}*/ // PackagesWriter::DoPackage - Process a single package /*{{{*/ // --------------------------------------------------------------------- @@ -524,12 +531,16 @@ bool PackagesWriter::DoPackage(string FileName) return Db.Finish(); } /*}}}*/ +PackagesWriter::~PackagesWriter() /*{{{*/ +{ +} + /*}}}*/ // TranslationWriter::TranslationWriter - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Create a Translation-Master file for this Packages file */ TranslationWriter::TranslationWriter(string const &File, string const &TransCompress, - mode_t const &Permissions) : RefCounter(0) + mode_t const &Permissions) : Comp(NULL), Output(NULL) { if (File.empty() == true) return; @@ -568,10 +579,8 @@ bool TranslationWriter::DoPackage(string const &Pkg, string const &Desc, /* */ TranslationWriter::~TranslationWriter() { - if (Comp == NULL) - return; - - delete Comp; + if (Comp != NULL) + delete Comp; } /*}}}*/ diff --git a/ftparchive/writer.h b/ftparchive/writer.h index 0ba60db5e..b9c1f672a 100644 --- a/ftparchive/writer.h +++ b/ftparchive/writer.h @@ -64,6 +64,7 @@ class FTWScanner public: FileFd *Output; + bool OwnsOutput; unsigned int DoHashes; unsigned long DeLinkLimit; @@ -79,7 +80,7 @@ class FTWScanner bool SetExts(string const &Vals); FTWScanner(FileFd * const Output, string const &Arch = string()); - virtual ~FTWScanner() {}; + virtual ~FTWScanner(); }; class MultiCompress; @@ -88,17 +89,12 @@ class TranslationWriter { MultiCompress *Comp; std::set Included; - unsigned short RefCounter; FileFd *Output; public: - void IncreaseRefCounter() { ++RefCounter; }; - unsigned short DecreaseRefCounter() { return (RefCounter == 0) ? 0 : --RefCounter; }; - unsigned short GetRefCounter() const { return RefCounter; }; bool DoPackage(string const &Pkg, string const &Desc, string const &MD5); TranslationWriter(string const &File, string const &TransCompress, mode_t const &Permissions); - TranslationWriter() : Comp(NULL), RefCounter(0) {}; ~TranslationWriter(); }; @@ -119,18 +115,18 @@ class PackagesWriter : public FTWScanner string PathPrefix; string DirStrip; struct CacheDB::Stats &Stats; - TranslationWriter *TransWriter; + TranslationWriter * const TransWriter; inline bool ReadOverride(string const &File) {return Over.ReadOverride(File);}; inline bool ReadExtraOverride(string const &File) {return Over.ReadExtraOverride(File);}; virtual bool DoPackage(string FileName); - PackagesWriter(FileFd * const Output, string const &DB, + PackagesWriter(FileFd * const Output, TranslationWriter * const TransWriter, string const &DB, string const &Overrides, string const &ExtOverrides = "", string const &Arch = ""); - virtual ~PackagesWriter() {}; + virtual ~PackagesWriter(); }; class ContentsWriter : public FTWScanner diff --git a/test/integration/framework b/test/integration/framework index 5d949009f..059cba9fb 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -143,6 +143,7 @@ gdb() { aptcache) CMD="apt-cache";; aptmark) CMD="apt-mark";; apthelper) CMD="apt-helper";; + aptftparchive) CMD="apt-ftparchive";; *) CMD="$1";; esac shift @@ -1415,6 +1416,8 @@ testfailure() { if expr match "$1" '^apt.*' >/dev/null; then if grep -q -E ' runtime error: ' "$OUTPUT"; then msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" + elif grep -q -E '==ERROR' "$OUTPUT"; then + msgfailoutput 'compiler sanitizers reported errors' "$OUTPUT" "$@" elif ! grep -q -E '^E: ' "$OUTPUT"; then msgfailoutput "run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" else diff --git a/test/libapt/cdrom_test.cc b/test/libapt/cdrom_test.cc index 7257eaf1b..b4c51cdb0 100644 --- a/test/libapt/cdrom_test.cc +++ b/test/libapt/cdrom_test.cc @@ -91,7 +91,7 @@ TEST(CDROMTest,ReduceSourcelist) } TEST(CDROMTest, FindMountPointForDevice) { - char * tempfile = NULL; + std::string tempfile; FileFd fd; createTemporaryFile("mountpoints", fd, &tempfile, "rootfs / rootfs rw 0 0\n" @@ -109,7 +109,6 @@ TEST(CDROMTest, FindMountPointForDevice) EXPECT_EQ("/boot/efi", FindMountPointForDevice("/dev/sda1")); EXPECT_EQ("/tmp", FindMountPointForDevice("tmpfs")); - if (tempfile != NULL) - unlink(tempfile); - free(tempfile); + if (tempfile.empty() == false) + unlink(tempfile.c_str()); } diff --git a/test/libapt/file-helpers.cc b/test/libapt/file-helpers.cc index 5edb9a9fe..387192868 100644 --- a/test/libapt/file-helpers.cc +++ b/test/libapt/file-helpers.cc @@ -53,20 +53,19 @@ void helperCreateLink(std::string const &dir, std::string const &targetname, std link.append(linkname); ASSERT_EQ(0, symlink(target.c_str(), link.c_str())); } -void helperCreateTemporaryFile(std::string const &id, FileFd &fd, char * * const filename, char const * const content) +void helperCreateTemporaryFile(std::string const &id, FileFd &fd, std::string * const filename, char const * const content) { std::string name("apt-test-"); name.append(id).append(".XXXXXXXX"); char * tempfile = strdup(name.c_str()); + ASSERT_STRNE(NULL, tempfile); int tempfile_fd = mkstemp(tempfile); ASSERT_NE(-1, tempfile_fd); if (filename != NULL) *filename = tempfile; else - { unlink(tempfile); - free(tempfile); - } + free(tempfile); EXPECT_TRUE(fd.OpenDescriptor(tempfile_fd, FileFd::ReadWrite)); if (content != NULL) diff --git a/test/libapt/file-helpers.h b/test/libapt/file-helpers.h index e8472d503..f639c1cbc 100644 --- a/test/libapt/file-helpers.h +++ b/test/libapt/file-helpers.h @@ -24,6 +24,6 @@ void helperCreateDirectory(std::string const &dir, std::string const &name); void helperCreateLink(std::string const &dir, std::string const &targetname, std::string const &linkname); #define createTemporaryFile(id, fd, filename, content) \ ASSERT_NO_FATAL_FAILURE(helperCreateTemporaryFile(id, fd, filename, content)) -void helperCreateTemporaryFile(std::string const &id, FileFd &fd, char * * const filename, char const * const content); +void helperCreateTemporaryFile(std::string const &id, FileFd &fd, std::string * const filename, char const * const content); #endif diff --git a/test/libapt/sourcelist_test.cc b/test/libapt/sourcelist_test.cc index 747ab4957..9e6f82213 100644 --- a/test/libapt/sourcelist_test.cc +++ b/test/libapt/sourcelist_test.cc @@ -20,7 +20,7 @@ class SourceList : public pkgSourceList { TEST(SourceListTest,ParseFileDeb822) { FileFd fd; - char * tempfile = NULL; + std::string tempfile; createTemporaryFile("parsefiledeb822", fd, &tempfile, "Types: deb\n" "URIs: http://ftp.debian.org/debian\n" @@ -39,5 +39,6 @@ TEST(SourceListTest,ParseFileDeb822) EXPECT_EQ(2, sources.ParseFileDeb822(tempfile)); EXPECT_EQ(2, sources.size()); - unlink(tempfile); + if (tempfile.empty() == false) + unlink(tempfile.c_str()); } -- cgit v1.2.3-70-g09d2 From 463c8d801595ce5ac94d7c032264820be7434232 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 21 Jun 2015 16:47:53 +0200 Subject: support lang= and target= sources.list options We support arch= for a while, now we finally add lang= as well and as a first simple way of controlling which targets to acquire also target=. This asked for a redesign of the internal API of parsing and storing information about 'deb' and 'deb-src' lines. As this API isn't visible to the outside no damage done through. Beside being a nice cleanup (= it actually does more in less lines) it also provides us with a predictable order of architectures as provides in the configuration rather than based on string sorting-order, so that now the native architecture is parsed/displayed first. Observeable e.g. in apt-get output. --- apt-pkg/deb/debindexfile.cc | 6 +- apt-pkg/deb/debmetaindex.cc | 430 +++++++++------------ apt-pkg/deb/debmetaindex.h | 38 +- apt-pkg/sourcelist.cc | 40 +- apt-pkg/sourcelist.h | 8 +- cmdline/apt-get.cc | 4 +- doc/sources.list.5.xml | 16 + .../test-bug-632221-cross-dependency-satisfaction | 22 +- .../test-ignore-provides-if-versioned-breaks | 10 +- .../test-ignore-provides-if-versioned-conflicts | 10 +- .../test-sourceslist-lang-plusminus-options | 87 +++++ 11 files changed, 354 insertions(+), 317 deletions(-) create mode 100755 test/integration/test-sourceslist-lang-plusminus-options (limited to 'test') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 29a9a941c..c5086b04b 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -510,7 +510,7 @@ class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { return new debDebFileRecordParser(File.FileName()); }; - debIFTypeDebPkgFile() {Label = "deb Package file";}; + debIFTypeDebPkgFile() {Label = "Debian deb file";}; }; class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { @@ -519,7 +519,7 @@ class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { return new debDscRecordParser(DscFile, NULL); }; - debIFTypeDscFile() {Label = "dsc File Source Index";}; + debIFTypeDscFile() {Label = "Debian dsc file";}; }; class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { @@ -528,7 +528,7 @@ class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); }; - debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";}; + debIFTypeDebianSourceDir() {Label = "Debian control file";}; }; APT_HIDDEN debIFTypeSrc _apt_Src; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 5a517b290..f690a8d64 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -29,11 +29,25 @@ #include #include -using namespace std; - -string debReleaseIndex::MetaIndexInfo(const char *Type) const +class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ +{ + public: + struct APT_HIDDEN debSectionEntry + { + std::string Name; + std::vector Targets; + std::vector Architectures; + std::vector Languages; + }; + + std::vector DebEntries; + std::vector DebSrcEntries; +}; + /*}}}*/ +// ReleaseIndex::MetaIndex* - display helpers /*{{{*/ +std::string debReleaseIndex::MetaIndexInfo(const char *Type) const { - string Info = ::URI::ArchiveOnly(URI) + ' '; + std::string Info = ::URI::ArchiveOnly(URI) + ' '; if (Dist[Dist.size() - 1] == '/') { if (Dist != "/") @@ -50,15 +64,15 @@ std::string debReleaseIndex::Describe() const return MetaIndexInfo("Release"); } -string debReleaseIndex::MetaIndexFile(const char *Type) const +std::string debReleaseIndex::MetaIndexFile(const char *Type) const { return _config->FindDir("Dir::State::lists") + URItoFileName(MetaIndexURI(Type)); } -string debReleaseIndex::MetaIndexURI(const char *Type) const +std::string debReleaseIndex::MetaIndexURI(const char *Type) const { - string Res; + std::string Res; if (Dist == "/") Res = URI; @@ -70,8 +84,8 @@ string debReleaseIndex::MetaIndexURI(const char *Type) const Res += Type; return Res; } - -std::string debReleaseIndex::LocalFileName() const + /*}}}*/ +std::string debReleaseIndex::LocalFileName() const /*{{{*/ { // see if we have a InRelease file std::string PathInRelease = MetaIndexFile("InRelease"); @@ -84,28 +98,24 @@ std::string debReleaseIndex::LocalFileName() const return ""; } - -debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist) : - metaIndex(URI, Dist, "deb"), d(NULL), Trusted(CHECK_TRUST) + /*}}}*/ +// ReleaseIndex Con- and Destructors /*{{{*/ +debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) : + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()), Trusted(CHECK_TRUST) {} - -debReleaseIndex::debReleaseIndex(string const &URI, string const &Dist, bool const Trusted) : - metaIndex(URI, Dist, "deb"), d(NULL) { +debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted) : + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) { SetTrusted(Trusted); } - debReleaseIndex::~debReleaseIndex() { - for (map >::const_iterator A = ArchEntries.begin(); - A != ArchEntries.end(); ++A) - for (vector::const_iterator S = A->second.begin(); - S != A->second.end(); ++S) - delete *S; + if (d != NULL) + delete d; } - -template -void foreachTarget(std::string const &URI, std::string const &Dist, - std::map > const &ArchEntries, - CallC &Call) + /*}}}*/ +// ReleaseIndex::GetIndexTargets /*{{{*/ +static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const &Dist, + std::vector const &entries, + std::vector &IndexTargets) { bool const flatArchive = (Dist[Dist.length() - 1] == '/'); std::string baseURI = URI; @@ -118,148 +128,101 @@ void foreachTarget(std::string const &URI, std::string const &Dist, baseURI += "dists/" + Dist + "/"; std::string const Release = (Dist == "/") ? "" : Dist; std::string const Site = ::URI::ArchiveOnly(URI); - std::vector lang = APT::Configuration::getLanguages(true); - if (lang.empty()) - lang.push_back("none"); - map >::const_iterator const src = ArchEntries.find("source"); - if (src != ArchEntries.end()) + + for (std::vector::const_iterator E = entries.begin(); E != entries.end(); ++E) { - std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb-src", "", true); - for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) + for (std::vector::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T) { -#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb-src::") + *T + "::" + (X)) - std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); - std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); - std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); +#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::" + (X)) + std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); + std::string const tplShortDesc = APT_T_CONFIG("ShortDescription"); + std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); #undef APT_T_CONFIG - if (MetaKey.empty()) + if (tplMetaKey.empty()) continue; - vector const SectionEntries = src->second; - for (vector::const_iterator I = SectionEntries.begin(); - I != SectionEntries.end(); ++I) + for (std::vector::const_iterator L = E->Languages.begin(); L != E->Languages.end(); ++L) { - for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) + if (*L == "none" && tplMetaKey.find("$(LANGUAGE)") != std::string::npos) + continue; + + for (std::vector::const_iterator A = E->Architectures.begin(); A != E->Architectures.end(); ++A) { - if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) - continue; std::map Options; Options.insert(std::make_pair("SITE", Site)); Options.insert(std::make_pair("RELEASE", Release)); - if (MetaKey.find("$(COMPONENT)") != std::string::npos) - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - if (MetaKey.find("$(LANGUAGE)") != std::string::npos) - Options.insert(std::make_pair("LANGUAGE", *l)); - Options.insert(std::make_pair("ARCHITECTURE", "source")); + if (tplMetaKey.find("$(COMPONENT)") != std::string::npos) + Options.insert(std::make_pair("COMPONENT", E->Name)); + if (tplMetaKey.find("$(LANGUAGE)") != std::string::npos) + Options.insert(std::make_pair("LANGUAGE", *L)); + if (tplMetaKey.find("$(ARCHITECTURE)") != std::string::npos) + Options.insert(std::make_pair("ARCHITECTURE", *A)); Options.insert(std::make_pair("BASE_URI", baseURI)); Options.insert(std::make_pair("REPO_URI", URI)); Options.insert(std::make_pair("TARGET_OF", "deb-src")); Options.insert(std::make_pair("CREATED_BY", *T)); - Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); - if (MetaKey.find("$(LANGUAGE)") == std::string::npos) + std::string MetaKey = tplMetaKey; + std::string ShortDesc = tplShortDesc; + std::string LongDesc = tplLongDesc; + for (std::map::const_iterator O = Options.begin(); O != Options.end(); ++O) + { + MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second); + ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second); + LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second); + } + IndexTarget Target( + MetaKey, + ShortDesc, + LongDesc, + Options.find("BASE_URI")->second + MetaKey, + IsOptional, + Options + ); + IndexTargets.push_back(Target); + + if (tplMetaKey.find("$(ARCHITECTURE)") == std::string::npos) break; - } - - if (MetaKey.find("$(COMPONENT)") == std::string::npos) - break; - } - } - } - - std::vector const targets = _config->FindVector("APT::Acquire::Targets::deb", "", true); - for (std::vector::const_iterator T = targets.begin(); T != targets.end(); ++T) - { -#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::deb::") + *T + "::" + (X)) - std::string const MetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); - std::string const ShortDesc = APT_T_CONFIG("ShortDescription"); - std::string const LongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); - bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb::") + *T + "::Optional", true); -#undef APT_T_CONFIG - if (MetaKey.empty()) - continue; - - for (map >::const_iterator a = ArchEntries.begin(); - a != ArchEntries.end(); ++a) - { - if (a->first == "source") - continue; - - for (vector ::const_iterator I = a->second.begin(); - I != a->second.end(); ++I) { - - for (vector::const_iterator l = lang.begin(); l != lang.end(); ++l) - { - if (*l == "none" && MetaKey.find("$(LANGUAGE)") != std::string::npos) - continue; - - std::map Options; - Options.insert(std::make_pair("SITE", Site)); - Options.insert(std::make_pair("RELEASE", Release)); - if (MetaKey.find("$(COMPONENT)") != std::string::npos) - Options.insert(std::make_pair("COMPONENT", (*I)->Section)); - if (MetaKey.find("$(LANGUAGE)") != std::string::npos) - Options.insert(std::make_pair("LANGUAGE", *l)); - if (MetaKey.find("$(ARCHITECTURE)") != std::string::npos) - Options.insert(std::make_pair("ARCHITECTURE", a->first)); - Options.insert(std::make_pair("BASE_URI", baseURI)); - Options.insert(std::make_pair("REPO_URI", URI)); - Options.insert(std::make_pair("TARGET_OF", "deb")); - Options.insert(std::make_pair("CREATED_BY", *T)); - Call(MetaKey, ShortDesc, LongDesc, IsOptional, Options); - if (MetaKey.find("$(LANGUAGE)") == std::string::npos) - break; } - if (MetaKey.find("$(COMPONENT)") == std::string::npos) + if (tplMetaKey.find("$(LANGUAGE)") == std::string::npos) break; + } - if (MetaKey.find("$(ARCHITECTURE)") == std::string::npos) - break; } } } - - -struct ComputeIndexTargetsClass -{ - vector IndexTargets; - - void operator()(std::string MetaKey, std::string ShortDesc, std::string LongDesc, - bool const IsOptional, std::map Options) - { - for (std::map::const_iterator O = Options.begin(); O != Options.end(); ++O) - { - MetaKey = SubstVar(MetaKey, std::string("$(") + O->first + ")", O->second); - ShortDesc = SubstVar(ShortDesc, std::string("$(") + O->first + ")", O->second); - LongDesc = SubstVar(LongDesc, std::string("$(") + O->first + ")", O->second); - } - IndexTarget Target( - MetaKey, - ShortDesc, - LongDesc, - Options.find("BASE_URI")->second + MetaKey, - IsOptional, - Options - ); - IndexTargets.push_back(Target); - } -}; - std::vector debReleaseIndex::GetIndexTargets() const { - ComputeIndexTargetsClass comp; - foreachTarget(URI, Dist, ArchEntries, comp); - return comp.IndexTargets; + std::vector IndexTargets; + GetIndexTargetsFor("deb-src", URI, Dist, d->DebSrcEntries, IndexTargets); + GetIndexTargetsFor("deb", URI, Dist, d->DebEntries, IndexTargets); + return IndexTargets; } + /*}}}*/ +void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{{{*/ + std::vector const &Targets, + std::vector const &Architectures, + std::vector Languages) +{ + if (Languages.empty() == true) + Languages.push_back("none"); + debReleaseIndexPrivate::debSectionEntry const entry = { + Name, Targets, Architectures, Languages + }; + if (isSrc) + d->DebSrcEntries.push_back(entry); + else + d->DebEntries.push_back(entry); +} + /*}}}*/ - /*}}}*/ -bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const +bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{{{*/ { indexRecords * const iR = new indexRecords(Dist); if (Trusted == ALWAYS_TRUSTED) @@ -282,7 +245,8 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const return true; } - + /*}}}*/ +// ReleaseIndex::*Trusted setters and checkers /*{{{*/ void debReleaseIndex::SetTrusted(bool const Trusted) { if (Trusted == true) @@ -290,7 +254,6 @@ void debReleaseIndex::SetTrusted(bool const Trusted) else this->Trusted = NEVER_TRUSTED; } - bool debReleaseIndex::IsTrusted() const { if (Trusted == ALWAYS_TRUSTED) @@ -303,19 +266,13 @@ bool debReleaseIndex::IsTrusted() const if(URI.substr(0,strlen("cdrom:")) == "cdrom:") return true; - string VerifiedSigFile = _config->FindDir("Dir::State::lists") + - URItoFileName(MetaIndexURI("Release")) + ".gpg"; - - if (FileExists(VerifiedSigFile)) + if (FileExists(MetaIndexFile("Release.gpg"))) return true; - VerifiedSigFile = _config->FindDir("Dir::State::lists") + - URItoFileName(MetaIndexURI("InRelease")); - - return FileExists(VerifiedSigFile); + return FileExists(MetaIndexFile("InRelease")); } - -std::vector *debReleaseIndex::GetIndexFiles() + /*}}}*/ +std::vector *debReleaseIndex::GetIndexFiles() /*{{{*/ { if (Indexes != NULL) return Indexes; @@ -335,23 +292,9 @@ std::vector *debReleaseIndex::GetIndexFiles() } return Indexes; } + /*}}}*/ -void debReleaseIndex::PushSectionEntry(vector const &Archs, const debSectionEntry *Entry) { - for (vector::const_iterator a = Archs.begin(); - a != Archs.end(); ++a) - ArchEntries[*a].push_back(new debSectionEntry(Entry->Section, Entry->IsSrc)); - delete Entry; -} - -void debReleaseIndex::PushSectionEntry(string const &Arch, const debSectionEntry *Entry) { - ArchEntries[Arch].push_back(Entry); -} - -debReleaseIndex::debSectionEntry::debSectionEntry (string const &Section, - bool const &IsSrc): Section(Section), IsSrc(IsSrc) -{} - -static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile) +static bool ReleaseFileName(debReleaseIndex const * const That, std::string &ReleaseFile)/*{{{*/ { ReleaseFile = That->MetaIndexFile("InRelease"); bool releaseExists = false; @@ -365,7 +308,7 @@ static bool ReleaseFileName(debReleaseIndex const * const That, std::string &Rel } return releaseExists; } - + /*}}}*/ bool debReleaseIndex::Merge(pkgCacheGenerator &Gen,OpProgress * /*Prog*/) const/*{{{*/ { std::string ReleaseFile; @@ -459,46 +402,46 @@ pkgCache::RlsFileIterator debReleaseIndex::FindInCache(pkgCache &Cache, bool con } /*}}}*/ -debDebFileMetaIndex::~debDebFileMetaIndex() {} - -class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type +static std::vector parsePlusMinusOptions(std::string const &Name, /*{{{*/ + std::map const &Options, std::vector const &defaultValues) { - protected: + std::map::const_iterator val = Options.find(Name); + std::vector Values; + if (val != Options.end()) + Values = VectorizeString(val->second, ','); + else + Values = defaultValues; - bool CreateItemInternal(vector &List, string const &URI, - string const &Dist, string const &Section, - bool const &IsSrc, map const &Options) const + if ((val = Options.find(Name + "+")) != Options.end()) { - // parse arch=, arch+= and arch-= settings - map::const_iterator arch = Options.find("arch"); - vector Archs; - if (arch != Options.end()) - Archs = VectorizeString(arch->second, ','); - else - Archs = APT::Configuration::getArchitectures(); - - if ((arch = Options.find("arch+")) != Options.end()) - { - std::vector const plusArch = VectorizeString(arch->second, ','); - for (std::vector::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus) - if (std::find(Archs.begin(), Archs.end(), *plus) == Archs.end()) - Archs.push_back(*plus); - } - if ((arch = Options.find("arch-")) != Options.end()) + std::vector const plusArch = VectorizeString(val->second, ','); + for (std::vector::const_iterator plus = plusArch.begin(); plus != plusArch.end(); ++plus) + if (std::find(Values.begin(), Values.end(), *plus) == Values.end()) + Values.push_back(*plus); + } + if ((val = Options.find(Name + "-")) != Options.end()) + { + std::vector const minusArch = VectorizeString(val->second, ','); + for (std::vector::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus) { - std::vector const minusArch = VectorizeString(arch->second, ','); - for (std::vector::const_iterator minus = minusArch.begin(); minus != minusArch.end(); ++minus) - { - std::vector::iterator kill = std::find(Archs.begin(), Archs.end(), *minus); - if (kill != Archs.end()) - Archs.erase(kill); - } + std::vector::iterator kill = std::find(Values.begin(), Values.end(), *minus); + if (kill != Values.end()) + Values.erase(kill); } + } + return Values; +} + /*}}}*/ +class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ +{ + protected: - map::const_iterator const trusted = Options.find("trusted"); - + bool CreateItemInternal(std::vector &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + bool const &IsSrc, std::map const &Options) const + { debReleaseIndex *Deb = NULL; - for (vector::const_iterator I = List.begin(); + for (std::vector::const_iterator I = List.begin(); I != List.end(); ++I) { // We only worry about debian entries here @@ -523,87 +466,86 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type List.push_back(Deb); } - if (IsSrc == true) - Deb->PushSectionEntry ("source", new debReleaseIndex::debSectionEntry(Section, IsSrc)); - else - { - if (Dist[Dist.size() - 1] == '/') - Deb->PushSectionEntry ("any", new debReleaseIndex::debSectionEntry(Section, IsSrc)); - else - Deb->PushSectionEntry (Archs, new debReleaseIndex::debSectionEntry(Section, IsSrc)); - } + Deb->AddComponent( + IsSrc, + Section, + parsePlusMinusOptions("target", Options, _config->FindVector(std::string("APT::Acquire::Targets::") + Name, "", true)), + parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()), + parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) + ); + std::map::const_iterator const trusted = Options.find("trusted"); if (trusted != Options.end()) Deb->SetTrusted(StringToBool(trusted->second, false)); return true; } -}; - -debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) - : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile) -{ - DebIndex = new debDebPkgFileIndex(DebFile); - Indexes = new vector(); - Indexes->push_back(DebIndex); -} - -class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian + debSLTypeDebian(char const * const Name, char const * const Label) : Type(Name, Label) + { + } +}; + /*}}}*/ +class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian /*{{{*/ { public: - bool CreateItem(vector &List, string const &URI, - string const &Dist, string const &Section, - std::map const &Options) const + bool CreateItem(std::vector &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + std::map const &Options) const { return CreateItemInternal(List, URI, Dist, Section, false, Options); } - debSLTypeDeb() + debSLTypeDeb() : debSLTypeDebian("deb", "Debian binary tree") { - Name = "deb"; - Label = "Standard Debian binary tree"; - } + } }; - -class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian + /*}}}*/ +class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian /*{{{*/ { public: - bool CreateItem(vector &List, string const &URI, - string const &Dist, string const &Section, - std::map const &Options) const + bool CreateItem(std::vector &List, std::string const &URI, + std::string const &Dist, std::string const &Section, + std::map const &Options) const { return CreateItemInternal(List, URI, Dist, Section, true, Options); } - - debSLTypeDebSrc() + + debSLTypeDebSrc() : debSLTypeDebian("deb-src", "Debian source tree") { - Name = "deb-src"; - Label = "Standard Debian source tree"; - } + } }; + /*}}}*/ -class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type +debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) /*{{{*/ + : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile) +{ + DebIndex = new debDebPkgFileIndex(DebFile); + Indexes = new std::vector(); + Indexes->push_back(DebIndex); +} +debDebFileMetaIndex::~debDebFileMetaIndex() {} + /*}}}*/ +class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type /*{{{*/ { public: - bool CreateItem(vector &List, string const &URI, - string const &/*Dist*/, string const &/*Section*/, - std::map const &/*Options*/) const + bool CreateItem(std::vector &List, std::string const &URI, + std::string const &/*Dist*/, std::string const &/*Section*/, + std::map const &/*Options*/) const { metaIndex *mi = new debDebFileMetaIndex(URI); List.push_back(mi); return true; } - - debSLTypeDebFile() + + debSLTypeDebFile() : Type("deb-file", "Debian local deb file") { - Name = "deb-file"; - Label = "Debian Deb File"; - } + } }; + /*}}}*/ APT_HIDDEN debSLTypeDeb _apt_DebType; APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 648c22436..9b60b6137 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -1,4 +1,3 @@ -// ijones, walters #ifndef PKGLIB_DEBMETAINDEX_H #define PKGLIB_DEBMETAINDEX_H @@ -22,26 +21,20 @@ class debDebPkgFileIndex; class IndexTarget; class pkgCacheGenerator; class OpProgress; +class debReleaseIndexPrivate; -class APT_HIDDEN debReleaseIndex : public metaIndex { - public: +class APT_HIDDEN debReleaseIndex : public metaIndex +{ + debReleaseIndexPrivate * const d; - class debSectionEntry - { - public: - debSectionEntry (std::string const &Section, bool const &IsSrc); - std::string const Section; - bool const IsSrc; - }; - - private: - /** \brief dpointer placeholder (for later in case we need it) */ - void * const d; - std::map > ArchEntries; enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted; public: + APT_HIDDEN std::string MetaIndexInfo(const char *Type) const; + APT_HIDDEN std::string MetaIndexFile(const char *Types) const; + APT_HIDDEN std::string MetaIndexURI(const char *Type) const; + debReleaseIndex(std::string const &URI, std::string const &Dist); debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted); virtual ~debReleaseIndex(); @@ -54,22 +47,17 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - std::string MetaIndexInfo(const char *Type) const; - std::string MetaIndexFile(const char *Types) const; - std::string MetaIndexURI(const char *Type) const; - -#if APT_PKG_ABI >= 413 - virtual -#endif - std::string LocalFileName() const; + virtual std::string LocalFileName() const; virtual std::vector *GetIndexFiles(); void SetTrusted(bool const Trusted); virtual bool IsTrusted() const; - void PushSectionEntry(std::vector const &Archs, const debSectionEntry *Entry); - void PushSectionEntry(std::string const &Arch, const debSectionEntry *Entry); + void AddComponent(bool const isSrc, std::string const &Name, + std::vector const &Targets, + std::vector const &Architectures, + std::vector Languages); }; class APT_HIDDEN debDebFileMetaIndex : public metaIndex diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 99b646513..6ef99863d 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -37,25 +37,26 @@ using namespace std; // Global list of Items supported -static pkgSourceList::Type *ItmList[10]; +static pkgSourceList::Type *ItmList[10]; pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList; unsigned long pkgSourceList::Type::GlobalListLen = 0; // Type::Type - Constructor /*{{{*/ // --------------------------------------------------------------------- /* Link this to the global list of items*/ -pkgSourceList::Type::Type() : Name(NULL), Label(NULL) +pkgSourceList::Type::Type(char const * const pName, char const * const pLabel) : Name(pName), Label(pLabel) { ItmList[GlobalListLen] = this; - GlobalListLen++; + ++GlobalListLen; } +pkgSourceList::Type::~Type() {} /*}}}*/ // Type::GetType - Get a specific meta for a given type /*{{{*/ // --------------------------------------------------------------------- /* */ pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type) { - for (unsigned I = 0; I != GlobalListLen; I++) + for (unsigned I = 0; I != GlobalListLen; ++I) if (strcmp(GlobalList[I]->Name,Type) == 0) return GlobalList[I]; return 0; @@ -91,23 +92,26 @@ bool pkgSourceList::Type::ParseStanza(vector &List, string Enabled = Tags.FindS("Enabled"); if (Enabled.size() > 0 && StringToBool(Enabled) == false) return true; - - // Define external/internal options - const char* option_deb822[] = { - "Architectures", "Architectures-Add", "Architectures-Remove", "Trusted", - }; - const char* option_internal[] = { - "arch", "arch+", "arch-", "trusted", - }; - for (unsigned int j=0; j < sizeof(option_deb822)/sizeof(char*); j++) - if (Tags.Exists(option_deb822[j])) + + std::map mapping; +#define APT_PLUSMINUS(X, Y) \ + mapping.insert(std::make_pair(X, Y)); \ + mapping.insert(std::make_pair(X "Add", Y "+")); \ + mapping.insert(std::make_pair(X "Remove", Y "-")) + APT_PLUSMINUS("Architectures", "arch"); + APT_PLUSMINUS("Languages", "lang"); + APT_PLUSMINUS("Targets", "target"); +#undef APT_PLUSMINUS + mapping.insert(std::make_pair("Trusted", "trusted")); + for (std::map::const_iterator m = mapping.begin(); m != mapping.end(); ++m) + if (Tags.Exists(m->first)) { // for deb822 the " " is the delimiter, but the backend expects "," - std::string option = Tags.FindS(option_deb822[j]); + std::string option = Tags.FindS(m->first); std::replace(option.begin(), option.end(), ' ', ','); - Options[option_internal[j]] = option; + Options[m->second] = option; } - + // now create one item per suite/section string Suite = Tags.FindS("Suites"); Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture")); @@ -209,7 +213,7 @@ bool pkgSourceList::Type::ParseLine(vector &List, if (FixupURI(URI) == false) return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str()); - + // Check for an absolute dists specification. if (Dist.empty() == false && Dist[Dist.size() - 1] == '/') { diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index e17ad6a9a..4f42b3e91 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -66,8 +66,8 @@ class pkgSourceList static unsigned long GlobalListLen; static Type *GetType(const char *Type) APT_PURE; - const char *Name; - const char *Label; + char const * const Name; + char const * const Label; bool FixupURI(std::string &URI) const; virtual bool ParseStanza(std::vector &List, @@ -80,8 +80,8 @@ class pkgSourceList virtual bool CreateItem(std::vector &List,std::string const &URI, std::string const &Dist,std::string const &Section, std::map const &Options) const = 0; - Type(); - virtual ~Type() {}; + Type(char const * const Name, char const * const Label); + virtual ~Type(); }; typedef std::vector::const_iterator const_iterator; diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 632c7cfea..500a0a3c5 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1045,7 +1045,7 @@ static bool DoBuildDep(CommandLine &CmdL) { ioprintf(c1out, _("Note, using directory '%s' to get the build dependencies\n"), *I); // FIXME: how can we make this more elegant? - std::string TypeName = "debian/control File Source Index"; + std::string TypeName = "Debian control file"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) LastOwner = Last = Type->CreateSrcPkgParser(*I); @@ -1056,7 +1056,7 @@ static bool DoBuildDep(CommandLine &CmdL) ioprintf(c1out, _("Note, using file '%s' to get the build dependencies\n"), *I); // see if we can get a parser for this pkgIndexFile type - string TypeName = flExtension(*I) + " File Source Index"; + string TypeName = "Debian " + flExtension(*I) + " file"; pkgIndexFile::Type *Type = pkgIndexFile::Type::GetType(TypeName.c_str()); if(Type != NULL) LastOwner = Last = Type->CreateSrcPkgParser(*I); diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index da4f571b5..6ebba3528 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -137,9 +137,25 @@ can be used to specify for which architectures information should be downloaded. If this option is not set all architectures defined by the APT::Architectures option will be downloaded. + arch+=arch1,arch2,… and arch-=arch1,arch2,… which can be used to add/remove architectures from the set which will be downloaded. + + lang=lang1,lang2,…, + lang+=lang1,lang2,… and + lang-=lang1,lang2,… functioning in + the same way as the arch-options described before. They can be used to specify for + which languages apt will acquire metadata, like translated package descriptions, for. If not specified, the + default set is defined by the Acquire::Languages config option. + + target=target1,target2,…, + target+=target1,target2,… and + target-=target1,target2,… again functioning in + the same way as the arch-options described before. They can be used to specify which + targets apt will try to acquire from this source. If not specified, the default set is defined by + the APT::Acquire::Targets configuration scope. + trusted=yes can be set to indicate that packages from this source are always authenticated even if the Release file is not signed or the signature can't be checked. This disables parts of &apt-secure; diff --git a/test/integration/test-bug-632221-cross-dependency-satisfaction b/test/integration/test-bug-632221-cross-dependency-satisfaction index 563821173..12704e5de 100755 --- a/test/integration/test-bug-632221-cross-dependency-satisfaction +++ b/test/integration/test-bug-632221-cross-dependency-satisfaction @@ -167,17 +167,17 @@ Conf libfwibble-dev (1.0 unstable [armel])' aptget build-dep apt -s testsuccessequal 'Reading package lists... Building dependency tree... The following NEW packages will be installed: - amdboot:amd64 cool doxygen foreigner libc6:amd64 libc6 libc6-dev:amd64 - libc6-dev libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64 + amdboot:amd64 cool doxygen foreigner libc6 libc6:amd64 libc6-dev + libc6-dev:amd64 libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64 0 upgraded, 11 newly installed, 0 to remove and 0 not upgraded. Inst amdboot:amd64 (1.0 unstable [amd64]) Inst cool (1.0 unstable [armel]) Inst doxygen (1.0 unstable [armel]) Inst foreigner (1.0 unstable [armel]) -Inst libc6:amd64 (1.0 unstable [amd64]) Inst libc6 (1.0 unstable [armel]) -Inst libc6-dev:amd64 (1.0 unstable [amd64]) +Inst libc6:amd64 (1.0 unstable [amd64]) Inst libc6-dev (1.0 unstable [armel]) +Inst libc6-dev:amd64 (1.0 unstable [amd64]) Inst libfwibble1:amd64 (1.0 unstable [amd64]) Inst libfwibble-dev:amd64 (1.0 unstable [amd64]) Inst linux-stuff:amd64 (1.0 unstable [amd64]) @@ -185,10 +185,10 @@ Conf amdboot:amd64 (1.0 unstable [amd64]) Conf cool (1.0 unstable [armel]) Conf doxygen (1.0 unstable [armel]) Conf foreigner (1.0 unstable [armel]) -Conf libc6:amd64 (1.0 unstable [amd64]) Conf libc6 (1.0 unstable [armel]) -Conf libc6-dev:amd64 (1.0 unstable [amd64]) +Conf libc6:amd64 (1.0 unstable [amd64]) Conf libc6-dev (1.0 unstable [armel]) +Conf libc6-dev:amd64 (1.0 unstable [amd64]) Conf libfwibble1:amd64 (1.0 unstable [amd64]) Conf libfwibble-dev:amd64 (1.0 unstable [amd64]) Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64 @@ -275,24 +275,24 @@ Conf libfwibble-dev (1.0 unstable [armel])' aptget build-dep apt -s testsuccessequal 'Reading package lists... Building dependency tree... The following NEW packages will be installed: - amdboot:amd64 doxygen libc6:amd64 libc6 libc6-dev:amd64 libc6-dev + amdboot:amd64 doxygen libc6 libc6:amd64 libc6-dev libc6-dev:amd64 libfwibble-dev:amd64 libfwibble1:amd64 linux-stuff:amd64 0 upgraded, 9 newly installed, 0 to remove and 2 not upgraded. Inst amdboot:amd64 (1.0 unstable [amd64]) Inst doxygen (1.0 unstable [armel]) -Inst libc6:amd64 (1.0 unstable [amd64]) Inst libc6 (1.0 unstable [armel]) -Inst libc6-dev:amd64 (1.0 unstable [amd64]) +Inst libc6:amd64 (1.0 unstable [amd64]) Inst libc6-dev (1.0 unstable [armel]) +Inst libc6-dev:amd64 (1.0 unstable [amd64]) Inst libfwibble1:amd64 (1.0 unstable [amd64]) Inst libfwibble-dev:amd64 (1.0 unstable [amd64]) Inst linux-stuff:amd64 (1.0 unstable [amd64]) Conf amdboot:amd64 (1.0 unstable [amd64]) Conf doxygen (1.0 unstable [armel]) -Conf libc6:amd64 (1.0 unstable [amd64]) Conf libc6 (1.0 unstable [armel]) -Conf libc6-dev:amd64 (1.0 unstable [amd64]) +Conf libc6:amd64 (1.0 unstable [amd64]) Conf libc6-dev (1.0 unstable [armel]) +Conf libc6-dev:amd64 (1.0 unstable [amd64]) Conf libfwibble1:amd64 (1.0 unstable [amd64]) Conf libfwibble-dev:amd64 (1.0 unstable [amd64]) Conf linux-stuff:amd64 (1.0 unstable [amd64])' aptget build-dep apt -s -a amd64 diff --git a/test/integration/test-ignore-provides-if-versioned-breaks b/test/integration/test-ignore-provides-if-versioned-breaks index 20424b942..4d6114637 100755 --- a/test/integration/test-ignore-provides-if-versioned-breaks +++ b/test/integration/test-ignore-provides-if-versioned-breaks @@ -134,17 +134,17 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f testsuccessequal 'Reading package lists... Building dependency tree... The following extra packages will be installed: - foo-same:amd64 foo-same + foo-same foo-same:amd64 The following NEW packages will be installed: foo-same-breaker-3 foo-same-provider The following packages will be upgraded: - foo-same:amd64 foo-same + foo-same foo-same:amd64 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. -Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) [foo-same:amd64 on foo-same:i386] [foo-same:i386 on foo-same:amd64] [foo-same:i386 ] -Inst foo-same [2.0] (4.0 unstable [i386]) +Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo-same:amd64 on foo-same:i386] [foo-same:amd64 ] +Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) Inst foo-same-breaker-3 (1.0 unstable [i386]) Inst foo-same-provider (1.0 unstable [i386]) -Conf foo-same (4.0 unstable [i386]) Conf foo-same:amd64 (4.0 unstable [amd64]) +Conf foo-same (4.0 unstable [i386]) Conf foo-same-breaker-3 (1.0 unstable [i386]) Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s diff --git a/test/integration/test-ignore-provides-if-versioned-conflicts b/test/integration/test-ignore-provides-if-versioned-conflicts index a781d8e44..6a0c924e2 100755 --- a/test/integration/test-ignore-provides-if-versioned-conflicts +++ b/test/integration/test-ignore-provides-if-versioned-conflicts @@ -134,17 +134,17 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f testsuccessequal 'Reading package lists... Building dependency tree... The following extra packages will be installed: - foo-same:amd64 foo-same + foo-same foo-same:amd64 The following NEW packages will be installed: foo-same-breaker-3 foo-same-provider The following packages will be upgraded: - foo-same:amd64 foo-same + foo-same foo-same:amd64 2 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. -Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) [foo-same:amd64 on foo-same:i386] [foo-same:i386 on foo-same:amd64] [foo-same:i386 ] -Inst foo-same [2.0] (4.0 unstable [i386]) +Inst foo-same [2.0] (4.0 unstable [i386]) [foo-same:i386 on foo-same:amd64] [foo-same:amd64 on foo-same:i386] [foo-same:amd64 ] +Inst foo-same:amd64 [2.0] (4.0 unstable [amd64]) Inst foo-same-breaker-3 (1.0 unstable [i386]) Inst foo-same-provider (1.0 unstable [i386]) -Conf foo-same (4.0 unstable [i386]) Conf foo-same:amd64 (4.0 unstable [amd64]) +Conf foo-same (4.0 unstable [i386]) Conf foo-same-breaker-3 (1.0 unstable [i386]) Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider foo-same-breaker-3 -s diff --git a/test/integration/test-sourceslist-lang-plusminus-options b/test/integration/test-sourceslist-lang-plusminus-options new file mode 100755 index 000000000..28d5f9e06 --- /dev/null +++ b/test/integration/test-sourceslist-lang-plusminus-options @@ -0,0 +1,87 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'native' + +testlangs() { + msgtest 'Test acquired languages for' "$1" + local LANGS="$2" + shift 2 + rm -f gotlangs.list + aptget files --no-release-info 'Created-By: Translations' "$@" --format '$(LANGUAGE)' | sort -u > gotlangs.list + if [ -z "$LANGS" ]; then + echo -n | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail + else + echo -n "$LANGS" | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail + fi +} +echo 'deb http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'default' 'en' + +echo 'Acquire::Languages "environment,en";' > rootdir/etc/apt/apt.conf.d/langs.conf +testlangs 'default config' 'en' + +echo 'Acquire::Languages "en,en,en";' > rootdir/etc/apt/apt.conf.d/langs.conf +testlangs 'duplicated config' 'en' + +echo 'Acquire::Languages "none";' > rootdir/etc/apt/apt.conf.d/langs.conf +testlangs 'none config' '' + +echo 'Acquire::Languages "en,none,de,de_DE";' > rootdir/etc/apt/apt.conf.d/langs.conf +testlangs 'english + german config' 'en,de,de_DE' + +echo 'deb [lang=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang=pt' 'pt' + +echo 'deb [lang=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang=en' 'en' + +echo 'deb [lang=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang=de_DE' 'de_DE' + +echo 'deb [lang=none] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang=none' '' +testequal 'amd64' aptget files --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)' + +echo 'deb [lang+=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang+=pt' 'en,de,de_DE,pt' + +echo 'deb [lang+=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang+=en' 'en,de,de_DE' + +echo 'deb [lang+=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang+=de_DE' 'en,de,de_DE' + +echo 'deb [lang-=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang-=pt' 'en,de,de_DE' + +echo 'deb [lang-=en] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang-=en' 'de,de_DE' + +echo 'deb [lang-=de_DE] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list +testlangs 'lang-=de_DE' 'en,de' + +echo 'deb http://example.org/debian stable rocks +deb http://example.org/debian stable solid' > rootdir/etc/apt/sources.list +testlangs 'english + german config multicomponent' 'en,de,de_DE' + +echo 'deb http://example.org/debian stable rocks +deb [lang=pt] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list +testlangs 'multicomponent one lang= combined' 'en,de,de_DE,pt' +testlangs 'multicomponent one lang= rocks' 'en,de,de_DE' 'Component: rocks' +testlangs 'multicomponent one lang= solid' 'pt' 'Component: solid' + +echo 'deb [lang=pt] http://example.org/debian stable rocks +deb [lang=de] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list +testlangs 'multicomponent different lang= combined' 'de,pt' +testlangs 'multicomponent different lang= rocks' 'pt' 'Component: rocks' +testlangs 'multicomponent different lang= solid' 'de' 'Component: solid' + +echo 'deb [lang+=pt] http://example.org/debian stable rocks +deb [lang-=de] http://example.org/debian stable solid' > rootdir/etc/apt/sources.list +testlangs 'multicomponent different lang+-= combined' 'en,de,de_DE,pt' +testlangs 'multicomponent different lang+-= rocks' 'en,de,de_DE,pt' 'Component: rocks' +testlangs 'multicomponent different lang+-= solid' 'en,de_DE' 'Component: solid' -- cgit v1.2.3-70-g09d2 From 81460e32961bb0b9922bf8a1a27d87705d8c3e51 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 21 Jun 2015 23:12:24 +0200 Subject: bring back deb822 sources.list entries as .sources Having two different formats in the same file is very dirty and causes external tools to fail hard trying to parse them. It is probably not a good idea for them to parse them in the first place, but they do and we shouldn't break them if there is a better way. So we solve this issue for now by giving our deb822 format a new filename extension ".sources" which unsupporting applications are likely to ignore an can begin gradually moving forward rather than waiting for the unknown applications to catch up. Currently and for the forseeable future apt is going to support both with the same feature set as documented in the manpage, with the longtime plan of adopting the 'new' format as default, but that is a long way to go and might get going more from having an easier time setting options than from us pushing it explicitely. --- apt-pkg/policy.cc | 19 +- apt-pkg/sourcelist.cc | 228 ++++++++++----------- apt-pkg/sourcelist.h | 16 +- apt-pkg/tagfile.cc | 8 + apt-pkg/tagfile.h | 8 + doc/sources.list.5.xml | 337 +++++++++++++++++++++---------- test/integration/test-apt-sources-deb822 | 75 +++++-- test/libapt/file-helpers.cc | 11 +- test/libapt/sourcelist_test.cc | 15 +- vendor/README | 8 +- vendor/blankon/apt-vendor.ent | 9 + vendor/debian/apt-vendor.ent | 12 ++ vendor/debian/sources.list.in | 3 +- vendor/raspbian/apt-vendor.ent | 6 + vendor/steamos/apt-vendor.ent | 7 + vendor/steamos/sources.list.in | 4 +- vendor/tanglu/apt-vendor.ent | 6 + vendor/ubuntu/apt-vendor.ent | 13 ++ 18 files changed, 500 insertions(+), 285 deletions(-) (limited to 'test') diff --git a/apt-pkg/policy.cc b/apt-pkg/policy.cc index cd48e040c..170da7c63 100644 --- a/apt-pkg/policy.cc +++ b/apt-pkg/policy.cc @@ -396,21 +396,6 @@ APT_PURE signed short pkgPolicy::GetPriority(pkgCache::PkgFileIterator const &Fi return PFPriority[File->ID]; } /*}}}*/ -// PreferenceSection class - Overriding the default TrimRecord method /*{{{*/ -// --------------------------------------------------------------------- -/* The preference file is a user generated file so the parser should - therefore be a bit more friendly by allowing comments and new lines - all over the place rather than forcing a special format */ -class PreferenceSection : public pkgTagSection -{ - void TrimRecord(bool /*BeforeRecord*/, const char* &End) - { - for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) - if (Stop[0] == '#') - Stop = (const char*) memchr(Stop,'\n',End-Stop); - } -}; - /*}}}*/ // ReadPinDir - Load the pin files from this dir into a Policy /*{{{*/ // --------------------------------------------------------------------- /* This will load each pin file in the given dir into a Policy. If the @@ -455,8 +440,8 @@ bool ReadPinFile(pkgPolicy &Plcy,string File) pkgTagFile TF(&Fd); if (_error->PendingError() == true) return false; - - PreferenceSection Tags; + + pkgUserTagSection Tags; while (TF.Step(Tags) == true) { // can happen when there are only comments in a record diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 6ef99863d..69f7ac043 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -82,15 +82,15 @@ bool pkgSourceList::Type::FixupURI(string &URI) const return true; } /*}}}*/ -bool pkgSourceList::Type::ParseStanza(vector &List, +bool pkgSourceList::Type::ParseStanza(vector &List, /*{{{*/ pkgTagSection &Tags, - int i, + unsigned int const i, FileFd &Fd) { map Options; string Enabled = Tags.FindS("Enabled"); - if (Enabled.size() > 0 && StringToBool(Enabled) == false) + if (Enabled.empty() == false && StringToBool(Enabled) == false) return true; std::map mapping; @@ -115,46 +115,63 @@ bool pkgSourceList::Type::ParseStanza(vector &List, // now create one item per suite/section string Suite = Tags.FindS("Suites"); Suite = SubstVar(Suite,"$(ARCH)",_config->Find("APT::Architecture")); - string const Section = Tags.FindS("Sections"); - string URIS = Tags.FindS("URIs"); + string const Component = Tags.FindS("Components"); + string const URIS = Tags.FindS("URIs"); + + std::vector const list_uris = VectorizeString(URIS, ' '); + std::vector const list_suite = VectorizeString(Suite, ' '); + std::vector const list_comp = VectorizeString(Component, ' '); + + if (list_uris.empty()) + // TRANSLATOR: %u is a line number, the first %s is a filename of a file with the extension "second %s" and the third %s is a unique identifier for bugreports + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI"); - std::vector list_uris = StringSplit(URIS, " "); - std::vector list_dist = StringSplit(Suite, " "); - std::vector list_section = StringSplit(Section, " "); - for (std::vector::const_iterator U = list_uris.begin(); U != list_uris.end(); ++U) { - std::string URI = (*U); - if (!FixupURI(URI)) - { - _error->Error(_("Malformed stanza %u in source list %s (URI parse)"),i,Fd.Name().c_str()); - return false; - } + std::string URI = *U; + if (U->empty() || FixupURI(URI) == false) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "URI parse"); + + if (list_suite.empty()) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Suite"); - for (std::vector::const_iterator I = list_dist.begin(); - I != list_dist.end(); ++I) + for (std::vector::const_iterator S = list_suite.begin(); + S != list_suite.end(); ++S) { - for (std::vector::const_iterator J = list_section.begin(); - J != list_section.end(); ++J) - { - if (CreateItem(List, URI, (*I), (*J), Options) == false) - { - return false; - } - } + if (S->empty() == false && (*S)[S->size() - 1] == '/') + { + if (list_comp.empty() == false) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "absolute Suite Component"); + if (CreateItem(List, URI, *S, "", Options) == false) + return false; + } + else + { + if (list_comp.empty()) + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), i, "sources", Fd.Name().c_str(), "Component"); + + for (std::vector::const_iterator C = list_comp.begin(); + C != list_comp.end(); ++C) + { + if (CreateItem(List, URI, *S, *C, Options) == false) + { + return false; + } + } + } } } return true; } - + /*}}}*/ // Type::ParseLine - Parse a single line /*{{{*/ // --------------------------------------------------------------------- /* This is a generic one that is the 'usual' format for sources.list Weird types may override this. */ bool pkgSourceList::Type::ParseLine(vector &List, const char *Buffer, - unsigned long const &CurLine, + unsigned int const CurLine, string const &File) const { for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces @@ -171,10 +188,10 @@ bool pkgSourceList::Type::ParseLine(vector &List, // get one option, e.g. option1=value1 string option; if (ParseQuoteWord(Buffer,option) == false) - return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] unparseable"); if (option.length() < 3) - return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] too short"); // accept options even if the last has no space before the ]-end marker if (option.at(option.length()-1) == ']') @@ -185,16 +202,16 @@ bool pkgSourceList::Type::ParseLine(vector &List, size_t const needle = option.find('='); if (needle == string::npos) - return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] not assignment"); string const key = string(option, 0, needle); string const value = string(option, needle + 1, option.length()); if (key.empty() == true) - return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no key"); if (value.empty() == true) - return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "[option] no value"); Options[key] = value; } @@ -207,33 +224,33 @@ bool pkgSourceList::Type::ParseLine(vector &List, string Section; if (ParseQuoteWord(Buffer,URI) == false) - return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI"); if (ParseQuoteWord(Buffer,Dist) == false) - return _error->Error(_("Malformed line %lu in source list %s (dist)"),CurLine,File.c_str()); - + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Suite"); + if (FixupURI(URI) == false) - return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "URI parse"); // Check for an absolute dists specification. if (Dist.empty() == false && Dist[Dist.size() - 1] == '/') { if (ParseQuoteWord(Buffer,Section) == true) - return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str()); + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "absolute Suite Component"); Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture")); return CreateItem(List, URI, Dist, Section, Options); } - + // Grab the rest of the dists if (ParseQuoteWord(Buffer,Section) == false) - return _error->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine,File.c_str()); - + return _error->Error(_("Malformed entry %u in %s file %s (%s)"), CurLine, "list", File.c_str(), "Component"); + do { if (CreateItem(List, URI, Dist, Section, Options) == false) return false; } while (ParseQuoteWord(Buffer,Section) == true); - + return true; } /*}}}*/ @@ -242,11 +259,6 @@ bool pkgSourceList::Type::ParseLine(vector &List, /* */ pkgSourceList::pkgSourceList() : d(NULL) { -} - -pkgSourceList::pkgSourceList(string File) : d(NULL) -{ - Read(File); } /*}}}*/ // SourceList::~pkgSourceList - Destructor /*{{{*/ @@ -305,7 +317,7 @@ void pkgSourceList::Reset() // SourceList::Read - Parse the sourcelist file /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::Read(string File) +bool pkgSourceList::Read(string const &File) { Reset(); return ReadAppend(File); @@ -314,71 +326,63 @@ bool pkgSourceList::Read(string File) // SourceList::ReadAppend - Parse a sourcelist file /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ReadAppend(string File) +bool pkgSourceList::ReadAppend(string const &File) { - if (_config->FindB("APT::Sources::Use-Deb822", false) == true) - { - int lines_parsed =ParseFileDeb822(File); - if (lines_parsed < 0) - return false; - else if (lines_parsed > 0) - return true; - // no lines parsed ... fall through and use old style parser - } - return ParseFileOldStyle(File); + if (flExtension(File) == "sources") + return ParseFileDeb822(File); + else + return ParseFileOldStyle(File); } // SourceList::ReadFileOldStyle - Read Traditional style sources.list /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ParseFileOldStyle(string File) +bool pkgSourceList::ParseFileOldStyle(std::string const &File) { // Open the stream for reading ifstream F(File.c_str(),ios::in /*| ios::nocreate*/); if (F.fail() == true) return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str()); - // CNC:2003-12-10 - 300 is too short. - char Buffer[1024]; - - int CurLine = 0; - while (F.eof() == false) + std::string Buffer; + for (unsigned int CurLine = 1; std::getline(F, Buffer); ++CurLine) { - F.getline(Buffer,sizeof(Buffer)); - CurLine++; - _strtabexpand(Buffer,sizeof(Buffer)); - if (F.fail() && !F.eof()) - return _error->Error(_("Line %u too long in source list %s."), - CurLine,File.c_str()); - - - char *I; - // CNC:2003-02-20 - Do not break if '#' is inside []. - for (I = Buffer; *I != 0 && *I != '#'; I++) - if (*I == '[') - { - char *b_end = strchr(I + 1, ']'); - if (b_end != NULL) - I = b_end; - } - *I = 0; - - const char *C = _strstrip(Buffer); - - // Comment or blank - if (C[0] == '#' || C[0] == 0) + // remove comments + size_t curpos = 0; + while ((curpos = Buffer.find('#', curpos)) != std::string::npos) + { + size_t const openbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, '['); + size_t const closedbrackets = std::count(Buffer.begin(), Buffer.begin() + curpos, ']'); + if (openbrackets > closedbrackets) + { + // a # in an option, unlikely, but oh well, it was supported so stick to it + ++curpos; + continue; + } + Buffer.erase(curpos); + break; + } + // remove spaces before/after + curpos = Buffer.find_first_not_of(" \t\r"); + if (curpos != 0) + Buffer.erase(0, curpos); + curpos = Buffer.find_last_not_of(" \t\r"); + if (curpos != std::string::npos) + Buffer.erase(curpos + 1); + + if (Buffer.empty()) continue; - + // Grok it - string LineType; - if (ParseQuoteWord(C,LineType) == false) + std::string const LineType = Buffer.substr(0, Buffer.find(' ')); + if (LineType.empty() || LineType == Buffer) return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str()); Type *Parse = Type::GetType(LineType.c_str()); if (Parse == 0) return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str()); - - if (Parse->ParseLine(SrcList, C, CurLine, File) == false) + + if (Parse->ParseLine(SrcList, Buffer.c_str() + LineType.length(), CurLine, File) == false) return false; } return true; @@ -387,30 +391,25 @@ bool pkgSourceList::ParseFileOldStyle(string File) // SourceList::ParseFileDeb822 - Parse deb822 style sources.list /*{{{*/ // --------------------------------------------------------------------- /* Returns: the number of stanzas parsed*/ -int pkgSourceList::ParseFileDeb822(string File) +bool pkgSourceList::ParseFileDeb822(string const &File) { - pkgTagSection Tags; - unsigned int i=0; + pkgUserTagSection Tags; + unsigned int i = 1; // see if we can read the file - _error->PushToStack(); FileFd Fd(File, FileFd::ReadOnly); pkgTagFile Sources(&Fd); if (_error->PendingError() == true) - { - _error->RevertToStack(); - return 0; - } - _error->MergeWithStack(); - + return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str()); + // read step by step while (Sources.Step(Tags) == true) { - if(!Tags.Exists("Types")) - continue; + if(Tags.Exists("Types") == false) + return _error->Error(_("Malformed stanza %u in source list %s (type)"),i,File.c_str()); string const types = Tags.FindS("Types"); - std::vector list_types = StringSplit(types, " "); + std::vector const list_types = VectorizeString(types, ' '); for (std::vector::const_iterator I = list_types.begin(); I != list_types.end(); ++I) { @@ -418,18 +417,16 @@ int pkgSourceList::ParseFileDeb822(string File) if (Parse == 0) { _error->Error(_("Type '%s' is not known on stanza %u in source list %s"), (*I).c_str(),i,Fd.Name().c_str()); - return -1; + return false; } - + if (!Parse->ParseStanza(SrcList, Tags, i, Fd)) - return -1; + return false; - i++; + ++i; } } - - // we are done, return the number of stanzas read - return i; + return true; } /*}}}*/ // SourceList::FindIndex - Get the index associated with a file /*{{{*/ @@ -471,9 +468,12 @@ bool pkgSourceList::GetIndexes(pkgAcquire *Owner, bool GetAll) const // Based on ReadConfigDir() /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgSourceList::ReadSourceDir(string Dir) +bool pkgSourceList::ReadSourceDir(string const &Dir) { - vector const List = GetListOfFilesInDir(Dir, "list", true); + std::vector ext; + ext.push_back("list"); + ext.push_back("sources"); + std::vector const List = GetListOfFilesInDir(Dir, ext, true); // Read the files for (vector::const_iterator I = List.begin(); I != List.end(); ++I) diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index 4f42b3e91..079f3cb3d 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -72,11 +72,11 @@ class pkgSourceList bool FixupURI(std::string &URI) const; virtual bool ParseStanza(std::vector &List, pkgTagSection &Tags, - int stanza_n, + unsigned int const stanza_n, FileFd &Fd); virtual bool ParseLine(std::vector &List, const char *Buffer, - unsigned long const &CurLine,std::string const &File) const; + unsigned int const CurLine,std::string const &File) const; virtual bool CreateItem(std::vector &List,std::string const &URI, std::string const &Dist,std::string const &Section, std::map const &Options) const = 0; @@ -90,18 +90,19 @@ class pkgSourceList std::vector SrcList; - int ParseFileDeb822(std::string File); - bool ParseFileOldStyle(std::string File); + private: + APT_HIDDEN bool ParseFileDeb822(std::string const &File); + APT_HIDDEN bool ParseFileOldStyle(std::string const &File); public: bool ReadMainList(); - bool Read(std::string File); + bool Read(std::string const &File); // CNC:2003-03-03 void Reset(); - bool ReadAppend(std::string File); - bool ReadSourceDir(std::string Dir); + bool ReadAppend(std::string const &File); + bool ReadSourceDir(std::string const &Dir); // List accessors inline const_iterator begin() const {return SrcList.begin();}; @@ -117,7 +118,6 @@ class pkgSourceList time_t GetLastModifiedTime(); pkgSourceList(); - explicit pkgSourceList(std::string File); virtual ~pkgSourceList(); }; diff --git a/apt-pkg/tagfile.cc b/apt-pkg/tagfile.cc index 6d7d8185b..cc63b213f 100644 --- a/apt-pkg/tagfile.cc +++ b/apt-pkg/tagfile.cc @@ -775,6 +775,14 @@ bool pkgTagSection::Write(FileFd &File, char const * const * const Order, std::v } /*}}}*/ +void pkgUserTagSection::TrimRecord(bool /*BeforeRecord*/, const char* &End)/*{{{*/ +{ + for (; Stop < End && (Stop[0] == '\n' || Stop[0] == '\r' || Stop[0] == '#'); Stop++) + if (Stop[0] == '#') + Stop = (const char*) memchr(Stop,'\n',End-Stop); +} + /*}}}*/ + #include "tagfile-order.c" // TFRewrite - Rewrite a control record /*{{{*/ diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index d0d0c7a84..81fff89f0 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -142,6 +142,14 @@ class pkgTagSection bool Write(FileFd &File, char const * const * const Order = NULL, std::vector const &Rewrite = std::vector()) const; }; + +/* For user generated file the parser should be a bit more relaxed in exchange + for being a bit slower to allow comments and new lines all over the place */ +class pkgUserTagSection : public pkgTagSection +{ + virtual void TrimRecord(bool BeforeRecord, const char* &End); +}; + class pkgTagFilePrivate; class pkgTagFile { diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index 6ebba3528..8506017ad 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -31,37 +31,99 @@ Description - The source list /etc/apt/sources.list is designed to support - any number of active sources and a variety of source media. The file lists one - source per line, with the most preferred source listed first. The information available - from the configured sources is acquired by apt-get update - (or by an equivalent command from another APT front-end). - - - Each line specifying a source starts with type (e.g. deb-src) - followed by options and arguments for this type. - Individual entries cannot be continued onto a following line. Empty lines - are ignored, and a # character anywhere on a line marks - the remainder of that line as a comment. + The source list /etc/apt/sources.list and the the + files contained in /etc/apt/sources.list.d/ are + designed to support any number of active sources and a variety of source + media. The files list one source per line (one line style) or contain multiline + stanzas defining one or more sources per stanza (deb822 style), with the + most preferred source listed first. The information available from the + configured sources is acquired by apt-get update (or + by an equivalent command from another APT front-end). sources.list.d - The /etc/apt/sources.list.d directory provides - a way to add sources.list entries in separate files. - The format is the same as for the regular sources.list file. - File names need to end with - .list and may only contain letters (a-z and A-Z), - digits (0-9), underscore (_), hyphen (-) and period (.) characters. - Otherwise APT will print a notice that it has ignored a file, unless that - file matches a pattern in the Dir::Ignore-Files-Silently - configuration list - in which case it will be silently ignored. + The /etc/apt/sources.list.d directory provides + a way to add sources.list entries in separate files. + Two different file formats are allowed as described in the next two sections. + Filenames need to have either the extension .list or + .sources depending on the contained format. + The filenames may only contain letters (a-z and A-Z), + digits (0-9), underscore (_), hyphen (-) and period (.) characters. + Otherwise APT will print a notice that it has ignored a file, unless that + file matches a pattern in the Dir::Ignore-Files-Silently + configuration list - in which case it will be silently ignored. - The deb and deb-src types + one line style format + + Files in this format have the extension .list. + Each line specifying a source starts with a type (e.g. deb-src) + followed by options and arguments for this type. + + Individual entries cannot be continued onto a following line. Empty lines + are ignored, and a # character anywhere on a line marks + the remainder of that line as a comment. Consequently an entry can be + disabled by commenting out the entire line. + + If options should be provided they are separated by spaces and all of + them together are enclosed by square brackets ([]) + included in the line after the type separated from it with a space. + If an option allows multiple values these are separated from each other + with a comma (,). An option name is separated from its + value(s) by a equal sign (=). Multivalue options have + also -= and += as separator which + instead of replacing the default with the given value(s) modify the default + value(s) to remove or include the given values. + + This is the traditional format and supported by all apt versions. + Note that not all options as described below are supported by all apt versions. + Note also that some older applications parsing this format on its own might not + expect to encounter options as they were uncommon before the introduction of + multi-architecture support. + + + + deb822 style format + + Files in this format have the extension .sources. + The format is similar in syntax to other files used by Debian and its + derivatives, like the metadata itself apt will download from the configured + sources or the debian/control file in a Debian source package. + + Individual entries are separated by an empty line, additional empty + lines are ignored, and a # character at the start of + the line marks the entire line as a comment. An entry can hence be + disabled by commenting out each line belonging to the stanza, but it is + usually easier to add the field "Enabled: no" to the stanza to disable + the entry. Removing the field or setting it to yes reenables it. + + Options have the same syntax as every other field: A fieldname separated by + a colon (:) and optionally spaces from its value(s). + Note especially that multiple values are separated by spaces, not by + commas as in the one line format. Multivalue fields like Architectures + also have Architectures-Add and Architectures-Remove + to modify the default value rather than replacing it. + + This is a new format supported by apt itself since version 1.1. Previous + versions ignore such files with a notice message as described earlier. + It is intended to make this format gradually the default format and + deprecating the previously described one line style format as it is + easier to create, extend and modify by humans and machines alike + especially if a lot of sources and/or options are involved. + + Developers who are working with and/or parsing apt sources are highly + encouraged to add support for this format and to contact the APT team + to coordinate and share this work. Users can freely adopt this format + already, but could encounter problems with software not supporting + the format yet. + + + + The deb and deb-src types: General Format The deb type references a typical two-level Debian archive, distribution/component. The - distribution is generally an archive name like + distribution is generally a suite name like stable or testing or a codename like &stable-codename; or &testing-codename; while component is one of main, contrib or @@ -70,42 +132,33 @@ code in the same form as the deb type. A deb-src line is required to fetch source indexes. - The format for a sources.list entry using the + The format for two one line style entries using the deb and deb-src types is: - deb [ options ] uri suite [component1] [component2] [...] + deb [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...] +deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [...] - Alternatively a rfc822 style format is also supported: + Alternatively the equivalent entry in deb822 style looks like this: Types: deb deb-src - URIs: http://example.com - Suites: stable testing - Sections: component1 component2 - Description: short - long long long - [option1]: [option1-value] - - Types: deb - URIs: http://another.example.com - Suites: experimental - Sections: component1 component2 - Enabled: no - Description: short - long long long - [option1]: [option1-value] + URIs: uri + Suites: suite + Components: [component1] [component2] [...] + option1: value1 + option2: value2 The URI for the deb type must specify the base of the - Debian distribution, from which APT will find the information it needs. - suite can specify an exact path, in which case the + Debian distribution, from which APT will find the information it needs. + suite can specify an exact path, in which case the components must be omitted and suite must end with a slash (/). This is useful for the case when only a - particular sub-section of the archive denoted by the URI is of interest. + particular sub-directory of the archive denoted by the URI is of interest. If suite does not specify an exact path, at least one component must be present. - suite may also contain a variable, + suite may also contain a variable, $(ARCH) which expands to the Debian architecture (such as amd64 or armel) used on the system. This permits architecture-independent @@ -113,67 +166,80 @@ of interest when specifying an exact path, APT will automatically generate a URI with the current architecture otherwise. - In the traditional style sources.list format since only one - distribution can be specified per line it may be necessary to have - multiple lines for the same URI, if a subset of all available - distributions or components at that location is desired. APT will - sort the URI list after it has generated a complete set internally, - and will collapse multiple references to the same Internet host, - for instance, into a single connection, so that it does not - inefficiently establish an FTP connection, close it, do something - else, and then re-establish a connection to that same host. This - feature is useful for accessing busy FTP sites with limits on the - number of simultaneous anonymous users. APT also parallelizes - connections to different hosts to more effectively deal with sites - with low bandwidth. - - options is always optional and needs to be surrounded by - square brackets. It can consist of multiple settings in the form - setting=value. - Multiple settings are separated by spaces. The following settings are supported by APT - (note however that unsupported settings will be ignored silently): - - arch=arch1,arch2,… - can be used to specify for which architectures information should - be downloaded. If this option is not set all architectures defined by the - APT::Architectures option will be downloaded. - - arch+=arch1,arch2,… - and arch-=arch1,arch2,… - which can be used to add/remove architectures from the set which will be downloaded. - - lang=lang1,lang2,…, - lang+=lang1,lang2,… and - lang-=lang1,lang2,… functioning in - the same way as the arch-options described before. They can be used to specify for - which languages apt will acquire metadata, like translated package descriptions, for. If not specified, the - default set is defined by the Acquire::Languages config option. - - target=target1,target2,…, - target+=target1,target2,… and - target-=target1,target2,… again functioning in - the same way as the arch-options described before. They can be used to specify which - targets apt will try to acquire from this source. If not specified, the default set is defined by - the APT::Acquire::Targets configuration scope. - - trusted=yes can be set to indicate that packages - from this source are always authenticated even if the Release file - is not signed or the signature can't be checked. This disables parts of &apt-secure; - and should therefore only be used in a local and trusted context. trusted=no - is the opposite which handles even correctly authenticated sources as not authenticated. - + Especially in the one line style format since only one distribution + can be specified per line it may be necessary to have multiple lines for + the same URI, if a subset of all available distributions or components at + that location is desired. APT will sort the URI list after it has + generated a complete set internally, and will collapse multiple + references to the same Internet host, for instance, into a single + connection, so that it does not inefficiently establish a + connection, close it, do something else, and then re-establish a + connection to that same host. APT also parallelizes connections to + different hosts to more effectively deal with sites with low + bandwidth. It is important to list sources in order of preference, with the most preferred source listed first. Typically this will result in sorting by speed from fastest to slowest (CD-ROM followed by hosts on a local network, followed by distant Internet hosts, for example). - Some examples: - -deb http://ftp.debian.org/debian &stable-codename; main contrib non-free -deb http://security.debian.org/ &stable-codename;/updates main contrib non-free - + As an example, the sources for your distribution could look like this + in one line style format: + &sourceslist-list-format; or like this in + deb822 style format: + &sourceslist-sources-format; + + The deb and deb-src types: Options + Each source entry can have options specified modifying which and how + the source is accessed and data acquired from it. Format, syntax and names + of the options varies between the two formats one line and deb822 style + as described, but they have both the same options available. For simplicity + we list the deb822 fieldname and provide the one line name in brackets. + Remember that beside setting multivalue options explicitly, there is also + the option to modify them based on the default, but we aren't listing those + names explicitly here. Unsupported options are silently ignored by all + APT versions. + + + Architectures + (arch) is a multivalue option defining for + which architectures information should be downloaded. If this + option isn't set the default is all architectures as defined by + the APT::Architectures config option. + + + Languages + (lang) is a multivalue option defining for + which languages information like translated package + descriptions should be downloaded. If this option isn't set + the default is all languages as defined by the + Acquire::Languages config option. + + + Targets + (target) is a multivalue option defining + which download targets apt will try to acquire from this + source. If not specified, the default set is defined by the + APT::Acquire::Targets configuration scope. + + + Trusted (trusted) + is a tri-state value which defaults to APT deciding if a source + is considered trusted or if warnings should be raised before e.g. + packages are installed from this source. This option can be used + to override this decision either with the value yes, + which lets APT consider this source always as a trusted source + even if it has no or fails authentication checks by disabling parts + of &apt-secure; and should therefore only be used in a local and trusted + context (if at all) as otherwise security is breached. The opposite + can be achieved with the value no, which causes the source to be handled + as untrusted even if the authentication checks passed successfully. + The default value can't be set explicitly. + + + + URI specification @@ -247,34 +313,70 @@ deb http://security.debian.org/ &stable-codename;/updates main contrib non-free Examples - Uses the archive stored locally (or NFS mounted) at /home/jason/debian + Uses the archive stored locally (or NFS mounted) at /home/apt/debian for stable/main, stable/contrib, and stable/non-free. - deb file:/home/jason/debian stable main contrib non-free + deb file:/home/apt/debian stable main contrib non-free + Types: deb +URIs: file:/home/apt/debian +Suites: stable +Components: main contrib non-free As above, except this uses the unstable (development) distribution. - deb file:/home/jason/debian unstable main contrib non-free + deb file:/home/apt/debian unstable main contrib non-free + Types: deb +URIs: file:/home/apt/debian +Suites: unstable +Components: main contrib non-free Source line for the above - deb-src file:/home/jason/debian unstable main contrib non-free + deb-src file:/home/apt/debian unstable main contrib non-free + Types: deb-src +URIs: file:/home/apt/debian +Suites: unstable +Components: main contrib non-free + The first line gets package information for the architectures in APT::Architectures while the second always retrieves amd64 and armel. - deb http://ftp.debian.org/debian &stable-codename; main -deb [ arch=amd64,armel ] http://ftp.debian.org/debian &stable-codename; main + deb http://httpredir.debian.org/debian &stable-codename; main +deb [ arch=amd64,armel ] http://httpredir.debian.org/debian &stable-codename; main + Types: deb +URIs: http://httpredir.debian.org/debian +Suites: &stable-codename; +Components: main + +Types: deb +URIs: http://httpredir.debian.org/debian +Suites: &stable-codename; +Components: main +Architectures: amd64 armel + Uses HTTP to access the archive at archive.debian.org, and uses only the hamm/main area. deb http://archive.debian.org/debian-archive hamm main + Types: deb +URIs: http://archive.debian.org/debian-archive +Suites: hamm +Components: main Uses FTP to access the archive at ftp.debian.org, under the debian directory, and uses only the &stable-codename;/contrib area. deb ftp://ftp.debian.org/debian &stable-codename; contrib + Types: deb +URIs: ftp://ftp.debian.org/debian +Suites: &stable-codename; +Components: contrib Uses FTP to access the archive at ftp.debian.org, under the debian directory, and uses only the unstable/contrib area. If this line appears as well as the one in the previous example in sources.list a single FTP session will be used for both resource lines. deb ftp://ftp.debian.org/debian unstable contrib + Types: deb +URIs: ftp://ftp.debian.org/debian +Suites: unstable +Components: contrib Uses HTTP to access the archive at ftp.tlh.debian.org, under the universe directory, and uses only files found under @@ -284,15 +386,32 @@ deb [ arch=amd64,armel ] http://ftp.debian.org/debian &stable-codename; maindeb http://ftp.tlh.debian.org/universe unstable/binary-$(ARCH)/ + Types: deb +URIs: http://ftp.tlh.debian.org/universe +Suites: unstable/binary-$(ARCH)/ + + Uses HTTP to get binary packages as well as sources from the stable, testing and unstable + suites and the components main and contrib. + deb http://httpredir.debian.org/debian stable main contrib +deb-src http://httpredir.debian.org/debian stable main contrib +deb http://httpredir.debian.org/debian testing main contrib +deb-src http://httpredir.debian.org/debian testing main contrib +deb http://httpredir.debian.org/debian unstable main contrib +deb-src http://httpredir.debian.org/debian unstable main contrib + Types: deb deb-src +URIs: http://httpredir.debian.org/debian +Suites: stable testing unstable +Components: main contrib + + - + See Also - &apt-cache; &apt-conf; + &apt-get;, &apt-conf; &manbugs; - - + diff --git a/test/integration/test-apt-sources-deb822 b/test/integration/test-apt-sources-deb822 index 51fe7bcfe..adfe0e003 100755 --- a/test/integration/test-apt-sources-deb822 +++ b/test/integration/test-apt-sources-deb822 @@ -7,9 +7,8 @@ TESTDIR=$(readlink -f $(dirname $0)) setupenvironment configarchitecture 'i386' -echo 'APT::Sources::Use-Deb822 "true";' > rootdir/etc/apt/apt.conf.d/00enabledeb822 - -SOURCES='rootdir/etc/apt/sources.list' +LISTS='rootdir/etc/apt/sources.list.d/test.list' +SOURCES='rootdir/etc/apt/sources.list.d/test.sources' BASE='# some comment # that contains a : as well #Types: meep @@ -17,23 +16,48 @@ BASE='# some comment Types: deb URIs: http://ftp.debian.org/debian Suites: stable -Sections: main +Components: main Description: summay and the long part' -msgtest 'Test sources.list' 'old style' -echo "deb http://ftp.debian.org/debian stable main" > $SOURCES +msgcleantest() { + rm -f $LISTS $SOURCES + msgtest "$@" +} + +msgcleantest 'Test sources.list' 'old style' +echo "deb http://ftp.debian.org/debian stable main" > $LISTS +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris + +msgcleantest 'Test sources.list' 'old style with options' +echo "deb [trusted=yes arch+=armel,powerpc] http://ftp.debian.org/debian stable main" > $LISTS +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-powerpc/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-powerpc_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris + +msgcleantest 'Test sources.list' 'old style with comments' +echo "deb http://ftp.debian.org/debian stable main # non-free" > $LISTS +testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 +'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 +'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris + +msgcleantest 'Test sources.list' 'old style with option comments' +echo "deb [trusted=yes#yeahreally] http://ftp.debian.org/debian stable main # non-free" > $LISTS testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris -msgtest 'Test sources.list' 'simple deb822' +msgcleantest 'Test sources.list' 'simple deb822' echo "$BASE" > $SOURCES testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris -msgtest 'Test deb822 with' 'two entries' +msgcleantest 'Test deb822 with' 'two entries' # Two entries echo "$BASE" > $SOURCES echo "" >> $SOURCES @@ -46,7 +70,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb 'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris # two suite entries -msgtest 'Test deb822 with' 'two Suite entries' +msgcleantest 'Test deb822 with' 'two Suite entries' echo "$BASE" | sed -e "s/stable/stable unstable/" > $SOURCES testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 'http://ftp.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-i386_Packages 0 @@ -55,7 +79,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb 'http://ftp.debian.org/debian/dists/unstable/main/binary-i386/Packages.bz2' ftp.debian.org_debian_dists_unstable_main_binary-i386_Packages 0 'http://ftp.debian.org/debian/dists/unstable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_unstable_main_i18n_Translation-en 0 " aptget update --print-uris -msgtest 'Test deb822' 'architecture option' +msgcleantest 'Test deb822' 'architecture option' echo "$BASE" > $SOURCES echo "Architectures: amd64 armel" >> $SOURCES testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 @@ -63,17 +87,30 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb 'http://ftp.debian.org/debian/dists/stable/main/binary-armel/Packages.bz2' ftp.debian.org_debian_dists_stable_main_binary-armel_Packages 0 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris - -msgtest 'Test old-style sources.list file which has' 'malformed dist' -echo "deb http://ftp.debian.org" > $SOURCES -testequal --nomsg "E: Malformed line 1 in source list $TMPWORKINGDIRECTORY/rootdir/etc/apt/sources.list (dist) +msgcleantest 'Test old-style' 'suite arch variable' +echo 'deb http://ftp.tlh.debian.org/universe unstable/binary-$(ARCH)/' > $LISTS +testequal --nomsg "'http://ftp.tlh.debian.org/universe/unstable/binary-i386/InRelease' ftp.tlh.debian.org_universe_unstable_binary-i386_InRelease 0 +'http://ftp.tlh.debian.org/universe/unstable/binary-i386/Packages.bz2' ftp.tlh.debian.org_universe_unstable_binary-i386_Packages 0 +'http://ftp.tlh.debian.org/universe/unstable/binary-i386/en.bz2' ftp.tlh.debian.org_universe_unstable_binary-i386_en 0 " aptget update --print-uris + +msgcleantest 'Test deb822' 'suite arch variable' +echo 'Types: deb +URIs: http://ftp.tlh.debian.org/universe +Suites: stable/binary-$(ARCH)/' > $SOURCES +testequal --nomsg "'http://ftp.tlh.debian.org/universe/stable/binary-i386/InRelease' ftp.tlh.debian.org_universe_stable_binary-i386_InRelease 0 +'http://ftp.tlh.debian.org/universe/stable/binary-i386/Packages.bz2' ftp.tlh.debian.org_universe_stable_binary-i386_Packages 0 +'http://ftp.tlh.debian.org/universe/stable/binary-i386/en.bz2' ftp.tlh.debian.org_universe_stable_binary-i386_en 0 " aptget update --print-uris + +msgcleantest 'Test old-style sources.list file which has' 'malformed dist' +echo "deb http://ftp.debian.org" > $LISTS +testequal --nomsg "E: Malformed entry 1 in list file $TMPWORKINGDIRECTORY/$LISTS (Suite) E: The list of sources could not be read." aptget update --print-uris -msgtest 'Test deb822 sources.list file which has' 'malformed URI' +msgcleantest 'Test deb822 sources.list file which has' 'malformed URI' echo "Types: deb Suites: stable " > $SOURCES -testequal --nomsg "E: Malformed stanza 0 in source list $TMPWORKINGDIRECTORY/rootdir/etc/apt/sources.list (URI parse) +testequal --nomsg "E: Malformed entry 1 in sources file $TMPWORKINGDIRECTORY/$SOURCES (URI) E: The list of sources could not be read." aptget update --print-uris # with Enabled: false @@ -82,7 +119,7 @@ echo "Enabled: no" >> $SOURCES testempty aptget update --print-uris # multiple URIs -msgtest 'Test deb822 sources.list file which has' 'Multiple URIs work' +msgcleantest 'Test deb822 sources.list file which has' 'Multiple URIs work' echo "$BASE" | sed -e 's#http://ftp.debian.org/debian#http://ftp.debian.org/debian http://ftp.de.debian.org/debian#' > $SOURCES testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp.de.debian.org_debian_dists_stable_InRelease 0 'http://ftp.de.debian.org/debian/dists/stable/main/binary-i386/Packages.bz2' ftp.de.debian.org_debian_dists_stable_main_binary-i386_Packages 0 @@ -92,7 +129,7 @@ testequal --nomsg "'http://ftp.de.debian.org/debian/dists/stable/InRelease' ftp 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris # multiple Type in one field -msgtest 'Test deb822 sources.list file which has' 'Multiple Types work' +msgcleantest 'Test deb822 sources.list file which has' 'Multiple Types work' echo "$BASE" | sed -e 's#Types: deb#Types: deb deb-src#' > $SOURCES testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.debian.org_debian_dists_stable_InRelease 0 'http://ftp.debian.org/debian/dists/stable/main/source/Sources.bz2' ftp.debian.org_debian_dists_stable_main_source_Sources 0 @@ -100,7 +137,7 @@ testequal --nomsg "'http://ftp.debian.org/debian/dists/stable/InRelease' ftp.deb 'http://ftp.debian.org/debian/dists/stable/main/i18n/Translation-en.bz2' ftp.debian.org_debian_dists_stable_main_i18n_Translation-en 0 " aptget update --print-uris # a Suite -msgtest 'Test deb822 sources.list file which has' 'a exact path and no sections' +msgcleantest 'Test deb822 sources.list file which has' 'an exact path and no sections' cat > $SOURCES < + + + + diff --git a/vendor/debian/apt-vendor.ent b/vendor/debian/apt-vendor.ent index 6cda5995c..8b26da385 100644 --- a/vendor/debian/apt-vendor.ent +++ b/vendor/debian/apt-vendor.ent @@ -5,3 +5,15 @@ /usr/share/keyrings/debian-archive-removed-keys.gpg"> + + + diff --git a/vendor/debian/sources.list.in b/vendor/debian/sources.list.in index 2e430296a..c36fb16a7 100644 --- a/vendor/debian/sources.list.in +++ b/vendor/debian/sources.list.in @@ -1,7 +1,6 @@ # See sources.list(5) manpage for more information # Remember that CD-ROMs, DVDs and such are managed through the apt-cdrom tool. -deb http://ftp.us.debian.org/debian &debian-stable-codename; main contrib non-free -deb http://security.debian.org &debian-stable-codename;/updates main contrib non-free +&sourceslist-list-format; # Uncomment if you want the apt-get source function to work #deb-src http://ftp.us.debian.org/debian &debian-stable-codename; main contrib non-free diff --git a/vendor/raspbian/apt-vendor.ent b/vendor/raspbian/apt-vendor.ent index e359d2001..dc69f3c03 100644 --- a/vendor/raspbian/apt-vendor.ent +++ b/vendor/raspbian/apt-vendor.ent @@ -5,3 +5,9 @@ /usr/share/keyrings/raspbian-archive-removed-keys.gpg"> + + + diff --git a/vendor/steamos/apt-vendor.ent b/vendor/steamos/apt-vendor.ent index dc1b798e6..7cf100fc4 100644 --- a/vendor/steamos/apt-vendor.ent +++ b/vendor/steamos/apt-vendor.ent @@ -6,3 +6,10 @@ + + + diff --git a/vendor/steamos/sources.list.in b/vendor/steamos/sources.list.in index 69174d090..246d2e336 100644 --- a/vendor/steamos/sources.list.in +++ b/vendor/steamos/sources.list.in @@ -1,5 +1,3 @@ # See sources.list(5) manpage for more information # Remember that CD-ROMs, DVDs and such are managed through the apt-cdrom tool. - -deb http://repo.steampowered.com/steamos ¤t-codename; main contrib non-free -deb-src http://repo.steampowered.com/steamos ¤t-codename; main contrib non-free +&sourceslist-list-format; diff --git a/vendor/tanglu/apt-vendor.ent b/vendor/tanglu/apt-vendor.ent index d2442209c..f5cd813bf 100644 --- a/vendor/tanglu/apt-vendor.ent +++ b/vendor/tanglu/apt-vendor.ent @@ -6,3 +6,9 @@ + + + diff --git a/vendor/ubuntu/apt-vendor.ent b/vendor/ubuntu/apt-vendor.ent index caa532699..dcebc9209 100644 --- a/vendor/ubuntu/apt-vendor.ent +++ b/vendor/ubuntu/apt-vendor.ent @@ -5,3 +5,16 @@ /usr/share/keyrings/ubuntu-archive-removed-keys.gpg"> + + + -- cgit v1.2.3-70-g09d2 From 268ffcebb9ae4278b1e3c3f89f8167f229164dbd Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 22 Jun 2015 12:34:11 +0200 Subject: detect and error out on conflicting Trusted settings A specific trust state can be enforced via a sources.list option, but it effects all entries handled by the same Release file, not just the entry it was given on so we enforce acknowledgement of this by requiring the same value to be (not) set on all such entries. --- apt-pkg/deb/debmetaindex.cc | 43 ++++++++++++++-------- apt-pkg/deb/debmetaindex.h | 8 ++-- apt-pkg/metaindex.cc | 2 +- apt-pkg/metaindex.h | 1 - doc/sources.list.5.xml | 8 ++++ .../test-bug-596498-trusted-unsigned-repo | 8 ++-- test/integration/test-sourceslist-trusted-options | 17 +++++++++ 7 files changed, 63 insertions(+), 24 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f690a8d64..1f725ba05 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -29,6 +29,8 @@ #include #include +#include + class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ { public: @@ -42,6 +44,11 @@ class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ std::vector DebEntries; std::vector DebSrcEntries; + + debReleaseIndex::TriState Trusted; + + debReleaseIndexPrivate() : Trusted(debReleaseIndex::TRI_UNSET) {} + debReleaseIndexPrivate(bool const pTrusted) : Trusted(pTrusted ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) {} }; /*}}}*/ // ReleaseIndex::MetaIndex* - display helpers /*{{{*/ @@ -101,12 +108,11 @@ std::string debReleaseIndex::LocalFileName() const /*{{{*/ /*}}}*/ // ReleaseIndex Con- and Destructors /*{{{*/ debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) : - metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()), Trusted(CHECK_TRUST) + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) {} debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted) : - metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) { - SetTrusted(Trusted); -} + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate(Trusted)) +{} debReleaseIndex::~debReleaseIndex() { if (d != NULL) delete d; @@ -225,9 +231,9 @@ void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{{{*/ { indexRecords * const iR = new indexRecords(Dist); - if (Trusted == ALWAYS_TRUSTED) + if (d->Trusted == TRI_YES) iR->SetTrusted(true); - else if (Trusted == NEVER_TRUSTED) + else if (d->Trusted == TRI_NO) iR->SetTrusted(false); // special case for --print-uris @@ -246,19 +252,21 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{ return true; } /*}}}*/ -// ReleaseIndex::*Trusted setters and checkers /*{{{*/ -void debReleaseIndex::SetTrusted(bool const Trusted) +// ReleaseIndex::IsTrusted /*{{{*/ +bool debReleaseIndex::SetTrusted(TriState const Trusted) { - if (Trusted == true) - this->Trusted = ALWAYS_TRUSTED; - else - this->Trusted = NEVER_TRUSTED; + if (d->Trusted == TRI_UNSET) + d->Trusted = Trusted; + else if (d->Trusted != Trusted) + // TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str()); + return true; } bool debReleaseIndex::IsTrusted() const { - if (Trusted == ALWAYS_TRUSTED) + if (d->Trusted == TRI_YES) return true; - else if (Trusted == NEVER_TRUSTED) + else if (d->Trusted == TRI_NO) return false; @@ -476,7 +484,12 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ std::map::const_iterator const trusted = Options.find("trusted"); if (trusted != Options.end()) - Deb->SetTrusted(StringToBool(trusted->second, false)); + { + if (Deb->SetTrusted(StringToBool(trusted->second, false) ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) == false) + return false; + } + else if (Deb->SetTrusted(debReleaseIndex::TRI_DONTCARE) == false) + return false; return true; } diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 9b60b6137..a6db4e287 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -27,8 +27,6 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { debReleaseIndexPrivate * const d; - enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted; - public: APT_HIDDEN std::string MetaIndexInfo(const char *Type) const; @@ -51,7 +49,11 @@ class APT_HIDDEN debReleaseIndex : public metaIndex virtual std::vector *GetIndexFiles(); - void SetTrusted(bool const Trusted); + enum APT_HIDDEN TriState { + TRI_YES, TRI_DONTCARE, TRI_NO, TRI_UNSET + }; + bool SetTrusted(TriState const Trusted); + virtual bool IsTrusted() const; void AddComponent(bool const isSrc, std::string const &Name, diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index d96349974..0c88ee9cd 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -41,7 +41,7 @@ bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) -: d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(false) +: d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist) { /* nothing */ } diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 1bcec1c4a..9667e1c92 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -34,7 +34,6 @@ class metaIndex const char *Type; std::string URI; std::string Dist; - bool Trusted; public: diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index 8506017ad..f87dcda23 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -223,7 +223,15 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. source. If not specified, the default set is defined by the APT::Acquire::Targets configuration scope. + + + Further more, there are options which if set effect + all sources with the same URI and Suite, so they + have to be set on all such entries and can not be varied between + different components. APT will try to detect and error out on such + anomalies. + Trusted (trusted) is a tri-state value which defaults to APT deciding if a source is considered trusted or if warnings should be raised before e.g. diff --git a/test/integration/test-bug-596498-trusted-unsigned-repo b/test/integration/test-bug-596498-trusted-unsigned-repo index 1ff0f1d8d..c515837a3 100755 --- a/test/integration/test-bug-596498-trusted-unsigned-repo +++ b/test/integration/test-bug-596498-trusted-unsigned-repo @@ -18,7 +18,7 @@ aptgetupdate() { PKGTEXT="$(aptget install cool --assume-no -d | head -n 8)" DOWNLOG="$(echo "$PKGTEXT" | tail -n 1)" PKGTEXT="$(echo "$PKGTEXT" | head -n 7)" -DEBFILE='rootdir/etc/apt/sources.list.d/apt-test-unstable-deb.list' +DEBFILE='rootdir/etc/apt/sources.list.d/apt-test-unstable-*.list' testsuccessequal "$PKGTEXT $DOWNLOG @@ -28,7 +28,7 @@ testsuccessequal "$PKGTEXT $DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated -sed -i -e 's#deb#deb [trusted=no]#' $DEBFILE +sed -i -e 's#\(deb\(-src\)\?\) #\1 [trusted=no] #' $DEBFILE aptgetupdate 'testsuccess' testfailureequal "$PKGTEXT @@ -38,7 +38,7 @@ Install these packages without verification? [y/N] N E: Some packages could not be authenticated" aptget install cool --assume-no -d find aptarchive/ \( -name 'Release.gpg' -o -name 'InRelease' \) -delete -sed -i -e 's#deb \[trusted=no\]#deb#' $DEBFILE +sed -i -e 's#\(deb\(-src\)\?\) \[trusted=no\] #\1 #' $DEBFILE aptgetupdate testfailureequal "$PKGTEXT @@ -54,7 +54,7 @@ Authentication warning overridden. $DOWNLOG Download complete and in download only mode" aptget install cool --assume-no -d --allow-unauthenticated -sed -i -e 's#deb#deb [trusted=yes]#' $DEBFILE +sed -i -e 's#\(deb\(-src\)\?\) #\1 [trusted=yes] #' $DEBFILE aptgetupdate testsuccessequal "$PKGTEXT diff --git a/test/integration/test-sourceslist-trusted-options b/test/integration/test-sourceslist-trusted-options index 5fe4933ce..86036e242 100755 --- a/test/integration/test-sourceslist-trusted-options +++ b/test/integration/test-sourceslist-trusted-options @@ -199,3 +199,20 @@ insecureaptgetupdate everythingfails everythingfails -t stable everythingfails -t testing + +msgmsg 'Test conflicting trusted options are refused' +testsource() { + echo "$@" > rootdir/etc/apt/sources.list.d/example.list + testfailuremsg 'E: Conflicting values set for option Trusted concerning source http://example.org/bad/ unstable +E: The list of sources could not be read.' aptget update --print-uris +} +for VAL in 'yes' 'no'; do + testsource "deb http://example.org/bad unstable main +deb [trusted=${VAL}] http://example.org/bad unstable non-free" + testsource "deb [trusted=${VAL}] http://example.org/bad unstable main +deb http://example.org/bad unstable non-free" +done +testsource 'deb [trusted=yes] http://example.org/bad unstable main +deb [trusted=no] http://example.org/bad unstable non-free' +testsource 'deb [trusted=no] http://example.org/bad unstable main +deb [trusted=yes] http://example.org/bad unstable non-free' -- cgit v1.2.3-70-g09d2 From 5ad0096a4e19e191b59634e8a8817995ec4045ad Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 23 Jun 2015 15:16:08 +0200 Subject: merge indexRecords into metaIndex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit indexRecords was used to parse the Release file – mostly the hashes – while metaIndex deals with downloading the Release file, storing all indexes coming from this release and … parsing the Release file, but this time mostly for the other fields. That wasn't a problem in metaIndex as this was done in the type specific subclass, but indexRecords while allowing to override the parsing method did expect by default a specific format. APT isn't really supporting different types at the moment, but this is a violation of the abstraction we have everywhere else and, which is the actual reason for this merge: Options e.g. coming from the sources.list come to metaIndex naturally, which needs to wrap them up and bring them into indexRecords, so the acquire system is told about it as they don't get to see the metaIndex, but they don't really belong in indexRecords as this is just for storing data loaded from the Release file… the result is a complete mess. I am not saying it is a lot prettier after the merge, but at least adding new options is now slightly easier and there is just one place responsible for parsing the Release file. That can't hurt. --- apt-pkg/acquire-item.cc | 113 +++++++------- apt-pkg/acquire-item.h | 9 +- apt-pkg/deb/debmetaindex.cc | 231 +++++++++++++++++++++++----- apt-pkg/deb/debmetaindex.h | 29 ++-- apt-pkg/indexcopy.cc | 18 ++- apt-pkg/indexcopy.h | 4 +- apt-pkg/indexrecords.cc | 284 ----------------------------------- apt-pkg/indexrecords.h | 88 ----------- apt-pkg/metaindex.cc | 76 ++++++++-- apt-pkg/metaindex.h | 66 ++++++-- apt-pkg/sourcelist.cc | 1 + cmdline/apt-get.cc | 35 ++--- test/integration/test-apt-cli-update | 4 +- 13 files changed, 423 insertions(+), 535 deletions(-) delete mode 100644 apt-pkg/indexrecords.cc delete mode 100644 apt-pkg/indexrecords.h (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 0ab52a0cd..100199bc1 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -109,9 +109,9 @@ static std::string GetDiffsPatchFileName(std::string const &Final) /*{{{*/ } /*}}}*/ -static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser, pkgAcqMetaClearSig * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ +static bool AllowInsecureRepositories(metaIndex const * const MetaIndexParser, pkgAcqMetaClearSig * const TransactionManager, pkgAcquire::Item * const I) /*{{{*/ { - if(MetaIndexParser->IsAlwaysTrusted() || _config->FindB("Acquire::AllowInsecureRepositories") == true) + if(MetaIndexParser->GetTrusted() == metaIndex::TRI_YES || _config->FindB("Acquire::AllowInsecureRepositories") == true) return true; _error->Error(_("Use --allow-insecure-repositories to force the update")); @@ -120,11 +120,11 @@ static bool AllowInsecureRepositories(indexRecords const * const MetaIndexParser return false; } /*}}}*/ -static HashStringList GetExpectedHashesFromFor(indexRecords * const Parser, std::string const &MetaKey)/*{{{*/ +static HashStringList GetExpectedHashesFromFor(metaIndex * const Parser, std::string const &MetaKey)/*{{{*/ { if (Parser == NULL) return HashStringList(); - indexRecords::checkSum * const R = Parser->Lookup(MetaKey); + metaIndex::checkSum * const R = Parser->Lookup(MetaKey); if (R == NULL) return HashStringList(); return R->Hashes; @@ -144,7 +144,8 @@ APT_CONST bool pkgAcqTransactionItem::HashesRequired() const we can at least trust them for integrity of the download itself. Only repositories without a Release file can (obviously) not have hashes – and they are very uncommon and strongly discouraged */ - return TransactionManager->MetaIndexParser != NULL; + return TransactionManager->MetaIndexParser != NULL && + TransactionManager->MetaIndexParser->GetLoadedSuccessfully() != metaIndex::TRI_UNSET; } HashStringList pkgAcqTransactionItem::GetExpectedHashes() const { @@ -900,26 +901,28 @@ bool pkgAcqMetaBase::CheckAuthDone(string const &Message) /*{{{*/ } if (RealFileExists(FinalInRelease) || RealFileExists(FinalRelease)) { - TransactionManager->LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (TransactionManager->LastMetaIndexParser != NULL) { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); } - _error->RevertToStack(); } } - if (TransactionManager->MetaIndexParser->Load(DestFile) == false) + if (TransactionManager->MetaIndexParser->Load(DestFile, &ErrorText) == false) { Status = StatAuthError; - ErrorText = TransactionManager->MetaIndexParser->ErrorText; return false; } @@ -1065,14 +1068,16 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ TransactionManager->IMSHit = true; unlink(DestFile.c_str()); PartialFile = DestFile = GetFinalFilename(); - delete TransactionManager->MetaIndexParser; - TransactionManager->MetaIndexParser = TransactionManager->LastMetaIndexParser; + // load the 'old' file in the 'new' one instead of flipping pointers as + // the new one isn't owned by us, while the old one is so cleanup would be confused. + TransactionManager->MetaIndexParser->swapLoad(TransactionManager->LastMetaIndexParser); + delete TransactionManager->LastMetaIndexParser; TransactionManager->LastMetaIndexParser = NULL; } if (_config->FindB("Debug::pkgAcquire::Auth", false)) { - std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetDist() << std::endl; + std::cerr << "Got Codename: " << TransactionManager->MetaIndexParser->GetCodename() << std::endl; std::cerr << "Expecting Dist: " << TransactionManager->MetaIndexParser->GetExpectedDist() << std::endl; std::cerr << "Transformed Dist: " << Transformed << std::endl; } @@ -1083,14 +1088,14 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ // Status = StatAuthError; // ErrorText = "Conflicting distribution; expected " // + MetaIndexParser->GetExpectedDist() + " but got " -// + MetaIndexParser->GetDist(); +// + MetaIndexParser->GetCodename(); // return false; if (!Transformed.empty()) { _error->Warning(_("Conflicting distribution: %s (expected %s but got %s)"), Desc.Description.c_str(), Transformed.c_str(), - TransactionManager->MetaIndexParser->GetDist().c_str()); + TransactionManager->MetaIndexParser->GetCodename().c_str()); } } @@ -1105,7 +1110,7 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ IndexTarget const &ClearsignedTarget, IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, std::vector const &IndexTargets, - indexRecords * const MetaIndexParser) : + metaIndex * const MetaIndexParser) : pkgAcqMetaIndex(Owner, this, ClearsignedTarget, DetachedSigTarget, IndexTargets), d(NULL), ClearsignedTarget(ClearsignedTarget), DetachedDataTarget(DetachedDataTarget), @@ -1118,8 +1123,6 @@ pkgAcqMetaClearSig::pkgAcqMetaClearSig(pkgAcquire * const Owner, /*{{{*/ /*}}}*/ pkgAcqMetaClearSig::~pkgAcqMetaClearSig() /*{{{*/ { - if (MetaIndexParser != NULL) - delete MetaIndexParser; if (LastMetaIndexParser != NULL) delete LastMetaIndexParser; } @@ -1218,25 +1221,28 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c // open the last Release if we have it if (TransactionManager->IMSHit == false) { - TransactionManager->LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (TransactionManager->LastMetaIndexParser != NULL) { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); } - _error->RevertToStack(); } } // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him - if (TransactionManager->MetaIndexParser->Load(PartialRelease) == false || VerifyVendor(Message) == false) + if (TransactionManager->MetaIndexParser->Load(PartialRelease, &ErrorText) == false || VerifyVendor(Message) == false) /* expired Release files are still a problem you need extra force for */; else QueueIndexes(true); @@ -1303,8 +1309,6 @@ void pkgAcqMetaIndex::Failed(string const &Message, { // ensure old Release files are removed TransactionManager->TransactionStageRemoval(this, GetFinalFilename()); - delete TransactionManager->MetaIndexParser; - TransactionManager->MetaIndexParser = NULL; // queue without any kind of hashsum support QueueIndexes(false); @@ -1453,25 +1457,28 @@ void pkgAcqMetaSig::Failed(string const &Message,pkgAcquire::MethodConfig const // open the last Release if we have it if (TransactionManager->IMSHit == false) { - TransactionManager->LastMetaIndexParser = new indexRecords; - _error->PushToStack(); - if (RealFileExists(FinalInRelease)) - TransactionManager->LastMetaIndexParser->Load(FinalInRelease); - else - TransactionManager->LastMetaIndexParser->Load(FinalRelease); - // its unlikely to happen, but if what we have is bad ignore it - if (_error->PendingError()) + TransactionManager->LastMetaIndexParser = TransactionManager->MetaIndexParser->UnloadedClone(); + if (TransactionManager->LastMetaIndexParser != NULL) { - delete TransactionManager->LastMetaIndexParser; - TransactionManager->LastMetaIndexParser = NULL; + _error->PushToStack(); + if (RealFileExists(FinalInRelease)) + TransactionManager->LastMetaIndexParser->Load(FinalInRelease, NULL); + else + TransactionManager->LastMetaIndexParser->Load(FinalRelease, NULL); + // its unlikely to happen, but if what we have is bad ignore it + if (_error->PendingError()) + { + delete TransactionManager->LastMetaIndexParser; + TransactionManager->LastMetaIndexParser = NULL; + } + _error->RevertToStack(); } - _error->RevertToStack(); } } // we parse the indexes here because at this point the user wanted // a repository that may potentially harm him - if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile) == false || MetaIndex->VerifyVendor(Message) == false) + if (TransactionManager->MetaIndexParser->Load(MetaIndex->DestFile, &ErrorText) == false || MetaIndex->VerifyVendor(Message) == false) /* expired Release files are still a problem you need extra force for */; else MetaIndex->QueueIndexes(true); diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 4d235dce2..10ece76c9 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -34,7 +34,6 @@ #include #include #include -#include #endif /** \addtogroup acquire @@ -43,11 +42,11 @@ * \file acquire-item.h */ -class indexRecords; class pkgRecords; class pkgSourceList; class pkgAcqMetaClearSig; class pkgAcqIndexMergeDiffs; +class metaIndex; class pkgAcquire::Item : public WeakPointable /*{{{*/ /** \brief Represents the process by which a pkgAcquire object should @@ -559,8 +558,8 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex public: /** \brief A package-system-specific parser for the meta-index file. */ - indexRecords *MetaIndexParser; - indexRecords *LastMetaIndexParser; + metaIndex *MetaIndexParser; + metaIndex *LastMetaIndexParser; virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual std::string Custom600Headers() const; @@ -573,7 +572,7 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex IndexTarget const &DetachedDataTarget, IndexTarget const &DetachedSigTarget, std::vector const &IndexTargets, - indexRecords * const MetaIndexParser); + metaIndex * const MetaIndexParser); virtual ~pkgAcqMetaClearSig(); }; /*}}}*/ diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 1f725ba05..f0b859eb4 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -45,10 +44,7 @@ class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ std::vector DebEntries; std::vector DebSrcEntries; - debReleaseIndex::TriState Trusted; - - debReleaseIndexPrivate() : Trusted(debReleaseIndex::TRI_UNSET) {} - debReleaseIndexPrivate(bool const pTrusted) : Trusted(pTrusted ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) {} + debReleaseIndexPrivate() {} }; /*}}}*/ // ReleaseIndex::MetaIndex* - display helpers /*{{{*/ @@ -92,27 +88,15 @@ std::string debReleaseIndex::MetaIndexURI(const char *Type) const return Res; } /*}}}*/ -std::string debReleaseIndex::LocalFileName() const /*{{{*/ -{ - // see if we have a InRelease file - std::string PathInRelease = MetaIndexFile("InRelease"); - if (FileExists(PathInRelease)) - return PathInRelease; - - // and if not return the normal one - if (FileExists(PathInRelease)) - return MetaIndexFile("Release"); - - return ""; -} - /*}}}*/ // ReleaseIndex Con- and Destructors /*{{{*/ debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist) : metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) {} -debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted) : - metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate(Trusted)) -{} +debReleaseIndex::debReleaseIndex(std::string const &URI, std::string const &Dist, bool const pTrusted) : + metaIndex(URI, Dist, "deb"), d(new debReleaseIndexPrivate()) +{ + Trusted = pTrusted ? TRI_YES : TRI_NO; +} debReleaseIndex::~debReleaseIndex() { if (d != NULL) delete d; @@ -227,22 +211,197 @@ void debReleaseIndex::AddComponent(bool const isSrc, std::string const &Name,/*{ } /*}}}*/ +bool debReleaseIndex::Load(std::string const &Filename, std::string * const ErrorText)/*{{{*/ +{ + LoadedSuccessfully = TRI_NO; + FileFd Fd; + if (OpenMaybeClearSignedFile(Filename, Fd) == false) + return false; + + pkgTagFile TagFile(&Fd, Fd.Size()); + if (_error->PendingError() == true) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); + return false; + } + + pkgTagSection Section; + const char *Start, *End; + if (TagFile.Step(Section) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("No sections in Release file %s"), Filename.c_str()); + return false; + } + // FIXME: find better tag name + SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false); + + Suite = Section.FindS("Suite"); + Codename = Section.FindS("Codename"); + + bool FoundHashSum = false; + for (int i=0;HashString::SupportedHashes()[i] != NULL; i++) + { + if (!Section.Find(HashString::SupportedHashes()[i], Start, End)) + continue; + + std::string Name; + std::string Hash; + unsigned long long Size; + while (Start < End) + { + if (!parseSumData(Start, End, Name, Hash, Size)) + return false; + + if (Entries.find(Name) == Entries.end()) + { + metaIndex::checkSum *Sum = new metaIndex::checkSum; + Sum->MetaKeyFilename = Name; + Sum->Size = Size; + Sum->Hashes.FileSize(Size); + APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) + Entries[Name] = Sum; + } + Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); + FoundHashSum = true; + } + } + + if(FoundHashSum == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("No Hash entry in Release file %s"), Filename.c_str()); + return false; + } + + std::string const StrDate = Section.FindS("Date"); + if (RFC1123StrToTime(StrDate.c_str(), Date) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str()); + return false; + } -bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{{{*/ + std::string const Label = Section.FindS("Label"); + std::string const StrValidUntil = Section.FindS("Valid-Until"); + + // if we have a Valid-Until header in the Release file, use it as default + if (StrValidUntil.empty() == false) + { + if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); + return false; + } + } + // get the user settings for this archive and use what expires earlier + int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); + if (Label.empty() == false) + MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); + int MinAge = _config->FindI("Acquire::Min-ValidTime", 0); + if (Label.empty() == false) + MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); + + LoadedSuccessfully = TRI_YES; + if(MaxAge == 0 && + (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file + return true; + + if (MinAge != 0 && ValidUntil != 0) { + time_t const min_date = Date + MinAge; + if (ValidUntil < min_date) + ValidUntil = min_date; + } + if (MaxAge != 0) { + time_t const max_date = Date + MaxAge; + if (ValidUntil == 0 || ValidUntil > max_date) + ValidUntil = max_date; + } + + return true; +} + /*}}}*/ +metaIndex * debReleaseIndex::UnloadedClone() const /*{{{*/ +{ + if (Trusted == TRI_NO) + return new debReleaseIndex(URI, Dist, false); + else if (Trusted == TRI_YES) + return new debReleaseIndex(URI, Dist, true); + else + return new debReleaseIndex(URI, Dist); +} + /*}}}*/ +bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/ + std::string &Name, std::string &Hash, unsigned long long &Size) { - indexRecords * const iR = new indexRecords(Dist); - if (d->Trusted == TRI_YES) - iR->SetTrusted(true); - else if (d->Trusted == TRI_NO) - iR->SetTrusted(false); + Name = ""; + Hash = ""; + Size = 0; + /* Skip over the first blank */ + while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r') + && Start < End) + Start++; + if (Start >= End) + return false; - // special case for --print-uris + /* Move EntryEnd to the end of the first entry (the hash) */ + const char *EntryEnd = Start; + while ((*EntryEnd != '\t' && *EntryEnd != ' ') + && EntryEnd < End) + EntryEnd++; + if (EntryEnd == End) + return false; + + Hash.append(Start, EntryEnd-Start); + + /* Skip over intermediate blanks */ + Start = EntryEnd; + while (*Start == '\t' || *Start == ' ') + Start++; + if (Start >= End) + return false; + + EntryEnd = Start; + /* Find the end of the second entry (the size) */ + while ((*EntryEnd != '\t' && *EntryEnd != ' ' ) + && EntryEnd < End) + EntryEnd++; + if (EntryEnd == End) + return false; + + Size = strtoull (Start, NULL, 10); + + /* Skip over intermediate blanks */ + Start = EntryEnd; + while (*Start == '\t' || *Start == ' ') + Start++; + if (Start >= End) + return false; + + EntryEnd = Start; + /* Find the end of the third entry (the filename) */ + while ((*EntryEnd != '\t' && *EntryEnd != ' ' && + *EntryEnd != '\n' && *EntryEnd != '\r') + && EntryEnd < End) + EntryEnd++; + + Name.append(Start, EntryEnd-Start); + Start = EntryEnd; //prepare for the next round + return true; +} + /*}}}*/ + +bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/ +{ std::vector const targets = GetIndexTargets(); #define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), - targets, iR); + targets, this); #undef APT_TARGET + // special case for --print-uris if (GetAll) { for (std::vector::const_iterator Target = targets.begin(); Target != targets.end(); ++Target) @@ -253,20 +412,20 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const/*{ } /*}}}*/ // ReleaseIndex::IsTrusted /*{{{*/ -bool debReleaseIndex::SetTrusted(TriState const Trusted) +bool debReleaseIndex::SetTrusted(TriState const pTrusted) { - if (d->Trusted == TRI_UNSET) - d->Trusted = Trusted; - else if (d->Trusted != Trusted) + if (Trusted == TRI_UNSET) + Trusted = pTrusted; + else if (Trusted != pTrusted) // TRANSLATOR: The first is an option name from sources.list manpage, the other two URI and Suite return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str()); return true; } bool debReleaseIndex::IsTrusted() const { - if (d->Trusted == TRI_YES) + if (Trusted == TRI_YES) return true; - else if (d->Trusted == TRI_NO) + else if (Trusted == TRI_NO) return false; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index a6db4e287..19fe6806c 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -27,6 +27,8 @@ class APT_HIDDEN debReleaseIndex : public metaIndex { debReleaseIndexPrivate * const d; + APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name, + std::string &Hash, unsigned long long &Size); public: APT_HIDDEN std::string MetaIndexInfo(const char *Type) const; @@ -38,20 +40,18 @@ class APT_HIDDEN debReleaseIndex : public metaIndex virtual ~debReleaseIndex(); virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; - virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false); virtual std::vector GetIndexTargets() const; virtual std::string Describe() const; virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual std::string LocalFileName() const; + virtual bool Load(std::string const &Filename, std::string * const ErrorText); + virtual metaIndex * UnloadedClone() const; virtual std::vector *GetIndexFiles(); - enum APT_HIDDEN TriState { - TRI_YES, TRI_DONTCARE, TRI_NO, TRI_UNSET - }; bool SetTrusted(TriState const Trusted); virtual bool IsTrusted() const; @@ -64,15 +64,15 @@ class APT_HIDDEN debReleaseIndex : public metaIndex class APT_HIDDEN debDebFileMetaIndex : public metaIndex { - private: - void * const d; +private: + void * const d; std::string DebFile; debDebPkgFileIndex *DebIndex; - public: +public: virtual std::string ArchiveURI(std::string const& /*File*/) const { return DebFile; } - virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) const { + virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) { return true; } virtual std::vector GetIndexTargets() const { @@ -84,6 +84,17 @@ class APT_HIDDEN debDebFileMetaIndex : public metaIndex virtual bool IsTrusted() const { return true; } + virtual bool Load(std::string const &, std::string * const ErrorText) + { + LoadedSuccessfully = TRI_NO; + if (ErrorText != NULL) + strprintf(*ErrorText, "Unparseable metaindex as it represents the standalone deb file %s", DebFile.c_str()); + return false; + } + virtual metaIndex * UnloadedClone() const + { + return NULL; + } debDebFileMetaIndex(std::string const &DebFile); virtual ~debDebFileMetaIndex(); diff --git a/apt-pkg/indexcopy.cc b/apt-pkg/indexcopy.cc index 6d210e65b..f9adb2fb8 100644 --- a/apt-pkg/indexcopy.cc +++ b/apt-pkg/indexcopy.cc @@ -19,10 +19,11 @@ #include #include #include -#include +#include #include #include #include +#include #include #include @@ -476,9 +477,9 @@ bool SourceCopy::RewriteEntry(FileFd &Target, std::string const &File) } /*}}}*/ // SigVerify::Verify - Verify a files md5sum against its metaindex /*{{{*/ -bool SigVerify::Verify(string prefix, string file, indexRecords *MetaIndex) +bool SigVerify::Verify(string prefix, string file, metaIndex *MetaIndex) { - const indexRecords::checkSum *Record = MetaIndex->Lookup(file); + const metaIndex::checkSum *Record = MetaIndex->Lookup(file); bool const Debug = _config->FindB("Debug::aptcdrom",false); // we skip non-existing files in the verifcation of the Release file @@ -545,11 +546,11 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, // Read all Release files for (vector::iterator I = SigList.begin(); I != SigList.end(); ++I) - { + { if(Debug) cout << "Signature verify for: " << *I << endl; - indexRecords *MetaIndex = new indexRecords; + metaIndex *MetaIndex = new debReleaseIndex("",""); string prefix = *I; string const releasegpg = *I+"Release.gpg"; @@ -591,12 +592,13 @@ bool SigVerify::CopyAndVerify(string CDROM,string Name,vector &SigList, } // Open the Release file and add it to the MetaIndex - if(!MetaIndex->Load(release)) + std::string ErrorText; + if(MetaIndex->Load(release, &ErrorText) == false) { - _error->Error("%s",MetaIndex->ErrorText.c_str()); + _error->Error("%s", ErrorText.c_str()); return false; } - + // go over the Indexfiles and see if they verify // if so, remove them from our copy of the lists vector keys = MetaIndex->MetaKeys(); diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 4f4c47169..6eecad028 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -25,9 +25,9 @@ using std::vector; #endif class pkgTagSection; -class indexRecords; class pkgCdromStatus; class FileFd; +class metaIndex; class IndexCopy /*{{{*/ { @@ -106,7 +106,7 @@ class SigVerify /*{{{*/ /** \brief dpointer placeholder (for later in case we need it) */ void * const d; - APT_HIDDEN bool Verify(std::string prefix,std::string file, indexRecords *records); + APT_HIDDEN bool Verify(std::string prefix,std::string file, metaIndex *records); APT_HIDDEN bool CopyMetaIndex(std::string CDROM, std::string CDName, std::string prefix, std::string file); diff --git a/apt-pkg/indexrecords.cc b/apt-pkg/indexrecords.cc deleted file mode 100644 index 03ba59460..000000000 --- a/apt-pkg/indexrecords.cc +++ /dev/null @@ -1,284 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -// Description /*{{{*/ -// $Id: indexrecords.cc,v 1.1.2.4 2003/12/30 02:11:43 mdz Exp $ - /*}}}*/ -// Include Files /*{{{*/ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - /*}}}*/ - -using std::string; - -APT_PURE string indexRecords::GetDist() const -{ - return this->Dist; -} - -APT_PURE string indexRecords::GetSuite() const -{ - return this->Suite; -} - -APT_PURE bool indexRecords::GetSupportsAcquireByHash() const -{ - return this->SupportsAcquireByHash; -} - -APT_PURE bool indexRecords::CheckDist(string const &MaybeDist) const -{ - return (this->Dist == MaybeDist - || this->Suite == MaybeDist); -} - -APT_PURE string indexRecords::GetExpectedDist() const -{ - return this->ExpectedDist; -} - -APT_PURE time_t indexRecords::GetValidUntil() const -{ - return this->ValidUntil; -} - -APT_PURE time_t indexRecords::GetDate() const -{ - return this->Date; -} - -APT_PURE indexRecords::checkSum *indexRecords::Lookup(string const &MetaKey) -{ - std::map::const_iterator sum = Entries.find(MetaKey); - if (sum == Entries.end()) - return NULL; - return sum->second; -} - -APT_PURE bool indexRecords::Exists(string const &MetaKey) const -{ - return Entries.find(MetaKey) != Entries.end(); -} - -bool indexRecords::Load(string const &Filename) /*{{{*/ -{ - FileFd Fd; - if (OpenMaybeClearSignedFile(Filename, Fd) == false) - return false; - - pkgTagFile TagFile(&Fd, Fd.Size()); - if (_error->PendingError() == true) - { - strprintf(ErrorText, _("Unable to parse Release file %s"),Filename.c_str()); - return false; - } - - pkgTagSection Section; - const char *Start, *End; - if (TagFile.Step(Section) == false) - { - strprintf(ErrorText, _("No sections in Release file %s"), Filename.c_str()); - return false; - } - // FIXME: find better tag name - SupportsAcquireByHash = Section.FindB("Acquire-By-Hash", false); - - Suite = Section.FindS("Suite"); - Dist = Section.FindS("Codename"); - - bool FoundHashSum = false; - for (int i=0;HashString::SupportedHashes()[i] != NULL; i++) - { - if (!Section.Find(HashString::SupportedHashes()[i], Start, End)) - continue; - - string Name; - string Hash; - unsigned long long Size; - while (Start < End) - { - if (!parseSumData(Start, End, Name, Hash, Size)) - return false; - - if (Entries.find(Name) == Entries.end()) - { - indexRecords::checkSum *Sum = new indexRecords::checkSum; - Sum->MetaKeyFilename = Name; - Sum->Size = Size; - Sum->Hashes.FileSize(Size); - APT_IGNORE_DEPRECATED(Sum->Hash = HashString(HashString::SupportedHashes()[i],Hash);) - Entries[Name] = Sum; - } - Entries[Name]->Hashes.push_back(HashString(HashString::SupportedHashes()[i],Hash)); - FoundHashSum = true; - } - } - - if(FoundHashSum == false) - { - strprintf(ErrorText, _("No Hash entry in Release file %s"), Filename.c_str()); - return false; - } - - string const StrDate = Section.FindS("Date"); - if (RFC1123StrToTime(StrDate.c_str(), Date) == false) - { - strprintf(ErrorText, _("Invalid 'Date' entry in Release file %s"), Filename.c_str()); - return false; - } - - string const Label = Section.FindS("Label"); - string const StrValidUntil = Section.FindS("Valid-Until"); - - // if we have a Valid-Until header in the Release file, use it as default - if (StrValidUntil.empty() == false) - { - if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) - { - strprintf(ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); - return false; - } - } - // get the user settings for this archive and use what expires earlier - int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); - if (Label.empty() == false) - MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); - int MinAge = _config->FindI("Acquire::Min-ValidTime", 0); - if (Label.empty() == false) - MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); - - if(MaxAge == 0 && - (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file - return true; - - if (MinAge != 0 && ValidUntil != 0) { - time_t const min_date = Date + MinAge; - if (ValidUntil < min_date) - ValidUntil = min_date; - } - if (MaxAge != 0) { - time_t const max_date = Date + MaxAge; - if (ValidUntil == 0 || ValidUntil > max_date) - ValidUntil = max_date; - } - - return true; -} - /*}}}*/ -std::vector indexRecords::MetaKeys() /*{{{*/ -{ - std::vector keys; - std::map::iterator I = Entries.begin(); - while(I != Entries.end()) { - keys.push_back((*I).first); - ++I; - } - return keys; -} - /*}}}*/ -bool indexRecords::parseSumData(const char *&Start, const char *End, /*{{{*/ - string &Name, string &Hash, unsigned long long &Size) -{ - Name = ""; - Hash = ""; - Size = 0; - /* Skip over the first blank */ - while ((*Start == '\t' || *Start == ' ' || *Start == '\n' || *Start == '\r') - && Start < End) - Start++; - if (Start >= End) - return false; - - /* Move EntryEnd to the end of the first entry (the hash) */ - const char *EntryEnd = Start; - while ((*EntryEnd != '\t' && *EntryEnd != ' ') - && EntryEnd < End) - EntryEnd++; - if (EntryEnd == End) - return false; - - Hash.append(Start, EntryEnd-Start); - - /* Skip over intermediate blanks */ - Start = EntryEnd; - while (*Start == '\t' || *Start == ' ') - Start++; - if (Start >= End) - return false; - - EntryEnd = Start; - /* Find the end of the second entry (the size) */ - while ((*EntryEnd != '\t' && *EntryEnd != ' ' ) - && EntryEnd < End) - EntryEnd++; - if (EntryEnd == End) - return false; - - Size = strtoull (Start, NULL, 10); - - /* Skip over intermediate blanks */ - Start = EntryEnd; - while (*Start == '\t' || *Start == ' ') - Start++; - if (Start >= End) - return false; - - EntryEnd = Start; - /* Find the end of the third entry (the filename) */ - while ((*EntryEnd != '\t' && *EntryEnd != ' ' && - *EntryEnd != '\n' && *EntryEnd != '\r') - && EntryEnd < End) - EntryEnd++; - - Name.append(Start, EntryEnd-Start); - Start = EntryEnd; //prepare for the next round - return true; -} - /*}}}*/ - -APT_PURE bool indexRecords::IsAlwaysTrusted() const -{ - if (Trusted == ALWAYS_TRUSTED) - return true; - return false; -} -APT_PURE bool indexRecords::IsNeverTrusted() const -{ - if (Trusted == NEVER_TRUSTED) - return true; - return false; -} -void indexRecords::SetTrusted(bool const Trusted) -{ - if (Trusted == true) - this->Trusted = ALWAYS_TRUSTED; - else - this->Trusted = NEVER_TRUSTED; -} - -indexRecords::indexRecords(const string &ExpectedDist) : - Trusted(CHECK_TRUST), d(NULL), ExpectedDist(ExpectedDist), ValidUntil(0), - SupportsAcquireByHash(false) -{ -} - -indexRecords::~indexRecords() { - for (std::map::const_iterator S = Entries.begin(); S != Entries.end(); ++S) - delete S->second; -} diff --git a/apt-pkg/indexrecords.h b/apt-pkg/indexrecords.h deleted file mode 100644 index 683247e42..000000000 --- a/apt-pkg/indexrecords.h +++ /dev/null @@ -1,88 +0,0 @@ -// -*- mode: cpp; mode: fold -*- -#ifndef PKGLIB_INDEXRECORDS_H -#define PKGLIB_INDEXRECORDS_H - -#include - -#include -#include -#include -#include - -#ifndef APT_8_CLEANER_HEADERS -#include -#endif -#ifndef APT_10_CLEANER_HEADERS -#include -#endif - -class indexRecords -{ - APT_HIDDEN bool parseSumData(const char *&Start, const char *End, std::string &Name, - std::string &Hash, unsigned long long &Size); - public: - struct checkSum; - std::string ErrorText; - - private: - enum APT_HIDDEN { ALWAYS_TRUSTED, NEVER_TRUSTED, CHECK_TRUST } Trusted; - // dpointer (for later) - void * const d; - - protected: - std::string Dist; - std::string Suite; - std::string ExpectedDist; - time_t Date; - time_t ValidUntil; - bool SupportsAcquireByHash; - - std::map Entries; - - public: - explicit indexRecords(const std::string &ExpectedDist = ""); - - // Lookup function - virtual checkSum *Lookup(std::string const &MetaKey); - /** \brief tests if a checksum for this file is available */ - bool Exists(std::string const &MetaKey) const; - std::vector MetaKeys(); - - virtual bool Load(std::string const &Filename); - virtual bool CheckDist(std::string const &MaybeDist) const; - - std::string GetDist() const; - std::string GetSuite() const; - bool GetSupportsAcquireByHash() const; - time_t GetValidUntil() const; - time_t GetDate() const; - std::string GetExpectedDist() const; - - /** \brief check if source is marked as always trusted */ - bool IsAlwaysTrusted() const; - /** \brief check if source is marked as never trusted */ - bool IsNeverTrusted() const; - - /** \brief sets an explicit trust value - * - * \b true means that the source should always be considered trusted, - * while \b false marks a source as always untrusted, even if we have - * a valid signature and everything. - */ - void SetTrusted(bool const Trusted); - - virtual ~indexRecords(); -}; - -APT_IGNORE_DEPRECATED_PUSH -struct indexRecords::checkSum -{ - std::string MetaKeyFilename; - HashStringList Hashes; - unsigned long long Size; - - APT_DEPRECATED HashString Hash; -}; -APT_IGNORE_DEPRECATED_POP - -#endif diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 0c88ee9cd..8bd13bb18 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -9,20 +9,6 @@ #include /*}}}*/ -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) -std::string metaIndex::LocalFileName() const { return ""; } -#else -#include -std::string metaIndex::LocalFileName() const -{ - debReleaseIndex const * deb = dynamic_cast(this); - if (deb != NULL) - return deb->LocalFileName(); - - return ""; -} -#endif - std::string metaIndex::Describe() const { return "Release"; @@ -38,10 +24,11 @@ bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const return Gen.SelectReleaseFile("", ""); } - metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) -: d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist) +: d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(TRI_UNSET), + LoadedSuccessfully(TRI_UNSET), + Date(0), ValidUntil(0), SupportsAcquireByHash(false) { /* nothing */ } @@ -55,3 +42,60 @@ metaIndex::~metaIndex() delete *I; delete Indexes; } + +// one line Getters for public fields /*{{{*/ +APT_PURE std::string metaIndex::GetURI() const { return URI; } +APT_PURE std::string metaIndex::GetDist() const { return Dist; } +APT_PURE const char* metaIndex::GetType() const { return Type; } +APT_PURE metaIndex::TriState metaIndex::GetTrusted() const { return Trusted; } +APT_PURE std::string metaIndex::GetCodename() const { return Codename; } +APT_PURE std::string metaIndex::GetSuite() const { return Suite; } +APT_PURE bool metaIndex::GetSupportsAcquireByHash() const { return SupportsAcquireByHash; } +APT_PURE time_t metaIndex::GetValidUntil() const { return ValidUntil; } +APT_PURE time_t metaIndex::GetDate() const { return this->Date; } +APT_PURE metaIndex::TriState metaIndex::GetLoadedSuccessfully() const { return LoadedSuccessfully; } + +APT_PURE bool metaIndex::CheckDist(string const &MaybeDist) const +{ + return (this->Codename == MaybeDist + || this->Suite == MaybeDist); +} +APT_PURE std::string metaIndex::GetExpectedDist() const +{ + // TODO: Used to be an explicit value set in the constructor + return ""; +} + /*}}}*/ +APT_PURE metaIndex::checkSum *metaIndex::Lookup(string const &MetaKey) const /*{{{*/ +{ + std::map::const_iterator sum = Entries.find(MetaKey); + if (sum == Entries.end()) + return NULL; + return sum->second; +} + /*}}}*/ +APT_PURE bool metaIndex::Exists(string const &MetaKey) const /*{{{*/ +{ + return Entries.find(MetaKey) != Entries.end(); +} + /*}}}*/ +std::vector metaIndex::MetaKeys() const /*{{{*/ +{ + std::vector keys; + std::map::const_iterator I = Entries.begin(); + while(I != Entries.end()) { + keys.push_back((*I).first); + ++I; + } + return keys; +} + /*}}}*/ +void metaIndex::swapLoad(metaIndex * const OldMetaIndex) /*{{{*/ +{ + std::swap(Entries, OldMetaIndex->Entries); + std::swap(Date, OldMetaIndex->Date); + std::swap(ValidUntil, OldMetaIndex->ValidUntil); + std::swap(SupportsAcquireByHash, OldMetaIndex->SupportsAcquireByHash); + std::swap(LoadedSuccessfully, OldMetaIndex->LoadedSuccessfully); +} + /*}}}*/ diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 9667e1c92..5be7397ae 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -28,35 +28,81 @@ class OpProgress; class metaIndex { +public: + APT_IGNORE_DEPRECATED_PUSH + struct checkSum + { + std::string MetaKeyFilename; + HashStringList Hashes; + unsigned long long Size; + + APT_DEPRECATED HashString Hash; + }; + APT_IGNORE_DEPRECATED_POP + + enum APT_HIDDEN TriState { + TRI_YES, TRI_DONTCARE, TRI_NO, TRI_UNSET + }; +private: void * const d; - protected: +protected: std::vector *Indexes; + // parsed from the sources.list const char *Type; std::string URI; std::string Dist; + TriState Trusted; + TriState LoadedSuccessfully; - public: + // parsed from a file + std::string Suite; + std::string Codename; + time_t Date; + time_t ValidUntil; + bool SupportsAcquireByHash; + std::map Entries; +public: // Various accessors - virtual std::string GetURI() const {return URI;} - virtual std::string GetDist() const {return Dist;} - virtual const char* GetType() const {return Type;} + std::string GetURI() const; + std::string GetDist() const; + const char* GetType() const; + TriState GetTrusted() const; - // interface to to query it - /** \return the path of the local file (or "" if its not available) */ - virtual std::string LocalFileName() const; + std::string GetCodename() const; + std::string GetSuite() const; + bool GetSupportsAcquireByHash() const; + time_t GetValidUntil() const; + time_t GetDate() const; + + std::string GetExpectedDist() const; + bool CheckDist(std::string const &MaybeDist) const; // Interface for acquire + virtual std::string Describe() const; virtual std::string ArchiveURI(std::string const& File) const = 0; - virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) const = 0; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) = 0; virtual std::vector GetIndexTargets() const = 0; virtual std::vector *GetIndexFiles() = 0; virtual bool IsTrusted() const = 0; + virtual bool Load(std::string const &Filename, std::string * const ErrorText) = 0; + /** @return a new metaIndex object based on this one, but without information from #Load */ + virtual metaIndex * UnloadedClone() const = 0; + // the given metaIndex is potentially invalid after this call and should be deleted + void swapLoad(metaIndex * const OldMetaIndex); - virtual std::string Describe() const; + // Lookup functions for parsed Hashes + checkSum *Lookup(std::string const &MetaKey) const; + /** \brief tests if a checksum for this file is available */ + bool Exists(std::string const &MetaKey) const; + std::vector MetaKeys() const; + TriState GetLoadedSuccessfully() const; + + // Interfaces for pkgCacheGen virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + metaIndex(std::string const &URI, std::string const &Dist, char const * const Type); virtual ~metaIndex(); diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 69f7ac043..0502f0e1d 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -103,6 +103,7 @@ bool pkgSourceList::Type::ParseStanza(vector &List, /*{{{*/ APT_PLUSMINUS("Targets", "target"); #undef APT_PLUSMINUS mapping.insert(std::make_pair("Trusted", "trusted")); + for (std::map::const_iterator m = mapping.begin(); m != mapping.end(); ++m) if (Tags.Exists(m->first)) { diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 500a0a3c5..10d4b3cc5 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -137,11 +137,9 @@ static bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, return true; } /*}}}*/ -// GetReleaseForSourceRecord - Return Suite for the given srcrecord /*{{{*/ -// --------------------------------------------------------------------- -/* */ -static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, - pkgSrcRecords::Parser *Parse) +// GetReleaseFileForSourceRecord - Return Suite for the given srcrecord /*{{{*/ +static pkgCache::RlsFileIterator GetReleaseFileForSourceRecord(CacheFile &CacheFile, + pkgSourceList *SrcList, pkgSrcRecords::Parser *Parse) { // try to find release const pkgIndexFile& CurrentIndexFile = Parse->Index(); @@ -154,18 +152,10 @@ static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList, IF != Indexes->end(); ++IF) { if (&CurrentIndexFile == (*IF)) - { - std::string const path = (*S)->LocalFileName(); - if (path != "") - { - indexRecords records; - records.Load(path); - return records.GetSuite(); - } - } + return (*S)->FindInCache(CacheFile, false); } } - return ""; + return pkgCache::RlsFileIterator(CacheFile); } /*}}}*/ // FindSrc - Find a source record /*{{{*/ @@ -379,13 +369,16 @@ static pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, // See if we need to look for a specific release tag if (RelTag != "" && UserRequestedVerTag == "") { - const string Rel = GetReleaseForSourceRecord(SrcList, Parse); - - if (Rel == RelTag) + pkgCache::RlsFileIterator const Rls = GetReleaseFileForSourceRecord(CacheFile, SrcList, Parse); + if (Rls.end() == false) { - Last = Parse; - Offset = Parse->Offset(); - Version = Ver; + if ((Rls->Archive != 0 && RelTag == Rls.Archive()) || + (Rls->Codename != 0 && RelTag == Rls.Codename())) + { + Last = Parse; + Offset = Parse->Offset(); + Version = Ver; + } } } diff --git a/test/integration/test-apt-cli-update b/test/integration/test-apt-cli-update index d68ab25e4..dad365f7e 100755 --- a/test/integration/test-apt-cli-update +++ b/test/integration/test-apt-cli-update @@ -13,9 +13,7 @@ insertinstalledpackage 'foo' 'all' '1.0' setupaptarchive --no-update -APTARCHIVE=$(readlink -f ./aptarchive) - -testfailureequal 'E: The update command takes no arguments' apt update -q arguments +testfailuremsg 'E: The update command takes no arguments' apt update arguments testsuccessequal "1 package can be upgraded. Run 'apt list --upgradable' to see it." apt update -q -- cgit v1.2.3-70-g09d2 From 0741daeb7ab870b4dd62a93fa12a1cf6330f9a72 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 23 Jun 2015 17:26:57 +0200 Subject: add sources.list Check-Valid-Until and Valid-Until-{Max,Min} options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These options could be set via configuration before, but the connection to the actual sources is so strong that they should really be set in the sources.list instead – especially as this can be done a lot more specific rather than e.g. disabling Valid-Until for all sources at once. Valid-Until-* names are chosen instead of the Min/Max-ValidTime as this seems like a better name and their use in the wild is probably low enough that this isn't going to confuse anyone if we have to names for the same thing in different areas. In the longrun, the config options should be removed, but for now documentation hinting at the new options is good enough as these are the kind of options you set once across many systems with different apt versions, so the new way should work everywhere first before we deprecate the old way. --- apt-pkg/acquire-item.cc | 4 +- apt-pkg/deb/debmetaindex.cc | 134 ++++++++++++++++++-------- apt-pkg/deb/debmetaindex.h | 3 + apt-pkg/sourcelist.cc | 3 + doc/apt-get.8.xml | 10 +- doc/apt.conf.5.xml | 8 +- doc/sources.list.5.xml | 55 +++++++++-- test/integration/test-releasefile-valid-until | 9 ++ 8 files changed, 170 insertions(+), 56 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 100199bc1..a30a5d154 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1041,8 +1041,8 @@ bool pkgAcqMetaBase::VerifyVendor(string const &Message) /*{{{*/ Transformed = ""; } - if (_config->FindB("Acquire::Check-Valid-Until", true) == true && - TransactionManager->MetaIndexParser->GetValidUntil() > 0) { + if (TransactionManager->MetaIndexParser->GetValidUntil() > 0) + { time_t const invalid_since = time(NULL) - TransactionManager->MetaIndexParser->GetValidUntil(); if (invalid_since > 0) { diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index f0b859eb4..5d7e539c7 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -44,7 +44,11 @@ class APT_HIDDEN debReleaseIndexPrivate /*{{{*/ std::vector DebEntries; std::vector DebSrcEntries; - debReleaseIndexPrivate() {} + metaIndex::TriState CheckValidUntil; + time_t ValidUntilMin; + time_t ValidUntilMax; + + debReleaseIndexPrivate() : CheckValidUntil(metaIndex::TRI_UNSET), ValidUntilMin(0), ValidUntilMax(0) {} }; /*}}}*/ // ReleaseIndex::MetaIndex* - display helpers /*{{{*/ @@ -283,43 +287,56 @@ bool debReleaseIndex::Load(std::string const &Filename, std::string * const Erro return false; } - std::string const Label = Section.FindS("Label"); - std::string const StrValidUntil = Section.FindS("Valid-Until"); + bool CheckValidUntil = _config->FindB("Acquire::Check-Valid-Until", true); + if (d->CheckValidUntil == metaIndex::TRI_NO) + CheckValidUntil = false; + else if (d->CheckValidUntil == metaIndex::TRI_YES) + CheckValidUntil = true; - // if we have a Valid-Until header in the Release file, use it as default - if (StrValidUntil.empty() == false) + if (CheckValidUntil == true) { - if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + std::string const Label = Section.FindS("Label"); + std::string const StrValidUntil = Section.FindS("Valid-Until"); + + // if we have a Valid-Until header in the Release file, use it as default + if (StrValidUntil.empty() == false) { - if (ErrorText != NULL) - strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); - return false; + if(RFC1123StrToTime(StrValidUntil.c_str(), ValidUntil) == false) + { + if (ErrorText != NULL) + strprintf(*ErrorText, _("Invalid 'Valid-Until' entry in Release file %s"), Filename.c_str()); + return false; + } + } + // get the user settings for this archive and use what expires earlier + time_t MaxAge = d->ValidUntilMax; + if (MaxAge == 0) + { + MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); + if (Label.empty() == false) + MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); + } + time_t MinAge = d->ValidUntilMin; + if (MinAge == 0) + { + MinAge = _config->FindI("Acquire::Min-ValidTime", 0); + if (Label.empty() == false) + MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); } - } - // get the user settings for this archive and use what expires earlier - int MaxAge = _config->FindI("Acquire::Max-ValidTime", 0); - if (Label.empty() == false) - MaxAge = _config->FindI(("Acquire::Max-ValidTime::" + Label).c_str(), MaxAge); - int MinAge = _config->FindI("Acquire::Min-ValidTime", 0); - if (Label.empty() == false) - MinAge = _config->FindI(("Acquire::Min-ValidTime::" + Label).c_str(), MinAge); - - LoadedSuccessfully = TRI_YES; - if(MaxAge == 0 && - (MinAge == 0 || ValidUntil == 0)) // No user settings, use the one from the Release file - return true; - if (MinAge != 0 && ValidUntil != 0) { - time_t const min_date = Date + MinAge; - if (ValidUntil < min_date) - ValidUntil = min_date; - } - if (MaxAge != 0) { - time_t const max_date = Date + MaxAge; - if (ValidUntil == 0 || ValidUntil > max_date) - ValidUntil = max_date; + if (MinAge != 0 && ValidUntil != 0) { + time_t const min_date = Date + MinAge; + if (ValidUntil < min_date) + ValidUntil = min_date; + } + if (MaxAge != 0) { + time_t const max_date = Date + MaxAge; + if (ValidUntil == 0 || ValidUntil > max_date) + ValidUntil = max_date; + } } + LoadedSuccessfully = TRI_YES; return true; } /*}}}*/ @@ -411,7 +428,7 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/ return true; } /*}}}*/ -// ReleaseIndex::IsTrusted /*{{{*/ +// ReleaseIndex::Set* TriState options /*{{{*/ bool debReleaseIndex::SetTrusted(TriState const pTrusted) { if (Trusted == TRI_UNSET) @@ -421,6 +438,32 @@ bool debReleaseIndex::SetTrusted(TriState const pTrusted) return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Trusted", URI.c_str(), Dist.c_str()); return true; } +bool debReleaseIndex::SetCheckValidUntil(TriState const pCheckValidUntil) +{ + if (d->CheckValidUntil == TRI_UNSET) + d->CheckValidUntil = pCheckValidUntil; + else if (d->CheckValidUntil != pCheckValidUntil) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Check-Valid-Until", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMin(time_t const Valid) +{ + if (d->ValidUntilMin == 0) + d->ValidUntilMin = Valid; + else if (d->ValidUntilMin != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Min-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} +bool debReleaseIndex::SetValidUntilMax(time_t const Valid) +{ + if (d->ValidUntilMax == 0) + d->ValidUntilMax = Valid; + else if (d->ValidUntilMax != Valid) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str()); + return true; +} + /*}}}*/ +// ReleaseIndex::IsTrusted /*{{{*/ bool debReleaseIndex::IsTrusted() const { if (Trusted == TRI_YES) @@ -601,6 +644,22 @@ static std::vector parsePlusMinusOptions(std::string const &Name, / /*}}}*/ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ { + metaIndex::TriState GetTriStateOption(std::mapconst &Options, char const * const name) const + { + std::map::const_iterator const opt = Options.find(name); + if (opt != Options.end()) + return StringToBool(opt->second, false) ? metaIndex::TRI_YES : metaIndex::TRI_NO; + return metaIndex::TRI_DONTCARE; + } + + time_t GetTimeOption(std::mapconst &Options, char const * const name) const + { + std::map::const_iterator const opt = Options.find(name); + if (opt == Options.end()) + return 0; + return strtoull(opt->second.c_str(), NULL, 10); + } + protected: bool CreateItemInternal(std::vector &List, std::string const &URI, @@ -641,13 +700,10 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) ); - std::map::const_iterator const trusted = Options.find("trusted"); - if (trusted != Options.end()) - { - if (Deb->SetTrusted(StringToBool(trusted->second, false) ? debReleaseIndex::TRI_YES : debReleaseIndex::TRI_NO) == false) - return false; - } - else if (Deb->SetTrusted(debReleaseIndex::TRI_DONTCARE) == false) + if (Deb->SetTrusted(GetTriStateOption(Options, "trusted")) == false || + Deb->SetCheckValidUntil(GetTriStateOption(Options, "check-valid-until")) == false || + Deb->SetValidUntilMax(GetTimeOption(Options, "valid-until-max")) == false || + Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false) return false; return true; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 19fe6806c..879eb3bfc 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -53,6 +53,9 @@ class APT_HIDDEN debReleaseIndex : public metaIndex virtual std::vector *GetIndexFiles(); bool SetTrusted(TriState const Trusted); + bool SetCheckValidUntil(TriState const Trusted); + bool SetValidUntilMin(time_t const Valid); + bool SetValidUntilMax(time_t const Valid); virtual bool IsTrusted() const; diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 0502f0e1d..0d65558ed 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -103,6 +103,9 @@ bool pkgSourceList::Type::ParseStanza(vector &List, /*{{{*/ APT_PLUSMINUS("Targets", "target"); #undef APT_PLUSMINUS mapping.insert(std::make_pair("Trusted", "trusted")); + mapping.insert(std::make_pair("Check-Valid-Until", "check-valid-until")); + mapping.insert(std::make_pair("Valid-Until-Min", "valid-until-min")); + mapping.insert(std::make_pair("Valid-Until-Max", "valid-until-max")); for (std::map::const_iterator m = mapping.begin(); m != mapping.end(); ++m) if (Tags.Exists(m->first)) diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 5b6788ed4..b0fe390df 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -531,9 +531,13 @@ - Ignore if packages can't be authenticated and don't prompt about it. - This is useful for tools like pbuilder. - Configuration Item: APT::Get::AllowUnauthenticated. + Ignore if packages can't be authenticated and don't prompt + about it. This can be useful while working with local repositories, + but is a huge security risk if data authenticity isn't ensured in + another way by the user itself. The usage of the + option for &sources-list; entries should + usually be preferred over this global override. Configuration Item: + APT::Get::AllowUnauthenticated. diff --git a/doc/apt.conf.5.xml b/doc/apt.conf.5.xml index 7d5f7e9b3..103d0622c 100644 --- a/doc/apt.conf.5.xml +++ b/doc/apt.conf.5.xml @@ -301,6 +301,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; Valid-Until header, but if they don't or a stricter value is desired the Max-ValidTime option below can be used. + The option of &sources-list; entries should be + preferred to disable the check selectively instead of using this global override. @@ -312,7 +314,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; the earlier date of the two is used as the expiration date. The default value is 0 which stands for "valid forever". Archive specific settings can be made by appending the label of the archive - to the option name. + to the option name. Preferably, the same can be achieved for specific + &sources-list; entries by using the option there. @@ -324,7 +327,8 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";}; frequently updated archive with a Valid-Until header instead of completely disabling the expiration date checking. Archive specific settings can and should be used by appending the label of - the archive to the option name. + the archive to the option name. Preferably, the same can be achieved for specific + &sources-list; entries by using the option there. diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index f87dcda23..aded8ecef 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -202,26 +202,26 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. APT versions. - Architectures - (arch) is a multivalue option defining for + + () is a multivalue option defining for which architectures information should be downloaded. If this option isn't set the default is all architectures as defined by - the APT::Architectures config option. + the config option. - Languages - (lang) is a multivalue option defining for + + () is a multivalue option defining for which languages information like translated package descriptions should be downloaded. If this option isn't set the default is all languages as defined by the - Acquire::Languages config option. + config option. - Targets - (target) is a multivalue option defining + + () is a multivalue option defining which download targets apt will try to acquire from this source. If not specified, the default set is defined by the - APT::Acquire::Targets configuration scope. + configuration scope. @@ -232,7 +232,7 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. anomalies. - Trusted (trusted) + () is a tri-state value which defaults to APT deciding if a source is considered trusted or if warnings should be raised before e.g. packages are installed from this source. This option can be used @@ -245,6 +245,41 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. as untrusted even if the authentication checks passed successfully. The default value can't be set explicitly. + + () + is a yes/no value which controls if APT should try to detect + replay attacks. A repository creator can declare until then the + data provided in the repository should be considered valid and + if this time is reached, but no new data is provided the data + is considered expired and an error is raised. Beside + increasing security as a malicious attacker can't sent old data + forever denying a user to be able to upgrade to a new version, + this also helps users identify mirrors which are no longer + updated. Some repositories like historic archives aren't + updated anymore by design through, so this check can be + disabled by setting this option to no. + Defaults to the value of configuration option + which itself + defaults to yes. + + + + () and + + () can be used to raise or + lower the time period in seconds in which the data from this + repository is considered valid. -Max can be especially useful + if the repository provides no Valid-Until field on its Release + file to set your own value, while -Min can be used to increase + the valid time on seldomly updated (local) mirrors of a more + frequently updated but less accessible archive (which is in the + sources.list as well) instead of disabling the check entirely. + Default to the value of the configuration options + and + which are both unset by + default. + + diff --git a/test/integration/test-releasefile-valid-until b/test/integration/test-releasefile-valid-until index e000abf5d..43574ec3e 100755 --- a/test/integration/test-releasefile-valid-until +++ b/test/integration/test-releasefile-valid-until @@ -46,3 +46,12 @@ runtest 'accepted' 'good Min-Valid (bad Until, good Max-Valid) <' 'now - 7 days' runtest 'rejected' 'bad Max-Valid (bad Until, good Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=2419200 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) <' 'now - 7 days' 'now - 2 days' -o Acquire::Min-ValidTime=12096 -o Acquire::Max-ValidTime=241920 runtest 'rejected' 'bad Max-Valid (bad Until, bad Min-Valid) >' 'now - 7 days' 'now - 2 days' -o Acquire::Max-ValidTime=12096 -o Acquire::Min-ValidTime=241920 + +sed -i -e 's#\(deb\(-src\)\?\) #\1 [check-valid-until=no] #' rootdir/etc/apt/sources.list.d/* +runtest 'accepted' 'bad Until but overriden by sources option' 'now - 7 days' 'now - 4 days' + +sed -i -e 's#\(deb\(-src\)\?\) \[check-valid-until=no\] #\1 [valid-until-max=86400] #' rootdir/etc/apt/sources.list.d/* +runtest 'rejected' 'bad Max-Valid (good Until) via sources option' 'now - 7 days' 'now + 4 days' + +sed -i -e 's#\(deb\(-src\)\?\) \[valid-until-max=86400\] #\1 [valid-until-min=1209600] #' rootdir/etc/apt/sources.list.d/* +runtest 'accepted' 'good Min-Valid (bad Until) via sources option' 'now - 7 days' 'now - 4 days' -- cgit v1.2.3-70-g09d2 From b0d408547734100bf86781615f546487ecf390d9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Wed, 24 Jun 2015 19:31:22 +0200 Subject: implement Signed-By option for sources.list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limits which key(s) can be used to sign a repository. Not immensely useful from a security perspective all by itself, but if the user has additional measures in place to confine a repository (like pinning) an attacker who gets the key for such a repository is limited to its potential and can't use the key to sign its attacks for an other (maybe less limited) repository… (yes, this is as weak as it sounds, but having the capability might come in handy for implementing other stuff later). --- apt-pkg/acquire-item.cc | 15 +++++++- apt-pkg/acquire-item.h | 1 + apt-pkg/contrib/gpgv.cc | 17 +++++++++- apt-pkg/contrib/gpgv.h | 5 ++- apt-pkg/deb/debmetaindex.cc | 35 +++++++++++++++++++ apt-pkg/deb/debmetaindex.h | 1 + apt-pkg/metaindex.cc | 4 +-- apt-pkg/metaindex.h | 4 ++- apt-pkg/sourcelist.cc | 28 ++++++++------- cmdline/apt-key.in | 22 ++++++++++-- doc/sources.list.5.xml | 24 ++++++------- methods/gpgv.cc | 18 +++++----- test/integration/framework | 23 +++++++++---- test/integration/test-apt-key | 37 ++++++++++++++++++-- test/integration/test-releasefile-verification | 47 +++++++++++++++++++++++--- 15 files changed, 225 insertions(+), 56 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index a30a5d154..01a679fe0 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -808,7 +808,6 @@ string pkgAcqMetaBase::Custom600Headers() const Header += MaximumSize; string const FinalFile = GetFinalFilename(); - struct stat Buf; if (stat(FinalFile.c_str(),&Buf) == 0) Header += "\nLast-Modified: " + TimeRFC1123(Buf.st_mtime); @@ -1132,6 +1131,10 @@ string pkgAcqMetaClearSig::Custom600Headers() const { string Header = pkgAcqMetaBase::Custom600Headers(); Header += "\nFail-Ignore: true"; + std::string const key = TransactionManager->MetaIndexParser->GetSignedBy(); + if (key.empty() == false) + Header += "\nSigned-By: " + key; + return Header; } /*}}}*/ @@ -1372,6 +1375,16 @@ pkgAcqMetaSig::pkgAcqMetaSig(pkgAcquire * const Owner, /*}}}*/ pkgAcqMetaSig::~pkgAcqMetaSig() /*{{{*/ { +} + /*}}}*/ +// pkgAcqMetaSig::Custom600Headers - Insert custom request headers /*{{{*/ +std::string pkgAcqMetaSig::Custom600Headers() const +{ + std::string Header = pkgAcqTransactionItem::Custom600Headers(); + std::string const key = TransactionManager->MetaIndexParser->GetSignedBy(); + if (key.empty() == false) + Header += "\nSigned-By: " + key; + return Header; } /*}}}*/ // AcqMetaSig::Done - The signature was downloaded/verified /*{{{*/ diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 10ece76c9..1cd2a6d03 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -541,6 +541,7 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf); + virtual std::string Custom600Headers() const; /** \brief Create a new pkgAcqMetaSig. */ pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, diff --git a/apt-pkg/contrib/gpgv.cc b/apt-pkg/contrib/gpgv.cc index a01e319eb..ef84da0d8 100644 --- a/apt-pkg/contrib/gpgv.cc +++ b/apt-pkg/contrib/gpgv.cc @@ -16,6 +16,8 @@ #include #include #include + +#include #include #include #include @@ -42,7 +44,7 @@ static char * GenerateTemporaryFileTemplate(const char *basename) /*{{{*/ of the lifting in regards to merging keyrings. Fun for the whole family. */ void ExecGPGV(std::string const &File, std::string const &FileGPG, - int const &statusfd, int fd[2]) + int const &statusfd, int fd[2], std::string const &key) { #define EINTERNAL 111 std::string const aptkey = _config->FindFile("Dir::Bin::apt-key", "/usr/bin/apt-key"); @@ -55,6 +57,19 @@ void ExecGPGV(std::string const &File, std::string const &FileGPG, Args.push_back(aptkey.c_str()); Args.push_back("--quiet"); Args.push_back("--readonly"); + if (key.empty() == false) + { + if (key[0] == '/') + { + Args.push_back("--keyring"); + Args.push_back(key.c_str()); + } + else + { + Args.push_back("--keyid"); + Args.push_back(key.c_str()); + } + } Args.push_back("verify"); char statusfdstr[10]; diff --git a/apt-pkg/contrib/gpgv.h b/apt-pkg/contrib/gpgv.h index f018893fd..2a4cdad72 100644 --- a/apt-pkg/contrib/gpgv.h +++ b/apt-pkg/contrib/gpgv.h @@ -38,9 +38,12 @@ class FileFd; * * @param File is the message (unsigned or clear-signed) * @param FileSig is the signature (detached or clear-signed) + * @param statusfd is the fd given to gpgv as --status-fd + * @param fd is used as a pipe for the standard output of gpgv + * @param key is the specific one to be used instead of using all */ void ExecGPGV(std::string const &File, std::string const &FileSig, - int const &statusfd, int fd[2]) APT_NORETURN; + int const &statusfd, int fd[2], std::string const &Key = "") APT_NORETURN; inline APT_NORETURN void ExecGPGV(std::string const &File, std::string const &FileSig, int const &statusfd = -1) { int fd[2]; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 5d7e539c7..4bb03a942 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -461,6 +461,29 @@ bool debReleaseIndex::SetValidUntilMax(time_t const Valid) else if (d->ValidUntilMax != Valid) return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Max-ValidTime", URI.c_str(), Dist.c_str()); return true; +} +bool debReleaseIndex::SetSignedBy(std::string const &pSignedBy) +{ + if (SignedBy.empty() == true && pSignedBy.empty() == false) + { + if (pSignedBy[0] == '/') // no check for existence as we could be chrooting later or such things + ; // absolute path to a keyring file + else + { + // we could go all fancy and allow short/long/string matches as gpgv/apt-key does, + // but fingerprints are harder to fake than the others and this option is set once, + // not interactively all the time so easy to type is not really a concern. + std::string finger = pSignedBy; + finger.erase(std::remove(finger.begin(), finger.end(), ' '), finger.end()); + std::transform(finger.begin(), finger.end(), finger.begin(), ::toupper); + if (finger.length() != 40 || finger.find_first_not_of("0123456789ABCDEF") != std::string::npos) + return _error->Error(_("Invalid value set for option %s concerning source %s %s (%s)"), "Signed-By", URI.c_str(), Dist.c_str(), "not a fingerprint"); + } + SignedBy = pSignedBy; + } + else if (SignedBy != pSignedBy) + return _error->Error(_("Conflicting values set for option %s concerning source %s %s"), "Signed-By", URI.c_str(), Dist.c_str()); + return true; } /*}}}*/ // ReleaseIndex::IsTrusted /*{{{*/ @@ -706,6 +729,18 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ Deb->SetValidUntilMin(GetTimeOption(Options, "valid-until-min")) == false) return false; + std::map::const_iterator const signedby = Options.find("signed-by"); + if (signedby == Options.end()) + { + if (Deb->SetSignedBy("") == false) + return false; + } + else + { + if (Deb->SetSignedBy(signedby->second) == false) + return false; + } + return true; } diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 879eb3bfc..bf5b7c1ce 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -56,6 +56,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex bool SetCheckValidUntil(TriState const Trusted); bool SetValidUntilMin(time_t const Valid); bool SetValidUntilMax(time_t const Valid); + bool SetSignedBy(std::string const &SignedBy); virtual bool IsTrusted() const; diff --git a/apt-pkg/metaindex.cc b/apt-pkg/metaindex.cc index 8bd13bb18..baf695f16 100644 --- a/apt-pkg/metaindex.cc +++ b/apt-pkg/metaindex.cc @@ -27,8 +27,7 @@ bool metaIndex::Merge(pkgCacheGenerator &Gen,OpProgress *) const metaIndex::metaIndex(std::string const &URI, std::string const &Dist, char const * const Type) : d(NULL), Indexes(NULL), Type(Type), URI(URI), Dist(Dist), Trusted(TRI_UNSET), - LoadedSuccessfully(TRI_UNSET), - Date(0), ValidUntil(0), SupportsAcquireByHash(false) + Date(0), ValidUntil(0), SupportsAcquireByHash(false), LoadedSuccessfully(TRI_UNSET) { /* nothing */ } @@ -48,6 +47,7 @@ APT_PURE std::string metaIndex::GetURI() const { return URI; } APT_PURE std::string metaIndex::GetDist() const { return Dist; } APT_PURE const char* metaIndex::GetType() const { return Type; } APT_PURE metaIndex::TriState metaIndex::GetTrusted() const { return Trusted; } +APT_PURE std::string metaIndex::GetSignedBy() const { return SignedBy; } APT_PURE std::string metaIndex::GetCodename() const { return Codename; } APT_PURE std::string metaIndex::GetSuite() const { return Suite; } APT_PURE bool metaIndex::GetSupportsAcquireByHash() const { return SupportsAcquireByHash; } diff --git a/apt-pkg/metaindex.h b/apt-pkg/metaindex.h index 5be7397ae..d284655bf 100644 --- a/apt-pkg/metaindex.h +++ b/apt-pkg/metaindex.h @@ -52,7 +52,7 @@ protected: std::string URI; std::string Dist; TriState Trusted; - TriState LoadedSuccessfully; + std::string SignedBy; // parsed from a file std::string Suite; @@ -61,6 +61,7 @@ protected: time_t ValidUntil; bool SupportsAcquireByHash; std::map Entries; + TriState LoadedSuccessfully; public: // Various accessors @@ -68,6 +69,7 @@ public: std::string GetDist() const; const char* GetType() const; TriState GetTrusted() const; + std::string GetSignedBy() const; std::string GetCodename() const; std::string GetSuite() const; diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index 0d65558ed..eef0ee709 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -93,27 +93,29 @@ bool pkgSourceList::Type::ParseStanza(vector &List, /*{{{*/ if (Enabled.empty() == false && StringToBool(Enabled) == false) return true; - std::map mapping; + std::map > mapping; #define APT_PLUSMINUS(X, Y) \ - mapping.insert(std::make_pair(X, Y)); \ - mapping.insert(std::make_pair(X "Add", Y "+")); \ - mapping.insert(std::make_pair(X "Remove", Y "-")) + mapping.insert(std::make_pair(X, std::make_pair(Y, true))); \ + mapping.insert(std::make_pair(X "Add", std::make_pair(Y "+", true))); \ + mapping.insert(std::make_pair(X "Remove", std::make_pair(Y "-", true))) APT_PLUSMINUS("Architectures", "arch"); APT_PLUSMINUS("Languages", "lang"); APT_PLUSMINUS("Targets", "target"); #undef APT_PLUSMINUS - mapping.insert(std::make_pair("Trusted", "trusted")); - mapping.insert(std::make_pair("Check-Valid-Until", "check-valid-until")); - mapping.insert(std::make_pair("Valid-Until-Min", "valid-until-min")); - mapping.insert(std::make_pair("Valid-Until-Max", "valid-until-max")); + mapping.insert(std::make_pair("Trusted", std::make_pair("trusted", false))); + mapping.insert(std::make_pair("Check-Valid-Until", std::make_pair("check-valid-until", false))); + mapping.insert(std::make_pair("Valid-Until-Min", std::make_pair("valid-until-min", false))); + mapping.insert(std::make_pair("Valid-Until-Max", std::make_pair("valid-until-max", false))); + mapping.insert(std::make_pair("Signed-By", std::make_pair("signed-by", false))); - for (std::map::const_iterator m = mapping.begin(); m != mapping.end(); ++m) + for (std::map >::const_iterator m = mapping.begin(); m != mapping.end(); ++m) if (Tags.Exists(m->first)) { - // for deb822 the " " is the delimiter, but the backend expects "," - std::string option = Tags.FindS(m->first); - std::replace(option.begin(), option.end(), ' ', ','); - Options[m->second] = option; + std::string option = Tags.FindS(m->first); + // for deb822 the " " is the delimiter, but the backend expects "," + if (m->second.second == true) + std::replace(option.begin(), option.end(), ' ', ','); + Options[m->second.first] = option; } // now create one item per suite/section diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index 2a66ad74d..16887bd50 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -199,7 +199,7 @@ remove_key_from_keyring() { foreach_keyring_do() { local ACTION="$1" shift - # if a --keyring was given, just remove from there + # if a --keyring was given, just work on this one if [ -n "$FORCED_KEYRING" ]; then $ACTION "$FORCED_KEYRING" "$@" else @@ -279,7 +279,14 @@ merge_back_changes() { } setup_merged_keyring() { - if [ -z "$FORCED_KEYRING" ]; then + if [ -n "$FORCED_KEYID" ]; then + foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/allrings.gpg" + FORCED_KEYRING="${GPGHOMEDIR}/forcedkeyid.gpg" + TRUSTEDFILE="${FORCED_KEYRING}" + GPG="$GPG --keyring $TRUSTEDFILE" + # ignore error as this "just" means we haven't found the forced keyid and the keyring will be empty + $GPG_CMD --batch --yes --keyring "${GPGHOMEDIR}/allrings.gpg" --export "$FORCED_KEYID" | $GPG --batch --yes --import || true + elif [ -z "$FORCED_KEYRING" ]; then foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" if [ -r "${GPGHOMEDIR}/pubring.gpg" ]; then cp -a "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg" @@ -328,12 +335,17 @@ while [ -n "$1" ]; do TRUSTEDFILE="$1" FORCED_KEYRING="$1" ;; + --keyid) + shift + FORCED_KEYID="$1" + ;; --secret-keyring) shift FORCED_SECRET_KEYRING="$1" ;; --readonly) merge_back_changes() { true; } + create_new_keyring() { true; } ;; --fakeroot) requires_root() { true; } @@ -460,7 +472,11 @@ case "$command" in verify) setup_merged_keyring if which gpgv >/dev/null 2>&1; then - gpgv --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" + if [ -n "$FORCED_KEYRING" ]; then + gpgv --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@" + else + gpgv --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" + fi else $GPG --verify "$@" fi diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index aded8ecef..12a7773f5 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -232,18 +232,18 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. anomalies. - () - is a tri-state value which defaults to APT deciding if a source - is considered trusted or if warnings should be raised before e.g. - packages are installed from this source. This option can be used - to override this decision either with the value yes, - which lets APT consider this source always as a trusted source - even if it has no or fails authentication checks by disabling parts - of &apt-secure; and should therefore only be used in a local and trusted - context (if at all) as otherwise security is breached. The opposite - can be achieved with the value no, which causes the source to be handled - as untrusted even if the authentication checks passed successfully. - The default value can't be set explicitly. + () + is either an absolute path to a keyring file (has to be + accessible and readable for the _apt user, + so ensure everyone has read-permissions on the file) or a + fingerprint of a key in either the + trusted.gpg keyring or in one of the + keyrings in the trusted.gpg.d/ directory + (see apt-key fingerprint). If the option is + set only the key(s) in this keyring or only the key with this + fingerprint is used for the &apt-secure; verification of this + repository. Otherwise all keys in the trusted keyrings are + considered valid signers for this repository. () diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 41f138be6..014430041 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -37,13 +37,14 @@ class GPGVMethod : public pkgAcqMethod { private: string VerifyGetSigners(const char *file, const char *outfile, - vector &GoodSigners, + std::string const &key, + vector &GoodSigners, vector &BadSigners, vector &WorthlessSigners, vector &NoPubKeySigners); protected: - virtual bool Fetch(FetchItem *Itm); + virtual bool URIAcquire(std::string const &Message, FetchItem *Itm); virtual bool Configuration(string Message); public: @@ -61,6 +62,7 @@ bool GPGVMethod::Configuration(string Message) } string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, + std::string const &key, vector &GoodSigners, vector &BadSigners, vector &WorthlessSigners, @@ -80,7 +82,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, if (pid < 0) return string("Couldn't spawn new process") + strerror(errno); else if (pid == 0) - ExecGPGV(outfile, file, 3, fd); + ExecGPGV(outfile, file, 3, fd, key); close(fd[1]); FILE *pipein = fdopen(fd[0], "r"); @@ -174,11 +176,11 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, return _("Unknown error executing apt-key"); } -bool GPGVMethod::Fetch(FetchItem *Itm) +bool GPGVMethod::URIAcquire(std::string const &Message, FetchItem *Itm) { - URI Get = Itm->Uri; - string Path = Get.Host + Get.Path; // To account for relative paths - string keyID; + URI const Get = Itm->Uri; + string const Path = Get.Host + Get.Path; // To account for relative paths + std::string const key = LookupTag(Message, "Signed-By"); vector GoodSigners; vector BadSigners; // a worthless signature is a expired or revoked one @@ -190,7 +192,7 @@ bool GPGVMethod::Fetch(FetchItem *Itm) URIStart(Res); // Run apt-key on file, extract contents and get the key ID of the signer - string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), + string msg = VerifyGetSigners(Path.c_str(), Itm->DestFile.c_str(), key, GoodSigners, BadSigners, WorthlessSigners, NoPubKeySigners); if (GoodSigners.empty() || !BadSigners.empty() || !NoPubKeySigners.empty()) diff --git a/test/integration/framework b/test/integration/framework index 059cba9fb..6ae5003f7 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1414,14 +1414,23 @@ testfailure() { else local EXITCODE=$? if expr match "$1" '^apt.*' >/dev/null; then - if grep -q -E ' runtime error: ' "$OUTPUT"; then - msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" - elif grep -q -E '==ERROR' "$OUTPUT"; then - msgfailoutput 'compiler sanitizers reported errors' "$OUTPUT" "$@" - elif ! grep -q -E '^E: ' "$OUTPUT"; then - msgfailoutput "run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" + if [ "$1" = 'aptkey' ]; then + if grep -q -E " Can't check signature: " "$OUTPUT" || \ + grep -q -E " BAD signature from " "$OUTPUT"; then + msgpass + else + msgfailoutput "run failed with exitcode ${EXITCODE}, but no signature error" "$OUTPUT" "$@" + fi else - msgpass + if grep -q -E ' runtime error: ' "$OUTPUT"; then + msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" + elif grep -q -E '==ERROR' "$OUTPUT"; then + msgfailoutput 'compiler sanitizers reported errors' "$OUTPUT" "$@" + elif ! grep -q -E '^E: ' "$OUTPUT"; then + msgfailoutput "run failed with exitcode ${EXITCODE}, but with no errors" "$OUTPUT" "$@" + else + msgpass + fi fi else msgpass diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key index 486acccc8..e1be08c65 100755 --- a/test/integration/test-apt-key +++ b/test/integration/test-apt-key @@ -73,7 +73,7 @@ pub 2048R/DBAC8DAE 2010-08-18' testsuccess aptkey --fakeroot del DBAC8DAE testempty aptkey list - msgtest 'Test key removal with' 'lowercase key ID' #keylength somewher between 8byte and short + msgtest 'Test key removal with' 'lowercase key ID' #keylength somewhere between 8byte and short cleanplate cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg testsuccess --nomsg aptkey --fakeroot del d141dbac8dae @@ -166,6 +166,40 @@ pub 2048R/528144E2 2011-01-16' msgtest 'Test merge-back of' 'removed duplicate keys' testsuccess --nomsg aptkey adv --batch --yes --delete-keys DBAC8DAE testaptkeys 'pub 2048R/528144E2 2011-01-16' + + cleanplate + cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg + cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg + msgtest 'Test signing a file' 'with a key' + echo 'Verify me. This is my signature.' > signature + testsuccess --nomsg aptkey --quiet --keyring keys/marvinparanoid.pub --secret-keyring keys/marvinparanoid.sec --readonly \ + adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output signature.gpg signature + + msgtest 'Test verify a file' 'with all keys' + testsuccess --nomsg aptkey --quiet --readonly verify signature.gpg signature + + msgtest 'Test verify a file' 'with good keyring' + testsuccess --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature.gpg signature + + msgtest 'Test fail verify a file' 'with bad keyring' + testfailure --nomsg aptkey --quiet --readonly --keyring keys/joesixpack.pub verify signature.gpg signature + + msgtest 'Test fail verify a file' 'with non-existing keyring' + testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature + testfailure test -e keys/does-not-exist.pub + + msgtest 'Test verify a file' 'with good keyid' + testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify signature.gpg signature + + msgtest 'Test fail verify a file' 'with bad keyid' + testfailure --nomsg aptkey --quiet --readonly --keyid 'Sixpack' verify signature.gpg signature + + msgtest 'Test fail verify a file' 'with non-existing keyid' + testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify signature.gpg signature + + msgtest 'Test verify fails on' 'bad file' + echo 'lalalalala' > signature + testfailure --nomsg aptkey --quiet --readonly verify signature.gpg signature } setupgpgcommand() { @@ -187,4 +221,3 @@ setupgpgcommand 'gpg' testrun setupgpgcommand 'gpg2' testrun - diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index e8419524c..1c3953c8b 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -139,11 +139,6 @@ runtest() { failaptold prepare ${PKGFILE}-new - # weborf doesn't support If-Range - for release in $(find rootdir/var/lib/apt/lists/partial/ -name '*Release'); do - rm $release - touch $release - done signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgmsg 'Bad warm archive signed by' 'Joe Sixpack' @@ -191,6 +186,48 @@ runtest() { testsuccessequal "$(cat ${PKGFILE}-new) " aptcache show apt installaptnew + + prepare ${PKGFILE} + rm -rf rootdir/var/lib/apt/lists + signreleasefiles 'Marvin Paranoid' + find aptarchive/ -name "$DELETEFILE" -delete + msgmsg 'Cold archive signed by good keyring' 'Marvin Paranoid' + local MARVIN="$(readlink -f keys/marvinparanoid.pub)" + sed -i "s#^\(deb\(-src\)\?\) #\1 [signed-by=$MARVIN] #" rootdir/etc/apt/sources.list.d/* + testsuccess aptget update -o Debug::pkgAcquire::Worker=1 + testsuccessequal "$(cat ${PKGFILE}) +" aptcache show apt + installaptold + + rm -rf rootdir/var/lib/apt/lists + signreleasefiles 'Joe Sixpack' + find aptarchive/ -name "$DELETEFILE" -delete + msgmsg 'Cold archive signed by bad keyring' 'Joe Sixpack' + updatewithwarnings '^W: .* NO_PUBKEY' + + sed -i "s#^\(deb\(-src\)\?\) \[signed-by=$MARVIN\] #\1 #" rootdir/etc/apt/sources.list.d/* + local MARVIN="$(aptkey --keyring $MARVIN finger | grep 'Key fingerprint' | cut -d'=' -f 2 | tr -d ' ')" + + prepare ${PKGFILE} + rm -rf rootdir/var/lib/apt/lists + signreleasefiles 'Marvin Paranoid' + find aptarchive/ -name "$DELETEFILE" -delete + msgmsg 'Cold archive signed by good keyid' 'Marvin Paranoid' + sed -i "s#^\(deb\(-src\)\?\) #\1 [signed-by=$MARVIN] #" rootdir/etc/apt/sources.list.d/* + cp keys/marvinparanoid.pub rootdir/etc/apt/trusted.gpg.d/marvinparanoid.gpg + testsuccess aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::gpgv=1 + testsuccessequal "$(cat ${PKGFILE}) +" aptcache show apt + installaptold + rm -f rootdir/etc/apt/trusted.gpg.d/marvinparanoid.gpg + + rm -rf rootdir/var/lib/apt/lists + signreleasefiles 'Joe Sixpack' + find aptarchive/ -name "$DELETEFILE" -delete + msgmsg 'Cold archive signed by bad keyid' 'Joe Sixpack' + updatewithwarnings '^W: .* NO_PUBKEY' + + sed -i "s#^\(deb\(-src\)\?\) \[signed-by=$MARVIN\] #\1 #" rootdir/etc/apt/sources.list.d/* } runtest2() { -- cgit v1.2.3-70-g09d2 From 653ef26c70dc9c0e2cbfdd4e79117876bb63e87d Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 30 Jun 2015 10:53:51 +0200 Subject: allow individual targets to be kept compressed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is an option to keep all targets (Packages, Sources, …) compressed for a while now, but the all-or-nothing approach is a bit limited for our purposes with additional targets as some of them are very big (Contents) and rarely used in comparison, so keeping them compressed by default can make sense, while others are still unpacked. Most interesting is the copy-change maybe: Copy is used by the acquire system as an uncompressor and it is hence expected that it returns the hashes for the "output", not the input. Now, in the case of keeping a file compressed, the output is never written to disk, but generated in memory and we should still validated it, so for compressed files copy is expected to return the hashes of the uncompressed file. We used to use the config option to enable on-the-fly decompress in the method, but in reality copy is never used in a way where it shouldn't decompress a compressed file to get its hashes, so we can save us the trouble of sending this information to the method and just do it always. --- apt-pkg/acquire-item.cc | 14 +++++++------- apt-pkg/deb/debmetaindex.cc | 7 +++++-- apt-pkg/indexfile.cc | 5 +++-- apt-pkg/indexfile.h | 5 ++++- methods/copy.cc | 8 ++------ test/integration/test-apt-acquire-additional-files | 18 +++++++++++++++++- test/integration/test-compressed-indexes | 2 +- 7 files changed, 39 insertions(+), 20 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 01a679fe0..b6466115e 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -80,18 +80,18 @@ static std::string GetFinalFileNameFromURI(std::string const &uri) /*{{{*/ return _config->FindDir("Dir::State::lists") + URItoFileName(uri); } /*}}}*/ -static std::string GetCompressedFileName(std::string const &URI, std::string const &Name, std::string const &Ext) /*{{{*/ +static std::string GetCompressedFileName(IndexTarget const &Target, std::string const &Name, std::string const &Ext) /*{{{*/ { if (Ext.empty() || Ext == "uncompressed") return Name; // do not reverify cdrom sources as apt-cdrom may rewrite the Packages // file when its doing the indexcopy - if (URI.substr(0,6) == "cdrom:") + if (Target.URI.substr(0,6) == "cdrom:") return Name; // adjust DestFile if its compressed on disk - if (_config->FindB("Acquire::GzipIndexes",false) == true) + if (Target.KeepCompressed == true) return Name + '.' + Ext; return Name; } @@ -269,7 +269,7 @@ std::string pkgAcqDiffIndex::GetFinalFilename() const std::string pkgAcqIndex::GetFinalFilename() const { std::string const FinalFile = GetFinalFileNameFromURI(Target.URI); - return GetCompressedFileName(Target.URI, FinalFile, CurrentCompressionExtension); + return GetCompressedFileName(Target, FinalFile, CurrentCompressionExtension); } std::string pkgAcqMetaSig::GetFinalFilename() const { @@ -2456,7 +2456,7 @@ void pkgAcqIndex::ReverifyAfterIMS() { // update destfile to *not* include the compression extension when doing // a reverify (as its uncompressed on disk already) - DestFile = GetCompressedFileName(Target.URI, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension); + DestFile = GetCompressedFileName(Target, GetPartialFileNameFromURI(Target.URI), CurrentCompressionExtension); // copy FinalFile into partial/ so that we check the hash again string FinalFile = GetFinalFilename(); @@ -2532,8 +2532,8 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const return; } - // If we have compressed indexes enabled, queue for hash verification - if (_config->FindB("Acquire::GzipIndexes",false)) + // If we want compressed indexes, just copy in place for hash verification + if (Target.KeepCompressed == true) { DestFile = GetPartialFileNameFromURI(Target.URI + '.' + CurrentCompressionExtension); EraseFileName = ""; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 4bb03a942..10ab0f844 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -123,6 +123,7 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const Release = (Dist == "/") ? "" : Dist; std::string const Site = ::URI::ArchiveOnly(URI); + bool const GzipIndex = _config->FindB("Acquire::GzipIndexes", false); for (std::vector::const_iterator E = entries.begin(); E != entries.end(); ++E) { for (std::vector::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T) @@ -131,7 +132,8 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const tplShortDesc = APT_T_CONFIG("ShortDescription"); std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); - bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::deb-src::") + *T + "::Optional", true); + bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::Optional", true); + bool const KeepCompressed = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); #undef APT_T_CONFIG if (tplMetaKey.empty()) continue; @@ -173,6 +175,7 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, LongDesc, Options.find("BASE_URI")->second + MetaKey, IsOptional, + KeepCompressed, Options ); IndexTargets.push_back(Target); @@ -413,7 +416,7 @@ bool debReleaseIndex::parseSumData(const char *&Start, const char *End, /*{{{*/ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll)/*{{{*/ { std::vector const targets = GetIndexTargets(); -#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, std::map()) +#define APT_TARGET(X) IndexTarget("", X, MetaIndexInfo(X), MetaIndexURI(X), false, false, std::map()) pkgAcqMetaClearSig * const TransactionManager = new pkgAcqMetaClearSig(Owner, APT_TARGET("InRelease"), APT_TARGET("Release"), APT_TARGET("Release.gpg"), targets, this); diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index e9e1b08c3..cce17403d 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -115,8 +115,9 @@ APT_DEPRECATED std::string pkgIndexFile::LanguageCode() { // IndexTarget - Constructor /*{{{*/ IndexTarget::IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, std::string const &LongDesc, std::string const &URI, bool const IsOptional, - std::map const &Options) : - URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), IsOptional(IsOptional), Options(Options) + bool const KeepCompressed, std::map const &Options) : + URI(URI), Description(LongDesc), ShortDesc(ShortDesc), MetaKey(MetaKey), + IsOptional(IsOptional), KeepCompressed(KeepCompressed), Options(Options) { } /*}}}*/ diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 7eeccdbd3..44d39110d 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -60,6 +60,9 @@ class IndexTarget /*{{{*/ /** \brief Is it okay if the file isn't found in the meta index */ bool IsOptional; + /** \brief If the file is downloaded compressed, do not unpack it */ + bool KeepCompressed; + /** \brief options with which this target was created Prefer the usage of #Option if at all possible. Beware: Not all of these options are intended for public use */ @@ -67,7 +70,7 @@ class IndexTarget /*{{{*/ IndexTarget(std::string const &MetaKey, std::string const &ShortDesc, std::string const &LongDesc, std::string const &URI, bool const IsOptional, - std::map const &Options); + bool const KeepCompressed, std::map const &Options); enum OptionKeys { SITE, diff --git a/methods/copy.cc b/methods/copy.cc index a8e289df5..4bdc15f75 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -38,11 +38,7 @@ class CopyMethod : public pkgAcqMethod void CopyMethod::CalculateHashes(FetchItem const * const Itm, FetchResult &Res) { Hashes Hash(Itm->ExpectedHashes); - FileFd::CompressMode CompressMode = FileFd::None; - if (_config->FindB("Acquire::GzipIndexes", false) == true) - CompressMode = FileFd::Extension; - - FileFd Fd(Res.Filename, FileFd::ReadOnly, CompressMode); + FileFd Fd(Res.Filename, FileFd::ReadOnly, FileFd::Extension); Hash.AddFD(Fd); Res.TakeHashes(Hash); } @@ -53,7 +49,7 @@ void CopyMethod::CalculateHashes(FetchItem const * const Itm, FetchResult &Res) bool CopyMethod::Fetch(FetchItem *Itm) { // this ensures that relative paths work in copy - std::string File = Itm->Uri.substr(Itm->Uri.find(':')+1); + std::string const File = Itm->Uri.substr(Itm->Uri.find(':')+1); // Stat the file and send a start message struct stat Buf; diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index 3465c0a16..fecdf30bf 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -57,7 +57,23 @@ testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64)" aptget files --format '$(FILENAME)' 'Created-By: Contents' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64' 'aptarchive/dists/unstable/main/Contents-amd64' -# no automatic uncompress based on the name please, +rm ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64 +testempty aptget files --format '$(FILENAME)' 'Created-By: Contents' + +# if we asked for keeping it compressed, keep it +echo 'APT::Acquire::Targets::deb::Contents::KeepCompressed "true";' >> rootdir/etc/apt/apt.conf.d/content-target.conf +testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease +Get:2 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] +Reading package lists..." aptget update + +testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget files --format '$(FILENAME)' 'Created-By: Contents' +testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' 'aptarchive/dists/unstable/main/Contents-amd64.gz' + +rm ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz +testempty aptget files --format '$(FILENAME)' 'Created-By: Contents' + +# and no automatic uncompress based on the name please, # only if we downloaded a compressed file, but target was uncompressed cat > rootdir/etc/apt/apt.conf.d/content-target.conf </dev/null testsuccessequal 'Reading package lists... -- cgit v1.2.3-70-g09d2 From f14cde2ca702f72415486bf5c310208a7c500e9c Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 6 Jul 2015 21:15:45 +0200 Subject: support gpg 2.1.x in apt-key The output of gpg slightly changes in 2.1 which breaks the testcase, but the real problem is that this branch introduces a new default keyring format (which is called keybox) and mixing it with simple keyrings (the previous default format) has various problems like failing in the keybox to keyring import (#790665) or [older] gpgv versions not being able to deal with keyboxes (and newer versions as well currently: https://bugs.gnupg.org/gnupg/issue2025). We fix this by being a bit more careful in who creates keyrings (aka: we do it or we take a simple keyring as base) to ensure we always have a keyring instead of a keybox. This way we can ensure that any version combination of gpv/gpgv2 and gnupg/gnupg2 without doing explicit version checks and use the same code for all of them. Closes: 781042 --- cmdline/apt-key.in | 85 ++++++++++++++++++++++--------- test/integration/test-apt-key | 115 +++++++++++++++++++++++------------------- 2 files changed, 124 insertions(+), 76 deletions(-) (limited to 'test') diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index e37745357..b15f71f6d 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -145,7 +145,7 @@ update() { # attacker might as well replace the master-archive-keyring file # in the package and add his own keys. so this check wouldn't # add any security. we *need* this check on net-update though - $GPG_CMD --quiet --batch --keyring $ARCHIVE_KEYRING --export | $GPG --import + import_keyring_into_keyring "$ARCHIVE_KEYRING" '' && cat "${GPGHOMEDIR}/gpgoutput.log" if [ -r "$REMOVED_KEYS" ]; then # remove no-longer supported/used keys @@ -231,22 +231,49 @@ run_cmd_on_keyring() { $GPG_CMD --keyring "$KEYRINGFILE" --batch "$@" 2>/dev/null || true } -import_keys_from_keyring() { - local IMPORT="$1" - local KEYRINGFILE="$2" - if ! $GPG_CMD --keyring "$KEYRINGFILE" --batch --import "$IMPORT" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false +import_keyring_into_keyring() { + local FROM="${1:-${GPGHOMEDIR}/pubring.gpg}" + local TO="${2:-${GPGHOMEDIR}/pubring.gpg}" + shift 2 + rm -f "${GPGHOMEDIR}/gpgoutput.log" + # the idea is simple: We take keys from one keyring and copy it to another + # we do this with so many checks inbetween to ensure that WE control the + # creation, so we know that the (potentially) created $TO keyring is a + # simple keyring rather than a keybox as gpg2 would create it which in turn + # can't be read by gpgv. + # BEWARE: This is designed more in the way to work with the current + # callers, than to have a well defined it would be easy to add new callers to. + if [ ! -s "$TO" ]; then + if [ -s "$FROM" ]; then + if [ -z "$2" ]; then + if ! $GPG_CMD --keyring "$FROM" --export ${1:+"$1"} > "$TO" 2> "${GPGHOMEDIR}/gpgoutput.log"; then + cat >&2 "${GPGHOMEDIR}/gpgoutput.log" + false + else + chmod 0644 -- "$TO" + fi + else + create_new_keyring "$TO" + fi + else + create_new_keyring "$TO" + fi + elif [ -s "$FROM" ]; then + local EXPORTLIMIT="$1" + if [ -n "$1$2" ]; then shift; fi + if ! $GPG_CMD --keyring "$FROM" --export ${EXPORTLIMIT:+"$EXPORTLIMIT"} | $GPG_CMD --keyring "$TO" --batch --import "$@" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then + cat >&2 "${GPGHOMEDIR}/gpgoutput.log" + false + fi fi } +import_keys_from_keyring() { + import_keyring_into_keyring "$1" "$2" +} + merge_keys_into_keyrings() { - local KEYRINGFILE="$1" - local IMPORT="$2" - if ! $GPG_CMD --keyring "$KEYRINGFILE" --batch --import --import-options 'merge-only' "$IMPORT" > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi + import_keyring_into_keyring "$2" "$1" '' --import-options 'merge-only' } merge_back_changes() { @@ -267,11 +294,7 @@ merge_back_changes() { foreach_keyring_do 'remove_key_from_keyring' "$key" elif grep -q "^${key}$" "${GPGHOMEDIR}/pubring.keylst"; then # key is part of new keyring, so we need to import it - create_new_keyring "$TRUSTEDFILE" - if ! $GPG --batch --yes --export "$key" | $GPG_CMD --keyring "$TRUSTEDFILE" --batch --yes --import > "${GPGHOMEDIR}/gpgoutput.log" 2>&1; then - cat >&2 "${GPGHOMEDIR}/gpgoutput.log" - false - fi + import_keyring_into_keyring '' "$TRUSTEDFILE" "$key" else echo >&2 "Errror: Key ${key} (dis)appeared out of nowhere" fi @@ -280,12 +303,12 @@ merge_back_changes() { setup_merged_keyring() { if [ -n "$FORCED_KEYID" ]; then - foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/allrings.gpg" + foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" FORCED_KEYRING="${GPGHOMEDIR}/forcedkeyid.gpg" TRUSTEDFILE="${FORCED_KEYRING}" GPG="$GPG --keyring $TRUSTEDFILE" # ignore error as this "just" means we haven't found the forced keyid and the keyring will be empty - $GPG_CMD --batch --yes --keyring "${GPGHOMEDIR}/allrings.gpg" --export "$FORCED_KEYID" | $GPG --batch --yes --import || true + import_keyring_into_keyring '' "$TRUSTEDFILE" "$FORCED_KEYID" || true elif [ -z "$FORCED_KEYRING" ]; then foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" if [ -r "${GPGHOMEDIR}/pubring.gpg" ]; then @@ -295,8 +318,8 @@ setup_merged_keyring() { fi GPG="$GPG --keyring ${GPGHOMEDIR}/pubring.gpg" else - GPG="$GPG --keyring $TRUSTEDFILE" create_new_keyring "$TRUSTEDFILE" + GPG="$GPG --keyring $TRUSTEDFILE" fi } @@ -345,7 +368,7 @@ while [ -n "$1" ]; do ;; --readonly) merge_back_changes() { true; } - create_new_keyring() { true; } + create_new_keyring() { if [ ! -r $FORCED_KEYRING ]; then TRUSTEDFILE='/dev/null'; FORCED_KEYRING="$TRUSTEDFILE"; fi; } ;; --fakeroot) requires_root() { true; } @@ -437,6 +460,12 @@ if [ "$command" != "help" ]; then rm -f "$SECRETKEYRING" cp -a "$FORCED_SECRET_KEYRING" "$SECRETKEYRING" fi + + # older gpg versions need a secring file, but newer versions take it as + # a hint to start a migration from earlier versions. The file is empty + # anyhow, so nothing actually happens, but its three lines of output + # nobody expects to see in apt-key context, so trigger it in silence + echo -n | $GPG --batch --import >/dev/null 2>&1 || true fi case "$command" in @@ -482,11 +511,17 @@ case "$command" in ;; verify) setup_merged_keyring - if which gpgv >/dev/null 2>&1; then + GPGV='' + eval $(apt-config shell GPGV Apt::Key::gpgvcommand) + if [ -n "$GPGV" ] && ! which "$GPGV" >/dev/null 2>&1; then GPGV=''; + elif which gpgv >/dev/null 2>&1; then GPGV='gpgv'; + elif which gpgv2 >/dev/null 2>&1; then GPGV='gpgv2'; + fi + if [ -n "$GPGV" ]; then if [ -n "$FORCED_KEYRING" ]; then - gpgv --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@" + $GPGV --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@" else - gpgv --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" + $GPGV --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" fi else $GPG --verify "$@" diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key index e1be08c65..4dbf3d66d 100755 --- a/test/integration/test-apt-key +++ b/test/integration/test-apt-key @@ -13,11 +13,33 @@ cleanplate() { mkdir rootdir/etc/apt/trusted.gpg.d/ } +createlistofkeys() { + while [ -n "$1" ]; do + # gpg 2.1 has a slightly different output format + if grep -q ' rsa2048/' aptkey.list; then + case "$1" in + *Joe*|*Sixpack*) echo 'pub rsa2048/DBAC8DAE 2010-08-18';; + *Rex*|*Expired*) echo 'pub rsa2048/27CE74F9 2013-07-12 [expired: 2013-07-13]';; + *Marvin*|*Paranoid*) echo 'pub rsa2048/528144E2 2011-01-16';; + *) echo 'UNKNOWN KEY';; + esac + else + case "$1" in + *Joe*|*Sixpack*) echo 'pub 2048R/DBAC8DAE 2010-08-18';; + *Rex*|*Expired*) echo 'pub 2048R/27CE74F9 2013-07-12 [expired: 2013-07-13]';; + *Marvin*|*Paranoid*) echo 'pub 2048R/528144E2 2011-01-16';; + *) echo 'UNKNOWN KEY';; + esac + fi + shift + done +} + testaptkeys() { if ! aptkey list | grep '^pub' > aptkey.list; then echo -n > aptkey.list fi - testfileequal './aptkey.list' "$1" + testfileequal './aptkey.list' "$(createlistofkeys "$@")" } echo 'APT::Key::ArchiveKeyring "./keys/joesixpack.pub"; @@ -32,16 +54,15 @@ testrun() { msgtest 'Check that paths in finger output are not' 'double-slashed' aptkey finger 2>&1 | grep -q '//' && msgfail || msgpass - - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18' + testaptkeys 'Joe Sixpack' testsuccessequal 'gpg: key DBAC8DAE: "Joe Sixpack (APT Testcases Dummy) " not changed gpg: Total number processed: 1 gpg: unchanged: 1' aptkey --fakeroot update - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18' - + testaptkeys 'Joe Sixpack' testfailure test -e rootdir/etc/apt/trusted.gpg + testsuccess aptkey --fakeroot add ./keys/rexexpired.pub msgtest 'Check if trusted.gpg is created with permissions set to' '0644' if [ "$(stat -c '%a' rootdir/etc/apt/trusted.gpg )" = '644' ]; then @@ -50,8 +71,7 @@ gpg: unchanged: 1' aptkey --fakeroot update msgfail fi - testaptkeys 'pub 2048R/27CE74F9 2013-07-12 [expired: 2013-07-13] -pub 2048R/DBAC8DAE 2010-08-18' + testaptkeys 'Rex Expired' 'Joe Sixpack' msgtest 'Check that Sixpack key can be' 'exported' aptkey export 'Sixpack' > aptkey.export @@ -63,12 +83,12 @@ pub 2048R/DBAC8DAE 2010-08-18' msgtest 'Execute update again to trigger removal of' 'Rex Expired key' testsuccess --nomsg aptkey --fakeroot update - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18' + testaptkeys 'Joe Sixpack' msgtest "Try to remove a key which exists, but isn't in the" 'forced keyring' testsuccess --nomsg aptkey --fakeroot --keyring rootdir/etc/apt/trusted.gpg del DBAC8DAE - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18' + testaptkeys 'Joe Sixpack' testsuccess aptkey --fakeroot del DBAC8DAE testempty aptkey list @@ -114,22 +134,21 @@ pub 2048R/DBAC8DAE 2010-08-18' cleanplate testsuccess aptkey --fakeroot add ./keys/joesixpack.pub testsuccess aptkey --fakeroot add ./keys/marvinparanoid.pub - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/528144E2 2011-01-16' + testaptkeys 'Joe Sixpack' 'Marvin Paranoid' cp -a rootdir/etc/apt/trusted.gpg keys/testcase-multikey.pub # store for reuse msgtest 'Test key removal with' 'multi key in real file' cleanplate cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg testsuccess --nomsg aptkey --fakeroot del DBAC8DAE - testaptkeys 'pub 2048R/528144E2 2011-01-16' + testaptkeys 'Marvin Paranoid' testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ msgtest 'Test key removal with' 'multi key in softlink' cleanplate ln -s $(readlink -f ./keys/testcase-multikey.pub) rootdir/etc/apt/trusted.gpg.d/multikey.gpg testsuccess --nomsg aptkey --fakeroot del DBAC8DAE - testaptkeys 'pub 2048R/528144E2 2011-01-16' + testaptkeys 'Marvin Paranoid' testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ testfailure test -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg testsuccess test -L rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ @@ -139,7 +158,7 @@ pub 2048R/528144E2 2011-01-16' cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg testsuccess --nomsg aptkey --fakeroot del DBAC8DAE - testaptkeys 'pub 2048R/528144E2 2011-01-16' + testaptkeys 'Marvin Paranoid' testfailure test -e rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg testsuccess cmp keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg~ testsuccess cmp keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg~ @@ -147,25 +166,18 @@ pub 2048R/528144E2 2011-01-16' cleanplate cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg cp -a keys/testcase-multikey.pub rootdir/etc/apt/trusted.gpg.d/multikey.gpg - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/528144E2 2011-01-16' + testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid' msgtest 'Test merge-back of' 'added keys' testsuccess --nomsg aptkey adv --batch --yes --import keys/rexexpired.pub - testaptkeys 'pub 2048R/27CE74F9 2013-07-12 [expired: 2013-07-13] -pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/528144E2 2011-01-16' + testaptkeys 'Rex Expired' 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid' msgtest 'Test merge-back of' 'removed keys' testsuccess --nomsg aptkey adv --batch --yes --delete-keys 27CE74F9 - testaptkeys 'pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/DBAC8DAE 2010-08-18 -pub 2048R/528144E2 2011-01-16' + testaptkeys 'Joe Sixpack' 'Joe Sixpack' 'Marvin Paranoid' msgtest 'Test merge-back of' 'removed duplicate keys' testsuccess --nomsg aptkey adv --batch --yes --delete-keys DBAC8DAE - testaptkeys 'pub 2048R/528144E2 2011-01-16' + testaptkeys 'Marvin Paranoid' cleanplate cp -a keys/joesixpack.pub rootdir/etc/apt/trusted.gpg.d/joesixpack.gpg @@ -175,43 +187,44 @@ pub 2048R/528144E2 2011-01-16' testsuccess --nomsg aptkey --quiet --keyring keys/marvinparanoid.pub --secret-keyring keys/marvinparanoid.sec --readonly \ adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output signature.gpg signature - msgtest 'Test verify a file' 'with all keys' - testsuccess --nomsg aptkey --quiet --readonly verify signature.gpg signature - msgtest 'Test verify a file' 'with good keyring' - testsuccess --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature.gpg signature + for GPGV in 'gpgv' 'gpgv2' '/does/not/exist'; do + echo "APT::Key::GPGVCommand \"$GPGV\";" > rootdir/etc/apt/apt.conf.d/00gpgvcmd + + msgtest 'Test verify a file' 'with all keys' + testsuccess --nomsg aptkey --quiet --readonly verify signature.gpg signature - msgtest 'Test fail verify a file' 'with bad keyring' - testfailure --nomsg aptkey --quiet --readonly --keyring keys/joesixpack.pub verify signature.gpg signature + msgtest 'Test verify a file' 'with good keyring' + testsuccess --nomsg aptkey --quiet --readonly --keyring keys/testcase-multikey.pub verify signature.gpg signature - msgtest 'Test fail verify a file' 'with non-existing keyring' - testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature - testfailure test -e keys/does-not-exist.pub + msgtest 'Test fail verify a file' 'with bad keyring' + testfailure --nomsg aptkey --quiet --readonly --keyring keys/joesixpack.pub verify signature.gpg signature - msgtest 'Test verify a file' 'with good keyid' - testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify signature.gpg signature + msgtest 'Test fail verify a file' 'with non-existing keyring' + testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature + testfailure test -e keys/does-not-exist.pub - msgtest 'Test fail verify a file' 'with bad keyid' - testfailure --nomsg aptkey --quiet --readonly --keyid 'Sixpack' verify signature.gpg signature + msgtest 'Test verify a file' 'with good keyid' + testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify signature.gpg signature - msgtest 'Test fail verify a file' 'with non-existing keyid' - testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify signature.gpg signature + msgtest 'Test fail verify a file' 'with bad keyid' + testfailure --nomsg aptkey --quiet --readonly --keyid 'Sixpack' verify signature.gpg signature - msgtest 'Test verify fails on' 'bad file' - echo 'lalalalala' > signature - testfailure --nomsg aptkey --quiet --readonly verify signature.gpg signature + msgtest 'Test fail verify a file' 'with non-existing keyid' + testfailure --nomsg aptkey --quiet --readonly --keyid 'Kalnischkies' verify signature.gpg signature + + msgtest 'Test verify fails on' 'bad file' + echo 'lalalalala' > signature2 + testfailure --nomsg aptkey --quiet --readonly verify signature.gpg signature2 + done } setupgpgcommand() { echo "APT::Key::GPGCommand \"$1\";" > rootdir/etc/apt/apt.conf.d/00gpgcmd - msgtest 'Test that apt-key uses for the following tests command' "$1" - aptkey adv --version >aptkey.version 2>&1 - if grep -q "^Executing: $1 --" aptkey.version; then - msgpass - else - cat aptkey.version - msgfail - fi + msgmsg 'Force tests to be run with' "$1" + testsuccess aptkey --readonly adv --version + cp rootdir/tmp/testsuccess.output aptkey.version + testsuccess grep "^Executing: $1 --" aptkey.version } # run with default (whatever this is) -- cgit v1.2.3-70-g09d2 From 25f2731928f0b571f7521d7d7a7e301499d0f6ee Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 7 Jul 2015 11:46:39 +0200 Subject: merge keyrings with cat instead of gpg in apt-key If all keyrings are simple keyrings we can merge the keyrings with cat rather than doing a detour over gpg --export | --import (see #790665), which means 'apt-key verify' can do without gpg and just use gpgv as before the merging change. We declare this gpgv usage explicit now in the dependencies. This isn't a new dependency as gnupg as well as debian-archive-keyring depend on and we used it before unconditionally, just that we didn't declare it. The handling of the merged keyring needs to be slightly different as our merged keyring can end up containing the same key multiple times, but at least currently gpg does remove only the first occurrence with --delete-keys, so we move the handling to a if one is gone, all are gone rather than an (implicit) quid pro quo or even no effect. Thanks: Daniel Kahn Gillmor for the suggestion --- cmdline/apt-key.in | 128 ++++++++++++++++++++++++++++-------------- debian/control | 2 +- test/integration/test-apt-key | 2 +- 3 files changed, 88 insertions(+), 44 deletions(-) (limited to 'test') diff --git a/cmdline/apt-key.in b/cmdline/apt-key.in index b15f71f6d..881f8a990 100644 --- a/cmdline/apt-key.in +++ b/cmdline/apt-key.in @@ -34,7 +34,8 @@ get_fingerprints_of_keyring() { elif [ "${fprline%%:*}" != 'fpr' ]; then continue; fi echo "$fprline" | cut -d':' -f 10 done - done + # order in the keyring shouldn't be important + done | sort } add_keys_with_verify_against_master_keyring() { @@ -167,8 +168,10 @@ remove_key_from_keyring() { local GPG="$GPG_CMD --keyring $KEYRINGFILE" for KEY in "$@"; do - # check if the key is in this keyring: the key id is in the 5 column at the end - if ! get_fingerprints_of_keyring "$KEYRINGFILE" | grep -iq "^[0-9A-F]*${KEY}$"; then + local FINGERPRINTS="${GPGHOMEDIR}/keyringfile.keylst" + get_fingerprints_of_keyring "$KEYRINGFILE" > "$FINGERPRINTS" + # check if the key is in this keyring + if ! grep -iq "^[0-9A-F]*${KEY}$" "$FINGERPRINTS"; then continue fi if [ ! -w "$KEYRINGFILE" ]; then @@ -176,7 +179,7 @@ remove_key_from_keyring() { continue fi # check if it is the only key in the keyring and if so remove the keyring altogether - if [ '1' = "$(get_fingerprints_of_keyring "$KEYRINGFILE" | wc -l)" ]; then + if [ '1' = "$(uniq "$FINGERPRINTS" | wc -l)" ]; then mv -f "$KEYRINGFILE" "${KEYRINGFILE}~" # behave like gpg return fi @@ -188,7 +191,7 @@ remove_key_from_keyring() { cp -a "$REALTARGET" "$KEYRINGFILE" fi # delete the key from the keyring - $GPG --batch --delete-key --yes "$KEY" + $GPG --batch --delete-keys --yes "$KEY" if [ -n "$REALTARGET" ]; then # the real backup is the old link, not the copy we made mv -f "${KEYRINGFILE}.dpkg-tmp" "${KEYRINGFILE}~" @@ -268,6 +271,33 @@ import_keyring_into_keyring() { fi } +merge_all_trusted_keyrings_into_pubring() { + # does the same as: + # foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" + # but without using gpg, just cat and find + local PUBRING="${GPGHOMEDIR}/pubring.gpg" + # if a --keyring was given, just use this one + if [ -n "$FORCED_KEYRING" ]; then + if [ -s "$FORCED_KEYRING" ]; then + cp --dereference "$FORCED_KEYRING" "$PUBRING" + fi + else + # otherwise all known keyrings are merged + local TRUSTEDPARTS="/etc/apt/trusted.gpg.d" + eval $(apt-config shell TRUSTEDPARTS Dir::Etc::TrustedParts/d) + if [ -d "$TRUSTEDPARTS" ]; then + # ignore errors mostly for non-existing $TRUSTEDFILE + cat /dev/null "$TRUSTEDFILE" $(find -L "$TRUSTEDPARTS" -type f -name '*.gpg') > "$PUBRING" 2>/dev/null || true + elif [ -s "$TRUSTEDFILE" ]; then + cp --dereference "$TRUSTEDFILE" "$PUBRING" + fi + fi + + if [ ! -s "$PUBRING" ]; then + touch "$PUBRING" + fi +} + import_keys_from_keyring() { import_keyring_into_keyring "$1" "$2" } @@ -288,29 +318,29 @@ merge_back_changes() { # look for keys which were added or removed get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.orig.gpg" > "${GPGHOMEDIR}/pubring.orig.keylst" get_fingerprints_of_keyring "${GPGHOMEDIR}/pubring.gpg" > "${GPGHOMEDIR}/pubring.keylst" - sort "${GPGHOMEDIR}/pubring.keylst" "${GPGHOMEDIR}/pubring.orig.keylst" | uniq --unique | while read key; do - if grep -q "^${key}$" "${GPGHOMEDIR}/pubring.orig.keylst"; then - # key isn't part of new keyring, so remove - foreach_keyring_do 'remove_key_from_keyring' "$key" - elif grep -q "^${key}$" "${GPGHOMEDIR}/pubring.keylst"; then - # key is part of new keyring, so we need to import it - import_keyring_into_keyring '' "$TRUSTEDFILE" "$key" - else - echo >&2 "Errror: Key ${key} (dis)appeared out of nowhere" - fi + comm -3 "${GPGHOMEDIR}/pubring.keylst" "${GPGHOMEDIR}/pubring.orig.keylst" > "${GPGHOMEDIR}/pubring.diff" + # key isn't part of new keyring, so remove + cut -f 2 "${GPGHOMEDIR}/pubring.diff" | while read key; do + if [ -z "$key" ]; then continue; fi + foreach_keyring_do 'remove_key_from_keyring' "$key" + done + # key is only part of new keyring, so we need to import it + cut -f 1 "${GPGHOMEDIR}/pubring.diff" | while read key; do + if [ -z "$key" ]; then continue; fi + import_keyring_into_keyring '' "$TRUSTEDFILE" "$key" done } setup_merged_keyring() { if [ -n "$FORCED_KEYID" ]; then - foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" + merge_all_trusted_keyrings_into_pubring FORCED_KEYRING="${GPGHOMEDIR}/forcedkeyid.gpg" TRUSTEDFILE="${FORCED_KEYRING}" GPG="$GPG --keyring $TRUSTEDFILE" # ignore error as this "just" means we haven't found the forced keyid and the keyring will be empty import_keyring_into_keyring '' "$TRUSTEDFILE" "$FORCED_KEYID" || true elif [ -z "$FORCED_KEYRING" ]; then - foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" + merge_all_trusted_keyrings_into_pubring if [ -r "${GPGHOMEDIR}/pubring.gpg" ]; then cp -a "${GPGHOMEDIR}/pubring.gpg" "${GPGHOMEDIR}/pubring.orig.gpg" else @@ -407,7 +437,23 @@ if [ -z "$command" ]; then fi shift -if [ "$command" != "help" ]; then +create_gpg_home() { + # gpg needs (in different versions more or less) files to function correctly, + # so we give it its own homedir and generate some valid content for it later on + if [ -n "$TMPDIR" ]; then + # tmpdir is a directory and current user has rwx access to it + # same tests as in apt-pkg/contrib/fileutl.cc GetTempDir() + if [ ! -d "$TMPDIR" ] || [ ! -r "$TMPDIR" ] || [ ! -w "$TMPDIR" ] || [ ! -x "$TMPDIR" ]; then + unset TMPDIR + fi + fi + GPGHOMEDIR="$(mktemp -d)" + CURRENTTRAP="${CURRENTTRAP} rm -rf '${GPGHOMEDIR}';" + trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM + chmod 700 "$GPGHOMEDIR" +} + +prepare_gpg_home() { eval $(apt-config shell GPG_EXE Apt::Key::gpgcommand) if [ -n "$GPG_EXE" ] && which "$GPG_EXE" >/dev/null 2>&1; then @@ -418,7 +464,7 @@ if [ "$command" != "help" ]; then GPG_EXE="gpg2" else echo >&2 "Error: gnupg or gnupg2 do not seem to be installed," - echo >&2 "Error: but apt-key requires gnupg or gnupg2 for operation." + echo >&2 "Error: but apt-key requires gnupg or gnupg2 for this operation." echo >&2 exit 255 fi @@ -428,19 +474,8 @@ if [ "$command" != "help" ]; then fi GPG_CMD="$GPG_EXE --ignore-time-conflict --no-options --no-default-keyring" - # gpg needs (in different versions more or less) files to function correctly, - # so we give it its own homedir and generate some valid content for it - if [ -n "$TMPDIR" ]; then - # tmpdir is a directory and current user has rwx access to it - # same tests as in apt-pkg/contrib/fileutl.cc GetTempDir() - if [ ! -d "$TMPDIR" ] || [ ! -r "$TMPDIR" ] || [ ! -w "$TMPDIR" ] || [ ! -x "$TMPDIR" ]; then - unset TMPDIR - fi - fi - GPGHOMEDIR="$(mktemp -d)" - CURRENTTRAP="${CURRENTTRAP} rm -rf '${GPGHOMEDIR}';" - trap "${CURRENTTRAP}" 0 HUP INT QUIT ILL ABRT FPE SEGV PIPE TERM - chmod 700 "$GPGHOMEDIR" + create_gpg_home + # We don't use a secret keyring, of course, but gpg panics and # implodes if there isn't one available - and writeable for imports SECRETKEYRING="${GPGHOMEDIR}/secring.gpg" @@ -466,6 +501,10 @@ if [ "$command" != "help" ]; then # anyhow, so nothing actually happens, but its three lines of output # nobody expects to see in apt-key context, so trigger it in silence echo -n | $GPG --batch --import >/dev/null 2>&1 || true +} + +if [ "$command" != 'help' ] && [ "$command" != 'verify' ]; then + prepare_gpg_home fi case "$command" in @@ -500,7 +539,7 @@ case "$command" in foreach_keyring_do 'run_cmd_on_keyring' --fingerprint "$@" ;; export|exportall) - foreach_keyring_do 'import_keys_from_keyring' "${GPGHOMEDIR}/pubring.gpg" + merge_all_trusted_keyrings_into_pubring $GPG_CMD --keyring "${GPGHOMEDIR}/pubring.gpg" --armor --export "$@" ;; adv*) @@ -510,21 +549,26 @@ case "$command" in merge_back_changes ;; verify) - setup_merged_keyring GPGV='' eval $(apt-config shell GPGV Apt::Key::gpgvcommand) - if [ -n "$GPGV" ] && ! which "$GPGV" >/dev/null 2>&1; then GPGV=''; + if [ -n "$GPGV" ] && which "$GPGV" >/dev/null 2>&1; then true; elif which gpgv >/dev/null 2>&1; then GPGV='gpgv'; elif which gpgv2 >/dev/null 2>&1; then GPGV='gpgv2'; + else + echo >&2 'ERROR: gpgv or gpgv2 required for verification' + exit 29 fi - if [ -n "$GPGV" ]; then - if [ -n "$FORCED_KEYRING" ]; then - $GPGV --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@" - else - $GPGV --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" - fi + # for a forced keyid we need gpg --export, so full wrapping required + if [ -n "$FORCED_KEYID" ]; then + prepare_gpg_home + else + create_gpg_home + fi + setup_merged_keyring + if [ -n "$FORCED_KEYRING" ]; then + $GPGV --homedir "${GPGHOMEDIR}" --keyring "${FORCED_KEYRING}" --ignore-time-conflict "$@" else - $GPG --verify "$@" + $GPGV --homedir "${GPGHOMEDIR}" --keyring "${GPGHOMEDIR}/pubring.gpg" --ignore-time-conflict "$@" fi ;; help) diff --git a/debian/control b/debian/control index e71cb5103..7e2db7373 100644 --- a/debian/control +++ b/debian/control @@ -18,7 +18,7 @@ XS-Testsuite: autopkgtest Package: apt Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, ${apt:keyring}, gnupg | gnupg2, adduser +Depends: ${shlibs:Depends}, ${misc:Depends}, ${apt:keyring}, gpgv | gpgv2, gnupg | gnupg2, adduser Replaces: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~), sun-java6-jdk (>> 0), sun-java5-jdk (>> 0), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~) Breaks: manpages-pl (<< 20060617-3~), manpages-it (<< 2.80-4~), sun-java6-jdk (>> 0), sun-java5-jdk (>> 0), openjdk-6-jdk (<< 6b24-1.11-0ubuntu1~) Conflicts: python-apt (<< 0.7.93.2~) diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key index 4dbf3d66d..1226e7dc4 100755 --- a/test/integration/test-apt-key +++ b/test/integration/test-apt-key @@ -188,7 +188,7 @@ gpg: unchanged: 1' aptkey --fakeroot update adv --batch --yes --default-key 'Marvin' --armor --detach-sign --sign --output signature.gpg signature - for GPGV in 'gpgv' 'gpgv2' '/does/not/exist'; do + for GPGV in '' 'gpgv' 'gpgv2'; do echo "APT::Key::GPGVCommand \"$GPGV\";" > rootdir/etc/apt/apt.conf.d/00gpgvcmd msgtest 'Test verify a file' 'with all keys' -- cgit v1.2.3-70-g09d2 From 4e03c47de15164f2656d9655edab6fb3570cb2f2 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 7 Jul 2015 22:11:20 +0200 Subject: implement Signed-By without using gpg for verification The previous commit returns to the possibility of using just gpgv for verification proposes. There is one problem through: We can't enforce a specific keyid without using gpg, but our acquire method can as it parses gpgv output anyway, so it can deal with good signatures from not expected signatures and treats them as unknown keys instead. Git-Dch: Ignore --- methods/gpgv.cc | 69 ++++++++++++++++++++++---- test/integration/test-apt-key | 1 + test/integration/test-releasefile-verification | 4 +- 3 files changed, 63 insertions(+), 11 deletions(-) (limited to 'test') diff --git a/methods/gpgv.cc b/methods/gpgv.cc index 014430041..d88a06789 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -15,6 +15,8 @@ #include #include #include + +#include #include #include #include @@ -74,6 +76,7 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::clog << "inside VerifyGetSigners" << std::endl; int fd[2]; + bool const keyIsID = (key.empty() == false && key[0] != '/'); if (pipe(fd) < 0) return "Couldn't create pipe"; @@ -82,12 +85,13 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, if (pid < 0) return string("Couldn't spawn new process") + strerror(errno); else if (pid == 0) - ExecGPGV(outfile, file, 3, fd, key); + ExecGPGV(outfile, file, 3, fd, (keyIsID ? "" : key)); close(fd[1]); FILE *pipein = fdopen(fd[0], "r"); // Loop over the output of apt-key (which really is gnupg), and check the signatures. + std::vector ValidSigners; size_t buffersize = 0; char *buffer = NULL; while (1) @@ -107,32 +111,31 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::clog << "Got BADSIG! " << std::endl; BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - - if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0) + else if (strncmp(buffer, GNUPGNOPUBKEY, sizeof(GNUPGNOPUBKEY)-1) == 0) { if (Debug == true) std::clog << "Got NO_PUBKEY " << std::endl; NoPubKeySigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0) + else if (strncmp(buffer, GNUPGNODATA, sizeof(GNUPGBADSIG)-1) == 0) { if (Debug == true) std::clog << "Got NODATA! " << std::endl; BadSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0) + else if (strncmp(buffer, GNUPGKEYEXPIRED, sizeof(GNUPGKEYEXPIRED)-1) == 0) { if (Debug == true) std::clog << "Got KEYEXPIRED! " << std::endl; WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0) + else if (strncmp(buffer, GNUPGREVKEYSIG, sizeof(GNUPGREVKEYSIG)-1) == 0) { if (Debug == true) std::clog << "Got REVKEYSIG! " << std::endl; WorthlessSigners.push_back(string(buffer+sizeof(GNUPGPREFIX))); } - if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0) + else if (strncmp(buffer, GNUPGGOODSIG, sizeof(GNUPGGOODSIG)-1) == 0) { char *sig = buffer + sizeof(GNUPGPREFIX); char *p = sig + sizeof("GOODSIG"); @@ -143,10 +146,48 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, std::clog << "Got GOODSIG, key ID:" << sig << std::endl; GoodSigners.push_back(string(sig)); } + else if (strncmp(buffer, GNUPGVALIDSIG, sizeof(GNUPGVALIDSIG)-1) == 0) + { + char *sig = buffer + sizeof(GNUPGVALIDSIG); + char *p = sig; + while (*p && isxdigit(*p)) + p++; + *p = 0; + if (Debug == true) + std::clog << "Got VALIDSIG, key ID: " << sig << std::endl; + ValidSigners.push_back(string(sig)); + } } fclose(pipein); free(buffer); + // apt-key has a --keyid parameter, but this requires gpg, so we call it without it + // and instead check after the fact which keyids where used for verification + if (keyIsID == true) + { + if (Debug == true) + std::clog << "GoodSigs needs to be limited to keyid " << key << std::endl; + std::vector::iterator const foundItr = std::find(ValidSigners.begin(), ValidSigners.end(), key); + bool const found = (foundItr != ValidSigners.end()); + std::copy(GoodSigners.begin(), GoodSigners.end(), std::back_insert_iterator >(NoPubKeySigners)); + if (found) + { + // we look for GOODSIG here as well as an expired sig is a valid sig as well (but not a good one) + std::string const goodlongkeyid = "GOODSIG " + key.substr(24, 16); + bool const foundGood = std::find(GoodSigners.begin(), GoodSigners.end(), goodlongkeyid) != GoodSigners.end(); + if (Debug == true) + std::clog << "Key " << key << " is valid sig, is " << goodlongkeyid << " also a good one? " << (foundGood ? "yes" : "no") << std::endl; + GoodSigners.clear(); + if (foundGood) + { + GoodSigners.push_back(goodlongkeyid); + NoPubKeySigners.erase(std::remove(NoPubKeySigners.begin(), NoPubKeySigners.end(), goodlongkeyid), NoPubKeySigners.end()); + } + } + else + GoodSigners.clear(); + } + int status; waitpid(pid, &status, 0); if (Debug == true) @@ -156,8 +197,18 @@ string GPGVMethod::VerifyGetSigners(const char *file, const char *outfile, if (WEXITSTATUS(status) == 0) { - if (GoodSigners.empty()) - return _("Internal error: Good signature, but could not determine key fingerprint?!"); + if (keyIsID) + { + // gpgv will report success, but we want to enforce a certain keyring + // so if we haven't found the key the valid we found is in fact invalid + if (GoodSigners.empty()) + return _("At least one invalid signature was encountered."); + } + else + { + if (GoodSigners.empty()) + return _("Internal error: Good signature, but could not determine key fingerprint?!"); + } return ""; } else if (WEXITSTATUS(status) == 1) diff --git a/test/integration/test-apt-key b/test/integration/test-apt-key index 1226e7dc4..a1a0d883d 100755 --- a/test/integration/test-apt-key +++ b/test/integration/test-apt-key @@ -204,6 +204,7 @@ gpg: unchanged: 1' aptkey --fakeroot update testfailure --nomsg aptkey --quiet --readonly --keyring keys/does-not-exist.pub verify signature.gpg signature testfailure test -e keys/does-not-exist.pub + # note: this isn't how apts gpgv method implements keyid for verify msgtest 'Test verify a file' 'with good keyid' testsuccess --nomsg aptkey --quiet --readonly --keyid 'Paranoid' verify signature.gpg signature diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 1c3953c8b..759242514 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -92,7 +92,7 @@ touch aptarchive/apt.deb PKGFILE="${TESTDIR}/$(echo "$(basename $0)" | sed 's#^test-#Packages-#')" updatewithwarnings() { - testwarning aptget update + testwarning aptget update -o Debug::pkgAcquire::Worker=1 -o Debug::Acquire::gpgv=1 testsuccess grep -E "$1" rootdir/tmp/testwarning.output } @@ -225,7 +225,7 @@ runtest() { signreleasefiles 'Joe Sixpack' find aptarchive/ -name "$DELETEFILE" -delete msgmsg 'Cold archive signed by bad keyid' 'Joe Sixpack' - updatewithwarnings '^W: .* NO_PUBKEY' + updatewithwarnings '^W: .* be verified because the public key is not available: .*' sed -i "s#^\(deb\(-src\)\?\) \[signed-by=$MARVIN\] #\1 #" rootdir/etc/apt/sources.list.d/* } -- cgit v1.2.3-70-g09d2 From 3b3028467ceccca0b73a8f53051c0fa4de313111 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 9 Jul 2015 00:35:40 +0200 Subject: add c++11 override marker to overridden methods C++11 adds the 'override' specifier to mark that a method is overriding a base class method and error out if not. We hide it in the APT_OVERRIDE macro to ensure that we keep compiling in pre-c++11 standards. Reported-By: clang-modernize -add-override -override-macros Git-Dch: Ignore --- apt-inst/deb/debfile.h | 6 +- apt-inst/extract.h | 6 +- apt-pkg/acquire-item.cc | 4 +- apt-pkg/acquire-item.h | 140 +++++++++++++++--------------- apt-pkg/algorithms.h | 8 +- apt-pkg/cachefilter.h | 46 +++++----- apt-pkg/contrib/md5.h | 2 +- apt-pkg/contrib/progress.h | 5 +- apt-pkg/contrib/sha1.h | 2 +- apt-pkg/contrib/sha2.h | 4 +- apt-pkg/deb/debindexfile.cc | 10 +-- apt-pkg/deb/debindexfile.h | 56 ++++++------ apt-pkg/deb/deblistparser.h | 34 ++++---- apt-pkg/deb/debmetaindex.cc | 6 +- apt-pkg/deb/debmetaindex.h | 34 ++++---- apt-pkg/deb/debrecords.h | 32 +++---- apt-pkg/deb/debsrcrecords.h | 24 ++--- apt-pkg/deb/debsystem.h | 16 ++-- apt-pkg/deb/debversion.h | 4 +- apt-pkg/deb/dpkgpm.h | 12 +-- apt-pkg/depcache.h | 2 +- apt-pkg/edsp/edspindexfile.cc | 2 +- apt-pkg/edsp/edspindexfile.h | 2 +- apt-pkg/edsp/edsplistparser.h | 8 +- apt-pkg/edsp/edspsystem.h | 18 ++-- apt-pkg/indexcopy.h | 16 ++-- apt-pkg/indexfile.h | 8 +- apt-pkg/install-progress.h | 28 +++--- apt-pkg/policy.h | 6 +- apt-pkg/tagfile.h | 2 +- apt-private/acqprogress.h | 18 ++-- apt-private/private-cacheset.h | 16 ++-- apt-private/private-moo.h | 2 + cmdline/apt-cdrom.cc | 8 +- cmdline/apt-extracttemplates.h | 4 +- cmdline/apt-get.cc | 2 +- ftparchive/contents.h | 2 +- ftparchive/writer.h | 8 +- methods/cdrom.cc | 4 +- methods/copy.cc | 2 +- methods/file.cc | 2 +- methods/ftp.cc | 1 - methods/ftp.h | 6 +- methods/gpgv.cc | 4 +- methods/gzip.cc | 4 +- methods/http.h | 34 ++++---- methods/https.h | 34 ++++---- methods/mirror.h | 10 +-- methods/rred.cc | 4 +- methods/rsh.h | 4 +- methods/server.h | 4 +- test/interactive-helper/testdeb.cc | 2 +- test/libapt/acqprogress_test.cc | 4 +- test/libapt/indexcopytosourcelist_test.cc | 8 +- 54 files changed, 368 insertions(+), 362 deletions(-) (limited to 'test') diff --git a/apt-inst/deb/debfile.h b/apt-inst/deb/debfile.h index 9d286716a..6ad9b7659 100644 --- a/apt-inst/deb/debfile.h +++ b/apt-inst/deb/debfile.h @@ -65,7 +65,7 @@ class debDebFile::ControlExtract : public pkgDirStream { public: - virtual bool DoItem(Item &Itm,int &Fd); + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; }; class debDebFile::MemControlExtract : public pkgDirStream @@ -80,10 +80,10 @@ class debDebFile::MemControlExtract : public pkgDirStream std::string Member; // Members from DirStream - virtual bool DoItem(Item &Itm,int &Fd); + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; virtual bool Process(Item &Itm,const unsigned char *Data, #if APT_PKG_ABI >= 413 - unsigned long long Size,unsigned long long Pos); + unsigned long long Size,unsigned long long Pos) APT_OVERRIDE; #else unsigned long Size,unsigned long Pos); #endif diff --git a/apt-inst/extract.h b/apt-inst/extract.h index 8ad9ac629..a62ff51bd 100644 --- a/apt-inst/extract.h +++ b/apt-inst/extract.h @@ -38,9 +38,9 @@ class pkgExtract : public pkgDirStream public: - virtual bool DoItem(Item &Itm,int &Fd); - virtual bool Fail(Item &Itm,int Fd); - virtual bool FinishedFile(Item &Itm,int Fd); + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; + virtual bool Fail(Item &Itm,int Fd) APT_OVERRIDE; + virtual bool FinishedFile(Item &Itm,int Fd) APT_OVERRIDE; bool Finished(); bool Aborted(); diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index b6466115e..864b93188 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -391,8 +391,8 @@ class APT_HIDDEN NoActionItem : public pkgAcquire::Item /*{{{*/ { IndexTarget const Target; public: - virtual std::string DescURI() const {return Target.URI;}; - virtual HashStringList GetExpectedHashes() const {return HashStringList();}; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI;}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE {return HashStringList();}; NoActionItem(pkgAcquire * const Owner, IndexTarget const &Target) : pkgAcquire::Item(Owner), Target(Target) diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 93d812248..2349d386c 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -349,7 +349,7 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ IndexTarget const Target; HashStringList GetExpectedHashesFor(std::string const &MetaKey) const; - bool QueueURI(pkgAcquire::ItemDesc &Item); + bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; public: /** \brief storge name until a transaction is finished */ @@ -364,10 +364,10 @@ class APT_HIDDEN pkgAcqTransactionItem: public pkgAcquire::Item /*{{{*/ }; virtual bool TransactionState(TransactionStates const state); - virtual std::string DescURI() const { return Target.URI; } - virtual HashStringList GetExpectedHashes() const; + virtual std::string DescURI() const APT_OVERRIDE { return Target.URI; } + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; virtual std::string GetMetaKey() const; - virtual bool HashesRequired() const; + virtual bool HashesRequired() const APT_OVERRIDE; pkgAcqTransactionItem(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); @@ -417,7 +417,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ /** \brief Queue the downloaded Signature for verification */ void QueueForSignatureVerify(pkgAcqTransactionItem * const I, std::string const &File, std::string const &Signature); - virtual std::string Custom600Headers() const; + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Called when authentication succeeded. * @@ -440,15 +440,15 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ */ bool VerifyVendor(std::string const &Message); - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // This refers more to the Transaction-Manager than the actual file bool IMSHit; - virtual bool QueueURI(pkgAcquire::ItemDesc &Item); - virtual HashStringList GetExpectedHashes() const; - virtual bool HashesRequired() const; + virtual bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; // transaction code void Add(pkgAcqTransactionItem * const I); @@ -466,7 +466,7 @@ class APT_HIDDEN pkgAcqMetaBase : public pkgAcqTransactionItem /*{{{*/ void TransactionStageRemoval(pkgAcqTransactionItem * const I, const std::string &FinalFile); /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; pkgAcqMetaBase(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, std::vector const &IndexTargets, @@ -494,13 +494,13 @@ class APT_HIDDEN pkgAcqMetaIndex : public pkgAcqMetaBase void Init(std::string const &URIDesc, std::string const &ShortDesc); public: - virtual std::string DescURI() const; + virtual std::string DescURI() const APT_OVERRIDE; // Specialized action members - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual void Finished(); + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual void Finished() APT_OVERRIDE; /** \brief Create a new pkgAcqMetaIndex. */ pkgAcqMetaIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, @@ -531,16 +531,16 @@ class APT_HIDDEN pkgAcqMetaSig : public pkgAcqTransactionItem protected: /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; public: - virtual bool HashesRequired() const { return false; } + virtual bool HashesRequired() const APT_OVERRIDE { return false; } // Specialized action members - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string Custom600Headers() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Create a new pkgAcqMetaSig. */ pkgAcqMetaSig(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, @@ -561,10 +561,10 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex metaIndex *MetaIndexParser; metaIndex *LastMetaIndexParser; - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); - virtual std::string Custom600Headers() const; + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; /** \brief Create a new pkgAcqMetaClearSig. */ pkgAcqMetaClearSig(pkgAcquire * const Owner, @@ -583,7 +583,7 @@ class APT_HIDDEN pkgAcqBaseIndex : public pkgAcqTransactionItem public: /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; pkgAcqBaseIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); @@ -614,19 +614,19 @@ class APT_HIDDEN pkgAcqDiffIndex : public pkgAcqBaseIndex std::string Description; /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - virtual bool QueueURI(pkgAcquire::ItemDesc &Item); + virtual bool QueueURI(pkgAcquire::ItemDesc &Item) APT_OVERRIDE; - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // Specialized action members - virtual void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string DescURI() const {return Target.URI + "Index";}; - virtual std::string Custom600Headers() const; - virtual std::string GetMetaKey() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "Index";}; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string GetMetaKey() const APT_OVERRIDE; /** \brief Parse the Index file for a set of Packages diffs. * @@ -724,13 +724,13 @@ class APT_HIDDEN pkgAcqIndexMergeDiffs : public pkgAcqBaseIndex * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string Custom600Headers() const; - virtual std::string DescURI() const {return Target.URI + "Index";}; - virtual HashStringList GetExpectedHashes() const; - virtual bool HashesRequired() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "Index";}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create an index merge-diff item. * @@ -836,14 +836,14 @@ class APT_HIDDEN pkgAcqIndexDiffs : public pkgAcqBaseIndex * This method will fall back to downloading the whole index file * outright; its arguments are ignored. */ - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string Custom600Headers() const; - virtual std::string DescURI() const {return Target.URI + "IndexDiffs";}; - virtual HashStringList GetExpectedHashes() const; - virtual bool HashesRequired() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Target.URI + "IndexDiffs";}; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create an index diff item. * @@ -928,18 +928,18 @@ class APT_HIDDEN pkgAcqIndex : public pkgAcqBaseIndex void ReverifyAfterIMS(); /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; - virtual bool TransactionState(TransactionStates const state); + virtual bool TransactionState(TransactionStates const state) APT_OVERRIDE; public: // Specialized action members - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string Custom600Headers() const; - virtual std::string DescURI() const {return Desc.URI;}; - virtual std::string GetMetaKey() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; + virtual std::string GetMetaKey() const APT_OVERRIDE; pkgAcqIndex(pkgAcquire * const Owner, pkgAcqMetaClearSig * const TransactionManager, IndexTarget const &Target); @@ -1000,19 +1000,19 @@ class pkgAcqArchive : public pkgAcquire::Item bool QueueNext(); /** \brief Get the full pathname of the final file for the current URI */ - virtual std::string GetFinalFilename() const; + virtual std::string GetFinalFilename() const APT_OVERRIDE; public: - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string DescURI() const; - virtual std::string ShortDesc() const; - virtual void Finished(); - virtual bool IsTrusted() const; - virtual HashStringList GetExpectedHashes() const; - virtual bool HashesRequired() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE; + virtual std::string ShortDesc() const APT_OVERRIDE; + virtual void Finished() APT_OVERRIDE; + virtual bool IsTrusted() const APT_OVERRIDE; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; /** \brief Create a new pkgAcqArchive. * @@ -1053,14 +1053,14 @@ class pkgAcqChangelog : public pkgAcquire::Item public: // we will never have hashes for changelogs. // If you need verified ones, download the deb and extract the changelog. - virtual HashStringList GetExpectedHashes() const { return HashStringList(); } - virtual bool HashesRequired() const { return false; } + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE { return HashStringList(); } + virtual bool HashesRequired() const APT_OVERRIDE { return false; } // Specialized action members - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string DescURI() const {return Desc.URI;}; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; /** returns the URI to the changelog of this version * @@ -1172,15 +1172,15 @@ class pkgAcqFile : public pkgAcquire::Item HashStringList const ExpectedHashes; public: - virtual HashStringList GetExpectedHashes() const; - virtual bool HashesRequired() const; + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE; + virtual bool HashesRequired() const APT_OVERRIDE; // Specialized action members - virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &CalcHashes, - pkgAcquire::MethodConfig const * const Cnf); - virtual std::string DescURI() const {return Desc.URI;}; - virtual std::string Custom600Headers() const; + pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; + virtual std::string DescURI() const APT_OVERRIDE {return Desc.URI;}; + virtual std::string Custom600Headers() const APT_OVERRIDE; /** \brief Create a new pkgAcqFile object. * diff --git a/apt-pkg/algorithms.h b/apt-pkg/algorithms.h index d9cce672a..28057fa5c 100644 --- a/apt-pkg/algorithms.h +++ b/apt-pkg/algorithms.h @@ -62,7 +62,7 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ pkgDepCache *Cache; public: - virtual VerIterator GetCandidateVer(PkgIterator const &Pkg) + virtual VerIterator GetCandidateVer(PkgIterator const &Pkg) APT_OVERRIDE { return (*Cache)[Pkg].CandidateVerIter(*Cache); } @@ -77,9 +77,9 @@ class pkgSimulate : public pkgPackageManager /*{{{*/ pkgDepCache::ActionGroup group; // The Actuall installation implementation - virtual bool Install(PkgIterator Pkg,std::string File); - virtual bool Configure(PkgIterator Pkg); - virtual bool Remove(PkgIterator Pkg,bool Purge); + virtual bool Install(PkgIterator Pkg,std::string File) APT_OVERRIDE; + virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE; + virtual bool Remove(PkgIterator Pkg,bool Purge) APT_OVERRIDE; private: APT_HIDDEN void ShortBreaks(); diff --git a/apt-pkg/cachefilter.h b/apt-pkg/cachefilter.h index df9e9460a..2719154c1 100644 --- a/apt-pkg/cachefilter.h +++ b/apt-pkg/cachefilter.h @@ -30,33 +30,33 @@ public: class PackageMatcher : public Matcher { public: virtual bool operator() (pkgCache::PkgIterator const &Pkg) = 0; - virtual bool operator() (pkgCache::VerIterator const &Ver) { return (*this)(Ver.ParentPkg()); } - virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) { return false; } + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE { return (*this)(Ver.ParentPkg()); } + virtual bool operator() (pkgCache::GrpIterator const &/*Grp*/) APT_OVERRIDE { return false; } virtual ~PackageMatcher(); }; // Generica like True, False, NOT, AND, OR /*{{{*/ class TrueMatcher : public Matcher { public: - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; }; class FalseMatcher : public Matcher { public: - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; }; class NOTMatcher : public Matcher { Matcher * const matcher; public: explicit NOTMatcher(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~NOTMatcher(); }; @@ -71,9 +71,9 @@ public: ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4); ANDMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5); ANDMatcher& AND(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~ANDMatcher(); }; class ORMatcher : public Matcher { @@ -87,9 +87,9 @@ public: ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4); ORMatcher(Matcher * const matcher1, Matcher * const matcher2, Matcher * const matcher3, Matcher * const matcher4, Matcher * const matcher5); ORMatcher& OR(Matcher * const matcher); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); - virtual bool operator() (pkgCache::VerIterator const &Ver); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; + virtual bool operator() (pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual ~ORMatcher(); }; /*}}}*/ @@ -97,8 +97,8 @@ class PackageNameMatchesRegEx : public PackageMatcher { /*{{{*/ regex_t* pattern; public: explicit PackageNameMatchesRegEx(std::string const &Pattern); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; virtual ~PackageNameMatchesRegEx(); }; /*}}}*/ @@ -106,8 +106,8 @@ class PackageNameMatchesFnmatch : public PackageMatcher { /*{{{*/ const std::string Pattern; public: explicit PackageNameMatchesFnmatch(std::string const &Pattern); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); - virtual bool operator() (pkgCache::GrpIterator const &Grp); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual bool operator() (pkgCache::GrpIterator const &Grp) APT_OVERRIDE; virtual ~PackageNameMatchesFnmatch() {}; }; /*}}}*/ @@ -133,7 +133,7 @@ public: */ PackageArchitectureMatchesSpecification(std::string const &pattern, bool const isPattern = true); bool operator() (char const * const &arch); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; virtual ~PackageArchitectureMatchesSpecification(); }; /*}}}*/ @@ -141,7 +141,7 @@ class PackageIsNewInstall : public PackageMatcher { /*{{{*/ pkgCacheFile * const Cache; public: explicit PackageIsNewInstall(pkgCacheFile * const Cache); - virtual bool operator() (pkgCache::PkgIterator const &Pkg); + virtual bool operator() (pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; virtual ~PackageIsNewInstall(); }; /*}}}*/ diff --git a/apt-pkg/contrib/md5.h b/apt-pkg/contrib/md5.h index f4992c223..a16ea4d2d 100644 --- a/apt-pkg/contrib/md5.h +++ b/apt-pkg/contrib/md5.h @@ -48,7 +48,7 @@ class MD5Summation : public SummationImplementation public: - bool Add(const unsigned char *inbuf, unsigned long long inlen); + bool Add(const unsigned char *inbuf, unsigned long long inlen) APT_OVERRIDE; using SummationImplementation::Add; MD5SumValue Result(); diff --git a/apt-pkg/contrib/progress.h b/apt-pkg/contrib/progress.h index f7fbc9ccf..427b1bd35 100644 --- a/apt-pkg/contrib/progress.h +++ b/apt-pkg/contrib/progress.h @@ -24,6 +24,7 @@ #include #include +#include #ifndef APT_8_CLEANER_HEADERS using std::string; @@ -74,12 +75,12 @@ class OpTextProgress : public OpProgress bool NoUpdate; bool NoDisplay; unsigned long LastLen; - virtual void Update(); + virtual void Update() APT_OVERRIDE; void Write(const char *S); public: - virtual void Done(); + virtual void Done() APT_OVERRIDE; OpTextProgress(bool NoUpdate = false) : NoUpdate(NoUpdate), NoDisplay(false), LastLen(0) {}; diff --git a/apt-pkg/contrib/sha1.h b/apt-pkg/contrib/sha1.h index 5770c315a..1c5cb5aa1 100644 --- a/apt-pkg/contrib/sha1.h +++ b/apt-pkg/contrib/sha1.h @@ -37,7 +37,7 @@ class SHA1Summation : public SummationImplementation bool Done; public: - bool Add(const unsigned char *inbuf, unsigned long long inlen); + bool Add(const unsigned char *inbuf, unsigned long long inlen) APT_OVERRIDE; using SummationImplementation::Add; SHA1SumValue Result(); diff --git a/apt-pkg/contrib/sha2.h b/apt-pkg/contrib/sha2.h index a25ad4d32..70e8384f2 100644 --- a/apt-pkg/contrib/sha2.h +++ b/apt-pkg/contrib/sha2.h @@ -45,7 +45,7 @@ class SHA256Summation : public SHA2SummationBase unsigned char Sum[32]; public: - bool Add(const unsigned char *inbuf, unsigned long long len) + bool Add(const unsigned char *inbuf, unsigned long long len) APT_OVERRIDE { if (Done) return false; @@ -78,7 +78,7 @@ class SHA512Summation : public SHA2SummationBase unsigned char Sum[64]; public: - bool Add(const unsigned char *inbuf, unsigned long long len) + bool Add(const unsigned char *inbuf, unsigned long long len) APT_OVERRIDE { if (Done) return false; diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index c5086b04b..972feba7f 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -482,7 +482,7 @@ class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -497,7 +497,7 @@ class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -506,7 +506,7 @@ class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debDebFileRecordParser(File.FileName()); }; @@ -515,7 +515,7 @@ class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const APT_OVERRIDE { return new debDscRecordParser(DscFile, NULL); }; @@ -524,7 +524,7 @@ class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const APT_OVERRIDE { return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); }; diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 1de609a7b..71ca22e4d 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -38,14 +38,14 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile virtual const Type *GetType() const APT_CONST; // Interface for acquire - virtual std::string Describe(bool /*Short*/) const {return File;}; + virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE {return File;}; // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const {return true;}; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual bool Exists() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE {return true;}; + virtual unsigned long Size() const APT_OVERRIDE; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; debStatusIndex(std::string File); virtual ~debStatusIndex(); @@ -59,12 +59,12 @@ class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile virtual const Type *GetType() const APT_CONST; // Stuff for accessing files on remote items - virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const; + virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const APT_OVERRIDE; // Interface for the Cache Generator - virtual bool HasPackages() const {return true;}; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual bool HasPackages() const APT_OVERRIDE {return true;}; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; debPackagesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debPackagesIndex(); @@ -78,9 +78,9 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile virtual const Type *GetType() const APT_CONST; // Interface for the Cache Generator - virtual bool HasPackages() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual bool HasPackages() const APT_OVERRIDE; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; debTranslationsIndex(IndexTarget const &Target); virtual ~debTranslationsIndex(); @@ -95,13 +95,13 @@ class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile // Stuff for accessing files on remote items virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record, - pkgSrcRecords::File const &File) const; + pkgSrcRecords::File const &File) const APT_OVERRIDE; // Interface for the record parsers - virtual pkgSrcRecords::Parser *CreateSrcParser() const; + virtual pkgSrcRecords::Parser *CreateSrcParser() const APT_OVERRIDE; // Interface for the Cache Generator - virtual bool HasPackages() const {return false;}; + virtual bool HasPackages() const APT_OVERRIDE {return false;}; debSourcesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debSourcesIndex(); @@ -117,7 +117,7 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile public: virtual const Type *GetType() const APT_CONST; - virtual std::string Describe(bool /*Short*/) const { + virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE { return DebFile; } @@ -130,16 +130,16 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile static bool GetContent(std::ostream &content, std::string const &debfile); // Interface for the Cache Generator - virtual bool Exists() const; - virtual bool HasPackages() const { + virtual bool Exists() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE { return true; }; - virtual unsigned long Size() const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; + virtual unsigned long Size() const APT_OVERRIDE; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; // Interface for acquire - virtual std::string ArchiveURI(std::string /*File*/) const; + virtual std::string ArchiveURI(std::string /*File*/) const APT_OVERRIDE; debDebPkgFileIndex(std::string DebFile); virtual ~debDebPkgFileIndex(); @@ -152,11 +152,11 @@ class APT_HIDDEN debDscFileIndex : public pkgIndexFile std::string DscFile; public: virtual const Type *GetType() const APT_CONST; - virtual pkgSrcRecords::Parser *CreateSrcParser() const; - virtual bool Exists() const; - virtual bool HasPackages() const {return false;}; - virtual unsigned long Size() const; - virtual std::string Describe(bool /*Short*/) const { + virtual pkgSrcRecords::Parser *CreateSrcParser() const APT_OVERRIDE; + virtual bool Exists() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE {return false;}; + virtual unsigned long Size() const APT_OVERRIDE; + virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE { return DscFile; }; diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 3fd040bdd..4bc3c2341 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -62,24 +62,24 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser APT_PUBLIC static unsigned char GetPrio(std::string Str); // These all operate against the current section - virtual std::string Package(); - virtual std::string Architecture(); - virtual bool ArchitectureAll(); - virtual std::string Version(); - virtual bool NewVersion(pkgCache::VerIterator &Ver); - virtual std::string Description(std::string const &lang); - virtual std::vector AvailableDescriptionLanguages(); - virtual MD5SumValue Description_md5(); - virtual unsigned short VersionHash(); + virtual std::string Package() APT_OVERRIDE; + virtual std::string Architecture() APT_OVERRIDE; + virtual bool ArchitectureAll() APT_OVERRIDE; + virtual std::string Version() APT_OVERRIDE; + virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE; + virtual std::string Description(std::string const &lang) APT_OVERRIDE; + virtual std::vector AvailableDescriptionLanguages() APT_OVERRIDE; + virtual MD5SumValue Description_md5() APT_OVERRIDE; + virtual unsigned short VersionHash() APT_OVERRIDE; #if APT_PKG_ABI >= 413 - virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver); + virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver) APT_OVERRIDE; #endif virtual bool UsePackage(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver); - virtual map_filesize_t Offset() {return iOffset;}; - virtual map_filesize_t Size() {return Section.size();}; + pkgCache::VerIterator &Ver) APT_OVERRIDE; + virtual map_filesize_t Offset() APT_OVERRIDE {return iOffset;}; + virtual map_filesize_t Size() APT_OVERRIDE {return Section.size();}; - virtual bool Step(); + virtual bool Step() APT_OVERRIDE; bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, std::string const §ion); @@ -111,15 +111,15 @@ class APT_HIDDEN debDebFileParser : public debListParser public: debDebFileParser(FileFd *File, std::string const &DebFile); virtual bool UsePackage(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver); + pkgCache::VerIterator &Ver) APT_OVERRIDE; }; class APT_HIDDEN debTranslationsParser : public debListParser { public: // a translation can never be a real package - virtual std::string Architecture() { return ""; } - virtual std::string Version() { return ""; } + virtual std::string Architecture() APT_OVERRIDE { return ""; } + virtual std::string Version() APT_OVERRIDE { return ""; } debTranslationsParser(FileFd *File, std::string const &Arch = "") : debListParser(File, Arch) {}; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 10ab0f844..46a7181fc 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -758,7 +758,7 @@ class APT_HIDDEN debSLTypeDeb : public debSLTypeDebian /*{{{*/ bool CreateItem(std::vector &List, std::string const &URI, std::string const &Dist, std::string const &Section, - std::map const &Options) const + std::map const &Options) const APT_OVERRIDE { return CreateItemInternal(List, URI, Dist, Section, false, Options); } @@ -774,7 +774,7 @@ class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian /*{{{*/ bool CreateItem(std::vector &List, std::string const &URI, std::string const &Dist, std::string const &Section, - std::map const &Options) const + std::map const &Options) const APT_OVERRIDE { return CreateItemInternal(List, URI, Dist, Section, true, Options); } @@ -800,7 +800,7 @@ class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type /*{{{*/ bool CreateItem(std::vector &List, std::string const &URI, std::string const &/*Dist*/, std::string const &/*Section*/, - std::map const &/*Options*/) const + std::map const &/*Options*/) const APT_OVERRIDE { metaIndex *mi = new debDebFileMetaIndex(URI); List.push_back(mi); diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index bf5b7c1ce..8c13237cb 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -39,18 +39,18 @@ class APT_HIDDEN debReleaseIndex : public metaIndex debReleaseIndex(std::string const &URI, std::string const &Dist, bool const Trusted); virtual ~debReleaseIndex(); - virtual std::string ArchiveURI(std::string const &File) const {return URI + File;}; - virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false); - virtual std::vector GetIndexTargets() const; + virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE {return URI + File;}; + virtual bool GetIndexes(pkgAcquire *Owner, bool const &GetAll=false) APT_OVERRIDE; + virtual std::vector GetIndexTargets() const APT_OVERRIDE; - virtual std::string Describe() const; - virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + virtual std::string Describe() const APT_OVERRIDE; + virtual pkgCache::RlsFileIterator FindInCache(pkgCache &Cache, bool const ModifyCheck) const APT_OVERRIDE; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; - virtual bool Load(std::string const &Filename, std::string * const ErrorText); - virtual metaIndex * UnloadedClone() const; + virtual bool Load(std::string const &Filename, std::string * const ErrorText) APT_OVERRIDE; + virtual metaIndex * UnloadedClone() const APT_OVERRIDE; - virtual std::vector *GetIndexFiles(); + virtual std::vector *GetIndexFiles() APT_OVERRIDE; bool SetTrusted(TriState const Trusted); bool SetCheckValidUntil(TriState const Trusted); @@ -58,7 +58,7 @@ class APT_HIDDEN debReleaseIndex : public metaIndex bool SetValidUntilMax(time_t const Valid); bool SetSignedBy(std::string const &SignedBy); - virtual bool IsTrusted() const; + virtual bool IsTrusted() const APT_OVERRIDE; void AddComponent(bool const isSrc, std::string const &Name, std::vector const &Targets, @@ -73,29 +73,29 @@ private: std::string DebFile; debDebPkgFileIndex *DebIndex; public: - virtual std::string ArchiveURI(std::string const& /*File*/) const { + virtual std::string ArchiveURI(std::string const& /*File*/) const APT_OVERRIDE { return DebFile; } - virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) { + virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) APT_OVERRIDE { return true; } - virtual std::vector GetIndexTargets() const { + virtual std::vector GetIndexTargets() const APT_OVERRIDE { return std::vector(); } - virtual std::vector *GetIndexFiles() { + virtual std::vector *GetIndexFiles() APT_OVERRIDE { return Indexes; } - virtual bool IsTrusted() const { + virtual bool IsTrusted() const APT_OVERRIDE { return true; } - virtual bool Load(std::string const &, std::string * const ErrorText) + virtual bool Load(std::string const &, std::string * const ErrorText) APT_OVERRIDE { LoadedSuccessfully = TRI_NO; if (ErrorText != NULL) strprintf(*ErrorText, "Unparseable metaindex as it represents the standalone deb file %s", DebFile.c_str()); return false; } - virtual metaIndex * UnloadedClone() const + virtual metaIndex * UnloadedClone() const APT_OVERRIDE { return NULL; } diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h index 4d0b713d4..7fc82a88d 100644 --- a/apt-pkg/deb/debrecords.h +++ b/apt-pkg/deb/debrecords.h @@ -33,23 +33,23 @@ class APT_HIDDEN debRecordParserBase : public pkgRecords::Parser public: // These refer to the archive file for the Version - virtual std::string FileName(); - virtual std::string SourcePkg(); - virtual std::string SourceVer(); + virtual std::string FileName() APT_OVERRIDE; + virtual std::string SourcePkg() APT_OVERRIDE; + virtual std::string SourceVer() APT_OVERRIDE; - virtual HashStringList Hashes() const; + virtual HashStringList Hashes() const APT_OVERRIDE; // These are some general stats about the package - virtual std::string Maintainer(); - virtual std::string ShortDesc(std::string const &lang); - virtual std::string LongDesc(std::string const &lang); - virtual std::string Name(); - virtual std::string Homepage(); + virtual std::string Maintainer() APT_OVERRIDE; + virtual std::string ShortDesc(std::string const &lang) APT_OVERRIDE; + virtual std::string LongDesc(std::string const &lang) APT_OVERRIDE; + virtual std::string Name() APT_OVERRIDE; + virtual std::string Homepage() APT_OVERRIDE; // An arbitrary custom field - virtual std::string RecordField(const char *fieldName); + virtual std::string RecordField(const char *fieldName) APT_OVERRIDE; - virtual void GetRec(const char *&Start,const char *&Stop); + virtual void GetRec(const char *&Start,const char *&Stop) APT_OVERRIDE; debRecordParserBase(); virtual ~debRecordParserBase(); @@ -62,8 +62,8 @@ class APT_HIDDEN debRecordParser : public debRecordParserBase FileFd File; pkgTagFile Tags; - virtual bool Jump(pkgCache::VerFileIterator const &Ver); - virtual bool Jump(pkgCache::DescFileIterator const &Desc); + virtual bool Jump(pkgCache::VerFileIterator const &Ver) APT_OVERRIDE; + virtual bool Jump(pkgCache::DescFileIterator const &Desc) APT_OVERRIDE; public: debRecordParser(std::string FileName,pkgCache &Cache); @@ -80,11 +80,11 @@ class APT_HIDDEN debDebFileRecordParser : public debRecordParserBase APT_HIDDEN bool LoadContent(); protected: // single file files, so no jumping whatsoever - bool Jump(pkgCache::VerFileIterator const &); - bool Jump(pkgCache::DescFileIterator const &); + bool Jump(pkgCache::VerFileIterator const &) APT_OVERRIDE; + bool Jump(pkgCache::DescFileIterator const &) APT_OVERRIDE; public: - virtual std::string FileName(); + virtual std::string FileName() APT_OVERRIDE; debDebFileRecordParser(std::string FileName); virtual ~debDebFileRecordParser(); diff --git a/apt-pkg/deb/debsrcrecords.h b/apt-pkg/deb/debsrcrecords.h index 64b07a1ec..89134af5f 100644 --- a/apt-pkg/deb/debsrcrecords.h +++ b/apt-pkg/deb/debsrcrecords.h @@ -36,24 +36,24 @@ class APT_HIDDEN debSrcRecordParser : public pkgSrcRecords::Parser public: - virtual bool Restart() {return Jump(0);}; - virtual bool Step() {iOffset = Tags.Offset(); return Tags.Step(Sect);}; - virtual bool Jump(unsigned long const &Off) {iOffset = Off; return Tags.Jump(Sect,Off);}; + virtual bool Restart() APT_OVERRIDE {return Jump(0);}; + virtual bool Step() APT_OVERRIDE {iOffset = Tags.Offset(); return Tags.Step(Sect);}; + virtual bool Jump(unsigned long const &Off) APT_OVERRIDE {iOffset = Off; return Tags.Jump(Sect,Off);}; - virtual std::string Package() const {return Sect.FindS("Package");}; - virtual std::string Version() const {return Sect.FindS("Version");}; - virtual std::string Maintainer() const {return Sect.FindS("Maintainer");}; - virtual std::string Section() const {return Sect.FindS("Section");}; - virtual const char **Binaries(); - virtual bool BuildDepends(std::vector &BuildDeps, bool const &ArchOnly, bool const &StripMultiArch = true); - virtual unsigned long Offset() {return iOffset;}; - virtual std::string AsStr() + virtual std::string Package() const APT_OVERRIDE {return Sect.FindS("Package");}; + virtual std::string Version() const APT_OVERRIDE {return Sect.FindS("Version");}; + virtual std::string Maintainer() const APT_OVERRIDE {return Sect.FindS("Maintainer");}; + virtual std::string Section() const APT_OVERRIDE {return Sect.FindS("Section");}; + virtual const char **Binaries() APT_OVERRIDE; + virtual bool BuildDepends(std::vector &BuildDeps, bool const &ArchOnly, bool const &StripMultiArch = true) APT_OVERRIDE; + virtual unsigned long Offset() APT_OVERRIDE {return iOffset;}; + virtual std::string AsStr() APT_OVERRIDE { const char *Start=0,*Stop=0; Sect.GetSection(Start,Stop); return std::string(Start,Stop); }; - virtual bool Files(std::vector &F); + virtual bool Files(std::vector &F) APT_OVERRIDE; bool Files2(std::vector &F); debSrcRecordParser(std::string const &File,pkgIndexFile const *Index); diff --git a/apt-pkg/deb/debsystem.h b/apt-pkg/deb/debsystem.h index e59bbebed..aed77520e 100644 --- a/apt-pkg/deb/debsystem.h +++ b/apt-pkg/deb/debsystem.h @@ -33,15 +33,15 @@ class debSystem : public pkgSystem public: - virtual bool Lock(); - virtual bool UnLock(bool NoErrors = false); - virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const; - virtual bool Initialize(Configuration &Cnf); - virtual bool ArchiveSupported(const char *Type); - virtual signed Score(Configuration const &Cnf); - virtual bool AddStatusFiles(std::vector &List); + virtual bool Lock() APT_OVERRIDE; + virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE; + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE; + virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; + virtual bool ArchiveSupported(const char *Type) APT_OVERRIDE; + virtual signed Score(Configuration const &Cnf) APT_OVERRIDE; + virtual bool AddStatusFiles(std::vector &List) APT_OVERRIDE; virtual bool FindIndex(pkgCache::PkgFileIterator File, - pkgIndexFile *&Found) const; + pkgIndexFile *&Found) const APT_OVERRIDE; debSystem(); virtual ~debSystem(); diff --git a/apt-pkg/deb/debversion.h b/apt-pkg/deb/debversion.h index 7befe6372..6d7eca7c1 100644 --- a/apt-pkg/deb/debversion.h +++ b/apt-pkg/deb/debversion.h @@ -27,11 +27,11 @@ class debVersioningSystem : public pkgVersioningSystem const char *B,const char *Bend) APT_PURE; virtual bool CheckDep(const char *PkgVer,int Op,const char *DepVer) APT_PURE; virtual APT_PURE int DoCmpReleaseVer(const char *A,const char *Aend, - const char *B,const char *Bend) + const char *B,const char *Bend) APT_OVERRIDE { return DoCmpVersion(A,Aend,B,Bend); } - virtual std::string UpstreamVersion(const char *A); + virtual std::string UpstreamVersion(const char *A) APT_OVERRIDE; debVersioningSystem(); }; diff --git a/apt-pkg/deb/dpkgpm.h b/apt-pkg/deb/dpkgpm.h index a1b36c6c0..82c1bef5d 100644 --- a/apt-pkg/deb/dpkgpm.h +++ b/apt-pkg/deb/dpkgpm.h @@ -120,14 +120,14 @@ class pkgDPkgPM : public pkgPackageManager void ProcessDpkgStatusLine(char *line); // The Actuall installation implementation - virtual bool Install(PkgIterator Pkg,std::string File); - virtual bool Configure(PkgIterator Pkg); - virtual bool Remove(PkgIterator Pkg,bool Purge = false); + virtual bool Install(PkgIterator Pkg,std::string File) APT_OVERRIDE; + virtual bool Configure(PkgIterator Pkg) APT_OVERRIDE; + virtual bool Remove(PkgIterator Pkg,bool Purge = false) APT_OVERRIDE; - virtual bool Go(APT::Progress::PackageManager *progress); - virtual bool Go(int StatusFd=-1); + virtual bool Go(APT::Progress::PackageManager *progress) APT_OVERRIDE; + virtual bool Go(int StatusFd=-1) APT_OVERRIDE; - virtual void Reset(); + virtual void Reset() APT_OVERRIDE; public: diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 40a2fcaab..2c3304ba8 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -204,7 +204,7 @@ class pkgDepCache : protected pkgCache::Namespace DefaultRootSetFunc() : Configuration::MatchAgainstConfig("APT::NeverAutoRemove") {}; virtual ~DefaultRootSetFunc() {}; - bool InRootSet(const pkgCache::PkgIterator &pkg) { return pkg.end() == false && Match(pkg.Name()); }; + bool InRootSet(const pkgCache::PkgIterator &pkg) APT_OVERRIDE { return pkg.end() == false && Match(pkg.Name()); }; }; struct StateCache diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index 3bffc27e9..649d94b5d 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -67,7 +67,7 @@ bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const class APT_HIDDEN edspIFType: public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const APT_OVERRIDE { // we don't have a record parser for this type as the file is not presistent return NULL; diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index 265a016c5..b2a510f14 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -27,7 +27,7 @@ class APT_HIDDEN edspIndex : public debStatusIndex virtual const Type *GetType() const APT_CONST; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const; + virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; edspIndex(std::string File); virtual ~edspIndex(); diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 98dde4bf5..2a09e8c47 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -29,11 +29,11 @@ class APT_HIDDEN edspListParser : public debListParser { void * const d; public: - virtual bool NewVersion(pkgCache::VerIterator &Ver); + virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE; virtual std::string Description(); virtual std::string DescriptionLanguage(); - virtual MD5SumValue Description_md5(); - virtual unsigned short VersionHash(); + virtual MD5SumValue Description_md5() APT_OVERRIDE; + virtual unsigned short VersionHash() APT_OVERRIDE; bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, std::string const §ion); @@ -42,7 +42,7 @@ class APT_HIDDEN edspListParser : public debListParser virtual ~edspListParser(); protected: - virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver) APT_OVERRIDE; }; diff --git a/apt-pkg/edsp/edspsystem.h b/apt-pkg/edsp/edspsystem.h index 156b02bb5..ec42bef75 100644 --- a/apt-pkg/edsp/edspsystem.h +++ b/apt-pkg/edsp/edspsystem.h @@ -16,6 +16,8 @@ #include +#include + class Configuration; class pkgDepCache; class pkgIndexFile; @@ -31,15 +33,15 @@ class APT_HIDDEN edspSystem : public pkgSystem public: - virtual bool Lock() APT_CONST; - virtual bool UnLock(bool NoErrors = false) APT_CONST; - virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_CONST; - virtual bool Initialize(Configuration &Cnf); - virtual bool ArchiveSupported(const char *Type) APT_CONST; - virtual signed Score(Configuration const &Cnf); - virtual bool AddStatusFiles(std::vector &List); + virtual bool Lock() APT_OVERRIDE APT_CONST; + virtual bool UnLock(bool NoErrors = false) APT_OVERRIDE APT_CONST; + virtual pkgPackageManager *CreatePM(pkgDepCache *Cache) const APT_OVERRIDE APT_CONST; + virtual bool Initialize(Configuration &Cnf) APT_OVERRIDE; + virtual bool ArchiveSupported(const char *Type) APT_OVERRIDE APT_CONST; + virtual signed Score(Configuration const &Cnf) APT_OVERRIDE; + virtual bool AddStatusFiles(std::vector &List) APT_OVERRIDE; virtual bool FindIndex(pkgCache::PkgFileIterator File, - pkgIndexFile *&Found) const; + pkgIndexFile *&Found) const APT_OVERRIDE; edspSystem(); virtual ~edspSystem(); diff --git a/apt-pkg/indexcopy.h b/apt-pkg/indexcopy.h index 6eecad028..316672e1d 100644 --- a/apt-pkg/indexcopy.h +++ b/apt-pkg/indexcopy.h @@ -62,10 +62,10 @@ class PackageCopy : public IndexCopy /*{{{*/ void * const d; protected: - virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FileFd &Target, std::string const &File); - virtual const char *GetFileName() {return "Packages";}; - virtual const char *Type() {return "Package";}; + virtual bool GetFile(std::string &Filename,unsigned long long &Size) APT_OVERRIDE; + virtual bool RewriteEntry(FileFd &Target, std::string const &File) APT_OVERRIDE; + virtual const char *GetFileName() APT_OVERRIDE {return "Packages";}; + virtual const char *Type() APT_OVERRIDE {return "Package";}; public: PackageCopy(); @@ -77,10 +77,10 @@ class SourceCopy : public IndexCopy /*{{{*/ void * const d; protected: - virtual bool GetFile(std::string &Filename,unsigned long long &Size); - virtual bool RewriteEntry(FileFd &Target, std::string const &File); - virtual const char *GetFileName() {return "Sources";}; - virtual const char *Type() {return "Source";}; + virtual bool GetFile(std::string &Filename,unsigned long long &Size) APT_OVERRIDE; + virtual bool RewriteEntry(FileFd &Target, std::string const &File) APT_OVERRIDE; + virtual const char *GetFileName() APT_OVERRIDE {return "Sources";}; + virtual const char *Type() APT_OVERRIDE {return "Source";}; public: SourceCopy(); diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 44d39110d..5be7794bf 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -160,10 +160,10 @@ protected: std::string IndexFileName() const; public: - virtual std::string ArchiveURI(std::string File) const; - virtual std::string Describe(bool Short = false) const; - virtual bool Exists() const; - virtual unsigned long Size() const; + virtual std::string ArchiveURI(std::string File) const APT_OVERRIDE; + virtual std::string Describe(bool Short = false) const APT_OVERRIDE; + virtual bool Exists() const APT_OVERRIDE; + virtual unsigned long Size() const APT_OVERRIDE; pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted); virtual ~pkgIndexTargetFile(); diff --git a/apt-pkg/install-progress.h b/apt-pkg/install-progress.h index 07fc15fd8..ee03ac217 100644 --- a/apt-pkg/install-progress.h +++ b/apt-pkg/install-progress.h @@ -72,21 +72,21 @@ namespace Progress { explicit PackageManagerProgressFd(int progress_fd); virtual ~PackageManagerProgressFd(); - virtual void StartDpkg(); - virtual void Stop(); + virtual void StartDpkg() APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; virtual void Error(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ErrorMessage); + std::string ErrorMessage) APT_OVERRIDE; virtual void ConffilePrompt(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ConfMessage); + std::string ConfMessage) APT_OVERRIDE; }; @@ -103,21 +103,21 @@ namespace Progress { explicit PackageManagerProgressDeb822Fd(int progress_fd); virtual ~PackageManagerProgressDeb822Fd(); - virtual void StartDpkg(); - virtual void Stop(); + virtual void StartDpkg() APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; virtual void Error(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ErrorMessage); + std::string ErrorMessage) APT_OVERRIDE; virtual void ConffilePrompt(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string ConfMessage); + std::string ConfMessage) APT_OVERRIDE; }; class PackageManagerFancy : public PackageManager @@ -144,12 +144,12 @@ namespace Progress { public: PackageManagerFancy(); virtual ~PackageManagerFancy(); - virtual void Start(int child_pty=-1); - virtual void Stop(); + virtual void Start(int child_pty=-1) APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; // return a progress bar of the given size for the given progress // percent between 0.0 and 1.0 in the form "[####...]" @@ -163,7 +163,7 @@ namespace Progress { virtual bool StatusChanged(std::string PackageName, unsigned int StepsDone, unsigned int TotalSteps, - std::string HumanReadableAction); + std::string HumanReadableAction) APT_OVERRIDE; PackageManagerText(); virtual ~PackageManagerText(); diff --git a/apt-pkg/policy.h b/apt-pkg/policy.h index 58b062a7b..b3e1ec6b1 100644 --- a/apt-pkg/policy.h +++ b/apt-pkg/policy.h @@ -78,10 +78,10 @@ class pkgPolicy : public pkgDepCache::Policy pkgCache::VerIterator GetMatch(pkgCache::PkgIterator const &Pkg); // Things for the cache interface. - virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg); - virtual signed short GetPriority(pkgCache::PkgIterator const &Pkg); + virtual pkgCache::VerIterator GetCandidateVer(pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; + virtual signed short GetPriority(pkgCache::PkgIterator const &Pkg) APT_OVERRIDE; virtual signed short GetPriority(pkgCache::VerIterator const &Pkg); - virtual signed short GetPriority(pkgCache::PkgFileIterator const &File); + virtual signed short GetPriority(pkgCache::PkgFileIterator const &File) APT_OVERRIDE; bool InitDefaults(); diff --git a/apt-pkg/tagfile.h b/apt-pkg/tagfile.h index 81fff89f0..77a84c832 100644 --- a/apt-pkg/tagfile.h +++ b/apt-pkg/tagfile.h @@ -147,7 +147,7 @@ class pkgTagSection for being a bit slower to allow comments and new lines all over the place */ class pkgUserTagSection : public pkgTagSection { - virtual void TrimRecord(bool BeforeRecord, const char* &End); + virtual void TrimRecord(bool BeforeRecord, const char* &End) APT_OVERRIDE; }; class pkgTagFilePrivate; diff --git a/apt-private/acqprogress.h b/apt-private/acqprogress.h index cbb06fbec..6b6d555b1 100644 --- a/apt-private/acqprogress.h +++ b/apt-private/acqprogress.h @@ -28,15 +28,15 @@ class APT_PUBLIC AcqTextStatus : public pkgAcquireStatus public: - virtual bool MediaChange(std::string Media,std::string Drive); - virtual void IMSHit(pkgAcquire::ItemDesc &Itm); - virtual void Fetch(pkgAcquire::ItemDesc &Itm); - virtual void Done(pkgAcquire::ItemDesc &Itm); - virtual void Fail(pkgAcquire::ItemDesc &Itm); - virtual void Start(); - virtual void Stop(); - - bool Pulse(pkgAcquire *Owner); + virtual bool MediaChange(std::string Media,std::string Drive) APT_OVERRIDE; + virtual void IMSHit(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; + virtual void Fetch(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; + virtual void Done(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; + virtual void Fail(pkgAcquire::ItemDesc &Itm) APT_OVERRIDE; + virtual void Start() APT_OVERRIDE; + virtual void Stop() APT_OVERRIDE; + + bool Pulse(pkgAcquire *Owner) APT_OVERRIDE; AcqTextStatus(std::ostream &out, unsigned int &ScreenWidth,unsigned int const Quiet); }; diff --git a/apt-private/private-cacheset.h b/apt-private/private-cacheset.h index 0eb22b788..518f179f3 100644 --- a/apt-private/private-cacheset.h +++ b/apt-private/private-cacheset.h @@ -81,13 +81,13 @@ class CacheSetHelperVirtuals: public APT::CacheSetHelper { public: APT::PackageSet virtualPkgs; - virtual pkgCache::VerIterator canNotGetVersion(enum CacheSetHelper::VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtual pkgCache::VerIterator canNotGetVersion(enum CacheSetHelper::VerSelector const select, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) APT_OVERRIDE { if (select == NEWEST || select == CANDIDATE || select == ALL) virtualPkgs.insert(Pkg); return CacheSetHelper::canNotGetVersion(select, Cache, Pkg); } - virtual void canNotFindVersion(enum CacheSetHelper::VerSelector const select, APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtual void canNotFindVersion(enum CacheSetHelper::VerSelector const select, APT::VersionContainerInterface * vci, pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) APT_OVERRIDE { if (select == NEWEST || select == CANDIDATE || select == ALL) virtualPkgs.insert(Pkg); return CacheSetHelper::canNotFindVersion(select, vci, Cache, Pkg); @@ -113,23 +113,23 @@ public: explicitlyNamed = true; } - virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) { + virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) APT_OVERRIDE { ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), Pkg.FullName(true).c_str(), pattern.c_str()); explicitlyNamed = false; } - virtual void showFnmatchSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) { + virtual void showFnmatchSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) APT_OVERRIDE { ioprintf(out, _("Note, selecting '%s' for glob '%s'\n"), Pkg.FullName(true).c_str(), pattern.c_str()); explicitlyNamed = false; } - virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) { + virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, std::string const &pattern) APT_OVERRIDE { ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"), Pkg.FullName(true).c_str(), pattern.c_str()); explicitlyNamed = false; } virtual void showSelectedVersion(pkgCache::PkgIterator const &/*Pkg*/, pkgCache::VerIterator const Ver, - std::string const &ver, bool const /*verIsRel*/) { + std::string const &ver, bool const /*verIsRel*/) APT_OVERRIDE { if (ver == Ver.VerStr()) return; selectedByRelease.push_back(make_pair(Ver, ver)); @@ -191,7 +191,7 @@ public: return false; } - virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) APT_OVERRIDE { APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::CANDIDATE); if (verset.empty() == false) return *(verset.begin()); @@ -202,7 +202,7 @@ public: return pkgCache::VerIterator(Cache, 0); } - virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) APT_OVERRIDE { if (Pkg->ProvidesList != 0) { APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, CacheSetHelper::NEWEST); diff --git a/apt-private/private-moo.h b/apt-private/private-moo.h index b8e1cfed6..bc8b3e7dd 100644 --- a/apt-private/private-moo.h +++ b/apt-private/private-moo.h @@ -1,6 +1,8 @@ #ifndef APT_PRIVATE_MOO_H #define APT_PRIVATE_MOO_H +#include + class CommandLine; APT_PUBLIC bool DoMoo(CommandLine &CmdL); diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc index d95c169cd..c0541d196 100644 --- a/cmdline/apt-cdrom.cc +++ b/cmdline/apt-cdrom.cc @@ -44,12 +44,12 @@ protected: OpTextProgress Progress; void Prompt(const char *Text); string PromptLine(const char *Text); - bool AskCdromName(string &name); + bool AskCdromName(string &name) APT_OVERRIDE; public: - virtual void Update(string text, int current); - virtual bool ChangeCdrom(); - virtual OpProgress* GetOpProgress(); + virtual void Update(string text, int current) APT_OVERRIDE; + virtual bool ChangeCdrom() APT_OVERRIDE; + virtual OpProgress* GetOpProgress() APT_OVERRIDE; }; void pkgCdromTextStatus::Prompt(const char *Text) diff --git a/cmdline/apt-extracttemplates.h b/cmdline/apt-extracttemplates.h index b129a2d51..91e385e70 100644 --- a/cmdline/apt-extracttemplates.h +++ b/cmdline/apt-extracttemplates.h @@ -26,9 +26,9 @@ class DebFile : public pkgDirStream public: explicit DebFile(const char *FileName); ~DebFile(); - bool DoItem(Item &I, int &fd); + bool DoItem(Item &I, int &fd) APT_OVERRIDE; bool Process(pkgDirStream::Item &I, const unsigned char *data, - unsigned long long size, unsigned long long pos); + unsigned long long size, unsigned long long pos) APT_OVERRIDE; bool Go(); bool ParseInfo(); diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 10d4b3cc5..9232e1505 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -572,7 +572,7 @@ static bool DoClean(CommandLine &) class LogCleaner : public pkgArchiveCleaner { protected: - virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) + virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St) APT_OVERRIDE { c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl; diff --git a/ftparchive/contents.h b/ftparchive/contents.h index 953d0d54b..bc691d473 100644 --- a/ftparchive/contents.h +++ b/ftparchive/contents.h @@ -81,7 +81,7 @@ class ContentsExtract : public pkgDirStream bool Read(debDebFile &Deb); - virtual bool DoItem(Item &Itm,int &Fd); + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; void Reset() {CurSize = 0;}; bool TakeContents(const void *Data,unsigned long long Length); void Add(GenContents &Contents,std::string const &Package); diff --git a/ftparchive/writer.h b/ftparchive/writer.h index b9c1f672a..98012beee 100644 --- a/ftparchive/writer.h +++ b/ftparchive/writer.h @@ -120,7 +120,7 @@ class PackagesWriter : public FTWScanner inline bool ReadOverride(string const &File) {return Over.ReadOverride(File);}; inline bool ReadExtraOverride(string const &File) {return Over.ReadExtraOverride(File);}; - virtual bool DoPackage(string FileName); + virtual bool DoPackage(string FileName) APT_OVERRIDE; PackagesWriter(FileFd * const Output, TranslationWriter * const TransWriter, string const &DB, string const &Overrides, @@ -142,7 +142,7 @@ class ContentsWriter : public FTWScanner string Prefix; bool DoPackage(string FileName,string Package); - virtual bool DoPackage(string FileName) + virtual bool DoPackage(string FileName) APT_OVERRIDE {return DoPackage(FileName,string());}; bool ReadFromPkgs(string const &PkgFile,string const &PkgCompress); @@ -171,7 +171,7 @@ class SourcesWriter : public FTWScanner string DirStrip; struct CacheDB::Stats &Stats; - virtual bool DoPackage(string FileName); + virtual bool DoPackage(string FileName) APT_OVERRIDE; SourcesWriter(FileFd * const Output, string const &DB,string const &BOverrides,string const &SOverrides, string const &ExtOverrides=string()); @@ -182,7 +182,7 @@ class ReleaseWriter : public FTWScanner { public: ReleaseWriter(FileFd * const Output, string const &DB); - virtual bool DoPackage(string FileName); + virtual bool DoPackage(string FileName) APT_OVERRIDE; void Finish(); // General options diff --git a/methods/cdrom.cc b/methods/cdrom.cc index 67265cfa3..d9ddecb6a 100644 --- a/methods/cdrom.cc +++ b/methods/cdrom.cc @@ -42,9 +42,9 @@ class CDROMMethod : public pkgAcqMethod bool IsCorrectCD(URI want, string MountPath, string& NewID); bool AutoDetectAndMount(const URI, string &NewID); - virtual bool Fetch(FetchItem *Itm); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; string GetID(string Name); - virtual void Exit(); + virtual void Exit() APT_OVERRIDE; public: diff --git a/methods/copy.cc b/methods/copy.cc index 4bdc15f75..0c9f322e6 100644 --- a/methods/copy.cc +++ b/methods/copy.cc @@ -27,7 +27,7 @@ class CopyMethod : public pkgAcqMethod { - virtual bool Fetch(FetchItem *Itm); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; void CalculateHashes(FetchItem const * const Itm, FetchResult &Res); public: diff --git a/methods/file.cc b/methods/file.cc index 5c76ec122..40e85bce5 100644 --- a/methods/file.cc +++ b/methods/file.cc @@ -30,7 +30,7 @@ class FileMethod : public pkgAcqMethod { - virtual bool Fetch(FetchItem *Itm); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; public: diff --git a/methods/ftp.cc b/methods/ftp.cc index 92d8573f1..5fee20f23 100644 --- a/methods/ftp.cc +++ b/methods/ftp.cc @@ -39,7 +39,6 @@ // Internet stuff #include -#include #include #include diff --git a/methods/ftp.h b/methods/ftp.h index 2efd28ec6..2c4e9f57a 100644 --- a/methods/ftp.h +++ b/methods/ftp.h @@ -10,8 +10,10 @@ #ifndef APT_FTP_H #define APT_FTP_H +#include #include +#include #include #include #include @@ -71,8 +73,8 @@ class FTPConn class FtpMethod : public pkgAcqMethod { - virtual bool Fetch(FetchItem *Itm); - virtual bool Configuration(std::string Message); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; + virtual bool Configuration(std::string Message) APT_OVERRIDE; FTPConn *Server; diff --git a/methods/gpgv.cc b/methods/gpgv.cc index d88a06789..490833d8c 100644 --- a/methods/gpgv.cc +++ b/methods/gpgv.cc @@ -46,8 +46,8 @@ class GPGVMethod : public pkgAcqMethod vector &NoPubKeySigners); protected: - virtual bool URIAcquire(std::string const &Message, FetchItem *Itm); - virtual bool Configuration(string Message); + virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE; + virtual bool Configuration(string Message) APT_OVERRIDE; public: GPGVMethod() : pkgAcqMethod("1.0",SingleInstance | SendConfig) {}; diff --git a/methods/gzip.cc b/methods/gzip.cc index 65519633c..637aae124 100644 --- a/methods/gzip.cc +++ b/methods/gzip.cc @@ -32,8 +32,8 @@ const char *Prog; class GzipMethod : public pkgAcqMethod { - virtual bool Fetch(FetchItem *Itm); - virtual bool Configuration(std::string Message); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; + virtual bool Configuration(std::string Message) APT_OVERRIDE; public: diff --git a/methods/http.h b/methods/http.h index e73871931..da6139b02 100644 --- a/methods/http.h +++ b/methods/http.h @@ -99,23 +99,23 @@ struct HttpServerState: public ServerState int ServerFd; protected: - virtual bool ReadHeaderLines(std::string &Data); - virtual bool LoadNextResponse(bool const ToFile, FileFd * const File); - virtual bool WriteResponse(std::string const &Data); + virtual bool ReadHeaderLines(std::string &Data) APT_OVERRIDE; + virtual bool LoadNextResponse(bool const ToFile, FileFd * const File) APT_OVERRIDE; + virtual bool WriteResponse(std::string const &Data) APT_OVERRIDE; public: - virtual void Reset() { ServerState::Reset(); ServerFd = -1; }; + virtual void Reset() APT_OVERRIDE { ServerState::Reset(); ServerFd = -1; }; - virtual bool RunData(FileFd * const File); + virtual bool RunData(FileFd * const File) APT_OVERRIDE; - virtual bool Open(); - virtual bool IsOpen(); - virtual bool Close(); - virtual bool InitHashes(HashStringList const &ExpectedHashes); - virtual Hashes * GetHashes(); - virtual bool Die(FileFd &File); - virtual bool Flush(FileFd * const File); - virtual bool Go(bool ToFile, FileFd * const File); + virtual bool Open() APT_OVERRIDE; + virtual bool IsOpen() APT_OVERRIDE; + virtual bool Close() APT_OVERRIDE; + virtual bool InitHashes(HashStringList const &ExpectedHashes) APT_OVERRIDE; + virtual Hashes * GetHashes() APT_OVERRIDE; + virtual bool Die(FileFd &File) APT_OVERRIDE; + virtual bool Flush(FileFd * const File) APT_OVERRIDE; + virtual bool Go(bool ToFile, FileFd * const File) APT_OVERRIDE; HttpServerState(URI Srv, HttpMethod *Owner); virtual ~HttpServerState() {Close();}; @@ -124,12 +124,12 @@ struct HttpServerState: public ServerState class HttpMethod : public ServerMethod { public: - virtual void SendReq(FetchItem *Itm); + virtual void SendReq(FetchItem *Itm) APT_OVERRIDE; - virtual bool Configuration(std::string Message); + virtual bool Configuration(std::string Message) APT_OVERRIDE; - virtual ServerState * CreateServerState(URI uri); - virtual void RotateDNS(); + virtual ServerState * CreateServerState(URI uri) APT_OVERRIDE; + virtual void RotateDNS() APT_OVERRIDE; protected: std::string AutoDetectProxyCmd; diff --git a/methods/https.h b/methods/https.h index 57fc292ee..29b20b921 100644 --- a/methods/https.h +++ b/methods/https.h @@ -32,23 +32,23 @@ class HttpsServerState : public ServerState Hashes * Hash; protected: - virtual bool ReadHeaderLines(std::string &/*Data*/) { return false; } - virtual bool LoadNextResponse(bool const /*ToFile*/, FileFd * const /*File*/) { return false; } + virtual bool ReadHeaderLines(std::string &/*Data*/) APT_OVERRIDE { return false; } + virtual bool LoadNextResponse(bool const /*ToFile*/, FileFd * const /*File*/) APT_OVERRIDE { return false; } public: - virtual bool WriteResponse(std::string const &/*Data*/) { return false; } + virtual bool WriteResponse(std::string const &/*Data*/) APT_OVERRIDE { return false; } /** \brief Transfer the data from the socket */ - virtual bool RunData(FileFd * const /*File*/) { return false; } + virtual bool RunData(FileFd * const /*File*/) APT_OVERRIDE { return false; } - virtual bool Open() { return false; } - virtual bool IsOpen() { return false; } - virtual bool Close() { return false; } - virtual bool InitHashes(HashStringList const &ExpectedHashes); - virtual Hashes * GetHashes(); - virtual bool Die(FileFd &/*File*/) { return false; } - virtual bool Flush(FileFd * const /*File*/) { return false; } - virtual bool Go(bool /*ToFile*/, FileFd * const /*File*/) { return false; } + virtual bool Open() APT_OVERRIDE { return false; } + virtual bool IsOpen() APT_OVERRIDE { return false; } + virtual bool Close() APT_OVERRIDE { return false; } + virtual bool InitHashes(HashStringList const &ExpectedHashes) APT_OVERRIDE; + virtual Hashes * GetHashes() APT_OVERRIDE; + virtual bool Die(FileFd &/*File*/) APT_OVERRIDE { return false; } + virtual bool Flush(FileFd * const /*File*/) APT_OVERRIDE { return false; } + virtual bool Go(bool /*ToFile*/, FileFd * const /*File*/) APT_OVERRIDE { return false; } HttpsServerState(URI Srv, HttpsMethod *Owner); virtual ~HttpsServerState() {Close();}; @@ -59,7 +59,7 @@ class HttpsMethod : public ServerMethod // minimum speed in bytes/se that triggers download timeout handling static const int DL_MIN_SPEED = 10; - virtual bool Fetch(FetchItem *); + virtual bool Fetch(FetchItem *) APT_OVERRIDE; static size_t parse_header(void *buffer, size_t size, size_t nmemb, void *userp); static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp); @@ -70,14 +70,14 @@ class HttpsMethod : public ServerMethod ServerState *Server; // Used by ServerMethods unused by https - virtual void SendReq(FetchItem *) { exit(42); } - virtual void RotateDNS() { exit(42); } + virtual void SendReq(FetchItem *) APT_OVERRIDE { exit(42); } + virtual void RotateDNS() APT_OVERRIDE { exit(42); } public: FileFd *File; - virtual bool Configuration(std::string Message); - virtual ServerState * CreateServerState(URI uri); + virtual bool Configuration(std::string Message) APT_OVERRIDE; + virtual ServerState * CreateServerState(URI uri) APT_OVERRIDE; using pkgAcqMethod::FetchResult; using pkgAcqMethod::FetchItem; diff --git a/methods/mirror.h b/methods/mirror.h index 6c0ce370e..425bea673 100644 --- a/methods/mirror.h +++ b/methods/mirror.h @@ -46,14 +46,14 @@ class MirrorMethod : public HttpMethod bool Clean(std::string dir); // we need to overwrite those to transform the url back - virtual void Fail(std::string Why, bool Transient = false); - virtual void URIStart(FetchResult &Res); - virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0); - virtual bool Configuration(std::string Message); + virtual void Fail(std::string Why, bool Transient = false) APT_OVERRIDE; + virtual void URIStart(FetchResult &Res) APT_OVERRIDE; + virtual void URIDone(FetchResult &Res,FetchResult *Alt = 0) APT_OVERRIDE; + virtual bool Configuration(std::string Message) APT_OVERRIDE; public: MirrorMethod(); - virtual bool Fetch(FetchItem *Itm); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; }; diff --git a/methods/rred.cc b/methods/rred.cc index 54123ab9c..91b6dda22 100644 --- a/methods/rred.cc +++ b/methods/rred.cc @@ -558,7 +558,7 @@ class RredMethod : public pkgAcqMethod { } protected: - virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) { + virtual bool URIAcquire(std::string const &Message, FetchItem *Itm) APT_OVERRIDE { Debug = _config->FindB("Debug::pkgAcquire::RRed", false); URI Get = Itm->Uri; std::string Path = Get.Host + Get.Path; // rred:/path - no host @@ -671,7 +671,7 @@ class RredMethod : public pkgAcqMethod { return true; } - bool Configuration(std::string Message) + bool Configuration(std::string Message) APT_OVERRIDE { if (pkgAcqMethod::Configuration(Message) == false) return false; diff --git a/methods/rsh.h b/methods/rsh.h index dd259e744..34492971c 100644 --- a/methods/rsh.h +++ b/methods/rsh.h @@ -56,8 +56,8 @@ class RSHConn class RSHMethod : public pkgAcqMethod { - virtual bool Fetch(FetchItem *Itm); - virtual bool Configuration(std::string Message); + virtual bool Fetch(FetchItem *Itm) APT_OVERRIDE; + virtual bool Configuration(std::string Message) APT_OVERRIDE; RSHConn *Server; diff --git a/methods/server.h b/methods/server.h index 8d7d33ee6..f9f6e9071 100644 --- a/methods/server.h +++ b/methods/server.h @@ -106,7 +106,7 @@ struct ServerState class ServerMethod : public pkgAcqMethod { protected: - virtual bool Fetch(FetchItem *); + virtual bool Fetch(FetchItem *) APT_OVERRIDE; ServerState *Server; std::string NextURI; @@ -146,7 +146,7 @@ class ServerMethod : public pkgAcqMethod static time_t FailTime; static APT_NORETURN void SigTerm(int); - virtual bool Configuration(std::string Message); + virtual bool Configuration(std::string Message) APT_OVERRIDE; virtual bool Flush() { return Server->Flush(File); }; int Loop(); diff --git a/test/interactive-helper/testdeb.cc b/test/interactive-helper/testdeb.cc index 6aae9f563..69e1ffe0b 100644 --- a/test/interactive-helper/testdeb.cc +++ b/test/interactive-helper/testdeb.cc @@ -13,7 +13,7 @@ class NullStream : public pkgDirStream { public: - virtual bool DoItem(Item &/*Itm*/, int &/*Fd*/) {return true;}; + virtual bool DoItem(Item &/*Itm*/, int &/*Fd*/) APT_OVERRIDE {return true;}; }; static bool Test(const char *File) diff --git a/test/libapt/acqprogress_test.cc b/test/libapt/acqprogress_test.cc index dc31423fc..50792528d 100644 --- a/test/libapt/acqprogress_test.cc +++ b/test/libapt/acqprogress_test.cc @@ -13,8 +13,8 @@ class TestItem: public pkgAcquire::Item public: TestItem(pkgAcquire * const Acq) : pkgAcquire::Item(Acq) {} - virtual std::string DescURI() const { return ""; } - virtual HashStringList GetExpectedHashes() const { return HashStringList(); } + virtual std::string DescURI() const APT_OVERRIDE { return ""; } + virtual HashStringList GetExpectedHashes() const APT_OVERRIDE { return HashStringList(); } }; diff --git a/test/libapt/indexcopytosourcelist_test.cc b/test/libapt/indexcopytosourcelist_test.cc index 1b0427564..2d07dba15 100644 --- a/test/libapt/indexcopytosourcelist_test.cc +++ b/test/libapt/indexcopytosourcelist_test.cc @@ -15,10 +15,10 @@ class NoCopy : public IndexCopy { IndexCopy::ConvertToSourceList(CD, Path); return Path; } - bool GetFile(std::string &/*Filename*/, unsigned long long &/*Size*/) { return false; } - bool RewriteEntry(FileFd & /*Target*/, std::string const &/*File*/) { return false; } - const char *GetFileName() { return NULL; } - const char *Type() { return NULL; } + bool GetFile(std::string &/*Filename*/, unsigned long long &/*Size*/) APT_OVERRIDE { return false; } + bool RewriteEntry(FileFd & /*Target*/, std::string const &/*File*/) APT_OVERRIDE { return false; } + const char *GetFileName() APT_OVERRIDE { return NULL; } + const char *Type() APT_OVERRIDE { return NULL; } }; -- cgit v1.2.3-70-g09d2 From a4b8112b19763cbd2c12b81d55bc7d43a591d610 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 9 Jul 2015 12:21:20 +0200 Subject: handle site-changing redirects as mirror changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Redirectors like httpredir.debian.org orchestra the download from multiple (hopefully close) mirrors while having only a single central sources.list entry by using redirects. This has the effect that the progress report always shows the source it started with, not the mirror it ends up fetching from, which is especially problematic for error reporting as having a report for a "Hashsum mismatch" for the redirector URI is next to useless as nobody knows which URI it was really fetched from (regardless of it coming from a user or via the report script) from this output alone. You would need to enable debug output and hope for the same situation to arise again… We hence reuse the UsedMirror field of the mirror:// method and detect redirects which change the site and declare this new site as the UsedMirrror (and adapt the description). The disadvantage is that there is no obvious mapping anymore (it is relatively easy to guess through with some experience) from progress lines to sources.list lines, so error messages need to take care to use the Target description (rather than current Item description) if they want to refer to the sources.list entry. --- apt-pkg/acquire-item.cc | 4 +- apt-pkg/acquire-worker.cc | 48 ++++++++++++++-------- .../test-handle-redirect-as-used-mirror-change | 23 +++++++++++ 3 files changed, 56 insertions(+), 19 deletions(-) create mode 100755 test/integration/test-handle-redirect-as-used-mirror-change (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 38f753cbb..8a566fea0 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -457,7 +457,6 @@ void pkgAcquire::Item::Failed(string const &Message,pkgAcquire::MethodConfig con { if(ErrorText.empty()) ErrorText = LookupTag(Message,"Message"); - UsedMirror = LookupTag(Message,"UsedMirror"); if (QueueCounter <= 1) { /* This indicates that the file is not available right now but might @@ -516,11 +515,10 @@ void pkgAcquire::Item::Start(string const &/*Message*/, unsigned long long const } /*}}}*/ // Acquire::Item::Done - Item downloaded OK /*{{{*/ -void pkgAcquire::Item::Done(string const &Message, HashStringList const &Hashes, +void pkgAcquire::Item::Done(string const &/*Message*/, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const /*Cnf*/) { // We just downloaded something.. - UsedMirror = LookupTag(Message,"UsedMirror"); if (FileSize == 0) { unsigned long long const downloadedSize = Hashes.FileSize(); diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index c0f93f9ce..dc03a8870 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -204,19 +204,22 @@ bool pkgAcquire::Worker::RunMessages() return _error->Error("Invalid message from method %s: %s",Access.c_str(),Message.c_str()); string URI = LookupTag(Message,"URI"); - pkgAcquire::Queue::QItem *Itm = 0; + pkgAcquire::Queue::QItem *Itm = NULL; if (URI.empty() == false) Itm = OwnerQ->FindItem(URI,this); - // update used mirror - string UsedMirror = LookupTag(Message,"UsedMirror", ""); - if (!UsedMirror.empty() && - Itm && - Itm->Description.find(" ") != string::npos) + if (Itm != NULL) { - Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); - // FIXME: will we need this as well? - //Itm->ShortDesc = UsedMirror; + // update used mirror + string UsedMirror = LookupTag(Message,"UsedMirror", ""); + if (UsedMirror.empty() == false) + { + for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) + (*O)->UsedMirror = UsedMirror; + + if (Itm->Description.find(" ") != string::npos) + Itm->Description.replace(0, Itm->Description.find(" "), UsedMirror); + } } // Determine the message number and dispatch @@ -248,17 +251,14 @@ bool pkgAcquire::Worker::RunMessages() break; } - string NewURI = LookupTag(Message,"New-URI",URI.c_str()); + std::string const NewURI = LookupTag(Message,"New-URI",URI.c_str()); Itm->URI = NewURI; ItemDone(); // Change the status so that it can be dequeued for (pkgAcquire::Queue::QItem::owner_iterator O = Itm->Owners.begin(); O != Itm->Owners.end(); ++O) - { - pkgAcquire::Item *Owner = *O; - Owner->Status = pkgAcquire::Item::StatIdle; - } + (*O)->Status = pkgAcquire::Item::StatIdle; // Mark the item as done (taking care of all queues) // and then put it in the main queue again std::vector const ItmOwners = Itm->Owners; @@ -267,12 +267,28 @@ bool pkgAcquire::Worker::RunMessages() for (pkgAcquire::Queue::QItem::owner_iterator O = ItmOwners.begin(); O != ItmOwners.end(); ++O) { pkgAcquire::Item *Owner = *O; - pkgAcquire::ItemDesc desc = Owner->GetItemDesc(); + pkgAcquire::ItemDesc &desc = Owner->GetItemDesc(); + // if we change site, treat it as a mirror change + if (URI::SiteOnly(NewURI) != URI::SiteOnly(desc.URI)) + { + std::string const OldSite = desc.Description.substr(0, desc.Description.find(" ")); + if (likely(APT::String::Startswith(desc.URI, OldSite))) + { + std::string const OldExtra = desc.URI.substr(OldSite.length() + 1); + if (likely(APT::String::Endswith(NewURI, OldExtra))) + { + std::string const NewSite = NewURI.substr(0, NewURI.length() - OldExtra.length()); + Owner->UsedMirror = URI::ArchiveOnly(NewSite); + if (desc.Description.find(" ") != string::npos) + desc.Description.replace(0, desc.Description.find(" "), Owner->UsedMirror); + } + } + } desc.URI = NewURI; OwnerQ->Owner->Enqueue(desc); if (Log != 0) - Log->Done(Owner->GetItemDesc()); + Log->Done(desc); } break; } diff --git a/test/integration/test-handle-redirect-as-used-mirror-change b/test/integration/test-handle-redirect-as-used-mirror-change new file mode 100755 index 000000000..08a39a5e6 --- /dev/null +++ b/test/integration/test-handle-redirect-as-used-mirror-change @@ -0,0 +1,23 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' +configcompression '.' 'gz' + +buildsimplenativepackage 'unrelated' 'all' '0.5~squeeze1' 'unstable' + +setupaptarchive --no-update +changetowebserver -o 'aptwebserver::redirect::replace::/redirectme/=http://0.0.0.0:8080/' +rewritesourceslist 'http://localhost:8080/redirectme' + +testsuccessequal "Get:1 http://0.0.0.0:8080 unstable InRelease [$(stat -c %s aptarchive/dists/unstable/InRelease) B] +Get:2 http://0.0.0.0:8080 unstable/main Sources [$(stat -c %s aptarchive/dists/unstable/main/source/Sources.gz) B] +Get:3 http://0.0.0.0:8080 unstable/main amd64 Packages [$(stat -c %s aptarchive/dists/unstable/main/binary-amd64/Packages.gz) B] +Get:4 http://0.0.0.0:8080 unstable/main Translation-en [$(stat -c %s aptarchive/dists/unstable/main/i18n/Translation-en.gz) B] +Reading package lists..." aptget update + +testsuccessequal 'Hit:1 http://0.0.0.0:8080 unstable InRelease +Reading package lists...' aptget update -- cgit v1.2.3-70-g09d2 From c2a4a8dded2dfb56dbcab9689b6cb4b96c9999b6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 10 Jul 2015 00:07:37 +0200 Subject: rename 'apt-get files' to 'apt-get indextargets' 'files' is a bit too generic as a name for a command usually only used programmatically (if at all) by developers, so instead of "wasting" this generic name for this we use "indextargets" which is actually the name of the datastructure the displayed data is stored in. Along with this rename the config options are renamed accordingly. --- apt-pkg/deb/debmetaindex.cc | 10 +++---- apt-pkg/init.cc | 34 +++++++++++----------- apt-private/private-cmndline.cc | 6 ++-- cmdline/apt-get.cc | 10 +++---- doc/acquire-additional-files.txt | 18 +++++++----- doc/apt-get.8.xml | 24 +++++++-------- doc/sources.list.5.xml | 2 +- .../test-acquire-same-repository-multiple-times | 2 +- test/integration/test-apt-acquire-additional-files | 26 ++++++++--------- .../integration/test-apt-get-update-unauth-warning | 2 +- .../test-sourceslist-lang-plusminus-options | 4 +-- 11 files changed, 70 insertions(+), 68 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 46a7181fc..480317db3 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -128,12 +128,12 @@ static void GetIndexTargetsFor(char const * const Type, std::string const &URI, { for (std::vector::const_iterator T = E->Targets.begin(); T != E->Targets.end(); ++T) { -#define APT_T_CONFIG(X) _config->Find(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::" + (X)) +#define APT_T_CONFIG(X) _config->Find(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::" + (X)) std::string const tplMetaKey = APT_T_CONFIG(flatArchive ? "flatMetaKey" : "MetaKey"); std::string const tplShortDesc = APT_T_CONFIG("ShortDescription"); - std::string const tplLongDesc = APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); - bool const IsOptional = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::Optional", true); - bool const KeepCompressed = _config->FindB(std::string("APT::Acquire::Targets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); + std::string const tplLongDesc = "$(SITE) " + APT_T_CONFIG(flatArchive ? "flatDescription" : "Description"); + bool const IsOptional = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::Optional", true); + bool const KeepCompressed = _config->FindB(std::string("Acquire::IndexTargets::") + Type + "::" + *T + "::KeepCompressed", GzipIndex); #undef APT_T_CONFIG if (tplMetaKey.empty()) continue; @@ -721,7 +721,7 @@ class APT_HIDDEN debSLTypeDebian : public pkgSourceList::Type /*{{{*/ Deb->AddComponent( IsSrc, Section, - parsePlusMinusOptions("target", Options, _config->FindVector(std::string("APT::Acquire::Targets::") + Name, "", true)), + parsePlusMinusOptions("target", Options, _config->FindVector(std::string("Acquire::IndexTargets::") + Name, "", true)), parsePlusMinusOptions("arch", Options, APT::Configuration::getArchitectures()), parsePlusMinusOptions("lang", Options, APT::Configuration::getLanguages(true)) ); diff --git a/apt-pkg/init.cc b/apt-pkg/init.cc index 1fbb035f7..858bcec43 100644 --- a/apt-pkg/init.cc +++ b/apt-pkg/init.cc @@ -99,23 +99,23 @@ bool pkgInitConfig(Configuration &Cnf) // The default user we drop to in the methods Cnf.CndSet("APT::Sandbox::User", "_apt"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatMetaKey", "Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::ShortDescription", "Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Description", "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::flatDescription", "$(SITE) $(RELEASE) Packages"); - Cnf.CndSet("APT::Acquire::Targets::deb::Packages::Optional", false); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb::Translations::flatDescription", "$(SITE) $(RELEASE) Translation-$(LANGUAGE)"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatMetaKey", "Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::ShortDescription", "Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Description", "$(SITE) $(RELEASE)/$(COMPONENT) Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::flatDescription", "$(SITE) $(RELEASE) Sources"); - Cnf.CndSet("APT::Acquire::Targets::deb-src::Sources::Optional", false); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::MetaKey", "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatMetaKey", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::ShortDescription", "Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Description", "$(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::flatDescription", "$(RELEASE) Packages"); + Cnf.CndSet("Acquire::IndexTargets::deb::Packages::Optional", false); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::MetaKey", "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatMetaKey", "$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::ShortDescription", "Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::Description", "$(RELEASE)/$(COMPONENT) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb::Translations::flatDescription", "$(RELEASE) Translation-$(LANGUAGE)"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::MetaKey", "$(COMPONENT)/source/Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatMetaKey", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::ShortDescription", "Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Description", "$(RELEASE)/$(COMPONENT) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::flatDescription", "$(RELEASE) Sources"); + Cnf.CndSet("Acquire::IndexTargets::deb-src::Sources::Optional", false); Cnf.CndSet("Acquire::Changelogs::URI::Origin::Debian", "http://metadata.ftp-master.debian.org/changelogs/CHANGEPATH_changelog"); Cnf.CndSet("Acquire::Changelogs::URI::Origin::Ubuntu", "http://changelogs.ubuntu.com/changelogs/pool/CHANGEPATH/changelog"); diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 11e88b1e7..71dceb559 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -163,10 +163,10 @@ static bool addArgumentsAPTGet(std::vector &Args, char const // once sbuild is fixed, this option can be removed addArg('f', "fix-broken", "APT::Get::Fix-Broken", 0); } - else if (CmdMatches("files")) + else if (CmdMatches("indextargets")) { - addArg(0,"format","APT::Get::Files::Format", CommandLine::HasArg); - addArg(0,"release-info","APT::Get::Files::ReleaseInfo", 0); + addArg(0,"format","APT::Get::IndexTargets::Format", CommandLine::HasArg); + addArg(0,"release-info","APT::Get::IndexTargets::ReleaseInfo", 0); } else if (CmdMatches("clean", "autoclean", "check", "download", "changelog") || CmdMatches("markauto", "unmarkauto")) // deprecated commands diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 9232e1505..a69f5418a 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1468,7 +1468,7 @@ static bool DoChangelog(CommandLine &CmdL) return true; } /*}}}*/ -// DoFiles - Lists all IndexTargets /*{{{*/ +// DoIndexTargets - Lists all IndexTargets /*{{{*/ static std::string format_key(std::string key) { // deb822 is case-insensitive, but the human eye prefers candy @@ -1484,7 +1484,7 @@ static std::string format_key(std::string key) } return key; } -static bool DoFiles(CommandLine &CmdL) +static bool DoIndexTargets(CommandLine &CmdL) { pkgCacheFile CacheFile; pkgSourceList *SrcList = CacheFile.GetSourceList(); @@ -1492,8 +1492,8 @@ static bool DoFiles(CommandLine &CmdL) if (SrcList == NULL) return false; - std::string const Format = _config->Find("APT::Get::Files::Format"); - bool const ReleaseInfo = _config->FindB("APT::Get::Files::ReleaseInfo", true); + std::string const Format = _config->Find("APT::Get::IndexTargets::Format"); + bool const ReleaseInfo = _config->FindB("APT::Get::IndexTargets::ReleaseInfo", true); bool Filtered = CmdL.FileSize() > 1; for (pkgSourceList::const_iterator S = SrcList->begin(); S != SrcList->end(); ++S) { @@ -1687,7 +1687,7 @@ int main(int argc,const char *argv[]) /*{{{*/ {"source",&DoSource}, {"download",&DoDownload}, {"changelog",&DoChangelog}, - {"files",&DoFiles}, + {"indextargets",&DoIndexTargets}, {"moo",&DoMoo}, {"help",&ShowHelp}, {0,0}}; diff --git a/doc/acquire-additional-files.txt b/doc/acquire-additional-files.txt index f9a16318d..71ce7b0cb 100644 --- a/doc/acquire-additional-files.txt +++ b/doc/acquire-additional-files.txt @@ -26,7 +26,7 @@ they would be written in a configuration file the configuration instructing the Acquire system to download the Packages files would look like this (see also apt.conf(5) manpage for configuration file syntax): - APT::Acquire::Targets::deb::Packages { + Acquire::IndexTargets::deb::Packages { MetaKey "$(COMPONENT)/binary-$(ARCHITECTURE)/Packages"; ShortDescription "Packages"; Description "$(SITE) $(RELEASE)/$(COMPONENT) $(ARCHITECTURE) Packages"; @@ -38,7 +38,7 @@ like this (see also apt.conf(5) manpage for configuration file syntax): }; All files which should be downloaded (nicknamed 'Targets') are mentioned -below the APT::Acquire::Targets scope. 'deb' is here the type of the +below the Acquire::IndexTargets scope. 'deb' is here the type of the sources.list entry the file should be acquired for. The only other supported value is hence 'deb-src'. Beware: You can't specify multiple types here and you can't download the same (evaluated) MetaKey from @@ -47,7 +47,7 @@ multiple types! After the type you can pick any valid and unique string which preferable refers to the file it downloads (In the example we picked 'Packages'). This string is used as identifier for the target class and accessible as -'Created-By' e.g. in the "apt-get files" output as detailed below. +'Created-By' e.g. in the "apt-get indextargets" output as detailed below. All targets have three main properties you can define: * MetaKey: The identifier of the file to be downloaded as used in the @@ -92,7 +92,7 @@ NO properties have to be set to enable this. The stanzas for Translation-* files as well as for Sources files would look like this: -APT::Acquire::Targets { +Acquire::IndexTargets { deb::Translations { MetaKey "$(COMPONENT)/i18n/Translation-$(LANGUAGE)"; ShortDescription "Translation-$(LANGUAGE)"; @@ -152,7 +152,7 @@ design so multiple applications can download and use the same file rather than each and every one of them potentially downloads and uses its own copy somewhere on disk. -"apt-get files" can be used to get the location as well as other +"apt-get indextargets" can be used to get the location as well as other information about all files downloaded (aka: you will see Packages, Sources and Translation-* files here as well). Provide a line of the default output format as parameter to filter out all entries which do @@ -161,12 +161,16 @@ own output style. The variables are what you see in the output, just all uppercase and wrapped in $(), as in the configuration file. To get all the filenames of all Translation-en files you can e.g. call: - apt-get files --format '$(FILENAME)' "Created-By: Translations" "Language: en" + apt-get indextargets --format '$(FILENAME)' "Created-By: Translations" "Language: en" + +The line-based filtering and the formating is rather crude and feature- +less by design, so it is recommend to use dedicated and more powerful +tools like 'grep-dctrl'. Accessing this information via libapt is done by reading the sources.lists (pkgSourceList), iterating over the metaIndex objects this creates and calling GetIndexTargets() on them. See the sourcecode of -"apt-get files" for a complete example. +"apt-get indextargets" for a complete example. Note that by default targets are not listed if they weren't downloaded. If you want to see all targets, you can use the --no-release-info, which diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index b0fe390df..81a9036c4 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -239,9 +239,9 @@ - + Displays by default a deb822 formatted listing of - information about all data files apt-get + information about all data files (aka index targets) apt-get update would download. Supports a option to modify the output format as well as accepts lines of the default output to filter the records @@ -327,17 +327,15 @@ - No action; perform a simulation of events that would occur but do not - actually change the system. - Configuration Item: APT::Get::Simulate. - - Simulated runs performed as a user will automatically deactivate locking - (Debug::NoLocking), and if the option - APT::Get::Show-User-Simulation-Note is set - (as it is by default) a notice will also be displayed indicating that - this is only a simulation. Runs performed as root do not trigger either - NoLocking or the notice - superusers should know what they are doing - without further warnings from apt-get. + No action; perform a simulation of events that would occur + based on the current system state but do not actually change the + system. Locking will be disabled () + so the system state could change while apt-get is + running. Simulations can also be executed by non-root users which might + not have read access to all apt configuration distorting the simulation. + A notice expressing this warning is also shown by default for non-root + users (). + Configuration Item: APT::Get::Simulate. Simulated runs print out a series of lines, each representing a dpkg operation: configure (Conf), remove (Remv) diff --git a/doc/sources.list.5.xml b/doc/sources.list.5.xml index 12a7773f5..3bc8a94ac 100644 --- a/doc/sources.list.5.xml +++ b/doc/sources.list.5.xml @@ -221,7 +221,7 @@ deb-src [ option1=value1 option2=value2 ] uri suite [component1] [component2] [. () is a multivalue option defining which download targets apt will try to acquire from this source. If not specified, the default set is defined by the - configuration scope. + configuration scope. diff --git a/test/integration/test-acquire-same-repository-multiple-times b/test/integration/test-acquire-same-repository-multiple-times index ad9cd6d7e..d3cb46c14 100755 --- a/test/integration/test-acquire-same-repository-multiple-times +++ b/test/integration/test-acquire-same-repository-multiple-times @@ -43,7 +43,7 @@ tworepos() { testsuccess --nomsg aptget update -o Debug::pkgAcquire::Worker=1 cp rootdir/tmp/testsuccess.output download.log #cat download.log - aptget files --format '$(FILENAME)' --no-release-info | sort > file.lst + aptget indextargets --format '$(FILENAME)' --no-release-info | sort > file.lst testequal "$(find $(readlink -f ./rootdir/var/lib/apt/lists) -name '*_dists_*' \( ! -name '*InRelease' \) -type f | sort)" cat file.lst testsuccess aptcache policy testequal "foo: diff --git a/test/integration/test-apt-acquire-additional-files b/test/integration/test-apt-acquire-additional-files index fecdf30bf..ee7908a2d 100755 --- a/test/integration/test-apt-acquire-additional-files +++ b/test/integration/test-apt-acquire-additional-files @@ -30,18 +30,18 @@ Reading package lists..." aptget update testempty find rootdir/var/lib/apt/lists -name '*Contents*' cat > rootdir/etc/apt/apt.conf.d/content-target.conf <> rootdir/etc/apt/apt.conf.d/content-target.conf +echo 'Acquire::IndexTargets::deb::Contents::KeepCompressed "true";' >> rootdir/etc/apt/apt.conf.d/content-target.conf testsuccessequal "Hit:1 http://localhost:8080 unstable InRelease Get:2 http://localhost:8080 unstable/main amd64 Contents [$(stat -c%s aptarchive/dists/unstable/main/Contents-amd64.gz) B] Reading package lists..." aptget update testequal 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' find rootdir/var/lib/apt/lists -name '*Contents*' -testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget files --format '$(FILENAME)' 'Created-By: Contents' +testequal "$(readlink -f ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz)" aptget indextargets --format '$(FILENAME)' 'Created-By: Contents' testsuccess cmp 'rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz' 'aptarchive/dists/unstable/main/Contents-amd64.gz' rm ./rootdir/var/lib/apt/lists/localhost:8080_dists_unstable_main_Contents-amd64.gz -testempty aptget files --format '$(FILENAME)' 'Created-By: Contents' +testempty aptget indextargets --format '$(FILENAME)' 'Created-By: Contents' # and no automatic uncompress based on the name please, # only if we downloaded a compressed file, but target was uncompressed cat > rootdir/etc/apt/apt.conf.d/content-target.conf < gotlangs.list + aptget indextargets --no-release-info 'Created-By: Translations' "$@" --format '$(LANGUAGE)' | sort -u > gotlangs.list if [ -z "$LANGS" ]; then echo -n | tr ',' '\n' | sort | checkdiff - gotlangs.list && msgpass || msgfail else @@ -44,7 +44,7 @@ testlangs 'lang=de_DE' 'de_DE' echo 'deb [lang=none] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list testlangs 'lang=none' '' -testequal 'amd64' aptget files --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)' +testequal 'amd64' aptget indextargets --no-release-info 'Created-By: Packages' --format '$(ARCHITECTURE)' echo 'deb [lang+=pt] http://example.org/debian stable rocks' > rootdir/etc/apt/sources.list testlangs 'lang+=pt' 'en,de,de_DE,pt' -- cgit v1.2.3-70-g09d2 From a0c19a217ca2ed38ae0ecb4b8d2d4f8c4e53289f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 12 Jul 2015 13:41:12 +0200 Subject: implement a more generic ShowList method apt-get is displaying various lists of package names, which until now it was building as a string before passing it to ShowList, which inserted linebreaks at fitting points and showed a title if needed, but it never really understood what it was working with. With the help of C++11 the new generic knows not only what it works with, but generates the list on the fly rather than asking for it and potentially discarding parts of the input (= the non-default verbose display). It also doubles as a test for how usable the CacheSets are with C++11. (Not all callers are adapted yet.) Git-Dch: Ignore --- apt-pkg/cacheset.h | 99 ++++++-- apt-private/private-cachefile.cc | 61 ++--- apt-private/private-cachefile.h | 59 +++-- apt-private/private-cacheset.h | 16 +- apt-private/private-install.cc | 69 +++--- apt-private/private-output.cc | 263 ++++++++++----------- apt-private/private-output.h | 67 +++++- po/apt-all.pot | 2 +- po/ar.po | 4 +- po/ast.po | 4 +- po/bg.po | 4 +- po/bs.po | 2 +- po/ca.po | 4 +- po/cs.po | 4 +- po/cy.po | 4 +- po/da.po | 4 +- po/de.po | 4 +- po/dz.po | 2 +- po/el.po | 4 +- po/es.po | 4 +- po/eu.po | 4 +- po/fi.po | 4 +- po/fr.po | 4 +- po/gl.po | 4 +- po/he.po | 4 +- po/hu.po | 4 +- po/it.po | 4 +- po/ja.po | 4 +- po/km.po | 4 +- po/ko.po | 4 +- po/ku.po | 2 +- po/lt.po | 4 +- po/mr.po | 2 +- po/nb.po | 4 +- po/ne.po | 4 +- po/nl.po | 4 +- po/nn.po | 4 +- po/pl.po | 4 +- po/pt.po | 4 +- po/pt_BR.po | 4 +- po/ro.po | 4 +- po/ru.po | 4 +- po/sk.po | 4 +- po/sl.po | 4 +- po/sv.po | 4 +- po/th.po | 4 +- po/tl.po | 4 +- po/tr.po | 4 +- po/uk.po | 4 +- po/vi.po | 4 +- po/zh_CN.po | 4 +- po/zh_TW.po | 4 +- test/integration/test-apt-get-autoremove | 26 ++ .../test-bug-596498-trusted-unsigned-repo | 9 + .../integration/test-bug-604222-new-and-autoremove | 26 ++ .../test-bug-613420-new-garbage-dependency | 16 ++ .../test-bug-675449-essential-are-protected | 14 ++ test/integration/test-kernel-helper-autoremove | 16 ++ 58 files changed, 570 insertions(+), 341 deletions(-) (limited to 'test') diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 03f3605a1..0b9b9441c 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -17,6 +17,7 @@ #include #endif #include +#include #include #include #include @@ -210,16 +211,15 @@ private: void * const d; }; /*}}}*/ // Iterator templates for our Containers /*{{{*/ -template class Container_iterator_base : +template class Container_iterator_base : public std::iterator::iterator_category, container_iterator>, public Interface::iterator_base { protected: container_iterator _iter; - inline virtual typename Container::value_type getType(void) const APT_OVERRIDE { return *_iter; } public: explicit Container_iterator_base(container_iterator i) : _iter(i) {} - inline typename Container::value_type operator*(void) const { return *_iter; } + inline container_value operator*(void) const { return this->getType(); } operator container_iterator(void) const { return _iter; } inline iterator_type& operator++() { ++_iter; return static_cast(*this); } inline iterator_type operator++(int) { iterator_type tmp(*this); operator++(); return tmp; } @@ -241,48 +241,56 @@ public: friend Master; }; template class Container_const_iterator : - public Container_iterator_base, typename Container::const_iterator> + public Container_iterator_base, typename Container::const_iterator, typename Container::value_type> { typedef Container_const_iterator iterator_type; typedef typename Container::const_iterator container_iterator; public: explicit Container_const_iterator(container_iterator i) : - Container_iterator_base(i) {} + Container_iterator_base(i) {} + + inline virtual typename Container::value_type getType(void) const APT_OVERRIDE { return *this->_iter; } }; template class Container_iterator : - public Container_iterator_base, typename Container::iterator> + public Container_iterator_base, typename Container::iterator, typename Container::value_type> { typedef Container_iterator iterator_type; typedef typename Container::iterator container_iterator; public: explicit Container_iterator(container_iterator i) : - Container_iterator_base(i) {} + Container_iterator_base(i) {} operator typename Master::const_iterator() { return typename Master::const_iterator(this->_iter); } inline iterator_type& operator=(iterator_type const &i) { this->_iter = i._iter; return static_cast(*this); } inline iterator_type& operator=(container_iterator const &i) { this->_iter = i; return static_cast(*this); } + + inline virtual typename Container::value_type getType(void) const APT_OVERRIDE { return *this->_iter; } }; template class Container_const_reverse_iterator : - public Container_iterator_base, typename Container::const_reverse_iterator> + public Container_iterator_base, typename Container::const_reverse_iterator, typename Container::value_type> { typedef Container_const_reverse_iterator iterator_type; typedef typename Container::const_reverse_iterator container_iterator; public: explicit Container_const_reverse_iterator(container_iterator i) : - Container_iterator_base(i) {} + Container_iterator_base(i) {} + + inline virtual typename Container::value_type getType(void) const APT_OVERRIDE { return *this->_iter; } }; template class Container_reverse_iterator : - public Container_iterator_base, typename Container::reverse_iterator> + public Container_iterator_base, typename Container::reverse_iterator, typename Container::value_type> { typedef Container_reverse_iterator iterator_type; typedef typename Container::reverse_iterator container_iterator; public: explicit Container_reverse_iterator(container_iterator i) : - Container_iterator_base(i) {} + Container_iterator_base(i) {} operator typename Master::const_iterator() { return typename Master::const_iterator(this->_iter); } inline iterator_type& operator=(iterator_type const &i) { this->_iter = i._iter; return static_cast(*this); } inline iterator_type& operator=(container_iterator const &i) { this->_iter = i; return static_cast(*this); } + + inline virtual typename Container::value_type getType(void) const APT_OVERRIDE { return *this->_iter; } }; /*}}}*/ class PackageContainerInterface { /*{{{*/ @@ -583,6 +591,10 @@ template<> template void PackageContainer template void PackageContainer >::insert(PackageContainer const &pkgcont) { + for (typename PackageContainer::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) + _cont.push_back(*p); +} template<> template void PackageContainer >::insert(PackageContainer const &pkgcont) { for (typename PackageContainer::const_iterator p = pkgcont.begin(); p != pkgcont.end(); ++p) _cont.push_back(*p); @@ -603,6 +615,12 @@ template<> inline bool PackageContainer return true; } #endif +template<> inline bool PackageContainer >::insert(pkgCache::PkgIterator const &P) { + if (P.end() == true) + return false; + _cont.push_back(P); + return true; +} template<> inline bool PackageContainer >::insert(pkgCache::PkgIterator const &P) { if (P.end() == true) return false; @@ -619,6 +637,10 @@ template<> inline void PackageContainer _cont.push_front(*p); } #endif +template<> inline void PackageContainer >::insert(const_iterator begin, const_iterator end) { + for (const_iterator p = begin; p != end; ++p) + _cont.push_back(*p); +} template<> inline void PackageContainer >::insert(const_iterator begin, const_iterator end) { for (const_iterator p = begin; p != end; ++p) _cont.push_back(*p); @@ -647,6 +669,10 @@ template<> template inline bool PackageContainer template inline bool PackageContainer >::sort(Compare Comp) { + std::sort(_cont.begin(), _cont.end(), Comp); + return true; +} /*}}}*/ // class PackageUniverse - pkgCache as PackageContainerInterface /*{{{*/ @@ -657,22 +683,35 @@ template<> template inline bool PackageContainer + { + protected: + inline virtual pkgCache::PkgIterator getType(void) const APT_OVERRIDE + { + return _iter; + } + public: + explicit const_iterator(pkgCache::PkgIterator i): + Container_iterator_base(i) {} + + }; + typedef const_iterator iterator; APT_PUBLIC bool empty() const APT_OVERRIDE { return false; } APT_PUBLIC size_t size() const APT_OVERRIDE { return _cont->Head().PackageCount; } - APT_PUBLIC const_iterator begin() const { return _cont->PkgBegin(); } - APT_PUBLIC const_iterator end() const { return _cont->PkgEnd(); } - APT_PUBLIC const_iterator cbegin() const { return _cont->PkgBegin(); } - APT_PUBLIC const_iterator cend() const { return _cont->PkgEnd(); } - APT_PUBLIC iterator begin() { return _cont->PkgBegin(); } - APT_PUBLIC iterator end() { return _cont->PkgEnd(); } + APT_PUBLIC const_iterator begin() const { return const_iterator(_cont->PkgBegin()); } + APT_PUBLIC const_iterator end() const { return const_iterator(_cont->PkgEnd()); } + APT_PUBLIC const_iterator cbegin() const { return const_iterator(_cont->PkgBegin()); } + APT_PUBLIC const_iterator cend() const { return const_iterator(_cont->PkgEnd()); } + APT_PUBLIC iterator begin() { return iterator(_cont->PkgBegin()); } + APT_PUBLIC iterator end() { return iterator(_cont->PkgEnd()); } + + APT_PUBLIC pkgCache * data() const { return _cont; } explicit APT_PUBLIC PackageUniverse(pkgCache * const Owner); APT_PUBLIC virtual ~PackageUniverse(); @@ -693,6 +732,7 @@ typedef PackageContainer > PackageUnor typedef PackageContainer > PackageForwardList; #endif typedef PackageContainer > PackageList; +typedef PackageContainer > PackageDeque; typedef PackageContainer > PackageVector; class VersionContainerInterface { /*{{{*/ @@ -1059,6 +1099,10 @@ template<> template void VersionContainer template void VersionContainer >::insert(VersionContainer const &vercont) { + for (typename VersionContainer::const_iterator v = vercont.begin(); v != vercont.end(); ++v) + _cont.push_back(*v); +} template<> template void VersionContainer >::insert(VersionContainer const &vercont) { for (typename VersionContainer::const_iterator v = vercont.begin(); v != vercont.end(); ++v) _cont.push_back(*v); @@ -1079,6 +1123,12 @@ template<> inline bool VersionContainer return true; } #endif +template<> inline bool VersionContainer >::insert(pkgCache::VerIterator const &V) { + if (V.end() == true) + return false; + _cont.push_back(V); + return true; +} template<> inline bool VersionContainer >::insert(pkgCache::VerIterator const &V) { if (V.end() == true) return false; @@ -1095,6 +1145,10 @@ template<> inline void VersionContainer _cont.push_front(*v); } #endif +template<> inline void VersionContainer >::insert(const_iterator begin, const_iterator end) { + for (const_iterator v = begin; v != end; ++v) + _cont.push_back(*v); +} template<> inline void VersionContainer >::insert(const_iterator begin, const_iterator end) { for (const_iterator v = begin; v != end; ++v) _cont.push_back(*v); @@ -1123,6 +1177,10 @@ template<> template inline bool VersionContainer template inline bool VersionContainer >::sort(Compare Comp) { + std::sort(_cont.begin(), _cont.end(), Comp); + return true; +} /*}}}*/ typedef VersionContainer > VersionSet; @@ -1131,6 +1189,7 @@ typedef VersionContainer > VersionUnor typedef VersionContainer > VersionForwardList; #endif typedef VersionContainer > VersionList; +typedef VersionContainer > VersionDeque; typedef VersionContainer > VersionVector; } #endif diff --git a/apt-private/private-cachefile.cc b/apt-private/private-cachefile.cc index 29e665245..2b2050684 100644 --- a/apt-private/private-cachefile.cc +++ b/apt-private/private-cachefile.cc @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -21,39 +21,40 @@ using namespace std; -// CacheFile::NameComp - QSort compare by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache *CacheFile::SortCache = 0; -int CacheFile::NameComp(const void *a,const void *b) +static bool SortPackagesByName(pkgCache * const Owner, + map_pointer_t const A, map_pointer_t const B) { - if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0) - return *(pkgCache::Package **)a - *(pkgCache::Package **)b; - - const pkgCache::Package &A = **(pkgCache::Package **)a; - const pkgCache::Package &B = **(pkgCache::Package **)b; - const pkgCache::Group * const GA = SortCache->GrpP + A.Group; - const pkgCache::Group * const GB = SortCache->GrpP + B.Group; - - return strcmp(SortCache->StrP + GA->Name,SortCache->StrP + GB->Name); + if (A == 0) + return false; + if (B == 0 || A == B) + return true; + pkgCache::Group const * const GA = Owner->GrpP + A; + pkgCache::Group const * const GB = Owner->GrpP + B; + return strcmp(Owner->StrP + GA->Name, Owner->StrP + GB->Name) <= 0; } - /*}}}*/ -// CacheFile::Sort - Sort by name /*{{{*/ -// --------------------------------------------------------------------- -/* */ -void CacheFile::Sort() +SortedPackageUniverse::SortedPackageUniverse(CacheFile &Cache) : + PackageUniverse{Cache}, List{Cache.UniverseList} { - delete [] List; - List = new pkgCache::Package *[Cache->Head().PackageCount]; - memset(List,0,sizeof(*List)*Cache->Head().PackageCount); - pkgCache::PkgIterator I = Cache->PkgBegin(); - for (;I.end() != true; ++I) - List[I->ID] = I; - - SortCache = *this; - qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp); } - /*}}}*/ +void SortedPackageUniverse::LazyInit() const +{ + if (List.empty() == false) + return; + pkgCache * const Owner = data(); + // In Multi-Arch systems Grps are easier to sort than Pkgs + std::vector GrpList; + List.reserve(Owner->Head().GroupCount); + for (pkgCache::GrpIterator I{Owner->GrpBegin()}; I.end() != true; ++I) + GrpList.emplace_back(I - Owner->GrpP); + std::stable_sort(GrpList.begin(), GrpList.end(), std::bind( &SortPackagesByName, Owner, std::placeholders::_1, std::placeholders::_2 )); + List.reserve(Owner->Head().PackageCount); + for (auto G : GrpList) + { + pkgCache::GrpIterator const Grp(*Owner, Owner->GrpP + G); + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() != true; P = Grp.NextPkg(P)) + List.emplace_back(P - Owner->PkgP); + } +} // CacheFile::CheckDeps - Open the cache file /*{{{*/ // --------------------------------------------------------------------- /* This routine generates the caches and then opens the dependency cache diff --git a/apt-private/private-cachefile.h b/apt-private/private-cachefile.h index 1fddabfbd..4a68d9733 100644 --- a/apt-private/private-cachefile.h +++ b/apt-private/private-cachefile.h @@ -7,12 +7,13 @@ #include #include #include +#include + #include -// FIXME: we need to find a way to export this +// FIXME: we need to find a way to export this class APT_PUBLIC SourceList : public pkgSourceList { - public: // Add custom metaIndex (e.g. local files) void AddMetaIndex(metaIndex *mi) { @@ -22,17 +23,11 @@ class APT_PUBLIC SourceList : public pkgSourceList }; // class CacheFile - Cover class for some dependency cache functions /*{{{*/ -// --------------------------------------------------------------------- -/* */ class APT_PUBLIC CacheFile : public pkgCacheFile { - static pkgCache *SortCache; - APT_HIDDEN static int NameComp(const void *a,const void *b) APT_PURE; - public: - pkgCache::Package **List; - - void Sort(); + std::vector UniverseList; + bool CheckDeps(bool AllowBroken = false); bool BuildCaches(bool WithLock = true) { @@ -51,14 +46,10 @@ class APT_PUBLIC CacheFile : public pkgCacheFile return _error->Error(_("The list of sources could not be read.")); return true; } - bool Open(bool WithLock = true) + bool Open(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(&Prog,WithLock) == false) - return false; - Sort(); - - return true; + return pkgCacheFile::Open(&Prog,WithLock); }; bool OpenForInstall() { @@ -67,11 +58,39 @@ class APT_PUBLIC CacheFile : public pkgCacheFile else return Open(true); } - CacheFile() : List(0) {}; - ~CacheFile() { - delete[] List; - } }; /*}}}*/ +class APT_PUBLIC SortedPackageUniverse : public APT::PackageUniverse +{ + std::vector &List; + void LazyInit() const; + +public: + SortedPackageUniverse(CacheFile &Cache); + + class const_iterator : public APT::Container_iterator_base::const_iterator, pkgCache::PkgIterator> + { + pkgCache * const Cache; + protected: + inline virtual pkgCache::PkgIterator getType(void) const APT_OVERRIDE + { + if (*_iter == 0) return pkgCache::PkgIterator(*Cache); + return pkgCache::PkgIterator(*Cache, Cache->PkgP + *_iter); + } + public: + explicit const_iterator(pkgCache * const Owner, std::vector::const_iterator i): + Container_iterator_base::const_iterator, pkgCache::PkgIterator>(i), Cache(Owner) {} + + }; + typedef const_iterator iterator; + + APT_PUBLIC const_iterator begin() const { LazyInit(); return const_iterator(data(), List.begin()); } + APT_PUBLIC const_iterator end() const { LazyInit(); return const_iterator(data(), List.end()); } + APT_PUBLIC const_iterator cbegin() const { LazyInit(); return const_iterator(data(), List.begin()); } + APT_PUBLIC const_iterator cend() const { LazyInit(); return const_iterator(data(), List.end()); } + APT_PUBLIC iterator begin() { LazyInit(); return iterator(data(), List.begin()); } + APT_PUBLIC iterator end() { LazyInit(); return iterator(data(), List.end()); } +}; + #endif diff --git a/apt-private/private-cacheset.h b/apt-private/private-cacheset.h index 518f179f3..7cafe4fdd 100644 --- a/apt-private/private-cacheset.h +++ b/apt-private/private-cacheset.h @@ -12,6 +12,8 @@ #include #include +#include + #include #include #include @@ -21,8 +23,6 @@ #include #include -#include "private-output.h" - #include class OpProgress; @@ -174,17 +174,19 @@ public: std::string VersionsList; SPtrArray Seen = new bool[Cache.GetPkgCache()->Head().PackageCount]; memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen)); + APT::PackageList pkglist; for (pkgCache::DepIterator Dep = Pkg.RevDependsList(); Dep.end() == false; ++Dep) { if (Dep->Type != pkgCache::Dep::Replaces) continue; - if (Seen[Dep.ParentPkg()->ID] == true) + pkgCache::PkgIterator const DP = Dep.ParentPkg(); + if (Seen[DP->ID] == true) continue; - Seen[Dep.ParentPkg()->ID] = true; - List += Dep.ParentPkg().FullName(true) + " "; - //VersionsList += std::string(Dep.ParentPkg().CurVersion) + "\n"; ??? + Seen[DP->ID] = true; + pkglist.insert(DP); } - ShowList(c1out,_("However the following packages replace it:"),List,VersionsList); + ShowList(c1out, _("However the following packages replace it:"), pkglist, + &AlwaysTrue, &PrettyFullName, &EmptyString); } c1out << std::endl; } diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 3474d262a..cdca45755 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -374,11 +374,10 @@ static bool DoAutomaticRemove(CacheFile &Cache) unsigned long autoRemoveCount = 0; APT::PackageSet tooMuch; - APT::PackageList autoRemoveList; + SortedPackageUniverse Universe(Cache); // look over the cache to see what can be removed - for (unsigned J = 0; J < Cache->Head().PackageCount; ++J) + for (auto const &Pkg: Universe) { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); if (Cache[Pkg].Garbage) { if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install()) @@ -395,8 +394,6 @@ static bool DoAutomaticRemove(CacheFile &Cache) } else { - if (hideAutoRemove == false && Cache[Pkg].Delete() == false) - autoRemoveList.insert(Pkg); // if the package is a new install and already garbage we don't need to // install it in the first place, so nuke it instead of show it if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0) @@ -456,18 +453,6 @@ static bool DoAutomaticRemove(CacheFile &Cache) } while (Changed == true); } - std::string autoremovelist, autoremoveversions; - if (smallList == false && autoRemoveCount != 0) - { - for (APT::PackageList::const_iterator Pkg = autoRemoveList.begin(); Pkg != autoRemoveList.end(); ++Pkg) - { - if (Cache[Pkg].Garbage == false) - continue; - autoremovelist += Pkg.FullName(true) + " "; - autoremoveversions += std::string(Cache[Pkg].CandVersion) + "\n"; - } - } - // Now see if we had destroyed anything (if we had done anything) if (Cache->BrokenCount() != 0) { @@ -482,12 +467,17 @@ static bool DoAutomaticRemove(CacheFile &Cache) } // if we don't remove them, we should show them! - if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0)) + if (doAutoRemove == false && autoRemoveCount != 0) { if (smallList == false) + { + SortedPackageUniverse Universe(Cache); ShowList(c1out, P_("The following package was automatically installed and is no longer required:", "The following packages were automatically installed and are no longer required:", - autoRemoveCount), autoremovelist, autoremoveversions); + autoRemoveCount), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) { return (*Cache)[Pkg].Garbage == true && (*Cache)[Pkg].Delete() == false; }, + &PrettyFullName, CandidateVersion(&Cache)); + } else ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n", "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount); @@ -651,6 +641,18 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache, // DoInstall - Install packages from the command line /*{{{*/ // --------------------------------------------------------------------- /* Install named packages */ +struct PkgIsExtraInstalled { + pkgCacheFile * const Cache; + APT::VersionSet const * const verset; + PkgIsExtraInstalled(pkgCacheFile * const Cache, APT::VersionSet const * const Container) : Cache(Cache), verset(Container) {} + bool operator() (pkgCache::PkgIterator const Pkg) + { + if ((*Cache)[Pkg].Install() == false) + return false; + pkgCache::VerIterator const Cand = (*Cache)[Pkg].CandidateVerIter(*Cache); + return verset->find(Cand) == verset->end(); + } +}; bool DoInstall(CommandLine &CmdL) { CacheFile Cache; @@ -689,35 +691,18 @@ bool DoInstall(CommandLine &CmdL) /* Print out a list of packages that are going to be installed extra to what the user asked */ + SortedPackageUniverse Universe(Cache); if (Cache->InstCount() != verset[MOD_INSTALL].size()) - { - std::string List; - std::string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if ((*Cache)[I].Install() == false) - continue; - pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache); - - if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end()) - continue; - - List += I.FullName(true) + " "; - VersionsList += std::string(Cache[I].CandVersion) + "\n"; - } - - ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList); - } + ShowList(c1out, _("The following extra packages will be installed:"), Universe, + PkgIsExtraInstalled(&Cache, &verset[MOD_INSTALL]), + &PrettyFullName, CandidateVersion(&Cache)); /* Print out a list of suggested and recommended packages */ { std::string SuggestsList, RecommendsList; std::string SuggestsVersions, RecommendsVersions; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + for (auto const &Pkg: Universe) { - pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); - /* Just look at the ones we want to install */ if ((*Cache)[Pkg].Install() == false) continue; @@ -738,7 +723,6 @@ bool DoInstall(CommandLine &CmdL) for(;;) { /* Skip if package is installed already, or is about to be */ - std::string target = Start.TargetPkg().FullName(true) + " "; pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); if (TarPkg->SelectedState == pkgCache::State::Install || TarPkg->SelectedState == pkgCache::State::Hold || @@ -749,6 +733,7 @@ bool DoInstall(CommandLine &CmdL) } /* Skip if we already saw it */ + std::string target = Start.TargetPkg().FullName(true) + " "; if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) { foundInstalledInOrGroup=true; diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index 9944ab002..b77efff86 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -25,6 +25,8 @@ #include #include +#include + #include /*}}}*/ @@ -491,11 +493,9 @@ void ShowBroken(ostream &out, CacheFile &Cache, bool const Now) return; out << _("The following packages have unmet dependencies:") << endl; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator const I(Cache,Cache.List[J]); - ShowBrokenPackage(out, &Cache, I, Now); - } + SortedPackageUniverse Universe(Cache); + for (auto const &Pkg: Universe) + ShowBrokenPackage(out, &Cache, Pkg, Now); } void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) { @@ -503,98 +503,64 @@ void ShowBroken(ostream &out, pkgCacheFile &Cache, bool const Now) return; out << _("The following packages have unmet dependencies:") << endl; - for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); Pkg.end() == false; ++Pkg) + APT::PackageUniverse Universe(Cache); + for (auto const &Pkg: Universe) ShowBrokenPackage(out, &Cache, Pkg, Now); } /*}}}*/ // ShowNew - Show packages to newly install /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowNew(ostream &out,CacheFile &Cache) { - /* Print out a list of packages that are going to be installed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].NewInstall() == true) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CandVersion) + "\n"; - } - } - - ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following NEW packages will be installed:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].NewInstall(); }, + &PrettyFullName, + CandidateVersion(&Cache)); } /*}}}*/ // ShowDel - Show packages to delete /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowDel(ostream &out,CacheFile &Cache) { - /* Print out a list of packages that are going to be removed extra - to what the user asked */ - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].Delete() == true) - { - if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) - List += I.FullName(true) + "* "; - else - List += I.FullName(true) + " "; - - VersionsList += string(Cache[I].CandVersion)+ "\n"; - } - } - - ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages will be REMOVED:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) { return Cache[Pkg].Delete(); }, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + std::string str = PrettyFullName(Pkg); + if (((*Cache)[Pkg].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) + str.append("*"); + return str; + }, + CandidateVersion(&Cache)); } /*}}}*/ // ShowKept - Show kept packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowKept(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false || - I->CurrentVer == 0 || Cache[I].Delete() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages have been kept back:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages have been kept back:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Upgrade() == false && + Cache[Pkg].Upgradable() == true && + Pkg->CurrentVer != 0 && + Cache[Pkg].Delete() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowUpgraded - Show upgraded packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ void ShowUpgraded(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - ShowList(out,_("The following packages will be upgraded:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + ShowList(out,_("The following packages will be upgraded:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Upgrade() == true && Cache[Pkg].NewInstall() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowDowngraded - Show downgraded packages /*{{{*/ @@ -602,74 +568,73 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) /* */ bool ShowDowngraded(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - - // Not interesting - if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) - continue; - - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + return ShowList(out,_("The following packages will be DOWNGRADED:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Cache[Pkg].Downgrade() == true && Cache[Pkg].NewInstall() == false; + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowHold - Show held but changed packages /*{{{*/ -// --------------------------------------------------------------------- -/* */ bool ShowHold(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) - { - pkgCache::PkgIterator I(Cache,Cache.List[J]); - if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() && - I->SelectedState == pkgCache::State::Hold) { - List += I.FullName(true) + " "; - VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; - } - } - - return ShowList(out,_("The following held packages will be changed:"),List,VersionsList); + SortedPackageUniverse Universe(Cache); + return ShowList(out,_("The following held packages will be changed:"), Universe, + [&Cache](pkgCache::PkgIterator const &Pkg) + { + return Pkg->SelectedState == pkgCache::State::Hold && + Cache[Pkg].InstallVer != (pkgCache::Version *)Pkg.CurrentVer(); + }, + &PrettyFullName, + CurrentToCandidateVersion(&Cache)); } /*}}}*/ // ShowEssential - Show an essential package warning /*{{{*/ // --------------------------------------------------------------------- /* This prints out a warning message that is not to be ignored. It shows - all essential packages and their dependents that are to be removed. + all essential packages and their dependents that are to be removed. It is insanely risky to remove the dependents of an essential package! */ +struct APT_HIDDEN PrettyFullNameWithDue { + std::map due; + PrettyFullNameWithDue() {} + std::string operator() (pkgCache::PkgIterator const &Pkg) + { + std::string const A = PrettyFullName(Pkg); + std::map::const_iterator d = due.find(Pkg->ID); + if (d == due.end()) + return A; + + std::string const B = PrettyFullName(d->second); + std::ostringstream outstr; + ioprintf(outstr, _("%s (due to %s)"), A.c_str(), B.c_str()); + return outstr.str(); + } +}; bool ShowEssential(ostream &out,CacheFile &Cache) { - string List; - string VersionsList; - bool *Added = new bool[Cache->Head().PackageCount]; - for (unsigned int I = 0; I != Cache->Head().PackageCount; I++) - Added[I] = false; - - for (unsigned J = 0; J < Cache->Head().PackageCount; J++) + std::vector Added(Cache->Head().PackageCount, false); + APT::PackageDeque pkglist; + PrettyFullNameWithDue withdue; + + SortedPackageUniverse Universe(Cache); + for (pkgCache::PkgIterator const &I: Universe) { - pkgCache::PkgIterator I(Cache,Cache.List[J]); if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential && (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important) continue; - + // The essential package is being removed - if (Cache[I].Delete() == true) + if (Cache[I].Delete() == false) + continue; + + if (Added[I->ID] == false) { - if (Added[I->ID] == false) - { - Added[I->ID] = true; - List += I.FullName(true) + " "; - //VersionsList += string(Cache[I].CurVersion) + "\n"; ??? - } + Added[I->ID] = true; + pkglist.insert(I); } - else - continue; if (I->CurrentVer == 0) continue; @@ -681,27 +646,23 @@ bool ShowEssential(ostream &out,CacheFile &Cache) if (D->Type != pkgCache::Dep::PreDepends && D->Type != pkgCache::Dep::Depends) continue; - + pkgCache::PkgIterator P = D.SmartTargetPkg(); if (Cache[P].Delete() == true) { if (Added[P->ID] == true) continue; Added[P->ID] = true; - - char S[300]; - snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str()); - List += S; - //VersionsList += "\n"; ??? - } - } + + pkglist.insert(P); + withdue.due[P->ID] = I; + } + } } - - delete [] Added; return ShowList(out,_("WARNING: The following essential packages will be removed.\n" - "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList); + "This should NOT be done unless you know exactly what you are doing!"), + pkglist, &AlwaysTrue, withdue, &EmptyString); } - /*}}}*/ // Stats - Show some statistics /*{{{*/ // --------------------------------------------------------------------- @@ -829,3 +790,33 @@ bool AnalPrompt(const char *Text) return false; } /*}}}*/ + +std::string PrettyFullName(pkgCache::PkgIterator const &Pkg) +{ + return Pkg.FullName(true); +} +std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg) +{ + return (*Cache)[Pkg].CandVersion; +} +std::function CandidateVersion(pkgCacheFile * const Cache) +{ + return std::bind(static_cast(&CandidateVersion), Cache, std::placeholders::_1); +} +std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg) +{ + return std::string((*Cache)[Pkg].CurVersion) + " => " + (*Cache)[Pkg].CandVersion; +} +std::function CurrentToCandidateVersion(pkgCacheFile * const Cache) +{ + return std::bind(static_cast(&CurrentToCandidateVersion), Cache, std::placeholders::_1); +} +bool AlwaysTrue(pkgCache::PkgIterator const &) +{ + return true; +} +std::string EmptyString(pkgCache::PkgIterator const &) +{ + return std::string(); +} + diff --git a/apt-private/private-output.h b/apt-private/private-output.h index d5b57adec..b9151b245 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -1,9 +1,11 @@ #ifndef APT_PRIVATE_OUTPUT_H #define APT_PRIVATE_OUTPUT_H +#include #include #include +#include #include #include #include @@ -32,8 +34,63 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now); APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now); -APT_PUBLIC bool ShowList(std::ostream &out, std::string Title, std::string List, +template APT_PUBLIC bool ShowList(std::ostream &out, std::string const &Title, + Container const &cont, + std::function Predicate, + std::function PkgDisplay, + std::function VerboseDisplay) +{ + size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0; + int ScreenUsed = 0; + bool const ShowVersions = _config->FindB("APT::Get::Show-Versions", false); + bool printedTitle = false; + + for (auto const &Pkg: cont) + { + if (Predicate(Pkg) == false) + continue; + + if (printedTitle == false) + { + out << Title; + printedTitle = true; + } + + if (ShowVersions == true) + { + out << std::endl << " " << PkgDisplay(Pkg); + std::string const verbose = VerboseDisplay(Pkg); + if (verbose.empty() == false) + out << " (" << verbose << ")"; + } + else + { + std::string const PkgName = PkgDisplay(Pkg); + if (ScreenUsed == 0 || (ScreenUsed + PkgName.length()) >= ScreenWidth) + { + out << std::endl << " "; + ScreenUsed = 0; + } + else if (ScreenUsed != 0) + { + out << " "; + ++ScreenUsed; + } + out << PkgName; + ScreenUsed += PkgName.length(); + } + } + + if (printedTitle == true) + { + out << std::endl; + return false; + } + return true; +} +APT_DEPRECATED APT_PUBLIC bool ShowList(std::ostream &out, std::string Title, std::string List, std::string VersionsList); + void ShowNew(std::ostream &out,CacheFile &Cache); void ShowDel(std::ostream &out,CacheFile &Cache); void ShowKept(std::ostream &out,CacheFile &Cache); @@ -49,4 +106,12 @@ void Stats(std::ostream &out, pkgDepCache &Dep); bool YnPrompt(bool Default=true); bool AnalPrompt(const char *Text); +APT_PUBLIC std::string PrettyFullName(pkgCache::PkgIterator const &Pkg); +APT_PUBLIC std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); +APT_PUBLIC std::function CandidateVersion(pkgCacheFile * const Cache); +APT_PUBLIC std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); +APT_PUBLIC std::function CurrentToCandidateVersion(pkgCacheFile * const Cache); +APT_PUBLIC std::string EmptyString(pkgCache::PkgIterator const &); +APT_PUBLIC bool AlwaysTrue(pkgCache::PkgIterator const &); + #endif diff --git a/po/apt-all.pot b/po/apt-all.pot index 73b033876..e2d09401b 100644 --- a/po/apt-all.pot +++ b/po/apt-all.pot @@ -1135,7 +1135,7 @@ msgstr "" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " +msgid "%s (due to %s)" msgstr "" #: apt-private/private-output.cc:696 diff --git a/po/ar.po b/po/ar.po index 3e71fef80..8c1622d91 100644 --- a/po/ar.po +++ b/po/ar.po @@ -1151,8 +1151,8 @@ msgstr "سيتم تغيير الحزم المبقاة التالية:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (بسبب %s) " +msgid "%s (due to %s)" +msgstr "%s (بسبب %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ast.po b/po/ast.po index 1995c12f6..07888ebe2 100644 --- a/po/ast.po +++ b/po/ast.po @@ -1261,8 +1261,8 @@ msgstr "Van camudase los siguientes paquetes reteníos:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (por %s) " +msgid "%s (due to %s)" +msgstr "%s (por %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/bg.po b/po/bg.po index 7dff005e6..6dc47f5bb 100644 --- a/po/bg.po +++ b/po/bg.po @@ -1294,8 +1294,8 @@ msgstr "Следните задържани пакети ще бъдат про #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (поради %s) " +msgid "%s (due to %s)" +msgstr "%s (поради %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/bs.po b/po/bs.po index abb9a570a..e68cee981 100644 --- a/po/bs.po +++ b/po/bs.po @@ -1159,7 +1159,7 @@ msgstr "" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " +msgid "%s (due to %s)" msgstr "" #: apt-private/private-output.cc:696 diff --git a/po/ca.po b/po/ca.po index 065ad0ea7..3f111875d 100644 --- a/po/ca.po +++ b/po/ca.po @@ -1276,8 +1276,8 @@ msgstr "Es canviaran els paquets retinguts següents:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (per %s) " +msgid "%s (due to %s)" +msgstr "%s (per %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/cs.po b/po/cs.po index 3f6bcb4a7..4de2b7006 100644 --- a/po/cs.po +++ b/po/cs.po @@ -1301,8 +1301,8 @@ msgstr "Následující podržené balíky budou změněny:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (kvůli %s) " +msgid "%s (due to %s)" +msgstr "%s (kvůli %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/cy.po b/po/cy.po index b05bc7c59..db9ec0bbc 100644 --- a/po/cy.po +++ b/po/cy.po @@ -1288,8 +1288,8 @@ msgstr "Caiff y pecynnau wedi eu dal canlynol eu newid:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (oherwydd %s) " +msgid "%s (due to %s)" +msgstr "%s (oherwydd %s)" #: apt-private/private-output.cc:696 #, fuzzy diff --git a/po/da.po b/po/da.po index d6b8e07a1..f337879f6 100644 --- a/po/da.po +++ b/po/da.po @@ -1319,8 +1319,8 @@ msgstr "Følgende tilbageholdte pakker vil blive ændret:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (grundet %s) " +msgid "%s (due to %s)" +msgstr "%s (grundet %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/de.po b/po/de.po index d4ca0d5a0..0b363c8de 100644 --- a/po/de.po +++ b/po/de.po @@ -1364,8 +1364,8 @@ msgstr "Die folgenden zurückgehaltenen Pakete werden verändert:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (wegen %s) " +msgid "%s (due to %s)" +msgstr "%s (wegen %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/dz.po b/po/dz.po index a4c50d245..e27ea6a90 100644 --- a/po/dz.po +++ b/po/dz.po @@ -1256,7 +1256,7 @@ msgstr "འོག་གི་འཆང་ཡོད་པའི་ཐུམ་ས #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " +msgid "%s (due to %s)" msgstr "%s( %s་གིས་སྦེ)" #: apt-private/private-output.cc:696 diff --git a/po/el.po b/po/el.po index 98e1f31c9..b2370c6ad 100644 --- a/po/el.po +++ b/po/el.po @@ -1272,8 +1272,8 @@ msgstr "Τα ακόλουθα κρατημένα πακέτα θα αλλαχθ #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (λόγω του %s) " +msgid "%s (due to %s)" +msgstr "%s (λόγω του %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/es.po b/po/es.po index a2a9a71e9..c071ffb4a 100644 --- a/po/es.po +++ b/po/es.po @@ -1388,8 +1388,8 @@ msgstr "Se cambiarán los siguientes paquetes retenidos:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (por %s) " +msgid "%s (due to %s)" +msgstr "%s (por %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/eu.po b/po/eu.po index f1e90411a..528c6cc51 100644 --- a/po/eu.po +++ b/po/eu.po @@ -1257,8 +1257,8 @@ msgstr "Ondorengo pakete atxikiak aldatu egingo dira:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (arrazoia: %s) " +msgid "%s (due to %s)" +msgstr "%s (arrazoia: %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/fi.po b/po/fi.po index c40ed8e9e..5a5299255 100644 --- a/po/fi.po +++ b/po/fi.po @@ -1248,8 +1248,8 @@ msgstr "Seuraavat pysytetyt paketit muutetaan:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (syynä %s) " +msgid "%s (due to %s)" +msgstr "%s (syynä %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/fr.po b/po/fr.po index ecb752f5e..0a437907f 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1328,8 +1328,8 @@ msgstr "Les paquets retenus suivants seront changés :" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (en raison de %s) " +msgid "%s (due to %s)" +msgstr "%s (en raison de %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/gl.po b/po/gl.po index 2adaa302a..9ec10122b 100644 --- a/po/gl.po +++ b/po/gl.po @@ -1275,8 +1275,8 @@ msgstr "Vanse modificar os paquetes retidos seguintes:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (por mor de %s) " +msgid "%s (due to %s)" +msgstr "%s (por mor de %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/he.po b/po/he.po index ab7b50745..2c355f863 100644 --- a/po/he.po +++ b/po/he.po @@ -610,8 +610,8 @@ msgstr "החבילות המחוזקות הבאות ישונו:" #: cmdline/apt-get.cc:545 #, c-format -msgid "%s (due to %s) " -msgstr "%s (בגלל %s) " +msgid "%s (due to %s)" +msgstr "%s (בגלל %s)" #: cmdline/apt-get.cc:553 #, fuzzy diff --git a/po/hu.po b/po/hu.po index 635184c75..fcf53f727 100644 --- a/po/hu.po +++ b/po/hu.po @@ -1291,8 +1291,8 @@ msgstr "Az alábbi visszafogott csomagokat cserélem:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (%s miatt) " +msgid "%s (due to %s)" +msgstr "%s (%s miatt)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/it.po b/po/it.po index 178754c52..6d9793c55 100644 --- a/po/it.po +++ b/po/it.po @@ -1323,8 +1323,8 @@ msgstr "I seguenti pacchetti bloccati saranno cambiati:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (a causa di %s) " +msgid "%s (due to %s)" +msgstr "%s (a causa di %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ja.po b/po/ja.po index f8f55f8aa..6e0e21418 100644 --- a/po/ja.po +++ b/po/ja.po @@ -1324,8 +1324,8 @@ msgstr "以下の変更禁止パッケージは変更されます:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (%s のため) " +msgid "%s (due to %s)" +msgstr "%s (%s のため)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/km.po b/po/km.po index 8c72865f8..8ae605510 100644 --- a/po/km.po +++ b/po/km.po @@ -1242,8 +1242,8 @@ msgstr "កញ្ចប់​រង់ចាំ​ខាងក្រោម​ន #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (ដោយ​សារតែ​ %s) " +msgid "%s (due to %s)" +msgstr "%s (ដោយ​សារតែ​ %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ko.po b/po/ko.po index 51cc27d61..e5b08fdec 100644 --- a/po/ko.po +++ b/po/ko.po @@ -1250,8 +1250,8 @@ msgstr "고정되었던 다음 패키지를 바꿀 것입니다:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (%s때문에) " +msgid "%s (due to %s)" +msgstr "%s (%s때문에)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ku.po b/po/ku.po index 540307937..3b2d6ed12 100644 --- a/po/ku.po +++ b/po/ku.po @@ -1162,7 +1162,7 @@ msgstr "" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " +msgid "%s (due to %s)" msgstr "%s (ji ber %s)" #: apt-private/private-output.cc:696 diff --git a/po/lt.po b/po/lt.po index 1f485b28d..6d0365183 100644 --- a/po/lt.po +++ b/po/lt.po @@ -1166,8 +1166,8 @@ msgstr "Bus pakeisti šie sulaikyti paketai:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (dėl %s) " +msgid "%s (due to %s)" +msgstr "%s (dėl %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/mr.po b/po/mr.po index 24e470cef..31bdb63c9 100644 --- a/po/mr.po +++ b/po/mr.po @@ -1240,7 +1240,7 @@ msgstr "पुढिल ठेवलेली पॅकेजेस बदलत #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " +msgid "%s (due to %s)" msgstr "%s (च्या मुळे %s)" #: apt-private/private-output.cc:696 diff --git a/po/nb.po b/po/nb.po index 433e33909..41563cecd 100644 --- a/po/nb.po +++ b/po/nb.po @@ -1258,8 +1258,8 @@ msgstr "Følgende pakker vil bli endret:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (pga. %s) " +msgid "%s (due to %s)" +msgstr "%s (pga. %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ne.po b/po/ne.po index 4c6f2d098..b5fb2c6fc 100644 --- a/po/ne.po +++ b/po/ne.po @@ -1240,8 +1240,8 @@ msgstr "निम्न भइरहेको प्याकेजहरू प #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (%s कारणले) " +msgid "%s (due to %s)" +msgstr "%s (%s कारणले)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/nl.po b/po/nl.po index 5c774fe8d..2214ac65c 100644 --- a/po/nl.po +++ b/po/nl.po @@ -1337,8 +1337,8 @@ msgstr "De volgende vastgehouden pakketten zullen gewijzigd worden:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (vanwege %s) " +msgid "%s (due to %s)" +msgstr "%s (vanwege %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/nn.po b/po/nn.po index 0886c266a..5c8c39967 100644 --- a/po/nn.po +++ b/po/nn.po @@ -1251,8 +1251,8 @@ msgstr "Dei f #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (fordi %s) " +msgid "%s (due to %s)" +msgstr "%s (fordi %s)" #: apt-private/private-output.cc:696 #, fuzzy diff --git a/po/pl.po b/po/pl.po index 1851fa805..f248841c9 100644 --- a/po/pl.po +++ b/po/pl.po @@ -1302,8 +1302,8 @@ msgstr "Zostaną zmienione następujące zatrzymane pakiety:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (z powodu %s) " +msgid "%s (due to %s)" +msgstr "%s (z powodu %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/pt.po b/po/pt.po index 4f05ada82..0e106a7d1 100644 --- a/po/pt.po +++ b/po/pt.po @@ -1291,8 +1291,8 @@ msgstr "Os seguintes pacotes mantidos serão mudados:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (devido a %s) " +msgid "%s (due to %s)" +msgstr "%s (devido a %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/pt_BR.po b/po/pt_BR.po index 5e2abd988..c50792b79 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -1264,8 +1264,8 @@ msgstr "Os seguintes pacotes mantidos serão mudados:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (por causa de %s) " +msgid "%s (due to %s)" +msgstr "%s (por causa de %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ro.po b/po/ro.po index 9b0a1494a..7b94bd3d8 100644 --- a/po/ro.po +++ b/po/ro.po @@ -1267,8 +1267,8 @@ msgstr "Următoarele pachete ținute vor fi schimbate:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (datorită %s) " +msgid "%s (due to %s)" +msgstr "%s (datorită %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/ru.po b/po/ru.po index 7d30cb696..5e52b9234 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1614,8 +1614,8 @@ msgstr "" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (вследствие %s) " +msgid "%s (due to %s)" +msgstr "%s (вследствие %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/sk.po b/po/sk.po index 631ddd826..0aeb167ea 100644 --- a/po/sk.po +++ b/po/sk.po @@ -1280,8 +1280,8 @@ msgstr "Nasledovné pridržané balíky sa zmenia:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (kvôli %s) " +msgid "%s (due to %s)" +msgstr "%s (kvôli %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/sl.po b/po/sl.po index 845fe3c5f..496919956 100644 --- a/po/sl.po +++ b/po/sl.po @@ -1277,8 +1277,8 @@ msgstr "Naslednji zadržani paketi bodo spremenjeni:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (zaradi %s) " +msgid "%s (due to %s)" +msgstr "%s (zaradi %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/sv.po b/po/sv.po index 52f65b598..bdf00ff65 100644 --- a/po/sv.po +++ b/po/sv.po @@ -1266,8 +1266,8 @@ msgstr "Följande tillbakahållna paket kommer att ändras:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (på grund av %s) " +msgid "%s (due to %s)" +msgstr "%s (på grund av %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/th.po b/po/th.po index 60a468ea4..c016205c5 100644 --- a/po/th.po +++ b/po/th.po @@ -1287,8 +1287,8 @@ msgstr "จะเปลี่ยนแปลงรายการคงรุ่ #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (เนื่องจาก %s) " +msgid "%s (due to %s)" +msgstr "%s (เนื่องจาก %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/tl.po b/po/tl.po index 970b0b387..be3371704 100644 --- a/po/tl.po +++ b/po/tl.po @@ -1258,8 +1258,8 @@ msgstr "Ang susunod na mga hinawakang mga pakete ay babaguhin:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (dahil sa %s) " +msgid "%s (due to %s)" +msgstr "%s (dahil sa %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/tr.po b/po/tr.po index 79945ebd3..8b8691a55 100644 --- a/po/tr.po +++ b/po/tr.po @@ -1315,8 +1315,8 @@ msgstr "Aşağıdaki eski sürümlerinde tutulan paketler değiştirilecek:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (%s nedeniyle) " +msgid "%s (due to %s)" +msgstr "%s (%s nedeniyle)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/uk.po b/po/uk.po index 47976d39c..514403641 100644 --- a/po/uk.po +++ b/po/uk.po @@ -1298,8 +1298,8 @@ msgstr "Пакунки, які мали б залишитися без змін, #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (внаслідок %s) " +msgid "%s (due to %s)" +msgstr "%s (внаслідок %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/vi.po b/po/vi.po index 2edb52f22..73770ce74 100644 --- a/po/vi.po +++ b/po/vi.po @@ -1334,8 +1334,8 @@ msgstr "Những gói giữ lại sau đây sẽ bị THAY ĐỔI:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (bởi vì %s) " +msgid "%s (due to %s)" +msgstr "%s (bởi vì %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/zh_CN.po b/po/zh_CN.po index 6e9610ac9..1f92d6269 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -1289,8 +1289,8 @@ msgstr "下列被要求保持版本不变的软件包将被改变:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s (是由于 %s) " +msgid "%s (due to %s)" +msgstr "%s (是由于 %s)" #: apt-private/private-output.cc:696 msgid "" diff --git a/po/zh_TW.po b/po/zh_TW.po index 201d9d675..f37e5e0ed 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -1236,8 +1236,8 @@ msgstr "下列被保留 (hold) 的套件將會被更改:" #: apt-private/private-output.cc:688 #, c-format -msgid "%s (due to %s) " -msgstr "%s(因為 %s)" +msgid "%s (due to %s)" +msgstr "%s(因為 %s" #: apt-private/private-output.cc:696 msgid "" diff --git a/test/integration/test-apt-get-autoremove b/test/integration/test-apt-get-autoremove index a0e4d3c24..454b47976 100755 --- a/test/integration/test-apt-get-autoremove +++ b/test/integration/test-apt-get-autoremove @@ -27,6 +27,19 @@ The following packages will be REMOVED: po-debconf 0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded. Remv po-debconf [1.0.16]' aptget autoremove -s +testequal "Reading package lists... +Building dependency tree... +Reading state information... +The following package was automatically installed and is no longer required: + po-debconf +Use 'apt-get autoremove' to remove it. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -s +testequal "Reading package lists... +Building dependency tree... +Reading state information... +1 package was automatically installed and is no longer required. +Use 'apt-get autoremove' to remove it. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -s -o APT::Get::HideAutoRemove=small testdpkginstalled 'po-debconf' echo 'APT::NeverAutoRemove { "^po-debconf$"; };' > rootdir/etc/apt/apt.conf.d/00autoremove @@ -63,6 +76,19 @@ The following packages will be REMOVED: 0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded. Remv debhelper [8.0.0] Remv po-debconf [1.0.16]' aptget autoremove -s +testequal "Reading package lists... +Building dependency tree... +Reading state information... +The following packages were automatically installed and are no longer required: + debhelper po-debconf +Use 'apt-get autoremove' to remove them. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -s +testequal "Reading package lists... +Building dependency tree... +Reading state information... +2 packages were automatically installed and are no longer required. +Use 'apt-get autoremove' to remove them. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -s -o APT::Get::HideAutoRemove=small testsuccess aptmark hold debhelper testsuccessequal 'Reading package lists... diff --git a/test/integration/test-bug-596498-trusted-unsigned-repo b/test/integration/test-bug-596498-trusted-unsigned-repo index c515837a3..94f280b81 100755 --- a/test/integration/test-bug-596498-trusted-unsigned-repo +++ b/test/integration/test-bug-596498-trusted-unsigned-repo @@ -37,6 +37,15 @@ WARNING: The following packages cannot be authenticated! Install these packages without verification? [y/N] N E: Some packages could not be authenticated" aptget install cool --assume-no -d +configarchitecture 'amd64' 'i386' +testequal "$(echo "$PKGTEXT" | sed 's#cool$#cool:i386#g') +WARNING: The following packages cannot be authenticated! + cool:i386 +Authentication warning overridden. +$DOWNLOG +Download complete and in download only mode" aptget install cool:i386 --assume-no -d --allow-unauthenticated +configarchitecture 'i386' + find aptarchive/ \( -name 'Release.gpg' -o -name 'InRelease' \) -delete sed -i -e 's#\(deb\(-src\)\?\) \[trusted=no\] #\1 #' $DEBFILE aptgetupdate diff --git a/test/integration/test-bug-604222-new-and-autoremove b/test/integration/test-bug-604222-new-and-autoremove index 52992680b..3b5fa20c4 100755 --- a/test/integration/test-bug-604222-new-and-autoremove +++ b/test/integration/test-bug-604222-new-and-autoremove @@ -23,6 +23,17 @@ The following NEW packages will be installed: Inst libavcodec52 (4:0.5.2-6 localhost [i386]) Conf libavcodec52 (4:0.5.2-6 localhost [i386])" aptget install libavcodec52 -s +testsuccessequal "Reading package lists... +Building dependency tree... +Reading state information... +1 package was automatically installed and is no longer required. +Use 'apt-get autoremove' to remove it. +The following NEW packages will be installed: + libavcodec52 +0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. +Inst libavcodec52 (4:0.5.2-6 localhost [i386]) +Conf libavcodec52 (4:0.5.2-6 localhost [i386])" aptget install libavcodec52 -s -o APT::Get::HideAutoRemove=small + testfailureequal "Reading package lists... Building dependency tree... Reading state information... @@ -39,6 +50,21 @@ The following packages will be upgraded: Need to get 0 B/19.4 MB of archives. After this operation, 17.3 MB of additional disk space will be used. E: Trivial Only specified but this is not a trivial operation." aptget install dummy-archive --trivial-only +testequal "Reading package lists... +Building dependency tree... +Reading state information... +1 package was automatically installed and is no longer required. +Use 'apt-get autoremove' to remove it. +The following extra packages will be installed: + libavcodec52 libopenal-dev libvtk5.4 +The following NEW packages will be installed: + dummy-archive libavcodec52 libopenal-dev +The following packages will be upgraded: + libvtk5.4 +1 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Need to get 0 B/19.4 MB of archives. +After this operation, 17.3 MB of additional disk space will be used. +E: Trivial Only specified but this is not a trivial operation." aptget install dummy-archive --trivial-only -o APT::Get::HideAutoRemove=small echo -n > rootdir/var/lib/dpkg/status rm rootdir/var/lib/apt/extended_states diff --git a/test/integration/test-bug-613420-new-garbage-dependency b/test/integration/test-bug-613420-new-garbage-dependency index 5839f8798..18eab79c2 100755 --- a/test/integration/test-bug-613420-new-garbage-dependency +++ b/test/integration/test-bug-613420-new-garbage-dependency @@ -35,3 +35,19 @@ The following packages will be upgraded: 1 upgraded, 3 newly installed, 1 to remove and 0 not upgraded. After this operation, 126 MB disk space will be freed. E: Trivial Only specified but this is not a trivial operation." aptget install libreoffice --trivial-only +testequal "Reading package lists... +Building dependency tree... +Reading state information... +2 packages were automatically installed and are no longer required. +Use 'apt-get autoremove' to remove them. +The following extra packages will be installed: + libreoffice-core libreoffice-officebean openoffice.org-officebean +The following packages will be REMOVED: + openoffice.org-core +The following NEW packages will be installed: + libreoffice libreoffice-core libreoffice-officebean +The following packages will be upgraded: + openoffice.org-officebean +1 upgraded, 3 newly installed, 1 to remove and 0 not upgraded. +After this operation, 126 MB disk space will be freed. +E: Trivial Only specified but this is not a trivial operation." aptget install libreoffice --trivial-only -o APT::Get::HideAutoRemove=small diff --git a/test/integration/test-bug-675449-essential-are-protected b/test/integration/test-bug-675449-essential-are-protected index f50507532..e62add938 100755 --- a/test/integration/test-bug-675449-essential-are-protected +++ b/test/integration/test-bug-675449-essential-are-protected @@ -87,3 +87,17 @@ Inst pkg-none-native [1] (2 unstable [amd64]) Conf pkg-none-native (2 unstable [amd64]) Inst pkg-none-new (2 unstable [amd64]) Conf pkg-none-new (2 unstable [amd64])' aptget dist-upgrade -s + +insertinstalledpackage 'foo' 'amd64' '1' 'Depends: libfoo +Essential: yes' +insertinstalledpackage 'libfoo' 'amd64' '1' +testequal 'Reading package lists... +Building dependency tree... +The following packages will be REMOVED: + foo* libfoo* +WARNING: The following essential packages will be removed. +This should NOT be done unless you know exactly what you are doing! + foo libfoo (due to foo) +0 upgraded, 0 newly installed, 2 to remove and 4 not upgraded. +Purg foo [1] +Purg libfoo [1]' aptget purge libfoo -s diff --git a/test/integration/test-kernel-helper-autoremove b/test/integration/test-kernel-helper-autoremove index c2fc37ee7..2b020ceca 100755 --- a/test/integration/test-kernel-helper-autoremove +++ b/test/integration/test-kernel-helper-autoremove @@ -58,6 +58,22 @@ testprotected() { testsuccessequal "Reading package lists... Building dependency tree... Reading state information... +The following packages were automatically installed and are no longer required: + linux-headers-1000000-1-generic (100.0.0-1) + linux-image-1.0.0-2-generic (1.0.0-2) + linux-image-100.0.0-1-generic (100.0.0-1) + $CURRENTKERNEL (1) +Use 'apt-get autoremove' to remove them. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -sV +testequal "Reading package lists... +Building dependency tree... +Reading state information... +4 packages were automatically installed and are no longer required. +Use 'apt-get autoremove' to remove them. +0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded." aptget install -s -o APT::Get::HideAutoRemove=small +testequal "Reading package lists... +Building dependency tree... +Reading state information... The following packages will be REMOVED: linux-headers-1000000-1-generic (100.0.0-1) linux-image-1.0.0-2-generic (1.0.0-2) -- cgit v1.2.3-70-g09d2 From 9112f77703c39d46e2e0471c48c8a5e1f93f4abf Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 13 Jul 2015 03:36:59 +0200 Subject: show or-groups in not-installed recommends and suggests lists Further abstracting our new ShowList allows to use it for containers of strings as well giving us the option to implement an or-groups display for the recommends and suggests lists which is a nice trick given that it also helps with migrating the last remaining other cases of old ShowList. --- apt-pkg/cachefile.cc | 34 +++-- apt-pkg/cachefile.h | 27 ++-- apt-pkg/cacheset.cc | 110 ++++++++++++++ apt-pkg/cacheset.h | 6 +- apt-pkg/depcache.cc | 15 +- apt-private/private-cachefile.h | 14 +- apt-private/private-download.cc | 13 +- apt-private/private-download.h | 3 +- apt-private/private-install.cc | 135 +++++++++--------- apt-private/private-output.cc | 60 -------- apt-private/private-output.h | 24 ++-- cmdline/apt-get.cc | 8 +- .../test-apt-showlist-orgroup-in-recommends | 158 +++++++++++++++++++++ .../test-bug-470115-new-and-tighten-recommends | 2 + ...est-bug-549968-install-depends-of-not-installed | 2 + test/integration/test-handling-broken-orgroups | 2 +- test/integration/test-release-candidate-switching | 2 +- test/integration/test-releasefile-verification | 8 +- 18 files changed, 420 insertions(+), 203 deletions(-) create mode 100755 test/integration/test-apt-showlist-orgroup-in-recommends (limited to 'test') diff --git a/apt-pkg/cachefile.cc b/apt-pkg/cachefile.cc index 690776266..ed3c2dd0a 100644 --- a/apt-pkg/cachefile.cc +++ b/apt-pkg/cachefile.cc @@ -35,10 +35,13 @@ #include /*}}}*/ // CacheFile::CacheFile - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL), - SrcList(NULL), Policy(NULL) +pkgCacheFile::pkgCacheFile() : d(NULL), ExternOwner(false), Map(NULL), Cache(NULL), + DCache(NULL), SrcList(NULL), Policy(NULL) +{ +} +pkgCacheFile::pkgCacheFile(pkgDepCache * const Owner) : d(NULL), ExternOwner(true), + Map(&Owner->GetCache().GetMap()), Cache(&Owner->GetCache()), + DCache(Owner), SrcList(NULL), Policy(NULL) { } /*}}}*/ @@ -47,12 +50,16 @@ pkgCacheFile::pkgCacheFile() : d(NULL), Map(NULL), Cache(NULL), DCache(NULL), /* */ pkgCacheFile::~pkgCacheFile() { - delete DCache; + if (ExternOwner == false) + { + delete DCache; + delete Cache; + delete Map; + } delete Policy; delete SrcList; - delete Cache; - delete Map; - _system->UnLock(true); + if (ExternOwner == false) + _system->UnLock(true); } /*}}}*/ // CacheFile::BuildCaches - Open and build the cache files /*{{{*/ @@ -229,11 +236,16 @@ void pkgCacheFile::RemoveCaches() /* */ void pkgCacheFile::Close() { - delete DCache; + if (ExternOwner == false) + { + delete DCache; + delete Cache; + delete Map; + } + else + ExternOwner = false; delete Policy; - delete Cache; delete SrcList; - delete Map; _system->UnLock(true); Map = NULL; diff --git a/apt-pkg/cachefile.h b/apt-pkg/cachefile.h index 83dd90d36..f4cadf5e6 100644 --- a/apt-pkg/cachefile.h +++ b/apt-pkg/cachefile.h @@ -38,9 +38,9 @@ class pkgCacheFile { /** \brief dpointer placeholder (for later in case we need it) */ void * const d; + bool ExternOwner; protected: - MMap *Map; pkgCache *Cache; pkgDepCache *DCache; @@ -50,18 +50,18 @@ class pkgCacheFile pkgPolicy *Policy; // We look pretty much exactly like a pointer to a dep cache - inline operator pkgCache &() {return *Cache;}; - inline operator pkgCache *() {return Cache;}; - inline operator pkgDepCache &() {return *DCache;}; - inline operator pkgDepCache *() {return DCache;}; - inline operator pkgPolicy &() {return *Policy;}; - inline operator pkgPolicy *() {return Policy;}; - inline operator pkgSourceList &() {return *SrcList;}; - inline operator pkgSourceList *() {return SrcList;}; - inline pkgDepCache *operator ->() {return DCache;}; - inline pkgDepCache &operator *() {return *DCache;}; - inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) {return (*DCache)[I];}; - inline unsigned char &operator [](pkgCache::DepIterator const &I) {return (*DCache)[I];}; + inline operator pkgCache &() const {return *Cache;}; + inline operator pkgCache *() const {return Cache;}; + inline operator pkgDepCache &() const {return *DCache;}; + inline operator pkgDepCache *() const {return DCache;}; + inline operator pkgPolicy &() const {return *Policy;}; + inline operator pkgPolicy *() const {return Policy;}; + inline operator pkgSourceList &() const {return *SrcList;}; + inline operator pkgSourceList *() const {return SrcList;}; + inline pkgDepCache *operator ->() const {return DCache;}; + inline pkgDepCache &operator *() const {return *DCache;}; + inline pkgDepCache::StateCache &operator [](pkgCache::PkgIterator const &I) const {return (*DCache)[I];}; + inline unsigned char &operator [](pkgCache::DepIterator const &I) const {return (*DCache)[I];}; bool BuildCaches(OpProgress *Progress = NULL,bool WithLock = true); APT_DEPRECATED bool BuildCaches(OpProgress &Progress,bool const &WithLock = true) { return BuildCaches(&Progress, WithLock); }; @@ -85,6 +85,7 @@ class pkgCacheFile inline bool IsSrcListBuilt() const { return (SrcList != NULL); }; pkgCacheFile(); + explicit pkgCacheFile(pkgDepCache * const Owner); virtual ~pkgCacheFile(); }; diff --git a/apt-pkg/cacheset.cc b/apt-pkg/cacheset.cc index a4e330a0a..f5cf52159 100644 --- a/apt-pkg/cacheset.cc +++ b/apt-pkg/cacheset.cc @@ -582,6 +582,116 @@ bool VersionContainerInterface::FromPackage(VersionContainerInterface * const vc return found; } /*}}}*/ +// FromDependency - versions satisfying a given dependency /*{{{*/ +bool VersionContainerInterface::FromDependency(VersionContainerInterface * const vci, + pkgCacheFile &Cache, + pkgCache::DepIterator const &D, + CacheSetHelper::VerSelector const selector, + CacheSetHelper &helper) +{ + bool found = false; + switch(selector) { + case CacheSetHelper::ALL: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + for (pkgCache::VerIterator Ver = T.VersionList(); Ver.end() == false; ++Ver) + { + if (D.IsSatisfied(Ver) == true) + { + vci->insert(Ver); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + if (unlikely(V.end() == true) || D.IsSatisfied(Prv) == false) + continue; + vci->insert(V); + found = true; + } + } + return found; + } + case CacheSetHelper::CANDANDINST: + { + found = FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); + found &= FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); + return found; + } + case CacheSetHelper::CANDIDATE: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = Cache[T].CandidateVerIter(Cache); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Cache[Prv.OwnerPkg()].CandidateVerIter(Cache); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::INSTALLED: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = T.CurrentVer(); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Prv.OwnerPkg().CurrentVer(); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::CANDINST: + return FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper) || + FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper); + case CacheSetHelper::INSTCAND: + return FromDependency(vci, Cache, D, CacheSetHelper::INSTALLED, helper) || + FromDependency(vci, Cache, D, CacheSetHelper::CANDIDATE, helper); + case CacheSetHelper::NEWEST: + { + pkgCache::PkgIterator const T = D.TargetPkg(); + pkgCache::VerIterator const Cand = T.VersionList(); + if (Cand.end() == false && D.IsSatisfied(Cand) == true) + { + vci->insert(Cand); + found = true; + } + for (pkgCache::PrvIterator Prv = T.ProvidesList(); Prv.end() != true; ++Prv) + { + pkgCache::VerIterator const V = Prv.OwnerVer(); + pkgCache::VerIterator const Cand = Prv.OwnerPkg().VersionList(); + if (Cand.end() == true || V != Cand || D.IsSatisfied(Prv) == false) + continue; + vci->insert(Cand); + found = true; + } + return found; + } + case CacheSetHelper::RELEASE: + case CacheSetHelper::VERSIONNUMBER: + // both make no sense here, so always false + return false; + } + return found; +} + /*}}}*/ // getCandidateVer - Returns the candidate version of the given package /*{{{*/ pkgCache::VerIterator VersionContainerInterface::getCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, CacheSetHelper &helper) { diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 0b9b9441c..5455fe74b 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -1068,7 +1068,7 @@ APT_IGNORE_DEPRECATED_POP static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, CacheSetHelper::VerSelector const selector) { CacheSetHelper helper; - return FromPackage(Cache, D, selector, helper); + return FromDependency(Cache, D, selector, helper); } APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, @@ -1080,11 +1080,11 @@ APT_IGNORE_DEPRECATED_PUSH static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D, Version const &selector) { CacheSetHelper helper; - return FromPackage(Cache, D, (CacheSetHelper::VerSelector)selector, helper); + return FromDependency(Cache, D, (CacheSetHelper::VerSelector)selector, helper); } APT_IGNORE_DEPRECATED_POP static VersionContainer FromDependency(pkgCacheFile &Cache, pkgCache::DepIterator const &D) { - return FromPackage(Cache, D, CacheSetHelper::CANDIDATE); + return FromDependency(Cache, D, CacheSetHelper::CANDIDATE); } /*}}}*/ }; /*}}}*/ diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index d01c14223..0e972dbad 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -1189,18 +1190,8 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, fixing the problem for "positive" dependencies */ if (Start.IsNegative() == false && (DepState[Start->ID] & DepCVer) == DepCVer) { - APT::VersionList verlist; - pkgCache::VerIterator Cand = PkgState[Start.TargetPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == false && Start.IsSatisfied(Cand) == true) - verlist.insert(Cand); - for (PrvIterator Prv = Start.TargetPkg().ProvidesList(); Prv.end() != true; ++Prv) - { - pkgCache::VerIterator V = Prv.OwnerVer(); - pkgCache::VerIterator Cand = PkgState[Prv.OwnerPkg()->ID].CandidateVerIter(*this); - if (Cand.end() == true || V != Cand || Start.IsSatisfied(Prv) == false) - continue; - verlist.insert(Cand); - } + pkgCacheFile CacheFile(this); + APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, Start, APT::CacheSetHelper::CANDIDATE); CompareProviders comp(Start); do { diff --git a/apt-private/private-cachefile.h b/apt-private/private-cachefile.h index 4a68d9733..221852629 100644 --- a/apt-private/private-cachefile.h +++ b/apt-private/private-cachefile.h @@ -61,7 +61,7 @@ class APT_PUBLIC CacheFile : public pkgCacheFile }; /*}}}*/ -class APT_PUBLIC SortedPackageUniverse : public APT::PackageUniverse +class SortedPackageUniverse : public APT::PackageUniverse { std::vector &List; void LazyInit() const; @@ -85,12 +85,12 @@ public: }; typedef const_iterator iterator; - APT_PUBLIC const_iterator begin() const { LazyInit(); return const_iterator(data(), List.begin()); } - APT_PUBLIC const_iterator end() const { LazyInit(); return const_iterator(data(), List.end()); } - APT_PUBLIC const_iterator cbegin() const { LazyInit(); return const_iterator(data(), List.begin()); } - APT_PUBLIC const_iterator cend() const { LazyInit(); return const_iterator(data(), List.end()); } - APT_PUBLIC iterator begin() { LazyInit(); return iterator(data(), List.begin()); } - APT_PUBLIC iterator end() { LazyInit(); return iterator(data(), List.end()); } + const_iterator begin() const { LazyInit(); return const_iterator(data(), List.begin()); } + const_iterator end() const { LazyInit(); return const_iterator(data(), List.end()); } + const_iterator cbegin() const { LazyInit(); return const_iterator(data(), List.begin()); } + const_iterator cend() const { LazyInit(); return const_iterator(data(), List.end()); } + iterator begin() { LazyInit(); return iterator(data(), List.begin()); } + iterator end() { LazyInit(); return iterator(data(), List.end()); } }; #endif diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc index 37fae18e9..099146187 100644 --- a/apt-private/private-download.cc +++ b/apt-private/private-download.cc @@ -78,20 +78,23 @@ bool CheckDropPrivsMustBeDisabled(pkgAcquire &Fetcher) /*{{{*/ // CheckAuth - check if each download comes form a trusted source /*{{{*/ bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser) { - std::string UntrustedList; + std::vector UntrustedList; for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I) if (!(*I)->IsTrusted()) - UntrustedList += std::string((*I)->ShortDesc()) + " "; + UntrustedList.push_back((*I)->ShortDesc()); - if (UntrustedList == "") + if (UntrustedList.empty()) return true; return AuthPrompt(UntrustedList, PromptUser); } -bool AuthPrompt(std::string const &UntrustedList, bool const PromptUser) +bool AuthPrompt(std::vector const &UntrustedList, bool const PromptUser) { - ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,""); + ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"), UntrustedList, + [](std::string const&) { return true; }, + [](std::string const&str) { return str; }, + [](std::string const&) { return ""; }); if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true) { diff --git a/apt-private/private-download.h b/apt-private/private-download.h index 0a0ac6b95..0f3db5e7a 100644 --- a/apt-private/private-download.h +++ b/apt-private/private-download.h @@ -4,6 +4,7 @@ #include #include +#include class pkgAcquire; @@ -14,7 +15,7 @@ APT_PUBLIC bool CheckAuth(pkgAcquire& Fetcher, bool const PromptUser); // show a authentication warning prompt and return true if the system // should continue -APT_PUBLIC bool AuthPrompt(std::string const &UntrustedList, bool const PromptUser); +APT_PUBLIC bool AuthPrompt(std::vector const &UntrustedList, bool const PromptUser); APT_PUBLIC bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure); diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index cdca45755..0b5e33ae5 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -330,19 +330,17 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) } std::set const disappearedPkgs = PM->GetDisappearedPackages(); - if (disappearedPkgs.empty() == true) - return true; - - std::string disappear; - for (std::set::const_iterator d = disappearedPkgs.begin(); - d != disappearedPkgs.end(); ++d) - disappear.append(*d).append(" "); - - ShowList(c1out, P_("The following package disappeared from your system as\n" - "all files have been overwritten by other packages:", - "The following packages disappeared from your system as\n" - "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, ""); - c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; + if (disappearedPkgs.empty() == false) + { + ShowList(c1out, P_("The following package disappeared from your system as\n" + "all files have been overwritten by other packages:", + "The following packages disappeared from your system as\n" + "all files have been overwritten by other packages:", disappearedPkgs.size()), disappearedPkgs, + [](std::string const &Pkg) { return Pkg.empty() == false; }, + [](std::string const &Pkg) { return Pkg; }, + [](std::string const &) { return std::string(); }); + c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; + } return true; } @@ -699,8 +697,7 @@ bool DoInstall(CommandLine &CmdL) /* Print out a list of suggested and recommended packages */ { - std::string SuggestsList, RecommendsList; - std::string SuggestsVersions, RecommendsVersions; + std::list Recommends, Suggests, SingleRecommends, SingleSuggests; for (auto const &Pkg: Universe) { /* Just look at the ones we want to install */ @@ -714,77 +711,79 @@ bool DoInstall(CommandLine &CmdL) pkgCache::DepIterator Start; pkgCache::DepIterator End; D.GlobOr(Start,End); // advances D + if (Start->Type != pkgCache::Dep::Recommends && Start->Type != pkgCache::Dep::Suggests) + continue; - // FIXME: we really should display a or-group as a or-group to the user - // the problem is that ShowList is incapable of doing this - std::string RecommendsOrList,RecommendsOrVersions; - std::string SuggestsOrList,SuggestsOrVersions; - bool foundInstalledInOrGroup = false; - for(;;) { - /* Skip if package is installed already, or is about to be */ - pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); - if (TarPkg->SelectedState == pkgCache::State::Install || - TarPkg->SelectedState == pkgCache::State::Hold || - Cache[Start.TargetPkg()].Install()) - { - foundInstalledInOrGroup=true; - break; - } - - /* Skip if we already saw it */ - std::string target = Start.TargetPkg().FullName(true) + " "; - if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1) + // Skip if we already saw this + std::string target; + for (pkgCache::DepIterator I = Start; I != D; ++I) { - foundInstalledInOrGroup=true; - break; + if (target.empty() == false) + target.append(" | "); + target.append(I.TargetPkg().FullName(true)); } + std::list &Type = Start->Type == pkgCache::Dep::Recommends ? SingleRecommends : SingleSuggests; + if (std::find(Type.begin(), Type.end(), target) != Type.end()) + continue; + Type.push_back(target); + } - // this is a dep on a virtual pkg, check if any package that provides it - // should be installed - if(Start.TargetPkg().ProvidesList() != 0) + std::list OrList; + bool foundInstalledInOrGroup = false; + for (pkgCache::DepIterator I = Start; I != D; ++I) + { { - pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList(); - for (; I.end() == false; ++I) + // satisfying package is installed and not marked for deletion + APT::VersionList installed = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::INSTALLED); + if (std::find_if(installed.begin(), installed.end(), + [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Delete() == false; }) != installed.end()) { - pkgCache::PkgIterator Pkg = I.OwnerPkg(); - if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && - Pkg.CurrentVer() != 0) - foundInstalledInOrGroup=true; + foundInstalledInOrGroup = true; + break; } } - if (Start->Type == pkgCache::Dep::Suggests) - { - SuggestsOrList += target; - SuggestsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n"; - } - - if (Start->Type == pkgCache::Dep::Recommends) { - RecommendsOrList += target; - RecommendsOrVersions += std::string(Cache[Start.TargetPkg()].CandVersion) + "\n"; + // satisfying package is upgraded to/new install + APT::VersionList upgrades = APT::VersionList::FromDependency(Cache, I, APT::CacheSetHelper::CANDIDATE); + if (std::find_if(upgrades.begin(), upgrades.end(), + [&Cache](pkgCache::VerIterator const &Ver) { return Cache[Ver.ParentPkg()].Upgrade(); }) != upgrades.end()) + { + foundInstalledInOrGroup = true; + break; + } } - if (Start >= End) - break; - ++Start; + if (OrList.empty()) + OrList.push_back(I.TargetPkg().FullName(true)); + else + OrList.push_back("| " + I.TargetPkg().FullName(true)); } - + if(foundInstalledInOrGroup == false) { - RecommendsList += RecommendsOrList; - RecommendsVersions += RecommendsOrVersions; - SuggestsList += SuggestsOrList; - SuggestsVersions += SuggestsOrVersions; + std::list &Type = Start->Type == pkgCache::Dep::Recommends ? Recommends : Suggests; + std::move(OrList.begin(), OrList.end(), std::back_inserter(Type)); } - } } - - ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions); - ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions); - + auto always_true = [](std::string const&) { return true; }; + auto string_ident = [](std::string const&str) { return str; }; + auto verbose_show_candidate = + [&Cache](std::string str) + { + if (APT::String::Startswith(str, "| ")) + str.erase(0, 2); + pkgCache::PkgIterator const Pkg = Cache->FindPkg(str); + if (Pkg.end() == true) + return ""; + return (*Cache)[Pkg].CandVersion; + }; + ShowList(c1out,_("Suggested packages:"), Suggests, + always_true, string_ident, verbose_show_candidate); + ShowList(c1out,_("Recommended packages:"), Recommends, + always_true, string_ident, verbose_show_candidate); } // See if we need to prompt @@ -792,7 +791,7 @@ bool DoInstall(CommandLine &CmdL) if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0) return InstallPackages(Cache,false,false); - return InstallPackages(Cache,false); + return InstallPackages(Cache,false); } /*}}}*/ diff --git a/apt-private/private-output.cc b/apt-private/private-output.cc index b77efff86..b8e6dec02 100644 --- a/apt-private/private-output.cc +++ b/apt-private/private-output.cc @@ -300,66 +300,6 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, /*{{{*/ out << output; } /*}}}*/ -// ShowList - Show a list /*{{{*/ -// --------------------------------------------------------------------- -/* This prints out a string of space separated words with a title and - a two space indent line wraped to the current screen width. */ -bool ShowList(ostream &out,string Title,string List,string VersionsList) -{ - if (List.empty() == true) - return true; - // trim trailing space - int NonSpace = List.find_last_not_of(' '); - if (NonSpace != -1) - { - List = List.erase(NonSpace + 1); - if (List.empty() == true) - return true; - } - - // Acount for the leading space - int ScreenWidth = ::ScreenWidth - 3; - - out << Title << endl; - string::size_type Start = 0; - string::size_type VersionsStart = 0; - while (Start < List.size()) - { - if(_config->FindB("APT::Get::Show-Versions",false) == true && - VersionsList.size() > 0) { - string::size_type End; - string::size_type VersionsEnd; - - End = List.find(' ',Start); - VersionsEnd = VersionsList.find('\n', VersionsStart); - - out << " " << string(List,Start,End - Start) << " (" << - string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) << - ")" << endl; - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - - Start = End + 1; - VersionsStart = VersionsEnd + 1; - } else { - string::size_type End; - - if (Start + ScreenWidth >= List.size()) - End = List.size(); - else - End = List.rfind(' ',Start+ScreenWidth); - - if (End == string::npos || End < Start) - End = Start + ScreenWidth; - out << " " << string(List,Start,End - Start) << endl; - Start = End + 1; - } - } - - return false; -} - /*}}}*/ // ShowBroken - Debugging aide /*{{{*/ // --------------------------------------------------------------------- /* This prints out the names of all the packages that are broken along diff --git a/apt-private/private-output.h b/apt-private/private-output.h index b9151b245..4930fd981 100644 --- a/apt-private/private-output.h +++ b/apt-private/private-output.h @@ -34,11 +34,11 @@ void ListSingleVersion(pkgCacheFile &CacheFile, pkgRecords &records, APT_PUBLIC void ShowBroken(std::ostream &out, CacheFile &Cache, bool const Now); APT_PUBLIC void ShowBroken(std::ostream &out, pkgCacheFile &Cache, bool const Now); -template APT_PUBLIC bool ShowList(std::ostream &out, std::string const &Title, +template APT_PUBLIC bool ShowList(std::ostream &out, std::string const &Title, Container const &cont, - std::function Predicate, - std::function PkgDisplay, - std::function VerboseDisplay) + PredicateC Predicate, + DisplayP PkgDisplay, + DisplayV VerboseDisplay) { size_t const ScreenWidth = (::ScreenWidth > 3) ? ::ScreenWidth - 3 : 0; int ScreenUsed = 0; @@ -88,8 +88,6 @@ template APT_PUBLIC bool ShowList(std::ostream &out, std::strin } return true; } -APT_DEPRECATED APT_PUBLIC bool ShowList(std::ostream &out, std::string Title, std::string List, - std::string VersionsList); void ShowNew(std::ostream &out,CacheFile &Cache); void ShowDel(std::ostream &out,CacheFile &Cache); @@ -106,12 +104,12 @@ void Stats(std::ostream &out, pkgDepCache &Dep); bool YnPrompt(bool Default=true); bool AnalPrompt(const char *Text); -APT_PUBLIC std::string PrettyFullName(pkgCache::PkgIterator const &Pkg); -APT_PUBLIC std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); -APT_PUBLIC std::function CandidateVersion(pkgCacheFile * const Cache); -APT_PUBLIC std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); -APT_PUBLIC std::function CurrentToCandidateVersion(pkgCacheFile * const Cache); -APT_PUBLIC std::string EmptyString(pkgCache::PkgIterator const &); -APT_PUBLIC bool AlwaysTrue(pkgCache::PkgIterator const &); +std::string PrettyFullName(pkgCache::PkgIterator const &Pkg); +std::string CandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); +std::function CandidateVersion(pkgCacheFile * const Cache); +std::string CurrentToCandidateVersion(pkgCacheFile * const Cache, pkgCache::PkgIterator const &Pkg); +std::function CurrentToCandidateVersion(pkgCacheFile * const Cache); +std::string EmptyString(pkgCache::PkgIterator const &); +bool AlwaysTrue(pkgCache::PkgIterator const &); #endif diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 6fefbde47..ca9650998 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -742,7 +742,7 @@ static bool DoSource(CommandLine &CmdL) // Load the requestd sources into the fetcher unsigned J = 0; - std::string UntrustedList; + std::vector UntrustedList; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; @@ -756,8 +756,8 @@ static bool DoSource(CommandLine &CmdL) } if (Last->Index().IsTrusted() == false) - UntrustedList += Src + " "; - + UntrustedList.push_back(Src); + string srec = Last->AsStr(); string::size_type pos = srec.find("\nVcs-"); while (pos != string::npos) @@ -884,7 +884,7 @@ static bool DoSource(CommandLine &CmdL) CheckDropPrivsMustBeDisabled(Fetcher); // check authentication status of the source as well - if (UntrustedList != "" && !AuthPrompt(UntrustedList, false)) + if (UntrustedList.empty() == false && AuthPrompt(UntrustedList, false) == false) return false; // Run it diff --git a/test/integration/test-apt-showlist-orgroup-in-recommends b/test/integration/test-apt-showlist-orgroup-in-recommends new file mode 100755 index 000000000..bce421ac4 --- /dev/null +++ b/test/integration/test-apt-showlist-orgroup-in-recommends @@ -0,0 +1,158 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework + +setupenvironment +configarchitecture 'i386' + +# simple case +insertinstalledpackage 'aaa' 'all' '1' +insertinstalledpackage 'ddd' 'all' '1' +insertpackage 'unstable' 'aaa' 'all' '1' +insertpackage 'unstable' 'ddd' 'all' '1' +insertpackage 'unstable' 'yyy' 'all' '1' +insertpackage 'unstable' 'zzz' 'all' '1' +insertpackage 'unstable' 'simple' 'all' '1' 'Recommends: aaa, bbb +Suggests: ccc, ddd' +insertpackage 'unstable' 'orgroup' 'all' '1' 'Recommends: aaa | bbb +Suggests: ccc | ddd' +insertpackage 'unstable' 'orgroup2' 'all' '1' 'Recommends: xxx | yyy +Suggests: yyy | zzz' +insertpackage 'unstable' 'orgroup3' 'all' '1' 'Recommends: xxx | yyy +Suggests: yyy | zzz' +insertpackage 'unstable' 'orgroup4' 'all' '1' 'Recommends: xxx +Suggests: zzz' +insertpackage 'unstable' 'versionedor' 'all' '1' 'Recommends: aaa (>> 2) | bbb +Suggests: ccc | ddd (>> 2)' + +setupaptarchive + +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + ccc +Recommended packages: + bbb +The following NEW packages will be installed: + simple +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst simple (1 unstable [all]) +Conf simple (1 unstable [all])' aptget install simple -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + ccc +Recommended packages: + aaa bbb +The following packages will be REMOVED: + aaa +The following NEW packages will be installed: + simple +0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. +Remv aaa [1] +Inst simple (1 unstable [all]) +Conf simple (1 unstable [all])' aptget install simple aaa- -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + orgroup +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup (1 unstable [all]) +Conf orgroup (1 unstable [all])' aptget install orgroup -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Recommended packages: + aaa | bbb +The following packages will be REMOVED: + aaa +The following NEW packages will be installed: + orgroup +0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. +Remv aaa [1] +Inst orgroup (1 unstable [all]) +Conf orgroup (1 unstable [all])' aptget install orgroup aaa- -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + yyy | zzz +Recommended packages: + xxx | yyy +The following NEW packages will be installed: + orgroup2 +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup2 (1 unstable [all]) +Conf orgroup2 (1 unstable [all])' aptget install orgroup2 -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + yyy | zzz +Recommended packages: + xxx | yyy +The following NEW packages will be installed: + orgroup2 orgroup3 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup2 (1 unstable [all]) +Inst orgroup3 (1 unstable [all]) +Conf orgroup2 (1 unstable [all]) +Conf orgroup3 (1 unstable [all])' aptget install orgroup2 orgroup3 -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + yyy | zzz zzz +Recommended packages: + xxx | yyy xxx +The following NEW packages will be installed: + orgroup2 orgroup4 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup2 (1 unstable [all]) +Inst orgroup4 (1 unstable [all]) +Conf orgroup2 (1 unstable [all]) +Conf orgroup4 (1 unstable [all])' aptget install orgroup2 orgroup4 -s --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + yyy (1) + | zzz (1) + zzz (1) +Recommended packages: + xxx + | yyy (1) + xxx +The following NEW packages will be installed: + orgroup2 (1) + orgroup4 (1) +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup2 (1 unstable [all]) +Inst orgroup4 (1 unstable [all]) +Conf orgroup2 (1 unstable [all]) +Conf orgroup4 (1 unstable [all])' aptget install orgroup2 orgroup4 -s -V --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + zzz (1) +Recommended packages: + xxx +The following NEW packages will be installed: + orgroup2 (1) + orgroup4 (1) + yyy (1) +0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Inst orgroup2 (1 unstable [all]) +Inst orgroup4 (1 unstable [all]) +Inst yyy (1 unstable [all]) +Conf orgroup2 (1 unstable [all]) +Conf orgroup4 (1 unstable [all]) +Conf yyy (1 unstable [all])' aptget install orgroup2 orgroup4 yyy -s -V --no-install-recommends +testsuccessequal 'Reading package lists... +Building dependency tree... +Suggested packages: + ccc | ddd +Recommended packages: + aaa | bbb +The following NEW packages will be installed: + versionedor +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst versionedor (1 unstable [all]) +Conf versionedor (1 unstable [all])' aptget install versionedor -s --no-install-recommends diff --git a/test/integration/test-bug-470115-new-and-tighten-recommends b/test/integration/test-bug-470115-new-and-tighten-recommends index 0970e2f23..80f699ef3 100755 --- a/test/integration/test-bug-470115-new-and-tighten-recommends +++ b/test/integration/test-bug-470115-new-and-tighten-recommends @@ -165,6 +165,8 @@ Conf upgrade-over-new (2 unstable [all])' aptget install upgrade-over-new -s # the user doesn't seem to need it so avoid upgrading it testsuccessequal 'Reading package lists... Building dependency tree... +Recommended packages: + cool The following packages will be upgraded: now-satisfiable 1 upgraded, 0 newly installed, 0 to remove and 12 not upgraded. diff --git a/test/integration/test-bug-549968-install-depends-of-not-installed b/test/integration/test-bug-549968-install-depends-of-not-installed index 3ff4807de..1d969fea2 100755 --- a/test/integration/test-bug-549968-install-depends-of-not-installed +++ b/test/integration/test-bug-549968-install-depends-of-not-installed @@ -19,6 +19,8 @@ Building dependency tree... MarkInstall coolstuff [ i386 ] < none -> 1.0 > ( other ) FU=1 Ignore MarkInstall of extracoolstuff [ i386 ] < none -> 1.0 > ( other ) as its mode (Keep) is protected Package 'extracoolstuff' is not installed, so not removed +Recommended packages: + extracoolstuff The following NEW packages will be installed: coolstuff 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. diff --git a/test/integration/test-handling-broken-orgroups b/test/integration/test-handling-broken-orgroups index 149f05fa9..15964a270 100755 --- a/test/integration/test-handling-broken-orgroups +++ b/test/integration/test-handling-broken-orgroups @@ -63,7 +63,7 @@ E: Unable to correct problems, you have held broken packages.' aptget install co testsuccessequal 'Reading package lists... Building dependency tree... Recommended packages: - cool2 stuff2 + cool2 | stuff2 The following NEW packages will be installed: coolstuff-brokenrec 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. diff --git a/test/integration/test-release-candidate-switching b/test/integration/test-release-candidate-switching index a1a6a6142..510a8e078 100755 --- a/test/integration/test-release-candidate-switching +++ b/test/integration/test-release-candidate-switching @@ -370,7 +370,7 @@ The following extra packages will be installed: Recommended packages: amarok-utils (2.3.1-1+sid) phonon-backend-xine (4.6.0really4.4.2-1+sid) - phonon-backend () + | phonon-backend libmtp8 (0.3.1+sid) libc6 (2.11.2-7+sid) The following NEW packages will be installed: diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 759242514..06701c623 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -36,7 +36,7 @@ installaptold() { testsuccessequal 'Reading package lists... Building dependency tree... Suggested packages: - aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt + aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. @@ -49,7 +49,7 @@ installaptnew() { testsuccessequal 'Reading package lists... Building dependency tree... Suggested packages: - aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt + aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. @@ -62,7 +62,7 @@ failaptold() { testfailureequal 'Reading package lists... Building dependency tree... Suggested packages: - aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt + aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. @@ -76,7 +76,7 @@ failaptnew() { testfailureequal 'Reading package lists... Building dependency tree... Suggested packages: - aptitude synaptic wajig dpkg-dev apt-doc bzip2 lzma python-apt + aptitude | synaptic | wajig dpkg-dev apt-doc bzip2 lzma python-apt The following NEW packages will be installed: apt 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. -- cgit v1.2.3-70-g09d2 From fd23676e809b7fa87ae138cc22d2c683d212950e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 13 Jul 2015 12:47:05 +0200 Subject: bunch of micro-optimizations for depcache DepCache functions are called a lot, so if we can squeeze some drops out of them for free we should do so. Takes also the opportunity to remove some whitespace errors from these functions. Git-Dch: Ignore --- apt-pkg/deb/deblistparser.cc | 11 +- apt-pkg/deb/debversion.cc | 47 +++--- apt-pkg/depcache.cc | 170 ++++++++++----------- apt-pkg/depcache.h | 28 ++-- apt-pkg/pkgcache.cc | 21 ++- test/integration/test-apt-cache | 24 +-- .../test-apt-showlist-orgroup-in-recommends | 2 +- 7 files changed, 149 insertions(+), 154 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 4e49e1c78..7c21bd8b3 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -209,23 +209,22 @@ bool debListParser::NewVersion(pkgCache::VerIterator &Ver) Ver->Priority = pkgCache::State::Extra; } - if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) - return false; if (ParseDepends(Ver,"Pre-Depends",pkgCache::Dep::PreDepends) == false) return false; - if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false) - return false; - if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false) + if (ParseDepends(Ver,"Depends",pkgCache::Dep::Depends) == false) return false; if (ParseDepends(Ver,"Conflicts",pkgCache::Dep::Conflicts) == false) return false; if (ParseDepends(Ver,"Breaks",pkgCache::Dep::DpkgBreaks) == false) return false; + if (ParseDepends(Ver,"Recommends",pkgCache::Dep::Recommends) == false) + return false; + if (ParseDepends(Ver,"Suggests",pkgCache::Dep::Suggests) == false) + return false; if (ParseDepends(Ver,"Replaces",pkgCache::Dep::Replaces) == false) return false; if (ParseDepends(Ver,"Enhances",pkgCache::Dep::Enhances) == false) return false; - // Obsolete. if (ParseDepends(Ver,"Optional",pkgCache::Dep::Suggests) == false) return false; diff --git a/apt-pkg/deb/debversion.cc b/apt-pkg/deb/debversion.cc index a5eacb7f5..043025912 100644 --- a/apt-pkg/deb/debversion.cc +++ b/apt-pkg/deb/debversion.cc @@ -34,29 +34,26 @@ debVersioningSystem::debVersioningSystem() // debVS::CmpFragment - Compare versions /*{{{*/ // --------------------------------------------------------------------- -/* This compares a fragment of the version. This is a slightly adapted - version of what dpkg uses. */ -#define order(x) ((x) == '~' ? -1 \ - : isdigit((x)) ? 0 \ - : !(x) ? 0 \ - : isalpha((x)) ? (x) \ - : (x) + 256) -int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, - const char *B,const char *BEnd) +/* This compares a fragment of the version. This is a slightly adapted + version of what dpkg uses in dpkg/lib/dpkg/version.c. + In particular, the a | b = NULL check is removed as we check this in the + caller, we use an explicit end for a | b strings and we check ~ explicit. */ +static int order(char c) { - if (A >= AEnd && B >= BEnd) + if (isdigit(c)) return 0; - if (A >= AEnd) - { - if (*B == '~') return 1; + else if (isalpha(c)) + return c; + else if (c == '~') return -1; - } - if (B >= BEnd) - { - if (*A == '~') return -1; - return 1; - } - + else if (c) + return c + 256; + else + return 0; +} +int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, + const char *B,const char *BEnd) +{ /* Iterate over the whole string What this does is to split the whole string into groups of numeric and non numeric portions. For instance: @@ -77,19 +74,19 @@ int debVersioningSystem::CmpFragment(const char *A,const char *AEnd, int rc = order(*rhs); if (vc != rc) return vc - rc; - lhs++; rhs++; + ++lhs; ++rhs; } while (*lhs == '0') - lhs++; + ++lhs; while (*rhs == '0') - rhs++; + ++rhs; while (isdigit(*lhs) && isdigit(*rhs)) { if (!first_diff) first_diff = *lhs - *rhs; - lhs++; - rhs++; + ++lhs; + ++rhs; } if (isdigit(*lhs)) diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 0e972dbad..6271a024a 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -95,7 +95,7 @@ pkgDepCache::ActionGroup::~ActionGroup() // DepCache::pkgDepCache - Constructors /*{{{*/ // --------------------------------------------------------------------- /* */ -pkgDepCache::pkgDepCache(pkgCache *pCache,Policy *Plcy) : +pkgDepCache::pkgDepCache(pkgCache * const pCache,Policy * const Plcy) : group_level(0), Cache(pCache), PkgState(0), DepState(0), iUsrSize(0), iDownloadSize(0), iInstCount(0), iDelCount(0), iKeepCount(0), iBrokenCount(0), iPolicyBrokenCount(0), iBadCount(0), d(NULL) @@ -121,7 +121,7 @@ pkgDepCache::~pkgDepCache() // DepCache::Init - Generate the initial extra structures. /*{{{*/ // --------------------------------------------------------------------- /* This allocats the extension buffers and initializes them. */ -bool pkgDepCache::Init(OpProgress *Prog) +bool pkgDepCache::Init(OpProgress * const Prog) { // Suppress mark updates during this operation (just in case) and // run a mark operation when Init terminates. @@ -132,7 +132,7 @@ bool pkgDepCache::Init(OpProgress *Prog) PkgState = new StateCache[Head().PackageCount]; DepState = new unsigned char[Head().DependsCount]; memset(PkgState,0,sizeof(*PkgState)*Head().PackageCount); - memset(DepState,0,sizeof(*DepState)*Head().DependsCount); + memset(DepState,0,sizeof(*DepState)*Head().DependsCount); if (Prog != 0) { @@ -140,7 +140,7 @@ bool pkgDepCache::Init(OpProgress *Prog) _("Building dependency tree")); Prog->SubProgress(Head().PackageCount,_("Candidate versions")); } - + /* Set the current state of everything. In this state all of the packages are kept exactly as is. See AllUpgrade */ int Done = 0; @@ -148,7 +148,7 @@ bool pkgDepCache::Init(OpProgress *Prog) { if (Prog != 0 && Done%20 == 0) Prog->Progress(Done); - + // Find the proper cache slot StateCache &State = PkgState[I->ID]; State.iFlags = 0; @@ -157,28 +157,27 @@ bool pkgDepCache::Init(OpProgress *Prog) State.CandidateVer = GetCandidateVer(I); State.InstallVer = I.CurrentVer(); State.Mode = ModeKeep; - + State.Update(I,*this); - } - + } + if (Prog != 0) { - Prog->OverallProgress(Head().PackageCount,2*Head().PackageCount, Head().PackageCount, _("Building dependency tree")); Prog->SubProgress(Head().PackageCount,_("Dependency generation")); } - + Update(Prog); if(Prog != 0) Prog->Done(); return true; -} +} /*}}}*/ -bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ +bool pkgDepCache::readStateFile(OpProgress * const Prog) /*{{{*/ { FileFd state_file; string const state = _config->FindFile("Dir::State::extended_states"); @@ -186,7 +185,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ state_file.Open(state, FileFd::ReadOnly); off_t const file_size = state_file.Size(); if(Prog != NULL) - Prog->OverallProgress(0, file_size, 1, + Prog->OverallProgress(0, file_size, 1, _("Reading state information")); pkgTagFile tagfile(&state_file); @@ -230,7 +229,7 @@ bool pkgDepCache::readStateFile(OpProgress *Prog) /*{{{*/ return true; } /*}}}*/ -bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{{*/ +bool pkgDepCache::writeStateFile(OpProgress * const /*prog*/, bool const InstalledOnly) /*{{{*/ { bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); @@ -340,7 +339,7 @@ bool pkgDepCache::writeStateFile(OpProgress * /*prog*/, bool InstalledOnly) /*{{ then walks along the package provides list and checks if each provides will be installed then checks the provides against the dep. Res will be set to the package which was used to satisfy the dep. */ -bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) +bool pkgDepCache::CheckDep(DepIterator const &Dep,int const Type,PkgIterator &Res) { Res = Dep.TargetPkg(); @@ -351,22 +350,26 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) { PkgIterator Pkg = Dep.TargetPkg(); // Check the base package - if (Type == NowVersion && Pkg->CurrentVer != 0) - if (Dep.IsSatisfied(Pkg.CurrentVer()) == true) + if (Type == NowVersion) + { + if (Pkg->CurrentVer != 0 && Dep.IsSatisfied(Pkg.CurrentVer()) == true) return true; - - if (Type == InstallVersion && PkgState[Pkg->ID].InstallVer != 0) - if (Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true) + } + else if (Type == InstallVersion) + { + if (PkgState[Pkg->ID].InstallVer != 0 && + Dep.IsSatisfied(PkgState[Pkg->ID].InstVerIter(*this)) == true) return true; - - if (Type == CandidateVersion && PkgState[Pkg->ID].CandidateVer != 0) - if (Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true) + } + else if (Type == CandidateVersion) + if (PkgState[Pkg->ID].CandidateVer != 0 && + Dep.IsSatisfied(PkgState[Pkg->ID].CandidateVerIter(*this)) == true) return true; } - + if (Dep->Type == Dep::Obsoletes) return false; - + // Check the providing packages PrvIterator P = Dep.TargetPkg().ProvidesList(); for (; P.end() != true; ++P) @@ -380,21 +383,19 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) if (P.OwnerPkg().CurrentVer() != P.OwnerVer()) continue; } - - if (Type == InstallVersion) + else if (Type == InstallVersion) { StateCache &State = PkgState[P.OwnerPkg()->ID]; if (State.InstallVer != (Version *)P.OwnerVer()) continue; } - - if (Type == CandidateVersion) + else if (Type == CandidateVersion) { StateCache &State = PkgState[P.OwnerPkg()->ID]; if (State.CandidateVer != (Version *)P.OwnerVer()) continue; } - + // Compare the versions. if (Dep.IsSatisfied(P) == true) { @@ -402,7 +403,7 @@ bool pkgDepCache::CheckDep(DepIterator Dep,int Type,PkgIterator &Res) return true; } } - + return false; } /*}}}*/ @@ -484,47 +485,46 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert) { signed char const Add = (Invert == false) ? 1 : -1; StateCache &State = PkgState[Pkg->ID]; - + // The Package is broken (either minimal dep or policy dep) if ((State.DepState & DepInstMin) != DepInstMin) iBrokenCount += Add; if ((State.DepState & DepInstPolicy) != DepInstPolicy) iPolicyBrokenCount += Add; - + // Bad state if (Pkg.State() != PkgIterator::NeedsNothing) iBadCount += Add; - + // Not installed if (Pkg->CurrentVer == 0) { if (State.Mode == ModeDelete && (State.iFlags & Purge) == Purge && Pkg.Purge() == false) iDelCount += Add; - + if (State.Mode == ModeInstall) iInstCount += Add; return; } - + // Installed, no upgrade if (State.Status == 0) - { + { if (State.Mode == ModeDelete) iDelCount += Add; else if ((State.iFlags & ReInstall) == ReInstall) iInstCount += Add; - return; } - + // Alll 3 are possible if (State.Mode == ModeDelete) - iDelCount += Add; - if (State.Mode == ModeKeep) + iDelCount += Add; + else if (State.Mode == ModeKeep) iKeepCount += Add; - if (State.Mode == ModeInstall) + else if (State.Mode == ModeInstall) iInstCount += Add; } /*}}}*/ @@ -535,7 +535,6 @@ void pkgDepCache::AddStates(const PkgIterator &Pkg, bool const Invert) void pkgDepCache::BuildGroupOrs(VerIterator const &V) { unsigned char Group = 0; - for (DepIterator D = V.DependsList(); D.end() != true; ++D) { // Build the dependency state. @@ -545,18 +544,18 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) right sense for a conflicts group */ if (D.IsNegative() == true) State = ~State; - + // Add to the group if we are within an or.. State &= 0x7; Group |= State; State |= Group << 3; if ((D->CompareOp & Dep::Or) != Dep::Or) Group = 0; - + // Invert for Conflicts if (D.IsNegative() == true) State = ~State; - } + } } /*}}}*/ // DepCache::VersionState - Perform a pass over a dependency list /*{{{*/ @@ -565,34 +564,31 @@ void pkgDepCache::BuildGroupOrs(VerIterator const &V) state of the list, filtering it through both a Min check and a Policy check. The return result will have SetMin/SetPolicy low if a check fails. It uses the DepState cache for it's computations. */ -unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check, - unsigned char SetMin, - unsigned char SetPolicy) +unsigned char pkgDepCache::VersionState(DepIterator D, unsigned char const Check, + unsigned char const SetMin, + unsigned char const SetPolicy) const { unsigned char Dep = 0xFF; - while (D.end() != true) { - // Compute a single dependency element (glob or) - DepIterator Start = D; - unsigned char State = 0; - for (bool LastOR = true; D.end() == false && LastOR == true; ++D) - { - State |= DepState[D->ID]; - LastOR = (D->CompareOp & Dep::Or) == Dep::Or; - } - + // the last or-dependency has the state of all previous or'ed + DepIterator Start, End; + D.GlobOr(Start, End); + // ignore if we are called with Dep{Install,…} or DepG{Install,…} + // the later would be more correct, but the first is what we get + unsigned char const State = DepState[End->ID] | (DepState[End->ID] >> 3); + // Minimum deps that must be satisfied to have a working package if (Start.IsCritical() == true) + { if ((State & Check) != Check) - Dep &= ~SetMin; - + return Dep &= ~(SetMin | SetPolicy); + } // Policy deps that must be satisfied to install the package - if (IsImportantDep(Start) == true && + else if (IsImportantDep(Start) == true && (State & Check) != Check) Dep &= ~SetPolicy; } - return Dep; } /*}}}*/ @@ -601,17 +597,17 @@ unsigned char pkgDepCache::VersionState(DepIterator D,unsigned char Check, /* This is the main dependency computation bit. It computes the 3 main results for a dependencys, Now, Install and Candidate. Callers must invert the result if dealing with conflicts. */ -unsigned char pkgDepCache::DependencyState(DepIterator &D) +unsigned char pkgDepCache::DependencyState(DepIterator const &D) { unsigned char State = 0; - + if (CheckDep(D,NowVersion) == true) State |= DepNow; if (CheckDep(D,InstallVersion) == true) State |= DepInstall; if (CheckDep(D,CandidateVersion) == true) State |= DepCVer; - + return State; } /*}}}*/ @@ -620,7 +616,7 @@ unsigned char pkgDepCache::DependencyState(DepIterator &D) /* This determines the combined dependency representation of a package for its two states now and install. This is done by using the pre-generated dependency information. */ -void pkgDepCache::UpdateVerState(PkgIterator Pkg) +void pkgDepCache::UpdateVerState(PkgIterator const &Pkg) { // Empty deps are always true StateCache &State = PkgState[Pkg->ID]; @@ -654,7 +650,7 @@ void pkgDepCache::UpdateVerState(PkgIterator Pkg) // --------------------------------------------------------------------- /* This will figure out the state of all the packages and all the dependencies based on the current policy. */ -void pkgDepCache::Update(OpProgress *Prog) +void pkgDepCache::Update(OpProgress * const Prog) { iUsrSize = 0; iDownloadSize = 0; @@ -1655,10 +1651,10 @@ const char *pkgDepCache::StateCache::StripEpoch(const char *Ver) return 0; // Strip any epoch - for (const char *I = Ver; *I != 0; I++) - if (*I == ':') - return I + 1; - return Ver; + char const * const I = strchr(Ver, ':'); + if (I == nullptr) + return Ver; + return I + 1; } /*}}}*/ // Policy::GetCandidateVer - Returns the Candidate install version /*{{{*/ @@ -1701,17 +1697,17 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk // Policy::IsImportantDep - True if the dependency is important /*{{{*/ // --------------------------------------------------------------------- /* */ -bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) +bool pkgDepCache::Policy::IsImportantDep(DepIterator const &Dep) const { if(Dep.IsCritical()) return true; - else if(Dep->Type == pkgCache::Dep::Recommends) + else if(Dep->Type == pkgCache::Dep::Recommends) { if (InstallRecommends) return true; // we suport a special mode to only install-recommends for certain // sections - // FIXME: this is a meant as a temporarly solution until the + // FIXME: this is a meant as a temporarly solution until the // recommends are cleaned up const char *sec = Dep.ParentVer().Section(); if (sec && ConfigValueInSubTree("APT::Install-Recommends-Sections", sec)) @@ -1757,24 +1753,22 @@ bool pkgDepCache::MarkRequired(InRootSetFunc &userFunc) if (_config->Find("APT::Solver", "internal") != "internal") return true; - bool follow_recommends; - bool follow_suggests; - bool debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); + bool const debug_autoremove = _config->FindB("Debug::pkgAutoRemove",false); // init the states - for(PkgIterator p = PkgBegin(); !p.end(); ++p) + map_id_t const PackagesCount = Head().PackageCount; + for(map_id_t i = 0; i < PackagesCount; ++i) { - PkgState[p->ID].Marked = false; - PkgState[p->ID].Garbage = false; - - // debug output - if(debug_autoremove && PkgState[p->ID].Flags & Flag::Auto) - std::clog << "AutoDep: " << p.FullName() << std::endl; + PkgState[i].Marked = false; + PkgState[i].Garbage = false; } + if (debug_autoremove) + for(PkgIterator p = PkgBegin(); !p.end(); ++p) + if(PkgState[p->ID].Flags & Flag::Auto) + std::clog << "AutoDep: " << p.FullName() << std::endl; - // init vars - follow_recommends = MarkFollowsRecommends(); - follow_suggests = MarkFollowsSuggests(); + bool const follow_recommends = MarkFollowsRecommends(); + bool const follow_suggests = MarkFollowsSuggests(); // do the mark part, this is the core bit of the algorithm for(PkgIterator p = PkgBegin(); !p.end(); ++p) diff --git a/apt-pkg/depcache.h b/apt-pkg/depcache.h index 2c3304ba8..aa281f695 100644 --- a/apt-pkg/depcache.h +++ b/apt-pkg/depcache.h @@ -267,7 +267,7 @@ class pkgDepCache : protected pkgCache::Namespace // Helper functions void BuildGroupOrs(VerIterator const &V); - void UpdateVerState(PkgIterator Pkg); + void UpdateVerState(PkgIterator const &Pkg); // User Policy control class Policy @@ -279,7 +279,7 @@ class pkgDepCache : protected pkgCache::Namespace } virtual VerIterator GetCandidateVer(PkgIterator const &Pkg); - virtual bool IsImportantDep(DepIterator const &Dep); + virtual bool IsImportantDep(DepIterator const &Dep) const; virtual signed short GetPriority(PkgIterator const &Pkg); virtual signed short GetPriority(PkgFileIterator const &File); @@ -323,18 +323,18 @@ class pkgDepCache : protected pkgCache::Namespace Policy *LocalPolicy; // Check for a matching provides - bool CheckDep(DepIterator Dep,int Type,PkgIterator &Res); - inline bool CheckDep(DepIterator Dep,int Type) + bool CheckDep(DepIterator const &Dep,int const Type,PkgIterator &Res); + inline bool CheckDep(DepIterator const &Dep,int const Type) { PkgIterator Res(*this,0); return CheckDep(Dep,Type,Res); } // Computes state information for deps and versions (w/o storing) - unsigned char DependencyState(DepIterator &D); - unsigned char VersionState(DepIterator D,unsigned char Check, - unsigned char SetMin, - unsigned char SetPolicy); + unsigned char DependencyState(DepIterator const &D); + unsigned char VersionState(DepIterator D,unsigned char const Check, + unsigned char const SetMin, + unsigned char const SetPolicy) const; // Recalculates various portions of the cache, call after changing something void Update(DepIterator Dep); // Mostly internal @@ -362,7 +362,7 @@ class pkgDepCache : protected pkgCache::Namespace // Policy implementation inline VerIterator GetCandidateVer(PkgIterator const &Pkg) {return LocalPolicy->GetCandidateVer(Pkg);}; - inline bool IsImportantDep(DepIterator Dep) {return LocalPolicy->IsImportantDep(Dep);}; + inline bool IsImportantDep(DepIterator Dep) const {return LocalPolicy->IsImportantDep(Dep);}; inline Policy &GetPolicy() {return *LocalPolicy;}; // Accessors @@ -471,8 +471,8 @@ class pkgDepCache : protected pkgCache::Namespace unsigned long Depth = 0, bool FromUser = true); // read persistent states - bool readStateFile(OpProgress *prog); - bool writeStateFile(OpProgress *prog, bool InstalledOnly=true); + bool readStateFile(OpProgress * const prog); + bool writeStateFile(OpProgress * const prog, bool const InstalledOnly=true); // Size queries inline signed long long UsrSize() {return iUsrSize;}; @@ -484,11 +484,11 @@ class pkgDepCache : protected pkgCache::Namespace inline unsigned long PolicyBrokenCount() {return iPolicyBrokenCount;}; inline unsigned long BadCount() {return iBadCount;}; - bool Init(OpProgress *Prog); + bool Init(OpProgress * const Prog); // Generate all state information - void Update(OpProgress *Prog = 0); + void Update(OpProgress * const Prog = 0); - pkgDepCache(pkgCache *Cache,Policy *Plcy = 0); + pkgDepCache(pkgCache * const Cache,Policy * const Plcy = 0); virtual ~pkgDepCache(); protected: diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index aebbffe8b..897f1ee2a 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -697,29 +697,34 @@ void pkgCache::DepIterator::GlobOr(DepIterator &Start,DepIterator &End) // --------------------------------------------------------------------- /* Deps like self-conflicts should be ignored as well as implicit conflicts on virtual packages. */ -bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &/*Pkg*/) const +bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const { if (IsNegative() == false) return false; - pkgCache::PkgIterator PP = ParentPkg(); - pkgCache::PkgIterator PT = TargetPkg(); + pkgCache::PkgIterator const PP = ParentPkg(); if (PP->Group != PT->Group) return false; // self-conflict if (PP == PT) return true; - pkgCache::VerIterator PV = ParentVer(); + pkgCache::VerIterator const PV = ParentVer(); // ignore group-conflict on a M-A:same package - but not our implicit dependencies // so that we can have M-A:same packages conflicting with their own real name if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) { // Replaces: ${self}:other ( << ${binary:Version}) - if (S->Type == pkgCache::Dep::Replaces && S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; + if (S->Type == pkgCache::Dep::Replaces) + { + if (S->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) + return false; + } // Breaks: ${self}:other (!= ${binary:Version}) - if (S->Type == pkgCache::Dep::DpkgBreaks && S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; + else if (S->Type == pkgCache::Dep::DpkgBreaks) + { + if (S->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) + return false; + } return true; } diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index 97dc0f939..7da2ab71f 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -56,21 +56,21 @@ testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive uns testsuccessequal 'foo Depends: bar - |Recommends: - Recommends: Conflicts: - Conflicts: ' aptcache depends foo + Conflicts: + |Recommends: + Recommends: ' aptcache depends foo testsuccessequal 'foo Depends: bar - Recommends: Conflicts: - Conflicts: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 + Conflicts: + Recommends: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 testsuccessequal 'foo Depends: bar - |Recommends: (>= 2) - Recommends: (<< 5) Conflicts: - Conflicts: ' aptcache depends foo -o APT::Cache::ShowVersion=1 + Conflicts: + |Recommends: (>= 2) + Recommends: (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 testsuccessequal 'foo Depends: bar Conflicts: @@ -82,20 +82,20 @@ testsuccessequal 'foo Conflicts: ' aptcache depends foo --important --no-depends --conflicts testsuccessequal 'foo Depends: bar - |Recommends: - Recommends: Conflicts: Conflicts: + |Recommends: + Recommends: bar Depends: bar Breaks: foo Breaks: Replaces: foo Replaces: - - + + ' aptcache depends foo --recurse testsuccessequal 'foo Depends: bar diff --git a/test/integration/test-apt-showlist-orgroup-in-recommends b/test/integration/test-apt-showlist-orgroup-in-recommends index bce421ac4..929f7feb9 100755 --- a/test/integration/test-apt-showlist-orgroup-in-recommends +++ b/test/integration/test-apt-showlist-orgroup-in-recommends @@ -13,7 +13,7 @@ insertinstalledpackage 'ddd' 'all' '1' insertpackage 'unstable' 'aaa' 'all' '1' insertpackage 'unstable' 'ddd' 'all' '1' insertpackage 'unstable' 'yyy' 'all' '1' -insertpackage 'unstable' 'zzz' 'all' '1' +insertpackage 'unstable' 'zzz' 'all' '1:1' insertpackage 'unstable' 'simple' 'all' '1' 'Recommends: aaa, bbb Suggests: ccc, ddd' insertpackage 'unstable' 'orgroup' 'all' '1' 'Recommends: aaa | bbb -- cgit v1.2.3-70-g09d2 From b291aa59ee63983204d8aeb166c388b1f97edce7 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Tue, 14 Jul 2015 13:41:11 +0200 Subject: link DependencyData structs together Cache generation needs a way of quickly iterating over the unique potion of the dependencies to be able to share them. By linking them together we can reduce the speed penality (~ 80%) with only a small reduction in saved size (~ 20%). Git-Dch: Ignore --- apt-pkg/cacheiterators.h | 5 +-- apt-pkg/pkgcache.h | 4 ++- apt-pkg/pkgcachegen.cc | 77 ++++++++++++++++++++--------------------- test/integration/test-apt-cache | 8 ++--- 4 files changed, 47 insertions(+), 47 deletions(-) (limited to 'test') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 82c5d082b..4173326ca 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -318,11 +318,12 @@ class pkgCache::DepIterator : public Iterator { map_pointer_t &DependencyData; map_pointer_t &NextRevDepends; map_pointer_t &NextDepends; + map_pointer_t &NextData; DependencyProxy const * operator->() const { return this; } DependencyProxy * operator->() { return this; } }; - inline DependencyProxy operator->() const {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends };} - inline DependencyProxy operator->() {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends };} + inline DependencyProxy operator->() const {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };} + inline DependencyProxy operator->() {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };} void ReMap(void const * const oldMap, void const * const newMap) { Iterator::ReMap(oldMap, newMap); diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 41709eae8..b3a2e3184 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -366,7 +366,7 @@ struct pkgCache::Header the same number of pools as there are structure types. The generator stores this information so future additions can make use of any unused pool blocks. */ - DynamicMMap::Pool Pools[9]; + DynamicMMap::Pool Pools[12]; /** \brief hash tables providing rapid group/package name lookup @@ -731,6 +731,8 @@ struct pkgCache::DependencyData If the high bit is set then it is a logical OR with the previous record. */ unsigned char CompareOp; + + map_pointer_t NextData; }; struct pkgCache::Dependency { diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index d5b282007..a82483d15 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -952,33 +952,30 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, bool isDuplicate = false; map_pointer_t DependencyData = 0; - map_pointer_t * PkgRevDepends = &Pkg->RevDepends; - map_pointer_t previous_id = 0; - - while (*PkgRevDepends != 0) + map_pointer_t PreviousData = 0; + if (Pkg->RevDepends != 0) { - pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends; - PkgRevDepends = &L->NextRevDepends; - if (L->DependencyData == previous_id) - break; - previous_id = L->DependencyData; - pkgCache::DependencyData const * const D = Cache.DepDataP + previous_id; - if (D->Type == Type && D->CompareOp == Op && D->Version == Version) - { - DependencyData = previous_id; - isDuplicate = true; - break; - } + pkgCache::Dependency const * const L = Cache.DepP + Pkg->RevDepends; + DependencyData = L->DependencyData; + do { + pkgCache::DependencyData const * const D = Cache.DepDataP + DependencyData; + if (Version > D->Version) + break; + if (D->Version == Version && D->Type == Type && D->CompareOp == Op) + { + isDuplicate = true; + break; + } + PreviousData = DependencyData; + DependencyData = D->NextData; + } while (DependencyData != 0); } if (isDuplicate == false) { - void const * const oldMap2 = Map.Data(); DependencyData = AllocateInMap(sizeof(pkgCache::DependencyData)); if (unlikely(DependencyData == 0)) return false; - if (oldMap2 != Map.Data()) - PkgRevDepends += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap2; } pkgCache::Dependency * Link = Cache.DepP + Dependency; @@ -987,7 +984,6 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, Link->ID = Cache.HeaderP->DependsCount++; pkgCache::DepIterator Dep(Cache, Link); - Dynamic DynDep(Dep); if (isDuplicate == false) { Dep->Type = Type; @@ -995,31 +991,32 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, Dep->Version = Version; Dep->Package = Pkg.Index(); ++Cache.HeaderP->DependsDataCount; - Link->NextRevDepends = Pkg->RevDepends; - Pkg->RevDepends = Dependency; + if (PreviousData != 0) + { + pkgCache::DependencyData * const D = Cache.DepDataP + PreviousData; + Dep->NextData = D->NextData; + D->NextData = DependencyData; + } + else if (Pkg->RevDepends != 0) + { + pkgCache::Dependency const * const D = Cache.DepP + Pkg->RevDepends; + Dep->NextData = D->DependencyData; + } + } + + if (isDuplicate == true || PreviousData != 0) + { + pkgCache::Dependency * const L = Cache.DepP + Pkg->RevDepends; + Link->NextRevDepends = L->NextRevDepends; + L->NextRevDepends = Dependency; } else { - // dependency data is already fine, we just set the reverse link - // and in such a way that the loop above can finish fast, so we keep - // non-duplicates at the front and for the duplicates we: - // a) move to the end of the list, b) insert before another own duplicate - // or c) find two duplicates behind each other. - map_pointer_t const own_id = Link->DependencyData; - while (*PkgRevDepends != 0) - { - pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends; - PkgRevDepends = &L->NextRevDepends; - if (L->DependencyData == own_id || L->DependencyData == previous_id) - { - Link->NextRevDepends = L->NextRevDepends; - break; - } - previous_id = L->DependencyData; - } - *PkgRevDepends = Dependency; + Link->NextRevDepends = Pkg->RevDepends; + Pkg->RevDepends = Dependency; } + // Do we know where to link the Dependency to? if (OldDepLast == NULL) { diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index 7da2ab71f..a22b08c20 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -113,12 +113,12 @@ Reverse Depends: bar' aptcache rdepends foo testsuccessequal 'foo Reverse Depends: - Replaces: bar - Breaks: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 + Breaks: bar + Replaces: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 testsuccessequal 'foo Reverse Depends: - Replaces: bar (<< 1) - Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 + Breaks: bar (<< 1) + Replaces: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 testsuccessequal 'foo Reverse Depends: Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks -- cgit v1.2.3-70-g09d2 From 8c7af4d4c95d0423fbd0f3baa979792504f4f45f Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Jul 2015 11:15:25 +0200 Subject: hide implicit deps in apt-cache again by default Before MultiArch implicits weren't a thing, so they were hidden by default by definition. Adding them for MultiArch solved many problems, but having no reliable way of detecting which dependency (and provides) is implicit or not causes problems everytime we want to output dependencies without confusing our observers with unneeded implementation details. The really notworthy point here is actually that we keep now a better record of how a dependency came to be so that we can later reason about it more easily, but that is hidden so deep down in the library internals that change is more the problems it solves than the change itself. --- apt-pkg/cacheiterators.h | 18 ++++- apt-pkg/deb/deblistparser.cc | 8 +-- apt-pkg/edsp.cc | 8 +-- apt-pkg/pkgcache.cc | 61 +++++------------ apt-pkg/pkgcache.h | 16 +++-- apt-pkg/pkgcachegen.cc | 32 ++++----- apt-pkg/pkgcachegen.h | 15 +++-- apt-private/private-cmndline.cc | 1 + cmdline/apt-cache.cc | 11 ++- doc/apt-cache.8.xml | 15 ++++- test/integration/test-apt-cache | 78 ++++++++++++++++++++-- .../test-ordering-ignore-not-matching-breaks | 56 ---------------- 12 files changed, 169 insertions(+), 150 deletions(-) delete mode 100755 test/integration/test-ordering-ignore-not-matching-breaks (limited to 'test') diff --git a/apt-pkg/cacheiterators.h b/apt-pkg/cacheiterators.h index 7e6adb92f..1063d6f9e 100644 --- a/apt-pkg/cacheiterators.h +++ b/apt-pkg/cacheiterators.h @@ -295,7 +295,16 @@ class pkgCache::DepIterator : public Iterator { bool IsNegative() const APT_PURE; bool IsIgnorable(PrvIterator const &Prv) const APT_PURE; bool IsIgnorable(PkgIterator const &Pkg) const APT_PURE; - bool IsMultiArchImplicit() const APT_PURE; + /* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding dependencies to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ + inline bool IsMultiArchImplicit() const APT_PURE { + return (S2->CompareOp & pkgCache::Dep::MultiArchImplicit) == pkgCache::Dep::MultiArchImplicit; + } + /* This covers additionally negative dependencies, which aren't arch-specific, + but change architecture nontheless as a Conflicts: foo does applies for all archs */ + bool IsImplicit() const APT_PURE; + bool IsSatisfied(VerIterator const &Ver) const APT_PURE; bool IsSatisfied(PrvIterator const &Prv) const APT_PURE; void GlobOr(DepIterator &Start,DepIterator &End); @@ -367,7 +376,12 @@ class pkgCache::PrvIterator : public Iterator { inline VerIterator OwnerVer() const {return VerIterator(*Owner,Owner->VerP + S->Version);} inline PkgIterator OwnerPkg() const {return PkgIterator(*Owner,Owner->PkgP + Owner->VerP[S->Version].ParentPkg);} - bool IsMultiArchImplicit() const APT_PURE; + /* MultiArch can be translated to SingleArch for an resolver and we did so, + by adding provides to help the resolver understand the problem, but + sometimes it is needed to identify these to ignore them… */ + bool IsMultiArchImplicit() const APT_PURE + { return (S->Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; } + inline PrvIterator() : Iterator(), Type(PrvVer) {} inline PrvIterator(pkgCache &Owner, Provides *Trg, Version*) : diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index e57a3524f..df0879641 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -812,7 +812,7 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, // … but this is probably the best thing to do. if (Arch == "native") Arch = _config->Find("APT::Architecture"); - if (NewDepends(Ver,Package,Arch,Version,Op,Type) == false) + if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false) return false; } else @@ -858,13 +858,13 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) } else if (archfound != string::npos) { string OtherArch = Package.substr(archfound+1, string::npos); Package = Package.substr(0, archfound); - if (NewProvides(Ver, Package, OtherArch, Version) == false) + if (NewProvides(Ver, Package, OtherArch, Version, pkgCache::Flag::ArchSpecific) == false) return false; } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { if (NewProvidesAllArch(Ver, Package, Version) == false) return false; } else { - if (NewProvides(Ver, Package, Arch, Version) == false) + if (NewProvides(Ver, Package, Arch, Version, 0) == false) return false; } @@ -890,7 +890,7 @@ bool debListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const for (std::vector::const_iterator a = Architectures.begin(); a != Architectures.end(); ++a) { - if (NewProvides(Ver, Package, *a, Version) == false) + if (NewProvides(Ver, Package, *a, Version, pkgCache::Flag::MultiArchImplicit) == false) return false; } return true; diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index 5c53581fe..34b0b0cc7 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -102,11 +102,11 @@ static void WriteScenarioDependency( FILE* output, pkgCache::VerIterator const & bool orGroup = false; for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) { - if (Dep.IsMultiArchImplicit() == true) + if (Dep.IsImplicit() == true) continue; if (orGroup == false) dependencies[Dep->Type].append(", "); - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific)); if (Dep->Version != 0) dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) @@ -140,7 +140,7 @@ static void WriteScenarioLimitedDependency(FILE* output, bool orGroup = false; for (pkgCache::DepIterator Dep = Ver.DependsList(); Dep.end() == false; ++Dep) { - if (Dep.IsMultiArchImplicit() == true) + if (Dep.IsImplicit() == true) continue; if (orGroup == false) { @@ -156,7 +156,7 @@ static void WriteScenarioLimitedDependency(FILE* output, orGroup = false; continue; } - dependencies[Dep->Type].append(Dep.TargetPkg().Name()); + dependencies[Dep->Type].append(Dep.TargetPkg().FullName((Dep->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific)); if (Dep->Version != 0) dependencies[Dep->Type].append(" (").append(pkgCache::CompTypeDeb(Dep->CompareOp)).append(" ").append(Dep.TargetVer()).append(")"); if ((Dep->CompareOp & pkgCache::Dep::Or) == pkgCache::Dep::Or) diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 5034ee38a..e8c95738e 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -727,21 +727,7 @@ bool pkgCache::DepIterator::IsIgnorable(PkgIterator const &PT) const // ignore group-conflict on a M-A:same package - but not our implicit dependencies // so that we can have M-A:same packages conflicting with their own real name if ((PV->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) - { - // Replaces: ${self}:other ( << ${binary:Version}) - if (S2->Type == pkgCache::Dep::Replaces) - { - if (S2->CompareOp == pkgCache::Dep::Less && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - } - // Breaks: ${self}:other (!= ${binary:Version}) - else if (S2->Type == pkgCache::Dep::DpkgBreaks) - { - if (S2->CompareOp == pkgCache::Dep::NotEquals && strcmp(PV.VerStr(), TargetVer()) == 0) - return false; - } - return true; - } + return IsMultiArchImplicit() == false; return false; } @@ -756,27 +742,12 @@ bool pkgCache::DepIterator::IsIgnorable(PrvIterator const &Prv) const if (Prv.OwnerPkg()->Group == Pkg->Group) return true; // Implicit group-conflicts should not be applied on providers of other groups - if (Pkg->Group == TargetPkg()->Group && Prv.OwnerPkg()->Group != Pkg->Group) + if (IsMultiArchImplicit() && Prv.OwnerPkg()->Group != Pkg->Group) return true; return false; } /*}}}*/ -// DepIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ -// --------------------------------------------------------------------- -/* MultiArch can be translated to SingleArch for an resolver and we did so, - by adding dependencies to help the resolver understand the problem, but - sometimes it is needed to identify these to ignore them… */ -bool pkgCache::DepIterator::IsMultiArchImplicit() const -{ - if (ParentPkg()->Arch != TargetPkg()->Arch && - (S2->Type == pkgCache::Dep::Replaces || - S2->Type == pkgCache::Dep::DpkgBreaks || - S2->Type == pkgCache::Dep::Conflicts)) - return true; - return false; -} - /*}}}*/ // DepIterator::IsSatisfied - check if a version satisfied the dependency /*{{{*/ bool pkgCache::DepIterator::IsSatisfied(VerIterator const &Ver) const { @@ -787,6 +758,20 @@ bool pkgCache::DepIterator::IsSatisfied(PrvIterator const &Prv) const return Owner->VS->CheckDep(Prv.ProvideVersion(),S2->CompareOp,TargetVer()); } /*}}}*/ +// DepIterator::IsImplicit - added by the cache generation /*{{{*/ +bool pkgCache::DepIterator::IsImplicit() const +{ + if (IsMultiArchImplicit() == true) + return true; + if (IsNegative() || S2->Type == pkgCache::Dep::Replaces) + { + if ((S2->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific && + strcmp(ParentPkg().Arch(), TargetPkg().Arch()) != 0) + return true; + } + return false; +} + /*}}}*/ // ostream operator to handle string representation of a dependecy /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1067,19 +1052,5 @@ pkgCache::DescIterator pkgCache::VerIterator::TranslatedDescription() const } /*}}}*/ -// PrvIterator::IsMultiArchImplicit - added by the cache generation /*{{{*/ -// --------------------------------------------------------------------- -/* MultiArch can be translated to SingleArch for an resolver and we did so, - by adding provides to help the resolver understand the problem, but - sometimes it is needed to identify these to ignore them… */ -bool pkgCache::PrvIterator::IsMultiArchImplicit() const -{ - pkgCache::PkgIterator const Owner = OwnerPkg(); - pkgCache::PkgIterator const Parent = ParentPkg(); - if (strcmp(Owner.Arch(), Parent.Arch()) != 0 || Owner.Group()->Name == Parent.Group()->Name) - return true; - return false; -} - /*}}}*/ pkgCache::~pkgCache() {} diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index fba692982..8a726085e 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -149,8 +149,12 @@ class pkgCache /*{{{*/ The lower 4 bits are used to indicate what operator is being specified and the upper 4 bits are flags. OR indicates that the next package is or'd with the current package. */ - enum DepCompareOp {Or=0x10,NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3, - Greater=0x4,Equals=0x5,NotEquals=0x6}; + enum DepCompareOp {NoOp=0,LessEq=0x1,GreaterEq=0x2,Less=0x3, + Greater=0x4,Equals=0x5,NotEquals=0x6, + Or=0x10, /*!< or'ed with the next dependency */ + MultiArchImplicit=0x20, /*!< generated internally, not spelled out in the index */ + ArchSpecific=0x40 /*!< was decorated with an explicit architecture in index */ + }; }; struct State @@ -178,6 +182,10 @@ class pkgCache /*{{{*/ NotAutomatic=(1<<0), /*!< archive has a default pin of 1 */ ButAutomaticUpgrades=(1<<1), /*!< (together with the previous) archive has a default pin of 100 */ }; + enum ProvidesFlags { + MultiArchImplicit=pkgCache::Dep::MultiArchImplicit, /*!< generated internally, not spelled out in the index */ + ArchSpecific=pkgCache::Dep::ArchSpecific /*!< was decorated with an explicit architecture in index */ + }; }; protected: @@ -725,9 +733,9 @@ struct pkgCache::Provides /** \brief version in the provides line (if any) This version allows dependencies to depend on specific versions of a - Provides, as well as allowing Provides to override existing packages. - This is experimental. Note that Debian doesn't allow versioned provides */ + Provides, as well as allowing Provides to override existing packages. */ map_stringitem_t ProvideVersion; + map_flags_t Flags; /** \brief next provides (based of package) */ map_pointer_t NextProvides; // Provides /** \brief next provides (based of version) */ diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index a82483d15..9acb2563a 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -709,16 +709,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::GrpIterator &G, { // Replaces: ${self}:other ( << ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::Less, pkgCache::Dep::Replaces, + pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, + pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other NewDepends(D, V, 0, - pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, + pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts, OldDepLast); } } @@ -737,16 +737,16 @@ bool pkgCacheGenerator::AddImplicitDepends(pkgCache::VerIterator &V, map_stringitem_t const VerStrIdx = V->VerStr; // Replaces: ${self}:other ( << ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::Less, pkgCache::Dep::Replaces, + pkgCache::Dep::Less | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Replaces, OldDepLast); // Breaks: ${self}:other (!= ${binary:Version}) NewDepends(D, V, VerStrIdx, - pkgCache::Dep::NotEquals, pkgCache::Dep::DpkgBreaks, + pkgCache::Dep::NotEquals | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::DpkgBreaks, OldDepLast); } else { // Conflicts: ${self}:other NewDepends(D, V, 0, - pkgCache::Dep::NoOp, pkgCache::Dep::Conflicts, + pkgCache::Dep::NoOp | pkgCache::Dep::MultiArchImplicit, pkgCache::Dep::Conflicts, OldDepLast); } return true; @@ -913,8 +913,8 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, string const &Version, - unsigned int const &Op, - unsigned int const &Type, + uint8_t const Op, + uint8_t const Type, map_stringitem_t* &OldDepLast) { map_stringitem_t index = 0; @@ -940,8 +940,8 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, map_pointer_t const Version, - unsigned int const &Op, - unsigned int const &Type, + uint8_t const Op, + uint8_t const Type, map_pointer_t* &OldDepLast) { void const * const oldMap = Map.Data(); @@ -1040,8 +1040,8 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, const string &PackageName, const string &Arch, const string &Version, - unsigned int Op, - unsigned int Type) + uint8_t const Op, + uint8_t const Type) { pkgCache::GrpIterator Grp; Dynamic DynGrp(Grp); @@ -1073,12 +1073,11 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, } /*}}}*/ // ListParser::NewProvides - Create a Provides element /*{{{*/ -// --------------------------------------------------------------------- -/* */ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, - const string &PkgName, + const string &PkgName, const string &PkgArch, - const string &Version) + const string &Version, + uint8_t const Flags) { pkgCache &Cache = Owner->Cache; @@ -1097,6 +1096,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); Dynamic DynPrv(Prv); Prv->Version = Ver.Index(); + Prv->Flags = Flags; Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); if (Version.empty() == false) { diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index c56b5abae..c5527ff30 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -82,11 +82,11 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List); bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - std::string const &Version, unsigned int const &Op, - unsigned int const &Type, map_pointer_t* &OldDepLast); + std::string const &Version, uint8_t const Op, + uint8_t const Type, map_pointer_t* &OldDepLast); bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - map_pointer_t const Version, unsigned int const &Op, - unsigned int const &Type, map_pointer_t* &OldDepLast); + map_pointer_t const Version, uint8_t const Op, + uint8_t const Type, map_pointer_t* &OldDepLast); map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr,map_pointer_t const Next) APT_DEPRECATED { return NewVersion(Ver, VerStr, 0, 0, Next); } map_pointer_t NewVersion(pkgCache::VerIterator &Ver,const std::string &VerStr, @@ -162,10 +162,11 @@ class APT_HIDDEN pkgCacheGenerator::ListParser inline map_stringitem_t WriteString(const std::string &S) {return Owner->WriteStringInMap(S);}; inline map_stringitem_t WriteString(const char *S,unsigned int Size) {return Owner->WriteStringInMap(S,Size);}; bool NewDepends(pkgCache::VerIterator &Ver,const std::string &Package, const std::string &Arch, - const std::string &Version,unsigned int Op, - unsigned int Type); + const std::string &Version,uint8_t const Op, + uint8_t const Type); bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName, - const std::string &PkgArch, const std::string &Version); + const std::string &PkgArch, const std::string &Version, + uint8_t const Flags); public: diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index 71dceb559..cfdc13259 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -51,6 +51,7 @@ static bool addArgumentsAPTCache(std::vector &Args, char cons addArg(0, "conflicts", "APT::Cache::ShowConflicts", 0); addArg(0, "enhances", "APT::Cache::ShowEnhances", 0); addArg(0, "recurse", "APT::Cache::RecurseDepends", 0); + addArg(0, "implicit", "APT::Cache::ShowImplicit", 0); } else if (CmdMatches("search")) { diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 2fc721f69..1eb891e8e 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -689,6 +689,7 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends) bool const ShowBreaks = _config->FindB("APT::Cache::ShowBreaks", Important == false); bool const ShowEnhances = _config->FindB("APT::Cache::ShowEnhances", Important == false); bool const ShowOnlyFirstOr = _config->FindB("APT::Cache::ShowOnlyFirstOr", false); + bool const ShowImplicit = _config->FindB("APT::Cache::ShowImplicit", false); while (verset.empty() != true) { @@ -709,12 +710,16 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends) case pkgCache::Dep::Depends: if (!ShowDepends) continue; break; case pkgCache::Dep::Recommends: if (!ShowRecommends) continue; break; case pkgCache::Dep::Suggests: if (!ShowSuggests) continue; break; - case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break; case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break; + case pkgCache::Dep::Replaces: if (!ShowReplaces) continue; break; + case pkgCache::Dep::Conflicts: if (!ShowConflicts) continue; break; case pkgCache::Dep::DpkgBreaks: if (!ShowBreaks) continue; break; case pkgCache::Dep::Enhances: if (!ShowEnhances) continue; break; } + if (ShowImplicit == false && D.IsImplicit()) + continue; pkgCache::PkgIterator Trg = RevDepends ? D.ParentPkg() : D.TargetPkg(); + bool const showNoArch = RevDepends || (D->CompareOp & pkgCache::Dep::ArchSpecific) != pkgCache::Dep::ArchSpecific; if((Installed && Trg->CurrentVer != 0) || !Installed) { @@ -728,9 +733,9 @@ static bool ShowDepends(CommandLine &CmdL, bool const RevDepends) if (ShowDepType == true) cout << D.DepType() << ": "; if (Trg->VersionList == 0) - cout << "<" << Trg.FullName(true) << ">"; + cout << "<" << Trg.FullName(showNoArch) << ">"; else - cout << Trg.FullName(true); + cout << Trg.FullName(showNoArch); if (ShowVersion == true && D->Version != 0) cout << " (" << pkgCache::CompTypeDeb(D->CompareOp) << ' ' << D.TargetVer() << ')'; cout << std::endl; diff --git a/doc/apt-cache.8.xml b/doc/apt-cache.8.xml index a9f6c8da2..e20f66770 100644 --- a/doc/apt-cache.8.xml +++ b/doc/apt-cache.8.xml @@ -281,12 +281,23 @@ Reverse Provides: - Per default the depends and - rdepends print all dependencies. This can be tweaked with + Per default the depends and + rdepends print all dependencies. This can be tweaked with these flags which will omit the specified dependency type. Configuration Item: APT::Cache::ShowDependencyType e.g. APT::Cache::ShowRecommends. + + + Per default depends and rdepends + print only dependencies explicitly expressed in the metadata. With this flag + it will also show dependencies implicitely added based on the encountered data. + A Conflicts: foo e.g. expresses implicitely that this package + also conflicts with the package foo from any other architecture. + Configuration Item: APT::Cache::ShowImplicit. + + + Print full package records when searching. Configuration Item: APT::Cache::ShowFull. diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index a22b08c20..a8ddfd889 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -16,6 +16,9 @@ Recommends: cool (>= 2) | cooler (<< 5)' "$DESCR" insertpackage 'unstable' 'bar' 'all' '1' 'Depends: bar Breaks: foo (<< 1) Replaces: foo (<< 1)' "$DESCR" +insertpackage 'unstable' 'specific' 'all' '1' 'Depends: bar:i386, specific:amd64 +Breaks: foo:amd64 (<< 1) +Replaces: foo:i386 (<< 1)' "$DESCR" setupaptarchive @@ -44,6 +47,7 @@ testsuccess test -s dump.output testsuccessequal 'dpkg bar +specific fancy foo' aptcache pkgnames testsuccessequal 'bar' aptcache pkgnames bar @@ -57,29 +61,60 @@ testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive uns testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: Recommends: ' aptcache depends foo testsuccessequal 'foo Depends: bar Conflicts: Conflicts: + |Recommends: + Recommends: ' aptcache depends foo --implicit +testsuccessequal 'foo + Depends: bar + Conflicts: Recommends: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 testsuccessequal 'foo Depends: bar Conflicts: Conflicts: + Recommends: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit +testsuccessequal 'foo + Depends: bar + Conflicts: |Recommends: (>= 2) Recommends: (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: ' aptcache depends foo --no-recommends + Conflicts: + |Recommends: (>= 2) + Recommends: (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit testsuccessequal 'foo - Depends: bar' aptcache depends foo --important + Depends: bar + Conflicts: ' aptcache depends foo --no-recommends +testsuccessequal 'foo + Depends: bar + Conflicts: + Conflicts: ' aptcache depends foo --no-recommends --implicit +testsuccessequal 'foo + Depends: bar' aptcache depends foo --important --implicit testsuccessequal 'foo + Conflicts: ' aptcache depends foo --important --no-depends --conflicts +testsuccessequal 'foo + Conflicts: + Conflicts: ' aptcache depends foo --important --no-depends --conflicts --implicit +testsuccessequal 'foo + Depends: bar Conflicts: - Conflicts: ' aptcache depends foo --important --no-depends --conflicts + |Recommends: + Recommends: +bar + Depends: bar + Breaks: foo + Replaces: foo + + +' aptcache depends foo --recurse testsuccessequal 'foo Depends: bar Conflicts: @@ -96,29 +131,58 @@ bar -' aptcache depends foo --recurse +' aptcache depends foo --recurse --implicit +testsuccessequal 'foo + Depends: bar +bar + Depends: bar + Replaces: foo' aptcache depends foo --recurse --important --replaces testsuccessequal 'foo Depends: bar bar Depends: bar Replaces: foo Replaces: -' aptcache depends foo --recurse --important --replaces +' aptcache depends foo --recurse --important --replaces --implicit +testsuccessequal 'bar + Depends: bar + Breaks: foo + Replaces: foo' aptcache depends bar +testsuccessequal 'bar + Depends: bar + Breaks: foo + Breaks: + Replaces: foo + Replaces: ' aptcache depends bar --implicit +testsuccessequal 'specific + Depends: + Depends: specific:amd64 + Breaks: foo:amd64 + Replaces: ' aptcache depends specific +testsuccessequal 'specific + Depends: + Depends: specific:amd64 + Breaks: foo:amd64 + Replaces: ' aptcache depends specific --implicit ## rdpends testsuccessequal 'foo Reverse Depends: bar + specific bar' aptcache rdepends foo testsuccessequal 'foo Reverse Depends: Breaks: bar + Breaks: specific Replaces: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 testsuccessequal 'foo Reverse Depends: Breaks: bar (<< 1) + Breaks: specific (<< 1) Replaces: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 testsuccessequal 'foo Reverse Depends: - Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks + Breaks: bar (<< 1) + Breaks: specific (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks diff --git a/test/integration/test-ordering-ignore-not-matching-breaks b/test/integration/test-ordering-ignore-not-matching-breaks deleted file mode 100755 index 7c1365bdd..000000000 --- a/test/integration/test-ordering-ignore-not-matching-breaks +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -set -e - -TESTDIR=$(readlink -f $(dirname $0)) -. $TESTDIR/framework -setupenvironment -configarchitecture 'amd64' 'i386' - -insertpackage 'unstable-mp' 'crda' 'i386,amd64' '1.1.1-1ubuntu4mp' 'Provides: wireless-crda -Multi-Arch: foreign' -insertpackage 'unstable-m' 'crda' 'i386,amd64' '1.1.1-1ubuntu4m' 'Multi-Arch: foreign' -insertpackage 'unstable-p' 'crda' 'i386,amd64' '1.1.1-1ubuntu4p' 'Provides: wireless-crda' -insertpackage 'unstable' 'wireless-crda' 'i386,amd64' '1.16' - - -insertinstalledpackage 'wireless-crda' 'amd64' '1.14' - -setupaptarchive - -testsuccessequal 'Reading package lists... -Building dependency tree... -The following NEW packages will be installed: - crda -0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. -Inst crda (1.1.1-1ubuntu4m unstable-m [amd64]) -Conf crda (1.1.1-1ubuntu4m unstable-m [amd64])' aptget install crda -s -t unstable-m - -testsuccessequal 'Reading package lists... -Building dependency tree... -The following NEW packages will be installed: - crda -0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. -Inst crda (1.1.1-1ubuntu4p unstable-p [amd64]) -Conf crda (1.1.1-1ubuntu4p unstable-p [amd64])' aptget install crda -s -t unstable-p - -testsuccessequal 'Reading package lists... -Building dependency tree... -The following NEW packages will be installed: - crda -0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. -Inst crda (1.1.1-1ubuntu4mp unstable-mp [amd64]) -Conf crda (1.1.1-1ubuntu4mp unstable-mp [amd64])' aptget install crda -s -t unstable-mp - -rm rootdir/var/lib/dpkg/status -insertinstalledpackage 'crda' 'amd64' '1.1.1-1ubuntu4mp' 'Provides: wireless-crda -Conflicts: wireless-crda (<< 1.15) -Replaces: wireless-crda ( << 1.15) -Multi-arch: foreign' - -testsuccessequal 'Reading package lists... -Building dependency tree... -The following NEW packages will be installed: - wireless-crda -0 upgraded, 1 newly installed, 0 to remove and 1 not upgraded. -Inst wireless-crda (1.16 unstable [amd64]) -Conf wireless-crda (1.16 unstable [amd64])' aptget install wireless-crda -s -t unstable -- cgit v1.2.3-70-g09d2 From ecc138f858fab61e0b888d3d13854d1422c3432b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Thu, 16 Jul 2015 19:41:45 +0200 Subject: just-in-time creation for (implicit) Provides Expecting the worst is easy to code, but has its disadvantages e.g. by creating package structures which otherwise would have never existed. By creating the provides instead at the time a package structure is added we are well prepared for the introduction of partial architectures, massive amounts of M-A:foreign (and :allowed) and co as far as provides are concerned at least. We have something relatively similar for dependencies already. Many tests are added for both M-A states and the code cleaned to properly support implicit provides for foreign architectures and architectures we 'just' happen to parse. Git-Dch: Ignore --- apt-pkg/deb/deblistparser.cc | 20 +- apt-pkg/deb/deblistparser.h | 1 - apt-pkg/pkgcachegen.cc | 123 ++++++++--- apt-pkg/pkgcachegen.h | 4 + cmdline/apt-cache.cc | 4 +- .../test-bug-723586-any-stripped-in-single-arch | 2 +- .../test-bug-758153-versioned-provides-support | 84 +++++++ test/integration/test-multiarch-allowed | 246 +++++++++++++++++++++ test/integration/test-multiarch-foreign | 33 +++ 9 files changed, 466 insertions(+), 51 deletions(-) create mode 100755 test/integration/test-multiarch-allowed (limited to 'test') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index df0879641..87aa99c6e 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -861,7 +861,7 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) if (NewProvides(Ver, Package, OtherArch, Version, pkgCache::Flag::ArchSpecific) == false) return false; } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) { - if (NewProvidesAllArch(Ver, Package, Version) == false) + if (NewProvidesAllArch(Ver, Package, Version, 0) == false) return false; } else { if (NewProvides(Ver, Package, Arch, Version, 0) == false) @@ -876,26 +876,14 @@ bool debListParser::ParseProvides(pkgCache::VerIterator &Ver) if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) { string const Package = string(Ver.ParentPkg().Name()).append(":").append("any"); - return NewProvidesAllArch(Ver, Package, Ver.VerStr()); + return NewProvidesAllArch(Ver, Package, Ver.VerStr(), pkgCache::Flag::MultiArchImplicit); } else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) - return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr()); + return NewProvidesAllArch(Ver, Ver.ParentPkg().Name(), Ver.VerStr(), pkgCache::Flag::MultiArchImplicit); return true; } /*}}}*/ -// ListParser::NewProvides - add provides for all architectures /*{{{*/ -bool debListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, - string const &Version) { - for (std::vector::const_iterator a = Architectures.begin(); - a != Architectures.end(); ++a) - { - if (NewProvides(Ver, Package, *a, Version, pkgCache::Flag::MultiArchImplicit) == false) - return false; - } - return true; -} - /*}}}*/ // ListParser::GrabWord - Matches a word and returns /*{{{*/ // --------------------------------------------------------------------- /* Looks for a word in a list of words - for ParseStatus */ @@ -991,7 +979,7 @@ bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg, bool res = debListParser::UsePackage(Pkg, Ver); // we use the full file path as a provides so that the file is found // by its name - if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr()) == false) + if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr(), 0) == false) return false; return res; } diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 3884aafb9..30e52718d 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -53,7 +53,6 @@ class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag, unsigned int Type); bool ParseProvides(pkgCache::VerIterator &Ver); - bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, std::string const &Version); static bool GrabWord(std::string Word,WordList *List,unsigned char &Out); APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors); diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 9acb2563a..c04320555 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -648,6 +648,16 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name return false; Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package); + // Set the name, arch and the ID + APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) + Pkg->Group = Grp.Index(); + // all is mapped to the native architecture + map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); + if (unlikely(idxArch == 0)) + return false; + Pkg->Arch = idxArch; + Pkg->ID = Cache.HeaderP->PackageCount++; + // Insert the package into our package list if (Grp->FirstPackage == 0) // the group is new { @@ -662,23 +672,36 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name } else // Group the Packages together { + // but first get implicit provides done + if (APT::Configuration::checkArchitecture(Pkg.Arch()) == true) + { + pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); // native or any foreign pkg will do + if (M.end() == false) + for (pkgCache::PrvIterator Prv = M.ProvidesList(); Prv.end() == false; ++Prv) + { + if ((Prv->Flags & pkgCache::Flag::ArchSpecific) != 0) + continue; + pkgCache::VerIterator Ver = Prv.OwnerVer(); + if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed || + ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign && + (Prv->Flags & pkgCache::Flag::MultiArchImplicit) == 0)) + if (NewProvides(Ver, Pkg, Prv->ProvideVersion, Prv->Flags) == false) + return false; + } + + for (pkgCache::PkgIterator P = Grp.PackageList(); P.end() == false; P = Grp.NextPkg(P)) + for (pkgCache::VerIterator Ver = P.VersionList(); Ver.end() == false; ++Ver) + if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) + if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false) + return false; + } + // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); Pkg->NextPackage = LastPkg->NextPackage; LastPkg->NextPackage = Package; } Grp->LastPackage = Package; - - // Set the name, arch and the ID - APT_IGNORE_DEPRECATED(Pkg->Name = Grp->Name;) - Pkg->Group = Grp.Index(); - // all is mapped to the native architecture - map_stringitem_t const idxArch = (Arch == "all") ? Cache.HeaderP->Architecture : StoreString(MIXED, Arch); - if (unlikely(idxArch == 0)) - return false; - Pkg->Arch = idxArch; - Pkg->ID = Cache.HeaderP->PackageCount++; - return true; } /*}}}*/ @@ -1079,44 +1102,82 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, const string &Version, uint8_t const Flags) { - pkgCache &Cache = Owner->Cache; + pkgCache const &Cache = Owner->Cache; // We do not add self referencing provides if (Ver.ParentPkg().Name() == PkgName && (PkgArch == Ver.ParentPkg().Arch() || (PkgArch == "all" && strcmp((Cache.StrP + Cache.HeaderP->Architecture), Ver.ParentPkg().Arch()) == 0))) return true; - + + // Locate the target package + pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); + if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) + return false; + + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + return Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags); +} +bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator &Ver, + pkgCache::PkgIterator &Pkg, + map_pointer_t const ProvideVersion, + uint8_t const Flags) +{ // Get a structure - map_pointer_t const Provides = Owner->AllocateInMap(sizeof(pkgCache::Provides)); + map_pointer_t const Provides = AllocateInMap(sizeof(pkgCache::Provides)); if (unlikely(Provides == 0)) return false; - Cache.HeaderP->ProvidesCount++; - + ++Cache.HeaderP->ProvidesCount; + // Fill it in pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP); - Dynamic DynPrv(Prv); Prv->Version = Ver.Index(); + Prv->ProvideVersion = ProvideVersion; Prv->Flags = Flags; Prv->NextPkgProv = Ver->ProvidesList; Ver->ProvidesList = Prv.Index(); - if (Version.empty() == false) { - map_stringitem_t const idxProvideVersion = WriteString(Version); - Prv->ProvideVersion = idxProvideVersion; - if (unlikely(idxProvideVersion == 0)) - return false; - } - - // Locate the target package - pkgCache::PkgIterator Pkg; - Dynamic DynPkg(Pkg); - if (unlikely(Owner->NewPackage(Pkg,PkgName, PkgArch) == false)) - return false; - + // Link it to the package Prv->ParentPkg = Pkg.Index(); Prv->NextProvides = Pkg->ProvidesList; Pkg->ProvidesList = Prv.Index(); - + return true; +} + /*}}}*/ +// ListParser::NewProvidesAllArch - add provides for all architectures /*{{{*/ +bool pkgCacheGenerator::ListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, + string const &Version, uint8_t const Flags) { + pkgCache &Cache = Owner->Cache; + pkgCache::GrpIterator const Grp = Cache.FindGrp(Package); + if (Grp.end() == true) + return NewProvides(Ver, Package, Cache.NativeArch(), Version, Flags); + else + { + map_stringitem_t idxProvideVersion = 0; + if (Version.empty() == false) { + idxProvideVersion = StoreString(VERSIONNUMBER, Version); + if (unlikely(idxProvideVersion == 0)) + return false; + } + + bool const isImplicit = (Flags & pkgCache::Flag::MultiArchImplicit) == pkgCache::Flag::MultiArchImplicit; + bool const isArchSpecific = (Flags & pkgCache::Flag::ArchSpecific) == pkgCache::Flag::ArchSpecific; + pkgCache::PkgIterator const OwnerPkg = Ver.ParentPkg(); + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (isImplicit && OwnerPkg == Pkg) + continue; + if (isArchSpecific == false && APT::Configuration::checkArchitecture(OwnerPkg.Arch()) == false) + continue; + if (Owner->NewProvides(Ver, Pkg, idxProvideVersion, Flags) == false) + return false; + } + } return true; } /*}}}*/ diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index c5527ff30..34dc6fead 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -93,6 +93,8 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ map_pointer_t const ParentPkg, unsigned short const Hash, map_pointer_t const Next); map_pointer_t NewDescription(pkgCache::DescIterator &Desc,const std::string &Lang,const MD5SumValue &md5sum,map_stringitem_t const idxmd5str); + bool NewProvides(pkgCache::VerIterator &Ver, pkgCache::PkgIterator &Pkg, + map_stringitem_t const ProvidesVersion, uint8_t const Flags); public: @@ -167,6 +169,8 @@ class APT_HIDDEN pkgCacheGenerator::ListParser bool NewProvides(pkgCache::VerIterator &Ver,const std::string &PkgName, const std::string &PkgArch, const std::string &Version, uint8_t const Flags); + bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, + std::string const &Version, uint8_t const Flags); public: diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 1eb891e8e..e61914298 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -253,12 +253,12 @@ static bool DumpPackage(CommandLine &CmdL) { cout << Cur.VerStr() << " - "; for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; ++Prv) - cout << Prv.ParentPkg().FullName(true) << " "; + cout << Prv.ParentPkg().FullName(true) << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ") "; cout << endl; } cout << "Reverse Provides: " << endl; for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; ++Prv) - cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << endl; + cout << Prv.OwnerPkg().FullName(true) << " " << Prv.OwnerVer().VerStr() << " (= " << (Prv->ProvideVersion == 0 ? "" : Prv.ProvideVersion()) << ")"<< endl; } return true; diff --git a/test/integration/test-bug-723586-any-stripped-in-single-arch b/test/integration/test-bug-723586-any-stripped-in-single-arch index 0cf3362cf..8a835a6db 100755 --- a/test/integration/test-bug-723586-any-stripped-in-single-arch +++ b/test/integration/test-bug-723586-any-stripped-in-single-arch @@ -50,5 +50,5 @@ configarchitecture 'amd64' 'armhf' rm rootdir/var/cache/apt/*.bin testsuccessequal "$INSTALLLOG" aptget install python3-gnupg -s -testsuccessequal "$(sed 's#3.3.2-16 - python3#3.3.2-16 - python3:any:armhf python3#' showpkg.log)" aptcache showpkg python3 +testsuccessequal "$(cat showpkg.log)" aptcache showpkg python3 testfailureequal "$FAILLOG" aptget install python-mips -s diff --git a/test/integration/test-bug-758153-versioned-provides-support b/test/integration/test-bug-758153-versioned-provides-support index 30bc921c3..bf42f57fd 100755 --- a/test/integration/test-bug-758153-versioned-provides-support +++ b/test/integration/test-bug-758153-versioned-provides-support @@ -30,6 +30,18 @@ insertpackage 'unstable' 'baz' 'i386,amd64' '1' 'Depends: bar' insertpackage 'experimental' 'baz' 'i386,amd64' '2' 'Depends: bar:i386' insertpackage 'experimental' 'baz-broken' 'i386' '2' 'Depends: bar:amd64' +insertpackage 'unstable' 'next' 'amd64' '1' 'Multi-Arch: foreign +Provides: next (= 2)' +insertpackage 'unstable' 'needsrealnext' 'amd64,i386' '2' 'Depends: next (>= 2)' + +insertpackage 'unstable' 'virtualnext2' 'amd64' '1' 'Multi-Arch: foreign +Provides: next2 (= 2)' +insertpackage 'unstable' 'needsnext2' 'amd64,i386' '2' 'Depends: next2 (>= 2)' + +insertpackage 'unstable' 'virtualnext3' 'amd64' '1' 'Multi-Arch: no +Provides: next3 (= 2)' +insertpackage 'unstable' 'needsnext3' 'amd64,i386' '2' 'Depends: next3 (>= 2)' + setupaptarchive testsuccessequal 'Reading package lists... @@ -204,3 +216,75 @@ The following information may help to resolve the situation: The following packages have unmet dependencies: baz-broken:i386 : Depends: bar but it is not installable E: Unable to correct problems, you have held broken packages.' aptget install baz-broken -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + next +The following NEW packages will be installed: + needsrealnext next +0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. +Inst next (1 unstable [amd64]) +Inst needsrealnext (2 unstable [amd64]) +Conf next (1 unstable [amd64]) +Conf needsrealnext (2 unstable [amd64])' aptget install needsrealnext -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + next +The following NEW packages will be installed: + needsrealnext:i386 next +0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. +Inst next (1 unstable [amd64]) +Inst needsrealnext:i386 (2 unstable [i386]) +Conf next (1 unstable [amd64]) +Conf needsrealnext:i386 (2 unstable [i386])' aptget install needsrealnext:i386 -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + virtualnext2 +The following NEW packages will be installed: + needsnext2 virtualnext2 +0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. +Inst virtualnext2 (1 unstable [amd64]) +Inst needsnext2 (2 unstable [amd64]) +Conf virtualnext2 (1 unstable [amd64]) +Conf needsnext2 (2 unstable [amd64])' aptget install needsnext2 -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + virtualnext2 +The following NEW packages will be installed: + needsnext2:i386 virtualnext2 +0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. +Inst virtualnext2 (1 unstable [amd64]) +Inst needsnext2:i386 (2 unstable [i386]) +Conf virtualnext2 (1 unstable [amd64]) +Conf needsnext2:i386 (2 unstable [i386])' aptget install needsnext2:i386 -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + virtualnext3 +The following NEW packages will be installed: + needsnext3 virtualnext3 +0 upgraded, 2 newly installed, 0 to remove and 2 not upgraded. +Inst virtualnext3 (1 unstable [amd64]) +Inst needsnext3 (2 unstable [amd64]) +Conf virtualnext3 (1 unstable [amd64]) +Conf needsnext3 (2 unstable [amd64])' aptget install needsnext3 -s + +testfailureequal 'Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: + +The following packages have unmet dependencies: + needsnext3:i386 : Depends: next3:i386 (>= 2) but it is not installable +E: Unable to correct problems, you have held broken packages.' aptget install needsnext3:i386 -s diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed new file mode 100755 index 000000000..a643cd2dc --- /dev/null +++ b/test/integration/test-multiarch-allowed @@ -0,0 +1,246 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' + +insertpackage 'unstable' 'foo' 'amd64,i386' '1' 'Multi-Arch: allowed' +insertpackage 'unstable' 'needsfoo' 'amd64,i386' '1' 'Depends: foo' +insertpackage 'unstable' 'needsfooany' 'amd64,i386' '1' 'Depends: foo:any' +insertpackage 'unstable' 'needsfoover1' 'amd64,i386' '1' 'Depends: foo:any (>= 1)' +insertpackage 'unstable' 'needsfoover2' 'amd64,i386' '1' 'Depends: foo:any (>= 2)' +insertpackage 'unstable' 'hatesfoo' 'amd64' '1' 'Conflicts: foo' +insertpackage 'unstable' 'hatesfooany' 'amd64' '1' 'Conflicts: foo:any' # this makes no sense… +insertpackage 'unstable' 'hatesfoonative' 'amd64' '1' 'Conflicts: foo:amd64' + +insertpackage 'unstable' 'coolfoo' 'amd64' '1' 'Multi-Arch:allowed +Provides: coolbar' +insertpackage 'unstable' 'coolfoover' 'amd64' '1' 'Multi-Arch:allowed +Provides: coolbar (= 2)' +insertpackage 'unstable' 'needscoolfoo' 'amd64' '1' 'Depends: coolfoo, coolbar' +insertpackage 'unstable' 'needscoolfooany' 'amd64' '1' 'Depends: coolfoo:any, coolbar:any' +insertpackage 'unstable' 'needscoolfoover0' 'amd64' '1' 'Depends: coolfoo:any (>= 1), coolbar' +insertpackage 'unstable' 'needscoolfoover1' 'amd64' '1' 'Depends: coolfoo:any (>= 1), coolbar (>= 1)' +insertpackage 'unstable' 'needscoolfoover2' 'amd64' '1' 'Depends: coolfoo:any (>= 2), coolbar (>= 1)' +insertpackage 'unstable' 'needscoolfoover3' 'amd64' '1' 'Depends: coolfoo:any (>= 2), coolbar (>= 3)' + +setupaptarchive + +BADPREFIX='Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: +' + +solveableinsinglearch0() { + testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + foo needsfoo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [amd64]) +Inst needsfoo (1 unstable [amd64]) +Conf foo (1 unstable [amd64]) +Conf needsfoo (1 unstable [amd64])' aptget install needsfoo -s +} +solveableinsinglearch0 +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo:i386 +The following NEW packages will be installed: + foo:i386 needsfoo:i386 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:i386 (1 unstable [i386]) +Inst needsfoo:i386 (1 unstable [i386]) +Conf foo:i386 (1 unstable [i386]) +Conf needsfoo:i386 (1 unstable [i386])' aptget install needsfoo:i386 -s +testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + needsfoo:i386 : Depends: foo:i386 but it is not going to be installed +E: Unable to correct problems, you have held broken packages." aptget install needsfoo:i386 foo:amd64 -s +testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + needsfoo : Depends: foo but it is not going to be installed +E: Unable to correct problems, you have held broken packages." aptget install needsfoo foo:i386 -s + +solveableinsinglearch1() { + testsuccessequal "Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + foo $1 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [amd64]) +Inst $1 (1 unstable [amd64]) +Conf foo (1 unstable [amd64]) +Conf $1 (1 unstable [amd64])" aptget install $1 -s +} + +testneedsfooallgood() { + solveableinsinglearch1 $1 + testsuccessequal "Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo +The following NEW packages will be installed: + foo $1:i386 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo (1 unstable [amd64]) +Inst $1:i386 (1 unstable [i386]) +Conf foo (1 unstable [amd64]) +Conf $1:i386 (1 unstable [i386])" aptget install $1:i386 -s + testsuccessequal "Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + foo:i386 $1:i386 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:i386 (1 unstable [i386]) +Inst $1:i386 (1 unstable [i386]) +Conf foo:i386 (1 unstable [i386]) +Conf $1:i386 (1 unstable [i386])" aptget install $1:i386 foo:i386 -s + testsuccessequal "Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + foo:i386 $1 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:i386 (1 unstable [i386]) +Inst $1 (1 unstable [amd64]) +Conf foo:i386 (1 unstable [i386]) +Conf $1 (1 unstable [amd64])" aptget install $1 foo:i386 -s +} +testneedsfooallgood 'needsfooany' +testneedsfooallgood 'needsfoover1' + +NEEDSFOO2NATIVE="$BADPREFIX +The following packages have unmet dependencies: + needsfoover2 : Depends: foo:any (>= 2) +E: Unable to correct problems, you have held broken packages." +NEEDSFOO2FOREIGN="$BADPREFIX +The following packages have unmet dependencies: + needsfoover2:i386 : Depends: foo:any:i386 (>= 2) +E: Unable to correct problems, you have held broken packages." +testfailureequal "$NEEDSFOO2NATIVE" aptget install needsfoover2 -s +testfailureequal "$NEEDSFOO2FOREIGN" aptget install needsfoover2:i386 -s +testfailureequal "$NEEDSFOO2FOREIGN" aptget install needsfoover2:i386 foo:i386 -s +testfailureequal "$NEEDSFOO2NATIVE" aptget install needsfoover2 foo:i386 -s + +solveableinsinglearch2() { + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hatesfoo : Conflicts: foo but 1 is to be installed +E: Unable to correct problems, you have held broken packages." aptget install foo hatesfoo -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hatesfooany : Conflicts: foo:any +E: Unable to correct problems, you have held broken packages." aptget install foo hatesfooany -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hatesfoonative : Conflicts: foo but 1 is to be installed +E: Unable to correct problems, you have held broken packages." aptget install foo hatesfoonative -s +} +solveableinsinglearch2 +testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hatesfoo : Conflicts: foo:i386 but 1 is to be installed +E: Unable to correct problems, you have held broken packages." aptget install foo:i386 hatesfoo -s +testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hatesfooany : Conflicts: foo:any +E: Unable to correct problems, you have held broken packages." aptget install foo:i386 hatesfooany -s +testsuccessequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + foo:i386 hatesfoonative +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst foo:i386 (1 unstable [i386]) +Inst hatesfoonative (1 unstable [amd64]) +Conf foo:i386 (1 unstable [i386]) +Conf hatesfoonative (1 unstable [amd64])' aptget install foo:i386 hatesfoonative -s + +solveableinsinglearch3() { + testsuccessequal "Reading package lists... +Building dependency tree... +The following extra packages will be installed: + coolfoo +The following NEW packages will be installed: + coolfoo needscoolfoo +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst coolfoo (1 unstable [amd64]) +Inst needscoolfoo (1 unstable [amd64]) +Conf coolfoo (1 unstable [amd64]) +Conf needscoolfoo (1 unstable [amd64])" aptget install needscoolfoo -s + testsuccessequal "Reading package lists... +Building dependency tree... +The following extra packages will be installed: + coolfoo +The following NEW packages will be installed: + coolfoo coolfoover needscoolfoo +0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Inst coolfoo (1 unstable [amd64]) +Inst coolfoover (1 unstable [amd64]) +Inst needscoolfoo (1 unstable [amd64]) +Conf coolfoo (1 unstable [amd64]) +Conf coolfoover (1 unstable [amd64]) +Conf needscoolfoo (1 unstable [amd64])" aptget install needscoolfoo coolfoover -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + needscoolfooany : Depends: coolbar:any but it is not installable +E: Unable to correct problems, you have held broken packages." aptget install needscoolfooany -s + testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + coolfoo +The following NEW packages will be installed: + coolfoo needscoolfoover0 +0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. +Inst coolfoo (1 unstable [amd64]) +Inst needscoolfoover0 (1 unstable [amd64]) +Conf coolfoo (1 unstable [amd64]) +Conf needscoolfoover0 (1 unstable [amd64])' aptget install needscoolfoover0 -s + testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + coolfoo coolfoover +The following NEW packages will be installed: + coolfoo coolfoover needscoolfoover1 +0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded. +Inst coolfoo (1 unstable [amd64]) +Inst coolfoover (1 unstable [amd64]) +Inst needscoolfoover1 (1 unstable [amd64]) +Conf coolfoo (1 unstable [amd64]) +Conf coolfoover (1 unstable [amd64]) +Conf needscoolfoover1 (1 unstable [amd64])' aptget install needscoolfoover1 -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + needscoolfoover2 : Depends: coolfoo:any (>= 2) +E: Unable to correct problems, you have held broken packages." aptget install needscoolfoover2 -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + needscoolfoover3 : Depends: coolfoo:any (>= 2) + Depends: coolbar (>= 3) +E: Unable to correct problems, you have held broken packages." aptget install needscoolfoover3 -s +} +solveableinsinglearch3 + +msgmsg 'switch to single architecture' +configarchitecture 'amd64' + +solveableinsinglearch0 +testfailureequal 'Reading package lists... +Building dependency tree... +E: Unable to locate package needsfoo' aptget install needsfoo:i386 -s + +solveableinsinglearch1 'needsfooany' +solveableinsinglearch1 'needsfoover1' +testfailureequal "$NEEDSFOO2NATIVE" aptget install needsfoover2 -s +solveableinsinglearch2 +solveableinsinglearch3 diff --git a/test/integration/test-multiarch-foreign b/test/integration/test-multiarch-foreign index 7870126f5..a266e35ed 100755 --- a/test/integration/test-multiarch-foreign +++ b/test/integration/test-multiarch-foreign @@ -9,11 +9,17 @@ configarchitecture 'amd64' 'i386' 'armel' insertpackage 'unstable' 'cool-foo' 'amd64,i386' '1.0' 'Depends: foo' insertpackage 'unstable' 'cool-foo-x64' 'amd64' '1.0' 'Depends: foo:amd64' insertpackage 'unstable' 'cool-foo-x32' 'amd64' '1.0' 'Depends: foo:i386' +insertpackage 'unstable' 'hates-foo' 'amd64,i386' '1.0' 'Conflicts: foo' +insertpackage 'unstable' 'hates-foo-x64' 'amd64' '1.0' 'Conflicts: foo:amd64' +insertpackage 'unstable' 'hates-foo-x32' 'amd64' '1.0' 'Conflicts: foo:i386' insertpackage 'unstable' 'foo' 'amd64,i386,armel' '1.0' 'Multi-Arch: foreign' insertpackage 'unstable' 'cool-bar' 'amd64,i386' '1.0' 'Depends: bar-provider' insertpackage 'unstable' 'cool-bar-x64' 'amd64' '1.0' 'Depends: bar-provider:amd64' insertpackage 'unstable' 'cool-bar-x32' 'amd64' '1.0' 'Depends: bar-provider:i386' +insertpackage 'unstable' 'hates-bar' 'amd64,i386' '1.0' 'Conflicts: bar-provider' +insertpackage 'unstable' 'hates-bar-x64' 'amd64' '1.0' 'Conflicts: bar-provider:amd64' +insertpackage 'unstable' 'hates-bar-x32' 'amd64' '1.0' 'Conflicts: bar-provider:i386' insertpackage 'unstable' 'bar' 'amd64,i386,armel' '1.0' 'Provides: bar-provider Multi-Arch: foreign' @@ -163,6 +169,33 @@ Conf foo (1.0 unstable [amd64]) Conf cool-foo-x64 (1.0 unstable [amd64])' aptget install cool-foo-x64 -s } +hatersgonnahate() { + BADPREFIX='Reading package lists... +Building dependency tree... +Some packages could not be installed. This may mean that you have +requested an impossible situation or if you are using the unstable +distribution that some required packages have not yet been created +or been moved out of Incoming. +The following information may help to resolve the situation: +' + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hates-foo : Conflicts: foo + Conflicts: foo:i386 + Conflicts: foo:armel +E: Unable to correct problems, you have held broken packages." aptget install $1 hates-foo -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hates-foo-x64 : Conflicts: foo +E: Unable to correct problems, you have held broken packages." aptget install $1 hates-foo-x64 -s + testfailureequal "$BADPREFIX +The following packages have unmet dependencies: + hates-foo-x32 : Conflicts: foo:i386 +E: Unable to correct problems, you have held broken packages." aptget install $1 hates-foo-x32 -s +} +hatersgonnahate 'foo' +hatersgonnahate 'foo:i386' + #FIXME: do not work in single-arch as i386 isn't known at cache generation time testsuccessequal 'Reading package lists... Building dependency tree... -- cgit v1.2.3-70-g09d2 From bb0f6a34c4cebea7884de828c011dc85765ff820 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Fri, 17 Jul 2015 10:53:01 +0200 Subject: just-in-time creation for (explicit) negative deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we deal with provides in a more dynamic fashion the last remaining problem is explicit dependencies like 'Conflicts: foo' which have to apply to all architectures, but creating them all at the same time requires us to know all architectures ending up in the cache which isn't needed to be the same set as all foreign architectures. The effect is visible already now through as this prevents the creation of a bunch of virtual packages for arch:all packages and as such also many dependencies, just not very visible if you don't look at the stats… Git-Dch Ignore --- apt-pkg/deb/deblistparser.cc | 30 +----- apt-pkg/pkgcachegen.cc | 112 +++++++++++++-------- apt-pkg/pkgcachegen.h | 5 +- test/integration/test-apt-cache | 15 +-- .../test-bug-590041-prefer-non-virtual-packages | 2 +- test/integration/test-multiarch-allowed | 7 +- 6 files changed, 83 insertions(+), 88 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 87aa99c6e..1154016a9 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -790,43 +790,23 @@ bool debListParser::ParseDepends(pkgCache::VerIterator &Ver, return _error->Error("Problem parsing dependency %s",Tag); size_t const found = Package.rfind(':'); - // If negative is unspecific it needs to apply on all architectures - if (MultiArchEnabled == true && found == string::npos && - (Type == pkgCache::Dep::Conflicts || - Type == pkgCache::Dep::DpkgBreaks || - Type == pkgCache::Dep::Replaces)) + if (found == string::npos || strcmp(Package.c_str() + found, ":any") == 0) { - for (std::vector::const_iterator a = Architectures.begin(); - a != Architectures.end(); ++a) - if (NewDepends(Ver,Package,*a,Version,Op,Type) == false) - return false; - if (NewDepends(Ver,Package,"none",Version,Op,Type) == false) + if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) return false; } - else if (found != string::npos && - strcmp(Package.c_str() + found, ":any") != 0) + else { string Arch = Package.substr(found+1, string::npos); Package = Package.substr(0, found); // Such dependencies are not supposed to be accepted … - // … but this is probably the best thing to do. + // … but this is probably the best thing to do anyway if (Arch == "native") Arch = _config->Find("APT::Architecture"); if (NewDepends(Ver,Package,Arch,Version,Op | pkgCache::Dep::ArchSpecific,Type) == false) return false; } - else - { - if (NewDepends(Ver,Package,pkgArch,Version,Op,Type) == false) - return false; - if ((Type == pkgCache::Dep::Conflicts || - Type == pkgCache::Dep::DpkgBreaks || - Type == pkgCache::Dep::Replaces) && - NewDepends(Ver, Package, - (pkgArch != "none") ? "none" : _config->Find("APT::Architecture"), - Version,Op,Type) == false) - return false; - } + if (Start == Stop) break; } diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index c04320555..26a5e60a6 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -695,6 +695,23 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name if (NewProvides(Ver, Pkg, Ver->VerStr, pkgCache::Flag::MultiArchImplicit) == false) return false; } + // and negative dependencies, don't forget negative dependencies + { + pkgCache::PkgIterator const M = Grp.FindPreferredPkg(false); + if (M.end() == false) + for (pkgCache::DepIterator Dep = M.RevDependsList(); Dep.end() == false; ++Dep) + { + if ((Dep->CompareOp & (pkgCache::Dep::ArchSpecific | pkgCache::Dep::MultiArchImplicit)) != 0) + continue; + if (Dep->Type != pkgCache::Dep::DpkgBreaks && Dep->Type != pkgCache::Dep::Conflicts && + Dep->Type != pkgCache::Dep::Replaces) + continue; + pkgCache::VerIterator Ver = Dep.ParentVer(); + map_pointer_t * unused = NULL; + if (NewDepends(Pkg, Ver, Dep->Version, Dep->CompareOp, Dep->Type, unused) == false) + return false; + } + } // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); @@ -933,33 +950,6 @@ map_pointer_t pkgCacheGenerator::NewDescription(pkgCache::DescIterator &Desc, // --------------------------------------------------------------------- /* This creates a dependency element in the tree. It is linked to the version and to the package that it is pointing to. */ -bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, - pkgCache::VerIterator &Ver, - string const &Version, - uint8_t const Op, - uint8_t const Type, - map_stringitem_t* &OldDepLast) -{ - map_stringitem_t index = 0; - if (Version.empty() == false) - { - int const CmpOp = Op & 0x0F; - // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) - if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0) - index = Ver->VerStr; - - if (index == 0) - { - void const * const oldMap = Map.Data(); - index = StoreString(VERSIONNUMBER, Version); - if (unlikely(index == 0)) - return false; - if (OldDepLast != 0 && oldMap != Map.Data()) - OldDepLast += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap; - } - } - return NewDepends(Pkg, Ver, index, Op, Type, OldDepLast); -} bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, map_pointer_t const Version, @@ -1071,28 +1061,64 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, if (unlikely(Owner->NewGroup(Grp, PackageName) == false)) return false; - // Locate the target package - pkgCache::PkgIterator Pkg = Grp.FindPkg(Arch); - // we don't create 'none' packages and their dependencies if we can avoid it … - if (Pkg.end() == true && Arch == "none" && strcmp(Ver.ParentPkg().Arch(), "none") != 0) - return true; - Dynamic DynPkg(Pkg); - if (Pkg.end() == true) { - if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) - return false; - } - // Is it a file dependency? if (unlikely(PackageName[0] == '/')) FoundFileDeps = true; - /* Caching the old end point speeds up generation substantially */ - if (OldDepVer != Ver) { - OldDepLast = NULL; - OldDepVer = Ver; + map_stringitem_t idxVersion = 0; + if (Version.empty() == false) + { + int const CmpOp = Op & 0x0F; + // =-deps are used (79:1) for lockstep on same-source packages (e.g. data-packages) + if (CmpOp == pkgCache::Dep::Equals && strcmp(Version.c_str(), Ver.VerStr()) == 0) + idxVersion = Ver->VerStr; + + if (idxVersion == 0) + { + idxVersion = StoreString(VERSIONNUMBER, Version); + if (unlikely(idxVersion == 0)) + return false; + } + } + + bool const isNegative = (Type == pkgCache::Dep::DpkgBreaks || + Type == pkgCache::Dep::Conflicts || + Type == pkgCache::Dep::Replaces); + + pkgCache::PkgIterator Pkg; + Dynamic DynPkg(Pkg); + if (isNegative == false || (Op & pkgCache::Dep::ArchSpecific) == pkgCache::Dep::ArchSpecific || Grp->FirstPackage == 0) + { + // Locate the target package + Pkg = Grp.FindPkg(Arch); + if (Pkg.end() == true) { + if (unlikely(Owner->NewPackage(Pkg, PackageName, Arch) == false)) + return false; + } + + /* Caching the old end point speeds up generation substantially */ + if (OldDepVer != Ver) { + OldDepLast = NULL; + OldDepVer = Ver; + } + + return Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast); } + else + { + /* Caching the old end point speeds up generation substantially */ + if (OldDepVer != Ver) { + OldDepLast = NULL; + OldDepVer = Ver; + } - return Owner->NewDepends(Pkg, Ver, Version, Op, Type, OldDepLast); + for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + if (Owner->NewDepends(Pkg, Ver, idxVersion, Op, Type, OldDepLast) == false) + return false; + } + } + return true; } /*}}}*/ // ListParser::NewProvides - Create a Provides element /*{{{*/ diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 34dc6fead..0d0fb893f 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -76,14 +76,11 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ // Flag file dependencies bool FoundFileDeps; - + bool NewGroup(pkgCache::GrpIterator &Grp,const std::string &Name); bool NewPackage(pkgCache::PkgIterator &Pkg,const std::string &Name, const std::string &Arch); bool NewFileVer(pkgCache::VerIterator &Ver,ListParser &List); bool NewFileDesc(pkgCache::DescIterator &Desc,ListParser &List); - bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, - std::string const &Version, uint8_t const Op, - uint8_t const Type, map_pointer_t* &OldDepLast); bool NewDepends(pkgCache::PkgIterator &Pkg, pkgCache::VerIterator &Ver, map_pointer_t const Version, uint8_t const Op, uint8_t const Type, map_pointer_t* &OldDepLast); diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index a8ddfd889..1d90eed5c 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -66,7 +66,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: Recommends: ' aptcache depends foo --implicit testsuccessequal 'foo @@ -76,7 +75,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: Recommends: ' aptcache depends foo -o APT::Cache::ShowOnlyFirstOr=1 --implicit testsuccessequal 'foo Depends: bar @@ -86,7 +84,6 @@ testsuccessequal 'foo testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: (>= 2) Recommends: (<< 5)' aptcache depends foo -o APT::Cache::ShowVersion=1 --implicit testsuccessequal 'foo @@ -94,15 +91,13 @@ testsuccessequal 'foo Conflicts: ' aptcache depends foo --no-recommends testsuccessequal 'foo Depends: bar - Conflicts: - Conflicts: ' aptcache depends foo --no-recommends --implicit + Conflicts: ' aptcache depends foo --no-recommends --implicit testsuccessequal 'foo Depends: bar' aptcache depends foo --important --implicit testsuccessequal 'foo Conflicts: ' aptcache depends foo --important --no-depends --conflicts testsuccessequal 'foo - Conflicts: - Conflicts: ' aptcache depends foo --important --no-depends --conflicts --implicit + Conflicts: ' aptcache depends foo --important --no-depends --conflicts --implicit testsuccessequal 'foo Depends: bar Conflicts: @@ -118,17 +113,15 @@ bar testsuccessequal 'foo Depends: bar Conflicts: - Conflicts: |Recommends: Recommends: bar Depends: bar Breaks: foo - Breaks: Replaces: foo + Breaks: Replaces: - ' aptcache depends foo --recurse --implicit @@ -151,8 +144,8 @@ testsuccessequal 'bar testsuccessequal 'bar Depends: bar Breaks: foo - Breaks: Replaces: foo + Breaks: Replaces: ' aptcache depends bar --implicit testsuccessequal 'specific Depends: diff --git a/test/integration/test-bug-590041-prefer-non-virtual-packages b/test/integration/test-bug-590041-prefer-non-virtual-packages index 3bd7d436e..4e2a5142c 100755 --- a/test/integration/test-bug-590041-prefer-non-virtual-packages +++ b/test/integration/test-bug-590041-prefer-non-virtual-packages @@ -45,7 +45,7 @@ EOF setupaptarchive -testshowvirtual libc6:i386 +testnopackage libc6:i386 testsuccessequal "$pkglibc6" aptcache show libc6:armel testsuccessequal "$pkglibc6" aptcache show libc6 testsuccessequal "$pkglibdb1" aptcache show libdb1:i386 diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed index a643cd2dc..2c791ca19 100755 --- a/test/integration/test-multiarch-allowed +++ b/test/integration/test-multiarch-allowed @@ -138,10 +138,8 @@ solveableinsinglearch2() { The following packages have unmet dependencies: hatesfoo : Conflicts: foo but 1 is to be installed E: Unable to correct problems, you have held broken packages." aptget install foo hatesfoo -s - testfailureequal "$BADPREFIX -The following packages have unmet dependencies: - hatesfooany : Conflicts: foo:any -E: Unable to correct problems, you have held broken packages." aptget install foo hatesfooany -s + # the message differs slightly between single and multiarch + testfailuremsg 'E: Unable to correct problems, you have held broken packages.' aptget install foo hatesfooany -s testfailureequal "$BADPREFIX The following packages have unmet dependencies: hatesfoonative : Conflicts: foo but 1 is to be installed @@ -155,6 +153,7 @@ E: Unable to correct problems, you have held broken packages." aptget install fo testfailureequal "$BADPREFIX The following packages have unmet dependencies: hatesfooany : Conflicts: foo:any + Conflicts: foo:any:i386 E: Unable to correct problems, you have held broken packages." aptget install foo:i386 hatesfooany -s testsuccessequal 'Reading package lists... Building dependency tree... -- cgit v1.2.3-70-g09d2 From 5465192b9aeb1ccea778950ccf2d1b7b32f2cd91 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sat, 18 Jul 2015 18:03:54 +0200 Subject: add volatile sources support in libapt-pkg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sources are usually defined in sources.list (and co) and are pretty stable, but once in a while a frontend might want to add an additional "source" like a local .deb file to install this package (No support for 'real' sources being added this way as this is a multistep process). We had a hack in place to allow apt-get and apt to pull this of for a short while now, but other frontends are either left in the cold by this and/or the code for it looks dirty with FIXMEs plastering it and has on top of this also some problems (like including these 'volatile' sources in the srcpkgcache.bin file). So the biggest part in this commit is actually the rewrite of the cache generation as it is now potentially a three step process. The biggest problem with adding support now through is that this makes a bunch of previously mostly unusable by externs and therefore hidden classes public, so a bit of further tuneing on this now public API is in order… --- apt-pkg/deb/debindexfile.cc | 27 +- apt-pkg/deb/debindexfile.h | 18 +- apt-pkg/deb/deblistparser.cc | 2 +- apt-pkg/deb/debmetaindex.cc | 29 --- apt-pkg/deb/debmetaindex.h | 39 --- apt-pkg/edsp/edspsystem.cc | 3 +- apt-pkg/pkgcachegen.cc | 401 ++++++++++++++---------------- apt-pkg/pkgcachegen.h | 1 - apt-pkg/pkgsystem.h | 5 +- apt-pkg/sourcelist.cc | 28 ++- apt-pkg/sourcelist.h | 19 ++ apt-private/private-cachefile.h | 21 -- apt-private/private-install.cc | 21 +- test/integration/framework | 12 +- test/integration/test-apt-get-install-deb | 45 +++- 15 files changed, 309 insertions(+), 362 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 972feba7f..e67233e5f 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -339,18 +339,16 @@ APT_CONST bool debStatusIndex::Exists() const } /*}}}*/ -// debDebPkgFile - Single .deb file /*{{{*/ -debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile) +// debDebPkgFileIndex - Single .deb file /*{{{*/ +debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) : pkgIndexFile(true), d(NULL), DebFile(DebFile) { DebFileFullPath = flAbsPath(DebFile); } - std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const { return "file:" + DebFileFullPath; } - bool debDebPkgFileIndex::Exists() const { return FileExists(DebFile); @@ -403,6 +401,8 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const if (GetContent(content, DebFile) == false) return false; std::string const contentstr = content.str(); + if (contentstr.empty()) + return true; DebControl->Write(contentstr.c_str(), contentstr.length()); // rewind for the listparser DebControl->Seek(0); @@ -431,7 +431,7 @@ pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const return File; } - + return File; } unsigned long debDebPkgFileIndex::Size() const @@ -443,12 +443,11 @@ unsigned long debDebPkgFileIndex::Size() const } /*}}}*/ -// debDscFileIndex stuff -debDscFileIndex::debDscFileIndex(std::string &DscFile) +// debDscFileIndex - a .dsc file /*{{{*/ +debDscFileIndex::debDscFileIndex(std::string const &DscFile) : pkgIndexFile(true), d(NULL), DscFile(DscFile) { } - bool debDscFileIndex::Exists() const { return FileExists(DscFile); @@ -461,8 +460,6 @@ unsigned long debDscFileIndex::Size() const return buf.st_size; return 0; } - -// DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/ pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const { if (!FileExists(DscFile)) @@ -471,18 +468,17 @@ pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const return new debDscRecordParser(DscFile,this); } /*}}}*/ + // Index File types for Debian /*{{{*/ class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type { public: - debIFTypeSrc() {Label = "Debian Source Index";}; }; class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -496,8 +492,7 @@ class APT_HIDDEN debIFTypeTrans : public debIFTypePkg class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -506,7 +501,7 @@ class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE { return new debDebFileRecordParser(File.FileName()); }; diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 71ca22e4d..4a818121a 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -27,7 +27,7 @@ class pkgAcquire; class pkgCacheGenerator; -class APT_HIDDEN debStatusIndex : public pkgIndexFile +class debStatusIndex : public pkgIndexFile { void * const d; protected: @@ -51,7 +51,7 @@ class APT_HIDDEN debStatusIndex : public pkgIndexFile virtual ~debStatusIndex(); }; -class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile +class debPackagesIndex : public pkgIndexTargetFile { void * const d; public: @@ -70,7 +70,7 @@ class APT_HIDDEN debPackagesIndex : public pkgIndexTargetFile virtual ~debPackagesIndex(); }; -class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile +class debTranslationsIndex : public pkgIndexTargetFile { void * const d; public: @@ -86,7 +86,7 @@ class APT_HIDDEN debTranslationsIndex : public pkgIndexTargetFile virtual ~debTranslationsIndex(); }; -class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile +class debSourcesIndex : public pkgIndexTargetFile { void * const d; public: @@ -107,7 +107,7 @@ class APT_HIDDEN debSourcesIndex : public pkgIndexTargetFile virtual ~debSourcesIndex(); }; -class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile +class debDebPkgFileIndex : public pkgIndexFile { private: void * const d; @@ -141,11 +141,11 @@ class APT_HIDDEN debDebPkgFileIndex : public pkgIndexFile // Interface for acquire virtual std::string ArchiveURI(std::string /*File*/) const APT_OVERRIDE; - debDebPkgFileIndex(std::string DebFile); + debDebPkgFileIndex(std::string const &DebFile); virtual ~debDebPkgFileIndex(); }; -class APT_HIDDEN debDscFileIndex : public pkgIndexFile +class debDscFileIndex : public pkgIndexFile { private: void * const d; @@ -160,11 +160,11 @@ class APT_HIDDEN debDscFileIndex : public pkgIndexFile return DscFile; }; - debDscFileIndex(std::string &DscFile); + debDscFileIndex(std::string const &DscFile); virtual ~debDscFileIndex(); }; -class APT_HIDDEN debDebianSourceDirIndex : public debDscFileIndex +class debDebianSourceDirIndex : public debDscFileIndex { public: virtual const Type *GetType() const APT_CONST; diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 1154016a9..b7988d499 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -959,7 +959,7 @@ bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg, bool res = debListParser::UsePackage(Pkg, Ver); // we use the full file path as a provides so that the file is found // by its name - if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr(), 0) == false) + if(NewProvides(Ver, DebFile, Pkg.Cache()->NativeArch(), Ver.VerStr(), 0) == false) return false; return res; } diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 480317db3..123c91648 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -785,34 +785,5 @@ class APT_HIDDEN debSLTypeDebSrc : public debSLTypeDebian /*{{{*/ }; /*}}}*/ -debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile) /*{{{*/ - : metaIndex(DebFile, "local-uri", "deb-dist"), d(NULL), DebFile(DebFile) -{ - DebIndex = new debDebPkgFileIndex(DebFile); - Indexes = new std::vector(); - Indexes->push_back(DebIndex); -} -debDebFileMetaIndex::~debDebFileMetaIndex() {} - /*}}}*/ -class APT_HIDDEN debSLTypeDebFile : public pkgSourceList::Type /*{{{*/ -{ - public: - - bool CreateItem(std::vector &List, std::string const &URI, - std::string const &/*Dist*/, std::string const &/*Section*/, - std::map const &/*Options*/) const APT_OVERRIDE - { - metaIndex *mi = new debDebFileMetaIndex(URI); - List.push_back(mi); - return true; - } - - debSLTypeDebFile() : Type("deb-file", "Debian local deb file") - { - } -}; - /*}}}*/ - APT_HIDDEN debSLTypeDeb _apt_DebType; APT_HIDDEN debSLTypeDebSrc _apt_DebSrcType; -APT_HIDDEN debSLTypeDebFile _apt_DebFileType; diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 8c13237cb..e93959a21 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -17,7 +17,6 @@ class pkgAcquire; class pkgIndexFile; -class debDebPkgFileIndex; class IndexTarget; class pkgCacheGenerator; class OpProgress; @@ -66,42 +65,4 @@ class APT_HIDDEN debReleaseIndex : public metaIndex std::vector Languages); }; -class APT_HIDDEN debDebFileMetaIndex : public metaIndex -{ -private: - void * const d; - std::string DebFile; - debDebPkgFileIndex *DebIndex; -public: - virtual std::string ArchiveURI(std::string const& /*File*/) const APT_OVERRIDE { - return DebFile; - } - virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) APT_OVERRIDE { - return true; - } - virtual std::vector GetIndexTargets() const APT_OVERRIDE { - return std::vector(); - } - virtual std::vector *GetIndexFiles() APT_OVERRIDE { - return Indexes; - } - virtual bool IsTrusted() const APT_OVERRIDE { - return true; - } - virtual bool Load(std::string const &, std::string * const ErrorText) APT_OVERRIDE - { - LoadedSuccessfully = TRI_NO; - if (ErrorText != NULL) - strprintf(*ErrorText, "Unparseable metaindex as it represents the standalone deb file %s", DebFile.c_str()); - return false; - } - virtual metaIndex * UnloadedClone() const APT_OVERRIDE - { - return NULL; - } - debDebFileMetaIndex(std::string const &DebFile); - virtual ~debDebFileMetaIndex(); - -}; - #endif diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index 4fb34b896..f65fcc0d2 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -91,8 +91,7 @@ signed edspSystem::Score(Configuration const &Cnf) return -1000; } /*}}}*/ -// System::AddStatusFiles - Register the status files /*{{{*/ -bool edspSystem::AddStatusFiles(std::vector &List) +bool edspSystem::AddStatusFiles(std::vector &List) /*{{{*/ { if (StatusFile == 0) { diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 26a5e60a6..9529f42dc 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include #include @@ -1332,10 +1334,10 @@ map_stringitem_t pkgCacheGenerator::StoreString(enum StringType const type, cons /* This just verifies that each file in the list of index files exists, has matching attributes with the cache and the cache does not have any extra files. */ -static bool CheckValidity(const string &CacheFile, +static bool CheckValidity(const string &CacheFile, pkgSourceList &List, - FileIterator Start, - FileIterator End, + FileIterator const Start, + FileIterator const End, MMap **OutMap = 0) { bool const Debug = _config->FindB("Debug::pkgCacheGen", false); @@ -1343,7 +1345,7 @@ static bool CheckValidity(const string &CacheFile, if (CacheFile.empty() == true || FileExists(CacheFile) == false) { if (Debug == true) - std::clog << "CacheFile doesn't exist" << std::endl; + std::clog << "CacheFile " << CacheFile << " doesn't exist" << std::endl; return false; } @@ -1361,7 +1363,7 @@ static bool CheckValidity(const string &CacheFile, if (_error->PendingError() == true || Map->Size() == 0) { if (Debug == true) - std::clog << "Errors are pending or Map is empty()" << std::endl; + std::clog << "Errors are pending or Map is empty() for " << CacheFile << std::endl; _error->Discard(); return false; } @@ -1385,10 +1387,9 @@ static bool CheckValidity(const string &CacheFile, if (Debug == true) std::clog << "with ID " << RlsFile->ID << " is valid" << std::endl; - std::vector *Indexes = (*i)->GetIndexFiles(); - for (std::vector::const_iterator j = Indexes->begin(); j != Indexes->end(); ++j) - if ((*j)->HasPackages()) - Files.push_back (*j); + std::vector const * const Indexes = (*i)->GetIndexFiles(); + std::copy_if(Indexes->begin(), Indexes->end(), std::back_inserter(Files), + [](pkgIndexFile const * const I) { return I->HasPackages(); }); } for (unsigned I = 0; I != Cache.HeaderP->ReleaseFileCount; ++I) if (RlsVisited[I] == false) @@ -1398,8 +1399,7 @@ static bool CheckValidity(const string &CacheFile, return false; } - for (; Start != End; ++Start) - Files.push_back(*Start); + std::copy(Start, End, std::back_inserter(Files)); /* Now we check every index file, see if it is in the cache, verify the IMS data and check that it is on the disk too.. */ @@ -1482,16 +1482,41 @@ static map_filesize_t ComputeSize(pkgSourceList const * const List, FileIterator } /*}}}*/ // BuildCache - Merge the list of index files into the cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ static bool BuildCache(pkgCacheGenerator &Gen, - OpProgress *Progress, + OpProgress * const Progress, map_filesize_t &CurrentSize,map_filesize_t TotalSize, pkgSourceList const * const List, - FileIterator Start, FileIterator End) + FileIterator const Start, FileIterator const End) { std::vector Files; bool const HasFileDeps = Gen.HasFileDeps(); + bool mergeFailure = false; + + auto const indexFileMerge = [&](pkgIndexFile * const I) { + if (HasFileDeps) + Files.push_back(I); + + if (I->HasPackages() == false || mergeFailure) + return; + + if (I->Exists() == false) + return; + + if (I->FindInCache(Gen.GetCache()).end() == false) + { + _error->Warning("Duplicate sources.list entry %s", + I->Describe().c_str()); + return; + } + + map_filesize_t const Size = I->Size(); + if (Progress != NULL) + Progress->OverallProgress(CurrentSize, TotalSize, Size, _("Reading package lists")); + CurrentSize += Size; + + if (I->Merge(Gen,Progress) == false) + mergeFailure = true; + }; if (List != NULL) { @@ -1508,63 +1533,20 @@ static bool BuildCache(pkgCacheGenerator &Gen, return false; std::vector *Indexes = (*i)->GetIndexFiles(); - for (std::vector::const_iterator I = Indexes->begin(); I != Indexes->end(); ++I) - { - if (HasFileDeps) - Files.push_back(*I); - - if ((*I)->HasPackages() == false) - continue; - - if ((*I)->Exists() == false) - continue; - - if ((*I)->FindInCache(Gen.GetCache()).end() == false) - { - _error->Warning("Duplicate sources.list entry %s", - (*I)->Describe().c_str()); - continue; - } - - map_filesize_t Size = (*I)->Size(); - if (Progress != NULL) - Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); - CurrentSize += Size; - - if ((*I)->Merge(Gen,Progress) == false) - return false; - } + if (Indexes != NULL) + std::for_each(Indexes->begin(), Indexes->end(), indexFileMerge); + if (mergeFailure) + return false; } } - Gen.SelectReleaseFile("", ""); - FileIterator I; - for (I = Start; I != End; ++I) + if (Start != End) { - if (HasFileDeps) - Files.push_back(*I); - - if ((*I)->HasPackages() == false) - continue; - - if ((*I)->Exists() == false) - continue; - - if ((*I)->FindInCache(Gen.GetCache()).end() == false) - { - _error->Warning("Duplicate sources.list entry %s", - (*I)->Describe().c_str()); - continue; - } - - map_filesize_t Size = (*I)->Size(); - if (Progress != NULL) - Progress->OverallProgress(CurrentSize,TotalSize,Size,_("Reading package lists")); - CurrentSize += Size; - - if ((*I)->Merge(Gen,Progress) == false) + Gen.SelectReleaseFile("", ""); + std::for_each(Start, End, indexFileMerge); + if (mergeFailure) return false; - } + } if (HasFileDeps == true) { @@ -1582,12 +1564,20 @@ static bool BuildCache(pkgCacheGenerator &Gen, return false; } } - + return true; } /*}}}*/ -// CacheGenerator::CreateDynamicMMap - load an mmap with configuration options /*{{{*/ -DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long Flags) { +// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/ +// --------------------------------------------------------------------- +/* This makes sure that the status cache (the cache that has all + index files from the sources list and all local ones) is ready + to be mmaped. If OutMap is not zero then a MMap object representing + the cache will be stored there. This is pretty much mandetory if you + are using AllowMem. AllowMem lets the function be run as non-root + where it builds the cache 'fast' into a memory buffer. */ +static DynamicMMap* CreateDynamicMMap(FileFd * const CacheF, unsigned long Flags) +{ map_filesize_t const MapStart = _config->FindI("APT::Cache-Start", 24*1024*1024); map_filesize_t const MapGrow = _config->FindI("APT::Cache-Grow", 1*1024*1024); map_filesize_t const MapLimit = _config->FindI("APT::Cache-Limit", 0); @@ -1599,15 +1589,42 @@ DynamicMMap* pkgCacheGenerator::CreateDynamicMMap(FileFd *CacheF, unsigned long else return new DynamicMMap(Flags, MapStart, MapGrow, MapLimit); } - /*}}}*/ -// CacheGenerator::MakeStatusCache - Construct the status cache /*{{{*/ -// --------------------------------------------------------------------- -/* This makes sure that the status cache (the cache that has all - index files from the sources list and all local ones) is ready - to be mmaped. If OutMap is not zero then a MMap object representing - the cache will be stored there. This is pretty much mandetory if you - are using AllowMem. AllowMem lets the function be run as non-root - where it builds the cache 'fast' into a memory buffer. */ +static bool writeBackMMapToFile(pkgCacheGenerator * const Gen, DynamicMMap * const Map, + std::string const &FileName) +{ + FileFd SCacheF(FileName, FileFd::WriteAtomic); + if (_error->PendingError() == true) + return false; + + fchmod(SCacheF.Fd(),0644); + + // Write out the main data + if (SCacheF.Write(Map->Data(),Map->Size()) == false) + return _error->Error(_("IO Error saving source cache")); + SCacheF.Sync(); + + // Write out the proper header + Gen->GetCache().HeaderP->Dirty = false; + if (SCacheF.Seek(0) == false || + SCacheF.Write(Map->Data(),sizeof(*Gen->GetCache().HeaderP)) == false) + return _error->Error(_("IO Error saving source cache")); + Gen->GetCache().HeaderP->Dirty = true; + SCacheF.Sync(); + return true; +} +static bool loadBackMMapFromFile(std::unique_ptr &Gen, + SPtr &Map, OpProgress * const Progress, std::string const &FileName) +{ + Map = CreateDynamicMMap(NULL, 0); + FileFd CacheF(FileName, FileFd::ReadOnly); + map_pointer_t const alloc = Map->RawAllocate(CacheF.Size()); + if ((alloc == 0 && _error->PendingError()) + || CacheF.Read((unsigned char *)Map->Data() + alloc, + CacheF.Size()) == false) + return false; + Gen.reset(new pkgCacheGenerator(Map.Get(),Progress)); + return true; +} APT_DEPRECATED bool pkgMakeStatusCache(pkgSourceList &List,OpProgress &Progress, MMap **OutMap, bool AllowMem) { return pkgCacheGenerator::MakeStatusCache(List, &Progress, OutMap, AllowMem); } @@ -1617,18 +1634,6 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress bool const Debug = _config->FindB("Debug::pkgCacheGen", false); std::vector Files; - /* - for (std::vector::const_iterator i = List.begin(); - i != List.end(); - ++i) - { - std::vector *Indexes = (*i)->GetIndexFiles(); - for (std::vector::const_iterator j = Indexes->begin(); - j != Indexes->end(); - ++j) - Files.push_back (*j); - } -*/ if (_system->AddStatusFiles(Files) == false) return false; @@ -1649,160 +1654,130 @@ bool pkgCacheGenerator::MakeStatusCache(pkgSourceList &List,OpProgress *Progress CreateDirectory(dir, flNotFile(SrcCacheFile)); } - // Decide if we can write to the cache - bool Writeable = false; - if (CacheFile.empty() == false) - Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0; - else - if (SrcCacheFile.empty() == false) - Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0; - if (Debug == true) - std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl; - - if (Writeable == false && AllowMem == false && CacheFile.empty() == false) - return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str()); - if (Progress != NULL) Progress->OverallProgress(0,1,1,_("Reading package lists")); - // Cache is OK, Fin. - if (CheckValidity(CacheFile, List, Files.begin(),Files.end(),OutMap) == true) + bool pkgcache_fine = false; + bool srcpkgcache_fine = false; + bool volatile_fine = List.GetVolatileFiles().empty(); + + if (CheckValidity(CacheFile, List, Files.begin(), Files.end(), volatile_fine ? OutMap : NULL) == true) { - if (Progress != NULL) - Progress->OverallProgress(1,1,1,_("Reading package lists")); if (Debug == true) - std::clog << "pkgcache.bin is valid - no need to build anything" << std::endl; - return true; + std::clog << "pkgcache.bin is valid - no need to build any cache" << std::endl; + pkgcache_fine = true; + srcpkgcache_fine = true; } - else if (Debug == true) - std::clog << "pkgcache.bin is NOT valid" << std::endl; - - /* At this point we know we need to reconstruct the package cache, - begin. */ - SPtr CacheF; - SPtr Map; - if (Writeable == true && CacheFile.empty() == false) + if (pkgcache_fine == false) { - _error->PushToStack(); - unlink(CacheFile.c_str()); - CacheF = new FileFd(CacheFile,FileFd::WriteAtomic); - fchmod(CacheF->Fd(),0644); - Map = CreateDynamicMMap(CacheF, MMap::Public); - if (_error->PendingError() == true) + if (CheckValidity(SrcCacheFile, List, Files.end(), Files.end()) == true) { - delete CacheF.UnGuard(); - delete Map.UnGuard(); if (Debug == true) - std::clog << "Open filebased MMap FAILED" << std::endl; - Writeable = false; - if (AllowMem == false) - { - _error->MergeWithStack(); - return false; - } - _error->RevertToStack(); - } - else - { - _error->MergeWithStack(); - if (Debug == true) - std::clog << "Open filebased MMap" << std::endl; + std::clog << "srcpkgcache.bin is valid - it can be reused" << std::endl; + srcpkgcache_fine = true; } } - if (Writeable == false || CacheFile.empty() == true) + + if (volatile_fine == true && srcpkgcache_fine == true && pkgcache_fine == true) { - // Just build it in memory.. - Map = CreateDynamicMMap(NULL); - if (Debug == true) - std::clog << "Open memory Map (not filebased)" << std::endl; + if (Progress != NULL) + Progress->OverallProgress(1,1,1,_("Reading package lists")); + return true; } - - // Lets try the source cache. - map_filesize_t CurrentSize = 0; - map_filesize_t TotalSize = 0; - if (CheckValidity(SrcCacheFile, List, Files.end(), - Files.end()) == true) + + bool Writeable = false; + if (srcpkgcache_fine == false || pkgcache_fine == false) { + if (CacheFile.empty() == false) + Writeable = access(flNotFile(CacheFile).c_str(),W_OK) == 0; + else if (SrcCacheFile.empty() == false) + Writeable = access(flNotFile(SrcCacheFile).c_str(),W_OK) == 0; + if (Debug == true) - std::clog << "srcpkgcache.bin is valid - populate MMap with it." << std::endl; - // Preload the map with the source cache - FileFd SCacheF(SrcCacheFile,FileFd::ReadOnly); - map_pointer_t const alloc = Map->RawAllocate(SCacheF.Size()); - if ((alloc == 0 && _error->PendingError()) - || SCacheF.Read((unsigned char *)Map->Data() + alloc, - SCacheF.Size()) == false) - return false; + std::clog << "Do we have write-access to the cache files? " << (Writeable ? "YES" : "NO") << std::endl; + + if (Writeable == false && AllowMem == false) + { + if (CacheFile.empty() == false) + return _error->Error(_("Unable to write to %s"),flNotFile(CacheFile).c_str()); + else if (SrcCacheFile.empty() == false) + return _error->Error(_("Unable to write to %s"),flNotFile(SrcCacheFile).c_str()); + else + return _error->Error("Unable to create caches as file usage is disabled, but memory not allowed either!"); + } + } - TotalSize = ComputeSize(NULL, Files.begin(), Files.end()); + // At this point we know we need to construct something, so get storage ready + SPtr Map = CreateDynamicMMap(NULL, 0); + if (Debug == true) + std::clog << "Open memory Map (not filebased)" << std::endl; - // Build the status cache - pkgCacheGenerator Gen(Map.Get(),Progress); - if (_error->PendingError() == true) - return false; - if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL, - Files.begin(),Files.end()) == false) + std::unique_ptr Gen{nullptr}; + map_filesize_t CurrentSize = 0; + std::vector VolatileFiles = List.GetVolatileFiles(); + map_filesize_t TotalSize = ComputeSize(NULL, VolatileFiles.begin(), VolatileFiles.end()); + if (srcpkgcache_fine == true && pkgcache_fine == false) + { + if (Debug == true) + std::clog << "srcpkgcache.bin was valid - populate MMap with it" << std::endl; + if (loadBackMMapFromFile(Gen, Map, Progress, SrcCacheFile) == false) return false; + srcpkgcache_fine = true; + TotalSize += ComputeSize(NULL, Files.begin(), Files.end()); } - else + else if (srcpkgcache_fine == false) { if (Debug == true) std::clog << "srcpkgcache.bin is NOT valid - rebuild" << std::endl; - TotalSize = ComputeSize(&List, Files.begin(),Files.end()); - - // Build the source cache - pkgCacheGenerator Gen(Map.Get(),Progress); - if (_error->PendingError() == true) - return false; - if (BuildCache(Gen, Progress, CurrentSize, TotalSize, &List, - Files.end(),Files.end()) == false) + Gen.reset(new pkgCacheGenerator(Map.Get(),Progress)); + + TotalSize += ComputeSize(&List, Files.begin(),Files.end()); + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, &List, + Files.end(),Files.end()) == false) return false; - - // Write it back + if (Writeable == true && SrcCacheFile.empty() == false) - { - FileFd SCacheF(SrcCacheFile,FileFd::WriteAtomic); - if (_error->PendingError() == true) + if (writeBackMMapToFile(Gen.get(), Map.Get(), SrcCacheFile) == false) return false; - - fchmod(SCacheF.Fd(),0644); - - // Write out the main data - if (SCacheF.Write(Map->Data(),Map->Size()) == false) - return _error->Error(_("IO Error saving source cache")); - SCacheF.Sync(); - - // Write out the proper header - Gen.GetCache().HeaderP->Dirty = false; - if (SCacheF.Seek(0) == false || - SCacheF.Write(Map->Data(),sizeof(*Gen.GetCache().HeaderP)) == false) - return _error->Error(_("IO Error saving source cache")); - Gen.GetCache().HeaderP->Dirty = true; - SCacheF.Sync(); - } - - // Build the status cache - if (BuildCache(Gen, Progress, CurrentSize, TotalSize, NULL, - Files.begin(), Files.end()) == false) + } + + if (pkgcache_fine == false) + { + if (Debug == true) + std::clog << "Building status cache in pkgcache.bin now" << std::endl; + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(), Files.end()) == false) return false; + + if (Writeable == true && CacheFile.empty() == false) + if (writeBackMMapToFile(Gen.get(), Map.Get(), CacheFile) == false) + return false; } + if (Debug == true) - std::clog << "Caches are ready for shipping" << std::endl; + std::clog << "Caches done. Now bring in the volatile files (if any)" << std::endl; - if (_error->PendingError() == true) - return false; - if (OutMap != 0) + if (volatile_fine == false) { - if (CacheF != 0) + if (Gen == nullptr) { - delete Map.UnGuard(); - *OutMap = new MMap(*CacheF,0); + if (Debug == true) + std::clog << "Populate new MMap with cachefile contents" << std::endl; + if (loadBackMMapFromFile(Gen, Map, Progress, CacheFile) == false) + return false; } - else - { - *OutMap = Map.UnGuard(); - } + + Files = List.GetVolatileFiles(); + if (BuildCache(*Gen, Progress, CurrentSize, TotalSize, NULL, + Files.begin(), Files.end()) == false) + return false; } - + + if (OutMap != nullptr) + *OutMap = Map.UnGuard(); + + if (Debug == true) + std::clog << "Everything is ready for shipping" << std::endl; return true; } /*}}}*/ @@ -1817,7 +1792,7 @@ bool pkgCacheGenerator::MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **O if (_system->AddStatusFiles(Files) == false) return false; - SPtr Map = CreateDynamicMMap(NULL); + SPtr Map = CreateDynamicMMap(NULL, 0); map_filesize_t CurrentSize = 0; map_filesize_t TotalSize = 0; diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 0d0fb893f..4b6b91992 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -116,7 +116,6 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ APT_PUBLIC static bool MakeStatusCache(pkgSourceList &List,OpProgress *Progress, MMap **OutMap = 0,bool AllowMem = false); APT_PUBLIC static bool MakeOnlyStatusCache(OpProgress *Progress,DynamicMMap **OutMap); - APT_PUBLIC static DynamicMMap* CreateDynamicMMap(FileFd *CacheF, unsigned long Flags = 0); void ReMap(void const * const oldMap, void const * const newMap); diff --git a/apt-pkg/pkgsystem.h b/apt-pkg/pkgsystem.h index 5be93d059..5b31457e0 100644 --- a/apt-pkg/pkgsystem.h +++ b/apt-pkg/pkgsystem.h @@ -52,7 +52,7 @@ class Configuration; class pkgIndexFile; class pkgSystem -{ +{ public: // Global list of supported systems @@ -81,7 +81,8 @@ class pkgSystem virtual bool ArchiveSupported(const char *Type) = 0; // Return a list of system index files.. - virtual bool AddStatusFiles(std::vector &List) = 0; + virtual bool AddStatusFiles(std::vector &List) = 0; + virtual bool FindIndex(pkgCache::PkgFileIterator File, pkgIndexFile *&Found) const = 0; diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc index eef0ee709..46e51f592 100644 --- a/apt-pkg/sourcelist.cc +++ b/apt-pkg/sourcelist.cc @@ -274,6 +274,10 @@ pkgSourceList::~pkgSourceList() { for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I) delete *I; + SrcList.clear(); + for (pkgIndexFile * const File : VolatileFiles) + delete File; + VolatileFiles.clear(); } /*}}}*/ // SourceList::ReadMainList - Read the main source list from etc /*{{{*/ @@ -339,7 +343,7 @@ bool pkgSourceList::ReadAppend(string const &File) else return ParseFileOldStyle(File); } - + /*}}}*/ // SourceList::ReadFileOldStyle - Read Traditional style sources.list /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -454,7 +458,15 @@ bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File, } } } - + for (vector::const_iterator J = VolatileFiles.begin(); + J != VolatileFiles.end(); ++J) + { + if ((*J)->FindInCache(*File.Cache()) == File) + { + Found = (*J); + return true; + } + } return false; } /*}}}*/ @@ -511,4 +523,14 @@ time_t pkgSourceList::GetLastModifiedTime() return mtime_sources; } /*}}}*/ - +std::vector pkgSourceList::GetVolatileFiles() const /*{{{*/ +{ + return VolatileFiles; +} + /*}}}*/ +void pkgSourceList::AddVolatileFile(pkgIndexFile * const File) /*{{{*/ +{ + if (File != NULL) + VolatileFiles.push_back(File); +} + /*}}}*/ diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h index d80131438..47a562d18 100644 --- a/apt-pkg/sourcelist.h +++ b/apt-pkg/sourcelist.h @@ -50,6 +50,7 @@ class metaIndex; class pkgSourceList { void * const d; + std::vector VolatileFiles; public: // List of supported source list types @@ -113,6 +114,24 @@ class pkgSourceList // query last-modified time time_t GetLastModifiedTime(); + /** \brief add file for parsing, but not to the cache + * + * pkgIndexFiles origining from pkgSourcesList are included in + * srcpkgcache, the status files added via #AddStatusFiles are + * included in pkgcache, but these files here are not included in + * any cache to have the possibility of having a file included just + * for a single run like a local .deb/.dsc file. + * + * The volatile files do not count as "normal" sourceslist entries, + * can't be iterated over with #begin and #end and can't be + * downloaded, but they can be found via #FindIndex. + * + * @param File is an index file; pointer-ownership is transferred + */ + void AddVolatileFile(pkgIndexFile * const File); + /** @return list of files registered with #AddVolatileFile */ + std::vector GetVolatileFiles() const; + pkgSourceList(); virtual ~pkgSourceList(); }; diff --git a/apt-private/private-cachefile.h b/apt-private/private-cachefile.h index ed9342db0..51703b0ad 100644 --- a/apt-private/private-cachefile.h +++ b/apt-private/private-cachefile.h @@ -11,17 +11,6 @@ #include -// FIXME: we need to find a way to export this -class APT_PUBLIC SourceList : public pkgSourceList -{ - public: - // Add custom metaIndex (e.g. local files) - void AddMetaIndex(metaIndex *mi) { - SrcList.push_back(mi); - } - -}; - // class CacheFile - Cover class for some dependency cache functions /*{{{*/ class APT_PUBLIC CacheFile : public pkgCacheFile { @@ -36,16 +25,6 @@ class APT_PUBLIC CacheFile : public pkgCacheFile return false; return true; } - // FIXME: this can go once the "libapt-pkg" pkgSourceList has a way - // to add custom metaIndexes (or custom local files or so) - bool BuildSourceList(OpProgress */*Progress*/ = NULL) { - if (SrcList != NULL) - return true; - SrcList = new SourceList(); - if (SrcList->ReadMainList() == false) - return _error->Error(_("The list of sources could not be read.")); - return true; - } bool Open(bool WithLock = true) { OpTextProgress Prog(*_config); diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index 116e01038..074874903 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -647,24 +648,8 @@ bool DoInstall(CommandLine &CmdL) // first check for local pkgs and add them to the cache for (const char **I = CmdL.FileList; *I != 0; I++) { - if(FileExists(*I)) - { - // FIXME: make this more elegant - std::string TypeStr = flExtension(*I) + "-file"; - pkgSourceList::Type *Type = pkgSourceList::Type::GetType(TypeStr.c_str()); - if(Type != 0) - { - std::vector List; - std::map Options; - if(Type->CreateItem(List, *I, "", "", Options)) - { - // we have our own CacheFile that gives us a SourceList - // with superpowerz - SourceList *sources = (SourceList*)Cache.GetSourceList(); - sources->AddMetaIndex(List[0]); - } - } - } + if(FileExists(*I) && flExtension(*I) == "deb") + Cache.GetSourceList()->AddVolatileFile(new debDebPkgFileIndex(*I)); } // then open the cache diff --git a/test/integration/framework b/test/integration/framework index 6ae5003f7..f3cc1eff9 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -99,10 +99,14 @@ msgdone() { } getaptconfig() { if [ -f ./aptconfig.conf ]; then - echo "./aptconfig.conf" + echo "$(readlink -f ./aptconfig.conf)" elif [ -f ../aptconfig.conf ]; then - echo "../aptconfig.conf" - fi + echo "$(readlink -f ../aptconfig.conf)" + elif [ -f ../../aptconfig.conf ]; then + echo "$(readlink -f ../../aptconfig.conf)" + elif [ -f "${TMPWORKINGDIRECTORY}/aptconfig.conf" ]; then + echo "$(readlink -f "${TMPWORKINGDIRECTORY}/aptconfig.conf")" + fi } runapt() { msgdebug "Executing: ${CCMD}$*${CDEBUG} " @@ -141,6 +145,8 @@ gdb() { case "$1" in aptget) CMD="apt-get";; aptcache) CMD="apt-cache";; + aptcdrom) CMD="apt-cdrom";; + aptconfig) CMD="apt-config";; aptmark) CMD="apt-mark";; apthelper) CMD="apt-helper";; aptftparchive) CMD="apt-ftparchive";; diff --git a/test/integration/test-apt-get-install-deb b/test/integration/test-apt-get-install-deb index 0f34692fe..991185dea 100755 --- a/test/integration/test-apt-get-install-deb +++ b/test/integration/test-apt-get-install-deb @@ -5,15 +5,21 @@ TESTDIR=$(readlink -f $(dirname $0)) . $TESTDIR/framework setupenvironment -configarchitecture "i386" +configarchitecture 'amd64' 'i386' # regression test for #754904 testfailureequal 'E: Unable to locate package /dev/null' aptget install -qq /dev/null -# and ensure we fail for invalid debs -cat > foo.deb < foo.rpm < Date: Mon, 20 Jul 2015 10:17:29 +0200 Subject: elimate duplicated code in pkgIndexFile subclasses Trade deduplication of code for a bunch of new virtuals, so it is actually visible how the different indexes behave cleaning up the interface at large in the process. Git-Dch: Ignore --- apt-pkg/contrib/fileutl.cc | 15 +- apt-pkg/contrib/fileutl.h | 5 +- apt-pkg/deb/debindexfile.cc | 416 ++++++++---------------------- apt-pkg/deb/debindexfile.h | 84 +++--- apt-pkg/deb/deblistparser.cc | 7 +- apt-pkg/deb/deblistparser.h | 2 +- apt-pkg/edsp/edspindexfile.cc | 75 +++--- apt-pkg/edsp/edspindexfile.h | 16 +- apt-pkg/edsp/edspsystem.cc | 8 +- apt-pkg/indexfile.cc | 175 ++++++++++++- apt-pkg/indexfile.h | 79 ++++-- apt-pkg/pkgcachegen.cc | 18 +- apt-pkg/pkgcachegen.h | 17 +- cmdline/apt-internal-solver.cc | 1 + test/integration/framework | 2 +- test/integration/test-apt-get-install-deb | 12 +- 16 files changed, 460 insertions(+), 472 deletions(-) (limited to 'test') diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index f40526b5c..3b2e06431 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -2115,28 +2115,27 @@ std::string GetTempDir() /*{{{*/ return string(tmpdir); } /*}}}*/ -FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink) /*{{{*/ +FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink, FileFd * const TmpFd) /*{{{*/ { char fn[512]; - FileFd *Fd = new FileFd(); + FileFd * const Fd = TmpFd == NULL ? new FileFd() : TmpFd; - std::string tempdir = GetTempDir(); - snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", + std::string const tempdir = GetTempDir(); + snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), Prefix.c_str()); - int fd = mkstemp(fn); + int const fd = mkstemp(fn); if(ImmediateUnlink) unlink(fn); - if (fd < 0) + if (fd < 0) { _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn); return NULL; } - if (!Fd->OpenDescriptor(fd, FileFd::WriteOnly, FileFd::None, true)) + if (!Fd->OpenDescriptor(fd, FileFd::ReadWrite, FileFd::None, true)) { _error->Errno("GetTempFile",_("Unable to write to %s"),fn); return NULL; } - return Fd; } /*}}}*/ diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h index 3a99e3e61..acfd560ab 100644 --- a/apt-pkg/contrib/fileutl.h +++ b/apt-pkg/contrib/fileutl.h @@ -159,8 +159,9 @@ time_t GetModificationTime(std::string const &Path); bool Rename(std::string From, std::string To); std::string GetTempDir(); -FileFd* GetTempFile(std::string const &Prefix = "", - bool ImmediateUnlink = true); +FileFd* GetTempFile(std::string const &Prefix = "", + bool ImmediateUnlink = true, + FileFd * const TmpFd = NULL); /** \brief Ensure the existence of the given Path * diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index e67233e5f..627cd36c5 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -36,27 +36,20 @@ #include #include #include +#include #include /*}}}*/ -using std::string; - -// SourcesIndex::debSourcesIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ +// Sources Index /*{{{*/ debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) : - pkgIndexTargetFile(Target, Trusted), d(NULL) + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { } - /*}}}*/ -// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/ -// --------------------------------------------------------------------- -/* The result looks like: - http://foo/debian/ stable/main src 1.1.1 (dsc) */ -string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, +std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { - string Res = Target.Description; + // The result looks like: http://foo/debian/ stable/main src 1.1.1 (dsc) + std::string Res = Target.Description; Res.erase(Target.Description.rfind(' ')); Res += " "; @@ -67,294 +60,111 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, Res += " (" + File.Type + ")"; return Res; } - /*}}}*/ -// SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const { - string const SourcesURI = IndexFileName(); + std::string const SourcesURI = IndexFileName(); if (FileExists(SourcesURI)) return new debSrcRecordParser(SourcesURI, this); return NULL; +} +bool debSourcesIndex::OpenListFile(FileFd &, std::string const &) +{ + return true; +} +pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &) +{ + return NULL; +} +uint8_t debSourcesIndex::GetIndexFlags() const +{ + return 0; } /*}}}*/ - -// PackagesIndex::debPackagesIndex - Contructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ +// Packages Index /*{{{*/ debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) : - pkgIndexTargetFile(Target, Trusted), d(NULL) + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { } - /*}}}*/ -// PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ -// --------------------------------------------------------------------- -/* This is a shorter version that is designed to be < 60 chars or so */ -string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const +std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const { - std::string const Dist = Target.Option(IndexTarget::RELEASE); - string Res = Target.Option(IndexTarget::SITE) + " " + Dist; - std::string const Component = Target.Option(IndexTarget::COMPONENT); - if (Component.empty() == false) - Res += "/" + Component; + std::string Res = Target.Description; + Res.erase(Target.Description.rfind(' ')); Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; + std::string const Dist = Target.Option(IndexTarget::RELEASE); if (Dist.empty() == false && Dist[Dist.size() - 1] != '/') Res.append(Ver.Arch()).append(" "); Res += Ver.VerStr(); return Res; } - /*}}}*/ -// PackagesIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - string const PackageFile = IndexFileName(); - FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension); - debListParser Parser(&Pkg, Target.Option(IndexTarget::ARCHITECTURE)); - - if (_error->PendingError() == true) - return _error->Error("Problem opening %s",PackageFile.c_str()); - if (Prog != NULL) - Prog->SubProgress(0, Target.Description); - - - std::string const URI = Target.Option(IndexTarget::REPO_URI); - std::string Dist = Target.Option(IndexTarget::RELEASE); - if (Dist.empty()) - Dist = "/"; - ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile, *this, Target.Option(IndexTarget::ARCHITECTURE), Target.Option(IndexTarget::COMPONENT)) == false) - return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator File = Gen.GetCurFile(); - pkgCacheGenerator::Dynamic DynFile(File); - File->Size = Pkg.FileSize(); - File->mtime = Pkg.ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",PackageFile.c_str()); - - return true; -} - /*}}}*/ -// PackagesIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const +uint8_t debPackagesIndex::GetIndexFlags() const { - string const FileName = IndexFileName(); - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (File.FileName() == NULL || FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - - return File; + return 0; } /*}}}*/ - -// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ +// Translation-* Index /*{{{*/ debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) : - pkgIndexTargetFile(Target, true), d(NULL) + pkgDebianIndexTargetFile(Target, true), d(NULL) {} - /*}}}*/ -bool debTranslationsIndex::HasPackages() const /*{{{*/ +bool debTranslationsIndex::HasPackages() const { return Exists(); } - /*}}}*/ -// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - // Check the translation file, if in use - string const TranslationFile = IndexFileName(); - if (FileExists(TranslationFile)) - { - FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); - debTranslationsParser TransParser(&Trans); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0, Target.Description); - if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages) == false) - return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator TransFile = Gen.GetCurFile(); - TransFile->Size = Trans.FileSize(); - TransFile->mtime = Trans.ModificationTime(); - - if (Gen.MergeList(TransParser) == false) - return _error->Error("Problem with MergeList %s",TranslationFile.c_str()); - } - +bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) +{ + if (FileExists(FileName)) + return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName); return true; } - /*}}}*/ -// TranslationsIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const +uint8_t debTranslationsIndex::GetIndexFlags() const { - string FileName = IndexFileName(); - - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - return File; + return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages; } - /*}}}*/ - -// StatusIndex::debStatusIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), d(NULL), File(File) +std::string debTranslationsIndex::GetArchitecture() const { + return std::string(); } - /*}}}*/ -// StatusIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debStatusIndex::Size() const +pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg) { - struct stat S; - if (stat(File.c_str(),&S) != 0) - return 0; - return S.st_size; -} - /*}}}*/ -// StatusIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension); - if (_error->PendingError() == true) - return false; - debListParser Parser(&Pkg); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0,File); - if (Gen.SelectFile(File, *this, "", "now", pkgCache::Flag::NotSource) == false) - return _error->Error("Problem with SelectFile %s",File.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); - pkgCacheGenerator::Dynamic DynFile(CFile); - CFile->Size = Pkg.FileSize(); - CFile->mtime = Pkg.ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); - return true; + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debTranslationsParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; } /*}}}*/ -// StatusIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const +// dpkg/status Index /*{{{*/ +debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) { - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (this->File != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - return File; } - /*}}}*/ -// StatusIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -APT_CONST bool debStatusIndex::Exists() const +std::string debStatusIndex::GetArchitecture() const { - // Abort if the file does not exist. - return true; + return std::string(); } - /*}}}*/ - -// debDebPkgFileIndex - Single .deb file /*{{{*/ -debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) - : pkgIndexFile(true), d(NULL), DebFile(DebFile) +std::string debStatusIndex::GetComponent() const { - DebFileFullPath = flAbsPath(DebFile); + return "now"; } -std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const +uint8_t debStatusIndex::GetIndexFlags() const { - return "file:" + DebFileFullPath; + return pkgCache::Flag::NotSource; } -bool debDebPkgFileIndex::Exists() const + /*}}}*/ +// DebPkgFile Index - a single .deb file as an index /*{{{*/ +debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) + : pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile) { - return FileExists(DebFile); } bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile) { + struct stat Buf; + if (stat(debfile.c_str(), &Buf) != 0) + return false; + // get the control data out of the deb file via dpkg-deb -I std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb"); std::vector Args; @@ -381,91 +191,73 @@ bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &de ExecWait(Child, "Popen"); content << "Filename: " << debfile << "\n"; - struct stat Buf; - if (stat(debfile.c_str(), &Buf) != 0) - return false; content << "Size: " << Buf.st_size << "\n"; return true; } -bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const +bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) { - if(Prog) - Prog->SubProgress(0, "Reading deb file"); - // write the control data to a tempfile - SPtr DebControl = GetTempFile("deb-file-" + flNotDir(DebFile)); - if(DebControl == NULL) + if (GetTempFile("deb-file-" + flNotDir(FileName), true, &Pkg) == NULL) return false; std::ostringstream content; - if (GetContent(content, DebFile) == false) + if (GetContent(content, FileName) == false) return false; std::string const contentstr = content.str(); if (contentstr.empty()) return true; - DebControl->Write(contentstr.c_str(), contentstr.length()); - // rewind for the listparser - DebControl->Seek(0); - - // and give it to the list parser - debDebFileParser Parser(DebControl, DebFile); - if(Gen.SelectFile(DebFile, *this, "", "now", pkgCache::Flag::LocalSource) == false) - return _error->Error("Problem with SelectFile %s", DebFile.c_str()); - - pkgCache::PkgFileIterator File = Gen.GetCurFile(); - File->Size = DebControl->Size(); - File->mtime = DebControl->ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeLister for %s", DebFile.c_str()); - + if (Pkg.Write(contentstr.c_str(), contentstr.length()) == false || Pkg.Seek(0) == false) + return false; return true; } +pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debDebFileParser(&Pkg, DebFile); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; +} +uint8_t debDebPkgFileIndex::GetIndexFlags() const +{ + return pkgCache::Flag::LocalSource; +} +std::string debDebPkgFileIndex::GetArchitecture() const +{ + return std::string(); +} +std::string debDebPkgFileIndex::GetComponent() const +{ + return "local-deb"; +} pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const { + std::string const FileName = IndexFileName(); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) { - if (File.FileName() == NULL || DebFile != File.FileName()) + if (File.FileName() == NULL || FileName != File.FileName()) continue; - - return File; + // we can't do size checks here as file size != content size + return File; } return File; } -unsigned long debDebPkgFileIndex::Size() const -{ - struct stat buf; - if(stat(DebFile.c_str(), &buf) != 0) - return 0; - return buf.st_size; -} - /*}}}*/ -// debDscFileIndex - a .dsc file /*{{{*/ + /*}}}*/ +// DscFile Index - a single .dsc file as an index /*{{{*/ debDscFileIndex::debDscFileIndex(std::string const &DscFile) - : pkgIndexFile(true), d(NULL), DscFile(DscFile) + : pkgDebianIndexRealFile(DscFile, true), d(NULL) { } -bool debDscFileIndex::Exists() const -{ - return FileExists(DscFile); -} - -unsigned long debDscFileIndex::Size() const -{ - struct stat buf; - if(stat(DscFile.c_str(), &buf) == 0) - return buf.st_size; - return 0; -} pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const { - if (!FileExists(DscFile)) + if (Exists() == false) return NULL; - - return new debDscRecordParser(DscFile,this); + return new debDscRecordParser(File, this); } /*}}}*/ @@ -478,7 +270,7 @@ class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -492,7 +284,7 @@ class APT_HIDDEN debIFTypeTrans : public debIFTypePkg class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; @@ -501,7 +293,7 @@ class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debDebFileRecordParser(File.FileName()); }; @@ -510,7 +302,7 @@ class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const APT_OVERRIDE + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const APT_OVERRIDE { return new debDscRecordParser(DscFile, NULL); }; @@ -519,9 +311,9 @@ class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const APT_OVERRIDE + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const APT_OVERRIDE { - return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); + return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL); }; debIFTypeDebianSourceDir() {Label = "Debian control file";}; }; diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h index 4a818121a..02708b558 100644 --- a/apt-pkg/deb/debindexfile.h +++ b/apt-pkg/deb/debindexfile.h @@ -26,69 +26,73 @@ class OpProgress; class pkgAcquire; class pkgCacheGenerator; - -class debStatusIndex : public pkgIndexFile +class debStatusIndex : public pkgDebianIndexRealFile { void * const d; - protected: - std::string File; +protected: + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; - public: +public: virtual const Type *GetType() const APT_CONST; - // Interface for acquire - virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE {return File;}; - // Interface for the Cache Generator - virtual bool Exists() const APT_OVERRIDE; virtual bool HasPackages() const APT_OVERRIDE {return true;}; - virtual unsigned long Size() const APT_OVERRIDE; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; + // Abort if the file does not exist. + virtual bool Exists() const APT_OVERRIDE {return true;}; - debStatusIndex(std::string File); + debStatusIndex(std::string const &File); virtual ~debStatusIndex(); }; -class debPackagesIndex : public pkgIndexTargetFile +class debPackagesIndex : public pkgDebianIndexTargetFile { void * const d; - public: +protected: + virtual uint8_t GetIndexFlags() const; +public: virtual const Type *GetType() const APT_CONST; // Stuff for accessing files on remote items - virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const APT_OVERRIDE; + virtual std::string ArchiveInfo(pkgCache::VerIterator const &Ver) const APT_OVERRIDE; // Interface for the Cache Generator virtual bool HasPackages() const APT_OVERRIDE {return true;}; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; debPackagesIndex(IndexTarget const &Target, bool const Trusted); virtual ~debPackagesIndex(); }; -class debTranslationsIndex : public pkgIndexTargetFile +class debTranslationsIndex : public pkgDebianIndexTargetFile { void * const d; - public: +protected: + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; + +public: virtual const Type *GetType() const APT_CONST; // Interface for the Cache Generator virtual bool HasPackages() const APT_OVERRIDE; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; - virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; debTranslationsIndex(IndexTarget const &Target); virtual ~debTranslationsIndex(); }; -class debSourcesIndex : public pkgIndexTargetFile +class debSourcesIndex : public pkgDebianIndexTargetFile { void * const d; + virtual uint8_t GetIndexFlags() const; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; + public: virtual const Type *GetType() const APT_CONST; @@ -107,19 +111,20 @@ class debSourcesIndex : public pkgIndexTargetFile virtual ~debSourcesIndex(); }; -class debDebPkgFileIndex : public pkgIndexFile +class debDebPkgFileIndex : public pkgDebianIndexRealFile { - private: void * const d; std::string DebFile; - std::string DebFileFullPath; - public: - virtual const Type *GetType() const APT_CONST; +protected: + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; - virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE { - return DebFile; - } +public: + virtual const Type *GetType() const APT_CONST; /** get the control (file) content of the deb file * @@ -130,35 +135,22 @@ class debDebPkgFileIndex : public pkgIndexFile static bool GetContent(std::ostream &content, std::string const &debfile); // Interface for the Cache Generator - virtual bool Exists() const APT_OVERRIDE; - virtual bool HasPackages() const APT_OVERRIDE { - return true; - }; - virtual unsigned long Size() const APT_OVERRIDE; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE {return true;} virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; // Interface for acquire - virtual std::string ArchiveURI(std::string /*File*/) const APT_OVERRIDE; debDebPkgFileIndex(std::string const &DebFile); virtual ~debDebPkgFileIndex(); }; -class debDscFileIndex : public pkgIndexFile +class debDscFileIndex : public pkgDebianIndexRealFile { - private: void * const d; - std::string DscFile; public: virtual const Type *GetType() const APT_CONST; virtual pkgSrcRecords::Parser *CreateSrcParser() const APT_OVERRIDE; - virtual bool Exists() const APT_OVERRIDE; virtual bool HasPackages() const APT_OVERRIDE {return false;}; - virtual unsigned long Size() const APT_OVERRIDE; - virtual std::string Describe(bool /*Short*/) const APT_OVERRIDE { - return DscFile; - }; debDscFileIndex(std::string const &DscFile); virtual ~debDscFileIndex(); diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index b7988d499..cb2b15668 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -50,8 +50,9 @@ static debListParser::WordList PrioList[] = { /* Provide an architecture and only this one and "all" will be accepted in Step(), if no Architecture is given we will accept every arch we would accept in general with checkArchitecture() */ -debListParser::debListParser(FileFd *File, string const &Arch) : d(NULL), Tags(File), - Arch(Arch) { +debListParser::debListParser(FileFd *File, string const &Arch) : + pkgCacheListParser(), d(NULL), Tags(File), Arch(Arch) +{ if (Arch == "native") this->Arch = _config->Find("APT::Architecture"); Architectures = APT::Configuration::getArchitectures(); @@ -931,7 +932,7 @@ unsigned char debListParser::GetPrio(string Str) bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/ pkgCache::VerIterator const &Ver) { - if (pkgCacheGenerator::ListParser::SameVersion(Hash, Ver) == false) + if (pkgCacheListParser::SameVersion(Hash, Ver) == false) return false; // status file has no (Download)Size, but all others are fair game // status file is parsed last, so the first version we encounter is diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 30e52718d..975620070 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -26,7 +26,7 @@ class FileFd; -class APT_HIDDEN debListParser : public pkgCacheGenerator::ListParser +class APT_HIDDEN debListParser : public pkgCacheListParser { public: diff --git a/apt-pkg/edsp/edspindexfile.cc b/apt-pkg/edsp/edspindexfile.cc index 649d94b5d..a8a528131 100644 --- a/apt-pkg/edsp/edspindexfile.cc +++ b/apt-pkg/edsp/edspindexfile.cc @@ -26,59 +26,66 @@ #include /*}}}*/ -// edspIndex::edspIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -edspIndex::edspIndex(std::string File) : debStatusIndex(File), d(NULL) +// EDSP Index /*{{{*/ +edspIndex::edspIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) { } - /*}}}*/ -// StatusIndex::Merge - Load the index file into a cache /*{{{*/ -bool edspIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const +std::string edspIndex::GetComponent() const { - FileFd Pkg; - if (File != "stdin") - Pkg.Open(File, FileFd::ReadOnly); - else - Pkg.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - edspListParser Parser(&Pkg); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0,File); - if (Gen.SelectFile(File, *this, "", "edsp") == false) - return _error->Error("Problem with SelectFile %s",File.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); - pkgCacheGenerator::Dynamic DynFile(CFile); - CFile->Size = Pkg.FileSize(); - CFile->mtime = Pkg.ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); + return "edsp"; +} +std::string edspIndex::GetArchitecture() const +{ + return std::string(); +} +bool edspIndex::HasPackages() const +{ + return true; +} +bool edspIndex::Exists() const +{ + return true; +} +uint8_t edspIndex::GetIndexFlags() const +{ + return 0; +} +bool edspIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) +{ + if (FileName.empty() == false && FileName != "stdin") + return pkgDebianIndexRealFile::OpenListFile(Pkg, FileName); + if (Pkg.OpenDescriptor(STDIN_FILENO, FileFd::ReadOnly) == false) + return _error->Error("Problem opening %s",FileName.c_str()); return true; +} +pkgCacheListParser * edspIndex::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new edspListParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; } /*}}}*/ + // Index File types for APT /*{{{*/ class APT_HIDDEN edspIFType: public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator) const APT_OVERRIDE + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &) const APT_OVERRIDE { // we don't have a record parser for this type as the file is not presistent return NULL; }; edspIFType() {Label = "EDSP scenario file";}; }; -APT_HIDDEN edspIFType _apt_Universe; +APT_HIDDEN edspIFType _apt_Edsp; const pkgIndexFile::Type *edspIndex::GetType() const { - return &_apt_Universe; + return &_apt_Edsp; } /*}}}*/ diff --git a/apt-pkg/edsp/edspindexfile.h b/apt-pkg/edsp/edspindexfile.h index b2a510f14..edf799023 100644 --- a/apt-pkg/edsp/edspindexfile.h +++ b/apt-pkg/edsp/edspindexfile.h @@ -18,18 +18,24 @@ class OpProgress; class pkgCacheGenerator; -class APT_HIDDEN edspIndex : public debStatusIndex +class APT_HIDDEN edspIndex : public pkgDebianIndexRealFile { /** \brief dpointer placeholder (for later in case we need it) */ void * const d; - public: +protected: + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg) APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &File) APT_OVERRIDE; + virtual uint8_t GetIndexFlags() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; +public: virtual const Type *GetType() const APT_CONST; + virtual bool Exists() const APT_OVERRIDE; + virtual bool HasPackages() const APT_OVERRIDE; - virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const APT_OVERRIDE; - - edspIndex(std::string File); + edspIndex(std::string const &File); virtual ~edspIndex(); }; diff --git a/apt-pkg/edsp/edspsystem.cc b/apt-pkg/edsp/edspsystem.cc index f65fcc0d2..c4583252f 100644 --- a/apt-pkg/edsp/edspsystem.cc +++ b/apt-pkg/edsp/edspsystem.cc @@ -81,13 +81,9 @@ bool edspSystem::ArchiveSupported(const char * /*Type*/) return false; } /*}}}*/ -// System::Score - Determine if we should use the edsp system /*{{{*/ -signed edspSystem::Score(Configuration const &Cnf) +// System::Score - Never use the EDSP system automatically /*{{{*/ +signed edspSystem::Score(Configuration const &) { - if (Cnf.Find("edsp::scenario", "") == "stdin") - return 1000; - if (RealFileExists(Cnf.FindFile("edsp::scenario","")) == true) - return 1000; return -1000; } /*}}}*/ diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index cce17403d..b592ae5a0 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -16,14 +16,23 @@ #include #include #include +#include #include #include +#include #include +#include + +#include +#include +#include + #include #include #include #include +#include /*}}}*/ // Global list of Item supported @@ -52,13 +61,13 @@ pkgIndexFile::Type *pkgIndexFile::Type::GetType(const char *Type) return 0; } /*}}}*/ -pkgIndexFile::pkgIndexFile(bool Trusted) : /*{{{*/ +pkgIndexFile::pkgIndexFile(bool const Trusted) : /*{{{*/ d(NULL), Trusted(Trusted) { } /*}}}*/ // IndexFile::ArchiveInfo - Stub /*{{{*/ -std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator /*Ver*/) const +std::string pkgIndexFile::ArchiveInfo(pkgCache::VerIterator const &/*Ver*/) const { return std::string(); } @@ -89,7 +98,7 @@ bool pkgIndexFile::TranslationsAvailable() { is already done in getLanguages(). Note also that this check is rather bad (doesn't take three character like ast into account). TODO: Remove method with next API break */ -APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char *Lang) +APT_DEPRECATED bool pkgIndexFile::CheckLanguageCode(const char * const Lang) { if (strlen(Lang) == 2 || (strlen(Lang) == 5 && Lang[2] == '_')) return true; @@ -172,24 +181,24 @@ std::string IndexTarget::Format(std::string format) const /*{{{*/ } /*}}}*/ -pkgIndexTargetFile::pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ - pkgIndexFile(Trusted), d(NULL), Target(Target) +pkgDebianIndexTargetFile::pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted) :/*{{{*/ + pkgDebianIndexFile(Trusted), d(NULL), Target(Target) { } /*}}}*/ -std::string pkgIndexTargetFile::ArchiveURI(std::string File) const/*{{{*/ +std::string pkgDebianIndexTargetFile::ArchiveURI(std::string const &File) const/*{{{*/ { return Target.Option(IndexTarget::REPO_URI) + File; } /*}}}*/ -std::string pkgIndexTargetFile::Describe(bool Short) const /*{{{*/ +std::string pkgDebianIndexTargetFile::Describe(bool const Short) const /*{{{*/ { if (Short) return Target.Description; return Target.Description + " (" + IndexFileName() + ")"; } /*}}}*/ -std::string pkgIndexTargetFile::IndexFileName() const /*{{{*/ +std::string pkgDebianIndexTargetFile::IndexFileName() const /*{{{*/ { std::string const s = Target.Option(IndexTarget::FILENAME); if (FileExists(s)) @@ -205,7 +214,7 @@ std::string pkgIndexTargetFile::IndexFileName() const /*{{{*/ return s; } /*}}}*/ -unsigned long pkgIndexTargetFile::Size() const /*{{{*/ +unsigned long pkgDebianIndexTargetFile::Size() const /*{{{*/ { unsigned long size = 0; @@ -223,11 +232,155 @@ unsigned long pkgIndexTargetFile::Size() const /*{{{*/ return size; } /*}}}*/ -bool pkgIndexTargetFile::Exists() const /*{{{*/ +bool pkgDebianIndexTargetFile::Exists() const /*{{{*/ { return FileExists(IndexFileName()); } /*}}}*/ +std::string pkgDebianIndexTargetFile::GetArchitecture() const /*{{{*/ +{ + return Target.Option(IndexTarget::ARCHITECTURE); +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::GetComponent() const /*{{{*/ +{ + return Target.Option(IndexTarget::COMPONENT); +} + /*}}}*/ +bool pkgDebianIndexTargetFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/ +{ + if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::Extension) == false) + return _error->Error("Problem opening %s",FileName.c_str()); + return true; +} + /*}}}*/ +std::string pkgDebianIndexTargetFile::GetProgressDescription() const +{ + return Target.Description; +} + +pkgDebianIndexRealFile::pkgDebianIndexRealFile(std::string const &File, bool const Trusted) :/*{{{*/ + pkgDebianIndexFile(Trusted), d(NULL), File(flAbsPath(File)) +{ +} + /*}}}*/ +// IndexRealFile::Size - Return the size of the index /*{{{*/ +unsigned long pkgDebianIndexRealFile::Size() const +{ + struct stat S; + if (stat(File.c_str(),&S) != 0) + return 0; + return S.st_size; +} + /*}}}*/ +bool pkgDebianIndexRealFile::Exists() const /*{{{*/ +{ + return FileExists(File); +} + /*}}}*/ +std::string pkgDebianIndexRealFile::Describe(bool const /*Short*/) const/*{{{*/ +{ + return File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::ArchiveURI(std::string const &/*File*/) const/*{{{*/ +{ + return "file:" + File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::IndexFileName() const /*{{{*/ +{ + return File; +} + /*}}}*/ +std::string pkgDebianIndexRealFile::GetProgressDescription() const +{ + return File; +} +bool pkgDebianIndexRealFile::OpenListFile(FileFd &Pkg, std::string const &FileName)/*{{{*/ +{ + if (Pkg.Open(FileName, FileFd::ReadOnly, FileFd::None) == false) + return _error->Error("Problem opening %s",FileName.c_str()); + return true; +} + /*}}}*/ + +pkgDebianIndexFile::pkgDebianIndexFile(bool const Trusted) : pkgIndexFile(Trusted) +{ +} +pkgDebianIndexFile::~pkgDebianIndexFile() +{ +} +pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg) +{ + if (Pkg.IsOpen() == false) + return NULL; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debListParser(&Pkg, GetArchitecture()); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + return newError ? NULL : Parser; +} +bool pkgDebianIndexFile::Merge(pkgCacheGenerator &Gen,OpProgress * const Prog) +{ + std::string const PackageFile = IndexFileName(); + FileFd Pkg; + if (OpenListFile(Pkg, PackageFile) == false) + return false; + _error->PushToStack(); + std::unique_ptr Parser(CreateListParser(Pkg)); + bool const newError = _error->PendingError(); + if (newError == false && Parser == nullptr) + return true; + if (Parser == NULL) + return false; + + if (Prog != NULL) + Prog->SubProgress(0, GetProgressDescription()); + + if (Gen.SelectFile(PackageFile, *this, GetArchitecture(), GetComponent(), GetIndexFlags()) == false) + return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); + + // Store the IMS information + pkgCache::PkgFileIterator File = Gen.GetCurFile(); + pkgCacheGenerator::Dynamic DynFile(File); + File->Size = Pkg.FileSize(); + File->mtime = Pkg.ModificationTime(); + + if (Gen.MergeList(*Parser) == false) + return _error->Error("Problem with MergeList %s",PackageFile.c_str()); + return true; +} +pkgCache::PkgFileIterator pkgDebianIndexFile::FindInCache(pkgCache &Cache) const +{ + std::string const FileName = IndexFileName(); + pkgCache::PkgFileIterator File = Cache.FileBegin(); + for (; File.end() == false; ++File) + { + if (File.FileName() == NULL || FileName != File.FileName()) + continue; + + struct stat St; + if (stat(File.FileName(),&St) != 0) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "DebianIndexFile::FindInCache - stat failed on " << File.FileName() << std::endl; + return pkgCache::PkgFileIterator(Cache); + } + if ((map_filesize_t)St.st_size != File->Size || St.st_mtime != File->mtime) + { + if (_config->FindB("Debug::pkgCacheGen", false)) + std::clog << "DebianIndexFile::FindInCache - size (" << St.st_size << " <> " << File->Size + << ") or mtime (" << St.st_mtime << " <> " << File->mtime + << ") doesn't match for " << File.FileName() << std::endl; + return pkgCache::PkgFileIterator(Cache); + } + return File; + } + + return File; +} APT_CONST pkgIndexFile::~pkgIndexFile() {} -APT_CONST pkgIndexTargetFile::~pkgIndexTargetFile() {} +APT_CONST pkgDebianIndexTargetFile::~pkgDebianIndexTargetFile() {} +APT_CONST pkgDebianIndexRealFile::~pkgDebianIndexRealFile() {} diff --git a/apt-pkg/indexfile.h b/apt-pkg/indexfile.h index 5be7794bf..77e80ed41 100644 --- a/apt-pkg/indexfile.h +++ b/apt-pkg/indexfile.h @@ -38,6 +38,7 @@ class pkgAcquire; #endif class pkgCacheGenerator; +class pkgCacheListParser; class OpProgress; class IndexTarget /*{{{*/ @@ -105,12 +106,12 @@ class pkgIndexFile // Global list of Items supported static Type **GlobalList; static unsigned long GlobalListLen; - static Type *GetType(const char *Type) APT_PURE; + static Type *GetType(const char * const Type) APT_PURE; const char *Label; - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator /*File*/) const {return 0;}; - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string /*File*/) const {return 0;}; + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &/*File*/) const {return 0;}; + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &/*File*/) const {return 0;}; Type(); virtual ~Type() {}; }; @@ -118,13 +119,13 @@ class pkgIndexFile virtual const Type *GetType() const = 0; // Return descriptive strings of various sorts - virtual std::string ArchiveInfo(pkgCache::VerIterator Ver) const; + virtual std::string ArchiveInfo(pkgCache::VerIterator const &Ver) const; virtual std::string SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const; - virtual std::string Describe(bool Short = false) const = 0; + virtual std::string Describe(bool const Short = false) const = 0; // Interface for acquire - virtual std::string ArchiveURI(std::string /*File*/) const {return std::string();}; + virtual std::string ArchiveURI(std::string const &/*File*/) const {return std::string();}; // Interface for the record parsers virtual pkgSrcRecords::Parser *CreateSrcParser() const {return 0;}; @@ -133,40 +134,78 @@ class pkgIndexFile virtual bool Exists() const = 0; virtual bool HasPackages() const = 0; virtual unsigned long Size() const = 0; - virtual bool Merge(pkgCacheGenerator &/*Gen*/, OpProgress* /*Prog*/) const { return false; }; - APT_DEPRECATED virtual bool Merge(pkgCacheGenerator &Gen, OpProgress &Prog) const - { return Merge(Gen, &Prog); }; - virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) const {return true;}; - APT_DEPRECATED virtual bool MergeFileProvides(pkgCacheGenerator &Gen, OpProgress &Prog) const - {return MergeFileProvides(Gen, &Prog);}; + virtual bool Merge(pkgCacheGenerator &/*Gen*/, OpProgress* const /*Prog*/) { return true; }; + virtual bool MergeFileProvides(pkgCacheGenerator &/*Gen*/,OpProgress* /*Prog*/) {return true;}; virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const; static bool TranslationsAvailable(); - static bool CheckLanguageCode(const char *Lang); + static bool CheckLanguageCode(const char * const Lang); static std::string LanguageCode(); bool IsTrusted() const { return Trusted; }; - explicit pkgIndexFile(bool Trusted); + explicit pkgIndexFile(bool const Trusted); virtual ~pkgIndexFile(); }; -class pkgIndexTargetFile : public pkgIndexFile +class pkgDebianIndexFile : public pkgIndexFile +{ +protected: + virtual std::string IndexFileName() const = 0; + virtual std::string GetComponent() const = 0; + virtual std::string GetArchitecture() const = 0; + virtual std::string GetProgressDescription() const = 0; + virtual uint8_t GetIndexFlags() const = 0; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) = 0; + APT_HIDDEN virtual pkgCacheListParser * CreateListParser(FileFd &Pkg); + +public: + virtual bool Merge(pkgCacheGenerator &Gen, OpProgress* const Prog) APT_OVERRIDE; + virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const APT_OVERRIDE; + + pkgDebianIndexFile(bool const Trusted); + virtual ~pkgDebianIndexFile(); +}; + +class pkgDebianIndexTargetFile : public pkgDebianIndexFile { void * const d; protected: IndexTarget const Target; - std::string IndexFileName() const; + virtual std::string IndexFileName() const APT_OVERRIDE; + virtual std::string GetComponent() const APT_OVERRIDE; + virtual std::string GetArchitecture() const APT_OVERRIDE; + virtual std::string GetProgressDescription() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; + +public: + virtual std::string ArchiveURI(std::string const &File) const APT_OVERRIDE; + virtual std::string Describe(bool const Short = false) const APT_OVERRIDE; + virtual bool Exists() const APT_OVERRIDE; + virtual unsigned long Size() const APT_OVERRIDE; + + pkgDebianIndexTargetFile(IndexTarget const &Target, bool const Trusted); + virtual ~pkgDebianIndexTargetFile(); +}; + +class pkgDebianIndexRealFile : public pkgDebianIndexFile +{ + void * const d; +protected: + std::string File; + virtual std::string IndexFileName() const APT_OVERRIDE; + virtual std::string GetProgressDescription() const APT_OVERRIDE; + virtual bool OpenListFile(FileFd &Pkg, std::string const &FileName) APT_OVERRIDE; public: - virtual std::string ArchiveURI(std::string File) const APT_OVERRIDE; - virtual std::string Describe(bool Short = false) const APT_OVERRIDE; + virtual std::string Describe(bool const /*Short*/ = false) const APT_OVERRIDE; virtual bool Exists() const APT_OVERRIDE; virtual unsigned long Size() const APT_OVERRIDE; + virtual std::string ArchiveURI(std::string const &/*File*/) const APT_OVERRIDE; - pkgIndexTargetFile(IndexTarget const &Target, bool const Trusted); - virtual ~pkgIndexTargetFile(); + pkgDebianIndexRealFile(std::string const &File, bool const Trusted); + virtual ~pkgDebianIndexRealFile(); }; #endif diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index 9529f42dc..cf845b0fb 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -1051,7 +1051,7 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg, // --------------------------------------------------------------------- /* This creates a Group and the Package to link this dependency to if needed and handles also the caching of the old endpoint */ -bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, +bool pkgCacheListParser::NewDepends(pkgCache::VerIterator &Ver, const string &PackageName, const string &Arch, const string &Version, @@ -1077,7 +1077,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, if (idxVersion == 0) { - idxVersion = StoreString(VERSIONNUMBER, Version); + idxVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); if (unlikely(idxVersion == 0)) return false; } @@ -1124,7 +1124,7 @@ bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator &Ver, } /*}}}*/ // ListParser::NewProvides - Create a Provides element /*{{{*/ -bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, +bool pkgCacheListParser::NewProvides(pkgCache::VerIterator &Ver, const string &PkgName, const string &PkgArch, const string &Version, @@ -1145,7 +1145,7 @@ bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator &Ver, map_stringitem_t idxProvideVersion = 0; if (Version.empty() == false) { - idxProvideVersion = StoreString(VERSIONNUMBER, Version); + idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); if (unlikely(idxProvideVersion == 0)) return false; } @@ -1178,7 +1178,7 @@ bool pkgCacheGenerator::NewProvides(pkgCache::VerIterator &Ver, } /*}}}*/ // ListParser::NewProvidesAllArch - add provides for all architectures /*{{{*/ -bool pkgCacheGenerator::ListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, +bool pkgCacheListParser::NewProvidesAllArch(pkgCache::VerIterator &Ver, string const &Package, string const &Version, uint8_t const Flags) { pkgCache &Cache = Owner->Cache; pkgCache::GrpIterator const Grp = Cache.FindGrp(Package); @@ -1188,7 +1188,7 @@ bool pkgCacheGenerator::ListParser::NewProvidesAllArch(pkgCache::VerIterator &Ve { map_stringitem_t idxProvideVersion = 0; if (Version.empty() == false) { - idxProvideVersion = StoreString(VERSIONNUMBER, Version); + idxProvideVersion = StoreString(pkgCacheGenerator::VERSIONNUMBER, Version); if (unlikely(idxProvideVersion == 0)) return false; } @@ -1209,7 +1209,7 @@ bool pkgCacheGenerator::ListParser::NewProvidesAllArch(pkgCache::VerIterator &Ve return true; } /*}}}*/ -bool pkgCacheGenerator::ListParser::SameVersion(unsigned short const Hash,/*{{{*/ +bool pkgCacheListParser::SameVersion(unsigned short const Hash, /*{{{*/ pkgCache::VerIterator const &Ver) { return Hash == Ver->Hash; @@ -1835,5 +1835,5 @@ bool pkgCacheGenerator::FinishCache(OpProgress * /*Progress*/) } /*}}}*/ -pkgCacheGenerator::ListParser::ListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false), d(NULL) {} -pkgCacheGenerator::ListParser::~ListParser() {} +pkgCacheListParser::pkgCacheListParser() : Owner(NULL), OldDepLast(NULL), FoundFileDeps(false), d(NULL) {} +pkgCacheListParser::~pkgCacheListParser() {} diff --git a/apt-pkg/pkgcachegen.h b/apt-pkg/pkgcachegen.h index 4b6b91992..15e73627d 100644 --- a/apt-pkg/pkgcachegen.h +++ b/apt-pkg/pkgcachegen.h @@ -32,10 +32,10 @@ class FileFd; class pkgSourceList; class OpProgress; class pkgIndexFile; +class pkgCacheListParser; class APT_HIDDEN pkgCacheGenerator /*{{{*/ { - private: APT_HIDDEN map_stringitem_t WriteStringInMap(std::string const &String) { return WriteStringInMap(String.c_str()); }; APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String); APT_HIDDEN map_stringitem_t WriteStringInMap(const char *String, const unsigned long &Len); @@ -46,10 +46,10 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ std::map strPkgNames; std::map strVersions; + friend class pkgCacheListParser; + typedef pkgCacheListParser ListParser; + public: - - class ListParser; - friend class ListParser; template class Dynamic { public: @@ -138,11 +138,12 @@ class APT_HIDDEN pkgCacheGenerator /*{{{*/ }; /*}}}*/ // This is the abstract package list parser class. /*{{{*/ -class APT_HIDDEN pkgCacheGenerator::ListParser +class APT_HIDDEN pkgCacheListParser { pkgCacheGenerator *Owner; friend class pkgCacheGenerator; - + template using Dynamic = pkgCacheGenerator::Dynamic; + // Some cache items pkgCache::VerIterator OldDepVer; map_pointer_t *OldDepLast; @@ -197,8 +198,8 @@ class APT_HIDDEN pkgCacheGenerator::ListParser virtual bool CollectFileProvides(pkgCache &/*Cache*/, pkgCache::VerIterator &/*Ver*/) {return true;}; - ListParser(); - virtual ~ListParser(); + pkgCacheListParser(); + virtual ~pkgCacheListParser(); }; /*}}}*/ diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc index 939061b93..af301dbcd 100644 --- a/cmdline/apt-internal-solver.cc +++ b/cmdline/apt-internal-solver.cc @@ -109,6 +109,7 @@ int main(int argc,const char *argv[]) /*{{{*/ if (_config->FindI("quiet", 0) < 1) _config->Set("Debug::EDSP::WriteSolution", true); + _config->Set("APT::System", "Debian APT solver interface"); _config->Set("APT::Solver", "internal"); _config->Set("edsp::scenario", "stdin"); int input = STDIN_FILENO; diff --git a/test/integration/framework b/test/integration/framework index f3cc1eff9..53157e2d0 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1296,7 +1296,7 @@ testdpkgstatus() { local PKGS="$(dpkg -l "$@" 2>/dev/null | grep "^${STATE}" | wc -l)" if [ "$PKGS" != $NR ]; then echo >&2 $PKGS - dpkg -l "$@" | grep '^[a-z]' >&2 + dpkg -l "$@" | grep '^[a-z]' >&2 || true msgfail else msgpass diff --git a/test/integration/test-apt-get-install-deb b/test/integration/test-apt-get-install-deb index 991185dea..bd720bede 100755 --- a/test/integration/test-apt-get-install-deb +++ b/test/integration/test-apt-get-install-deb @@ -22,9 +22,9 @@ E: Couldn't find any package by regex './foo.rpm'" aptget install -qq ./foo.rpm mv foo.rpm foo.deb testfailure aptget install ./foo.deb testsuccess grep '^E: Sub-process Popen returned an error code' rootdir/tmp/testfailure.output -testequal 'E: Encountered a section with no Package: header -E: Problem with MergeLister for ./foo.deb -E: The package lists or status file could not be parsed or opened.' tail -n 3 rootdir/tmp/testfailure.output +testequal "E: Encountered a section with no Package: header +E: Problem with MergeList ${TMPWORKINGDIRECTORY}/foo.deb +E: The package lists or status file could not be parsed or opened." tail -n 3 rootdir/tmp/testfailure.output # fakeroot is currently not found, framwork needs updating buildsimplenativepackage 'foo' 'i386,amd64' '1.0' @@ -45,7 +45,7 @@ The following packages have unmet dependencies: E: Unable to correct problems, you have held broken packages." aptget install ./incoming/foo_1.0_i386.deb ./incoming/foo_1.0_amd64.deb -s -q=0 testdpkgnotinstalled 'foo' -testsuccess aptget install ./incoming/foo_1.0_i386.deb +testsuccess aptget install ./incoming/foo_1.0_i386.deb -o Debug::pkgCacheGen=1 testdpkginstalled 'foo' testsuccessequal "Reading package lists... @@ -58,5 +58,5 @@ The following NEW packages will be installed: foo 0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. Remv foo:i386 [1.0] -Inst foo (1.0 now [amd64]) -Conf foo (1.0 now [amd64])" aptget install ./incoming/foo_1.0_amd64.deb -s -q=0 +Inst foo (1.0 local-deb [amd64]) +Conf foo (1.0 local-deb [amd64])" aptget install ./incoming/foo_1.0_amd64.deb -s -q=0 -- cgit v1.2.3-70-g09d2 From 7f8c0eed6983db7b8959f1498fc8bc80c98d719e Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 20 Jul 2015 12:32:46 +0200 Subject: parse packages from all architectures into the cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we can dynamically create dependencies and provides as needed rather than requiring to know with which architectures we will deal before running we can allow the listparser to parse all records rather than skipping records of "unknown" architectures. This can e.g. happen if a user has foreign architecture packages in his status file without dpkg knowing about this architecture (or apt configured in this way). A sideeffect is that now arch:all packages are (correctly) recorded as available from any Packages file, not just from the native one – which has its downsides for the resolver as mixed-arch source packages can appear in different architectures at different times, but that is the problem of the resolver and dealing with it in the parser is at best a hack (and also depends on a helpful repository). Another sideeffect is that his allows :none packages to appear in Packages files again as we don't do any kind of checks now, but given that they aren't really supported (anymore) by anyone we can live with that. --- apt-pkg/deb/deblistparser.cc | 39 +--------- apt-pkg/deb/deblistparser.h | 9 +-- apt-pkg/edsp/edsplistparser.cc | 2 +- apt-pkg/edsp/edsplistparser.h | 2 +- apt-pkg/indexfile.cc | 2 +- apt-pkg/pkgcache.cc | 87 +++++++++------------ test/integration/test-apt-cache | 3 +- .../test-bug-612958-use-dpkg-multiarch-config | 19 ++--- .../test-bug-686346-package-missing-architecture | 8 -- test/integration/test-parse-all-archs-into-cache | 91 ++++++++++++++++++++++ .../test-specific-architecture-dependencies | 6 +- 11 files changed, 152 insertions(+), 116 deletions(-) create mode 100755 test/integration/test-parse-all-archs-into-cache (limited to 'test') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index cb2b15668..c7c4ffe77 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -50,13 +50,9 @@ static debListParser::WordList PrioList[] = { /* Provide an architecture and only this one and "all" will be accepted in Step(), if no Architecture is given we will accept every arch we would accept in general with checkArchitecture() */ -debListParser::debListParser(FileFd *File, string const &Arch) : - pkgCacheListParser(), d(NULL), Tags(File), Arch(Arch) +debListParser::debListParser(FileFd *File) : + pkgCacheListParser(), d(NULL), Tags(File) { - if (Arch == "native") - this->Arch = _config->Find("APT::Architecture"); - Architectures = APT::Configuration::getArchitectures(); - MultiArchEnabled = Architectures.size() > 1; } /*}}}*/ // ListParser::Package - Return the package name /*{{{*/ @@ -887,34 +883,7 @@ bool debListParser::GrabWord(string Word,WordList *List,unsigned char &Out) bool debListParser::Step() { iOffset = Tags.Offset(); - while (Tags.Step(Section) == true) - { - /* See if this is the correct Architecture, if it isn't then we - drop the whole section. A missing arch tag only happens (in theory) - inside the Status file, so that is a positive return */ - string const Architecture = Section.FindS("Architecture"); - - if (Arch.empty() == true || Arch == "any" || MultiArchEnabled == false) - { - if (APT::Configuration::checkArchitecture(Architecture) == true) - return true; - /* parse version stanzas without an architecture only in the status file - (and as misfortune bycatch flat-archives) */ - if ((Arch.empty() == true || Arch == "any") && Architecture.empty() == true) - return true; - } - else - { - if (Architecture == Arch) - return true; - - if (Architecture == "all" && Arch == _config->Find("APT::Architecture")) - return true; - } - - iOffset = Tags.Offset(); - } - return false; + return Tags.Step(Section); } /*}}}*/ // ListParser::GetPrio - Convert the priority from a string /*{{{*/ @@ -950,7 +919,7 @@ bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/ /*}}}*/ debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile) - : debListParser(File, ""), DebFile(DebFile) + : debListParser(File), DebFile(DebFile) { } diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 975620070..747e022d8 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -45,9 +45,6 @@ class APT_HIDDEN debListParser : public pkgCacheListParser pkgTagFile Tags; pkgTagSection Section; map_filesize_t iOffset; - std::string Arch; - std::vector Architectures; - bool MultiArchEnabled; virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); bool ParseDepends(pkgCache::VerIterator &Ver,const char *Tag, @@ -96,7 +93,7 @@ class APT_HIDDEN debListParser : public pkgCacheListParser APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op); - debListParser(FileFd *File, std::string const &Arch = ""); + debListParser(FileFd *File); virtual ~debListParser(); }; @@ -118,8 +115,8 @@ class APT_HIDDEN debTranslationsParser : public debListParser virtual std::string Architecture() APT_OVERRIDE { return ""; } virtual std::string Version() APT_OVERRIDE { return ""; } - debTranslationsParser(FileFd *File, std::string const &Arch = "") - : debListParser(File, Arch) {}; + debTranslationsParser(FileFd *File) + : debListParser(File) {}; }; #endif diff --git a/apt-pkg/edsp/edsplistparser.cc b/apt-pkg/edsp/edsplistparser.cc index 63f006628..a54a46b1e 100644 --- a/apt-pkg/edsp/edsplistparser.cc +++ b/apt-pkg/edsp/edsplistparser.cc @@ -22,7 +22,7 @@ /*}}}*/ // ListParser::edspListParser - Constructor /*{{{*/ -edspListParser::edspListParser(FileFd *File, std::string const &Arch) : debListParser(File, Arch), d(NULL) +edspListParser::edspListParser(FileFd *File) : debListParser(File), d(NULL) {} /*}}}*/ // ListParser::NewVersion - Fill in the version structure /*{{{*/ diff --git a/apt-pkg/edsp/edsplistparser.h b/apt-pkg/edsp/edsplistparser.h index 2a09e8c47..221229302 100644 --- a/apt-pkg/edsp/edsplistparser.h +++ b/apt-pkg/edsp/edsplistparser.h @@ -38,7 +38,7 @@ class APT_HIDDEN edspListParser : public debListParser bool LoadReleaseInfo(pkgCache::RlsFileIterator &FileI,FileFd &File, std::string const §ion); - edspListParser(FileFd *File, std::string const &Arch = ""); + edspListParser(FileFd *File); virtual ~edspListParser(); protected: diff --git a/apt-pkg/indexfile.cc b/apt-pkg/indexfile.cc index b592ae5a0..06312c173 100644 --- a/apt-pkg/indexfile.cc +++ b/apt-pkg/indexfile.cc @@ -316,7 +316,7 @@ pkgCacheListParser * pkgDebianIndexFile::CreateListParser(FileFd &Pkg) if (Pkg.IsOpen() == false) return NULL; _error->PushToStack(); - pkgCacheListParser * const Parser = new debListParser(&Pkg, GetArchitecture()); + pkgCacheListParser * const Parser = new debListParser(&Pkg); bool const newError = _error->PendingError(); _error->MergeWithStack(); return newError ? NULL : Parser; diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index e8c95738e..045d7b41e 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -866,10 +868,32 @@ pkgCache::VerFileIterator pkgCache::VerIterator::NewestFile() const // --------------------------------------------------------------------- /* This describes the version from a release-centric manner. The output is a list of Label:Version/Archive */ +static std::string PkgFileIteratorToRelString(pkgCache::PkgFileIterator const &File) +{ + std::string Res; + if (File.Label() != 0) + Res = Res + File.Label() + ':'; + + if (File.Archive() != 0) + { + if (File.Version() == 0) + Res += File.Archive(); + else + Res = Res + File.Version() + '/' + File.Archive(); + } + else + { + // No release file, print the host name that this came from + if (File.Site() == 0 || File.Site()[0] == 0) + Res += "localhost"; + else + Res += File.Site(); + } + return Res; +} string pkgCache::VerIterator::RelStr() const { - bool First = true; - string Res; + std::vector RelStrs; for (pkgCache::VerFileIterator I = this->FileList(); I.end() == false; ++I) { // Do not print 'not source' entries' @@ -877,58 +901,21 @@ string pkgCache::VerIterator::RelStr() const if (File.Flagged(pkgCache::Flag::NotSource)) continue; - // See if we have already printed this out.. - bool Seen = false; - for (pkgCache::VerFileIterator J = this->FileList(); I != J; ++J) - { - pkgCache::PkgFileIterator const File2 = J.File(); - if (File2.Label() == 0 || File.Label() == 0) - continue; - - if (strcmp(File.Label(),File2.Label()) != 0) - continue; - - if (File2.Version() == File.Version()) - { - Seen = true; - break; - } - if (File2.Version() == 0 || File.Version() == 0) - break; - if (strcmp(File.Version(),File2.Version()) == 0) - Seen = true; - } - - if (Seen == true) + std::string const RS = PkgFileIteratorToRelString(File); + if (std::find(RelStrs.begin(), RelStrs.end(), RS) != RelStrs.end()) continue; - - if (First == false) - Res += ", "; - else - First = false; - - if (File.Label() != 0) - Res = Res + File.Label() + ':'; - if (File.Archive() != 0) - { - if (File.Version() == 0) - Res += File.Archive(); - else - Res = Res + File.Version() + '/' + File.Archive(); - } - else - { - // No release file, print the host name that this came from - if (File.Site() == 0 || File.Site()[0] == 0) - Res += "localhost"; - else - Res += File.Site(); - } + RelStrs.push_back(RS); + } + std::ostringstream os; + if (likely(RelStrs.empty() == false)) + { + std::copy(RelStrs.begin(), RelStrs.end()-1, std::ostream_iterator(os, ", ")); + os << *RelStrs.rbegin(); } if (S->ParentPkg != 0) - Res.append(" [").append(Arch()).append("]"); - return Res; + os << " [" << Arch() << "]"; + return os.str(); } /*}}}*/ // VerIterator::MultiArchType - string representing MultiArch flag /*{{{*/ diff --git a/test/integration/test-apt-cache b/test/integration/test-apt-cache index 1d90eed5c..97d180a74 100755 --- a/test/integration/test-apt-cache +++ b/test/integration/test-apt-cache @@ -54,7 +54,8 @@ testsuccessequal 'bar' aptcache pkgnames bar testsuccessequal 'fancy foo' aptcache pkgnames f -testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive unstable/main amd64 Packages" aptcache madison foo +testsuccessequal " foo | 1 | file:$(readlink -f .)/aptarchive unstable/main amd64 Packages + foo | 1 | file:$(readlink -f .)/aptarchive unstable/main i386 Packages" aptcache madison foo ### depends diff --git a/test/integration/test-bug-612958-use-dpkg-multiarch-config b/test/integration/test-bug-612958-use-dpkg-multiarch-config index 7bf5781e8..9556a5aef 100755 --- a/test/integration/test-bug-612958-use-dpkg-multiarch-config +++ b/test/integration/test-bug-612958-use-dpkg-multiarch-config @@ -5,22 +5,19 @@ TESTDIR=$(readlink -f $(dirname $0)) . $TESTDIR/framework setupenvironment configarchitecture 'i386' -setupaptarchive - -insertinstalledpackage 'libapt' 'i386' '1.0' -insertinstalledpackage 'libapt' 'amd64' '1.0' -insertinstalledpackage 'libapt' 'armel' '1.0' testpass() { - rm rootdir/var/cache/apt/*.bin - msgtest 'Test architecture handling' "$1 with $2" - testsuccess --nomsg aptcache show libapt:$2 + msgtest 'Test architecture handling success' "$1 with $2" + rm -f archs.conf + aptconfig dump --no-empty --format='%V%n' APT::Architectures > archs.conf + testsuccess --nomsg grep "^$2\$" archs.conf } testfail() { - rm rootdir/var/cache/apt/*.bin - msgtest 'Test architecture handling' "$1 with $2" - testfailure --nomsg aptcache show libapt:$2 + msgtest 'Test architecture handling failure' "$1 with $2" + rm -f archs.conf + aptconfig dump --no-empty --format='%V%n' APT::Architectures > archs.conf + testfailure --nomsg grep "^$2\$" archs.conf } testpass 'no config' 'i386' diff --git a/test/integration/test-bug-686346-package-missing-architecture b/test/integration/test-bug-686346-package-missing-architecture index d51bbabfe..dae0fa81d 100755 --- a/test/integration/test-bug-686346-package-missing-architecture +++ b/test/integration/test-bug-686346-package-missing-architecture @@ -11,7 +11,6 @@ insertinstalledpackage 'pkgd' 'none' '1' insertpackage 'unstable' 'pkga' 'amd64' '2' 'Depends: pkgb' insertpackage 'unstable' 'pkgb' 'amd64' '2' insertpackage 'unstable' 'pkgc' 'amd64' '1' 'Conflicts: pkgb' -insertpackage 'unstable' 'pkge' 'none' '1' setupaptarchive @@ -41,13 +40,6 @@ Inst pkga (2 unstable [amd64]) Conf pkgb (2 unstable [amd64]) Conf pkga (2 unstable [amd64])' aptget install pkga -s -# ensure that arch-less stanzas from Packages files are ignored -msgtest 'Package is distributed in the Packages files' 'pkge' -grep -q 'Package: pkge' $(find aptarchive -name 'Packages') && msgpass || msgfail -testnopackage pkge -testnopackage pkge:none -testnopackage pkge:* - # do not automatically change from none-arch to whatever-arch as # this breaks other none packages and dpkg has this ruleset as # this difference seems so important that it has to be maintained … diff --git a/test/integration/test-parse-all-archs-into-cache b/test/integration/test-parse-all-archs-into-cache new file mode 100755 index 000000000..f61862912 --- /dev/null +++ b/test/integration/test-parse-all-archs-into-cache @@ -0,0 +1,91 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'i386' + +insertpackage 'unstable' 'bar' 'i386' '1' 'Depends: foo' +insertpackage 'unstable' 'foo' 'i386' '1' 'Multi-Arch: foreign +Depends: libfoo1' +insertpackage 'unstable' 'libfoo1' 'i386' '1' 'Multi-Arch: same' +insertpackage 'experimental' 'foo' 'i386' '2' 'Multi-Arch: foreign +Depends: libfoo1 (>= 2)' +insertpackage 'experimental' 'libfoo1' 'i386' '2' 'Multi-Arch: same' + +# note: the system has amd64 not configured! +insertinstalledpackage 'foo' 'amd64' '1' 'Multi-Arch: foreign +Depends: libfoo1' + +setupaptarchive + +testfailureequal "Reading package lists... +Building dependency tree... +You might want to run 'apt-get -f install' to correct these. +The following packages have unmet dependencies: + foo:amd64 : Depends: libfoo1:amd64 but it is not installable +E: Unmet dependencies. Try using -f." aptget check -s + +insertinstalledpackage 'libfoo1' 'amd64' '1' 'Multi-Arch: same' + +testsuccessequal 'Reading package lists... +Building dependency tree...' aptget check -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + libfoo1 +The following packages will be REMOVED: + foo:amd64 +The following NEW packages will be installed: + foo libfoo1 +0 upgraded, 2 newly installed, 1 to remove and 0 not upgraded. +Remv foo:amd64 [1] +Inst libfoo1 (1 unstable [i386]) +Inst foo (1 unstable [i386]) +Conf libfoo1 (1 unstable [i386]) +Conf foo (1 unstable [i386])' aptget install foo -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + libfoo1 +The following packages will be REMOVED: + foo:amd64 libfoo1:amd64 +The following NEW packages will be installed: + foo libfoo1 +0 upgraded, 2 newly installed, 2 to remove and 0 not upgraded. +Remv foo:amd64 [1] +Remv libfoo1:amd64 [1] +Inst libfoo1 (2 experimental [i386]) +Inst foo (2 experimental [i386]) +Conf libfoo1 (2 experimental [i386]) +Conf foo (2 experimental [i386])' aptget install foo/experimental -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following extra packages will be installed: + foo libfoo1 +The following packages will be REMOVED: + foo:amd64 +The following NEW packages will be installed: + bar foo libfoo1 +0 upgraded, 3 newly installed, 1 to remove and 0 not upgraded. +Remv foo:amd64 [1] +Inst libfoo1 (1 unstable [i386]) +Inst foo (1 unstable [i386]) +Inst bar (1 unstable [i386]) +Conf libfoo1 (1 unstable [i386]) +Conf foo (1 unstable [i386]) +Conf bar (1 unstable [i386])' aptget install bar -s + +configarchitecture 'i386' 'amd64' + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following NEW packages will be installed: + bar +0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +Inst bar (1 unstable [i386]) +Conf bar (1 unstable [i386])' aptget install bar -s diff --git a/test/integration/test-specific-architecture-dependencies b/test/integration/test-specific-architecture-dependencies index 1c72d7b22..e3dfd0c2a 100755 --- a/test/integration/test-specific-architecture-dependencies +++ b/test/integration/test-specific-architecture-dependencies @@ -289,12 +289,14 @@ The following NEW packages will be installed: Inst foo-native-depender (1 unstable [amd64]) Conf foo-native-depender (1 unstable [amd64])' aptget install foo-native-depender -s -# libold:i386 is installed, but we don't see it as i386 isn't configured testequal 'Reading package lists... Building dependency tree... +The following packages will be REMOVED: + libold:i386 The following NEW packages will be installed: breaker-x32 -0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. +0 upgraded, 1 newly installed, 1 to remove and 0 not upgraded. +Remv libold:i386 [1] Inst breaker-x32 (1 unstable [amd64]) Conf breaker-x32 (1 unstable [amd64])' aptget install breaker-x32:amd64 -s -- cgit v1.2.3-70-g09d2 From dd676dc71e31c20f66d5b9d9ac1c5a4c8883cd79 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 9 Aug 2015 17:40:57 +0200 Subject: enhance "hit paywall" error message to mention the probable cause MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reporting errors from Done() is bad for progress reporting and such, so factoring this out is a good idea and we start with moving the supposed- to-be clearsigned file isn't clearsigned out first – improving the error message in the process as we use the same message for a similar case (NODATA) as this is what I have to look at with the venue wifi at DebCamp and the old errormessage doesn't really say anything. --- apt-pkg/acquire-item.cc | 90 +++++++++++----------- apt-pkg/acquire-item.h | 23 ++++++ apt-pkg/acquire-worker.cc | 9 ++- test/integration/test-apt-update-nofallback | 5 +- .../test-ubuntu-bug-346386-apt-get-update-paywall | 11 +-- ...st-ubuntu-bug-784473-InRelease-one-message-only | 5 +- 6 files changed, 83 insertions(+), 60 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 8a566fea0..0a7e0e11f 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -514,6 +514,23 @@ void pkgAcquire::Item::Start(string const &/*Message*/, unsigned long long const FileSize = Size; } /*}}}*/ +// Acquire::Item::VerifyDone - check if Item was downloaded OK /*{{{*/ +/* Note that hash-verification is 'hardcoded' in acquire-worker and has + * already passed if this method is called. */ +bool pkgAcquire::Item::VerifyDone(std::string const &Message, + pkgAcquire::MethodConfig const * const /*Cnf*/) +{ + std::string const FileName = LookupTag(Message,"Filename"); + if (FileName.empty() == true) + { + Status = StatError; + ErrorText = "Method gave a blank filename"; + return false; + } + + return true; +} + /*}}}*/ // Acquire::Item::Done - Item downloaded OK /*{{{*/ void pkgAcquire::Item::Done(string const &/*Message*/, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const /*Cnf*/) @@ -585,8 +602,8 @@ bool pkgAcquire::Item::RenameOnError(pkgAcquire::Item::RenameOnErrorState const Status = StatError; break; case NotClearsigned: - errtext = _("Does not start with a cleartext signature"); - Status = StatError; + strprintf(errtext, _("Clearsigned file isn't valid, got '%s' (does the network require authentication?)"), "NOSPLIT"); + Status = StatAuthError; break; case MaximumSizeExceeded: // the method is expected to report a good error for this @@ -783,7 +800,7 @@ bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const s _error->Error(_("GPG error: %s: %s"), Desc.Description.c_str(), LookupTag(Message,"Message").c_str()); - I->Status = StatError; + I->Status = StatAuthError; return true; } else { _error->Warning(_("GPG error: %s: %s"), @@ -829,14 +846,7 @@ bool pkgAcqMetaBase::CheckDownloadDone(pkgAcqTransactionItem * const I, const st // We have just finished downloading a Release file (it is not // verified yet) - string const FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - I->Status = StatError; - I->ErrorText = "Method gave a blank filename"; - return false; - } - + std::string const FileName = LookupTag(Message,"Filename"); if (FileName != I->DestFile && RealFileExists(I->DestFile) == false) { I->Local = true; @@ -1142,6 +1152,16 @@ string pkgAcqMetaClearSig::Custom600Headers() const return Header; } /*}}}*/ +bool pkgAcqMetaClearSig::VerifyDone(std::string const &Message, + pkgAcquire::MethodConfig const * const Cnf) +{ + Item::VerifyDone(Message, Cnf); + + if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile)) + return RenameOnError(NotClearsigned); + + return true; +} // pkgAcqMetaClearSig::Done - We got a file /*{{{*/ void pkgAcqMetaClearSig::Done(std::string const &Message, HashStringList const &Hashes, @@ -1149,17 +1169,6 @@ void pkgAcqMetaClearSig::Done(std::string const &Message, { Item::Done(Message, Hashes, Cnf); - // if we expect a ClearTextSignature (InRelease), ensure that - // this is what we get and if not fail to queue a - // Release/Release.gpg, see #346386 - if (FileExists(DestFile) && !StartsWithGPGClearTextSignature(DestFile)) - { - pkgAcquire::Item::Failed(Message, Cnf); - RenameOnError(NotClearsigned); - TransactionManager->AbortTransaction(); - return; - } - if(AuthPass == false) { if(CheckDownloadDone(this, Message, Hashes) == true) @@ -1190,6 +1199,16 @@ void pkgAcqMetaClearSig::Failed(string const &Message,pkgAcquire::MethodConfig c if (AuthPass == false) { + if (Status == StatAuthError) + { + // if we expected a ClearTextSignature (InRelease) and got a file, + // but it wasn't valid we end up here (see VerifyDone). + // As these is usually called by web-portals we do not try Release/Release.gpg + // as this is gonna fail anyway and instead abort our try (LP#346386) + TransactionManager->AbortTransaction(); + return; + } + // Queue the 'old' InRelease file for removal if we try Release.gpg // as otherwise the file will stay around and gives a false-auth // impression (CVE-2012-0214) @@ -2500,7 +2519,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const Complete = true; // Handle the unzipd case - string FileName = LookupTag(Message,"Alt-Filename"); + std::string FileName = LookupTag(Message,"Alt-Filename"); if (FileName.empty() == false) { Stage = STAGE_DECOMPRESS_AND_VERIFY; @@ -2511,13 +2530,7 @@ void pkgAcqIndex::StageDownloadDone(string const &Message, HashStringList const SetActiveSubprocess("copy"); return; } - FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - Status = StatError; - ErrorText = "Method gave a blank filename"; - } // Methods like e.g. "file:" will give us a (compressed) FileName that is // not the "DestFile" we set, in this case we uncompress from the local file @@ -2791,15 +2804,7 @@ void pkgAcqArchive::Done(string const &Message, HashStringList const &Hashes, Item::Done(Message, Hashes, Cfg); // Grab the output filename - string FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - Status = StatError; - ErrorText = "Method gave a blank filename"; - return; - } - - // Reference filename + std::string const FileName = LookupTag(Message,"Filename"); if (DestFile != FileName && RealFileExists(DestFile) == false) { StoreFilename = DestFile = FileName; @@ -3121,14 +3126,7 @@ void pkgAcqFile::Done(string const &Message,HashStringList const &CalcHashes, { Item::Done(Message,CalcHashes,Cnf); - string FileName = LookupTag(Message,"Filename"); - if (FileName.empty() == true) - { - Status = StatError; - ErrorText = "Method gave a blank filename"; - return; - } - + std::string const FileName = LookupTag(Message,"Filename"); Complete = true; // The files timestamp matches diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index 2349d386c..d6bcdafcb 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -176,6 +176,28 @@ class pkgAcquire::Item : public WeakPointable /*{{{*/ */ virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf); + /** \brief Invoked by the acquire worker to check if the successfully + * fetched object is also the objected we wanted to have. + * + * Note that the object might \e not have been written to + * DestFile; check for the presence of an Alt-Filename entry in + * Message to find the file to which it was really written. + * + * This is called before Done is called and can prevent it by returning + * \b false which will result in Failed being called instead. + * + * You should prefer to use this method over calling Failed() from Done() + * as this has e.g. the wrong progress reporting. + * + * \param Message Data from the acquire method. Use LookupTag() + * to parse it. + * \param Cnf The method via which the object was fetched. + * + * \sa pkgAcqMethod + */ + virtual bool VerifyDone(std::string const &Message, + pkgAcquire::MethodConfig const * const Cnf); + /** \brief Invoked by the acquire worker when the object was * fetched successfully. * @@ -563,6 +585,7 @@ class APT_HIDDEN pkgAcqMetaClearSig : public pkgAcqMetaIndex virtual void Failed(std::string const &Message,pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual std::string Custom600Headers() const APT_OVERRIDE; + virtual bool VerifyDone(std::string const &Message, pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; virtual void Done(std::string const &Message, HashStringList const &Hashes, pkgAcquire::MethodConfig const * const Cnf) APT_OVERRIDE; diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index dc03a8870..2c84020fe 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -411,11 +411,14 @@ bool pkgAcquire::Worker::RunMessages() else consideredOkay = true; + if (consideredOkay == true) + consideredOkay = Owner->VerifyDone(Message, Config); + else // hashsum mismatch + Owner->Status = pkgAcquire::Item::StatAuthError; + if (consideredOkay == true) { Owner->Done(Message, ReceivedHashes, Config); - - // Log that we are done if (Log != 0) { if (isIMSHit) @@ -426,9 +429,7 @@ bool pkgAcquire::Worker::RunMessages() } else { - Owner->Status = pkgAcquire::Item::StatAuthError; Owner->Failed(Message,Config); - if (Log != 0) Log->Fail(Owner->GetItemDesc()); } diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index 2ded73122..5bffab6ee 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -151,9 +151,8 @@ test_subvert_inrelease() # replace InRelease with something else mv $APTARCHIVE/dists/unstable/Release $APTARCHIVE/dists/unstable/InRelease - testfailureequal "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease Does not start with a cleartext signature - -E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq + testfailuremsg "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease Clearsigned file isn't valid, got 'NOSPLIT' (does the network require authentication?) +E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update # ensure we keep the repo testfileequal lists.before "$(listcurrentlistsdirectory)" diff --git a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall index ea516fc12..8f468b376 100755 --- a/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall +++ b/test/integration/test-ubuntu-bug-346386-apt-get-update-paywall @@ -36,8 +36,8 @@ ensure_n_canary_strings_in_dir() { LISTS='rootdir/var/lib/apt/lists' rm -rf rootdir/var/lib/apt/lists -msgtest 'Got expected failure message' 'apt-get update' -aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail +testfailure aptget update +testsuccess grep '^W:.*Clearsigned file .*NOSPLIT.*' rootdir/tmp/testfailure.output ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 testequal 'lock @@ -48,8 +48,8 @@ for f in Release Release.gpg main_binary-amd64_Packages main_source_Sources; do echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_${f} done -msgtest 'Got expected failure message in' 'apt-get update' -aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail +testfailure aptget update +testsuccess grep '^W:.*Clearsigned file .*NOSPLIT.*' rootdir/tmp/testfailure.output ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 4 ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 @@ -58,7 +58,8 @@ ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 echo 'peng neee-wom' > $LISTS/localhost:8080_dists_stable_InRelease rm -f $LISTS/localhost:8080_dists_stable_Release $LISTS/localhost:8080_dists_stable_Release.gpg msgtest 'excpected failure of' 'apt-get update' -aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail +testfailure aptget update +testsuccess grep '^W:.*Clearsigned file .*NOSPLIT.*' rootdir/tmp/testfailure.output ensure_n_canary_strings_in_dir $LISTS 'peng neee-wom' 3 ensure_n_canary_strings_in_dir $LISTS 'ni ni ni' 0 diff --git a/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only index 754487a90..dbcb49a41 100755 --- a/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only +++ b/test/integration/test-ubuntu-bug-784473-InRelease-one-message-only @@ -27,8 +27,9 @@ MD5Sum: 1b895931853981ad8204d2439821b999 4144 Packages.gz'; echo; cat ${RELEASE}.old;) > ${RELEASE} done -msgtest 'The unsigned garbage before signed block is' 'ignored' -aptget update -qq 2>&1 | grep -q 'W:.*Does not start with a cleartext signature' && msgpass || msgfail +testfailure aptget update +testsuccess grep '^W:.*Clearsigned file .*NOSPLIT.*' rootdir/tmp/testfailure.output + ROOTDIR="$(readlink -f .)" testsuccessequal "Package files: -- cgit v1.2.3-70-g09d2 From 0efb29eb36184bbe6de7b1013d1898796d94b171 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Sun, 9 Aug 2015 19:01:49 +0200 Subject: drop extra newline in 'Failed to fetch' and 'GPG error' message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I never understood why there is an extra newline in those messages, so now is as good time as any to drop them. Lets see if someone complains with a good reason to keep it… --- apt-pkg/acquire-item.cc | 2 +- apt-pkg/update.cc | 2 +- test/integration/test-apt-update-nofallback | 4 ---- test/integration/test-apt-update-not-modified | 2 -- test/integration/test-apt-update-rollback | 4 ---- test/integration/test-bug-595691-empty-and-broken-archive-files | 2 -- 6 files changed, 2 insertions(+), 14 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index 0a7e0e11f..3ed52dbf2 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -790,7 +790,7 @@ bool pkgAcqMetaBase::CheckStopAuthentication(pkgAcquire::Item * const I, const s _error->Warning(_("An error occurred during the signature " "verification. The repository is not updated " "and the previous index files will be used. " - "GPG error: %s: %s\n"), + "GPG error: %s: %s"), Desc.Description.c_str(), LookupTag(Message,"Message").c_str()); RunScripts("APT::Update::Auth-Failure"); diff --git a/apt-pkg/update.cc b/apt-pkg/update.cc index 2908a4820..6e65c387c 100644 --- a/apt-pkg/update.cc +++ b/apt-pkg/update.cc @@ -74,7 +74,7 @@ bool AcquireUpdate(pkgAcquire &Fetcher, int const PulseInterval, uri.User.clear(); uri.Password.clear(); string descUri = string(uri); - _error->Warning(_("Failed to fetch %s %s\n"), descUri.c_str(), + _error->Warning(_("Failed to fetch %s %s"), descUri.c_str(), (*I)->ErrorText.c_str()); if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError) diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index 5bffab6ee..2f4ddc016 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -171,9 +171,7 @@ test_inrelease_to_invalid_inrelease() inject_evil_package testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable InRelease: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) - W: Failed to fetch file:${APTARCHIVE}/dists/unstable/InRelease The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) - W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq # ensure we keep the repo @@ -195,9 +193,7 @@ test_release_gpg_to_invalid_release_release_gpg() inject_evil_package testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable Release: The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) - W: Failed to fetch file:${APTARCHIVE}/dists/unstable/Release.gpg The following signatures were invalid: BADSIG 5A90D141DBAC8DAE Joe Sixpack (APT Testcases Dummy) - W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq testfailure grep 'evil' rootdir/var/lib/apt/lists/*Release diff --git a/test/integration/test-apt-update-not-modified b/test/integration/test-apt-update-not-modified index 6d176a655..3f822586a 100755 --- a/test/integration/test-apt-update-not-modified +++ b/test/integration/test-apt-update-not-modified @@ -47,7 +47,6 @@ Get:2 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable Err:2 $1 unstable/main amd64 Packages Hash Sum mismatch W: Failed to fetch $1/dists/unstable/main/binary-amd64/Packages.gz Hash Sum mismatch - E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" rm -rf aptarchive/dists @@ -107,7 +106,6 @@ Get:4 $1 unstable/main amd64 Packages [$(stat -c '%s' 'aptarchive/dists/unstable Err:4 $1 unstable/main amd64 Packages Hash Sum mismatch W: Failed to fetch $1/dists/unstable/main/binary-amd64/Packages.gz Hash Sum mismatch - E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update testfileequal 'listsdir-without-amd64.lst' "$(listcurrentlistsdirectory)" rm -rf aptarchive/dists diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback index 70619dd08..646484e7b 100755 --- a/test/integration/test-apt-update-rollback +++ b/test/integration/test-apt-update-rollback @@ -61,7 +61,6 @@ test_inrelease_to_broken_hash_reverts_all() { # test the error condition testfailureequal "W: Failed to fetch file:${APTARCHIVE}/dists/unstable/main/source/Sources.gz Hash Sum mismatch - E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq # ensure that the Packages file is also rolled back testfileequal lists.before "$(listcurrentlistsdirectory)" @@ -128,7 +127,6 @@ E: There are problems and -y was used without --force-yes" aptget install -qq -y break_repository_sources_index '+1hour' testfailureequal "W: Failed to fetch file:$APTARCHIVE/dists/unstable/main/source/Sources.gz Hash Sum mismatch - E: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq testfileequal lists.before "$(listcurrentlistsdirectory)" @@ -145,9 +143,7 @@ test_inrelease_to_unauth_inrelease() { signreleasefiles 'Marvin Paranoid' testwarningequal "W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: file:${APTARCHIVE} unstable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2 - W: Failed to fetch file:$APTARCHIVE/dists/unstable/InRelease The following signatures couldn't be verified because the public key is not available: NO_PUBKEY E8525D47528144E2 - W: Some index files failed to download. They have been ignored, or old ones used instead." aptget update -qq testfileequal lists.before "$(listcurrentlistsdirectory)" diff --git a/test/integration/test-bug-595691-empty-and-broken-archive-files b/test/integration/test-bug-595691-empty-and-broken-archive-files index 47dd62712..0c02aee30 100755 --- a/test/integration/test-bug-595691-empty-and-broken-archive-files +++ b/test/integration/test-bug-595691-empty-and-broken-archive-files @@ -55,7 +55,6 @@ Reading package lists..." "empty archive Packages.$COMPRESS over file" Err:2 file:$APTARCHIVE Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:${APTARCHIVE}/Packages.$COMPRESS Empty files can't be valid archives - E: Some index files failed to download. They have been ignored, or old ones used instead." "empty file Packages.$COMPRESS over file" } @@ -72,7 +71,6 @@ Reading package lists..." "empty archive Packages.$COMPRESS over http" Err:2 http://localhost:8080 Packages Empty files can't be valid archives W: Failed to fetch ${COMPRESSOR}:$(readlink -f rootdir/var/lib/apt/lists/partial/localhost:8080_Packages.${COMPRESS}) Empty files can't be valid archives - E: Some index files failed to download. They have been ignored, or old ones used instead." "empty file Packages.$COMPRESS over http" } -- cgit v1.2.3-70-g09d2 From 3cbeed985254de7e8d186ebebb69a659727eaeb0 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 3 Aug 2015 07:00:33 +0200 Subject: mark again deps of pkgs in APT::Never-MarkAuto-Sections as manual MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 50ef3344c3afaaf9943142906b2f976a0337d264 (and similar for other branches), while 'fixing' the edgecase of a package being in multiple sections (e.g. moved from libs to oldlibs in newer releases) I accidently broke the feature itself completely by operating on the package itself and no longer on its dependencies… The behaviour isn't ideal in multiple ways, which we are hopefully able to fix with new ideas as mentioned in the buglog, but until then the functionality of this "hack" should be restored. Reported-By: Raphaël Hertzog Tested-By: Adam Conrad Closes: 793360 LP: 1479207 Thanks: Raphaël Hertzog and Adam Conrad for detailed reports and initial patches --- apt-pkg/depcache.cc | 9 +- test/integration/framework | 4 +- test/integration/test-apt-never-markauto-sections | 106 ++++++++++++++++++++++ 3 files changed, 116 insertions(+), 3 deletions(-) create mode 100755 test/integration/test-apt-never-markauto-sections (limited to 'test') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 7b1448c73..e466cba28 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1093,7 +1093,12 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (DebugMarker == true) std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl; - DepIterator Dep = P.InstVerIter(*this).DependsList(); + VerIterator const PV = P.InstVerIter(*this); + if (unlikely(PV.end() == true)) + return false; + bool const PinNeverMarkAutoSection = (PV->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); + + DepIterator Dep = PV.DependsList(); for (; Dep.end() != true;) { // Grok or groups @@ -1206,7 +1211,7 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, continue; } // now check if we should consider it a automatic dependency or not - if(InstPkg->CurrentVer == 0 && InstVer->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", InstVer.Section())) + if(InstPkg->CurrentVer == 0 && PinNeverMarkAutoSection) { if(DebugAutoInstall == true) std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " diff --git a/test/integration/framework b/test/integration/framework index 53157e2d0..2f08c5fdc 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -570,10 +570,12 @@ echo '$NAME says \"Hello!\"'" > ${BUILDDIR}/${NAME} -- Joe Sixpack $(date -R)" > ${BUILDDIR}/debian/changelog echo "Source: $NAME -Section: $SECTION Priority: $PRIORITY Maintainer: Joe Sixpack Standards-Version: 3.9.3" > ${BUILDDIR}/debian/control + if [ "$SECTION" != '' ]; then + echo "Section: $SECTION" >> ${BUILDDIR}/debian/control + fi local BUILDDEPS="$(echo "$DEPENDENCIES" | grep '^Build-')" test -z "$BUILDDEPS" || echo "$BUILDDEPS" >> ${BUILDDIR}/debian/control echo " diff --git a/test/integration/test-apt-never-markauto-sections b/test/integration/test-apt-never-markauto-sections new file mode 100755 index 000000000..6c88c69fa --- /dev/null +++ b/test/integration/test-apt-never-markauto-sections @@ -0,0 +1,106 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' 'i386' + +aptconfig dump --no-empty --format '%v%n' APT::Never-MarkAuto-Sections > nevermarkauto.sections +testsuccess grep '^metapackages$' nevermarkauto.sections + +# this is a very crude regression test, not a "this is how it should be" test: +# In theory mydesktop-core and texteditor should be marked as manual, but +# texteditor is installed as a dependency of bad-texteditor, not of +# mydesktop-core and mydesktop-core is removed while bad-texteditor is +# installed losing the manual bit as the problem resolver will later decide to +# drop bad-texteditor and re-instate mydesktop-core which is considered an +# auto-install at that point (in theory the never-auto handling should be +# copied to this place – as to the many other places dependencies are resolved +# 'by hand' instead of via MarkInstall AutoInst… +# +# Both could be fixed if apt would figure out early that installing +# bad-texteditor is a bad idea and eventually it should (as mydesktop-core is +# a direct descendant of mydesktop which was a user-request mydesktop-core should +# be as protected from removal as mydesktop is), but this is hard in the general case +# as with more or-groups and provides you can produce 'legal' examples for this. + +buildsimplenativepackage 'mydesktop' 'all' '1' 'unstable' 'Depends: mydesktop-core, foreignpkg +Recommends: notavailable' '' 'metapackages' +buildsimplenativepackage 'mydesktop-core' 'amd64' '1' 'unstable' 'Depends: bad-texteditor | texteditor, browser (>= 42), nosection, foreignpkg +Recommends: notavailable +Multi-Arch: foreign' '' 'metapackages' +buildsimplenativepackage 'browser' 'amd64' '41' 'stable' +buildsimplenativepackage 'browser' 'amd64' '42' 'unstable' +buildsimplenativepackage 'texteditor' 'amd64' '1' 'stable' +buildsimplenativepackage 'bad-texteditor' 'amd64' '1' 'stable' 'Depends: texteditor +Conflicts: mydesktop-core' +buildsimplenativepackage 'nosection' 'amd64' '1' 'stable' '' '' '' +buildsimplenativepackage 'foreignpkg' 'i386' '1' 'stable' 'Multi-Arch: foreign' +setupaptarchive + +testsuccess aptcache show nosection +testfailure grep 'Section' rootdir/tmp/testsuccess.output +testequal 'dpkg' aptmark showmanual + +testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 + +testequal 'browser +dpkg +foreignpkg:i386 +mydesktop +nosection' aptmark showmanual +testmarkedauto 'mydesktop-core' 'texteditor' + +testequal 'Reading package lists... +Building dependency tree... +Reading state information... +The following packages will be REMOVED: + mydesktop mydesktop-core texteditor +0 upgraded, 0 newly installed, 3 to remove and 0 not upgraded. +Remv mydesktop [1] +Remv mydesktop-core [1] +Remv texteditor [1]' aptget autoremove mydesktop -s + +testequal 'Reading package lists... +Building dependency tree... +Reading state information... +The following packages will be REMOVED: + mydesktop mydesktop-core texteditor +0 upgraded, 0 newly installed, 3 to remove and 0 not upgraded. +Remv mydesktop [1] +Remv mydesktop-core [1] +Remv texteditor [1]' aptget autoremove texteditor -s +testsuccess aptget autoremove texteditor -y + +testdpkgnotinstalled mydesktop mydesktop-core texteditor +testdpkginstalled browser + +testequal 'browser +dpkg +foreignpkg:i386 +nosection' aptmark showmanual +testmarkedauto + +# test that installed/upgraded auto-pkgs are not set to manual + +testsuccess aptget install browser=41 -y --force-yes + +testequal 'browser +dpkg +foreignpkg:i386 +nosection' aptmark showmanual +testmarkedauto +testsuccess aptmark auto browser +testmarkedauto 'browser' +testsuccess aptmark auto nosection +testmarkedauto 'browser' 'nosection' +testequal 'dpkg +foreignpkg:i386' aptmark showmanual + +testsuccess aptget install mydesktop -y + +testequal 'dpkg +foreignpkg:i386 +mydesktop' aptmark showmanual +testmarkedauto 'browser' 'nosection' 'mydesktop-core' 'texteditor' -- cgit v1.2.3-70-g09d2 From 22df31be37d56c07ed029f5a4d5041f21070d2d6 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 10 Aug 2015 11:31:28 +0200 Subject: no value for MultiArch field is 'no', not 'none' Git-Dch: Ignore --- apt-pkg/deb/deblistparser.cc | 6 +++--- apt-pkg/pkgcache.h | 2 +- cmdline/apt-get.cc | 4 ++-- test/integration/test-bug-632221-cross-dependency-satisfaction | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index a908057d7..489d0434e 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -95,14 +95,14 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ unsigned char MA; string const MultiArch = Section.FindS("Multi-Arch"); if (MultiArch.empty() == true || MultiArch == "no") - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; else if (MultiArch == "same") { if (ArchitectureAll() == true) { if (showErrors == true) _error->Warning("Architecture: all package '%s' can't be Multi-Arch: same", Section.FindS("Package").c_str()); - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; } else MA = pkgCache::Version::Same; @@ -116,7 +116,7 @@ unsigned char debListParser::ParseMultiArch(bool const showErrors) /*{{{*/ if (showErrors == true) _error->Warning("Unknown Multi-Arch type '%s' for package '%s'", MultiArch.c_str(), Section.FindS("Package").c_str()); - MA = pkgCache::Version::None; + MA = pkgCache::Version::No; } if (ArchitectureAll() == true) diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 8a726085e..62c734283 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -599,7 +599,7 @@ struct pkgCache::Version map_stringitem_t SourceVerStr; /** \brief Multi-Arch capabilities of a package version */ - enum VerMultiArch { None = 0, /*!< is the default and doesn't trigger special behaviour */ + enum VerMultiArch { No = 0, /*!< is the default and doesn't trigger special behaviour */ All = (1<<0), /*!< will cause that Ver.Arch() will report "all" */ Foreign = (1<<1), /*!< can satisfy dependencies in another architecture */ Same = (1<<2), /*!< can be co-installed with itself from other architectures */ diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index d515a0f4f..918942505 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1172,12 +1172,12 @@ static bool DoBuildDep(CommandLine &CmdL) for (; Ver != verlist.end(); ++Ver) { forbidden.clear(); - if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All) + if (Ver->MultiArch == pkgCache::Version::No || Ver->MultiArch == pkgCache::Version::All) { if (colon == string::npos) Pkg = Ver.ParentPkg().Group().FindPkg(hostArch); else if (strcmp(D->Package.c_str() + colon, ":any") == 0) - forbidden = "Multi-Arch: none"; + forbidden = "Multi-Arch: no"; else if (strcmp(D->Package.c_str() + colon, ":native") == 0) Pkg = Ver.ParentPkg().Group().FindPkg("native"); } diff --git a/test/integration/test-bug-632221-cross-dependency-satisfaction b/test/integration/test-bug-632221-cross-dependency-satisfaction index 12704e5de..6444c6110 100755 --- a/test/integration/test-bug-632221-cross-dependency-satisfaction +++ b/test/integration/test-bug-632221-cross-dependency-satisfaction @@ -23,7 +23,7 @@ insertpackage 'unstable' 'linux-stuff' 'amd64,armel' '1.0' insertsource 'unstable' 'apt' 'any' '0.8.15' 'Build-Depends: doxygen, libc6-dev, libc6-dev:native, cool:any, amdboot:amd64, foreigner, libfwibble-dev, arm-stuff [any-armel] | linux-stuff [ linux-any]' -insertsource 'unstable' 'forbidden-none' 'any' '1' 'Build-Depends: amdboot:any' +insertsource 'unstable' 'forbidden-no' 'any' '1' 'Build-Depends: amdboot:any' insertsource 'unstable' 'forbidden-same' 'any' '1' 'Build-Depends: libc6:any' insertsource 'unstable' 'forbidden-foreign' 'any' '1' 'Build-Depends: doxygen:any' @@ -37,7 +37,7 @@ setupaptarchive testfailureequal "Reading package lists... Building dependency tree... -E: Build-Depends dependency for forbidden-none can't be satisfied because amdboot:any is not allowed on 'Multi-Arch: none' packages" aptget build-dep forbidden-none -s -a armel +E: Build-Depends dependency for forbidden-no can't be satisfied because amdboot:any is not allowed on 'Multi-Arch: no' packages" aptget build-dep forbidden-no -s -a armel testfailureequal "Reading package lists... Building dependency tree... E: Build-Depends dependency for forbidden-same can't be satisfied because libc6:any is not allowed on 'Multi-Arch: same' packages" aptget build-dep forbidden-same -s -a armel -- cgit v1.2.3-70-g09d2 From 7c2cc4a7bc999c8e07fba607354bfaa3b09118f9 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 10 Aug 2015 14:44:14 +0200 Subject: move APT::Never-MarkAuto-Sections handling to MarkDelete Having the handling in MarkInstall means that it just effects installation of the metapackage, but if the dependencies change the new dependencies aren't protected (and the old dependencies are still protected for no 'reason'). Having it in MarkDelete means that if a metapackage is sheduled for removal all its currently installed dependencies are marked as manual, which helps against both as in this case there is no new/old and additionally if a user decides the installation of a metapackage was wrong he can just remove it explicitely avoid the manual marking entirely. --- apt-pkg/depcache.cc | 44 +++++++++++++---- test/integration/framework | 11 +++++ test/integration/test-apt-never-markauto-sections | 60 ++++++++--------------- 3 files changed, 66 insertions(+), 49 deletions(-) (limited to 'test') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index e466cba28..99e694a06 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -836,6 +836,41 @@ bool pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge, ActionGroup group(*this); + if (FromUser == false) + { + VerIterator const PV = P.InstVerIter(*this); + if (PV.end() == false) + { + // removed metapackages mark their dependencies as manual to prevent in "desktop depends browser, texteditor" + // the removal of browser to suggest the removal of desktop and texteditor. + // We ignore the auto-bit here as we can't deal with metapackage cascardes otherwise. + // We do not check for or-groups here as we don't know which package takes care of + // providing the feature the user likes e.g.: browser1 | browser2 | browser3 + // Temporary removals are effected by this as well, which is bad, but unlikely in practice + bool const PinNeverMarkAutoSection = (PV->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); + if (PinNeverMarkAutoSection) + { + for (DepIterator D = PV.DependsList(); D.end() != true; ++D) + { + if (D.IsMultiArchImplicit() == true || D.IsNegative() == true || IsImportantDep(D) == false) + continue; + + pkgCacheFile CacheFile(this); + APT::VersionList verlist = APT::VersionList::FromDependency(CacheFile, D, APT::CacheSetHelper::INSTALLED); + for (auto const &V : verlist) + { + PkgIterator const DP = V.ParentPkg(); + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << DP.FullName(false) << " NOT as auto-installed (direct " + << D.DepType() << " of " << Pkg.FullName(false) << " which is in APT::Never-MarkAuto-Sections)" << std::endl; + + MarkAuto(DP, false); + } + } + } + } + } + if (DebugMarker == true) std::clog << OutputInDepth(Depth) << (rPurge ? "MarkPurge " : "MarkDelete ") << Pkg << " FU=" << FromUser << std::endl; @@ -1096,7 +1131,6 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, VerIterator const PV = P.InstVerIter(*this); if (unlikely(PV.end() == true)) return false; - bool const PinNeverMarkAutoSection = (PV->Section != 0 && ConfigValueInSubTree("APT::Never-MarkAuto-Sections", PV.Section())); DepIterator Dep = PV.DependsList(); for (; Dep.end() != true;) @@ -1210,14 +1244,6 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, verlist.erase(InstVer); continue; } - // now check if we should consider it a automatic dependency or not - if(InstPkg->CurrentVer == 0 && PinNeverMarkAutoSection) - { - if(DebugAutoInstall == true) - std::clog << OutputInDepth(Depth) << "Setting NOT as auto-installed (direct " - << Start.DepType() << " of pkg in APT::Never-MarkAuto-Sections)" << std::endl; - MarkAuto(InstPkg, false); - } break; } while(true); continue; diff --git a/test/integration/framework b/test/integration/framework index 2f08c5fdc..2efe7439e 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1324,6 +1324,17 @@ testmarkedauto() { fi aptmark showauto 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail } +testmarkedmanual() { + local COMPAREFILE="${TMPWORKINGDIRECTORY}/rootdir/tmp/testmarkedmanual.comparefile" + if [ -n "$1" ]; then + msgtest 'Test for correctly marked as manually installed' "$*" + while [ -n "$1" ]; do echo "$1"; shift; done | sort > $COMPAREFILE + else + msgtest 'Test for correctly marked as manually installed' 'no package' + echo -n > $COMPAREFILE + fi + aptmark showmanual 2>&1 | checkdiff $COMPAREFILE - && msgpass || msgfail +} msgfailoutput() { local MSG="$1" diff --git a/test/integration/test-apt-never-markauto-sections b/test/integration/test-apt-never-markauto-sections index 6c88c69fa..a469b4c15 100755 --- a/test/integration/test-apt-never-markauto-sections +++ b/test/integration/test-apt-never-markauto-sections @@ -9,22 +9,6 @@ configarchitecture 'amd64' 'i386' aptconfig dump --no-empty --format '%v%n' APT::Never-MarkAuto-Sections > nevermarkauto.sections testsuccess grep '^metapackages$' nevermarkauto.sections -# this is a very crude regression test, not a "this is how it should be" test: -# In theory mydesktop-core and texteditor should be marked as manual, but -# texteditor is installed as a dependency of bad-texteditor, not of -# mydesktop-core and mydesktop-core is removed while bad-texteditor is -# installed losing the manual bit as the problem resolver will later decide to -# drop bad-texteditor and re-instate mydesktop-core which is considered an -# auto-install at that point (in theory the never-auto handling should be -# copied to this place – as to the many other places dependencies are resolved -# 'by hand' instead of via MarkInstall AutoInst… -# -# Both could be fixed if apt would figure out early that installing -# bad-texteditor is a bad idea and eventually it should (as mydesktop-core is -# a direct descendant of mydesktop which was a user-request mydesktop-core should -# be as protected from removal as mydesktop is), but this is hard in the general case -# as with more or-groups and provides you can produce 'legal' examples for this. - buildsimplenativepackage 'mydesktop' 'all' '1' 'unstable' 'Depends: mydesktop-core, foreignpkg Recommends: notavailable' '' 'metapackages' buildsimplenativepackage 'mydesktop-core' 'amd64' '1' 'unstable' 'Depends: bad-texteditor | texteditor, browser (>= 42), nosection, foreignpkg @@ -45,21 +29,21 @@ testequal 'dpkg' aptmark showmanual testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 -testequal 'browser -dpkg -foreignpkg:i386 -mydesktop -nosection' aptmark showmanual -testmarkedauto 'mydesktop-core' 'texteditor' +testmarkedmanual 'dpkg' 'mydesktop' +testmarkedauto 'mydesktop-core' 'foreignpkg:i386' 'texteditor' 'browser' 'nosection' +# if the remove is from a user, don't do manual-bit passing testequal 'Reading package lists... Building dependency tree... Reading state information... The following packages will be REMOVED: - mydesktop mydesktop-core texteditor -0 upgraded, 0 newly installed, 3 to remove and 0 not upgraded. + browser foreignpkg:i386 mydesktop mydesktop-core nosection texteditor +0 upgraded, 0 newly installed, 6 to remove and 0 not upgraded. Remv mydesktop [1] Remv mydesktop-core [1] +Remv browser [42] +Remv foreignpkg:i386 [1] +Remv nosection [1] Remv texteditor [1]' aptget autoremove mydesktop -s testequal 'Reading package lists... @@ -70,37 +54,33 @@ The following packages will be REMOVED: 0 upgraded, 0 newly installed, 3 to remove and 0 not upgraded. Remv mydesktop [1] Remv mydesktop-core [1] -Remv texteditor [1]' aptget autoremove texteditor -s +Remv texteditor [1]' aptget autoremove texteditor -s #-o Debug::pkgDepCache::AutoInstall=1 -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 testsuccess aptget autoremove texteditor -y testdpkgnotinstalled mydesktop mydesktop-core texteditor testdpkginstalled browser -testequal 'browser -dpkg -foreignpkg:i386 -nosection' aptmark showmanual +testmarkedmanual 'browser' 'dpkg' 'foreignpkg:i386' 'nosection' testmarkedauto # test that installed/upgraded auto-pkgs are not set to manual testsuccess aptget install browser=41 -y --force-yes -testequal 'browser -dpkg -foreignpkg:i386 -nosection' aptmark showmanual +testmarkedmanual 'browser' 'dpkg' 'foreignpkg:i386' 'nosection' testmarkedauto testsuccess aptmark auto browser testmarkedauto 'browser' testsuccess aptmark auto nosection testmarkedauto 'browser' 'nosection' -testequal 'dpkg -foreignpkg:i386' aptmark showmanual +testmarkedmanual 'dpkg' 'foreignpkg:i386' + +# nosection should be auto, not manual, but is marked as such by the resolver +# removing mydesktop-core temporally… the resolver should be figuring out here +# that there is no point of removing mydesktop-core as its an unavoidable +# dependency of the user-requested mydesktop -testsuccess aptget install mydesktop -y +testsuccess aptget install mydesktop -y -o Debug::pkgProblemResolver=1 -o Debug::pkgDepCache::Marker=1 -o Debug::pkgDepCache::AutoInstall=1 -testequal 'dpkg -foreignpkg:i386 -mydesktop' aptmark showmanual -testmarkedauto 'browser' 'nosection' 'mydesktop-core' 'texteditor' +testmarkedmanual 'dpkg' 'foreignpkg:i386' 'mydesktop' 'nosection' +testmarkedauto 'browser' 'mydesktop-core' 'texteditor' -- cgit v1.2.3-70-g09d2 From 5f4495e342e94a75b17ceed2fa05d689f050df7b Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 10 Aug 2015 16:08:21 +0200 Subject: move manual-bit from 'oldlibs' pkg to its dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit oldlibs used to be in APT::Never-MarkAuto-Sections so that old transition packages can be removed without causing the then (autoinstalled) renamed package to be autoremoved. It isn't ideal through as ideally you want the oldlibs package to be removed after nothing depends on it anymore regardless of if you have once installed it by hand or not – and if you had the package talking over (the dependencies) should carry the manual bit now as they are the real deal now. As an added bonus if the package has no dependencies because it is an oldlibs without a direct replacement you should move away from (like lib1 and lib2 are currently in the archive, but there will hopefully only be lib2 in the release) you get a lib1 marked as auto. If the user still needs the oldlibs package for some reason all he has to do is mark it as manual once as this move is only performed if a installed package changes its section from a not-Move-Autobit-Sections to a Move-Autobit-Sections. --- apt-pkg/depcache.cc | 28 +++++++++++++++++++ debian/apt.conf.autoremove | 4 +++ .../test-apt-move-and-forget-manual-sections | 31 ++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100755 test/integration/test-apt-move-and-forget-manual-sections (limited to 'test') diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 99e694a06..02f61bf13 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1128,9 +1128,26 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, if (DebugMarker == true) std::clog << OutputInDepth(Depth) << "MarkInstall " << Pkg << " FU=" << FromUser << std::endl; + bool MoveAutoBitToDependencies = false; VerIterator const PV = P.InstVerIter(*this); if (unlikely(PV.end() == true)) return false; + else if (PV->Section != 0 && (P.Flags & Flag::Auto) != Flag::Auto) + { + VerIterator const CurVer = Pkg.CurrentVer(); + if (CurVer.end() == false && CurVer->Section != 0 && strcmp(CurVer.Section(), PV.Section()) != 0) + { + bool const CurVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", CurVer.Section()); + bool const InstVerInMoveSection = ConfigValueInSubTree("APT::Move-Autobit-Sections", PV.Section()); + MoveAutoBitToDependencies = (CurVerInMoveSection == false && InstVerInMoveSection == true); + if (MoveAutoBitToDependencies == true) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << Pkg.FullName(false) << " as auto-installed, moving manual to its dependencies" << std::endl; + MarkAuto(Pkg, true); + } + } + } DepIterator Dep = PV.DependsList(); for (; Dep.end() != true;) @@ -1244,6 +1261,17 @@ bool pkgDepCache::MarkInstall(PkgIterator const &Pkg,bool AutoInst, verlist.erase(InstVer); continue; } + + // now check if we should consider it a automatic dependency or not + if(InstPkg->CurrentVer == 0 && MoveAutoBitToDependencies) + { + if(DebugAutoInstall == true) + std::clog << OutputInDepth(Depth) << "Setting " << InstPkg.FullName(false) << " NOT as auto-installed (direct " + << Start.DepType() << " of " << Pkg.FullName(false) << " which is manual and in APT::Move-Autobit-Sections)" << std::endl; + MarkAuto(InstPkg, false); + } + + break; } while(true); continue; diff --git a/debian/apt.conf.autoremove b/debian/apt.conf.autoremove index fc02350ae..3c4843e3d 100644 --- a/debian/apt.conf.autoremove +++ b/debian/apt.conf.autoremove @@ -32,6 +32,10 @@ APT "restricted/metapackages"; "universe/metapackages"; "multiverse/metapackages"; + }; + + Move-Autobit-Sections + { "oldlibs"; "restricted/oldlibs"; "universe/oldlibs"; diff --git a/test/integration/test-apt-move-and-forget-manual-sections b/test/integration/test-apt-move-and-forget-manual-sections new file mode 100755 index 000000000..845444f53 --- /dev/null +++ b/test/integration/test-apt-move-and-forget-manual-sections @@ -0,0 +1,31 @@ +#!/bin/sh +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +aptconfig dump --no-empty --format '%v%n' APT::Move-Autobit-Sections > move-autobit.sections +testsuccess grep '^oldlibs$' move-autobit.sections + +buildsimplenativepackage 'libabc' 'amd64' '1' 'stable' '' '' 'libs' +buildsimplenativepackage 'libabc' 'amd64' '2' 'unstable' 'Depends: libdef' '' 'oldlibs' +buildsimplenativepackage 'libdef' 'amd64' '1' 'unstable' '' '' 'libs' +setupaptarchive + +testmarkedauto +testmarkedmanual + +testsuccess aptget install libabc/stable -y +testdpkginstalled 'libabc' +testdpkgnotinstalled 'libdef' + +testmarkedmanual 'libabc' +testmarkedauto + +testsuccess aptget dist-upgrade -y +testdpkginstalled 'libabc' 'libdef' + +testmarkedauto 'libabc' +testmarkedmanual 'libdef' -- cgit v1.2.3-70-g09d2 From 3261271e8e813b883917f0f57031ffcecbce6e20 Mon Sep 17 00:00:00 2001 From: David Kalnischkies Date: Mon, 10 Aug 2015 19:00:16 +0200 Subject: travis: add ppa:ubuntu-toolschain-r/test as source for gcc-5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes travis-ci able to run our tests again. Sometimes. If it doesn't spontaneously fails with internal gcc errors… Git-Dch: Ignore --- .travis.yml | 6 +++++- test/integration/framework | 13 +++++++++++-- test/integration/test-apt-update-filesize-mismatch | 2 +- test/integration/test-apt-update-hashsum-mismatch | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/.travis.yml b/.travis.yml index b449aeba5..a20018a79 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ language: cpp before_install: + - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update -q +install: - sudo ./prepare-release travis-ci -script: make && make test && test/integration/run-tests + - export CC=gcc-5 + - export CXX=g++-5 +script: make -j1 && make test && test/integration/run-tests diff --git a/test/integration/framework b/test/integration/framework index 2efe7439e..b443f2a7b 100644 --- a/test/integration/framework +++ b/test/integration/framework @@ -1377,8 +1377,17 @@ testsuccess() { if expr match "$1" '^apt.*' >/dev/null; then if grep -q -E ' runtime error: ' "$OUTPUT"; then msgfailoutput 'compiler detected undefined behavior' "$OUTPUT" "$@" - elif grep -q -E '^[WE]: ' "$OUTPUT"; then - msgfailoutput 'successful run, but output contains warnings/errors' "$OUTPUT" "$@" + elif grep -E '^[WE]: ' "$OUTPUT" > "${TMPWORKINGDIRECTORY}/rootdir/tmp/checkforwarnings.output" 2>&1; then + if [ "$IGNORE_PTY_NOT_MOUNTED" = '1' ]; then + if echo 'E: Can not write log (Is /dev/pts mounted?) - posix_openpt (2: No such file or directory)' \ + | cmp - "${TMPWORKINGDIRECTORY}/rootdir/tmp/checkforwarnings.output" >/dev/null 2>&1; then + msgpass + else + msgfailoutput 'successful run, but output contains warnings/errors' "$OUTPUT" "$@" + fi + else + msgfailoutput 'successful run, but output contains warnings/errors' "$OUTPUT" "$@" + fi else msgpass fi diff --git a/test/integration/test-apt-update-filesize-mismatch b/test/integration/test-apt-update-filesize-mismatch index f78b83b5f..a23c03c3f 100755 --- a/test/integration/test-apt-update-filesize-mismatch +++ b/test/integration/test-apt-update-filesize-mismatch @@ -40,7 +40,7 @@ for get in $(sed -n 's#^GET /\([^ ]\+\.gz\) HTTP.\+$#\1#p' aptarchive/webserver. testfailure aptget update -o Debug::pkgAcquire::Worker=1 cp rootdir/tmp/testfailure.output rootdir/tmp/update.output - testsuccess grep -E "$(basename -s '.gz' "$COMPRESSFILE").*Hash Sum mismatch" rootdir/tmp/update.output + testsuccess grep -E "$(basename "$COMPRESSFILE" '.gz').*Hash Sum mismatch" rootdir/tmp/update.output testfailure aptcache show foo testfailure aptget install foo -s diff --git a/test/integration/test-apt-update-hashsum-mismatch b/test/integration/test-apt-update-hashsum-mismatch index c2c5b3887..4627f7afd 100755 --- a/test/integration/test-apt-update-hashsum-mismatch +++ b/test/integration/test-apt-update-hashsum-mismatch @@ -35,7 +35,7 @@ for get in $(sed -n 's#^GET /\([^ ]\+\.gz\) HTTP.\+$#\1#p' aptarchive/webserver. testfailure aptget update cp rootdir/tmp/testfailure.output rootdir/tmp/update.output - testsuccess grep -E "$(basename -s '.gz' "$get").*Hash Sum mismatch" rootdir/tmp/update.output + testsuccess grep -E "$(basename "$get" '.gz').*Hash Sum mismatch" rootdir/tmp/update.output testfailure aptcache show foo testfailure aptget install foo -s -- cgit v1.2.3-70-g09d2 From ad42ed4698c88e04bc242fb579f5b3e6fd9a0ee4 Mon Sep 17 00:00:00 2001 From: Daniel Hartwig Date: Tue, 11 Aug 2015 19:56:31 +0200 Subject: replace direct calls to egrep with grep -E MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rest of the initial patch is not needed or incorrect in our usage. Big changes for the dselect scripts seem unneeded as well as those are hardly used by anyone anymore… [commit message written by commiter] Closes: 255577 Thanks: David Weinehall for initial patch --- buildlib/libversion.mak | 6 +++--- dselect/install | 2 +- prepare-release | 2 +- test/integration/test-apt-download-progress | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/buildlib/libversion.mak b/buildlib/libversion.mak index deb3da377..1b1855be3 100644 --- a/buildlib/libversion.mak +++ b/buildlib/libversion.mak @@ -4,11 +4,11 @@ # with each non-ABI break to the lib, please increase RELEASE. # The versionnumber is extracted from apt-pkg/macros.h - see also there. LIBAPTPKG_MAJOR=$(shell awk -v ORS='.' '/^\#define APT_PKG_M/ {print $$3}' $(BASE)/apt-pkg/contrib/macros.h | sed 's/\.$$//') -LIBAPTPKG_RELEASE=$(shell grep -E '^\#define APT_PKG_RELEASE' $(BASE)/apt-pkg/contrib/macros.h | cut -d ' ' -f 3) +LIBAPTPKG_RELEASE=$(shell grep '^\#define APT_PKG_RELEASE' $(BASE)/apt-pkg/contrib/macros.h | cut -d ' ' -f 3) # Version number of libapt-inst # Please increase MAJOR with each ABI break, # with each non-ABI break to the lib, please increase MINOR. # The versionnumber is extracted from apt-inst/makefile - see also there. -LIBAPTINST_MAJOR=$(shell egrep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2) -LIBAPTINST_MINOR=$(shell egrep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2) +LIBAPTINST_MAJOR=$(shell grep '^MAJOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2) +LIBAPTINST_MINOR=$(shell grep '^MINOR=' $(BASE)/apt-inst/makefile |cut -d '=' -f 2) diff --git a/dselect/install b/dselect/install index 7104ee280..ef8de9b73 100755 --- a/dselect/install +++ b/dselect/install @@ -65,7 +65,7 @@ fi # Finished OK if [ $RES -eq 0 ]; then - if [ $(ls $ARCHIVES $ARCHIVES/partial | egrep -v "^lock$|^partial$" | wc -l) \ + if [ $(ls $ARCHIVES $ARCHIVES/partial | grep -E -v "^lock$|^partial$" | wc -l) \ -eq 0 ]; then exit 0 fi diff --git a/prepare-release b/prepare-release index 734dc5f32..91f65028d 100755 --- a/prepare-release +++ b/prepare-release @@ -11,7 +11,7 @@ VERSION=$(dpkg-parsechangelog | sed -n -e '/^Version:/s/^Version: //p') DISTRIBUTION=$(dpkg-parsechangelog | sed -n -e '/^Distribution:/s/^Distribution: //p') LIBAPTPKGVERSION="$(awk -v ORS='.' '/^\#define APT_PKG_M/ {print $3}' apt-pkg/contrib/macros.h | sed 's/\.$//')" -LIBAPTINSTVERSION="$(egrep '^MAJOR=' apt-inst/makefile |cut -d '=' -f 2)" +LIBAPTINSTVERSION="$(grep '^MAJOR=' apt-inst/makefile |cut -d '=' -f 2)" librarysymbolsfromfile() { local MISSING="$(grep '^+#MISSING' "$1")" diff --git a/test/integration/test-apt-download-progress b/test/integration/test-apt-download-progress index 7caeca971..bf6a412ad 100755 --- a/test/integration/test-apt-download-progress +++ b/test/integration/test-apt-download-progress @@ -13,7 +13,7 @@ changetohttpswebserver assertprogress() { T="$1" testsuccess grep "dlstatus:1:0:Retrieving file 1 of 1" "$T" - if ! egrep -q "dlstatus:1:[1-9][0-9](\..*)?:Retrieving file 1 of 1" "$T"; then + if ! grep -E -q "dlstatus:1:[1-9][0-9](\..*)?:Retrieving file 1 of 1" "$T"; then cat "$T" msgfail "Failed to detect download progress" fi -- cgit v1.2.3-70-g09d2 From 94171725b18be91ddcc2530c5fe5f40e78d041c1 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Tue, 11 Aug 2015 20:08:43 +0200 Subject: Replace all "press enter" occurrences with "press [Enter]" Thanks: Andre Felipe Machado for initial patch Closes: 414848 --- apt-pkg/acquire-worker.cc | 2 +- apt-private/acqprogress.cc | 2 +- cmdline/apt-cdrom.cc | 2 +- dselect/install | 10 +++++----- dselect/update | 2 +- po/apt-all.pot | 8 ++++---- test/integration/test-apt-cdrom | 2 +- 7 files changed, 14 insertions(+), 14 deletions(-) (limited to 'test') diff --git a/apt-pkg/acquire-worker.cc b/apt-pkg/acquire-worker.cc index 2c84020fe..e9ef4e9ac 100644 --- a/apt-pkg/acquire-worker.cc +++ b/apt-pkg/acquire-worker.cc @@ -538,7 +538,7 @@ bool pkgAcquire::Worker::MediaChange(string Message) ostringstream msg,status; ioprintf(msg,_("Please insert the disc labeled: " "'%s' " - "in the drive '%s' and press enter."), + "in the drive '%s' and press [Enter]."), Media.c_str(),Drive.c_str()); status << "media-change: " // message << Media << ":" // media diff --git a/apt-private/acqprogress.cc b/apt-private/acqprogress.cc index f6c3d1204..62b2c13d0 100644 --- a/apt-private/acqprogress.cc +++ b/apt-private/acqprogress.cc @@ -296,7 +296,7 @@ bool AcqTextStatus::MediaChange(std::string Media, std::string Drive) clearLastLine(); ioprintf(out,_("Media change: please insert the disc labeled\n" " '%s'\n" - "in the drive '%s' and press enter\n"), + "in the drive '%s' and press [Enter]\n"), Media.c_str(),Drive.c_str()); char C = 0; diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc index c0541d196..dcc784746 100644 --- a/cmdline/apt-cdrom.cc +++ b/cmdline/apt-cdrom.cc @@ -89,7 +89,7 @@ void pkgCdromTextStatus::Update(string text, int /*current*/) bool pkgCdromTextStatus::ChangeCdrom() { - Prompt(_("Please insert a Disc in the drive and press enter")); + Prompt(_("Please insert a Disc in the drive and press [Enter]")); return true; } diff --git a/dselect/install b/dselect/install index ef8de9b73..75f0c0fc4 100755 --- a/dselect/install +++ b/dselect/install @@ -49,7 +49,7 @@ yesno() { if [ "$WAIT" = "true" ]; then $APTGET $DSELECT_UPGRADE_OPTS $OPTS "$APT_OPT0" "$APT_OPT1" -d dselect-upgrade - echo $"Press enter to continue." && read RES + echo $"Press [Enter] to continue." && read RES $APTGET $DSELECT_UPGRADE_OPTS $OPTS "$APT_OPT0" "$APT_OPT1" dselect-upgrade RES=$? else @@ -81,18 +81,18 @@ if [ $RES -eq 0 ]; then case $(echo $CLEAN | tr '[:upper:]' '[:lower:]') in auto) $APTGET "$APT_OPT0" "$APT_OPT1" autoclean && - echo $"Press enter to continue." && read RES && exit 0; + echo $"Press [Enter] to continue." && read RES && exit 0; ;; always) $APTGET "$APT_OPT0" "$APT_OPT1" clean && - echo $"Press enter to continue." && read RES && exit 0; + echo $"Press [Enter] to continue." && read RES && exit 0; ;; prompt) exec 3>&1 echo -n $"Do you want to erase any previously downloaded .deb files?" if [ $(yesno "" y) = y ]; then $APTGET "$APT_OPT0" "$APT_OPT1" clean && - echo $"Press enter to continue." && read RES && exit 0; + echo $"Press [Enter] to continue." && read RES && exit 0; fi ;; *) @@ -103,7 +103,7 @@ else echo $"will be configured. This may result in duplicate errors" echo $"or errors caused by missing dependencies. This is OK, only the errors" echo $"above this message are important. Please fix them and run [I]nstall again" - echo $"Press enter to continue." + echo $"Press [Enter] to continue." read RES && $DPKG "$DPKG_OPTS" --configure -a exit 100 fi diff --git a/dselect/update b/dselect/update index 487fbf226..0ab317ee4 100755 --- a/dselect/update +++ b/dselect/update @@ -42,7 +42,7 @@ then fi if [ x$PROMPT = "xtrue" ]; then - echo $"Press enter to continue." && read RES; + echo $"Press [Enter] to continue." && read RES; fi exit $STATUS diff --git a/po/apt-all.pot b/po/apt-all.pot index e2d09401b..4a70213f4 100644 --- a/po/apt-all.pot +++ b/po/apt-all.pot @@ -200,7 +200,7 @@ msgid "Please provide a name for this Disc, such as 'Debian 5.0.3 Disk 1'" msgstr "" #: cmdline/apt-cdrom.cc:92 -msgid "Please insert a Disc in the drive and press enter" +msgid "Please insert a Disc in the drive and press [Enter]" msgstr "" #: cmdline/apt-cdrom.cc:140 @@ -1563,7 +1563,7 @@ msgstr "" msgid "" "Media change: please insert the disc labeled\n" " '%s'\n" -"in the drive '%s' and press enter\n" +"in the drive '%s' and press [Enter]\n" msgstr "" #. Only warn if there are no sources.list.d. @@ -1623,7 +1623,7 @@ msgstr "" #: dselect/install:52 dselect/install:84 dselect/install:88 dselect/install:95 #: dselect/install:106 dselect/update:45 -msgid "Press enter to continue." +msgid "Press [Enter] to continue." msgstr "" #: dselect/install:92 @@ -2057,7 +2057,7 @@ msgstr "" #: apt-pkg/acquire-worker.cc:485 #, c-format -msgid "Please insert the disc labeled: '%s' in the drive '%s' and press enter." +msgid "Please insert the disc labeled: '%s' in the drive '%s' and press [Enter]." msgstr "" #: apt-pkg/cachefile.cc:94 diff --git a/test/integration/test-apt-cdrom b/test/integration/test-apt-cdrom index 108805daa..ce31b5934 100755 --- a/test/integration/test-apt-cdrom +++ b/test/integration/test-apt-cdrom @@ -38,7 +38,7 @@ aptautotest_aptcdromlog_add() { aptautotest_aptget_update "$@"; } CDROM_PRE="Using CD-ROM mount point $(readlink -f ./rootdir/media)/cdrom/ Unmounting CD-ROM... Waiting for disc... -Please insert a Disc in the drive and press enter +Please insert a Disc in the drive and press [Enter] Mounting CD-ROM... Scanning disc for index files..." CDROM_POST="This disc is called: -- cgit v1.2.3-70-g09d2 From bb08e2046e18014e01d54606784936c25dff84b8 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 13 Aug 2015 10:31:50 +0200 Subject: Fix integration tests for the removal of the Package pin output This should make them work again. --- test/integration/test-bug-543966-downgrade-below-1000-pin | 11 ++++------- test/integration/test-policy-pinning | 6 +----- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/test/integration/test-bug-543966-downgrade-below-1000-pin b/test/integration/test-bug-543966-downgrade-below-1000-pin index ede9ad6aa..435b6876e 100755 --- a/test/integration/test-bug-543966-downgrade-below-1000-pin +++ b/test/integration/test-bug-543966-downgrade-below-1000-pin @@ -33,20 +33,17 @@ Pin-Priority: $2" > rootdir/etc/apt/preferences testpinning() { - local PKGPIN='' local PKGPINPRIO='' local REPPINPRIO='' if [ "$1" != '*' ]; then PKGPINPRIO='' REPPINPRIO=' 500' - PKGPIN='Package pin: 5.0.0 - ' fi writepin "$1" '99' testsuccessequal "base-files: Installed: 5.0.0-1 Candidate: 5.0.0-1 - ${PKGPIN}Version table: + Version table: *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-99} @@ -56,7 +53,7 @@ testpinning() { testsuccessequal "base-files: Installed: 5.0.0-1 Candidate: 5.0.0-1 - ${PKGPIN}Version table: + Version table: *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-100} @@ -66,7 +63,7 @@ testpinning() { testsuccessequal "base-files: Installed: 5.0.0-1 Candidate: 5.0.0-1 - ${PKGPIN}Version table: + Version table: *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-999} @@ -76,7 +73,7 @@ testpinning() { testsuccessequal "base-files: Installed: 5.0.0-1 Candidate: 5.0.0 - ${PKGPIN}Version table: + Version table: *** 5.0.0-1 100 100 $STATUS 5.0.0 ${PKGPINPRIO:-1000} diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index c4f478efc..1c8d92bcc 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -89,10 +89,6 @@ testequalpolicycoolstuff() { local AB="$3" local AS="$4" local PB="$5" - local PINVERSION="$6" - if [ -n "$PINVERSION" ]; then - PINVERSION="Package pin: $PINVERSION - " fi local IS="" local IB="" @@ -118,7 +114,7 @@ testequalpolicycoolstuff() { testsuccessequal "coolstuff: Installed: $INSTALLED Candidate: $CANDIDATE - ${PINVERSION}Version table:${BPO2ARCHIVE} + Version table:${BPO2ARCHIVE} $IB 2.0~bpo1 $PB ${BPO1ARCHIVE}$SB $IS 1.0 $AS -- cgit v1.2.3-70-g09d2 From eb8ef1bb77a8fe2909a861fff3255ef6330c8ed5 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Thu, 13 Aug 2015 10:48:22 +0200 Subject: Remove an invalid fi from a testcase Gbp-Dch: ignore --- test/integration/test-policy-pinning | 1 - 1 file changed, 1 deletion(-) (limited to 'test') diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index 1c8d92bcc..d54e1bc36 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -89,7 +89,6 @@ testequalpolicycoolstuff() { local AB="$3" local AS="$4" local PB="$5" - fi local IS="" local IB="" local SB="" -- cgit v1.2.3-70-g09d2 From b381a482eab0fc7b65b63cf0512ef1f97d775e34 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 14 Aug 2015 11:49:45 +0200 Subject: Replace --force-yes by various options starting with --allow This enables more fine grained control over such exceptions. --- apt-private/private-cmndline.cc | 3 + apt-private/private-download.cc | 6 +- apt-private/private-install.cc | 43 ++++++---- doc/apt-get.8.xml | 26 +++++- test/integration/test-allow | 98 ++++++++++++++++++++++ .../integration/test-apt-get-update-unauth-warning | 2 +- test/integration/test-apt-never-markauto-sections | 2 +- test/integration/test-apt-update-nofallback | 2 +- test/integration/test-apt-update-rollback | 4 +- ...bug-712116-dpkg-pre-install-pkgs-hook-multiarch | 2 +- test/integration/test-releasefile-verification | 4 +- 11 files changed, 167 insertions(+), 25 deletions(-) create mode 100755 test/integration/test-allow (limited to 'test') diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc index fa8416824..487349c8c 100644 --- a/apt-private/private-cmndline.cc +++ b/apt-private/private-cmndline.cc @@ -202,6 +202,9 @@ static bool addArgumentsAPTGet(std::vector &Args, char const addArg(0,"ignore-hold","APT::Ignore-Hold",0); addArg(0,"upgrade","APT::Get::upgrade",0); addArg(0,"only-upgrade","APT::Get::Only-Upgrade",0); + addArg(0,"allow-change-held-packages","APT::Get::allow-change-held-packages",CommandLine::Boolean); + addArg(0,"allow-remove-essential","APT::Get::allow-remove-essential",CommandLine::Boolean); + addArg(0,"allow-downgrades","APT::Get::allow-downgrades",CommandLine::Boolean); addArg(0,"force-yes","APT::Get::force-yes",0); addArg(0,"print-uris","APT::Get::Print-URIs",0); addArg(0,"trivial-only","APT::Get::Trivial-Only",0); diff --git a/apt-private/private-download.cc b/apt-private/private-download.cc index 099146187..18a9b1fbc 100644 --- a/apt-private/private-download.cc +++ b/apt-private/private-download.cc @@ -114,10 +114,12 @@ bool AuthPrompt(std::vector const &UntrustedList, bool const Prompt return true; } - else if (_config->FindB("APT::Get::Force-Yes",false) == true) + else if (_config->FindB("APT::Get::Force-Yes",false) == true) { + _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead.")); return true; + } - return _error->Error(_("There are problems and -y was used without --force-yes")); + return _error->Error(_("There were unauthenticated packages and -y was used without --allow-unauthenticated")); } /*}}}*/ bool AcquireRun(pkgAcquire &Fetcher, int const PulseInterval, bool * const Failure, bool * const TransientNetworkFailure)/*{{{*/ diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc index d2b4bed51..96e33f7de 100644 --- a/apt-private/private-install.cc +++ b/apt-private/private-install.cc @@ -58,7 +58,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) } } - bool Fail = false; + bool Hold = false; + bool Downgrade = false; bool Essential = false; // Show all the various warning indicators @@ -66,13 +67,17 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) ShowNew(c1out,Cache); if (ShwKept == true) ShowKept(c1out,Cache); - Fail |= !ShowHold(c1out,Cache); + Hold = !ShowHold(c1out,Cache); if (_config->FindB("APT::Get::Show-Upgraded",true) == true) ShowUpgraded(c1out,Cache); - Fail |= !ShowDowngraded(c1out,Cache); + Downgrade = !ShowDowngraded(c1out,Cache); + if (_config->FindB("APT::Get::Download-Only",false) == false) Essential = !ShowEssential(c1out,Cache); - Fail |= Essential; + + // All kinds of failures + bool Fail = (Essential || Downgrade || Hold); + Stats(c1out,Cache); // Sanity check @@ -89,7 +94,25 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) // No remove flag if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false) return _error->Error(_("Packages need to be removed but remove is disabled.")); - + + // Fail safe check + if (_config->FindI("quiet",0) >= 2 || + _config->FindB("APT::Get::Assume-Yes",false) == true) + { + if (_config->FindB("APT::Get::Force-Yes",false) == true) { + _error->Warning(_("--force-yes is deprecated, use one of the options starting with --allow instead.")); + } + + if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) { + if (Essential == true && _config->FindB("APT::Get::allow-remove-essential", false) == false) + return _error->Error(_("Essential packages were removed and -y was used without --allow-remove-essential.")); + if (Downgrade == true && _config->FindB("APT::Get::allow-downgrades", false) == false) + return _error->Error(_("Packages were downgraded and -y was used without --allow-downgrades.")); + if (Hold == true && _config->FindB("APT::Get::allow-change-held-packages", false) == false) + return _error->Error(_("Held packages were changed and -y was used without --allow-change-held-packages.")); + } + } + // Run the simulator .. if (_config->FindB("APT::Get::Simulate") == true) { @@ -173,15 +196,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask, bool Safety) if (CheckFreeSpaceBeforeDownload(_config->FindDir("Dir::Cache::Archives"), (FetchBytes - FetchPBytes)) == false) return false; - // Fail safe check - if (_config->FindI("quiet",0) >= 2 || - _config->FindB("APT::Get::Assume-Yes",false) == true) - { - if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) - return _error->Error(_("There are problems and -y was used without --force-yes")); - } - - if (Essential == true && Safety == true) + if (Essential == true && Safety == true && _config->FindB("APT::Get::allow-remove-essential", false) == false) { if (_config->FindB("APT::Get::Trivial-Only",false) == true) return _error->Error(_("Trivial Only specified but this is not a trivial operation.")); diff --git a/doc/apt-get.8.xml b/doc/apt-get.8.xml index 81a9036c4..76a53aec2 100644 --- a/doc/apt-get.8.xml +++ b/doc/apt-get.8.xml @@ -429,12 +429,36 @@ Configuration Item: APT::Get::Only-Upgrade. + + This is a dangerous option that will cause apt to continue + without prompting if it is doing downgrades. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-downgrades. Introduced in APT 1.1. + + + + Force yes; this is a dangerous option that will cause apt to continue + without prompting if it is removing essentials. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-remove-essential. Introduced in APT 1.1. + + + + Force yes; this is a dangerous option that will cause apt to continue + without prompting if it is changing held packages. It + should not be used except in very special situations. Using + it can potentially destroy your system! + Configuration Item: APT::Get::allow-change-held-packages. Introduced in APT 1.1. + + Force yes; this is a dangerous option that will cause apt to continue without prompting if it is doing something potentially harmful. It should not be used except in very special situations. Using force-yes can potentially destroy your system! - Configuration Item: APT::Get::force-yes. + Configuration Item: APT::Get::force-yes. This is deprecated and replaced by , , in 1.1. diff --git a/test/integration/test-allow b/test/integration/test-allow new file mode 100755 index 000000000..3d773ee95 --- /dev/null +++ b/test/integration/test-allow @@ -0,0 +1,98 @@ +#!/bin/sh +# +# Test for --allow-remove-essential and friends replacing --force-yes +# +set -e + +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture 'amd64' + +insertpackage 'unstable' 'downgrade' 'all' '1' +insertinstalledpackage 'downgrade' 'all' '2' + +insertpackage 'unstable' 'hold' 'all' '2' +insertinstalledpackage 'hold' 'all' '1' + +insertinstalledpackage 'essential' 'all' '1' 'Essential: yes' + +setupaptarchive + +testsuccess aptmark hold hold + +# Test --allow-remove--essential + +testfailureequal 'Reading package lists... +Building dependency tree... +The following packages will be REMOVED: + essential +WARNING: The following essential packages will be removed. +This should NOT be done unless you know exactly what you are doing! + essential +0 upgraded, 0 newly installed, 1 to remove and 1 not upgraded. +E: Essential packages were removed and -y was used without --allow-remove-essential.' aptget remove essential -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following packages will be REMOVED: + essential +WARNING: The following essential packages will be removed. +This should NOT be done unless you know exactly what you are doing! + essential +0 upgraded, 0 newly installed, 1 to remove and 1 not upgraded. +Remv essential [1]' aptget remove essential -y --allow-remove-essential -s + +# Test --allow-change-held-packages (should not influence dist-upgrade, but an install) + +testsuccessequal 'Reading package lists... +Building dependency tree... +Calculating upgrade... +The following packages have been kept back: + hold +0 upgraded, 0 newly installed, 0 to remove and 1 not upgraded.' aptget dist-upgrade --allow-change-held-packages -s + +testfailureequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +E: Held packages were changed and -y was used without --allow-change-held-packages.' aptget install hold -y -s + +testfailureequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +E: Held packages were changed and -y was used without --allow-change-held-packages.' aptget install hold -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following held packages will be changed: + hold +The following packages will be upgraded: + hold +1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. +Inst hold [1] (2 unstable [all]) +Conf hold (2 unstable [all])' aptget install hold -y -s --allow-change-held-packages + +# Test --allow-downgrades + +testfailureequal 'Reading package lists... +Building dependency tree... +The following packages will be DOWNGRADED: + downgrade +0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 1 not upgraded. +E: Packages were downgraded and -y was used without --allow-downgrades.' aptget install downgrade=1 -y -s + +testsuccessequal 'Reading package lists... +Building dependency tree... +The following packages will be DOWNGRADED: + downgrade +0 upgraded, 0 newly installed, 1 downgraded, 0 to remove and 1 not upgraded. +Inst downgrade [2] (1 unstable [all]) +Conf downgrade (1 unstable [all])' aptget install downgrade=1 --allow-downgrades -y -s diff --git a/test/integration/test-apt-get-update-unauth-warning b/test/integration/test-apt-get-update-unauth-warning index bc8e6d3ea..4c45f8f26 100755 --- a/test/integration/test-apt-get-update-unauth-warning +++ b/test/integration/test-apt-get-update-unauth-warning @@ -81,4 +81,4 @@ W: The repository 'file:$APTARCHIVE unstable Release' does not have a Release fi # ensure we can not install the package testfailureequal "WARNING: The following packages cannot be authenticated! foo -E: There are problems and -y was used without --force-yes" aptget install -qq -y foo +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y foo diff --git a/test/integration/test-apt-never-markauto-sections b/test/integration/test-apt-never-markauto-sections index a469b4c15..9f490a1bd 100755 --- a/test/integration/test-apt-never-markauto-sections +++ b/test/integration/test-apt-never-markauto-sections @@ -65,7 +65,7 @@ testmarkedauto # test that installed/upgraded auto-pkgs are not set to manual -testsuccess aptget install browser=41 -y --force-yes +testsuccess aptget install browser=41 -y --allow-downgrades testmarkedmanual 'browser' 'dpkg' 'foreignpkg:i386' 'nosection' testmarkedauto diff --git a/test/integration/test-apt-update-nofallback b/test/integration/test-apt-update-nofallback index 2f4ddc016..6e9db2cae 100755 --- a/test/integration/test-apt-update-nofallback +++ b/test/integration/test-apt-update-nofallback @@ -101,7 +101,7 @@ test_from_inrelease_to_unsigned_with_override() # but that the individual packages are still considered untrusted testfailureequal "WARNING: The following packages cannot be authenticated! evil -E: There are problems and -y was used without --force-yes" aptget install -qq -y evil +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y evil } test_cve_2012_0214() diff --git a/test/integration/test-apt-update-rollback b/test/integration/test-apt-update-rollback index 646484e7b..503b81985 100755 --- a/test/integration/test-apt-update-rollback +++ b/test/integration/test-apt-update-rollback @@ -120,7 +120,7 @@ test_unauthenticated_to_invalid_inrelease() { listcurrentlistsdirectory > lists.before testfailureequal "WARNING: The following packages cannot be authenticated! old -E: There are problems and -y was used without --force-yes" aptget install -qq -y old +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y old # go to authenticated but not correct add_new_package '+1hour' @@ -133,7 +133,7 @@ E: Some index files failed to download. They have been ignored, or old ones used testfailure ls rootdir/var/lib/apt/lists/*_InRelease testfailureequal "WARNING: The following packages cannot be authenticated! old -E: There are problems and -y was used without --force-yes" aptget install -qq -y old +E: There were unauthenticated packages and -y was used without --allow-unauthenticated" aptget install -qq -y old } test_inrelease_to_unauth_inrelease() { diff --git a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch index 62355a6b5..93a33d30f 100755 --- a/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch +++ b/test/integration/test-bug-712116-dpkg-pre-install-pkgs-hook-multiarch @@ -48,7 +48,7 @@ DPkg::Tools::options::\"./${hook}-v${1}.sh\"::Version \"$1\";" > rootdir/etc/apt observehook() { rm -f ${hook}-v2.list ${hook}-v3.list msgtest 'Observe hooks while' "$*" - testsuccess --nomsg aptget "$@" -y --force-yes + testsuccess --nomsg aptget "$@" -y --allow-downgrades } testrun() { diff --git a/test/integration/test-releasefile-verification b/test/integration/test-releasefile-verification index 06701c623..c4d1455eb 100755 --- a/test/integration/test-releasefile-verification +++ b/test/integration/test-releasefile-verification @@ -69,7 +69,7 @@ The following NEW packages will be installed: After this operation, 5370 kB of additional disk space will be used. WARNING: The following packages cannot be authenticated! apt -E: There are problems and -y was used without --force-yes' aptget install apt -dy +E: There were unauthenticated packages and -y was used without --allow-unauthenticated' aptget install apt -dy } failaptnew() { @@ -83,7 +83,7 @@ The following NEW packages will be installed: After this operation, 5808 kB of additional disk space will be used. WARNING: The following packages cannot be authenticated! apt -E: There are problems and -y was used without --force-yes' aptget install apt -dy +E: There were unauthenticated packages and -y was used without --allow-unauthenticated' aptget install apt -dy } # fake our downloadable file -- cgit v1.2.3-70-g09d2 From e916a815e18b497aecd535ae14dc5034aa6a384f Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Fri, 14 Aug 2015 13:44:28 +0200 Subject: Add integration test for Pin-Priority range checks Gbp-Dch: ignore --- test/integration/test-policy-pinning | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'test') diff --git a/test/integration/test-policy-pinning b/test/integration/test-policy-pinning index d54e1bc36..ea266e934 100755 --- a/test/integration/test-policy-pinning +++ b/test/integration/test-policy-pinning @@ -246,3 +246,63 @@ aptgetupdate testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 500 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 100 990 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t stable testequalpolicycoolstuff "2.0~bpo1" "2.0~bpo2" 990 500 100 "" "2.0~bpo2" -o Test=ButAutomaticUpgrades -t backports + + +tmppath=$(readlink -f .) + +# Check 16-bit integers +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 32767 +" > rootdir/etc/apt/preferences + +testsuccess aptget install -s coolstuff -o PinPriority=32767 + +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: -32768 +" > rootdir/etc/apt/preferences +testsuccess aptget install -s coolstuff -o PinPriority=-32768 + + +# Check for 32-bit integers +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 32768 +" > rootdir/etc/apt/preferences + +testfailureequal "Reading package lists... +E: ${tmppath}/rootdir/etc/apt/preferences: Value 32768 is outside the range of valid pin priorities (-32768 to 32767)" \ + aptget install -s coolstuff -o PinPriority=32768 + + +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: -32769 +" > rootdir/etc/apt/preferences + +testfailureequal "Reading package lists... +E: ${tmppath}/rootdir/etc/apt/preferences: Value -32769 is outside the range of valid pin priorities (-32768 to 32767)" \ + aptget install -s coolstuff -o PinPriority=-32769 + +# Check for 64-bit integers + +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 2147483648 +" > rootdir/etc/apt/preferences + +testfailureequal "Reading package lists... +E: Cannot convert 2147483648 to integer - (34: Numerical result out of range) +E: ${tmppath}/rootdir/etc/apt/preferences: Value 2147483648 is outside the range of valid pin priorities (-32768 to 32767)" \ + aptget install -s coolstuff -o PinPriority=2147483648 + +# Check for 0 +echo "Package: coolstuff +Pin: release n=backports +Pin-Priority: 0 +" > rootdir/etc/apt/preferences + +testfailureequal "Reading package lists... +E: No priority (or zero) specified for pin" \ + aptget install -s coolstuff -o PinPriority=0 -- cgit v1.2.3-70-g09d2 From e7ebb41440cbe298b07c7fb7c6b20a64a17200f0 Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 17 Aug 2015 18:37:09 +0200 Subject: Fix the test suite again Gbp-Dch: ignore --- .../test-allow-scores-for-all-dependency-types | 4 +-- .../test-architecture-specification-parsing | 6 ++--- .../test-bug-470115-new-and-tighten-recommends | 18 ++++++------- .../integration/test-bug-604222-new-and-autoremove | 6 ++--- .../test-bug-612099-multiarch-conflicts | 8 +++--- test/integration/test-bug-612557-garbage-upgrade | 4 +-- .../test-bug-613420-new-garbage-dependency | 4 +-- .../test-bug-686346-package-missing-architecture | 2 +- .../test-bug-709560-set-candidate-release | 2 +- .../test-bug-723586-any-stripped-in-single-arch | 2 +- .../test-bug-723705-tagfile-truncates-fields | 2 +- .../test-bug-735967-lib32-to-i386-unavailable | 2 +- .../test-bug-758153-versioned-provides-support | 16 ++++++------ test/integration/test-bug-multiarch-upgrade | 2 +- test/integration/test-essential-force-loopbreak | 2 +- test/integration/test-handling-broken-orgroups | 8 +++--- .../test-ignore-provides-if-versioned-breaks | 6 ++--- .../test-ignore-provides-if-versioned-conflicts | 6 ++--- test/integration/test-multiarch-allowed | 16 ++++++------ test/integration/test-multiarch-foreign | 16 ++++++------ test/integration/test-parse-all-archs-into-cache | 6 ++--- .../test-prefer-higher-priority-providers | 10 ++++---- ...prefer-native-architecture-over-higher-priority | 2 +- ...prevent-markinstall-multiarch-same-versionscrew | 2 +- test/integration/test-release-candidate-switching | 30 +++++++++++----------- .../test-specific-architecture-dependencies | 14 +++++----- ...u-bug-1130419-prefer-installed-ma-same-siblings | 12 ++++----- test/integration/test-ubuntu-bug-614993 | 2 +- .../test-ubuntu-bug-806274-install-suggests | 8 +++--- ...u-bug-835625-multiarch-lockstep-installed-first | 4 +-- .../test-unpack-different-version-unpacked | 12 ++++----- test/integration/test-xorg-break-providers | 2 +- 32 files changed, 118 insertions(+), 118 deletions(-) (limited to 'test') diff --git a/test/integration/test-allow-scores-for-all-dependency-types b/test/integration/test-allow-scores-for-all-dependency-types index 56cfc9a69..30cc2fc93 100755 --- a/test/integration/test-allow-scores-for-all-dependency-types +++ b/test/integration/test-allow-scores-for-all-dependency-types @@ -115,7 +115,7 @@ Inst baz (2 unversioned [amd64]) Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following packages will be REMOVED: bar @@ -139,7 +139,7 @@ Inst baz (2 unversioned [amd64]) Conf baz (2 unversioned [amd64])' aptget install baz -st unversioned testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following packages will be REMOVED: bar diff --git a/test/integration/test-architecture-specification-parsing b/test/integration/test-architecture-specification-parsing index f5a5b123e..701b10c3e 100755 --- a/test/integration/test-architecture-specification-parsing +++ b/test/integration/test-architecture-specification-parsing @@ -28,7 +28,7 @@ setupaptarchive testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo pkg-arch-foo @@ -48,7 +48,7 @@ Conf pkg-arch-no-foo (1.0 stable [${NATIVE}])" aptget install pkg-arch-no-foo -s testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo pkg-arch-foo-unrelated-no @@ -60,7 +60,7 @@ Conf pkg-arch-foo-unrelated-no (1.0 stable [${NATIVE}])" aptget install pkg-arch testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo pkg-arch-foo-unrelated-no2 diff --git a/test/integration/test-bug-470115-new-and-tighten-recommends b/test/integration/test-bug-470115-new-and-tighten-recommends index 80f699ef3..3c159811d 100755 --- a/test/integration/test-bug-470115-new-and-tighten-recommends +++ b/test/integration/test-bug-470115-new-and-tighten-recommends @@ -49,7 +49,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following packages will be upgraded: cool tighten-cool @@ -61,7 +61,7 @@ Conf tighten-cool (2 unstable [all])' aptget install tighten-cool -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: stuff The following packages will be upgraded: stuff tighten-coolorstuff @@ -73,7 +73,7 @@ Conf tighten-coolorstuff (2 unstable [all])' aptget install tighten-coolorstuff testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following packages will be upgraded: cool tighten-coolorstuff2 @@ -85,7 +85,7 @@ Conf tighten-coolorstuff2 (2 unstable [all])' aptget install tighten-coolorstuff testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following packages will be upgraded: cool newrec-cool @@ -97,7 +97,7 @@ Conf newrec-cool (2 unstable [all])' aptget install newrec-cool -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: super The following NEW packages will be installed: super @@ -111,7 +111,7 @@ Conf super (2 unstable [all])' aptget install newrec-super -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following packages will be upgraded: cool newrec-coolorstuff @@ -123,7 +123,7 @@ Conf newrec-coolorstuff (2 unstable [all])' aptget install newrec-coolorstuff -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: stuff The following packages will be upgraded: cool-gone stuff @@ -135,7 +135,7 @@ Conf stuff (2 unstable [all])' aptget install cool-gone -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: super The following NEW packages will be installed: super @@ -151,7 +151,7 @@ Conf super-overtake (2 unstable [all])' aptget install super-overtake -s # the first option in an or-group should be the preferred one… testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following packages will be upgraded: cool upgrade-over-new diff --git a/test/integration/test-bug-604222-new-and-autoremove b/test/integration/test-bug-604222-new-and-autoremove index 3b5fa20c4..e910c70cb 100755 --- a/test/integration/test-bug-604222-new-and-autoremove +++ b/test/integration/test-bug-604222-new-and-autoremove @@ -40,7 +40,7 @@ Reading state information... The following package was automatically installed and is no longer required: libvtk5.4 Use 'apt-get autoremove' to remove it. -The following extra packages will be installed: +The following additional packages will be installed: libavcodec52 libopenal-dev libvtk5.4 The following NEW packages will be installed: dummy-archive libavcodec52 libopenal-dev @@ -55,7 +55,7 @@ Building dependency tree... Reading state information... 1 package was automatically installed and is no longer required. Use 'apt-get autoremove' to remove it. -The following extra packages will be installed: +The following additional packages will be installed: libavcodec52 libopenal-dev libvtk5.4 The following NEW packages will be installed: dummy-archive libavcodec52 libopenal-dev @@ -78,7 +78,7 @@ Building dependency tree... MarkKeep libvtk5-dev [ i386 ] < none -> 5.4.2-8 > ( libdevel ) FU=0 MarkKeep libvtk5-dev [ i386 ] < none -> 5.4.2-8 > ( libdevel ) FU=0 MarkDelete libvtk5.4 [ i386 ] < none -> 5.4.2-8 > ( libs ) FU=0 -The following extra packages will be installed: +The following additional packages will be installed: libavcodec52 libopenal-dev The following NEW packages will be installed: dummy-archive libavcodec52 libopenal-dev diff --git a/test/integration/test-bug-612099-multiarch-conflicts b/test/integration/test-bug-612099-multiarch-conflicts index 401b521a5..af8391555 100755 --- a/test/integration/test-bug-612099-multiarch-conflicts +++ b/test/integration/test-bug-612099-multiarch-conflicts @@ -41,7 +41,7 @@ Conf foobar (1.0 stable [i386])' aptget install foobar -st stable testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libc6:amd64 The following packages will be REMOVED: libc6 @@ -96,7 +96,7 @@ Conf foobar (1.0 stable [i386])' aptget install foobar/stable -st testing testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libc6:amd64 The following packages will be REMOVED: libc6 @@ -145,7 +145,7 @@ Conf foobar-same (1.0 stable [i386])' aptget install foobar-same -st stable testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libc6-same:amd64 The following NEW packages will be installed: foobar-same:amd64 libc6-same:amd64 @@ -206,7 +206,7 @@ Conf foobar-same (1.0 stable [i386])' aptget install foobar-same/stable -st test testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libc6-same:amd64 The following packages will be REMOVED: libc6-same diff --git a/test/integration/test-bug-612557-garbage-upgrade b/test/integration/test-bug-612557-garbage-upgrade index 552330d81..1709af7f2 100755 --- a/test/integration/test-bug-612557-garbage-upgrade +++ b/test/integration/test-bug-612557-garbage-upgrade @@ -20,7 +20,7 @@ testmarkedauto python-uno openoffice.org-common testfailureequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libreoffice-common The following packages will be REMOVED: openoffice.org-common openoffice.org-emailmerge @@ -38,7 +38,7 @@ testmarkedauto python-uno openoffice.org-common openoffice.org-emailmerge testfailureequal 'Reading package lists... Building dependency tree... Reading state information... -The following extra packages will be installed: +The following additional packages will be installed: libreoffice-common The following packages will be REMOVED: openoffice.org-common openoffice.org-emailmerge diff --git a/test/integration/test-bug-613420-new-garbage-dependency b/test/integration/test-bug-613420-new-garbage-dependency index 18eab79c2..8424b10b7 100755 --- a/test/integration/test-bug-613420-new-garbage-dependency +++ b/test/integration/test-bug-613420-new-garbage-dependency @@ -24,7 +24,7 @@ Reading state information... The following packages were automatically installed and are no longer required: libreoffice-officebean openoffice.org-officebean Use 'apt-get autoremove' to remove them. -The following extra packages will be installed: +The following additional packages will be installed: libreoffice-core libreoffice-officebean openoffice.org-officebean The following packages will be REMOVED: openoffice.org-core @@ -40,7 +40,7 @@ Building dependency tree... Reading state information... 2 packages were automatically installed and are no longer required. Use 'apt-get autoremove' to remove them. -The following extra packages will be installed: +The following additional packages will be installed: libreoffice-core libreoffice-officebean openoffice.org-officebean The following packages will be REMOVED: openoffice.org-core diff --git a/test/integration/test-bug-686346-package-missing-architecture b/test/integration/test-bug-686346-package-missing-architecture index dae0fa81d..d9bc0c3f2 100755 --- a/test/integration/test-bug-686346-package-missing-architecture +++ b/test/integration/test-bug-686346-package-missing-architecture @@ -27,7 +27,7 @@ Conf pkgc (1 unstable [amd64])' aptget install pkgc -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: pkgb The following packages will be REMOVED: pkgb:none diff --git a/test/integration/test-bug-709560-set-candidate-release b/test/integration/test-bug-709560-set-candidate-release index ab41d8f2a..502ade92c 100755 --- a/test/integration/test-bug-709560-set-candidate-release +++ b/test/integration/test-bug-709560-set-candidate-release @@ -25,7 +25,7 @@ testsuccessequal "Reading package lists... Building dependency tree... Selected version '2.0' (experimental [all]) for 'foo' Selected version '2.1' (experimental [all]) for 'foo-dep' because of 'foo' -The following extra packages will be installed: +The following additional packages will be installed: foo-dep The following NEW packages will be installed: foo foo-dep diff --git a/test/integration/test-bug-723586-any-stripped-in-single-arch b/test/integration/test-bug-723586-any-stripped-in-single-arch index 8a835a6db..78c4eae64 100755 --- a/test/integration/test-bug-723586-any-stripped-in-single-arch +++ b/test/integration/test-bug-723586-any-stripped-in-single-arch @@ -17,7 +17,7 @@ setupaptarchive INSTALLLOG='Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: python3 The following NEW packages will be installed: python3-gnupg diff --git a/test/integration/test-bug-723705-tagfile-truncates-fields b/test/integration/test-bug-723705-tagfile-truncates-fields index 29f98550c..21878ebf0 100755 --- a/test/integration/test-bug-723705-tagfile-truncates-fields +++ b/test/integration/test-bug-723705-tagfile-truncates-fields @@ -12,7 +12,7 @@ aptget install --print-uris -y cdebconf-newt-terminal cdebconf-gtk-terminal 2>&1 testfileequal filename.log "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cdebconf-gtk-udeb cdebconf-newt-udeb cdebconf-udeb libc6-udeb libglib2.0-udeb libgtk2.0-0-udeb libvte9-udeb The following NEW packages will be installed: diff --git a/test/integration/test-bug-735967-lib32-to-i386-unavailable b/test/integration/test-bug-735967-lib32-to-i386-unavailable index eb6e1a331..1523b81e0 100755 --- a/test/integration/test-bug-735967-lib32-to-i386-unavailable +++ b/test/integration/test-bug-735967-lib32-to-i386-unavailable @@ -78,7 +78,7 @@ Conf lib32nss-mdns (0.10-6 unstable [amd64])' aptget dist-upgrade -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libfoo libfoo-bin:i386 The following NEW packages will be installed: foo libfoo libfoo-bin:i386 diff --git a/test/integration/test-bug-758153-versioned-provides-support b/test/integration/test-bug-758153-versioned-provides-support index bf42f57fd..6d43d9943 100755 --- a/test/integration/test-bug-758153-versioned-provides-support +++ b/test/integration/test-bug-758153-versioned-provides-support @@ -157,7 +157,7 @@ Conf cool-webapp (4 experimental [all])' aptget install cool-webapp foreign-webs testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: baz:i386 foo @@ -182,7 +182,7 @@ E: Unable to correct problems, you have held broken packages.' aptget install ba testsuccessequal "Reading package lists... Building dependency tree... Selected version '2' (experimental [amd64]) for 'baz' -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: baz foo @@ -195,7 +195,7 @@ Conf baz (2 experimental [amd64])" aptget install baz/experimental -s -q=0 testsuccessequal "Reading package lists... Building dependency tree... Selected version '2' (experimental [i386]) for 'baz:i386' -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: baz:i386 foo @@ -219,7 +219,7 @@ E: Unable to correct problems, you have held broken packages.' aptget install ba testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: next The following NEW packages will be installed: needsrealnext next @@ -231,7 +231,7 @@ Conf needsrealnext (2 unstable [amd64])' aptget install needsrealnext -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: next The following NEW packages will be installed: needsrealnext:i386 next @@ -243,7 +243,7 @@ Conf needsrealnext:i386 (2 unstable [i386])' aptget install needsrealnext:i386 - testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: virtualnext2 The following NEW packages will be installed: needsnext2 virtualnext2 @@ -255,7 +255,7 @@ Conf needsnext2 (2 unstable [amd64])' aptget install needsnext2 -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: virtualnext2 The following NEW packages will be installed: needsnext2:i386 virtualnext2 @@ -267,7 +267,7 @@ Conf needsnext2:i386 (2 unstable [i386])' aptget install needsnext2:i386 -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: virtualnext3 The following NEW packages will be installed: needsnext3 virtualnext3 diff --git a/test/integration/test-bug-multiarch-upgrade b/test/integration/test-bug-multiarch-upgrade index 56071f184..b8821126f 100755 --- a/test/integration/test-bug-multiarch-upgrade +++ b/test/integration/test-bug-multiarch-upgrade @@ -18,7 +18,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libcups2 The following packages will be upgraded: libcups2 libcups2:i386 diff --git a/test/integration/test-essential-force-loopbreak b/test/integration/test-essential-force-loopbreak index 50c682d43..86a852c32 100755 --- a/test/integration/test-essential-force-loopbreak +++ b/test/integration/test-essential-force-loopbreak @@ -27,7 +27,7 @@ testforcebreak() { rm -f rootdir/var/lib/apt/extended_states testfailureequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: sysvinit The following NEW packages will be installed: systemd-sysv diff --git a/test/integration/test-handling-broken-orgroups b/test/integration/test-handling-broken-orgroups index 15964a270..a465e5234 100755 --- a/test/integration/test-handling-broken-orgroups +++ b/test/integration/test-handling-broken-orgroups @@ -25,7 +25,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: cool The following NEW packages will be installed: cool coolstuff @@ -37,7 +37,7 @@ Conf coolstuff (1.0-1 unstable [all])' aptget install coolstuff -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: stuff The following NEW packages will be installed: coolstuff2 stuff @@ -72,7 +72,7 @@ Conf coolstuff-brokenrec (1.0-1 unstable [all])' aptget install coolstuff-broken testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: stuff The following NEW packages will be installed: coolstuff-conflict stuff @@ -84,7 +84,7 @@ Conf coolstuff-conflict (1.0-1 unstable [all])' aptget install coolstuff-conflic testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: extrastuff The following NEW packages will be installed: coolstuff-provided extrastuff diff --git a/test/integration/test-ignore-provides-if-versioned-breaks b/test/integration/test-ignore-provides-if-versioned-breaks index 4d6114637..a7d9d4054 100755 --- a/test/integration/test-ignore-provides-if-versioned-breaks +++ b/test/integration/test-ignore-provides-if-versioned-breaks @@ -57,7 +57,7 @@ Conf foo-provider (1.0 unstable [i386])' aptget install foo-provider foo-breaker testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo-breaker-3 foo-provider @@ -95,7 +95,7 @@ Conf foo-foreign-provider (1.0 unstable [i386])' aptget install foo-foreign-prov testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo-foreign:amd64 The following NEW packages will be installed: foo-foreign-breaker-3 foo-foreign-provider @@ -133,7 +133,7 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo-same foo-same:amd64 The following NEW packages will be installed: foo-same-breaker-3 foo-same-provider diff --git a/test/integration/test-ignore-provides-if-versioned-conflicts b/test/integration/test-ignore-provides-if-versioned-conflicts index 6a0c924e2..f30789ea6 100755 --- a/test/integration/test-ignore-provides-if-versioned-conflicts +++ b/test/integration/test-ignore-provides-if-versioned-conflicts @@ -57,7 +57,7 @@ Conf foo-provider (1.0 unstable [i386])' aptget install foo-provider foo-breaker testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo-breaker-3 foo-provider @@ -95,7 +95,7 @@ Conf foo-foreign-provider (1.0 unstable [i386])' aptget install foo-foreign-prov testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo-foreign:amd64 The following NEW packages will be installed: foo-foreign-breaker-3 foo-foreign-provider @@ -133,7 +133,7 @@ Conf foo-same-provider (1.0 unstable [i386])' aptget install foo-same-provider f testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo-same foo-same:amd64 The following NEW packages will be installed: foo-same-breaker-3 foo-same-provider diff --git a/test/integration/test-multiarch-allowed b/test/integration/test-multiarch-allowed index 2c791ca19..2eb479c17 100755 --- a/test/integration/test-multiarch-allowed +++ b/test/integration/test-multiarch-allowed @@ -40,7 +40,7 @@ The following information may help to resolve the situation: solveableinsinglearch0() { testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo needsfoo @@ -53,7 +53,7 @@ Conf needsfoo (1 unstable [amd64])' aptget install needsfoo -s solveableinsinglearch0 testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo:i386 The following NEW packages will be installed: foo:i386 needsfoo:i386 @@ -74,7 +74,7 @@ E: Unable to correct problems, you have held broken packages." aptget install ne solveableinsinglearch1() { testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo $1 @@ -89,7 +89,7 @@ testneedsfooallgood() { solveableinsinglearch1 $1 testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: foo $1:i386 @@ -168,7 +168,7 @@ Conf hatesfoonative (1 unstable [amd64])' aptget install foo:i386 hatesfoonative solveableinsinglearch3() { testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: coolfoo The following NEW packages will be installed: coolfoo needscoolfoo @@ -179,7 +179,7 @@ Conf coolfoo (1 unstable [amd64]) Conf needscoolfoo (1 unstable [amd64])" aptget install needscoolfoo -s testsuccessequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: coolfoo The following NEW packages will be installed: coolfoo coolfoover needscoolfoo @@ -196,7 +196,7 @@ The following packages have unmet dependencies: E: Unable to correct problems, you have held broken packages." aptget install needscoolfooany -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: coolfoo The following NEW packages will be installed: coolfoo needscoolfoover0 @@ -207,7 +207,7 @@ Conf coolfoo (1 unstable [amd64]) Conf needscoolfoover0 (1 unstable [amd64])' aptget install needscoolfoover0 -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: coolfoo coolfoover The following NEW packages will be installed: coolfoo coolfoover needscoolfoover1 diff --git a/test/integration/test-multiarch-foreign b/test/integration/test-multiarch-foreign index a266e35ed..58e5b462a 100755 --- a/test/integration/test-multiarch-foreign +++ b/test/integration/test-multiarch-foreign @@ -27,7 +27,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: cool-foo:i386 foo @@ -59,7 +59,7 @@ Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 foo:armel -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: bar cool-bar:i386 @@ -103,7 +103,7 @@ Conf cool-bar (1.0 unstable [amd64])" aptget install cool-bar bar-provider:i386 satisfiable_in_singlearch() { testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: cool-foo foo @@ -125,7 +125,7 @@ Conf cool-foo (1.0 unstable [amd64])' aptget install cool-foo:amd64 foo:amd64 -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: bar cool-bar @@ -158,7 +158,7 @@ Conf cool-bar (1.0 unstable [amd64])" aptget install cool-bar bar-provider -s -q testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: cool-foo-x64 foo @@ -199,7 +199,7 @@ hatersgonnahate 'foo:i386' #FIXME: do not work in single-arch as i386 isn't known at cache generation time testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: cool-foo-x32 foo @@ -211,7 +211,7 @@ Conf cool-foo-x32 (1.0 unstable [amd64])' aptget install cool-foo-x32 -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: bar cool-bar-x32 @@ -223,7 +223,7 @@ Conf cool-bar-x32 (1.0 unstable [amd64])' aptget install cool-bar-x32 -s -q=0 testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: bar cool-bar-x64 diff --git a/test/integration/test-parse-all-archs-into-cache b/test/integration/test-parse-all-archs-into-cache index f61862912..7741563e3 100755 --- a/test/integration/test-parse-all-archs-into-cache +++ b/test/integration/test-parse-all-archs-into-cache @@ -34,7 +34,7 @@ Building dependency tree...' aptget check -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libfoo1 The following packages will be REMOVED: foo:amd64 @@ -49,7 +49,7 @@ Conf foo (1 unstable [i386])' aptget install foo -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libfoo1 The following packages will be REMOVED: foo:amd64 libfoo1:amd64 @@ -65,7 +65,7 @@ Conf foo (2 experimental [i386])' aptget install foo/experimental -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo libfoo1 The following packages will be REMOVED: foo:amd64 diff --git a/test/integration/test-prefer-higher-priority-providers b/test/integration/test-prefer-higher-priority-providers index 85a302fb1..e6da2e151 100755 --- a/test/integration/test-prefer-higher-priority-providers +++ b/test/integration/test-prefer-higher-priority-providers @@ -15,7 +15,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: awesome foo @@ -39,7 +39,7 @@ testsuccessequal "Reading package lists... Building dependency tree... Package 'bar' is not installed, so not removed Package 'baz' is not installed, so not removed -The following extra packages will be installed: +The following additional packages will be installed: foo The following NEW packages will be installed: awesome foo @@ -52,7 +52,7 @@ Conf awesome (1 unstable [all])" aptget install awesome bar- baz- -s testsuccessequal "Reading package lists... Building dependency tree... Package 'foo' is not installed, so not removed -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: awesome bar @@ -66,7 +66,7 @@ testsuccessequal "Reading package lists... Building dependency tree... Package 'foo' is not installed, so not removed Package 'baz' is not installed, so not removed -The following extra packages will be installed: +The following additional packages will be installed: bar The following NEW packages will be installed: awesome bar @@ -80,7 +80,7 @@ testsuccessequal "Reading package lists... Building dependency tree... Package 'foo' is not installed, so not removed Package 'bar' is not installed, so not removed -The following extra packages will be installed: +The following additional packages will be installed: baz The following NEW packages will be installed: awesome baz diff --git a/test/integration/test-prefer-native-architecture-over-higher-priority b/test/integration/test-prefer-native-architecture-over-higher-priority index 7e4f8f34b..e7f8c28e7 100755 --- a/test/integration/test-prefer-native-architecture-over-higher-priority +++ b/test/integration/test-prefer-native-architecture-over-higher-priority @@ -14,7 +14,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: m4 The following NEW packages will be installed: autoconf m4 diff --git a/test/integration/test-prevent-markinstall-multiarch-same-versionscrew b/test/integration/test-prevent-markinstall-multiarch-same-versionscrew index 5f67c0191..11c120c53 100755 --- a/test/integration/test-prevent-markinstall-multiarch-same-versionscrew +++ b/test/integration/test-prevent-markinstall-multiarch-same-versionscrew @@ -83,7 +83,7 @@ E: Unable to correct problems, you have held broken packages.' aptget install de testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libsame3:i386 libsame3 The following NEW packages will be installed: depender3 libsame3 diff --git a/test/integration/test-release-candidate-switching b/test/integration/test-release-candidate-switching index 510a8e078..1790e8381 100755 --- a/test/integration/test-release-candidate-switching +++ b/test/integration/test-release-candidate-switching @@ -56,7 +56,7 @@ setupaptarchive testfailureequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.1-1+sid) amarok-utils (2.3.1-1+sid) libc6 (2.11.2-7+sid) @@ -75,7 +75,7 @@ E: Trivial Only specified but this is not a trivial operation." aptget install a testfailureequal "Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -97,7 +97,7 @@ Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -119,7 +119,7 @@ Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-null' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-null' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -143,7 +143,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -173,7 +173,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-higher' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-higher' Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine' because of 'amarok-higher' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-higher' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -197,7 +197,7 @@ Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-null2' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-null2' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-null2' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -221,7 +221,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine' Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine' because of 'amarok-xine' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -245,7 +245,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine2' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine2' Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-xine2' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine2' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -270,7 +270,7 @@ Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because Selected version '5:4.6.0+exp' (experimental [i386]) for 'phonon-backend-xine3' because of 'amarok-xine3' Selected version '2.0' (experimental [all]) for 'intermediatepkg' because of 'phonon-backend-xine3' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine3' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) intermediatepkg (2.0) @@ -296,7 +296,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-xine4' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-xine4' Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-xine4' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-xine4' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -320,7 +320,7 @@ Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-broken' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-broken' Selected version '5:4.20.0+exp' (experimental [i386]) for 'phonon-backend-null' because of 'amarok-broken' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-broken' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -343,7 +343,7 @@ Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends' Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-utils' because of 'amarok-recommends' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) amarok-utils (2.3.2-2+exp) libc6 (2.11.2-7+sid) @@ -365,7 +365,7 @@ testfailureequal "Reading package lists... Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) Recommended packages: amarok-utils (2.3.1-1+sid) @@ -386,7 +386,7 @@ testfailureequal "Reading package lists... Building dependency tree... Selected version '2.3.2-2+exp' (experimental [i386]) for 'amarok-recommends2' Selected version '2.3.2-2+exp' (experimental [all]) for 'amarok-common' because of 'amarok-recommends2' -The following extra packages will be installed: +The following additional packages will be installed: amarok-common (2.3.2-2+exp) libc6 (2.11.2-7+sid) libmtp8 (0.3.1+sid) diff --git a/test/integration/test-specific-architecture-dependencies b/test/integration/test-specific-architecture-dependencies index e3dfd0c2a..f6635a4d6 100755 --- a/test/integration/test-specific-architecture-dependencies +++ b/test/integration/test-specific-architecture-dependencies @@ -35,7 +35,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6:i386 The following NEW packages will be installed: libc6:i386 pre-depender @@ -47,7 +47,7 @@ Conf pre-depender (1 unstable [all])' aptget install pre-depender -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6:i386 The following NEW packages will be installed: depender libc6:i386 @@ -59,7 +59,7 @@ Conf depender (1 unstable [all])' aptget install depender -s testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6:i386 The following NEW packages will be installed: depender-x32:i386 libc6:i386 @@ -71,7 +71,7 @@ Conf depender-x32:i386 (1 unstable [i386])' aptget install depender-x32:i386 -s testequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6:i386 The following NEW packages will be installed: depender-x32 libc6:i386 @@ -83,7 +83,7 @@ Conf depender-x32 (1 unstable [amd64])' aptget install depender-x32:amd64 -s testequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6 The following NEW packages will be installed: depender-x64 libc6 @@ -95,7 +95,7 @@ Conf depender-x64 (1 unstable [amd64])' aptget install depender-x64:amd64 -s testequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6 The following NEW packages will be installed: depender-x64:i386 libc6 @@ -267,7 +267,7 @@ configarchitecture 'amd64' testequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libc6 The following NEW packages will be installed: depender-x64 libc6 diff --git a/test/integration/test-ubuntu-bug-1130419-prefer-installed-ma-same-siblings b/test/integration/test-ubuntu-bug-1130419-prefer-installed-ma-same-siblings index 192ed5efc..2fc67096e 100755 --- a/test/integration/test-ubuntu-bug-1130419-prefer-installed-ma-same-siblings +++ b/test/integration/test-ubuntu-bug-1130419-prefer-installed-ma-same-siblings @@ -22,7 +22,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa:i386 The following NEW packages will be installed: libmesa:i386 steam:i386 @@ -33,7 +33,7 @@ Conf libmesa:i386 (1 stable [i386]) Conf steam:i386 (1 stable [i386])' aptget install steam -st stable testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa:i386 The following NEW packages will be installed: libmesa:i386 steam:i386 @@ -47,7 +47,7 @@ cp rootdir/var/lib/dpkg/status default-status.dpkg insertinstalledpackage 'libmesa' 'amd64' '1' 'Multi-Arch: same' testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa:i386 The following NEW packages will be installed: libmesa:i386 steam:i386 @@ -58,7 +58,7 @@ Conf libmesa:i386 (1 stable [i386]) Conf steam:i386 (1 stable [i386])' aptget install steam -st stable testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa libmesa:i386 The following NEW packages will be installed: libmesa:i386 steam:i386 @@ -78,7 +78,7 @@ Conflicts: libmesa Multi-Arch: same' testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa-lts:i386 The following NEW packages will be installed: libmesa-lts:i386 steam:i386 @@ -89,7 +89,7 @@ Conf libmesa-lts:i386 (1 stable [i386]) Conf steam:i386 (1 stable [i386])' aptget install steam -st stable testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libmesa-lts libmesa-lts:i386 The following NEW packages will be installed: libmesa-lts:i386 steam:i386 diff --git a/test/integration/test-ubuntu-bug-614993 b/test/integration/test-ubuntu-bug-614993 index 7067713e8..6e0a53025 100755 --- a/test/integration/test-ubuntu-bug-614993 +++ b/test/integration/test-ubuntu-bug-614993 @@ -10,7 +10,7 @@ setupaptarchive # test success UPGRADE="Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: libdrm-intel1 libdrm-nouveau1 libmtdev1 libutouch-grail1 libx11-xcb1 libxcb-aux0 libxcb-dri2-0 libxfont1 xserver-common xserver-xorg-core xserver-xorg-input-evdev xserver-xorg-input-mouse diff --git a/test/integration/test-ubuntu-bug-806274-install-suggests b/test/integration/test-ubuntu-bug-806274-install-suggests index 3f02316f4..2d1cfcd9f 100755 --- a/test/integration/test-ubuntu-bug-806274-install-suggests +++ b/test/integration/test-ubuntu-bug-806274-install-suggests @@ -17,7 +17,7 @@ setupaptarchive testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar foo Suggested packages: baz @@ -34,7 +34,7 @@ Conf bar (1.0 unstable [i386])' aptget install apt -s --install-recommends --no- testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: bar baz foo The following NEW packages will be installed: apt bar baz foo @@ -50,7 +50,7 @@ Conf baz (1.0 unstable [i386])' aptget install apt -s --install-recommends --ins testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: foo Suggested packages: baz @@ -66,7 +66,7 @@ Conf apt (0.8.15 unstable [i386])' aptget install apt -s --no-install-recommends testsuccessequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: baz foo Recommended packages: bar diff --git a/test/integration/test-ubuntu-bug-835625-multiarch-lockstep-installed-first b/test/integration/test-ubuntu-bug-835625-multiarch-lockstep-installed-first index 269038d0f..9eab1cbfd 100755 --- a/test/integration/test-ubuntu-bug-835625-multiarch-lockstep-installed-first +++ b/test/integration/test-ubuntu-bug-835625-multiarch-lockstep-installed-first @@ -16,7 +16,7 @@ setupaptarchive testequalor2 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: apt:i386 libsame:i386 The following NEW packages will be installed: libsame @@ -30,7 +30,7 @@ Conf libsame (2 unstable [amd64]) [apt:i386 ] Inst apt:i386 [1] (2 unstable [i386]) Conf apt:i386 (2 unstable [i386])' 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: apt:i386 libsame:i386 The following NEW packages will be installed: libsame diff --git a/test/integration/test-unpack-different-version-unpacked b/test/integration/test-unpack-different-version-unpacked index ae121cf4e..cdc187d15 100755 --- a/test/integration/test-unpack-different-version-unpacked +++ b/test/integration/test-unpack-different-version-unpacked @@ -32,7 +32,7 @@ insertinstalledpackage 'libqtcore4' 'i386' '1' 'Multi-Arch: same' '' 'install ok testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4:i386 The following packages will be upgraded: libqtcore4:i386 @@ -48,7 +48,7 @@ insertinstalledpackage 'libqtcore4' 'amd64' '1' 'Multi-Arch: same' '' 'install o testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4 The following packages will be upgraded: libqtcore4 @@ -64,7 +64,7 @@ insertinstalledpackage 'libqtcore4' 'i386' '1' 'Multi-Arch: same' testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4:i386 The following packages will be upgraded: libqtcore4:i386 @@ -80,7 +80,7 @@ insertinstalledpackage 'libqtcore4' 'amd64' '1' 'Multi-Arch: same' testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4 The following packages will be upgraded: libqtcore4 @@ -96,7 +96,7 @@ insertinstalledpackage 'libqtcore4' 'i386' '1' 'Multi-Arch: same' '' 'install ok testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4:i386 The following packages will be upgraded: libqtcore4:i386 @@ -111,7 +111,7 @@ insertinstalledpackage 'libqtcore4' 'amd64' '1' 'Multi-Arch: same' '' 'install o testsuccessequal 'Reading package lists... Building dependency tree... Correcting dependencies... Done -The following extra packages will be installed: +The following additional packages will be installed: libqtcore4 The following packages will be upgraded: libqtcore4 diff --git a/test/integration/test-xorg-break-providers b/test/integration/test-xorg-break-providers index ff1f3b077..57fd0e234 100755 --- a/test/integration/test-xorg-break-providers +++ b/test/integration/test-xorg-break-providers @@ -15,7 +15,7 @@ setupaptarchive testfailureequal 'Reading package lists... Building dependency tree... -The following extra packages will be installed: +The following additional packages will be installed: xserver-xorg-video-intel The following packages will be upgraded: xserver-xorg-core xserver-xorg-video-intel -- cgit v1.2.3-70-g09d2 From 858f91bb796e68b8133574cc85649b9af87a9e8b Mon Sep 17 00:00:00 2001 From: Julian Andres Klode Date: Mon, 17 Aug 2015 18:58:34 +0200 Subject: Fix the test suite harder Gbp-Dch: ignore --- test/integration/test-bug-611729-mark-as-manual | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/integration/test-bug-611729-mark-as-manual b/test/integration/test-bug-611729-mark-as-manual index a7bde393b..31856b2c1 100755 --- a/test/integration/test-bug-611729-mark-as-manual +++ b/test/integration/test-bug-611729-mark-as-manual @@ -37,14 +37,14 @@ testmarkedauto 'b' testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -b is already the newest version. +b is already the newest version (1.0). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget install b --only-upgrade testmarkedauto 'b' testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -b is already the newest version. +b is already the newest version (1.0). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget install b -d testmarkedauto 'b' @@ -62,7 +62,7 @@ Reinstall: b:i386 (1.0)' testsuccessequal 'Reading package lists... Building dependency tree... Reading state information... -b is already the newest version. +b is already the newest version (1.0). b set to manually installed. 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.' aptget install b testmarkedauto -- cgit v1.2.3-70-g09d2