From 3ebaeefa180d195823e3b11a2159f76a26bd6790 Mon Sep 17 00:00:00 2001 From: Bhadra Date: Thu, 8 Jan 2026 18:08:59 +0530 Subject: [PATCH] fix(windows): fix CLI argument passing for switches like -DryRun - Fix mole.cmd batch launcher to properly pass switch arguments - Store %~dp0 before parse loop to avoid expansion issues - Use PowerShell splatting in Invoke-MoleCommand for proper switch handling - Rename $script:DryRun to $script:MoleDryRunMode in file_ops.ps1 to avoid variable shadowing when dot-sourcing - Handle switches passed as strings (e.g., '-ShowHelp') in mole.ps1 Main() Fixes issue where 'mole clean -DryRun' would run cleanup instead of preview. --- windows/install.ps1 | 15 ++++++- windows/lib/core/file_ops.ps1 | 16 ++++---- windows/mole.ps1 | 74 ++++++++++++++++++++++++++++++----- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/windows/install.ps1 b/windows/install.ps1 index 7854144..2bca337 100644 --- a/windows/install.ps1 +++ b/windows/install.ps1 @@ -294,9 +294,22 @@ function Install-Mole { } # Create launcher batch file for easier access + # Note: Store %~dp0 immediately to avoid issues with delayed expansion in the parse loop $batchContent = @" @echo off -powershell.exe -ExecutionPolicy Bypass -NoLogo -File "%~dp0mole.ps1" %* +setlocal EnableDelayedExpansion + +rem Store the script directory immediately before any shifting +set "MOLE_DIR=%~dp0" + +set "ARGS=" +:parse +if "%~1"=="" goto run +set "ARGS=!ARGS! '%~1'" +shift +goto parse +:run +powershell.exe -ExecutionPolicy Bypass -NoLogo -NoProfile -Command "& '%MOLE_DIR%mole.ps1' !ARGS!" "@ $batchPath = Join-Path $InstallDir "mole.cmd" Set-Content -Path $batchPath -Value $batchContent -Encoding ASCII diff --git a/windows/lib/core/file_ops.ps1 b/windows/lib/core/file_ops.ps1 index 53eb416..7be9188 100644 --- a/windows/lib/core/file_ops.ps1 +++ b/windows/lib/core/file_ops.ps1 @@ -17,7 +17,7 @@ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path # Global State # ============================================================================ -$script:DryRun = $env:MOLE_DRY_RUN -eq "1" +$script:MoleDryRunMode = $env:MOLE_DRY_RUN -eq "1" $script:TotalSizeCleaned = 0 $script:FilesCleaned = 0 $script:TotalItems = 0 @@ -153,7 +153,7 @@ function Remove-SafeItem { $sizeHuman = Format-ByteSize -Bytes $size # Handle dry run - if ($script:DryRun) { + if ($script:MoleDryRunMode) { $name = if ($Description) { $Description } else { Split-Path -Leaf $Path } Write-DryRun "$name $($script:Colors.Yellow)($sizeHuman dry)$($script:Colors.NC)" Set-SectionActivity @@ -216,7 +216,7 @@ function Remove-SafeItems { $size = Get-PathSize -Path $path - if ($script:DryRun) { + if ($script:MoleDryRunMode) { $totalSize += $size $removedCount++ continue @@ -243,7 +243,7 @@ function Remove-SafeItems { $sizeKB = [Math]::Ceiling($totalSize / 1024) $sizeHuman = Format-ByteSize -Bytes $totalSize - if ($script:DryRun) { + if ($script:MoleDryRunMode) { Write-DryRun "$Description $($script:Colors.Yellow)($removedCount items, $sizeHuman dry)$($script:Colors.NC)" } else { @@ -330,7 +330,7 @@ function Remove-EmptyDirectories { foreach ($dir in $emptyDirs) { if (Test-SafePath -Path $dir.FullName) { - if (-not $script:DryRun) { + if (-not $script:MoleDryRunMode) { try { Remove-Item -Path $dir.FullName -Force -ErrorAction Stop $removedCount++ @@ -347,7 +347,7 @@ function Remove-EmptyDirectories { } if ($removedCount -gt 0) { - if ($script:DryRun) { + if ($script:MoleDryRunMode) { Write-DryRun "$Description $($script:Colors.Yellow)($removedCount dirs dry)$($script:Colors.NC)" } else { @@ -422,7 +422,7 @@ function Set-DryRunMode { Enable or disable dry-run mode #> param([bool]$Enabled) - $script:DryRun = $Enabled + $script:MoleDryRunMode = $Enabled } function Test-DryRunMode { @@ -430,7 +430,7 @@ function Test-DryRunMode { .SYNOPSIS Check if dry-run mode is enabled #> - return $script:DryRun + return $script:MoleDryRunMode } # ============================================================================ diff --git a/windows/mole.ps1 b/windows/mole.ps1 index 00833bd..cc8f1b0 100644 --- a/windows/mole.ps1 +++ b/windows/mole.ps1 @@ -146,7 +146,7 @@ function Show-MainMenu { # Command Router # ============================================================================ -function Invoke-Command { +function Invoke-MoleCommand { param( [string]$CommandName, [string[]]$Arguments @@ -161,8 +161,45 @@ function Invoke-Command { return } - # Execute the command script with arguments - & $scriptPath @Arguments + # Execute the command script with arguments using splatting + # This properly handles switch parameters passed as strings + if ($Arguments -and $Arguments.Count -gt 0) { + # Build a hashtable for splatting + $splatParams = @{} + $positionalArgs = @() + + foreach ($arg in $Arguments) { + # Remove surrounding quotes if present + $cleanArg = $arg.Trim("'`"") + + if ($cleanArg -match '^-(\w+)$') { + # It's a switch parameter (e.g., -DryRun) + $paramName = $Matches[1] + $splatParams[$paramName] = $true + } + elseif ($cleanArg -match '^-(\w+)[=:](.+)$') { + # It's a named parameter with value (e.g., -Name=Value or -Name:Value) + $paramName = $Matches[1] + $paramValue = $Matches[2].Trim("'`"") + $splatParams[$paramName] = $paramValue + } + else { + # Positional argument + $positionalArgs += $cleanArg + } + } + + # Execute with splatting + if ($positionalArgs.Count -gt 0) { + & $scriptPath @splatParams @positionalArgs + } + else { + & $scriptPath @splatParams + } + } + else { + & $scriptPath + } } # ============================================================================ @@ -194,27 +231,44 @@ function Main { # Initialize Initialize-Mole + # Handle switches passed as strings (when called via batch file with quoted args) + # e.g., mole '-ShowHelp' becomes $Command = "-ShowHelp" instead of $ShowHelp = $true + $effectiveShowHelp = $ShowHelp + $effectiveVersion = $Version + $effectiveCommand = $Command + + if ($Command -match '^-(.+)$') { + $switchName = $Matches[1] + switch ($switchName) { + 'ShowHelp' { $effectiveShowHelp = $true; $effectiveCommand = $null } + 'Help' { $effectiveShowHelp = $true; $effectiveCommand = $null } + 'h' { $effectiveShowHelp = $true; $effectiveCommand = $null } + 'Version' { $effectiveVersion = $true; $effectiveCommand = $null } + 'v' { $effectiveVersion = $true; $effectiveCommand = $null } + } + } + # Handle version flag - if ($Version) { + if ($effectiveVersion) { Show-Version return } # Handle help flag - if ($ShowHelp -and -not $Command) { + if ($effectiveShowHelp -and -not $effectiveCommand) { Show-MainHelp return } # If command specified, route to it - if ($Command) { + if ($effectiveCommand) { $validCommands = @("clean", "uninstall", "analyze", "status", "optimize", "purge") - if ($Command -in $validCommands) { - Invoke-Command -CommandName $Command -Arguments $CommandArgs + if ($effectiveCommand -in $validCommands) { + Invoke-MoleCommand -CommandName $effectiveCommand -Arguments $CommandArgs } else { - Write-Error "Unknown command: $Command" + Write-Error "Unknown command: $effectiveCommand" Write-Host "" Write-Host "Available commands: $($validCommands -join ', ')" Write-Host "Run 'mole -ShowHelp' for more information" @@ -239,7 +293,7 @@ function Main { } Clear-Host - Invoke-Command -CommandName $selectedCommand -Arguments @() + Invoke-MoleCommand -CommandName $selectedCommand -Arguments @() Write-Host "" Write-Host " Press any key to continue..."