X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/421c8d109932a2615b9327c8b69aad715d4b1162..231fea14113439c08eba185830c58d716e905f87:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 652e86e48..4933e38a7 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-get.cc,v 1.77 1999/09/30 06:30:34 jgg Exp $ +// $Id: apt-get.cc,v 1.91 1999/11/28 01:03:28 jgg Exp $ /* ###################################################################### apt-get - Cover for dpkg @@ -52,6 +52,7 @@ #include #include #include +#include #include /*}}}*/ @@ -166,7 +167,7 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now) // Print out each package and the failed dependencies out <<" " << I.Name() << ":"; - int Indent = strlen(I.Name()) + 3; + unsigned Indent = strlen(I.Name()) + 3; bool First = true; if (Cache[I].InstVerIter(Cache).end() == true) { @@ -184,43 +185,62 @@ void ShowBroken(ostream &out,CacheFile &Cache,bool Now) if (Cache->IsImportantDep(End) == false || (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall) continue; - - if (First == false) - for (int J = 0; J != Indent; J++) - out << ' '; - First = false; - out << ' ' << End.DepType() << ": " << End.TargetPkg().Name(); - - // Show a quick summary of the version requirements - if (End.TargetVer() != 0) - out << " (" << End.CompType() << " " << End.TargetVer() << - ")"; - - /* Show a summary of the target package if possible. In the case - of virtual packages we show nothing */ - pkgCache::PkgIterator Targ = End.TargetPkg(); - if (Targ->ProvidesList == 0) + bool FirstOr = true; + while (1) { - out << " but "; - pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); - if (Ver.end() == false) - out << Ver.VerStr() << (Now?" is installed":" is to be installed"); + if (First == false) + for (unsigned J = 0; J != Indent; J++) + out << ' '; + First = false; + + if (FirstOr == false) + { + for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++) + out << ' '; + } else + out << ' ' << End.DepType() << ": "; + FirstOr = false; + + out << Start.TargetPkg().Name(); + + // Show a quick summary of the version requirements + if (Start.TargetVer() != 0) + out << " (" << Start.CompType() << " " << Start.TargetVer() << + ")"; + + /* Show a summary of the target package if possible. In the case + of virtual packages we show nothing */ + pkgCache::PkgIterator Targ = Start.TargetPkg(); + if (Targ->ProvidesList == 0) { - if (Cache[Targ].CandidateVerIter(Cache).end() == true) + out << " but "; + pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache); + if (Ver.end() == false) + out << Ver.VerStr() << (Now?" is installed":" is to be installed"); + else { - if (Targ->ProvidesList == 0) - out << "it is not installable"; + if (Cache[Targ].CandidateVerIter(Cache).end() == true) + { + if (Targ->ProvidesList == 0) + out << "it is not installable"; + else + out << "it is a virtual package"; + } else - out << "it is a virtual package"; - } - else - out << (Now?"it is not installed":"it is not going to be installed"); - } - } - - out << endl; + out << (Now?"it is not installed":"it is not going to be installed"); + } + } + + if (Start != End) + cout << " or"; + out << endl; + + if (Start == End) + break; + Start++; + } } } } @@ -388,6 +408,7 @@ void Stats(ostream &out,pkgDepCache &Dep) { unsigned long Upgrade = 0; unsigned long Install = 0; + unsigned long ReInstall = 0; for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++) { if (Dep[I].NewInstall() == true) @@ -395,11 +416,15 @@ void Stats(ostream &out,pkgDepCache &Dep) else if (Dep[I].Upgrade() == true) Upgrade++; + if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall) + ReInstall++; } out << Upgrade << " packages upgraded, " << - Install << " newly installed, " << - Dep.DelCount() << " to remove and " << + Install << " newly installed, "; + if (ReInstall != 0) + out << ReInstall << " reinstalled, "; + out << Dep.DelCount() << " to remove and " << Dep.KeepCount() << " not upgraded." << endl; if (Dep.BadCount() != 0) @@ -525,10 +550,14 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = return _error->Error("Internal Error, InstallPackages was called with broken packages!"); } - if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && + if (Cache->DelCount() == 0 && Cache->InstCount() == 0 && Cache->BadCount() == 0) return true; + // No remove flag + if (Cache->DelCount() != 0 && _config->FindB("APT::Get::No-Remove",false) == true) + return _error->Error("Packages need to be removed but No Remove was specified."); + // Run the simulator .. if (_config->FindB("APT::Get::Simulate") == true) { @@ -579,16 +608,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = 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 "; @@ -608,6 +627,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = if (_error->PendingError() == true) return false; + // 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()); + // Fail safe check if (_config->FindI("quiet",0) >= 2 || _config->FindB("APT::Get::Assume-Yes",false) == true) @@ -618,6 +647,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = if (Essential == true && Saftey == true) { + if (_config->FindB("APT::Get::Trivial-Only",false) == true) + return _error->Error("Trivial Only specified but this is not a trivial operation."); + 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; @@ -628,10 +660,13 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = } } else - { + { // Prompt to continue if (Ask == true || Fail == true) { + if (_config->FindB("APT::Get::Trivial-Only",false) == true) + return _error->Error("Trivial Only specified but this is not a trivial operation."); + if (_config->FindI("quiet",0) < 2 && _config->FindB("APT::Get::Assume-Yes",false) == false) { @@ -660,7 +695,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = while (1) { if (_config->FindB("APT::Get::No-Download",false) == false) - if( Fetcher.Run() == pkgAcquire::Failed) + if (Fetcher.Run() == pkgAcquire::Failed) return false; // Print out errors @@ -672,8 +707,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = (*I)->Complete == true) continue; - (*I)->Finished(); - if ((*I)->Status == pkgAcquire::Item::StatIdle) { Transient = true; @@ -685,6 +718,16 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = 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) { @@ -695,12 +738,6 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = 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?"); } @@ -728,6 +765,124 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = } } /*}}}*/ +// 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, selecting " << 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 (Remove == true && Pkg->CurrentVer == 0) + { + if (AllowFail == false) + return false; + return _error->Error("Package %s is not installed",Pkg.Name()); + } + + if (State.CandidateVer == 0 && Remove == false) + { + 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, has been obsoleted or is not available with the contents " << endl; + c1out << "of sources.list" << 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); + } + + _error->Error("Package %s has no installation candidate",Pkg.Name()); + return false; + } + + Fix.Clear(Pkg); + Fix.Protect(Pkg); + if (Remove == true) + { + Fix.Remove(Pkg); + Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false)); + return true; + } + + // Install it + Cache.MarkInstall(Pkg,false); + if (State.Install() == false) + { + if (_config->FindB("APT::Get::ReInstall",false) == true) + { + if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false) + c1out << "Sorry, re-installation of " << Pkg.Name() << " is not possible, it cannot be downloaded" << endl; + else + Cache.SetReInstall(Pkg,true); + } + else + { + if (AllowFail == true) + c1out << "Sorry, " << Pkg.Name() << " is already the newest version" << endl; + } + } + else + ExpectedInst++; + + // Install it with autoinstalling enabled. + if (State.InstBroken() == true && BrokenFix == false) + Cache.MarkInstall(Pkg,true); + return true; +} + /*}}}*/ // DoUpdate - Update the package lists /*{{{*/ // --------------------------------------------------------------------- @@ -872,78 +1027,44 @@ bool DoInstall(CommandLine &CmdL) pkgCache::PkgIterator Pkg = Cache->FindPkg(S); Packages++; if (Pkg.end() == true) - return _error->Error("Couldn't find package %s",S); - - // Handle the no-upgrade case - if (_config->FindB("APT::Get::no-upgrade",false) == true && - Pkg->CurrentVer != 0) { - c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl; - continue; - } - - // Check if there is something new to install - pkgDepCache::StateCache &State = (*Cache)[Pkg]; - if (State.CandidateVer == 0) - { - if (Pkg->ProvidesList != 0) - { - c1out << "Package " << S << " 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 explicly select one to install." << endl; - } - else + // Check if the name is a regex + const char *I; + for (I = S; *I != 0; I++) + if (*I == '.' || *I == '?' || *I == '*') + break; + if (*I == 0) + return _error->Error("Couldn't find package %s",S); + + // Regexs must always be confirmed + ExpectedInst += 1000; + + // Compile the regex pattern + regex_t Pattern; + if (regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE | + REG_NOSUB) != 0) + return _error->Error("Regex compilation error"); + + // Run over the matches + bool Hit = false; + for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++) { - c1out << "Package " << S << " 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; + if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0) + continue; - 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); + Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix, + ExpectedInst,false); } + regfree(&Pattern); - return _error->Error("Package %s has no installation candidate",S); + if (Hit == false) + return _error->Error("Couldn't find package %s",S); } - - Fix.Protect(Pkg); - if (Remove == true) - { - Fix.Remove(Pkg); - Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false)); - continue; - } - - // Install it - Cache->MarkInstall(Pkg,false); - if (State.Install() == false) - c1out << "Sorry, " << S << " is already the newest version" << endl; else - ExpectedInst++; - - // Install it with autoinstalling enabled. - if (State.InstBroken() == true && BrokenFix == false) - Cache->MarkInstall(Pkg,true); + { + if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false) + return false; + } } /* If we are in the Broken fixing mode we do not attempt to fix the @@ -1114,6 +1235,22 @@ bool DoDSelectUpgrade(CommandLine &CmdL) /* */ bool DoClean(CommandLine &CmdL) { + if (_config->FindB("APT::Get::Simulate") == true) + { + cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " << + _config->FindDir("Dir::Cache::archives") << "partial/*" << endl; + return true; + } + + // 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"); + } + pkgAcquire Fetcher; Fetcher.Clean(_config->FindDir("Dir::Cache::archives")); Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/"); @@ -1138,6 +1275,15 @@ class LogCleaner : public pkgArchiveCleaner bool DoAutoClean(CommandLine &CmdL) { + // 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"); + } + CacheFile Cache; if (Cache.Open() == false) return false; @@ -1515,11 +1661,11 @@ int main(int argc,const char *argv[]) {'d',"download-only","APT::Get::Download-Only",0}, {'b',"compile","APT::Get::Compile",0}, {'b',"build","APT::Get::Compile",0}, - {'s',"simulate","APT::Get::Simulate",0}, - {'s',"just-print","APT::Get::Simulate",0}, - {'s',"recon","APT::Get::Simulate",0}, - {'s',"no-act","APT::Get::Simulate",0}, - {'y',"yes","APT::Get::Assume-Yes",0}, + {'s',"simulate","APT::Get::Simulate",0}, + {'s',"just-print","APT::Get::Simulate",0}, + {'s',"recon","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}, {'f',"fix-broken","APT::Get::Fix-Broken",0}, {'u',"show-upgraded","APT::Get::Show-Upgraded",0}, @@ -1534,6 +1680,9 @@ int main(int argc,const char *argv[]) {0,"tar-only","APT::Get::tar-Only",0}, {0,"purge","APT::Get::Purge",0}, {0,"list-cleanup","APT::Get::List-Cleanup",0}, + {0,"reinstall","APT::Get::ReInstall",0}, + {0,"trivial-only","APT::Get::Trivial-Only",0}, + {0,"no-remove","APT::Get::No-Remove",0}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}};