X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/e234fa49da6ae970227358a4275d9bf4344c21b5..c8db3fff877f102dc6fb62c4e4c7f700160b68f5:/cmdline/apt-get.cc diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 7875ae20f..d3ddcbfe8 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -40,11 +40,12 @@ #include #include #include - + #include #include #include "acqprogress.h" +#include "cacheset.h" #include #include @@ -90,14 +91,14 @@ class CacheFile : public pkgCacheFile bool BuildCaches(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::BuildCaches(Prog,WithLock) == false) + if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false) return false; return true; } bool Open(bool WithLock = true) { OpTextProgress Prog(*_config); - if (pkgCacheFile::Open(Prog,WithLock) == false) + if (pkgCacheFile::Open(&Prog,WithLock) == false) return false; Sort(); @@ -692,7 +693,7 @@ bool CacheFile::CheckDeps(bool AllowBroken) } else { - 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,*this,true); return _error->Error(_("Unmet dependencies. Try using -f.")); @@ -811,20 +812,19 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, pkgRecords Recs(Cache); if (_error->PendingError() == true) return false; - - // Lock the archive directory - FileFd Lock; - if (_config->FindB("Debug::NoLocking",false) == false && - _config->FindB("APT::Get::Print-URIs") == 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 + pkgAcquire Fetcher; AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + if (_config->FindB("APT::Get::Print-URIs", false) == true) + { + // force a hashsum for compatibility reasons + _config->CndSet("Acquire::ForceHash", "md5sum"); + if (Fetcher.Setup(&Stat, "") == false) + return false; + } + else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false) + return false; // Read the source list pkgSourceList List; @@ -838,9 +838,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, return false; // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); if (DebBytes != Cache->DebSize()) { c0out << DebBytes << ',' << Cache->DebSize() << endl; @@ -1045,7 +1045,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, if (Res == pkgPackageManager::Failed || _error->PendingError() == true) return false; if (Res == pkgPackageManager::Completed) - return true; + break; // Reload the fetcher object and loop again for media swapping Fetcher.Shutdown(); @@ -1053,7 +1053,24 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, return false; _system->Lock(); - } + } + + std::set const disappearedPkgs = PM->GetDisappearedPackages(); + if (disappearedPkgs.empty() == true) + return true; + + string disappear; + for (std::set::const_iterator d = disappearedPkgs.begin(); + d != disappearedPkgs.end(); ++d) + disappear.append(*d).append(" "); + + ShowList(c1out, P_("The following package disappeared from your system as\n" + "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; + + return true; } /*}}}*/ // TryToInstall - Try to install a single package /*{{{*/ @@ -1062,43 +1079,8 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, 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) + bool AllowFail = true) { - /* This is a pure virtual package and there is a single available - candidate providing it. */ - if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0) - { - pkgCache::PkgIterator Prov; - bool found_one = false; - - for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; P++) - { - pkgCache::VerIterator const PVer = P.OwnerVer(); - pkgCache::PkgIterator const PPkg = PVer.ParentPkg(); - - /* Ignore versions that are not a candidate. */ - if (Cache[PPkg].CandidateVer != PVer) - continue; - - if (found_one == false) - { - Prov = PPkg; - found_one = true; - } - else if (PPkg != Prov) - { - found_one = false; // we found at least two - break; - } - } - - if (found_one == true) - { - ioprintf(c1out,_("Note, selecting %s instead of %s\n"), - Prov.FullName(true).c_str(),Pkg.FullName(true).c_str()); - Pkg = Prov; - } - } // Handle the no-upgrade case if (_config->FindB("APT::Get::upgrade",true) == false && @@ -1148,20 +1130,27 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, Pkg.FullName(true).c_str()); pkgCache::PrvIterator I = Pkg.ProvidesList(); + unsigned short provider = 0; for (; I.end() == false; I++) { pkgCache::PkgIterator Pkg = I.OwnerPkg(); if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) { + c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr(); if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false) - c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr() << - _(" [Installed]") << endl; - else - c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr() << endl; - } + c1out << _(" [Installed]"); + c1out << endl; + ++provider; + } } - c1out << _("You should explicitly select one to install.") << endl; + // if we found no candidate which provide this package, show non-candidates + if (provider == 0) + for (I = Pkg.ProvidesList(); I.end() == false; I++) + c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr() + << _(" [Not candidate version]") << endl; + else + c1out << _("You should explicitly select one to install.") << endl; } else { @@ -1220,9 +1209,7 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, Pkg.FullName(true).c_str()); } } - else - ExpectedInst++; - + // Install it with autoinstalling enabled (if we not respect the minial // required deps or the policy) if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false) @@ -1231,36 +1218,6 @@ bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, return true; } /*}}}*/ -// TryToChangeVer - Try to change a candidate version /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache, - const char *VerTag,bool IsRel) -{ - pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release : - pkgVersionMatch::Version)); - - pkgCache::VerIterator Ver = Match.Find(Pkg); - - if (Ver.end() == true) - { - if (IsRel == true) - return _error->Error(_("Release '%s' for '%s' was not found"), - VerTag,Pkg.FullName(true).c_str()); - return _error->Error(_("Version '%s' for '%s' was not found"), - VerTag,Pkg.FullName(true).c_str()); - } - - if (strcmp(VerTag,Ver.VerStr()) != 0) - { - ioprintf(c1out,_("Selected version %s (%s) for %s\n"), - Ver.VerStr(),Ver.RelStr().c_str(),Pkg.FullName(true).c_str()); - } - - Cache.SetCandidateVersion(Ver); - return true; -} - /*}}}*/ // FindSrc - Find a source record /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -1291,12 +1248,30 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, { if(VerTag.empty() == false || DefRel.empty() == false) { + bool fuzzy = false; // 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.end() == false; Ver++) + for (pkgCache::VerIterator Ver = Pkg.VersionList();; Ver++) { + // try first only exact matches, later fuzzy matches + if (Ver.end() == true) + { + if (fuzzy == true) + break; + fuzzy = true; + Ver = Pkg.VersionList(); + // exit right away from the Pkg.VersionList() loop if we + // don't have any versions + if (Ver.end() == true) + break; + } + // We match against a concrete version (or a part of this version) + if (VerTag.empty() == false && + (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match + (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match + continue; + for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false; VF++) { @@ -1309,10 +1284,6 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver) continue; - // We match against a concrete version (or a part of this version) - if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0) - continue; - // or we match against a release if(VerTag.empty() == false || (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) || @@ -1323,10 +1294,9 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, // no SourcePkg name, so it is the "binary" name if (Src.empty() == true) Src = TmpSrc; - // no Version, so we try the Version of the SourcePkg - - // and after that the version of the binary package - if (VerTag.empty() == true) - VerTag = Parse.SourceVer(); + // the Version we have is possibly fuzzy or includes binUploads, + // so we use the Version of the SourcePkg (empty if same as package) + VerTag = Parse.SourceVer(); if (VerTag.empty() == true) VerTag = Ver.VerStr(); break; @@ -1338,9 +1308,11 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Src.empty() == true) { // Sources files have no codename information - if (VerTag.empty() == true && DefRel.empty() == false) - _error->Warning(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str()); - DefRel.clear(); + if (VerTag.empty() == true && DefRel.empty() == false) + { + _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str()); + return 0; + } } } if (Src.empty() == true) @@ -1390,7 +1362,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, const string Ver = Parse->Version(); // Ignore all versions which doesn't fit - if (VerTag.empty() == false && strncmp(VerTag.c_str(), Ver.c_str(), VerTag.size()) != 0) + if (VerTag.empty() == false && + Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match continue; // Newer version or an exact match? Save the hit @@ -1407,8 +1380,8 @@ pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs, if (Last != 0 || VerTag.empty() == true) break; //if (VerTag.empty() == false && Last == 0) - _error->Warning(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); - VerTag.clear(); + _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str()); + return 0; } if (Last == 0 || Last->Jump(Offset) == false) @@ -1430,23 +1403,19 @@ bool DoUpdate(CommandLine &CmdL) if (List.ReadMainList() == false) return false; - // Lock the list directory - FileFd Lock; - if (_config->FindB("Debug::NoLocking",false) == false) - { - Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); - if (_error->PendingError() == true) - return _error->Error(_("Unable to lock the list directory")); - } - // Create the progress AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); // Just print out the uris an exit if the --print-uris flag was used if (_config->FindB("APT::Get::Print-URIs") == true) { + // force a hashsum for compatibility reasons + _config->CndSet("Acquire::ForceHash", "md5sum"); + // get a fetcher - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; // Populate it with the source selection and get all Indexes // (GetAll=true) @@ -1583,60 +1552,87 @@ bool DoUpgrade(CommandLine &CmdL) return InstallPackages(Cache,true); } /*}}}*/ -// DoInstallTask - Install task from the command line /*{{{*/ -// --------------------------------------------------------------------- -/* Install named task */ -bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix, - bool BrokenFix, - unsigned int& ExpectedInst, - const char *taskname, - bool Remove) -{ - const char *start, *end; - pkgCache::PkgIterator Pkg; - char buf[64*1024]; - regex_t Pattern; - - // get the records - pkgRecords Recs(Cache); +// CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/ +class CacheSetHelperAPTGet : public APT::CacheSetHelper { + /** \brief stream message should be printed to */ + std::ostream &out; + /** \brief were things like Task or RegEx used to select packages? */ + bool explicitlyNamed; + +public: + CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) { + 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()); + 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()); + explicitlyNamed = false; + } + virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver, + string const &ver, bool const &verIsRel) { + if (ver != Ver.VerStr()) + ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"), + Ver.VerStr(), Ver.RelStr().c_str(), Pkg.FullName(true).c_str()); + } + + virtual APT::VersionSet canNotFindCandInstVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + return tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDINST); + } + + virtual APT::VersionSet canNotFindInstCandVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) { + return tryVirtualPackage(Cache, Pkg, APT::VersionSet::INSTCAND); + } + + APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg, + APT::VersionSet::Version const &select) { + /* This is a pure virtual package and there is a single available + candidate providing it. */ + if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0) { + if (select == APT::VersionSet::CANDINST) + return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg); + return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg); + } + + pkgCache::PkgIterator Prov; + bool found_one = false; + for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) { + pkgCache::VerIterator const PVer = P.OwnerVer(); + pkgCache::PkgIterator const PPkg = PVer.ParentPkg(); + + /* Ignore versions that are not a candidate. */ + if (Cache[PPkg].CandidateVer != PVer) + continue; + + if (found_one == false) { + Prov = PPkg; + found_one = true; + } else if (PPkg != Prov) { + found_one = false; // we found at least two + break; + } + } + + if (found_one == true) { + ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"), + Prov.FullName(true).c_str(), Pkg.FullName(true).c_str()); + return APT::VersionSet::FromPackage(Cache, Prov, select, *this); + } + if (select == APT::VersionSet::CANDINST) + return APT::CacheSetHelper::canNotFindCandInstVer(Cache, Pkg); + return APT::CacheSetHelper::canNotFindInstCandVer(Cache, Pkg); + } + + inline bool allPkgNamedExplicitly() const { return explicitlyNamed; } - // build regexp for the task - char S[300]; - snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname); - if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0) - return _error->Error("Failed to compile task regexp"); - - bool found = false; - bool res = true; - - // two runs, first ignore dependencies, second install any missing - for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--) - { - for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++) - { - pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache); - if(ver.end()) - continue; - pkgRecords::Parser &parser = Recs.Lookup(ver.FileList()); - parser.GetRec(start,end); - strncpy(buf, start, end-start); - buf[end-start] = 0x0; - if (regexec(&Pattern,buf,0,0,0) != 0) - continue; - res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst); - found = true; - } - } - - // now let the problem resolver deal with any issues - Fix.Resolve(true); - - if(!found) - _error->Error(_("Couldn't find task %s"),taskname); - - regfree(&Pattern); - return res; -} +}; /*}}}*/ // DoInstall - Install packages from the command line /*{{{*/ // --------------------------------------------------------------------- @@ -1654,169 +1650,96 @@ bool DoInstall(CommandLine &CmdL) BrokenFix = true; unsigned int AutoMarkChanged = 0; - unsigned int ExpectedInst = 0; - unsigned int Packages = 0; pkgProblemResolver Fix(Cache); - - bool DefRemove = false; + + static const unsigned short MOD_REMOVE = 1; + static const unsigned short MOD_INSTALL = 2; + + unsigned short fallback = MOD_INSTALL; if (strcasecmp(CmdL.FileList[0],"remove") == 0) - DefRemove = true; + fallback = MOD_REMOVE; else if (strcasecmp(CmdL.FileList[0], "purge") == 0) { _config->Set("APT::Get::Purge", true); - DefRemove = true; + fallback = MOD_REMOVE; } else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0) { _config->Set("APT::Get::AutomaticRemove", "true"); - DefRemove = true; + fallback = MOD_REMOVE; + } + + std::list mods; + mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDINST)); + mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-", + APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::INSTCAND)); + CacheSetHelperAPTGet helper(c0out); + std::map verset = APT::VersionSet::GroupedFromCommandLine(Cache, + CmdL.FileList + 1, mods, fallback, helper); + + if (_error->PendingError() == true) + return false; + + unsigned short order[] = { 0, 0, 0 }; + if (fallback == MOD_INSTALL) { + order[0] = MOD_INSTALL; + order[1] = MOD_REMOVE; + } else { + order[0] = MOD_REMOVE; + order[1] = MOD_INSTALL; } + // new scope for the ActionGroup { pkgDepCache::ActionGroup group(Cache); - for (const char **I = CmdL.FileList + 1; *I != 0; I++) + for (unsigned short i = 0; order[i] != 0; ++i) { - // Duplicate the string - unsigned int Length = strlen(*I); - char S[300]; - if (Length >= sizeof(S)) - continue; - strcpy(S,*I); - - // See if we are removing and special indicators.. - bool Remove = DefRemove; - char *VerTag = 0; - bool VerIsRel = false; + if (order[i] == MOD_INSTALL) + for (APT::VersionSet::const_iterator Ver = verset[MOD_INSTALL].begin(); + Ver != verset[MOD_INSTALL].end(); ++Ver) + { + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); + Cache->SetCandidateVersion(Ver); - // this is a task! - if (Length >= 1 && S[Length - 1] == '^') - { - S[--Length] = 0; - // tasks must always be confirmed - ExpectedInst += 1000; - // see if we can install it - TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove); - continue; - } + if (TryToInstall(Pkg, Cache, Fix, false, BrokenFix) == false) + return false; - while (Cache->FindPkg(S).end() == true) - { - // Handle an optional end tag indicating what to do - if (Length >= 1 && S[Length - 1] == '-') - { - Remove = true; - S[--Length] = 0; - continue; - } - - if (Length >= 1 && S[Length - 1] == '+') - { - Remove = false; - S[--Length] = 0; - continue; - } - - char *Slash = strchr(S,'='); - if (Slash != 0) - { - VerIsRel = false; - *Slash = 0; - VerTag = Slash + 1; + // see if we need to fix the auto-mark flag + // e.g. apt-get install foo + // where foo is marked automatic + if (Cache[Pkg].Install() == false && + (Cache[Pkg].Flags & pkgCache::Flag::Auto) && + _config->FindB("APT::Get::ReInstall",false) == false && + _config->FindB("APT::Get::Only-Upgrade",false) == false && + _config->FindB("APT::Get::Download-Only",false) == false) + { + ioprintf(c1out,_("%s set to manually installed.\n"), + Pkg.FullName(true).c_str()); + Cache->MarkAuto(Pkg,false); + AutoMarkChanged++; + } } - - Slash = strchr(S,'/'); - if (Slash != 0) + else if (order[i] == MOD_REMOVE) + for (APT::VersionSet::const_iterator Ver = verset[MOD_REMOVE].begin(); + Ver != verset[MOD_REMOVE].end(); ++Ver) { - VerIsRel = true; - *Slash = 0; - VerTag = Slash + 1; - } - - break; - } - - // Locate the package - pkgCache::PkgIterator Pkg = Cache->FindPkg(S); - Packages++; - if (Pkg.end() == true) - { - // Check if the name is a regex - const char *I; - for (I = S; *I != 0; I++) - if (*I == '?' || *I == '*' || *I == '|' || - *I == '[' || *I == '^' || *I == '$') - break; - if (*I == 0) - return _error->Error(_("Couldn't find package %s"),S); + pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - // Regexs must always be confirmed - ExpectedInst += 1000; - - // Compile the regex pattern - regex_t Pattern; - int Res; - if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE | - REG_NOSUB)) != 0) - { - char Error[300]; - regerror(Res,&Pattern,Error,sizeof(Error)); - return _error->Error(_("Regex compilation error - %s"),Error); - } - - // Run over the matches - bool Hit = false; - for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++) - { - if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0) - continue; - - ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"), - Pkg.Name(),S); - - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) - return false; - - Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix, - ExpectedInst,false); - } - regfree(&Pattern); - - if (Hit == false) - return _error->Error(_("Couldn't find package %s"),S); - } - else - { - if (VerTag != 0) - if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false) + if (TryToInstall(Pkg, Cache, Fix, true, BrokenFix) == false) return false; - if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false) - return false; - - // see if we need to fix the auto-mark flag - // e.g. apt-get install foo - // where foo is marked automatic - if(!Remove && - Cache[Pkg].Install() == false && - (Cache[Pkg].Flags & pkgCache::Flag::Auto) && - _config->FindB("APT::Get::ReInstall",false) == false && - _config->FindB("APT::Get::Only-Upgrade",false) == false && - _config->FindB("APT::Get::Download-Only",false) == false) - { - ioprintf(c1out,_("%s set to manually installed.\n"), - Pkg.FullName(true).c_str()); - Cache->MarkAuto(Pkg,false); - AutoMarkChanged++; } - } } + if (_error->PendingError() == true) + return false; + /* 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; + c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl; ShowBroken(c1out,Cache,false); return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).")); @@ -1857,7 +1780,7 @@ bool DoInstall(CommandLine &CmdL) /* Print out a list of packages that are going to be installed extra to what the user asked */ - if (Cache->InstCount() != ExpectedInst) + if (Cache->InstCount() != verset[MOD_INSTALL].size()) { string List; string VersionsList; @@ -1910,9 +1833,10 @@ bool DoInstall(CommandLine &CmdL) { /* Skip if package is installed already, or is about to be */ string target = Start.TargetPkg().FullName(true) + " "; - - if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install - || Cache[Start.TargetPkg()].Install()) + pkgCache::PkgIterator const TarPkg = Start.TargetPkg(); + if (TarPkg->SelectedState == pkgCache::State::Install || + TarPkg->SelectedState == pkgCache::State::Hold || + Cache[Start.TargetPkg()].Install()) { foundInstalledInOrGroup=true; break; @@ -1982,11 +1906,52 @@ bool DoInstall(CommandLine &CmdL) Cache->writeStateFile(NULL); // See if we need to prompt - if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0) + // FIXME: check if really the packages in the set are going to be installed + if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0) return InstallPackages(Cache,false,false); return InstallPackages(Cache,false); } + +/* mark packages as automatically/manually installed. */ +bool DoMarkAuto(CommandLine &CmdL) +{ + bool Action = true; + int AutoMarkChanged = 0; + OpTextProgress progress; + CacheFile Cache; + if (Cache.Open() == false) + return false; + + if (strcasecmp(CmdL.FileList[0],"markauto") == 0) + Action = true; + else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0) + Action = false; + + for (const char **I = CmdL.FileList + 1; *I != 0; I++) + { + const char *S = *I; + // Locate the package + pkgCache::PkgIterator Pkg = Cache->FindPkg(S); + if (Pkg.end() == true) { + return _error->Error(_("Couldn't find package %s"),S); + } + else + { + if (!Action) + ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name()); + else + ioprintf(c1out,_("%s set to automatically installed.\n"), + Pkg.Name()); + + Cache->MarkAuto(Pkg,Action); + AutoMarkChanged++; + } + } + if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false)) + return Cache->writeStateFile(NULL); + return false; +} /*}}}*/ // DoDistUpgrade - Automatic smart upgrader /*{{{*/ // --------------------------------------------------------------------- @@ -2195,13 +2160,23 @@ bool DoSource(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; DscFile *Dsc = new DscFile[CmdL.FileSize()]; // insert all downloaded uris into this set to avoid downloading them // twice set queued; + + // Diff only mode only fetches .diff files + bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false); + // Tar only mode only fetches .tar files + bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false); + // Dsc only mode only fetches .dsc files + bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false); + // Load the requestd sources into the fetcher unsigned J = 0; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) @@ -2212,6 +2187,33 @@ bool DoSource(CommandLine &CmdL) if (Last == 0) return _error->Error(_("Unable to find a source package for %s"),Src.c_str()); + string srec = Last->AsStr(); + string::size_type pos = srec.find("\nVcs-"); + while (pos != string::npos) + { + pos += strlen("\nVcs-"); + string vcs = srec.substr(pos,srec.find(":",pos)-pos); + if(vcs == "Browser") + { + pos = srec.find("\nVcs-", pos); + continue; + } + pos += vcs.length()+2; + string::size_type epos = srec.find("\n", pos); + string uri = srec.substr(pos,epos-pos).c_str(); + ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in " + "the '%s' version control system at:\n" + "%s\n"), + Src.c_str(), vcs.c_str(), uri.c_str()); + if(vcs == "Bzr") + ioprintf(c1out,_("Please use:\n" + "bzr get %s\n" + "to retrieve the latest (possibly unreleased) " + "updates to the package.\n"), + uri.c_str()); + break; + } + // Back track vector Lst; if (Last->Files(Lst) == false) @@ -2228,21 +2230,17 @@ bool DoSource(CommandLine &CmdL) Dsc[J].Version = Last->Version(); Dsc[J].Dsc = flNotDir(I->Path); } - - // Diff only mode only fetches .diff files - if (_config->FindB("APT::Get::Diff-Only",false) == true && - I->Type != "diff") - continue; - - // Tar only mode only fetches .tar files - if (_config->FindB("APT::Get::Tar-Only",false) == true && - I->Type != "tar") - continue; - // Dsc only mode only fetches .dsc files - if (_config->FindB("APT::Get::Dsc-Only",false) == true && - I->Type != "dsc") - continue; + // Handle the only options so that multiple can be used at once + if (diffOnly == true || tarOnly == true || dscOnly == true) + { + if ((diffOnly == true && I->Type == "diff") || + (tarOnly == true && I->Type == "tar") || + (dscOnly == true && I->Type == "dsc")) + ; // Fine, we want this file downloaded + else + continue; + } // don't download the same uri twice (should this be moved to // the fetcher interface itself?) @@ -2272,9 +2270,9 @@ bool DoSource(CommandLine &CmdL) } // Display statistics - double FetchBytes = Fetcher.FetchNeeded(); - double FetchPBytes = Fetcher.PartialPresent(); - double DebBytes = Fetcher.TotalNeeded(); + unsigned long long FetchBytes = Fetcher.FetchNeeded(); + unsigned long long FetchPBytes = Fetcher.PartialPresent(); + unsigned long long DebBytes = Fetcher.TotalNeeded(); // Check for enough free space struct statvfs Buf; @@ -2356,6 +2354,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++) { string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str()); @@ -2368,7 +2367,7 @@ bool DoSource(CommandLine &CmdL) // See if the package is already unpacked struct stat Stat; - if (stat(Dir.c_str(),&Stat) == 0 && + if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 && S_ISDIR(Stat.st_mode) != 0) { ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"), @@ -2452,7 +2451,9 @@ bool DoBuildDep(CommandLine &CmdL) // Create the download object AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0)); - pkgAcquire Fetcher(&Stat); + pkgAcquire Fetcher; + if (Fetcher.Setup(&Stat) == false) + return false; unsigned J = 0; for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++) @@ -2490,7 +2491,6 @@ bool DoBuildDep(CommandLine &CmdL) } // Install the requested packages - unsigned int ExpectedInst = 0; vector ::iterator D; pkgProblemResolver Fix(Cache); bool skipAlternatives = false; // skip remaining alternatives in an or group @@ -2521,7 +2521,7 @@ bool DoBuildDep(CommandLine &CmdL) */ if (IV.end() == false && Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true) - TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst); + TryToInstall(Pkg,Cache,Fix,true,false); } else // BuildDep || BuildDepIndep { @@ -2637,7 +2637,7 @@ bool DoBuildDep(CommandLine &CmdL) if (_config->FindB("Debug::BuildDeps",false) == true) cout << " Trying to install " << (*D).Package << endl; - if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true) + if (TryToInstall(Pkg,Cache,Fix,false,false) == true) { // We successfully installed something; skip remaining alternatives skipAlternatives = hasAlternatives; @@ -2768,6 +2768,8 @@ bool ShowHelp(CommandLine &CmdL) " clean - Erase downloaded archive files\n" " autoclean - Erase old downloaded archive files\n" " check - Verify that there are no broken dependencies\n" + " markauto - Mark the given packages as automatically installed\n" + " unmarkauto - Mark the given packages as manually installed\n" "\n" "Options:\n" " -h This help text.\n" @@ -2873,7 +2875,8 @@ int main(int argc,const char *argv[]) /*{{{*/ {"remove",&DoInstall}, {"purge",&DoInstall}, {"autoremove",&DoInstall}, - {"purge",&DoInstall}, + {"markauto",&DoMarkAuto}, + {"unmarkauto",&DoMarkAuto}, {"dist-upgrade",&DoDistUpgrade}, {"dselect-upgrade",&DoDSelectUpgrade}, {"build-dep",&DoBuildDep}, @@ -2924,7 +2927,7 @@ int main(int argc,const char *argv[]) /*{{{*/ } // Deal with stdout not being a tty - if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1) + if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) _config->Set("quiet","1"); // Setup the output streams @@ -2945,13 +2948,11 @@ int main(int argc,const char *argv[]) /*{{{*/ CmdL.DispatchArg(Cmds); // Print any errors or warnings found during parsing - if (_error->empty() == false) - { - bool Errors = _error->PendingError(); + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) _error->DumpErrors(); - return Errors == true?100:0; - } - - return 0; + else + _error->DumpErrors(GlobalError::DEBUG); + return Errors == true ? 100 : 0; } /*}}}*/