diff options
Diffstat (limited to 'apt-pkg')
-rw-r--r-- | apt-pkg/acquire-item.cc | 1 | ||||
-rw-r--r-- | apt-pkg/acquire-item.h | 2 | ||||
-rw-r--r-- | apt-pkg/cacheset.h | 2 | ||||
-rw-r--r-- | apt-pkg/contrib/fileutl.cc | 6 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 11 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 8 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.h | 3 | ||||
-rw-r--r-- | apt-pkg/deb/debsrcrecords.cc | 8 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 3 | ||||
-rw-r--r-- | apt-pkg/depcache.cc | 4 | ||||
-rw-r--r-- | apt-pkg/edsp.cc | 69 | ||||
-rw-r--r-- | apt-pkg/edsp.h | 6 | ||||
-rw-r--r-- | apt-pkg/packagemanager.cc | 354 | ||||
-rw-r--r-- | apt-pkg/packagemanager.h | 19 | ||||
-rw-r--r-- | apt-pkg/pkgcache.cc | 12 | ||||
-rw-r--r-- | apt-pkg/pkgcache.h | 6 | ||||
-rw-r--r-- | apt-pkg/pkgcachegen.cc | 8 | ||||
-rw-r--r-- | apt-pkg/pkgrecords.cc | 2 | ||||
-rw-r--r-- | apt-pkg/srcrecords.cc | 37 | ||||
-rw-r--r-- | apt-pkg/srcrecords.h | 9 |
21 files changed, 317 insertions, 255 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc index e111ed4ca..e45308557 100644 --- a/apt-pkg/acquire-item.cc +++ b/apt-pkg/acquire-item.cc @@ -1654,7 +1654,6 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify) /*{{{*/ // at this point the real Items are loaded in the fetcher ExpectedAdditionalItems = 0; - for (vector <IndexTarget*>::const_iterator Target = IndexTargets->begin(); Target != IndexTargets->end(); ++Target) diff --git a/apt-pkg/acquire-item.h b/apt-pkg/acquire-item.h index cda92e84f..b4cac2f04 100644 --- a/apt-pkg/acquire-item.h +++ b/apt-pkg/acquire-item.h @@ -748,7 +748,7 @@ class pkgAcqIndex : public pkgAcqBaseIndex std::string ShortDesc, HashStringList const &ExpectedHashes, std::string compressExt=""); pkgAcqIndex(pkgAcquire *Owner, - struct IndexTarget const * const Target, + IndexTarget const * const Target, HashStringList const &ExpectedHash, indexRecords *MetaIndexParser); void Init(std::string const &URI, std::string const &URIDesc, diff --git a/apt-pkg/cacheset.h b/apt-pkg/cacheset.h index 16a3daa42..dde4e221e 100644 --- a/apt-pkg/cacheset.h +++ b/apt-pkg/cacheset.h @@ -584,7 +584,7 @@ public: /*{{{*/ static VersionContainer FromString(pkgCacheFile &Cache, std::string const &pkg, Version const &fallback, CacheSetHelper &helper, - bool const onlyFromName = false) { + bool const /*onlyFromName = false*/) { VersionContainer vercon; VersionContainerInterface::FromString(&vercon, Cache, pkg, fallback, helper); return vercon; diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc index 02b30dc1f..29450ada0 100644 --- a/apt-pkg/contrib/fileutl.cc +++ b/apt-pkg/contrib/fileutl.cc @@ -1278,7 +1278,8 @@ bool FileFd::OpenInternDescriptor(unsigned int const Mode, APT::Configuration::C if (d->lzma == NULL) d->lzma = new FileFdPrivate::LZMAFILE; d->lzma->file = (FILE*) compress_struct; - d->lzma->stream = LZMA_STREAM_INIT; + lzma_stream tmp_stream = LZMA_STREAM_INIT; + d->lzma->stream = tmp_stream; if ((Mode & ReadWrite) == ReadWrite) return FileFdError("ReadWrite mode is not supported for file %s", FileName.c_str()); @@ -1834,7 +1835,8 @@ static bool StatFileFd(char const * const msg, int const iFd, std::string const // higher-level code will generate more meaningful messages, // even translated this would be meaningless for users return _error->Errno("fstat", "Unable to determine %s for fd %i", msg, iFd); - ispipe = S_ISFIFO(Buf.st_mode); + if (FileName.empty() == false) + ispipe = S_ISFIFO(Buf.st_mode); } // for compressor pipes st_size is undefined and at 'best' zero diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 7cb8e3b68..3bdc551b4 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -526,7 +526,7 @@ bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const if (FileExists(TranslationFile)) { FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); - debListParser TransParser(&Trans); + debTranslationsParser TransParser(&Trans); if (_error->PendingError() == true) return false; diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index 5a2282f9c..56a83b36e 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -115,4 +115,15 @@ class debDebFileParser : public debListParser pkgCache::VerIterator &Ver); }; +class debTranslationsParser : public debListParser +{ + public: + // a translation can never be a real package + virtual std::string Architecture() { return ""; } + virtual std::string Version() { return ""; } + + debTranslationsParser(FileFd *File, std::string const &Arch = "") + : debListParser(File, Arch) {}; +}; + #endif diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 607dae882..73010e867 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -186,8 +186,8 @@ debReleaseIndex::~debReleaseIndex() { delete *S; } -vector <struct IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const { - vector <struct IndexTarget *>* IndexTargets = new vector <IndexTarget *>; +vector <IndexTarget *>* debReleaseIndex::ComputeIndexTargets() const { + vector <IndexTarget *>* IndexTargets = new vector <IndexTarget *>; map<string, vector<debSectionEntry const*> >::const_iterator const src = ArchEntries.find("source"); if (src != ArchEntries.end()) { @@ -255,8 +255,8 @@ bool debReleaseIndex::GetIndexes(pkgAcquire *Owner, bool const &GetAll) const // special case for --print-uris if (GetAll) { - vector <struct IndexTarget *> *targets = ComputeIndexTargets(); - for (vector <struct IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) { + vector <IndexTarget *> *targets = ComputeIndexTargets(); + for (vector <IndexTarget*>::const_iterator Target = targets->begin(); Target != targets->end(); ++Target) { new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description, (*Target)->ShortDesc, HashStringList()); } diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h index 0e70bba87..7091c198f 100644 --- a/apt-pkg/deb/debmetaindex.h +++ b/apt-pkg/deb/debmetaindex.h @@ -19,6 +19,7 @@ class pkgAcquire; class pkgIndexFile; class debDebPkgFileIndex; +class IndexTarget; class debReleaseIndex : public metaIndex { public: @@ -45,7 +46,7 @@ class 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 <struct IndexTarget *>* ComputeIndexTargets() const; + std::vector <IndexTarget *>* ComputeIndexTargets() const; std::string Info(const char *Type, std::string const &Section, std::string const &Arch="") const; std::string MetaIndexInfo(const char *Type) const; diff --git a/apt-pkg/deb/debsrcrecords.cc b/apt-pkg/deb/debsrcrecords.cc index bf5e56ec9..97f43aca2 100644 --- a/apt-pkg/deb/debsrcrecords.cc +++ b/apt-pkg/deb/debsrcrecords.cc @@ -57,12 +57,13 @@ const char **debSrcRecordParser::Binaries() char* binStartNext = strchrnul(bin, ','); char* binEnd = binStartNext - 1; for (; isspace(*binEnd) != 0; --binEnd) - binEnd = '\0'; + binEnd = 0; StaticBinList.push_back(bin); if (*binStartNext != ',') break; *binStartNext = '\0'; - for (bin = binStartNext + 1; isspace(*bin) != 0; ++bin); + for (bin = binStartNext + 1; isspace(*bin) != 0; ++bin) + ; } while (*bin != '\0'); StaticBinList.push_back(NULL); @@ -238,7 +239,8 @@ bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &List) /* */ debSrcRecordParser::~debSrcRecordParser() { - delete[] Buffer; + // was allocated via strndup() + free(Buffer); } /*}}}*/ diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 32ef343aa..76b708359 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -1438,7 +1438,8 @@ bool pkgDPkgPM::GoNoABIBreak(APT::Progress::PackageManager *progress) if (_config->FindB("DPkg::FlushSTDIN",true) == true && isatty(STDIN_FILENO)) { - int Flags,dummy; + int Flags; + int dummy = 0; if ((Flags = fcntl(STDIN_FILENO,F_GETFL,dummy)) < 0) _exit(100); diff --git a/apt-pkg/depcache.cc b/apt-pkg/depcache.cc index 19a6e0d7e..c25672d1c 100644 --- a/apt-pkg/depcache.cc +++ b/apt-pkg/depcache.cc @@ -1374,7 +1374,7 @@ bool pkgDepCache::IsInstallOkDependenciesSatisfiableByCandidates(PkgIterator con // the dependency is critical, but can't be installed, so discard the candidate // as the problemresolver will trip over it otherwise trying to install it (#735967) - if (Pkg->CurrentVer != 0) + if (Pkg->CurrentVer != 0 && (PkgState[Pkg->ID].iFlags & Protected) != Protected) SetCandidateVersion(Pkg.CurrentVer()); return false; } @@ -1678,7 +1678,7 @@ pkgCache::VerIterator pkgDepCache::Policy::GetCandidateVer(PkgIterator const &Pk { /* Not source/not automatic versions cannot be a candidate version unless they are already installed */ - VerIterator Last(*(pkgCache *)this,0); + VerIterator Last; for (VerIterator I = Pkg.VersionList(); I.end() == false; ++I) { diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc index ee42267bc..6d1b68c23 100644 --- a/apt-pkg/edsp.cc +++ b/apt-pkg/edsp.cc @@ -18,6 +18,7 @@ #include <apt-pkg/pkgcache.h> #include <apt-pkg/cacheiterators.h> #include <apt-pkg/strutl.h> +#include <apt-pkg/pkgrecords.h> #include <ctype.h> #include <stddef.h> @@ -87,7 +88,12 @@ bool EDSP::WriteLimitedScenario(pkgDepCache &Cache, FILE* output, void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) { + pkgRecords Recs(Cache); + pkgRecords::Parser &rec = Recs.Lookup(Ver.FileList()); + string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg(); + fprintf(output, "Package: %s\n", Pkg.Name()); + fprintf(output, "Source: %s\n", srcpkg.c_str()); fprintf(output, "Architecture: %s\n", Ver.Arch()); fprintf(output, "Version: %s\n", Ver.VerStr()); if (Pkg.CurrentVer() == Ver) @@ -107,10 +113,22 @@ void EDSP::WriteScenarioVersion(pkgDepCache &Cache, FILE* output, pkgCache::PkgI else if ((Ver->MultiArch & pkgCache::Version::Same) == pkgCache::Version::Same) fprintf(output, "Multi-Arch: same\n"); signed short Pin = std::numeric_limits<signed short>::min(); - for (pkgCache::VerFileIterator File = Ver.FileList(); File.end() == false; ++File) { - signed short const p = Cache.GetPolicy().GetPriority(File.File()); + std::set<string> Releases; + for (pkgCache::VerFileIterator I = Ver.FileList(); I.end() == false; ++I) { + pkgCache::PkgFileIterator File = I.File(); + signed short const p = Cache.GetPolicy().GetPriority(File); if (Pin < p) Pin = p; + if ((File->Flags & pkgCache::Flag::NotSource) != pkgCache::Flag::NotSource) { + string Release = File.RelStr(); + if (!Release.empty()) + Releases.insert(Release); + } + } + if (!Releases.empty()) { + fprintf(output, "APT-Release:\n"); + for (std::set<string>::iterator R = Releases.begin(); R != Releases.end(); ++R) + fprintf(output, " %s\n", R->c_str()); } fprintf(output, "APT-Pin: %d\n", Pin); if (Cache.GetCandidateVer(Pkg) == Ver) @@ -231,7 +249,16 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade, continue; req->append(" ").append(Pkg.FullName()); } - fprintf(output, "Request: EDSP 0.4\n"); + fprintf(output, "Request: EDSP 0.5\n"); + + const char *arch = _config->Find("APT::Architecture").c_str(); + std::vector<string> archs = APT::Configuration::getArchitectures(); + fprintf(output, "Architecture: %s\n", arch); + fprintf(output, "Architectures:"); + for (std::vector<string>::const_iterator a = archs.begin(); a != archs.end(); ++a) + fprintf(output, " %s", a->c_str()); + fprintf(output, "\n"); + if (del.empty() == false) fprintf(output, "Remove: %s\n", del.c_str()+1); if (inst.empty() == false) @@ -411,6 +438,13 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install, distUpgrade = EDSP::StringToBool(line.c_str() + 14, false); else if (line.compare(0, 11, "Autoremove:") == 0) autoRemove = EDSP::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) + { + std::string const archs = line.c_str() + 15; + _config->Set("APT::Architectures", SubstVar(archs, " ", ",")); + } else _error->Warning("Unknown line in EDSP Request stanza: %s", line.c_str()); @@ -508,7 +542,7 @@ bool EDSP::WriteError(char const * const uuid, std::string const &message, FILE* } /*}}}*/ // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/ -bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { +pid_t EDSP::ExecuteSolver(const char* const solver, int * const solver_in, int * const solver_out, bool) { std::vector<std::string> const solverDirs = _config->FindVector("Dir::Bin::Solvers"); std::string file; for (std::vector<std::string>::const_iterator dir = solverDirs.begin(); @@ -520,10 +554,16 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o } if (file.empty() == true) - return _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + { + _error->Error("Can't call external solver '%s' as it is not in a configured directory!", solver); + return 0; + } int external[4] = {-1, -1, -1, -1}; if (pipe(external) != 0 || pipe(external + 2) != 0) - return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + { + _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP"); + return 0; + } for (int i = 0; i < 4; ++i) SetCloseExec(external[i], true); @@ -540,11 +580,19 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o close(external[3]); if (WaitFd(external[1], true, 5) == false) - return _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + { + _error->Errno("Resolve", "Timed out while Waiting on availability of solver stdin"); + return 0; + } *solver_in = external[1]; *solver_out = external[2]; - return true; + return Solver; +} +bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_out) { + if (ExecuteSolver(solver, solver_in, solver_out, true) == 0) + return false; + return true; } /*}}}*/ // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/ @@ -552,7 +600,8 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, bool const upgrade, bool const distUpgrade, bool const autoRemove, OpProgress *Progress) { int solver_in, solver_out; - if (EDSP::ExecuteSolver(solver, &solver_in, &solver_out) == false) + pid_t const solver_pid = EDSP::ExecuteSolver(solver, &solver_in, &solver_out, true); + if (solver_pid == 0) return false; FILE* output = fdopen(solver_in, "w"); @@ -572,6 +621,6 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache, if (EDSP::ReadResponse(solver_out, Cache, Progress) == false) return false; - return true; + return ExecWait(solver_pid, solver); } /*}}}*/ diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h index f3092d3c6..9e833556a 100644 --- a/apt-pkg/edsp.h +++ b/apt-pkg/edsp.h @@ -205,10 +205,10 @@ public: * \param[out] solver_in will be the stdin of the solver * \param[out] solver_out will be the stdout of the solver * - * \return true if the solver could be started and the pipes - * are set up correctly, otherwise false and the pipes are invalid + * \return PID of the started solver or 0 if failure occurred */ - bool static ExecuteSolver(const char* const solver, int *solver_in, int *solver_out); + 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); /** \brief call an external resolver to handle the request * diff --git a/apt-pkg/packagemanager.cc b/apt-pkg/packagemanager.cc index 0ec9f3309..d9df28ba3 100644 --- a/apt-pkg/packagemanager.cc +++ b/apt-pkg/packagemanager.cc @@ -262,7 +262,7 @@ bool pkgPackageManager::CheckRConflicts(PkgIterator Pkg,DepIterator D, if (Cache.VS().CheckDep(Ver,D->CompareOp,D.TargetVer()) == false) continue; - if (EarlyRemove(D.ParentPkg()) == false) + if (EarlyRemove(D.ParentPkg(), &D) == false) return _error->Error("Reverse conflicts early remove for package '%s' failed", Pkg.FullName().c_str()); } @@ -314,18 +314,41 @@ bool pkgPackageManager::ConfigureAll() return true; } /*}}}*/ +// PM::NonLoopingSmart - helper to avoid loops while calling Smart methods /*{{{*/ +// ----------------------------------------------------------------------- +/* ensures that a loop of the form A depends B, B depends A (and similar) + is not leading us down into infinite recursion segfault land */ +bool pkgPackageManager::NonLoopingSmart(SmartAction const action, pkgCache::PkgIterator &Pkg, + pkgCache::PkgIterator DepPkg, int const Depth, bool const PkgLoop, + bool * const Bad, bool * const Changed) +{ + if (PkgLoop == false) + List->Flag(Pkg,pkgOrderList::Loop); + bool success = false; + switch(action) + { + case UNPACK_IMMEDIATE: success = SmartUnPack(DepPkg, true, Depth + 1); break; + case UNPACK: success = SmartUnPack(DepPkg, false, Depth + 1); break; + case CONFIGURE: success = SmartConfigure(DepPkg, Depth + 1); break; + } + if (PkgLoop == false) + List->RmFlag(Pkg,pkgOrderList::Loop); + + if (success == false) + return false; + + if (Bad != NULL) + *Bad = false; + if (Changed != NULL && List->IsFlag(DepPkg,pkgOrderList::Loop) == false) + *Changed = true; + return true; +} + /*}}}*/ // PM::SmartConfigure - Perform immediate configuration of the pkg /*{{{*/ // --------------------------------------------------------------------- /* This function tries to put the system in a state where Pkg can be configured. - This involves checking each of Pkg's dependanies and unpacking and - configuring packages where needed. - - Note on failure: This method can fail, without causing any problems. - This can happen when using Immediate-Configure-All, SmartUnPack may call - SmartConfigure, it may fail because of a complex dependency situation, but - a error will only be reported if ConfigureAll fails. This is why some of the - messages this function reports on failure (return false;) as just warnings - only shown when debuging*/ + This involves checking each of Pkg's dependencies and unpacking and + configuring packages where needed. */ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) { // If this is true, only check and correct and dependencies without the Loop flag @@ -340,9 +363,9 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) } VerIterator const instVer = Cache[Pkg].InstVerIter(Cache); - - /* Because of the ordered list, most dependencies should be unpacked, - however if there is a loop (A depends on B, B depends on A) this will not + + /* Because of the ordered list, most dependencies should be unpacked, + however if there is a loop (A depends on B, B depends on A) this will not be the case, so check for dependencies before configuring. */ bool Bad = false, Changed = false; const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000); @@ -389,25 +412,15 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (Debug) std::clog << OutputInDepth(Depth) << "Package " << Pkg << " loops in SmartConfigure" << std::endl; Bad = false; - break; } else { if (Debug) clog << OutputInDepth(Depth) << "Unpacking " << DepPkg.FullName() << " to avoid loop " << Cur << endl; - if (PkgLoop == false) - List->Flag(Pkg,pkgOrderList::Loop); - if (SmartUnPack(DepPkg, true, Depth + 1) == true) - { - Bad = false; - if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false) - Changed = true; - } - if (PkgLoop == false) - List->RmFlag(Pkg,pkgOrderList::Loop); - if (Bad == false) - break; + if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) + return false; } + break; } if (Cur == End || Bad == false) @@ -462,25 +475,12 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) Bad = false; break; } - /* Check for a loop to prevent one forming - If A depends on B and B depends on A, SmartConfigure will - just hop between them if this is not checked. Dont remove the - loop flag after finishing however as loop is already set. - This means that there is another SmartConfigure call for this - package and it will remove the loop flag */ - if (PkgLoop == false) - List->Flag(Pkg,pkgOrderList::Loop); - if (SmartConfigure(DepPkg, Depth + 1) == true) - { - Bad = false; - if (List->IsFlag(DepPkg,pkgOrderList::Loop) == false) - Changed = true; - } - if (PkgLoop == false) - List->RmFlag(Pkg,pkgOrderList::Loop); - // If SmartConfigure was succesfull, Bad is false, so break - if (Bad == false) - break; + if (Debug) + std::clog << OutputInDepth(Depth) << "Configure already unpacked " << DepPkg << std::endl; + if (NonLoopingSmart(CONFIGURE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) + return false; + break; + } else if (List->IsFlag(DepPkg,pkgOrderList::Configured)) { @@ -499,19 +499,16 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) if (i++ > max_loops) return _error->Error("Internal error: MaxLoopCount reached in SmartUnPack (2) for %s, aborting", Pkg.FullName().c_str()); } while (Changed == true); - - if (Bad) { - if (Debug) - _error->Warning(_("Could not configure '%s'. "),Pkg.FullName().c_str()); - return false; - } - + + if (Bad == true) + return _error->Error(_("Could not configure '%s'. "),Pkg.FullName().c_str()); + if (PkgLoop) return true; static std::string const conf = _config->Find("PackageManager::Configure","all"); static bool const ConfigurePkgs = (conf == "all" || conf == "smart"); - if (List->IsFlag(Pkg,pkgOrderList::Configured)) + if (List->IsFlag(Pkg,pkgOrderList::Configured)) return _error->Error("Internal configure error on '%s'.", Pkg.FullName().c_str()); if (ConfigurePkgs == true && Configure(Pkg) == false) @@ -528,7 +525,8 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) Cache[P].InstallVer == 0 || (P.CurrentVer() == Cache[P].InstallVer && (Cache[Pkg].iFlags & pkgDepCache::ReInstall) != pkgDepCache::ReInstall)) continue; - SmartConfigure(P, (Depth +1)); + if (SmartConfigure(P, (Depth +1)) == false) + return false; } // Sanity Check @@ -543,28 +541,36 @@ bool pkgPackageManager::SmartConfigure(PkgIterator Pkg, int const Depth) /* This is called to deal with conflicts arising from unpacking */ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg) { + return EarlyRemove(Pkg, NULL); +} +bool pkgPackageManager::EarlyRemove(PkgIterator Pkg, DepIterator const * const Dep) +{ if (List->IsNow(Pkg) == false) return true; - + // Already removed it if (List->IsFlag(Pkg,pkgOrderList::Removed) == true) return true; - + // Woops, it will not be re-installed! if (List->IsFlag(Pkg,pkgOrderList::InList) == false) return false; + // these breaks on M-A:same packages can be dealt with. They 'loop' by design + if (Dep != NULL && (*Dep)->Type == pkgCache::Dep::DpkgBreaks && Dep->IsMultiArchImplicit() == true) + return true; + // Essential packages get special treatment bool IsEssential = false; if ((Pkg->Flags & pkgCache::Flag::Essential) != 0 || (Pkg->Flags & pkgCache::Flag::Important) != 0) IsEssential = true; - /* Check for packages that are the dependents of essential packages and + /* Check for packages that are the dependents of essential packages and promote them too */ if (Pkg->CurrentVer != 0) { - for (DepIterator D = Pkg.RevDependsList(); D.end() == false && + for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() == false && IsEssential == false; ++D) if (D->Type == pkgCache::Dep::Depends || D->Type == pkgCache::Dep::PreDepends) if ((D.ParentPkg()->Flags & pkgCache::Flag::Essential) != 0 || @@ -581,11 +587,14 @@ bool pkgPackageManager::EarlyRemove(PkgIterator Pkg) "but if you really want to do it, activate the " "APT::Force-LoopBreak option."),Pkg.FullName().c_str()); } - + // dpkg will auto-deconfigure it, no need for the big remove hammer + else if (Dep != NULL && (*Dep)->Type == pkgCache::Dep::DpkgBreaks) + return true; + bool Res = SmartRemove(Pkg); if (Cache[Pkg].Delete() == false) List->Flag(Pkg,pkgOrderList::Removed,pkgOrderList::States); - + return Res; } /*}}}*/ @@ -630,13 +639,14 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c VerIterator const instVer = Cache[Pkg].InstVerIter(Cache); - /* PreUnpack Checks: This loop checks and attempts to rectify and problems that would prevent the package being unpacked. + /* PreUnpack Checks: This loop checks and attempts to rectify any problems that would prevent the package being unpacked. It addresses: PreDepends, Conflicts, Obsoletes and Breaks (DpkgBreaks). Any resolutions that do not require it should avoid configuration (calling SmartUnpack with Immediate=true), this is because when unpacking some packages with - complex dependency structures, trying to configure some packages while breaking the loops can complicate things . + complex dependency structures, trying to configure some packages while breaking the loops can complicate things. This will be either dealt with if the package is configured as a dependency of Pkg (if and when Pkg is configured), or by the ConfigureAll call at the end of the for loop in OrderInstall. */ - bool Changed = false; + bool SomethingBad = false, Changed = false; + bool couldBeTemporaryRemoved = Depth != 0 && List->IsFlag(Pkg,pkgOrderList::Removed) == false; const unsigned int max_loops = _config->FindI("APT::pkgPackageManager::MaxLoopCount", 5000); unsigned int i = 0; do @@ -684,184 +694,142 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c for (Version **I = VList; *I != 0; ++I) { VerIterator Ver(Cache,*I); - PkgIterator Pkg = Ver.ParentPkg(); + PkgIterator DepPkg = Ver.ParentPkg(); // Not the install version - if (Cache[Pkg].InstallVer != *I || - (Cache[Pkg].Keep() == true && Pkg.State() == PkgIterator::NeedsNothing)) + if (Cache[DepPkg].InstallVer != *I || + (Cache[DepPkg].Keep() == true && DepPkg.State() == PkgIterator::NeedsNothing)) continue; - if (List->IsFlag(Pkg,pkgOrderList::Configured)) + if (List->IsFlag(DepPkg,pkgOrderList::Configured)) { Bad = false; break; } // check if it needs unpack or if if configure is enough - if (List->IsFlag(Pkg,pkgOrderList::UnPacked) == false) + if (List->IsFlag(DepPkg,pkgOrderList::UnPacked) == false) { if (Debug) - clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << Pkg.FullName() << endl; - // SmartUnpack with the ImmediateFlag to ensure its really ready - if (SmartUnPack(Pkg, true, Depth + 1) == true) - { - Bad = false; - if (List->IsFlag(Pkg,pkgOrderList::Loop) == false) - Changed = true; - break; - } + clog << OutputInDepth(Depth) << "Trying to SmartUnpack " << DepPkg.FullName() << endl; + if (NonLoopingSmart(UNPACK_IMMEDIATE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) + return false; } else { if (Debug) - clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << Pkg.FullName() << endl; - if (SmartConfigure(Pkg, Depth + 1) == true) - { - Bad = false; - if (List->IsFlag(Pkg,pkgOrderList::Loop) == false) - Changed = true; - break; - } + clog << OutputInDepth(Depth) << "Trying to SmartConfigure " << DepPkg.FullName() << endl; + if (NonLoopingSmart(CONFIGURE, Pkg, DepPkg, Depth, PkgLoop, &Bad, &Changed) == false) + return false; } + break; } } if (Bad == true) - { - if (Start == End) - return _error->Error("Couldn't configure pre-depend %s for %s, " - "probably a dependency cycle.", - End.TargetPkg().FullName().c_str(),Pkg.FullName().c_str()); - } - else - continue; + SomethingBad = true; } else if (End->Type == pkgCache::Dep::Conflicts || - End->Type == pkgCache::Dep::Obsoletes) + End->Type == pkgCache::Dep::Obsoletes || + End->Type == pkgCache::Dep::DpkgBreaks) { - /* Look for conflicts. Two packages that are both in the install - state cannot conflict so we don't check.. */ SPtrArray<Version *> VList = End.AllTargets(); - for (Version **I = VList; *I != 0; I++) + for (Version **I = VList; *I != 0; ++I) { VerIterator Ver(Cache,*I); PkgIterator ConflictPkg = Ver.ParentPkg(); - VerIterator InstallVer(Cache,Cache[ConflictPkg].InstallVer); + if (ConflictPkg.CurrentVer() != Ver) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Ignore not-installed version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl; + continue; + } - // See if the current version is conflicting - if (ConflictPkg.CurrentVer() == Ver && List->IsNow(ConflictPkg)) + if (List->IsNow(ConflictPkg) == false) { if (Debug) - clog << OutputInDepth(Depth) << Pkg.FullName() << " conflicts with " << ConflictPkg.FullName() << endl; - /* If a loop is not present or has not yet been detected, attempt to unpack packages - to resolve this conflict. If there is a loop present, remove packages to resolve this conflict */ - if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false) - { - if (Cache[ConflictPkg].Keep() == 0 && Cache[ConflictPkg].InstallVer != 0) - { - if (Debug) - clog << OutputInDepth(Depth) << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to prevent conflict" << endl; - List->Flag(Pkg,pkgOrderList::Loop); - if (SmartUnPack(ConflictPkg,false, Depth + 1) == true) - if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) == false) - Changed = true; - // Remove loop to allow it to be used later if needed - List->RmFlag(Pkg,pkgOrderList::Loop); - } - else if (EarlyRemove(ConflictPkg) == false) - return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str()); - } - else if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == false) + std::clog << OutputInDepth(Depth) << "Ignore already dealt-with version " << Ver.VerStr() << " of " << ConflictPkg.FullName() << " for " << End << std::endl; + continue; + } + + if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true) + { + if (Debug) + clog << OutputInDepth(Depth) << "Ignoring " << End << " as " << ConflictPkg.FullName() << "was temporarily removed" << endl; + continue; + } + + if (List->IsFlag(ConflictPkg,pkgOrderList::Loop) && PkgLoop) + { + if (End->Type == pkgCache::Dep::DpkgBreaks && End.IsMultiArchImplicit() == true) { if (Debug) - clog << OutputInDepth(Depth) << "Because of conficts knot, removing " << ConflictPkg.FullName() << " to conflict violation" << endl; - if (EarlyRemove(ConflictPkg) == false) - return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str()); + clog << OutputInDepth(Depth) << "Because dependency is MultiArchImplicit we ignored looping on: " << ConflictPkg << endl; + continue; } - } - } - } - else if (End->Type == pkgCache::Dep::DpkgBreaks) - { - SPtrArray<Version *> VList = End.AllTargets(); - for (Version **I = VList; *I != 0; ++I) - { - VerIterator Ver(Cache,*I); - PkgIterator BrokenPkg = Ver.ParentPkg(); - if (BrokenPkg.CurrentVer() != Ver) - { if (Debug) - std::clog << OutputInDepth(Depth) << " Ignore not-installed version " << Ver.VerStr() << " of " << Pkg.FullName() << " for " << End << std::endl; + { + if (End->Type == pkgCache::Dep::DpkgBreaks) + clog << OutputInDepth(Depth) << "Because of breaks knot, deconfigure " << ConflictPkg.FullName() << " temporarily" << endl; + else + clog << OutputInDepth(Depth) << "Because of conflict knot, removing " << ConflictPkg.FullName() << " temporarily" << endl; + } + if (EarlyRemove(ConflictPkg, &End) == false) + return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str()); + SomethingBad = true; continue; } - // Check if it needs to be unpacked - if (List->IsFlag(BrokenPkg,pkgOrderList::InList) && Cache[BrokenPkg].Delete() == false && - List->IsNow(BrokenPkg)) + if (Cache[ConflictPkg].Delete() == false) { - if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) && PkgLoop) + if (Debug) { - // This dependency has already been dealt with by another SmartUnPack on Pkg - break; + clog << OutputInDepth(Depth) << "Unpacking " << ConflictPkg.FullName() << " to avoid " << End; + if (PkgLoop == true) + clog << " (Looping)"; + clog << std::endl; } - else + // we would like to avoid temporary removals and all that at best via a simple unpack + _error->PushToStack(); + if (NonLoopingSmart(UNPACK, Pkg, ConflictPkg, Depth, PkgLoop, NULL, &Changed) == false) { - // Found a break, so see if we can unpack the package to avoid it - // but do not set loop if another SmartUnPack already deals with it - // Also, avoid it if the package we would unpack pre-depends on this one - VerIterator InstallVer(Cache,Cache[BrokenPkg].InstallVer); - bool circle = false; - for (pkgCache::DepIterator D = InstallVer.DependsList(); D.end() == false; ++D) + // but if it fails ignore this failure and look for alternative ways of solving + if (Debug) + { + clog << OutputInDepth(Depth) << "Avoidance unpack of " << ConflictPkg.FullName() << " failed for " << End << std::endl; + _error->DumpErrors(std::clog); + } + _error->RevertToStack(); + // ignorance can only happen if a) one of the offenders is already gone + if (List->IsFlag(ConflictPkg,pkgOrderList::Removed) == true) { - if (D->Type != pkgCache::Dep::PreDepends) - continue; - SPtrArray<Version *> VL = D.AllTargets(); - for (Version **I = VL; *I != 0; ++I) - { - VerIterator V(Cache,*I); - PkgIterator P = V.ParentPkg(); - // we are checking for installation as an easy 'protection' against or-groups and (unchosen) providers - if (P != Pkg || (P.CurrentVer() != V && Cache[P].InstallVer != V)) - continue; - circle = true; - break; - } - if (circle == true) - break; + if (Debug) + clog << OutputInDepth(Depth) << "But " << ConflictPkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl; } - if (circle == true) + else if (List->IsFlag(Pkg,pkgOrderList::Removed) == true) { if (Debug) - clog << OutputInDepth(Depth) << " Avoiding " << End << " avoided as " << BrokenPkg.FullName() << " has a pre-depends on " << Pkg.FullName() << std::endl; - continue; + clog << OutputInDepth(Depth) << "But " << Pkg.FullName() << " was temporarily removed in the meantime to satisfy " << End << endl; } + // or b) we can make one go (removal or dpkg auto-deconfigure) else { if (Debug) - { - clog << OutputInDepth(Depth) << " Unpacking " << BrokenPkg.FullName() << " to avoid " << End; - if (PkgLoop == true) - clog << " (Looping)"; - clog << std::endl; - } - if (PkgLoop == false) - List->Flag(Pkg,pkgOrderList::Loop); - if (SmartUnPack(BrokenPkg, false, Depth + 1) == true) - { - if (List->IsFlag(BrokenPkg,pkgOrderList::Loop) == false) - Changed = true; - } - if (PkgLoop == false) - List->RmFlag(Pkg,pkgOrderList::Loop); + clog << OutputInDepth(Depth) << "So temprorary remove/deconfigure " << ConflictPkg.FullName() << " to satisfy " << End << endl; + if (EarlyRemove(ConflictPkg, &End) == false) + return _error->Error("Internal Error, Could not early remove %s (2)",ConflictPkg.FullName().c_str()); } } + else + _error->MergeWithStack(); } - // Check if a package needs to be removed - else if (Cache[BrokenPkg].Delete() == true && List->IsFlag(BrokenPkg,pkgOrderList::Configured) == false) + else { if (Debug) - clog << OutputInDepth(Depth) << " Removing " << BrokenPkg.FullName() << " to avoid " << End << endl; - SmartRemove(BrokenPkg); + clog << OutputInDepth(Depth) << "Removing " << ConflictPkg.FullName() << " now to avoid " << End << endl; + // no earlyremove() here as user has already agreed to the permanent removal + if (SmartRemove(Pkg) == false) + return _error->Error("Internal Error, Could not early remove %s (1)",ConflictPkg.FullName().c_str()); } } } @@ -869,7 +837,17 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c if (i++ > max_loops) return _error->Error("Internal error: APT::pkgPackageManager::MaxLoopCount reached in SmartConfigure for %s, aborting", Pkg.FullName().c_str()); } while (Changed == true); - + + if (SomethingBad == true) + return _error->Error("Couldn't configure %s, probably a dependency cycle.", Pkg.FullName().c_str()); + + if (couldBeTemporaryRemoved == true && List->IsFlag(Pkg,pkgOrderList::Removed) == true) + { + if (Debug) + std::clog << OutputInDepth(Depth) << "Prevent unpack as " << Pkg << " is currently temporarily removed" << std::endl; + return true; + } + // Check for reverse conflicts. if (CheckRConflicts(Pkg,Pkg.RevDependsList(), instVer.VerStr()) == false) @@ -930,7 +908,7 @@ bool pkgPackageManager::SmartUnPack(PkgIterator Pkg, bool const Immediate, int c if (Immediate == true) { // Perform immedate configuration of the package. if (SmartConfigure(Pkg, Depth + 1) == false) - _error->Warning(_("Could not perform immediate configuration on '%s'. " + _error->Error(_("Could not perform immediate configuration on '%s'. " "Please see man 5 apt.conf under APT::Immediate-Configure for details. (%d)"),Pkg.FullName().c_str(),2); } diff --git a/apt-pkg/packagemanager.h b/apt-pkg/packagemanager.h index 8a51a455c..558132ceb 100644 --- a/apt-pkg/packagemanager.h +++ b/apt-pkg/packagemanager.h @@ -84,13 +84,14 @@ class pkgPackageManager : protected pkgCache::Namespace // Install helpers bool ConfigureAll(); - bool SmartConfigure(PkgIterator Pkg, int const Depth); + bool SmartConfigure(PkgIterator Pkg, int const Depth) APT_MUSTCHECK; //FIXME: merge on abi break - bool SmartUnPack(PkgIterator Pkg); - bool SmartUnPack(PkgIterator Pkg, bool const Immediate, int const Depth); - bool SmartRemove(PkgIterator Pkg); - bool EarlyRemove(PkgIterator Pkg); - + bool SmartUnPack(PkgIterator Pkg) APT_MUSTCHECK; + bool SmartUnPack(PkgIterator Pkg, bool const Immediate, int const Depth) APT_MUSTCHECK; + bool SmartRemove(PkgIterator Pkg) APT_MUSTCHECK; + bool EarlyRemove(PkgIterator Pkg, DepIterator const * const Dep) APT_MUSTCHECK; + APT_DEPRECATED bool EarlyRemove(PkgIterator Pkg) APT_MUSTCHECK; + // The Actual installation implementation virtual bool Install(PkgIterator /*Pkg*/,std::string /*File*/) {return false;}; virtual bool Configure(PkgIterator /*Pkg*/) {return false;}; @@ -144,6 +145,12 @@ class pkgPackageManager : protected pkgCache::Namespace pkgPackageManager(pkgDepCache *Cache); virtual ~pkgPackageManager(); + + private: + 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, + bool * const Bad, bool * const Changed) APT_MUSTCHECK; }; #endif diff --git a/apt-pkg/pkgcache.cc b/apt-pkg/pkgcache.cc index 2b6153634..4fbdc93d5 100644 --- a/apt-pkg/pkgcache.cc +++ b/apt-pkg/pkgcache.cc @@ -55,11 +55,7 @@ pkgCache::Header::Header() /* Whenever the structures change the major version should be bumped, whenever the generator changes the minor version should be bumped. */ MajorVersion = 9; -#if (APT_PKG_MAJOR >= 4 && APT_PKG_MINOR >= 13) MinorVersion = 2; -#else - MinorVersion = 1; -#endif Dirty = false; HeaderSz = sizeof(pkgCache::Header); @@ -218,7 +214,7 @@ pkgCache::PkgIterator pkgCache::SingleArchFindPkg(const string &Name) { // Look at the hash bucket Package *Pkg = PkgP + HeaderP->PkgHashTable[Hash(Name)]; - for (; Pkg != PkgP; Pkg = PkgP + Pkg->NextPackage) + for (; Pkg != PkgP; Pkg = PkgP + Pkg->Next) { if (unlikely(Pkg->Name == 0)) continue; @@ -374,7 +370,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::FindPkg(string Arch) const { (= different packages with same calculated hash), so we need to check the name also */ for (pkgCache::Package *Pkg = PackageList(); Pkg != Owner->PkgP; - Pkg = Owner->PkgP + Pkg->NextPackage) { + Pkg = Owner->PkgP + Pkg->Next) { if (S->Name == Pkg->Name && stringcasecmp(Arch, Owner->StrP + Pkg->Arch) == 0) return PkgIterator(*Owner, Pkg); @@ -423,7 +419,7 @@ pkgCache::PkgIterator pkgCache::GrpIterator::NextPkg(pkgCache::PkgIterator const if (S->LastPackage == LastPkg.Index()) return PkgIterator(*Owner, 0); - return PkgIterator(*Owner, Owner->PkgP + LastPkg->NextPackage); + return PkgIterator(*Owner, Owner->PkgP + LastPkg->Next); } /*}}}*/ // GrpIterator::operator ++ - Postfix incr /*{{{*/ @@ -450,7 +446,7 @@ void pkgCache::PkgIterator::operator ++(int) { // Follow the current links if (S != Owner->PkgP) - S = Owner->PkgP + S->NextPackage; + S = Owner->PkgP + S->Next; // Follow the hash table while (S == Owner->PkgP && (HashIndex+1) < (signed)_count(Owner->HeaderP->PkgHashTable)) diff --git a/apt-pkg/pkgcache.h b/apt-pkg/pkgcache.h index 22dc6218c..55f0187f9 100644 --- a/apt-pkg/pkgcache.h +++ b/apt-pkg/pkgcache.h @@ -316,8 +316,8 @@ struct pkgCache::Header these packages are stored as a sequence in the list. Beware: The Hashmethod assumes that the hash table sizes are equal */ - map_ptrloc PkgHashTable[2*1048]; - map_ptrloc GrpHashTable[2*1048]; + map_ptrloc PkgHashTable[64*1048]; + map_ptrloc GrpHashTable[64*1048]; /** \brief Size of the complete cache file */ unsigned long CacheFileSize; @@ -390,7 +390,7 @@ struct pkgCache::Package // Linked list /** \brief Link to the next package in the same bucket */ - map_ptrloc NextPackage; // Package + map_ptrloc Next; // Package /** \brief List of all dependencies on this package */ map_ptrloc RevDepends; // Dependency /** \brief List of all "packages" this package provide */ diff --git a/apt-pkg/pkgcachegen.cc b/apt-pkg/pkgcachegen.cc index ac1cea0eb..9615b4c22 100644 --- a/apt-pkg/pkgcachegen.cc +++ b/apt-pkg/pkgcachegen.cc @@ -656,16 +656,16 @@ bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,const string &Name unsigned long const Hash = Cache.Hash(Name); map_ptrloc *insertAt = &Cache.HeaderP->PkgHashTable[Hash]; while (*insertAt != 0 && strcasecmp(Name.c_str(), Cache.StrP + (Cache.PkgP + *insertAt)->Name) > 0) - insertAt = &(Cache.PkgP + *insertAt)->NextPackage; - Pkg->NextPackage = *insertAt; + insertAt = &(Cache.PkgP + *insertAt)->Next; + Pkg->Next = *insertAt; *insertAt = Package; } else // Group the Packages together { // this package is the new last package pkgCache::PkgIterator LastPkg(Cache, Cache.PkgP + Grp->LastPackage); - Pkg->NextPackage = LastPkg->NextPackage; - LastPkg->NextPackage = Package; + Pkg->Next = LastPkg->Next; + LastPkg->Next = Package; } Grp->LastPackage = Package; diff --git a/apt-pkg/pkgrecords.cc b/apt-pkg/pkgrecords.cc index c403e4dc3..859af3a09 100644 --- a/apt-pkg/pkgrecords.cc +++ b/apt-pkg/pkgrecords.cc @@ -26,7 +26,7 @@ // Records::pkgRecords - Constructor /*{{{*/ // --------------------------------------------------------------------- /* This will create the necessary structures to access the status files */ -pkgRecords::pkgRecords(pkgCache &Cache) : d(NULL), Cache(Cache), +pkgRecords::pkgRecords(pkgCache &aCache) : d(NULL), Cache(aCache), Files(Cache.HeaderP->PackageFileCount) { for (pkgCache::PkgFileIterator I = Cache.FileBegin(); diff --git a/apt-pkg/srcrecords.cc b/apt-pkg/srcrecords.cc index 775cf2e5f..81b1c545d 100644 --- a/apt-pkg/srcrecords.cc +++ b/apt-pkg/srcrecords.cc @@ -81,6 +81,27 @@ bool pkgSrcRecords::Restart() return true; } /*}}}*/ +// SrcRecords::Step - Step to the next Source Record /*{{{*/ +// --------------------------------------------------------------------- +/* Step to the next source package record */ +const pkgSrcRecords::Parser* pkgSrcRecords::Step() +{ + if (Current == Files.end()) + return 0; + + // Step to the next record, possibly switching files + while ((*Current)->Step() == false) + { + if (_error->PendingError() == true) + return 0; + ++Current; + if (Current == Files.end()) + return 0; + } + + return *Current; +} + /*}}}*/ // SrcRecords::Find - Find the first source package with the given name /*{{{*/ // --------------------------------------------------------------------- /* This searches on both source package names and output binary names and @@ -88,21 +109,11 @@ bool pkgSrcRecords::Restart() function to be called multiple times to get successive entries */ pkgSrcRecords::Parser *pkgSrcRecords::Find(const char *Package,bool const &SrcOnly) { - if (Current == Files.end()) - return 0; - while (true) { - // Step to the next record, possibly switching files - while ((*Current)->Step() == false) - { - if (_error->PendingError() == true) - return 0; - ++Current; - if (Current == Files.end()) - return 0; - } - + if(Step() == 0) + return 0; + // IO error somehow if (_error->PendingError() == true) return 0; diff --git a/apt-pkg/srcrecords.h b/apt-pkg/srcrecords.h index 69b3cfd99..c68d374bb 100644 --- a/apt-pkg/srcrecords.h +++ b/apt-pkg/srcrecords.h @@ -105,8 +105,13 @@ class pkgSrcRecords // Reset the search bool Restart(); - // Locate a package by name - Parser *Find(const char *Package,bool const &SrcOnly = false); + // Step to the next SourcePackage and return pointer to the + // next SourceRecord. The pointer is owned by libapt. + const Parser* Step(); + + // Locate a package by name and return pointer to the Parser. + // The pointer is owned by libapt. + Parser* Find(const char *Package,bool const &SrcOnly = false); pkgSrcRecords(pkgSourceList &List); virtual ~pkgSrcRecords(); |