#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 # 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; // 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 [uint]$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 (![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"