summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2018-12-11 17:38:27 +0100
committerJulian Andres Klode <julian.klode@canonical.com>2019-01-10 10:38:59 +0100
commitbe7eb047e1202971f84bb4ac27e796d85bebdce9 (patch)
tree7c754a5a0f4cfd4b50352988b97ca09fcb54ce14
parent29626ddaf19284855ba3244cff28612cbc1e2b84 (diff)
apt-mark: Introduce minimize-manual
This visits dependencies of all manually installed metapackages, as determined by APT::Never-MarkAuto-Sections, and marks them as automatically installed. It can be used to clean up autoflags after a d-i install, for example.
-rw-r--r--apt-private/private-cmndline.cc11
-rw-r--r--cmdline/apt-mark.cc122
-rw-r--r--doc/apt-mark.8.xml8
3 files changed, 139 insertions, 2 deletions
diff --git a/apt-private/private-cmndline.cc b/apt-private/private-cmndline.cc
index 101e0ae40..87deb6bf0 100644
--- a/apt-private/private-cmndline.cc
+++ b/apt-private/private-cmndline.cc
@@ -287,7 +287,7 @@ static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const
{
if (CmdMatches("auto", "manual", "hold", "unhold", "showauto",
"showmanual", "showhold", "showholds",
- "markauto", "unmarkauto"))
+ "markauto", "unmarkauto", "minimize-manual"))
{
addArg('f',"file","Dir::State::extended_states",CommandLine::HasArg);
}
@@ -303,7 +303,14 @@ static bool addArgumentsAPTMark(std::vector<CommandLine::Args> &Args, char const
addArg('v',"verbose","APT::MarkAuto::Verbose",0);
}
- if (Cmd != nullptr && strncmp(Cmd, "show", strlen("show")) != 0)
+ if (CmdMatches("minimize-manual"))
+ {
+ addArg('y',"yes","APT::Get::Assume-Yes",0);
+ addArg('y',"assume-yes","APT::Get::Assume-Yes",0);
+ addArg(0,"assume-no","APT::Get::Assume-No",0);
+ }
+
+ if (CmdMatches("minimize-manual") || (Cmd != nullptr && strncmp(Cmd, "show", strlen("show")) != 0))
{
addArg('s',"simulate","APT::Mark::Simulate",0);
addArg('s',"just-print","APT::Mark::Simulate",0);
diff --git a/cmdline/apt-mark.cc b/cmdline/apt-mark.cc
index 927b31d2f..161845b53 100644
--- a/cmdline/apt-mark.cc
+++ b/cmdline/apt-mark.cc
@@ -125,6 +125,127 @@ static bool DoMarkAuto(CommandLine &CmdL)
return true;
}
/*}}}*/
+// helper for Install-Recommends-Sections and Never-MarkAuto-Sections /*{{{*/
+static bool
+ConfigValueInSubTree(const char *SubTree, const char *needle)
+{
+ // copied from depcache.cc
+ Configuration::Item const *Opts;
+ Opts = _config->Tree(SubTree);
+ if (Opts != 0 && Opts->Child != 0)
+ {
+ Opts = Opts->Child;
+ for (; Opts != 0; Opts = Opts->Next)
+ {
+ if (Opts->Value.empty() == true)
+ continue;
+ if (strcmp(needle, Opts->Value.c_str()) == 0)
+ return true;
+ }
+ }
+ return false;
+}
+ /*}}}*/
+/* DoMinimize - minimize manually installed {{{*/
+/* Traverses dependencies of meta packages and marks them as manually
+ * installed. */
+static bool DoMinimize(CommandLine &CmdL)
+{
+
+ pkgCacheFile CacheFile;
+ pkgDepCache *const DepCache = CacheFile.GetDepCache();
+ if (unlikely(DepCache == nullptr))
+ return false;
+
+ if (CmdL.FileList[1] != nullptr)
+ return _error->Error(_("%s does not take any arguments"), "apt-mark minimize-manual");
+
+ auto Debug = _config->FindB("Debug::AptMark::Minimize", false);
+ auto is_root = [&DepCache](pkgCache::PkgIterator const &pkg) {
+ auto ver = pkg.CurrentVer();
+ return ver.end() == false && ((*DepCache)[pkg].Flags & pkgCache::Flag::Auto) == 0 &&
+ ver->Section != 0 &&
+ ConfigValueInSubTree("APT::Never-MarkAuto-Sections", ver.Section());
+ };
+
+ APT::PackageSet roots;
+ for (auto Pkg = DepCache->PkgBegin(); Pkg.end() == false; ++Pkg)
+ {
+ if (is_root(Pkg))
+ {
+ if (Debug)
+ std::clog << "Found root " << Pkg.Name() << std::endl;
+ roots.insert(Pkg);
+ }
+ }
+
+ APT::PackageSet workset(roots);
+ APT::PackageSet seen;
+ APT::PackageSet changed;
+
+ pkgDepCache::ActionGroup group(*DepCache);
+
+ while (workset.empty() == false)
+ {
+ if (Debug)
+ std::clog << "Iteration\n";
+
+ APT::PackageSet workset2;
+ for (auto &Pkg : workset)
+ {
+ if (seen.find(Pkg) != seen.end())
+ continue;
+
+ seen.insert(Pkg);
+
+ if (Debug)
+ std::cerr << " Visiting " << Pkg.FullName(true) << "\n";
+ if (roots.find(Pkg) == roots.end() && ((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == 0)
+ {
+ DepCache->MarkAuto(Pkg, true);
+ changed.insert(Pkg);
+ }
+
+ // Visit dependencies, add them to next working set
+ for (auto Dep = Pkg.CurrentVer().DependsList(); !Dep.end(); ++Dep)
+ {
+ if (DepCache->IsImportantDep(Dep) == false)
+ continue;
+ std::unique_ptr<pkgCache::Version *[]> targets(Dep.AllTargets());
+ for (int i = 0; targets[i] != nullptr; i++)
+ {
+ pkgCache::VerIterator Tgt(*DepCache, targets[i]);
+ if (Tgt.ParentPkg()->CurrentVer != 0 && Tgt.ParentPkg().CurrentVer()->ID == Tgt->ID)
+ workset2.insert(Tgt.ParentPkg());
+ }
+ }
+ }
+
+ workset = std::move(workset2);
+ }
+
+ if (changed.empty()) {
+ cout << _("No changes necessary") << endl;
+ return true;
+ }
+
+ ShowList(c1out, _("The following packages will be marked as automatically installed:"), changed,
+ [](const pkgCache::PkgIterator &) { return true; },
+ &PrettyFullName,
+ &PrettyFullName);
+
+ if (_config->FindB("APT::Mark::Simulate", false) == false)
+ {
+ if (YnPrompt(_("Do you want to continue?"), false) == false)
+ return true;
+
+ return DepCache->writeStateFile(NULL);
+ }
+
+ return true;
+}
+ /*}}}*/
+
/* ShowAuto - show automatically installed packages (sorted) {{{*/
static bool ShowAuto(CommandLine &CmdL)
{
@@ -293,6 +414,7 @@ static std::vector<aptDispatchWithHelp> GetCommands() /*{{{*/
return {
{"auto",&DoAuto, _("Mark the given packages as automatically installed")},
{"manual",&DoAuto, _("Mark the given packages as manually installed")},
+ {"minimize-manual", &DoMinimize, _("Mark all dependencies of meta packages as automatically installed.")},
{"hold",&DoSelection, _("Mark a package as held back")},
{"unhold",&DoSelection, _("Unset a package set as held back")},
{"install",&DoSelection, nullptr},
diff --git a/doc/apt-mark.8.xml b/doc/apt-mark.8.xml
index ddde0416f..ea39b7faa 100644
--- a/doc/apt-mark.8.xml
+++ b/doc/apt-mark.8.xml
@@ -66,6 +66,14 @@
</para></listitem>
</varlistentry>
+ <varlistentry><term><option>minimize-manual</option></term>
+ <listitem><para><literal>minimize-manual</literal> is used to mark
+ (transitive) dependencies of metapackages as automatically installed.
+ This can be used after an installation for example, to minimize the
+ number of manually installed packages; or continuously on systems
+ managed by system configuration metapackages.
+ </para></listitem>
+ </varlistentry>
<varlistentry><term><option>showauto</option></term>
<listitem><para><literal>showauto</literal> is used to print a
list of automatically installed packages with each package on a new line.