and verifies that the system is OK. */
bool CacheFile::CheckDeps(bool AllowBroken)
{
+ bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false);
+
if (_error->PendingError() == true)
return false;
if (pkgApplyStatus(*DCache) == false)
return false;
+ if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true)
+ {
+ FixBroken = true;
+ if ((DCache->PolicyBrokenCount() > 0))
+ {
+ // upgrade all policy-broken packages with ForceImportantDeps=True
+ for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); I++)
+ if ((*DCache)[I].NowPolicyBroken() == true)
+ DCache->MarkInstall(I,true,0, false, true);
+ }
+ }
+
// Nothing is broken
if (DCache->BrokenCount() == 0 || AllowBroken == true)
return true;
// Attempt to fix broken things
- if (_config->FindB("APT::Get::Fix-Broken",false) == true)
+ if (FixBroken == true)
{
c1out << _("Correcting dependencies...") << flush;
if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
else
ExpectedInst++;
- // Install it with autoinstalling enabled.
- if (State.InstBroken() == true && BrokenFix == false)
+ // 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)
Cache.MarkInstall(Pkg,true);
+
return true;
}
/*}}}*/
return false;
bool Failed = false;
+ bool TransientNetworkFailure = false;
for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
{
if ((*I)->Status == pkgAcquire::Item::StatDone)
continue;
(*I)->Finished();
-
+
fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
(*I)->ErrorText.c_str());
+
+ if ((*I)->Status == pkgAcquire::Item::StatTransientNetworkError)
+ {
+ TransientNetworkFailure = true;
+ continue;
+ }
+
Failed = true;
}
// Clean out any old list files
- if (!Failed && _config->FindB("APT::Get::List-Cleanup",true) == true)
+ if (!TransientNetworkFailure &&
+ _config->FindB("APT::Get::List-Cleanup",true) == true)
{
if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
if (Cache.BuildCaches() == false)
return false;
- if (Failed == true)
+ if (TransientNetworkFailure == true)
+ _error->Warning(_("Some index files failed to download, they have been ignored, or old ones used instead."));
+ else if (Failed == true)
return _error->Error(_("Some index files failed to download, they have been ignored, or old ones used instead."));
-
+
return true;
}
/*}}}*/
/* Remove unused automatic packages */
bool DoAutomaticRemove(CacheFile &Cache)
{
- if(_config->FindI("Debug::pkgAutoRemove",false))
- std::cout << "DoAutomaticRemove()" << std::endl;
+ bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
+ bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
+ bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
+ pkgDepCache::ActionGroup group(*Cache);
- if (_config->FindB("APT::Get::Remove",true) == false)
- return _error->Error(_("We are not supposed to delete stuff, can't "
- "start AutoRemover"));
+ if(Debug)
+ std::cout << "DoAutomaticRemove()" << std::endl;
+ if (_config->FindB("APT::Get::Remove",true) == false &&
+ doAutoRemove == true)
{
- pkgDepCache::ActionGroup group(*Cache);
-
- // look over the cache to see what can be removed
- for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
- {
- if (Cache[Pkg].Garbage)
- {
- if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
- fprintf(stdout,"We could delete %s\n", Pkg.Name());
+ c1out << _("We are not supposed to delete stuff, can't start "
+ "AutoRemover") << std::endl;
+ doAutoRemove = false;
+ }
- if(Pkg.CurrentVer() != 0 && Pkg->CurrentState != pkgCache::State::ConfigFiles)
+ string autoremovelist, autoremoveversions;
+ // look over the cache to see what can be removed
+ for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
+ {
+ if (Cache[Pkg].Garbage)
+ {
+ if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
+ if(Debug)
+ std::cout << "We could delete %s" << Pkg.Name() << std::endl;
+
+ // only show stuff in the list that is not yet marked for removal
+ if(Cache[Pkg].Delete() == false)
+ {
+ autoremovelist += string(Pkg.Name()) + " ";
+ autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
+ }
+ if (doAutoRemove)
+ {
+ if(Pkg.CurrentVer() != 0 &&
+ Pkg->CurrentState != pkgCache::State::ConfigFiles)
Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
- else
+ else
Cache->MarkKeep(Pkg, false, false);
- }
- }
+ }
+ }
}
+ if (!hideAutoRemove)
+ ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
+ if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
+ c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
// Now see if we destroyed anything
if (Cache->BrokenCount() != 0)
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)
+{
+ const char *start, *end;
+ pkgCache::PkgIterator Pkg;
+ char buf[64*1024];
+ regex_t Pattern;
+
+ // get the records
+ pkgRecords Recs(Cache);
+
+ // build regexp for the task
+ char S[300];
+ snprintf(S, sizeof(S), "^Task:.*[^a-z]%s[^a-z].*\n", taskname);
+ regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE);
+
+ bool found = false;
+ bool res = true;
+ 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,false,BrokenFix,ExpectedInst);
+ found = true;
+ }
+
+ if(!found)
+ _error->Error(_("Couldn't find task %s"),taskname);
+
+ regfree(&Pattern);
+ return res;
+}
+
// DoInstall - Install packages from the command line /*{{{*/
// ---------------------------------------------------------------------
/* Install named packages */
if (Cache->BrokenCount() != 0)
BrokenFix = true;
+ unsigned int AutoMarkChanged = 0;
unsigned int ExpectedInst = 0;
unsigned int Packages = 0;
pkgProblemResolver Fix(Cache);
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))
+ {
+ ioprintf(c1out,_("%s set to manual installed.\n"),
+ Pkg.Name());
+ Cache->MarkAuto(Pkg,false);
+ AutoMarkChanged++;
+ }
}
}
string SuggestsVersions, RecommendsVersions;
for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
{
- pkgCache::PkgIterator I(Cache,Cache.List[J]);
+ pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
/* Just look at the ones we want to install */
- if ((*Cache)[I].Install() == false)
+ if ((*Cache)[Pkg].Install() == false)
continue;
- for (pkgCache::VerIterator V = I.VersionList(); V.end() == false; V++)
- {
- for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; )
- {
- pkgCache::DepIterator Start;
- pkgCache::DepIterator End;
- D.GlobOr(Start,End); // advances D
-
- /*
- * If this is a virtual package, we need to check the list of
- * packages that provide it and see if any of those are
- * installed
- */
-
- bool providedBySomething = false;
- for (pkgCache::PrvIterator Prv = Start.TargetPkg().ProvidesList();
- Prv.end() != true;
- Prv++)
- if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
- {
- providedBySomething = true;
- break;
- }
-
- if (providedBySomething) continue;
-
- for(;;)
- {
- /* Skip if package is installed already, or is about to be */
- string target = string(Start.TargetPkg().Name()) + " ";
-
- if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
- || Cache[Start.TargetPkg()].Install())
- break;
-
- /* Skip if we already saw it */
- if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
- break;
-
- if (Start->Type == pkgCache::Dep::Suggests) {
- SuggestsList += target;
- SuggestsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
- }
-
- if (Start->Type == pkgCache::Dep::Recommends) {
- RecommendsList += target;
- RecommendsVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
- }
-
- if (Start >= End)
- break;
- Start++;
- }
- }
- }
+ // get the recommends/suggests for the candidate ver
+ pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
+ for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
+ {
+ pkgCache::DepIterator Start;
+ pkgCache::DepIterator End;
+ D.GlobOr(Start,End); // advances D
+
+ // FIXME: we really should display a or-group as a or-group to the user
+ // the problem is that ShowList is incapable of doing this
+ string RecommendsOrList,RecommendsOrVersions;
+ string SuggestsOrList,SuggestsOrVersions;
+ bool foundInstalledInOrGroup = false;
+ for(;;)
+ {
+ /* Skip if package is installed already, or is about to be */
+ string target = string(Start.TargetPkg().Name()) + " ";
+
+ if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
+ || Cache[Start.TargetPkg()].Install())
+ {
+ foundInstalledInOrGroup=true;
+ break;
+ }
+
+ /* Skip if we already saw it */
+ if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
+ {
+ foundInstalledInOrGroup=true;
+ break;
+ }
+
+ // this is a dep on a virtual pkg, check if any package that provides it
+ // should be installed
+ if(Start.TargetPkg().ProvidesList() != 0)
+ {
+ pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
+ for (; I.end() == false; I++)
+ {
+ pkgCache::PkgIterator Pkg = I.OwnerPkg();
+ if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
+ Pkg.CurrentVer() != 0)
+ foundInstalledInOrGroup=true;
+ }
+ }
+
+ if (Start->Type == pkgCache::Dep::Suggests)
+ {
+ SuggestsOrList += target;
+ SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+ }
+
+ if (Start->Type == pkgCache::Dep::Recommends)
+ {
+ RecommendsOrList += target;
+ RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
+ }
+
+ if (Start >= End)
+ break;
+ Start++;
+ }
+
+ if(foundInstalledInOrGroup == false)
+ {
+ RecommendsList += RecommendsOrList;
+ RecommendsVersions += RecommendsOrVersions;
+ SuggestsList += SuggestsOrList;
+ SuggestsVersions += SuggestsOrVersions;
+ }
+
+ }
}
+
ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
}
+ // if nothing changed in the cache, but only the automark information
+ // we write the StateFile here, otherwise it will be written in
+ // cache.commit()
+ if (AutoMarkChanged > 0 &&
+ Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
+ Cache->BadCount() == 0)
+ Cache->writeStateFile(NULL);
+
// See if we need to prompt
if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
return InstallPackages(Cache,false,false);
{0,"arch-only","APT::Get::Arch-Only",0},
{0,"auto-remove","APT::Get::AutomaticRemove",0},
{0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
+ {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
+ {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
{'c',"config-file",0,CommandLine::ConfigFile},
{'o',"option",0,CommandLine::ArbItem},
{0,0,0,0}};