Browse Source

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

master
Julian Noble 4 months 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. 50
      src/bootsupport/modules/shellfilter-0.2.tm
  4. 5
      src/bootsupport/modules/shellthread-1.6.1.tm
  5. 361
      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. 50
      src/modules/shellfilter-0.2.tm
  10. 5
      src/modules/shellthread-1.6.1.tm
  11. 361
      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. 50
      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. 361
      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. 50
      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. 361
      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?) #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])} { 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 {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} { if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src" puts stderr "Try cd to $project_base/src"
} }
} else { } else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} { if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile." puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} { 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 #use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { #review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#todo - notify if exit because of timeout! #review - on timeout what happens? (implemented in shellfilter)
puts stderr "exitinfo: $exitinfo" # - if just stderr/stdout redirection channels closed - what happens with stdin?
set exitcode [dict get $exitinfo exitcode] # e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
} else { try {
puts stderr "Error unable to determine exitcode. err: $exitinfo" #cd $sourcefolder ;#dev paths can overide bootsupport modules
#cd $startdir 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 return false
} finally {
cd $startdir
} }
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} { if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode" puts stderr "FAILED with exitcode $exitcode"
return false return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath" puts stdout "$current_source_dir/$modpath"
puts stdout "to:" puts stdout "to:"
puts stdout "$podtree_copy" 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 file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} { if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} { 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::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay { tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend #based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine 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 #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* #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) #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} { if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'" 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 #namespace may or may not be a package
# allow with or without leading :: # allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} { if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

50
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. #consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ; set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) "" set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar) set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} { if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'" ::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#} #}
chan close $chan chan close $chan
#catch {chan close $wrerr} #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 set $waitfor stderr
} }
} }
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code set ::shellfilter::shellcommandvars($call_id,exitcode) $code
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
} }
@ -3230,7 +3237,10 @@ namespace eval shellfilter {
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
@ -3241,8 +3251,27 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data #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(?) #e.g x hrs with no data(?)
#reset timeout when data detected. #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] { #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)]} { 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 ""} { if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% } catch { chan close %wrerr% }
catch { chan close %rdout%} catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
} }
set %w% "timeout" set %w% "timeout"
} }
}] }]]
vwait $waitvar 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)] set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $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 flush stderr
} }
if {[string length $teefile]} { 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 #set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out] #after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting 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 waiting_for [list]
set ended [list] set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1 set timedout 1
break break
} else { } else {
after cancel $cancelid
lappend ended $::shellthread::waitfor lappend ended $::shellthread::waitfor
} }
} }

361
src/make.tcl

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib { 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} { proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare' #Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} { 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" 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_module_paths [list]
set bootsupport_library_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. #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 # - 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]]} { 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_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else { } else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv] lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir bootsupport lib]
} }
set bootsupport_paths_exist 0 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]} { if {[file exists $p]} {
lappend sourcesupport_library_paths $p lappend sourcesupport_library_paths $p
} }
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there.. #very basic test there is something there..
set support_contents_exist 0 set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] { 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]} { if {[llength $contents]} {
set support_contents_exist 1 set support_contents_exist 1
break 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set missing_rows [list] set missing_rows [list]
set fields_blank_missing [dict create\ 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set broken_rows [list] set broken_rows [list]
set fields_blank_broken [dict create\ set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
} }
return $broken_out return $broken_out
} }
proc ::punkboot::define_global_ansi {pkg_availability} { proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ? #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 global A
set A(RST) \x1b\[m if {!$has_ansi} {
if {!$haspkg(punk::ansi)} { if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow set A(RST) ""
set A(BWHITE) \x1b\[97m ;#brightwhite set A(HIGHLIGHT) ""
set A(OK) \x1b\[92m ;#brightgreen set A(BWHITE) ""
set A(BAD) \x1b\[33m ;# orange set A(OK) ""
set A(ERR) \x1b\[31m ;# red 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 { } else {
namespace eval ::punkboot { namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a namespace import ::punk::ansi::a+ ::punk::ansi::a
} }
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow] set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite] set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen 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. #gather details on what is missing so that the info is always reported in help output.
variable pkg_availability variable pkg_availability
global A 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)} ... 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) #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 #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_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $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" 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 exit 0
} }
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements { dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} { 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 "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot" puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src 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 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])" puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders { foreach fld $vendorlibfolders {
puts stdout " src/$fld" puts stdout " src/$fld"
} }
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])" puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders { foreach fld $vendormodulefolders {
puts stdout " src/$fld" puts stdout " src/$fld"
@ -1473,7 +1618,10 @@ if {$::punkboot::command eq "vendorupdate"} {
set sourcefolder $projectroot/src set sourcefolder $projectroot/src
#todo vendor/lib #todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*] 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*] set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules #lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders { foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which "" 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]} { if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list 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}} { 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 { foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx set source_lib_folder $sourcefolder/$lf
if {$tclx ne ""} { set target_lib_folder $projectroot/lib
set which _$tclx 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 { } 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 if {![llength $vendorlibfolders]} {
#-antiglob_paths takes relative patterns e.g puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
# */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\ if {$::punkboot::command in {project packages libs}} {
README.md\ ########################################################
] lappend projectlibfolders lib
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)" #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\ set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\ -overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\ -antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
] ]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }
if {![llength $vendorlibfolders]} { if {![llength $projectlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found." 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}} { 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}} { if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version #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}. "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 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 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." paths whose names may contain glob-sensitive characters."
-join -type none -help\ -join -type none -help\
"The remaining pattern arguments, after option processing, are treated as a single "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?) #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])} { 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 {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} { if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src" puts stderr "Try cd to $project_base/src"
} }
} else { } else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} { if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile." puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} { 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 #use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { #review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#todo - notify if exit because of timeout! #review - on timeout what happens? (implemented in shellfilter)
puts stderr "exitinfo: $exitinfo" # - if just stderr/stdout redirection channels closed - what happens with stdin?
set exitcode [dict get $exitinfo exitcode] # e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
} else { try {
puts stderr "Error unable to determine exitcode. err: $exitinfo" #cd $sourcefolder ;#dev paths can overide bootsupport modules
#cd $startdir 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 return false
} finally {
cd $startdir
} }
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} { if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode" puts stderr "FAILED with exitcode $exitcode"
return false return false

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

@ -1,6 +1,7 @@
package require punk::mix::util package require punk::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay { tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend #based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine 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 #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* #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) #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} { if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'" 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 #namespace may or may not be a package
# allow with or without leading :: # allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} { if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

50
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. #consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ; set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) "" set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar) set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} { if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'" ::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#} #}
chan close $chan chan close $chan
#catch {chan close $wrerr} #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 set $waitfor stderr
} }
} }
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code set ::shellfilter::shellcommandvars($call_id,exitcode) $code
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
} }
@ -3230,7 +3237,10 @@ namespace eval shellfilter {
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
@ -3241,8 +3251,27 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data #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(?) #e.g x hrs with no data(?)
#reset timeout when data detected. #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] { #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)]} { 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 ""} { if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% } catch { chan close %wrerr% }
catch { chan close %rdout%} catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
} }
set %w% "timeout" set %w% "timeout"
} }
}] }]]
vwait $waitvar 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)] set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $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 flush stderr
} }
if {[string length $teefile]} { 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 #set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out] #after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting 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 waiting_for [list]
set ended [list] set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1 set timedout 1
break break
} else { } else {
after cancel $cancelid
lappend ended $::shellthread::waitfor lappend ended $::shellthread::waitfor
} }
} }

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

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib { 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} { proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare' #Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} { 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" 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_module_paths [list]
set bootsupport_library_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. #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 # - 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]]} { 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_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else { } else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv] lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir bootsupport lib]
} }
set bootsupport_paths_exist 0 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]} { if {[file exists $p]} {
lappend sourcesupport_library_paths $p lappend sourcesupport_library_paths $p
} }
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there.. #very basic test there is something there..
set support_contents_exist 0 set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] { 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]} { if {[llength $contents]} {
set support_contents_exist 1 set support_contents_exist 1
break 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set missing_rows [list] set missing_rows [list]
set fields_blank_missing [dict create\ 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set broken_rows [list] set broken_rows [list]
set fields_blank_broken [dict create\ set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
} }
return $broken_out return $broken_out
} }
proc ::punkboot::define_global_ansi {pkg_availability} { proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ? #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 global A
set A(RST) \x1b\[m if {!$has_ansi} {
if {!$haspkg(punk::ansi)} { if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow set A(RST) ""
set A(BWHITE) \x1b\[97m ;#brightwhite set A(HIGHLIGHT) ""
set A(OK) \x1b\[92m ;#brightgreen set A(BWHITE) ""
set A(BAD) \x1b\[33m ;# orange set A(OK) ""
set A(ERR) \x1b\[31m ;# red 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 { } else {
namespace eval ::punkboot { namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a namespace import ::punk::ansi::a+ ::punk::ansi::a
} }
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow] set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite] set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen 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. #gather details on what is missing so that the info is always reported in help output.
variable pkg_availability variable pkg_availability
global A 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)} ... 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) #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 #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_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $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" 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 exit 0
} }
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements { dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} { 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 "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot" puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src 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 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])" puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders { foreach fld $vendorlibfolders {
puts stdout " src/$fld" puts stdout " src/$fld"
} }
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])" puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders { foreach fld $vendormodulefolders {
puts stdout " src/$fld" puts stdout " src/$fld"
@ -1473,7 +1618,10 @@ if {$::punkboot::command eq "vendorupdate"} {
set sourcefolder $projectroot/src set sourcefolder $projectroot/src
#todo vendor/lib #todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*] 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*] set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules #lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders { foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which "" 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]} { if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list 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}} { 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 { foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx set source_lib_folder $sourcefolder/$lf
if {$tclx ne ""} { set target_lib_folder $projectroot/lib
set which _$tclx 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 { } 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 if {![llength $vendorlibfolders]} {
#-antiglob_paths takes relative patterns e.g puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
# */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\ if {$::punkboot::command in {project packages libs}} {
README.md\ ########################################################
] lappend projectlibfolders lib
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)" #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\ set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\ -overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\ -antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
] ]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }
if {![llength $vendorlibfolders]} { if {![llength $projectlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found." 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}} { 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}} { if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version #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?) #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])} { 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 {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} { if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src" puts stderr "Try cd to $project_base/src"
} }
} else { } else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} { if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile." puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} { 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 #use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { #review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#todo - notify if exit because of timeout! #review - on timeout what happens? (implemented in shellfilter)
puts stderr "exitinfo: $exitinfo" # - if just stderr/stdout redirection channels closed - what happens with stdin?
set exitcode [dict get $exitinfo exitcode] # e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
} else { try {
puts stderr "Error unable to determine exitcode. err: $exitinfo" #cd $sourcefolder ;#dev paths can overide bootsupport modules
#cd $startdir 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 return false
} finally {
cd $startdir
} }
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} { if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode" puts stderr "FAILED with exitcode $exitcode"
return false return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath" puts stdout "$current_source_dir/$modpath"
puts stdout "to:" puts stdout "to:"
puts stdout "$podtree_copy" 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 file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} { if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} { 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::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay { tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend #based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine 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 #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* #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) #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} { if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'" 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 #namespace may or may not be a package
# allow with or without leading :: # allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} { if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

50
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. #consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ; set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) "" set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar) set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} { if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'" ::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#} #}
chan close $chan chan close $chan
#catch {chan close $wrerr} #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 set $waitfor stderr
} }
} }
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code set ::shellfilter::shellcommandvars($call_id,exitcode) $code
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
} }
@ -3230,7 +3237,10 @@ namespace eval shellfilter {
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
@ -3241,8 +3251,27 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data #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(?) #e.g x hrs with no data(?)
#reset timeout when data detected. #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] { #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)]} { 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 ""} { if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% } catch { chan close %wrerr% }
catch { chan close %rdout%} catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
} }
set %w% "timeout" set %w% "timeout"
} }
}] }]]
vwait $waitvar 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)] set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $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 flush stderr
} }
if {[string length $teefile]} { 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 #set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out] #after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting 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 waiting_for [list]
set ended [list] set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1 set timedout 1
break break
} else { } else {
after cancel $cancelid
lappend ended $::shellthread::waitfor lappend ended $::shellthread::waitfor
} }
} }

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

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib { 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} { proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare' #Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} { 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" 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_module_paths [list]
set bootsupport_library_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. #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 # - 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]]} { 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_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else { } else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv] lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir bootsupport lib]
} }
set bootsupport_paths_exist 0 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]} { if {[file exists $p]} {
lappend sourcesupport_library_paths $p lappend sourcesupport_library_paths $p
} }
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there.. #very basic test there is something there..
set support_contents_exist 0 set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] { 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]} { if {[llength $contents]} {
set support_contents_exist 1 set support_contents_exist 1
break 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set missing_rows [list] set missing_rows [list]
set fields_blank_missing [dict create\ 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set broken_rows [list] set broken_rows [list]
set fields_blank_broken [dict create\ set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
} }
return $broken_out return $broken_out
} }
proc ::punkboot::define_global_ansi {pkg_availability} { proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ? #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 global A
set A(RST) \x1b\[m if {!$has_ansi} {
if {!$haspkg(punk::ansi)} { if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow set A(RST) ""
set A(BWHITE) \x1b\[97m ;#brightwhite set A(HIGHLIGHT) ""
set A(OK) \x1b\[92m ;#brightgreen set A(BWHITE) ""
set A(BAD) \x1b\[33m ;# orange set A(OK) ""
set A(ERR) \x1b\[31m ;# red 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 { } else {
namespace eval ::punkboot { namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a namespace import ::punk::ansi::a+ ::punk::ansi::a
} }
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow] set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite] set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen 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. #gather details on what is missing so that the info is always reported in help output.
variable pkg_availability variable pkg_availability
global A 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)} ... 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) #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 #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_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $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" 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 exit 0
} }
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements { dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} { 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 "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot" puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src 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 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])" puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders { foreach fld $vendorlibfolders {
puts stdout " src/$fld" puts stdout " src/$fld"
} }
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])" puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders { foreach fld $vendormodulefolders {
puts stdout " src/$fld" puts stdout " src/$fld"
@ -1473,7 +1618,10 @@ if {$::punkboot::command eq "vendorupdate"} {
set sourcefolder $projectroot/src set sourcefolder $projectroot/src
#todo vendor/lib #todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*] 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*] set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules #lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders { foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which "" 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]} { if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list 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}} { 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 { foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx set source_lib_folder $sourcefolder/$lf
if {$tclx ne ""} { set target_lib_folder $projectroot/lib
set which _$tclx 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 { } 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 if {![llength $vendorlibfolders]} {
#-antiglob_paths takes relative patterns e.g puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
# */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\ if {$::punkboot::command in {project packages libs}} {
README.md\ ########################################################
] lappend projectlibfolders lib
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)" #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\ set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\ -overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\ -antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
] ]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }
if {![llength $vendorlibfolders]} { if {![llength $projectlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found." 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}} { 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}} { if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version #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?) #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])} { 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 {[string length $project_base]} {
if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} { if {[file exists $project_base/src] && [string tolower [pwd]] ne [string tolower $project_base/src]} {
puts stderr "Try cd to $project_base/src" puts stderr "Try cd to $project_base/src"
} }
} else { } else {
#review - intended usecase?
if {[file exists $startdir/Makefile]} { if {[file exists $startdir/Makefile]} {
puts stdout "A Makefile exists at $startdir/Makefile." puts stdout "A Makefile exists at $startdir/Makefile."
if {"windows" eq $::tcl_platform(platform)} { 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 #use run so that stdout visible as it goes
if {![catch {run --timeout=55000 -debug [info nameofexecutable] $sourcefolder/make.tcl {*}$args} exitinfo]} { #review - is setting a timeout here useful? It will just be annoying if the project really does need the time.
#todo - notify if exit because of timeout! #review - on timeout what happens? (implemented in shellfilter)
puts stderr "exitinfo: $exitinfo" # - if just stderr/stdout redirection channels closed - what happens with stdin?
set exitcode [dict get $exitinfo exitcode] # e.g 'for dev make shell' - we just get no further responses but stdin still consuming keystrokes?
} else { try {
puts stderr "Error unable to determine exitcode. err: $exitinfo" #cd $sourcefolder ;#dev paths can overide bootsupport modules
#cd $startdir 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 return false
} finally {
cd $startdir
} }
puts stderr "exitinfo: $exitinfo"
set exitcode [dict get $exitinfo exitcode]
#cd $startdir
if {$exitcode != 0} { if {$exitcode != 0} {
puts stderr "FAILED with exitcode $exitcode" puts stderr "FAILED with exitcode $exitcode"
return false return false
@ -661,11 +681,7 @@ namespace eval punk::mix::cli {
puts stdout "$current_source_dir/$modpath" puts stdout "$current_source_dir/$modpath"
puts stdout "to:" puts stdout "to:"
puts stdout "$podtree_copy" 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 file copy $current_source_dir/$modpath $podtree_copy
if {$tmfile_versionsegment eq $magicversion} { if {$tmfile_versionsegment eq $magicversion} {
set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm set tmfile $buildfolder/#modpod-$basename-$module_build_version/$basename-$magicversion.tm
if {[file exists $tmfile]} { 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::mix::util
package require punk::args
tcl::namespace::eval ::punk::overlay { tcl::namespace::eval ::punk::overlay {
#based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend #based *loosely* on: wiki.tcl-lang.org/page/ensemble+extend
@ -80,6 +81,24 @@ tcl::namespace::eval ::punk::overlay {
return $routine 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 #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* #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) #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} { if {$separator in $bad_seps} {
error "import_commandset invalid separator '$separator'" 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 #namespace may or may not be a package
# allow with or without leading :: # allow with or without leading ::
if {[tcl::string::range $cmdnamespace 0 1] eq "::"} { if {[tcl::string::range $cmdnamespace 0 1] eq "::"} {

50
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. #consider other options if an alternative to the single vwait in this function is used.
set call_id [tcl::clock::microseconds] ; set call_id [tcl::clock::microseconds] ;
set ::shellfilter::shellcommandvars($call_id,exitcode) "" set ::shellfilter::shellcommandvars($call_id,exitcode) ""
set ::shellfilter::shellcommandvars($call_id,timeoutid) ""
set waitvar ::shellfilter::shellcommandvars($call_id,waitvar) set waitvar ::shellfilter::shellcommandvars($call_id,waitvar)
if {$debug} { if {$debug} {
::shellfilter::log::write $debugname " waitvar '$waitvar'" ::shellfilter::log::write $debugname " waitvar '$waitvar'"
@ -2951,7 +2952,10 @@ namespace eval shellfilter {
#} #}
chan close $chan chan close $chan
#catch {chan close $wrerr} #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 set $waitfor stderr
} }
} }
@ -3094,7 +3098,10 @@ namespace eval shellfilter {
set ::shellfilter::shellcommandvars($call_id,exitcode) $code set ::shellfilter::shellcommandvars($call_id,exitcode) $code
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
} }
@ -3230,7 +3237,10 @@ namespace eval shellfilter {
} }
catch {chan close $wrerr} 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 set $waitfor stdout
} }
@ -3241,8 +3251,27 @@ namespace eval shellfilter {
#todo - add ability to detect activity/data-flow and change timeout to only apply for period with zero data #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(?) #e.g x hrs with no data(?)
#reset timeout when data detected. #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] { #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)]} { 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 ""} { if {[set ::shellfilter::shellcommandvars(%id%,exitcode)] ne ""} {
catch { chan close %wrerr% } catch { chan close %wrerr% }
catch { chan close %rdout%} catch { chan close %rdout%}
@ -3278,14 +3307,23 @@ namespace eval shellfilter {
} }
set %w% "timeout" set %w% "timeout"
} }
}] }]]
vwait $waitvar 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)] set exitcode [set ::shellfilter::shellcommandvars($call_id,exitcode)]
if {![string is digit -strict $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 flush stderr
} }
if {[string length $teefile]} { 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 #set timeoutarr(shutdown_free_threads) waiting
#after $timeout [list set timeoutarr(shutdown_free_threads) timed-out] #after $timeout [list set timeoutarr(shutdown_free_threads) timed-out]
set ::shellthread::waitfor waiting 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 waiting_for [list]
set ended [list] set ended [list]
@ -713,6 +715,7 @@ namespace eval shellthread::manager {
set timedout 1 set timedout 1
break break
} else { } else {
after cancel $cancelid
lappend ended $::shellthread::waitfor lappend ended $::shellthread::waitfor
} }
} }

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

@ -28,6 +28,26 @@ namespace eval ::punkboot {
namespace eval ::punkboot::lib { 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} { proc tm_version_isvalid {versionpart} {
#Needs to be suitable for use with Tcl's 'package vcompare' #Needs to be suitable for use with Tcl's 'package vcompare'
if {![catch [list package vcompare $versionpart $versionpart]]} { 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" 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_module_paths [list]
set bootsupport_library_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. #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 # - 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]]} { 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_tcl$::tclmajorv] ;#more version-specific modules slightly higher in precedence order
lappend bootsupport_module_paths [file join $startdir src bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir src bootsupport lib]
} else { } else {
lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv] lappend bootsupport_module_paths [file join $startdir bootsupport modules_tcl$::tclmajorv]
lappend bootsupport_module_paths [file join $startdir bootsupport modules] 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] lappend bootsupport_library_paths [file join $startdir bootsupport lib]
} }
set bootsupport_paths_exist 0 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]} { if {[file exists $p]} {
lappend sourcesupport_library_paths $p lappend sourcesupport_library_paths $p
} }
@ -252,7 +374,11 @@ if {$bootsupport_paths_exist || $sourcesupport_paths_exist} {
#very basic test there is something there.. #very basic test there is something there..
set support_contents_exist 0 set support_contents_exist 0
foreach p [list {*}$bootsupport_module_paths {*}$bootsupport_library_paths {*}$sourcesupport_module_paths {*}$sourcesupport_library_paths] { 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]} { if {[llength $contents]} {
set support_contents_exist 1 set support_contents_exist 1
break 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set missing_rows [list] set missing_rows [list]
set fields_blank_missing [dict create\ 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)} ... array set haspkg [punkboot::package_bools $pkg_availability] ;#convenience e.g if {$haspkg(textblock)} ...
global A global A
if {![array size A]} { if {![array size A]} {
punkboot::define_global_ansi $pkg_availability punkboot::define_global_ansi
} }
set broken_rows [list] set broken_rows [list]
set fields_blank_broken [dict create\ set fields_blank_broken [dict create\
@ -1038,22 +1164,33 @@ proc ::punkboot::get_display_broken_packages {pkg_availability} {
} }
return $broken_out return $broken_out
} }
proc ::punkboot::define_global_ansi {pkg_availability} { proc ::punkboot::define_global_ansi {} {
#stick to basic colours for themable aspects ? #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 global A
set A(RST) \x1b\[m if {!$has_ansi} {
if {!$haspkg(punk::ansi)} { if {[info exists ::punk::console::colour_disabled] && $::punk::console::colour_disabled} {
set A(HIGHLIGHT) \x1b\[93m ;#brightyellow set A(RST) ""
set A(BWHITE) \x1b\[97m ;#brightwhite set A(HIGHLIGHT) ""
set A(OK) \x1b\[92m ;#brightgreen set A(BWHITE) ""
set A(BAD) \x1b\[33m ;# orange set A(OK) ""
set A(ERR) \x1b\[31m ;# red 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 { } else {
namespace eval ::punkboot { namespace eval ::punkboot {
namespace import ::punk::ansi::a+ ::punk::ansi::a namespace import ::punk::ansi::a+ ::punk::ansi::a
} }
set A(RST) \x1b\[m
set A(HIGHLIGHT) [a+ brightyellow] set A(HIGHLIGHT) [a+ brightyellow]
set A(BWHITE) [a+ brightwhite] set A(BWHITE) [a+ brightwhite]
set A(OK) [a+ web-lawngreen] ;#brightgreen 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. #gather details on what is missing so that the info is always reported in help output.
variable pkg_availability variable pkg_availability
global A 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)} ... 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) #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 #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_project $scriptfolder]]]} {
if {![string length [set projectroot [punk::repo::find_candidate $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" 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 exit 0
} }
if {![array size A]} {
punkboot::define_global_ansi
}
dict for {pkg pkginfo} $::punkboot::bootsupport_requirements { dict for {pkg pkginfo} $::punkboot::bootsupport_requirements {
set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised set verspec [dict get $pkginfo version] ;#version wanted specification always exists and is empty or normalised
if {[catch {package require $pkg {*}$verspec} errM]} { 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 "- -- --- --- --- --- --- --- --- --- -- -"
puts stdout "- projectroot : $projectroot" puts stdout "- projectroot : $projectroot"
set sourcefolder $projectroot/src 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 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])" puts stdout "- vendorlib folders: ([llength $vendorlibfolders])"
foreach fld $vendorlibfolders { foreach fld $vendorlibfolders {
puts stdout " src/$fld" puts stdout " src/$fld"
} }
set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
puts stdout "- vendormodule folders: ([llength $vendormodulefolders])" puts stdout "- vendormodule folders: ([llength $vendormodulefolders])"
foreach fld $vendormodulefolders { foreach fld $vendormodulefolders {
puts stdout " src/$fld" puts stdout " src/$fld"
@ -1473,7 +1618,10 @@ if {$::punkboot::command eq "vendorupdate"} {
set sourcefolder $projectroot/src set sourcefolder $projectroot/src
#todo vendor/lib #todo vendor/lib
set vendorlibfolders [glob -nocomplain -dir $sourcefolder -type d -tails vendorlib_tcl*] 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*] set vendormodulefolders [glob -nocomplain -dir $sourcefolder -type d -tails vendormodules vendormodules_tcl*]
#lappend vendormodulefolders vendormodules #lappend vendormodulefolders vendormodules
foreach vf $vendormodulefolders { foreach vf $vendormodulefolders {
@ -1484,7 +1632,7 @@ if {$::punkboot::command eq "vendorupdate"} {
set which "" 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]} { if {[file exists $vendor_config]} {
set targetroot $sourcefolder/vendormodules$which set targetroot $sourcefolder/vendormodules$which
source $vendor_config ;#populate $local_modules $git_modules $fossil_modules with project-specific list 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}} { 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 { foreach lf $vendorlibfolders {
lassign [split $lf _] _vm tclx set source_lib_folder $sourcefolder/$lf
if {$tclx ne ""} { set target_lib_folder $projectroot/lib
set which _$tclx 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 { } 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 if {![llength $vendorlibfolders]} {
#-antiglob_paths takes relative patterns e.g puts stderr "$A(BAD)VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found.$A(RST)"
# */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\ if {$::punkboot::command in {project packages libs}} {
README.md\ ########################################################
] lappend projectlibfolders lib
puts stdout "VENDORLIB$which: copying from $sourcefolder/$lf to $target_lib_folder (if source file changed)" #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\ set resultdict [punkcheck::install $sourcefolder/$lf $target_lib_folder\
-overwrite installedsourcechanged-targets\ -overwrite installedsourcechanged-targets\
-antiglob_paths $antipaths\ -antiglob_paths $antipaths\
@ -1840,9 +2052,51 @@ if {$::punkboot::command in {project packages libs}} {
] ]
puts stdout [punkcheck::summarize_install_resultdict $resultdict] puts stdout [punkcheck::summarize_install_resultdict $resultdict]
} }
if {![llength $vendorlibfolders]} { if {![llength $projectlibfolders]} {
puts stderr "VENDORLIB: No src/vendorlib or src/vendorlib_tcl* folder found." 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}} { 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}} { if {$::punkboot::command in {project packages modules}} {
#consolidated /modules /modules_tclX folder used for target where X is tcl major version #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