diff options
Diffstat (limited to 'cmdline')
-rw-r--r-- | cmdline/apt-cache.cc | 93 | ||||
-rw-r--r-- | cmdline/apt-config.cc | 13 | ||||
-rw-r--r-- | cmdline/apt-dump-solver.cc | 50 | ||||
-rw-r--r-- | cmdline/apt-get.cc | 266 | ||||
-rw-r--r-- | cmdline/apt-internal-solver.cc | 190 | ||||
-rwxr-xr-x | cmdline/apt-key | 17 | ||||
-rwxr-xr-x | cmdline/apt-mark | 101 | ||||
-rw-r--r-- | cmdline/apt-mark.cc | 373 | ||||
-rw-r--r-- | cmdline/makefile | 23 |
9 files changed, 864 insertions, 262 deletions
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 45ea50433..232bb93ec 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -121,9 +121,7 @@ bool ShowUnMet(pkgCache::VerIterator const &V, bool const &Important) continue; // Skip conflicts and replaces - if (End->Type == pkgCache::Dep::DpkgBreaks || - End->Type == pkgCache::Dep::Replaces || - End->Type == pkgCache::Dep::Conflicts) + if (End.IsNegative() == true) continue; // Verify the or group @@ -848,10 +846,7 @@ bool XVcg(CommandLine &CmdL) { /* If a conflicts does not meet anything in the database then show the relation but do not recurse */ - if (Hit == false && - (D->Type == pkgCache::Dep::Conflicts || - D->Type == pkgCache::Dep::DpkgBreaks || - D->Type == pkgCache::Dep::Obsoletes)) + if (Hit == false && D.IsNegative() == true) { if (Show[D.TargetPkg()->ID] == None && Show[D.TargetPkg()->ID] != ToShow) @@ -1060,9 +1055,7 @@ bool Dotty(CommandLine &CmdL) { /* If a conflicts does not meet anything in the database then show the relation but do not recurse */ - if (Hit == false && - (D->Type == pkgCache::Dep::Conflicts || - D->Type == pkgCache::Dep::Obsoletes)) + if (Hit == false && D.IsNegative() == true) { if (Show[D.TargetPkg()->ID] == None && Show[D.TargetPkg()->ID] != ToShow) @@ -1082,6 +1075,7 @@ bool Dotty(CommandLine &CmdL) { case pkgCache::Dep::Conflicts: case pkgCache::Dep::Obsoletes: + case pkgCache::Dep::DpkgBreaks: printf("[color=springgreen];\n"); break; @@ -1115,61 +1109,12 @@ bool Dotty(CommandLine &CmdL) } printf("}\n"); + delete[] Show; + delete[] Flags; + delete[] ShapeMap; return true; } /*}}}*/ -// DoAdd - Perform an adding operation /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool DoAdd(CommandLine &CmdL) -{ - return _error->Error("Unimplemented"); -#if 0 - // Make sure there is at least one argument - if (CmdL.FileSize() <= 1) - return _error->Error("You must give at least one file name"); - - // Open the cache - FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny); - if (_error->PendingError() == true) - return false; - - DynamicMMap Map(CacheF,MMap::Public); - if (_error->PendingError() == true) - return false; - - OpTextProgress Progress(*_config); - pkgCacheGenerator Gen(Map,Progress); - if (_error->PendingError() == true) - return false; - - unsigned long Length = CmdL.FileSize() - 1; - for (const char **I = CmdL.FileList + 1; *I != 0; I++) - { - Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache"); - Progress.SubProgress(Length); - - // Do the merge - FileFd TagF(*I,FileFd::ReadOnly); - debListParser Parser(TagF); - if (_error->PendingError() == true) - return _error->Error("Problem opening %s",*I); - - if (Gen.SelectFile(*I,"") == false) - return _error->Error("Problem with SelectFile"); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList"); - } - - Progress.Done(); - GCache = &Gen.GetCache(); - Stats(CmdL); - - return true; -#endif -} - /*}}}*/ // DisplayRecord - Displays the complete record for the package /*{{{*/ // --------------------------------------------------------------------- /* This displays the package record from the proper package index file. @@ -1383,9 +1328,8 @@ bool Search(CommandLine &CmdL) return _error->Error("Write to stdout failed"); return true; } - - -/* show automatically installed packages (sorted) */ + /*}}}*/ +/* ShowAuto - show automatically installed packages (sorted) {{{*/ bool ShowAuto(CommandLine &CmdL) { pkgCacheFile CacheFile; @@ -1406,6 +1350,7 @@ bool ShowAuto(CommandLine &CmdL) for (vector<string>::iterator I = packages.begin(); I != packages.end(); I++) cout << *I << "\n"; + _error->Notice(_("This command is deprecated. Please use 'apt-mark showauto' instead.")); return true; } /*}}}*/ @@ -1571,7 +1516,6 @@ bool Policy(CommandLine &CmdL) return true; } - string const myArch = _config->Find("APT::Architecture"); char const * const msgInstalled = _(" Installed: "); char const * const msgCandidate = _(" Candidate: "); short const InstalledLessCandidate = @@ -1584,14 +1528,8 @@ bool Policy(CommandLine &CmdL) // Print out detailed information for each package APT::CacheSetHelper helper(true, GlobalError::NOTICE); APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); - for (APT::PackageSet::const_iterator I = pkgset.begin(); I != pkgset.end(); ++I) + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) { - pkgCache::PkgIterator Pkg = I.Group().FindPkg("any"); - - for (; Pkg.end() != true; Pkg = I.Group().NextPkg(Pkg)) { - if (strcmp(Pkg.Arch(),"all") == 0) - continue; - cout << Pkg.FullName(true) << ":" << endl; // Installed version @@ -1640,7 +1578,6 @@ bool Policy(CommandLine &CmdL) Indx->Describe(true).c_str()); } } - } } return true; @@ -1743,15 +1680,13 @@ bool ShowHelp(CommandLine &Cmd) cout << _("Usage: apt-cache [options] command\n" - " apt-cache [options] add file1 [file2 ...]\n" " apt-cache [options] showpkg pkg1 [pkg2 ...]\n" " apt-cache [options] showsrc pkg1 [pkg2 ...]\n" "\n" - "apt-cache is a low-level tool used to manipulate APT's binary\n" - "cache files, and query information from them\n" + "apt-cache is a low-level tool used to query information\n" + "from APT's binary cache files\n" "\n" "Commands:\n" - " add - Add a package file to the source cache\n" " gencaches - Build both the package and source cache\n" " showpkg - Show some general information for a single package\n" " showsrc - Show source records\n" @@ -1761,7 +1696,6 @@ bool ShowHelp(CommandLine &Cmd) " unmet - Show unmet dependencies\n" " search - Search the package list for a regex pattern\n" " show - Show a readable record for the package\n" - " showauto - Display a list of automatically installed packages\n" " depends - Show raw dependency information for a package\n" " rdepends - Show reverse dependency information for a package\n" " pkgnames - List the names of all packages in the system\n" @@ -1811,7 +1745,6 @@ int main(int argc,const char *argv[]) /*{{{*/ {0,"enhances","APT::Cache::ShowEnhances",0}, {0,0,0,0}}; CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp}, - {"add",&DoAdd}, {"gencaches",&GenCaches}, {"showsrc",&ShowSrcPackage}, {0,0}}; diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc index 9919a9c94..589ee7ada 100644 --- a/cmdline/apt-config.cc +++ b/cmdline/apt-config.cc @@ -20,6 +20,8 @@ #include <apt-pkg/error.h> #include <apt-pkg/init.h> #include <apt-pkg/strutl.h> +#include <apt-pkg/configuration.h> +#include <apt-pkg/aptconfiguration.h> #include <config.h> #include <apti18n.h> @@ -27,6 +29,7 @@ #include <locale.h> #include <iostream> #include <string> +#include <vector> /*}}}*/ using namespace std; @@ -119,6 +122,16 @@ int main(int argc,const char *argv[]) /*{{{*/ CmdL.FileSize() == 0) return ShowHelp(); + std::vector<std::string> const langs = APT::Configuration::getLanguages(true); + _config->Clear("Acquire::Languages"); + for (std::vector<std::string>::const_iterator l = langs.begin(); l != langs.end(); ++l) + _config->Set("Acquire::Languages::", *l); + + std::vector<std::string> const archs = APT::Configuration::getArchitectures(); + _config->Clear("APT::Architectures"); + for (std::vector<std::string>::const_iterator a = archs.begin(); a != archs.end(); ++a) + _config->Set("APT::Architectures::", *a); + // Match the operation CmdL.DispatchArg(Cmds); diff --git a/cmdline/apt-dump-solver.cc b/cmdline/apt-dump-solver.cc new file mode 100644 index 000000000..dab0cc6fd --- /dev/null +++ b/cmdline/apt-dump-solver.cc @@ -0,0 +1,50 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ##################################################################### + + dummy solver to get quickly a scenario file out of APT + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <apt-pkg/edsp.h> + +#include <config.h> + +#include <cstdio> + /*}}}*/ + +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp() { + + std::cout << + PACKAGE " " VERSION " for " COMMON_ARCH " compiled on " __DATE__ " " __TIME__ << std::endl << + "Usage: apt-dump-resolver\n" + "\n" + "apt-dump-resolver is a dummy solver who just dumps its input to the\n" + "file /tmp/dump.edsp and exists with a proper EDSP error.\n" + "\n" + " This dump has lost Super Cow Powers.\n"; + return true; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + if (argc > 1 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1],"-h") == 0 || + strcmp(argv[1],"-v") == 0 || strcmp(argv[1],"--version") == 0)) { + ShowHelp(); + return 0; + } + + FILE* input = fdopen(STDIN_FILENO, "r"); + FILE* output = fopen("/tmp/dump.edsp", "w"); + char buffer[400]; + while (fgets(buffer, sizeof(buffer), input) != NULL) + fputs(buffer, output); + fclose(output); + fclose(input); + + EDSP::WriteError("ERR_JUST_DUMPING", "I am too dumb, i can just dump!\nPlease use one of my friends instead!", stdout); +} diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 61efa5601..66ebd30b8 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -382,8 +382,6 @@ void ShowNew(ostream &out,CacheFile &Cache) { pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].NewInstall() == true) { - if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) - continue; List += I.FullName(true) + " "; VersionsList += string(Cache[I].CandVersion) + "\n"; } @@ -406,8 +404,6 @@ void ShowDel(ostream &out,CacheFile &Cache) pkgCache::PkgIterator I(Cache,Cache.List[J]); if (Cache[I].Delete() == true) { - if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) - continue; if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge) List += I.FullName(true) + "* "; else @@ -456,8 +452,6 @@ void ShowUpgraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true) continue; - if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) - continue; List += I.FullName(true) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; @@ -479,8 +473,6 @@ bool ShowDowngraded(ostream &out,CacheFile &Cache) // Not interesting if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true) continue; - if (Cache[I].CandidateVerIter(Cache).Pseudo() == true) - continue; List += I.FullName(true) + " "; VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n"; @@ -584,9 +576,6 @@ void Stats(ostream &out,pkgDepCache &Dep) unsigned long ReInstall = 0; for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++) { - if (pkgCache::VerIterator(Dep, Dep[I].CandidateVer).Pseudo() == true) - continue; - if (Dep[I].NewInstall() == true) Install++; else @@ -775,7 +764,7 @@ struct TryToInstall { unsigned long AutoMarkChanged; APT::PackageSet doAutoInstallLater; - TryToInstall(pkgCacheFile &Cache, pkgProblemResolver &PM, bool const &FixBroken) : Cache(&Cache), Fix(&PM), + TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const &FixBroken) : Cache(&Cache), Fix(PM), FixBroken(FixBroken), AutoMarkChanged(0) {}; void operator() (pkgCache::VerIterator const &Ver) { @@ -793,8 +782,10 @@ struct TryToInstall { ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"), Pkg.FullName(true).c_str()); else { - Fix->Clear(Pkg); - Fix->Protect(Pkg); + if (Fix != NULL) { + Fix->Clear(Pkg); + Fix->Protect(Pkg); + } Cache->GetDepCache()->MarkInstall(Pkg,false); if (State.Install() == false) { @@ -882,20 +873,27 @@ struct TryToRemove { bool PurgePkgs; unsigned long AutoMarkChanged; - TryToRemove(pkgCacheFile &Cache, pkgProblemResolver &PM) : Cache(&Cache), Fix(&PM), + TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM), PurgePkgs(_config->FindB("APT::Get::Purge", false)) {}; void operator() (pkgCache::VerIterator const &Ver) { pkgCache::PkgIterator Pkg = Ver.ParentPkg(); - Fix->Clear(Pkg); - Fix->Protect(Pkg); - Fix->Remove(Pkg); + if (Fix != NULL) + { + Fix->Clear(Pkg); + Fix->Protect(Pkg); + Fix->Remove(Pkg); + } if ((Pkg->CurrentVer == 0 && PurgePkgs == false) || (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled)) + { ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str()); + // MarkInstall refuses to install packages on hold + Pkg->SelectedState = pkgCache::State::Hold; + } else Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs); } @@ -1392,10 +1390,10 @@ bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache, if (Remove == true) { - TryToRemove RemoveAction(Cache, Fix); + TryToRemove RemoveAction(Cache, &Fix); RemoveAction(Pkg.VersionList()); } else if (Cache[Pkg].CandidateVer != 0) { - TryToInstall InstallAction(Cache, Fix, BrokenFix); + TryToInstall InstallAction(Cache, &Fix, BrokenFix); InstallAction(Cache[Pkg].CandidateVerIter(Cache)); InstallAction.doAutoInstall(); } else @@ -1655,6 +1653,7 @@ bool DoAutomaticRemove(CacheFile &Cache) string autoremovelist, autoremoveversions; unsigned long autoRemoveCount = 0; + APT::PackageSet tooMuch; // look over the cache to see what can be removed for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg) { @@ -1677,7 +1676,10 @@ bool DoAutomaticRemove(CacheFile &Cache) // if the package is a new install and already garbage we don't need to // install it in the first place, so nuke it instead of show it if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0) + { Cache->MarkDelete(Pkg, false); + tooMuch.insert(Pkg); + } // only show stuff in the list that is not yet marked for removal else if(hideAutoRemove == false && Cache[Pkg].Delete() == false) { @@ -1693,6 +1695,45 @@ bool DoAutomaticRemove(CacheFile &Cache) } } + // we could have removed a new dependency of a garbage package, + // so check if a reverse depends is broken and if so install it again. + if (tooMuch.empty() == false && Cache->BrokenCount() != 0) + { + bool Changed; + do { + Changed = false; + for (APT::PackageSet::const_iterator P = tooMuch.begin(); + P != tooMuch.end() && Changed == false; ++P) + { + for (pkgCache::DepIterator R = P.RevDependsList(); + R.end() == false; ++R) + { + if (R->Type != pkgCache::Dep::Depends && + R->Type != pkgCache::Dep::PreDepends) + continue; + pkgCache::PkgIterator N = R.ParentPkg(); + if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false)) + continue; + if (Debug == true) + std::clog << "Save " << P << " as another installed garbage package depends on it" << std::endl; + Cache->MarkInstall(P, false); + if(hideAutoRemove == false) + { + ++autoRemoveCount; + if (smallList == false) + { + autoremovelist += P.FullName(true) + " "; + autoremoveversions += string(Cache[P].CandVersion) + "\n"; + } + } + tooMuch.erase(P); + Changed = true; + break; + } + } + } while (Changed == true); + } + // Now see if we had destroyed anything (if we had done anything) if (Cache->BrokenCount() != 0) { @@ -1755,8 +1796,10 @@ bool DoInstall(CommandLine &CmdL) bool BrokenFix = false; if (Cache->BrokenCount() != 0) BrokenFix = true; - - pkgProblemResolver Fix(Cache); + + pkgProblemResolver* Fix = NULL; + if (_config->FindB("APT::Get::CallResolver", true) == true) + Fix = new pkgProblemResolver(Cache); static const unsigned short MOD_REMOVE = 1; static const unsigned short MOD_INSTALL = 2; @@ -1787,17 +1830,12 @@ bool DoInstall(CommandLine &CmdL) if (_error->PendingError() == true) { helper.showVirtualPackageErrors(Cache); + if (Fix != NULL) + delete Fix; 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; - } + unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 }; TryToInstall InstallAction(Cache, Fix, BrokenFix); TryToRemove RemoveAction(Cache, Fix); @@ -1808,17 +1846,29 @@ bool DoInstall(CommandLine &CmdL) for (unsigned short i = 0; order[i] != 0; ++i) { - if (order[i] == MOD_INSTALL) { + if (order[i] == MOD_INSTALL) InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction); + else if (order[i] == MOD_REMOVE) + RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); + } + + if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true) + { + for (unsigned short i = 0; order[i] != 0; ++i) + { + if (order[i] != MOD_INSTALL) + continue; InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out); InstallAction.doAutoInstall(); } - else if (order[i] == MOD_REMOVE) - RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction); } if (_error->PendingError() == true) + { + if (Fix != NULL) + delete Fix; 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 @@ -1827,14 +1877,18 @@ bool DoInstall(CommandLine &CmdL) { c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl; ShowBroken(c1out,Cache,false); - + if (Fix != NULL) + delete Fix; 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(); + + if (Fix != NULL) + { + // Call the scored problem resolver + Fix->InstallProtect(); + Fix->Resolve(true); + delete Fix; + } // Now we check the state of the packages, if (Cache->BrokenCount() != 0) @@ -1858,8 +1912,11 @@ bool DoInstall(CommandLine &CmdL) c1out << _("The following information may help to resolve the situation:") << endl; c1out << endl; ShowBroken(c1out,Cache,false); - return _error->Error(_("Broken packages")); - } + if (_error->PendingError() == true) + return false; + else + return _error->Error(_("Broken packages")); + } } if (!DoAutomaticRemove(Cache)) return false; @@ -1876,8 +1933,6 @@ bool DoInstall(CommandLine &CmdL) if ((*Cache)[I].Install() == false) continue; pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache); - if (Cand.Pseudo() == true) - continue; if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end()) continue; @@ -1997,8 +2052,8 @@ bool DoInstall(CommandLine &CmdL) return InstallPackages(Cache,false); } - -/* mark packages as automatically/manually installed. */ + /*}}}*/ +/* mark packages as automatically/manually installed. {{{*/ bool DoMarkAuto(CommandLine &CmdL) { bool Action = true; @@ -2033,6 +2088,9 @@ bool DoMarkAuto(CommandLine &CmdL) AutoMarkChanged++; } } + + _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead.")); + if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false)) return Cache->writeStateFile(NULL); return false; @@ -2211,13 +2269,15 @@ bool DoDownload(CommandLine &CmdL) APT::CacheSetHelper helper(c0out); APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); - pkgAcquire Fetcher; - AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); - Fetcher.Setup(&Stat); if (verset.empty() == true) return false; + pkgAcquire Fetcher; + AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); + if (_config->FindB("APT::Get::Print-URIs") == true) + Fetcher.Setup(&Stat); + pkgRecords Recs(Cache); pkgSourceList *SrcList = Cache.GetSourceList(); for (APT::VersionSet::const_iterator Ver = verset.begin(); @@ -2250,9 +2310,18 @@ bool DoDownload(CommandLine &CmdL) // get the file new pkgAcqFile(&Fetcher, uri, hash.toStr(), (*Ver)->Size, descr, Pkg.Name(), "."); } - bool result = (Fetcher.Run() == pkgAcquire::Continue); - return result; + // Just print out the uris and exit if the --print-uris flag was used + if (_config->FindB("APT::Get::Print-URIs") == true) + { + 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; + } + + return (Fetcher.Run() == pkgAcquire::Continue); } /*}}}*/ // DoCheck - Perform the check operation /*{{{*/ @@ -2324,8 +2393,10 @@ bool DoSource(CommandLine &CmdL) string Src; pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache); - if (Last == 0) + if (Last == 0) { + delete[] Dsc; 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-"); @@ -2356,8 +2427,10 @@ bool DoSource(CommandLine &CmdL) // Back track vector<pkgSrcRecords::File> Lst; - if (Last->Files(Lst) == false) + if (Last->Files(Lst) == false) { + delete[] Dsc; return false; + } // Load them into the fetcher for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin(); @@ -2418,6 +2491,7 @@ bool DoSource(CommandLine &CmdL) struct statvfs Buf; string OutputDir = "."; if (statvfs(OutputDir.c_str(),&Buf) != 0) { + delete[] Dsc; if (errno == EOVERFLOW) return _error->WarningE("statvfs",_("Couldn't determine free space in %s"), OutputDir.c_str()); @@ -2431,10 +2505,12 @@ bool DoSource(CommandLine &CmdL) #if HAVE_STRUCT_STATFS_F_TYPE || unsigned(Stat.f_type) != RAMFS_MAGIC #endif - ) + ) { + delete[] Dsc; return _error->Error(_("You don't have enough free space in %s"), OutputDir.c_str()); - } + } + } // Number of bytes if (DebBytes != FetchBytes) @@ -2469,7 +2545,10 @@ bool DoSource(CommandLine &CmdL) // Run it if (Fetcher.Run() == pkgAcquire::Failed) + { + delete[] Dsc; return false; + } // Print error messages bool Failed = false; @@ -2484,8 +2563,11 @@ bool DoSource(CommandLine &CmdL) Failed = true; } if (Failed == true) + { + delete[] Dsc; return _error->Error(_("Failed to fetch some archives.")); - + } + if (_config->FindB("APT::Get::Download-only",false) == true) { c1out << _("Download complete and in download only mode") << endl; @@ -2576,6 +2658,9 @@ bool DoSource(CommandLine &CmdL) bool DoBuildDep(CommandLine &CmdL) { CacheFile Cache; + + _config->Set("APT::Install-Recommends", false); + if (Cache.Open(true) == false) return false; @@ -2881,6 +2966,7 @@ bool GuessThirdPartyChangelogUri(CacheFile &Cache, // now strip away the filename and add srcpkg_srcver.changelog return true; } + /*}}}*/ // DownloadChangelog - Download the changelog /*{{{*/ // --------------------------------------------------------------------- bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, @@ -2905,13 +2991,19 @@ bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, "http://packages.debian.org/changelogs"); path = GetChangelogPath(CacheFile, Pkg, Ver); strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str()); + if (_config->FindB("APT::Get::Print-URIs", false) == true) + { + std::cout << '\'' << changelog_uri << '\'' << std::endl; + return true; + } + strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str()); // queue it new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - // try downloading it, if that fails, they third-party-changelogs location - // FIXME: res is "Continue" even if I get a 404?!? - int res = Fetcher.Run(); + // try downloading it, if that fails, try third-party-changelogs location + // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!? + Fetcher.Run(); if (!FileExists(targetfile)) { string third_party_uri; @@ -2919,7 +3011,7 @@ bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher, { strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str()); new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile); - res = Fetcher.Run(); + Fetcher.Run(); } } @@ -2959,30 +3051,53 @@ bool DoChangelog(CommandLine &CmdL) APT::CacheSetHelper helper(c0out); APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache, CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper); + if (verset.empty() == true) + return false; pkgAcquire Fetcher; + + if (_config->FindB("APT::Get::Print-URIs", false) == true) + for (APT::VersionSet::const_iterator Ver = verset.begin(); + Ver != verset.end(); ++Ver) + return DownloadChangelog(Cache, Fetcher, Ver, ""); + AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0)); Fetcher.Setup(&Stat); - if (verset.empty() == true) - return false; - char *tmpdir = mkdtemp(strdup("/tmp/apt-changelog-XXXXXX")); - if (tmpdir == NULL) { - return _error->Errno("mkdtemp", "mkdtemp failed"); + bool const downOnly = _config->FindB("APT::Get::Download-Only", false); + + char tmpname[100]; + char* tmpdir = NULL; + if (downOnly == false) + { + const char* const tmpDir = getenv("TMPDIR"); + if (tmpDir != NULL && *tmpDir != '\0') + snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir); + else + strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname)); + tmpdir = mkdtemp(tmpname); + if (tmpdir == NULL) + return _error->Errno("mkdtemp", "mkdtemp failed"); } - + for (APT::VersionSet::const_iterator Ver = verset.begin(); Ver != verset.end(); ++Ver) { - string changelogfile = string(tmpdir) + "changelog"; - if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile)) + string changelogfile; + if (downOnly == false) + changelogfile.append(tmpname).append("changelog"); + else + changelogfile.append(Ver.ParentPkg().Name()).append(".changelog"); + if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false) + { DisplayFileInPager(changelogfile); - // cleanup temp file - unlink(changelogfile.c_str()); + // cleanup temp file + unlink(changelogfile.c_str()); + } } // clenaup tmp dir - rmdir(tmpdir); - free(tmpdir); + if (tmpdir != NULL) + rmdir(tmpdir); return true; } /*}}}*/ @@ -3076,8 +3191,6 @@ 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" " changelog - Download and display the changelog for the given package\n" " download - Download the binary package into the current directory\n" "\n" @@ -3159,7 +3272,9 @@ int main(int argc,const char *argv[]) /*{{{*/ {0,"auto-remove","APT::Get::AutomaticRemove",0}, {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0}, {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean}, + {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean}, {0,"fix-policy","APT::Get::Fix-Policy-Broken",0}, + {0,"solver","APT::Solver",CommandLine::HasArg}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}}; @@ -3211,7 +3326,10 @@ int main(int argc,const char *argv[]) /*{{{*/ } // simulate user-friendly if apt-get has no root privileges - if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true) + if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true && + (CmdL.FileSize() == 0 || + (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 && + strcmp(CmdL.FileList[0], "changelog") != 0))) { if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true) cout << _("NOTE: This is only a simulation!\n" diff --git a/cmdline/apt-internal-solver.cc b/cmdline/apt-internal-solver.cc new file mode 100644 index 000000000..ef6c688fe --- /dev/null +++ b/cmdline/apt-internal-solver.cc @@ -0,0 +1,190 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ##################################################################### + + cover around the internal solver to be able to run it like an external + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <apt-pkg/error.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/init.h> +#include <apt-pkg/cachefile.h> +#include <apt-pkg/strutl.h> +#include <apt-pkg/edsp.h> +#include <apt-pkg/algorithms.h> +#include <apt-pkg/fileutl.h> + +#include <config.h> +#include <apti18n.h> + +#include <unistd.h> +#include <cstdio> + /*}}}*/ + +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp(CommandLine &CmdL) { + ioprintf(std::cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION, + COMMON_ARCH,__DATE__,__TIME__); + + std::cout << + _("Usage: apt-internal-resolver\n" + "\n" + "apt-internal-resolver is an interface to use the current internal\n" + "like an external resolver for the APT family for debugging or alike\n" + "\n" + "Options:\n" + " -h This help text.\n" + " -q Loggable output - no progress indicator\n" + " -c=? Read this configuration file\n" + " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n" + "apt.conf(5) manual pages for more information and options.\n" + " This APT has Super Cow Powers.\n"); + return true; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {'v',"version","version",0}, + {'q',"quiet","quiet",CommandLine::IntLevel}, + {'q',"silent","quiet",CommandLine::IntLevel}, + {'c',"config-file",0,CommandLine::ConfigFile}, + {'o',"option",0,CommandLine::ArbItem}, + {0,0,0,0}}; + + CommandLine CmdL(Args,_config); + if (pkgInitConfig(*_config) == false || + CmdL.Parse(argc,argv) == false) { + _error->DumpErrors(); + return 2; + } + + // See if the help should be shown + if (_config->FindB("help") == true || + _config->FindB("version") == true) { + ShowHelp(CmdL); + return 1; + } + + if (CmdL.FileList[0] != 0 && strcmp(CmdL.FileList[0], "scenario") == 0) + { + if (pkgInitSystem(*_config,_system) == false) { + std::cerr << "System could not be initialized!" << std::endl; + return 1; + } + pkgCacheFile CacheFile; + CacheFile.Open(NULL, false); + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + FILE* output = stdout; + if (pkgset.empty() == true) + EDSP::WriteScenario(CacheFile, output); + else + EDSP::WriteLimitedScenario(CacheFile, output, pkgset); + fclose(output); + _error->DumpErrors(std::cerr); + return 0; + } + + // Deal with stdout not being a tty + if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) + _config->Set("quiet","1"); + + if (_config->FindI("quiet", 0) < 1) + _config->Set("Debug::EDSP::WriteSolution", true); + + _config->Set("APT::Solver", "internal"); + _config->Set("edsp::scenario", "stdin"); + int input = STDIN_FILENO; + FILE* output = stdout; + SetNonBlock(input, false); + + EDSP::WriteProgress(0, "Start up solver…", output); + + if (pkgInitSystem(*_config,_system) == false) { + std::cerr << "System could not be initialized!" << std::endl; + return 1; + } + + EDSP::WriteProgress(1, "Read request…", output); + + if (WaitFd(input, false, 5) == false) + std::cerr << "WAIT timed out in the resolver" << std::endl; + + std::list<std::string> install, remove; + bool upgrade, distUpgrade, autoRemove; + if (EDSP::ReadRequest(input, install, remove, upgrade, distUpgrade, autoRemove) == false) { + std::cerr << "Parsing the request failed!" << std::endl; + return 2; + } + + EDSP::WriteProgress(5, "Read scenario…", output); + + pkgCacheFile CacheFile; + CacheFile.Open(NULL, false); + + EDSP::WriteProgress(50, "Apply request on scenario…", output); + + if (EDSP::ApplyRequest(install, remove, CacheFile) == false) { + std::cerr << "Failed to apply request to depcache!" << std::endl; + return 3; + } + + pkgProblemResolver Fix(CacheFile); + for (std::list<std::string>::const_iterator i = remove.begin(); + i != remove.end(); ++i) { + pkgCache::PkgIterator P = CacheFile->FindPkg(*i); + Fix.Clear(P); + Fix.Protect(P); + Fix.Remove(P); + } + + for (std::list<std::string>::const_iterator i = install.begin(); + i != install.end(); ++i) { + pkgCache::PkgIterator P = CacheFile->FindPkg(*i); + Fix.Clear(P); + Fix.Protect(P); + } + + for (std::list<std::string>::const_iterator i = install.begin(); + i != install.end(); ++i) + CacheFile->MarkInstall(CacheFile->FindPkg(*i), true); + + EDSP::WriteProgress(60, "Call problemresolver on current scenario…", output); + + if (upgrade == true) { + if (pkgAllUpgrade(CacheFile) == false) { + EDSP::WriteError("ERR_UNSOLVABLE_UPGRADE", "An upgrade error occured", output); + return 0; + } + } else if (distUpgrade == true) { + if (pkgDistUpgrade(CacheFile) == false) { + EDSP::WriteError("ERR_UNSOLVABLE_DIST_UPGRADE", "An dist-upgrade error occured", output); + return 0; + } + } else if (Fix.Resolve() == false) { + EDSP::WriteError("ERR_UNSOLVABLE", "An error occured", output); + return 0; + } + + EDSP::WriteProgress(95, "Write solution…", output); + + if (EDSP::WriteSolution(CacheFile, output) == false) { + std::cerr << "Failed to output the solution!" << std::endl; + return 4; + } + + EDSP::WriteProgress(100, "Done", output); + + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(std::cerr); + else + _error->DumpErrors(std::cerr, GlobalError::DEBUG); + return Errors == true ? 100 : 0; +} + /*}}}*/ diff --git a/cmdline/apt-key b/cmdline/apt-key index c1e01a776..843163f82 100755 --- a/cmdline/apt-key +++ b/cmdline/apt-key @@ -7,7 +7,7 @@ unset GREP_OPTIONS # implodes if there isn't one available GPG_CMD='gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /etc/apt/secring.gpg' -if ! id -u > /dev/null; then +if [ "$(id -u)" -eq 0 ]; then GPG_CMD="$GPG_CMD --trustdb-name /etc/apt/trustdb.gpg" fi @@ -21,6 +21,13 @@ ARCHIVE_KEYRING_URI="" ARCHIVE_KEYRING=/usr/share/keyrings/debian-archive-keyring.gpg REMOVED_KEYS=/usr/share/keyrings/debian-archive-removed-keys.gpg +requires_root() { + if [ "$(id -u)" -ne 0 ]; then + echo >&1 "ERROR: This command can only be used by root." + exit 1 + fi +} + add_keys_with_verify_against_master_keyring() { ADD_KEYRING=$1 MASTER=$2 @@ -59,13 +66,14 @@ add_keys_with_verify_against_master_keyring() { # (otherwise it does not make sense from a security POV) net_update() { if [ -z "$ARCHIVE_KEYRING_URI" ]; then - echo "ERROR: no location for the archive-keyring given" + echo >&2 "ERROR: Your distribution is not supported in net-update as no uri for the archive-keyring is set" exit 1 fi + requires_root # in theory we would need to depend on wget for this, but this feature # isn't useable in debian anyway as we have no keyring uri nor a master key if ! which wget >/dev/null 2>&1; then - echo "ERROR: an installed wget is required for a network-based update" + echo >&2 "ERROR: an installed wget is required for a network-based update" exit 1 fi if [ ! -d /var/lib/apt/keyrings ]; then @@ -93,6 +101,7 @@ update() { echo >&2 "Is the debian-archive-keyring package installed?" exit 1 fi + requires_root # add new keys from the package; @@ -184,10 +193,12 @@ fi case "$command" in add) + requires_root $GPG --quiet --batch --import "$1" echo "OK" ;; del|rm|remove) + requires_root $GPG --quiet --batch --delete-key --yes "$1" echo "OK" ;; diff --git a/cmdline/apt-mark b/cmdline/apt-mark deleted file mode 100755 index c64d4356c..000000000 --- a/cmdline/apt-mark +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/python - -from optparse import OptionParser - -import sys -import os.path - -try: - import apt_pkg -except ImportError: - print >> sys.stderr, "Error importing apt_pkg, is python-apt installed?" - sys.exit(1) - -actions = { "markauto" : 1, - "unmarkauto": 0 - } - -def show_automatic(filename): - if not os.path.exists(STATE_FILE): - return - auto = set() - tagfile = apt_pkg.TagFile(open(STATE_FILE)) - for section in tagfile: - pkgname = section.get("Package") - autoInst = section.get("Auto-Installed") - if int(autoInst): - auto.add(pkgname) - print "\n".join(sorted(auto)) - - -def mark_unmark_automatic(filename, action, pkgs): - " mark or unmark automatic flag" - # open the statefile - if os.path.exists(STATE_FILE): - try: - tagfile = apt_pkg.TagFile(open(STATE_FILE)) - outfile = open(STATE_FILE+".tmp","w") - except IOError, msg: - print "%s, are you root?" % (msg) - sys.exit(1) - for section in tagfile: - pkgname = section.get("Package") - autoInst = section.get("Auto-Installed") - if pkgname in pkgs: - if options.verbose: - print "changing %s to %s" % (pkgname,action) - newsec = apt_pkg.rewrite_section(section, - [], - [ ("Auto-Installed",str(action)) ]) - pkgs.remove(pkgname) - outfile.write(newsec+"\n") - else: - outfile.write(str(section)+"\n") - if action == 1: - for pkgname in pkgs: - if options.verbose: - print "changing %s to %s" % (pkgname,action) - outfile.write("Package: %s\nAuto-Installed: %d\n\n" % (pkgname, action)) - # all done, rename the tmpfile - os.chmod(outfile.name, 0644) - os.rename(outfile.name, STATE_FILE) - os.chmod(STATE_FILE, 0644) - - -if __name__ == "__main__": - apt_pkg.init() - - # option parsing - parser = OptionParser() - parser.usage = "%prog [options] {markauto|unmarkauto} packages..." - parser.epilog = "apt-mark is deprecated, use apt-get markauto/unmarkauto." - parser.add_option("-f", "--file", action="store", type="string", - dest="filename", - help="read/write a different file") - parser.add_option("-v", "--verbose", - action="store_true", dest="verbose", default=False, - help="print verbose status messages to stdout") - (options, args) = parser.parse_args() - - if not args: - parser.print_help() - sys.exit(1) - - # get the state-file - if not options.filename: - STATE_FILE = apt_pkg.config.find_dir("Dir::State") + "extended_states" - else: - STATE_FILE=options.filename - - if len(args) == 0: - parser.error("first argument must be 'markauto', 'unmarkauto' or 'showauto'") - - if args[0] == "showauto": - show_automatic(STATE_FILE) - else: - # get pkgs to change - if args[0] not in actions.keys(): - parser.error("first argument must be 'markauto', 'unmarkauto' or 'showauto'") - pkgs = args[1:] - action = actions[args[0]] - mark_unmark_automatic(STATE_FILE, action, pkgs) diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc new file mode 100644 index 000000000..b2c664979 --- /dev/null +++ b/cmdline/apt-mark.cc @@ -0,0 +1,373 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ##################################################################### + apt-mark - show and change auto-installed bit information + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <apt-pkg/cachefile.h> +#include <apt-pkg/cacheset.h> +#include <apt-pkg/cmndline.h> +#include <apt-pkg/error.h> +#include <apt-pkg/init.h> +#include <apt-pkg/strutl.h> + +#include <config.h> +#include <apti18n.h> + +#include <algorithm> + /*}}}*/ +using namespace std; + +ostream c0out(0); +ostream c1out(0); +ostream c2out(0); +ofstream devnull("/dev/null"); +/* DoAuto - mark packages as automatically/manually installed {{{*/ +bool DoAuto(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgDepCache *DepCache = CacheFile.GetDepCache(); + if (unlikely(Cache == NULL || DepCache == NULL)) + return false; + + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + if (pkgset.empty() == true) + return _error->Error(_("No packages found")); + + bool MarkAuto = strcasecmp(CmdL.FileList[0],"auto") == 0; + int AutoMarkChanged = 0; + + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + { + if (Pkg->CurrentVer == 0) + { + ioprintf(c1out,_("%s can not be marked as it is not installed.\n"), Pkg.FullName(true).c_str()); + continue; + } + else if ((((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + { + if (MarkAuto == false) + ioprintf(c1out,_("%s was already set to manually installed.\n"), Pkg.FullName(true).c_str()); + else + ioprintf(c1out,_("%s was already set to automatically installed.\n"), Pkg.FullName(true).c_str()); + continue; + } + + if (MarkAuto == false) + ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.FullName(true).c_str()); + else + ioprintf(c1out,_("%s set to automatically installed.\n"), Pkg.FullName(true).c_str()); + + DepCache->MarkAuto(Pkg, MarkAuto); + ++AutoMarkChanged; + } + if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false) + return DepCache->writeStateFile(NULL); + return true; +} + /*}}}*/ +/* DoMarkAuto - mark packages as automatically/manually installed {{{*/ +/* Does the same as DoAuto but tries to do it exactly the same why as + the python implementation did it so it can be a drop-in replacement */ +bool DoMarkAuto(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgDepCache *DepCache = CacheFile.GetDepCache(); + if (unlikely(Cache == NULL || DepCache == NULL)) + return false; + + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + if (pkgset.empty() == true) + return _error->Error(_("No packages found")); + + bool const MarkAuto = strcasecmp(CmdL.FileList[0],"markauto") == 0; + bool const Verbose = _config->FindB("APT::MarkAuto::Verbose", false); + int AutoMarkChanged = 0; + + for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + { + if (Pkg->CurrentVer == 0 || + (((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + continue; + + if (Verbose == true) + ioprintf(c1out, "changing %s to %d\n", Pkg.Name(), (MarkAuto == false) ? 0 : 1); + + DepCache->MarkAuto(Pkg, MarkAuto); + ++AutoMarkChanged; + } + if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false) + return DepCache->writeStateFile(NULL); + + _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead.")); + + return true; +} + /*}}}*/ +/* ShowAuto - show automatically installed packages (sorted) {{{*/ +bool ShowAuto(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + pkgDepCache *DepCache = CacheFile.GetDepCache(); + if (unlikely(Cache == NULL || DepCache == NULL)) + return false; + + std::vector<string> packages; + + bool const ShowAuto = strcasecmp(CmdL.FileList[0],"showauto") == 0; + + if (CmdL.FileList[1] == 0) + { + packages.reserve(Cache->HeaderP->PackageCount / 3); + for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P) + if (P->CurrentVer != 0 && + (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto) + packages.push_back(P.FullName(true)); + } + else + { + APT::CacheSetHelper helper(false); // do not show errors + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); + packages.reserve(pkgset.size()); + for (APT::PackageSet::const_iterator P = pkgset.begin(); P != pkgset.end(); ++P) + if (P->CurrentVer != 0 && + (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto) + packages.push_back(P.FullName(true)); + } + + std::sort(packages.begin(), packages.end()); + + for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I) + std::cout << *I << std::endl; + + return true; +} + /*}}}*/ +/* DoHold - mark packages as hold by dpkg {{{*/ +bool DoHold(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + if (unlikely(Cache == NULL)) + return false; + + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1); + if (pkgset.empty() == true) + return _error->Error(_("No packages found")); + + bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0; + + for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + { + if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold) + { + if (MarkHold == true) + ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str()); + else + ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str()); + pkgset.erase(Pkg); + continue; + } + } + + if (pkgset.empty() == true) + return true; + + if (_config->FindB("APT::Mark::Simulate", false) == true) + { + for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + { + if (MarkHold == false) + ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str()); + else + ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str()); + } + return true; + } + + string dpkgcall = _config->Find("Dir::Bin::dpkg", "dpkg"); + std::vector<string> const dpkgoptions = _config->FindVector("DPkg::options"); + for (std::vector<string>::const_iterator o = dpkgoptions.begin(); + o != dpkgoptions.end(); ++o) + dpkgcall.append(" ").append(*o); + dpkgcall.append(" --set-selections"); + FILE *dpkg = popen(dpkgcall.c_str(), "w"); + if (dpkg == NULL) + return _error->Errno("DoHold", "fdopen on dpkg stdin failed"); + + for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg) + { + if (MarkHold == true) + { + fprintf(dpkg, "%s hold\n", Pkg.FullName(true).c_str()); + ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str()); + } + else + { + fprintf(dpkg, "%s install\n", Pkg.FullName(true).c_str()); + ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str()); + } + } + + int const status = pclose(dpkg); + if (status == -1) + return _error->Errno("DoHold", "dpkg execution failed in the end"); + if (WIFEXITED(status) == false || WEXITSTATUS(status) != 0) + return _error->Error(_("Executing dpkg failed. Are you root?")); + return true; +} + /*}}}*/ +/* ShowHold - show packages set on hold in dpkg status {{{*/ +bool ShowHold(CommandLine &CmdL) +{ + pkgCacheFile CacheFile; + pkgCache *Cache = CacheFile.GetPkgCache(); + if (unlikely(Cache == NULL)) + return false; + + std::vector<string> packages; + + if (CmdL.FileList[1] == 0) + { + packages.reserve(50); // how many holds are realistic? I hope just a few… + for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P) + if (P->SelectedState == pkgCache::State::Hold) + packages.push_back(P.FullName(true)); + } + else + { + APT::CacheSetHelper helper(false); // do not show errors + APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper); + packages.reserve(pkgset.size()); + for (APT::PackageSet::const_iterator P = pkgset.begin(); P != pkgset.end(); ++P) + if (P->SelectedState == pkgCache::State::Hold) + packages.push_back(P.FullName(true)); + } + + std::sort(packages.begin(), packages.end()); + + for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I) + std::cout << *I << std::endl; + + return true; +} + /*}}}*/ +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp(CommandLine &CmdL) +{ + ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION, + COMMON_ARCH,__DATE__,__TIME__); + + cout << + _("Usage: apt-mark [options] {auto|manual} pkg1 [pkg2 ...]\n" + "\n" + "apt-mark is a simple command line interface for marking packages\n" + "as manual or automatical installed. It can also list marks.\n" + "\n" + "Commands:\n" + " auto - Mark the given packages as automatically installed\n" + " manual - Mark the given packages as manually installed\n" + "\n" + "Options:\n" + " -h This help text.\n" + " -q Loggable output - no progress indicator\n" + " -qq No output except for errors\n" + " -s No-act. Just prints what would be done.\n" + " -f read/write auto/manual marking in the given file\n" + " -c=? Read this configuration file\n" + " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n" + "See the apt-mark(8) and apt.conf(5) manual pages for more information.") + << std::endl; + return true; +} + /*}}}*/ +int main(int argc,const char *argv[]) /*{{{*/ +{ + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {0,"version","version",0}, + {'q',"quiet","quiet",CommandLine::IntLevel}, + {'q',"silent","quiet",CommandLine::IntLevel}, + {'v',"verbose","APT::MarkAuto::Verbose",0}, + {'s',"simulate","APT::Mark::Simulate",0}, + {'s',"just-print","APT::Mark::Simulate",0}, + {'s',"recon","APT::Mark::Simulate",0}, + {'s',"dry-run","APT::Mark::Simulate",0}, + {'s',"no-act","APT::Mark::Simulate",0}, + {'f',"file","Dir::State::extended_states",CommandLine::HasArg}, + {'c',"config-file",0,CommandLine::ConfigFile}, + {'o',"option",0,CommandLine::ArbItem}, + {0,0,0,0}}; + CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp}, + {"auto",&DoAuto}, + {"manual",&DoAuto}, + {"hold",&DoHold}, + {"unhold",&DoHold}, + {"showauto",&ShowAuto}, + {"showmanual",&ShowAuto}, + {"showhold",&ShowHold}, + // be nice and forgive the typo + {"showholds",&ShowHold}, + // be nice and forgive it as it is technical right + {"install",&DoHold}, + // obsolete commands for compatibility + {"markauto", &DoMarkAuto}, + {"unmarkauto", &DoMarkAuto}, + {0,0}}; + + // Set up gettext support + setlocale(LC_ALL,""); + textdomain(PACKAGE); + + // Parse the command line and initialize the package library + CommandLine CmdL(Args,_config); + if (pkgInitConfig(*_config) == false || + CmdL.Parse(argc,argv) == false || + pkgInitSystem(*_config,_system) == false) + { + if (_config->FindB("version") == true) + ShowHelp(CmdL); + _error->DumpErrors(); + return 100; + } + + // See if the help should be shown + if (_config->FindB("help") == true || + _config->FindB("version") == true || + CmdL.FileSize() == 0) + { + ShowHelp(CmdL); + return 0; + } + + // Deal with stdout not being a tty + if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1) + _config->Set("quiet","1"); + + // Setup the output streams + c0out.rdbuf(cout.rdbuf()); + c1out.rdbuf(cout.rdbuf()); + c2out.rdbuf(cout.rdbuf()); + if (_config->FindI("quiet",0) > 0) + c0out.rdbuf(devnull.rdbuf()); + if (_config->FindI("quiet",0) > 1) + c1out.rdbuf(devnull.rdbuf()); + + // Match the operation + CmdL.DispatchArg(Cmds); + + // Print any errors or warnings found during parsing + bool const Errors = _error->PendingError(); + if (_config->FindI("quiet",0) > 0) + _error->DumpErrors(); + else + _error->DumpErrors(GlobalError::DEBUG); + return Errors == true ? 100 : 0; +} + /*}}}*/ diff --git a/cmdline/makefile b/cmdline/makefile index 917ccc96a..6d988a8f5 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -54,13 +54,28 @@ TARGET=program include $(COPY_H) # The apt-mark program -SOURCE=apt-mark -TO=$(BIN) -TARGET=program -include $(COPY_H) +PROGRAM=apt-mark +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt-mark.cc +include $(PROGRAM_H) # The apt-report-mirror-failure program #SOURCE=apt-report-mirror-failure #TO=$(BIN) #TARGET=program #include $(COPY_H) + +# The internal solver acting as an external +PROGRAM=apt-internal-solver +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt-internal-solver.cc +include $(PROGRAM_H) + +# The internal solver acting as an external +PROGRAM=apt-dump-solver +SLIBS = -lapt-pkg $(INTLLIBS) +LIB_MAKES = apt-pkg/makefile +SOURCE = apt-dump-solver.cc +include $(PROGRAM_H) |