Skip to content
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
38 changes: 38 additions & 0 deletions src/Cake.Core.Tests/Unit/IO/PathExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Cake.Core.IO;
using Cake.Testing;
using Xunit;
Expand Down Expand Up @@ -74,5 +75,42 @@ public void Should_Expand_Existing_Environment_Variables()
}
}
}

public sealed class TheExpandShortPathMethod
{
[Theory]
[InlineData("C:/Program Files/cake-build/addins", "C:/Program Files/cake-build/addins")]
[InlineData("C:/PROGRA~1/cake-build/addins", "C:/Program Files/cake-build/addins")]
public void Will_Normalize_Short_Paths_File(string input, string expected)
{
// Given, When
var path = new FilePath(input);

path = path.ExpandShortPath();

// Then
if (OperatingSystem.IsWindows())
{
Assert.Equal(expected, path.FullPath);
}
}

[Theory]
[InlineData("C:/Program Files/cake-build/addins", "C:/Program Files/cake-build/addins")]
[InlineData("C:/PROGRA~1/cake-build/addins", "C:/Program Files/cake-build/addins")]
public void Will_Normalize_Short_Paths_Directory(string input, string expected)
{
// Given, When
var path = new DirectoryPath(input);

path = path.ExpandShortPath();

// Then
if (OperatingSystem.IsWindows())
{
Assert.Equal(expected, path.FullPath);
}
}
}
}
}
1 change: 0 additions & 1 deletion src/Cake.Core.Tests/Unit/IO/PathTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Cake.Core.IO;
using Cake.Testing.Xunit;
using Xunit;
Expand Down
42 changes: 42 additions & 0 deletions src/Cake.Core.Tests/Unit/SetupContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using NSubstitute;
using Xunit;

namespace Cake.Core.Tests.Unit
{
public sealed class SetupContextTests
{
public sealed class TheConstructor
{
[Fact]
public void Returns_Empty_Tasks_When_Input_Is_Null()
{
var cakeContextMock = Substitute.For<ICakeContext>();
var cakeTaskInfoMock = Substitute.For<ICakeTaskInfo>();

// Given, When
var result = new SetupContext(cakeContextMock, cakeTaskInfoMock, null);

// Then
Assert.NotNull(result.TasksToExecute);
Assert.Empty(result.TasksToExecute);
}

[Fact]
public void Returns_Injected_Tasks_When_Input_Is_Not_Null()
{
var cakeContextMock = Substitute.For<ICakeContext>();
var cakeTaskInfoMock = Substitute.For<ICakeTaskInfo>();

// Given, When
var result = new SetupContext(cakeContextMock, cakeTaskInfoMock, new[]
{
cakeTaskInfoMock
});

// Then
Assert.NotNull(result.TasksToExecute);
Assert.Single(result.TasksToExecute);
}
}
}
}
12 changes: 6 additions & 6 deletions src/Cake.Core/IO/Path.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;

namespace Cake.Core.IO
{
Expand Down Expand Up @@ -57,15 +56,16 @@ protected Path(string path)
IsUNC = path.StartsWith(@"\\");
Separator = IsUNC ? '\\' : '/';

var separatorToReplace = '\\';
var separatorToReplaceWith = Separator;

if (IsUNC)
{
FullPath = path.Replace('/', Separator).Trim();
}
else
{
FullPath = path.Replace('\\', Separator).Trim();
separatorToReplace = '/';
}

FullPath = path.Replace(separatorToReplace, separatorToReplaceWith).Trim();

// Relative paths are considered empty.
FullPath = FullPath == "./" ? string.Empty : FullPath;

Expand Down
58 changes: 58 additions & 0 deletions src/Cake.Core/IO/PathExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,63 @@ public static DirectoryPath ExpandEnvironmentVariables(this DirectoryPath path,
var result = environment.ExpandEnvironmentVariables(path.FullPath);
return new DirectoryPath(result);
}

/// <summary>
/// Expands short paths (e.g. C:/Users/ABCDEF~1) to long paths (e.g. C:/Users/abcdefghij).
/// <para/>
/// Note that this method only works for absolute paths, as relative paths cannot be expanded without impact.
/// </summary>
/// <param name="path">The path to check.</param>
/// <returns>The path for which, if available, the short paths are expanded to long paths.</returns>
public static FilePath ExpandShortPath(this FilePath path)
{
if (!path.IsRelative)
{
// Only when not relative, resolve short paths to long paths, e.g.:
//
// C:/Users/ABCDEF~1/AppData/Local/Temp/cake-build/addins
// C:/Users/abcdefghij/AppData/Local/Temp/cake-build/addins
//
// The reason this is required is that tools / addins can't be located
// when using short paths
//
// Note that a path can contain multiple ~, thus we need to check for just ~
if (path.FullPath.Contains('~'))
{
return new FilePath(System.IO.Path.GetFullPath(path.FullPath));
}
}

return path;
}

/// <summary>
/// Expands short paths (e.g. C:/Users/ABCDEF~1) to long paths (e.g. C:/Users/abcdefghij).
/// <para/>
/// Note that this method only works for absolute paths, as relative paths cannot be expanded without impact.
/// </summary>
/// <param name="path">The path to check.</param>
/// <returns>The path for which, if available, the short paths are expanded to long paths.</returns>
public static DirectoryPath ExpandShortPath(this DirectoryPath path)
{
if (!path.IsRelative)
{
// Only when not relative, resolve short paths to long paths, e.g.:
//
// C:/Users/ABCDEF~1/AppData/Local/Temp/cake-build/addins
// C:/Users/abcdefghij/AppData/Local/Temp/cake-build/addins
//
// The reason this is required is that tools / addins can't be located
// when using short paths
//
// Note that a path can contain multiple ~, thus we need to check for just ~
if (path.FullPath.Contains('~'))
{
return new DirectoryPath(System.IO.Path.GetFullPath(path.FullPath));
}
}

return path;
}
}
}
2 changes: 1 addition & 1 deletion src/Cake.Core/Scripting/ScriptProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ private void InstallPackages(
}

// Make the installation root absolute.
installPath = installPath.MakeAbsolute(_environment);
installPath = installPath.MakeAbsolute(_environment).ExpandShortPath();

if (modules.Count > 0)
{
Expand Down
3 changes: 2 additions & 1 deletion src/Cake.Core/SetupContext.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Cake.Core
{
Expand All @@ -26,7 +27,7 @@ public SetupContext(ICakeContext context,
: base(context)
{
TargetTask = targetTask;
TasksToExecute = new List<ICakeTaskInfo>(tasksToExecute ?? Array.Empty<ICakeTaskInfo>());
TasksToExecute = tasksToExecute?.ToArray() ?? Array.Empty<ICakeTaskInfo>();
}
}
}
Loading