@@ -155,21 +155,15 @@ function Import-Yaml {
155155 )
156156
157157 begin {
158- $requestedPaths = [System.Collections.Generic.List [string ]]::new()
158+ $resolvedPaths = [System.Collections.Generic.List [string ]]::new()
159159 }
160160 process {
161161 $currentPaths = if ($PSCmdlet.ParameterSetName -eq ' LiteralPath' ) {
162162 $LiteralPath
163163 } else {
164164 $Path
165165 }
166- foreach ($currentPath in $currentPaths ) {
167- $requestedPaths.Add ($currentPath )
168- }
169- }
170- end {
171- $resolvedPaths = [System.Collections.Generic.List [string ]]::new()
172- foreach ($requestedPath in $requestedPaths ) {
166+ foreach ($requestedPath in $currentPaths ) {
173167 if ($PSCmdlet.ParameterSetName -eq ' LiteralPath' ) {
174168 try {
175169 $provider = $null
@@ -426,74 +420,100 @@ function Import-Yaml {
426420 $resolvedPaths.Add ([System.IO.Path ]::GetFullPath($pathInfo.ProviderPath ))
427421 }
428422 }
423+ }
424+ end {
429425
430- $caseSensitivePaths = [System.Collections.Generic.HashSet [ string ]]::new(
426+ $pathsByIdentity = [System.Collections.Generic.Dictionary [ string , string ]]::new(
431427 [System.StringComparer ]::Ordinal
432428 )
433- $caseInsensitivePaths = [System.Collections.Generic.HashSet [string ]]::new(
434- [System.StringComparer ]::OrdinalIgnoreCase
429+ $directoryNameGroups = [System.Collections.Generic.Dictionary [string , object ]]::new(
430+ [System.StringComparer ]::Ordinal
435431 )
436432 foreach ($resolvedPath in $resolvedPaths ) {
437- $useCaseSensitiveIdentity = -not $IsWindows
438- if ($IsWindows ) {
439- $identityPath = $resolvedPath
440- while (-not [string ]::IsNullOrEmpty($identityPath )) {
441- $directoryPath = [System.IO.Path ]::GetDirectoryName($identityPath )
442- if ([string ]::IsNullOrEmpty($directoryPath )) {
443- break
444- }
445- $leafName = [System.IO.Path ]::GetFileName($identityPath )
446- try {
447- $caseVariantCount = 0
433+ $identityComponents = [System.Collections.Generic.List [string ]]::new()
434+ $identityPath = $resolvedPath
435+ $identityFailed = $false
436+
437+ while ($true ) {
438+ $directoryPath = [System.IO.Path ]::GetDirectoryName($identityPath )
439+ $leafName = [System.IO.Path ]::GetFileName($identityPath )
440+ if ([string ]::IsNullOrEmpty($directoryPath ) -or
441+ [string ]::IsNullOrEmpty($leafName )) {
442+ break
443+ }
444+
445+ $nameGroups = $null
446+ try {
447+ if (-not $directoryNameGroups.TryGetValue (
448+ $directoryPath ,
449+ [ref ]$nameGroups
450+ )) {
451+ $nameGroups = (
452+ [System.Collections.Generic.Dictionary [string , object ]]::new(
453+ [System.StringComparer ]::OrdinalIgnoreCase
454+ )
455+ )
448456 foreach ($directoryEntry in (
449457 [System.IO.Directory ]::EnumerateFileSystemEntries($directoryPath )
450458 )) {
451- if ([string ]::Equals(
452- [System.IO.Path ]::GetFileName($directoryEntry ),
453- $leafName ,
454- [System.StringComparison ]::OrdinalIgnoreCase
455- )) {
456- $caseVariantCount ++
457- if ($caseVariantCount -gt 1 ) {
458- $useCaseSensitiveIdentity = $true
459- break
460- }
459+ $entryName = [System.IO.Path ]::GetFileName($directoryEntry )
460+ $nameGroup = $null
461+ if ($nameGroups.TryGetValue ($entryName , [ref ]$nameGroup )) {
462+ $nameGroup.Count ++
463+ } else {
464+ $nameGroups.Add (
465+ $entryName ,
466+ [pscustomobject ]@ {
467+ Count = 1
468+ CanonicalName = $entryName
469+ }
470+ )
461471 }
462472 }
463- } catch [System.UnauthorizedAccessException ] {
464- $useCaseSensitiveIdentity = $true
465- } catch [System.IO.IOException ] {
466- $useCaseSensitiveIdentity = $true
473+ $directoryNameGroups.Add ($directoryPath , $nameGroups )
467474 }
468- if ($useCaseSensitiveIdentity -or
469- [string ]::Equals(
470- $identityPath ,
471- $directoryPath ,
472- [System.StringComparison ]::Ordinal
473- )) {
475+
476+ $nameGroup = $null
477+ if (-not $nameGroups.TryGetValue ($leafName , [ref ]$nameGroup )) {
478+ $identityFailed = $true
474479 break
475480 }
476- $identityPath = $directoryPath
481+ if ($nameGroup.Count -gt 1 ) {
482+ $identityComponents.Add ($leafName )
483+ } else {
484+ $identityComponents.Add ($nameGroup.CanonicalName )
485+ }
486+ } catch [System.UnauthorizedAccessException ] {
487+ $identityFailed = $true
488+ break
489+ } catch [System.IO.IOException ] {
490+ $identityFailed = $true
491+ break
477492 }
493+
494+ $identityPath = $directoryPath
478495 }
479496
480- if ($useCaseSensitiveIdentity ) {
481- $null = $caseSensitivePaths .Add ( $ resolvedPath)
497+ if ($identityFailed ) {
498+ $identityKey = $resolvedPath
482499 } else {
483- $null = $caseInsensitivePaths.Add ($resolvedPath )
500+ $rootPath = [System.IO.Path ]::GetPathRoot($resolvedPath )
501+ if ($IsWindows ) {
502+ $rootPath = $rootPath.ToUpperInvariant ()
503+ }
504+ $identityComponents.Add ($rootPath )
505+ $identityComponents.Reverse ()
506+ $identityKey = $identityComponents -join [char ]0x1F
484507 }
508+
509+ $null = $pathsByIdentity.TryAdd ($identityKey , $resolvedPath )
485510 }
486- $uniquePaths = [System.Collections.Generic.List [string ]]::new()
487- foreach ($uniquePath in $caseSensitivePaths ) {
488- $uniquePaths.Add ($uniquePath )
489- }
490- foreach ($uniquePath in $caseInsensitivePaths ) {
491- $uniquePaths.Add ($uniquePath )
492- }
493- [string []] $orderedPaths = $uniquePaths
494- [System.Array ]::Sort($orderedPaths , [System.StringComparer ]::Ordinal)
495511
496- foreach ($resolvedPath in $orderedPaths ) {
512+ [string []] $orderedIdentityKeys = $pathsByIdentity.Keys
513+ [System.Array ]::Sort($orderedIdentityKeys , [System.StringComparer ]::Ordinal)
514+
515+ foreach ($identityKey in $orderedIdentityKeys ) {
516+ $resolvedPath = $pathsByIdentity [$identityKey ]
497517 try {
498518 $bytes = [System.IO.File ]::ReadAllBytes($resolvedPath )
499519 } catch [System.UnauthorizedAccessException ] {
0 commit comments