#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]} modfile]} { error "modpod zip stub error. Unable to determine module path. (possible safe interp restrictions?)" } if {$modfile eq "" || ![file exists $modfile]} { error "modpod zip stub error. Unable to determine module path" } set moddir [file dirname $modfile] set mod_and_ver [file rootname [file tail $modfile]] lassign [split $mod_and_ver -] moduletail version if {[file exists $moddir/#modpod-$mod_and_ver]} { source $moddir/#modpod-$mod_and_ver/$mod_and_ver.tm } else { #determine module namespace so we can mount appropriately proc 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 } 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 [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 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 $moddir/$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 $moddir/$mount_at] if {![file exists $moddir/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm]} { vfs::zip::Unmount $fd $moddir/$mount_at error "Unable to find $mod_and_ver.tm in $modfile for module $fullpackage" } } } source $moddir/$mount_at/#modpod-$mod_and_ver/$mod_and_ver.tm } } #zipped data follows PKZA7t&6Q.#modpod-packageTest-0.1.3/packageTest-0.1.3.tm}ޯn2aEɔ}]&ˠe18+n8}f  '!+g'&z`4g" )+/8[醽noe1+p`A(9@5?!(c( \u(`&hQ↰ ( 6 |4JA,:Zr( o8:/[CL2ekr"*|;f^/?u,<}Mg|-g_Au}^x"Vzɱ8iPi, AtGN?==eT &O2 lDu24,chQ.i`^fy) Z1Mf\<`fÓm}7 N:/j#E!ȣF8a6O ;m_0.HBEDx 2ʹN2s<L4lgǜ#|łmE+=S.ioSY!Z( S>I6 令.0'A5 1YȖN*b$Co2i\ nSp]pw|uC >Sxl^MVZvo8EbuWY(Wu]oYO5L5]{ N$Z-9?i0W4t,xFNig~8<G(/9(jdHdkX:T)Y?W5ϥ9w/؏?NƁu}/] 4|![/: -Pn;>&6 E]9]4-N}nHK*:`,Mj@݁j%'10+q: #A_^R"BI$6d3(* {)-DjC+Ͻգ9qC('jmSg0jx-@9z6al wmZrjl@e o8Àc۰tB e^T."L˂YzJ_#y޳>ShWX:HR$F0ճ[HD _1bMh`ֈ1ZaW[ϥ`S'#^oDi5x\7eM\y}spy3mw=*n8e.)(K/0ON)77l^B}c[-@M{F }@%-$o~>ĀJHhVu'6 g<@s?̉(e &H23\nUR3^?S]?)D M{y}֓YT>P/;*afi:==u~mW\ 6<{K@QC~--s a$ K a8Ѡ<t#x$8q7YpaR26F=i5,Aq|g 31dKml }ݛ 8 ./@ϞP˯t;1 P_D$*QϱOgNʬA@fir*Η}u}!e9U0U}b]AKuX\{OPמ5^ 1@ۃJV1#kk^y=6W3HP1`GH8:=Uwƫb^i<6*XcTJ|܌\lӾiY3r'T[!O̫&@5mCsq7 k5Ar6o*![@,s QAЙuf :Is>q4S0dVɜ<Xkǹ@v,g/q9@205->P)'a7e!(PXʨP&H'ypLnx^Sڎl͘h(uݟ/>GvhoBFMTܡ`KHpѝjf}ۍ!(@j.}Dy_T~ngˣdNpFгwCK@iWשxb$@U{1:ߝ `eytϥz}'c5HR0FB@S+^x)rC̎"Wa{E_Rpr,PWbl7h;&9_լةQ3Pfy"Tzx:㽃pAUY$o;\SP\sP5AX;&+9%WkO0Ӵ?I.'IRȥ Hb{ b^Pܳ %X8~:0ha9@ J̖~h =PƆYD7Wzj؎x$iKvko4-{TwʐA|=`3Y A,«꩓z3%`+vdz <`wZi0=~$O?r"MG!:#卭Te }(ܬM&59y6O0=k2kvJ^Q%ZVWaS;jY׌oQ'T6mqkxjv4Fbu>~]O~<ŧ2u*Y Tղ7w @j@YC^2Y!b.zꮯ_a*/fY@+w t(<#5TzN8,TL+OۅAtH(xPOujc͂%R=>aVZş8Fur~De#; <*qPfTrp_U hZwT,TUV(Pգ*-2\MF=W)HΠ s_N8k0u?73a:wEe(yy1O_ͲJ_G Ua<-3<,'3`x@ @@rgQjMs|EhZnTB_H*QLF꺎Iw|Au=3oMjX{dCU5/o'pS"ES]\L$mA!QLA\^B vՅ Pvy-D@xPqn|QW_|Zxc -tfy vnxkLc^ړ(p~dK[JI`]ԩp٩ߋO/?@Y4+RCT%Wg'+xm{BZ_[A{tl,tn7D|& ZpT0}ffgՙHIFbf si;}Y;=9@F\d8QW0yxk XW?n||J>$ꉣ?6M!i1jґ`׉aگkw"eh:f/M&{:Rpq)M`1y.xxNp~əEImRn(. } j-wsA:1O؍z$8ɰRDKp^}:ڊhm<.Q\->\u5/8C> 9<6,Z%8xPxQן}}ve83ټEA=ҩp0MԾ(֠5y\26+]KG{&D ?|RV瓁_cpR-PlJO:I .Zϼ =3е:/ u CGNL4ޗ!1=ޟp{}qٞ5 >A^x_3 t0w#z9._0yS>*/-p+6iyYўu ބޛK_]神