Browse Source

scriptapps update

master
Julian Noble 2 months ago
parent
commit
929782e083
  1. 798
      bin/getzig.cmd
  2. 0
      src/scriptapps/bin/getzig.bash
  3. 643
      src/scriptapps/bin/getzig.ps1
  4. 36
      src/scriptapps/bin/getzig_original.polyglot
  5. 42
      src/scriptapps/bin/getzig_wrap.toml
  6. 352
      src/scriptapps/getpunk.ps1
  7. 46
      src/scriptapps/getpunk_wrap.toml
  8. 832
      src/scriptapps/runtime.ps1
  9. 54
      src/scriptapps/runtime_wrap.toml

798
bin/getzig.cmd

@ -806,7 +806,13 @@ do if not defined param1 set %%~"param1=%2%%~"
rename set ""; rename S set; set k {-- "$@" "a}; if {[info exists ::env($k)]} {unset ::env($k)} ;# tidyup and restore
Hide :exit_multishell;Hide {<#};Hide '@
#---------------------------------------------------------------------
puts "info script : [info script]"
#puts "argcount : $::argc"
#puts "argvalues: $::argv"
#puts "argv0 : $::argv0"
# -- --- --- --- --- --- --- --- --- --- --- ---
#divert to configured nextshell
set script_as_called [info script]
package require platform
set plat_full [platform::generic]
set plat [lindex [split $plat_full -] 0]
@ -819,6 +825,14 @@ set in_data 0
set nextshellpath ""
set nextshelltype ""
puts stderr "PLAT: $plat"
switch -glob -- $plat {
"msys" - "mingw*" {
set os "win32"
}
default {
set os $plat
}
}
foreach ln [split $scriptdata \n] {
if {[string trim $ln] eq ""} {continue}
if {!$in_data} {
@ -826,14 +840,14 @@ foreach ln [split $scriptdata \n] {
set in_data 1
}
} else {
if {[string match "*@SET*nextshellpath?${plat}_*" $ln]} {
if {[string match "*@SET*nextshellpath?${os}_*" $ln]} {
set lineparts [split $ln =]
set tail [lindex $lineparts 1]
set nextshellpath [string trimright $tail {_"}]
if {$nextshellpath ne "" && $nextshelltype ne ""} {
break
}
} elseif {[string match "*@SET*nextshelltype?${plat}_*" $ln]} {
} elseif {[string match "*@SET*nextshelltype?${os}_*" $ln]} {
set lineparts [split $ln =]
set tail [lindex $lineparts 1]
set nextshelltype [string trimright $tail {_"}]
@ -846,7 +860,6 @@ foreach ln [split $scriptdata \n] {
}
}
if {$nextshelltype ne "tcl" && $nextshelltype ne "none"} {
set script_as_called [info script]
set script_rootname [file rootname $script_as_called]
if {$nextshelltype in "pwsh powershell"} {
# experimental
@ -907,20 +920,52 @@ if {$nextshelltype ne "tcl" && $nextshelltype ne "none"} {
set scrname $script_as_called
set arglist $::argv
}
puts stdout "tclsh launching subshell of type: $nextshelltype shellpath: $nextshellpath on script $scrname with args: $arglist"
#todo - handle /usr/bin/env
#todo - exitcode
if {[llength $nextshellpath] == 1 && [string index $nextshellpath 0] eq {"} && [string index $nextshellpath end] eq {"}} {
set nextshell_words [list $nextshellpath]
} else {
set nextshell_words $nextshellpath
#review - test spaced quoted words in nextshellpath?
#
#if {[llength $nextshellpath] == 1 && [string index $nextshellpath 0] eq {"} && [string index $nextshellpath end] eq {"}} {
# set nextshell_words [list $nextshellpath]
#} else {
# set nextshell_words $nextshellpath
#}
#perform any msys argument munging on a cmd/cmd.exe based nextshellpath before we convert the first word to an auto_exec path
switch -glob -- $plat {
"msys" - "mingw*" {
set cmdword [lindex $nextshellpath 0]
#we only act on cmd or cmd.exe - not a full path such as c:/WINDOWS/system32/cmd.exe
#the nextshellpath should generally be configured as cmd /c ... or cmd.exe ... but specifying it as a path could allow bypassing this un-munging.
#The un-munging only applies to msys/mingw, so such bypassing should be unnecessary - review
#maint: keep this munging in sync with zsh/bash and perl blocks which must also do msys mangling
if {[regexp {^cmd$|^cmd[.]exe$} $cmdword]} {
#need to deal with msys argument munging
puts stderr "cmd call via msys detected. performing translation of /c to //C"
#for now we only deal with /C or /c - todo - other cmd.exe flags?
#In this context we would usually only be using cmd.exe /c to launch older 'desktop' powershell to avoid spaced-argument problems - so we aren't expecting other flags
set new_nextshellpath [list $cmdword]
#for now - just do what zsh munging does - bash regex/string/array processing is tedious and footgunny for the unfamiliar (me),
#so determine the minimum viable case for code there, then port behaviour to perl/tcl msys munging sections.
foreach w [lrange $nextshellpath 1 end] {
if {[regexp {^/[Cc]$} $w]} {
lappend new_nextshellpath {//C}
} else {
lappend new_nextshellpath $w
}
}
set nextshellpath $new_nextshellpath
}
}
}
set ns_firstword [lindex $nextshellpath 0]
if {[string index $ns_firstword 0] eq {"} && [string index $ns_firstword end] eq {"}} {
set ns_firstword [string range $ns_firstword 1 end-1]
}
#review - is this test for extra layer of double quoting on first word really necessary?
#if we are treaing $nextshellpath as a tcl list - the first layer of double quotes will already have disappeared
##if {[string index $ns_firstword 0] eq {"} && [string index $ns_firstword end] eq {"}} {
## set ns_firstword [string range $ns_firstword 1 end-1]
##}
if {[string match {/*/env} $ns_firstword] && $::tcl_platform(platform) ne "windows"} {
if {$::tcl_platform(platform) ne "windows" && [string match {/*/env} $ns_firstword]} {
set exec_part $nextshellpath
} else {
set epath [auto_execok $ns_firstword]
@ -930,6 +975,10 @@ if {$nextshelltype ne "tcl" && $nextshelltype ne "none"} {
set exec_part [list {*}$epath {*}[lrange $nextshellpath 1 end]]
}
}
puts stdout "tclsh launching subshell of type: $nextshelltype shellpath: $nextshellpath on script $scrname with args: $arglist"
puts stdout "exec: $exec_part $scrname $arglist"
catch {exec {*}$exec_part $scrname {*}$arglist <@stdin >@stdout 2>@stderr} emsg eopts
if {[dict exists $eopts -errorcode]} {
@ -973,11 +1022,6 @@ namespace eval ::punk::multishell {
}
}
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---begin Tcl Payload
#puts "script : [info script]"
#puts "argcount : $::argc"
#puts "argvalues: $::argv"
#puts "argv0 : $::argv0"
# -- --- --- --- --- --- --- --- --- --- --- ---
#<tcl-payload>
puts stderr "No tcl code for this script. Try another program such as zsh or bash or perl"
@ -1006,7 +1050,7 @@ echo "var0: $0 @: $@"
# use oldschool backticks and sed (posix - lowest common denominator) \
# ps_shellname=`ps -p $$ | awk '$1 != "PID" {print $(NF)}' | tr -d '()' | sed -E 's/^.*\/|^-//'` \
# some ps impls will return arguments - so last field not always appropriate \
# some ps impls don't have -o (e.g gnu cygwin) so ps_shellname may remain empty and emit an error \
# some ps impls don't have -o (e.g cygwin) so ps_shellname may remain empty and emit an error \
ps_shellname=`ps -o pid,comm -p $$ | awk '$1 != "PID" {print $2}'`
# \
echo "shell from ps: $ps_shellname"
@ -1061,17 +1105,14 @@ if false==false # else {
then
: #
# zsh/bash \
shift && set -- "${@:1:$((${#@}-1))}"
# ## ### ### ### ### ### ### ### ### ### ### ### ### ###
# -- sh/bash script section
# -- leave as is if all that is required is launching the Tcl payload"
# --
# -- Note that sh/bash script isn't called when running a .bat/.cmd from cmd.exe on windows by default
# -- adjust the %nextshell% value above
# -- if sh/bash scripting needs to run on windows too.
# -- zsh/bash script section
# --
# -- review - for zsh do we want to use: setopt KSH_ARRAYS ?
# -- arrays in bash 0-based vs 1-based in zsh
# -- stick to the @:i:len syntax which is same for both
# ## ### ### ### ### ### ### ### ### ### ### ### ### ###
plat=$(uname -s) #platform/system
@ -1094,7 +1135,6 @@ elif [[ "$plat" == "MINGW64"* ]]; then
elif [[ "$plat" == "CYGWIN_NT"* ]]; then
os="win32"
elif [[ "$plat" == "MSYS_NT"* ]]; then
echo MSYS
#review..
#Need to consider the difference between when msys2 was launched (which strips some paths and sets up the environment)
@ -1141,6 +1181,8 @@ elif [[ "$ps_shellname" == "zsh" ]]; then
else
#fallback - doesn't seem to work in zsh - untested in early bash
IFS=$'\n' arr_oslines=($shellconfiglines)
IFS=$' \t\n'
# review
fi
nextshellpath=""
nextshelltype=""
@ -1182,23 +1224,33 @@ if [[ "$nextshelltype" != "bash" && "$nextshelltype" != "none" ]]; then
fi
if [[ "$plat" == "MSYS_NT"* ]]; then
#we need to deal with MSYS argument mangling
#we need to deal with MSYS argument munging
cmdpattern="^cmd.exe |^cmd "
#do not double quote cmdpattern - or it will be treated as literal string
if [[ "$nextshellpath" =~ $cmdpattern ]]; then
#for now - tell the user what's going on
echo "cmd call via msys detected. performing translation of /c to //c and escaping backslashes in script path"
echo "cmd call via msys detected. performing translation of /c to //c and escaping backslashes in script path" >&2
#flags to cmd.exe such as /c are interpreted by msys as looking like a unix path
#review - for nextshellpath targets specified in the block for win32 - we don't expect unix paths (?)
#what about other flags? - can we just double up all forward slashes?
nextshellpath="${nextshellpath// \/c / \/\/c }"
echo "new nextshellpath: ${nextshellpath}"
#maint: keep this munging in sync with the tcl block and perl block which must also do msys munging
nextshellpath="${nextshellpath// \/[cC] / \/\/c }"
# echo "new nextshellpath: ${nextshellpath}"
#review -
#don't double quote this
script=${script//\\/\\\\}
fi
echo "calling ${nextshellpath} $script $@"
# eval is required here - but why?
eval ${nextshellpath} "$script" "$@"
#load into array
cmd_array=($nextshellpath)
cmd_array+=("$script") #add script, which may contain spaces as a single entry ?
cmd_array+=( "$@" ) #add each element of args to array as a separate entry (equiv ? "${arr[@]}")
# printf "%s\n" "${cmd_array[@]}"
"${cmd_array[@]}"
# this works to make nextshellpath run - but joins $@ members incorrectly
#eval ${nextshellpath} "$script" "$@"
else
#e.g /usr/bin/env tclsh "$0" "$@"
${nextshellpath} "$script" "$@"
@ -1308,8 +1360,33 @@ if 0 {
# -- unbalanced braces { } here *even in comments* will cause problems if there was no Tcl exit or return above
# -- custom script should generally go below the begin_powershell_payload line
# ## ### ### ### ### ### ### ### ### ### ### ### ### ###
function GetScriptName { $myInvocation.ScriptName }
$scriptname = GetScriptName
#$MyInvocation.ScriptName should probably be considered deprecated
# https://stackoverflow.com/questions/78511229/how-can-i-choose-between-myinvocation-scriptname-and-myinvocation-pscommandpat
$runningscriptname = $PSCommandPath
if (-not $MyInvocation.PSCommandPath) {
$callingscriptname = ''
} else {
$callingscriptname = $MyInvocation.PSCommandPath
}
#The problem with psmodulepath
#https://github.com/PowerShell/PowerShell/issues/18108
# psmodulepath is shared by powershell and pwsh despite not all ps modules being compatible.
# It is futzed with by powershell/pwsh based on detecting the child process type.
# a psmodulepath that has been futzed with by pwsh will not work for a child powershell 5 process that isn't launched directly
#This is inherently unfriendly to situations where an intervening process may be something else such as cmd.exe,tcl,perl etc
# nevertheless, powershell/pwsh maintainers seem to have taken the MS-centric view of the world that such situations don't exist :/
#
#symptoms of these shenannigans not working include things like Get-FileHash failing in powershell desktop
#
#We don't know if the original console was pwsh/powershell or cmd.exe, and we need to potentially divert to powershell 5 (desktop)
#via tcl or perl etc - or cmd.exe
if ($PSVersionTable.PSVersion.Major -le 5) {
# For Windows PowerShell, we want to remove any PowerShell 7 paths from PSModulePath
#snipped from https://github.com/PowerShell/DSC/pull/777/commits/af9b99a4d38e0cf1e54c4bbd89cbb6a8a8598c4e
#Presumably users are supposed to know not to have custom paths for powershell desktop containing a 'powershell' subfolder??
$env:PSModulePath = ($env:PSModulePath -split ';' | Where-Object { $_ -notlike '*\powershell\*' }) -join ';'
}
function GetDynamicParamDictionary {
[CmdletBinding()]
param(
@ -1384,11 +1461,11 @@ function GetDynamicParamDictionary {
#}
#psmain @args
#"Timestamp : {0,10:yyyy-MM-dd HH:mm:ss}" -f $(Get-Date) | write-host
"Script Name : {0}" -f $scriptname | write-host
#"Running Script Name : {0}" -f $runningscriptname | write-host
"Powershell Version: {0}" -f $PSVersionTable.PSVersion.Major | write-host
"powershell args : {0}" -f ($args -join ", ") | write-host
#"powershell args : {0}" -f ($args -join ", ") | write-host
# -- --- --- ---
$thisfileContent = Get-Content $scriptname -Raw
$thisfileContent = Get-Content $runningscriptname -Raw
$startTag = ": <<asadmin_start>>"
$endTag = ": <<asadmin_end>>"
$pattern = "(?s)`n$startTag[^`n]*`n(.*?)`n$endTag"
@ -1487,7 +1564,7 @@ if ($match.Success) {
}
if (-not (("pwsh", "powershell", "") -contains $nextshell_type)) {
#nextshell diversion exists for this platform
write-host "os: $os pwsh/powershell launching subshell of type: $nextshell_type shellpath: $nextshell_path on script $scriptname"
write-host "os: $os pwsh/powershell launching subshell of type: $nextshell_type shellpath: $nextshell_path on script $runningscriptname"
# $arguments = @($($MyInvocation.MyCommand.Path))
# $arguments += $args
@ -1495,7 +1572,7 @@ if ($match.Success) {
# $process = (Start-Process -FilePath $nextshell_path -ArgumentList $arguments -NoNewWindow -Wait)
# Exit $process.ExitCode
& $nextshell_path $scriptname $args
& $nextshell_path $runningscriptname $args
exit $LASTEXITCODE
}
}
@ -1503,275 +1580,380 @@ if ($match.Success) {
# -- --- --- --- --- --- --- --- --- --- --- --- --- ---begin powershell Payload
#<powershell-payload>
#launch example
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'cmd.exe' -ArgumentList @('/c', 'getzig.cmd') -NoNewWindow -Wait"
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'getzig.cmd' -NoNewWindow -Wait"
#Join-Path using verbose method to support powershell 5?
#$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.."
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
Write-host "Base folder: $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"
} else {
Write-Host "Failed to find minisign using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is now available"
} else {
Write-Host "minisign is still not available"
#if we automatically relaunch - we could get stuck in a loop - ask user.
$response = read-host -Prompt "Relaunching process may make minizip available. Relaunch? Y|N"
#if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#} else {
#pwsh.exe
#}
if ($response -ieq "y") {
Start-Process 'getzig.cmd' -NoNewWindow -Wait
}
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) {
#https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip
$mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools")
$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
$dict_mirrors[$hostname]["latency"] = 888888 ;#default
$host_list += $hostname
#write-host "Host name: $hostname"
}
#write-host "dict: $($dict_mirrors | out-String)"
write-host "host_list: $host_list"
$automation_name = "punkshell+julian@precisium.com.au_target_by_latency"
#test-netconnection progressbar seems not-so-well-behaved (prog bar lingers)
#test-netconnection a function not cmdlet? Seems to need setting at global level
$OriginalProgressPreference = $Global:ProgressPreference
$Global:ProgressPreference = 'SilentlyContinue'
#temporary dev download source
$ihost = "10.30.30.107"
$imirror = "http://10.30.30.107/jn/punkbin/raw/branch/master/win32-x86_64/tools"
$itrace = test-netconnection $ihost -Hops 6 -TraceRoute -ErrorAction Ignore
if ((${itrace}.PingSucceeded) -and (${itrace}.TraceRoute.Count -lt 5)) {
$host_list += $ihost
$dict_mirrors[$ihost] = @{}
$dict_mirrors[$ihost]["latency"] = 1
$dict_mirrors[$ihost]["uri"] = $imirror
}
$trace = test-netconnection gitea1.intx.com.au -Hops 6 -TraceRoute -ErrorAction Ignore
$Global:ProgressPreference = $OriginalProgressPreference
if ((${trace}.PingSucceeded) -and (${trace}.TraceRoute.Count -lt 5)) {
$dict_mirrors["gitea1.intx.com.au"]["latency"] = 2
#short-circuit for hosts very near gitea1.intx.com.au
#don't even test others. This is primarily for hosts at intx.com.au and associated entities - which are more likely to use punkshell than anyone else.
} else {
if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#we seem to need -ErrorAction Ignore for bad/unresponsive host entries - but unlike with pwsh, we don't get any corresponding entry in the test_results, and -Quiet doesn't seem to give us results either REVIEW
$test_results = Test-Connection $host_list -Count 1 -ErrorAction Ignore
for ($i = 0; $i -lt $test_results.Count; $i++) {
$result = $test_results[$i]
if ($result) {
$targethost = $result.Address
if ($result.StatusCode -eq 0) {
$dict_mirrors[$targethost]["latency"] = $result.ResponseTime
} else {
$dict_mirrors[$targethost]["latency"] = 999999
}
} else {
$targethost = $host_list[$i]
$dict_mirrors[$targethost]["latency"] = 999999
}
}
} else {
#pwsh.exe
$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])
}
#need to ensure latency cast to integer (on powershell 5 at least)
$sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property { [int]$_.latency }
#Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)"
Write-Host "Sorted by latency: $($sorted_mirror_dicts | Out-String)"
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 #This is *insanely* (many minutes vs seconds) slow on powershell 5 at least - we get a progress meter, but it's too high a price to pay.
# -------------------------------------
Add-Type -Assembly "System.IO.Compression.Filesystem"
[System.IO.Compression.Zipfile]::ExtractToDirectory($outfile, $toolsfolder)
Write-Host " - archive extracted."
#We *intermittently* get permission errors when trying to rename the resulting folder (possibly also if we try to delete the zip file immediately)
#There seems to be some sort of lock held after ExtractToDirectory (possibly AV related)
#https://stackoverflow.com/questions/74582293/file-lock-issues-on-zip-file-after-io-compression-zipfileextracttodirectory
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
# -------------------------------------
#Remove-Item -Path "$outfile"
$zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive)
#Rename-Item -Path
#write-host "zip_rootname: $zip_rootname"
write-host "moving $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) to ${zigfolder}"
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"
}
#launch example
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'cmd.exe' -ArgumentList @('/c', 'getzig.cmd') -NoNewWindow -Wait"
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'getzig.cmd' -NoNewWindow -Wait"
#Join-Path using verbose method to support powershell 5?
#$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.."
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
Write-host "Base folder: $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 -ChildPath "zig.exe"
# $releasearchive = "zig-x86_64-windows-0.15.1.zip" ;#zip on windows, tarball on every other platform
$releasearchive = "zig-x86_64-windows-0.16.0-dev.254+6dd0270a1.zip"
Write-Output "powershell version: $($PSVersionTable.PSVersion)"
if (Get-Command $zigexe -ErrorAction SilentlyContinue) {
$relative_zigfolder = Resolve-Path -Path $zigfolder -RelativeBasePath $outbase -Relative
Write-Host "zig.exe is installed in $relative_zigfolder"
$zigv = & $zigexe 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 ${zigexe}: $stderr"
Write-Host "Consider deleting $zigexe and re-downloading"
} else {
Write-Host "$zigexe 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 -Scope CurrentUser -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"
} else {
Write-Host "Failed to find minisign using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is now available"
} else {
Write-Host "minisign is still not available"
#if we automatically relaunch - we could get stuck in a loop - ask user.
$response = read-host -Prompt "Relaunching process may make minizip available. Relaunch? Y|N"
#if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#} else {
#pwsh.exe
#}
if ($response -ieq "y") {
Start-Process 'getzig.cmd' -NoNewWindow -Wait
}
exit
}
}
#extract_zip to be called only after sig verified
;
function extractZip {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, Position = 0)][string] $releasearchive,
[Parameter(Mandatory=$true, Position = 1)] [string] $toolsfolder
)
Add-Type -Assembly "System.IO.Compression.Filesystem"
$outfile = Join-Path $toolsfolder -ChildPath $releasearchive
$zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive)
if (-not ($zip_rootname.Contains("zig"))) {
write-host "sanity check on zip_rootname '$zip_rootname' failed - aborting"
exit 1
}
$zip_extraction_folder = Join-Path -Path $toolsfolder -ChildPath $zip_rootname
if (Test-Path -Path $zip_extraction_folder -PathType Container) {
write-host "Existing folder found at $zip_extraction_folder - removing folder prior to extraction"
Remove-Item -Path $zip_extraction_folder -Recurse -Force -ErrorAction SilentlyContinue
}
#Expand-Archive -path $outfile -DestinationPath $toolsfolder -Force #This is *insanely* (many minutes vs seconds) slow on powershell 5 at least - we get a progress meter, but it's too high a price to pay.
# -------------------------------------
[System.IO.Compression.Zipfile]::ExtractToDirectory($outfile, $toolsfolder)
Write-Host " - archive extracted."
if (-not (Test-Path -Path $zip_extraction_folder -PathType Container)) {
write-host "Failed to verify extraction as folder at $zip_extraction_folder"
exit 1
}
$zigfolder = Join-Path $toolsfolder -ChildPath "zig"
$zigexe = Join-Path $zigfolder -ChildPath "zig.exe"
$retries = 10
$exe_missing = $true #missing until tested as a found leaf
$sleep_time = 2
while (($retries -gt 0) -and $exe_missing) {
$retries -= 1
#We *intermittently* get permission errors when trying to rename the resulting folder (possibly also if we try to delete the zip file immediately)
#There seems to be some sort of lock held after ExtractToDirectory (possibly AV related)
#https://stackoverflow.com/questions/74582293/file-lock-issues-on-zip-file-after-io-compression-zipfileextracttodirectory
#In some cases just the GC was enough.. but in other cases even sleep 3 seconds + GC didn't work
#sleep of 5 seems more reliable - but the size of the required delay may depend on what is running on the system,
# and the size of the extracted folder etc.
#Rather than use a large sleep to cover all cases - we use a limited retry loop with a somewhat shorter sleep e.g 2
Write-Host "waiting $sleep_time seconds and also running GC to allow locks to clear. Max remaining retries: $retries"
start-sleep -Seconds $sleep_time
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
# -------------------------------------
#Remove-Item -Path "$outfile"
#write-host "zip_rootname: $zip_rootname"
write-host "Attempting to move $zip_extraction_folder to ${zigfolder}"
Rename-Item -Path $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) -NewName $zigfolder -ErrorAction SilentlyContinue
if (-not $?) {
write-host "Renaming extracted folder into place at $zigfolder failed"
write-host " - error message: $($error[0].Exception.Message)"
}
if (Test-Path -Path $zigexe -PathType leaf) {
$exe_missing = $false
}
}
if (Test-Path -Path $zigexe -PathType leaf) {
Write-Host "Zig installed in ${zigfolder}"
return $true
} else {
Write-Host "Failed to install as $zigexe"
return $false
}
}
$zigpubkey = "RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U"
$outfile = Join-Path $toolsfolder -ChildPath $releasearchive
$sigfile = "${outfile}.minisig"
$download_required = $true #default assumption
if (Test-Path -Path $outfile -PathType Leaf) {
if (Test-Path -Path $sigfile) {
write-host "Found existing $outfile and ${outfile}.minisig - validating signature..."
$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 of existing $outfile with $outfile.minisig"
Remove-Item -Path $outfile -ErrorAction SilentlyContinue
Remove-Item -Path "${outfile}.minisig" -ErrorAction SilentlyContinue
} else {
$download_required = $false
}
}
}
if (-not $download_required) {
write-host "Existing zip and zip.minisig ok - download not required"
Write-Host "Signature OK - extracting existing archive ..."
$null = extractZip $releasearchive $toolsfolder
$zigexe = Join-Path $zigfolder -ChildPath "zig.exe"
$v = Invoke-Expression "$zigexe version"
Write-Host "ZIG VERSION: ${v}"
exit 0
}
$mirrors_url = "https://ziglang.org/download/community-mirrors.txt"
$mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url)
if ($mirrors_response.StatusCode -eq 200) {
#https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip
$mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools")
$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
$dict_mirrors[$hostname]["latency"] = 888888 ;#default
$host_list += $hostname
#write-host "Host name: $hostname"
}
#write-host "dict: $($dict_mirrors | out-String)"
write-host "host_list: $host_list"
$automation_name = "punkshell+julian@precisium.com.au_target_by_latency"
#test-netconnection progressbar seems not-so-well-behaved (prog bar lingers)
#test-netconnection a function not cmdlet? Seems to need setting at global level
$OriginalProgressPreference = $Global:ProgressPreference
$Global:ProgressPreference = 'SilentlyContinue'
#temporary dev download source
$ihost = "10.30.30.107"
$imirror = "http://10.30.30.107/jn/punkbin/raw/branch/master/win32-x86_64/tools"
$itrace = test-netconnection $ihost -Hops 6 -TraceRoute -ErrorAction Ignore
if ((${itrace}.PingSucceeded) -and (${itrace}.TraceRoute.Count -lt 5)) {
$host_list += $ihost
$dict_mirrors[$ihost] = @{}
$dict_mirrors[$ihost]["latency"] = 1
$dict_mirrors[$ihost]["uri"] = $imirror
}
$trace = test-netconnection gitea1.intx.com.au -Hops 6 -TraceRoute -ErrorAction Ignore
$Global:ProgressPreference = $OriginalProgressPreference
if ((${trace}.PingSucceeded) -and (${trace}.TraceRoute.Count -lt 5)) {
$dict_mirrors["gitea1.intx.com.au"]["latency"] = 2
#short-circuit for hosts very near gitea1.intx.com.au
#don't even test others. This is primarily for hosts at intx.com.au and associated entities - which are more likely to use punkshell than anyone else.
} else {
if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#we seem to need -ErrorAction Ignore for bad/unresponsive host entries - but unlike with pwsh, we don't get any corresponding entry in the test_results, and -Quiet doesn't seem to give us results either REVIEW
$test_results = Test-Connection $host_list -Count 1 -ErrorAction Ignore
for ($i = 0; $i -lt $test_results.Count; $i++) {
$result = $test_results[$i]
if ($result) {
$targethost = $result.Address
if ($result.StatusCode -eq 0) {
$dict_mirrors[$targethost]["latency"] = $result.ResponseTime
} else {
$dict_mirrors[$targethost]["latency"] = 999999
}
} else {
$targethost = $host_list[$i]
$dict_mirrors[$targethost]["latency"] = 999999
}
}
} else {
#pwsh.exe
$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])
}
#need to ensure latency cast to integer (on powershell 5 at least)
$sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property { [int]$_.latency }
#Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)"
Write-Host "Sorted by latency: $($sorted_mirror_dicts | Out-String)"
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}"
}
#download the minisig first - because if that fails, we should move on without trying the larger download
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 signature from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring"
continue
}
Write-Host "Downloading zig distribution from $full_uristring"
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 "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 downloaded archive ..."
$null = extractZip $releasearchive $toolsfolder
$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"
}
#</powershell-payload>

0
src/scriptapps/getzig.bash → src/scriptapps/bin/getzig.bash

643
src/scriptapps/getzig.ps1 → src/scriptapps/bin/getzig.ps1

@ -1,269 +1,374 @@
#launch example
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'cmd.exe' -ArgumentList @('/c', 'getzig.cmd') -NoNewWindow -Wait"
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'getzig.cmd' -NoNewWindow -Wait"
#Join-Path using verbose method to support powershell 5?
#$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.."
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
Write-host "Base folder: $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"
} else {
Write-Host "Failed to find minisign using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is now available"
} else {
Write-Host "minisign is still not available"
#if we automatically relaunch - we could get stuck in a loop - ask user.
$response = read-host -Prompt "Relaunching process may make minizip available. Relaunch? Y|N"
#if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#} else {
#pwsh.exe
#}
if ($response -ieq "y") {
Start-Process 'getzig.cmd' -NoNewWindow -Wait
}
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) {
#https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip
$mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools")
$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
$dict_mirrors[$hostname]["latency"] = 888888 ;#default
$host_list += $hostname
#write-host "Host name: $hostname"
}
#write-host "dict: $($dict_mirrors | out-String)"
write-host "host_list: $host_list"
$automation_name = "punkshell+julian@precisium.com.au_target_by_latency"
#test-netconnection progressbar seems not-so-well-behaved (prog bar lingers)
#test-netconnection a function not cmdlet? Seems to need setting at global level
$OriginalProgressPreference = $Global:ProgressPreference
$Global:ProgressPreference = 'SilentlyContinue'
#temporary dev download source
$ihost = "10.30.30.107"
$imirror = "http://10.30.30.107/jn/punkbin/raw/branch/master/win32-x86_64/tools"
$itrace = test-netconnection $ihost -Hops 6 -TraceRoute -ErrorAction Ignore
if ((${itrace}.PingSucceeded) -and (${itrace}.TraceRoute.Count -lt 5)) {
$host_list += $ihost
$dict_mirrors[$ihost] = @{}
$dict_mirrors[$ihost]["latency"] = 1
$dict_mirrors[$ihost]["uri"] = $imirror
}
$trace = test-netconnection gitea1.intx.com.au -Hops 6 -TraceRoute -ErrorAction Ignore
$Global:ProgressPreference = $OriginalProgressPreference
if ((${trace}.PingSucceeded) -and (${trace}.TraceRoute.Count -lt 5)) {
$dict_mirrors["gitea1.intx.com.au"]["latency"] = 2
#short-circuit for hosts very near gitea1.intx.com.au
#don't even test others. This is primarily for hosts at intx.com.au and associated entities - which are more likely to use punkshell than anyone else.
} else {
if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#we seem to need -ErrorAction Ignore for bad/unresponsive host entries - but unlike with pwsh, we don't get any corresponding entry in the test_results, and -Quiet doesn't seem to give us results either REVIEW
$test_results = Test-Connection $host_list -Count 1 -ErrorAction Ignore
for ($i = 0; $i -lt $test_results.Count; $i++) {
$result = $test_results[$i]
if ($result) {
$targethost = $result.Address
if ($result.StatusCode -eq 0) {
$dict_mirrors[$targethost]["latency"] = $result.ResponseTime
} else {
$dict_mirrors[$targethost]["latency"] = 999999
}
} else {
$targethost = $host_list[$i]
$dict_mirrors[$targethost]["latency"] = 999999
}
}
} else {
#pwsh.exe
$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])
}
#need to ensure latency cast to integer (on powershell 5 at least)
$sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property { [int]$_.latency }
#Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)"
Write-Host "Sorted by latency: $($sorted_mirror_dicts | Out-String)"
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 #This is *insanely* (many minutes vs seconds) slow on powershell 5 at least - we get a progress meter, but it's too high a price to pay.
# -------------------------------------
Add-Type -Assembly "System.IO.Compression.Filesystem"
[System.IO.Compression.Zipfile]::ExtractToDirectory($outfile, $toolsfolder)
Write-Host " - archive extracted."
#We *intermittently* get permission errors when trying to rename the resulting folder (possibly also if we try to delete the zip file immediately)
#There seems to be some sort of lock held after ExtractToDirectory (possibly AV related)
#https://stackoverflow.com/questions/74582293/file-lock-issues-on-zip-file-after-io-compression-zipfileextracttodirectory
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
# -------------------------------------
#Remove-Item -Path "$outfile"
$zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive)
#Rename-Item -Path
#write-host "zip_rootname: $zip_rootname"
write-host "moving $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) to ${zigfolder}"
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"
}
#launch example
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'cmd.exe' -ArgumentList @('/c', 'getzig.cmd') -NoNewWindow -Wait"
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/bin/getzig.cmd' -OutFile 'getzig.cmd'; Start-Process 'getzig.cmd' -NoNewWindow -Wait"
#Join-Path using verbose method to support powershell 5?
#$outbase = Join-Path -Path $PSScriptRoot -ChildPath "../.."
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
Write-host "Base folder: $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 -ChildPath "zig.exe"
# $releasearchive = "zig-x86_64-windows-0.15.1.zip" ;#zip on windows, tarball on every other platform
$releasearchive = "zig-x86_64-windows-0.16.0-dev.254+6dd0270a1.zip"
Write-Output "powershell version: $($PSVersionTable.PSVersion)"
if (Get-Command $zigexe -ErrorAction SilentlyContinue) {
$relative_zigfolder = Resolve-Path -Path $zigfolder -RelativeBasePath $outbase -Relative
Write-Host "zig.exe is installed in $relative_zigfolder"
$zigv = & $zigexe 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 ${zigexe}: $stderr"
Write-Host "Consider deleting $zigexe and re-downloading"
} else {
Write-Host "$zigexe 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 -Scope CurrentUser -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"
} else {
Write-Host "Failed to find minisign using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "minisign" -ErrorAction SilentlyContinue) {
Write-Host "minisign is now available"
} else {
Write-Host "minisign is still not available"
#if we automatically relaunch - we could get stuck in a loop - ask user.
$response = read-host -Prompt "Relaunching process may make minizip available. Relaunch? Y|N"
#if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#} else {
#pwsh.exe
#}
if ($response -ieq "y") {
Start-Process 'getzig.cmd' -NoNewWindow -Wait
}
exit
}
}
#extract_zip to be called only after sig verified
;
function extractZip {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, Position = 0)][string] $releasearchive,
[Parameter(Mandatory=$true, Position = 1)] [string] $toolsfolder
)
Add-Type -Assembly "System.IO.Compression.Filesystem"
$outfile = Join-Path $toolsfolder -ChildPath $releasearchive
$zip_rootname = [System.IO.Path]::GetFileNameWithoutExtension($releasearchive)
if (-not ($zip_rootname.Contains("zig"))) {
write-host "sanity check on zip_rootname '$zip_rootname' failed - aborting"
exit 1
}
$zip_extraction_folder = Join-Path -Path $toolsfolder -ChildPath $zip_rootname
if (Test-Path -Path $zip_extraction_folder -PathType Container) {
write-host "Existing folder found at $zip_extraction_folder - removing folder prior to extraction"
Remove-Item -Path $zip_extraction_folder -Recurse -Force -ErrorAction SilentlyContinue
}
#Expand-Archive -path $outfile -DestinationPath $toolsfolder -Force #This is *insanely* (many minutes vs seconds) slow on powershell 5 at least - we get a progress meter, but it's too high a price to pay.
# -------------------------------------
[System.IO.Compression.Zipfile]::ExtractToDirectory($outfile, $toolsfolder)
Write-Host " - archive extracted."
if (-not (Test-Path -Path $zip_extraction_folder -PathType Container)) {
write-host "Failed to verify extraction as folder at $zip_extraction_folder"
exit 1
}
$zigfolder = Join-Path $toolsfolder -ChildPath "zig"
$zigexe = Join-Path $zigfolder -ChildPath "zig.exe"
$retries = 10
$exe_missing = $true #missing until tested as a found leaf
$sleep_time = 2
while (($retries -gt 0) -and $exe_missing) {
$retries -= 1
#We *intermittently* get permission errors when trying to rename the resulting folder (possibly also if we try to delete the zip file immediately)
#There seems to be some sort of lock held after ExtractToDirectory (possibly AV related)
#https://stackoverflow.com/questions/74582293/file-lock-issues-on-zip-file-after-io-compression-zipfileextracttodirectory
#In some cases just the GC was enough.. but in other cases even sleep 3 seconds + GC didn't work
#sleep of 5 seems more reliable - but the size of the required delay may depend on what is running on the system,
# and the size of the extracted folder etc.
#Rather than use a large sleep to cover all cases - we use a limited retry loop with a somewhat shorter sleep e.g 2
Write-Host "waiting $sleep_time seconds and also running GC to allow locks to clear. Max remaining retries: $retries"
start-sleep -Seconds $sleep_time
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
# -------------------------------------
#Remove-Item -Path "$outfile"
#write-host "zip_rootname: $zip_rootname"
write-host "Attempting to move $zip_extraction_folder to ${zigfolder}"
Rename-Item -Path $(Join-Path -Path $toolsfolder -ChildPath $zip_rootname) -NewName $zigfolder -ErrorAction SilentlyContinue
if (-not $?) {
write-host "Renaming extracted folder into place at $zigfolder failed"
write-host " - error message: $($error[0].Exception.Message)"
}
if (Test-Path -Path $zigexe -PathType leaf) {
$exe_missing = $false
}
}
if (Test-Path -Path $zigexe -PathType leaf) {
Write-Host "Zig installed in ${zigfolder}"
return $true
} else {
Write-Host "Failed to install as $zigexe"
return $false
}
}
$zigpubkey = "RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U"
$outfile = Join-Path $toolsfolder -ChildPath $releasearchive
$sigfile = "${outfile}.minisig"
$download_required = $true #default assumption
if (Test-Path -Path $outfile -PathType Leaf) {
if (Test-Path -Path $sigfile) {
write-host "Found existing $outfile and ${outfile}.minisig - validating signature..."
$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 of existing $outfile with $outfile.minisig"
Remove-Item -Path $outfile -ErrorAction SilentlyContinue
Remove-Item -Path "${outfile}.minisig" -ErrorAction SilentlyContinue
} else {
$download_required = $false
}
}
}
if (-not $download_required) {
write-host "Existing zip and zip.minisig ok - download not required"
Write-Host "Signature OK - extracting existing archive ..."
$null = extractZip $releasearchive $toolsfolder
$zigexe = Join-Path $zigfolder -ChildPath "zig.exe"
$v = Invoke-Expression "$zigexe version"
Write-Host "ZIG VERSION: ${v}"
exit 0
}
$mirrors_url = "https://ziglang.org/download/community-mirrors.txt"
$mirrors_response = $(Invoke-WebRequest -Uri $mirrors_url)
if ($mirrors_response.StatusCode -eq 200) {
#https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools/zig-x86_64-windows-0.15.1.zip
$mirror_array = @("https://gitea1.intx.com.au/jn/punkbin/raw/branch/master/win32-x86_64/tools")
$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
$dict_mirrors[$hostname]["latency"] = 888888 ;#default
$host_list += $hostname
#write-host "Host name: $hostname"
}
#write-host "dict: $($dict_mirrors | out-String)"
write-host "host_list: $host_list"
$automation_name = "punkshell+julian@precisium.com.au_target_by_latency"
#test-netconnection progressbar seems not-so-well-behaved (prog bar lingers)
#test-netconnection a function not cmdlet? Seems to need setting at global level
$OriginalProgressPreference = $Global:ProgressPreference
$Global:ProgressPreference = 'SilentlyContinue'
#temporary dev download source
$ihost = "10.30.30.107"
$imirror = "http://10.30.30.107/jn/punkbin/raw/branch/master/win32-x86_64/tools"
$itrace = test-netconnection $ihost -Hops 6 -TraceRoute -ErrorAction Ignore
if ((${itrace}.PingSucceeded) -and (${itrace}.TraceRoute.Count -lt 5)) {
$host_list += $ihost
$dict_mirrors[$ihost] = @{}
$dict_mirrors[$ihost]["latency"] = 1
$dict_mirrors[$ihost]["uri"] = $imirror
}
$trace = test-netconnection gitea1.intx.com.au -Hops 6 -TraceRoute -ErrorAction Ignore
$Global:ProgressPreference = $OriginalProgressPreference
if ((${trace}.PingSucceeded) -and (${trace}.TraceRoute.Count -lt 5)) {
$dict_mirrors["gitea1.intx.com.au"]["latency"] = 2
#short-circuit for hosts very near gitea1.intx.com.au
#don't even test others. This is primarily for hosts at intx.com.au and associated entities - which are more likely to use punkshell than anyone else.
} else {
if ($PSVersionTable.PSEdition -eq "Desktop") {
#powershell.exe
#we seem to need -ErrorAction Ignore for bad/unresponsive host entries - but unlike with pwsh, we don't get any corresponding entry in the test_results, and -Quiet doesn't seem to give us results either REVIEW
$test_results = Test-Connection $host_list -Count 1 -ErrorAction Ignore
for ($i = 0; $i -lt $test_results.Count; $i++) {
$result = $test_results[$i]
if ($result) {
$targethost = $result.Address
if ($result.StatusCode -eq 0) {
$dict_mirrors[$targethost]["latency"] = $result.ResponseTime
} else {
$dict_mirrors[$targethost]["latency"] = 999999
}
} else {
$targethost = $host_list[$i]
$dict_mirrors[$targethost]["latency"] = 999999
}
}
} else {
#pwsh.exe
$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])
}
#need to ensure latency cast to integer (on powershell 5 at least)
$sorted_mirror_dicts = $list_mirror_dicts | Sort-Object -Property { [int]$_.latency }
#Write-Host "Sorted by latency: $($sorted_mirror_dicts | Format-Table -AutoSize | Out-String)"
Write-Host "Sorted by latency: $($sorted_mirror_dicts | Out-String)"
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}"
}
#download the minisig first - because if that fails, we should move on without trying the larger download
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 signature from $sig_uristring to ${outfile}.minisig .. aborting download from $uristring"
continue
}
Write-Host "Downloading zig distribution from $full_uristring"
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 "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 downloaded archive ..."
$null = extractZip $releasearchive $toolsfolder
$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"
}

36
src/scriptapps/getzig_original.polyglot → src/scriptapps/bin/getzig_original.polyglot

@ -1,18 +1,18 @@
#!/bin/sh
echo `# <#`
mkdir -p ./zig
wget https://ziglang.org/download/0.10.1/zig-linux-x86_64-0.10.1.tar.xz -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
exit
#> > $null
Invoke-WebRequest -Uri "https://ziglang.org/download/0.10.1/zig-windows-x86_64-0.10.1.zip" -OutFile ".\zig-windows-x86_64-0.10.1.zip"
Expand-Archive -Path ".\zig-windows-x86_64-0.10.1.zip" -DestinationPath ".\" -Force
Remove-Item -Path " .\zig-windows-x86_64-0.10.1.zip"
Rename-Item -Path ".\zig-windows-x86_64-0.10.1" -NewName ".\zig"
Write-Host "Zig installed."
./zig/zig.exe version
#!/bin/sh
echo `# <#`
mkdir -p ./zig
wget https://ziglang.org/download/0.10.1/zig-linux-x86_64-0.10.1.tar.xz -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
exit
#> > $null
Invoke-WebRequest -Uri "https://ziglang.org/download/0.10.1/zig-windows-x86_64-0.10.1.zip" -OutFile ".\zig-windows-x86_64-0.10.1.zip"
Expand-Archive -Path ".\zig-windows-x86_64-0.10.1.zip" -DestinationPath ".\" -Force
Remove-Item -Path " .\zig-windows-x86_64-0.10.1.zip"
Rename-Item -Path ".\zig-windows-x86_64-0.10.1" -NewName ".\zig"
Write-Host "Zig installed."
./zig/zig.exe version

42
src/scriptapps/getzig_wrap.toml → src/scriptapps/bin/getzig_wrap.toml

@ -1,21 +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 -nop -nol -ExecutionPolicy bypass -c"
win32.nextshelltype="pwsh"
win32.outputfile="getzig.cmd"
[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 -nop -nol -ExecutionPolicy bypass -c"
win32.nextshelltype="pwsh"
win32.outputfile="getzig.cmd"

352
src/scriptapps/getpunk.ps1

@ -1,176 +1,176 @@
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/getpunk.cmd' -OutFile 'getpunk.cmd'; Start-Process 'getpunk.cmd' -NoNewWindow -Wait"
#todo - support either fossil or git
#check if git available
#if not, check/install winget, winget git
$git_upstream = "https://gitea1.intx.com.au/jn/punkshell.git"
$launchdir = Get-Location #store original CWD
$scriptfolder = Resolve-Path (Split-Path -Path $PSCommandPath -Parent)
$punkfolder = ""
$scriptroot = "$([System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath))"
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (-not (Get-Command "git" -ErrorAction SilentlyContinue)) {
Write-Host "The git command doesn't seem to be available. 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"
}
$gitversion = (Find-WinGetPackage Git.Git).Version
if ($gitversion) {
Write-Host "Installing git version: ${gitversion}"
Install-WinGetPackage -Id "Git.Git"
} else {
Write-Host "Failed to find git using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "git" -ErrorAction SilentlyContinue) {
Write-Host "git is now available"
} else {
Write-Host "git is still not available"
Write-HOst "Please install Git or relaunch your terminal and check it is available on the path."
exit
}
}
if (($launchdir.Path) -ne ($scriptfolder.Path)) {
Write-Host "The current directory does not seem to be the folder in which the getpunk script is located."
$answer = Read-Host "Do you want to use the current directory '$($launchdir.Path) as the location for punkshell? Y|N`n Y to use launchdir '$($launchdir.Path)'`n 'N' to use script folder '$($scriptfolder.Path)`n Any other value to abort: "
if ($answer -match "y") {
$punkfolder = $launchdir
} elseif ($answer -match "n") {
$punkfolder = $scriptfolder
} else {
exit 1
}
} else {
$punkfolder = $scriptfolder
}
$punkfoldercontents = Get-ChildItem -Path $punkfolder -Force #include possibly hidden items such as .git folder
$contentcount = ( $punkfoldercontents | Measure-Object).Count
$effectively_empty = 0
if ($contentcount -eq 0) {
$effectively_empty = 1
} elseif ($punkfolder -eq $scriptfolder -and $contentcount -lt 10) {
#treat as empty if we have only a few files matching script root name
$scriptlike = get-childitem -Path $punkfolder | Where-Object {$_.name -like "${scriptroot}.*"}
if ($scriptlike.Count -eq $contentcount) {
$effectively_empty = 1
}
}
if (-not($effectively_empty)) {
if (-not(Test-Path -Path (Join-Path -Path $punkfolder -ChildPath ".git") -PathType Container)) {
Write-Host "The folder $punkfolder contains other items, and it does not appear to be a git project root."
Write-Host "Please place this script in an empty folder which is to be the punkshell base folder."
exit
} else {
$repo_origin = git remote get-url origin
if ($repo_origin -ne $git_upstream) {
Write-Host "The current repository origin '$repo_origin' is not the expected upstream '${git_upstream}'"
$answer = Read-Host "Continue anyway? (Y|N)"
if (-not($answer -match "y")) {
exit 1
}
}
}
} else {
#punkfolder is empty, or has just the current script
}
Set-Location -Path $punkfolder
if (-not(Test-Path -Path (Join-Path -Path $punkfolder -ChildPath ".git") -PathType Container)) {
git init
git remote add origin $git_upstream
}
git fetch origin
if (($launchdir.Path) -eq ($scriptfolder.Path)) {
if (Test-Path -Path "${scriptroot}.cmd") {
#rename-item won't allow overwriting existing target file
Move-Item -Path "${scriptroot}.cmd" -Destination "${scriptroot}.cmd.lastrun" -Force
}
}
git pull $git_upstream master
git checkout "${scriptroot}.cmd"
git branch --set-upstream-to=origin/master master
Set-Location $launchdir #restore original CWD
#see also: https://github.com/jdhitsolutions/WTToolbox
# Define the necessary Win32 API functions and constants
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class WinAPI
{
// Console Input/Output Handles
public const int STD_OUTPUT_HANDLE = -11;
public const uint ENABLE_QUICK_EDIT_MODE = 0x0040;
public const uint ENABLE_EXTENDED_FLAGS = 0x0080;
public const uint ENABLE_MOUSE_INPUT = 0x0010;
public const uint ENABLE_WINDOW_INPUT = 0x0008;
public const uint ENABLE_INSERT_MODE = 0x0020;
public const uint ENABLE_LINE_INPUT = 0x0002;
public const uint ENABLE_ECHO_INPUT = 0x0004;
public const uint ENABLE_PROCESSED_INPUT = 0x0001;
// Console Modes
public const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
public const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
}
"@
# Get the handle to the console output buffer
$stdoutHandle = [WinAPI]::GetStdHandle([WinAPI]::STD_OUTPUT_HANDLE)
# Get the current console mode
[uint32]$currentMode = 0
if (![WinAPI]::GetConsoleMode($stdoutHandle, [ref]$currentMode)) {
Write-Error "Failed to get console mode. Error code: $($LAST_ERROR)"
return
}
# Enable virtual terminal processing
$newMode = $currentMode -bor [WinAPI]::ENABLE_VIRTUAL_TERMINAL_PROCESSING
# Set the new console mode
if (-not [WinAPI]::SetConsoleMode($stdoutHandle, $newMode)) {
Write-Error "Failed to set console mode. Error code: $($LAST_ERROR)"
return
}
Write-Host "Virtual terminal processing enabled successfully."
write-host "`e[92m getpunk done `e[m"
#powershell -Command "Invoke-WebRequest -Uri 'https://www.gitea1.intx.com.au/jn/punkshell/raw/branch/master/getpunk.cmd' -OutFile 'getpunk.cmd'; Start-Process 'getpunk.cmd' -NoNewWindow -Wait"
#todo - support either fossil or git
#check if git available
#if not, check/install winget, winget git
$git_upstream = "https://gitea1.intx.com.au/jn/punkshell.git"
$launchdir = Get-Location #store original CWD
$scriptfolder = Resolve-Path (Split-Path -Path $PSCommandPath -Parent)
$punkfolder = ""
$scriptroot = "$([System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath))"
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (-not (Get-Command "git" -ErrorAction SilentlyContinue)) {
Write-Host "The git command doesn't seem to be available. 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"
}
$gitversion = (Find-WinGetPackage Git.Git).Version
if ($gitversion) {
Write-Host "Installing git version: ${gitversion}"
Install-WinGetPackage -Id "Git.Git"
} else {
Write-Host "Failed to find git using winget"
exit
}
#refreshing the current session's path should make the new command available (required for powershell 5 at least)
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
if (Get-Command "git" -ErrorAction SilentlyContinue) {
Write-Host "git is now available"
} else {
Write-Host "git is still not available"
Write-HOst "Please install Git or relaunch your terminal and check it is available on the path."
exit
}
}
if (($launchdir.Path) -ne ($scriptfolder.Path)) {
Write-Host "The current directory does not seem to be the folder in which the getpunk script is located."
$answer = Read-Host "Do you want to use the current directory '$($launchdir.Path) as the location for punkshell? Y|N`n Y to use launchdir '$($launchdir.Path)'`n 'N' to use script folder '$($scriptfolder.Path)`n Any other value to abort: "
if ($answer -match "y") {
$punkfolder = $launchdir
} elseif ($answer -match "n") {
$punkfolder = $scriptfolder
} else {
exit 1
}
} else {
$punkfolder = $scriptfolder
}
$punkfoldercontents = Get-ChildItem -Path $punkfolder -Force #include possibly hidden items such as .git folder
$contentcount = ( $punkfoldercontents | Measure-Object).Count
$effectively_empty = 0
if ($contentcount -eq 0) {
$effectively_empty = 1
} elseif ($punkfolder -eq $scriptfolder -and $contentcount -lt 10) {
#treat as empty if we have only a few files matching script root name
$scriptlike = get-childitem -Path $punkfolder | Where-Object {$_.name -like "${scriptroot}.*"}
if ($scriptlike.Count -eq $contentcount) {
$effectively_empty = 1
}
}
if (-not($effectively_empty)) {
if (-not(Test-Path -Path (Join-Path -Path $punkfolder -ChildPath ".git") -PathType Container)) {
Write-Host "The folder $punkfolder contains other items, and it does not appear to be a git project root."
Write-Host "Please place this script in an empty folder which is to be the punkshell base folder."
exit
} else {
$repo_origin = git remote get-url origin
if ($repo_origin -ne $git_upstream) {
Write-Host "The current repository origin '$repo_origin' is not the expected upstream '${git_upstream}'"
$answer = Read-Host "Continue anyway? (Y|N)"
if (-not($answer -match "y")) {
exit 1
}
}
}
} else {
#punkfolder is empty, or has just the current script
}
Set-Location -Path $punkfolder
if (-not(Test-Path -Path (Join-Path -Path $punkfolder -ChildPath ".git") -PathType Container)) {
git init
git remote add origin $git_upstream
}
git fetch origin
if (($launchdir.Path) -eq ($scriptfolder.Path)) {
if (Test-Path -Path "${scriptroot}.cmd") {
#Rename-Item won't allow overwriting existing target file
Move-Item -Path "${scriptroot}.cmd" -Destination "${scriptroot}.cmd.lastrun" -Force
}
}
git pull $git_upstream master
git checkout "${scriptroot}.cmd"
git branch --set-upstream-to=origin/master master
Set-Location $launchdir #restore original CWD
#see also: https://github.com/jdhitsolutions/WTToolbox
# Define the necessary Win32 API functions and constants
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class WinAPI
{
// Console Input/Output Handles
public const int STD_OUTPUT_HANDLE = -11;
public const uint ENABLE_QUICK_EDIT_MODE = 0x0040;
public const uint ENABLE_EXTENDED_FLAGS = 0x0080;
public const uint ENABLE_MOUSE_INPUT = 0x0010;
public const uint ENABLE_WINDOW_INPUT = 0x0008;
public const uint ENABLE_INSERT_MODE = 0x0020;
public const uint ENABLE_LINE_INPUT = 0x0002;
public const uint ENABLE_ECHO_INPUT = 0x0004;
public const uint ENABLE_PROCESSED_INPUT = 0x0001;
// Console Modes
public const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
public const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
}
"@
# Get the handle to the console output buffer
$stdoutHandle = [WinAPI]::GetStdHandle([WinAPI]::STD_OUTPUT_HANDLE)
# Get the current console mode
[uint32]$currentMode = 0
if (![WinAPI]::GetConsoleMode($stdoutHandle, [ref]$currentMode)) {
Write-Error "Failed to get console mode. Error code: $($LAST_ERROR)"
return
}
# Enable virtual terminal processing
$newMode = $currentMode -bor [WinAPI]::ENABLE_VIRTUAL_TERMINAL_PROCESSING
# Set the new console mode
if (-not [WinAPI]::SetConsoleMode($stdoutHandle, $newMode)) {
Write-Error "Failed to set console mode. Error code: $($LAST_ERROR)"
return
}
Write-Host "Virtual terminal processing enabled successfully."
write-host "`e[92m getpunk done `e[m"

46
src/scriptapps/getpunk_wrap.toml

@ -1,23 +1,23 @@
[application]
template="punk.multishell.cmd"
as_admin=false
scripts=[
"getpunk.ps1",
"getpunk.bash"
]
default_outputfile="getpunk.cmd"
default_nextshellpath="/usr/bin/env bash"
default_nextshelltype="bash"
#valid nextshelltype entries are: tcl perl powershell bash.
#nextshellpath entries must be 128 characters or less.
#win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -File"
#win32.nextshelltype="pwsh"
win32.nextshellpath="cmd.exe /c powershell -nop -nol -ExecutionPolicy ByPass -File"
win32.nextshelltype="powershell"
win32.outputfile="getpunk.cmd"
[application]
template="punk.multishell.cmd"
as_admin=false
scripts=[
"getpunk.ps1",
"getpunk.bash"
]
default_outputfile="getpunk.cmd"
default_nextshellpath="/usr/bin/env bash"
default_nextshelltype="bash"
#valid nextshelltype entries are: tcl perl powershell bash.
#nextshellpath entries must be 128 characters or less.
#win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -File"
#win32.nextshelltype="pwsh"
win32.nextshellpath="cmd.exe /c powershell -nop -nol -ExecutionPolicy ByPass -File"
win32.nextshelltype="powershell"
win32.outputfile="getpunk.cmd"

832
src/scriptapps/runtime.ps1

@ -1,416 +1,416 @@
function GetDynamicParamDictionary {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true, Mandatory=$true)]
[string] $CommandName
)
begin {
# Get a list of params that should be ignored (they're common to all advanced functions)
$CommonParameterNames = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject([type] [System.Management.Automation.Internal.CommonParameters]) |
Get-Member -MemberType Properties |
Select-Object -ExpandProperty Name
}
process {
# Create the dictionary that this scriptblock will return:
$DynParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
# Convert to object array and get rid of Common params:
(Get-Command $CommandName | Select-Object -exp Parameters).GetEnumerator() |
Where-Object { $CommonParameterNames -notcontains $_.Key } |
ForEach-Object {
$DynamicParameter = New-Object System.Management.Automation.RuntimeDefinedParameter (
$_.Key,
$_.Value.ParameterType,
$_.Value.Attributes
)
$DynParamDictionary.Add($_.Key, $DynamicParameter)
}
# Return the dynamic parameters
return $DynParamDictionary
}
}
function ParameterDefinitions {
param(
[Parameter(ValueFromRemainingArguments=$true,Position = 1)][string[]] $opts
)
}
function psmain {
[CmdletBinding()]
#Empty param block (extra params can be added)
param(
[Parameter(Mandatory=$false, Position = 0)][string] $action = ""
)
dynamicparam {
if ($action -eq 'list') {
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "listruntime"
Mandatory = $false
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'remote', [switch], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('remote', $dynParam1)
return $paramDictionary
} elseif ($action -eq 'fetch') {
#GetDynamicParamDictionary ParameterDefinitions
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "fetchruntime"
Mandatory = $false
Position = 1
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'runtime', [string], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('runtime', $dynParam1)
return $paramDictionary
} elseif ($action -eq 'run') {
#GetDynamicParamDictionary ParameterDefinitions
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "runargs"
Mandatory = $false
ValueFromRemainingArguments = $true
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'opts', [string[]], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('opts', $dynParam1)
return $paramDictionary
} else {
#accept all args when action is unrecognised - so we can go to help anyway
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "invalidaction"
Mandatory = $false
ValueFromRemainingArguments = $true
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'opts', [string[]], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('opts', $dynParam1)
return $paramDictionary
}
}
process {
#Called once - we get a single item being our PSBoundParameters dictionary
#write-host "Bound Parameters:$($PSBoundParameters.Keys)"
switch ($PSBoundParameters.keys) {
'action' {
write-host "got action " $PSBoundParameters.action
Set-Variable -Name $_ -Value $PSBoundParameters."$_"
$known_actions = @("fetch", "list", "run")
if (-not($known_actions -contains $action)) {
write-host "fetch '$action' not understood. Known_actions: $known_actions"
exit 1
}
}
'opts' {
# write-warning "Unused parameters: $($PSBoundParameters.$_)"
}
Default {
# write-warning "Unhandled parameter -> [$($_)]"
}
}
#foreach ($boundparam in $PSBoundParameters.Keys) {
# write-host "k: $boundparam"
#}
}
end {
# PSBoundParameters
#write-host "action:'$action'"
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
#expected script location is the bin folder of a punk project
$rtfolder = Join-Path -Path $outbase -ChildPath "runtime"
#Binary artifact server url. (git is not ideal for this - but will do for now - todo - use artifact system within gitea?)
$artifacturl = "https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
switch ($action) {
'fetch' {
$arch = "win32-x86_64"
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
$archurl = "$artifacturl/$arch"
$sha1url = "$archurl/sha1sums.txt"
$runtime = "tclsh902z.exe"
foreach ($boundparam in $PSBoundParameters.Keys) {
write-host "fetchopt: $boundparam $($PSBoundParameters[$boundparam])"
}
if ( $PSBoundParameters["runtime"].Length ) {
$runtime = $PSBoundParameters["runtime"]
}
$fileurl = "$archurl/$runtime"
$output = join-path -Path $archfolder -ChildPath $runtime
$sha1local = join-path -Path $archfolder -ChildPath "sha1sums.txt"
$container = split-path -Path $output -Parent
new-item -Path $container -ItemType Directory -force #create with intermediary folders if not already present
try {
Write-Host "Fetching $sha1url"
Invoke-WebRequest -Uri $sha1url -OutFile $sha1local -ErrorAction Stop
Write-Host "sha1 saved at $sha1local"
} catch {
Write-Host "An error occurred while downloading ${sha1url}: $($_.Exception.Message)"
if ($_.Exception.Response) {
Write-Host "HTTP Status code: $($_.Exception.Response.StatusCode)"
}
}
if (Test-Path -Path $sha1local -PathType Leaf) {
$sha1Content = Get-Content -Path $sha1local
$stored_sha1 = ""
foreach ($line in $sha1Content) {
#all sha1sums have * (binary indicator) - review
$match = [regex]::Match($line,"(.*) [*]${runtime}$")
if ($match.Success) {
$stored_sha1 = $match.Groups[1].Value
Write-host "stored hash from sha1sums.txt: $storedhash"
break
}
}
if ($stored_sha1 -eq "") {
Write-Host "Unable to locate hash for $runtime in $sha1local - Aborting"
Write-Host "Please download and verify manually"
return
}
$need_download = $false
if (Test-Path -Path $output -PathType Leaf) {
Write-Host "Runtime already found at $output"
Write-Host "Checking sha1 checksum of local file versus sha1 of server file"
$file_sha1 = Get-FileHash -Path "$output" -Algorithm SHA1
if (${file_sha1}.Hash -ne $stored_sha1) {
Write-Host "$runtime on server has different sha1 hash - Download required"
$need_download = $true
}
} else {
Write-Host "$runtime not found locally - Download required"
$need_download = $true
}
if ($need_download) {
Write-Host "Downloading from $fileurl ..."
try {
Invoke-WebRequest -Uri $fileurl -OutFile "${output}.tmp" -ErrorAction Stop
Write-Host "Runtime saved at $output.tmp"
}
catch {
Write-Host "An error occurred while downloading $fileurl $($_.Exception.Message)"
if ($_.Exception.Response) {
Write-Host "HTTP Status code: $($_.Exception.Response.StatusCode)"
}
return
}
Write-Host "comparing sha1 checksum of downloaded file with data in sha1sums.txt"
Start-Sleep -Seconds 1 #REVIEW - give at least some time for windows to do its thing? (av filters?)
$newfile_sha1 = Get-FileHash -Path "${output}.tmp" -Algorithm SHA1
if (${newfile_sha1}.Hash -eq $stored_sha1) {
Write-Host "sha1 checksum ok"
Move-Item -Path "${output}.tmp" -Destination "${output}" -Force
Write-Host "Runtime is available at ${output}"
} else {
Write-Host "WARNING! sha1 of downloaded file at $output.tmp does not match stored sha1 from sha1sums.txt"
return
}
} else {
Write-Host "Local copy of runtime at $output seems to match sha1 checksum of file on server."
Write-Host "No download required"
}
} else {
Write-Host "Unable to consult local copy of sha1sums.txt at $sha1local"
if (Test-Path -Path $output -PathType Leaf) {
Write-Host "A runtime is available at $output - but we failed to retrieve the list of sha1sums from the server"
Write-Host "Unable to check for updated version at this time."
} else {
Write-Host "Please retry - or manually download a runtime from $archurl and verify checksums"
}
}
}
'run' {
#select first (or configured default) runtime and launch, passing arguments
$arch = "win32-x86_64"
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
if (-not(Test-Path -Path $archfolder -PathType Container)) {
write-host "No runtimes seem to be installed for $arch`nPlease use 'runtime.cmd fetch' to install"
} else {
$dircontents = (get-childItem -Path $archfolder -File | Sort-Object Name)
if ($dircontents.Count -gt 0) {
#write-host "run.."
write-host "num params: $($PSBoundParameters.opts.count)"
#todo - use 'active' runtime - need to lookup (PSToml?)
#when no 'active' runtime for this os-arch - use last item (sorted in dictionary order)
$active = $dircontents[-1].FullName
write-host "using: $active"
if ($PSBoundParameters.opts.Length -gt 0) {
$optsType = $PSBoundParameters.opts.GetType() #method can only be called if .opts is not null
write-host "type of opts: $($optsType.FullName)"
foreach ($boundparam in $PSBoundParameters.opts) {
write-host $boundparam
}
Write-Host "opts: $($PSBoundParameters.opts)"
Write-Host "args: $args"
Write-HOst "argscount: $($args.Count)"
$arglist = @()
foreach ($o in $PSBoundParameters.opts) {
$oquoted = $o -replace '"', "`\`""
#$oquoted = $oquoted -replace "'", "`'"
if ($oquoted -match "\s") {
$oquoted = "`"$oquoted`""
}
$arglist += @($oquoted)
}
$arglist = $arglist.TrimEnd(' ')
write-host "arglist: $arglist"
#$arglist = $PSBoundParameters.opts
Start-Process -FilePath $active -ArgumentList $arglist -NoNewWindow -Wait
} else {
#powershell 5.1 and earlier can't accept an empty -ArgumentList value :/ !!
#$arglist = @()
#Start-Process -FilePath $active -ArgumentList $arglist -NoNewWindow -Wait
#Start-Process -FilePath $active -ArgumentList "" -NoNewWindow -Wait
Start-Process -FilePath $active -NoNewWindow -Wait
}
} else {
write-host "No files found in $archfolder"
write-host "No runtimes seem to be installed for $arch`nPlease use 'runtime.cmd fetch' to install."
}
}
}
'list' {
#todo - option to list for other os-arch
$arch = 'win32-x86_64'
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
$sha1local = join-path -Path $archfolder -ChildPath "sha1sums.txt"
$archurl = "$artifacturl/$arch"
$sha1url = "$archurl/sha1sums.txt"
if ( $PSBoundParameters.ContainsKey('remote') ) {
if (-not (test-path -Path $archfolder -Type Container)) {
new-item -Path $container -ItemType Directory -force #create with intermediary folders if not already present
}
write-host "Checking for available remote runtimes for"
Write-Host "Fetching $sha1url"
Invoke-WebRequest -Uri $sha1url -OutFile $sha1local -ErrorAction Stop
Write-Host "sha1 saved at $sha1local"
$sha1Content = Get-Content -Path $sha1local
$remotedict = @{}
foreach ($line in $sha1Content) {
#all sha1sums have * (binary indicator) - review
$match = [regex]::Match($line,"(.*) [*](.*)$")
if ($match.Success) {
$server_sha1 = $match.Groups[1].Value
$server_rt = $match.Groups[2].Value
$remotedict[$server_rt] = $server_sha1
}
}
$localdict = @{}
if (test-path -Path $archfolder -Type Container) {
$dircontents = (get-childItem -Path $archfolder -File | Where-object {-not ($(".txt",".tm") -contains $_.Extension) })
foreach ($f in $dircontents) {
$local_sha1 = Get-FileHash -Path $(${f}.FullName) -Algorithm SHA1
$localdict[$f.Name] = ${local_sha1}.Hash
}
}
Write-host "-----------------------------------------------------------------------"
Write-host "Runtimes for $arch"
Write-host "Local $archfolder"
Write-host "Remote $archurl"
Write-host "-----------------------------------------------------------------------"
Write-host "Local Remote"
Write-host "-----------------------------------------------------------------------"
# 12345678910234567892023456789302345
$G = "`e[32m" #Green
$Y = "`e[33m" #Yellow
$R = "`e[31m" #Red
$RST = "`e[m"
foreach ($key in $localdict.Keys) {
$local_sha1 = $($localdict[$key])
if ($remotedict.ContainsKey($key)) {
if ($local_sha1 -eq $remotedict[$key]) {
$rhs = "Same version"
$C = $G
} else {
$rhs = "UPDATE AVAILABLE"
$C = $Y
}
} else {
$C = $R
$rhs = "(not listed on server)"
}
#ansi problems from cmd.exe not in windows terminal - review
$C = ""
$RST = ""
$lhs = "$key".PadRight(35, ' ')
write-host -nonewline "${C}${lhs}${RST}"
write-host $rhs
}
$lhs_missing = "-".PadRight(35, ' ')
foreach ($key in $remotedict.Keys) {
if (-not ($localdict.ContainsKey($key))) {
write-host -nonewline $lhs_missing
write-host $key
}
}
Write-host "-----------------------------------------------------------------------"
} else {
if (test-path -Path $archfolder -Type Container) {
Write-host "-----------------------------------------------------------------------"
Write-Host "Local runtimes for $arch"
$dircontents = (get-childItem -Path $archfolder -File | Where-object {-not ($(".txt",".tm") -contains $_.Extension) })
write-host "$(${dircontents}.count) files in $archfolder"
Write-host "-----------------------------------------------------------------------"
foreach ($f in $dircontents) {
write-host $f.Name
}
Write-host "-----------------------------------------------------------------------"
Write-host "Use: 'list -remote' to compare local runtimes with those available on the artifact server"
} else {
write-host "No runtimes seem to be installed for $arch in $archfolder`nPlease use 'runtime.cmd fetch' to install."
write-host "Use 'runtime.cmd list -remote' to see available runtimes for $arch"
}
}
}
default {
$actions = @("fetch", "list", "run")
write-host "Available actions: $actions"
write-host "received"
foreach ($boundparam in $PSBoundParameters.opts) {
write-host $boundparam
}
}
}
return $PSBoundParameters
}
}
#write-host (psmain @args)
#$returnvalue = psmain @args
#Write-Host "Function Returned $returnvalue" -ForegroundColor Cyan
#return $returnvalue
psmain @args | out-null
exit 0
function GetDynamicParamDictionary {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true, Mandatory=$true)]
[string] $CommandName
)
begin {
# Get a list of params that should be ignored (they're common to all advanced functions)
$CommonParameterNames = [System.Runtime.Serialization.FormatterServices]::GetUninitializedObject([type] [System.Management.Automation.Internal.CommonParameters]) |
Get-Member -MemberType Properties |
Select-Object -ExpandProperty Name
}
process {
# Create the dictionary that this scriptblock will return:
$DynParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
# Convert to object array and get rid of Common params:
(Get-Command $CommandName | Select-Object -exp Parameters).GetEnumerator() |
Where-Object { $CommonParameterNames -notcontains $_.Key } |
ForEach-Object {
$DynamicParameter = New-Object System.Management.Automation.RuntimeDefinedParameter (
$_.Key,
$_.Value.ParameterType,
$_.Value.Attributes
)
$DynParamDictionary.Add($_.Key, $DynamicParameter)
}
# Return the dynamic parameters
return $DynParamDictionary
}
}
function ParameterDefinitions {
param(
[Parameter(ValueFromRemainingArguments=$true,Position = 1)][string[]] $opts
)
}
function psmain {
[CmdletBinding()]
#Empty param block (extra params can be added)
param(
[Parameter(Mandatory=$false, Position = 0)][string] $action = ""
)
dynamicparam {
if ($action -eq 'list') {
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "listruntime"
Mandatory = $false
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'remote', [switch], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('remote', $dynParam1)
return $paramDictionary
} elseif ($action -eq 'fetch') {
#GetDynamicParamDictionary ParameterDefinitions
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "fetchruntime"
Mandatory = $false
Position = 1
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'runtime', [string], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('runtime', $dynParam1)
return $paramDictionary
} elseif ($action -eq 'run') {
#GetDynamicParamDictionary ParameterDefinitions
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "runargs"
Mandatory = $false
ValueFromRemainingArguments = $true
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'opts', [string[]], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('opts', $dynParam1)
return $paramDictionary
} else {
#accept all args when action is unrecognised - so we can go to help anyway
$parameterAttribute = [System.Management.Automation.ParameterAttribute]@{
ParameterSetName = "invalidaction"
Mandatory = $false
ValueFromRemainingArguments = $true
}
$attributeCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attributeCollection.Add($parameterAttribute)
$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new(
'opts', [string[]], $attributeCollection
)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add('opts', $dynParam1)
return $paramDictionary
}
}
process {
#Called once - we get a single item being our PSBoundParameters dictionary
#write-host "Bound Parameters:$($PSBoundParameters.Keys)"
switch ($PSBoundParameters.keys) {
'action' {
write-host "got action " $PSBoundParameters.action
Set-Variable -Name $_ -Value $PSBoundParameters."$_"
$known_actions = @("fetch", "list", "run")
if (-not($known_actions -contains $action)) {
write-host "fetch '$action' not understood. Known_actions: $known_actions"
exit 1
}
}
'opts' {
# write-warning "Unused parameters: $($PSBoundParameters.$_)"
}
Default {
# write-warning "Unhandled parameter -> [$($_)]"
}
}
#foreach ($boundparam in $PSBoundParameters.Keys) {
# write-host "k: $boundparam"
#}
}
end {
# PSBoundParameters
#write-host "action:'$action'"
$outbase = $PSScriptRoot
$outbase = Resolve-Path -Path $outbase
#expected script location is the bin folder of a punk project
$rtfolder = Join-Path -Path $outbase -ChildPath "runtime"
#Binary artifact server url. (git is not ideal for this - but will do for now - todo - use artifact system within gitea?)
$artifacturl = "https://www.gitea1.intx.com.au/jn/punkbin/raw/branch/master"
switch ($action) {
'fetch' {
$arch = "win32-x86_64"
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
$archurl = "$artifacturl/$arch"
$sha1url = "$archurl/sha1sums.txt"
$runtime = "tclsh902z.exe"
foreach ($boundparam in $PSBoundParameters.Keys) {
write-host "fetchopt: $boundparam $($PSBoundParameters[$boundparam])"
}
if ( $PSBoundParameters["runtime"].Length ) {
$runtime = $PSBoundParameters["runtime"]
}
$fileurl = "$archurl/$runtime"
$output = join-path -Path $archfolder -ChildPath $runtime
$sha1local = join-path -Path $archfolder -ChildPath "sha1sums.txt"
$container = split-path -Path $output -Parent
new-item -Path $container -ItemType Directory -force #create with intermediary folders if not already present
try {
Write-Host "Fetching $sha1url"
Invoke-WebRequest -Uri $sha1url -OutFile $sha1local -ErrorAction Stop
Write-Host "sha1 saved at $sha1local"
} catch {
Write-Host "An error occurred while downloading ${sha1url}: $($_.Exception.Message)"
if ($_.Exception.Response) {
Write-Host "HTTP Status code: $($_.Exception.Response.StatusCode)"
}
}
if (Test-Path -Path $sha1local -PathType Leaf) {
$sha1Content = Get-Content -Path $sha1local
$stored_sha1 = ""
foreach ($line in $sha1Content) {
#all sha1sums have * (binary indicator) - review
$match = [regex]::Match($line,"(.*) [*]${runtime}$")
if ($match.Success) {
$stored_sha1 = $match.Groups[1].Value
Write-host "stored hash from sha1sums.txt: $storedhash"
break
}
}
if ($stored_sha1 -eq "") {
Write-Host "Unable to locate hash for $runtime in $sha1local - Aborting"
Write-Host "Please download and verify manually"
return
}
$need_download = $false
if (Test-Path -Path $output -PathType Leaf) {
Write-Host "Runtime already found at $output"
Write-Host "Checking sha1 checksum of local file versus sha1 of server file"
$file_sha1 = Get-FileHash -Path "$output" -Algorithm SHA1
if (${file_sha1}.Hash -ne $stored_sha1) {
Write-Host "$runtime on server has different sha1 hash - Download required"
$need_download = $true
}
} else {
Write-Host "$runtime not found locally - Download required"
$need_download = $true
}
if ($need_download) {
Write-Host "Downloading from $fileurl ..."
try {
Invoke-WebRequest -Uri $fileurl -OutFile "${output}.tmp" -ErrorAction Stop
Write-Host "Runtime saved at $output.tmp"
}
catch {
Write-Host "An error occurred while downloading $fileurl $($_.Exception.Message)"
if ($_.Exception.Response) {
Write-Host "HTTP Status code: $($_.Exception.Response.StatusCode)"
}
return
}
Write-Host "comparing sha1 checksum of downloaded file with data in sha1sums.txt"
Start-Sleep -Seconds 1 #REVIEW - give at least some time for windows to do its thing? (av filters?)
$newfile_sha1 = Get-FileHash -Path "${output}.tmp" -Algorithm SHA1
if (${newfile_sha1}.Hash -eq $stored_sha1) {
Write-Host "sha1 checksum ok"
Move-Item -Path "${output}.tmp" -Destination "${output}" -Force
Write-Host "Runtime is available at ${output}"
} else {
Write-Host "WARNING! sha1 of downloaded file at $output.tmp does not match stored sha1 from sha1sums.txt"
return
}
} else {
Write-Host "Local copy of runtime at $output seems to match sha1 checksum of file on server."
Write-Host "No download required"
}
} else {
Write-Host "Unable to consult local copy of sha1sums.txt at $sha1local"
if (Test-Path -Path $output -PathType Leaf) {
Write-Host "A runtime is available at $output - but we failed to retrieve the list of sha1sums from the server"
Write-Host "Unable to check for updated version at this time."
} else {
Write-Host "Please retry - or manually download a runtime from $archurl and verify checksums"
}
}
}
'run' {
#select first (or configured default) runtime and launch, passing arguments
$arch = "win32-x86_64"
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
if (-not(Test-Path -Path $archfolder -PathType Container)) {
write-host "No runtimes seem to be installed for $arch`nPlease use 'runtime.cmd fetch' to install"
} else {
$dircontents = (get-childItem -Path $archfolder -File | Sort-Object Name)
if ($dircontents.Count -gt 0) {
#write-host "run.."
write-host "num params: $($PSBoundParameters.opts.count)"
#todo - use 'active' runtime - need to lookup (PSToml?)
#when no 'active' runtime for this os-arch - use last item (sorted in dictionary order)
$active = $dircontents[-1].FullName
write-host "using: $active"
if ($PSBoundParameters.opts.Length -gt 0) {
$optsType = $PSBoundParameters.opts.GetType() #method can only be called if .opts is not null
write-host "type of opts: $($optsType.FullName)"
foreach ($boundparam in $PSBoundParameters.opts) {
write-host $boundparam
}
Write-Host "opts: $($PSBoundParameters.opts)"
Write-Host "args: $args"
Write-HOst "argscount: $($args.Count)"
$arglist = @()
foreach ($o in $PSBoundParameters.opts) {
$oquoted = $o -replace '"', "`\`""
#$oquoted = $oquoted -replace "'", "`'"
if ($oquoted -match "\s") {
$oquoted = "`"$oquoted`""
}
$arglist += @($oquoted)
}
$arglist = $arglist.TrimEnd(' ')
write-host "arglist: $arglist"
#$arglist = $PSBoundParameters.opts
Start-Process -FilePath $active -ArgumentList $arglist -NoNewWindow -Wait
} else {
#powershell 5.1 and earlier can't accept an empty -ArgumentList value :/ !!
#$arglist = @()
#Start-Process -FilePath $active -ArgumentList $arglist -NoNewWindow -Wait
#Start-Process -FilePath $active -ArgumentList "" -NoNewWindow -Wait
Start-Process -FilePath $active -NoNewWindow -Wait
}
} else {
write-host "No files found in $archfolder"
write-host "No runtimes seem to be installed for $arch`nPlease use 'runtime.cmd fetch' to install."
}
}
}
'list' {
#todo - option to list for other os-arch
$arch = 'win32-x86_64'
$archfolder = Join-Path -Path $rtfolder -ChildPath "$arch"
$sha1local = join-path -Path $archfolder -ChildPath "sha1sums.txt"
$archurl = "$artifacturl/$arch"
$sha1url = "$archurl/sha1sums.txt"
if ( $PSBoundParameters.ContainsKey('remote') ) {
if (-not (test-path -Path $archfolder -Type Container)) {
new-item -Path $container -ItemType Directory -force #create with intermediary folders if not already present
}
write-host "Checking for available remote runtimes for"
Write-Host "Fetching $sha1url"
Invoke-WebRequest -Uri $sha1url -OutFile $sha1local -ErrorAction Stop
Write-Host "sha1 saved at $sha1local"
$sha1Content = Get-Content -Path $sha1local
$remotedict = @{}
foreach ($line in $sha1Content) {
#all sha1sums have * (binary indicator) - review
$match = [regex]::Match($line,"(.*) [*](.*)$")
if ($match.Success) {
$server_sha1 = $match.Groups[1].Value
$server_rt = $match.Groups[2].Value
$remotedict[$server_rt] = $server_sha1
}
}
$localdict = @{}
if (test-path -Path $archfolder -Type Container) {
$dircontents = (get-childItem -Path $archfolder -File | Where-object {-not ($(".txt",".tm") -contains $_.Extension) })
foreach ($f in $dircontents) {
$local_sha1 = Get-FileHash -Path $(${f}.FullName) -Algorithm SHA1
$localdict[$f.Name] = ${local_sha1}.Hash
}
}
Write-host "-----------------------------------------------------------------------"
Write-host "Runtimes for $arch"
Write-host "Local $archfolder"
Write-host "Remote $archurl"
Write-host "-----------------------------------------------------------------------"
Write-host "Local Remote"
Write-host "-----------------------------------------------------------------------"
# 12345678910234567892023456789302345
$G = "`e[32m" #Green
$Y = "`e[33m" #Yellow
$R = "`e[31m" #Red
$RST = "`e[m"
foreach ($key in $localdict.Keys) {
$local_sha1 = $($localdict[$key])
if ($remotedict.ContainsKey($key)) {
if ($local_sha1 -eq $remotedict[$key]) {
$rhs = "Same version"
$C = $G
} else {
$rhs = "UPDATE AVAILABLE"
$C = $Y
}
} else {
$C = $R
$rhs = "(not listed on server)"
}
#ansi problems from cmd.exe not in windows terminal - review
$C = ""
$RST = ""
$lhs = "$key".PadRight(35, ' ')
write-host -nonewline "${C}${lhs}${RST}"
write-host $rhs
}
$lhs_missing = "-".PadRight(35, ' ')
foreach ($key in $remotedict.Keys) {
if (-not ($localdict.ContainsKey($key))) {
write-host -nonewline $lhs_missing
write-host $key
}
}
Write-host "-----------------------------------------------------------------------"
} else {
if (test-path -Path $archfolder -Type Container) {
Write-host "-----------------------------------------------------------------------"
Write-Host "Local runtimes for $arch"
$dircontents = (get-childItem -Path $archfolder -File | Where-object {-not ($(".txt",".tm") -contains $_.Extension) })
write-host "$(${dircontents}.count) files in $archfolder"
Write-host "-----------------------------------------------------------------------"
foreach ($f in $dircontents) {
write-host $f.Name
}
Write-host "-----------------------------------------------------------------------"
Write-host "Use: 'list -remote' to compare local runtimes with those available on the artifact server"
} else {
write-host "No runtimes seem to be installed for $arch in $archfolder`nPlease use 'runtime.cmd fetch' to install."
write-host "Use 'runtime.cmd list -remote' to see available runtimes for $arch"
}
}
}
default {
$actions = @("fetch", "list", "run")
write-host "Available actions: $actions"
write-host "received"
foreach ($boundparam in $PSBoundParameters.opts) {
write-host $boundparam
}
}
}
return $PSBoundParameters
}
}
#write-host (psmain @args)
#$returnvalue = psmain @args
#Write-Host "Function Returned $returnvalue" -ForegroundColor Cyan
#return $returnvalue
psmain @args | out-null
exit 0

54
src/scriptapps/runtime_wrap.toml

@ -1,27 +1,27 @@
[application]
template="punk.multishell.cmd"
as_admin=false
scripts=[
"runtime.ps1",
"runtime.bash"
]
default_outputfile="runtime.cmd"
default_nextshellpath="/usr/bin/env bash"
default_nextshelltype="bash"
#valid nextshelltype entries are: tcl perl powershell bash.
#nextshellpath entries must be 64 characters or less.
#don't use -c for launching - or in old powershell, arguments such as "a b" will become 2 arguments a b
#do use -File (even though pwsh doesn't require it)
#win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -File"
#win32.nextshelltype="pwsh"
#powershell needs cmd.exe to preserve spaced args
win32.nextshellpath="cmd.exe /c powershell -nop -nol -ExecutionPolicy bypass -File"
win32.nextshelltype="powershell"
win32.outputfile="runtime.cmd"
[application]
template="punk.multishell.cmd"
as_admin=false
scripts=[
"runtime.ps1",
"runtime.bash"
]
default_outputfile="runtime.cmd"
default_nextshellpath="/usr/bin/env bash"
default_nextshelltype="bash"
#valid nextshelltype entries are: tcl perl powershell bash.
#nextshellpath entries must be 64 characters or less.
#don't use -c for launching - or in old powershell, arguments such as "a b" will become 2 arguments a b
#do use -File (even though pwsh doesn't require it)
#win32.nextshellpath="pwsh -nop -nol -ExecutionPolicy bypass -File"
#win32.nextshelltype="pwsh"
#powershell needs cmd.exe to preserve spaced args
win32.nextshellpath="cmd.exe /c powershell -nop -nol -ExecutionPolicy bypass -File"
win32.nextshelltype="powershell"
win32.outputfile="runtime.cmd"

Loading…
Cancel
Save