diff --git a/scripts/build.ps1 b/scripts/build.ps1 index 640bba1..735245d 100644 --- a/scripts/build.ps1 +++ b/scripts/build.ps1 @@ -1,181 +1,181 @@ -<# -.Synopsis - Build Cmder -.DESCRIPTION - Use this script to build your own edition of Cmder - - This script builds dependencies from current vendor/sources.json file and unpacks them. - - You will need to make this script executable by setting your Powershell Execution Policy to Remote signed - Then unblock the script for execution with UnblockFile .\build.ps1 -.EXAMPLE - .\build.ps1 - - Executes the default build for Cmder; ConEmu, clink. This is equivalent to the "minimum" style package in the releases -.EXAMPLE - .\build.ps1 -Compile - - Recompile the launcher executable if you have the requisite build tools for C++ installed. -.EXAMPLE - .\build.ps1 -Compile -NoVendor - - Skip all downloads and only build launcher. -.EXAMPLE - .\build -verbose - - Execute the build and see what's going on. -.EXAMPLE - .\build.ps1 -SourcesPath '~/custom/vendors.json' - - Build cmder with your own packages. See vendor/sources.json for the syntax you need to copy. -.NOTES - AUTHORS - Samuel Vasko, Jack Bennett - Part of the Cmder project. -.LINK - http://cmder.app/ - Project Home -#> -[CmdletBinding(SupportsShouldProcess = $true)] -Param( - # CmdletBinding will give us; - # -verbose switch to turn on logging and - # -whatif switch to not actually make changes - - # Path to the vendor configuration source file - [string]$sourcesPath = "$PSScriptRoot\..\vendor\sources.json", - - # Vendor folder location - [string]$saveTo = "$PSScriptRoot\..\vendor\", - - # Launcher folder location - [string]$launcher = "$PSScriptRoot\..\launcher", - - # Config folder location - [string]$config = "$PSScriptRoot\..\config", - - # Using this option will skip all downloads, if you only need to build launcher - [switch]$noVendor, - - # Build launcher if you have MSBuild tools installed - [switch]$Compile -) - -# Get the scripts and cmder root dirs we are building in. -$cmder_root = Resolve-Path "$PSScriptRoot\.." - -# Dot source util functions into this scope -. "$PSScriptRoot\utils.ps1" -$ErrorActionPreference = "Stop" - -if ($Compile) { - # Check for requirements - Ensure-Executable "msbuild" - - # Get the version string - $version = Get-VersionStr - - Push-Location -Path $launcher - Create-RC $version ($launcher + '\src\version.rc2') - - Write-Verbose "Building the launcher..." - - # Reference: https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference - msbuild CmderLauncher.vcxproj /t:Clean,Build /p:configuration=Release /m - - if ($LastExitCode -ne 0) { - throw "MSBuild failed to build the launcher executable." - } - Pop-Location -} - -if (-not $noVendor) { - # Check for requirements - Ensure-Exists $sourcesPath - Ensure-Executable "7z" - - # Get the vendor sources - $sources = Get-Content $sourcesPath | Out-String | ConvertFrom-Json - - Push-Location -Path $saveTo - New-Item -Type Directory -Path (Join-Path $saveTo "/tmp/") -ErrorAction SilentlyContinue >$null - - $vend = $pwd - - # Preserve modified (by user) ConEmu setting file - if ($config -ne "") { - $ConEmuXml = Join-Path $saveTo "conemu-maximus5\ConEmu.xml" - if (Test-Path $ConEmuXml -pathType leaf) { - $ConEmuXmlSave = Join-Path $config "ConEmu.xml" - Write-Verbose "Backup '$ConEmuXml' to '$ConEmuXmlSave'" - Copy-Item $ConEmuXml $ConEmuXmlSave - } - else { $ConEmuXml = "" } - } - else { $ConEmuXml = "" } - - # Kill ssh-agent.exe if it is running from the $env:cmder_root we are building - foreach ($ssh_agent in $(Get-Process ssh-agent -ErrorAction SilentlyContinue)) { - if ([string]$($ssh_agent.path) -Match [string]$cmder_root.replace('\', '\\')) { - Write-Verbose $("Stopping " + $ssh_agent.path + "!") - Stop-Process $ssh_agent.id - } - } - - foreach ($s in $sources) { - Write-Verbose "Getting vendored $($s.name) $($s.version)..." - - # We do not care about the extensions/type of archive - $tempArchive = "tmp/$($s.name).tmp" - Delete-Existing $tempArchive - Delete-Existing $s.name - - Download-File -Url $s.url -File $vend\$tempArchive -ErrorAction Stop - Extract-Archive $tempArchive $s.name - - if ((Get-ChildItem $s.name).Count -eq 1) { - Flatten-Directory($s.name) - } - - # Write current version to .cmderver file, for later. - "$($s.version)" | Out-File "$($s.name)/.cmderver" - } - - # Restore ConEmu user configuration - if ($ConEmuXml -ne "") { - Write-Verbose "Restore '$ConEmuXmlSave' to '$ConEmuXml'" - Copy-Item $ConEmuXmlSave $ConEmuXml - } - - # Put vendor\cmder.sh in /etc/profile.d so it runs when we start bash or mintty - if ( (Test-Path $($saveTo + "git-for-windows/etc/profile.d") ) ) { - Write-Verbose "Adding cmder.sh /etc/profile.d" - Copy-Item $($saveTo + "cmder.sh") $($saveTo + "git-for-windows/etc/profile.d/cmder.sh") - } - - # Replace /etc/profile.d/git-prompt.sh with cmder lambda prompt so it runs when we start bash or mintty - if ( !(Test-Path $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh.bak") ) ) { - Write-Verbose "Replacing /etc/profile.d/git-prompt.sh with our git-prompt.sh" - Move-Item $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh") $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh.bak") - Copy-Item $($saveTo + "git-prompt.sh") $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh") - } - - Pop-Location -} - -if (-not $Compile -or $noVendor) { - Write-Warning "You are not building the full project, Use -Compile without -noVendor" - Write-Warning "This cannot be a release. Test build only!" - return -} - -Write-Verbose "Successfully built Cmder v$version!" - -if ( $Env:APPVEYOR -eq 'True' ) { - Add-AppveyorMessage -Message "Building Cmder v$version was successful." -Category Information -} - -if ( $Env:GITHUB_ACTIONS -eq 'true' ) { - Write-Output "::notice title=Build Complete::Building Cmder v$version was successful." -} - -Write-Host -ForegroundColor green "All good and done!" +<# +.Synopsis + Build Cmder +.DESCRIPTION + Use this script to build your own edition of Cmder + + This script builds dependencies from current vendor/sources.json file and unpacks them. + + You will need to make this script executable by setting your Powershell Execution Policy to Remote signed + Then unblock the script for execution with UnblockFile .\build.ps1 +.EXAMPLE + .\build.ps1 + + Executes the default build for Cmder; ConEmu, clink. This is equivalent to the "minimum" style package in the releases +.EXAMPLE + .\build.ps1 -Compile + + Recompile the launcher executable if you have the requisite build tools for C++ installed. +.EXAMPLE + .\build.ps1 -Compile -NoVendor + + Skip all downloads and only build launcher. +.EXAMPLE + .\build -verbose + + Execute the build and see what's going on. +.EXAMPLE + .\build.ps1 -SourcesPath '~/custom/vendors.json' + + Build Cmder with your own packages. See vendor/sources.json for the syntax you need to copy. +.NOTES + AUTHORS + Samuel Vasko, Jack Bennett + Part of the Cmder project. +.LINK + http://cmder.app/ - Project Home +#> +[CmdletBinding(SupportsShouldProcess = $true)] +Param( + # CmdletBinding will give us; + # -verbose switch to turn on logging and + # -whatif switch to not actually make changes + + # Path to the vendor configuration source file + [string]$sourcesPath = "$PSScriptRoot\..\vendor\sources.json", + + # Vendor folder location + [string]$saveTo = "$PSScriptRoot\..\vendor\", + + # Launcher folder location + [string]$launcher = "$PSScriptRoot\..\launcher", + + # Config folder location + [string]$config = "$PSScriptRoot\..\config", + + # Using this option will skip all downloads, if you only need to build launcher + [switch]$noVendor, + + # Build launcher if you have MSBuild tools installed + [switch]$Compile +) + +# Get the scripts and Cmder root dirs we are building in. +$cmder_root = Resolve-Path "$PSScriptRoot\.." + +# Dot source util functions into this scope +. "$PSScriptRoot\utils.ps1" +$ErrorActionPreference = "Stop" + +if ($Compile) { + # Check for requirements + Ensure-Executable "msbuild" + + # Get the version string + $version = Get-VersionStr + + Push-Location -Path $launcher + Create-RC $version ($launcher + '\src\version.rc2') + + Write-Verbose "Building the launcher..." + + # Reference: https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + msbuild CmderLauncher.vcxproj /t:Clean,Build /p:configuration=Release /m + + if ($LastExitCode -ne 0) { + throw "MSBuild failed to build the launcher executable." + } + Pop-Location +} + +if (-not $noVendor) { + # Check for requirements + Ensure-Exists $sourcesPath + Ensure-Executable "7z" + + # Get the vendor sources + $sources = Get-Content $sourcesPath | Out-String | ConvertFrom-Json + + Push-Location -Path $saveTo + New-Item -Type Directory -Path (Join-Path $saveTo "/tmp/") -ErrorAction SilentlyContinue >$null + + $vend = $pwd + + # Preserve modified (by user) ConEmu setting file + if ($config -ne "") { + $ConEmuXml = Join-Path $saveTo "conemu-maximus5\ConEmu.xml" + if (Test-Path $ConEmuXml -pathType leaf) { + $ConEmuXmlSave = Join-Path $config "ConEmu.xml" + Write-Verbose "Backup '$ConEmuXml' to '$ConEmuXmlSave'" + Copy-Item $ConEmuXml $ConEmuXmlSave + } + else { $ConEmuXml = "" } + } + else { $ConEmuXml = "" } + + # Kill ssh-agent.exe if it is running from the $env:cmder_root we are building + foreach ($ssh_agent in $(Get-Process ssh-agent -ErrorAction SilentlyContinue)) { + if ([string]$($ssh_agent.path) -Match [string]$cmder_root.replace('\', '\\')) { + Write-Verbose $("Stopping " + $ssh_agent.path + "!") + Stop-Process $ssh_agent.id + } + } + + foreach ($s in $sources) { + Write-Verbose "Getting vendored $($s.name) $($s.version)..." + + # We do not care about the extensions/type of archive + $tempArchive = "tmp/$($s.name).tmp" + Delete-Existing $tempArchive + Delete-Existing $s.name + + Download-File -Url $s.url -File $vend\$tempArchive -ErrorAction Stop + Extract-Archive $tempArchive $s.name + + if ((Get-ChildItem $s.name).Count -eq 1) { + Flatten-Directory($s.name) + } + + # Write current version to .cmderver file, for later. + "$($s.version)" | Out-File "$($s.name)/.cmderver" + } + + # Restore ConEmu user configuration + if ($ConEmuXml -ne "") { + Write-Verbose "Restore '$ConEmuXmlSave' to '$ConEmuXml'" + Copy-Item $ConEmuXmlSave $ConEmuXml + } + + # Put vendor\cmder.sh in /etc/profile.d so it runs when we start bash or mintty + if ( (Test-Path $($saveTo + "git-for-windows/etc/profile.d") ) ) { + Write-Verbose "Adding cmder.sh /etc/profile.d" + Copy-Item $($saveTo + "cmder.sh") $($saveTo + "git-for-windows/etc/profile.d/cmder.sh") + } + + # Replace /etc/profile.d/git-prompt.sh with cmder lambda prompt so it runs when we start bash or mintty + if ( !(Test-Path $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh.bak") ) ) { + Write-Verbose "Replacing /etc/profile.d/git-prompt.sh with our git-prompt.sh" + Move-Item $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh") $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh.bak") + Copy-Item $($saveTo + "git-prompt.sh") $($saveTo + "git-for-windows/etc/profile.d/git-prompt.sh") + } + + Pop-Location +} + +if (-not $Compile -or $noVendor) { + Write-Warning "You are not building the full project, Use -Compile without -noVendor" + Write-Warning "This cannot be a release. Test build only!" + return +} + +Write-Verbose "Successfully built Cmder v$version!" + +if ( $Env:APPVEYOR -eq 'True' ) { + Add-AppveyorMessage -Message "Building Cmder v$version was successful." -Category Information +} + +if ( $Env:GITHUB_ACTIONS -eq 'true' ) { + Write-Output "::notice title=Build Complete::Building Cmder v$version was successful." +} + +Write-Host -ForegroundColor green "All good and done!" diff --git a/scripts/pack.ps1 b/scripts/pack.ps1 index 418fdcd..eaad68d 100644 --- a/scripts/pack.ps1 +++ b/scripts/pack.ps1 @@ -1,76 +1,76 @@ -<# -.Synopsis - Pack Cmder -.DESCRIPTION - Use this script to pack cmder into release archives - - You will need to make this script executable by setting your Powershell Execution Policy to Remote signed - Then unblock the script for execution with UnblockFile .\pack.ps1 -.EXAMPLE - .\pack.ps1 - - Creates default archives for cmder -.EXAMPLE - .\pack.ps1 -verbose - - Creates default archives for cmder with plenty of information -.NOTES - AUTHORS - Samuel Vasko, Jack Bennett, Martin Kemp - Part of the Cmder project. -.LINK - https://github.com/cmderdev/cmder - Project Home -#> - -[CmdletBinding(SupportsShouldProcess = $true)] -Param( - # CmdletBinding will give us; - # -verbose switch to turn on logging and - # -whatif switch to not actually make changes - - # Path to the vendor configuration source file - [string]$cmderRoot = "$PSScriptRoot\..", - - # Vendor folder locaton - [string]$saveTo = "$PSScriptRoot\..\build" -) - -$cmderRoot = Resolve-Path $cmderRoot - -. "$PSScriptRoot\utils.ps1" -$ErrorActionPreference = "Stop" -Ensure-Executable "7z" - -$targets = @{ - "cmder.7z" = "-t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on -myx=7 -mqs=on"; - "cmder.zip" = "-mm=Deflate -mfb=128 -mpass=3"; - "cmder_mini.zip" = "-xr!`"vendor\git-for-windows`""; -} - -Push-Location -Path $cmderRoot - -Delete-Existing "$cmderRoot\Version*" -Delete-Existing "$cmderRoot\build\*" - -if (-not (Test-Path -PathType container $saveTo)) { - (New-Item -ItemType Directory -Path $saveTo) | Out-Null -} - -$saveTo = Resolve-Path $saveTo - -$version = Get-VersionStr -(New-Item -ItemType file "$cmderRoot\Version $version") | Out-Null - -if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { - Write-Verbose "Packing Cmder $version in $saveTo..." - $excluded = (Get-Content -Path "$cmderRoot\packignore") -Split [System.Environment]::NewLine | Where-Object { $_ } - Get-ChildItem $cmderRoot -Force -Exclude $excluded -} - -foreach ($t in $targets.GetEnumerator()) { - Create-Archive "$cmderRoot" "$saveTo\$($t.Name)" $t.Value - $hash = (Digest-Hash "$saveTo\$($t.Name)") - Add-Content -path "$saveTo\hashes.txt" -value ($t.Name + ' ' + $hash) -} - -Pop-Location +<# +.Synopsis + Pack Cmder +.DESCRIPTION + Use this script to pack Cmder into release archives + + You will need to make this script executable by setting your Powershell Execution Policy to Remote signed + Then unblock the script for execution with UnblockFile .\pack.ps1 +.EXAMPLE + .\pack.ps1 + + Creates default archives for Cmder +.EXAMPLE + .\pack.ps1 -verbose + + Creates default archives for Cmder with plenty of information +.NOTES + AUTHORS + Samuel Vasko, Jack Bennett, Martin Kemp + Part of the Cmder project. +.LINK + https://github.com/cmderdev/cmder - Project Home +#> + +[CmdletBinding(SupportsShouldProcess = $true)] +Param( + # CmdletBinding will give us; + # -verbose switch to turn on logging and + # -whatif switch to not actually make changes + + # Path to the vendor configuration source file + [string]$cmderRoot = "$PSScriptRoot\..", + + # Vendor folder locaton + [string]$saveTo = "$PSScriptRoot\..\build" +) + +$cmderRoot = Resolve-Path $cmderRoot + +. "$PSScriptRoot\utils.ps1" +$ErrorActionPreference = "Stop" +Ensure-Executable "7z" + +$targets = @{ + "cmder.7z" = "-t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on -myx=7 -mqs=on"; + "cmder.zip" = "-mm=Deflate -mfb=128 -mpass=3"; + "cmder_mini.zip" = "-xr!`"vendor\git-for-windows`""; +} + +Push-Location -Path $cmderRoot + +Delete-Existing "$cmderRoot\Version*" +Delete-Existing "$cmderRoot\build\*" + +if (-not (Test-Path -PathType container $saveTo)) { + (New-Item -ItemType Directory -Path $saveTo) | Out-Null +} + +$saveTo = Resolve-Path $saveTo + +$version = Get-VersionStr +(New-Item -ItemType file "$cmderRoot\Version $version") | Out-Null + +if ($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent) { + Write-Verbose "Packing Cmder $version in $saveTo..." + $excluded = (Get-Content -Path "$cmderRoot\packignore") -Split [System.Environment]::NewLine | Where-Object { $_ } + Get-ChildItem $cmderRoot -Force -Exclude $excluded +} + +foreach ($t in $targets.GetEnumerator()) { + Create-Archive "$cmderRoot" "$saveTo\$($t.Name)" $t.Value + $hash = (Digest-Hash "$saveTo\$($t.Name)") + Add-Content -path "$saveTo\hashes.txt" -value ($t.Name + ' ' + $hash) +} + +Pop-Location diff --git a/scripts/utils.ps1 b/scripts/utils.ps1 index 2b81a70..0ac1bc0 100644 --- a/scripts/utils.ps1 +++ b/scripts/utils.ps1 @@ -1,251 +1,251 @@ -function Ensure-Exists($path) { - if (-not (Test-Path $path)) { - Write-Error "Missing required $path! Ensure it is installed" - exit 1 - } - return $true > $null -} - -function Ensure-Executable($command) { - try { Get-Command $command -ErrorAction Stop > $null } - catch { - if( ($command -eq "7z") -and (Test-Path "$env:programfiles\7-zip\7z.exe") ){ - Set-Alias -Name "7z" -Value "$env:programfiles\7-zip\7z.exe" -Scope script - } - elseif( ($command -eq "7z") -and (Test-Path "$env:programw6432\7-zip\7z.exe") ) { - Set-Alias -Name "7z" -Value "$env:programw6432\7-zip\7z.exe" -Scope script - } - else { - Write-Error "Missing $command! Ensure it is installed and on in the PATH" - exit 1 - } - } -} - -function Delete-Existing($path) { - if (Test-Path $path) { - Write-Verbose "Remove existing $path" - } - Remove-Item -Recurse -Force $path -ErrorAction SilentlyContinue -} - -function Extract-Archive($source, $target) { - Write-Verbose $("Extracting Archive '$cmder_root\vendor\" + $source.replace('/','\') + " to '$cmder_root\vendor\$target'") - Invoke-Expression "7z x -y -o`"$($target)`" `"$source`" > `$null" - if ($LastExitCode -ne 0) { - Write-Error "Extracting of $source failed" - } - Remove-Item $source -} - -function Create-Archive($source, $target, $params) { - $command = "7z a -x@`"$source\packignore`" $params `"$target`" `"*`" > `$null" - Write-Verbose "Creating Archive from '$source' in '$target' with parameters '$params'" - Push-Location $source - Invoke-Expression $command - Pop-Location - if ($LastExitCode -ne 0) { - Write-Error "Compressing $source failed" - } -} - -# If directory contains only one child directory -# Flatten it instead -function Flatten-Directory($name) { - $name = Resolve-Path $name - $moving = "$($name)_moving" - Rename-Item $name -NewName $moving - Write-Verbose "Flattening the '$name' directory..." - $child = (Get-ChildItem $moving)[0] | Resolve-Path - Move-Item -Path $child -Destination $name - Remove-Item -Recurse $moving -} - -function Digest-Hash($path) { - if (Get-Command Get-FileHash -ErrorAction SilentlyContinue) { - return (Get-FileHash -Algorithm SHA256 -Path $path).Hash - } - - return Invoke-Expression "md5sum $path" -} - -function Set-GHVariable { - param( - [Parameter(Mandatory = $true)] - [string]$Name, - [Parameter(Mandatory = $true)] - [string]$Value - ) - - Write-Verbose "Setting CI variable $Name to $Value" -Verbose - - if ($env:GITHUB_ENV) { - Write-Output "$Name=$Value" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - } -} - -function Get-GHTempPath { - $temp = [System.IO.Path]::GetTempPath() - if ($env:RUNNER_TEMP) { - $temp = $env:RUNNER_TEMP - } - - Write-Verbose "Get CI Temp path: $temp" -Verbose - return $temp -} - -function Get-VersionStr { - # Clear existing variable - if ($string) { Clear-Variable -name string } - - # Determine if git is available - if (Get-Command "git.exe" -ErrorAction SilentlyContinue) { - # Determine if the current directory is a git repository - $GitPresent = Invoke-Expression "git rev-parse --is-inside-work-tree" -ErrorAction SilentlyContinue - - if ( $GitPresent -eq 'true' ) { - $string = Invoke-Expression "git describe --abbrev=0 --tags" - } - } - - # Fallback used when Git is not available - if ( -not($string) ) { - $string = Parse-Changelog ($PSScriptRoot + '\..\' + 'CHANGELOG.md') - } - - # Add build number, if AppVeyor is present - if ( $Env:APPVEYOR -eq 'True' ) { - $string = $string + '.' + $Env:APPVEYOR_BUILD_NUMBER - } - elseif ( $Env:GITHUB_ACTIONS -eq 'true' ) { - $string = $string + '.' + $Env:GITHUB_RUN_NUMBER - } - - # Remove starting 'v' characters - $string = $string -replace '^v+','' # normalize version string - - return $string -} - -function Parse-Changelog($file) { - # Define the regular expression to match the version string from changelog - [regex]$regex = '^## \[(?[\w\-\.]+)\]\([^\n()]+\)\s+\([^\n()]+\)$'; - - # Find the first match of the version string which means the latest version - $version = Select-String -Path $file -Pattern $regex | Select-Object -First 1 | ForEach-Object { $_.Matches.Groups[1].Value } - - return $version -} - -function Create-RC($string, $path) { - $version = $string + '.0.0.0.0' # padding for version string - - if ( !(Test-Path "$path.sample") ) { - throw "Invalid path provided for resources file." - } - - $resource = Get-Content -Path "$path.sample" - $pattern = @( "Cmder-Major-Version", "Cmder-Minor-Version", "Cmder-Revision-Version", "Cmder-Build-Version" ) - $index = 0 - - # Replace all non-numeric characters to dots and split to array - $version = $version -replace '[^0-9]+','.' -split '\.' - - foreach ($fragment in $version) { - if ( !$fragment ) { break } - elseif ($index -le $pattern.length) { - $resource = $resource.Replace( "{" + $pattern[$index++] + "}", $fragment ) - } - } - - # Add the version string - $resource = $resource.Replace( "{Cmder-Version-Str}", '"' + $string + '"' ) - - # Write the results - Set-Content -Path $path -Value $resource -} - -function Register-Cmder() { - [CmdletBinding()] - Param - ( - # Text for the context menu item. - $MenuText = "Cmder Here" - - , # Defaults to the current cmder directory when run from cmder. - $PathToExe = (Join-Path $env:CMDER_ROOT "cmder.exe") - - , # Commands the context menu will execute. - $Command = "%V" - - , # Defaults to the icons folder in the cmder package. - $icon = (Split-Path $PathToExe | Join-Path -ChildPath 'icons/cmder.ico') - ) - Begin - { - New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT > $null - } - Process - { - New-Item -Path "HKCR:\Directory\Shell\Cmder" -Force -Value $MenuText - New-ItemProperty -Path "HKCR:\Directory\Shell\Cmder" -Force -Name "Icon" -Value `"$icon`" - New-ItemProperty -Path "HKCR:\Directory\Shell\Cmder" -Force -Name "NoWorkingDirectory" - New-Item -Path "HKCR:\Directory\Shell\Cmder\Command" -Force -Value "`"$PathToExe`" `"$Command`" " - - New-Item -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Value $MenuText - New-ItemProperty -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Name "Icon" -Value `"$icon`" - New-ItemProperty -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Name "NoWorkingDirectory" - New-Item -Path "HKCR:\Directory\Background\Shell\Cmder\Command" -Force -Value "`"$PathToExe`" `"$Command`" " - } - End - { - Remove-PSDrive -Name HKCR - } -} - -function Unregister-Cmder { - Begin - { - New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT > $null - } - Process - { - Remove-Item -Path "HKCR:\Directory\Shell\Cmder" -Recurse - Remove-Item -Path "HKCR:\Directory\Background\Shell\Cmder" -Recurse - } - End - { - Remove-PSDrive -Name HKCR - } -} - -function Download-File { - param ( - $Url, - $File - ) - [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 - - $useBitTransfer = $null -ne (Get-Module -Name BitsTransfer -ListAvailable) -and ($PSVersionTable.PSVersion.Major -le 5) - - $File = $File -replace "/", "\" - - try { - if ($useBitTransfer) { - Start-BitsTransfer -Source $Url -Destination $File -DisplayName "Downloading '$Url' to $File" - return - } - } - catch { - Write-Error "Failed to download file using BITS, reason: $_`nUsing fallback method instead...`n" -ErrorAction:Continue - } - - Write-Verbose "Downloading from $Url to $File`n" - - $wc = New-Object System.Net.WebClient - if ($env:https_proxy) { - $wc.proxy = (New-Object System.Net.WebProxy($env:https_proxy)) - } - $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; - $wc.DownloadFile($Url, $File) -} +function Ensure-Exists($path) { + if (-not (Test-Path $path)) { + Write-Error "Missing required $path! Ensure it is installed" + exit 1 + } + return $true > $null +} + +function Ensure-Executable($command) { + try { Get-Command $command -ErrorAction Stop > $null } + catch { + if( ($command -eq "7z") -and (Test-Path "$env:programfiles\7-zip\7z.exe") ){ + Set-Alias -Name "7z" -Value "$env:programfiles\7-zip\7z.exe" -Scope script + } + elseif( ($command -eq "7z") -and (Test-Path "$env:programw6432\7-zip\7z.exe") ) { + Set-Alias -Name "7z" -Value "$env:programw6432\7-zip\7z.exe" -Scope script + } + else { + Write-Error "Missing $command! Ensure it is installed and on in the PATH" + exit 1 + } + } +} + +function Delete-Existing($path) { + if (Test-Path $path) { + Write-Verbose "Remove existing $path" + } + Remove-Item -Recurse -Force $path -ErrorAction SilentlyContinue +} + +function Extract-Archive($source, $target) { + Write-Verbose $("Extracting Archive '$cmder_root\vendor\" + $source.replace('/','\') + " to '$cmder_root\vendor\$target'") + Invoke-Expression "7z x -y -o`"$($target)`" `"$source`" > `$null" + if ($LastExitCode -ne 0) { + Write-Error "Extracting of $source failed" + } + Remove-Item $source +} + +function Create-Archive($source, $target, $params) { + $command = "7z a -x@`"$source\packignore`" $params `"$target`" `"*`" > `$null" + Write-Verbose "Creating Archive from '$source' in '$target' with parameters '$params'" + Push-Location $source + Invoke-Expression $command + Pop-Location + if ($LastExitCode -ne 0) { + Write-Error "Compressing $source failed" + } +} + +# If directory contains only one child directory +# Flatten it instead +function Flatten-Directory($name) { + $name = Resolve-Path $name + $moving = "$($name)_moving" + Rename-Item $name -NewName $moving + Write-Verbose "Flattening the '$name' directory..." + $child = (Get-ChildItem $moving)[0] | Resolve-Path + Move-Item -Path $child -Destination $name + Remove-Item -Recurse $moving +} + +function Digest-Hash($path) { + if (Get-Command Get-FileHash -ErrorAction SilentlyContinue) { + return (Get-FileHash -Algorithm SHA256 -Path $path).Hash + } + + return Invoke-Expression "md5sum $path" +} + +function Set-GHVariable { + param( + [Parameter(Mandatory = $true)] + [string]$Name, + [Parameter(Mandatory = $true)] + [string]$Value + ) + + Write-Verbose "Setting CI variable $Name to $Value" -Verbose + + if ($env:GITHUB_ENV) { + Write-Output "$Name=$Value" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + } +} + +function Get-GHTempPath { + $temp = [System.IO.Path]::GetTempPath() + if ($env:RUNNER_TEMP) { + $temp = $env:RUNNER_TEMP + } + + Write-Verbose "Get CI Temp path: $temp" -Verbose + return $temp +} + +function Get-VersionStr { + # Clear existing variable + if ($string) { Clear-Variable -name string } + + # Determine if git is available + if (Get-Command "git.exe" -ErrorAction SilentlyContinue) { + # Determine if the current directory is a git repository + $GitPresent = Invoke-Expression "git rev-parse --is-inside-work-tree" -ErrorAction SilentlyContinue + + if ( $GitPresent -eq 'true' ) { + $string = Invoke-Expression "git describe --abbrev=0 --tags" + } + } + + # Fallback used when Git is not available + if ( -not($string) ) { + $string = Parse-Changelog ($PSScriptRoot + '\..\' + 'CHANGELOG.md') + } + + # Add build number, if AppVeyor is present + if ( $Env:APPVEYOR -eq 'True' ) { + $string = $string + '.' + $Env:APPVEYOR_BUILD_NUMBER + } + elseif ( $Env:GITHUB_ACTIONS -eq 'true' ) { + $string = $string + '.' + $Env:GITHUB_RUN_NUMBER + } + + # Remove starting 'v' characters + $string = $string -replace '^v+','' # normalize version string + + return $string +} + +function Parse-Changelog($file) { + # Define the regular expression to match the version string from changelog + [regex]$regex = '^## \[(?[\w\-\.]+)\]\([^\n()]+\)\s+\([^\n()]+\)$'; + + # Find the first match of the version string which means the latest version + $version = Select-String -Path $file -Pattern $regex | Select-Object -First 1 | ForEach-Object { $_.Matches.Groups[1].Value } + + return $version +} + +function Create-RC($string, $path) { + $version = $string + '.0.0.0.0' # padding for version string + + if ( !(Test-Path "$path.sample") ) { + throw "Invalid path provided for resources file." + } + + $resource = Get-Content -Path "$path.sample" + $pattern = @( "Cmder-Major-Version", "Cmder-Minor-Version", "Cmder-Revision-Version", "Cmder-Build-Version" ) + $index = 0 + + # Replace all non-numeric characters to dots and split to array + $version = $version -replace '[^0-9]+','.' -split '\.' + + foreach ($fragment in $version) { + if ( !$fragment ) { break } + elseif ($index -le $pattern.length) { + $resource = $resource.Replace( "{" + $pattern[$index++] + "}", $fragment ) + } + } + + # Add the version string + $resource = $resource.Replace( "{Cmder-Version-Str}", '"' + $string + '"' ) + + # Write the results + Set-Content -Path $path -Value $resource +} + +function Register-Cmder() { + [CmdletBinding()] + Param + ( + # Text for the context menu item. + $MenuText = "Cmder Here" + + , # Defaults to the current Cmder directory when run from Cmder. + $PathToExe = (Join-Path $env:CMDER_ROOT "cmder.exe") + + , # Commands the context menu will execute. + $Command = "%V" + + , # Defaults to the icons folder in the Cmder package. + $icon = (Split-Path $PathToExe | Join-Path -ChildPath 'icons/cmder.ico') + ) + Begin + { + New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT > $null + } + Process + { + New-Item -Path "HKCR:\Directory\Shell\Cmder" -Force -Value $MenuText + New-ItemProperty -Path "HKCR:\Directory\Shell\Cmder" -Force -Name "Icon" -Value `"$icon`" + New-ItemProperty -Path "HKCR:\Directory\Shell\Cmder" -Force -Name "NoWorkingDirectory" + New-Item -Path "HKCR:\Directory\Shell\Cmder\Command" -Force -Value "`"$PathToExe`" `"$Command`" " + + New-Item -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Value $MenuText + New-ItemProperty -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Name "Icon" -Value `"$icon`" + New-ItemProperty -Path "HKCR:\Directory\Background\Shell\Cmder" -Force -Name "NoWorkingDirectory" + New-Item -Path "HKCR:\Directory\Background\Shell\Cmder\Command" -Force -Value "`"$PathToExe`" `"$Command`" " + } + End + { + Remove-PSDrive -Name HKCR + } +} + +function Unregister-Cmder { + Begin + { + New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT > $null + } + Process + { + Remove-Item -Path "HKCR:\Directory\Shell\Cmder" -Recurse + Remove-Item -Path "HKCR:\Directory\Background\Shell\Cmder" -Recurse + } + End + { + Remove-PSDrive -Name HKCR + } +} + +function Download-File { + param ( + $Url, + $File + ) + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 + + $useBitTransfer = $null -ne (Get-Module -Name BitsTransfer -ListAvailable) -and ($PSVersionTable.PSVersion.Major -le 5) + + $File = $File -replace "/", "\" + + try { + if ($useBitTransfer) { + Start-BitsTransfer -Source $Url -Destination $File -DisplayName "Downloading '$Url' to $File" + return + } + } + catch { + Write-Error "Failed to download file using BITS, reason: $_`nUsing fallback method instead...`n" -ErrorAction:Continue + } + + Write-Verbose "Downloading from $Url to $File`n" + + $wc = New-Object System.Net.WebClient + if ($env:https_proxy) { + $wc.proxy = (New-Object System.Net.WebProxy($env:https_proxy)) + } + $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; + $wc.DownloadFile($Url, $File) +}