diff --git a/src/bootsupport/modules/include_modules.config b/src/bootsupport/modules/include_modules.config index e643dc39..8517d9bb 100644 --- a/src/bootsupport/modules/include_modules.config +++ b/src/bootsupport/modules/include_modules.config @@ -25,6 +25,7 @@ set bootsupport_modules [list\ src/vendormodules patternlib\ src/vendormodules patternpredator2\ src/vendormodules patterncipher\ + src/vendormodules platform\ src/vendormodules promise\ src/vendormodules sha1\ src/vendormodules tomlish\ @@ -41,9 +42,8 @@ set bootsupport_modules [list\ modules argp\ modules flagfilter\ modules funcl\ - modules natsort\ modules punk\ - modules punk::pipe\ + modules punk::pipe\ modules punkapp\ modules punkcheck\ modules punkcheck::cli\ diff --git a/src/bootsupport/modules/natsort-0.1.1.7.tm b/src/bootsupport/modules/natsort-0.1.1.7.tm index 5ce217ba..0724c20c 100644 --- a/src/bootsupport/modules/natsort-0.1.1.7.tm +++ b/src/bootsupport/modules/natsort-0.1.1.7.tm @@ -1659,13 +1659,13 @@ namespace eval natsort { set allfiles [concat $allfiles $dotfiles $files] } else { #file (or link?) - set files [glob -nocomplain -directory [file dirname $item] -tail [file tail $item]] + set files [glob -nocomplain -directory [file dirname $item] -tail -- [file tail $item]] set allfiles [concat $allfiles $files] } } else { - set folders [glob -nocomplain -directory $item -type {d} -tail [file tail $item]] + set folders [glob -nocomplain -directory $item -type {d} -tail -- [file tail $item]] set allfolders [concat $allfolders $folders] - set files [glob -nocomplain -directory [file dirname $item] -tail [file tail $item]] + set files [glob -nocomplain -directory [file dirname $item] -tail -- [file tail $item]] set allfiles [concat $allfiles $files] } } diff --git a/src/bootsupport/modules/platform-1.0.19.tm b/src/bootsupport/modules/platform-1.0.19.tm new file mode 100644 index 00000000..acaebf26 --- /dev/null +++ b/src/bootsupport/modules/platform-1.0.19.tm @@ -0,0 +1,450 @@ +# -*- tcl -*- +# ### ### ### ######### ######### ######### +## Overview + +# Heuristics to assemble a platform identifier from publicly available +# information. The identifier describes the platform of the currently +# running tcl shell. This is a mixture of the runtime environment and +# of build-time properties of the executable itself. +# +# Examples: +# <1> A tcl shell executing on a x86_64 processor, but having a +# wordsize of 4 was compiled for the x86 environment, i.e. 32 +# bit, and loaded packages have to match that, and not the +# actual cpu. +# +# <2> The hp/solaris 32/64 bit builds of the core cannot be +# distinguished by looking at tcl_platform. As packages have to +# match the 32/64 information we have to look in more places. In +# this case we inspect the executable itself (magic numbers, +# i.e. fileutil::magic::filetype). +# +# The basic information used comes out of the 'os' and 'machine' +# entries of the 'tcl_platform' array. A number of general and +# os/machine specific transformation are applied to get a canonical +# result. +# +# General +# Only the first element of 'os' is used - we don't care whether we +# are on "Windows NT" or "Windows XP" or whatever. +# +# Machine specific +# % amd64 -> x86_64 +# % arm* -> arm +# % sun4* -> sparc +# % ia32* -> ix86 +# % intel -> ix86 +# % i*86* -> ix86 +# % Power* -> powerpc +# % x86_64 + wordSize 4 => x86 code +# +# OS specific +# % AIX are always powerpc machines +# % HP-UX 9000/800 etc means parisc +# % linux has to take glibc version into account +# % sunos -> solaris, and keep version number +# +# NOTE: A platform like linux glibc 2.3, which can use glibc 2.2 stuff +# has to provide all possible allowed platform identifiers when +# searching search. Ditto a solaris 2.8 platform can use solaris 2.6 +# packages. Etc. This is handled by the other procedure, see below. + +# ### ### ### ######### ######### ######### +## Requirements + +namespace eval ::platform {} + +# ### ### ### ######### ######### ######### +## Implementation + +# -- platform::generic +# +# Assembles an identifier for the generic platform. It leaves out +# details like kernel version, libc version, etc. + +proc ::platform::generic {} { + global tcl_platform + + set plat [string tolower [lindex $tcl_platform(os) 0]] + set cpu $tcl_platform(machine) + + switch -glob -- $cpu { + sun4* { + set cpu sparc + } + intel - + ia32* - + i*86* { + set cpu ix86 + } + x86_64 { + if {$tcl_platform(wordSize) == 4} { + # See Example <1> at the top of this file. + set cpu ix86 + } + } + ppc - + "Power*" { + set cpu powerpc + } + "arm*" { + set cpu arm + } + ia64 { + if {$tcl_platform(wordSize) == 4} { + append cpu _32 + } + } + } + + switch -glob -- $plat { + windows { + if {$tcl_platform(platform) == "unix"} { + set plat cygwin + } else { + set plat win32 + } + if {$cpu eq "amd64"} { + # Do not check wordSize, win32-x64 is an IL32P64 platform. + set cpu x86_64 + } + } + sunos { + set plat solaris + if {[string match "ix86" $cpu]} { + if {$tcl_platform(wordSize) == 8} { + set cpu x86_64 + } + } elseif {![string match "ia64*" $cpu]} { + # sparc + if {$tcl_platform(wordSize) == 8} { + append cpu 64 + } + } + } + darwin { + set plat macosx + # Correctly identify the cpu when running as a 64bit + # process on a machine with a 32bit kernel + if {$cpu eq "ix86"} { + if {$tcl_platform(wordSize) == 8} { + set cpu x86_64 + } + } + } + aix { + set cpu powerpc + if {$tcl_platform(wordSize) == 8} { + append cpu 64 + } + } + hp-ux { + set plat hpux + if {![string match "ia64*" $cpu]} { + set cpu parisc + if {$tcl_platform(wordSize) == 8} { + append cpu 64 + } + } + } + osf1 { + set plat tru64 + } + default { + set plat [lindex [split $plat _-] 0] + } + } + + return "${plat}-${cpu}" +} + +# -- platform::identify +# +# Assembles an identifier for the exact platform, by extending the +# generic identifier. I.e. it adds in details like kernel version, +# libc version, etc., if they are relevant for the loading of +# packages on the platform. + +proc ::platform::identify {} { + global tcl_platform + + set id [generic] + regexp {^([^-]+)-([^-]+)$} $id -> plat cpu + + switch -- $plat { + solaris { + regsub {^5} $tcl_platform(osVersion) 2 text + append plat $text + return "${plat}-${cpu}" + } + macosx { + set major [lindex [split $tcl_platform(osVersion) .] 0] + if {$major > 19} { + set minor [lindex [split $tcl_platform(osVersion) .] 1] + incr major -9 + append plat $major.[expr {$minor - 1}] + } else { + incr major -4 + append plat 10.$major + return "${plat}-${cpu}" + } + return "${plat}-${cpu}" + } + linux { + # Look for the libc*.so and determine its version + # (libc5/6, libc6 further glibc 2.X) + + set v unknown + + # Determine in which directory to look. /lib, or /lib64. + # For that we use the tcl_platform(wordSize). + # + # We could use the 'cpu' info, per the equivalence below, + # that however would be restricted to intel. And this may + # be a arm, mips, etc. system. The wordsize is more + # fundamental. + # + # ix86 <=> (wordSize == 4) <=> 32 bit ==> /lib + # x86_64 <=> (wordSize == 8) <=> 64 bit ==> /lib64 + # + # Do not look into /lib64 even if present, if the cpu + # doesn't fit. + + # TODO: Determine the prefixes (i386, x86_64, ...) for + # other cpus. The path after the generic one is utterly + # specific to intel right now. Ok, on Ubuntu, possibly + # other Debian systems we may apparently be able to query + # the necessary CPU code. If we can't we simply use the + # hardwired fallback. + + switch -exact -- $tcl_platform(wordSize) { + 4 { + lappend bases /lib + if {[catch { + exec dpkg-architecture -qDEB_HOST_MULTIARCH + } res]} { + lappend bases /lib/i386-linux-gnu + } else { + # dpkg-arch returns the full tripled, not just cpu. + lappend bases /lib/$res + } + } + 8 { + lappend bases /lib64 + if {[catch { + exec dpkg-architecture -qDEB_HOST_MULTIARCH + } res]} { + lappend bases /lib/x86_64-linux-gnu + } else { + # dpkg-arch returns the full tripled, not just cpu. + lappend bases /lib/$res + } + } + default { + return -code error "Bad wordSize $tcl_platform(wordSize), expected 4 or 8" + } + } + + foreach base $bases { + if {[LibcVersion $base -> v]} break + } + + append plat -$v + return "${plat}-${cpu}" + } + } + + return $id +} + +proc ::platform::LibcVersion {base _->_ vv} { + upvar 1 $vv v + set libclist [lsort [glob -nocomplain -directory $base libc*]] + + if {![llength $libclist]} { return 0 } + + set libc [lindex $libclist 0] + + # Try executing the library first. This should suceed + # for a glibc library, and return the version + # information. + + if {![catch { + set vdata [lindex [split [exec $libc] \n] 0] + }]} { + regexp {version ([0-9]+(\.[0-9]+)*)} $vdata -> v + foreach {major minor} [split $v .] break + set v glibc${major}.${minor} + return 1 + } else { + # We had trouble executing the library. We are now + # inspecting its name to determine the version + # number. This code by Larry McVoy. + + if {[regexp -- {libc-([0-9]+)\.([0-9]+)} $libc -> major minor]} { + set v glibc${major}.${minor} + return 1 + } + } + return 0 +} + +# -- platform::patterns +# +# Given an exact platform identifier, i.e. _not_ the generic +# identifier it assembles a list of exact platform identifier +# describing platform which should be compatible with the +# input. +# +# I.e. packages for all platforms in the result list should be +# loadable on the specified platform. + +# << Should we add the generic identifier to the list as well ? In +# general it is not compatible I believe. So better not. In many +# cases the exact identifier is identical to the generic one +# anyway. +# >> + +proc ::platform::patterns {id} { + set res [list $id] + if {$id eq "tcl"} {return $res} + + switch -glob -- $id { + solaris*-* { + if {[regexp {solaris([^-]*)-(.*)} $id -> v cpu]} { + if {$v eq ""} {return $id} + foreach {major minor} [split $v .] break + incr minor -1 + for {set j $minor} {$j >= 6} {incr j -1} { + lappend res solaris${major}.${j}-${cpu} + } + } + } + linux*-* { + if {[regexp {linux-glibc([^-]*)-(.*)} $id -> v cpu]} { + foreach {major minor} [split $v .] break + incr minor -1 + for {set j $minor} {$j >= 0} {incr j -1} { + lappend res linux-glibc${major}.${j}-${cpu} + } + } + } + macosx-powerpc { + lappend res macosx-universal + } + macosx-x86_64 { + lappend res macosx-i386-x86_64 + } + macosx-ix86 { + lappend res macosx-universal macosx-i386-x86_64 + } + macosx*-* { + # 10.5+,11.0+ + if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} { + + switch -exact -- $cpu { + ix86 { + lappend alt i386-x86_64 + lappend alt universal + } + x86_64 { + if {[lindex [split $::tcl_platform(osVersion) .] 0] < 19} { + set alt i386-x86_64 + } else { + set alt {} + } + } + arm { + lappend alt x86_64 + } + default { set alt {} } + } + + if {$v ne ""} { + foreach {major minor} [split $v .] break + + set res {} + if {$major eq 13} { + # Add 13.0 to 13.minor to patterns. + for {set j $minor} {$j >= 0} {incr j -1} { + lappend res macosx${major}.${j}-${cpu} + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + set major 12 + set minor 5 + } + if {$major eq 12} { + # Add 12.0 to 12.minor to patterns. + for {set j $minor} {$j >= 0} {incr j -1} { + lappend res macosx${major}.${j}-${cpu} + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + set major 11 + set minor 5 + } + if {$major eq 11} { + # Add 11.0 to 11.minor to patterns. + for {set j $minor} {$j >= 0} {incr j -1} { + lappend res macosx${major}.${j}-${cpu} + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + set major 10 + set minor 15 + } + # Add 10.5 to 10.minor to patterns. + for {set j $minor} {$j >= 5} {incr j -1} { + if {$cpu ne "arm"} { + lappend res macosx${major}.${j}-${cpu} + } + foreach a $alt { + lappend res macosx${major}.${j}-$a + } + } + + # Add unversioned patterns for 10.3/10.4 builds. + lappend res macosx-${cpu} + foreach a $alt { + lappend res macosx-$a + } + } else { + # No version, just do unversioned patterns. + foreach a $alt { + lappend res macosx-$a + } + } + } else { + # no v, no cpu ... nothing + } + } + } + lappend res tcl ; # Pure tcl packages are always compatible. + return $res +} + + +# ### ### ### ######### ######### ######### +## Ready + +package provide platform 1.0.19 + +# ### ### ### ######### ######### ######### +## Demo application + +if {[info exists argv0] && ($argv0 eq [info script])} { + puts ==================================== + parray tcl_platform + puts ==================================== + puts Generic\ identification:\ [::platform::generic] + puts Exact\ identification:\ \ \ [::platform::identify] + puts ==================================== + puts Search\ patterns: + puts *\ [join [::platform::patterns [::platform::identify]] \n*\ ] + puts ==================================== + exit 0 +} diff --git a/src/bootsupport/modules/punk-0.1.1.tm b/src/bootsupport/modules/punk-0.1.1.tm index e3ba36b4..cf54a13e 100644 --- a/src/bootsupport/modules/punk-0.1.1.tm +++ b/src/bootsupport/modules/punk-0.1.1.tm @@ -6618,7 +6618,7 @@ namespace eval punk { } } else { - #set executables [lsort -unique [glob -nocomplain -directory $p -types {f x} -tail {*}$binglobs]] + #set executables [lsort -unique [glob -nocomplain -directory $p -types {f x} -tail -- {*}$binglobs]] set executables [lsort -unique [glob -nocomplain -directory $p -types {f x} -tail *]] } } @@ -8160,9 +8160,9 @@ namespace eval punk { (pipeline data inserted at end of each |...> segment is passed as single item unless inserted with an expanding insertion specifier such as .=>* ) e.g1: - .= list a b c |v1,/1-end,/0>\\ - .=>* inspect -label i1 -- |>\\ - .=v1> inspect -label i2 -- |>\\ + .= list a b c |v1,/1..end,/0>\\ + .=>* inspect -label i1 -- |>\\ + .=v1> inspect -label i2 -- |>\\ string toupper (3) i1: {a b c} {b c} a (1) i2: a b c diff --git a/src/bootsupport/modules/punk/args-0.2.1.tm b/src/bootsupport/modules/punk/args-0.2.1.tm index 24c2ddf7..4a9b18c0 100644 --- a/src/bootsupport/modules/punk/args-0.2.1.tm +++ b/src/bootsupport/modules/punk/args-0.2.1.tm @@ -3688,14 +3688,20 @@ tcl::namespace::eval punk::args { @id -id ::punk::args::update_definitions @cmd -name punk::args::update_definitions\ -summary\ - ""\ + "Update internal caches with new definitions from packages that have been loaded since the last scan."\ -help\ - "" + "Scans for new definitions in the specified namespaces and updates internal caches. + This is called automatically by punk::args::real_id when an id is not found - + to ensure that any definitions in newly loaded packages are available for retrieval. + It can also be called manually to pre-load definitions from specific namespaces + - e.g to prepare for a series of calls to punk::args::real_id where the namespace origin of the ids is" @values -min 1 - id - arglist -type list -help\ - "list containing arguments to be parsed as per the - argument specification identified by the supplied id." + nslist -type list -help\ + "list of namespaces to update definitions for. + If a package namespace is included that hasn't been scanned yet, + it will be scanned as part of this call. If the list contains the single element '*', + all registered namespaces will be updated. + (scanned if not already scanned, and any new loaded packages will be included)." }] #scanned_packages (list) #namespace_docpackages (dict) diff --git a/src/bootsupport/modules/punk/du-0.1.0.tm b/src/bootsupport/modules/punk/du-0.1.0.tm index ca7f58e9..168fdf61 100644 --- a/src/bootsupport/modules/punk/du-0.1.0.tm +++ b/src/bootsupport/modules/punk/du-0.1.0.tm @@ -1879,16 +1879,16 @@ namespace eval punk::du { #if {![llength $types_entry] || "d" in $types_entry} {} if {!$skip_dirs} { #we need to check directories for hidden attribute - as on windows, not all dotfiles are hidden, and not all hidden files are dotfiles - set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} {*}$globs] - set dirs [glob -nocomplain -dir $folderpath -types d {*}$globs] + set hdirs [glob -nocomplain -dir $folderpath -types {hidden d} -- {*}$globs] + set dirs [glob -nocomplain -dir $folderpath -types d -- {*}$globs] } if {!$skip_links} { - set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} {*}$globs] - set links [glob -nocomplain -dir $folderpath -types l {*}$globs] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique + set hlinks [glob -nocomplain -dir $folderpath -types {hidden l} -- {*}$globs] + set links [glob -nocomplain -dir $folderpath -types l -- {*}$globs] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique } if {!$skip_files} { - set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} {*}$globs] - set files [glob -nocomplain -dir $folderpath -types f {*}$globs] + set hfiles [glob -nocomplain -dir $folderpath -types {hidden f} -- {*}$globs] + set files [glob -nocomplain -dir $folderpath -types f -- {*}$globs] } } else { if {$opt_glob eq "*"} { @@ -1901,13 +1901,13 @@ namespace eval punk::du { #however - these are still significantly slower than a single glob with no restrictions - so we want to minimize the number of globs we do #- but we also want to avoid doing extra work classifying entries that we will end up ignoring based on types/attributes/permissions filters. if {!$skip_dirs} { - set dirs [glob -nocomplain -dir $folderpath -types d {*}$globs] + set dirs [glob -nocomplain -dir $folderpath -types d -- {*}$globs] } if {!$skip_links} { - set links [glob -nocomplain -dir $folderpath -types l {*}$globs] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique + set links [glob -nocomplain -dir $folderpath -types l -- {*}$globs] ;#links may have dupes - we don't care. punk::lib::struct_set_diff_unique } if {!$skip_files} { - set files [glob -nocomplain -dir $folderpath -types f {*}$globs] + set files [glob -nocomplain -dir $folderpath -types f -- {*}$globs] } } diff --git a/src/bootsupport/modules/punk/lib-0.1.6.tm b/src/bootsupport/modules/punk/lib-0.1.6.tm index 5fecb48d..fb0cf96b 100644 --- a/src/bootsupport/modules/punk/lib-0.1.6.tm +++ b/src/bootsupport/modules/punk/lib-0.1.6.tm @@ -808,7 +808,7 @@ namespace eval punk::lib { set argd [punk::args::parse $args withid ::punk::lib::tempdir_newfolder] set opt_dir [dict get $argd opts -dir] set opt_prefix [dict get $argd opts -prefix] - puts "opt_prefix: $opt_prefix" + #puts "opt_prefix: $opt_prefix" if {[llength [file split $opt_prefix]] > 1} { error "punk::lib::tempdir_newfolder -prefix option should not contain any path separators" } @@ -962,10 +962,13 @@ namespace eval punk::lib { return [join $newparts .] } proc tm_version_required_canonical {versionspec} { - #also trim leading zero from any dottedpart? - #Tcl *allows* leading zeros in any of the dotted parts - but they are not significant. - #e.g 1.01 is equivalent to 1.1 and 01.001 - #also 1b3 == 1b0003 + #Tcl *allows* leading zeros in any of the dotted parts, including either side of a or b - but they are not significant. + #an a or b must have a digit either side to be valid. + #e.g 1.1 is canonical and equivalent to 1.01 and 01.001 + #e.g 1a1 is canonical and equivalent to 1a01 and 01a001 + #e.g 1b3 is canonical and equivalent to 1b0003 + #e.g 1.0a3 is canonical and equivalent to 1.0a0003 and 01.00a0003 + #e.g 1.10b0 is canonical and equivalent to 1.010b000 and 01.10b000 if {[string trim $versionspec] eq ""} {return ""} ;#unspecified = any version set errmsg "tm_version_required_canonical - invalid version specification" @@ -1036,7 +1039,8 @@ namespace eval punk::lib { Returns a two element list - with the first element being the modulename and the second element being the version. - Tcl module version numbers are understood with leading zeros in each dotted part, but leading zeros are not canonical. + Tcl module version numbers are understood with leading zeros in each dotted part, including either side of a or b, + but leading zeros are not canonical. This split does not canonicalise the version number. If the last dash-separated segment of the name doesn't look like a valid version number diff --git a/src/bootsupport/modules/punk/mix/base-0.1.tm b/src/bootsupport/modules/punk/mix/base-0.1.tm index ba24f31d..81496c06 100644 --- a/src/bootsupport/modules/punk/mix/base-0.1.tm +++ b/src/bootsupport/modules/punk/mix/base-0.1.tm @@ -705,15 +705,15 @@ namespace eval punk::mix::base { } if {[catch { #{*}$tarpath needed in case spaces in tarpath - exec {*}$tarpath -cf {*}$flags $archivename $target + exec {*}$tarpath {*}$flags -cf $archivename $target } errMsg]} { set tsend [clock millis] set ms [expr {$tsend - $tsstart}] - puts stdout " 'tar -cf $flags' ERROR ($ms ms) - falling back to tar::create\n error info: $errMsg" + puts stdout " 'tar $flags -cf ' ERROR ($ms ms) - falling back to tar::create\n error info: $errMsg" } else { set tsend [clock millis] set ms [expr {$tsend - $tsstart}] - puts stdout " 'tar -cf $flags' done ($ms ms)" + puts stdout " 'tar $flags -cf' done ($ms ms)" } } diff --git a/src/bootsupport/modules/punk/mix/cli-0.3.1.tm b/src/bootsupport/modules/punk/mix/cli-0.3.1.tm index 6ac3cc1e..e29dd871 100644 --- a/src/bootsupport/modules/punk/mix/cli-0.3.1.tm +++ b/src/bootsupport/modules/punk/mix/cli-0.3.1.tm @@ -551,15 +551,15 @@ namespace eval punk::mix::cli { set process_modules [dict create] #put pods first in processing order - set src_pods [glob -nocomplain -dir $current_source_dir -type d -tail $podglob] + set src_pods [glob -nocomplain -dir $current_source_dir -type d -tail -- $podglob] foreach podpath $src_pods { dict set process_modules $podpath [dict create -type pod] } - set src_tarjars [glob -nocomplain -dir $current_source_dir -type d -tail $tarjarglob] + set src_tarjars [glob -nocomplain -dir $current_source_dir -type d -tail -- $tarjarglob] foreach tarjarpath $src_tarjars { dict set process_modules $tarjarpath [dict create -type tarjar] } - set src_modules [glob -nocomplain -dir $current_source_dir -type f -tail $fileglob] + set src_modules [glob -nocomplain -dir $current_source_dir -type f -tail -- $fileglob] foreach modulepath $src_modules { dict set process_modules $modulepath [dict create -type file] } diff --git a/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm b/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm index 9b1263e3..7fc43fa2 100644 --- a/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm +++ b/src/bootsupport/modules/punk/mix/commandset/project-0.1.0.tm @@ -118,7 +118,7 @@ namespace eval punk::mix::commandset::project { @cmd -name "punk::mix::commandset::project::new" -help\ "" @leaders -min 1 -max 1 - project -type string -help\ + project -type string -help\ "Project name or path. If just a name is given ... (todo)" @opts diff --git a/src/bootsupport/modules/punk/mix/util-0.1.0.tm b/src/bootsupport/modules/punk/mix/util-0.1.0.tm index 8dbe8feb..50289cab 100644 --- a/src/bootsupport/modules/punk/mix/util-0.1.0.tm +++ b/src/bootsupport/modules/punk/mix/util-0.1.0.tm @@ -48,6 +48,14 @@ namespace eval punk::mix::util { supports the same options (encoding, translation, eofchar) but also includes some additional handling for windows paths (if punk::winpath is available)." @opts + -n|--line-number -type none -help\ + "Each file line is preceded by its line number, starting at line 1." + -ranges -type indexset -default "1..end" -help\ + "comma delimited set of line ranges. + Restrict output to the specified line ranges of the file. Lines are numbered starting at 1. + For example, -ranges 1..5,10 would return lines 1 to 5 and line 10 of the file. + -ranges end-1..end would return the last two lines of the file. + -ranges end-4.. would return the last 5 lines of the file." -noredirect -type none -help\ "By default, fcat will follow windows shortcuts (.lnk files) and .fauxlink files if punk::winpath or punk::fauxlink is available. @@ -106,6 +114,12 @@ namespace eval punk::mix::util { if {$opt_noredirect} { set opts [dict remove $opts -noredirect] } + set do_ln [dict exists $received --line-number] + if {$do_ln} { + set opts [dict remove $opts --line-number] + } + set ranges [dict get $opts -ranges] + set opts [dict remove $opts -ranges] set finalpaths [list] @@ -152,7 +166,68 @@ namespace eval punk::mix::util { } set finalpaths $resolved_finalpaths } - fileutil::cat {*}$opts {*}$eopts {*}$finalpaths + + set lnc "" + set lnr "" + if {$ranges ni [list "0..end" "1..end" ".." "0.." "1.." "..end"]} { + set filedata [fileutil::cat {*}$opts {*}$eopts {*}$finalpaths] + set lines [split $filedata \n] + set linecount [llength $lines] + set w [string length $linecount] + set indices [punk::lib::indexset_resolve -base 1 $linecount $ranges] + set filedata "" + + if {$do_ln} { + foreach idx $indices { + append filedata "$lnc[format %${w}s $idx]$lnr [lindex $lines $idx-1]" \n + } + } else { + foreach idx $indices { + append filedata [lindex $lines $idx-1] \n + } + } + #no superfluous trailing newline allowed. see test::punk::ns test: corp_linecount_match + if {[string index $filedata end] eq "\n"} { + set filedata [string range $filedata 0 end-1] + } + } else { + #range was specified in a standard way to mean 'all lines' + if {$do_ln} { + set filedata [fileutil::cat {*}$opts {*}$eopts {*}$finalpaths] + set lines [split $filedata \n] + set linecount [llength $lines] + set w [string length $linecount] + set filedata "" + set n 1 + foreach ln $lines { + append filedata \n "$lnc[format %${w}s $n]$lnr $ln" + incr n + } + set filedata [string range $filedata 1 end] ;#strip leading newline + return $filedata + } else { + set filedata [fileutil::cat {*}$opts {*}$eopts {*}$finalpaths] + } + } + return $filedata + + #if {$opt_linenumber} { + # set filedata [fileutil::cat {*}$opts {*}$eopts {*}$finalpaths] + # set lines [split $filedata \n] + # set linecount [llength $lines] + # set w [string length $linecount] + # set filedata "" + # set n 1 + # set lnc "" + # set lnr "" + # foreach ln $lines { + # append filedata \n "$lnc[format %${w}s $n]$lnr $ln" + # incr n + # } + # set filedata [string range $filedata 1 end] ;#strip leading newline + # return $filedata + #} + #fileutil::cat {*}$opts {*}$eopts {*}$finalpaths } #---------------------------------------- diff --git a/src/bootsupport/modules/punk/mod-0.1.1.tm b/src/bootsupport/modules/punk/mod-0.1.1.tm index e09ff748..35559708 100644 --- a/src/bootsupport/modules/punk/mod-0.1.1.tm +++ b/src/bootsupport/modules/punk/mod-0.1.1.tm @@ -48,7 +48,7 @@ namespace eval punk::mod::cli { set namematches $appname set parts [split $appname -] } else { - set namematches [glob -nocomplain -dir $containerfolder -type d -tail ${appname}-*] + set namematches [glob -nocomplain -dir $containerfolder -type d -tail -- ${appname}-*] set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort? } foreach nm $namematches { @@ -95,7 +95,7 @@ namespace eval punk::mod::cli { if {[llength $apps] == 0} { if {[string first * $glob] <0 && [string first ? $glob] <0} { #no glob chars supplied - only launch if exact match for name part - set namematches [glob -nocomplain -dir $apps_folder -type d -tail ${glob}-*] + set namematches [glob -nocomplain -dir $apps_folder -type d -tail -- ${glob}-*] set namematches [lsort $namematches] ;#todo - -ascii? -dictionary? natsort? if {[llength $namematches] > 0} { set latest [lindex $namematches end] diff --git a/src/bootsupport/modules/punk/path-0.1.0.tm b/src/bootsupport/modules/punk/path-0.1.0.tm index 4527dbb2..8abba4fa 100644 --- a/src/bootsupport/modules/punk/path-0.1.0.tm +++ b/src/bootsupport/modules/punk/path-0.1.0.tm @@ -1208,7 +1208,7 @@ namespace eval punk::path { set files [list] set dir_state [directory_state $opt_glob_paths $opt_dir_match $callallbelow] if {[dict get $dir_state include_files]} { - if {[catch {glob -nocomplain -dir $opt_dir -type f {*}$tailglobs} matches]} { + if {[catch {glob -nocomplain -dir $opt_dir -type f -- {*}$tailglobs} matches]} { puts stderr "treefilenames error while listing files in dir $opt_dir\n $matches" set dirfiles [list] } else { diff --git a/src/bootsupport/modules/punk/repl-0.1.2.tm b/src/bootsupport/modules/punk/repl-0.1.2.tm index 2fb4236d..8d1e845d 100644 --- a/src/bootsupport/modules/punk/repl-0.1.2.tm +++ b/src/bootsupport/modules/punk/repl-0.1.2.tm @@ -158,7 +158,8 @@ namespace eval punk::repl::class { } } namespace eval punk::repl { - tsv::set repl runid 0 + #tsv::set repl runid 0 + tsv::incr repl runid 0 ;#ensure exists #todo - key on shell/subshell tsv::set repl runchunks-0 [list] ;#last_run_display diff --git a/src/bootsupport/modules/punkcheck-0.1.1.tm b/src/bootsupport/modules/punkcheck-0.1.1.tm index bdff666e..72e4a5ec 100644 --- a/src/bootsupport/modules/punkcheck-0.1.1.tm +++ b/src/bootsupport/modules/punkcheck-0.1.1.tm @@ -948,9 +948,9 @@ namespace eval punkcheck { #windows: file exist + file type = 2ms vs 500ms for 2x glob set floc [file dirname $fpath] set fname [file tail $fpath] - set file_set [glob -nocomplain -dir $floc -type f -tails $fname] - set dir_set [glob -nocomplain -dir $floc -type d -tails $fname] - set link_set [glob -nocomplain -dir $floc -type l -tails $fname] + set file_set [glob -nocomplain -dir $floc -type f -tails -- $fname] + set dir_set [glob -nocomplain -dir $floc -type d -tails -- $fname] + set link_set [glob -nocomplain -dir $floc -type l -tails -- $fname] if {[llength $file_set] == 0 && [llength $dir_set] == 0 && [llength $link_set] == 0} { #could also theoretically exist as less common types, b,c,p,s (block,char,pipe,socket) #- we don't expect them here - REVIEW - ever possible? @@ -1644,8 +1644,8 @@ namespace eval punkcheck { set sources_unchanged [list] - set candidate_list [glob -nocomplain -dir $current_source_dir -type f -tail $fileglob] - set hidden_candidate_list [glob -nocomplain -dir $current_source_dir -types {hidden f} -tail $fileglob] + set candidate_list [glob -nocomplain -dir $current_source_dir -type f -tail -- $fileglob] + set hidden_candidate_list [glob -nocomplain -dir $current_source_dir -types {hidden f} -tail -- $fileglob] foreach h $hidden_candidate_list { if {$h ni $candidate_list} { lappend candidate_list $h diff --git a/src/bootsupport/modules/shellrun-0.1.2.tm b/src/bootsupport/modules/shellrun-0.1.2.tm index 7a353961..07bca217 100644 --- a/src/bootsupport/modules/shellrun-0.1.2.tm +++ b/src/bootsupport/modules/shellrun-0.1.2.tm @@ -16,6 +16,8 @@ namespace eval shellrun { variable runout variable runerr + tsv::incr repl runid 0 ;#ensure exists + #do we need these? #variable punkout #variable punkerr diff --git a/src/bootsupport/tclpackages.toml b/src/bootsupport/tclpackages.toml index f9430fd8..4b48d81e 100644 --- a/src/bootsupport/tclpackages.toml +++ b/src/bootsupport/tclpackages.toml @@ -82,49 +82,65 @@ name = "patterncmd" source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules patternlib + name = "patternlib" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules patternpredator2 + name = "patternpredator2" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules patterncipher + name = "patterncipher" + source = "src/vendormodules" [[modules.tcl.allplatforms]] name = "platform" source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules promise - [[modules.tcl.allplatforms]] - #src/vendormodules sha1 + name = "promise" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules tomlish + name = "sha1" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules test::tomlish + name = "tomlish" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules dictn + name = "test::tomlish" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::adjust + name = "dictn" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::repeat + name = "textutil::adjust" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::split + name = "textutil::repeat" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::string + name = "textutil::split" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::tabify + name = "textutil::string" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::trim + name = "textutil::tabify" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules textutil::wcswidth + name = "textutil::trim" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - #src/vendormodules uuid + name = "textutil::wcswidth" + source = "src/vendormodules" [[modules.tcl.allplatforms]] - src/vendormodules uuid + name = "uuid" + source = "src/vendormodules" [[modules.tcl.allplatforms]] name = "argp" source = "modules" [[modules.tcl.allplatforms]] - #modules flagfilter + name = "flagfilter" + source = "modules" [[modules.tcl.allplatforms]] - #modules funcl + name = "funcl" + source = "modules" [[modules.tcl.allplatforms]] name = "natsort" source = "modules" @@ -133,9 +149,11 @@ source = "modules punk" requirements = ["0.1.1-"] [[modules.tcl.allplatforms]] - mod#ules punk::pipe + name = "punk::pipe" + source = "modules" [[modules.tcl.allplatforms]] - #modules punkapp + name = "punkapp" + source = "modules" [[modules.tcl.allplatforms]] name = "punkcheck" source = "modules punkcheck" @@ -144,126 +162,185 @@ name = "punkcheck::cli" source = "modules" [[modules.tcl.allplatforms]] - #modules punk::aliascore + name = "punk::aliascore" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::ansi::colourmap + name = "punk::ansi::colourmap" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::ansi + name = "punk::ansi" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::ansi::sauce + name = "punk::ansi::sauce" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::assertion + name = "punk::assertion" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::args + name = "punk::args" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::args::moduledoc::tclcore + name = "punk::args::moduledoc::tclcore" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::auto_exec + name = "punk::auto_exec" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::cap + name = "punk::cap" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::cap::handlers::caphandler + name = "punk::cap::handlers::caphandler" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::cap::handlers::scriptlibs + name = "punk::cap::handlers::scriptlibs" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::cap::handlers::templates + name = "punk::cap::handlers::templates" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::char + name = "punk::char" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::config + name = "punk::config" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::console + name = "punk::console" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::du + name = "punk::du" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::encmime + name = "punk::encmime" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::fileline + name = "punk::fileline" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::docgen + name = "punk::docgen" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::lib + name = "punk::lib" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::libunknown + name = "punk::libunknown" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix + name = "punk::mix" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::base + name = "punk::mix::base" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::cli + name = "punk::mix::cli" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::util + name = "punk::mix::util" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::templates + name = "punk::mix::templates" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::buildsuite + name = "punk::mix::commandset::buildsuite" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::debug + name = "punk::mix::commandset::debug" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::doc + name = "punk::mix::commandset::doc" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::layout + name = "punk::mix::commandset::layout" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::loadedlib + name = "punk::mix::commandset::loadedlib" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::module + name = "punk::mix::commandset::module" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::project + name = "punk::mix::commandset::project" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::repo + name = "punk::mix::commandset::repo" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mix::commandset::scriptwrap + name = "punk::mix::commandset::scriptwrap" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::mod + name = "punk::mod" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::nav::fs + name = "punk::nav::fs" + source = "modules" [[modules.tcl.allplatforms]] name = "punk::nav::ns" source = "modules" [[modules.tcl.allplatforms]] - #modules punk::ns + name = "punk::ns" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::overlay + name = "punk::overlay" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::path + name = "punk::path" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::packagepreference + name = "punk::packagepreference" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::repl + name = "punk::repl" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::repl::codethread + name = "punk::repl::codethread" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::repo + name = "punk::repo" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::tdl + name = "punk::tdl" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::trie + name = "punk::trie" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::unixywindows + name = "punk::unixywindows" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::zip + name = "punk::zip" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::winpath + name = "punk::winpath" + source = "modules" [[modules.tcl.allplatforms]] - #modules punk::winlnk + name = "punk::winlnk" + source = "modules" [[modules.tcl.allplatforms]] - #modules overtype + name = "overtype" + source = "modules" [[modules.tcl.allplatforms]] - #modules shellfilter + name = "shellfilter" + source = "modules" [[modules.tcl.allplatforms]] - #modules shellrun + name = "shellrun" + source = "modules" [[modules.tcl.allplatforms]] - #modules shellthread + name = "shellthread" + source = "modules" [[modules.tcl.allplatforms]] - #modules textblock + name = "textblock" + source = "modules" [[modules.tcl.allplatforms]] - #modules natsort + name = "natsort" + source = "modules" [[modules.tcl.allplatforms]] - #modules oolib + name = "oolib" + source = "modules" [[modules.tcl.allplatforms]] - #modules zipper + name = "zipper" + source = "modules" [[modules.tcl.allplatforms]] - #modules zzzload + name = "zzzload" + source = "modules" #-------------- [modules.tcl8] diff --git a/src/make.tcl b/src/make.tcl index 917cd4d7..1d74becb 100644 --- a/src/make.tcl +++ b/src/make.tcl @@ -1794,7 +1794,7 @@ if {$::punkboot::command eq "vendorupdate"} { #todo - check if requested_module has version extension and allow explicit versions instead of just latest #allow modulename-* literal in .config to request all versions - set pkgmatches [glob -nocomplain -dir $srclocation -tail [namespace tail $requested_module]-*] + set pkgmatches [glob -nocomplain -dir $srclocation -tail -- [namespace tail $requested_module]-*] #lsort won't sort version numbers properly e.g with -dictionary 0.1.1 comes before 0.1 if {![llength $pkgmatches]} { puts stderr "Missing local source for requested vendor module $requested_module - not found in $srclocation" @@ -1912,9 +1912,9 @@ if {$::punkboot::command eq "bootsupport"} { #bare lib.tm with no version is not valid. if {[string first - $modulematch] != -1} { #version or part thereof is specified. - set pkgmatches [glob -nocomplain -dir $srclocation -tail -type f [namespace tail $modulematch]*.tm] + set pkgmatches [glob -nocomplain -dir $srclocation -tail -type f -- [namespace tail $modulematch]*.tm] } else { - set pkgmatches [glob -nocomplain -dir $srclocation -tail -type f [namespace tail $modulematch]-*.tm] + set pkgmatches [glob -nocomplain -dir $srclocation -tail -type f -- [namespace tail $modulematch]-*.tm] } if {![llength $pkgmatches]} { puts stderr "Missing source for bootsupport module $modulematch - no matches in $srclocation"