Skip to content

Commit 26fbf0c

Browse files
committed
+Invoke-TreeCommand for running a command for every file in a source folder with {InputFileName} and {OutputFileName} tokens to mirror results in an OutputFolder
For a tokendump of the entire Delphi source folder: ```powershell $BaseOutput = 'C:\Delphi\tokendump' $TimeStamp = Get-Date -Format 'yyyy-MM-dd.HH-mm' $OutputDirectory = Join-Path $BaseOutput $TimeStamp Invoke-TreeCommand ` -InputDirectory 'C:\Delphi\RADStudio37\source' ` -OutputDirectory $OutputDirectory ` -FileSpec '*.pas' ` -ExeToRun '..\projects\TreeDump\win64\release\DelphiParser.TreeDump.exe' ` -CLIOptions '"{InputFileName}" > "{OutputFileName}.txt"' ` -UseCmdShell $ZipPath = "$OutputDirectory.zip" Compress-Archive -Path "$OutputDirectory\*" -DestinationPath $ZipPath Write-Host "Compressed to: $ZipPath" ```
1 parent 710a2ae commit 26fbf0c

2 files changed

Lines changed: 224 additions & 1 deletion

File tree

src/ContinuousDelphi.Tools/ContinuousDelphi.Tools.psd1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
RootModule = 'ContinuousDelphi.Tools.psm1'
3-
ModuleVersion = '0.6.0'
3+
ModuleVersion = '0.7.0'
44
GUID = '9e6d3f3e-6c6c-4b1c-9c7a-3c4d4c9a7b11'
55

66
Author = 'Darian Miller'
@@ -13,6 +13,7 @@
1313
FunctionsToExport = @(
1414
'Test-NonAsciiContent',
1515
'Add-ToSystemPath',
16+
'Invoke-TreeCommand',
1617
'Set-FileLineEnding'
1718
)
1819

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#requires -Version 7.0
2+
#requires -PSEdition Core
3+
function Invoke-TreeCommand {
4+
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Run')]
5+
param(
6+
[Parameter(Mandatory = $true, ParameterSetName = 'Run')]
7+
[ValidateNotNullOrEmpty()]
8+
[string]$InputDirectory,
9+
10+
[Parameter(Mandatory = $true, ParameterSetName = 'Run')]
11+
[ValidateNotNullOrEmpty()]
12+
[string]$OutputDirectory,
13+
14+
[Parameter(Mandatory = $true, ParameterSetName = 'Run')]
15+
[ValidateNotNullOrEmpty()]
16+
[string]$FileSpec,
17+
18+
[Parameter(Mandatory = $true, ParameterSetName = 'Run')]
19+
[ValidateNotNullOrEmpty()]
20+
[string]$ExeToRun,
21+
22+
[Parameter(Mandatory = $true, ParameterSetName = 'Run')]
23+
[ValidateNotNullOrEmpty()]
24+
[string]$CLIOptions,
25+
26+
[Parameter(ParameterSetName = 'Run')]
27+
[switch]$PassThru,
28+
29+
[Parameter(ParameterSetName = 'Run')]
30+
[switch]$StopOnError,
31+
32+
[Parameter(ParameterSetName = 'Run')]
33+
[switch]$UseCmdShell,
34+
35+
[Parameter(Mandatory = $true, ParameterSetName = 'Version')]
36+
[switch]$Version
37+
)
38+
39+
$script:ToolVersion = '1.0.0'
40+
41+
if ($Version) {
42+
$scriptVersion
43+
return
44+
}
45+
46+
function Expand-TreeCommandTokenList {
47+
param(
48+
[Parameter(Mandatory = $true)]
49+
[string]$Template,
50+
51+
[Parameter(Mandatory = $true)]
52+
[string]$InputFileName,
53+
54+
[Parameter(Mandatory = $true)]
55+
[string]$OutputFileName
56+
)
57+
58+
$Result = $Template.Replace('{InputFileName}', $InputFileName)
59+
$Result = $Result.Replace('{OutputFileName}', $OutputFileName)
60+
return $Result
61+
}
62+
63+
function Get-TreeCommandResult {
64+
param(
65+
[Parameter(Mandatory = $true)]
66+
[string]$InputFileName,
67+
68+
[Parameter(Mandatory = $true)]
69+
[string]$OutputFileName,
70+
71+
[Parameter(Mandatory = $true)]
72+
[string]$CommandLine,
73+
74+
[AllowNull()]
75+
[int]$ExitCode,
76+
77+
[AllowNull()]
78+
[bool]$Success,
79+
80+
[Parameter(Mandatory = $true)]
81+
[bool]$Executed,
82+
83+
[Parameter(Mandatory = $true)]
84+
[bool]$UsedCmdShell
85+
)
86+
87+
[pscustomobject]@{
88+
InputFileName = $InputFileName
89+
OutputFileName = $OutputFileName
90+
CommandLine = $CommandLine
91+
ExitCode = $ExitCode
92+
Success = $Success
93+
Executed = $Executed
94+
UsedCmdShell = $UsedCmdShell
95+
}
96+
}
97+
98+
try {
99+
$ResolvedInputDirectory = (Resolve-Path -Path $InputDirectory -ErrorAction Stop).Path
100+
}
101+
catch {
102+
throw "InputDirectory not found: $InputDirectory"
103+
}
104+
105+
$ResolvedInputDirectory = [System.IO.Path]::GetFullPath($ResolvedInputDirectory)
106+
$ResolvedOutputDirectory = [System.IO.Path]::GetFullPath($OutputDirectory)
107+
108+
$DirectorySeparator = [System.IO.Path]::DirectorySeparatorChar
109+
if (-not $ResolvedInputDirectory.EndsWith($DirectorySeparator)) {
110+
$ResolvedInputDirectory += $DirectorySeparator
111+
}
112+
113+
[int]$TotalFiles = 0
114+
[int]$Attempted = 0
115+
[int]$Succeeded = 0
116+
[int]$Failed = 0
117+
[int]$Skipped = 0
118+
119+
$Files = Get-ChildItem -Path $ResolvedInputDirectory -Recurse -File -Filter $FileSpec
120+
121+
foreach ($File in $Files) {
122+
$TotalFiles++
123+
124+
$InputFileName = [System.IO.Path]::GetFullPath($File.FullName)
125+
126+
if (-not $InputFileName.StartsWith($ResolvedInputDirectory, [System.StringComparison]::OrdinalIgnoreCase)) {
127+
Write-Warning "Skipping file outside InputDirectory boundary: $InputFileName"
128+
$Skipped++
129+
continue
130+
}
131+
132+
$RelativePath = $InputFileName.Substring($ResolvedInputDirectory.Length)
133+
$OutputFileName = Join-Path -Path $ResolvedOutputDirectory -ChildPath $RelativePath
134+
$OutputParentDirectory = Split-Path -Path $OutputFileName -Parent
135+
136+
$ExpandedOptions = Expand-TreeCommandTokenList `
137+
-Template $CLIOptions `
138+
-InputFileName $InputFileName `
139+
-OutputFileName $OutputFileName
140+
141+
$ExitCode = $null
142+
$Success = $null
143+
$Executed = $false
144+
145+
$CommandLine = "`"$ExeToRun`" $ExpandedOptions"
146+
147+
if ($UseCmdShell) {
148+
$ActionDescription = "Execute via cmd.exe: $CommandLine"
149+
}
150+
else {
151+
$ActionDescription = "Execute: $CommandLine"
152+
}
153+
154+
if ($PSCmdlet.ShouldProcess($InputFileName, $ActionDescription)) {
155+
if (-not [string]::IsNullOrWhiteSpace($OutputParentDirectory)) {
156+
if (-not (Test-Path -LiteralPath $OutputParentDirectory)) {
157+
New-Item -ItemType Directory -Path $OutputParentDirectory -Force | Out-Null
158+
}
159+
}
160+
161+
$Attempted++
162+
$Executed = $true
163+
164+
if ($UseCmdShell) {
165+
& cmd.exe /d /c $CommandLine
166+
$ExitCode = $LASTEXITCODE
167+
}
168+
else {
169+
$ArgumentTokens = [System.Management.Automation.PSParser]::Tokenize($ExpandedOptions, [ref]$null)
170+
$ArgumentList = @(
171+
foreach ($Token in $ArgumentTokens) {
172+
if ($Token.Type -eq 'CommandArgument') {
173+
$Token.Content
174+
}
175+
}
176+
)
177+
178+
& $ExeToRun @ArgumentList
179+
$ExitCode = $LASTEXITCODE
180+
}
181+
182+
$Success = ($ExitCode -eq 0)
183+
184+
if ($Success) {
185+
$Succeeded++
186+
Write-Verbose "SUCCESS ($ExitCode): $InputFileName"
187+
}
188+
else {
189+
$Failed++
190+
Write-Warning "FAIL ($ExitCode): $InputFileName"
191+
}
192+
}
193+
else {
194+
$Skipped++
195+
Write-Verbose "WHATIF: $ActionDescription"
196+
}
197+
198+
if ($PassThru) {
199+
Get-TreeCommandResult `
200+
-InputFileName $InputFileName `
201+
-OutputFileName $OutputFileName `
202+
-CommandLine $CommandLine `
203+
-ExitCode $ExitCode `
204+
-Success $Success `
205+
-Executed $Executed `
206+
-UsedCmdShell $UseCmdShell.IsPresent
207+
}
208+
209+
if ($Executed -and (-not $Success) -and $StopOnError) {
210+
Write-Warning 'Stopping due to -StopOnError.'
211+
break
212+
}
213+
}
214+
215+
Write-Output ''
216+
Write-Output 'Summary:'
217+
Write-Output " Total Files : $TotalFiles"
218+
Write-Output " Attempted : $Attempted"
219+
Write-Output " Succeeded : $Succeeded"
220+
Write-Output " Failed : $Failed"
221+
Write-Output " Skipped : $Skipped"
222+
}

0 commit comments

Comments
 (0)