<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/6fc7146aece9e7e94814816ffde37934dd918fa5">https://github.com/macports/macports-base/commit/6fc7146aece9e7e94814816ffde37934dd918fa5</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 6fc7146aece9e7e94814816ffde37934dd918fa5
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Wed Jan 31 11:29:13 2024 +1100

<span style='display:block; white-space:pre;color:#404040;'>    Simplify portlist code with dict
</span>---
 src/port/port.tcl            | 229 ++++++++++++++++++++++++-------------------
 src/portlist1.0/portlist.tcl |  56 +++++------
 2 files changed, 152 insertions(+), 133 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/port/port.tcl b/src/port/port.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index f3711328d..d279d23c0 100755
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/port/port.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/port/port.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1285,29 +1285,58 @@ proc element { resname } {
</span>     return $el
 }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+proc add_ports_to_portlist_with_defaults {listname ports {overrides ""}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    upvar $listname portlist
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {![dict exists $overrides options]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set i 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        foreach port $ports {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $port options]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set port options [array get ::global_options]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set ports [lreplace ${ports}[set ports {}] $i $i $port]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            incr i
</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;'>+    set i 0
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    foreach port $ports {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $port url] && ![dict exists $port name]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set url file://.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set portname [url_to_portname $url]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict set port url $url
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict set port name $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {$portname eq ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ui_error "A default port name could not be supplied."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set ports [lreplace ${ports}[set ports {}] $i $i $port]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        incr i
</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;'>+    add_ports_to_portlist portlist $ports $overrides
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+}
</span> 
 proc add_multiple_ports { resname ports {remainder ""} } {
     upvar $resname reslist
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    set version ""
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    array unset variants
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    array unset options
</span>     parsePortSpec version variants options $remainder
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    array unset overrides
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set overrides [dict create]
</span>     if {$version ne ""} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set overrides(version) $version
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set overrides(metadata) [list explicit_version 1]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict set overrides version $version
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict set overrides metadata [dict create explicit_version 1]]
</span>     }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[array size variants]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[array size variants] > 0} {
</span>         # we always record the requested variants separately,
         # but requested ones always override existing ones
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set overrides(requested_variants) [array get variants]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        set overrides(variants) [array get variants]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict set overrides requested_variants [array get variants]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict set overrides variants [array get variants]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[array size options] > 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict set overrides options [array get options]
</span>     }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[array size options]} { set overrides(options) [array get options] }
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    add_ports_to_portlist reslist $ports [array get overrides]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    add_ports_to_portlist_with_defaults reslist $ports $overrides
</span> }
 
 proc parseFullPortSpec { urlname namename vername varname optname } {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1686,7 +1715,7 @@ proc action_info { action portlist opts } {
</span>     set separator ""
     foreachport $portlist {
         set index_only 0
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists options(ports_info_index)] && $options(ports_info_index)} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[dict exists $options ports_info_index] && [dict get $options ports_info_index]} {
</span>             set index_only 1
         }
         puts -nonewline $separator
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1711,25 +1740,25 @@ proc action_info { action portlist opts } {
</span>             # Add any global_variations to the variations
             # specified for the port (so we get e.g. dependencies right)
             array unset merged_variations
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set merged_variations [array get variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            array set merged_variations $variations
</span>             foreach { variation value } [array get global_variations] {
                 if { ![info exists merged_variations($variation)] } {
                     set merged_variations($variation) $value
                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![info exists options(subport)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $options subport]} {
</span>                 if {[info exists portinfo(name)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portinfo(name)
</span>                 } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portname
</span>                 }
             }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[catch {set mport [mportopen $porturl [array get options] [array get merged_variations]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[catch {set mport [mportopen $porturl $options [array get merged_variations]]} result]} {
</span>                 ui_debug "$::errorInfo"
                 break_softcontinue "Unable to open port: $result" 1 status
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            unset options(subport)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict unset options subport
</span>             array unset portinfo
             array set portinfo [mportinfo $mport]
             mportclose $mport
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1740,7 +1769,7 @@ proc action_info { action portlist opts } {
</span>             ui_warn "no PortIndex entry found for $portname"
             continue
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        array unset options ports_info_index
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        dict unset options ports_info_index
</span> 
         # Understand which info items are actually lists by specifying
         # separators for the output. The list items correspond to the
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1810,13 +1839,13 @@ proc action_info { action portlist opts } {
</span>         }
 
         # Interpret a convenient field abbreviation
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists options(ports_info_depends)] && $options(ports_info_depends) eq "yes"} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset options ports_info_depends
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[dict exists $options ports_info_depends] && [dict get $options ports_info_depends] eq "yes"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict unset options ports_info_depends
</span>             set all_depends_options [list ports_info_depends_fetch ports_info_depends_extract \
                 ports_info_depends_patch ports_info_depends_build ports_info_depends_lib \
                 ports_info_depends_run ports_info_depends_test]
             foreach depends_option $all_depends_options {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options($depends_option) yes
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options $depends_option yes
</span>             }
             # replace all occurrences of --depends with the expanded options
             while 1 {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1837,18 +1866,18 @@ proc action_info { action portlist opts } {
</span>         set list_map_index 0
 
         # For human-readable summary, which is the default with no options
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[llength [array get options ports_info_*]] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[llength [dict filter $options key ports_info_*]] == 0} {
</span>             set pretty_print 1
             set list_map_index 1
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        } elseif {[info exists options(ports_info_pretty)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } elseif {[dict exists $options ports_info_pretty]} {
</span>             set pretty_print 1
             set list_map_index 1
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset options ports_info_pretty
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict unset options ports_info_pretty
</span>         }
 
         # Tune for sort(1)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists options(ports_info_line)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset options ports_info_line
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[dict exists $options ports_info_line]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict unset options ports_info_line
</span>             set noseparator 1
             set show_label 0
             set field_sep "\t"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1875,7 +1904,7 @@ proc action_info { action portlist opts } {
</span>         #  ::struct::set intersect does not keep order of items
         set opts_todo [list]
         foreach elem $opts_action {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[info exists options($elem)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[dict exists $options $elem]} {
</span>                 lappend opts_todo $elem
             }
         }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2016,9 +2045,9 @@ proc action_info { action portlist opts } {
</span>                 set inf [list]
                 foreach v [lsort $pi_vars] {
                     set varmodifier ""
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {[info exists variations($v)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {[dict exists $variations $v]} {
</span>                         # selected by command line, prefixed with +/-
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        set varmodifier $variations($v)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        set varmodifier [dict get $variations $v]
</span>                     } elseif {[info exists global_variations($v)]} {
                         # selected by variants.conf, prefixed with (+)/(-)
                         set varmodifier "($global_variations($v))"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2110,7 +2139,7 @@ proc action_location { action portlist opts } {
</span>         return 1
     }
     foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if { [catch {set ilist [registry_installed $portname [composite_version $portversion [array get variations]]]} result] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if { [catch {set ilist [registry_installed $portname [composite_version $portversion $variations]]} result] } {
</span>             ui_debug $::errorInfo
             break_softcontinue "port location failed: $result" 1 status
         } else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2161,22 +2190,22 @@ proc action_notes { action portlist opts } {
</span>         # Add any global_variations to the variations
         # specified for the port
         array unset merged_variations
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set merged_variations [array get variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        array set merged_variations $variations
</span>         foreach { variation value } [array get global_variations] {
             if { ![info exists merged_variations($variation)] } {
                 set merged_variations($variation) $value
             }
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(subport)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $options subport]} {
</span>             if {[info exists portinfo(name)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options subport $portinfo(name)
</span>             } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(subport) $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options subport $portname
</span>             }
         }
 
         # Open the Portfile associated with this port.
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[catch {set mport [mportopen $porturl [array get options] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[catch {set mport [mportopen $porturl $options \
</span>                                          [array get merged_variations]]} \
                    result]} {
             ui_debug $::errorInfo
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2257,19 +2286,19 @@ proc action_activate { action portlist opts } {
</span>         return 1
     }
     foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(ports_activate_no-exec)]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set composite_version [composite_version $portversion $variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $options ports_activate_no-exec]
</span>             && ![catch {set ilist [registry::installed $portname $composite_version]}]
             && [llength $ilist] == 1} {
 
             set i [lindex $ilist 0]
             set regref [registry::entry open $portname [lindex $i 1] [lindex $i 2] [lindex $i 3] [lindex $i 5]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[$regref installtype] eq "image" && [registry::run_target $regref activate [array get options]]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[$regref installtype] eq "image" && [registry::run_target $regref activate $options]} {
</span>                 continue
             }
         }
         if {![macports::global_option_isset ports_dryrun]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if { [catch {portimage::activate_composite $portname $composite_version [array get options]} result] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if { [catch {portimage::activate_composite $portname $composite_version $options} result] } {
</span>                 ui_debug $::errorInfo
                 break_softcontinue "port activate failed: $result" 1 status
             }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2289,8 +2318,8 @@ proc action_deactivate { action portlist opts } {
</span>     }
     set portlist [portlist_sortdependents $portlist]
     foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(ports_deactivate_no-exec)]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set composite_version [composite_version $portversion $variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $options ports_deactivate_no-exec]
</span>             && ![catch {set ilist [registry::active $portname]}]} {
 
             set i [lindex $ilist 0]
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2299,13 +2328,13 @@ proc action_deactivate { action portlist opts } {
</span>             set ivariants [lindex $i 3]
             if {$composite_version eq "" || $composite_version eq "${iversion}_${irevision}${ivariants}"} {
                 set regref [registry::entry open $portname $iversion $irevision $ivariants [lindex $i 5]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {[$regref installtype] eq "image" && [registry::run_target $regref deactivate [array get options]]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[$regref installtype] eq "image" && [registry::run_target $regref deactivate $options]} {
</span>                     continue
                 }
             }
         }
         if {![macports::global_option_isset ports_dryrun]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if { [catch {portimage::deactivate_composite $portname $composite_version [array get options]} result] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if { [catch {portimage::deactivate_composite $portname $composite_version $options} result] } {
</span>                 ui_debug $::errorInfo
                 break_softcontinue "port deactivate failed: $result" 1 status
             }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2523,7 +2552,7 @@ proc action_setrequested { action portlist opts } {
</span>     # set or unset?
     set val [string equal $action "setrequested"]
     foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set composite_version [composite_version $portversion $variations]
</span>         if {![catch {set ilist [registry::installed $portname $composite_version]} result]} {
             ui_info "Setting requested flag for $portname to $val"
             foreach i $ilist {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2552,7 +2581,7 @@ proc action_reclaim { action portlist opts } {
</span>     set status [macports::reclaim_main $opts]
 
     if {$status == 0 &&
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        ![info exists options(ports_upgrade_no-rev-upgrade)] &&
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ![dict exists $opts ports_upgrade_no-rev-upgrade] &&
</span>         ${macports::revupgrade_autorun}} {
         set status [action_revupgrade $action $portlist $opts]
     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2571,7 +2600,7 @@ proc action_upgrade { action portlist opts } {
</span>     set status 0
     foreachport $portlist {
         if {![info exists depscache(port:$portname)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set status [macports::upgrade $portname "port:$portname" [array get requested_variations] [array get options] depscache]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set status [macports::upgrade $portname "port:$portname" $requested_variations $options depscache]
</span>             # status 2 means the port was not found in the index,
             # status 3 means the port is not installed
             if {$status != 0 && $status != 2 && $status != 3 && ![macports::ui_isset ports_processall]} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2583,8 +2612,7 @@ proc action_upgrade { action portlist opts } {
</span>     if {$status != 0 && $status != 2 && $status != 3} {
         print_tickets_url
     } elseif {$status == 0} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set options $opts
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(ports_upgrade_no-rev-upgrade)] && ${macports::revupgrade_autorun} && ![macports::global_option_isset ports_dryrun]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $opts ports_upgrade_no-rev-upgrade] && ${macports::revupgrade_autorun} && ![macports::global_option_isset ports_dryrun]} {
</span>             set status [action_revupgrade $action $portlist $opts]
         }
     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2635,7 +2663,7 @@ proc action_dependents { action portlist opts } {
</span> 
     set status 0
     foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set composite_version [composite_version $portversion $variations]
</span>         if { [catch {set ilist [registry::installed $portname $composite_version]} result] } {
             ui_debug $::errorInfo
             break_softcontinue "$result" 1 status
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2701,7 +2729,7 @@ proc action_dependents { action portlist opts } {
</span>                     set cur_port [lindex $cur_portlist $cur_pos]
                     set cur_portname [lindex $cur_port 2]
                     set spaces [string repeat " " [expr {[llength $pos_stack] * 2}]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {![info exists seen($cur_portname)] || ([info exists options(ports_rdependents_full)] && [string is true -strict $options(ports_rdependents_full)])} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {![info exists seen($cur_portname)] || ([dict exists $options ports_rdependents_full] && [string is true -strict [dict get $options ports_rdependents_full]])} {
</span>                         puts "${spaces}${cur_portname}"
                         set seen($cur_portname) 1
                         incr cur_pos
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2745,11 +2773,11 @@ proc action_deps { action portlist opts } {
</span> 
     foreachport $portlist {
         set deptypes [list]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {!([info exists options(ports_${action}_no-build)] && [string is true -strict $options(ports_${action}_no-build)])} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {!([dict exists $options ports_${action}_no-build] && [string is true -strict [dict get $options ports_${action}_no-build]])} {
</span>             lappend deptypes depends_fetch depends_extract depends_patch depends_build
         }
         lappend deptypes depends_lib depends_run
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {!([info exists options(ports_${action}_no-test)] && [string is true -strict $options(ports_${action}_no-test)])} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {!([dict exists $options ports_${action}_no-test] && [string is true -strict [dict get $options ports_${action}_no-test]])} {
</span>             lappend deptypes depends_test
         }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2792,24 +2820,24 @@ proc action_deps { action portlist opts } {
</span>             }
         }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {!([info exists options(ports_${action}_index)] && $options(ports_${action}_index) eq "yes")} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {!([dict exists $options ports_${action}_index] && [dict get $options ports_${action}_index] eq "yes")} {
</span>             # Add any global_variations to the variations
             # specified for the port, so we get dependencies right
             array unset merged_variations
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set merged_variations [array get variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            array set merged_variations $variations
</span>             foreach { variation value } [array get global_variations] {
                 if { ![info exists merged_variations($variation)] } {
                     set merged_variations($variation) $value
                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![info exists options(subport)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $options subport]} {
</span>                 if {[info exists portinfo(name)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portinfo(name)
</span>                 } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portname
</span>                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[catch {set mport [mportopen $porturl [array get options] [array get merged_variations]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[catch {set mport [mportopen $porturl $options [array get merged_variations]]} result]} {
</span>                 ui_debug "$::errorInfo"
                 break_softcontinue "Unable to open port: $result" 1 status
             }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2887,11 +2915,11 @@ proc action_deps { action portlist opts } {
</span>                     array unset portinfo
                     array set portinfo [lindex $result 1]
                     set porturl $portinfo(porturl)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portinfo(name)
</span> 
                     # open the portfile if requested
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {!([info exists options(ports_${action}_index)] && $options(ports_${action}_index) eq "yes")} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        if {[catch {set mport [mportopen $porturl [array get options] [array get merged_variations]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {!([dict exists $options ports_${action}_index] && [dict get $options ports_${action}_index] eq "yes")} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        if {[catch {set mport [mportopen $porturl $options [array get merged_variations]]} result]} {
</span>                             ui_debug "$::errorInfo"
                             break_softcontinue "Unable to open port: $result" 1 status
                         }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2942,7 +2970,7 @@ proc action_deps { action portlist opts } {
</span>             set cur_port [lindex $cur_portlist $cur_pos]
             set cur_portname [lindex [split $cur_port :] end]
             set spaces [string repeat " " [expr {[llength $pos_stack] * 2}]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![info exists seen($cur_portname)] || ([info exists options(ports_${action}_full)] && [string is true -strict $options(ports_${action}_full)])} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![info exists seen($cur_portname)] || ([dict exists $options ports_${action}_full] && [string is true -strict [dict get $options ports_${action}_full]])} {
</span>                 if {[macports::ui_isset ports_verbose]} {
                     puts "${spaces}${cur_port}"
                 } else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -2997,20 +3025,20 @@ proc action_uninstall { action portlist opts } {
</span>             }
             continue
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(ports_uninstall_no-exec)]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set composite_version [composite_version $portversion $variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $options ports_uninstall_no-exec]
</span>             && ![catch {set ilist [registry::installed $portname $composite_version]}]
             && [llength $ilist] == 1} {
 
             set i [lindex $ilist 0]
             set iactive [lindex $i 4]
             set regref [registry::entry open $portname [lindex $i 1] [lindex $i 2] [lindex $i 3] [lindex $i 5]]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[registry::run_target $regref uninstall [array get options]]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[registry::run_target $regref uninstall $options]} {
</span>                 continue
             }
         }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if { [catch {registry_uninstall::uninstall_composite $portname $composite_version [array get options]} result] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if { [catch {registry_uninstall::uninstall_composite $portname $composite_version $options} result] } {
</span>             ui_debug $::errorInfo
             break_softcontinue "port uninstall failed: $result" 1 status
         }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3029,7 +3057,7 @@ proc action_installed { action portlist opts } {
</span>     if { [llength $portlist] || (![info exists private_options(ports_no_args)] || $private_options(ports_no_args) eq "no")} {
         set restrictedList 1
         foreachport $portlist {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set composite_version [composite_version $portversion [array get variations]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set composite_version [composite_version $portversion $variations]
</span>             if { [catch {set ilist [concat $ilist [registry::installed $portname $composite_version]]} result] } {
                 if {![string match "* not registered as installed." $result]} {
                     ui_debug $::errorInfo
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3320,7 +3348,7 @@ proc action_space {action portlist opts} {
</span>                         set space [expr {$space + [file size $file]}]
                     }
                 }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {![info exists options(ports_space_total)] || $options(ports_space_total) ne "yes"} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {![dict exists $options ports_space_total] || [dict get $options ports_space_total] ne "yes"} {
</span>                     set msg "[bytesize $space $units] $portname"
                     if { $portversion ne {} } {
                         append msg " @$portversion"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3335,7 +3363,7 @@ proc action_space {action portlist opts} {
</span>             puts stderr "Port $portname is not installed."
         }
     }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[llength $portlist] > 1 || ([info exists options(ports_space_total)] && $options(ports_space_total) eq "yes")} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[llength $portlist] > 1 || ([dict exists $options ports_space_total] && [dict get $options ports_space_total] eq "yes")} {
</span>         puts "[bytesize $spaceall $units] total"
     }
     return 0
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3365,24 +3393,24 @@ proc action_variants { action portlist opts } {
</span>             set portdir $portinfo(portdir)
         }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {!([info exists options(ports_variants_index)] && $options(ports_variants_index) eq "yes")} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {!([dict exists $options ports_variants_index] && [dict get $options ports_variants_index] eq "yes")} {
</span>             # Add any global_variations to the variations specified for
             # the port (default variants may change based on this)
             array unset merged_variations
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set merged_variations [array get variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            array set merged_variations $variations
</span>             foreach {variation value} [array get global_variations] {
                 if {![info exists merged_variations($variation)]} {
                     set merged_variations($variation) $value
                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![info exists options(subport)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $options subport]} {
</span>                 if {[info exists portinfo(name)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portinfo(name)
</span>                 } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set options(subport) $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set options subport $portname
</span>                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[catch {set mport [mportopen $porturl [array get options] [array get merged_variations]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[catch {set mport [mportopen $porturl $options [array get merged_variations]]} result]} {
</span>                 ui_debug "$::errorInfo"
                 break_softcontinue "Unable to open port: $result" 1 status
             }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3430,8 +3458,8 @@ proc action_variants { action portlist opts } {
</span>                     }
 
                     # XXX Keep these varmodifiers in sync with action_info, or create a wrapper for it
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {[info exists variations($v)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        set varmodifier "  $variations($v)"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {[dict exists $variations $v]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        set varmodifier "  [dict get $variations $v]"
</span>                     } elseif {[info exists global_variations($v)]} {
                         # selected by variants.conf, prefixed with (+)/(-)
                         set varmodifier "($global_variations($v))"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3672,13 +3700,13 @@ proc action_echo { action portlist opts } {
</span>     foreachport $portlist {
         if {![macports::ui_isset ports_quiet]} {
             set opts [list]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            foreach { key value } [array get options] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            foreach { key value } $options {
</span>                 if {![info exists global_options($key)]} {
                     lappend opts "$key=$value"
                 }
             }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set composite_version [composite_version $portversion [array get variations] 1]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set composite_version [composite_version $portversion $variations 1]
</span>             if { $composite_version ne "" } {
                 set ver_field "@$composite_version"
             } else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3904,29 +3932,28 @@ proc action_target { action portlist opts } {
</span>         # being asked for a version we can't provide.
         if {[string length $portversion]} {
             if {$action eq "clean"} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(ports_version_glob) $portversion
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            } elseif {[info exists portmetadata(explicit_version)] && [info exists portinfo(version)] \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options ports_version_glob $portversion
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } elseif {[dict exists $portmetadata explicit_version] && [info exists portinfo(version)] \
</span>                     && $portversion ne "$portinfo(version)_$portinfo(revision)" && $portversion ne $portinfo(version)} {
                 break_softcontinue "$portname version $portversion is not available (current version is $portinfo(version)_$portinfo(revision))" 1 status
             }
         }
 
         # use existing variants iff none were explicitly requested
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[array get requested_variations] eq "" && [array get variations] ne ""} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset requested_variations
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set requested_variations [array get variations]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {$requested_variations eq "" && $variations ne ""} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set requested_variations $variations
</span>         }
 
         # Add any global_variations to the variations
         # specified for the port
         foreach { variation value } [array get global_variations] {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if { ![info exists requested_variations($variation)] } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set requested_variations($variation) $value
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $requested_variations $variation]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set requested_variations $variation $value
</span>             }
         }
 
         if {$action eq "install"} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[info exists portinfo(replaced_by)] && ![info exists options(ports_install_no-replace)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[info exists portinfo(replaced_by)] && ![dict exists $options ports_install_no-replace]} {
</span>                 ui_notice "$portname is replaced by $portinfo(replaced_by)"
                 set portname $portinfo(replaced_by)
                 array unset portinfo
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3940,7 +3967,7 @@ proc action_target { action portlist opts } {
</span>                 set porturl $portinfo(porturl)
             }
             if {[info exists portinfo(known_fail)] && [string is true -strict $portinfo(known_fail)]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                && ![info exists options(ports_install_allow-failing)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                && ![dict exists $options ports_install_allow-failing]} {
</span>                 if {[info exists macports::ui_options(questions_yesno)]} {
                     set retvalue [$macports::ui_options(questions_yesno) "$portname is known to fail." "KnownFail" {} {n} 0 "Try to install anyway?"]
                     if {$retvalue != 0} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3950,12 +3977,12 @@ proc action_target { action portlist opts } {
</span>                     break_softcontinue "$portname is known to fail (use --allow-failing to try to install anyway)" 1 status
                 }
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[info exists options(ports_install_allow-failing)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(ignore_known_fail) 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[dict exists $options ports_install_allow-failing]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options ignore_known_fail 1
</span>             }
             # mark the port as explicitly requested
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![info exists options(ports_install_unrequested)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(ports_requested) 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $options ports_install_unrequested]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options ports_requested 1
</span>             }
             # we actually activate as well
             set target activate
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3964,14 +3991,14 @@ proc action_target { action portlist opts } {
</span>         } else {
             set target $action
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(subport)]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $options subport]} {
</span>             if {[info exists portinfo(name)]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(subport) $portinfo(name)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options subport $portinfo(name)
</span>             } else {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                set options(subport) $portname
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set options subport $portname
</span>             }
         }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[catch {set workername [mportopen $porturl [array get options] [array get requested_variations]]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[catch {set workername [mportopen $porturl $options $requested_variations]} result]} {
</span>             ui_debug $::errorInfo
             break_softcontinue "Unable to open port $portname: $result" 1 status
         }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -3991,8 +4018,7 @@ proc action_target { action portlist opts } {
</span>     }
 
     if {$status == 0 && $action eq "install" && ![macports::global_option_isset ports_dryrun]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set options $opts
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {![info exists options(ports_nodeps)] && ![info exists options(ports_install_no-rev-upgrade)] && ${macports::revupgrade_autorun}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $opts ports_nodeps] && ![dict exists $opts ports_install_no-rev-upgrade] && ${macports::revupgrade_autorun}} {
</span>             set status [action_revupgrade $action $portlist $opts]
         }
     }
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -4004,10 +4030,9 @@ proc action_target { action portlist opts } {
</span> proc action_mirror { action portlist opts } {
     global macports::portdbpath
     # handle --new option here so we only delete the db once
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    array set options $opts
</span>     set mirror_filemap_path [file join $macports::portdbpath distfiles_mirror.db]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[info exists options(ports_mirror_new)]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        && [string is true -strict $options(ports_mirror_new)]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[dict exists $opts ports_mirror_new]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        && [string is true -strict [dict get $opts ports_mirror_new]]
</span>         && [file exists $mirror_filemap_path]} {
             # Trash the map file if it existed.
             file delete -force $mirror_filemap_path
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/portlist1.0/portlist.tcl b/src/portlist1.0/portlist.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index f96fa5260..80940e0bd 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/portlist1.0/portlist.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/portlist1.0/portlist.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -66,18 +66,18 @@ proc entry_for_portlist {portentry} {
</span>     #   fullname        (name/version_revision+-variants)
     #       Note: name always normalised to lower case in fullname
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    array set port $portentry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(url)]}       { set port(url) "" }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(name)]}      { set port(name) "" }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(version)]}   { set port(version) "" }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(variants)]}  { set port(variants) "" }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(requested_variants)]}  { set port(requested_variants) "" }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {![info exists port(options)]}   { set port(options) "" }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    foreach key {url name version variants requested_variants options} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {![dict exists $portentry $key]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict set portentry $key ""
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    }
</span> 
     # Form the fully discriminated portname: portname/version_revison+-variants
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    set port(fullname) [string tolower $port(name)]/[composite_version $port(version) $port(variants)]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set normname [string tolower [dict get $portentry name]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set fullvers [composite_version [dict get $portentry version] [dict get $portentry variants]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    dict set portentry fullname ${normname}/${fullvers}
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    return [array get port]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return $portentry
</span> }
 
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -89,20 +89,17 @@ proc add_to_portlist {listname portentry} {
</span> }
 
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-proc add_ports_to_portlist {listname ports {overridelist ""}} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc add_ports_to_portlist {listname ports {overrides ""}} {
</span>     upvar $listname portlist
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    array set overrides $overridelist
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span>     # Add each entry to the named portlist, overriding any values
     # specified as overrides
     foreach portentry $ports {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        array set port $portentry
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists overrides(version)]}   { set port(version) $overrides(version) }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists overrides(variants)]}  { set port(variants) $overrides(variants) }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists overrides(requested_variants)]}  { set port(requested_variants) $overrides(requested_variants) }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[info exists overrides(options)]}   { set port(options) $overrides(options) }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        add_to_portlist portlist [array get port]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # typically version, variants, requested_variants, options
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        foreach key [dict keys $overrides] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            dict set portentry $key [dict get $overrides $key]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        add_to_portlist portlist $portentry
</span>     }
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -114,20 +111,16 @@ proc foreachport {portlist block} {
</span>     foreach portspec $portlist {
 
         # Set the variables for the block
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        uplevel 1 "array unset portspec; array set portspec { $portspec }"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        uplevel 1 [list set portspec $portspec]
</span>         uplevel 1 {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set porturl $portspec(url)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            set portname $portspec(name)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            set portversion $portspec(version)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset variations
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set variations $portspec(variants)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset requested_variations
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set requested_variations $portspec(requested_variants)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset options
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array set options $portspec(options)
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            array unset portmetadata
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[info exists portspec(metadata)]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                array set portmetadata $portspec(metadata)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set porturl [dict get $portspec url]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set portname [dict get $portspec name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set portversion [dict get $portspec version]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set variations [dict get $portspec variants]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set requested_variations [dict get $portspec requested_variants]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set options [dict get $portspec options]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[dict exists $portspec metadata]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set portmetadata [dict get $portspec metadata]
</span>             }
         }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -139,6 +132,7 @@ proc foreachport {portlist block} {
</span>         if {[file exists $savedir]} {
             cd $savedir
         } else {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+            # XXX Tcl9 unsafe
</span>             cd ~
         }
     }
</pre><pre style='margin:0'>

</pre>