From 9d47fcf4db4d9d8a56de8f0ba44c04598f673e5b Mon Sep 17 00:00:00 2001 From: Aleksei Nikiforov Date: Thu, 26 Oct 2017 15:58:22 +0300 Subject: [PATCH] Add skeleton of apt-mark. --- apt/apt-pkg/depcache.cc | 26 +++- apt/apt-pkg/depcache.h | 7 + apt/apt-pkg/rpm/rpmsystem.cc | 5 +- apt/cmdline/Makefile.am | 4 +- apt/cmdline/apt-get.cc | 1 + apt/cmdline/apt-mark.cc | 287 +++++++++++++++++++++++++++++++++++ apt/cmdline/apt-shell.cc | 1 + 7 files changed, 328 insertions(+), 3 deletions(-) create mode 100644 apt/cmdline/apt-mark.cc diff --git a/apt/apt-pkg/depcache.cc b/apt/apt-pkg/depcache.cc index df2116b..b2d8c6a 100644 --- a/apt/apt-pkg/depcache.cc +++ b/apt/apt-pkg/depcache.cc @@ -613,6 +613,8 @@ void pkgDepCache::Update(OpProgress *Prog) if (Prog != 0) Prog->Progress(Done); + + readStateFile(Prog); } /*}}}*/ // DepCache::Update - Update the deps list of a package /*{{{*/ @@ -665,7 +667,15 @@ void pkgDepCache::Update(PkgIterator const &Pkg) Update(P.ParentPkg().RevDependsList()); } - /*}}}*/ +bool pkgDepCache::readStateFile(OpProgress * const prog) +{ + return false; +} + +bool pkgDepCache::writeStateFile(OpProgress * const prog, bool const InstalledOnly) +{ + return false; +} // DepCache::MarkKeep - Put the package in the keep state /*{{{*/ // --------------------------------------------------------------------- @@ -752,6 +762,20 @@ void pkgDepCache::MarkDelete(PkgIterator const &Pkg, bool rPurge) Update(Pkg); AddSizes(Pkg); } + +void pkgDepCache::MarkAuto(const PkgIterator &Pkg, bool Auto) +{ + StateCache &state = PkgState[Pkg->ID]; + + if (Auto) + { + state.Flags |= Flag::Auto; + } + else + { + state.Flags &= ~Flag::Auto; + } +} /*}}}*/ // DepCache::MarkInstall - Put the package in the install state /*{{{*/ // --------------------------------------------------------------------- diff --git a/apt/apt-pkg/depcache.h b/apt/apt-pkg/depcache.h index c7dd89e..918b328 100644 --- a/apt/apt-pkg/depcache.h +++ b/apt/apt-pkg/depcache.h @@ -198,6 +198,9 @@ class pkgDepCache : protected pkgCache::Namespace void MarkKeep(PkgIterator const &Pkg,bool Soft = false); void MarkDelete(PkgIterator const &Pkg,bool Purge = false); + /** Set the "is automatically installed" flag of Pkg. */ + void MarkAuto(const PkgIterator &Pkg, bool Auto); + // shallow mark; ret: -1 err, 0 already marked, 1 just marked int MarkInstall0(PkgIterator const &Pkg); // non-ambiguous recursive mark; MarkAgain should be marked again @@ -218,6 +221,10 @@ class pkgDepCache : protected pkgCache::Namespace // This is for debuging void Update(OpProgress *Prog = 0); + // read and write persistent states + bool readStateFile(OpProgress * const prog); + bool writeStateFile(OpProgress * const prog, bool const InstalledOnly = true); + // Size queries inline double UsrSize() {return iUsrSize;}; inline double DebSize() {return iDownloadSize;}; diff --git a/apt/apt-pkg/rpm/rpmsystem.cc b/apt/apt-pkg/rpm/rpmsystem.cc index 33130f7..24c6da7 100644 --- a/apt/apt-pkg/rpm/rpmsystem.cc +++ b/apt/apt-pkg/rpm/rpmsystem.cc @@ -130,7 +130,7 @@ pkgPackageManager *rpmSystem::CreatePM(pkgDepCache *Cache) const else return new pkgRPMExtPM(Cache); } - /*}}}*/ + // System::Initialize - Setup the configuration space.. /*{{{*/ // --------------------------------------------------------------------- /* These are the rpm specific configuration variables.. */ @@ -190,6 +190,9 @@ bool rpmSystem::Initialize(Configuration &Cnf) Cnf.Set("RPM::Options::", "--nodeps"); } + // In apt-get it's called 'Dir::State::apt_mark_storage', but format used here is incompatible, due to that name is different + Cnf.CndSet("Dir::State::apt_mark_storage", "apt_mark_storage"); + #if RPM_VERSION >= 0x040201 const char *RPMOptions[] = { diff --git a/apt/cmdline/Makefile.am b/apt/cmdline/Makefile.am index 3dc3b76..b4c5608 100644 --- a/apt/cmdline/Makefile.am +++ b/apt/cmdline/Makefile.am @@ -1,7 +1,7 @@ EXTRA_DIST = indexcopy.cc indexcopy.h -bin_PROGRAMS = apt-get apt-cache apt-cdrom apt-config +bin_PROGRAMS = apt-get apt-cache apt-cdrom apt-config apt-mark if COMPILE_APTSHELL bin_PROGRAMS += apt-shell apt-pipe @@ -22,6 +22,8 @@ apt_pipe_CPPFLAGS = -DAPT_PIPE apt_pipe_LDADD = $(LDADD) -lsetproctitle apt_config_SOURCES = apt-config.cc apt_cdrom_SOURCES = apt-cdrom.cc rpmindexcopy.cc rpmindexcopy.h +apt_mark_SOURCES = apt-mark.cc +apt_mark_LDADD = $(LDADD) -lreadline apt_get_static_SOURCES = $(apt_get_SOURCES) apt_get_static_LDFLAGS = -all-static diff --git a/apt/cmdline/apt-get.cc b/apt/cmdline/apt-get.cc index 1155b9e..e3eab5f 100644 --- a/apt/cmdline/apt-get.cc +++ b/apt/cmdline/apt-get.cc @@ -528,6 +528,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, Ret &= DoClean(*CmdL); else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) Ret &= DoAutoClean(*CmdL); + Cache->writeStateFile(0, false); return Ret; } diff --git a/apt/cmdline/apt-mark.cc b/apt/cmdline/apt-mark.cc new file mode 100644 index 0000000..93027fe --- /dev/null +++ b/apt/cmdline/apt-mark.cc @@ -0,0 +1,287 @@ +/* ##################################################################### + apt-mark - show and change auto-installed bit information + ##################################################################### */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +std::ostream c0out(0); +std::ostream c1out(0); +std::ostream c2out(0); +std::ostream c3out(0); // script output stream +std::ofstream devnull("/dev/null"); +unsigned int ScreenWidth = 80; + +/* DoAuto - mark packages as automatically/manually installed */ +static bool DoAuto(CommandLine &CmdL) +{ + CacheFile Cache(c1out); + if (!Cache.OpenForInstall()) + { + return false; + } + + pkgDepCache * const DepCache = static_cast(Cache); + if (DepCache == nullptr) + { + return false; + } + + if (CmdL.FileList[1] == nullptr) + { + return _error->Error(_("No packages found")); + } + + bool MarkAuto = (strcasecmp(CmdL.FileList[0], "auto") == 0); + int AutoMarkChanged = 0; + + for (const char **I = CmdL.FileList + 1; *I != 0; ++I) + { + auto pkgiter = Cache->FindPkg(*I); + if (!pkgiter.end()) + { + if (pkgiter->CurrentVer == 0) + { + ioprintf(c1out, _("%s can not be marked as it is not installed.\n"), pkgiter.Name()); + continue; + } + + else if ((((*DepCache)[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto) + { + if (!MarkAuto) + { + ioprintf(c1out,_("%s was already set to manually installed.\n"), pkgiter.Name()); + } + else + { + ioprintf(c1out,_("%s was already set to automatically installed.\n"), pkgiter.Name()); + } + + continue; + } + + if (!MarkAuto) + { + ioprintf(c1out,_("%s set to manually installed.\n"), pkgiter.Name()); + } + else + { + ioprintf(c1out,_("%s set to automatically installed.\n"), pkgiter.Name()); + } + + DepCache->MarkAuto(pkgiter, MarkAuto); + ++AutoMarkChanged; + } + } + + if ((AutoMarkChanged > 0) && (!_config->FindB("APT::Mark::Simulate", false))) + { + return DepCache->writeStateFile(NULL); + } + + return true; +} + +/* ShowAuto - show automatically installed packages (sorted) */ +static bool ShowAuto(CommandLine &CmdL) +{ + CacheFile Cache(c1out); + if (!Cache.Open(false)) + { + return false; + } + + pkgDepCache * const DepCache = static_cast(Cache); + if (DepCache == nullptr) + { + return false; + } + + std::vector packages; + + bool const ShowAuto = (strcasecmp(CmdL.FileList[0], "showauto") == 0); + + if (CmdL.FileList[1] == nullptr) + { + packages.reserve(DepCache->Head().PackageCount / 3); + for (pkgCache::PkgIterator P = DepCache->PkgBegin(); !P.end(); ++P) + { + if ((P->CurrentVer != 0) + && ((((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)) + { + packages.push_back(P.Name()); + } + } + } + else + { + { + size_t filelist_size = 0; + for (const char **I = CmdL.FileList + 1; *I != 0; ++I) + { + ++filelist_size; + } + + packages.reserve(filelist_size); + } + + for (const char **I = CmdL.FileList + 1; *I != 0; ++I) + { + auto pkgiter = Cache->FindPkg(*I); + if (!pkgiter.end()) + { + if ((pkgiter->CurrentVer != 0) + && ((((*DepCache)[pkgiter].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)) + { + packages.push_back(pkgiter.Name()); + } + } + } + } + + std::sort(packages.begin(), packages.end()); + + for (std::vector::const_iterator I = packages.begin(); I != packages.end(); ++I) + { + std::cout << *I << std::endl; + } + + return true; +} + +static bool ShowHelp() +{ + std::cout << + _("Usage: apt-mark [options] {auto|manual} pkg1 [pkg2 ...]\n" + "\n" + "apt-mark is a simple command line interface for marking packages\n" + "as manually or automatically installed.\n"); + + std::cout << + _("Usage: apt-mark [options] command\n" + "\n" + "apt-mark is a simple command line interface for marking packages\n" + "as manually or automatically installed.\n" + "\n" + "Commands:\n" + "\tauto pkg1 [pkg2 ...] - mark the given packages as automatically installed\n" + "\tmanual pkg1 [pkg2 ...] - mark the given packages as manually installed\n" + "\tshowauto [pkg1 ...] - print the list of automatically installed packages\n" + "\tshowmanual [pkg1 ...] - Print the list of manually installed packages\n"); + + return true; +} + +int main(int argc, char **argv) +{ + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {'v',"version","version",0}, + {'q',"quiet","quiet",CommandLine::IntLevel}, + { 0, "simple-output","simple-output",0}, + {'s',"simulate","APT::Mark::Simulate",0}, + {'s',"dry-run","APT::Mark::Simulate",0}, + {0,0,0,0} + }; + + CommandLine::Dispatch Cmds[] = { + {"auto",&DoAuto}, + {"manual",&DoAuto}, + {"showauto",&ShowAuto}, + {"showmanual",&ShowAuto}, + {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)) + || (!pkgInitSystem(*_config, _system)) + || (!CmdL.Parse(argc, const_cast(argv)))) + { + _error->DumpErrors(); + return 100; + } + + // See if the help should be shown + if (_config->FindB("help") + || (CmdL.FileSize() == 0)) + { + return ShowHelp(); + } + + // Deal with stdout not being a tty + if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1) + { + _config->Set("quiet","1"); + } + + // Setup the output streams + if (_config->FindB("simple-output")) + { + c0out.rdbuf(devnull.rdbuf()); + c1out.rdbuf(devnull.rdbuf()); + c2out.rdbuf(devnull.rdbuf()); + c3out.rdbuf(std::cout.rdbuf()); + } + else + { + c0out.rdbuf(std::cout.rdbuf()); + c1out.rdbuf(std::cout.rdbuf()); + c2out.rdbuf(std::cout.rdbuf()); + c3out.rdbuf(devnull.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 + if (!_error->empty()) + { + bool Errors = _error->PendingError(); + _error->DumpErrors(); + return (Errors ? 100 : 0); + } + + return 0; +} diff --git a/apt/cmdline/apt-shell.cc b/apt/cmdline/apt-shell.cc index 6bbef80..825d1f9 100644 --- a/apt/cmdline/apt-shell.cc +++ b/apt/cmdline/apt-shell.cc @@ -992,6 +992,7 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true, Ret &= DoClean(*CmdL); else if (_config->FindB("APT::Post-Install::AutoClean",false) == true) Ret &= DoAutoClean(*CmdL); + Cache->writeStateFile(0, false); return Ret; }