Browse Source

scriptwrapper work

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

1077
bin/getzig.cmd

File diff suppressed because it is too large Load Diff

44
src/modules/punk-0.1.tm

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

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

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

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

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

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

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

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

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

15
src/scriptapps/getzig.bash

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

186
src/scriptapps/getzig.ps1

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

21
src/scriptapps/getzig_wrap.toml

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