Skip to content

Commit 2c3c256

Browse files
authored
Add PatternRoot to Select-Match (#258)
1 parent f38fc12 commit 2c3c256

8 files changed

+232
-34
lines changed

powershell/Docs/ReleaseNotes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Release Notes
22

3+
## 0.8.3
4+
* Updated `Select-VstsMatch`. Added `-PatternRoot` parameter.
5+
* Breaking change for `Select-VstsMatch` due to positional parameter changes and partial parameter name impact.
6+
37
## 0.8.2
48
* Fixed issue with env block size limit.
59

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[CmdletBinding()]
2+
param()
3+
4+
# Arrange.
5+
. $PSScriptRoot\..\lib\Initialize-Test.ps1
6+
Invoke-VstsTaskScript -ScriptBlock {
7+
$itemPaths = @(
8+
'\hello\world.txt'
9+
'\hello\two-negate-markers.txt'
10+
'\hello\four-negate-markers.txt'
11+
'\initial-includes\hello.txt'
12+
'\initial-includes\one-negate-markers.txt'
13+
'\initial-includes\three-negate-markers.txt'
14+
)
15+
$patterns = @(
16+
'\initial-includes\*.txt'
17+
'!!\hello\two-negate-markers.txt'
18+
'!!!!\hello\four-negate-markers.txt'
19+
'!\initial-includes\one-negate-markers.txt'
20+
'!!!\initial-includes\three-negate-markers.txt'
21+
)
22+
23+
# Act.
24+
$actual = Select-VstsMatch -ItemPath $itemPaths -Pattern $patterns
25+
26+
# Assert.
27+
$expected = @(
28+
'\hello\two-negate-markers.txt'
29+
'\hello\four-negate-markers.txt'
30+
'\initial-includes\hello.txt'
31+
)
32+
Assert-AreEqual $expected $actual
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[CmdletBinding()]
2+
param()
3+
4+
# Arrange.
5+
. $PSScriptRoot\..\lib\Initialize-Test.ps1
6+
Invoke-VstsTaskScript -ScriptBlock {
7+
$itemPaths = @(
8+
'\matching\pattern\root\hello.txt'
9+
'\matching\pattern\root\hello\world.txt'
10+
'\matching\pattern\root\other.zzz'
11+
'\non-matching\pattern\root\hello.txt'
12+
'\non-matching\pattern\root\hello\world.txt'
13+
)
14+
$patterns = @(
15+
'\**\*'
16+
'!hello.txt'
17+
'!**\world.txt'
18+
)
19+
$patternRoot = '\matching\pattern\root'
20+
21+
# Act.
22+
$actual = Select-VstsMatch -ItemPath $itemPaths -Pattern $patterns -PatternRoot $patternRoot
23+
24+
# Assert.
25+
$expected = @(
26+
'\matching\pattern\root\other.zzz'
27+
'\non-matching\pattern\root\hello.txt'
28+
'\non-matching\pattern\root\hello\world.txt'
29+
)
30+
Assert-AreEqual $expected $actual
31+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[CmdletBinding()]
2+
param()
3+
4+
# Arrange.
5+
. $PSScriptRoot\..\lib\Initialize-Test.ps1
6+
Invoke-VstsTaskScript -ScriptBlock {
7+
$itemPaths = @(
8+
'\matching\pattern\root\hello.txt'
9+
'\matching\pattern\root\hello\world.txt'
10+
'\matching\pattern\root\other.zzz'
11+
'\non-matching\pattern\root\hello.txt'
12+
'\non-matching\pattern\root\hello\world.txt'
13+
)
14+
$patterns = @(
15+
'hello.txt'
16+
'**\world.txt'
17+
)
18+
$patternRoot = '\matching\pattern\root'
19+
20+
# Act.
21+
$actual = Select-VstsMatch -ItemPath $itemPaths -Pattern $patterns -PatternRoot $patternRoot
22+
23+
# Assert.
24+
$expected = @(
25+
'\matching\pattern\root\hello.txt'
26+
'\matching\pattern\root\hello\world.txt'
27+
)
28+
Assert-AreEqual $expected $actual
29+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[CmdletBinding()]
2+
param()
3+
4+
# Arrange.
5+
. $PSScriptRoot\..\lib\Initialize-Test.ps1
6+
Invoke-VstsTaskScript -ScriptBlock {
7+
$itemPaths = @(
8+
'\matching\pattern\root\hello.txt'
9+
'\matching\pattern\root\hello\world.txt'
10+
'\matching\pattern\root\other.zzz'
11+
'\non-matching\pattern\root\hello.txt'
12+
'\non-matching\pattern\root\hello\world.txt'
13+
)
14+
$patterns = @(
15+
'\**\*'
16+
'!hello.txt'
17+
'!**\world.txt'
18+
)
19+
$patternRoot = '\matching\pattern\root'
20+
$options = New-VstsMatchOptions -MatchBase
21+
22+
# Act.
23+
$actual = Select-VstsMatch -ItemPath $itemPaths -Pattern $patterns -PatternRoot $patternRoot -Options $options
24+
25+
# Assert.
26+
$expected = @(
27+
'\matching\pattern\root\other.zzz'
28+
'\non-matching\pattern\root\hello\world.txt'
29+
)
30+
Assert-AreEqual $expected $actual
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[CmdletBinding()]
2+
param()
3+
4+
# Arrange.
5+
. $PSScriptRoot\..\lib\Initialize-Test.ps1
6+
Invoke-VstsTaskScript -ScriptBlock {
7+
$itemPaths = @(
8+
'\matching\pattern\root\hello.txt'
9+
'\matching\pattern\root\hello\world.txt'
10+
'\matching\pattern\root\other.zzz'
11+
'\non-matching\pattern\root\hello.txt'
12+
'\non-matching\pattern\root\hello\world.txt'
13+
)
14+
$patterns = @(
15+
'hello.txt'
16+
'**\world.txt'
17+
)
18+
$patternRoot = '\matching\pattern\root'
19+
$options = New-VstsMatchOptions -MatchBase
20+
21+
# Act.
22+
$actual = Select-VstsMatch -ItemPath $itemPaths -Pattern $patterns -PatternRoot $patternRoot -Options $options
23+
24+
# Assert.
25+
$expected = @(
26+
'\matching\pattern\root\hello.txt'
27+
'\matching\pattern\root\hello\world.txt'
28+
'\non-matching\pattern\root\hello.txt'
29+
)
30+
Assert-AreEqual $expected $actual
31+
}

powershell/VstsTaskSdk/FindFunctions.ps1

Lines changed: 72 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ Array of paths.
297297
.PARAMETER Pattern
298298
Patterns to apply. Supports interleaved exclude patterns.
299299
300+
.PARAMETER PatternRoot
301+
Default root to apply to unrooted patterns. Not applied to basename-only patterns when Options.MatchBase is true.
302+
300303
.PARAMETER Options
301304
When the Options parameter is not specified, defaults to (New-VstsMatchOptions -Dot -NoBrace -NoCase).
302305
#>
@@ -307,6 +310,8 @@ function Select-Match {
307310
[string[]]$ItemPath,
308311
[Parameter()]
309312
[string[]]$Pattern,
313+
[Parameter()]
314+
[string]$PatternRoot,
310315
$Options)
311316

312317

@@ -344,7 +349,7 @@ function Select-Match {
344349
continue
345350
}
346351

347-
# Set NoComment.
352+
# Set NoComment. Brace expansion could result in a leading '#'.
348353
$Options.NoComment = $true
349354

350355
# Determine whether pattern is include or exclude.
@@ -368,46 +373,80 @@ function Select-Match {
368373
$Options.NoNegate = $true
369374
$Options.FlipNegate = $false
370375

371-
# Trim and skip empty.
372-
$pat = "$pat".Trim()
373-
if (!$pat) {
374-
Write-Verbose 'Skipping empty pattern.'
375-
continue
376+
# Expand braces - required to accurately root patterns.
377+
$expanded = $null
378+
$preExpanded = $pat
379+
if ($Options.NoBrace) {
380+
$expanded = @( $pat )
381+
} else {
382+
# Convert slashes on Windows before calling braceExpand(). Unfortunately this means braces cannot
383+
# be escaped on Windows, this limitation is consistent with current limitations of minimatch (3.0.3).
384+
Write-Verbose "Expanding braces."
385+
$convertedPattern = $pat -replace '\\', '/'
386+
$expanded = [Minimatch.Minimatcher]::BraceExpand(
387+
$convertedPattern,
388+
(ConvertTo-MinimatchOptions -Options $Options))
376389
}
377390

378-
if ($isIncludePattern) {
379-
# Apply the pattern.
380-
Write-Verbose 'Applying include pattern against original list'
381-
$matchResults = [Minimatch.Minimatcher]::Filter(
382-
$ItemPath,
383-
$pat,
384-
(ConvertTo-MinimatchOptions -Options $Options))
391+
# Set NoBrace.
392+
$Options.NoBrace = $true
385393

386-
# Union the results.
387-
$matchCount = 0
388-
foreach ($matchResult in $matchResults) {
389-
$matchCount++
390-
$map[$matchResult] = $true
394+
foreach ($pat in $expanded) {
395+
if ($pat -ne $preExpanded) {
396+
Write-Verbose "Pattern: '$pat'"
391397
}
392398

393-
Write-Verbose "$matchCount matches"
394-
}
395-
else {
396-
# Apply the pattern.
397-
Write-Verbose 'Applying exclude pattern against original list'
398-
$matchResults = [Minimatch.Minimatcher]::Filter(
399-
$ItemPath,
400-
$pat,
401-
(ConvertTo-MinimatchOptions -Options $Options))
399+
# Trim and skip empty.
400+
$pat = "$pat".Trim()
401+
if (!$pat) {
402+
Write-Verbose "Skipping empty pattern."
403+
continue
404+
}
405+
406+
# Root the pattern when all of the following conditions are true:
407+
if ($PatternRoot -and # PatternRoot is supplied
408+
!(Test-Rooted -Path $pat) -and # AND pattern is not rooted
409+
# # AND MatchBase=false or not basename only
410+
(!$Options.MatchBase -or ($pat -replace '\\', '/').IndexOf('/') -ge 0)) {
402411

403-
# Subtract the results.
404-
$matchCount = 0
405-
foreach ($matchResult in $matchResults) {
406-
$matchCount++
407-
$map.Remove($matchResult)
412+
# Root the include pattern.
413+
$pat = Get-RootedPattern -DefaultRoot $PatternRoot -Pattern $pat
414+
Write-Verbose "After Get-RootedPattern, pattern: '$pat'"
408415
}
409416

410-
Write-Verbose "$matchCount matches"
417+
if ($isIncludePattern) {
418+
# Apply the pattern.
419+
Write-Verbose 'Applying include pattern against original list.'
420+
$matchResults = [Minimatch.Minimatcher]::Filter(
421+
$ItemPath,
422+
$pat,
423+
(ConvertTo-MinimatchOptions -Options $Options))
424+
425+
# Union the results.
426+
$matchCount = 0
427+
foreach ($matchResult in $matchResults) {
428+
$matchCount++
429+
$map[$matchResult] = $true
430+
}
431+
432+
Write-Verbose "$matchCount matches"
433+
} else {
434+
# Apply the pattern.
435+
Write-Verbose 'Applying exclude pattern against original list'
436+
$matchResults = [Minimatch.Minimatcher]::Filter(
437+
$ItemPath,
438+
$pat,
439+
(ConvertTo-MinimatchOptions -Options $Options))
440+
441+
# Subtract the results.
442+
$matchCount = 0
443+
foreach ($matchResult in $matchResults) {
444+
$matchCount++
445+
$map.Remove($matchResult)
446+
}
447+
448+
Write-Verbose "$matchCount matches"
449+
}
411450
}
412451
}
413452

powershell/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vsts-task-sdk",
3-
"version": "0.8.2",
3+
"version": "0.8.3",
44
"description": "VSTS Task SDK",
55
"scripts": {
66
"build": "node make.js build",

0 commit comments

Comments
 (0)