Quellcode durchsuchen

add binary-specific options via Binary scope

Especially with apt now, it can be useful to set an option only for apt
and not for apt-get. Using a binary-specific subtree which is merged into
the root seems like a simple enough trick to achieve this.
David Kalnischkies vor 10 Jahren
Ursprung
Commit
c3ded84c6f

+ 53 - 0
apt-pkg/contrib/configuration.cc

@@ -485,6 +485,59 @@ void Configuration::Clear(string const &Name)
    }
 }
 									/*}}}*/
+void Configuration::MoveSubTree(char const * const OldRootName, char const * const NewRootName)/*{{{*/
+{
+   // prevent NewRoot being a subtree of OldRoot
+   if (OldRootName == nullptr)
+      return;
+   if (NewRootName != nullptr)
+   {
+      if (strcmp(OldRootName, NewRootName) == 0)
+	 return;
+      std::string const oldroot = std::string(OldRootName) + "::";
+      if (strcasestr(NewRootName, oldroot.c_str()) != NULL)
+	 return;
+   }
+
+   Item * Top;
+   Item const * const OldRoot = Top = Lookup(OldRootName, false);
+   if (Top == nullptr)
+      return;
+   std::string NewRoot;
+   if (NewRootName != nullptr)
+      NewRoot.append(NewRootName).append("::");
+
+   Top->Value.clear();
+   Item * const Stop = Top;
+   Top = Top->Child;
+   Stop->Child = 0;
+   for (; Top != 0;)
+   {
+      if (Top->Child != 0)
+      {
+	 Top = Top->Child;
+	 continue;
+      }
+
+      while (Top != 0 && Top->Next == 0)
+      {
+	 Set(NewRoot + Top->FullTag(OldRoot), Top->Value);
+	 Item const * const Tmp = Top;
+	 Top = Top->Parent;
+	 delete Tmp;
+
+	 if (Top == Stop)
+	    return;
+      }
+
+      Set(NewRoot + Top->FullTag(OldRoot), Top->Value);
+      Item const * const Tmp = Top;
+      if (Top != 0)
+	 Top = Top->Next;
+      delete Tmp;
+   }
+}
+									/*}}}*/
 // Configuration::Exists - Returns true if the Name exists		/*{{{*/
 // ---------------------------------------------------------------------
 /* */

+ 2 - 0
apt-pkg/contrib/configuration.h

@@ -103,6 +103,8 @@ class Configuration
    bool Exists(const char *Name) const;
    bool ExistsAny(const char *Name) const;
 
+   void MoveSubTree(char const * const OldRoot, char const * const NewRoot);
+
    // clear a whole tree
    void Clear(const std::string &Name);
    void Clear();

+ 16 - 2
apt-private/private-cmndline.cc

@@ -3,6 +3,7 @@
 
 #include <apt-pkg/cmndline.h>
 #include <apt-pkg/configuration.h>
+#include <apt-pkg/fileutl.h>
 #include <apt-pkg/pkgsystem.h>
 #include <apt-pkg/init.h>
 #include <apt-pkg/error.h>
@@ -322,8 +323,21 @@ void ParseCommandLine(CommandLine &CmdL, CommandLine::Dispatch * const Cmds, Com
       Configuration * const * const Cnf, pkgSystem ** const Sys, int const argc, const char *argv[], bool(*ShowHelp)(CommandLine &CmdL))
 {
    CmdL = CommandLine(Args,_config);
-   if ((Cnf != NULL && pkgInitConfig(**Cnf) == false) ||
-       CmdL.Parse(argc,argv) == false ||
+   if (Cnf != NULL && pkgInitConfig(**Cnf) == false)
+   {
+      _error->DumpErrors();
+      exit(100);
+   }
+
+   if (likely(argc != 0 && argv[0] != NULL))
+   {
+      std::string const binary = flNotDir(argv[0]);
+      _config->Set("Binary", binary);
+      std::string const conf = "Binary::" + binary;
+      _config->MoveSubTree(conf.c_str(), NULL);
+   }
+
+   if (CmdL.Parse(argc,argv) == false ||
        (Sys != NULL && pkgInitSystem(*_config, *Sys) == false))
    {
       if (_config->FindB("version") == true)

+ 20 - 0
doc/apt.conf.5.xml

@@ -54,6 +54,8 @@
 	 configuration list - in which case it will be silently ignored.</para></listitem>
       <listitem><para>the main configuration file specified by
 	 <literal>Dir::Etc::main</literal></para></listitem>
+      <listitem><para>all options set in the binary specific configuration
+	    subtree are moved into the root of the tree.</para></listitem>
       <listitem><para>the command line options are applied to override the
 	 configuration directives or to load even more configuration files.</para></listitem>
    </orderedlist>
@@ -673,6 +675,24 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
    </variablelist>
  </refsect1>
 
+ <refsect1><title>Binary specific configuration</title>
+    <para>Especially with the introduction of the <command>apt</command> binary
+       it can be useful to set certain options only for a specific binary as
+       even options which look like they would effect only a certain binary like
+       <option>APT::Get::Show-Versions</option> effect
+       <command>apt-get</command> as well as <command>apt</command>.
+    </para>
+    <para>Setting an option for a specific binary only can be achieved by
+       setting the option inside the
+       <option>Binary::<replaceable>specific-binary</replaceable></option>
+       scope. Setting the option <option>APT::Get::Show-Versions</option> for
+       the <command>apt</command> only can e.g. by done by setting
+       <option>Binary::apt::APT::Get::Show-Versions</option> instead.</para>
+    <para>Note that as seen in the DESCRIPTION section further above you can't
+       set binary-specific options on the commandline itself nor in
+       configuration files loaded via the commandline.</para>
+ </refsect1>
+
  <refsect1><title>Directories</title>
 
    <para>The <literal>Dir::State</literal> section has directories that pertain to local 

+ 42 - 0
test/integration/test-apt-showlist-orgroup-in-recommends

@@ -29,6 +29,17 @@ Suggests: ccc | ddd (>> 2)'
 
 setupaptarchive
 
+testsuccessequal 'Reading package lists...
+Building dependency tree...
+Suggested packages:
+  ccc
+Recommended packages:
+  bbb
+The following NEW packages will be installed:
+  simple
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst simple (1 unstable [all])
+Conf simple (1 unstable [all])' aptget install simple -s --install-recommends --install-suggests
 testsuccessequal 'Reading package lists...
 Building dependency tree...
 Suggested packages:
@@ -156,3 +167,34 @@ The following NEW packages will be installed:
 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
 Inst versionedor (1 unstable [all])
 Conf versionedor (1 unstable [all])' aptget install versionedor -s --no-install-recommends
+
+SHOWSUGGEST='Reading package lists...
+Building dependency tree...
+Suggested packages:
+  zzz
+Recommended packages:
+  xxx
+The following NEW packages will be installed:
+  orgroup4
+0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup4 (1 unstable [all])
+Conf orgroup4 (1 unstable [all])'
+INSTSUGGEST='Reading package lists...
+Building dependency tree...
+The following additional packages will be installed:
+  zzz
+Recommended packages:
+  xxx
+The following NEW packages will be installed:
+  orgroup4 zzz
+0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
+Inst orgroup4 (1 unstable [all])
+Inst zzz (1:1 unstable [all])
+Conf orgroup4 (1 unstable [all])
+Conf zzz (1:1 unstable [all])'
+testsuccessequal "$SHOWSUGGEST" aptget install orgroup4 -s
+testsuccessequal "$INSTSUGGEST" aptget install orgroup4 --install-suggests -s
+echo 'Binary::apt-get::APT::Install-Suggests "true";' > rootdir/etc/apt/apt.conf.d/99binaryspecific.conf
+testsuccessequal "$INSTSUGGEST" aptget install orgroup4 -s
+testsuccessequal "$SHOWSUGGEST" apt install orgroup4 -s
+testsuccessequal "$SHOWSUGGEST" aptget install orgroup4 -s --no-install-suggests

+ 17 - 0
test/libapt/configuration_test.cc

@@ -144,3 +144,20 @@ TEST(ConfigurationTest,Vector)
 	EXPECT_EQ("abel", vec[0]);
 	EXPECT_EQ("bravo", vec[1]);
 }
+TEST(ConfigurationTest,Merge)
+{
+	Configuration Cnf;
+	Cnf.Set("Binary::apt::option::foo", "bar");
+	Cnf.Set("option::foo", "foo");
+
+	Cnf.MoveSubTree("Binary::apt", "Binary::apt2");
+	EXPECT_FALSE(Cnf.Exists("Binary::apt::option"));
+	EXPECT_TRUE(Cnf.Exists("option"));
+	EXPECT_EQ("foo", Cnf.Find("option::foo"));
+	EXPECT_EQ("bar", Cnf.Find("Binary::apt2::option::foo"));
+
+	Cnf.MoveSubTree("Binary::apt2", NULL);
+	EXPECT_FALSE(Cnf.Exists("Binary::apt2::option"));
+	EXPECT_TRUE(Cnf.Exists("option"));
+	EXPECT_EQ("bar", Cnf.Find("option::foo"));
+}