<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/f1caca2b3c956b6de6d1a384848763a4e9472af2">https://github.com/macports/macports-base/commit/f1caca2b3c956b6de6d1a384848763a4e9472af2</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 f1caca2b3 Add dirempty command
</span>f1caca2b3 is described below

<span style='display:block; white-space:pre;color:#808000;'>commit f1caca2b3c956b6de6d1a384848763a4e9472af2
</span>Author: Joshua Root <jmr@macports.org>
AuthorDate: Thu Jun 20 04:37:35 2024 +1000

<span style='display:block; white-space:pre;color:#404040;'>    Add dirempty command
</span><span style='display:block; white-space:pre;color:#404040;'>    
</span><span style='display:block; white-space:pre;color:#404040;'>    In several places, we were using readdir to check if a directory is
</span><span style='display:block; white-space:pre;color:#404040;'>    empty. This does unnecessary work proportional to the number of entries
</span><span style='display:block; white-space:pre;color:#404040;'>    in the directory. Instead, dirempty stops as soon as any entry other
</span><span style='display:block; white-space:pre;color:#404040;'>    than . or .. is read.
</span>---
 src/macports1.0/reclaim.tcl      |  2 +-
 src/pextlib1.0/Pextlib.c         |  1 +
 src/pextlib1.0/readdir.c         | 43 +++++++++++++++++++++++++++++++++++++++-
 src/pextlib1.0/readdir.h         |  1 +
 src/port1.0/portclean.tcl        |  2 +-
 src/registry2.0/portimage.tcl    |  3 +--
 src/registry2.0/receipt_flat.tcl |  3 +--
 7 files changed, 48 insertions(+), 7 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 c666110e2..ca827b5df 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;'>@@ -451,7 +451,7 @@ namespace eval reclaim {
</span>                                         break
                                     }
 
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                                    if {[llength [readdir $directory]] > 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                                    if {![dirempty $directory]} {
</span>                                         break
                                     }
 
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/Pextlib.c b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;color:#808080;'>index f9c88e8a5..6aefb668f 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/Pextlib.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1075,6 +1075,7 @@ int Pextlib_Init(Tcl_Interp *interp)
</span>   Tcl_CreateObjCommand(interp, "system", SystemCmd, NULL, NULL);
        Tcl_CreateObjCommand(interp, "adv-flock", AdvFlockCmd, NULL, NULL);
        Tcl_CreateObjCommand(interp, "readdir", ReaddirCmd, NULL, NULL);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+        Tcl_CreateObjCommand(interp, "dirempty", DiremptyCmd, NULL, NULL);
</span>   Tcl_CreateObjCommand(interp, "strsed", StrsedCmd, NULL, NULL);
        Tcl_CreateObjCommand(interp, "mktemp", MktempCmd, NULL, NULL);
        Tcl_CreateObjCommand(interp, "mkdtemp", MkdtempCmd, NULL, NULL);
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/readdir.c b/src/pextlib1.0/readdir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 087bff75b..95882ce69 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/readdir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/readdir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -76,6 +76,47 @@ int ReaddirCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_O
</span>   }
        closedir(dirp);
        Tcl_SetObjResult(interp, tcl_result);
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   return TCL_OK;
</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;'>+ * Return 1 if there are no entries in a directory (other than  . and ..), 0 otherwise
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Synopsis: dirempty directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+int DiremptyCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   DIR *dirp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   struct dirent *mp;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   Tcl_Obj *tcl_result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   char *path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (objc != 2) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           Tcl_WrongNumArgs(interp, 1, objv, "directory");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return TCL_ERROR;
</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;'>+   path = Tcl_GetString(objv[1]);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   dirp = opendir(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   if (!dirp) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           Tcl_SetResult(interp, "Cannot read directory", TCL_STATIC);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           return TCL_ERROR;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   tcl_result = Tcl_NewIntObj(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   while ((mp = readdir(dirp))) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           /* Skip . and .. */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           if ((mp->d_name[0] != '.') ||
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   ((mp->d_name[1] != 0)        /* "." */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                           &&
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   ((mp->d_name[1] != '.') || (mp->d_name[2] != 0)))) /* ".." */ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   Tcl_SetIntObj(tcl_result, 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+           }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   closedir(dirp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+   Tcl_SetObjResult(interp, tcl_result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span>   return TCL_OK;
 }
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/readdir.h b/src/pextlib1.0/readdir.h
</span><span style='display:block; white-space:pre;color:#808080;'>index 909e5efe7..618946fe5 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/readdir.h
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/readdir.h
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -30,3 +30,4 @@
</span>  */
 
 int ReaddirCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+int DiremptyCmd(ClientData, Tcl_Interp *, int, Tcl_Obj *const objv[]);
</span><span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/port1.0/portclean.tcl b/src/port1.0/portclean.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index a38b8922f..22c790c95 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/port1.0/portclean.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/port1.0/portclean.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -144,7 +144,7 @@ proc portclean::clean_dist {args} {
</span>     if {$dist_subdir ne $name} {
         if {!([info exists ports_force] && $ports_force eq "yes")
             && [file isdirectory $distpath]
<span style='display:block; white-space:pre;background:#ffe0e0;'>-            && [llength [readdir $distpath]] > 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+            && ![dirempty $distpath]} {
</span>             ui_warn [format [msgcat::mc "Distfiles directory '%s' may contain distfiles needed for other ports, use the -f flag to force removal" ] $distpath]
         } else {
             lappend dirlist $dist_subdir
<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 c389dcb93..c1ab6e0d4 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;'>@@ -812,8 +812,7 @@ proc _deactivate_files {files directories progress_count progress_total} {
</span>         _progress update $progress_count $progress_total
     }
     foreach dstdir $directories {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-        # 0 items means empty.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-        if {[llength [readdir $dstdir]] == 0} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+        if {[dirempty $dstdir]} {
</span>             ui_debug "deactivating directory: $dstdir"
             ::file delete -- $dstdir
         } else {
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/registry2.0/receipt_flat.tcl b/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 4c488e9e8..79371bf47 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/registry2.0/receipt_flat.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -424,8 +424,7 @@ proc delete_entry {name version {revision 0} {variants ""}} {
</span>           # remove port receipt parent directory (if empty)
                set receipt_dir [::file join ${macports::registry.path} receipts ${name}]
                if { [::file isdirectory ${receipt_dir}] } {
<span style='display:block; white-space:pre;background:#ffe0e0;'>-                        # 0 item means empty.
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-                   if { [llength [readdir ${receipt_dir}]] == 0 } {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+                   if {[dirempty ${receipt_dir}]} {
</span>                           ui_debug "deleting directory: ${receipt_dir}"
                                file delete -force -- ${receipt_dir}
                        } else {
</pre><pre style='margin:0'>

</pre>