Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
81 changes: 1 addition & 80 deletions build_projects/dotnet-cli-build/MakeRelative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,12 @@ public class MakeRelative : Task
[Required]
public string Path2 { get; set; }

public char SeparatorChar { get; set; }

[Output]
public ITaskItem RelativePath { get; set; }

public override bool Execute()
{
if (SeparatorChar == default(char))
{
SeparatorChar = Path.DirectorySeparatorChar;
}

var relativePath = GetRelativePath(Path1, Path2, SeparatorChar);

RelativePath = ToTaskItem(Path1, Path2, relativePath);
RelativePath = ToTaskItem(Path1, Path2, Path.GetRelativePath(Path1, Path2));

This comment was marked as spam.


return true;
}
Expand All @@ -47,75 +38,5 @@ private static TaskItem ToTaskItem(string path1, string path2, string relativePa

return framework;
}

private static string GetRelativePath(string path1, string path2, char separator = default(char))
{

StringComparison compare;
if (CurrentPlatform.IsWindows)
{
compare = StringComparison.OrdinalIgnoreCase;
// check if paths are on the same volume
if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2)))
{
// on different volumes, "relative" path is just Path2
return path2;
}
}
else
{
compare = StringComparison.Ordinal;
}

var index = 0;
var path1Segments = path1.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
var path2Segments = path2.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
// if path1 does not end with / it is assumed the end is not a directory
// we will assume that is isn't a directory by ignoring the last split
var len1 = path1Segments.Length - 1;
var len2 = path2Segments.Length;

// find largest common absolute path between both paths
var min = Math.Min(len1, len2);
while (min > index)
{
if (!string.Equals(path1Segments[index], path2Segments[index], compare))
{
break;
}
// Handle scenarios where folder and file have same name (only if os supports same name for file and directory)
// e.g. /file/name /file/name/app
else if ((len1 == index && len2 > index + 1) || (len1 > index && len2 == index + 1))
{
break;
}
++index;
}

var path = "";

// check if path2 ends with a non-directory separator and if path1 has the same non-directory at the end
if (len1 + 1 == len2 && !string.IsNullOrEmpty(path1Segments[index]) &&
string.Equals(path1Segments[index], path2Segments[index], compare))
{
return path;
}

for (var i = index; len1 > i; ++i)
{
path += ".." + separator;
}
for (var i = index; len2 - 1 > i; ++i)
{
path += path2Segments[i] + separator;
}
// if path2 doesn't end with an empty string it means it ended with a non-directory name, so we add it back
if (!string.IsNullOrEmpty(path2Segments[len2 - 1]))
{
path += path2Segments[len2 - 1];
}

return path;
}
}
}
1 change: 1 addition & 0 deletions build_projects/dotnet-cli-build/dotnet-cli-build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App" Version="$(CLI_SharedFrameworkVersion)" />
<PackageReference Include="Microsoft.Build" Version="$(CLI_MSBuild_Version)" />
<PackageReference Include="Microsoft.CSharp" Version="4.0.1" />
<PackageReference Include="System.Dynamic.Runtime" Version="4.0.11" />
Expand Down
19 changes: 17 additions & 2 deletions src/Microsoft.DotNet.Cli.Utils/PathUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ public static string GetRelativePath(string path1, string path2, char separator,
{
compare = StringComparison.OrdinalIgnoreCase;
// check if paths are on the same volume
if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2)))
if (!string.Equals(Path.GetPathRoot(path1), Path.GetPathRoot(path2), compare))
{
// on different volumes, "relative" path is just path2
return path2;
Expand Down Expand Up @@ -273,7 +273,22 @@ public static string RemoveExtraPathSeparators(string path)

foreach (var component in components)
{
if (!string.IsNullOrEmpty(component))
if (string.IsNullOrEmpty(component))
{
continue;
}

if (string.IsNullOrEmpty(result))
{
result = component;

// On Windows, manually append a separator for drive references because Path.Combine won't do so
if (result.EndsWith(":") && RuntimeEnvironment.OperatingSystemPlatform == Platform.Windows)
{
result += Path.DirectorySeparatorChar;
}
}
else
{
result = Path.Combine(result, component);
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotnet/MsbuildProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private IEnumerable<string> GetIncludeAlternativesForRemoval(string reference)

string fullPath = Path.GetFullPath(reference);
ret.Add(fullPath);
ret.Add(PathUtility.GetRelativePath(ProjectDirectory, fullPath));
ret.Add(Path.GetRelativePath(ProjectDirectory, fullPath));

return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotnet/SlnFileExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static void AddProject(this SlnFile slnFile, string fullProjectPath)
throw new ArgumentException();
}

var relativeProjectPath = PathUtility.GetRelativePath(
var relativeProjectPath = Path.GetRelativePath(
PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory),
fullProjectPath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public override int Execute()
}

var relativePathReferences = _appliedCommand.Arguments.Select((r) =>
PathUtility.GetRelativePath(msbuildProj.ProjectDirectory, Path.GetFullPath(r)))
Path.GetRelativePath(msbuildProj.ProjectDirectory, Path.GetFullPath(r)))

This comment was marked as spam.

This comment was marked as spam.

.ToList();

int numberOfAddedReferences = msbuildProj.AddProjectToProjectReferences(
Expand Down
2 changes: 1 addition & 1 deletion src/dotnet/commands/dotnet-sln/remove/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public override int Execute()
SlnFile slnFile = SlnFileFactory.CreateFromFileOrDirectory(_fileOrDirectory);

var relativeProjectPaths = _appliedCommand.Arguments.Select(p =>
PathUtility.GetRelativePath(
Path.GetRelativePath(
PathUtility.EnsureTrailingSlash(slnFile.BaseDirectory),
Path.GetFullPath(p)))
.ToList();
Expand Down
34 changes: 34 additions & 0 deletions test/Microsoft.DotNet.Cli.Utils.Tests/PathUtilityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using Microsoft.DotNet.Tools.Common;
using Microsoft.DotNet.Tools.Test.Utilities;
using Xunit;

namespace Microsoft.DotNet.Cli.Utils
{
public class PathUtilityTests : TestBase
{
/// <summary>
/// Tests that PathUtility.GetRelativePath treats drive references as case insensitive on Windows.
/// </summary>
[WindowsOnlyFact]
public void GetRelativePathWithCaseInsensitiveDrives()
{
Assert.Equal(@"bar\", PathUtility.GetRelativePath(@"C:\foo\", @"C:\foo\bar\"));
Assert.Equal(@"Bar\Baz\", PathUtility.GetRelativePath(@"c:\foo\", @"C:\Foo\Bar\Baz\"));
Assert.Equal(@"baz\Qux\", PathUtility.GetRelativePath(@"C:\fOO\bar\", @"c:\foo\BAR\baz\Qux\"));
Assert.Equal(@"d:\foo\", PathUtility.GetRelativePath(@"C:\foo\", @"d:\foo\"));
}

/// <summary>
/// Tests that PathUtility.RemoveExtraPathSeparators works correctly with drive references on Windows.
/// </summary>
[WindowsOnlyFact]
public void RemoveExtraPathSeparatorsWithDrives()
{
Assert.Equal(@"c:\foo\bar\baz\", PathUtility.RemoveExtraPathSeparators(@"c:\\\foo\\\\bar\baz\\"));
Assert.Equal(@"D:\QUX\", PathUtility.RemoveExtraPathSeparators(@"D:\\\\\QUX\"));
}
}
}