greatly improved pwsh scripts

Common:

 - extracted common code to private/Common.ps1
 - removed boolean values for Parameter attributes

Invoke-Tests:

 - added auto sourcing of dotenv.ps1 file if needed
 - auto-exported shared libraries paths in the current build folder
 - added nice log messages for above two scenarios

Add-FolderOnPath:

 - added nice log messages for above two scenarios
 - extracted some code to cmdlets for shorter process block
This commit is contained in:
silverqx
2022-01-12 16:40:00 +01:00
parent eeeb72f6b0
commit 15ae4e062f
5 changed files with 390 additions and 137 deletions

View File

@@ -8,10 +8,12 @@ Param(
[string[]] $Path = $($(Get-Location).Path),
[Parameter(Position = 1, ValueFromPipelinebyPropertyName,
HelpMessage = 'Specifies the environment variable to which to add a Path, is env:PATH by default.')]
HelpMessage = 'Specifies the environment variable to which to add a Path, is env:PATH ' +
'by default.')]
[string] $Variable,
[Parameter(HelpMessage = 'Add a Path to the LD_LIBRARY_PATH environment variable (Variable parameter has higher priority).')]
[Parameter(HelpMessage = 'Add a Path to the LD_LIBRARY_PATH environment variable (Variable ' +
'parameter has higher priority).')]
[switch] $LibraryPath,
[Parameter(HelpMessage = 'Restore original path values for all changed environment variables.')]
@@ -29,6 +31,8 @@ begin {
}
$Script:Slashes = $null
. $PSScriptRoot\private\Common.ps1
function Initialize-EnvVariable {
[OutputType([string[]])]
Param()
@@ -77,7 +81,8 @@ begin {
# Backup to global variable
if (Test-Path $Script:envVariable) {
Set-Variable -Scope global -Name $globalName -Value (Get-Item $Script:envVariable).Value
Set-Variable -Scope global -Name $globalName `
-Value (Get-Item $Script:envVariable).Value
}
# Env. variable to back up is empty, so set global variable to $null
else {
@@ -104,83 +109,141 @@ begin {
Param()
foreach ($variable in $Global:TinyBackedUpVariables) {
Set-Item -Path "env:$variable" -Value (Get-Variable -Scope global "Tiny_$variable").Value
Set-Item -Path "env:$variable" `
-Value (Get-Variable -Scope global "Tiny_$variable").Value
Redo-GlobalState -Variable $variable
}
Remove-Variable -Scope global -Name 'TinyBackedUpVariables' -ErrorAction SilentlyContinue
Write-Host 'Restored' -ForegroundColor DarkGreen
}
# Get slashes by platform
function Get-Slashes {
[OutputType([string])]
Param()
# Cached value
if ($Script:Slashes) {
return $Script:Slashes
}
$platform = $PSVersionTable.Platform
switch ($platform) {
'Win32NT' {
return $Script:Slashes = '\\/'
}
'Unix' {
return $Script:Slashes = '/'
}
Default {
throw "$platform platform is not supported."
}
}
}
function Get-PathToMatch {
[OutputType([string])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
HelpMessage = "Specifies a path to modify to the match pattern.")]
[ValidateNotNullOrEmpty()]
[string]
$Path
)
$slashes = Get-Slashes
$pathToMatch = $Path `
-replace "[$slashes]+(?![$slashes]*$)", "[$slashes]+" `
-replace "[$slashes]+$", ''
$separator = [IO.Path]::PathSeparator
return "(?:^|$separator)$pathToMatch[$slashes]*(?:$|$separator)"
}
function Get-FullPath {
[CmdletBinding()]
# Obtain paths to add and excluded paths
function Initialize-Paths {
[CmdletBinding(PositionalBinding = $false)]
[OutputType([string[]])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
HelpMessage = "Specifies a path to normalize.")]
[string[]]
$Path
[Parameter(Mandatory,
HelpMessage = 'Specifies a value of env. variable, set to the $null value if ' +
"env. variable doesn't exist.")]
[AllowEmptyString()]
[string]
$VariableValue
)
process {
[string[]] $normalized = @()
# Check if paths to add are already on the $Script:envVariable ($env:$Variable)
$pathsToAdd = @()
$pathsExcluded = @()
if (-not ($VariableValue -eq '')) {
foreach ($p in $Path) {
$normalized += [System.IO.Path]::GetFullPath(($p -replace "[$(Get-Slashes)]+$", ''))
foreach ($pathToAdd in $Path) {
$pathToMatch = Get-PathToMatch -Path $pathToAdd
$pathToAddNormalized = $(Get-FullPath -Path $pathToAdd)
if ($VariableValue -notmatch $pathToMatch) {
$pathsToAdd += $pathToAddNormalized
}
else {
$pathsExcluded += $pathToAddNormalized
}
}
}
# When env. variable value is empty then add all Paths
else {
$pathsToAdd = Get-FullPath -Path $Path
}
return $normalized
return $pathsToAdd, $pathsExcluded
}
# Get final paths to add to the env. variable
function Join-PathsToAdd {
[CmdletBinding(PositionalBinding = $false)]
[OutputType([string])]
Param(
[Parameter(Mandatory,
HelpMessage = 'Specifies a value of env. variable, set to the $null value if ' +
"env. variable doesn't exist.")]
[AllowEmptyString()]
[string]
$VariableValue,
[Parameter(Mandatory,
HelpMessage = 'Specifies added paths to the env. variable.')]
[AllowEmptyCollection()]
[string[]]
$PathsToAdd
)
$pathsJoined = $PathsToAdd -join [IO.Path]::PathSeparator
# Env. variable value is empty
if ($VariableValue -eq '') {
$pathsFinal = $pathsJoined
}
# Prepend vs Append
elseif ($Append) {
$pathsFinal = $($VariableValue, $pathsJoined)
}
else {
$pathsFinal = $($pathsJoined, $VariableValue)
}
return $pathsFinal -join [IO.Path]::PathSeparator
}
function Write-Result {
[CmdletBinding(PositionalBinding=$false)]
[OutputType([void])]
Param(
[Parameter(Mandatory,
HelpMessage = 'Specifies a value of env. variable, set to the $null value if ' +
"env. variable doesn't exist.")]
[AllowEmptyString()]
[string]
$VariableValue,
[Parameter(Mandatory,
HelpMessage = "Specifies added paths to the env. variable.")]
[AllowEmptyCollection()]
[string[]]
$PathsToAdd,
[Parameter(Mandatory,
HelpMessage = 'Specifies excluded paths from the env. variable (if already ' +
'contains).')]
[AllowEmptyCollection()]
[string[]]
$PathsExcluded
)
$added = $Append ? 'appended' : 'prepended'
if ($VariableValue -eq '') {
Write-Host "All paths were $added." -ForegroundColor DarkGreen
return
}
if ($PathsToAdd.Length -gt 0) {
$addedCapital = $Append ? 'Appended' : 'Prepended'
$pathsToAddJoined = $PathsToAdd -join ', '
Write-Host "$($addedCapital): " -ForegroundColor DarkGreen -NoNewline
Write-Host $pathsToAddJoined
}
if ($PathsExcluded.Length -gt 0) {
$pathsExcludedJoined = $PathsExcluded -join ', '
Write-Host "Already contains: $pathsExcludedJoined" -ForegroundColor DarkGray
}
}
function Export-Path {
[CmdletBinding()]
[CmdletBinding(PositionalBinding = $false)]
[OutputType([void])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
@@ -189,52 +252,35 @@ begin {
$Path
)
begin {
Write-Host
Write-Host "Updating `$$Script:envVariable environment variable..." `
-ForegroundColor DarkBlue
Write-Host
}
process {
# Value of env. variable
if (Test-Path $Script:envVariable) {
$variableValue = Get-Item $Script:envVariable | Select-Object -ExpandProperty Value
}
# Set to empty value if env. variable doesn't exist
else {
$variableValue = ''
}
# Value of env. variable, set to the $null value if env. variable doesn't exist
$variableValue = Get-Item $Script:envVariable -ErrorAction SilentlyContinue | `
Select-Object -ExpandProperty Value
# Check if paths to add are already on the $Script:envVariable ($env:$Variable)
$pathsToAdd = @()
if (-not ($variableValue -eq '')) {
foreach ($pathToAdd in $Path) {
$pathToMatch = Get-PathToMatch -Path $pathToAdd
if ($variableValue -notmatch $pathToMatch) {
$pathsToAdd += Get-FullPath -Path $pathToAdd
}
}
}
# When env. variable value is empty then add all Paths
else {
$pathsToAdd = Get-FullPath -Path $Path
}
# Obtain paths to add and excluded paths
$pathsToAdd, $pathsExcluded = Initialize-Paths -VariableValue $variableValue
# Nothing to add
if ($pathsToAdd.Length -eq 0) {
return
}
$pathsJoined = $pathsToAdd -join [IO.Path]::PathSeparator
# Get final paths to add to the env. variable
$pathsFinal = Join-PathsToAdd -VariableValue $variableValue -PathsToAdd $pathsToAdd
# Env. variable value is empty
if (-not $variableValue) {
$pathsFinal = $pathsJoined
}
# Prepend vs Append
elseif ($Append) {
$pathsFinal = $($variableValue, $pathsJoined)
}
else {
$pathsFinal = $($pathsJoined, $variableValue)
}
Set-Item -Path $Script:envVariable -Value $pathsFinal
}
Set-Item -Path $Script:envVariable -Value ($pathsFinal -join [IO.Path]::PathSeparator)
end {
Write-Result -VariableValue $variableValue -PathsToAdd $pathsToAdd `
-PathsExcluded $pathsExcluded
}
}

View File

@@ -1,17 +1,19 @@
#!/usr/bin/env pwsh
Param(
[Parameter(Position = 0, Mandatory = $true,
HelpMessage = 'Specifies todo tasks to find on each line. The pattern value is treated as a regular expression.')]
[Parameter(Position = 0, Mandatory,
HelpMessage = 'Specifies todo tasks to find on each line. The pattern value is treated ' +
'as a regular expression.')]
[ValidateNotNullOrEmpty()]
[string[]] $Pattern,
[Parameter(Position = 1, Mandatory = $false,
HelpMessage = 'Specifies an array of one or more string patterns to be matched as the cmdlet gets child items.')]
[Parameter(Position = 1,
HelpMessage = 'Specifies an array of one or more string patterns to be matched as the ' +
'cmdlet gets child items.')]
[ValidateNotNullOrEmpty()]
[string[]] $Include = @('*.cpp', '*.hpp'),
[Parameter(Position = 2, Mandatory = $false,
[Parameter(Position = 2,
HelpMessage = 'Specifies the path to the project folder, is pwd by default.')]
[ValidateNotNullOrEmpty()]
[string] $Path = $($(Get-Location).Path) + '\*'

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env pwsh
Param(
[Parameter(Position = 0, Mandatory = $false,
[Parameter(Position = 0,
HelpMessage = 'Specifies how many times all AutoTests should be invoked.')]
[ValidateNotNullOrEmpty()]
[int] $Count = 1,
[Parameter(Position = 1, Mandatory = $false,
[Parameter(Position = 1,
HelpMessage = 'Specifies the path to the qmake build folder, is pwd by default.')]
[ValidateNotNullOrEmpty()]
[string] $BuildPath = $($(Get-Location).Path)
@@ -14,27 +14,144 @@ Param(
Set-StrictMode -Version 3.0
. $PSScriptRoot\private\Common.ps1
$Script:TotalElapsed = 0
$Script:AverageElapsed = 0
$Script:EnvPathBackup = $env:Path
$Script:Slashes = $null
function Initialize-Environment {
[OutputType([void])]
Param()
Write-Host
Write-Host 'Initializing environment...' -ForegroundColor DarkBlue
Write-Host
Initialize-DBEnvironment
Initialize-RuntimeEnvironment
Write-Host
}
# Source database env. variables if dotenv.ps1 exists
function Initialize-DBEnvironment {
[OutputType([void])]
Param()
if ((Test-Path env:DB_MYSQL_USERNAME) -or (Test-Path env:DB_PGSQL_USERNAME) -or `
(Test-Path env:DB_SQLITE_DATABASE)
) {
return
}
$dotenv = Get-ChildItem -Path $PSScriptRoot/.. -Include 'dotenv.ps1' -Recurse -File | `
Select-Object -First 1 -ExpandProperty FullName
if ($null -eq $dotenv) {
Write-Verbose "dotenv.ps1 file not found, look at tests/testdata/dotenv.example.ps1."
return
}
. $dotenv
Write-Host "Sourced env. file: " -ForegroundColor DarkGreen -NoNewline
Write-Host $dotenv
}
function Export-SharedLibraries {
[CmdletBinding(PositionalBinding = $false)]
[OutputType([string[]])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
HelpMessage = "Specifies path to export.")]
[string[]]
$Path
)
process {
# Check if they are already on the $env:Path
$dllPathsToAdd = @()
if (-not ($env:Path -eq '')) {
foreach ($dllPath in $Path) {
$dllPathToMatch = Get-PathToMatch -Path $dllPath
if ($env:Path -notmatch $dllPathToMatch) {
$dllPathsToAdd += Get-FullPath -Path $dllPath
}
}
}
# When the Path env. variable value is empty then add all Paths
else {
$dllPathsToAdd = Get-FullPath -Path $Path
}
# Nothing to pipe
if ($dllPathsToAdd.Length -eq 0) {
return
}
# Add to the $env:Path
$dllPathsJoined = $dllPathsToAdd -join [IO.Path]::PathSeparator
$env:Path = $dllPathsJoined, $env:Path -join [IO.Path]::PathSeparator
# Pipe exported path/s
Write-Output $dllPathsToAdd
}
}
# Export TinyOrm and TinyUtils dll folders
function Initialize-RuntimeEnvironment {
[OutputType([void])]
Param()
$platform = $PSVersionTable.Platform
switch ($platform) {
'Win32NT' {
# Find dll-s parent folders
$exportedPaths = Get-ChildItem -Path $BuildPath -Include 'Tiny*.dll' -Recurse -File
| Select-Object -ExpandProperty DirectoryName
| Export-SharedLibraries
}
'Unix' {
# Find dll-s parent folders (pwsh does not work with print0 :/)
$exportedPaths = find $BuildPath -type f -and -executable -and -name 'lib*.so*' -print
| xargs dirname | xargs realpath
| Export-SharedLibraries
}
Default {
throw "$platform platform is not supported."
}
}
Write-Host "Exported paths: " -ForegroundColor DarkGreen
$exportedPaths
}
function Get-Tests {
if ($PSVersionTable.Platform -ceq 'Unix') {
return find . -type f -and -executable -and -not -name '*.sh' -and -not -name 'lib*.so*'
return find $BuildPath -type f -and -executable -and `
-not -name '*.sh' -and -not -name 'lib*.so*'
}
else {
return Get-ChildItem -Path *.exe -Recurse
return Get-ChildItem -Path $BuildPath -Include '*.exe' -Recurse
}
}
function Get-Elapsed {
[CmdletBinding(PositionalBinding = $false)]
[OutputType([int])]
Param(
[Parameter(Position = 0, Mandatory = $true, HelpMessage = "Specifies the RegEx pattern to look up the elapsed value.")]
[Parameter(Position = 0, Mandatory,
HelpMessage = 'Specifies the RegEx pattern to look up the elapsed value.')]
[ValidateNotNullOrEmpty()]
[string]
$Pattern,
[Parameter(Position = 1, Mandatory = $true, HelpMessage = "Specifies the string in which to find the elapsed value.")]
[Parameter(Position = 1, Mandatory,
HelpMessage = 'Specifies the string in which to find the elapsed value.')]
[ValidateNotNullOrEmpty()]
[string]
$String
@@ -55,9 +172,12 @@ function Get-Elapsed {
}
function Write-HighlightedOutput {
[CmdletBinding(PositionalBinding = $false)]
[OutputType([void])]
Param(
[Parameter(Position = 0, Mandatory = $true, HelpMessage = "Specifies the Test Output in which to find and highlight the elapsed value.")]
[Parameter(Position = 0, Mandatory,
HelpMessage = 'Specifies the Test Output in which to find and highlight the elapsed ' +
'value.')]
[ValidateNotNullOrEmpty()]
[string[]]
$Value
@@ -80,41 +200,55 @@ function Write-HighlightedOutput {
Write-Host "$($elapsed)ms" -ForegroundColor DarkGreen
}
for ($i = 1; $i -le $Count; $i++) {
if ($i -gt 1) {
Write-Host
}
Write-Host "$i. AutoTests Run" -ForegroundColor DarkBlue
Write-Host
function Invoke-Tests {
[OutputType([void])]
Param()
$testsElapsed = 0
foreach ($test in Get-Tests) {
$testOutput = & $test -silent
if ($LASTEXITCODE -ne 0) {
for ($i = 1; $i -le $Count; $i++) {
if ($i -gt 1) {
Write-Host
throw "Last Exit code was not 0, it was: $LASTEXITCODE"
}
Write-Host "$i. AutoTests Run" -ForegroundColor DarkBlue
Write-Host
$testsElapsed = 0
foreach ($test in Get-Tests) {
$testOutput = & $test -silent
if ($LASTEXITCODE -ne 0) {
Write-Host
throw "Last Exit code was not 0, it was: $LASTEXITCODE"
}
# Execution time of the current test
$testsElapsed += Get-Elapsed -Pattern ', (?<elapsed>\d+)ms' `
-String $($testOutput -join "`n")
Write-HighlightedOutput -Value $testOutput
}
# Execution time of the current test
$testsElapsed += Get-Elapsed -Pattern ', (?<elapsed>\d+)ms' `
-String $($testOutput -join "`n")
Write-Host
Write-Host "Tests Execution time : " -NoNewline
Write-Host "$($testsElapsed)ms" -ForegroundColor Green
Write-HighlightedOutput -Value $testOutput
$Script:TotalElapsed += $testsElapsed
}
Write-Host
Write-Host "Tests Execution time : " -NoNewline
Write-Host "$($testsElapsed)ms" -ForegroundColor Green
Write-Host "All AutoTests Execution time : " -NoNewline
Write-Host "$($Script:TotalElapsed)ms" -ForegroundColor Green
$Script:TotalElapsed += $testsElapsed
[int] $averageElapsed = $Script:TotalElapsed / $Count
Write-Host "All AutoTests Average Execution time : " -NoNewline
Write-Host "$($averageElapsed)ms" -ForegroundColor Green
}
Write-Host
Write-Host "All AutoTests Execution time : " -NoNewline
Write-Host "$($Script:TotalElapsed)ms" -ForegroundColor Green
Initialize-Environment
[int] $averageElapsed = $Script:TotalElapsed / $Count
Write-Host "All AutoTests Average Execution time : " -NoNewline
Write-Host "$($averageElapsed)ms" -ForegroundColor Green
try {
Invoke-Tests
}
finally {
$env:Path = $Script:EnvPathBackup
}

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env pwsh
Param(
[Parameter(Position = 0, Mandatory = $false,
[Parameter(Position = 0,
HelpMessage = 'Specifies the path to the cmake build folder, is pwd by default.')]
[ValidateNotNullOrEmpty()]
[string] $BuildPath = $($(Get-Location).Path),

71
tools/private/Common.ps1 Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/env pwsh
Set-StrictMode -Version 3.0
# Get slashes by platform
function Get-Slashes {
[OutputType([string])]
Param()
# Cached value
if ($Script:Slashes) {
return $Script:Slashes
}
$platform = $PSVersionTable.Platform
switch ($platform) {
'Win32NT' {
return $Script:Slashes = '\\/'
}
'Unix' {
return $Script:Slashes = '/'
}
Default {
throw "$platform platform is not supported."
}
}
}
function Get-PathToMatch {
[OutputType([string])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
HelpMessage = "Specifies a path to modify to the match pattern.")]
[ValidateNotNullOrEmpty()]
[string]
$Path
)
$slashes = Get-Slashes
$pathToMatch = $Path `
-replace "[$slashes]+(?![$slashes]*$)", "[$slashes]+" `
-replace "[$slashes]+$", ''
$separator = [IO.Path]::PathSeparator
return "(?:^|$separator)$pathToMatch[$slashes]*(?:$|$separator)"
}
function Get-FullPath {
[CmdletBinding()]
[OutputType([string[]])]
Param(
[Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelinebyPropertyName,
HelpMessage = "Specifies a path to normalize.")]
[string[]]
$Path
)
process {
[string[]] $normalized = @()
foreach ($p in $Path) {
$normalized += [System.IO.Path]::GetFullPath(($p -replace "[$(Get-Slashes)]+$", ''))
}
return $normalized
}
}