From 7c5632f03d6a29b10e0df07f022f5cf3ad826ce1 Mon Sep 17 00:00:00 2001 From: apnadkarni Date: Tue, 3 Oct 2023 16:39:56 +0000 Subject: Some fixes, some tests --- generic/tclFileName.c | 8 ++++++-- generic/tclZipfs.c | 36 ++++++++++++++++++++++++++++++------ tests/zipfs.test | 46 ++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/generic/tclFileName.c b/generic/tclFileName.c index ac0dfa3..f23b468 100644 --- a/generic/tclFileName.c +++ b/generic/tclFileName.c @@ -1399,11 +1399,15 @@ Tcl_GlobObjCmd( * We must ensure that we haven't cut off too much, and turned * a valid path like '/' or 'C:/' into an incorrect path like * '' or 'C:'. The way we do this is to add a separator if - * there are none presently in the prefix. + * there are none presently in the prefix. Similar treatment + * for the zipfs volume. */ - if (strpbrk(Tcl_GetString(pathOrDir), "\\/") == NULL) { + const char *temp = Tcl_GetString(pathOrDir); + if (strpbrk(temp, "\\/") == NULL) { Tcl_AppendToObj(pathOrDir, last-1, 1); + } else if (!strcmp(temp, "//zipfs:")) { + Tcl_AppendToObj(pathOrDir, "/", 1); } } diff --git a/generic/tclZipfs.c b/generic/tclZipfs.c index 103c246..ffa46d6 100644 --- a/generic/tclZipfs.c +++ b/generic/tclZipfs.c @@ -5551,6 +5551,10 @@ ZipFSMatchInDirectoryProc( memcpy(pat + len, pattern, l + 1); scnt = CountSlashes(pat); + Tcl_HashTable duplicates; + int notDuplicate; + Tcl_InitHashTable(&duplicates, TCL_STRING_KEYS); + if (foundInHash) { for (hPtr = Tcl_FirstHashEntry(&ZipFS.fileHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { @@ -5563,26 +5567,46 @@ ZipFSMatchInDirectoryProc( if ((z->depth == scnt) && ((z->flags & ZE_F_VOLUME) == 0) /* Bug 14db54d81e */ && Tcl_StringCaseMatch(z->name, pat, 0)) { + Tcl_CreateHashEntry(&duplicates, z->name + strip, ¬Duplicate); + assert(notDuplicate); AppendWithPrefix(result, prefixBuf, z->name + strip, -1); } } - } else if (dirOnly) { - /* Not found in hash. May be a path that is the ancestor of a mount */ + } + if (dirOnly) { + /* + * Not found in hash. May be a path that is the ancestor of a mount. + * e.g. glob //zipfs:/a/* with mount at //zipfs:/a/b/c. Also have + * to be careful about duplicates, such as when another mount is + * //zipfs:/a/b/d + */ Tcl_HashEntry *hPtr; Tcl_HashSearch search; + Tcl_DString ds; + Tcl_DStringInit(&ds); for (hPtr = Tcl_FirstHashEntry(&ZipFS.zipHash, &search); hPtr; hPtr = Tcl_NextHashEntry(&search)) { ZipFile *zf = (ZipFile *)Tcl_GetHashValue(hPtr); if (Tcl_StringCaseMatch(zf->mountPoint, pat, 0)) { const char *tail = zf->mountPoint + len; + if (*tail == '\0') + continue; const char *end = strchr(tail, '/'); - AppendWithPrefix(result, - prefixBuf, - zf->mountPoint + strip, - end ? (int)(end - zf->mountPoint) : -1); + Tcl_DStringAppend(&ds, + zf->mountPoint + strip, + end ? (Tcl_Size)(end - zf->mountPoint) : -1); + const char *matchedPath = Tcl_DStringValue(&ds); + Tcl_HashEntry *dupTableEntry = + Tcl_CreateHashEntry(&duplicates, matchedPath, ¬Duplicate); + if (notDuplicate) { + AppendWithPrefix( + result, prefixBuf, matchedPath, Tcl_DStringLength(&ds)); + } + Tcl_DStringFree(&ds); } } } + Tcl_DeleteHashTable(&duplicates); ckfree(pat); end: diff --git a/tests/zipfs.test b/tests/zipfs.test index dbcf093..75a1651 100644 --- a/tests/zipfs.test +++ b/tests/zipfs.test @@ -412,7 +412,7 @@ namespace eval test_ns_zipfs { # list of paths -> list of paths under [zipfs root] proc zipfspaths {args} { - return [lmap path $args {file join [zipfs root] $path}] + return [lsort [lmap path $args {file join [zipfs root] $path}]] } proc cleanup {} { @@ -706,7 +706,7 @@ namespace eval test_ns_zipfs { testzipfslist no-pattern-mount-on-empty "" {test.zip {}} {{} test testdir testdir/test2} -constraints !zipfslib testzipfslist no-pattern-mount-on-root "" [list test.zip [zipfs root]] {{} test testdir testdir/test2} -constraints !zipfslib testzipfslist no-pattern-mount-on-slash "" [list test.zip /] {{} test testdir testdir/test2} -constraints !zipfslib - testzipfslist no-pattern-mount-on-level3 "" [list test.zip testmt/a/b] {{} testmt testmt/a testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2} -constraints {knownBug !zipfslib} + testzipfslist no-pattern-mount-on-mezzo "" [list test.zip testmt/a/b] {{} testmt testmt/a testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2} -constraints {knownBug !zipfslib} testzipfslist no-pattern-multiple "" {test.zip testmountA test.zip testmountB/subdir} { testmountA testmountA/test testmountA/testdir testmountA/testdir/test2 testmountB/subdir testmountB/subdir/test testmountB/subdir/testdir testmountB/subdir/testdir/test2 @@ -745,8 +745,8 @@ namespace eval test_ns_zipfs { testzipfsexists dir [file join $defaultMountPoint testdir] 1 testzipfsexists mountpoint $defaultMountPoint 1 testzipfsexists root [zipfs root] 1 $defaultMountPoint - testzipfsexists level3 [file join $defaultMountPoint a b] 1 [file join $defaultMountPoint a b c] - testzipfsexists level3-enoent [file join $defaultMountPoint a c] 0 [file join $defaultMountPoint a b c] + testzipfsexists mezzo [file join $defaultMountPoint a b] 1 [file join $defaultMountPoint a b c] + testzipfsexists mezzo-enoent [file join $defaultMountPoint a c] 0 [file join $defaultMountPoint a b c] # # zipfs find @@ -804,13 +804,13 @@ namespace eval test_ns_zipfs { # bug-6183f535c8 testzipfsfind root-path [zipfs root] { test.zip {} test.zip testmountB/subdir - } [zipfspaths test testdir testdir/test2] -constraints !zipfslib + } [zipfspaths test testdir testdir/test2 testmountB testmountB/subdir testmountB/subdir/test testmountB/subdir/testdir testmountB/subdir/testdir/test2] -constraints !zipfslib - testzipfsfind level3 [file join [zipfs root] testmt a] { + testzipfsfind mezzo [file join [zipfs root] testmt a] { test.zip testmt/a/b } [zipfspaths testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2] - testzipfsfind level3-root [zipfs root] { + testzipfsfind mezzo-root [zipfs root] { test.zip testmt/a/b } [zipfspaths testmt testmt/a testmt/a/b testmt/a/b/test testmt/a/b/testdir testmt/a/b/testdir/test2] \ -constraints bug-9e039ee0b9 @@ -888,7 +888,7 @@ namespace eval test_ns_zipfs { zipfs info $defaultMountPoint } -result [list [zippath junk-at-start.zip] 0 0 4] - test zipfs-info-level3 "zipfs info on mount point - verify correct offset of zip content" -setup { + test zipfs-info-mezzo "zipfs info on mount point - verify correct offset of zip content" -setup { # zip starts at offset 4 mount [zippath junk-at-start.zip] /testmt/a/b } -cleanup { @@ -1368,6 +1368,36 @@ namespace eval test_ns_zipfs { # # glob of zipfs file + proc xxx {id mounts cmdopts resultpaths args} { + set setup { + foreach {zippath mountpoint} $mounts { + zipfs mount [zippath $zippath] [file join [zipfs root] $mountpoint] + } + } + if {[dict exists $args -setup]} { + append setup \n[dict get $args -setup] + dict unset args -setup + } + set cleanup cleanup + if {[dict exists $args -cleanup]} { + set cleanup "[dict get $args -cleanup]\n$cleanup" + dict unset args -cleanup + } + set resultpaths [lsort $resultpaths] + test zipfs-xxx-$id "zipfs glob $id $cmdopts" -body { + lsort [glob {*}$cmdopts] + } -setup $setup -cleanup $cleanup -result $resultpaths {*}$args + } + xxx root {test.zip /} [list [zipfs root]*] [zipfspaths test testdir] + xxx root-pat {test.zip /} [list [zipfs root]*d*] [zipfspaths testdir] + xxx root-deep {test.zip /} [list [zipfs root]*/*] [zipfspaths testdir/test2] + xxx root-dir {test.zip /} [list -dir [zipfs root] *] [zipfspaths test testdir] + xxx root-dir-tails {test.zip /} [list -tails -dir [zipfs root] *] [list test testdir] + xxx root-type-d {test.zip /} [list -type d [zipfs root]*] [zipfspaths testdir] + xxx root-type-f {test.zip /} [list -type f [zipfs root]*] [zipfspaths test] + xxx root-path {test.zip /} [list -path [zipfs root]t *d*] [zipfspaths testdir] + + proc testzipfsglob {id mountpoint pat result {globopt {}} args} { test zipfs-glob-$id "zipfs glob $id" -setup { mount [zippath test.zip] $mountpoint -- cgit v0.12