Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 1 addition & 1 deletion src/Framework/ErrorUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.Build.Framework
// because some of the errors there will use localized resources from different assemblies,
// which won't be referenceable in Framework.

internal class FrameworkErrorUtilities
internal static class FrameworkErrorUtilities
{
/// <summary>
/// This method should be used in places where one would normally put
Expand Down
133 changes: 133 additions & 0 deletions src/Framework/FileUtilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.IO;

namespace Microsoft.Build.Framework
{
// TODO: this should be unified with Shared\FileUtilities, but it is hard to untangle everything in one go.
// Moved some of the methods here for now.

/// <summary>
/// This class contains utility methods for file IO.
/// Functions from FileUtilities are transferred here as part of the effort to remove Shared files.
/// </summary>
internal static class FrameworkFileUtilities
{
internal static readonly char[] Slashes = ['/', '\\'];

/// <summary>
/// Indicates if the given character is a slash.
/// </summary>
/// <param name="c"></param>
/// <returns>true, if slash</returns>
internal static bool IsSlash(char c)
{
return (c == Path.DirectorySeparatorChar) || (c == Path.AltDirectorySeparatorChar);
}

/// <summary>
/// Indicates if the given file-spec ends with a slash.
/// </summary>
/// <param name="fileSpec">The file spec.</param>
/// <returns>true, if file-spec has trailing slash</returns>
internal static bool EndsWithSlash(string fileSpec)
{
return (fileSpec.Length > 0)
? IsSlash(fileSpec[fileSpec.Length - 1])
: false;
}

Comment thread
JanProvaznik marked this conversation as resolved.
internal static string FixFilePath(string path)
{
return string.IsNullOrEmpty(path) || Path.DirectorySeparatorChar == '\\' ? path : path.Replace('\\', '/');
}

/// <summary>
/// If the given path doesn't have a trailing slash then add one.
/// If the path is an empty string, does not modify it.
/// </summary>
/// <param name="fileSpec">The path to check.</param>
/// <returns>A path with a slash.</returns>
internal static string EnsureTrailingSlash(string fileSpec)
{
fileSpec = FixFilePath(fileSpec);
if (fileSpec.Length > 0 && !IsSlash(fileSpec[fileSpec.Length - 1]))
{
fileSpec += Path.DirectorySeparatorChar;
}

return fileSpec;
}

/// <summary>
/// Ensures the path does not have a trailing slash.
/// </summary>
internal static string EnsureNoTrailingSlash(string path)
{
path = FixFilePath(path);
if (EndsWithSlash(path))
{
path = path.Substring(0, path.Length - 1);
}

return path;
}

#if !TASKHOST
/// <summary>
/// If the given path doesn't have a trailing slash then add one.
/// </summary>
/// <param name="path">The absolute path to check.</param>
/// <returns>An absolute path with a trailing slash.</returns>
internal static AbsolutePath EnsureTrailingSlash(AbsolutePath path)
{
return new AbsolutePath(EnsureTrailingSlash(path.Value),
original: path.OriginalValue,

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Source-Build (Managed))

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Source-Build (Managed))

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Linux Core)

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Linux Core)

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (macOS Core)

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (macOS Core)

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 86 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr

src/Framework/FileUtilities.cs#L86

src/Framework/FileUtilities.cs(86,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'
ignoreRootedCheck: true);
}

/// <summary>
/// Ensures the absolute path does not have a trailing slash.
/// </summary>
/// <param name="path">The absolute path to check.</param>
/// <returns>An absolute path without a trailing slash.</returns>
internal static AbsolutePath EnsureNoTrailingSlash(AbsolutePath path)
{
return new AbsolutePath(EnsureNoTrailingSlash(path.Value),
original: path.OriginalValue,

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Source-Build (Managed))

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Source-Build (Managed))

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Linux Core)

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Linux Core)

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (macOS Core)

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (macOS Core)

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 98 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr

src/Framework/FileUtilities.cs#L98

src/Framework/FileUtilities.cs(98,17): error CS1739: (NETCORE_ENGINEERING_TELEMETRY=Build) The best overload for 'AbsolutePath' does not have a parameter named 'original'
ignoreRootedCheck: true);
}

/// <summary>
/// Gets the canonicalized full path of the provided path.
/// Resolves relative segments like "." and "..". Fixes directory separators.
/// ASSUMES INPUT IS ALREADY UNESCAPED.
/// </summary>
internal static AbsolutePath NormalizePath(AbsolutePath path)
{
return new AbsolutePath(FixFilePath(Path.GetFullPath(path.Value)),
Comment thread
AR-May marked this conversation as resolved.
original: path.OriginalValue,

Check failure on line 110 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Source-Build (Managed))

src/Framework/FileUtilities.cs#L110

src/Framework/FileUtilities.cs(110,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 110 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (Linux Core)

src/Framework/FileUtilities.cs#L110

src/Framework/FileUtilities.cs(110,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 110 in src/Framework/FileUtilities.cs

View check run for this annotation

Azure Pipelines / msbuild-pr (macOS Core)

src/Framework/FileUtilities.cs#L110

src/Framework/FileUtilities.cs(110,32): error CS1061: (NETCORE_ENGINEERING_TELEMETRY=Build) 'AbsolutePath' does not contain a definition for 'OriginalValue' and no accessible extension method 'OriginalValue' accepting a first argument of type 'AbsolutePath' could be found (are you missing a using directive or an assembly reference?)
ignoreRootedCheck: true);
}

/// <summary>
/// Resolves relative segments like "." and "..".
/// ASSUMES INPUT IS ALREADY UNESCAPED.
/// </summary>
internal static AbsolutePath RemoveRelativeSegments(AbsolutePath path)
{
return new AbsolutePath(Path.GetFullPath(path.Value),
original: path.OriginalValue,
ignoreRootedCheck: true);
}

internal static AbsolutePath FixFilePath(AbsolutePath path)
{
return new AbsolutePath(FixFilePath(path.Value),
original: path.OriginalValue,
ignoreRootedCheck: true);
}
#endif
}
}
5 changes: 4 additions & 1 deletion src/MSBuildTaskHost/MSBuildTaskHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,12 @@
<Compile Include="..\Shared\ExceptionHandling.cs">
<Link>ExceptionHandling.cs</Link>
</Compile>
<Compile Include="..\Shared\FileUtilities.cs">
<Compile Include="..\Framework\FileUtilities.cs">
<Link>FileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\FileUtilities.cs">
<Link>SharedFileUtilities.cs</Link>
</Compile>
<Compile Include="..\Shared\FileUtilitiesRegex.cs">
<Link>FileUtilitiesRegex.cs</Link>
</Compile>
Expand Down
51 changes: 11 additions & 40 deletions src/Shared/FileUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static bool GetIsFileSystemCaseSensitive()
internal static char[] InvalidFileNameChars => InvalidFileNameCharsArray;
#endif

internal static readonly char[] Slashes = { '/', '\\' };
internal static readonly char[] Slashes = FrameworkFileUtilities.Slashes;

internal static readonly string DirectorySeparatorString = Path.DirectorySeparatorChar.ToString();

Expand Down Expand Up @@ -246,33 +246,24 @@ internal static void ClearCacheDirectory()
/// </summary>
/// <param name="fileSpec">The path to check.</param>
/// <returns>A path with a slash.</returns>
internal static string EnsureTrailingSlash(string fileSpec)
{
fileSpec = FixFilePath(fileSpec);
if (fileSpec.Length > 0 && !IsSlash(fileSpec[fileSpec.Length - 1]))
{
fileSpec += Path.DirectorySeparatorChar;
}

return fileSpec;
}
internal static string EnsureTrailingSlash(string fileSpec) => FrameworkFileUtilities.EnsureTrailingSlash(fileSpec);
Comment thread
JanProvaznik marked this conversation as resolved.
Outdated

/// <summary>
/// Ensures the path does not have a leading or trailing slash after removing the first 'start' characters.
/// </summary>
internal static string EnsureNoLeadingOrTrailingSlash(string path, int start)
{
int stop = path.Length;
while (start < stop && IsSlash(path[start]))
while (start < stop && FrameworkFileUtilities.IsSlash(path[start]))
{
start++;
}
while (start < stop && IsSlash(path[stop - 1]))
while (start < stop && FrameworkFileUtilities.IsSlash(path[stop - 1]))
{
stop--;
}

return FixFilePath(path.Substring(start, stop - start));
return FrameworkFileUtilities.FixFilePath(path.Substring(start, stop - start));
}

/// <summary>
Expand All @@ -281,12 +272,12 @@ internal static string EnsureNoLeadingOrTrailingSlash(string path, int start)
internal static string EnsureTrailingNoLeadingSlash(string path, int start)
{
int stop = path.Length;
while (start < stop && IsSlash(path[start]))
while (start < stop && FrameworkFileUtilities.IsSlash(path[start]))
{
start++;
}

return FixFilePath(start < stop && IsSlash(path[stop - 1]) ?
return FrameworkFileUtilities.FixFilePath(start < stop && FrameworkFileUtilities.IsSlash(path[stop - 1]) ?
path.Substring(start) :
#if NET
string.Concat(path.AsSpan(start), new(in Path.DirectorySeparatorChar)));
Expand All @@ -298,16 +289,7 @@ internal static string EnsureTrailingNoLeadingSlash(string path, int start)
/// <summary>
/// Ensures the path does not have a trailing slash.
/// </summary>
internal static string EnsureNoTrailingSlash(string path)
{
path = FixFilePath(path);
if (EndsWithSlash(path))
{
path = path.Substring(0, path.Length - 1);
}

return path;
}
internal static string EnsureNoTrailingSlash(string path) => FrameworkFileUtilities.EnsureNoTrailingSlash(path);

/// <summary>
/// Ensures the path is enclosed within single quotes.
Expand Down Expand Up @@ -370,22 +352,14 @@ internal static string EnsureQuotes(string path, bool isSingleQuote = true)
/// </summary>
/// <param name="fileSpec">The file spec.</param>
/// <returns>true, if file-spec has trailing slash</returns>
internal static bool EndsWithSlash(string fileSpec)
{
return (fileSpec.Length > 0)
? IsSlash(fileSpec[fileSpec.Length - 1])
: false;
}
internal static bool EndsWithSlash(string fileSpec) => FrameworkFileUtilities.EndsWithSlash(fileSpec);

/// <summary>
/// Indicates if the given character is a slash.
/// </summary>
/// <param name="c"></param>
/// <returns>true, if slash</returns>
internal static bool IsSlash(char c)
{
return (c == Path.DirectorySeparatorChar) || (c == Path.AltDirectorySeparatorChar);
}
internal static bool IsSlash(char c) => FrameworkFileUtilities.IsSlash(c);

/// <summary>
/// Trims the string and removes any double quotes around it.
Expand Down Expand Up @@ -578,10 +552,7 @@ From Path.cs in the CLR
}
#endif // FEATURE_LEGACY_GETFULLPATH

internal static string FixFilePath(string path)
{
return string.IsNullOrEmpty(path) || Path.DirectorySeparatorChar == '\\' ? path : path.Replace('\\', '/'); // .Replace("//", "/");
}
internal static string FixFilePath(string path) => FrameworkFileUtilities.FixFilePath(path);

/// <summary>
/// Normalizes all path separators (both forward and back slashes) to forward slashes.
Expand Down
Loading