<pre style='margin:0'>
Joshua Root (jmroot) pushed a commit to branch master
in repository macports-base.

</pre>
<p><a href="https://github.com/macports/macports-base/commit/f40f6556c301bf247e621534cf22239adfe0c1f2">https://github.com/macports/macports-base/commit/f40f6556c301bf247e621534cf22239adfe0c1f2</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit f40f6556c301bf247e621534cf22239adfe0c1f2
</span>Author: Clemens Lang <cal@macports.org>
AuthorDate: Sat Dec 2 00:16:19 2023 +0100

<span style='display:block; white-space:pre;color:#404040;'>    macports/restore: Fix alternative providers
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Fix the handling of ports in the snapshot that would conflict with
</span><span style='display:block; white-space:pre;color:#404040;'>    a dependency of a requested port by assuming that the port in the
</span><span style='display:block; white-space:pre;color:#404040;'>    snapshot is an alternative provider for the dependency it conflicts
</span><span style='display:block; white-space:pre;color:#404040;'>    with. This should fix restore for users that have certsync installed
</span><span style='display:block; white-space:pre;color:#404040;'>    instead of curl-ca-bundle or, for example, cmake-devel instead of cmake.
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    The previous approach to attempt to solve this was to patch the
</span><span style='display:block; white-space:pre;color:#404040;'>    dependency graph after the dependencies have been added and replacing
</span><span style='display:block; white-space:pre;color:#404040;'>    them with the alternative provider. Fixing this would have required to
</span><span style='display:block; white-space:pre;color:#404040;'>    also remove the dependency and its otherwise unneeded transitive
</span><span style='display:block; white-space:pre;color:#404040;'>    dependencies from the graph. It's much simpler to instead never add the
</span><span style='display:block; white-space:pre;color:#404040;'>    unwanted dependencies instead, which this commit implements.
</span>---
 src/macports1.0/restore.tcl | 89 +++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 43 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/restore.tcl b/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 6cfeef0ef..990364116 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/restore.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -233,6 +233,7 @@ namespace eval restore {
</span>         # depth-first dependency resolution.
         set worklist [list]
         set seen [list]
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        array set seen_conflicts {}
</span>         foreach port $portlist {
             lassign $port name requested _ _ _
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -285,49 +286,13 @@ namespace eval restore {
</span>             }
             array unset portinfo
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            # Check whether any of ports in the snapshot conflicts with this
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # port. If that's the case, then the port in the snapshot is likely
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # an alternative provider for the functionality of this port (like
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # for example certsync is for curl-ca-bundle) and the user had this
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # alternative installed.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set portinfo [mportinfo $mport]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[info exists portinfo(conflicts)] && [llength $portinfo(conflicts)] > 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set conflict_found 0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                foreach conflictport $portinfo(conflicts) {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {[info exists ports($conflictport)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        # The conflicting port was installed in the snapshot.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        # Identify all ports that depend on this port, and
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        # change their dependency to the port in the snapshot.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        ui_debug "Snapshot contains $conflictport, which conflicts with dependency $portinfo(name)"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        if {![$dependencies node exists $conflictport]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                            $dependencies node insert $conflictport
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        set arcs [$dependencies arcs -in $portinfo(name)]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        foreach arc $arcs {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                            ui_debug "Changing dependency [$dependencies arc source $arc]->[$dependencies arc target $arc] to [$dependencies arc source $arc]->$conflictport"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                            $dependencies arc move-target $arc $conflictport
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        set worklist [linsert $worklist 0 $conflictport]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        set conflict_found 1
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        break
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {$conflict_found} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    mportclose $mport
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    continue
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # Compute the dependencies for the 'install' target. Do not recurse
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # into the dependencies: we'll do that here manually in order to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # Compute the dependencies for the 'install' target. Do not recurse into the dependencies: we'll do that
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # here manually in order to
</span>             #  (1) keep our dependency graph updated
             #  (2) use the requested variants when opening the dependencies
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            #  (3) identify if an alternative provider was used based on the
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            #  snapshot and the conflicts information (such as for example when
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            #  a port depends on curl-ca-bundle, but the snapshot contains
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            #  certsync, which conflicts with curl-ca-bundle).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #  (3) identify if an alternative provider was used based on the snapshot and the conflicts information
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #  (such as for example when a port depends on curl-ca-bundle, but the snapshot contains certsync, which
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #  conflicts with curl-ca-bundle).
</span>             if {[mportdepends $mport install 0] != 0} {
                 error "Unable to determine dependencies for port '$portname'"
             }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -337,16 +302,54 @@ namespace eval restore {
</span>                 $dependencies node insert $provides
             }
             foreach dependency [ditem_key $mport requires] {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                lassign [dlist_search $macports::open_mports provides $dependency] dep_ditem
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set conflict_found 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                array set portinfo [mportinfo $dep_ditem]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[info exists portinfo(conflicts)] && [llength $portinfo(conflicts)] > 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    foreach conflict $portinfo(conflicts) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        if {[info exists ports($conflict)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # The conflicting port was installed in the snapshot. Assume that this happened because the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # conflicting port is an alternative provider for this dependency (e.g., curl-ca-bundle and
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # certsync, or a -devel port replacing its non-devel variant).
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # Do not add the dependency that mportdepends computed, but instead replace this dependency
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # with the conflicting port.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            #
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # Warn only once for every combination, otherwise users might see the same message multiple
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            # times.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            if {![info exists seen_conflicts($portinfo(name),$conflict)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                set seen_conflicts($portinfo(name),$conflict) 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                ui_warn "Snapshot contains $conflict, which conflicts with dependency $portinfo(name); assuming $conflict provides the functionality of $portinfo(name)"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            if {![$dependencies node exists $conflict]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                $dependencies node insert $conflict
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            $dependencies arc insert $provides $conflict
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            set worklist [linsert $worklist 0 $conflict]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            set conflict_found 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            break
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                array unset portinfo
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {$conflict_found} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    continue
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>                 if {![$dependencies node exists $dependency]} {
                     $dependencies node insert $dependency
                 }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                lassign [dlist_search $macports::open_mports provides $dependency] dep_ditem
</span>                 set dependency_requested_variants [[ditem_key $dep_ditem workername] eval {set requested_variants}]
                 set dep_ports($dependency) $dependency_requested_variants
 
                 $dependencies arc insert $provides $dependency
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                set worklist [linsert $worklist 0 $dependency]
</span>             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set worklist [linsert $worklist 0 {*}[ditem_key $mport requires]]
</span>             mportclose $mport
         }
 
</pre><pre style='margin:0'>

</pre>