diff --git a/base.linux/Backup-ViaSyncoid.ps1 b/base.linux/Backup-ViaSyncoid.ps1 index 4ae6e70..416bc90 100644 --- a/base.linux/Backup-ViaSyncoid.ps1 +++ b/base.linux/Backup-ViaSyncoid.ps1 @@ -1,7 +1,7 @@ [CmdletBinding()]param( [switch]$NoClearScreen, [string]$DataSet = 'szmedia/nextcloud', - [string]$DestBackupRoot = '_gw:z/szbackup' + [string]$DestBackupRoot = 'root@gw.lksz.me:z/szbackup' ) if( -not $NoClearScreen ) { Clear-Host } Write-Verbose "& syncoid --recursive `$DataSet{'$DataSet'} `"`$DestBackupRoot/`$DataSet`"{`"$DestBackupRoot/$DataSet`"}" diff --git a/base.linux/Repair-Permissions.ps1 b/base.linux/Repair-Permissions.ps1 index 87823a1..383f7a5 100644 --- a/base.linux/Repair-Permissions.ps1 +++ b/base.linux/Repair-Permissions.ps1 @@ -48,7 +48,7 @@ process { $local:item = $Path | Get-Item $Path | Get-Item | ForEach-Object { - $local:p = $_.FullName + $local:p = $_.FullName -replace "'","''" $local:nextCmd = "" $nextCmd = "(@(Get-Item '$p') + (Get-ChildItem '$p' $cmdArgs)) | " + diff --git a/base.linux/sranger.ps1 b/base.linux/sranger.ps1 index d8146d3..cd8082b 100644 --- a/base.linux/sranger.ps1 +++ b/base.linux/sranger.ps1 @@ -1 +1,20 @@ -Invoke-ExpressionEx -sudo "`$env:TERM='tmux-256color'; `$env:EDITOR='$env:EDITOR'; ranger $args" +[CmdletBinding()]param( + [Parameter(Position = 0, ValueFromRemainingArguments)] + [string[]]$Path, + [string]$User, + [switch]$NoTmuxManipulations +) + +$local:sudoParams = @{sudoArgs=@("-i")} +if( $User ) { + $sudoParams.sudoArgs += @("-u",$User) +} + +if( -not $NoTmuxManipulations ) { + # this should probably be controlled by byobu-keybindings script, but it looks like it's broken + tmux source-file $env:BYOBU_PREFIX/share/byobu/keybindings/f-keys.tmux.disable ';' source-file ~/.byobu/keybindings.tmux ';' display-message "Byobu F-keys: DISABLED" +} +Invoke-ExpressionEx -sudo @sudoParams "`$env:TERM='tmux-256color'; `$env:EDITOR='$env:EDITOR'; ranger $($Path -join '')" +if( -not $NoTmuxManipulations ) { + tmux source-file $env:BYOBU_PREFIX/share/byobu/keybindings/f-keys.tmux ';' source-file ~/.byobu/keybindings.tmux ';' display-message "Byobu F-keys: ENABLED" +} diff --git a/base/Move-WithRsync.ps1 b/base/Move-WithRsync.ps1 new file mode 100644 index 0000000..f70badc --- /dev/null +++ b/base/Move-WithRsync.ps1 @@ -0,0 +1,143 @@ +[CmdletBinding(SupportsShouldProcess,ConfirmImpact='Medium')]param( + [Parameter(Mandatory,ParameterSetName="RemoteSrc")] + [string]$RemoteSrc, + [Parameter(Mandatory,ParameterSetName="Local",Position=1)] + [Parameter(Mandatory,ParameterSetName="RemoteSrc",Position=1)] + [Parameter(Mandatory,ParameterSetName="RemoteDst",Position=1)] + [string]$SrcBase, + [Parameter(Mandatory,ParameterSetName="Local",Position=2)] + [Parameter(Mandatory,ParameterSetName="RemoteSrc",Position=2)] + [Parameter(Mandatory,ParameterSetName="RemoteDst",Position=2)] + [string]$DstBase, + [Parameter(Mandatory,ParameterSetName="RemoteDst")] + [string]$RemoteDst, + [Parameter(Position=4)] + [string]$Path=".", + [switch]$NoPassThru, + [int]$Depth=-1, + [int]$Limit, + [Alias("Do")] + [switch]$NoSimulate +) +Write-Host -ForegroundColor Cyan ( $PSCmdlet | Out-String ) +Write-Host -ForegroundColor Yellow ( $PSBoundParameters | Out-String ) + +function GetLocalPath{ +[CmdletBinding(SupportsShouldProcess,ConfirmImpact='Low')]param( + [string]$LocalBase, + [string]$Path = "." +) + return ([System.IO.Path]::GetFullPath((Join-Path $LocalBase $Path),"/")) +} + +function GetRemotePath{ +[CmdletBinding(SupportsShouldProcess,ConfirmImpact='Low')]param( + [string]$RemoteAddr, + [string]$RemoteBase, + [string]$Path = "." +) + return "$RemoteAddr`:$( + [Management.Automation.WildcardPattern]::Escape( + [System.IO.Path]::GetFullPath((Join-Path $RemoteBase $Path),"/") + ) -replace '([&\[\(\)\\])','\$1' + )" +} + +function GetSubstituedPath{ +[CmdletBinding(SupportsShouldProcess,ConfirmImpact='Low')]param( + [string]$OriginalPath, + [string]$Base, + [string]$ReplaceBase, + [string]$RemotePrefix +) + + $local:newPath = $OriginalPath -replace "^$([regex]::Escape($Base))",($ReplaceBase -replace '\$(\d)','\$$1') + if( $RemotePrefix ) { + $newPath = GetRemotePath $RemotePrefix $newPath + } + return $newPath +} + + +$local:SrcPath = GetLocalPath $SrcBase $Path +$local:DstPath = GetLocalPath $DstBase $Path +$local:LocalPath = [string]::Empty + +if( -not $RemoteSrc ) { + $LocalPath = $SrcPath +} else { + $LocalPath = $DstPath +} + +function GetSortedDirsDepthFirst { + param([string]$Path,$StopDepth=-1,$CurrentDepth=0) + + $local:dirs = Get-ChildItem $Path -Directory | + Sort-Object Name + foreach( $local:d in $dirs ) { + if( $StopDepth -lt 0 -or $CurrentDepth -lt $StopDepth ) { + GetSortedDirsDepthFirst $d.FullName $StopDepth ($CurrentDepth + 1) + } + $d + } +} + +$local:limitParam = @{} +if( $Limit -gt 0 ) { + $limitParam.First = $Limit +} +$local:Pairs = @() +if( -not $RemoteSrc ) { + $Pairs = GetSortedDirsDepthFirst $LocalPath -StopDepth $Depth | + Select-Object @limitParam | + ForEach-Object { + [PSCustomObject]([ordered]@{ + SrcGB = -1 + Src = GetLocalPath $_.FullName + Dst = GetSubstituedPath $_.FullName $SrcPath $DstPath $RemoteDst + }) + } +} else { + $Pairs = , ([PSCustomObject]([ordered]@{ + Src = GetRemotePath $RemoteSrc $SrcPath + Dst = $DstPath + })) +} + +$local:sw = [System.Diagnostics.Stopwatch]::StartNew(); +$Pairs | ForEach-Object { + $local:s = $_.Src -replace "'",'${Q}' + $local:d = $_.Dst -replace "'",'\\${Q}' + $local:skip = $false + if( $_.SrcGB ) { + $_.SrcGB = [Math]::Round( ( + Get-ChildItem -Recurse -File $_.Src | Measure-Object -Sum Length + ).Sum / 1000000000, 2) + if( -not $_.SrcGB ) { + $_.SrcGB = "Skip" + } else { + $_.SrcGB = "$($_.SrcGB) GB" + } + } + Write-Host -ForegroundColor Cyan ($($_ | Format-Table -HideTableHeaders | Out-String).Trim()) + $local:exp = "Q=\`"'\`"; rsync -avzh --remove-source-files --progress \`"$s/\`" \`"$d/\`"" + + $sw.Restart() + if( -not $_.SrcGB -or $_.SrcGB -ne "Skip" ) { + $exp | Out-Host + + sh -c $exp | Out-Host + } + + Write-Host -Cyan "Cleanup '$s'..." + $exp = "Q=\`"'\`"; find \`"$s\`" -type d -empty -delete" + sh -c $exp | Out-Host + + [PSCustomObject]([ordered]@{ + PSTypeName = 'RsyncReport' + SrcGB = $_.SrcGB + Elapsed = $sw.Elapsed + Src = $_.Src + Dst = $_.Dst + }) +} diff --git a/base/Remove-NoFileDirs.ps1 b/base/Remove-NoFileDirs.ps1 new file mode 100644 index 0000000..4b15401 --- /dev/null +++ b/base/Remove-NoFileDirs.ps1 @@ -0,0 +1,19 @@ +[CmdletBinding()]param( + [Parameter(ValueFromPipeline,ValueFromPipelineByPropertyName,Position=0,Mandatory)] + [Alias('FullName')] + [string[]]$Path +) + +begin {} +process { + $Path | + Get-ChildItem -Directory -Recurse | + Where-Object { + 0 -eq (Get-ChildItem -File -Recurse ($_.FullName -replace '([\[\]])','`$1')).Length + } | + ForEach-Object { + Write-Host "Removing $($_.FullName)..." + Remove-Item -Force -Recurse -LiteralPath $_.FullName + } +} +end {} diff --git a/docker/Switch-DockerCompose.ps1 b/docker/Switch-DockerCompose.ps1 index d6bafca..70a11f3 100644 --- a/docker/Switch-DockerCompose.ps1 +++ b/docker/Switch-DockerCompose.ps1 @@ -31,8 +31,7 @@ $ProjectPath | ForEach-Object { $gciParams.Depth = $Depth } $dcPathList += Get-ChildItem -Path $_ -Include "docker-compose$ext" @gciParams | - Select-Object -ExpandProperty Directory # | -# Where-Object { $Force -or -not (Test-Path $(Join-Path $_ .noauto.all)) } + Select-Object -ExpandProperty Directory } if( ($dcPathList -and -not $Recure) -or $ext -eq '.yaml' ) { break @@ -46,6 +45,16 @@ $local:QueryOnly = -not $On -and -not $Off -and -not $Toggle $dcPathList | ForEach-Object { $local:name = "$_" + $local:c = Get-Content -Head 3 (Join-Path $_ "docker-compose$ext") + $local:r = [ordered]@{ + Dir = Split-Path -Leaf $_ + State = "" + Version = ($c[0] -replace 'Version: ','' -replace "[`"']",'').Trim() + Stack = "?" + } + if( $c[1] -match "^# stack(?:\W*): ?(\w+)\W*$" ) { $r.Stack = $matches[1] } + if( $c[2] -match "^# ports prefix: ([\dx#]{4,5})" ) { $r.Stack = $matches[1] + " | " + $r.Stack } + if( $PWD -like $name ) { $name = Split-Path -Leaf $name } else { @@ -65,12 +74,16 @@ $dcPathList | ForEach-Object { } elseif( -not $QueryOnly -and -not $IsOff ) { $null = New-Item -ItemType File -Path $NoAutoPath -Value "" } - Write-Host -ForegroundColor Magenta -NoNewline "Off" + # Write-Host -ForegroundColor Magenta -NoNewline "Off" + $r.State = "Off" } elseif( ($QueryOnly -and -not $IsOff) -or (-not $QueryOnly -and $SetOn) ) { if( -not $QueryOnly -and $IsOff ) { Move-Item $NoAutoPath $NoAutoOffPath } - Write-Host -ForegroundColor Green -NoNewline "On " + # Write-Host -ForegroundColor Green -NoNewline "On " + $r.State = "On" } - Write-Host -ForegroundColor Cyan " $name" + # Write-Host -ForegroundColor Cyan " $name" + + [PSCustomObject]$r }