<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/bbc10c21357c19110ab26e84a3ed1ade661f3a41">https://github.com/macports/macports-base/commit/bbc10c21357c19110ab26e84a3ed1ade661f3a41</a></p>
<pre style="white-space: pre; background: #F8F8F8">The following commit(s) were added to refs/heads/master by this push:
<span style='display:block; white-space:pre;color:#404040;'>     new bbc10c213 reclaim: add option to keep build deps
</span>bbc10c213 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit bbc10c21357c19110ab26e84a3ed1ade661f3a41
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Mon Dec 9 18:50:50 2024 +1100

<span style='display:block; white-space:pre;color:#404040;'>    reclaim: add option to keep build deps
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Closes: https://trac.macports.org/ticket/60754
</span>---
 src/macports1.0/reclaim.tcl | 129 +++++++++++++++++++++++++++++++-------------
 src/port/port.tcl           |   2 +-
 2 files changed, 92 insertions(+), 39 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/macports1.0/reclaim.tcl b/src/macports1.0/reclaim.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index ca827b5df..adaa46366 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/macports1.0/reclaim.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/macports1.0/reclaim.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -72,7 +72,7 @@ namespace eval reclaim {
</span>             return
         }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        uninstall_unrequested
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        uninstall_unrequested [dict exists $opts ports_reclaim_keep-build-deps]
</span>         uninstall_inactive
         remove_distfiles
         remove_builds
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -663,13 +663,14 @@ namespace eval reclaim {
</span>             } elseif {${retval} == 0} {
                 set options [dict create ports_force true]
                 foreach port $inactive_ports {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                    set portname [$port name]
</span>                     # Note: 'uninstall' takes a name, version, revision, variants and an options list.
                     macports_try -pass_signal {
                         if {[macports::global_option_isset ports_uninstall_no-exec] || ![registry::run_target $port uninstall $options]} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                            registry_uninstall::uninstall [$port name] [$port version] [$port revision] [$port variants] $options
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            registry_uninstall::uninstall $portname [$port version] [$port revision] [$port variants] $options
</span>                         }
                     } on error {eMessage} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        ui_error "Error uninstalling $name: $eMessage"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        ui_error "Error uninstalling $portname: $eMessage"
</span>                     }
                 }
             } else {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -683,8 +684,70 @@ namespace eval reclaim {
</span>         return 0
     }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    proc get_build_deps {portname requested_variants} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set build_deps [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        lassign [mportlookup $portname] portname portinfo
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[dict exists $portinfo porturl]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set options [dict create subport $portname]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set splitvariant [split $requested_variants -]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set minusvariant [lrange $splitvariant 1 end]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set splitvariant [split [lindex $splitvariant 0] +]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set plusvariant [lrange $splitvariant 1 end]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set variations [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            foreach v $plusvariant {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set variations $v +
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            foreach v $minusvariant {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[string first "+" $v] == -1} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set variations $v -
</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:#ffe0e0;'>-    proc uninstall_unrequested {} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[catch {set mport [mportopen [dict get $portinfo porturl] $options $variations]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ui_debug "unable to open port $name ${requested_variants}: $result"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                set portinfo [mportinfo $mport]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                mportclose $mport
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            foreach type {depends_fetch depends_extract depends_patch depends_build} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[dict exists $portinfo $type]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    foreach d [dict get $portinfo $type] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        lappend build_deps [lindex [split $d :] end]
</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;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ui_debug "lookup of $portname failed"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        return $build_deps
</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;'>+    proc mark_deps_needed {port inc_build} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        upvar is_needed is_needed
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set portname [$port name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        foreach dep [$port dependencies] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set depname [$dep name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $is_needed $depname] || ![dict get $is_needed $depname]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                ui_debug "$depname is needed by $portname"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set is_needed $depname 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                mark_deps_needed $dep $inc_build
</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 {$inc_build} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            foreach depname [get_build_deps $portname [$port requested_variants]] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {![dict exists $is_needed $depname] || ![dict get $is_needed $depname]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    ui_debug "$depname is needed by $portname"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set is_needed $depname 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    foreach dep [registry::entry installed $depname] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        mark_deps_needed $dep $inc_build
</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;'>+        }
</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;'>+    proc uninstall_unrequested {keep_build_deps} {
</span> 
         # Attempts to uninstall unrequested ports no requested ports depend on
         #
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -693,48 +756,35 @@ namespace eval reclaim {
</span>         # Returns:
         #           0 if execution was successful. Errors (for now) if execution wasn't.
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        set installed_ports [sort_portlist_by_dependendents [registry::entry installed]]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         set unnecessary_ports  [list]
         set unnecessary_names  [list]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set unnecessary_count  0
</span> 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set isrequested [dict create]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set is_needed [dict create]
</span> 
         global macports::ui_prefix macports::ui_options
         ui_msg "$ui_prefix Checking for unnecessary unrequested ports"
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        foreach port [sort_portlist_by_dependendents [registry::entry imaged]] {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        foreach port $installed_ports {
</span>             set portname [$port name]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {![dict exists $isrequested $portname] || [dict get $isrequested $portname] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                dict set isrequested $portname [$port requested]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {[dict get $isrequested $portname] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set dependents [$port dependents]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                foreach dependent $dependents {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    set dname [$dependent name]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {![dict exists $isrequested $dname]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        ui_debug "$portname appears to have a circular dependency involving $dname"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        dict set isrequested $portname 1
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        break
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    } elseif {[dict get $isrequested $dname] != 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        ui_debug "$portname is requested by $dname"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                        dict set isrequested $portname 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;'>-                #foreach dependent $dependents {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                #    registry::entry close $dependent
</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 {[dict get $isrequested $portname] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    lappend unnecessary_ports $port
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    lappend unnecessary_names "$portname @[$port version]_[$port revision][$port variants]"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    incr unnecessary_count
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    #registry::entry close $port
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict exists $is_needed $portname] || ![dict get $is_needed $portname]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set is_needed $portname [$port requested]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[dict get $is_needed $portname]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    mark_deps_needed $port $keep_build_deps
</span>                 }
             }
         }
 
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        foreach port $installed_ports {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            set portname [$port name]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {![dict get $is_needed $portname]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                lappend unnecessary_ports $port
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                lappend unnecessary_names "$portname @[$port version]_[$port revision][$port variants]"
</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 unnecessary_count [llength $unnecessary_ports]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         if { $unnecessary_count == 0 } {
             ui_msg "Found no unrequested ports without requested dependents."
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -747,21 +797,24 @@ namespace eval reclaim {
</span>             if {${retval} == 0 && [macports::global_option_isset ports_dryrun]} {
                 ui_msg "Skipping uninstall of unrequested ports (dry run)"
             } elseif {${retval} == 0} {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                set options [dict create ports_force true]
</span>                 foreach port $unnecessary_ports {
                     # Note: 'uninstall' takes a name, version, revision, variants and an options list.
                     macports_try -pass_signal {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        registry_uninstall::uninstall [$port name] [$port version] [$port revision] [$port variants] {ports_force true}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        if {[macports::global_option_isset ports_uninstall_no-exec] || ![registry::run_target $port uninstall $options]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                            registry_uninstall::uninstall [$port name] [$port version] [$port revision] [$port variants] $options
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        }
</span>                     } on error {eMessage} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        ui_error "Error uninstalling $name: $eMessage"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                        ui_error "Error uninstalling $portname: $eMessage"
</span>                     }
                 }
             } else {
                 ui_msg "Not uninstalling ports; use 'port setrequested' to mark a port as explicitly requested."
             }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            foreach port $unnecessary_ports {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #foreach port $unnecessary_ports {
</span>                 # may have been uninstalled and thus already closed
                 #catch {registry::entry close $port}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            #}
</span>         }
         return 0
     }
<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 231c45558..448d3bc09 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;'>@@ -4247,7 +4247,7 @@ set cmd_opts_array [dict create {*}{
</span>     upgrade     {force enforce-variants no-replace no-rev-upgrade}
     rev-upgrade {id-loadcmd-check}
     diagnose    {quiet}
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    reclaim     {enable-reminders disable-reminders}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    reclaim     {enable-reminders disable-reminders keep-build-deps}
</span>     fetch       {no-mirrors}
     bump        {patch}
     snapshot    {create list {diff 1} all {delete 1} help {note 1} {export 1} {import 1}}
</pre><pre style='margin:0'>

</pre>