#zip file with Tcl loader prepended. Requires either builtin zipfs, or vfs::zip to mount while zipped. #Alternatively unzip so that extracted #modpod-package-version folder is in same folder as .tm file. #generated using: modpod::lib::make_zip_modpod -offsettype archive if {[catch {file normalize [info script]}]} { error "modpod zip stub error. Unable to determine module path. (possible safe interp restrictions?)" } apply {{modfile} { if {$modfile eq "" || ![file exists $modfile]} { error "modpod zip stub error. Unable to determine module path" } set moddir [file dirname $modfile] set exedir [file dirname [file normalize [info nameofexecutable]]] set mod_and_ver [file rootname [file tail $modfile]] lassign [split $mod_and_ver -] moduletail version set do_intersect {{A B} { if {[llength $A] == 0} {return {}} if {[llength $B] == 0} {return {}} if {[llength $B] > [llength $A]} { set res $A set A $B set B $res } set res {} foreach x $A {set ($x) {}} foreach x $B { if {[info exists ($x)]} { lappend res $x } } return $res }} #determine module namespace so we can mount appropriately set lcase_tmfile_segments [string tolower [file split $moddir]] set lcase_modulepaths [string tolower [tcl::tm::list]] foreach lc_mpath $lcase_modulepaths { set mpath_segments [file split $lc_mpath] if {[llength [apply $do_intersect $lcase_tmfile_segments $mpath_segments]] == [llength $mpath_segments]} { set tail_segments [lrange [file split $moddir] [llength $mpath_segments] end] ;#use properly cased tail break } } if {[llength $tail_segments]} { set fullpackage [join [concat $tail_segments $moduletail] ::] ;#full name of package as used in package require set mount_at #modpod/[file join {*}$tail_segments]/#mounted-modpod-$mod_and_ver } else { set fullpackage $moduletail set mount_at #modpod/#mounted-modpod-$mod_and_ver } if {[info commands tcl::zipfs::mount] ne ""} { #argument order changed to be consistent with vfs::zip::Mount etc #early versions: zipfs::Mount mountpoint zipname #since 2023-09: zipfs::Mount zipname mountpoint #don't use 'file exists' when testing mountpoints. (some versions at least give massive delays on windows platform for non-existance) #This is presumably related to // being interpreted as a network path set mountpoints [dict keys [tcl::zipfs::mount]] if {"//zipfs:/$mount_at" ni $mountpoints} { #despite API change tcl::zipfs package version was unfortunately not updated - so we don't know argument order without trying it if {[catch { #tcl::zipfs::mount $modfile //zipfs:/#mounted-modpod-$mod_and_ver ;#extremely slow if this is a wrong guess (artifact of aforementioned file exists issue ?) #puts "tcl::zipfs::mount $modfile $mount_at" tcl::zipfs::mount $modfile $mount_at } errM]} { #try old api if {![catch {tcl::zipfs::mount //zipfs:/$mount_at $modfile}]} { puts stderr "modpod stub>>> tcl::zipfs::mount failed.\nbut old api: tcl::zipfs::mount succeeded\n tcl::zipfs::mount //zipfs://$mount_at $modfile" puts stderr "Consider upgrading tcl runtime to one with fixed zipfs API" } } if {![file exists //zipfs:/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm]} { puts stderr "modpod stub>>> mount at //zipfs:/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm failed\n zipfs mounts: [zipfs mount]" #tcl::zipfs::unmount //zipfs:/$mount_at error "Unable to find $mod_and_ver.tm in $modfile for module $fullpackage" } } # #modpod-$mod_and_ver subdirectory always present in the archive so it can be conveniently extracted and run in that form uplevel 1 [list source //zipfs:/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm] } else { #fallback to slower vfs::zip #NB. We don't create the intermediate dirs - but the mount still works if {![file exists $exedir/$mount_at]} { if {[catch {package require vfs::zip} errM]} { set msg "Unable to load vfs::zip package to mount module $mod_and_ver (and zipfs not available either)" append msg \n "If neither zipfs or vfs::zip are available - the module can still be loaded by manually unzipping the file $modfile in place." append msg \n "The unzipped data will all be contained in a folder named #modpod-$mod_and_ver in the same parent folder as $modfile" error $msg } else { set fd [vfs::zip::Mount $modfile $exedir/$mount_at] if {![file exists $exedir/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm]} { vfs::zip::Unmount $fd $exedir/$mount_at error "Unable to find $mod_and_ver.tm in $modfile for module $fullpackage" } } } uplevel 1 [list source $exedir/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm] } }} [file normalize [info script]] #zipped data follows PKk\Q{> "#modpod-zipper-0.14/zipper-0.14.tmYoFDkوɱ$&h .9YgPJښ"U.)of/Qjk H_?Il4$=882 ?P~DbRZڻEfci?ҟa,}NA:;kCI~6j?͒@n,C= 3V$UJ$?d3%B=JTH6͔šuZ1ɩʰu"U"5S~3?Eq|LO^8#-˷RZ`*IwgdbCR(SA&HGs: {:zKG7c:T0jj1|໦~&<@k|lhR#-!Y8XpaX 5>/O^뽽OޛMӚoϛ]] vz'Y44,kZ%, W1yº5<{U/v]=v 84#9eu0Xɣ~~IQ 8[ι+{!a H|R2oDhzVOߴ &DjpXHU+@n9liE5:hkW;p^0ŶY{ia ptvl(T1!i1 #>EzLA<=d ?iK5lHEF $"WRQI2"6~uDWؒa~WWkqfJ6ʶah ->JNbmH7E̦!,D$uykMi+4Z E[ )`gklT݁8ruX߸RM߶9Vt߆6L6U\qtyb)[#y@R!W'] _fG'g$jo7b|ٯ'w=E ]9v5?\Zkc.w?z@tG?pͺD'ƐWKW'Yv"f~np$u\#5=|:Lcnqجɭ4^hoYx3 4Bsv~|xT{6{66w_@)Q/RZyӏrU޽gEF Dz|Q^ͭ]'%n)qjGt;;'Ź ߤdœR%}w)󐕤uQvxhKkx.(:<4u85#Ӟ>w "?~.; f1us+C[4Me*è05Ө5/^k<5'mK -V{=> Uz[kPR5E6uϲhWZvGZ*+4wy̦gF/έ7X_g/OwYooK~ 7Ա9`9JàA˰f(#2f #[wauOc4k;8X}>N.ykKe_9b.Gz Og rd-'s7X 2y1,X?U@)em:L] _ ̒5-;9;>*0xɈ,ہF4*vM=pkS?*b@vMpw9FɘGz!Ff]!ޤ589{bgf#߇/Pj-ã/4b_&)2+wY.Pj ݛS]n[:1ׄu{Drܹ]~[ƹSBS|_,WX:v"{9J&}?\PKB[yk!#modpod-zipper-0.14/zipper.README}Mo0 ӯ Ӭn`vȩCSȒ*q_?NfmxL Jq`k  .c%|=TDg5-3q)nT hy1XUiJ8PmeĥRF&:!|lûg.\m0qhHd1BעV #D۩sr˰su1y(8%O 9"8xllɅ(McIWJb)hj65oa悵%T#BbWΠ. Tl/O)cB |RE}0$0eQ4af@[B݋ժs Xlzmݕy3zIO Ɇc6>(\a}3ݞ"Qb :SI1Z Kz'g~PKk\Q{> "#modpod-zipper-0.14/zipper-0.14.tmPKB[yk! #modpod-zipper-0.14/zipper.READMEPK