-// TryToInstallBuildDep - Try to install a single package /*{{{*/
-// ---------------------------------------------------------------------
-/* This used to be inlined in DoInstall, but with the advent of regex package
- name matching it was split out.. */
-static bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
- pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
- bool AllowFail = true)
-{
- if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
- {
- CacheSetHelperAPTGet helper(c1out);
- helper.showErrors(false);
- pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
- if (Ver.end() == false)
- Pkg = Ver.ParentPkg();
- else if (helper.showVirtualPackageErrors(Cache) == false)
- return AllowFail;
- }
-
- if (_config->FindB("Debug::BuildDeps",false) == true)
- {
- if (Remove == true)
- cout << " Trying to remove " << Pkg << endl;
- else
- cout << " Trying to install " << Pkg << endl;
- }
-
- if (Remove == true)
- {
- TryToRemove RemoveAction(Cache, &Fix);
- RemoveAction(Pkg.VersionList());
- } else if (Cache[Pkg].CandidateVer != 0) {
- TryToInstall InstallAction(Cache, &Fix, BrokenFix);
- InstallAction(Cache[Pkg].CandidateVerIter(Cache));
- InstallAction.doAutoInstall();
- } else
- return AllowFail;
-
- return true;
-}
- /*}}}*/
-// GetReleaseForSourceRecord - Return Suite for the given srcrecord /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-static std::string GetReleaseForSourceRecord(pkgSourceList *SrcList,
- pkgSrcRecords::Parser *Parse)
-{
- // try to find release
- const pkgIndexFile& CurrentIndexFile = Parse->Index();
-
- for (pkgSourceList::const_iterator S = SrcList->begin();
- S != SrcList->end(); ++S)
- {
- vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
- for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
- IF != Indexes->end(); ++IF)
- {
- if (&CurrentIndexFile == (*IF))
- {
- std::string const path = (*S)->LocalFileName();
- if (path != "")
- {
- indexRecords records;
- records.Load(path);
- return records.GetSuite();
- }
- }
- }
- }
- return "";
-}
- /*}}}*/
-// FindSrc - Find a source record /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-static pkgSrcRecords::Parser *FindSrc(const char *Name,
- pkgSrcRecords &SrcRecs,string &Src,
- CacheFile &CacheFile)
-{
- string VerTag, UserRequestedVerTag;
- string ArchTag = "";
- string RelTag = _config->Find("APT::Default-Release");
- string TmpSrc = Name;
- pkgDepCache *Cache = CacheFile.GetDepCache();
-
- // extract release
- size_t found = TmpSrc.find_last_of("/");
- if (found != string::npos)
- {
- RelTag = TmpSrc.substr(found+1);
- TmpSrc = TmpSrc.substr(0,found);
- }
- // extract the version
- found = TmpSrc.find_last_of("=");
- if (found != string::npos)
- {
- VerTag = UserRequestedVerTag = TmpSrc.substr(found+1);
- TmpSrc = TmpSrc.substr(0,found);
- }
- // extract arch
- found = TmpSrc.find_last_of(":");
- if (found != string::npos)
- {
- ArchTag = TmpSrc.substr(found+1);
- TmpSrc = TmpSrc.substr(0,found);
- }
-
- /* Lookup the version of the package we would install if we were to
- install a version and determine the source package name, then look
- in the archive for a source package of the same name. */
- bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
- pkgCache::PkgIterator Pkg;
- if (ArchTag != "")
- Pkg = Cache->FindPkg(TmpSrc, ArchTag);
- else
- Pkg = Cache->FindPkg(TmpSrc);
-
- // if we can't find a package but the user qualified with a arch,
- // error out here
- if (Pkg.end() && ArchTag != "")
- {
- Src = Name;
- _error->Error(_("Can not find a package for architecture '%s'"),
- ArchTag.c_str());
- return 0;
- }
-
- if (MatchSrcOnly == false && Pkg.end() == false)
- {
- if(VerTag != "" || RelTag != "" || ArchTag != "")
- {
- bool fuzzy = false;
- // we have a default release, try to locate the pkg. we do it like
- // this because GetCandidateVer() will not "downgrade", that means
- // "apt-get source -t stable apt" won't work on a unstable system
- for (pkgCache::VerIterator Ver = Pkg.VersionList();; ++Ver)
- {
- // try first only exact matches, later fuzzy matches
- if (Ver.end() == true)
- {
- if (fuzzy == true)
- break;
- fuzzy = true;
- Ver = Pkg.VersionList();
- // exit right away from the Pkg.VersionList() loop if we
- // don't have any versions
- if (Ver.end() == true)
- break;
- }
-
- // ignore arches that are not for us
- if (ArchTag != "" && Ver.Arch() != ArchTag)
- continue;
-
- // pick highest version for the arch unless the user wants
- // something else
- if (ArchTag != "" && VerTag == "" && RelTag == "")
- if(Cache->VS().CmpVersion(VerTag, Ver.VerStr()) < 0)
- VerTag = Ver.VerStr();
-
- // We match against a concrete version (or a part of this version)
- if (VerTag.empty() == false &&
- (fuzzy == true || Cache->VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
- (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
- continue;
-
- for (pkgCache::VerFileIterator VF = Ver.FileList();
- VF.end() == false; ++VF)
- {
- /* If this is the status file, and the current version is not the
- version in the status file (ie it is not installed, or somesuch)
- 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 && Pkg.CurrentVer() != Ver)
- continue;
-
- // or we match against a release
- if(VerTag.empty() == false ||
- (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
- (VF.File().Codename() != 0 && VF.File().Codename() == RelTag))
- {
- Src = Ver.SourcePkgName();
- // the Version we have is possibly fuzzy or includes binUploads,
- // so we use the Version of the SourcePkg
- VerTag = Ver.SourceVerStr();
- break;
- }
- }
- if (Src.empty() == false)
- break;
- }
- }
-
- if (Src == "" && ArchTag != "")
- {
- if (VerTag != "")
- _error->Error(_("Can not find a package '%s' with version '%s'"),
- Pkg.FullName().c_str(), VerTag.c_str());
- if (RelTag != "")
- _error->Error(_("Can not find a package '%s' with release '%s'"),
- Pkg.FullName().c_str(), RelTag.c_str());
- Src = Name;
- return 0;
- }
-
-
- if (Src.empty() == true)
- {
- // if we don't have found a fitting package yet so we will
- // choose a good candidate and proceed with that.
- // Maybe we will find a source later on with the right VerTag
- // or RelTag
- pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
- if (Ver.end() == false)
- {
- if (strcmp(Ver.SourcePkgName(),Ver.ParentPkg().Name()) != 0)
- Src = Ver.SourcePkgName();
- if (VerTag.empty() == true && strcmp(Ver.SourceVerStr(),Ver.VerStr()) != 0)
- VerTag = Ver.SourceVerStr();
- }
- }
- }
-
- if (Src.empty() == true)
- {
- Src = TmpSrc;
- }
- else
- {
- /* if we have a source pkg name, make sure to only search
- for srcpkg names, otherwise apt gets confused if there
- is a binary package "pkg1" and a source package "pkg1"
- with the same name but that comes from different packages */
- MatchSrcOnly = true;
- if (Src != TmpSrc)
- {
- ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
- }
- }
-
- // The best hit
- pkgSrcRecords::Parser *Last = 0;
- unsigned long Offset = 0;
- string Version;
- pkgSourceList *SrcList = CacheFile.GetSourceList();
-
- /* Iterate over all of the hits, which includes the resulting
- binary packages in the search */
- pkgSrcRecords::Parser *Parse;
- while (true)
- {
- SrcRecs.Restart();
- while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
- {
- const string Ver = Parse->Version();
-
- // See if we need to look for a specific release tag
- if (RelTag != "" && UserRequestedVerTag == "")
- {
- const string Rel = GetReleaseForSourceRecord(SrcList, Parse);
-
- if (Rel == RelTag)
- {
- Last = Parse;
- Offset = Parse->Offset();
- Version = Ver;
- }
- }
-
- // Ignore all versions which doesn't fit
- if (VerTag.empty() == false &&
- Cache->VS().CmpVersion(VerTag, Ver) != 0) // exact match
- continue;
-
- // Newer version or an exact match? Save the hit
- if (Last == 0 || Cache->VS().CmpVersion(Version,Ver) < 0) {
- Last = Parse;
- Offset = Parse->Offset();
- Version = Ver;
- }
-
- // was the version check above an exact match?
- // If so, we don't need to look further
- if (VerTag.empty() == false && (VerTag == Ver))
- break;
- }
- if (UserRequestedVerTag == "" && Version != "" && RelTag != "")
- ioprintf(c1out, "Selected version '%s' (%s) for %s\n",
- Version.c_str(), RelTag.c_str(), Src.c_str());
-
- if (Last != 0 || VerTag.empty() == true)
- break;
- _error->Error(_("Can not find version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
- return 0;
- }
-
- if (Last == 0 || Last->Jump(Offset) == false)
- return 0;
-
- return Last;
-}
- /*}}}*/