-
Notifications
You must be signed in to change notification settings - Fork 266
feat: Add FileVersionInfo support #1177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 15 commits
8f3a2e6
6e407cd
4c569eb
f4c4404
d68c667
8178f70
f240e1b
7cfdca7
dd68ff2
2e6fa66
a8380f4
6628888
5d8e168
eb509ac
1f246a3
da9061e
c331fb6
b2a4ca9
41b3d88
73b4285
4d5efbd
dfe0449
dc49485
9feeb4e
c1e5520
0d92dbe
0e11ee4
4282915
d661eb3
6095538
4c06da3
23bdeb4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace System.IO.Abstractions.TestingHelpers | ||
{ | ||
/// <inheritdoc /> | ||
#if FEATURE_SERIALIZABLE | ||
[Serializable] | ||
#endif | ||
public class MockFileVersionInfo : FileVersionInfoBase | ||
{ | ||
/// <inheritdoc /> | ||
public MockFileVersionInfo( | ||
t4m45 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
string fileName, | ||
string fileVersion = null, | ||
Check failure on line 16 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string productVersion = null, | ||
Check failure on line 17 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string fileDescription = null, | ||
Check failure on line 18 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string productName = null, | ||
Check failure on line 19 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string companyName = null, | ||
Check failure on line 20 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string comments = null, | ||
Check failure on line 21 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string internalName = null, | ||
Check failure on line 22 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
bool isDebug = false, | ||
Check failure on line 23 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
bool isPatched = false, | ||
Check failure on line 24 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
bool isPrivateBuild = false, | ||
Check failure on line 25 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
bool isPreRelease = false, | ||
Check failure on line 26 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
bool isSpecialBuild = false, | ||
Check failure on line 27 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string language = null, | ||
Check failure on line 28 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string legalCopyright = null, | ||
Check failure on line 29 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string legalTrademarks = null, | ||
Check failure on line 30 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string originalFilename = null, | ||
Check failure on line 31 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string privateBuild = null, | ||
Check failure on line 32 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
string specialBuild = null) | ||
Check failure on line 33 in src/TestableIO.System.IO.Abstractions.TestingHelpers/MockFileVersionInfo.cs
|
||
{ | ||
FileName = fileName; | ||
FileVersion = fileVersion; | ||
ProductVersion = productVersion; | ||
FileDescription = fileDescription; | ||
ProductName = productName; | ||
CompanyName = companyName; | ||
Comments = comments; | ||
InternalName = internalName; | ||
IsDebug = isDebug; | ||
IsPatched = isPatched; | ||
IsPrivateBuild = isPrivateBuild; | ||
IsPreRelease = isPreRelease; | ||
IsSpecialBuild = isSpecialBuild; | ||
Language = language; | ||
LegalCopyright = legalCopyright; | ||
LegalTrademarks = legalTrademarks; | ||
OriginalFilename = originalFilename; | ||
PrivateBuild = privateBuild; | ||
SpecialBuild = specialBuild; | ||
|
||
if (Version.TryParse(fileVersion, out Version version)) | ||
{ | ||
FileMajorPart = version.Major; | ||
FileMinorPart = version.Minor; | ||
FileBuildPart = version.Build; | ||
FilePrivatePart = version.Revision; | ||
} | ||
|
||
var parsedProductVersion = ProductVersionParser.Parse(productVersion); | ||
|
||
ProductMajorPart = parsedProductVersion.Major; | ||
ProductMinorPart = parsedProductVersion.Minor; | ||
ProductBuildPart = parsedProductVersion.Build; | ||
ProductPrivatePart = parsedProductVersion.PrivatePart; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override string FileName { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string FileVersion { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string ProductVersion { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string FileDescription { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string ProductName { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string CompanyName { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string Comments { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string InternalName { get; } | ||
|
||
/// <inheritdoc/> | ||
public override bool IsDebug { get; } | ||
|
||
/// <inheritdoc/> | ||
public override bool IsPatched { get; } | ||
|
||
/// <inheritdoc/> | ||
public override bool IsPrivateBuild { get; } | ||
|
||
/// <inheritdoc/> | ||
public override bool IsPreRelease { get; } | ||
|
||
/// <inheritdoc/> | ||
public override bool IsSpecialBuild { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string Language { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string LegalCopyright { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string LegalTrademarks { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string OriginalFilename { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string PrivateBuild { get; } | ||
|
||
/// <inheritdoc/> | ||
public override string SpecialBuild { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int FileMajorPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int FileMinorPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int FileBuildPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int FilePrivatePart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int ProductMajorPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int ProductMinorPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int ProductBuildPart { get; } | ||
|
||
/// <inheritdoc/> | ||
public override int ProductPrivatePart { get; } | ||
|
||
/// <inheritdoc cref="FileVersionInfo.ToString" /> | ||
public override string ToString() | ||
{ | ||
// An initial capacity of 512 was chosen because it is large enough to cover | ||
// the size of the static strings with enough capacity left over to cover | ||
// average length property values. | ||
var sb = new StringBuilder(512); | ||
sb.Append("File: ").AppendLine(FileName); | ||
sb.Append("InternalName: ").AppendLine(InternalName); | ||
sb.Append("OriginalFilename: ").AppendLine(OriginalFilename); | ||
sb.Append("FileVersion: ").AppendLine(FileVersion); | ||
sb.Append("FileDescription: ").AppendLine(FileDescription); | ||
sb.Append("Product: ").AppendLine(ProductName); | ||
sb.Append("ProductVersion: ").AppendLine(ProductVersion); | ||
sb.Append("Debug: ").AppendLine(IsDebug.ToString()); | ||
sb.Append("Patched: ").AppendLine(IsPatched.ToString()); | ||
sb.Append("PreRelease: ").AppendLine(IsPreRelease.ToString()); | ||
sb.Append("PrivateBuild: ").AppendLine(IsPrivateBuild.ToString()); | ||
sb.Append("SpecialBuild: ").AppendLine(IsSpecialBuild.ToString()); | ||
sb.Append("Language: ").AppendLine(Language); | ||
return sb.ToString(); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace System.IO.Abstractions.TestingHelpers | ||
{ | ||
/// <inheritdoc /> | ||
#if FEATURE_SERIALIZABLE | ||
[Serializable] | ||
#endif | ||
public class MockFileVersionInfoFactory : IFileVersionInfoFactory | ||
{ | ||
private readonly IMockFileDataAccessor mockFileSystem; | ||
|
||
/// <inheritdoc /> | ||
public MockFileVersionInfoFactory(IMockFileDataAccessor mockFileSystem) | ||
{ | ||
this.mockFileSystem = mockFileSystem ?? throw new ArgumentNullException(nameof(mockFileSystem)); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IFileSystem FileSystem => mockFileSystem; | ||
|
||
/// <inheritdoc /> | ||
public IFileVersionInfo GetVersionInfo(string fileName) | ||
{ | ||
MockFileData mockFileData = mockFileSystem.GetFile(fileName); | ||
|
||
if (mockFileData != null) | ||
{ | ||
return mockFileData.FileVersionInfo; | ||
} | ||
|
||
throw CommonExceptions.FileNotFound(fileName); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
using System.Reflection; | ||
using System.Text.RegularExpressions; | ||
|
||
namespace System.IO.Abstractions.TestingHelpers | ||
{ | ||
/// <summary> | ||
/// Provides functionality to parse a product version string into its major, minor, build, and private parts. | ||
/// </summary> | ||
public static class ProductVersionParser | ||
t4m45 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
{ | ||
/// <summary> | ||
/// Parses a product version string and extracts the numeric values for the major, minor, build, and private parts, | ||
/// mimicking the behavior of the <see cref="AssemblyInformationalVersionAttribute"/> attribute. | ||
/// </summary> | ||
/// <param name="productVersion">The product version string to parse.</param> | ||
/// <returns> | ||
/// A <see cref="ProductVersion"/> object containing the parsed major, minor, build, and private parts. | ||
/// If the input is invalid, returns a <see cref="ProductVersion"/> with all parts set to 0. | ||
/// </returns> | ||
/// <remarks> | ||
/// The method splits the input string into segments separated by dots ('.') and attempts to extract | ||
/// the leading numeric value from each segment. A maximum of 4 segments are processed; if more than | ||
/// 4 segments are present, all segments are ignored. Additionally, if a segment does not contain | ||
/// a valid numeric part at its start or it contains more than just a number, the rest of the segments are ignored. | ||
/// </remarks> | ||
public static ProductVersion Parse(string productVersion) | ||
{ | ||
if (string.IsNullOrWhiteSpace(productVersion)) | ||
{ | ||
return new(); | ||
} | ||
|
||
var segments = productVersion.Split('.'); | ||
if (segments.Length > 4) | ||
{ | ||
// if more than 4 segments are present, all segments are ignored | ||
return new(); | ||
} | ||
|
||
var regex = new Regex(@"^\d+"); | ||
|
||
int[] parts = new int[4]; | ||
|
||
for (int i = 0; i < segments.Length; i++) | ||
{ | ||
var match = regex.Match(segments[i]); | ||
if (match.Success && int.TryParse(match.Value, out int number)) | ||
{ | ||
parts[i] = number; | ||
|
||
if (match.Value != segments[i]) | ||
{ | ||
// when a segment contains more than a number, the rest of the segments are ignored | ||
break; | ||
} | ||
} | ||
else | ||
{ | ||
// when a segment is not valid, the rest of the segments are ignored | ||
break; | ||
} | ||
} | ||
|
||
return new() | ||
{ | ||
Major = parts[0], | ||
Minor = parts[1], | ||
Build = parts[2], | ||
PrivatePart = parts[3] | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// Represents a product version with numeric parts for major, minor, build, and private versions. | ||
/// </summary> | ||
public class ProductVersion | ||
{ | ||
/// <summary> | ||
/// Gets the major part of the version number | ||
/// </summary> | ||
public int Major { get; init; } | ||
|
||
/// <summary> | ||
/// Gets the minor part of the version number | ||
/// </summary> | ||
public int Minor { get; init; } | ||
|
||
/// <summary> | ||
/// Gets the build part of the version number | ||
/// </summary> | ||
public int Build { get; init; } | ||
|
||
/// <summary> | ||
/// Gets the private part of the version number | ||
/// </summary> | ||
public int PrivatePart { get; init; } | ||
} | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.