-// DoUpdate - Update the package lists /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool DoUpdate(CommandLine &CmdL)
-{
- if (CmdL.FileSize() != 1)
- return _error->Error(_("The update command takes no arguments"));
-
- // Get the source list
- pkgSourceList List;
- if (List.ReadMainList() == false)
- return false;
-
- // 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;
- if (Fetcher.Setup(&Stat) == false)
- return false;
-
- // Populate it with the source selection and get all Indexes
- // (GetAll=true)
- if (List.GetIndexes(&Fetcher,true) == false)
- return false;
-
- pkgAcquire::UriIterator I = Fetcher.UriBegin();
- for (; I != Fetcher.UriEnd(); I++)
- cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
- I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
- return true;
- }
-
- // do the work
- CacheFile Cache;
- if (_config->FindB("APT::Get::Download",true) == true)
- ListUpdate(Stat, List);
-
- // Rebuild the cache.
- if (Cache.BuildCaches() == false)
- return false;
-
- return true;
-}
- /*}}}*/
-// DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
-// ---------------------------------------------------------------------
-/* Remove unused automatic packages */
-bool DoAutomaticRemove(CacheFile &Cache)
-{
- 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(Debug)
- std::cout << "DoAutomaticRemove()" << std::endl;
-
- // we don't want to autoremove and we don't want to see it, so why calculating?
- if (doAutoRemove == false && hideAutoRemove == true)
- return true;
-
- if (doAutoRemove == true &&
- _config->FindB("APT::Get::Remove",true) == false)
- {
- c1out << _("We are not supposed to delete stuff, can't start "
- "AutoRemover") << std::endl;
- return false;
- }
-
- bool purgePkgs = _config->FindB("APT::Get::Purge", false);
- bool smallList = (hideAutoRemove == false &&
- strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
-
- string autoremovelist, autoremoveversions;
- unsigned long autoRemoveCount = 0;
- // 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.FullName(true).c_str() << std::endl;
-
- if (doAutoRemove)
- {
- if(Pkg.CurrentVer() != 0 &&
- Pkg->CurrentState != pkgCache::State::ConfigFiles)
- Cache->MarkDelete(Pkg, purgePkgs);
- else
- Cache->MarkKeep(Pkg, false, false);
- }
- else
- {
- // only show stuff in the list that is not yet marked for removal
- if(Cache[Pkg].Delete() == false)
- {
- ++autoRemoveCount;
- // we don't need to fill the strings if we don't need them
- if (smallList == false)
- {
- autoremovelist += Pkg.FullName(true) + " ";
- autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
- }
- }
- }
- }
- }
- // if we don't remove them, we should show them!
- if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
- {
- if (smallList == false)
- ShowList(c1out, P_("The following package is automatically installed and is no longer required:",
- "The following packages were automatically installed and are no longer required:",
- autoRemoveCount), autoremovelist, autoremoveversions);
- else
- ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
- "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
- c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
- }
- // Now see if we had destroyed anything (if we had done anything)
- else if (Cache->BrokenCount() != 0)
- {
- c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
- "shouldn't happen. Please file a bug report against apt.") << endl;
- c1out << endl;
- c1out << _("The following information may help to resolve the situation:") << endl;
- c1out << endl;
- ShowBroken(c1out,Cache,false);
-
- return _error->Error(_("Internal Error, AutoRemover broke stuff"));
- }
- return true;
-}
- /*}}}*/
-// DoUpgrade - Upgrade all packages /*{{{*/
-// ---------------------------------------------------------------------
-/* Upgrade all packages without installing new packages or erasing old
- packages */
-bool DoUpgrade(CommandLine &CmdL)
-{
- CacheFile Cache;
- if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
- return false;
-
- // Do the upgrade
- if (pkgAllUpgrade(Cache) == false)
- {
- ShowBroken(c1out,Cache,false);
- return _error->Error(_("Internal error, AllUpgrade broke stuff"));
- }
-
- 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);
-
- // 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 /*{{{*/
-// ---------------------------------------------------------------------
-/* Install named packages */
-bool DoInstall(CommandLine &CmdL)
-{
- CacheFile Cache;
- if (Cache.OpenForInstall() == false ||
- Cache.CheckDeps(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 AutoMarkChanged = 0;
- unsigned int ExpectedInst = 0;
- unsigned int Packages = 0;
- pkgProblemResolver Fix(Cache);
-
- bool DefRemove = false;
- if (strcasecmp(CmdL.FileList[0],"remove") == 0)
- DefRemove = true;
- else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
- {
- _config->Set("APT::Get::Purge", true);
- DefRemove = true;
- }
- else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
- {
- _config->Set("APT::Get::AutomaticRemove", "true");
- DefRemove = true;
- }
- // new scope for the ActionGroup
- {
- pkgDepCache::ActionGroup group(Cache);
- for (const char **I = CmdL.FileList + 1; *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;
-
- // 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;
- }
-
- 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;
- }
-
- Slash = strchr(S,'/');
- if (Slash != 0)
- {
- 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);
-
- // 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 (pkgCache::GrpIterator Grp = Cache->GrpBegin(); Grp.end() == false; ++Grp)
- {
- if (regexec(&Pattern,Grp.Name(),0,0,0) != 0)
- continue;
- Pkg = Grp.FindPkg("native");
- if (unlikely(Pkg.end() == true))
- 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)
- 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 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,false);
-
- return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
- }
-
- // Call the scored problem resolver
- Fix.InstallProtect();
- if (Fix.Resolve(true) == false)
- _error->Discard();
-
- // Now we check the state of the packages,
- if (Cache->BrokenCount() != 0)
- {
- c1out <<
- _("Some packages could not be installed. This may mean that you have\n"
- "requested an impossible situation or if you are using the unstable\n"
- "distribution that some required packages have not yet been created\n"
- "or been moved out of Incoming.") << endl;
- /*
- if (Packages == 1)
- {
- c1out << endl;
- c1out <<
- _("Since you only requested a single operation it is extremely likely that\n"
- "the package is simply not installable and a bug report against\n"
- "that package should be filed.") << endl;
- }
- */
-
- c1out << _("The following information may help to resolve the situation:") << endl;
- c1out << endl;
- ShowBroken(c1out,Cache,false);
- return _error->Error(_("Broken packages"));
- }
- }
- if (!DoAutomaticRemove(Cache))
- return false;
-
- /* Print out a list of packages that are going to be installed extra
- to what the user asked */
- if (Cache->InstCount() != ExpectedInst)
- {
- string List;
- string VersionsList;
- for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
- {
- pkgCache::PkgIterator I(Cache,Cache.List[J]);
- if ((*Cache)[I].Install() == false)
- continue;
-
- const char **J;
- for (J = CmdL.FileList + 1; *J != 0; J++)
- if (strcmp(*J,I.Name()) == 0)
- break;
-
- if (*J == 0) {
- List += I.FullName(true) + " ";
- VersionsList += string(Cache[I].CandVersion) + "\n";
- }
- }
-
- ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
- }
-
- /* Print out a list of suggested and recommended packages */
- {
- string SuggestsList, RecommendsList, List;
- string SuggestsVersions, RecommendsVersions;
- for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
- {
- pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
-
- /* Just look at the ones we want to install */
- if ((*Cache)[Pkg].Install() == false)
- continue;
-
- // 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 = Start.TargetPkg().FullName(true) + " ";
- pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
- if (TarPkg->SelectedState == pkgCache::State::Install ||
- TarPkg->SelectedState == pkgCache::State::Hold ||
- 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 &&
- _config->FindB("APT::Get::Simulate",false) == false)
- Cache->writeStateFile(NULL);
-
- // See if we need to prompt
- if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
- return InstallPackages(Cache,false,false);
-
- return InstallPackages(Cache,false);
-}
-
-/* mark packages as automatically/manually installed. */
-bool DoMarkAuto(CommandLine &CmdL)