<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>