// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-get.cc,v 1.20 1998/11/27 01:52:58 jgg Exp $
+// $Id: apt-get.cc,v 1.47 1999/03/27 03:02:39 jgg Exp $
/* ######################################################################
apt-get - Cover for dpkg
#include <apt-pkg/acquire-item.h>
#include <apt-pkg/dpkgpm.h>
#include <apt-pkg/dpkginit.h>
-#include <strutl.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/clean.h>
#include <config.h>
#include <fstream.h>
#include <termios.h>
#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
#include <signal.h>
+#include <unistd.h>
#include <stdio.h>
/*}}}*/
{
if (_config->FindB("APT::Get::Assume-Yes",false) == true)
{
- c2out << 'Y' << endl;
+ c1out << 'Y' << endl;
return true;
}
return true;
}
/*}}}*/
+// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
+// ---------------------------------------------------------------------
+/* Returns true on a Yes.*/
+bool AnalPrompt(const char *Text)
+{
+ char Buf[1024];
+ cin.getline(Buf,sizeof(Buf));
+ if (strcmp(Buf,Text) == 0)
+ return true;
+ return false;
+}
+ /*}}}*/
// ShowList - Show a list /*{{{*/
// ---------------------------------------------------------------------
/* This prints out a string of space seperated words with a title and
pkgCache::DepIterator Start;
pkgCache::DepIterator End;
D.GlobOr(Start,End);
-
+
if (Cache.IsImportantDep(End) == false ||
(Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
continue;
for (;I.end() != true; I++)
if (Dep[I].Delete() == true)
List += string(I.Name()) + " ";
+
ShowList(out,"The following packages will be REMOVED:",List);
}
/*}}}*/
inline pkgDepCache *operator ->() {return Cache;};
inline pkgDepCache &operator *() {return *Cache;};
- bool Open();
+ bool Open(bool AllowBroken = false);
CacheFile() : File(0), Map(0), Cache(0) {};
~CacheFile()
{
// ---------------------------------------------------------------------
/* This routine generates the caches and then opens the dependency cache
and verifies that the system is OK. */
-bool CacheFile::Open()
+bool CacheFile::Open(bool AllowBroken)
{
if (_error->PendingError() == true)
return false;
pkgMakeStatusCache(List,Progress);
if (_error->PendingError() == true)
return _error->Error("The package lists or status file could not be parsed or opened.");
+ if (_error->empty() == false)
+ _error->Warning("You may want to run apt-get update to correct theses missing files");
Progress.Done();
return false;
// Nothing is broken
- if (Cache->BrokenCount() == 0)
+ if (Cache->BrokenCount() == 0 || AllowBroken == true)
return true;
// Attempt to fix broken things
// ---------------------------------------------------------------------
/* This displays the informative messages describing what is going to
happen and then calls the download routines */
-bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true)
+bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true)
{
bool Fail = false;
+ bool Essential = false;
// Show all the various warning indicators
ShowDel(c1out,Cache);
ShowNew(c1out,Cache);
if (ShwKept == true)
ShowKept(c1out,Cache);
- Fail |= ShowHold(c1out,Cache);
+ Fail |= !ShowHold(c1out,Cache);
if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
ShowUpgraded(c1out,Cache);
- Fail |= ShowEssential(c1out,Cache);
+ Essential = !ShowEssential(c1out,Cache);
+ Fail |= Essential;
Stats(c1out,Cache);
// Sanity check
if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
Cache->BadCount() == 0)
- return true;
+ return true;
// Run the simulator ..
if (_config->FindB("APT::Get::Simulate") == true)
// Create the package manager and prepare to download
pkgDPkgPM PM(Cache);
- if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
+ 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;
}
-
+
+ // 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",
+ OutputDir.c_str());
+
// Number of bytes
c1out << "Need to get ";
if (DebBytes != FetchBytes)
- c1out << SizeToStr(FetchBytes) << '/' << SizeToStr(DebBytes);
+ c1out << SizeToStr(FetchBytes) << "b/" << SizeToStr(DebBytes) << 'b';
else
- c1out << SizeToStr(DebBytes);
+ c1out << SizeToStr(DebBytes) << 'b';
c1out << " of archives. After unpacking ";
// Size delta
if (Cache->UsrSize() >= 0)
- c1out << SizeToStr(Cache->UsrSize()) << " will be used." << endl;
+ c1out << SizeToStr(Cache->UsrSize()) << "b will be used." << endl;
else
- c1out << SizeToStr(-1*Cache->UsrSize()) << " will be freed." << endl;
+ c1out << SizeToStr(-1*Cache->UsrSize()) << "b will be freed." << endl;
if (_error->PendingError() == true)
return false;
// Fail safe check
- if (_config->FindB("APT::Get::Assume-Yes",false) == true)
+ 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");
}
-
- // Prompt to continue
- if (Ask == 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)
+ 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 is bad'" << endl;
+ c2out << " ?] " << flush;
+ if (AnalPrompt("Yes, I understand this is bad") == false)
+ {
+ c2out << "Abort." << endl;
exit(1);
- }
+ }
+ }
+ else
+ {
+ // Prompt to continue
+ if (Ask == 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);
+ }
+ }
+ }
+ }
+
+ 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
if (Fetcher.Run() == 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)->Describe() << endl;
cerr << " " << (*I)->ErrorText << endl;
Failed = true;
}
+
+ if (_config->FindB("APT::Get::Download-Only",false) == true)
+ return true;
- if (Failed == true && _config->FindB("APT::Fix-Missing",false) == false)
+ if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
+ {
+ if (Transient == true)
+ {
+ c2out << "Upgrading with disk swapping is not supported in this version." << endl;
+ c2out << "Try running multiple times with --fix-missing" << endl;
+ }
+
return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
-
+ }
+
// Try to deal with missing package files
if (PM.FixMissing() == false)
{
bool DoInstall(CommandLine &CmdL)
{
CacheFile Cache;
- if (Cache.Open() == false)
+ if (Cache.Open(CmdL.FileSize() != 1) == false)
return false;
+ // Enter the special broken fixing mode if the user specified arguments
+ bool BrokenFix = false;
+ if (Cache->BrokenCount() != 0)
+ BrokenFix = true;
+
unsigned int ExpectedInst = 0;
unsigned int Packages = 0;
pkgProblemResolver Fix(Cache);
pkgCache::PkgIterator Pkg = I.OwnerPkg();
if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
- c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
-
- if ((*Cache)[Pkg].InstVerIter(*Cache) == I.OwnerVer())
- c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
- " [Installed]"<< endl;
+ {
+ 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 explicly select one to install." << endl;
}
ExpectedInst++;
// Install it with autoinstalling enabled.
- if (State.InstBroken() == true)
+ if (State.InstBroken() == true && BrokenFix == false)
Cache->MarkInstall(Pkg,true);
}
+ /* If we are in the Broken fixing mode we do not attempt to fix the
+ problems. This is if the user invoked install without -f and gave
+ packages */
+ if (BrokenFix == true && Cache->BrokenCount() != 0)
+ {
+ c1out << "You might want to run `apt-get -f install' to correct these." << endl;
+ ShowBroken(c1out,Cache);
+
+ return _error->Error("Unmet dependencies. Try using -f.");
+ }
+
// Call the scored problem resolver
Fix.InstallProtect();
if (Fix.Resolve(true) == false)
/* Install the package only if it is a new install, the autoupgrader
will deal with the rest */
if (I->SelectedState == pkgCache::State::Install)
- Cache->MarkInstall(I);
+ Cache->MarkInstall(I,true);
}
// Apply erasures now, they override everything else.
Cache->MarkDelete(I);
}
- /* Use updates smart upgrade to do the rest, it will automatically
- ignore held items */
+ /* Resolve any problems that dselect created, allupgrade cannot handle
+ such things. We do so quite agressively too.. */
+ if (Cache->BrokenCount() != 0)
+ {
+ pkgProblemResolver Fix(Cache);
+
+ // Hold back held packages.
+ if (_config->FindB("APT::Ingore-Hold",false) == false)
+ {
+ for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
+ {
+ if (I->SelectedState == pkgCache::State::Hold)
+ {
+ Fix.Protect(I);
+ Cache->MarkKeep(I);
+ }
+ }
+ }
+
+ if (Fix.Resolve() == false)
+ {
+ ShowBroken(c1out,Cache);
+ return _error->Error("Internal Error, problem resolver broke stuff");
+ }
+ }
+
+ // Now upgrade everything
if (pkgAllUpgrade(Cache) == false)
{
ShowBroken(c1out,Cache);
- return _error->Error("Internal Error, AllUpgrade broke stuff");
+ return _error->Error("Internal Error, problem resolver broke stuff");
}
return InstallPackages(Cache,false);
return true;
}
/*}}}*/
+// DoAutoClean - Smartly remove downloaded archives /*{{{*/
+// ---------------------------------------------------------------------
+/* This is similar to clean but it only purges things that cannot be
+ downloaded, that is old versions of cached packages. */
+class LogCleaner : public pkgArchiveCleaner
+{
+ protected:
+ virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
+ {
+ cout << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "b]" << endl;
+ };
+};
+
+bool DoAutoClean(CommandLine &CmdL)
+{
+ CacheFile Cache;
+ if (Cache.Open(true) == false)
+ return false;
+
+ LogCleaner Cleaner;
+
+ return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
+ Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
+}
+ /*}}}*/
// DoCheck - Perform the check operation /*{{{*/
// ---------------------------------------------------------------------
/* Opening automatically checks the system, this command is mostly used
// ShowHelp - Show a help screen /*{{{*/
// ---------------------------------------------------------------------
/* */
-int ShowHelp()
+bool ShowHelp(CommandLine &CmdL)
{
cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
" compiled on " << __DATE__ << " " << __TIME__ << endl;
-
+ if (_config->FindB("version") == true)
+ return 100;
+
cout << "Usage: apt-get [options] command" << endl;
cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
cout << endl;
cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
cout << " dselect-upgrade - Follow dselect selections" << endl;
cout << " clean - Erase downloaded archive files" << endl;
+ cout << " autoclean - Erase old downloaded archive files" << endl;
cout << " check - Verify that there are no broken dependencies" << endl;
cout << endl;
cout << "Options:" << endl;
cout << " -u Show a list of upgraded packages as well" << endl;
cout << " -c=? Read this configuration file" << endl;
cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
- cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
+ cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
cout << "pages for more information." << endl;
return 100;
}
{
CommandLine::Args Args[] = {
{'h',"help","help",0},
+ {'v',"version","version",0},
{'q',"quiet","quiet",CommandLine::IntLevel},
{'q',"silent","quiet",CommandLine::IntLevel},
{'d',"download-only","APT::Get::Download-Only",0},
{0,"ignore-hold","APT::Ingore-Hold",0},
{0,"no-upgrade","APT::Get::no-upgrade",0},
{0,"force-yes","APT::Get::force-yes",0},
+ {0,"print-uris","APT::Get::Print-URIs",0},
{'c',"config-file",0,CommandLine::ConfigFile},
{'o',"option",0,CommandLine::ArbItem},
{0,0,0,0}};
{"dist-upgrade",&DoDistUpgrade},
{"dselect-upgrade",&DoDSelectUpgrade},
{"clean",&DoClean},
+ {"autoclean",&DoAutoClean},
{"check",&DoCheck},
+ {"help",&ShowHelp},
{0,0}};
// Parse the command line and initialize the package library
// See if the help should be shown
if (_config->FindB("help") == true ||
+ _config->FindB("version") == true ||
CmdL.FileSize() == 0)
- return ShowHelp();
+ return ShowHelp(CmdL);
+ // Deal with stdout not being a tty
+ if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
+ _config->Set("quiet","1");
+
// Setup the output streams
c0out.rdbuf(cout.rdbuf());
c1out.rdbuf(cout.rdbuf());
{
bool Errors = _error->PendingError();
_error->DumpErrors();
- if (Errors == true)
- cout << "Returning 100." << endl;
return Errors == true?100:0;
}