<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/2140176c2482393f03934f5a8a041dc907ffb4cf">https://github.com/macports/macports-base/commit/2140176c2482393f03934f5a8a041dc907ffb4cf</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 2140176c2 _activate_contents improvements
</span>2140176c2 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit 2140176c2482393f03934f5a8a041dc907ffb4cf
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Fri Jun 21 09:09:34 2024 +1000

<span style='display:block; white-space:pre;color:#404040;'>    _activate_contents improvements
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    Handle directories separately, which saves a file type call per dir and
</span><span style='display:block; white-space:pre;color:#404040;'>    allows only the directory list to be sorted, rather than all files. Use
</span><span style='display:block; white-space:pre;color:#404040;'>    dicts to avoid list searches, one of which was unsorted.
</span>---
 src/registry2.0/portimage.tcl | 98 ++++++++++++++++++++++++-------------------
 1 file changed, 55 insertions(+), 43 deletions(-)

<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/portimage.tcl b/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 92750c79e..cc7c94c2f 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/portimage.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -316,14 +316,14 @@ proc _check_registry {name version revision variants {return_all 0}} {
</span>     throw registry::invalid "Registry error: ${name}${composite_spec} is not installed."
 }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-## Activates a file from an image into the filesystem. Deals with symlinks,
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-## directories and files.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+## Activates a file from an image into the filesystem. Deals with symlinks
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+## and regular files.
</span> ##
 ## @param [in] srcfile path to file in image
 ## @param [in] dstfile path to activate file to
 ## @return 1 if file needs to be explicitly deleted if we have to roll back, 0 otherwise
 proc _activate_file {srcfile dstfile} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    if {[catch {set filetype [::file type $srcfile]} result]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {[catch {::file type $srcfile} result]} {
</span>         # this can happen if the archive was built on case-sensitive and we're case-insensitive
         # we know any existing dstfile is ours because we checked for conflicts earlier
         if {![catch {file type $dstfile}]} {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -333,30 +333,30 @@ proc _activate_file {srcfile dstfile} {
</span>             error $result
         }
     }
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    switch $filetype {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        directory {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # Don't recursively copy directories
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            ui_debug "activating directory: $dstfile"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            # Don't do anything if the directory already exists.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if { ![::file isdirectory $dstfile] } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                ::file mkdir $dstfile
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                # fix attributes on the directory.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    ::file attributes $dstfile {*}[::file attributes $srcfile]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                } else {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    # not root, so can't set owner/group
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    ::file attributes $dstfile -permissions {*}[::file attributes $srcfile -permissions]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                # set mtime on installed element
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                ::file mtime $dstfile [::file mtime $srcfile]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            return 0
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        }
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        default {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            ui_debug "activating file: $dstfile"
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            ::file rename $srcfile $dstfile
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            return 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ui_debug "activating file: $dstfile"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ::file rename $srcfile $dstfile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    return 1
</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;'>+## Activates a directory from an image into the filesystem.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+##
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+## @param [in] srcdir path to dir in image
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+## @param [in] dstdir path to activate dir to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+proc _activate_directory {srcdir dstdir} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # Don't recursively copy directories
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    ui_debug "activating directory: $dstdir"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    # Don't do anything if the directory already exists.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    if {![::file isdirectory $dstdir]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ::file mkdir $dstdir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # fix attributes on the directory.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[getuid] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ::file attributes $dstdir {*}[::file attributes $srcdir]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            # not root, so can't set owner/group
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            ::file attributes $dstdir -permissions {*}[::file attributes $srcdir -permissions]
</span>         }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        # set mtime on installed element
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        ::file mtime $dstdir [::file mtime $srcdir]
</span>     }
 }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -571,7 +571,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>     variable progress_step
     variable progress_total_steps
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-    set files [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+    set filesdict [dict create]
</span>     set baksuffix .mp_[clock seconds]
     set portname [$port name]
     set location [$port location]
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -581,6 +581,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>     set extracted_dir [extract_archive_to_tmpdir $location]
 
     set backups [list]
<span style='display:block; white-space:pre;background:#e0ffe0;'>+    set seendirs [dict create]
</span>     # This is big and hairy and probably could be done better.
     # First, we need to check the source file, make sure it exists
     # Then we remove the $location from the path of the file in the contents
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -598,11 +599,11 @@ proc _activate_contents {port {rename_list {}}} {
</span>                 _progress update $progress_step $progress_total_steps
                 set srcfile "${extracted_dir}${file}"
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                # To be able to install links, we test if we can lstat the file to
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                # To be able to install links, we test if 'file type' errors to
</span>                 # figure out if the source file exists (file exists will return
                 # false for symlinks on files that do not exist)
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                if { [catch {::file lstat $srcfile dummystatvar}] } {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    throw registry::image-error "Image error: Source file $srcfile does not appear to exist (cannot lstat it).  Unable to activate port ${portname}."
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                if {[catch {::file type $srcfile}]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    throw registry::image-error "Image error: Source file $srcfile does not appear to exist.  Unable to activate port ${portname}."
</span>                 }
 
                 set owner [registry::entry owner $file]
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -619,7 +620,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>                 }
 
                 if {$owner ne "replaced"} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if { [string is true -strict $force] } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {$force} {
</span>                         # if we're forcing the activation, then we move any existing
                         # files to a backup file, both in the filesystem and in the
                         # registry
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -661,8 +662,8 @@ proc _activate_contents {port {rename_list {}}} {
</span>                 # we'll set the directory attributes properly for all
                 # directories.
                 set directory [::file dirname $file]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                while {$directory ni $files} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                    lappend files $directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                while {![dict exists $seendirs $directory]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    dict set seendirs $directory 1
</span>                     # Any add here will mean an additional step in the second
                     # phase of activation. We could just update this once after
                     # this foreach loop is complete, but that could make the
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -674,33 +675,38 @@ proc _activate_contents {port {rename_list {}}} {
</span>                 }
 
                 # Also add the filename to the imagefile list.
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                lappend files $file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict set filesdict $file 1
</span>             }
         }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        set directories [dict keys $seendirs]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        unset seendirs
</span> 
         # deactivate ports replaced_by this one
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        set deactivate_options [dict create ports_nodepcheck 1]
</span>         foreach owner $todeactivate {
             _progress intermission
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {$noexec || ![registry::run_target $owner deactivate [list ports_nodepcheck 1]]} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                deactivate [$owner name] "" "" 0 [list ports_nodepcheck 1]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {$noexec || ![registry::run_target $owner deactivate $deactivate_options]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                deactivate [$owner name] "" "" 0 $deactivate_options
</span>             }
         }
 
         # Sort the list in forward order, removing duplicates.
         # Since the list is sorted in forward order, we're sure that
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        # directories are before their elements.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        # parent directories are before their elements.
</span>         # We don't have to do this as mentioned above, but it makes the
         # debug output of activate make more sense.
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        set files [lsort -increasing -unique $files]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        set directories [lsort -increasing -unique $directories]
</span>         # handle files that are to be renamed
         set confirmed_rename_list [list]
         foreach {src dest} $rename_list {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            set index [lsearch -exact -sorted $files $src]
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-            if {$index != -1} {
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                set files [lreplace $files $index $index]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            if {[dict exists $filesdict $src]} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                dict unset filesdict $src
</span>                 lappend confirmed_rename_list $src $dest
             }
         }
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        set files [dict keys $filesdict]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        unset filesdict
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>         set rollback_filelist [list]
 
         registry::write {
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -708,8 +714,14 @@ proc _activate_contents {port {rename_list {}}} {
</span> 
             try {
                 $port activate $imagefiles
<span style='display:block; white-space:pre;background:#e0ffe0;'>+                foreach dir $directories {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    _activate_directory ${extracted_dir}${dir} $dir
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    _progress update $progress_step $progress_total_steps
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    incr progress_step
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                }
</span>                 foreach file $files {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    if {[_activate_file "${extracted_dir}${file}" $file] == 1} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    if {[_activate_file ${extracted_dir}${file} $file] == 1} {
</span>                         lappend rollback_filelist $file
                     }
 
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -779,7 +791,7 @@ proc _activate_contents {port {rename_list {}}} {
</span>             # reactivate deactivated ports
             foreach entry $todeactivate {
                 if {[$entry state] eq "imaged" && ($noexec || ![registry::run_target $entry activate ""])} {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                    activate [$entry name] [$entry version] [$entry revision] [$entry variants] [list ports_activate_no-exec $noexec]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                    activate [$entry name] [$entry version] [$entry revision] [$entry variants] [dict create ports_activate_no-exec $noexec]
</span>                 }
             }
         } finally {
</pre><pre style='margin:0'>

</pre>