public inbox for cygwin-apps@cygwin.com
 help / color / mirror / Atom feed
From: Jon Turney <jon.turney@dronecode.org.uk>
To: cygwin-apps@cygwin.com
Cc: Jon Turney <jon.turney@dronecode.org.uk>
Subject: [PATCH setup] Handle '--packages package=version'
Date: Sun, 18 Apr 2021 14:34:44 +0100	[thread overview]
Message-ID: <20210418133444.1287-1-jon.turney@dronecode.org.uk> (raw)

Handle '--packages package=version' to allow specifing the version of a
package to install on the command line.

isManuallyWanted() now returns the target packageversion (if specified),
or an empty packageversion (which is translated into an instruction to
the solver to choose the version).

In the 'upgrade' case, this changes from using the complex logic of
packagemeta::trustp() to determine the target version, when unspecified
on the command line, to allowing the solver to make that decision (which
should be broadly the same i.e. not downgrading test versions, etc.).

This also subtly changes the behaviour when the package version is not
specified.  Instead of forcing the current version, we allow the solver
to choose the version, so it may not pick that version, if other
constraints exist, which prevent a solution containing that version.

There's probably some future work which can be done to simplify the
remaining uses packagemeta::trustp(), which are only related to the UI.
---
 choose.cc       |  9 ++++---
 package_meta.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++----
 package_meta.h  |  3 ++-
 3 files changed, 73 insertions(+), 10 deletions(-)

diff --git a/choose.cc b/choose.cc
index 4fa0c74..7632bba 100644
--- a/choose.cc
+++ b/choose.cc
@@ -289,7 +289,8 @@ ChooserPage::applyCommandLinePackageSelection()
        i != db.packages.end (); ++i)
     {
       packagemeta &pkg = *(i->second);
-      bool wanted    = pkg.isManuallyWanted();
+      packageversion wanted_version;
+      bool wanted    = pkg.isManuallyWanted(wanted_version);
       bool deleted   = pkg.isManuallyDeleted();
       bool base      = pkg.categories.find ("Base") != pkg.categories.end ();
       bool orphaned  = pkg.categories.find ("Orphaned") != pkg.categories.end ();
@@ -299,15 +300,15 @@ ChooserPage::applyCommandLinePackageSelection()
       bool uninstall = (!(wanted  || base) && (deleted || PruneInstallOption))
 		     || (orphaned && CleanOrphansOption);
       if (install)
-        pkg.set_action (packagemeta::Install_action, UpgradeAlsoOption ? packageversion () : pkg.curr, true);
+        pkg.set_action (packagemeta::Install_action, UpgradeAlsoOption ? packageversion () : wanted_version, true);
       else if (reinstall)
-	pkg.set_action (packagemeta::Reinstall_action, pkg.curr);
+	pkg.set_action (packagemeta::Reinstall_action, !wanted ? pkg.curr : wanted_version);
       else if (uninstall)
 	pkg.set_action (packagemeta::Uninstall_action, packageversion ());
       else if (PruneInstallOption)
 	pkg.set_action (packagemeta::NoChange_action, pkg.curr);
       else if (upgrade)
-	pkg.set_action (packagemeta::Install_action, pkg.trustp(true, TRUST_UNKNOWN));
+	pkg.set_action (packagemeta::Install_action, !wanted ? packageversion () : wanted_version);
       else
 	pkg.set_action (packagemeta::NoChange_action, pkg.installed);
     }
diff --git a/package_meta.cc b/package_meta.cc
index 73239f1..1c6183c 100644
--- a/package_meta.cc
+++ b/package_meta.cc
@@ -214,6 +214,20 @@ packagemeta::add_version (const SolverPool::addPackageData &inpkgdata)
   return thepkg;
 }
 
+const packageversion *
+packagemeta::findVersion(std::string &version) const
+{
+  for (std::set <packageversion>::iterator i = versions.begin();
+       i != versions.end();
+       i++)
+    {
+      if (i->Canonical_version() == version)
+        return &(*i);
+    }
+
+  return NULL;
+}
+
 bool
 packagemeta::isBlacklisted(const packageversion &version) const
 {
@@ -310,10 +324,10 @@ validatePackageNames (std::set<std::string> &names)
     }
 }
 
-bool packagemeta::isManuallyWanted() const
+bool packagemeta::isManuallyWanted(packageversion &version) const
 {
   static bool parsed_yet = false;
-  static std::set<std::string> parsed_names;
+  static std::map<std::string, std::string> parsed_names;
   hasManualSelections |= parsed_names.size ();
   static std::set<std::string> parsed_categories;
   hasManualSelections |= parsed_categories.size ();
@@ -325,12 +339,40 @@ bool packagemeta::isManuallyWanted() const
   {
     std::vector<std::string> packages_options = PackageOption;
     std::vector<std::string> categories_options = CategoryOption;
+
+    std::set<std::string> items;
     for (std::vector<std::string>::iterator n = packages_options.begin ();
 		n != packages_options.end (); ++n)
       {
-	parseNames (parsed_names, *n);
+	parseNames (items, *n);
       }
-    validatePackageNames (parsed_names);
+
+    std::set<std::string> packages;
+    /* Separate any 'package=version' into package and version parts */
+    for (std::set<std::string>::iterator n = items.begin();
+         n != items.end();
+         ++n)
+      {
+        std::string package;
+        std::string version;
+        std::string::size_type loc = n->find ("=", 0);
+        if (loc != std::string::npos)
+          {
+            package = n->substr(0, loc);
+            version = n->substr(loc+1);
+          }
+        else
+          {
+            package = *n;
+            version = "";
+          }
+        Log (LOG_BABBLE) << "package: " << package << " version: " << version << endLog;
+        parsed_names[package] = version;
+        packages.insert(package);
+      }
+
+    validatePackageNames (packages);
+
     for (std::vector<std::string>::iterator n = categories_options.begin ();
 		n != categories_options.end (); ++n)
       {
@@ -341,7 +383,25 @@ bool packagemeta::isManuallyWanted() const
 
   /* Once we've already parsed the option string, just do
     a lookup in the cache of already-parsed names.  */
-  bReturn = parsed_names.find(name) != parsed_names.end();
+  std::map<std::string, std::string>::iterator i = parsed_names.find(name);
+  if (i != parsed_names.end())
+    {
+      bReturn = true;
+
+      /* Wanted version is unspecified */
+      version = packageversion();
+
+      /* ... unless a version was explicitly specified */
+      std::string v = i->second;
+      if (!v.empty())
+        {
+          const packageversion *pv = findVersion(v);
+          if (pv)
+            version = *pv;
+          else
+            Log (LOG_PLAIN) << "package: " << name << " version: " << v << " not found" << endLog;
+        }
+    }
 
   /* If we didn't select the package manually, did we select any
      of the categories it is in? */
@@ -352,6 +412,7 @@ bool packagemeta::isManuallyWanted() const
 	if (parsed_categories.find (*curcat) != parsed_categories.end ())
 	  {
 	    Log (LOG_BABBLE) << "Found category " << *curcat << " in package " << name << endLog;
+	    version = packageversion();
 	    bReturn = true;
 	  }
     }
diff --git a/package_meta.h b/package_meta.h
index 4faff41..fee385b 100644
--- a/package_meta.h
+++ b/package_meta.h
@@ -107,7 +107,7 @@ public:
   std::string name;			/* package name, like "cygwin" */
 
   /* true if package was selected on command-line. */
-  bool isManuallyWanted() const;
+  bool isManuallyWanted(packageversion &version) const;
   /* true if package was deleted on command-line. */
   bool isManuallyDeleted() const;
 
@@ -163,6 +163,7 @@ private:
   std::string trustLabel(packageversion const &) const;
   std::vector <Script> scripts_;
   static bool scan (const packageversion &pkg, bool mirror_mode);
+  const packageversion * findVersion(std::string &version) const;
 
   _actions _action;
 
-- 
2.31.1


             reply	other threads:[~2021-04-18 13:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-18 13:34 Jon Turney [this message]
2021-04-20 14:35 ` David Allsopp
2021-04-20 20:30   ` Jon Turney
2021-04-20 18:24 ` ASSI

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210418133444.1287-1-jon.turney@dronecode.org.uk \
    --to=jon.turney@dronecode.org.uk \
    --cc=cygwin-apps@cygwin.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).