Browse Source

Work on improved folder structure for cross-platform libs and modules

master
Julian Noble 1 month ago
parent
commit
332d6732a3
  1. 46
      src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  2. 30
      src/bootsupport/modules/punk/overlay-0.1.tm
  3. 62
      src/bootsupport/modules/shellfilter-0.2.tm
  4. 5
      src/bootsupport/modules/shellthread-1.6.1.tm
  5. 363
      src/make.tcl
  6. 2
      src/modules/punk/args/tclcore-999999.0a1.0.tm
  7. 42
      src/modules/punk/mix/cli-999999.0a1.0.tm
  8. 30
      src/modules/punk/overlay-0.1.tm
  9. 62
      src/modules/shellfilter-0.2.tm
  10. 5
      src/modules/shellthread-1.6.1.tm
  11. 363
      src/project_layouts/custom/_project/punk.basic/src/make.tcl
  12. 46
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  13. 30
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/overlay-0.1.tm
  14. 62
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellfilter-0.2.tm
  15. 5
      src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellthread-1.6.1.tm
  16. 363
      src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl
  17. 46
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm
  18. 30
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/overlay-0.1.tm
  19. 62
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellfilter-0.2.tm
  20. 5
      src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellthread-1.6.1.tm
  21. 363
      src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl
  22. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/allplatforms/README.md
  23. 9
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/freebsd-amd64/README.md
  24. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/linux-x86_64/README.md
  25. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/macosx-x86_64/README.md
  26. 8
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/msys-x86_64/README.md
  27. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/win32-x86_64/README.md
  28. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/allplatforms/README.md
  29. 9
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/freebsd-amd64/README.md
  30. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/linux-x86_64/README.md
  31. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/macosx-x86_64/README.md
  32. 8
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/msys-x86_64/README.md
  33. 7
      src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/win32-x86_64/README.md
  34. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/jpegtcl950.dll
  35. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libjpegtclstub950.a
  36. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libpngtclstub1638.a
  37. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libtifftclstub440.a
  38. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libtkimgstub1414.a
  39. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libzlibtclstub1213.a
  40. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/pkgIndex.tcl
  41. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/pngtcl1638.dll
  42. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tifftcl440.dll
  43. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimg1414.dll
  44. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgbmp1414.dll
  45. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgdted1414.dll
  46. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgflir1414.dll
  47. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimggif1414.dll
  48. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgico1414.dll
  49. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgjpeg1414.dll
  50. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpcx1414.dll
  51. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpixmap1414.dll
  52. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpng1414.dll
  53. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgppm1414.dll
  54. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgps1414.dll
  55. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgraw1414.dll
  56. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgsgi1414.dll
  57. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgsun1414.dll
  58. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgtga1414.dll
  59. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgtiff1414.dll
  60. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgwindow1414.dll
  61. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgxbm1414.dll
  62. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgxpm1414.dll
  63. 0
      src/vendorlib_tcl8/win32-x86_64/Img1.4.14/zlibtcl1213.dll
  64. 0
      src/vendorlib_tcl8/win32-x86_64/imgjp20.1/imgjp201.dll
  65. 0
      src/vendorlib_tcl8/win32-x86_64/imgjp20.1/pkgIndex.tcl
  66. 0
      src/vendorlib_tcl8/win32-x86_64/imgtools0.3/imgtools03.dll
  67. 0
      src/vendorlib_tcl8/win32-x86_64/imgtools0.3/pkgIndex.tcl
  68. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itcl.tcl
  69. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itcl423.dll
  70. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclConfig.sh
  71. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclHullCmds.tcl
  72. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclWidget.tcl
  73. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/libitclstub423.a
  74. 0
      src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/pkgIndex.tcl
  75. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Archetype.itk
  76. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Toplevel.itk
  77. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Widget.itk
  78. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/itk.tcl
  79. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/itk410.dll
  80. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/pkgIndex.tcl
  81. 0
      src/vendorlib_tcl8/win32-x86_64/itk4.1.0/tclIndex
  82. 0
      src/vendorlib_tcl8/win32-x86_64/sqlite3.40.0/pkgIndex.tcl
  83. 0
      src/vendorlib_tcl8/win32-x86_64/sqlite3.40.0/sqlite3400.dll
  84. 0
      src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/csv.tcl
  85. 0
      src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/pkgIndex.tcl
  86. 0
      src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/tclcsv23.dll
  87. 0
      src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/widgets.tcl
  88. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/d_config.tcl
  89. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/d_paths.tcl
  90. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/p_config.tcl
  91. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/p_paths.tcl
  92. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/pkgIndex.tcl
  93. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/aes/aes.tcl
  94. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/aes/pkgIndex.tcl
  95. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/S3.tcl
  96. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/pkgIndex.tcl
  97. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/xsxp.tcl
  98. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/asn/asn.tcl
  99. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/asn/pkgIndex.tcl
  100. 0
      src/vendorlib_tcl8/win32-x86_64/tcllib1.21/base32/base32.tcl
  101. Some files were not shown because too many files have changed in this diff Show More

46
src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -134,15 +134,20 @@ namespace eval punk::mix::cli {
}
}
#review - why can't we be anywhere in the project?
#for externally launched tclsh or punkshell running src/make.tcl the cwd
#needs to be such that make.tcl can find required bootsupport libraries without relying on auto_path or tcl::tm::list mechanisms.
#we can change directory during the run, and change back again afterwards.
#also - if no make.tcl - can we use the running shell's make.tcl ? (after prompting user?)
if {([file tail $sourcefolder] ne "src") || (![file exists $sourcefolder/make.tcl])} {
puts stderr "dev make must be run from src folder containing make.tcl - unable to proceed (cwd: [pwd])"
puts stderr "dev make must be run from src folder containing make.tcl or from within a project containing src/make.tcl - unable to proceed (cwd: [pwd])"
if {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src"
}
} else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} {
@ -177,20 +182,35 @@ namespace eval punk::mix::cli {
}
}
}
#cd $sourcefolder
#if {![catch {run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
# #todo - notify if exit because of timeout!
# puts stderr "exitinfo: $exitinfo"
# set exitcode [dict get $exitinfo exitcode]
#} else {
# puts stderr "Error unable to determine exitcode. err: $exitinfo"
# #cd $startdir
# return false
#}
#use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
} else {
puts stderr "Error unable to determine exitcode. err: $exitinfo"
#cd $startdir
#review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#review - on timeout what happens? (implemented in shellfilter)
# - if just stderr/stdout redirection channels closed - what happens with stdin?
# e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
try {
#cd $sourcefolder ;#dev paths can overide bootsupport modules
cd $project_base ;#bootsupport modules only
set exitinfo [run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args]
} trap {} {emsg eopts} {
puts stderr "Error, unable to determine exitcode. err: $emsg"
return false
} finally {
cd $startdir
}
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode"
return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath"
puts stdout "to:"
puts stdout "$podtree_copy"
#REVIEW
#todo - copy manually - renaming any files/folders with 999999.0a1.0 in the name to the applicable version
#(allow either shared files/folders or custom files/folders per package/version when in extracted form side by side)
file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} {

30
src/bootsupport/modules/punk/overlay-0.1.tm

@ -1,6 +1,7 @@
package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine
}
punk::args::define {
@id -id ::punk::overlay::import_commandset
@cmd -name punk::overlay::import_commandset\
-summary\
"Import commands into caller's namespace with optional prefix and separator."\
-help\
"Import commands that have been exported by another namespace into the caller's
namespace. Usually a prefix and optionally a separator should be used.
This is part of the punk::mix CLI commandset infrastructure - design in flux.
Todo - .toml configuration files for defining CLI configurations."
@values
prefix -type string
separator -type string -help\
"A string, usually punctuation, to separate the prefix and the command name
of the final imported command. The value \"::\" is disallowed in this context."
cmdnamespace -type string -help\
"Namespace from which to import commands. Commands are those that have been exported."
}
#load *exported* commands from cmdnamespace into caller's namespace - prefixing each command with $prefix
#Note: commandset may be imported by different CLIs with different bases *at the same time*
#so we don't make commands from the cli or its base available automatically (will generally require fully-qualified commands to use code from cli/base)
@ -94,6 +113,17 @@ tcl::namespace::eval ::punk::overlay {
if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'"
}
if {$prefix in $bad_seps} {
error "import_commandset invalid prefix '$prefix'"
}
if {"$prefix$separator" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
if {"[string index $prefix end][string index $separator 0]" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
#review - do we allow prefixes/separators such as a::b?
#namespace may or may not be a package
# allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

62
src/bootsupport/modules/shellfilter-0.2.tm

@ -2661,6 +2661,7 @@ namespace eval shellfilter {
#consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2846,9 +2847,9 @@ namespace eval shellfilter {
[chan configure $outchan -translation] \
[chan configure $errchan -translation] \
]
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#}
chan close $chan
#catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stderr
#}
if {[catch {chan configure $other}]} {
set $waitfor stderr
}
}
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
@ -3230,9 +3237,12 @@ namespace eval shellfilter {
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
}
}} $rdout $rderr $wrerr $outchan $errchan $read_proc_out_buffering $waitvar $outprefix $call_id $debug $debugname $command_pids]
@ -3240,9 +3250,28 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data
#e.g x hrs with no data(?)
#reset timeout when data detected.
after $timeout [string map [list %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
#reset timeout when data detected.
#review - stdin???
set ::shellfilter::shellcommandvars($call_id,timeoutid) [after $timeout [string map [list %cpids% $command_pids %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
if {[info exists ::shellfilter::shellcommandvars(%id%,exitcode)]} {
#killing the task (on windows) doesn't seem to work if done after we close the output channels
catch {puts stderr "timeout - closing.";flush stderr}
set command_pids "{%cpids%}"
if {[llength $command_pids]} {
set pid [lindex $command_pids 0]
if {$::tcl_platform(platform) eq "windows"} {
set killcmd [list [auto_execok taskkill] /F /PID $pid]
} else {
#set killcmd [list kill -9 $pid]
set killcmd [list kill -TERM $pid]
}
if {[catch {
exec {*}$killcmd
} errM]} {
puts stderr "Failed to kill '$pid': errMsg $errM"
flush stderr
}
}
if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% }
catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
}
set %w% "timeout"
}
}]
}]]
vwait $waitvar
after cancel $::shellfilter::shellcommandvars($call_id,timeoutid)
#puts stderr "waitvar:[set $waitvar]"
#flush stderr
#if {[set $waitvar] eq "timeout"} {
# #note: attempting to kill a process here (after channels closed) doesn't work (on windows at least)
# puts stderr "command_pids: $command_pids"
# flush stderr
#}
set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $exitcode]} {
puts stderr "Process exited with non-numeric code: $exitcode"
puts stderr "Process exited with non-numeric code: $exitcode closed_by:[set $waitvar]"
flush stderr
}
if {[string length $teefile]} {

5
src/bootsupport/modules/shellthread-1.6.1.tm

@ -694,7 +694,9 @@ namespace eval shellthread::manager {
#set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting
after $timeout [list set ::shellthread::waitfor]
#after $timeout [list set ::shellthread::waitfor]
#2025-07 timed-out untested review
set cancelid [after $timeout [list set ::shellthread::waitfor timed-out]]
set waiting_for [list]
set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1
break
} else {
after cancel $cancelid
lappend ended $::shellthread::waitfor
}
}

363
src/make.tcl

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib {
#for some purposes (whether a source folder is likely to have any useful content) we are interested in non dotfile/dotfolder immediate contents of a folder, but not whether a particular platform
#considers them hidden or not.
proc folder_nondotted_children {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_children error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_folders {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_folders error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types d *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_files {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_files error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types f $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
@ -154,6 +174,105 @@ namespace eval ::punkboot::lib {
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
#This is somewhat ugly - but we don't want to do any 'package require' operations at this stage
# even for something that is available in tcl_library.
#review
proc platform_generic {} {
#platform::generic - snipped straight from platform package
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}"
}
}
@ -181,17 +300,20 @@ set startdir [pwd]
# -------------------------------------------------------------------------------------
set bootsupport_module_paths [list]
set bootsupport_library_paths [list]
set this_platform_generic [punkboot::lib::platform_generic]
#we always create these lists in order of desired precedence.
# - this is the same order when adding to auto_path - but will need to be reversed when using tcl:tm::add
if {[file exists [file join $startdir src bootsupport]]} {
lappend bootsupport_module_paths [file join $startdir src bootsupport modules_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules]
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/allplatforms] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/$this_platform_generic] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/allplatforms]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/$this_platform_generic]
lappend bootsupport_library_paths [file join $startdir bootsupport lib]
}
set bootsupport_paths_exist 0
@ -218,7 +340,7 @@ if {[file tail $startdir] eq "src"} {
}
}
# -- -- --
foreach p [list $startdir/lib_tcl$::tclmajorv $startdir/lib $startdir/vendorlib_tcl$::tclmajorv $startdir/vendorlib] {
foreach p [list $startdir/lib_tcl$::tclmajorv/allplatforms $startdir/lib_tcl$::tclmajorv/$this_platform_generic $startdir/lib $startdir/vendorlib_tcl$::tclmajorv/allplatforms $startdir/vendorlib_tcl$::tclmajorv/$this_platform_generic $startdir/vendorlib] {
if {[file exists $p]} {
lappend sourcesupport_library_paths $p
}
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there..
set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] {
set contents [glob -nocomplain -dir $p -tail *]
#set contents [glob -nocomplain -dir $p -tail *]
set contents [punkboot::lib::folder_nondotted_children $p]
set readmeposn [lsearch -nocase $contents readme.md]
#don't assume 'ledit' available
set contents [lreplace $contents $readmeposn $readmeposn] ;#list unchanged if -1
if {[llength $contents]} {
set support_contents_exist 1
break
@ -890,7 +1016,7 @@ proc ::punkboot::get_display_missing_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set missing_rows [list]
set fields_blank_missing [dict create\
@ -938,7 +1064,7 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set broken_rows [list]
set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
}
return $broken_out
}
proc ::punkboot::define_global_ansi {pkg_availability} {
proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ?
#
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
set has_ansi [expr {[package provide punk::ansi] ne ""}]
global A
set A(RST) \x1b\[m
if {!$haspkg(punk::ansi)} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
if {!$has_ansi} {
if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(RST) ""
set A(HIGHLIGHT) ""
set A(BWHITE) ""
set A(OK) ""
set A(BAD) ""
set A(ERR) ""
} else {
set A(RST) \x1b\[m
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
}
} else {
namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a
}
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen
@ -1066,7 +1203,7 @@ proc ::punkboot::punkboot_gethelp {args} {
#gather details on what is missing so that the info is always reported in help output.
variable pkg_availability
global A
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
@ -1204,6 +1341,10 @@ set scriptfolder $::punkboot::scriptfolder
#first look for a project root (something under fossil or git revision control AND matches punk project folder structure)
#If that fails - just look for a 'project shaped folder' ie meets minimum requirements of /src /src/lib /src/modules /lib /modules
#test
if {[catch {punk::repo::find_project}]} {
puts stderr "punk::repo [package provide punk::repo]"
}
if {![string length [set projectroot [punk::repo::find_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $scriptfolder]]]} {
puts stderr "punkboot script unable to determine an approprite project root at or above the path '$scriptfolder' ensure the make script is within a project folder structure"
@ -1343,11 +1484,14 @@ if {$::punkboot::command eq "check"} {
exit 0
}
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} {
puts stdout "\x1b\[33m$errM\x1b\[m"
puts stdout "$A(BAD)$errM$A(RST)"
}
}
@ -1357,12 +1501,13 @@ if {$::punkboot::command eq "info"} {
puts stdout "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src
#todo show all but highlight the one that matches $this_platform_generic
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders {
puts stdout " src/$fld"
}
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders {
puts stdout " src/$fld"
@ -1471,9 +1616,12 @@ if {$::punkboot::command eq "vendorupdate"} {
set git_modules [list]
set fossil_modules [list]
set sourcefolder $projectroot/src
#todo vendor/lib
#todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
#todo platform folders under vendor/lib_tcl<v>
#todo platform folders under vendor/module_tcl<v>
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which ""
}
set vendor_config $sourcefolder/vendormodules$which/include_modules.config
set vendor_config $sourcefolder/vendormodules$which/include_modules.config ;#todo - change to toml
if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list
@ -1814,25 +1962,89 @@ if {$::punkboot::command in {project packages modules}} {
}
if {$::punkboot::command in {project packages libs}} {
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - vendorlib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
set source_lib_folder $sourcefolder/$lf
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "VENDORLIB: copying tcl-version neutral and platform neutral libraries from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib folder found."
}
#step2 - vendorlib_tcl<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm which ;#which is tcl8|tcl9 etc
set source_lib_folder $sourcefolder/vendorlib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
set which ""
puts stdout "$A(BAD)VENDORLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/vendorlib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mVENDORLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
}
if {![llength $vendorlibfolders]} {
puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
lappend projectlibfolders lib
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - src/lib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib]
foreach lf $projectlibfolders {
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "PROJECTLIB: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found."
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib folder found."
}
#step2 - src/lib_<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
foreach lf $projectlibfolders {
lassign [split $lf _] _vm which
set source_lib_folder $sourcefolder/lib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/lib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules libs}} {
@ -1915,39 +2169,6 @@ if {$::punkboot::command in {project packages modules libs}} {
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
lappend projectlibfolders lib
foreach lf $projectlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
} else {
set which ""
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "PROJECTLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib or src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version

2
src/modules/punk/args/tclcore-999999.0a1.0.tm

@ -2629,7 +2629,7 @@ tcl::namespace::eval punk::args::tclcore {
"Search for files which match the given patterns starting in the given ${$I}directory${$NI}.
This allows searching of directories whose name contains glob-sensitive characters
without the need to quote such characters explicitly. This option may not be used
in conjunction with ${$B}-path${$NI}, which is used to allow searching for complete file
in conjunction with ${$B}-path${$N}, which is used to allow searching for complete file
paths whose names may contain glob-sensitive characters."
-join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single

42
src/modules/punk/mix/cli-999999.0a1.0.tm

@ -134,15 +134,20 @@ namespace eval punk::mix::cli {
}
}
#review - why can't we be anywhere in the project?
#for externally launched tclsh or punkshell running src/make.tcl the cwd
#needs to be such that make.tcl can find required bootsupport libraries without relying on auto_path or tcl::tm::list mechanisms.
#we can change directory during the run, and change back again afterwards.
#also - if no make.tcl - can we use the running shell's make.tcl ? (after prompting user?)
if {([file tail $sourcefolder] ne "src") || (![file exists $sourcefolder/make.tcl])} {
puts stderr "dev make must be run from src folder containing make.tcl - unable to proceed (cwd: [pwd])"
puts stderr "dev make must be run from src folder containing make.tcl or from within a project containing src/make.tcl - unable to proceed (cwd: [pwd])"
if {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src"
}
} else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} {
@ -177,20 +182,35 @@ namespace eval punk::mix::cli {
}
}
}
#cd $sourcefolder
#if {![catch {run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
# #todo - notify if exit because of timeout!
# puts stderr "exitinfo: $exitinfo"
# set exitcode [dict get $exitinfo exitcode]
#} else {
# puts stderr "Error unable to determine exitcode. err: $exitinfo"
# #cd $startdir
# return false
#}
#use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
} else {
puts stderr "Error unable to determine exitcode. err: $exitinfo"
#cd $startdir
#review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#review - on timeout what happens? (implemented in shellfilter)
# - if just stderr/stdout redirection channels closed - what happens with stdin?
# e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
try {
#cd $sourcefolder ;#dev paths can overide bootsupport modules
cd $project_base ;#bootsupport modules only
set exitinfo [run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args]
} trap {} {emsg eopts} {
puts stderr "Error, unable to determine exitcode. err: $emsg"
return false
} finally {
cd $startdir
}
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode"
return false

30
src/modules/punk/overlay-0.1.tm

@ -1,6 +1,7 @@
package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine
}
punk::args::define {
@id -id ::punk::overlay::import_commandset
@cmd -name punk::overlay::import_commandset\
-summary\
"Import commands into caller's namespace with optional prefix and separator."\
-help\
"Import commands that have been exported by another namespace into the caller's
namespace. Usually a prefix and optionally a separator should be used.
This is part of the punk::mix CLI commandset infrastructure - design in flux.
Todo - .toml configuration files for defining CLI configurations."
@values
prefix -type string
separator -type string -help\
"A string, usually punctuation, to separate the prefix and the command name
of the final imported command. The value \"::\" is disallowed in this context."
cmdnamespace -type string -help\
"Namespace from which to import commands. Commands are those that have been exported."
}
#load *exported* commands from cmdnamespace into caller's namespace - prefixing each command with $prefix
#Note: commandset may be imported by different CLIs with different bases *at the same time*
#so we don't make commands from the cli or its base available automatically (will generally require fully-qualified commands to use code from cli/base)
@ -94,6 +113,17 @@ tcl::namespace::eval ::punk::overlay {
if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'"
}
if {$prefix in $bad_seps} {
error "import_commandset invalid prefix '$prefix'"
}
if {"$prefix$separator" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
if {"[string index $prefix end][string index $separator 0]" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
#review - do we allow prefixes/separators such as a::b?
#namespace may or may not be a package
# allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

62
src/modules/shellfilter-0.2.tm

@ -2661,6 +2661,7 @@ namespace eval shellfilter {
#consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2846,9 +2847,9 @@ namespace eval shellfilter {
[chan configure $outchan -translation] \
[chan configure $errchan -translation] \
]
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#}
chan close $chan
#catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stderr
#}
if {[catch {chan configure $other}]} {
set $waitfor stderr
}
}
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
@ -3230,9 +3237,12 @@ namespace eval shellfilter {
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
}
}} $rdout $rderr $wrerr $outchan $errchan $read_proc_out_buffering $waitvar $outprefix $call_id $debug $debugname $command_pids]
@ -3240,9 +3250,28 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data
#e.g x hrs with no data(?)
#reset timeout when data detected.
after $timeout [string map [list %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
#reset timeout when data detected.
#review - stdin???
set ::shellfilter::shellcommandvars($call_id,timeoutid) [after $timeout [string map [list %cpids% $command_pids %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
if {[info exists ::shellfilter::shellcommandvars(%id%,exitcode)]} {
#killing the task (on windows) doesn't seem to work if done after we close the output channels
catch {puts stderr "timeout - closing.";flush stderr}
set command_pids "{%cpids%}"
if {[llength $command_pids]} {
set pid [lindex $command_pids 0]
if {$::tcl_platform(platform) eq "windows"} {
set killcmd [list [auto_execok taskkill] /F /PID $pid]
} else {
#set killcmd [list kill -9 $pid]
set killcmd [list kill -TERM $pid]
}
if {[catch {
exec {*}$killcmd
} errM]} {
puts stderr "Failed to kill '$pid': errMsg $errM"
flush stderr
}
}
if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% }
catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
}
set %w% "timeout"
}
}]
}]]
vwait $waitvar
after cancel $::shellfilter::shellcommandvars($call_id,timeoutid)
#puts stderr "waitvar:[set $waitvar]"
#flush stderr
#if {[set $waitvar] eq "timeout"} {
# #note: attempting to kill a process here (after channels closed) doesn't work (on windows at least)
# puts stderr "command_pids: $command_pids"
# flush stderr
#}
set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $exitcode]} {
puts stderr "Process exited with non-numeric code: $exitcode"
puts stderr "Process exited with non-numeric code: $exitcode closed_by:[set $waitvar]"
flush stderr
}
if {[string length $teefile]} {

5
src/modules/shellthread-1.6.1.tm

@ -694,7 +694,9 @@ namespace eval shellthread::manager {
#set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting
after $timeout [list set ::shellthread::waitfor]
#after $timeout [list set ::shellthread::waitfor]
#2025-07 timed-out untested review
set cancelid [after $timeout [list set ::shellthread::waitfor timed-out]]
set waiting_for [list]
set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1
break
} else {
after cancel $cancelid
lappend ended $::shellthread::waitfor
}
}

363
src/project_layouts/custom/_project/punk.basic/src/make.tcl

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib {
#for some purposes (whether a source folder is likely to have any useful content) we are interested in non dotfile/dotfolder immediate contents of a folder, but not whether a particular platform
#considers them hidden or not.
proc folder_nondotted_children {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_children error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_folders {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_folders error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types d *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_files {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_files error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types f $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
@ -154,6 +174,105 @@ namespace eval ::punkboot::lib {
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
#This is somewhat ugly - but we don't want to do any 'package require' operations at this stage
# even for something that is available in tcl_library.
#review
proc platform_generic {} {
#platform::generic - snipped straight from platform package
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}"
}
}
@ -181,17 +300,20 @@ set startdir [pwd]
# -------------------------------------------------------------------------------------
set bootsupport_module_paths [list]
set bootsupport_library_paths [list]
set this_platform_generic [punkboot::lib::platform_generic]
#we always create these lists in order of desired precedence.
# - this is the same order when adding to auto_path - but will need to be reversed when using tcl:tm::add
if {[file exists [file join $startdir src bootsupport]]} {
lappend bootsupport_module_paths [file join $startdir src bootsupport modules_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules]
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/allplatforms] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/$this_platform_generic] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/allplatforms]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/$this_platform_generic]
lappend bootsupport_library_paths [file join $startdir bootsupport lib]
}
set bootsupport_paths_exist 0
@ -218,7 +340,7 @@ if {[file tail $startdir] eq "src"} {
}
}
# -- -- --
foreach p [list $startdir/lib_tcl$::tclmajorv $startdir/lib $startdir/vendorlib_tcl$::tclmajorv $startdir/vendorlib] {
foreach p [list $startdir/lib_tcl$::tclmajorv/allplatforms $startdir/lib_tcl$::tclmajorv/$this_platform_generic $startdir/lib $startdir/vendorlib_tcl$::tclmajorv/allplatforms $startdir/vendorlib_tcl$::tclmajorv/$this_platform_generic $startdir/vendorlib] {
if {[file exists $p]} {
lappend sourcesupport_library_paths $p
}
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there..
set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] {
set contents [glob -nocomplain -dir $p -tail *]
#set contents [glob -nocomplain -dir $p -tail *]
set contents [punkboot::lib::folder_nondotted_children $p]
set readmeposn [lsearch -nocase $contents readme.md]
#don't assume 'ledit' available
set contents [lreplace $contents $readmeposn $readmeposn] ;#list unchanged if -1
if {[llength $contents]} {
set support_contents_exist 1
break
@ -890,7 +1016,7 @@ proc ::punkboot::get_display_missing_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set missing_rows [list]
set fields_blank_missing [dict create\
@ -938,7 +1064,7 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set broken_rows [list]
set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
}
return $broken_out
}
proc ::punkboot::define_global_ansi {pkg_availability} {
proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ?
#
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
set has_ansi [expr {[package provide punk::ansi] ne ""}]
global A
set A(RST) \x1b\[m
if {!$haspkg(punk::ansi)} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
if {!$has_ansi} {
if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(RST) ""
set A(HIGHLIGHT) ""
set A(BWHITE) ""
set A(OK) ""
set A(BAD) ""
set A(ERR) ""
} else {
set A(RST) \x1b\[m
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
}
} else {
namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a
}
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen
@ -1066,7 +1203,7 @@ proc ::punkboot::punkboot_gethelp {args} {
#gather details on what is missing so that the info is always reported in help output.
variable pkg_availability
global A
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
@ -1204,6 +1341,10 @@ set scriptfolder $::punkboot::scriptfolder
#first look for a project root (something under fossil or git revision control AND matches punk project folder structure)
#If that fails - just look for a 'project shaped folder' ie meets minimum requirements of /src /src/lib /src/modules /lib /modules
#test
if {[catch {punk::repo::find_project}]} {
puts stderr "punk::repo [package provide punk::repo]"
}
if {![string length [set projectroot [punk::repo::find_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $scriptfolder]]]} {
puts stderr "punkboot script unable to determine an approprite project root at or above the path '$scriptfolder' ensure the make script is within a project folder structure"
@ -1343,11 +1484,14 @@ if {$::punkboot::command eq "check"} {
exit 0
}
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} {
puts stdout "\x1b\[33m$errM\x1b\[m"
puts stdout "$A(BAD)$errM$A(RST)"
}
}
@ -1357,12 +1501,13 @@ if {$::punkboot::command eq "info"} {
puts stdout "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src
#todo show all but highlight the one that matches $this_platform_generic
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders {
puts stdout " src/$fld"
}
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders {
puts stdout " src/$fld"
@ -1471,9 +1616,12 @@ if {$::punkboot::command eq "vendorupdate"} {
set git_modules [list]
set fossil_modules [list]
set sourcefolder $projectroot/src
#todo vendor/lib
#todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
#todo platform folders under vendor/lib_tcl<v>
#todo platform folders under vendor/module_tcl<v>
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which ""
}
set vendor_config $sourcefolder/vendormodules$which/include_modules.config
set vendor_config $sourcefolder/vendormodules$which/include_modules.config ;#todo - change to toml
if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list
@ -1814,25 +1962,89 @@ if {$::punkboot::command in {project packages modules}} {
}
if {$::punkboot::command in {project packages libs}} {
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - vendorlib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
set source_lib_folder $sourcefolder/$lf
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "VENDORLIB: copying tcl-version neutral and platform neutral libraries from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib folder found."
}
#step2 - vendorlib_tcl<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm which ;#which is tcl8|tcl9 etc
set source_lib_folder $sourcefolder/vendorlib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
set which ""
puts stdout "$A(BAD)VENDORLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/vendorlib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mVENDORLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
}
if {![llength $vendorlibfolders]} {
puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
lappend projectlibfolders lib
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - src/lib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib]
foreach lf $projectlibfolders {
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "PROJECTLIB: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found."
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib folder found."
}
#step2 - src/lib_<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
foreach lf $projectlibfolders {
lassign [split $lf _] _vm which
set source_lib_folder $sourcefolder/lib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/lib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules libs}} {
@ -1915,39 +2169,6 @@ if {$::punkboot::command in {project packages modules libs}} {
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
lappend projectlibfolders lib
foreach lf $projectlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
} else {
set which ""
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "PROJECTLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib or src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version

46
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -134,15 +134,20 @@ namespace eval punk::mix::cli {
}
}
#review - why can't we be anywhere in the project?
#for externally launched tclsh or punkshell running src/make.tcl the cwd
#needs to be such that make.tcl can find required bootsupport libraries without relying on auto_path or tcl::tm::list mechanisms.
#we can change directory during the run, and change back again afterwards.
#also - if no make.tcl - can we use the running shell's make.tcl ? (after prompting user?)
if {([file tail $sourcefolder] ne "src") || (![file exists $sourcefolder/make.tcl])} {
puts stderr "dev make must be run from src folder containing make.tcl - unable to proceed (cwd: [pwd])"
puts stderr "dev make must be run from src folder containing make.tcl or from within a project containing src/make.tcl - unable to proceed (cwd: [pwd])"
if {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src"
}
} else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} {
@ -177,20 +182,35 @@ namespace eval punk::mix::cli {
}
}
}
#cd $sourcefolder
#if {![catch {run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
# #todo - notify if exit because of timeout!
# puts stderr "exitinfo: $exitinfo"
# set exitcode [dict get $exitinfo exitcode]
#} else {
# puts stderr "Error unable to determine exitcode. err: $exitinfo"
# #cd $startdir
# return false
#}
#use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
} else {
puts stderr "Error unable to determine exitcode. err: $exitinfo"
#cd $startdir
#review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#review - on timeout what happens? (implemented in shellfilter)
# - if just stderr/stdout redirection channels closed - what happens with stdin?
# e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
try {
#cd $sourcefolder ;#dev paths can overide bootsupport modules
cd $project_base ;#bootsupport modules only
set exitinfo [run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args]
} trap {} {emsg eopts} {
puts stderr "Error, unable to determine exitcode. err: $emsg"
return false
} finally {
cd $startdir
}
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode"
return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath"
puts stdout "to:"
puts stdout "$podtree_copy"
#REVIEW
#todo - copy manually - renaming any files/folders with 999999.0a1.0 in the name to the applicable version
#(allow either shared files/folders or custom files/folders per package/version when in extracted form side by side)
file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} {

30
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/punk/overlay-0.1.tm

@ -1,6 +1,7 @@
package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine
}
punk::args::define {
@id -id ::punk::overlay::import_commandset
@cmd -name punk::overlay::import_commandset\
-summary\
"Import commands into caller's namespace with optional prefix and separator."\
-help\
"Import commands that have been exported by another namespace into the caller's
namespace. Usually a prefix and optionally a separator should be used.
This is part of the punk::mix CLI commandset infrastructure - design in flux.
Todo - .toml configuration files for defining CLI configurations."
@values
prefix -type string
separator -type string -help\
"A string, usually punctuation, to separate the prefix and the command name
of the final imported command. The value \"::\" is disallowed in this context."
cmdnamespace -type string -help\
"Namespace from which to import commands. Commands are those that have been exported."
}
#load *exported* commands from cmdnamespace into caller's namespace - prefixing each command with $prefix
#Note: commandset may be imported by different CLIs with different bases *at the same time*
#so we don't make commands from the cli or its base available automatically (will generally require fully-qualified commands to use code from cli/base)
@ -94,6 +113,17 @@ tcl::namespace::eval ::punk::overlay {
if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'"
}
if {$prefix in $bad_seps} {
error "import_commandset invalid prefix '$prefix'"
}
if {"$prefix$separator" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
if {"[string index $prefix end][string index $separator 0]" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
#review - do we allow prefixes/separators such as a::b?
#namespace may or may not be a package
# allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

62
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellfilter-0.2.tm

@ -2661,6 +2661,7 @@ namespace eval shellfilter {
#consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2846,9 +2847,9 @@ namespace eval shellfilter {
[chan configure $outchan -translation] \
[chan configure $errchan -translation] \
]
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#}
chan close $chan
#catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stderr
#}
if {[catch {chan configure $other}]} {
set $waitfor stderr
}
}
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
@ -3230,9 +3237,12 @@ namespace eval shellfilter {
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
}
}} $rdout $rderr $wrerr $outchan $errchan $read_proc_out_buffering $waitvar $outprefix $call_id $debug $debugname $command_pids]
@ -3240,9 +3250,28 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data
#e.g x hrs with no data(?)
#reset timeout when data detected.
after $timeout [string map [list %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
#reset timeout when data detected.
#review - stdin???
set ::shellfilter::shellcommandvars($call_id,timeoutid) [after $timeout [string map [list %cpids% $command_pids %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
if {[info exists ::shellfilter::shellcommandvars(%id%,exitcode)]} {
#killing the task (on windows) doesn't seem to work if done after we close the output channels
catch {puts stderr "timeout - closing.";flush stderr}
set command_pids "{%cpids%}"
if {[llength $command_pids]} {
set pid [lindex $command_pids 0]
if {$::tcl_platform(platform) eq "windows"} {
set killcmd [list [auto_execok taskkill] /F /PID $pid]
} else {
#set killcmd [list kill -9 $pid]
set killcmd [list kill -TERM $pid]
}
if {[catch {
exec {*}$killcmd
} errM]} {
puts stderr "Failed to kill '$pid': errMsg $errM"
flush stderr
}
}
if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% }
catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
}
set %w% "timeout"
}
}]
}]]
vwait $waitvar
after cancel $::shellfilter::shellcommandvars($call_id,timeoutid)
#puts stderr "waitvar:[set $waitvar]"
#flush stderr
#if {[set $waitvar] eq "timeout"} {
# #note: attempting to kill a process here (after channels closed) doesn't work (on windows at least)
# puts stderr "command_pids: $command_pids"
# flush stderr
#}
set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $exitcode]} {
puts stderr "Process exited with non-numeric code: $exitcode"
puts stderr "Process exited with non-numeric code: $exitcode closed_by:[set $waitvar]"
flush stderr
}
if {[string length $teefile]} {

5
src/project_layouts/custom/_project/punk.project-0.1/src/bootsupport/modules/shellthread-1.6.1.tm

@ -694,7 +694,9 @@ namespace eval shellthread::manager {
#set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting
after $timeout [list set ::shellthread::waitfor]
#after $timeout [list set ::shellthread::waitfor]
#2025-07 timed-out untested review
set cancelid [after $timeout [list set ::shellthread::waitfor timed-out]]
set waiting_for [list]
set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1
break
} else {
after cancel $cancelid
lappend ended $::shellthread::waitfor
}
}

363
src/project_layouts/custom/_project/punk.project-0.1/src/make.tcl

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib {
#for some purposes (whether a source folder is likely to have any useful content) we are interested in non dotfile/dotfolder immediate contents of a folder, but not whether a particular platform
#considers them hidden or not.
proc folder_nondotted_children {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_children error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_folders {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_folders error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types d *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_files {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_files error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types f $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
@ -154,6 +174,105 @@ namespace eval ::punkboot::lib {
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
#This is somewhat ugly - but we don't want to do any 'package require' operations at this stage
# even for something that is available in tcl_library.
#review
proc platform_generic {} {
#platform::generic - snipped straight from platform package
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}"
}
}
@ -181,17 +300,20 @@ set startdir [pwd]
# -------------------------------------------------------------------------------------
set bootsupport_module_paths [list]
set bootsupport_library_paths [list]
set this_platform_generic [punkboot::lib::platform_generic]
#we always create these lists in order of desired precedence.
# - this is the same order when adding to auto_path - but will need to be reversed when using tcl:tm::add
if {[file exists [file join $startdir src bootsupport]]} {
lappend bootsupport_module_paths [file join $startdir src bootsupport modules_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules]
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/allplatforms] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/$this_platform_generic] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/allplatforms]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/$this_platform_generic]
lappend bootsupport_library_paths [file join $startdir bootsupport lib]
}
set bootsupport_paths_exist 0
@ -218,7 +340,7 @@ if {[file tail $startdir] eq "src"} {
}
}
# -- -- --
foreach p [list $startdir/lib_tcl$::tclmajorv $startdir/lib $startdir/vendorlib_tcl$::tclmajorv $startdir/vendorlib] {
foreach p [list $startdir/lib_tcl$::tclmajorv/allplatforms $startdir/lib_tcl$::tclmajorv/$this_platform_generic $startdir/lib $startdir/vendorlib_tcl$::tclmajorv/allplatforms $startdir/vendorlib_tcl$::tclmajorv/$this_platform_generic $startdir/vendorlib] {
if {[file exists $p]} {
lappend sourcesupport_library_paths $p
}
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there..
set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] {
set contents [glob -nocomplain -dir $p -tail *]
#set contents [glob -nocomplain -dir $p -tail *]
set contents [punkboot::lib::folder_nondotted_children $p]
set readmeposn [lsearch -nocase $contents readme.md]
#don't assume 'ledit' available
set contents [lreplace $contents $readmeposn $readmeposn] ;#list unchanged if -1
if {[llength $contents]} {
set support_contents_exist 1
break
@ -890,7 +1016,7 @@ proc ::punkboot::get_display_missing_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set missing_rows [list]
set fields_blank_missing [dict create\
@ -938,7 +1064,7 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set broken_rows [list]
set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
}
return $broken_out
}
proc ::punkboot::define_global_ansi {pkg_availability} {
proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ?
#
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
set has_ansi [expr {[package provide punk::ansi] ne ""}]
global A
set A(RST) \x1b\[m
if {!$haspkg(punk::ansi)} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
if {!$has_ansi} {
if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(RST) ""
set A(HIGHLIGHT) ""
set A(BWHITE) ""
set A(OK) ""
set A(BAD) ""
set A(ERR) ""
} else {
set A(RST) \x1b\[m
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
}
} else {
namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a
}
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen
@ -1066,7 +1203,7 @@ proc ::punkboot::punkboot_gethelp {args} {
#gather details on what is missing so that the info is always reported in help output.
variable pkg_availability
global A
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
@ -1204,6 +1341,10 @@ set scriptfolder $::punkboot::scriptfolder
#first look for a project root (something under fossil or git revision control AND matches punk project folder structure)
#If that fails - just look for a 'project shaped folder' ie meets minimum requirements of /src /src/lib /src/modules /lib /modules
#test
if {[catch {punk::repo::find_project}]} {
puts stderr "punk::repo [package provide punk::repo]"
}
if {![string length [set projectroot [punk::repo::find_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $scriptfolder]]]} {
puts stderr "punkboot script unable to determine an approprite project root at or above the path '$scriptfolder' ensure the make script is within a project folder structure"
@ -1343,11 +1484,14 @@ if {$::punkboot::command eq "check"} {
exit 0
}
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} {
puts stdout "\x1b\[33m$errM\x1b\[m"
puts stdout "$A(BAD)$errM$A(RST)"
}
}
@ -1357,12 +1501,13 @@ if {$::punkboot::command eq "info"} {
puts stdout "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src
#todo show all but highlight the one that matches $this_platform_generic
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders {
puts stdout " src/$fld"
}
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders {
puts stdout " src/$fld"
@ -1471,9 +1616,12 @@ if {$::punkboot::command eq "vendorupdate"} {
set git_modules [list]
set fossil_modules [list]
set sourcefolder $projectroot/src
#todo vendor/lib
#todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
#todo platform folders under vendor/lib_tcl<v>
#todo platform folders under vendor/module_tcl<v>
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which ""
}
set vendor_config $sourcefolder/vendormodules$which/include_modules.config
set vendor_config $sourcefolder/vendormodules$which/include_modules.config ;#todo - change to toml
if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list
@ -1814,25 +1962,89 @@ if {$::punkboot::command in {project packages modules}} {
}
if {$::punkboot::command in {project packages libs}} {
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - vendorlib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
set source_lib_folder $sourcefolder/$lf
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "VENDORLIB: copying tcl-version neutral and platform neutral libraries from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib folder found."
}
#step2 - vendorlib_tcl<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm which ;#which is tcl8|tcl9 etc
set source_lib_folder $sourcefolder/vendorlib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
set which ""
puts stdout "$A(BAD)VENDORLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/vendorlib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mVENDORLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
}
if {![llength $vendorlibfolders]} {
puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
lappend projectlibfolders lib
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - src/lib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib]
foreach lf $projectlibfolders {
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "PROJECTLIB: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found."
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib folder found."
}
#step2 - src/lib_<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
foreach lf $projectlibfolders {
lassign [split $lf _] _vm which
set source_lib_folder $sourcefolder/lib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/lib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules libs}} {
@ -1915,39 +2169,6 @@ if {$::punkboot::command in {project packages modules libs}} {
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
lappend projectlibfolders lib
foreach lf $projectlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
} else {
set which ""
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "PROJECTLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib or src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version

46
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/mix/cli-0.3.1.tm

@ -134,15 +134,20 @@ namespace eval punk::mix::cli {
}
}
#review - why can't we be anywhere in the project?
#for externally launched tclsh or punkshell running src/make.tcl the cwd
#needs to be such that make.tcl can find required bootsupport libraries without relying on auto_path or tcl::tm::list mechanisms.
#we can change directory during the run, and change back again afterwards.
#also - if no make.tcl - can we use the running shell's make.tcl ? (after prompting user?)
if {([file tail $sourcefolder] ne "src") || (![file exists $sourcefolder/make.tcl])} {
puts stderr "dev make must be run from src folder containing make.tcl - unable to proceed (cwd: [pwd])"
puts stderr "dev make must be run from src folder containing make.tcl or from within a project containing src/make.tcl - unable to proceed (cwd: [pwd])"
if {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src"
}
} else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} {
@ -177,20 +182,35 @@ namespace eval punk::mix::cli {
}
}
}
#cd $sourcefolder
#if {![catch {run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
# #todo - notify if exit because of timeout!
# puts stderr "exitinfo: $exitinfo"
# set exitcode [dict get $exitinfo exitcode]
#} else {
# puts stderr "Error unable to determine exitcode. err: $exitinfo"
# #cd $startdir
# return false
#}
#use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} {
#todo - notify if exit because of timeout!
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
} else {
puts stderr "Error unable to determine exitcode. err: $exitinfo"
#cd $startdir
#review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#review - on timeout what happens? (implemented in shellfilter)
# - if just stderr/stdout redirection channels closed - what happens with stdin?
# e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
try {
#cd $sourcefolder ;#dev paths can overide bootsupport modules
cd $project_base ;#bootsupport modules only
set exitinfo [run --timeout=150000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args]
} trap {} {emsg eopts} {
puts stderr "Error, unable to determine exitcode. err: $emsg"
return false
} finally {
cd $startdir
}
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode"
return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath"
puts stdout "to:"
puts stdout "$podtree_copy"
#REVIEW
#todo - copy manually - renaming any files/folders with 999999.0a1.0 in the name to the applicable version
#(allow either shared files/folders or custom files/folders per package/version when in extracted form side by side)
file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} {

30
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/punk/overlay-0.1.tm

@ -1,6 +1,7 @@
package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine
}
punk::args::define {
@id -id ::punk::overlay::import_commandset
@cmd -name punk::overlay::import_commandset\
-summary\
"Import commands into caller's namespace with optional prefix and separator."\
-help\
"Import commands that have been exported by another namespace into the caller's
namespace. Usually a prefix and optionally a separator should be used.
This is part of the punk::mix CLI commandset infrastructure - design in flux.
Todo - .toml configuration files for defining CLI configurations."
@values
prefix -type string
separator -type string -help\
"A string, usually punctuation, to separate the prefix and the command name
of the final imported command. The value \"::\" is disallowed in this context."
cmdnamespace -type string -help\
"Namespace from which to import commands. Commands are those that have been exported."
}
#load *exported* commands from cmdnamespace into caller's namespace - prefixing each command with $prefix
#Note: commandset may be imported by different CLIs with different bases *at the same time*
#so we don't make commands from the cli or its base available automatically (will generally require fully-qualified commands to use code from cli/base)
@ -94,6 +113,17 @@ tcl::namespace::eval ::punk::overlay {
if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'"
}
if {$prefix in $bad_seps} {
error "import_commandset invalid prefix '$prefix'"
}
if {"$prefix$separator" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
if {"[string index $prefix end][string index $separator 0]" in $bad_seps} {
error "import_commandset invalid prefix/separator combination '$prefix$separator'"
}
#review - do we allow prefixes/separators such as a::b?
#namespace may or may not be a package
# allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

62
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellfilter-0.2.tm

@ -2661,6 +2661,7 @@ namespace eval shellfilter {
#consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2846,9 +2847,9 @@ namespace eval shellfilter {
[chan configure $outchan -translation] \
[chan configure $errchan -translation] \
]
chan configure $inchan -buffering $inbuffering -blocking 0 ;#we are setting up a readable handler for this - so non-blocking ok
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#}
chan close $chan
#catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stderr
#}
if {[catch {chan configure $other}]} {
set $waitfor stderr
}
}
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
@ -3230,9 +3237,12 @@ namespace eval shellfilter {
}
catch {chan close $wrerr}
if {$other ni [chan names]} {
#if {$other ni [chan names]} {
# set $waitfor stdout
#}
if {[catch {chan configure $other}]} {
set $waitfor stdout
}
}
}
}} $rdout $rderr $wrerr $outchan $errchan $read_proc_out_buffering $waitvar $outprefix $call_id $debug $debugname $command_pids]
@ -3240,9 +3250,28 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data
#e.g x hrs with no data(?)
#reset timeout when data detected.
after $timeout [string map [list %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
#reset timeout when data detected.
#review - stdin???
set ::shellfilter::shellcommandvars($call_id,timeoutid) [after $timeout [string map [list %cpids% $command_pids %w% $waitvar %id% $call_id %wrerr% $wrerr %rdout% $rdout %rderr% $rderr %debug% $debug %debugname% $debugname] {
if {[info exists ::shellfilter::shellcommandvars(%id%,exitcode)]} {
#killing the task (on windows) doesn't seem to work if done after we close the output channels
catch {puts stderr "timeout - closing.";flush stderr}
set command_pids "{%cpids%}"
if {[llength $command_pids]} {
set pid [lindex $command_pids 0]
if {$::tcl_platform(platform) eq "windows"} {
set killcmd [list [auto_execok taskkill] /F /PID $pid]
} else {
#set killcmd [list kill -9 $pid]
set killcmd [list kill -TERM $pid]
}
if {[catch {
exec {*}$killcmd
} errM]} {
puts stderr "Failed to kill '$pid': errMsg $errM"
flush stderr
}
}
if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% }
catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
}
set %w% "timeout"
}
}]
}]]
vwait $waitvar
after cancel $::shellfilter::shellcommandvars($call_id,timeoutid)
#puts stderr "waitvar:[set $waitvar]"
#flush stderr
#if {[set $waitvar] eq "timeout"} {
# #note: attempting to kill a process here (after channels closed) doesn't work (on windows at least)
# puts stderr "command_pids: $command_pids"
# flush stderr
#}
set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $exitcode]} {
puts stderr "Process exited with non-numeric code: $exitcode"
puts stderr "Process exited with non-numeric code: $exitcode closed_by:[set $waitvar]"
flush stderr
}
if {[string length $teefile]} {

5
src/project_layouts/custom/_project/punk.shell-0.1/src/bootsupport/modules/shellthread-1.6.1.tm

@ -694,7 +694,9 @@ namespace eval shellthread::manager {
#set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting
after $timeout [list set ::shellthread::waitfor]
#after $timeout [list set ::shellthread::waitfor]
#2025-07 timed-out untested review
set cancelid [after $timeout [list set ::shellthread::waitfor timed-out]]
set waiting_for [list]
set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1
break
} else {
after cancel $cancelid
lappend ended $::shellthread::waitfor
}
}

363
src/project_layouts/custom/_project/punk.shell-0.1/src/make.tcl

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib {
#for some purposes (whether a source folder is likely to have any useful content) we are interested in non dotfile/dotfolder immediate contents of a folder, but not whether a particular platform
#considers them hidden or not.
proc folder_nondotted_children {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_children error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_folders {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_folders error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types d *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc folder_nondotted_files {folder} {
if {![file isdirectory $folder]} {error "punkboot::lib::folder_nondotted_files error. Supplied folder 'folder' is not a directory"}
set contents [glob -nocomplain -dir $folder -types f $folder *]
#some platforms (windows) return dotted entries with *, although most don't
return [lsearch -all -inline -not $contents .*]
}
proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} {
@ -154,6 +174,105 @@ namespace eval ::punkboot::lib {
error "tm_version_required_canonical should have already returned a canonicalised versionspec - or produced an error with reason before this point"
}
}
#This is somewhat ugly - but we don't want to do any 'package require' operations at this stage
# even for something that is available in tcl_library.
#review
proc platform_generic {} {
#platform::generic - snipped straight from platform package
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}"
}
}
@ -181,17 +300,20 @@ set startdir [pwd]
# -------------------------------------------------------------------------------------
set bootsupport_module_paths [list]
set bootsupport_library_paths [list]
set this_platform_generic [punkboot::lib::platform_generic]
#we always create these lists in order of desired precedence.
# - this is the same order when adding to auto_path - but will need to be reversed when using tcl:tm::add
if {[file exists [file join $startdir src bootsupport]]} {
lappend bootsupport_module_paths [file join $startdir src bootsupport modules_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules]
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/allplatforms] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib_tcl$::tclmajorv/$this_platform_generic] ;#more version-specific pkgs slightly higher in precedence order
lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/allplatforms]
lappend bootsupport_library_paths [file join $startdir bootsupport lib_tcl$::tclmajorv/$this_platform_generic]
lappend bootsupport_library_paths [file join $startdir bootsupport lib]
}
set bootsupport_paths_exist 0
@ -218,7 +340,7 @@ if {[file tail $startdir] eq "src"} {
}
}
# -- -- --
foreach p [list $startdir/lib_tcl$::tclmajorv $startdir/lib $startdir/vendorlib_tcl$::tclmajorv $startdir/vendorlib] {
foreach p [list $startdir/lib_tcl$::tclmajorv/allplatforms $startdir/lib_tcl$::tclmajorv/$this_platform_generic $startdir/lib $startdir/vendorlib_tcl$::tclmajorv/allplatforms $startdir/vendorlib_tcl$::tclmajorv/$this_platform_generic $startdir/vendorlib] {
if {[file exists $p]} {
lappend sourcesupport_library_paths $p
}
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there..
set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] {
set contents [glob -nocomplain -dir $p -tail *]
#set contents [glob -nocomplain -dir $p -tail *]
set contents [punkboot::lib::folder_nondotted_children $p]
set readmeposn [lsearch -nocase $contents readme.md]
#don't assume 'ledit' available
set contents [lreplace $contents $readmeposn $readmeposn] ;#list unchanged if -1
if {[llength $contents]} {
set support_contents_exist 1
break
@ -890,7 +1016,7 @@ proc ::punkboot::get_display_missing_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set missing_rows [list]
set fields_blank_missing [dict create\
@ -938,7 +1064,7 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A
if {![array size A]} {
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
}
set broken_rows [list]
set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
}
return $broken_out
}
proc ::punkboot::define_global_ansi {pkg_availability} {
proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ?
#
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
set has_ansi [expr {[package provide punk::ansi] ne ""}]
global A
set A(RST) \x1b\[m
if {!$haspkg(punk::ansi)} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
if {!$has_ansi} {
if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(RST) ""
set A(HIGHLIGHT) ""
set A(BWHITE) ""
set A(OK) ""
set A(BAD) ""
set A(ERR) ""
} else {
set A(RST) \x1b\[m
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow
set A(BWHITE) \x1b\[97m ;#brightwhite
set A(OK) \x1b\[92m ;#brightgreen
set A(BAD) \x1b\[33m ;# orange
set A(ERR) \x1b\[31m ;# red
}
} else {
namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a
}
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen
@ -1066,7 +1203,7 @@ proc ::punkboot::punkboot_gethelp {args} {
#gather details on what is missing so that the info is always reported in help output.
variable pkg_availability
global A
punkboot::define_global_ansi $pkg_availability
punkboot::define_global_ansi
array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
@ -1204,6 +1341,10 @@ set scriptfolder $::punkboot::scriptfolder
#first look for a project root (something under fossil or git revision control AND matches punk project folder structure)
#If that fails - just look for a 'project shaped folder' ie meets minimum requirements of /src /src/lib /src/modules /lib /modules
#test
if {[catch {punk::repo::find_project}]} {
puts stderr "punk::repo [package provide punk::repo]"
}
if {![string length [set projectroot [punk::repo::find_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $scriptfolder]]]} {
puts stderr "punkboot script unable to determine an approprite project root at or above the path '$scriptfolder' ensure the make script is within a project folder structure"
@ -1343,11 +1484,14 @@ if {$::punkboot::command eq "check"} {
exit 0
}
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} {
puts stdout "\x1b\[33m$errM\x1b\[m"
puts stdout "$A(BAD)$errM$A(RST)"
}
}
@ -1357,12 +1501,13 @@ if {$::punkboot::command eq "info"} {
puts stdout "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src
#todo show all but highlight the one that matches $this_platform_generic
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders {
puts stdout " src/$fld"
}
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders {
puts stdout " src/$fld"
@ -1471,9 +1616,12 @@ if {$::punkboot::command eq "vendorupdate"} {
set git_modules [list]
set fossil_modules [list]
set sourcefolder $projectroot/src
#todo vendor/lib
#todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
#todo platform folders under vendor/lib_tcl<v>
#todo platform folders under vendor/module_tcl<v>
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which ""
}
set vendor_config $sourcefolder/vendormodules$which/include_modules.config
set vendor_config $sourcefolder/vendormodules$which/include_modules.config ;#todo - change to toml
if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list
@ -1814,25 +1962,89 @@ if {$::punkboot::command in {project packages modules}} {
}
if {$::punkboot::command in {project packages libs}} {
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib vendorlib_tcl*]
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - vendorlib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
set source_lib_folder $sourcefolder/$lf
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "VENDORLIB: copying tcl-version neutral and platform neutral libraries from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib folder found."
}
#step2 - vendorlib_tcl<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*]
foreach lf $vendorlibfolders {
lassign [split $lf _] _vm which ;#which is tcl8|tcl9 etc
set source_lib_folder $sourcefolder/vendorlib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
set which ""
puts stdout "$A(BAD)VENDORLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/vendorlib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "VENDORLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mVENDORLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
}
if {![llength $vendorlibfolders]} {
puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
lappend projectlibfolders lib
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
#step1 - src/lib - pkgIndex.tcl based libraries that are platform neutral and tcl-majorversion neutral
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib]
foreach lf $projectlibfolders {
set target_lib_folder $projectroot/lib
file mkdir $target_lib_folder
puts stdout "PROJECTLIB: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $vendorlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found."
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib folder found."
}
#step2 - src/lib_<majorv> - platform-neutral in 'allplatforms' folder + platform specific based on current platform
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
foreach lf $projectlibfolders {
lassign [split $lf _] _vm which
set source_lib_folder $sourcefolder/lib_$which/allplatforms
set target_lib_folder $projectroot/lib_$which/allplatforms
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform neutral folder found at $source_lib_folder$A(RST)"
}
#this_platform_generic
set source_lib_folder $sourcefolder/lib_$which/$this_platform_generic
set target_lib_folder $projectroot/lib_$which/$this_platform_generic
if {[file exists $source_lib_folder] && [llength [punkboot::lib::folder_nondotted_folders $source_lib_folder]]} {
file mkdir $target_lib_folder
puts stdout "PROJECTLIB_$which: copying from $source_lib_folder to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $source_lib_folder $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} else {
puts stdout "$A(BAD)mPROJECTLIB_$which - no platform specific folder found at $source_lib_folder$A(RST)"
}
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules libs}} {
@ -1915,39 +2169,6 @@ if {$::punkboot::command in {project packages modules libs}} {
}
}
if {$::punkboot::command in {project packages libs}} {
########################################################
set projectlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails lib_tcl*]
lappend projectlibfolders lib
foreach lf $projectlibfolders {
lassign [split $lf _] _vm tclx
if {$tclx ne ""} {
set which _$tclx
} else {
set which ""
}
set target_lib_folder $projectroot/lib$which
file mkdir $projectroot/lib$which
#exclude README.md from source folder - but only the root one
#-antiglob_paths takes relative patterns e.g
# */test.txt will only match test.txt exactly one level deep.
# */*/*.foo will match any path ending in .foo that is exactly 2 levels deep.
# **/test.txt will match at any level below the root (but not in the root)
set antipaths [list\
README.md\
]
puts stdout "PROJECTLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)"
set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\
-progresschannel stdout\
]
puts stdout [punkcheck::summarize_install_resultdict $resultdict]
}
if {![llength $projectlibfolders]} {
puts stderr "PROJECTLIB: No src/lib or src/lib_tcl* folder found."
}
}
if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/allplatforms/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries which are independent of platform.
This folder should not contain binaries.

9
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/freebsd-amd64/README.md vendored

@ -0,0 +1,9 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the freebsd-amd64 platform.
Note that amd64 is equivalent to x86_64 in this context.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/linux-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the linux-x86_64 platform.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/macosx-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the macosx-x86_64 platform.

8
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/msys-x86_64/README.md vendored

@ -0,0 +1,8 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the msys-x86_64 platform.
This is a somewhat unix-like environment running on windows.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl8/win32-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the win32-x86_64 platform.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/allplatforms/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries which are independent of platform.
This folder should not contain binaries.

9
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/freebsd-amd64/README.md vendored

@ -0,0 +1,9 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the freebsd-amd64 platform.
Note that amd64 is equivalent to x86_64 in this context.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/linux-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the linux-x86_64 platform.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/macosx-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the macosx-x86_64 platform.

8
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/msys-x86_64/README.md vendored

@ -0,0 +1,8 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the msys-x86_64 platform.
This is a somewhat unix-like environment running on windows.

7
src/project_layouts/vendor/punk/project-0.1/src/vendorlib_tcl9/win32-x86_64/README.md vendored

@ -0,0 +1,7 @@
Tcl library dependencies
pkgIndex.tcl based libraries specific to the win32-x86_64 platform.

0
src/vendorlib_tcl8/Img1.4.14/jpegtcl950.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/jpegtcl950.dll

0
src/vendorlib_tcl8/Img1.4.14/libjpegtclstub950.a → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libjpegtclstub950.a

0
src/vendorlib_tcl8/Img1.4.14/libpngtclstub1638.a → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libpngtclstub1638.a

0
src/vendorlib_tcl8/Img1.4.14/libtifftclstub440.a → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libtifftclstub440.a

0
src/vendorlib_tcl8/Img1.4.14/libtkimgstub1414.a → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libtkimgstub1414.a

0
src/vendorlib_tcl8/Img1.4.14/libzlibtclstub1213.a → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/libzlibtclstub1213.a

0
src/vendorlib_tcl8/Img1.4.14/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/pkgIndex.tcl

0
src/vendorlib_tcl8/Img1.4.14/pngtcl1638.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/pngtcl1638.dll

0
src/vendorlib_tcl8/Img1.4.14/tifftcl440.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tifftcl440.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimg1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimg1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgbmp1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgbmp1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgdted1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgdted1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgflir1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgflir1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimggif1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimggif1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgico1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgico1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgjpeg1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgjpeg1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgpcx1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpcx1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgpixmap1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpixmap1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgpng1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgpng1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgppm1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgppm1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgps1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgps1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgraw1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgraw1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgsgi1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgsgi1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgsun1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgsun1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgtga1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgtga1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgtiff1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgtiff1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgwindow1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgwindow1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgxbm1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgxbm1414.dll

0
src/vendorlib_tcl8/Img1.4.14/tkimgxpm1414.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/tkimgxpm1414.dll

0
src/vendorlib_tcl8/Img1.4.14/zlibtcl1213.dll → src/vendorlib_tcl8/win32-x86_64/Img1.4.14/zlibtcl1213.dll

0
src/vendorlib_tcl8/imgjp20.1/imgjp201.dll → src/vendorlib_tcl8/win32-x86_64/imgjp20.1/imgjp201.dll

0
src/vendorlib_tcl8/imgjp20.1/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/imgjp20.1/pkgIndex.tcl

0
src/vendorlib_tcl8/imgtools0.3/imgtools03.dll → src/vendorlib_tcl8/win32-x86_64/imgtools0.3/imgtools03.dll

0
src/vendorlib_tcl8/imgtools0.3/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/imgtools0.3/pkgIndex.tcl

0
src/vendorlib_tcl8/itcl4.2.3/itcl.tcl → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itcl.tcl

0
src/vendorlib_tcl8/itcl4.2.3/itcl423.dll → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itcl423.dll

0
src/vendorlib_tcl8/itcl4.2.3/itclConfig.sh → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclConfig.sh

0
src/vendorlib_tcl8/itcl4.2.3/itclHullCmds.tcl → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclHullCmds.tcl

0
src/vendorlib_tcl8/itcl4.2.3/itclWidget.tcl → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/itclWidget.tcl

0
src/vendorlib_tcl8/itcl4.2.3/libitclstub423.a → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/libitclstub423.a

0
src/vendorlib_tcl8/itcl4.2.3/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/itcl4.2.3/pkgIndex.tcl

0
src/vendorlib_tcl8/itk4.1.0/Archetype.itk → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Archetype.itk

0
src/vendorlib_tcl8/itk4.1.0/Toplevel.itk → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Toplevel.itk

0
src/vendorlib_tcl8/itk4.1.0/Widget.itk → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/Widget.itk

0
src/vendorlib_tcl8/itk4.1.0/itk.tcl → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/itk.tcl

0
src/vendorlib_tcl8/itk4.1.0/itk410.dll → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/itk410.dll

0
src/vendorlib_tcl8/itk4.1.0/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/pkgIndex.tcl

0
src/vendorlib_tcl8/itk4.1.0/tclIndex → src/vendorlib_tcl8/win32-x86_64/itk4.1.0/tclIndex

0
src/vendorlib_tcl8/sqlite3.40.0/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/sqlite3.40.0/pkgIndex.tcl

0
src/vendorlib_tcl8/sqlite3.40.0/sqlite3400.dll → src/vendorlib_tcl8/win32-x86_64/sqlite3.40.0/sqlite3400.dll

0
src/vendorlib_tcl8/tclcsv2.3/csv.tcl → src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/csv.tcl

0
src/vendorlib_tcl8/tclcsv2.3/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/pkgIndex.tcl

0
src/vendorlib_tcl8/tclcsv2.3/tclcsv23.dll → src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/tclcsv23.dll

0
src/vendorlib_tcl8/tclcsv2.3/widgets.tcl → src/vendorlib_tcl8/win32-x86_64/tclcsv2.3/widgets.tcl

0
src/vendorlib_tcl8/tcllib1.21/0compatibility/d_config.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/d_config.tcl

0
src/vendorlib_tcl8/tcllib1.21/0compatibility/d_paths.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/d_paths.tcl

0
src/vendorlib_tcl8/tcllib1.21/0compatibility/p_config.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/p_config.tcl

0
src/vendorlib_tcl8/tcllib1.21/0compatibility/p_paths.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/p_paths.tcl

0
src/vendorlib_tcl8/tcllib1.21/0compatibility/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/0compatibility/pkgIndex.tcl

0
src/vendorlib_tcl8/tcllib1.21/aes/aes.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/aes/aes.tcl

0
src/vendorlib_tcl8/tcllib1.21/aes/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/aes/pkgIndex.tcl

0
src/vendorlib_tcl8/tcllib1.21/amazon-s3/S3.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/S3.tcl

0
src/vendorlib_tcl8/tcllib1.21/amazon-s3/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/pkgIndex.tcl

0
src/vendorlib_tcl8/tcllib1.21/amazon-s3/xsxp.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/amazon-s3/xsxp.tcl

0
src/vendorlib_tcl8/tcllib1.21/asn/asn.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/asn/asn.tcl

0
src/vendorlib_tcl8/tcllib1.21/asn/pkgIndex.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/asn/pkgIndex.tcl

0
src/vendorlib_tcl8/tcllib1.21/base32/base32.tcl → src/vendorlib_tcl8/win32-x86_64/tcllib1.21/base32/base32.tcl

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save