X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/d953d210bb54accb416f2144104b79dcd29198ba..a12d5352927c7d3a2fe66a90fc7794b4a8e596ad:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 65eaef0d8..4e6cc32de 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -25,8 +25,7 @@ ##################################################################### */ /*}}}*/ // Include Files /*{{{*/ -#define _LARGEFILE_SOURCE -#define _LARGEFILE64_SOURCE +#include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -45,9 +45,10 @@ #include #include #include - -#include -#include +#include +#include +#include +#include #include "acqprogress.h" @@ -68,8 +69,7 @@ #include #include -#define statfs statfs64 -#define statvfs statvfs64 +#include /*}}}*/ #define RAMFS_MAGIC 0x858458f6 @@ -135,6 +135,11 @@ bool YnPrompt(bool Default=true) c1out << _("Y") << endl; return true; } + else if (_config->FindB("APT::Get::Assume-No",false) == true) + { + c1out << _("N") << endl; + return false; + } char response[1024] = ""; cin.getline(response, sizeof(response)); @@ -363,7 +368,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now) if (Start == End) break; - Start++; + ++Start; } } } @@ -537,7 +542,7 @@ bool ShowEssential(ostream &out,CacheFile &Cache) continue; // Print out any essential package depenendents that are to be removed - for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++) + for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D) { // Skip everything but depends if (D->Type != pkgCache::Dep::PreDepends && @@ -574,7 +579,7 @@ void Stats(ostream &out,pkgDepCache &Dep) unsigned long Downgrade = 0; unsigned long Install = 0; unsigned long ReInstall = 0; - for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++) + for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I) { if (Dep[I].NewInstall() == true) Install++; @@ -623,20 +628,18 @@ public: explicitlyNamed = true; } - virtual void showTaskSelection(APT::PackageSet const &pkgset, string const &pattern) { - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) - ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); + virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { + ioprintf(out, _("Note, selecting '%s' for task '%s'\n"), + Pkg.FullName(true).c_str(), pattern.c_str()); explicitlyNamed = false; } - virtual void showRegExSelection(APT::PackageSet const &pkgset, string const &pattern) { - for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) - ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"), - Pkg.FullName(true).c_str(), pattern.c_str()); + virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) { + 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, - string const &ver, bool const &verIsRel) { + string const &ver, bool const verIsRel) { if (ver == Ver.VerStr()) return; selectedByRelease.push_back(make_pair(Ver, ver)); @@ -657,22 +660,22 @@ public: pkgCache::PkgIterator Pkg = I.OwnerPkg(); if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) { - out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); + c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false) - out << _(" [Installed]"); - out << endl; + c1out << _(" [Installed]"); + c1out << endl; ++provider; } } // if we found no candidate which provide this package, show non-candidates if (provider == 0) - for (I = Pkg.ProvidesList(); I.end() == false; I++) - out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() + for (I = Pkg.ProvidesList(); I.end() == false; ++I) + c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() << _(" [Not candidate version]") << endl; else out << _("You should explicitly select one to install.") << endl; } else { - ioprintf(out, + ioprintf(c1out, _("Package %s is not available, but is referred to by another package.\n" "This may mean that the package is missing, has been obsoleted, or\n" "is only available from another source\n"),Pkg.FullName(true).c_str()); @@ -682,7 +685,7 @@ public: SPtrArray Seen = new bool[Cache.GetPkgCache()->Head().PackageCount]; memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen)); for (pkgCache::DepIterator Dep = Pkg.RevDependsList(); - Dep.end() == false; Dep++) { + Dep.end() == false; ++Dep) { if (Dep->Type != pkgCache::Dep::Replaces) continue; if (Seen[Dep.ParentPkg()->ID] == true) @@ -691,9 +694,9 @@ public: List += Dep.ParentPkg().FullName(true) + " "; //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ??? } - ShowList(out,_("However the following packages replace it:"),List,VersionsList); + ShowList(c1out,_("However the following packages replace it:"),List,VersionsList); } - out << std::endl; + c1out << std::endl; } return false; } @@ -702,7 +705,7 @@ public: APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE); if (verset.empty() == false) return *(verset.begin()); - if (ShowError == true) { + else if (ShowError == true) { _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str()); virtualPkgs.insert(Pkg); } @@ -710,11 +713,32 @@ public: } virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { - APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST); - if (verset.empty() == false) - return *(verset.begin()); - if (ShowError == true) - ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str()); + if (Pkg->ProvidesList != 0) + { + APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST); + if (verset.empty() == false) + return *(verset.begin()); + if (ShowError == true) + ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str()); + } + else + { + pkgCache::GrpIterator Grp = Pkg.Group(); + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if (P == Pkg) + continue; + if (P->CurrentVer != 0) { + // TRANSLATORS: Note, this is not an interactive question + ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), + Pkg.FullName(true).c_str(), P.FullName(true).c_str()); + break; + } + } + if (P.end() == true) + ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + } return pkgCache::VerIterator(Cache, 0); } @@ -739,6 +763,19 @@ public: Prov = PPkg; found_one = true; } else if (PPkg != Prov) { + // same group, so it's a foreign package + if (PPkg->Group == Prov->Group) { + // do we already have the requested arch? + if (strcmp(Pkg.Arch(), Prov.Arch()) == 0 || + strcmp(Prov.Arch(), "all") == 0 || + unlikely(strcmp(PPkg.Arch(), Prov.Arch()) == 0)) // packages have only on candidate, but just to be sure + continue; + // see which architecture we prefer more and switch to it + std::vector archs = APT::Configuration::getArchitectures(); + if (std::find(archs.begin(), archs.end(), PPkg.Arch()) < std::find(archs.begin(), archs.end(), Prov.Arch())) + Prov = PPkg; + continue; + } found_one = false; // we found at least two break; } @@ -764,7 +801,7 @@ struct TryToInstall { unsigned long AutoMarkChanged; APT::PackageSet doAutoInstallLater; - TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const &FixBroken) : Cache(&Cache), Fix(PM), + TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM), FixBroken(FixBroken), AutoMarkChanged(0) {}; void operator() (pkgCache::VerIterator const &Ver) { @@ -869,9 +906,7 @@ struct TryToInstall { struct TryToRemove { pkgCacheFile* Cache; pkgProblemResolver* Fix; - bool FixBroken; bool PurgePkgs; - unsigned long AutoMarkChanged; TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM), PurgePkgs(_config->FindB("APT::Get::Purge", false)) {}; @@ -890,7 +925,23 @@ struct TryToRemove { if ((Pkg->CurrentVer == 0 && PurgePkgs == false) || (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled)) { - ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + pkgCache::GrpIterator Grp = Pkg.Group(); + pkgCache::PkgIterator P = Grp.PackageList(); + for (; P.end() != true; P = Grp.NextPkg(P)) + { + if (P == Pkg) + continue; + if (P->CurrentVer != 0 || (PurgePkgs == true && P->CurrentState != pkgCache::State::NotInstalled)) + { + // TRANSLATORS: Note, this is not an interactive question + ioprintf(c1out,_("Package '%s' is not installed, so not removed. Did you mean '%s'?\n"), + Pkg.FullName(true).c_str(), P.FullName(true).c_str()); + break; + } + } + if (P.end() == true) + ioprintf(c1out,_("Package '%s' is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + // MarkInstall refuses to install packages on hold Pkg->SelectedState = pkgCache::State::Hold; } @@ -923,7 +974,7 @@ void CacheFile::Sort() 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++) + for (;I.end() != true; ++I) List[I->ID] = I; SortCache = *this; @@ -955,7 +1006,7 @@ bool CacheFile::CheckDeps(bool AllowBroken) if ((DCache->PolicyBrokenCount() > 0)) { // upgrade all policy-broken packages with ForceImportantDeps=True - for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); I++) + for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); ++I) if ((*DCache)[I].NowPolicyBroken() == true) DCache->MarkInstall(I,true,0, false, true); } @@ -1046,7 +1097,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, if (_config->FindB("APT::Get::Purge",false) == true) { pkgCache::PkgIterator I = Cache->PkgBegin(); - for (; I.end() == false; I++) + for (; I.end() == false; ++I) { if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) Cache->MarkDelete(I,true); @@ -1240,7 +1291,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, if (_config->FindB("APT::Get::Print-URIs") == true) { pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); I++) + for (; I != Fetcher.UriEnd(); ++I) cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; return true; @@ -1264,7 +1315,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, { if ((*I)->Local == true) { - I++; + ++I; continue; } @@ -1284,7 +1335,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, // Print out errors bool Failed = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) { if ((*I)->Status == pkgAcquire::Item::StatDone && (*I)->Complete == true) @@ -1364,7 +1415,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, "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 automatic and on purpose by dpkg.") << std::endl; + c0out << _("Note: This is done automatically and on purpose by dpkg.") << std::endl; return true; } @@ -1388,6 +1439,14 @@ bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, 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); @@ -1436,7 +1495,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, // 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++) + for (pkgCache::VerIterator Ver = Pkg.VersionList();; ++Ver) { // try first only exact matches, later fuzzy matches if (Ver.end() == true) @@ -1457,7 +1516,7 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, continue; for (pkgCache::VerFileIterator VF = Ver.FileList(); - VF.end() == false; VF++) + 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) @@ -1609,7 +1668,7 @@ bool DoUpdate(CommandLine &CmdL) return false; pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); I++) + for (; I != Fetcher.UriEnd(); ++I) cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; return true; @@ -1619,7 +1678,8 @@ bool DoUpdate(CommandLine &CmdL) if (_config->FindB("APT::Get::Download",true) == true) ListUpdate(Stat, *List); - // Rebuild the cache. + // Rebuild the cache. + pkgCacheFile::RemoveCaches(); if (Cache.BuildCaches() == false) return false; @@ -1651,12 +1711,13 @@ bool DoAutomaticRemove(CacheFile &Cache) bool smallList = (hideAutoRemove == false && strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0); - string autoremovelist, autoremoveversions; unsigned long autoRemoveCount = 0; APT::PackageSet tooMuch; + APT::PackageList autoRemoveList; // look over the cache to see what can be removed - for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg) + for (unsigned J = 0; J < Cache->Head().PackageCount; ++J) { + pkgCache::PkgIterator Pkg(Cache,Cache.List[J]); if (Cache[Pkg].Garbage) { if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install()) @@ -1673,67 +1734,75 @@ 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) { + if (Pkg.CandVersion() != 0) + tooMuch.insert(Pkg); Cache->MarkDelete(Pkg, false); - tooMuch.insert(Pkg); } // only show stuff in the list that is not yet marked for removal - else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) - { + else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) ++autoRemoveCount; - // we don't need to fill the strings if we don't need them - if (smallList == false) - { - autoremovelist += Pkg.FullName(true) + " "; - autoremoveversions += string(Cache[Pkg].CandVersion) + "\n"; - } - } } } } // we could have removed a new dependency of a garbage package, // so check if a reverse depends is broken and if so install it again. - if (tooMuch.empty() == false && Cache->BrokenCount() != 0) + if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0)) { bool Changed; do { Changed = false; - for (APT::PackageSet::const_iterator P = tooMuch.begin(); - P != tooMuch.end() && Changed == false; ++P) + for (APT::PackageSet::const_iterator Pkg = tooMuch.begin(); + Pkg != tooMuch.end() && Changed == false; ++Pkg) { - for (pkgCache::DepIterator R = P.RevDependsList(); - R.end() == false; ++R) - { - if (R->Type != pkgCache::Dep::Depends && - R->Type != pkgCache::Dep::PreDepends) - continue; - pkgCache::PkgIterator N = R.ParentPkg(); - if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) - continue; - if (Debug == true) - std::clog << "Save " << P << " as another installed garbage package depends on it" << std::endl; - Cache->MarkInstall(P, false); - if(hideAutoRemove == false) + APT::PackageSet too; + too.insert(*Pkg); + for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList(); + Prv.end() == false; ++Prv) + too.insert(Prv.ParentPkg()); + for (APT::PackageSet::const_iterator P = too.begin(); + P != too.end() && Changed == false; ++P) { + for (pkgCache::DepIterator R = P.RevDependsList(); + R.end() == false; ++R) { - ++autoRemoveCount; - if (smallList == false) - { - autoremovelist += P.FullName(true) + " "; - autoremoveversions += string(Cache[P].CandVersion) + "\n"; - } + if (R.IsNegative() == true || + Cache->IsImportantDep(R) == false) + continue; + pkgCache::PkgIterator N = R.ParentPkg(); + if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) + continue; + if (Debug == true) + std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl; + Cache->MarkInstall(Pkg, false); + if (hideAutoRemove == false) + ++autoRemoveCount; + tooMuch.erase(Pkg); + Changed = true; + break; } - tooMuch.erase(P); - Changed = true; - break; } } } 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 += string(Cache[Pkg].CandVersion) + "\n"; + } + } + // Now see if we had destroyed anything (if we had done anything) if (Cache->BrokenCount() != 0) { @@ -1757,7 +1826,7 @@ bool DoAutomaticRemove(CacheFile &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); - c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl; + c1out << P_("Use 'apt-get autoremove' to remove it.", "Use 'apt-get autoremove' to remove them.", autoRemoveCount) << std::endl; } return true; } @@ -1994,7 +2063,7 @@ bool DoInstall(CommandLine &CmdL) if(Start.TargetPkg().ProvidesList() != 0) { pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList(); - for (; I.end() == false; I++) + for (; I.end() == false; ++I) { pkgCache::PkgIterator Pkg = I.OwnerPkg(); if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() && @@ -2017,7 +2086,7 @@ bool DoInstall(CommandLine &CmdL) if (Start >= End) break; - Start++; + ++Start; } if(foundInstalledInOrGroup == false) @@ -2131,7 +2200,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) // Install everything with the install flag set pkgCache::PkgIterator I = Cache->PkgBegin(); - for (;I.end() != true; I++) + for (;I.end() != true; ++I) { /* Install the package only if it is a new install, the autoupgrader will deal with the rest */ @@ -2141,7 +2210,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) /* Now install their deps too, if we do this above then order of the status file is significant for | groups */ - for (I = Cache->PkgBegin();I.end() != true; I++) + for (I = Cache->PkgBegin();I.end() != true; ++I) { /* Install the package only if it is a new install, the autoupgrader will deal with the rest */ @@ -2150,7 +2219,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) } // Apply erasures now, they override everything else. - for (I = Cache->PkgBegin();I.end() != true; I++) + for (I = Cache->PkgBegin();I.end() != true; ++I) { // Remove packages if (I->SelectedState == pkgCache::State::DeInstall || @@ -2167,7 +2236,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) // Hold back held packages. if (_config->FindB("APT::Ignore-Hold",false) == false) { - for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++) + for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I) { if (I->SelectedState == pkgCache::State::Hold) { @@ -2199,10 +2268,14 @@ bool DoDSelectUpgrade(CommandLine &CmdL) /* */ bool DoClean(CommandLine &CmdL) { + std::string const archivedir = _config->FindDir("Dir::Cache::archives"); + std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache"); + std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache"); + if (_config->FindB("APT::Get::Simulate") == true) { - cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " << - _config->FindDir("Dir::Cache::archives") << "partial/*" << endl; + cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl + << "Del " << pkgcache << " " << srcpkgcache << endl; return true; } @@ -2210,14 +2283,17 @@ bool DoClean(CommandLine &CmdL) FileFd Lock; if (_config->FindB("Debug::NoLocking",false) == false) { - Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock")); + Lock.Fd(GetLock(archivedir + "lock")); if (_error->PendingError() == true) return _error->Error(_("Unable to lock the download directory")); } pkgAcquire Fetcher; - Fetcher.Clean(_config->FindDir("Dir::Cache::archives")); - Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/"); + Fetcher.Clean(archivedir); + Fetcher.Clean(archivedir + "partial/"); + + pkgCacheFile::RemoveCaches(); + return true; } /*}}}*/ @@ -2267,20 +2343,20 @@ bool DoDownload(CommandLine &CmdL) return false; APT::CacheSetHelper helper(c0out); - APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, - CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); + APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, + CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper); if (verset.empty() == true) return false; pkgAcquire Fetcher; AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); - if (_config->FindB("APT::Get::Print-URIs") == true) + if (_config->FindB("APT::Get::Print-URIs") == false) Fetcher.Setup(&Stat); pkgRecords Recs(Cache); pkgSourceList *SrcList = Cache.GetSourceList(); - for (APT::VersionSet::const_iterator Ver = verset.begin(); + for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) { @@ -2299,6 +2375,8 @@ bool DoDownload(CommandLine &CmdL) strprintf(descr, _("Downloading %s %s"), Pkg.Name(), Ver.VerStr()); // get the most appropriate hash HashString hash; + if (rec.SHA512Hash() != "") + hash = HashString("sha512", rec.SHA512Hash()); if (rec.SHA256Hash() != "") hash = HashString("sha256", rec.SHA256Hash()); else if (rec.SHA1Hash() != "") @@ -2313,7 +2391,7 @@ bool DoDownload(CommandLine &CmdL) if (_config->FindB("APT::Get::Print-URIs") == true) { pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); I++) + for (; I != Fetcher.UriEnd(); ++I) cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; return true; @@ -2368,8 +2446,7 @@ bool DoSource(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); pkgAcquire Fetcher; - if (Fetcher.Setup(&Stat) == false) - return false; + Fetcher.SetLog(&Stat); DscFile *Dsc = new DscFile[CmdL.FileSize()]; @@ -2432,7 +2509,7 @@ bool DoSource(CommandLine &CmdL) // Load them into the fetcher for (vector::const_iterator I = Lst.begin(); - I != Lst.end(); I++) + I != Lst.end(); ++I) { // Try to guess what sort of file it is we are getting. if (I->Type == "dsc") @@ -2534,7 +2611,7 @@ bool DoSource(CommandLine &CmdL) if (_config->FindB("APT::Get::Print-URIs") == true) { pkgAcquire::UriIterator I = Fetcher.UriBegin(); - for (; I != Fetcher.UriEnd(); I++) + for (; I != Fetcher.UriEnd(); ++I) cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' << I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl; delete[] Dsc; @@ -2550,7 +2627,7 @@ bool DoSource(CommandLine &CmdL) // Print error messages bool Failed = false; - for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) + for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I) { if ((*I)->Status == pkgAcquire::Item::StatDone && (*I)->Complete == true) @@ -2579,7 +2656,7 @@ bool DoSource(CommandLine &CmdL) if (Process == 0) { bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false); - for (unsigned I = 0; I != J; I++) + for (unsigned I = 0; I != J; ++I) { string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str()); @@ -2615,12 +2692,17 @@ bool DoSource(CommandLine &CmdL) // Try to compile it with dpkg-buildpackage if (_config->FindB("APT::Get::Compile",false) == true) { + string buildopts = _config->Find("APT::Get::Host-Architecture"); + if (buildopts.empty() == false) + buildopts = "-a " + buildopts + " "; + buildopts.append(_config->Find("DPkg::Build-Options","-b -uc")); + // Call dpkg-buildpackage char S[500]; snprintf(S,sizeof(S),"cd %s && %s %s", Dir.c_str(), _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(), - _config->Find("DPkg::Build-Options","-b -uc").c_str()); + buildopts.c_str()); if (system(S) != 0) { @@ -2682,8 +2764,19 @@ bool DoBuildDep(CommandLine &CmdL) if (Fetcher.Setup(&Stat) == false) return false; + bool StripMultiArch; + string hostArch = _config->Find("APT::Get::Host-Architecture"); + if (hostArch.empty() == false) + { + std::vector archs = APT::Configuration::getArchitectures(); + if (std::find(archs.begin(), archs.end(), hostArch) == archs.end()) + return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str()); + StripMultiArch = false; + } + else + StripMultiArch = true; + unsigned J = 0; - bool const StripMultiArch = APT::Configuration::getArchitectures().size() <= 1; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; @@ -2712,22 +2805,32 @@ bool DoBuildDep(CommandLine &CmdL) BuildDeps.push_back(rec); } - if (BuildDeps.size() == 0) + if (BuildDeps.empty() == true) { ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str()); continue; } - + // Install the requested packages vector ::iterator D; pkgProblemResolver Fix(Cache); bool skipAlternatives = false; // skip remaining alternatives in an or group - for (D = BuildDeps.begin(); D != BuildDeps.end(); D++) + for (D = BuildDeps.begin(); D != BuildDeps.end(); ++D) { bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or); if (skipAlternatives == true) { + /* + * if there are alternatives, we've already picked one, so skip + * the rest + * + * TODO: this means that if there's a build-dep on A|B and B is + * installed, we'll still try to install A; more importantly, + * if A is currently broken, we cannot go back and try B. To fix + * this would require we do a Resolve cycle for each package we + * add to the install list. Ugh + */ if (!hasAlternatives) skipAlternatives = false; // end of or group continue; @@ -2736,27 +2839,123 @@ bool DoBuildDep(CommandLine &CmdL) if ((*D).Type == pkgSrcRecords::Parser::BuildConflict || (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep) { - pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package); + pkgCache::GrpIterator Grp = Cache->FindGrp((*D).Package); // Build-conflicts on unknown packages are silently ignored - if (Pkg.end() == true) + if (Grp.end() == true) continue; - pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache); - - /* - * Remove if we have an installed version that satisfies the - * version criteria - */ - if (IV.end() == false && - Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) - TryToInstallBuildDep(Pkg,Cache,Fix,true,false); + for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + { + pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache); + /* + * Remove if we have an installed version that satisfies the + * version criteria + */ + if (IV.end() == false && + Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) + TryToInstallBuildDep(Pkg,Cache,Fix,true,false); + } } else // BuildDep || BuildDepIndep { - pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package); if (_config->FindB("Debug::BuildDeps",false) == true) cout << "Looking for " << (*D).Package << "...\n"; + pkgCache::PkgIterator Pkg; + + // Cross-Building? + if (StripMultiArch == false && D->Type != pkgSrcRecords::Parser::BuildDependIndep) + { + size_t const colon = D->Package.find(":"); + if (colon != string::npos && + (strcmp(D->Package.c_str() + colon, ":any") == 0 || strcmp(D->Package.c_str() + colon, ":native") == 0)) + Pkg = Cache->FindPkg(D->Package.substr(0,colon)); + else + Pkg = Cache->FindPkg(D->Package); + + // We need to decide if host or build arch, so find a version we can look at + pkgCache::VerIterator Ver; + + // a bad version either is invalid or doesn't satify dependency + #define BADVER(Ver) Ver.end() == true || \ + (Ver.end() == false && D->Version.empty() == false && \ + Cache->VS().CheckDep(Ver.VerStr(),D->Op,D->Version.c_str()) == false) + + if (Pkg.end() == false) + { + Ver = (*Cache)[Pkg].InstVerIter(*Cache); + if (BADVER(Ver)) + Ver = (*Cache)[Pkg].CandidateVerIter(*Cache); + } + if (BADVER(Ver)) + { + pkgCache::PkgIterator HostPkg = Cache->FindPkg(D->Package, hostArch); + if (HostPkg.end() == false) + { + Ver = (*Cache)[HostPkg].InstVerIter(*Cache); + if (BADVER(Ver)) + Ver = (*Cache)[HostPkg].CandidateVerIter(*Cache); + } + } + if ((BADVER(Ver)) == false) + { + string forbidden; + if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All) + { + if (colon == string::npos) + { + Pkg = Ver.ParentPkg().Group().FindPkg(hostArch); + } + } + else if (Ver->MultiArch == pkgCache::Version::Same) + { + if (colon == string::npos) + Pkg = Ver.ParentPkg().Group().FindPkg(hostArch); + else if (strcmp(D->Package.c_str() + colon, ":any") == 0) + forbidden = "Multi-Arch: same"; + // :native gets the buildArch + } + else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign) + { + if (colon != string::npos) + forbidden = "Multi-Arch: foreign"; + } + else if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed) + { + if (colon == string::npos) + Pkg = Ver.ParentPkg().Group().FindPkg(hostArch); + else if (strcmp(D->Package.c_str() + colon, ":any") == 0) + { + // prefer any installed over preferred non-installed architectures + pkgCache::GrpIterator Grp = Ver.ParentPkg().Group(); + // we don't check for version here as we are better of with upgrading than remove and install + for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg)) + if (Pkg.CurrentVer().end() == false) + break; + if (Pkg.end() == true) + Pkg = Grp.FindPreferredPkg(true); + } + // native gets buildArch + } + if (forbidden.empty() == false) + { + if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " :any is not allowed from M-A: same package " << (*D).Package << endl; + if (hasAlternatives) + continue; + return _error->Error(_("%s dependency for %s can't be satisfied " + "because %s is not allowed on '%s' packages"), + Last->BuildDepType(D->Type), Src.c_str(), + D->Package.c_str(), "Multi-Arch: same"); + } + } + else if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " No multiarch info as we have no satisfying installed nor candidate for " << D->Package << " on build or host arch" << endl; + #undef BADVER + } + else + Pkg = Cache->FindPkg(D->Package); + if (Pkg.end() == true) { if (_config->FindB("Debug::BuildDeps",false) == true) @@ -2771,99 +2970,74 @@ bool DoBuildDep(CommandLine &CmdL) (*D).Package.c_str()); } - /* - * if there are alternatives, we've already picked one, so skip - * the rest - * - * TODO: this means that if there's a build-dep on A|B and B is - * installed, we'll still try to install A; more importantly, - * if A is currently broken, we cannot go back and try B. To fix - * this would require we do a Resolve cycle for each package we - * add to the install list. Ugh - */ - - /* - * If this is a virtual package, we need to check the list of - * packages that provide it and see if any of those are - * installed - */ - pkgCache::PrvIterator Prv = Pkg.ProvidesList(); - for (; Prv.end() != true; Prv++) - { - if (_config->FindB("Debug::BuildDeps",false) == true) - cout << " Checking provider " << Prv.OwnerPkg().FullName() << endl; - - if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) - break; - } - - // Get installed version and version we are going to install pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache); + if (IV.end() == false) + { + if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " Is installed\n"; - if ((*D).Version[0] != '\0') { - // Versioned dependency - - pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache); - - for (; CV.end() != true; CV++) - { - if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) - break; - } - if (CV.end() == true) - { - if (hasAlternatives) - { - continue; - } - else - { - return _error->Error(_("%s dependency for %s cannot be satisfied " - "because no available versions of package %s " - "can satisfy version requirements"), - Last->BuildDepType((*D).Type),Src.c_str(), - (*D).Package.c_str()); - } - } - } - else - { - // Only consider virtual packages if there is no versioned dependency - if (Prv.end() == false) - { - if (_config->FindB("Debug::BuildDeps",false) == true) - cout << " Is provided by installed package " << Prv.OwnerPkg().FullName() << endl; - skipAlternatives = hasAlternatives; - continue; - } - } + if (D->Version.empty() == true || + Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) + { + skipAlternatives = hasAlternatives; + continue; + } - if (IV.end() == false) - { - if (_config->FindB("Debug::BuildDeps",false) == true) - cout << " Is installed\n"; + if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " ...but the installed version doesn't meet the version requirement\n"; - if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) - { - skipAlternatives = hasAlternatives; - continue; - } + if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq) + return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"), + Last->BuildDepType((*D).Type), Src.c_str(), Pkg.FullName(true).c_str()); + } - if (_config->FindB("Debug::BuildDeps",false) == true) - cout << " ...but the installed version doesn't meet the version requirement\n"; - - if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq) - { - return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"), - Last->BuildDepType((*D).Type), - Src.c_str(), - Pkg.FullName(true).c_str()); - } - } + // Only consider virtual packages if there is no versioned dependency + if ((*D).Version.empty() == true) + { + /* + * If this is a virtual package, we need to check the list of + * packages that provide it and see if any of those are + * installed + */ + pkgCache::PrvIterator Prv = Pkg.ProvidesList(); + for (; Prv.end() != true; ++Prv) + { + if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " Checking provider " << Prv.OwnerPkg().FullName() << endl; + if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false) + break; + } - if (_config->FindB("Debug::BuildDeps",false) == true) - cout << " Trying to install " << (*D).Package << endl; + if (Prv.end() == false) + { + if (_config->FindB("Debug::BuildDeps",false) == true) + cout << " Is provided by installed package " << Prv.OwnerPkg().FullName() << endl; + skipAlternatives = hasAlternatives; + continue; + } + } + else // versioned dependency + { + pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache); + if (CV.end() == true || + Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == false) + { + if (hasAlternatives) + continue; + else if (CV.end() == false) + return _error->Error(_("%s dependency for %s cannot be satisfied " + "because candidate version of package %s " + "can't satisfy version requirements"), + Last->BuildDepType(D->Type), Src.c_str(), + D->Package.c_str()); + else + return _error->Error(_("%s dependency for %s cannot be satisfied " + "because package %s has no candidate version"), + Last->BuildDepType(D->Type), Src.c_str(), + D->Package.c_str()); + } + } if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true) { @@ -3047,14 +3221,14 @@ bool DoChangelog(CommandLine &CmdL) return false; APT::CacheSetHelper helper(c0out); - APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, - CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); + APT::VersionList verset = APT::VersionList::FromCommandLine(Cache, + CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper); if (verset.empty() == true) return false; pkgAcquire Fetcher; if (_config->FindB("APT::Get::Print-URIs", false) == true) - for (APT::VersionSet::const_iterator Ver = verset.begin(); + for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) return DownloadChangelog(Cache, Fetcher, Ver, ""); @@ -3077,7 +3251,7 @@ bool DoChangelog(CommandLine &CmdL) return _error->Errno("mkdtemp", "mkdtemp failed"); } - for (APT::VersionSet::const_iterator Ver = verset.begin(); + for (APT::VersionList::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) { @@ -3121,7 +3295,7 @@ bool DoMoo(CommandLine &CmdL) /* */ bool ShowHelp(CommandLine &CmdL) { - ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION, + ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION, COMMON_ARCH,__DATE__,__TIME__); if (_config->FindB("version") == true) @@ -3243,12 +3417,14 @@ int main(int argc,const char *argv[]) /*{{{*/ {'s',"dry-run","APT::Get::Simulate",0}, {'s',"no-act","APT::Get::Simulate",0}, {'y',"yes","APT::Get::Assume-Yes",0}, - {'y',"assume-yes","APT::Get::Assume-Yes",0}, + {'y',"assume-yes","APT::Get::Assume-Yes",0}, + {0,"assume-no","APT::Get::Assume-No",0}, {'f',"fix-broken","APT::Get::Fix-Broken",0}, {'u',"show-upgraded","APT::Get::Show-Upgraded",0}, {'m',"ignore-missing","APT::Get::Fix-Missing",0}, {'t',"target-release","APT::Default-Release",CommandLine::HasArg}, {'t',"default-release","APT::Default-Release",CommandLine::HasArg}, + {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg}, {0,"download","APT::Get::Download",0}, {0,"fix-missing","APT::Get::Fix-Missing",0}, {0,"ignore-hold","APT::Ignore-Hold",0},