#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 PKT8@1*-'#modpod-treeobj-1.3.1/demo/demo-0.1.tclQJ1/?<kI*ҋ"4f̶|.P%Ǽ;%t wya3,〢Ä7'Ï @ DY>QgLX1?/ft=y:nQ#\ mIȡB#mq3{֩P\f(Ak: ZS%Btd-٦ȱHآ) ȳyv^N8ej ȸJp3rbӿ^漦E mds¬ؿ>hw>妍q^X7PK׎/\"u'?&#modpod-treeobj-1.3.1/treeobj-1.3.1.tmkoF+6IsCQC/hs( 4HY~].W$-bK3! /R\^\MX2OV k󗓥22*$;:NT* 7d1w K)`g Xd&6y wbɟyU垿lXܫrn=̳*,er%n"KK8짽P\;k2^.%)Rnx/2ܕ rDتB'R NC*J؋,(e3g#H//DA`bVJ2KTQx ej;)hNE%-"@ɊT \1㼗_sf YldB-+3x#8:-@ 1@X-2i>)l𘈑p࣒sHnpZGu?=yN0 +P%00l[By`!XG\C"pQYmKvY]AGDjlA|*Ə\e(iٕ|*:<[룑0 d QŖJVf2RY2 )w|(70frnEX%%Qd6NkCYST=cPӈFVWp5\o0Wk0t]EpTs S#m ).-N]V]ae sb:ca!Oc倬EW,JM9b֩y kA]BK 7 IĬ[Qp- u圍q FXΰa1m]fioeJ#FwW FenfXr97c&^nm+"8(L_7[=VK7G*ZU"v$3KF\VwNYNqgFw߉̃nEFւlKF <*5 ̴ YXD lXqm$ܓ4haG>gn[Fe8W{8*C]8q9۫5 0%# - N3lqStgcP\-c #bZOr0T[v=@p(hENOdO}5o4JO1+2O{MWh U{3!=҅-[:^BnrM`M0s$ٴE)saՏ MpHIELN9t$-rgSA*8JHhwq[w֐^KIfhzks˜&2TήOUc1-n%)uA@̊Uh|A ;QWK;S8?!XQx(,N-,U8]2PԳ92c^o_l_>ʰm[yqyA?O!!xx@KQFFFj"mz !7WIECd_]!f)|0JhC.E$Jm! 0퓈vWjJ_ }IeQ\a8ONPWb;fk@(W5N$ٖEv7ЖnO=oj;/w{ookx$o2fh['nŗt {jukW16^1 p1dugf NI ,-s*rcev7  WUk"8VF+'2n]v[%4>ӘdÕh! .^"qx+Y:298捸XdQU)^öW [+: mB a)BZ!L!.!r<~r-#\^pWQTçe/RPtgXFM ٧N[Û¤8 ~iDQSeϣ=E;zS,q4y1{s "203(b ϥtaUf)O%,̳3e`]BEc1, ;4_P6iJwB PP+R !(?%6r_~h;D^4&ץL >_&KȐ3Jw\E$qFMb5zZvbLgLHzS\<{ ,)٣8M{&MmG&v%Oi( SѪo w;~#!Ȕ ~Ԙ!xT(GI}t6.:[ӻiȿ`xU@hn ]R5JŁvmM;e!%V6L]"BC%Dz5ĩn,T-[nΗxh"" 2]", j$?'^uELr'$+ax AbW:ҌDo~=rblE 3M-<yؐ֟=Ec0OPo!w6ґ ;~4ؤH*g' y*AksFh `t ˋޫ| _ŒfD?U?Ðf$?:Q\'XukH.K{Υ, u)k췢zZ7TP,;o7lO Hui9[2`ӞlEcNψK8<(:n^: Ia,cnl$A"1}K.'k;|R9p6h”~Y`r 7M¢i|SH!ԎsZ{Wtه Ntg~n'OqoMj!s2-┾pov|xc0NR{88n)9F_2o).V@A]ܞIJLF][E;cۢV~ѥaiSZ#NFj\\ )|ˉ\lr+0ۼihF\ڜ # ?Z#L }s`=)@Y춖AAp%jS"yŧG%>B pvGo"ZpszJDYgGM )&8&1z Z0ڃ1@*5* %Y|˫ThѥG.P0;!:!bP ;< E|vBeB}s]lܲF~7&DkC,*7ږU%U,;-,1Ɵ_\aE<?)hU5{M3ՖI^$#\³2[.\J )W} _m@CzX웧O?zP18?PKT8@1*-'#modpod-treeobj-1.3.1/demo/demo-0.1.tclPK׎/\"u'?&t#modpod-treeobj-1.3.1/treeobj-1.3.1.tmPK