X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/38262e68caaa74127c951f45fe164ffc3d8cf38b..d556d1a1cc89e0f99d1b76fd6da72fd0174f5862:/cmdline/apt-get.cc?ds=sidebyside diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index a2c013206..67352c868 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.51 1999/04/12 02:25:25 jgg Exp $ +// $Id: apt-get.cc,v 1.69 1999/07/10 04:58:42 jgg Exp $ /* ###################################################################### apt-get - Cover for dpkg @@ -30,15 +30,14 @@ #include #include #include -#include #include #include #include -#include #include #include #include #include +#include #include @@ -52,6 +51,8 @@ #include #include #include +#include +#include /*}}}*/ ostream c0out; @@ -163,7 +164,7 @@ void ShowBroken(ostream &out,pkgDepCache &Cache) out << ' '; First = false; - cout << ' ' << End.DepType() << ": " << End.TargetPkg().Name(); + out << ' ' << End.DepType() << ": " << End.TargetPkg().Name(); // Show a quick summary of the version requirements if (End.TargetVer() != 0) @@ -224,8 +225,15 @@ void ShowDel(ostream &out,pkgDepCache &Dep) pkgCache::PkgIterator I = Dep.PkgBegin(); string List; for (;I.end() != true; I++) + { if (Dep[I].Delete() == true) - List += string(I.Name()) + " "; + { + if ((Dep[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) + List += string(I.Name()) + "* "; + else + List += string(I.Name()) + " "; + } + } ShowList(out,"The following packages will be REMOVED:",List); } @@ -372,70 +380,27 @@ void Stats(ostream &out,pkgDepCache &Dep) // class CacheFile - Cover class for some dependency cache functions /*{{{*/ // --------------------------------------------------------------------- /* */ -class CacheFile +class CacheFile : public pkgCacheFile { public: - FileFd *File; - MMap *Map; - pkgDepCache *Cache; - pkgDpkgLock Lock; - - inline operator pkgDepCache &() {return *Cache;}; - inline pkgDepCache *operator ->() {return Cache;}; - inline pkgDepCache &operator *() {return *Cache;}; - - bool Open(bool AllowBroken = false); - CacheFile() : File(0), Map(0), Cache(0) {}; - ~CacheFile() + bool CheckDeps(bool AllowBroken = false); + bool Open(bool WithLock = true) { - delete Cache; - delete Map; - delete File; - } + OpTextProgress Prog(*_config); + return pkgCacheFile::Open(Prog,WithLock); + }; }; /*}}}*/ // CacheFile::Open - Open the cache file /*{{{*/ // --------------------------------------------------------------------- /* This routine generates the caches and then opens the dependency cache and verifies that the system is OK. */ -bool CacheFile::Open(bool AllowBroken) +bool CacheFile::CheckDeps(bool AllowBroken) { if (_error->PendingError() == true) return false; - - // Create a progress class - OpTextProgress Progress(*_config); - - // Read the source list - pkgSourceList List; - if (List.ReadMainList() == false) - return _error->Error("The list of sources could not be read."); - - // Build all of the caches - 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(); - - // Open the cache file - File = new FileFd(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly); - if (_error->PendingError() == true) - return false; - - Map = new MMap(*File,MMap::Public | MMap::ReadOnly); - if (_error->PendingError() == true) - return false; - - Cache = new pkgDepCache(*Map,Progress); - if (_error->PendingError() == true) - return false; - Progress.Done(); - // Check that the system is OK if (Cache->DelCount() != 0 || Cache->InstCount() != 0) return _error->Error("Internal Error, non-zero counts"); @@ -482,6 +447,16 @@ bool CacheFile::Open(bool AllowBroken) happen and then calls the download routines */ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = true) { + if (_config->FindB("APT::Get::Purge",false) == true) + { + pkgCache::PkgIterator I = Cache->PkgBegin(); + for (; I.end() == false; I++) + { + if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete) + Cache->MarkDelete(I,true); + } + } + bool Fail = false; bool Essential = false; @@ -512,7 +487,12 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = if (_config->FindB("APT::Get::Simulate") == true) { pkgSimulate PM(Cache); - return PM.DoInstall(); + 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 @@ -567,17 +547,17 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = // Number of bytes c1out << "Need to get "; if (DebBytes != FetchBytes) - c1out << SizeToStr(FetchBytes) << "b/" << SizeToStr(DebBytes) << 'b'; + c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B'; else - c1out << SizeToStr(DebBytes) << 'b'; + c1out << SizeToStr(DebBytes) << 'B'; c1out << " of archives. After unpacking "; // Size delta if (Cache->UsrSize() >= 0) - c1out << SizeToStr(Cache->UsrSize()) << "b will be used." << endl; + c1out << SizeToStr(Cache->UsrSize()) << "B will be used." << endl; else - c1out << SizeToStr(-1*Cache->UsrSize()) << "b will be freed." << endl; + c1out << SizeToStr(-1*Cache->UsrSize()) << "B will be freed." << endl; if (_error->PendingError() == true) return false; @@ -631,53 +611,75 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,bool Saftey = } // Run it - if (Fetcher.Run() == false) - return false; - - // Print out errors - bool Failed = false; - bool Transient = false; - for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) + while (1) { - if ((*I)->Status == pkgAcquire::Item::StatDone && - (*I)->Complete == true) - continue; + if (_config->FindB("APT::Get::No-Download",false) == false) + if( Fetcher.Run() == pkgAcquire::Failed) + return false; - if ((*I)->Status == pkgAcquire::Item::StatIdle) + // Print out errors + bool Failed = false; + bool Transient = false; + for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) { - Transient = true; + if ((*I)->Status == pkgAcquire::Item::StatDone && + (*I)->Complete == true) + continue; + + (*I)->Finished(); + + if ((*I)->Status == pkgAcquire::Item::StatIdle) + { + Transient = true; + // Failed = true; + continue; + } + + cerr << "Failed to fetch " << (*I)->DescURI() << endl; + cerr << " " << (*I)->ErrorText << endl; Failed = true; - continue; } - cerr << "Failed to fetch " << (*I)->DescURI() << endl; - cerr << " " << (*I)->ErrorText << endl; - Failed = true; - } - - if (_config->FindB("APT::Get::Download-Only",false) == true) - return true; - - if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) - { - if (Transient == true) + if (_config->FindB("APT::Get::Download-Only",false) == true) { - c2out << "Upgrading with disk swapping is not supported in this version." << endl; - c2out << "Try running multiple times with --fix-missing" << endl; + if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false) + return _error->Error("Some files failed to download"); + return true; } - return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?"); - } - - // Try to deal with missing package files - if (PM.FixMissing() == false) - { - cerr << "Unable to correct missing packages." << endl; - return _error->Error("Aborting Install."); - } - - Cache.Lock.Close(); - return PM.DoInstall(); + 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?"); + } + + 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; + } } /*}}}*/ @@ -714,7 +716,7 @@ bool DoUpdate(CommandLine &) } // Run it - if (Fetcher.Run() == false) + if (Fetcher.Run() == pkgAcquire::Failed) return false; // Clean out any old list files @@ -737,7 +739,7 @@ bool DoUpdate(CommandLine &) bool DoUpgrade(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open() == false) + if (Cache.Open() == false || Cache.CheckDeps() == false) return false; // Do the upgrade @@ -756,7 +758,7 @@ bool DoUpgrade(CommandLine &CmdL) bool DoInstall(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open(CmdL.FileSize() != 1) == false) + if (Cache.Open() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false) return false; // Enter the special broken fixing mode if the user specified arguments @@ -783,19 +785,23 @@ bool DoInstall(CommandLine &CmdL) // See if we are removing the package bool Remove = DefRemove; - if (Cache->FindPkg(S).end() == true) + while (Cache->FindPkg(S).end() == true) { // Handle an optional end tag indicating what to do if (S[Length - 1] == '-') { Remove = true; S[--Length] = 0; + continue; } + if (S[Length - 1] == '+') { Remove = false; S[--Length] = 0; + continue; } + break; } // Locate the package @@ -860,7 +866,7 @@ bool DoInstall(CommandLine &CmdL) if (Remove == true) { Fix.Remove(Pkg); - Cache->MarkDelete(Pkg); + Cache->MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false)); continue; } @@ -881,10 +887,10 @@ bool DoInstall(CommandLine &CmdL) packages */ if (BrokenFix == true && Cache->BrokenCount() != 0) { - c1out << "You might want to run `apt-get -f install' to correct these." << endl; + 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."); + return _error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."); } // Call the scored problem resolver @@ -949,7 +955,7 @@ bool DoInstall(CommandLine &CmdL) bool DoDistUpgrade(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open() == false) + if (Cache.Open() == false || Cache.CheckDeps() == false) return false; c0out << "Calculating Upgrade... " << flush; @@ -971,7 +977,7 @@ bool DoDistUpgrade(CommandLine &CmdL) bool DoDSelectUpgrade(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open() == false) + if (Cache.Open() == false || Cache.CheckDeps() == false) return false; // Install everything with the install flag set @@ -1000,7 +1006,7 @@ bool DoDSelectUpgrade(CommandLine &CmdL) // Remove packages if (I->SelectedState == pkgCache::State::DeInstall || I->SelectedState == pkgCache::State::Purge) - Cache->MarkDelete(I); + Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge); } /* Resolve any problems that dselect created, allupgrade cannot handle @@ -1059,14 +1065,17 @@ 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; + cout << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl; + + if (_config->FindB("APT::Get::Simulate") == false) + unlink(File); }; }; bool DoAutoClean(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open(true) == false) + if (Cache.Open() == false) return false; LogCleaner Cleaner; @@ -1083,19 +1092,30 @@ bool DoCheck(CommandLine &CmdL) { CacheFile Cache; Cache.Open(); + Cache.CheckDeps(); return true; } /*}}}*/ // DoSource - Fetch a source archive /*{{{*/ // --------------------------------------------------------------------- -/* */ +/* Fetch souce packages */ +struct DscFile +{ + string Package; + string Version; + string Dsc; +}; + bool DoSource(CommandLine &CmdL) { CacheFile Cache; - if (Cache.Open(true) == false) + if (Cache.Open(false) == false) return false; + if (CmdL.FileSize() <= 1) + return _error->Error("Must specify at least one package to fetch source for"); + // Read the source list pkgSourceList List; if (List.ReadMainList() == false) @@ -1110,9 +1130,12 @@ bool DoSource(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); pkgAcquire Fetcher(&Stat); + + DscFile *Dsc = new DscFile[CmdL.FileSize()]; // Load the requestd sources into the fetcher - for (const char **I = CmdL.FileList + 1; *I != 0; I++) + unsigned J = 0; + for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) { string Src; @@ -1140,6 +1163,7 @@ bool DoSource(CommandLine &CmdL) pkgSrcRecords::Parser *Last = 0; unsigned long Offset = 0; string Version; + bool IsMatch = false; // Iterate over all of the hits pkgSrcRecords::Parser *Parse; @@ -1147,8 +1171,16 @@ bool DoSource(CommandLine &CmdL) while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0) { string Ver = Parse->Version(); - if (Last == 0 || pkgVersionCompare(Version,Ver) < 0) + + // Skip name mismatches + if (IsMatch == true && Parse->Package() != Src) + continue; + + // Newer version or an exact match + if (Last == 0 || pkgVersionCompare(Version,Ver) < 0 || + (Parse->Package() == Src && IsMatch == false)) { + IsMatch = Parse->Package() == Src; Last = Parse; Offset = Parse->Offset(); Version = Ver; @@ -1170,7 +1202,13 @@ bool DoSource(CommandLine &CmdL) // Try to guess what sort of file it is we are getting. string Comp; if (I->Path.find(".dsc") != string::npos) + { Comp = "dsc"; + Dsc[J].Package = Last->Package(); + Dsc[J].Version = Last->Version(); + Dsc[J].Dsc = flNotDir(I->Path); + } + if (I->Path.find(".tar.gz") != string::npos) Comp = "tar"; if (I->Path.find(".diff.gz") != string::npos) @@ -1200,11 +1238,18 @@ bool DoSource(CommandLine &CmdL) // Number of bytes c1out << "Need to get "; if (DebBytes != FetchBytes) - c1out << SizeToStr(FetchBytes) << "b/" << SizeToStr(DebBytes) << 'b'; + c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B'; else - c1out << SizeToStr(DebBytes) << 'b'; + c1out << SizeToStr(DebBytes) << 'B'; c1out << " of source archives." << endl; + if (_config->FindB("APT::Get::Simulate",false) == true) + { + for (unsigned I = 0; I != J; I++) + cout << "Fetch Source " << Dsc[I].Package << endl; + return true; + } + // Just print out the uris an exit if the --print-uris flag was used if (_config->FindB("APT::Get::Print-URIs") == true) { @@ -1216,10 +1261,11 @@ bool DoSource(CommandLine &CmdL) } // Run it - if (Fetcher.Run() == false) + if (Fetcher.Run() == pkgAcquire::Failed) return false; // Print error messages + bool Failed = false; for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++) { if ((*I)->Status == pkgAcquire::Item::StatDone && @@ -1228,7 +1274,76 @@ bool DoSource(CommandLine &CmdL) cerr << "Failed to fetch " << (*I)->DescURI() << endl; cerr << " " << (*I)->ErrorText << endl; + Failed = true; + } + if (Failed == true) + return _error->Error("Failed to fetch some archives."); + + if (_config->FindB("APT::Get::Download-only",false) == true) + return true; + + // Unpack the sources + pid_t Process = ExecFork(); + + if (Process == 0) + { + for (unsigned I = 0; I != J; I++) + { + string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str()); + + // See if the package is already unpacked + struct stat Stat; + if (stat(Dir.c_str(),&Stat) == 0 && + S_ISDIR(Stat.st_mode) != 0) + { + c0out << "Skipping unpack of already unpacked source in " << Dir << endl; + } + else + { + // Call dpkg-source + char S[500]; + snprintf(S,sizeof(S),"%s -x %s", + _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(), + Dsc[I].Dsc.c_str()); + if (system(S) != 0) + { + cerr << "Unpack command '" << S << "' failed." << endl; + _exit(1); + } + } + + // Try to compile it with dpkg-buildpackage + if (_config->FindB("APT::Get::Compile",false) == true) + { + // 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()); + + if (system(S) != 0) + { + cerr << "Build command '" << S << "' failed." << endl; + _exit(1); + } + } + } + + _exit(0); + } + + // Wait for the subprocess + int Status = 0; + while (waitpid(Process,&Status,0) != Process) + { + if (errno == EINTR) + continue; + return _error->Errno("waitpid","Couldn't wait for subprocess"); } + + if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) + return _error->Error("Child process failed"); return true; } @@ -1273,10 +1388,11 @@ bool ShowHelp(CommandLine &CmdL) cout << " -f Attempt to continue if the integrity check fails" << endl; cout << " -m Attempt to continue if archives are unlocatable" << endl; cout << " -u Show a list of upgraded packages as well" << endl; + cout << " -b Build the source package after fetching it" << endl; cout << " -c=? Read this configuration file" << endl; cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl; cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl; - cout << "pages for more information." << endl; + cout << "pages for more information and options." << endl; return 100; } /*}}}*/ @@ -1317,6 +1433,8 @@ int main(int argc,const char *argv[]) {'q',"quiet","quiet",CommandLine::IntLevel}, {'q',"silent","quiet",CommandLine::IntLevel}, {'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}, @@ -1326,11 +1444,13 @@ int main(int argc,const char *argv[]) {'f',"fix-broken","APT::Get::Fix-Broken",0}, {'u',"show-upgraded","APT::Get::Show-Upgraded",0}, {'m',"ignore-missing","APT::Get::Fix-Missing",0}, + {0,"no-download","APT::Get::No-Download",0}, {0,"fix-missing","APT::Get::Fix-Missing",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}, + {0,"purge","APT::Get::Purge",0}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}};