Browse Source

scriptwrapper work

master
Julian Noble 2 months ago
parent
commit
c9085f33f5
  1. 1077
      bin/getzig.cmd
  2. 44
      src/modules/punk-0.1.tm
  3. 29
      src/modules/punk/mix/commandset/scriptwrap-999999.0a1.0.tm
  4. 58
      src/modules/punk/mix/templates/utility/scriptappwrappers/multishell.cmd
  5. 289
      src/modules/punk/ubl-999999.0a1.0.tm
  6. 3
      src/modules/punk/ubl-buildversion.txt
  7. 15
      src/scriptapps/getzig.bash
  8. 186
      src/scriptapps/getzig.ps1
  9. 21
      src/scriptapps/getzig_wrap.toml

1077
bin/getzig.cmd

File diff suppressed because it is too large Load Diff

44
src/modules/punk-0.1.tm

@ -8259,9 +8259,29 @@ namespace eval punk {
interp alias {} d/~ {} punk::nav::fs::d/~ interp alias {} d/~ {} punk::nav::fs::d/~
interp alias "" x/ "" punk::nav::fs::x/ interp alias "" x/ "" punk::nav::fs::x/
variable pshell_path ""
# ----------------------------------------
set pshell_path [auto_execok pwsh] ;#Still not installed by default on win10 11?
if {$pshell_path eq ""} {
#fallback to powershell 5
#set pshell_path [auto_execok powershell]
set pshell_path powershell ;#temp
} else {
set pshell_path pwsh ;#temp
}
#todo - review run commands and handling of paths with spaces
# ----------------------------------------
if {$::tcl_platform(platform) eq "windows"} {
if {$pshell_path eq ""} {
set has_powershell 0
} else {
#todo - review powershell detection on non-windows platforms
set has_powershell 1 set has_powershell 1
}
if {$::tcl_platform(platform) eq "windows"} {
interp alias {} dl {} dir /q interp alias {} dl {} dir /q
interp alias {} dw {} dir /W/D interp alias {} dw {} dir /W/D
} else { } else {
@ -8269,8 +8289,6 @@ namespace eval punk {
#interp alias {} dl {} #interp alias {} dl {}
interp alias {} dl {} puts stderr "not implemented" interp alias {} dl {} puts stderr "not implemented"
interp alias {} dw {} puts stderr "not implemented" interp alias {} dw {} puts stderr "not implemented"
#todo - powershell detection on other platforms
set has_powershell 0
} }
#todo - distinguish non-preinstalled pwsh (powershell core) from powershell which is available by default #todo - distinguish non-preinstalled pwsh (powershell core) from powershell which is available by default
@ -8279,13 +8297,19 @@ namespace eval punk {
# powershell runspaces e.g $rs=[RunspaceFactory]::CreateRunspace() # powershell runspaces e.g $rs=[RunspaceFactory]::CreateRunspace()
# $ps = [Powershell]::Create() # $ps = [Powershell]::Create()
interp alias {} pse {} exec >@stdout pwsh -nolo -nop -c interp alias {} pse {} exec >@stdout {*}$pshell_path -nolo -nop -c
interp alias {} psx {} runx -n pwsh -nop -nolo -c interp alias {} psx {} runx -n {*}$pshell_path -nop -nolo -c
interp alias {} psr {} run -n pwsh -nop -nolo -c interp alias {} psr {} run -n {*}$pshell_path -nop -nolo -c
interp alias {} psout {} runout -n pwsh -nop -nolo -c interp alias {} psout {} runout -n {*}$pshell_path -nop -nolo -c
interp alias {} pserr {} runerr -n pwsh -nop -nolo -c interp alias {} pserr {} runerr -n {*}$pshell_path -nop -nolo -c
interp alias {} psls {} shellrun::runconsole pwsh -nop -nolo -c ls #interp alias {} psls {} shellrun::runconsole $pshell_path -nop -nolo -c ls
interp alias {} psps {} shellrun::runconsole pwsh -nop -nolo -c ps #interp alias {} psls {} shellrun::runconsole {*}$pshell_path -nop -nolo -c {ls | Select-Object Mode, @{Name='Owner';Expression={(Get-Acl $_.FullName).Owner}}, LastWriteTime, Length, Name | Format-Table}
proc psls args {
variable pshell_path
shellrun::runconsole {*}$pshell_path -nop -nolo -c {*}[string map [list %a% $args] {{ls %a% | Select-Object Mode, @{Name='Owner';Expression={(Get-Acl $_.FullName).Owner}}, LastWriteTime, Length, Name | Format-Table}}]
}
interp alias {} psls {} punk::psls
interp alias {} psps {} shellrun::runconsole {*}$pshell_path -nop -nolo -c ps
} else { } else {
set ps_missing "powershell missing (powershell is MIT licensed open source and can be installed on windows and most unix-like platforms)" set ps_missing "powershell missing (powershell is MIT licensed open source and can be installed on windows and most unix-like platforms)"
interp alias {} pse {} puts stderr $ps_missing interp alias {} pse {} puts stderr $ps_missing

29
src/modules/punk/mix/commandset/scriptwrap-999999.0a1.0.tm

@ -257,6 +257,24 @@ namespace eval punk::mix::commandset::scriptwrap {
set target_labels_found [dict create] set target_labels_found [dict create]
set possible_target_labels_found [dict create] set possible_target_labels_found [dict create]
set warning_target_labels_found [dict create] set warning_target_labels_found [dict create]
#todo - allow analysis of colon-less call. May need to check list of internal commands - but what about external ones?
#set searchregexex [list {(.*\s+|^)(@*call\s*:*)(\S.*)} {(.*\s+|^)(@*CALL\s*:*)(\S.*)} {(.*\s+|^)(@*goto\s*:*)(\S.*)} {(.*\s+|^)(@*GOTO\s*:*)(\S.*)}]
#order of regex testing is important - test more specific entries with colon/comment before we test whitespace only version of goto/call
set searchregexes [list {(.*\s+|^)(@*call\s*:)(\S.*)} {(.*\s+|^)(@*CALL\s*:)(\S.*)} {(.*\s+|^)(@*goto\s*:)(\S.*)} {(.*\s*|.*\s+|^)(@*GOTO\s*:)(\S.*)}]
lappend searchregexes {(.*\|\|.*)(@*GOTO\s*:)(\S.*)} ;#review
lappend searchregexes {(.*\s+|^)(@*goto\s+%=.*=%\s*:)(\S.*)}
lappend searchregexes {(.*\s+|^)(@*goto\s+%=.*=%\s+)(\S.*)}
lappend searchregexes {(.*\s+|^)(@*goto\s+)(\S.*)}
lappend searchregexes {(.*\s+|^)(@*GOTO\s+%=.*=%\s*:)(\S.*)}
lappend searchregexes {(.*\s+|^)(@*GOTO\s+%=.*=%\s+)(\S.*)}
lappend searchregexes {(.*\s+|^)(@*GOTO\s+)(\S.*)}
#review
#todo - better callsite analysis. There can be data between @GOTO or @CALL and : other than just whitespace
#e.g for @goto %= possible comment=% :mylabe%%l etc
for {set callingline_index 0} {$callingline_index < $line_count} {incr callingline_index} { for {set callingline_index 0} {$callingline_index < $line_count} {incr callingline_index} {
set callingline_info [$objFile lineinfo $callingline_index] set callingline_info [$objFile lineinfo $callingline_index]
set callingline_payload [dict get $callingline_info payload] set callingline_payload [dict get $callingline_info payload]
@ -273,18 +291,15 @@ namespace eval punk::mix::commandset::scriptwrap {
} }
default { default {
#todo - better callsite analysis. There can be data between @GOTO or @CALL and : other than just whitespace!
#todo - allow analysis of colon-less call. May need to check list of internal commands - but what about external ones? foreach search_regex $searchregexes {
#foreach search_regex [list {(.*\s+|^)(@*call\s*:*)(\S.*)} {(.*\s+|^)(@*CALL\s*:*)(\S.*)} {(.*\s+|^)(@*goto\s*:*)(\S.*)} {(.*\s+|^)(@*GOTO\s*:*)(\S.*)}] {}
foreach search_regex [list {(.*\s+|^)(@*call\s*:)(\S.*)} {(.*\s+|^)(@*CALL\s*:)(\S.*)} {(.*\s+|^)(@*goto\s*:)(\S.*)} {(.*\s*|.*\s+|^)(@*GOTO\s*:)(\S.*)} {(.*\|\|.*)(@*GOTO\s*:)(\S.*)}] {
if {[regexp $search_regex $callingline_payload _m precall call labelplus]} { if {[regexp $search_regex $callingline_payload _m precall call labelplus]} {
#todo further checks to see if it's actually a batch script line #todo further checks to see if it's actually a batch script line
# - - - - work out what cmd.exe considers start of 512B boundaries when scanning from a callsite # - - - - work out what cmd.exe considers start of 512B boundaries when scanning from a callsite
#callposn affected by newlines? #callposn affected by newlines?
#set callposn [expr {$file_offset + [string length $callingline_payload]}] ;#take callposn as end of line .. review - multiline statements? #set callposn [expr {$file_offset + [string length $callingline_payload]}] ;#take callposn as end of line .. review - multiline statements?
set callposn [expr {$file_offset + $callingline_len}] set callposn [expr {$file_offset + $callingline_len -1}]
#Note there are anomalies around target labels in bracketed sections such as IF blocks #Note there are anomalies around target labels in bracketed sections such as IF blocks
#this is bad practice - as it can lead to unbalanced braces - but batch files can still work under cmd.exe with them in some cases #this is bad practice - as it can lead to unbalanced braces - but batch files can still work under cmd.exe with them in some cases
#e.g unbalanced trailing bracket may be ignored. #e.g unbalanced trailing bracket may be ignored.
@ -1741,7 +1756,7 @@ namespace eval punk::mix::commandset::scriptwrap {
#note that: #note that:
#@REM ----- #@REM -----
#@goto ^ #@goto ^
#:label #:label
#@REM----- #@REM-----
# is a valid callsite - but doesn't appear to be found by the label scanner as it's own target label even though :label is on it's own line from non-batch perspective # is a valid callsite - but doesn't appear to be found by the label scanner as it's own target label even though :label is on it's own line from non-batch perspective
# so the caller will have to do some batch-style line processing to find all call sites # so the caller will have to do some batch-style line processing to find all call sites

58
src/modules/punk/mix/templates/utility/scriptappwrappers/multishell.cmd

@ -25,7 +25,7 @@ set -- "$@" "a=[Hide <#;Hide set;S 1 list]"; set -- : "$@";$1 = @'
@REM in batch scripts - array syntax with square brackets is a simulation of arrays or associative arrays. @REM in batch scripts - array syntax with square brackets is a simulation of arrays or associative arrays.
@REM note that many shells linked as sh do not support substition syntax and may fail - e.g dash etc - generally bash should be used in this context @REM note that many shells linked as sh do not support substition syntax and may fail - e.g dash etc - generally bash should be used in this context
@SETLOCAL EnableExtensions EnableDelayedExpansion @SETLOCAL EnableExtensions EnableDelayedExpansion
@SET "validshelltypes= powershell______ sh______________ wslbash_________ bash____________ tcl_____________ perl____________ none____________" @SET "validshelltypes= pwsh____________ powershell______ sh______________ wslbash_________ bash____________ tcl_____________ perl____________ none____________"
@REM for batch - only win32 is relevant - but other scripts on other platforms also parse the nextshell block to determine next shell to launch @REM for batch - only win32 is relevant - but other scripts on other platforms also parse the nextshell block to determine next shell to launch
@REM nextshellpath and nextshelltype indices (underscore-padded to 16wide) are "other" plus those returned by Tcl platform pkg e.g win32,linux,freebsd,macosx @REM nextshellpath and nextshelltype indices (underscore-padded to 16wide) are "other" plus those returned by Tcl platform pkg e.g win32,linux,freebsd,macosx
@REM The horrible underscore-padded fixed-widths are to keep the batch labels aligned whilst allowing values to be set @REM The horrible underscore-padded fixed-widths are to keep the batch labels aligned whilst allowing values to be set
@ -176,9 +176,9 @@ set -- "$@" "a=[Hide <#;Hide set;S 1 list]"; set -- : "$@";$1 = @'
) )
@REM avoid using CALL to launch pwsh,tclsh etc - it will intercept some args such as /? @REM avoid using CALL to launch pwsh,tclsh etc - it will intercept some args such as /?
@IF "!selected_shelltype_trimmed!"=="none" ( @IF "!selected_shelltype_trimmed!"=="none" (
SET selected_shelltype_trimmed=powershell SET selected_shelltype_trimmed=pwsh
) )
@IF "!selected_shelltype_trimmed!"=="powershell" ( @IF "!selected_shelltype_trimmed!"=="pwsh" (
REM pwsh vs powershell hasn't been tested because we didn't need to copy cmd to ps1 this time REM pwsh vs powershell hasn't been tested because we didn't need to copy cmd to ps1 this time
REM test availability of preferred option of powershell7+ pwsh REM test availability of preferred option of powershell7+ pwsh
pwsh -nop -nol -c set-executionpolicy -Scope Process Unrestricted; write-host "statusmessage: pwsh-found" >NUL pwsh -nop -nol -c set-executionpolicy -Scope Process Unrestricted; write-host "statusmessage: pwsh-found" >NUL
@ -189,33 +189,35 @@ set -- "$@" "a=[Hide <#;Hide set;S 1 list]"; set -- : "$@";$1 = @'
pwsh -nop -nol -c set-executionpolicy -Scope Process Unrestricted; "%~dp0%~n0.ps1" %arglist% pwsh -nop -nol -c set-executionpolicy -Scope Process Unrestricted; "%~dp0%~n0.ps1" %arglist%
SET task_exitcode=!errorlevel! SET task_exitcode=!errorlevel!
) ELSE ( ) ELSE (
REM CALL powershell -nop -nol -c write-host powershell-found REM TODO prompt user with option to call script to install pwsh using winget
REM powershell -nop -nol -file "%~dp0%~n0.ps1" %* REM powershell -nop -nol -c set-executionpolicy -Scope Process Unrestricted; "%~dp0%~n0.ps1" %arglist%
powershell -nop -nol -c set-executionpolicy -Scope Process Unrestricted; %~dp0%~n0.ps1" %arglist% powershell -nop -nol -ExecutionPolicy Bypass -c "%~dp0%~n0.ps1" %arglist%
SET task_exitcode=!errorlevel! SET task_exitcode=!errorlevel!
) )
) ELSE ( ) ELSE (
IF "!selected_shelltype_trimmed!"=="wslbash" ( IF "!selected_shelltype_trimmed!"=="powershell" (
CALL :getWslPath %winpath% wslpath powershell -nop -nol -ExecutionPolicy Bypass -c "%~dp0%~n0.ps1" %arglist%
REM ECHO wslfullpath "!wslpath!%fname%"
%selected_shellpath_trimmed% "!wslpath!%fname%" %arglist%
SET task_exitcode=!errorlevel! SET task_exitcode=!errorlevel!
) ELSE ( ) ELSE (
REM perl or tcl or sh or bash IF "!selected_shelltype_trimmed!"=="wslbash" (
IF NOT "x%keyRemoved%"=="x%validshelltypes%" ( CALL :getWslPath %winpath% wslpath
REM sh on windows uses /c/ instead of /mnt/c - at least if using msys. Todo, review what is the norm on windows with and without msys2,cygwin,wsl REM ECHO wslfullpath "!wslpath!%fname%"
REM and what logic if any may be needed. For now sh with /c/xxx seems to work the same as sh with c:/xxx %selected_shellpath_trimmed% "!wslpath!%fname%" %arglist%
REM The compound statement with trailing call is required to stop batch termination confirmation, whilst still capturing exitcode SET task_exitcode=!errorlevel!
@ECHO HERE "!selected_shelltype_trimmed!" "!selected_shellpath_trimmed!"
%selected_shellpath_trimmed% "%~dp0%fname%" %arglist% & SET task_exitcode=!errorlevel! & Call;
) ELSE ( ) ELSE (
ECHO %fname% has invalid nextshelltype value %selected_shelltype% valid options are %validshelltypes% REM perl or tcl or sh or bash
SET task_exitcode=66 IF NOT "x%keyRemoved%"=="x%validshelltypes%" (
@REM boundary padding REM sh on windows uses /c/ instead of /mnt/c - at least if using msys. Todo, review what is the norm on windows with and without msys2,cygwin,wsl
@REM boundary padding REM and what logic if any may be needed. For now sh with /c/xxx seems to work the same as sh with c:/xxx
@REM boundary padding REM The compound statement with trailing call is required to stop batch termination confirmation, whilst still capturing exitcode
@REM boundary padding @ECHO HERE "!selected_shelltype_trimmed!" "!selected_shellpath_trimmed!"
GOTO :exit_multishell %selected_shellpath_trimmed% "%~dp0%fname%" %arglist% & SET task_exitcode=!errorlevel! & Call;
) ELSE (
ECHO %fname% has invalid nextshelltype value %selected_shelltype% valid options are %validshelltypes%
SET task_exitcode=66
@REM boundary padding
GOTO :exit_multishell
)
) )
) )
) )
@ -803,9 +805,11 @@ if ($matches.count) {
$arguments = @("-NoProfile", "-NoExit", "-ExecutionPolicy", "Bypass") $arguments = @("-NoProfile", "-NoExit", "-ExecutionPolicy", "Bypass")
$arguments += @("-File", $($MyInvocation.MyCommand.Path)) $arguments += @("-File", $($MyInvocation.MyCommand.Path))
$arguments += $args $arguments += $args
if ($PSVersionTable.PSEdition -eq 'Core') {
#Start-Process -FilePath "pwsh.exe" -ArgumentList "-NoProfile -NoExit -ExecutionPolicy Bypass -File $($MyInvocation.MyCommand.Path)" -Wait -Verb RunAs Start-Process -FilePath "pwsh.exe" -ArgumentList $arguments -Wait -Verb RunAs
Start-Process -FilePath "pwsh.exe" -ArgumentList $arguments -Wait -Verb RunAs } else {
Start-Process -FilePath "powershell.exe" -ArgumentList $arguments -Wait -Verb RunAs
}
Exit # Exit the current non-elevated process Exit # Exit the current non-elevated process
} }
} }

289
src/modules/punk/ubl-999999.0a1.0.tm

@ -0,0 +1,289 @@
# -*- tcl -*-
# Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from <pkg>-buildversion.txt
# module template: shellspy/src/decktemplates/vendor/punk/modules/template_module-0.0.3.tm
#
# Please consider using a BSD or MIT style license for greatest compatibility with the Tcl ecosystem.
# Code using preferred Tcl licenses can be eligible for inclusion in Tcllib, Tklib and the punk package repository.
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# (C) 2025
#
# @@ Meta Begin
# Application punk::ubl 999999.0a1.0
# Meta platform tcl
# Meta license MIT
# @@ Meta End
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# doctools header
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[manpage_begin shellspy_module_punk::ubl 0 999999.0a1.0]
#[copyright "2025"]
#[titledesc {Module API}] [comment {-- Name section and table of contents description --}]
#[moddesc {-}] [comment {-- Description at end of page heading --}]
#[require punk::ubl]
#[keywords module]
#[description]
#[para] Basic UBL
#[para] https://docs.oasis-open.org/ubl/os-UBL-2.4/
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Overview]
#[para] overview of punk::ubl
#[subsection Concepts]
#[para] -
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Requirements
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection dependencies]
#[para] packages used by punk::ubl
#[list_begin itemized]
package require Tcl 8.6-
#*** !doctools
#[item] [package {Tcl 8.6}]
# #package require frobz
# #*** !doctools
# #[item] [package {frobz}]
#*** !doctools
#[list_end]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section API]
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# oo::class namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#tcl::namespace::eval punk::ubl::class {
#*** !doctools
#[subsection {Namespace punk::ubl::class}]
#[para] class definitions
#if {[tcl::info::commands [tcl::namespace::current]::interface_sample1] eq ""} {
#*** !doctools
#[list_begin enumerated]
# oo::class create interface_sample1 {
# #*** !doctools
# #[enum] CLASS [class interface_sample1]
# #[list_begin definitions]
# method test {arg1} {
# #*** !doctools
# #[call class::interface_sample1 [method test] [arg arg1]]
# #[para] test method
# puts "test: $arg1"
# }
# #*** !doctools
# #[list_end] [comment {-- end definitions interface_sample1}]
# }
#*** !doctools
#[list_end] [comment {--- end class enumeration ---}]
#}
#}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::ubl {
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Base namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[subsection {Namespace punk::ubl}]
#[para] Core API functions for punk::ubl
#[list_begin definitions]
variable PUNKARGS
#proc sample1 {p1 n args} {
# #*** !doctools
# #[call [fun sample1] [arg p1] [arg n] [opt {option value...}]]
# #[para]Description of sample1
# #[para] Arguments:
# # [list_begin arguments]
# # [arg_def tring p1] A description of string argument p1.
# # [arg_def integer n] A description of integer argument n.
# # [list_end]
# return "ok"
#}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::ubl ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# Secondary API namespace
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
tcl::namespace::eval punk::ubl::lib {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
tcl::namespace::path [tcl::namespace::parent]
#*** !doctools
#[subsection {Namespace punk::ubl::lib}]
#[para] Secondary functions that are part of the API
#[list_begin definitions]
#proc utility1 {p1 args} {
# #*** !doctools
# #[call lib::[fun utility1] [arg p1] [opt {?option value...?}]]
# #[para]Description of utility1
# return 1
#}
#*** !doctools
#[list_end] [comment {--- end definitions namespace punk::ubl::lib ---}]
}
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
#*** !doctools
#[section Internal]
#tcl::namespace::eval punk::ubl::system {
#*** !doctools
#[subsection {Namespace punk::ubl::system}]
#[para] Internal functions that are not part of the API
#}
# == === === === === === === === === === === === === === ===
# Sample 'about' function with punk::args documentation
# == === === === === === === === === === === === === === ===
tcl::namespace::eval punk::ubl {
tcl::namespace::export {[a-z]*} ;# Convention: export all lowercase
variable PUNKARGS
variable PUNKARGS_aliases
lappend PUNKARGS [list {
@id -id "(package)punk::ubl"
@package -name "punk::ubl" -help\
"Package
Description"
}]
namespace eval argdoc {
#namespace for custom argument documentation
proc package_name {} {
return punk::ubl
}
proc about_topics {} {
#info commands results are returned in an arbitrary order (like array keys)
set topic_funs [info commands [namespace current]::get_topic_*]
set about_topics [list]
foreach f $topic_funs {
set tail [namespace tail $f]
lappend about_topics [string range $tail [string length get_topic_] end]
}
#Adjust this function or 'default_topics' if a different order is required
return [lsort $about_topics]
}
proc default_topics {} {return [list Description *]}
# -------------------------------------------------------------
# get_topic_ functions add more to auto-include in about topics
# -------------------------------------------------------------
proc get_topic_Description {} {
punk::args::lib::tstr [string trim {
package punk::ubl
description to come..
} \n]
}
proc get_topic_License {} {
return "MIT"
}
proc get_topic_Version {} {
return "$::punk::ubl::version"
}
proc get_topic_Contributors {} {
set authors {{Julian Noble <julian@precisium.com.au>}}
set contributors ""
foreach a $authors {
append contributors $a \n
}
if {[string index $contributors end] eq "\n"} {
set contributors [string range $contributors 0 end-1]
}
return $contributors
}
proc get_topic_custom-topic {} {
punk::args::lib::tstr -return string {
A custom
topic
etc
}
}
# -------------------------------------------------------------
}
# we re-use the argument definition from punk::args::standard_about and override some items
set overrides [dict create]
dict set overrides @id -id "::punk::ubl::about"
dict set overrides @cmd -name "punk::ubl::about"
dict set overrides @cmd -help [string trim [punk::args::lib::tstr {
About punk::ubl
}] \n]
dict set overrides topic -choices [list {*}[punk::ubl::argdoc::about_topics] *]
dict set overrides topic -choicerestricted 1
dict set overrides topic -default [punk::ubl::argdoc::default_topics] ;#if -default is present 'topic' will always appear in parsed 'values' dict
set newdef [punk::args::resolved_def -antiglobs -package_about_namespace -override $overrides ::punk::args::package::standard_about *]
lappend PUNKARGS [list $newdef]
proc about {args} {
package require punk::args
#standard_about accepts additional choices for topic - but we need to normalize any abbreviations to full topic name before passing on
set argd [punk::args::parse $args withid ::punk::ubl::about]
lassign [dict values $argd] _leaders opts values _received
punk::args::package::standard_about -package_about_namespace ::punk::ubl::argdoc {*}$opts {*}[dict get $values topic]
}
}
# end of sample 'about' function
# == === === === === === === === === === === === === === ===
# -----------------------------------------------------------------------------
# register namespace(s) to have PUNKARGS,PUNKARGS_aliases variables checked
# -----------------------------------------------------------------------------
# variable PUNKARGS
# variable PUNKARGS_aliases
namespace eval ::punk::args::register {
#use fully qualified so 8.6 doesn't find existing var in global namespace
lappend ::punk::args::register::NAMESPACES ::punk::ubl
}
# -----------------------------------------------------------------------------
# ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++
## Ready
package provide punk::ubl [tcl::namespace::eval punk::ubl {
variable pkg punk::ubl
variable version
set version 999999.0a1.0
}]
return
#*** !doctools
#[manpage_end]

3
src/modules/punk/ubl-buildversion.txt

@ -0,0 +1,3 @@
0.1.0
#First line must be a semantic version number
#all other lines are ignored.

15
src/scriptapps/getzig.bash

@ -0,0 +1,15 @@
#mkdir -p ./zig
#tarball="zig-x86_64-windows-0.15.1.zip"
#tarball="zig-x86_64-freebsd-0.15.1.tar.xz"
tarball="zig-x86_64-linux-0.15.1.tar.xz"
automation_name="punkshell+julian@precisium.com.au_target_by_latency"
uristring="https://ziglang.org"
full_uristring="${uristring}/download/0.15.1/${tarball}?source=${automation_name}"
echo "Unimplemented: Download from ${full_uristring} and extract manually"
#wget $full_uristring -O ./zig/zig-linux-x86_64-0.10.1.tar.xz
#tar -xf ./zig/zig-linux-x86_64-0.10.1.tar.xz -C ./zig --strip-components=1
#rm ./zig/zig-linux-x86_64-0.10.1.tar.xz
#echo "Zig installed."
#./zig/zig version

186
src/scriptapps/getzig.ps1

@ -0,0 +1,186 @@
#Join-Path using verbose method to support powershell 5?
#$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.."
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
$toolsfolder = Join-Path -Path $outbase -ChildPath "tools"
if (-not(Test-Path -Path $toolsfolder -PathType Container)) {
#create folder - (can include missing intermediaries)
New-Item -Path $toolsfolder -ItemType Directory
}
$zigfolder = Join-Path $toolsfolder -ChildPath "zig"
$zigexe = Join-Path $zigfolder "zig.exe"
$releasearchive = "zig-x86_64-windows-0.15.1.zip" ;#zip on windows, tarball on every other platform
Write-Output "powershell version: $($PSVersionTable.PSVersion)"
if (Get-Command $zigexe -ErrorAction SilentlyContinue) {
Write-Host "zig.exe is installed in tools/zig"
$zigv = tools/zig/zig.exe version 2>&1
$stdout = $zigv | Where-Object {$_ -is [string]}
$stderr = $zigv | Where-Object {$_ -is [System.Management.Automation.ErrorRecord]}
if ($stderr) {
Write-Host "Unexpected output from tools/zig/zig.exe: $stderr"
Write-Host "Consider deleting tools/zig and re-downloading"
} else {
Write-Host "tools/zig/zig.exe version is: $stdout"
}
exit
}
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is available"
} else {
Write-Host "minisign is missing. Will attempt to install using winget."
#Find-Module/Install-Module: older mechanism, available in powershell
#Find-PSResource/Install-PSResource: only available in newer pwsh etc?
$wgclient = Get-Module -ListAvailable -Name Microsoft.WinGet.Client
if (${wgclient}.Length -eq 0) {
Write-Host "Microsoft.WinGet.Client module not installed.. will try to install."
Install-PackageProvider -Name NuGet -Force
$psgallery_existing_policy = (Get-PSRepository -Name PSGallery).InstallationPolicy
if ($psgallery_existing_policy -eq "Untrusted") {
#Applies to all versions of PowerShell for the user, and is persistent for current user.
#This has risks in that a powershell session started after this call, and before we reset it, will treat PSGallery as trusted
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
}
Install-Module -Scope CurrentUser -Name Microsoft.Winget.Client -Force -Repository PSGallery
Repair-WinGetPackageManager
import-module -name Microsoft.Winget.client
if ($psgallery_existing_policy -eq "Untrusted") {
Set-PSRepository -Name PSGallery -InstallationPolicy Untrusted
}
} else {
Write-Host "Microsoft.WinGet.Client is available"
}
$wingetversion = (Find-WinGetPackage jedisct1.minisign).Version
if ($wingetversion) {
Write-Host "Installing minisign version: ${wingetversion}"
Install-WinGetPackage -Id "jedisct1.minisign"
}
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is now available"
} else {
Write-Host "minisign is still not available"
}
exit
}
$zigpubkey = "RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U"
$mirrors_url = "https://ziglang.org/download/community-mirrors.txt"
$mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url)
if ($mirrors_response.StatusCode -eq 200) {
$mirror_array = $mirrors_response.Content.TrimEnd("`r`n") -split "`r`n|`n"
#$mirror_array += "https://bogusxxx.org" #test behaviour of a bogus/down entry
$mirror_array += "https://ziglang.org" #main site
$dict_mirrors = [ordered]@{}
$host_list = @() #same ordering as dict_mirrors
foreach ($mirror in $mirror_array) {
$uri = New-Object System.Uri($mirror)
$hostname = $uri.Host
$dict_mirrors[$hostname] = @{}
$dict_mirrors[$hostname]["uri"] = $mirror
$host_list += $hostname
#write-host "Host name: $hostname"
}
#write-host "dict: $($dict_mirrors | out-String)"
write-host "host_list: $host_list"
$test_results = Test-Connection -TargetName $host_list -Count 1 -Ipv4 -Detailed -TcpPort 443 -Quiet
for ($i = 0; $i -lt $test_results.Count; $i++) {
$result = $test_results[$i]
if ($result) {
$targethost = $result.Target
if ($result.Status -eq "Success") {
$dict_mirrors[$targethost]["latency"] = $result.Latency
} else {
$dict_mirrors[$targethost]["latency"] = 999999
}
} else {
$targethost = $host_list[$i]
$dict_mirrors[$targethost]["latency"] = 999999
}
}
$list_mirror_dicts = @()
#write-host "dict tested: $($dict_mirrors | Out-String)"
foreach ($key in $dict_mirrors.Keys) {
$list_mirror_dicts += $($dict_mirrors[$key])
}
$sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property Latency
Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)"
$automation_name = "punkshell+julian@precisium.com.au_target_by_latency"
foreach ($hostinfo in $sorted_mirror_dicts) {
$uristring = $hostinfo.uri
if ($uristring -eq "https://ziglang.org") {
$full_uristring = "${uristring}/download/0.15.1/${releasearchive}?source=${automation_name}"
$sig_uristring = "${uristring}/download/0.15.1/${releasearchive}.minisig?source=${automation_name}"
} else {
$full_uristring = "${uristring}/${releasearchive}?source=${automation_name}"
$sig_uristring = "${uristring}/${releasearchive}.minisig?source=${automation_name}"
}
Write-Host "Downloading zig from $full_uristring"
#$uriobj = [uri]$full_uristring
#$lastSegment = $uriobj.Segments[-1]
#$outfile = Join-Path $toolsfolder -ChildPath $lastSegment
$outfile = Join-Path $toolsfolder -ChildPath $releasearchive
Write-Host "Download to: $outfile"
Invoke-WebRequest -Uri $full_uristring -OutFile $outfile
if (-not(Test-Path -Path $outfile -PathType Leaf)) {
write-Host "Failed to download zig package from $full_uristring to ${outfile} .. aborting download from $uristring"
continue
}
Write-Host "Downloading minisig signature from $sig_uristring"
Invoke-WebRequest -Uri $sig_uristring -Outfile "${outfile}.minisig"
if (-not(Test-Path -Path "${outfile}.minisig" -PathType Leaf)) {
write-Host "Failed to download minisig from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring"
continue
}
write-host "downloaded $outfile and ${outfile}.minisig - validating signature..."
#validate releasearchive (tarball/zip)
$sigresult = minisign -V -P $zigpubkey -m $outfile 2>&1
$stdout = $sigresult | Where-Object {$_ -is [string]}
$stderr = $sigresult | Where-Object {$_ -is [System.Management.Automation.ErrorRecord]}
$is_valid = $false
if ($stderr) {
write-host "Signature validation failed with message: $stderr"
} else {
if (($stdout | Out-String).Contains("signature verified")) {
write-host $stdout
$is_valid = $true
} else {
write-host "Unexpected output from minisign: $stdout"
write-host "Did not contain 'signature verified'"
}
}
if (-not($is_valid)) {
write-Host "Couldn't verify signature from download site $uristring"
Remove-Item -Path $outfile -ErrorAction SilentlyContinue
Remove-Item -Path "${outfile}.minisig" -ErrorAction SilentlyContinue
continue
}
Write-Host "Signature OK - extracting archive"
Expand-Archive -path $outfile -DestinationPath $toolsfolder -Force
#Remove-Item -Path "$outfile"
$zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive)
#Rename-Item -Path
write-host "zip_rootname: $zip_rootname"
Rename-Item -Path $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) -NewName $zigfolder
Write-Host "Zig installed in ${zigfolder}"
$zigexe = Join-Path $zigfolder -ChildPath "zig.exe"
$v = Invoke-Expression "$zigexe version"
Write-Host "ZIG VERSION: ${v}"
$test_ok = 1 ;#todo
if ($test_ok) {
break
}
}
} else {
Write-Host "Unable to retrieve list of zig community mirrors from $mirrors_url"
}

21
src/scriptapps/getzig_wrap.toml

@ -0,0 +1,21 @@
[application]
template="punk.multishell.cmd"
as_admin=false
scripts=[
"getzig.ps1",
"getzig.bash"
]
default_outputfile="getzig.cmd"
default_nextshellpath="/usr/bin/env bash"
default_nextshelltype="bash"
#valid nextshelltype entries are: tcl perl pwsh powershell bash.
#nextshellpath entries must be 64 characters or less.
win32.nextshellpath="pwsh"
win32.nextshelltype="pwsh"
win32.outputfile="getzig.cmd"
Loading…
Cancel
Save