Skip to content

Commit 49230d8

Browse files
committed
Refactor globbing resolution to support IFileSystem abstraction
Reorganized globbing-related logic into the FileSystemGlobbing namespace. Introduced IFileSystem integration in GlobbingResolver and new wrapper classes for directory and file handling. Simplified service configuration using GitVersionAppModule.
1 parent 937dc2e commit 49230d8

12 files changed

+255
-26
lines changed

new-cli/GitVersion.Common/GitVersion.Common.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<ItemGroup>
33
<PackageReference Include="Polly" />
4+
<PackageReference Include="System.IO.Abstractions" />
45
</ItemGroup>
56
<ItemGroup>
67
<Compile Include="..\..\src\GitVersion.Core\Core\Abstractions\IEnvironment.cs" Link="Infrastructure\%(Filename)%(Extension)" />

src/GitVersion.App.Tests/ArgumentParserOnBuildServerTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using GitVersion.Agents;
22
using GitVersion.Core.Tests.Helpers;
3+
using GitVersion.Extensions;
34
using GitVersion.OutputVariables;
45
using Microsoft.Extensions.DependencyInjection;
56

@@ -15,8 +16,7 @@ public void SetUp()
1516
{
1617
var sp = ConfigureServices(services =>
1718
{
18-
services.AddSingleton<IArgumentParser, ArgumentParser>();
19-
services.AddSingleton<IGlobbingResolver, GlobbingResolver>();
19+
services.AddModule(new GitVersionAppModule());
2020
services.AddSingleton<ICurrentBuildAgent, MockBuildAgent>();
2121
});
2222
this.argumentParser = sp.GetRequiredService<IArgumentParser>();

src/GitVersion.App.Tests/ArgumentParserTests.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.IO.Abstractions;
22
using GitVersion.Configuration;
33
using GitVersion.Core.Tests.Helpers;
4+
using GitVersion.Extensions;
45
using GitVersion.Helpers;
56
using GitVersion.Logging;
67
using GitVersion.VersionCalculation;
@@ -18,11 +19,7 @@ public class ArgumentParserTests : TestBase
1819
[SetUp]
1920
public void SetUp()
2021
{
21-
var sp = ConfigureServices(services =>
22-
{
23-
services.AddSingleton<IArgumentParser, ArgumentParser>();
24-
services.AddSingleton<IGlobbingResolver, GlobbingResolver>();
25-
});
22+
var sp = ConfigureServices(services => services.AddModule(new GitVersionAppModule()));
2623
this.environment = sp.GetRequiredService<IEnvironment>();
2724
this.argumentParser = sp.GetRequiredService<IArgumentParser>();
2825
this.fileSystem = sp.GetRequiredService<IFileSystem>();

src/GitVersion.App/ArgumentParser.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.IO.Abstractions;
22
using GitVersion.Agents;
33
using GitVersion.Extensions;
4+
using GitVersion.FileSystemGlobbing;
45
using GitVersion.Helpers;
56
using GitVersion.Logging;
67
using GitVersion.OutputVariables;
@@ -152,11 +153,9 @@ private IEnumerable<string> ResolveFiles(string workingDirectory, ISet<string>?
152153

153154
foreach (var file in assemblyInfoFiles)
154155
{
155-
var paths = this.globbingResolver.Resolve(workingDirectory, file);
156-
157-
foreach (var path in paths)
156+
foreach (var path in this.globbingResolver.Resolve(workingDirectory, file))
158157
{
159-
yield return FileSystemHelper.Path.GetFullPath(FileSystemHelper.Path.Combine(workingDirectory, path));
158+
yield return path;
160159
}
161160
}
162161
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
using System.IO.Abstractions;
2+
3+
namespace GitVersion.FileSystemGlobbing;
4+
5+
internal sealed class DirectoryInfoGlobbingWrapper
6+
: Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase
7+
{
8+
private readonly IFileSystem _fileSystem;
9+
private readonly IDirectoryInfo _directoryInfo;
10+
private readonly bool _isParentPath;
11+
12+
public DirectoryInfoGlobbingWrapper(IFileSystem fileSystem, IDirectoryInfo directoryInfo)
13+
: this(fileSystem, directoryInfo, isParentPath: false) { }
14+
15+
private DirectoryInfoGlobbingWrapper(
16+
IFileSystem fileSystem,
17+
IDirectoryInfo directoryInfo,
18+
bool isParentPath
19+
)
20+
{
21+
_fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
22+
_directoryInfo = directoryInfo ?? throw new ArgumentNullException(nameof(directoryInfo));
23+
_isParentPath = isParentPath;
24+
}
25+
26+
public override string Name => _isParentPath ? ".." : _directoryInfo.Name;
27+
28+
public override string FullName => _directoryInfo.FullName;
29+
30+
public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase? ParentDirectory =>
31+
_directoryInfo.Parent is null
32+
? null
33+
: new DirectoryInfoGlobbingWrapper(_fileSystem, _directoryInfo.Parent);
34+
35+
public override IEnumerable<Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileSystemInfoBase> EnumerateFileSystemInfos()
36+
{
37+
if (_directoryInfo.Exists)
38+
{
39+
IEnumerable<IFileSystemInfo> fileSystemInfos;
40+
try
41+
{
42+
fileSystemInfos = _directoryInfo.EnumerateFileSystemInfos(
43+
"*",
44+
SearchOption.TopDirectoryOnly
45+
);
46+
}
47+
catch (DirectoryNotFoundException)
48+
{
49+
yield break;
50+
}
51+
52+
foreach (var fileSystemInfo in fileSystemInfos)
53+
{
54+
yield return fileSystemInfo switch
55+
{
56+
IDirectoryInfo directoryInfo
57+
=> new DirectoryInfoGlobbingWrapper(_fileSystem, directoryInfo),
58+
IFileInfo fileInfo => new FileInfoGlobbingWrapper(_fileSystem, fileInfo),
59+
var it => new FileSystemInfoGlobbingWrapper(_fileSystem, it),
60+
};
61+
}
62+
}
63+
}
64+
65+
public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase? GetDirectory(
66+
string path
67+
)
68+
{
69+
var isParentPath = string.Equals(path, "..", StringComparison.Ordinal);
70+
71+
if (isParentPath)
72+
{
73+
return new DirectoryInfoGlobbingWrapper(
74+
_fileSystem,
75+
_fileSystem.DirectoryInfo.New(Path.Combine(_directoryInfo.FullName, path)),
76+
isParentPath
77+
);
78+
}
79+
else
80+
{
81+
var dirs = _directoryInfo.GetDirectories(path);
82+
83+
return dirs switch
84+
{
85+
{ Length: 1 }
86+
=> new DirectoryInfoGlobbingWrapper(_fileSystem, dirs[0], isParentPath),
87+
{ Length: 0 } => null,
88+
// This shouldn't happen. The parameter name isn't supposed to contain wild card.
89+
_
90+
=> throw new InvalidOperationException(
91+
$"More than one sub directories are found under {_directoryInfo.FullName} with name {path}."
92+
),
93+
};
94+
}
95+
}
96+
97+
public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase GetFile(
98+
string path
99+
) =>
100+
new FileInfoGlobbingWrapper(
101+
_fileSystem,
102+
_fileSystem.FileInfo.New(Path.Combine(FullName, path))
103+
);
104+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.IO.Abstractions;
2+
using GitVersion.Extensions;
3+
4+
namespace GitVersion.FileSystemGlobbing;
5+
6+
/// <summary>
7+
/// Initialize a new instance
8+
/// </summary>
9+
/// <param name="fileSystem">The filesystem</param>
10+
/// <param name="fileInfo">The file</param>
11+
internal sealed class FileInfoGlobbingWrapper(IFileSystem fileSystem, IFileInfo fileInfo)
12+
: Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase
13+
{
14+
private readonly IFileSystem _fileSystem = fileSystem.NotNull();
15+
private readonly IFileInfo _fileInfo = fileInfo.NotNull();
16+
17+
/// <inheritdoc />
18+
public override string Name => _fileInfo.Name;
19+
20+
/// <inheritdoc />
21+
public override string FullName => _fileInfo.FullName;
22+
23+
/// <inheritdoc />
24+
public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase? ParentDirectory =>
25+
_fileInfo.Directory is null
26+
? null
27+
: new DirectoryInfoGlobbingWrapper(_fileSystem, _fileInfo.Directory);
28+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.IO.Abstractions;
2+
using GitVersion.Extensions;
3+
4+
namespace GitVersion.FileSystemGlobbing;
5+
6+
internal sealed class FileSystemInfoGlobbingWrapper(IFileSystem fileSystem, IFileSystemInfo fileSystemInfo) : Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileSystemInfoBase
7+
{
8+
private readonly IFileSystem _fileSystem = fileSystem.NotNull();
9+
private readonly IFileSystemInfo _fileSystemInfo = fileSystemInfo.NotNull();
10+
11+
public override string Name => _fileSystemInfo.Name;
12+
13+
public override string FullName => _fileSystemInfo.FullName;
14+
15+
public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase ParentDirectory =>
16+
new DirectoryInfoGlobbingWrapper(
17+
_fileSystem,
18+
_fileSystem.DirectoryInfo.New(_fileSystemInfo.FullName)
19+
);
20+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.IO.Abstractions;
2+
using GitVersion.Extensions;
3+
using Microsoft.Extensions.FileSystemGlobbing;
4+
5+
namespace GitVersion.FileSystemGlobbing;
6+
7+
internal class GlobbingResolver(IFileSystem fileSystem) : IGlobbingResolver
8+
{
9+
private readonly IFileSystem fileSystem = fileSystem.NotNull();
10+
private readonly Matcher matcher = new(StringComparison.OrdinalIgnoreCase);
11+
12+
public IEnumerable<string> Resolve(string workingDirectory, string pattern)
13+
{
14+
matcher.AddInclude(pattern);
15+
return matcher.GetResultsInFullPath(this.fileSystem, workingDirectory);
16+
}
17+
}

src/GitVersion.App/IGlobbingResolver.cs renamed to src/GitVersion.App/FileSystemGlobbing/IGlobbingResolver.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace GitVersion;
1+
namespace GitVersion.FileSystemGlobbing;
22

33
internal interface IGlobbingResolver
44
{
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
using System.IO.Abstractions;
2+
using Microsoft.Extensions.FileSystemGlobbing;
3+
4+
namespace GitVersion.FileSystemGlobbing;
5+
6+
internal static class MatcherExtensions
7+
{
8+
public static PatternMatchingResult Execute(
9+
this Matcher matcher,
10+
IFileSystem fileSystem,
11+
string directoryPath
12+
)
13+
{
14+
ArgumentNullException.ThrowIfNull(matcher);
15+
ArgumentNullException.ThrowIfNull(fileSystem);
16+
17+
return Execute(matcher, fileSystem, fileSystem.DirectoryInfo.New(directoryPath));
18+
}
19+
20+
private static PatternMatchingResult Execute(
21+
this Matcher matcher,
22+
IFileSystem fileSystem,
23+
IDirectoryInfo directoryInfo
24+
)
25+
{
26+
ArgumentNullException.ThrowIfNull(matcher);
27+
ArgumentNullException.ThrowIfNull(fileSystem);
28+
ArgumentNullException.ThrowIfNull(directoryInfo);
29+
30+
return matcher.Execute(new DirectoryInfoGlobbingWrapper(fileSystem, directoryInfo));
31+
}
32+
33+
public static IEnumerable<string> GetResultsInFullPath(
34+
this Matcher matcher,
35+
IFileSystem fileSystem,
36+
string directoryPath
37+
)
38+
{
39+
ArgumentNullException.ThrowIfNull(matcher);
40+
ArgumentNullException.ThrowIfNull(fileSystem);
41+
42+
return GetResultsInFullPath(
43+
matcher,
44+
fileSystem,
45+
fileSystem.DirectoryInfo.New(directoryPath)
46+
);
47+
}
48+
49+
private static IEnumerable<string> GetResultsInFullPath(
50+
this Matcher matcher,
51+
IFileSystem fileSystem,
52+
IDirectoryInfo directoryInfo
53+
)
54+
{
55+
ArgumentNullException.ThrowIfNull(matcher);
56+
ArgumentNullException.ThrowIfNull(fileSystem);
57+
ArgumentNullException.ThrowIfNull(directoryInfo);
58+
59+
var matches = Execute(matcher, fileSystem, directoryInfo);
60+
61+
if (!matches.HasMatches)
62+
{
63+
return EmptyStringsEnumerable;
64+
}
65+
66+
var fsPath = fileSystem.Path;
67+
var directoryFullName = directoryInfo.FullName;
68+
69+
return matches.Files.Select(GetFullPath);
70+
71+
string GetFullPath(FilePatternMatch match) =>
72+
fsPath.GetFullPath(fsPath.Combine(directoryFullName, match.Path));
73+
}
74+
75+
private static readonly IEnumerable<string> EmptyStringsEnumerable = [];
76+
}

0 commit comments

Comments
 (0)