+ if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+ Cache->BadCount() == 0)
+ return true;
+
+ // Run the simulator ..
+ if (_config->FindB("APT::Get::Simulate") == true)
+ {
+ pkgSimulate PM(Cache);
+ pkgPackageManager::OrderResult Res = PM.DoInstall();
+ if (Res == pkgPackageManager::Failed)
+ return false;
+ if (Res != pkgPackageManager::Completed)
+ return _error->Error("Internal Error, Ordering didn't finish");
+ return true;
+ }
+
+ // Create the text record parser
+ pkgRecords Recs(Cache);
+ if (_error->PendingError() == true)
+ return false;
+
+ // Lock the archive directory
+ FileFd Lock;
+ if (_config->FindB("Debug::NoLocking",false) == false)
+ {
+ Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
+ if (_error->PendingError() == true)
+ return _error->Error("Unable to lock the download directory");
+ }
+
+ // Create the download object
+ AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
+ pkgAcquire Fetcher(&Stat);
+
+ // Read the source list
+ pkgSourceList List;
+ if (List.ReadMainList() == false)
+ return _error->Error("The list of sources could not be read.");
+
+ // Create the package manager and prepare to download
+ pkgDPkgPM PM(Cache);
+ if (PM.GetArchives(&Fetcher,&List,&Recs) == false ||
+ _error->PendingError() == true)
+ return false;
+
+ // Display statistics
+ unsigned long FetchBytes = Fetcher.FetchNeeded();
+ unsigned long FetchPBytes = Fetcher.PartialPresent();
+ unsigned long DebBytes = Fetcher.TotalNeeded();
+ if (DebBytes != Cache->DebSize())
+ {
+ c0out << DebBytes << ',' << Cache->DebSize() << endl;
+ c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
+ }
+
+ // Number of bytes
+ c1out << "Need to get ";
+ if (DebBytes != FetchBytes)
+ c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B';
+ else
+ c1out << SizeToStr(DebBytes) << 'B';
+
+ c1out << " of archives. After unpacking ";
+
+ // Check for enough free space
+ struct statfs Buf;
+ string OutputDir = _config->FindDir("Dir::Cache::Archives");
+ if (statfs(OutputDir.c_str(),&Buf) != 0)
+ return _error->Errno("statfs","Couldn't determine free space in %s",
+ OutputDir.c_str());
+ if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
+ return _error->Error("Sorry, you don't have enough free space in %s to hold all the .debs.",
+ OutputDir.c_str());
+
+ // Size delta
+ if (Cache->UsrSize() >= 0)
+ c1out << SizeToStr(Cache->UsrSize()) << "B will be used." << endl;
+ else
+ c1out << SizeToStr(-1*Cache->UsrSize()) << "B will be freed." << endl;
+
+ if (_error->PendingError() == true)
+ return false;
+
+ // Fail safe check
+ if (_config->FindI("quiet",0) >= 2 ||
+ _config->FindB("APT::Get::Assume-Yes",false) == true)
+ {
+ if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
+ return _error->Error("There are problems and -y was used without --force-yes");
+ }
+
+ if (Essential == true && Saftey == true)
+ {
+ c2out << "You are about to do something potentially harmful" << endl;
+ c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
+ c2out << " ?] " << flush;
+ if (AnalPrompt("Yes, I understand this may be bad") == false)
+ {
+ c2out << "Abort." << endl;
+ exit(1);
+ }
+ }
+ else
+ {
+ // Prompt to continue
+ if (Ask == true || Fail == true)
+ {
+ if (_config->FindI("quiet",0) < 2 &&
+ _config->FindB("APT::Get::Assume-Yes",false) == false)
+ {
+ c2out << "Do you want to continue? [Y/n] " << flush;
+
+ if (YnPrompt() == false)
+ {
+ c2out << "Abort." << endl;
+ exit(1);
+ }
+ }
+ }
+ }
+
+ // Just print out the uris an exit if the --print-uris flag was used
+ if (_config->FindB("APT::Get::Print-URIs") == true)
+ {
+ pkgAcquire::UriIterator I = Fetcher.UriBegin();
+ for (; I != Fetcher.UriEnd(); I++)
+ cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
+ I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
+ return true;
+ }
+
+ // Run it
+ while (1)
+ {
+ if (_config->FindB("APT::Get::No-Download",false) == false)
+ if (Fetcher.Run() == pkgAcquire::Failed)
+ return false;
+
+ // Print out errors
+ bool Failed = false;
+ bool Transient = false;
+ for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
+ {
+ if ((*I)->Status == pkgAcquire::Item::StatDone &&
+ (*I)->Complete == true)
+ continue;
+
+ if ((*I)->Status == pkgAcquire::Item::StatIdle)
+ {
+ Transient = true;
+ // Failed = true;
+ continue;
+ }
+
+ cerr << "Failed to fetch " << (*I)->DescURI() << endl;
+ cerr << " " << (*I)->ErrorText << endl;
+ Failed = true;
+ }
+
+ /* If we are in no download mode and missing files then there were
+ 'failures' then the user must specify -m. Furthermore, there
+ is no such thing as a transient error in no-download mode! */
+ if (Transient == true &&
+ _config->FindB("APT::Get::No-Download",false) == true)
+ {
+ Transient = false;
+ Failed = true;
+ }
+
+ if (_config->FindB("APT::Get::Download-Only",false) == true)
+ {
+ if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+ return _error->Error("Some files failed to download");
+ return true;
+ }
+
+ if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+ {
+ return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
+ }
+
+ if (Transient == true && Failed == true)
+ return _error->Error("--fix-missing and media swapping is not currently supported");
+
+ // Try to deal with missing package files
+ if (Failed == true && PM.FixMissing() == false)
+ {
+ cerr << "Unable to correct missing packages." << endl;
+ return _error->Error("Aborting Install.");
+ }
+
+ Cache.ReleaseLock();
+ pkgPackageManager::OrderResult Res = PM.DoInstall();
+ if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
+ return false;
+ if (Res == pkgPackageManager::Completed)
+ return true;
+
+ // Reload the fetcher object and loop again for media swapping
+ Fetcher.Shutdown();
+ if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
+ return false;
+ }
+}
+ /*}}}*/
+// TryToInstall - 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.. */
+bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
+ pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
+ unsigned int &ExpectedInst,bool AllowFail = true)
+{
+ /* This is a pure virtual package and there is a single available
+ provides */
+ if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
+ Pkg.ProvidesList()->NextProvides == 0)
+ {
+ pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
+ c1out << "Note, installing " << Tmp.Name() << " instead of " << Pkg.Name() << endl;
+ Pkg = Tmp;
+ }
+
+ // Handle the no-upgrade case
+ if (_config->FindB("APT::Get::no-upgrade",false) == true &&
+ Pkg->CurrentVer != 0)
+ {
+ if (AllowFail == true)
+ c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
+ return true;
+ }
+
+ // Check if there is something at all to install
+ pkgDepCache::StateCache &State = Cache[Pkg];
+ if (State.CandidateVer == 0)
+ {
+ if (AllowFail == false)
+ return false;
+
+ if (Pkg->ProvidesList != 0)
+ {
+ c1out << "Package " << Pkg.Name() << " is a virtual package provided by:" << endl;
+
+ pkgCache::PrvIterator I = Pkg.ProvidesList();
+ for (; I.end() == false; I++)
+ {
+ pkgCache::PkgIterator Pkg = I.OwnerPkg();
+
+ if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
+ {
+ if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
+ c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
+ " [Installed]"<< endl;
+ else
+ c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
+ }
+ }
+ c1out << "You should explicitly select one to install." << endl;
+ }
+ else
+ {
+ c1out << "Package " << Pkg.Name() << " has no available version, but exists in the database." << endl;
+ c1out << "This typically means that the package was mentioned in a dependency and " << endl;
+ c1out << "never uploaded, or that it is an obsolete package." << endl;
+
+ string List;
+ pkgCache::DepIterator Dep = Pkg.RevDependsList();
+ for (; Dep.end() == false; Dep++)
+ {
+ if (Dep->Type != pkgCache::Dep::Replaces)
+ continue;
+ List += string(Dep.ParentPkg().Name()) + " ";
+ }
+ ShowList(c1out,"However the following packages replace it:",List);
+ }