Pārlūkot izejas kodu

edsp: add Forbid-{New-Install,Remove} and Upgrade-All

This allows to differentiate properly between 'apt-get upgrade', 'apt
upgrade' and 'apt full-upgrade'.
David Kalnischkies 10 gadi atpakaļ
vecāks
revīzija
43c71fad3a

+ 4 - 2
apt-pkg/algorithms.cc

@@ -637,7 +637,7 @@ bool pkgProblemResolver::Resolve(bool BrokenFix, OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
-      return EDSP::ResolveExternal(solver.c_str(), Cache, false, false, false, Progress);
+      return EDSP::ResolveExternal(solver.c_str(), Cache, 0, Progress);
    return ResolveInternal(BrokenFix);
 }
 									/*}}}*/
@@ -1134,7 +1134,9 @@ bool pkgProblemResolver::ResolveByKeep(OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
+      return EDSP::ResolveExternal(solver.c_str(), Cache,
+	    EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_NEW_INSTALL | EDSP::Request::FORBID_REMOVE,
+	    Progress);
    return ResolveByKeepInternal();
 }
 									/*}}}*/

+ 74 - 21
apt-pkg/edsp.cc

@@ -527,8 +527,8 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
    fprintf(output, "\n");
    return true;
 }
-bool EDSP::WriteRequest(pkgDepCache &Cache, FileFd &output, bool const Upgrade,
-			bool const DistUpgrade, bool const AutoRemove,
+bool EDSP::WriteRequest(pkgDepCache &Cache, FileFd &output,
+			unsigned int const flags,
 			OpProgress *Progress)
 {
    if (Progress != NULL)
@@ -564,12 +564,20 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FileFd &output, bool const Upgrade,
       WriteOkay(Okay, output, "Remove:", del, "\n");
    if (inst.empty() == false)
       WriteOkay(Okay, output, "Install:", inst, "\n");
-   if (Upgrade == true)
-      WriteOkay(Okay, output, "Upgrade: yes\n");
-   if (DistUpgrade == true)
-      WriteOkay(Okay, output, "Dist-Upgrade: yes\n");
-   if (AutoRemove == true)
+   if (flags & Request::AUTOREMOVE)
       WriteOkay(Okay, output, "Autoremove: yes\n");
+   if (flags & Request::UPGRADE_ALL)
+   {
+      WriteOkay(Okay, output, "Upgrade-All: yes\n");
+      if (flags & (Request::FORBID_NEW_INSTALL | Request::FORBID_REMOVE))
+	 WriteOkay(Okay, output, "Upgrade: yes\n");
+      else
+	 WriteOkay(Okay, output, "Dist-Upgrade: yes\n");
+   }
+   if (flags & Request::FORBID_NEW_INSTALL)
+      WriteOkay(Okay, output, "Forbid-New-Install: yes\n");
+   if (flags & Request::FORBID_REMOVE)
+      WriteOkay(Okay, output, "Forbid-Remove: yes\n");
    if (_config->FindB("APT::Solver::Strict-Pinning", true) == false)
       WriteOkay(Okay, output, "Strict-Pinning: no\n");
    string solverpref("APT::Solver::");
@@ -711,15 +719,23 @@ static bool StringToBool(char const *answer, bool const defValue) {
 }
 									/*}}}*/
 // EDSP::ReadRequest - first stanza from the given file descriptor	/*{{{*/
+static bool ReadFlag(unsigned int &flags, std::string const &line, APT::StringView const name, unsigned int const setflag)
+{
+   if (line.compare(0, name.length(), name.data()) != 0)
+      return false;
+   auto const l = line.c_str() + name.length() + 1;
+   if (StringToBool(l, false))
+      flags |= setflag;
+   else
+      flags &= ~setflag;
+   return true;
+}
 bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
-			std::list<std::string> &remove, bool &upgrade,
-			bool &distUpgrade, bool &autoRemove)
+			std::list<std::string> &remove, unsigned int &flags)
 {
    install.clear();
    remove.clear();
-   upgrade = false;
-   distUpgrade = false;
-   autoRemove = false;
+   flags = 0;
    std::string line;
    while (ReadLine(input, line) == true)
    {
@@ -747,12 +763,13 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
 	    line.erase(0, 7);
 	    request = &remove;
 	 }
-	 else if (line.compare(0, 8, "Upgrade:") == 0)
-	    upgrade = StringToBool(line.c_str() + 9, false);
-	 else if (line.compare(0, 13, "Dist-Upgrade:") == 0)
-	    distUpgrade = StringToBool(line.c_str() + 14, false);
-	 else if (line.compare(0, 11, "Autoremove:") == 0)
-	    autoRemove = StringToBool(line.c_str() + 12, false);
+	 else if (ReadFlag(flags, line, "Upgrade:", (Request::UPGRADE_ALL | Request::FORBID_REMOVE | Request::FORBID_NEW_INSTALL)) ||
+	       ReadFlag(flags, line, "Dist-Upgrade:", Request::UPGRADE_ALL) ||
+	       ReadFlag(flags, line, "Upgrade-All:", Request::UPGRADE_ALL) ||
+	       ReadFlag(flags, line, "Forbid-New-Install:", Request::FORBID_NEW_INSTALL) ||
+	       ReadFlag(flags, line, "Forbid-Remove:", Request::FORBID_REMOVE) ||
+	       ReadFlag(flags, line, "Autoremove:", Request::AUTOREMOVE))
+	    ;
 	 else if (line.compare(0, 13, "Architecture:") == 0)
 	    _config->Set("APT::Architecture", line.c_str() + 14);
 	 else if (line.compare(0, 14, "Architectures:") == 0)
@@ -783,6 +800,31 @@ bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
       }
    }
    return false;
+}
+bool EDSP::ReadRequest(int const input, std::list<std::string> &install,
+			std::list<std::string> &remove, bool &upgrade,
+			bool &distUpgrade, bool &autoRemove)
+{
+   unsigned int flags;
+   auto const ret = ReadRequest(input, install, remove, flags);
+   autoRemove = (flags & Request::AUTOREMOVE);
+   if (flags & Request::UPGRADE_ALL)
+   {
+      if (flags & (Request::FORBID_NEW_INSTALL | Request::FORBID_REMOVE))
+      {
+	 upgrade = true;
+	 distUpgrade = false;
+      } else {
+	 upgrade = false;
+	 distUpgrade = false;
+      }
+   }
+   else
+   {
+      upgrade = false;
+      distUpgrade = false;
+   }
+   return ret;
 }
 									/*}}}*/
 // EDSP::ApplyRequest - first stanza from the given file descriptor	/*{{{*/
@@ -954,8 +996,7 @@ bool EDSP::ExecuteSolver(const char* const solver, int *solver_in, int *solver_o
 									/*}}}*/
 // EDSP::ResolveExternal - resolve problems by asking external for help	{{{*/
 bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
-			 bool const upgrade, bool const distUpgrade,
-			 bool const autoRemove, OpProgress *Progress) {
+			 unsigned int const flags, OpProgress *Progress) {
 	int solver_in, solver_out;
 	pid_t const solver_pid = EDSP::ExecuteSolver(solver, &solver_in, &solver_out, true);
 	if (solver_pid == 0)
@@ -968,7 +1009,7 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 	bool Okay = output.Failed() == false;
 	if (Progress != NULL)
 		Progress->OverallProgress(0, 100, 5, _("Execute external solver"));
-	Okay &= EDSP::WriteRequest(Cache, output, upgrade, distUpgrade, autoRemove, Progress);
+	Okay &= EDSP::WriteRequest(Cache, output, flags, Progress);
 	if (Progress != NULL)
 		Progress->OverallProgress(5, 100, 20, _("Execute external solver"));
 	Okay &= EDSP::WriteScenario(Cache, output, Progress);
@@ -980,5 +1021,17 @@ bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
 		return false;
 
 	return ExecWait(solver_pid, solver);
+}
+bool EDSP::ResolveExternal(const char* const solver, pkgDepCache &Cache,
+			 bool const upgrade, bool const distUpgrade,
+			 bool const autoRemove, OpProgress *Progress) {
+   unsigned int flags = 0;
+   if (autoRemove)
+      flags |= Request::AUTOREMOVE;
+   if (upgrade)
+      flags |= Request::UPGRADE_ALL | Request::FORBID_REMOVE | Request::FORBID_NEW_INSTALL;
+   if (distUpgrade)
+      flags |= Request::UPGRADE_ALL;
+   return ResolveExternal(solver, Cache, flags, Progress);
 }
 									/*}}}*/

+ 18 - 9
apt-pkg/edsp.h

@@ -29,6 +29,16 @@ class OpProgress;
 
 namespace EDSP								/*{{{*/
 {
+	namespace Request
+	{
+	   enum Flags
+	   {
+	      AUTOREMOVE = (1 << 0), /*!< removal of unneeded packages should be performed */
+	      UPGRADE_ALL = (1 << 1), /*!< upgrade all installed packages, like 'apt-get full-upgrade' without forbid flags */
+	      FORBID_NEW_INSTALL = (1 << 2), /*!< forbid the resolver to install new packages */
+	      FORBID_REMOVE = (1 << 3), /*!< forbid the resolver to remove packages */
+	   };
+	}
 	/** \brief creates the EDSP request stanza
 	 *
 	 *  In the EDSP protocol the first thing send to the resolver is a stanza
@@ -38,17 +48,13 @@ namespace EDSP								/*{{{*/
 	 *
 	 *  \param Cache in which the request is encoded
 	 *  \param output is written to this "file"
-	 *  \param upgrade is true if it is an request like apt-get upgrade
-	 *  \param distUpgrade is true if it is a request like apt-get dist-upgrade
-	 *  \param autoRemove is true if removal of unneeded packages should be performed
+	 *  \param flags effecting the request documented in #EDSP::Request::Flags
 	 *  \param Progress is an instance to report progress to
 	 *
 	 *  \return true if request was composed successfully, otherwise false
 	 */
 	bool WriteRequest(pkgDepCache &Cache, FileFd &output,
-				 bool const upgrade = false,
-				 bool const distUpgrade = false,
-				 bool const autoRemove = false,
+				 unsigned int const flags = 0,
 				OpProgress *Progress = NULL);
 	bool WriteRequest(pkgDepCache &Cache, FILE* output,
 				 bool const upgrade = false,
@@ -130,6 +136,8 @@ namespace EDSP								/*{{{*/
 	 *  \return true if the request could be found and worked on, otherwise false
 	 */
 	bool ReadRequest(int const input, std::list<std::string> &install,
+			std::list<std::string> &remove, unsigned int &flags);
+	APT_DEPRECATED_MSG("use the flag-based version instead") bool ReadRequest(int const input, std::list<std::string> &install,
 			std::list<std::string> &remove, bool &upgrade,
 			bool &distUpgrade, bool &autoRemove);
 
@@ -212,15 +220,16 @@ namespace EDSP								/*{{{*/
 	 *
 	 *  \param solver to execute
 	 *  \param Cache with the problem and as universe to work in
-	 *  \param upgrade is true if it is a request like apt-get upgrade
-	 *  \param distUpgrade is true if it is a request like apt-get dist-upgrade
-	 *  \param autoRemove is true if unneeded packages should be removed
+	 *  \param flags effecting the request documented in #EDSP::Request::Flags
 	 *  \param Progress is an instance to report progress to
 	 *
 	 *  \return true if the solver has successfully solved the problem,
 	 *  otherwise false
 	 */
 	bool ResolveExternal(const char* const solver, pkgDepCache &Cache,
+				    unsigned int const flags = 0,
+				    OpProgress *Progress = NULL);
+	APT_DEPRECATED_MSG("use the flag-based version instead") bool ResolveExternal(const char* const solver, pkgDepCache &Cache,
 				    bool const upgrade, bool const distUpgrade,
 				    bool const autoRemove, OpProgress *Progress = NULL);
 }

+ 7 - 3
apt-pkg/upgrade.cc

@@ -28,7 +28,7 @@ static bool pkgDistUpgrade(pkgDepCache &Cache, OpProgress * const Progress)
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
-      return EDSP::ResolveExternal(solver.c_str(), Cache, false, true, false, Progress);
+      return EDSP::ResolveExternal(solver.c_str(), Cache, EDSP::Request::UPGRADE_ALL, Progress);
 
    if (Progress != NULL)
       Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
@@ -130,7 +130,9 @@ static bool pkgAllUpgradeNoNewPackages(pkgDepCache &Cache, OpProgress * const Pr
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
+      return EDSP::ResolveExternal(solver.c_str(), Cache,
+	    EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_NEW_INSTALL | EDSP::Request::FORBID_REMOVE,
+	    Progress);
 
    if (Progress != NULL)
       Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));
@@ -172,7 +174,9 @@ static bool pkgAllUpgradeWithNewPackages(pkgDepCache &Cache, OpProgress * const
 {
    std::string const solver = _config->Find("APT::Solver", "internal");
    if (solver != "internal")
-      return EDSP::ResolveExternal(solver.c_str(), Cache, true, false, false, Progress);
+       return EDSP::ResolveExternal(solver.c_str(), Cache,
+	    EDSP::Request::UPGRADE_ALL | EDSP::Request::FORBID_REMOVE,
+	    Progress);
 
    if (Progress != NULL)
       Progress->OverallProgress(0, 100, 1, _("Calculating upgrade"));

+ 14 - 7
cmdline/apt-internal-solver.cc

@@ -121,8 +121,8 @@ int main(int argc,const char *argv[])					/*{{{*/
 		DIE("WAIT timed out in the resolver");
 
 	std::list<std::string> install, remove;
-	bool upgrade, distUpgrade, autoRemove;
-	if (EDSP::ReadRequest(input, install, remove, upgrade, distUpgrade, autoRemove) == false)
+	unsigned int flags;
+	if (EDSP::ReadRequest(input, install, remove, flags) == false)
 		DIE("Parsing the request failed!");
 
 	EDSP::WriteProgress(5, "Read scenario…", output);
@@ -159,12 +159,19 @@ int main(int argc,const char *argv[])					/*{{{*/
 	EDSP::WriteProgress(60, "Call problemresolver on current scenario…", output);
 
 	std::string failure;
-	if (upgrade == true) {
-		if (APT::Upgrade::Upgrade(CacheFile, APT::Upgrade::FORBID_REMOVE_PACKAGES | APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES) == false)
+	if (flags & EDSP::Request::UPGRADE_ALL) {
+		int upgrade_flags = APT::Upgrade::ALLOW_EVERYTHING;
+		if (flags & EDSP::Request::FORBID_NEW_INSTALL)
+		   upgrade_flags |= APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES;
+		if (flags & EDSP::Request::FORBID_REMOVE)
+		   upgrade_flags |= APT::Upgrade::FORBID_REMOVE_PACKAGES;
+
+		if (APT::Upgrade::Upgrade(CacheFile, upgrade_flags))
+			;
+		else if (upgrade_flags == APT::Upgrade::ALLOW_EVERYTHING)
+			failure = "ERR_UNSOLVABLE_FULL_UPGRADE";
+		else
 			failure = "ERR_UNSOLVABLE_UPGRADE";
-	} else if (distUpgrade == true) {
-		if (APT::Upgrade::Upgrade(CacheFile, APT::Upgrade::ALLOW_EVERYTHING) == false)
-			failure = "ERR_UNSOLVABLE_DIST_UPGRADE";
 	} else if (Fix.Resolve() == false)
 		failure = "ERR_UNSOLVABLE";
 

+ 22 - 5
doc/external-dependency-solver-protocol.txt

@@ -156,17 +156,26 @@ The following **action fields** are supported in request stanzas:
   Install. This field denotes a list of packages that the user wants to
   remove, usually via APT `remove` or `purge` requests.
 
-- **Upgrade:** (optional, defaults to `no`). Allowed values: `yes`,
+- **Upgrade-All:** (optional, defaults to `no`). Allowed values `yes`,
   `no`. When set to `yes`, an upgrade of all installed packages has been
-  requested, usually via an APT `upgrade` request.
-
-- **Dist-Upgrade:** (optional, defaults to `no`). Allowed values: `yes`,
-  `no`. Same as Upgrade, but for APT `dist-upgrade` requests.
+  requested, usually via an upgrade command like 'apt full-upgrade'.
 
 - **Autoremove:** (optional, defaults to `no`). Allowed values: `yes`,
   `no`. When set to `yes`, a clean up of unused automatically installed
   packages has been requested, usually via an APT `autoremove` request.
 
+- **Upgrade:** (deprecated, optional, defaults to `no`). Allowed values:
+  `yes`, `no`. When set to `yes`, an upgrade of all installed packages
+  has been requested, usually via an APT `upgrade` request. A value of
+  `yes` is equivalent to the fields `Upgrade-All`,
+  `Forbid-New-Install`and `Forbid-Remove` all set to `yes`.
+
+- **Dist-Upgrade:** (deprecated, optional, defaults to `no`). Allowed
+  values: `yes`, `no`. Same as Upgrade, but for APT `dist-upgrade`
+  requests. A value of `yes` is equivalent to the field `Upgrade-All`
+  set to `yes` and the fields `Forbid-New-Install`and `Forbid-Remove`
+  set to `no`.
+
 The following **preference fields** are supported in request stanzas:
 
 - **Strict-Pinning:** (optional, defaults to `yes`). Allowed values:
@@ -178,6 +187,14 @@ The following **preference fields** are supported in request stanzas:
   field comes from the `APT::Solver::Strict-Pinning` configuration
   option.
 
+- **Forbid-New-Install:* (optional, defaults to `no`). Allowed values:
+  `yes`, `no`. When set to `yes` the resolver is forbidden to install
+  new packages in its returned solution.
+
+- **Forbid-Remove:* (optional, defaults to `no`). Allowed values: `yes`,
+  `no`.  When set to `yes` the resolver is forbidden to remove currently
+  installed packages in its returned solution.
+
 - **Solver:** (optional, defaults to the empty string) a purely
   informational string specifying to which solver this request was send
   initially.