Introducing Packages
Major Overhaul with Breaking Changes split into packaged, default behavior moved into 'base' package each package has a json package description file with criteria for loading Modified Setup-Profile to refer to 'base' package path for auto loading moved Linux aliases and command to 'base.linux' package created 'docker' package to address docker supported systems modified Get-MyScripts, Edit-MyScripts and Reload-MyScripts accordingly. Dropped -System and sys.*, package json conditions will take care of it. Supplied command to create/edit package json files: - New-MyPackage - Add-PackageCondition - Set-MyPackage
This commit is contained in:
parent
80a488484b
commit
42b39f4e25
83 changed files with 505 additions and 130 deletions
21
base/Add-PackageCondition.ps1
Normal file
21
base/Add-PackageCondition.ps1
Normal file
|
@ -0,0 +1,21 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[Parameter(mandatory=$true, ValueFromPipeline=$true)]
|
||||
[szPackage]$InputObject,
|
||||
[szLogic]$logic = "and",
|
||||
[ScriptBlock]$CustomCondition,
|
||||
[string[]]$System = $null,
|
||||
[string[]]$Hostname = $null,
|
||||
[string[]]$Username = $null
|
||||
)
|
||||
|
||||
process {
|
||||
$local:newCond = New-Object -Type 'szCondition'
|
||||
$newCond.custom = $CustomCondition
|
||||
$newCond.System = $System
|
||||
$newCond.Hostname = $Hostname
|
||||
$newCond.Username = $null
|
||||
$newCond.Logic = [szLogic]::and
|
||||
$InputObject.Condition += $newCond
|
||||
|
||||
$InputObject
|
||||
}
|
1
base/Aliases/dcedit.ps1
Normal file
1
base/Aliases/dcedit.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
Edit-DockerCompose
|
1
base/Aliases/dco.ps1
Normal file
1
base/Aliases/dco.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
docker-compose
|
1
base/Aliases/dps.ps1
Normal file
1
base/Aliases/dps.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
Get-DockerProcess
|
1
base/Aliases/edit
Normal file
1
base/Aliases/edit
Normal file
|
@ -0,0 +1 @@
|
|||
Edit-TextFile
|
1
base/Aliases/l.ps1
Normal file
1
base/Aliases/l.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
ls
|
1
base/Aliases/ll.ps1
Normal file
1
base/Aliases/ll.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
ls
|
1
base/Aliases/sz-update.ps1
Normal file
1
base/Aliases/sz-update.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
Update-OSz
|
1
base/Aliases/vi
Normal file
1
base/Aliases/vi
Normal file
|
@ -0,0 +1 @@
|
|||
Edit-TextFile
|
1
base/Aliases/vidc.ps1
Normal file
1
base/Aliases/vidc.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
Edit-DockerCompose
|
1
base/Aliases/vim
Normal file
1
base/Aliases/vim
Normal file
|
@ -0,0 +1 @@
|
|||
Edit-TextFile
|
2
base/ConvertFrom-Base64.ps1
Normal file
2
base/ConvertFrom-Base64.ps1
Normal file
|
@ -0,0 +1,2 @@
|
|||
param([string]$Base64String)
|
||||
return [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($Base64String))
|
24
base/Edit-MyConfig.ps1
Normal file
24
base/Edit-MyConfig.ps1
Normal file
|
@ -0,0 +1,24 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[Parameter(Position = 0, ValueFromRemainingArguments)]
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
[MyConfig]::_GetValidValues($wordToComplete,$true) | Sort-Object
|
||||
})]
|
||||
[string[]]$ConfigName,
|
||||
[switch]$Force,
|
||||
[switch]$sudo
|
||||
)
|
||||
if( -not $ConfigName ) {
|
||||
([MyConfig]::_GetValidValues('',$true)) | Sort-Object
|
||||
return
|
||||
}
|
||||
$local:ScriptPaths = [MyConfig]::GetConfigPaths($ConfigName,$Force)
|
||||
|
||||
Edit-TextFile -sudo:$sudo $ScriptPaths
|
||||
|
||||
$null = [MyConfig]::_GetValidValues('', $true)
|
23
base/Edit-MyProfiles.ps1
Normal file
23
base/Edit-MyProfiles.ps1
Normal file
|
@ -0,0 +1,23 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[switch]$Force,
|
||||
[Parameter(ValueFromRemainingArguments = $true)]
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
[MyScript]::_GetValidValues($wordToComplete,$true)
|
||||
})]
|
||||
[string[]]$AlsoEditTheseScripts
|
||||
)
|
||||
|
||||
$local:FilePaths = @() + $( Get-Profiles | Where-Object { $_.Exists -or $Force } | Select-Object -ExpandProperty Path )
|
||||
foreach( $local:p in $AlsoEditTheseScripts ) {
|
||||
$local:sp = Join-Path $MyPSScriptRoot "$p`.ps1"
|
||||
$FilePaths += $sp
|
||||
}
|
||||
|
||||
Edit-TextFile -sudo:$sudo $FilePaths
|
93
base/Edit-MyScript.ps1
Normal file
93
base/Edit-MyScript.ps1
Normal file
|
@ -0,0 +1,93 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
[FunctionName]::_GetValidValues($wordToComplete,$true)
|
||||
})]
|
||||
[string[]]$ImportFunction,
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
$local:NotAll = $true
|
||||
if( $fakeBoundParameters.ContainsKey("All") ) { $NotAll = -not $fakeBoundParameters.All }
|
||||
[Packagesz]::_GetValidValues($wordToComplete,$NotAll,$true)
|
||||
})]
|
||||
[string]$Package,
|
||||
[switch]$ForceImport,
|
||||
[switch]$All,
|
||||
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
$local:NotAll = $true
|
||||
$local:Pkg = [string]::Empty
|
||||
if( $fakeBoundParameters.ContainsKey("All") ) { $NotAll = -not $fakeBoundParameters.All }
|
||||
if( $fakeBoundParameters.ContainsKey("Package") ) { $Pkg = Join-Path $fakeBoundParameters.Package '' }
|
||||
$local:possibleValues = [MyScript]::_GetValidValues($wordToComplete,$NotAll,$true)
|
||||
if( $Pkg ) {
|
||||
$possibleValues = $possibleValues |
|
||||
Where-Object { $_ -match "^$Pkg" } |
|
||||
ForEach-Object { $_.Replace($Pkg,'') }
|
||||
}
|
||||
|
||||
$possibleValues
|
||||
})]
|
||||
[string[]]$ScriptName
|
||||
)
|
||||
|
||||
$local:EditRootPath=$MyPSScriptRoot
|
||||
if( $Package ) {
|
||||
$EditRootPath = Join-Path $EditRootPath $Package
|
||||
}
|
||||
$local:ScriptPaths = @()
|
||||
foreach( $local:p in $ImportFunction ) {
|
||||
$local:f = Get-Command $p -Type Function
|
||||
if( $f ) {
|
||||
$local:sp = Join-Path $EditRootPath "$p`.ps1"
|
||||
if( $ForceImport -or -not (Test-Path $sp) ) {
|
||||
Export-FunctionSource $p -NoHeader > $sp
|
||||
} elseif ( -not $ForceImport ) {
|
||||
throw "$p already exists in Script, to import the function again, use the -Force"
|
||||
}
|
||||
$ScriptPaths += $sp
|
||||
}
|
||||
}
|
||||
foreach( $local:p in $ScriptName ) {
|
||||
$local:sp = Join-Path $EditRootPath "$p`.ps1"
|
||||
$ScriptPaths += $sp
|
||||
}
|
||||
|
||||
if( -not $ScriptPaths ) {
|
||||
$ScriptPaths += $EditRootPath
|
||||
}
|
||||
|
||||
foreach( $local:p in $ScriptPaths ) {
|
||||
$local:parentPath = Split-Path -Parent $p;
|
||||
if( -not (Test-Path $p) -and -not (Test-Path $parentPath) ) {
|
||||
Write-Verbose "Creating missing path $parentPath..."
|
||||
New-Item -Type Directory $parentPath
|
||||
}
|
||||
}
|
||||
|
||||
$local:sw = [System.Diagnostics.Stopwatch]::StartNew();
|
||||
Edit-TextFile $ScriptPaths
|
||||
$sw.Stop();
|
||||
|
||||
if( $sw.Elapsed.TotalSeconds -lt 1 ) {
|
||||
$null = Read-Host "Waiting before refreshing. Press <Enter> when you're done editing ( don't forget to save ;) )..."
|
||||
}
|
||||
|
||||
Get-Command Reload-MyScripts -ErrorAction SilentlyContinue |
|
||||
ForEach-Object { . $_.Definition }
|
31
base/Edit-TextFile.ps1
Normal file
31
base/Edit-TextFile.ps1
Normal file
|
@ -0,0 +1,31 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
|
||||
[string[]]$Path
|
||||
)
|
||||
|
||||
$local:editors = $env:EDITOR,'nvim','code'
|
||||
$local:editor = $null
|
||||
foreach( $local:testEditor in $editors ) {
|
||||
if( $(try{Get-Command -Type Application $testEditor -ErrorAction SilentlyContinue}catch{}) ) {
|
||||
$editor = $testEditor
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( $editor -match 'vim?$' ) {
|
||||
$editor += ' -p'
|
||||
}
|
||||
|
||||
if( $editor -match 'code(\.exe)?$' ) {
|
||||
if( -not (Get-Process -Name 'code' -ErrorAction SilentlyContinue) ) {
|
||||
Invoke-ExpressionEx -sudo:$sudo $editor
|
||||
}
|
||||
}
|
||||
|
||||
$local:arguments = $Path -join "' '"
|
||||
if( $Path ) { $arguments = "'$arguments'" }
|
||||
|
||||
if( $PSCmdlet.ShouldProcess( "Edit ($editor): $arguments" ) ) {
|
||||
Invoke-ExpressionEx -sudo:$sudo $editor "$arguments"
|
||||
}
|
21
base/Get-MyPackages.ps1
Normal file
21
base/Get-MyPackages.ps1
Normal file
|
@ -0,0 +1,21 @@
|
|||
[CmdletBinding()]param(
|
||||
[Parameter(ParameterSetName="OptionA")]
|
||||
[Parameter(ParameterSetName="Path")]
|
||||
[switch]$Force,
|
||||
[Parameter(ParameterSetName="Path",Mandatory)]
|
||||
[switch]$ReturnFullPath,
|
||||
[Parameter(ParameterSetName="Path")]
|
||||
[switch]$IncludeRoot
|
||||
)
|
||||
|
||||
$local:packages = [Packagesz]::_GetValidValues("", -not $Force, $true) | Sort-Object
|
||||
if( $IncludeRoot -and $ReturnFullPath ) { $MyPSScriptRoot }
|
||||
foreach ( $local:pkg in $packages ) {
|
||||
if( $ReturnFullPath ) {
|
||||
Join-Path $MyPSScriptRoot $pkg
|
||||
} else {
|
||||
$pkg
|
||||
}
|
||||
}
|
||||
|
||||
|
44
base/Get-MyScript.ps1
Normal file
44
base/Get-MyScript.ps1
Normal file
|
@ -0,0 +1,44 @@
|
|||
[CmdletBinding()]param(
|
||||
[Parameter(ParameterSetName="Normal")]
|
||||
[Parameter(ParameterSetName="DropNamespace")]
|
||||
[string]$Filter,
|
||||
[Parameter(ParameterSetName="ByPackage",Mandatory)]
|
||||
[Parameter(ParameterSetName="DropNamespace",Mandatory)]
|
||||
[ArgumentCompleter({ param (
|
||||
$commandName,
|
||||
$parameterName,
|
||||
$wordToComplete,
|
||||
$commandAst,
|
||||
$fakeBoundParameters
|
||||
)
|
||||
$local:NotAll = $true
|
||||
if( $fakeBoundParameters.ContainsKey("Force") ) { $NotAll = -not $fakeBoundParameters.Force }
|
||||
[Packagesz]::_GetValidValues($wordToComplete,$NotAll,$true)
|
||||
})]
|
||||
[string]$Package,
|
||||
[Parameter(ParameterSetName="Normal")]
|
||||
[Parameter(ParameterSetName="ByPackage")]
|
||||
[Parameter(ParameterSetName="DropNamespace",Mandatory)]
|
||||
[switch]$NamesOnly,
|
||||
[Parameter(ParameterSetName="Normal")]
|
||||
[Parameter(ParameterSetName="ByPackage")]
|
||||
[Parameter(ParameterSetName="DropNamespace")]
|
||||
[switch]$Force,
|
||||
[Parameter(ParameterSetName="DropNamespace",Mandatory)]
|
||||
[switch]$DropNamespace
|
||||
)
|
||||
$local:rVal = [MyScript]::_GetValidValues($Filter,-not $Force,$true)
|
||||
|
||||
if( $Package ) {
|
||||
$Package = Join-Path $Package ''
|
||||
$rVal = $rVal |
|
||||
Where-Object { $_ -match "^$Package" }
|
||||
if( $DropNamespace ) {
|
||||
$rVal = $rVal |
|
||||
ForEach-Object { $_.Replace($Package,'') }
|
||||
}
|
||||
}
|
||||
|
||||
if( $NamesOnly ) { return $rVal }
|
||||
return $rVal | ForEach-Object { Join-Path $MyPSScriptRoot "$_`.ps1" }
|
||||
|
8
base/Get-Path.ps1
Normal file
8
base/Get-Path.ps1
Normal file
|
@ -0,0 +1,8 @@
|
|||
[CmdletBinding()]param([string]$Path)
|
||||
|
||||
try {
|
||||
get-item $Path -Force -ErrorAction Stop |
|
||||
Select-Object -ExpandProperty FullName
|
||||
} catch {
|
||||
$_.targetObject
|
||||
}
|
13
base/Get-PossibleArguments.ps1
Normal file
13
base/Get-PossibleArguments.ps1
Normal file
|
@ -0,0 +1,13 @@
|
|||
[CmdletBinding()]param(
|
||||
[string]$WordToComplete,
|
||||
[string[]]$FullValueSet,
|
||||
[switch]$Strict
|
||||
)
|
||||
$local:possibleValues = $fullValueSet
|
||||
if( $wordToComplete ) {
|
||||
$possibleValues = $possibleValues | Where-Object { $_ -match $wordToComplete }
|
||||
if( -not $strict -and ($wordToComplete -notin $possibleValues) ) {
|
||||
$possibleValues = $( $wordToComplete; $possibleValues )
|
||||
}
|
||||
}
|
||||
return $possibleValues
|
13
base/Get-Profiles.ps1
Normal file
13
base/Get-Profiles.ps1
Normal file
|
@ -0,0 +1,13 @@
|
|||
[CmdletBinding()]param(
|
||||
[switch]$AsDictionary
|
||||
)
|
||||
|
||||
filter ConvertTo-Hash { param([string]$Property="Name") begin { $hash = @{} } process{ $hash[$_."$Property"] = $_ } end {return $hash} }
|
||||
|
||||
$local:rVal = $PROFILE | fl * -Force | Out-String -Stream | Where-Object { $_ -match '( : /)|(:\\)' } |
|
||||
Select-Object @{
|
||||
N="Profile";E={($_ -split ": ")[0].Trim()}
|
||||
},@{N="Path";E={($_ -split ": ")[-1].Trim()}
|
||||
} | Select-Object *,@{N="Exists";E={Test-Path $_.Path}}
|
||||
if( $AsDictionary ) { return $rVal | ConvertTo-Hash -Property "Profile" }
|
||||
return $rVal
|
2
base/Get-ScopeDepth.ps1
Normal file
2
base/Get-ScopeDepth.ps1
Normal file
|
@ -0,0 +1,2 @@
|
|||
$local:_scope = 0;
|
||||
while ($true) { try { Get-Variable -Scope $_scope | Out-Null; $_scope += 1 } catch { return ($_scope - 1) } }
|
6
base/Invoke-Sudo.ps1
Normal file
6
base/Invoke-Sudo.ps1
Normal file
|
@ -0,0 +1,6 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[Parameter(Mandatory = $true,Position = 0, ValueFromRemainingArguments = $true)]
|
||||
$expr
|
||||
)
|
||||
|
||||
. Invoke-ExpressionEx -sudo $expr
|
5
base/New-MyPackage.ps1
Normal file
5
base/New-MyPackage.ps1
Normal file
|
@ -0,0 +1,5 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
[szPackage]::Create($Name)
|
111
base/Reload-MyScripts.ps1
Normal file
111
base/Reload-MyScripts.ps1
Normal file
|
@ -0,0 +1,111 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param()
|
||||
|
||||
try { Get-Alias Get-MyAliases -ErrorAction Stop | ForEach-Object { Remove-Item "Alias:$($_.Name)" } } catch {}
|
||||
function Get-MyAliases {
|
||||
[CmdletBinding(SupportsShouldProcess)]param([switch]$ScriptsOnly)
|
||||
|
||||
$local:allAliases = @()
|
||||
|
||||
$MyAliasScope = 0
|
||||
$local:_scope = 0
|
||||
$local:_done = $false
|
||||
do {
|
||||
try {
|
||||
$local:newAliases += Get-Alias -Scope $_scope |
|
||||
Where-Object {
|
||||
($_.Definition -match "^$MyPSScriptRoot") -or (-not $ScriptsOnly -and ($_.Description -match '#MyAlias'))
|
||||
}
|
||||
if( $newAliases ) {
|
||||
$allAliases += $newAliases
|
||||
$MyAliasScope = $_scope;
|
||||
Write-Verbose "`$MyAliasScope is now set to $MyAliasScope"
|
||||
}
|
||||
} catch {
|
||||
Write-Verbose "catch: $($_.Exception.Message)"
|
||||
$_done = $_.Exception.Message -match 'The scope .* exceeds'
|
||||
}
|
||||
$_scope += 1
|
||||
} until ( $_done )
|
||||
|
||||
$allAliases
|
||||
}
|
||||
|
||||
function getScriptName{param([string]$FullPath)
|
||||
$FullPath -replace '\.ps1$','' -replace "^$([regex]::Escape($MyPSScriptRoot)).",''
|
||||
}
|
||||
|
||||
$local:IsVerbose = [bool]($PSBoundParameters['Verbose'])
|
||||
|
||||
# Loads mandatory Package code
|
||||
try {
|
||||
$null = [Packagesz]
|
||||
} catch {
|
||||
$local:PackagePath = $(Join-Path $MyPSScriptRoot 'base')
|
||||
Join-Path $(Join-Path $PackagePath profile.d) 'classes.ps1' |
|
||||
Where-Object { Test-Path $_ } | ForEach-Object { . $_ }
|
||||
}
|
||||
$local:myPackages = Get-MyPackages -ReturnFullPath -IncludeRoot | Get-Item
|
||||
|
||||
$local:myAliases = [ordered]@{}
|
||||
|
||||
$myPackages |
|
||||
ForEach-Object { Join-Path $_.FullName Aliases } |
|
||||
Where-Object { Test-Path $_ } |
|
||||
Get-ChildItem | ForEach-Object {
|
||||
$myAliases[$_.BaseName] = Get-Content $_.FullName
|
||||
}
|
||||
|
||||
$script:MyAliasScope = 0
|
||||
|
||||
$local:oldAliases = Get-MyAliases
|
||||
|
||||
$oldAliases = Get-Alias -Scope $MyAliasScope |
|
||||
Where-Object Name -in $($oldAliases.Name + $myAliases.Keys)
|
||||
|
||||
if( $oldAliases -and $IsVerbose ) {
|
||||
Write-Verbose "Removing: $($oldAliases.Name -join ', ')"
|
||||
}
|
||||
if( Get-Command Remove-Alias -ErrorAction SilentlyContinue ) {
|
||||
$oldAliases | Remove-Alias -Scope $MyAliasScope
|
||||
} else {
|
||||
$oldAliases | ForEach-Object { Remove-Item "Alias:$($_.Name)" }
|
||||
}
|
||||
|
||||
if( $(. Get-ScopeDepth) -gt 0 ) {
|
||||
Write-Host -ForegroundColor Red "Try sourcing Reload-MyScripts instead of just running it"
|
||||
}
|
||||
|
||||
foreach( $local:PackagePath in $myPackages ) {
|
||||
$local:PackageName = $PackagePath.Name
|
||||
|
||||
Join-Path $PackagePath 'profile.d' | Where-Object { Test-Path $_ } |
|
||||
Get-ChildItem -Filter '*.ps1' |
|
||||
ForEach-Object {
|
||||
Write-Verbose "Loading $(getScriptName $_.FullName)...";
|
||||
". '$($_.FullName)';"
|
||||
} |
|
||||
Invoke-Expression
|
||||
|
||||
$local:CommandsToAlias = (
|
||||
@( $PackagePath ) + $(
|
||||
[SystemName]::_GetValidValues("",$true,$true) |
|
||||
ForEach-Object {
|
||||
Join-Path $PackagePath "sys.$_"
|
||||
}
|
||||
)) |
|
||||
Where-Object { Test-Path $_ } |
|
||||
ForEach-Object {
|
||||
Get-ChildItem (Join-Path $_ '*.ps1') | Where-Object Name -notmatch '\.inc\.ps1$'
|
||||
}
|
||||
|
||||
$CommandsToAlias | ForEach-Object {
|
||||
Write-Verbose "Creating alias for $(getScriptName $_.FullName) Script..."
|
||||
Set-Alias $($_.BaseName) $_.FullName -Scope $MyAliasScope
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $local:alias in $myAliases.Keys ) {
|
||||
Write-Verbose "Adding $($alias) alias..."
|
||||
Set-Alias -Name $alias -Value $myAliases[$alias] -Description '#MyAlias' -Scope $MyAliasScope
|
||||
}
|
||||
|
38
base/Set-MyPackage.ps1
Normal file
38
base/Set-MyPackage.ps1
Normal file
|
@ -0,0 +1,38 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[Parameter(mandatory=$true, ValueFromPipeline=$true)]
|
||||
[szPackage]$InputObject,
|
||||
[switch]$Force,
|
||||
[switch]$PassThru,
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
process {
|
||||
$local:outObj = @{ package = @{ Name = $InputObject.Name; Condition = @() } }
|
||||
foreach( $local:c in $InputObject.Condition ) {
|
||||
$local:newC = [ordered]@{}
|
||||
foreach( $local:p in $c.PSObject.Properties ) {
|
||||
if( $p.TypeNameOfValue -match 'ScriptBlock' -and $p.Value ) {
|
||||
$newC[$p.Name] = $p.Value.ToString().Trim()
|
||||
} else {
|
||||
$newC[$p.Name] = $p.Value
|
||||
}
|
||||
}
|
||||
$outObj.package.Condition += $newC;
|
||||
}
|
||||
$local:jsonOut = $outObj | ConvertTo-Json -Depth 4
|
||||
|
||||
if( -not $DryRun ) {
|
||||
$local:jsonPath = Join-Path $MyPSScriptRoot $_.name
|
||||
if( -not (Test-Path $jsonPath) ) { $null = New-Item -Type Directory $jsonPath -Force:$Force }
|
||||
$jsonPath = Join-Path $jsonPath '_.package.json'
|
||||
if( $Force -or -not (Test-Path $jsonPath) ) {
|
||||
$jsonOut | Out-File $jsonPath -Force:$Force
|
||||
} elseif ( Test-Path $jsonPath ) {
|
||||
throw 'Package already exists!'
|
||||
}
|
||||
}
|
||||
|
||||
if( $PassThru ) {
|
||||
$jsonOut
|
||||
}
|
||||
}
|
443
base/Setup-Profile.ps1
Normal file
443
base/Setup-Profile.ps1
Normal file
|
@ -0,0 +1,443 @@
|
|||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[switch]$RemoveOnly,
|
||||
[switch]$ShowSkipped,
|
||||
[switch]$Force,
|
||||
[switch]$NoGitAction,
|
||||
[string]$GitURL = 'https://code.lksz.me/lksz/PowerShell_Scripts',
|
||||
[Parameter(DontShow)]
|
||||
[string]$My_PSScriptRoot = $MyPSScriptRoot
|
||||
)
|
||||
|
||||
function _Setup {
|
||||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[switch]$RemoveOnly,
|
||||
[switch]$ShowSkipped,
|
||||
[switch]$Force,
|
||||
[switch]$NoGitAction,
|
||||
[string]$GitURL = 'https://code.lksz.me/lksz/PowerShell_Scripts',
|
||||
[Parameter(DontShow)]
|
||||
[string]$My_PSScriptRoot = $MyPSScriptRoot)
|
||||
|
||||
|
||||
#######################################################################
|
||||
## ProfileCode function (source) will contain the code to be written
|
||||
#######################################################################
|
||||
function ProfileCode_pre_common {
|
||||
# # If TMUX isn't loaded, start byobu, then exit this script (and current shell)
|
||||
# if ( -not ( Test-Path env:TMUX ) ) { byobu; exit }
|
||||
}
|
||||
#######################################################################
|
||||
## common Profile Code - receommended not to change this
|
||||
## Code will be loaded from profile.d sub-directory after this.
|
||||
#######################################################################
|
||||
function ProfileCode_post_common {
|
||||
# This loads the personal profile section from the $MyPSScriptRoot/profile.d directory
|
||||
Get-Command Reload-MyScripts -ErrorAction SilentlyContinue | ForEach-Object { . $_.Name }
|
||||
}
|
||||
#######################################################################
|
||||
## _Setup Logic starts here
|
||||
#######################################################################
|
||||
|
||||
. ProfileCode_common
|
||||
if( -not $MyPSScriptRoot ) { throw '$MyPSScriptRoot does NOT exist!' }
|
||||
|
||||
if ( -not $NoGitAction ) {
|
||||
if ( -not [bool]$(Get-Command git -ErrorAction SilentlyContinue) ) {
|
||||
throw "No git command found, you may either omit run with the -NoGitAction switch or install git and try again."
|
||||
}
|
||||
Push-Location $MyPSScriptRoot
|
||||
if( Test-Path $(Join-Path $MyPSScriptRoot '.git') ) {
|
||||
git pull
|
||||
} elseif ( $PSCmdlet.ShouldProcess("Pull git repo from $GitURL into $MyPSScriptRoot ?") ) {
|
||||
$local:tmpGitDir = New-TemporaryFile
|
||||
Remove-Item $tmpGitDir
|
||||
New-Item -Type Directory $tmpGitDir.FullName | Out-Null
|
||||
Write-Verbose "Cloning git repo [$GitURL] into temporary location ('$($tmpGitDir.FullName)')..."
|
||||
$local:GitOutput = "$(& git clone $GitURL $tmpGitDir.FullName --no-checkout)"
|
||||
Write-Verbose $GitOutput
|
||||
Write-Verbose "Moving git repo from temp location to $MyPSScriptRoot . . ."
|
||||
Copy-Item -Recurse (Join-Path $tmpGitDir.FullName .git) ./.git
|
||||
Remove-Item $tmpGitDir.FullName
|
||||
Write-Verbose "Checking out repo..."
|
||||
$GitOutput = "$(& git checkout --force)"
|
||||
Write-Verbose $GitOutput
|
||||
}
|
||||
Pop-Location
|
||||
Write-Verbose "Git operation done."
|
||||
}
|
||||
|
||||
$local:ProfileSignature = [PSCustomObject]([ordered]@{
|
||||
Begin = '#### SZ Auto Profile Setup - BEGIN ####'
|
||||
End = '#### SZ Auto Profile Setup - END ####'
|
||||
Removed = '#### SZ Auto Profile Setup - ----- ####'
|
||||
Match = '#### SZ Auto Profile Setup'
|
||||
})
|
||||
|
||||
function New-ProfileSetupStatus {
|
||||
param($Name, $Path, $Status, $Exist)
|
||||
return [PSCustomObject]([ordered]@{
|
||||
Name = $Name
|
||||
Path = $Path
|
||||
Status = $Status
|
||||
Exist = $Exist
|
||||
})
|
||||
}
|
||||
|
||||
$local:_profiles = $PROFILE | fl * -Force | Out-String -Stream | ForEach-Object {
|
||||
$local:p = $($_ -split ' : [/A-Z\\]');
|
||||
if ( $p[0] -match 'User' ) {
|
||||
$p[0].Trim()
|
||||
}
|
||||
}
|
||||
$local:_profile = $profile.CurrentUserAllHosts;
|
||||
$local:randomSeed = "####$(Get-Random)####";
|
||||
|
||||
if ( $RemoveOnly -and $ConfirmPreference -eq 'High' -and (-not $PSBoundParameters -or -not $PSBoundParameters.ContainsKey('Confirm')) ) {
|
||||
$script:ConfirmPreference = 'Low'
|
||||
}
|
||||
|
||||
|
||||
if ( $sudo -or $(Test-IsAdmin) ) { $_profile = $profile.AllUsersAllHosts }
|
||||
$_profiles | Foreach-Object {
|
||||
$local:p = Invoke-Expression "`$profile.$_"
|
||||
$local:profileContent = $randomSeed;
|
||||
$local:exists = Test-Path $p
|
||||
$local:userFile = $($_ -match 'CurrentUser')
|
||||
$local:cleanupValue = ''
|
||||
if ( $exists ) {
|
||||
if ( (Get-Content -Path $p | Out-String ) -match $ProfileSignature.Match ) {
|
||||
Write-Verbose "Found code in [$_]'$p', preparing..."
|
||||
$local:gate = $true;
|
||||
$profileContent = Get-Content $p | ForEach-Object {
|
||||
if ( -not $gate ) {
|
||||
if ( $_ -match $ProfileSignature.End ) {
|
||||
$gate = $true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( $_ -match $ProfileSignature.Match ) {
|
||||
if ( $_ -match $ProfileSignature.Begin ) {
|
||||
$gate = $false;
|
||||
}
|
||||
$cleanupValue = $ProfileSignature.Removed
|
||||
return $randomSeed;
|
||||
}
|
||||
return $_
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$profileContent += "`n`n$(Get-Content $p -Raw)"
|
||||
}
|
||||
}
|
||||
|
||||
if( -not( $profileContent -match $randomSeed ) ) { $profileContent = "$randomSeed`n$profileContent" }
|
||||
|
||||
$local:insertProfileCode = $false;
|
||||
if ( ($p -eq $_profile) -and -not $RemoveOnly ) {
|
||||
$insertProfileCode = $true
|
||||
Write-Verbose "Inserting ProfileCode into $($_)..."
|
||||
$cleanupValue = $((@(
|
||||
'',
|
||||
$ProfileSignature.Begin,
|
||||
'',
|
||||
$(Export-FunctionSource -NoHeader ProfileCode_pre_common),
|
||||
'',
|
||||
'',
|
||||
$(Export-FunctionSource -NoHeader ProfileCode_common),
|
||||
'',
|
||||
'',
|
||||
$(Export-FunctionSource -NoHeader ProfileCode_post_common),
|
||||
'',
|
||||
$ProfileSignature.End
|
||||
) -join "`n" ).Trim().Replace(('$' + '_'), ('$$' + '_')))
|
||||
}
|
||||
|
||||
$profileContent = $($profileContent -replace $randomSeed, $cleanupValue).Trim()
|
||||
|
||||
$local:shouldSudo = $sudo -and -not $userFile
|
||||
$local:status = 'Skipped'
|
||||
if ( $VerbosePreference -eq 'Continue' ) { $ShowSkipped = $true }
|
||||
# Test if new profile Content will be empty
|
||||
if ( -not ([string]::IsNullOrWhiteSpace($profileContent)) ) {
|
||||
$status = "Need $(if($insertProfileCode){if($exists){'Setup'}else{'Init'}}else{'Cleanup'})"
|
||||
if ( $sudo -or $userFile ) {
|
||||
Write-Verbose "Writing content to $($_)..."
|
||||
$local:tmpOutput = New-TemporaryFile -WhatIf:$false -Confirm:$false
|
||||
$profileContent | Out-File $tmpOutput.FullName -WhatIf:$false -Confirm:$false
|
||||
if ( $shouldSudo -and $( $PSVersionTable.Platform -eq 'Unix' ) ) {
|
||||
# Make sure the file has the right permissions on a Unix machine
|
||||
Invoke-ExpressionEx -sudo:$shouldSudo chmod 'a+r' $tmpOutput.FullName
|
||||
}
|
||||
try {
|
||||
$local:errMsg = $(Invoke-ExpressionEx -sudo:$shouldSudo @"
|
||||
if( -not (Test-Path $(Split-Path -Parent $p)) ) { New-Item -Type Directory $(Split-Path -Parent $p) -Force };
|
||||
Copy-Item $($tmpOutput.FullName) $p -Force:`$$Force -ErrorAction Stop | Out-Null;
|
||||
Remove-Item $($tmpOutput.FullName) -Force:`$$Force -ErrorAction Stop
|
||||
"@ 2>&1)
|
||||
if ( $errMsg ) {
|
||||
Write-Error "$errMsg"
|
||||
$status = $status -replace 'Need ', 'Failed '
|
||||
}
|
||||
else {
|
||||
$status = $status -replace 'Need ', ''
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Error "Writing $p failed!"
|
||||
}
|
||||
}
|
||||
else {
|
||||
$status = "Need $status"
|
||||
Write-Error "Cannot write into [$_]'$p'! Please re-run with sudo."
|
||||
}
|
||||
}
|
||||
elseif ( ($Force -or $RemoveOnly) -and $exists ) {
|
||||
$status = 'Need Removal'
|
||||
if ( $sudo -or $userFile ) {
|
||||
Write-Verbose "Removing [$_]'$p'..."
|
||||
try {
|
||||
Invoke-ExpressionEx -sudo:$shouldSudo Remove-Item $p
|
||||
if ( -not (Test-Path $p) ) { $status = 'Removed' }
|
||||
}
|
||||
catch {
|
||||
Write-Error "Removal of $p failed!"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "Cannot remove [$_]'$p'! Please re-run with sudo."
|
||||
}
|
||||
}
|
||||
if ( $status -ne 'Skipped' -or $ShowSkipped ) {
|
||||
if ( $shouldSudo -and $status -ne 'Skipped' ) { $status = "$status via sudo" }
|
||||
New-ProfileSetupStatus -Name $_ -Path $p -Status $status -Exist $(Test-Path $p)
|
||||
}
|
||||
}
|
||||
|
||||
Remove-Item function:ProfileCode* -Confirm:$false
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
## ProfileCode_common (source) containing mandatory code for $PROFILE
|
||||
#######################################################################
|
||||
function ProfileCode_common {
|
||||
function Get-PowerShellPath {
|
||||
Get-Process -PID $PID | ForEach-Object { $_.Path, $_.Parent.Path } | Where-Object { $_ -match 'powershell|pwsh' } | Select-Object -First 1
|
||||
}
|
||||
|
||||
function ConvertTo-Base64 {
|
||||
param([string]$String)
|
||||
return [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($String))
|
||||
}
|
||||
|
||||
function Invoke-ExpressionEx {
|
||||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[switch]$Force,
|
||||
[string]$Function,
|
||||
[switch]$MarshalOutput,
|
||||
[Parameter(Position = 1, ValueFromRemainingArguments = $true)]
|
||||
[string[]]$expr
|
||||
)
|
||||
|
||||
function do_sudo {
|
||||
[CmdletBinding()]param(
|
||||
[string]$sudo_cmd
|
||||
)
|
||||
|
||||
function do_sudo_win {
|
||||
[CmdletBinding()]param(
|
||||
[string]$sudo_cmd
|
||||
)
|
||||
|
||||
$local:sudo_exec = [string]::Empty
|
||||
if ( (Get-Command scoop -ErrorAction SilentlyContinue) ) {
|
||||
$sudo_exec = $(scoop which gsudo *>&1)
|
||||
if ( $sudo_exec -match 'not found' ) {
|
||||
$sudo_exec = $(scoop which sudo *>&1)
|
||||
}
|
||||
if ( $sudo_exec -match 'not found' ) { $sudo_exec = [string]::Empty }
|
||||
}
|
||||
if ( $sudo_exec ) {
|
||||
& $sudo_exec $sudo_cmd
|
||||
}
|
||||
else {
|
||||
Write-Error "Didn't find a known sudo command"
|
||||
}
|
||||
}
|
||||
|
||||
if ( $PSVersionTable.Platform -eq 'Unix' ) {
|
||||
/usr/bin/env sudo $(Get-PowerShellPath) "-noprofile" "-EncodedCommand" $(ConvertTo-Base64 $sudo_cmd)
|
||||
}
|
||||
else {
|
||||
$local:currentIdenity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
if ( $currentIdenity.UserClaims.Value -contains 'S-1-5-32-544' ) {
|
||||
do_sudo_win $sudo_cmd
|
||||
}
|
||||
else {
|
||||
Write-Error "User [$($currentIdenity.Name)]does not have permissions to run as admin."
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( $sudo -and -not $(Test-IsAdmin) ) {
|
||||
$local:tmpOutputFile = $null
|
||||
$local:tmpScriptFile = $null
|
||||
|
||||
$local:sudo_cmd = "$($expr -join ' ')".Trim()
|
||||
if ( $Function ) {
|
||||
$tmpScriptFile = New-TemporaryFile -WhatIf:$false -Confirm:$false
|
||||
$tmpScriptFile = Move-Item $tmpScriptFile.FullName "$($tmpScriptFile.FullName).ps1" -PassThru -WhatIf:$false -Confirm:$false
|
||||
|
||||
$local:tmpScriptContent = Export-FunctionSource $Function
|
||||
$sudo_cmd = "$Function $sudo_cmd"
|
||||
|
||||
$tmpScriptContent | Out-File $tmpScriptFile.FullName -WhatIf:$false
|
||||
$expr = @( ".", $tmpScriptFile.FullName, ";", "`n$Function" ) + $expr
|
||||
}
|
||||
|
||||
$expr = @(
|
||||
"`n`$WhatIfPreference=`$$WhatIfPreference;",
|
||||
"`n`$VerbosePreference='$VerbosePreference';",
|
||||
"`n`$ErrorActionPreference='$ErrorActionPreference';",
|
||||
"`n`$ConfirmPreference='$ConfirmPreference';`n"
|
||||
) + $expr
|
||||
|
||||
if ( $MarshalOutput ) {
|
||||
$tmpOutputFile = New-TemporaryFile -WhatIf:$false -Confirm:$false
|
||||
$expr += @( "| Export-CliXml -Path '$($tmpOutputFile.FullName)'" )
|
||||
}
|
||||
|
||||
$expr += @( ";`n exit `$LastExitCode" )
|
||||
|
||||
## $tmpScriptContent += "$($expr -join ' ')".Trim()
|
||||
Write-Verbose "Performing the following command line via SUDO:`n{$sudo_cmd}"
|
||||
|
||||
$sudo_cmd = "$($expr -join ' ')".Trim()
|
||||
|
||||
do_sudo $sudo_cmd
|
||||
## do_sudo 'Get-Content' $tmpScriptFile.FullName '|' 'Invoke-Expression' '|' 'Export-Clixml' '-Path' $tmpOutputFile.FullName
|
||||
#do_sudo $sudo_cmd
|
||||
|
||||
if ( $tmpScriptFile ) { Remove-Item $tmpScriptFile }
|
||||
if ( $tmpOutputFile ) { Import-Clixml $tmpOutputFile; Remove-Item $tmpOutputFile }
|
||||
return
|
||||
}
|
||||
|
||||
Write-Verbose "Perofrming the following expression in-line:`n{$($expr -join ' ')}"
|
||||
Invoke-Expression "$expr"
|
||||
}
|
||||
|
||||
function Test-IsAdmin {
|
||||
[CmdletBinding(ConfirmImpact = 'None')]
|
||||
[OutputType([bool])]
|
||||
param()
|
||||
|
||||
switch ($true) {
|
||||
$( ($PSVersionTable.PSEdition -eq 'Desktop') -or
|
||||
($PSVersionTable.Platform -eq 'Win32NT')
|
||||
) {
|
||||
# Fastest way on Windows
|
||||
([Security.Principal.WindowsPrincipal](
|
||||
[Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
)).IsInRole(
|
||||
[Security.Principal.WindowsBuiltInRole]'Administrator'
|
||||
)
|
||||
}
|
||||
$( ($PSVersionTable.PSEdition -eq 'Core') -and
|
||||
($PSVersionTable.Platform -eq 'Unix')
|
||||
) {
|
||||
# On macOS and Linux we use ID to figure out if we run elevated (0 means superuser rights)
|
||||
return $((id -u) -eq 0)
|
||||
}
|
||||
default {
|
||||
# Unable to figure it out!
|
||||
Write-Warning -Message 'Unknown'
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Export-FunctionSource {
|
||||
param(
|
||||
[switch]$NoHeader,
|
||||
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
|
||||
#[ValidateSet([Functions])]
|
||||
[string[]]$FunctionName
|
||||
)
|
||||
|
||||
$local:src = ""
|
||||
foreach ( $local:func in $FunctionName ) {
|
||||
$local:funcDef = $null
|
||||
foreach( $cmd in (Get-Command -All $func) ) {
|
||||
if( $cmd.CommandType -in @('Function','Filter') ) {
|
||||
$funcDef = $cmd.Definition
|
||||
break
|
||||
} elseif( -$funcDef -and ($cmd.CommandType -in @('Script','ExternalScript')) ) {
|
||||
$funcDef = Get-Content $cmd.Definition
|
||||
}
|
||||
}
|
||||
if( -not $funcDef ) {
|
||||
default { throw "Don't know how to handle $func" }
|
||||
}
|
||||
|
||||
if ( -not $NoHeader ) { $src += "`nfunction $func {" }
|
||||
$src += "`n"
|
||||
|
||||
$src += $funcDef
|
||||
if ( -not $NoHeader ) { $src += "`n}" }
|
||||
$src += "`n"
|
||||
}
|
||||
return $src.Trim()
|
||||
}
|
||||
|
||||
# Are we running in Unix or Windows?
|
||||
$global:PathEnvDelimiter = $(if ( $PSVersionTable.Platform -match 'unix' ) { ':' } else { ';' })
|
||||
function Split-PathEnv {
|
||||
param([string]$EnvPath)
|
||||
$EnvPath -split $PathEnvDelimiter
|
||||
}
|
||||
|
||||
# Establish Module Path
|
||||
$global:MyPSModulePath = Split-PathEnv $env:PSModulePath |
|
||||
Where-Object { $_ -match "^$($(Resolve-Path ~) -replace '\\',"\\")" } |
|
||||
Where-Object { Test-Path $_ } |
|
||||
Get-Item | Sort-Object -Property LastWriteTime -Descending |
|
||||
Select-Object -ExpandProperty FullName -First 1
|
||||
|
||||
if ( -not $MyPSModulePath ) {
|
||||
$MyPSModulePath = $(Join-Path $(Join-Path $(Resolve-Path ~) 'powershell') 'Modules')
|
||||
$env:PSModulePath = "$MyPSModulePath$PathEnvDelimiter$env:PSModulePath"
|
||||
}
|
||||
if ( -not (Test-Path $MyPSModulePath) ) {
|
||||
New-Item -ItemType Directory -Path $MyPSModulePath -Force | Out-Null
|
||||
}
|
||||
|
||||
Write-Verbose $(Get-Item $MyPSModulePath | Select-Object -ExpandProperty FullName)
|
||||
|
||||
# Establish local/personal Script Root and make sure it's in $env:Path
|
||||
$local:p = Split-PathEnv $env:PATH
|
||||
$local:My_PSScriptRoot = Join-Path (Split-Path -Parent $MyPSModulePath) Scripts
|
||||
Write-Verbose "MyPSScriptRoot = $My_PSScriptRoot"
|
||||
if ( -not (Test-Path $My_PSScriptRoot) ) {
|
||||
New-Item -ItemType Directory -Path $My_PSScriptRoot -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path $(Join-Path $My_PSScriptRoot base) -Force | Out-Null
|
||||
New-Item -ItemType Directory -Path $(Join-Path $(Join-Path $My_PSScriptRoot base) profile.d) -Force | Out-Null
|
||||
}
|
||||
$global:MyPSScriptRoot = $My_PSScriptRoot
|
||||
|
||||
$p = @($p[0], $(Join-Path $My_PSScriptRoot base)) + $($p | Select-Object -Skip 1)
|
||||
$env:PATH = $p -join $PathEnvDelimiter
|
||||
}
|
||||
|
||||
$SetupFromWeb = [bool]$(@( $SetupFromWeb, $sfw, $LoadCode ) | Where-Object { $_ })
|
||||
|
||||
if ( -not $SetupFromWeb ) {
|
||||
_setup @PSBoundParameters
|
||||
Get-Item function:_setup | Remove-Item
|
||||
Get-Command Reload-MyScripts -ErrorAction SilentlyContinue | ForEach-Object { . $_.Name }
|
||||
}
|
||||
Remove-Variable SetupFromWeb -ErrorAction SilentlyContinue
|
13
base/Stop-ProcessTree.ps1
Normal file
13
base/Stop-ProcessTree.ps1
Normal file
|
@ -0,0 +1,13 @@
|
|||
[cmdletbinding()]param([string]$ProcessName)
|
||||
$local:new_KillPIDs = @() + (Get-Process -name $processName | Select-Object -ExpandProperty ID)
|
||||
$local:KillPIDs = @()
|
||||
Do {
|
||||
$KillPIDs += $new_KillPIDs | Where-Object { $_ -notin $KillPIDs }
|
||||
Write-Verbose "Again"
|
||||
Write-Verbose $new_KillPIDs -join ", "
|
||||
$new_KillPIDs = $new_KillPIDs | ForEach-Object { Get-CimInstance -ClassName Win32_Process -Filter "ParentProcessId = $_" } | Select-Object -ExpandProperty ProcessId
|
||||
} Until ( -not $new_KillPIDs )
|
||||
|
||||
Write-Verbose "Done"
|
||||
|
||||
start-process powershell -ArgumentList "-command","Stop-Process -Force -Id @($($KillPIDs -join '', ''))" -WindowStyle Minimized
|
5
base/_.package.json
Normal file
5
base/_.package.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"package": {
|
||||
"name": "base"
|
||||
}
|
||||
}
|
32
base/profile.d/Docker.class.ps1
Normal file
32
base/profile.d/Docker.class.ps1
Normal file
|
@ -0,0 +1,32 @@
|
|||
class DockerContainer { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) {
|
||||
$local:possibleValues = $(
|
||||
docker ps -a --no-trunc --format "{{.Names}}"
|
||||
)
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [DockerContainer]::_GetValidValues('',$true)
|
||||
}
|
||||
}
|
||||
|
||||
class DockerComposeDirs { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) {
|
||||
$local:possibleValues = $(
|
||||
Get-ChildItem -Directory -Depth 3 |
|
||||
Where-Object { $_ |
|
||||
Get-ChildItem -Include 'docker-compose.y*l' |
|
||||
Where-Object Extension -in '.yml','.yaml'
|
||||
} | ForEach-Object {
|
||||
$_.FullName.Replace($(Join-Path $PWD ""),'')
|
||||
}
|
||||
)
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [DockerComposeDirs]::_GetValidValues('',$true)
|
||||
}
|
||||
}
|
||||
|
21
base/profile.d/FromPowerShellCookbook.ps1
Normal file
21
base/profile.d/FromPowerShellCookbook.ps1
Normal file
|
@ -0,0 +1,21 @@
|
|||
# PowerShell Cookbook has a lot of code there, I'm only interested in
|
||||
# the Add-ObjectCollector which adds an overloaded Out-Default version,
|
||||
# which stores a history of output objects.
|
||||
# One major problem with loading this from the module, is that when the
|
||||
# module is removed the shell BREAKS.
|
||||
#
|
||||
# The code below, makes sure the module is removed, and then imports
|
||||
# only the Add-ObjectCollector code from it.
|
||||
# All I really want is the Out-Default function created by
|
||||
# Add-ObjectCollector, and so, I'll also remove the function once done.
|
||||
|
||||
if( Get-Module PowerShellCookbook ) {
|
||||
Remove-Module PowerShellCookbook
|
||||
|
||||
Import-Module PowerShellCookbook -Cmdlet Add-ObjectCollector
|
||||
}
|
||||
#
|
||||
. Get-Command Add-ObjectCollector -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Add-ObjectCollector
|
||||
Get-Item function:/Add-ObjectCollector | Remove-Item
|
||||
}
|
21
base/profile.d/FunctionName.class.ps1
Normal file
21
base/profile.d/FunctionName.class.ps1
Normal file
|
@ -0,0 +1,21 @@
|
|||
class FunctionName { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) {
|
||||
$local:possibleValues = Get-Command -Type Function | Select-Object -ExpandProperty Name
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
static [String[]] _GetValidValues([string]$wordToComplete,[switch]$Strict) {
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $(Get-Command -Type Function | Select-Object -ExpandProperty Name) -Strict:$Strict)
|
||||
# $local:possibleValues =
|
||||
# if( $wordToComplete ) {
|
||||
# $possibleValues = $possibleValues | Where-Object { $_ -match $wordToComplete }
|
||||
# if( -not $strict -and ($wordToComplete -notin $possibleValues) ) {
|
||||
# $possibleValues = $( $wordToComplete; $possibleValues )
|
||||
# }
|
||||
# }
|
||||
# return $possibleValues
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [FunctionName]::_GetValidValues('',$true)
|
||||
}
|
||||
}
|
61
base/profile.d/MyConfig.class.ps1
Normal file
61
base/profile.d/MyConfig.class.ps1
Normal file
|
@ -0,0 +1,61 @@
|
|||
class MyConfig { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
hidden static [hashtable]$_HardCodedConfigDict = @{
|
||||
'myconfig' = @($(Join-Path $(Join-Path $PackagePath 'src') 'config.files.json'),
|
||||
$(Join-Path $(Join-Path $PackagePath 'src') 'config.files.local.json'))
|
||||
'mymodules' = @($(Join-Path $(Join-Path $PackagePath 'src') 'modules.json'),
|
||||
$(Join-Path $(Join-Path $PackagePath 'src') 'modules.local.json'))
|
||||
}
|
||||
|
||||
static [hashtable]GetConfigDictionary() {
|
||||
$local:result = @{}
|
||||
[MyConfig]::_HardCodedConfigDict.Keys | ForEach-Object { $result[$_] = [MyConfig]::_HardCodedConfigDict[$_] }
|
||||
foreach( $local:jsonSource in $result.myconfig ) {
|
||||
if( -not ( Test-Path $jsonSource ) ) { continue }
|
||||
foreach( $local:prop in $(Get-Content $jsonSource | ConvertFrom-Json).PSObject.Properties ) {
|
||||
$result[$prop.Name] = $prop.Value
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
static [string[]] GetConfigPaths([string[]]$ConfigNames,[switch]$Force) {
|
||||
$local:configDirectory = [MyConfig]::GetConfigDictionary()
|
||||
$local:result = [string[]]@()
|
||||
$local:flat = $false
|
||||
while(-not $flat) {
|
||||
$flat = $true
|
||||
$ConfigNames += $ConfigNames | ForEach-Object {
|
||||
$configDirectory[$_]
|
||||
} | Where-Object { $_ -match '^#[\w-\.]+$' } | ForEach-Object {
|
||||
$_.Substring(1)
|
||||
} | Where-Object { $_ -notin $ConfigNames } | ForEach-Object {
|
||||
$flat = false; $_;
|
||||
}
|
||||
}
|
||||
|
||||
$local:flatConfigList = $ConfigNames | ForEach-Object {
|
||||
$configDirectory[$_]
|
||||
} | Where-Object { $_ -notmatch '^#[\w-\.]+$' }
|
||||
|
||||
$local:exists = $false;
|
||||
$local:first = $null
|
||||
foreach( $local:configPath in $flatConfigList ) {
|
||||
if( -not $first ) { $first = $configPath }
|
||||
if( $Force -or (Test-Path $configPath) ) {
|
||||
$result += Get-Path $configPath
|
||||
$exists = $true
|
||||
}
|
||||
}
|
||||
if( -not $exists -and -not $Force ) {
|
||||
$result += $first
|
||||
}
|
||||
return $result
|
||||
}
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$Strict) {
|
||||
$local:possibleValues = [MyConfig]::GetConfigDictionary().Keys
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [MyConfig]::_GetValidValues('',$true)
|
||||
}
|
||||
}
|
16
base/profile.d/MyScript.class.ps1
Normal file
16
base/profile.d/MyScript.class.ps1
Normal file
|
@ -0,0 +1,16 @@
|
|||
class MyScript { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$CurrentOnly,[bool]$Strict) {
|
||||
$local:possibleValues = $(
|
||||
Get-MyPackages -ReturnFullPath -IncludeRoot -Force:$(-not $CurrentOnly) |
|
||||
Get-ChildItem -Filter '*.ps1' |
|
||||
Select-Object -ExpandProperty FullName | ForEach-Object {
|
||||
$_ -replace '\.ps1$','' -replace "$($MyPSScriptRoot -replace '\\',"\\")[/\\]",''
|
||||
}
|
||||
)
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [MyScript]::_GetValidValues('',$false,$true)
|
||||
}
|
||||
}
|
2
base/profile.d/Style.ps1
Normal file
2
base/profile.d/Style.ps1
Normal file
|
@ -0,0 +1,2 @@
|
|||
Get-Command Set-PSReadLineKeyHandler | ForEach-Object { Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete }
|
||||
Get-Command Set-Theme -ErrorAction SilentlyContinue | ForEach-Object { Set-Theme Paradox }
|
24
base/profile.d/Test-MyModules.ps1
Normal file
24
base/profile.d/Test-MyModules.ps1
Normal file
|
@ -0,0 +1,24 @@
|
|||
param([switch]$Force)
|
||||
|
||||
$local:currentSys = [SystemName]::_GetValidValues('',$true,$true);
|
||||
|
||||
if( -not $global:MyModulesWarning -or $Force ) {
|
||||
$global:MyModulesWarning = @()
|
||||
}
|
||||
[MyConfig]::GetConfigPaths('mymodules',$false) |
|
||||
ForEach-Object {
|
||||
$local:modules = $( Get-Content $_ | ConvertFrom-Json );
|
||||
$modules.Always;
|
||||
$currentSys | ForEach-Object { $modules."$_" } | Where-Object { $_}
|
||||
} | Where-Object {
|
||||
$local:m = $_
|
||||
if( $( try {
|
||||
-not (Get-Module -ListAvailable $m -ErrorAction stop)
|
||||
} catch { $true }
|
||||
)) {
|
||||
$m -notin $global:MyModulesWarning
|
||||
}
|
||||
} | ForEach-Object {
|
||||
$global:MyModulesWarning += $_
|
||||
Write-Warning "Missing module: $_"
|
||||
}
|
4
base/profile.d/UnixCompleters.ps1
Normal file
4
base/profile.d/UnixCompleters.ps1
Normal file
|
@ -0,0 +1,4 @@
|
|||
Get-Command Import-UnixCompleters -ErrorAction SilentlyContinue | ForEach-Object {
|
||||
Import-UnixCompleters
|
||||
Set-UnixCompleter -ShellType Zsh
|
||||
}
|
3
base/profile.d/classes.ps1
Normal file
3
base/profile.d/classes.ps1
Normal file
|
@ -0,0 +1,3 @@
|
|||
. Invoke-Expression ". $(Join-Path $(Join-Path $PackagePath 'src') 'SystemName.class.inc.ps1')"
|
||||
. Invoke-Expression ". $(Join-Path $(Join-Path $PackagePath 'src') 'Packagesz.class.inc.ps1')"
|
||||
|
3
base/profile.d/env.local.ps1.template
Normal file
3
base/profile.d/env.local.ps1.template
Normal file
|
@ -0,0 +1,3 @@
|
|||
# $env:DOMAIN_NAME='example.com'
|
||||
#
|
||||
# $env:EDITOR='/usr/bin/nvim'
|
1
base/profile.d/env.ps1
Normal file
1
base/profile.d/env.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
$env:SZ_SKIP_DEFAULT_SHELL = 1
|
1
base/profile.d/load-z.ps1
Normal file
1
base/profile.d/load-z.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
Get-Module -ListAvailable z | Import-Module
|
97
base/src/Packagesz.class.inc.ps1
Normal file
97
base/src/Packagesz.class.inc.ps1
Normal file
|
@ -0,0 +1,97 @@
|
|||
class Packagesz { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [hashtable]GetPackageDictionary() {
|
||||
$local:packages = @{}
|
||||
|
||||
Get-ChildItem $global:MyPSScriptRoot |
|
||||
ForEach-Object { Join-Path $_.FullName "_.package.json" } |
|
||||
Where-Object { Test-Path $_ } |
|
||||
Get-Item |
|
||||
ForEach-Object {
|
||||
$local:testPkg = Get-Content $_ -Raw |
|
||||
ConvertFrom-Json |
|
||||
Select-Object -ExpandProperty "package" -ErrorAction SilentlyContinue
|
||||
if( $testPkg ) {
|
||||
$local:k = $_.Directory.FullName.Replace($MyPSScriptRoot,'') -replace '^/',''
|
||||
$packages[$k] = $testPkg
|
||||
}
|
||||
}
|
||||
|
||||
return $packages;
|
||||
}
|
||||
static [bool] ValidatePackageConditions($Package) {
|
||||
if( -not $Package.Condition ) { return $true }
|
||||
$local:valid = $Package.Condition[0].Logic -notin ([szLogic]::or, [szLogic]::ornot)
|
||||
$local:currentSys = [SystemName]::_GetValidValues('',$true,$true);
|
||||
$local:hostname = $(hostname)
|
||||
$local:username = $env:USER ?? $env:USERNAME
|
||||
foreach( $local:c in $Package.Condition ) {
|
||||
if( $valid -eq ($c.Logic -in ([szLogic]::or, [szLogic]::ornot )) ) { continue }
|
||||
|
||||
$local:v = $true;
|
||||
if( $v -and $c.System ) {
|
||||
$v = $v -and $($c.System | Where-Object { $currentSys -contains $_ })
|
||||
}
|
||||
if( $v -and $c.Hostname ) {
|
||||
$v = $v -and $($c.Hostname | Where-Object { $hostname -match $_ })
|
||||
}
|
||||
if( $v -and $c.Username ) {
|
||||
$v = $v -and $($c.Username | Where-Object { $username -match $_ })
|
||||
}
|
||||
if( $v -and $c.custom ) {
|
||||
$v = $v -and ([bool]$(Invoke-ScriptBlock ([ScriptBlock]::Create($c.custom))))
|
||||
}
|
||||
switch( $c.Logic ) {
|
||||
[szLogic]::not { $valid = $valid -and -not $v }
|
||||
[szLogic]::or { $valid = $valid -or $v }
|
||||
[szLogic]::ornot { $valid = $valid -or -not $v }
|
||||
default { $valid = $valid -and $v }
|
||||
}
|
||||
}
|
||||
return $valid
|
||||
}
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$CurrentOnly,[bool]$Strict) {
|
||||
$local:pkgz = [Packagesz]::GetPackageDictionary()
|
||||
$local:possibleValues = $pkgz.Keys |
|
||||
Where-Object { -not $CurrentOnly -or $(
|
||||
[Packagesz]::ValidatePackageConditions($pkgz[$_])
|
||||
) }
|
||||
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [Packagesz]::_GetValidValues('',$false,$true)
|
||||
}
|
||||
}
|
||||
|
||||
enum szLogic {
|
||||
and = 0
|
||||
not = 1 # nand
|
||||
or = 2
|
||||
ornot = 3
|
||||
}
|
||||
|
||||
class szCondition {
|
||||
[ScriptBlock]$custom = { $true }
|
||||
[string[]]$System = $null
|
||||
[string[]]$Hostname = $null
|
||||
[string[]]$Username = $null
|
||||
[szLogic]$Logic = [szLogic]::and
|
||||
|
||||
[string] ToString() {
|
||||
return "Logic = $($this.Logic); System = $($this.System); Hostname = $($this.Hostname); Username = $($this.Username); Custom = { $($this.Custom.ToString().Trim()) }"
|
||||
}
|
||||
}
|
||||
|
||||
class szPackage {
|
||||
[string]$Name
|
||||
[szCondition[]]$Condition
|
||||
|
||||
static [szPackage]Create($Name) {
|
||||
$local:newPkg = New-Object -Type 'szPackage'
|
||||
$newPkg.Name = $Name
|
||||
$newPkg.Condition = @()
|
||||
|
||||
return $newPkg
|
||||
}
|
||||
}
|
38
base/src/SystemName.class.inc.ps1
Normal file
38
base/src/SystemName.class.inc.ps1
Normal file
|
@ -0,0 +1,38 @@
|
|||
class SystemName { #: System.Management.Automation.IValidateSetValuesGenerator {
|
||||
static [string[]] _GetValidValues([string]$wordToComplete,[bool]$CurrentOnly,[bool]$Strict) {
|
||||
$MyPSScriptRoot = "$global:MyPSScriptRoot";
|
||||
$local:possibleValues = [ordered]@{}
|
||||
$possibleValues.out = @()
|
||||
$possibleValues.Current = @(
|
||||
$($global:PSVersionTable.OS -split ' '|Select-Object -First 1).Replace('Microsoft','Windows'),
|
||||
$global:PSVersionTable.Platform,
|
||||
$global:PSVersionTable.PSEdition
|
||||
);
|
||||
$possibleValues.out = $possibleValues.Current
|
||||
|
||||
if( -not $CurrentOnly ) {
|
||||
$possibleValues.Platform = @( 'Windows','Linux','Unix' );
|
||||
$possibleValues.Edition = @( 'Desktop', 'Core' );
|
||||
$possibleValues.Exist = Get-ChildItem (Join-Path $MyPSScriptRoot "sys.*") | ForEach-Object { $_.Name -replace 'sys\.','' };
|
||||
$possibleValues.out += $possibleValues.Platform + $possibleValues.Edition + $possibleValues.Exist
|
||||
}
|
||||
$possibleValues.out = $possibleValues.out |
|
||||
Select-Object -Unique |
|
||||
Where-Object { $_ } |
|
||||
Sort-Object {
|
||||
$local:sortName = "zz_$_";
|
||||
if( $_ -in $possibleValues.Exist -and $_ -in $possibleValues.Current ) { $sortName[0] = "a" }
|
||||
elseif( $_ -in $possibleValues.Exist ) { $sortName[0] = "b" }
|
||||
elseif( $_ -in $possibleValues.Current ) { $sortName[0] = "c" }
|
||||
if( $_ -in $possibleValues.Platform ) { $sortName[1] = "a" }
|
||||
if( $_ -in $possibleValues.Edition ) { $sortName[1] = "b" }
|
||||
$sortName;
|
||||
}
|
||||
return $(Get-PossibleArguments -WordToComplete $wordToComplete -FullValueSet $possibleValues.out -Strict:$Strict );
|
||||
}
|
||||
|
||||
[String[]] GetValidValues() {
|
||||
return [SystemName]::_GetValidValues('',$false,$true)
|
||||
}
|
||||
}
|
||||
|
44
base/src/config.files.json
Normal file
44
base/src/config.files.json
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"neovim": [
|
||||
"~/.config/nvim/init.vim",
|
||||
"~/.config/nvim/vim-plug/plugins.vim",
|
||||
"#vim",
|
||||
"#vi"
|
||||
],
|
||||
"sz-shrc": "~/.sz.shrc.sh",
|
||||
"sz-rc-all": [
|
||||
"#sz-aliases-sh",
|
||||
"#sz-local-rc",
|
||||
"#sz-shrc",
|
||||
"#sz-zshrc",
|
||||
"#zshrc"
|
||||
],
|
||||
"vi": "~/.virc",
|
||||
"sz-local-rc": "~/.sz.local.sh",
|
||||
"zshrc": "~/.zshrc",
|
||||
"ansible": [
|
||||
"/etc/ansible/ansible.cfg",
|
||||
"/opt/ansible/ansible.cfg",
|
||||
"/opt/ansible/hosts"
|
||||
],
|
||||
"sz-aliases-sh": "~/.sz.aliases.sh",
|
||||
"vim": [
|
||||
"~/.vimrc",
|
||||
"~/.vim/vimrc"
|
||||
],
|
||||
"sz-zshrc": [
|
||||
"~/.sz.zshrc.sh",
|
||||
"#zshrc"
|
||||
],
|
||||
"tmux": [
|
||||
"~/.tmux.conf",
|
||||
"~/.byobu/.tmux.conf"
|
||||
],
|
||||
"ssh-pub": "~/.ssh/id_*.pub",
|
||||
"ssh-id": ["~/.ssh/id_ed25519","~/.ssh/id_rsa"],
|
||||
"ssh-auth": "~/.ssh/authorized_keys",
|
||||
"ssh-known": "~/.ssh/known_hosts",
|
||||
"ssh-conf": "~/.ssh/config",
|
||||
"sshd-conf": "/etc/ssh/sshd_config",
|
||||
"ssh" : [ "#ssh-auth", "#ssh-known", "#ssh-conf", "#sshd-conf", "#ssh-pub", "#ssh-id" ]
|
||||
}
|
14
base/src/modules.json
Normal file
14
base/src/modules.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"Always": [
|
||||
"PowerShellCookbook",
|
||||
"oh-my-posh",
|
||||
"posh-git",
|
||||
"z"
|
||||
],
|
||||
"Desktop": [
|
||||
],
|
||||
"Unix": [
|
||||
"Microsoft.PowerShell.UnixCompleters"
|
||||
]
|
||||
|
||||
}
|
18
base/src/smartsudo.inc.ps1
Normal file
18
base/src/smartsudo.inc.ps1
Normal file
|
@ -0,0 +1,18 @@
|
|||
function smartsudo() {
|
||||
[CmdletBinding(SupportsShouldProcess)]param(
|
||||
[switch]$sudo,
|
||||
[switch]$Force,
|
||||
[Parameter(Position = 0, ValueFromRemainingArguments = $true)]
|
||||
[string[]]$expr
|
||||
)
|
||||
|
||||
if( $sudo -and -not $(Test-IsAdmin) ) {
|
||||
Write-Verbose "Perofrming the following command line via SUDO:`n$($expr -join ' ')"
|
||||
$local:base64command = ConvertTo-Base64 "$expr"
|
||||
/usr/bin/env sudo pwsh -EncodedCommand $base64command
|
||||
return
|
||||
}
|
||||
|
||||
Write-Verbose "Perofrming the following expression in-line:`n$($expr -join ' ')"
|
||||
Invoke-Expression "$expr"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue