Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions src/functions/TestDrive.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,29 @@ function Clear-TestDrive {
[System.StringComparer]::OrdinalIgnoreCase)

# Only delete "root" new items (those whose parent directory is not also a new item).
# Deleting with -Recurse removes all descendants in one call, avoiding redundant
# Remove-Item calls on already-deleted children.
# Deleting recursively removes all descendants in one call, avoiding redundant
# deletions of already-deleted children.
foreach ($item in $newItemSet) {
$parent = [IO.Path]::GetDirectoryName($item)
if (-not $newItemSet.Contains($parent)) {
& $SafeCommands['Remove-Item'] -Path $item -Force -Recurse -ErrorAction Ignore
# .NET deletes are ~5x faster than Remove-Item and treat the path literally, so
# bracket or wildcard characters in file names no longer glob (Remove-Item -Path
# left a file named like 'file[1].txt' behind). Directory.Delete removes reparse
# points (symlinks, junctions) without following them into their target, same as
# Remove-TestDrive already does for the whole drive. Read-only or locked items throw
# and fall back to Remove-Item, which keeps the previous -Force -ErrorAction Ignore
# semantics for those.
try {
if ([IO.Directory]::Exists($item)) {
[IO.Directory]::Delete($item, $true)
}
else {
[IO.File]::Delete($item)
}
}
catch {
& $SafeCommands['Remove-Item'] -LiteralPath $item -Force -Recurse -ErrorAction Ignore
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/functions/TestRegistry.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ function Invoke-TestRegistryWithRetry {
function New-RandomTempRegistry {
do {
$tempPath = Get-TempRegistry
$Path = & $SafeCommands['Join-Path'] -Path $tempPath -ChildPath ([IO.Path]::GetRandomFileName().Substring(0, 4))
# registry provider paths always use backslash; plain interpolation avoids a per-call cmdlet invocation
$Path = "$tempPath\$([IO.Path]::GetRandomFileName().Substring(0, 4))"
Comment on lines +98 to +99

@fflaten fflaten Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really a hot path, but sure 👍

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got some free fable tokens, told it to optimize (especially the hot path), looks like most of the optimizations are microscopic.

# Test-Path is a read operation and can throw the same transient IOException as the
# New-Item write below, so retry it the same way.
$keyAlreadyExists = Invoke-TestRegistryWithRetry { & $SafeCommands['Test-Path'] -Path $Path -PathType Container }
Expand Down
Loading