<pre style='margin:0'>
Rainer Müller (raimue) pushed a commit to branch vcs-fetch
in repository macports-base.
</pre>
<p><a href="https://github.com/macports/macports-base/commit/37e40f2ac471d1aa2ff09c04a6c1a4aef6f20856">https://github.com/macports/macports-base/commit/37e40f2ac471d1aa2ff09c04a6c1a4aef6f20856</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit 37e40f2ac471d1aa2ff09c04a6c1a4aef6f20856
</span>Author: Rainer Müller <raimue@macports.org>
AuthorDate: Mon Apr 2 01:45:07 2018 +0200
<span style='display:block; white-space:pre;color:#404040;'> fs-traverse: Add -exclude option
</span>---
src/pextlib1.0/fs-traverse.c | 68 +++++++++++++++++++++++++++++++++---
src/pextlib1.0/tests/fs-traverse.tcl | 56 +++++++++++++++++++++++++++++
2 files changed, 119 insertions(+), 5 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/fs-traverse.c b/src/pextlib1.0/fs-traverse.c
</span><span style='display:block; white-space:pre;color:#808080;'>index a0e0e20..c8db16d 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/fs-traverse.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/fs-traverse.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -49,18 +49,19 @@
</span> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+#include <fnmatch.h>
</span>
#include <tcl.h>
#include "fs-traverse.h"
<span style='display:block; white-space:pre;background:#ffe0e0;'>-static int do_traverse(Tcl_Interp *interp, int flags, char * const *targets, Tcl_Obj *varname, Tcl_Obj *body);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static int do_traverse(Tcl_Interp *interp, int flags, const char * const *excludes, char * const *targets, Tcl_Obj *varname, Tcl_Obj *body);
</span>
#define F_DEPTH 0x1
#define F_IGNORE_ERRORS 0x2
#define F_TAILS 0x4
<span style='display:block; white-space:pre;background:#ffe0e0;'>-/* fs-traverse ?-depth? ?-ignoreErrors? ?-tails? ?--? varname target-list body */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+/* fs-traverse ?-depth? ?-ignoreErrors? ?-tails? ?-exclude path-list? ?--? varname target-list body */
</span> int
FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -70,6 +71,7 @@ FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
</span> int rval = TCL_OK;
Tcl_Obj *listPtr;
Tcl_Obj *CONST *objv_orig = objv;
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char **excludes = NULL;
</span> int lobjc;
Tcl_Obj **lobjv;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -94,6 +96,41 @@ FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
</span> ++objv, --objc;
continue;
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!strcmp(arg, "-exclude")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* free previous list, can happen if specified multiple times */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(excludes);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ excludes = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ++objv, --objc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (objc == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_WrongNumArgs(interp, 1, objv, "-exclude path-list");
</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;'>+ int lexcc = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_Obj **lexcv = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char **iter;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if ((rval = Tcl_ListObjGetElements(interp, *objv, &lexcc, &lexcv)) != TCL_OK) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return rval;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ ++objv, --objc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ excludes = calloc(lexcc + 1, sizeof(char *));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (excludes == NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_SetErrno(errno);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_ResetResult(interp);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_AppendResult(interp, "malloc: ", (char *) Tcl_PosixError(interp), NULL);
</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;'>+ iter = excludes;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ while (lexcc > 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *iter++ = Tcl_GetString(*lexcv);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ --lexcc, ++lexcv;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *iter = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span> if (!strcmp(arg, "--")) {
++objv, --objc;
break;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -103,7 +140,8 @@ FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
</span>
/* Parse remaining args */
if (objc != 3) {
<span style='display:block; white-space:pre;background:#ffe0e0;'>- Tcl_WrongNumArgs(interp, 1, objv_orig, "?-depth? ?-ignoreErrors? ?-tails? ?--? varname target-list body");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ Tcl_WrongNumArgs(interp, 1, objv_orig, "?-depth? ?-ignoreErrors? ?-tails? ?-exclude path-list? ?--? varname target-list body");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(excludes);
</span> return TCL_ERROR;
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -122,6 +160,8 @@ FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
</span> if (flags & F_TAILS && lobjc > 1) {
/* result would be ambiguous with multiple paths, so we do not allow this */
Tcl_SetResult(interp, "-tails cannot be used with multiple paths", TCL_STATIC);
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(excludes);
</span> return TCL_ERROR;
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -138,9 +178,11 @@ FsTraverseCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Ob
</span> --lobjc, ++lobjv;
}
*iter = NULL;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- rval = do_traverse(interp, flags, entries, varname, body);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ rval = do_traverse(interp, flags, excludes, entries, varname, body);
</span> free(entries);
}
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ free(excludes);
</span> return rval;
}
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -170,7 +212,7 @@ do_compare(const FTSENT **a, const FTSENT **b)
</span> }
static int
<span style='display:block; white-space:pre;background:#ffe0e0;'>-do_traverse(Tcl_Interp *interp, int flags, char * const *targets, Tcl_Obj *varname, Tcl_Obj *body)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+do_traverse(Tcl_Interp *interp, int flags, const char * const *excludes, char * const *targets, Tcl_Obj *varname, Tcl_Obj *body)
</span> {
int rval = TCL_OK;
FTS *root_fts;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -179,6 +221,22 @@ do_traverse(Tcl_Interp *interp, int flags, char * const *targets, Tcl_Obj *varna
</span> root_fts = fts_open(targets, FTS_PHYSICAL /*| FTS_COMFOLLOW */| FTS_NOCHDIR | FTS_XDEV, &do_compare);
while ((ent = fts_read(root_fts)) != NULL) {
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* match path against excludes */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char * const *iter = excludes;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int is_excluded = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ while (iter != NULL && *iter != NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char *xpath = extract_tail(targets[0], ent->fts_path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (fnmatch(*iter, xpath, FNM_PATHNAME) == 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ is_excluded = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ break;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ iter++;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (is_excluded) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fts_set(root_fts, ent, FTS_SKIP);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ continue;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> switch (ent->fts_info) {
case FTS_D: /* directory in pre-order */
case FTS_DP: /* directory in post-order*/
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/src/pextlib1.0/tests/fs-traverse.tcl b/src/pextlib1.0/tests/fs-traverse.tcl
</span><span style='display:block; white-space:pre;color:#808080;'>index 0030c2f..3285cc8 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/src/pextlib1.0/tests/fs-traverse.tcl
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/src/pextlib1.0/tests/fs-traverse.tcl
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -61,6 +61,27 @@ proc main {pextlibname} {
</span> }
check_output $output $trees(4)
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Test -exclude (simple)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set output [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fs-traverse -exclude b file $root {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend output $file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ check_output $output $trees(sub3)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Test -exclude (complex)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set output [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fs-traverse -exclude {a/c b/a */*/b b/c/} file $root {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend output $file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ check_output $output $trees(sub4)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Test empty -exclude
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set output [list]
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fs-traverse -exclude {} file $root {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ lappend output $file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ check_output $output $trees(1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> # Error raised for traversing directory that does not exist
if {![catch {fs-traverse file $root/does_not_exist {}}]} {
error "fs-traverse did not raise an error for a missing directory"
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -264,6 +285,41 @@ proc setup_trees {root} {
</span> $root/a/c/a/c directory
$root/a/c/a/d file
"
<span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ set trees(sub3) "
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/a file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/b file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/c directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/c/a {link ../d}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/c/b file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/c/c directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/c/d file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/a file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/b {link ../../b/a}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/c directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/d file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/e file
</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 trees(sub4) "
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/a file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/b file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/a file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/c directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/d/d file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/a/e file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/b directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/b/b directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/b/c directory
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/b/c/a file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $root/b/c/c file
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ "
</span>
set trees(2) "
$root/a/a file
</pre><pre style='margin:0'>
</pre>