-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update PathTraverser to return new IEnumerable instead of using yield
The previous change caused multiple enumerations to return different results Closes #59
- Loading branch information
Showing
8 changed files
with
218 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
# Release steps | ||
|
||
* Add github release | ||
* Tag release | ||
* Update changelog | ||
* Update changelog links | ||
* Update solution VersionPrefix | ||
* Update solution PackageReleaseNotes | ||
* Tag release | ||
* Add github release | ||
* Run azure release to nuget |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using GlobExpressions.AST; | ||
|
||
namespace GlobExpressions | ||
{ | ||
internal class PathTraverserEnumerable : IEnumerable<FileSystemInfo> | ||
{ | ||
private readonly List<DirectoryInfo> _originalRoots; | ||
private readonly Segment[] _segments; | ||
private readonly TraverseOptions _options; | ||
|
||
private static readonly FileSystemInfo[] _emptyFileSystemInfoArray = new FileSystemInfo[0]; | ||
private static readonly DirectoryInfo[] _emptyPathJobArray = new DirectoryInfo[0]; | ||
public PathTraverserEnumerable(List<DirectoryInfo> roots, Segment[] segments, TraverseOptions options) | ||
{ | ||
this._originalRoots = roots; | ||
this._segments = segments; | ||
this._options = options; | ||
} | ||
|
||
public IEnumerator<FileSystemInfo> GetEnumerator() | ||
{ | ||
var roots = new List<DirectoryInfo>(); | ||
var rootCache = new List<DirectoryInfo>(); | ||
roots.AddRange(_originalRoots); | ||
|
||
var segmentsLength = _segments.Length; | ||
var nextSegmentRoots = new List<DirectoryInfo>(); | ||
var segmentIndex = 0; | ||
var emitDirectories = _options.EmitDirectories; | ||
var emitFiles = _options.EmitFiles; | ||
var cache = new HashSet<string>(); | ||
|
||
void Swap(ref List<DirectoryInfo> other) | ||
{ | ||
var swap = roots; | ||
roots = other; | ||
other = swap; | ||
} | ||
|
||
while (true) | ||
{ | ||
// no more segments. return all current roots | ||
var noMoreSegments = segmentIndex == segmentsLength; | ||
if (emitDirectories && noMoreSegments) | ||
{ | ||
foreach (var info in roots.Where(info => !cache.Contains(info.FullName))) | ||
{ | ||
cache.Add(info.FullName); | ||
yield return info; | ||
} | ||
} | ||
|
||
// no more roots or no more segments, go to next segment | ||
if (roots.Count == 0 || noMoreSegments) | ||
{ | ||
roots.Clear(); | ||
if (nextSegmentRoots.Count > 0) | ||
{ | ||
Swap(ref nextSegmentRoots); | ||
segmentIndex++; | ||
continue; | ||
} | ||
|
||
yield break; | ||
} | ||
|
||
var segment = _segments[segmentIndex]; | ||
var onLastSegment = segmentIndex == segmentsLength - 1; | ||
if (emitFiles && onLastSegment) | ||
{ | ||
var allFiles = from job in roots | ||
let children = _options.GetFiles(job) | ||
from file in FilesMatchingSegment(children, segment, _options.CaseSensitive) | ||
select file; | ||
|
||
foreach (var info in allFiles) | ||
{ | ||
if (!cache.Contains(info.FullName)) | ||
{ | ||
cache.Add(info.FullName); | ||
yield return info; | ||
} | ||
} | ||
} | ||
rootCache.Clear(); | ||
rootCache.AddRange(roots.SelectMany(job => JobsMatchingSegment(nextSegmentRoots, job, segment))); | ||
|
||
Swap(ref rootCache); | ||
} | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
private IEnumerable<DirectoryInfo> JobsMatchingSegment(List<DirectoryInfo> nextSegmentRoots, DirectoryInfo directoryInfo, Segment segment) | ||
{ | ||
switch (segment) | ||
{ | ||
case DirectorySegment directorySegment: | ||
// consume DirectorySegment | ||
var pathJobs = (from directory in _options.GetDirectories(directoryInfo) | ||
where directorySegment.MatchesSegment(directory.Name, _options.CaseSensitive) | ||
select directory).ToArray(); | ||
|
||
nextSegmentRoots.AddRange(pathJobs); | ||
|
||
return _emptyPathJobArray; | ||
|
||
case DirectoryWildcard _: | ||
{ | ||
// match zero path segments, consuming DirectoryWildcard | ||
nextSegmentRoots.Add(directoryInfo); | ||
|
||
// match consume 1 path segment but not the Wildcard | ||
return _options.GetDirectories(directoryInfo); | ||
} | ||
|
||
default: | ||
return _emptyPathJobArray; | ||
} | ||
} | ||
|
||
|
||
|
||
private static IEnumerable<FileSystemInfo> FilesMatchingSegment(IEnumerable<FileInfo> fileInfos, Segment segment, bool caseSensitive) => | ||
segment switch | ||
{ | ||
DirectorySegment directorySegment => (IEnumerable<FileSystemInfo>)fileInfos.Where(file => directorySegment.MatchesSegment(file.Name, caseSensitive)), | ||
DirectoryWildcard _ => fileInfos, | ||
_ => _emptyFileSystemInfoArray | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.