Skip to content

Commit

Permalink
feat(utilities): implement AbsolutePath copy/move
Browse files Browse the repository at this point in the history
  • Loading branch information
matkoch committed Jun 12, 2024
1 parent b081057 commit 540c5aa
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 22 deletions.
9 changes: 9 additions & 0 deletions source/Nuke.Common/IO/FileSystemTasks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public static void DeleteFile(string file)
File.Delete(file);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Copy)}")]
public static void CopyFile(AbsolutePath source, AbsolutePath target, FileExistsPolicy policy = FileExistsPolicy.Fail, bool createDirectories = true)
{
if (!ShouldCopyFile(source, target, policy))
Expand All @@ -200,6 +201,7 @@ public static void CopyFile(AbsolutePath source, AbsolutePath target, FileExists
File.Copy(source, target, overwrite: true);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.CopyToDirectory)}")]
public static void CopyFileToDirectory(
AbsolutePath source,
AbsolutePath targetDirectory,
Expand All @@ -209,6 +211,7 @@ public static void CopyFileToDirectory(
CopyFile(source, Path.Combine(targetDirectory, Path.GetFileName(source).NotNull()), policy, createDirectories);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Move)}")]
public static void MoveFile(AbsolutePath source, AbsolutePath target, FileExistsPolicy policy = FileExistsPolicy.Fail, bool createDirectories = true)
{
if (!ShouldCopyFile(source, target, policy))
Expand All @@ -224,6 +227,7 @@ public static void MoveFile(AbsolutePath source, AbsolutePath target, FileExists
File.Move(source, target);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.MoveToDirectory)}")]
public static void MoveFileToDirectory(
AbsolutePath source,
AbsolutePath targetDirectory,
Expand All @@ -233,6 +237,7 @@ public static void MoveFileToDirectory(
MoveFile(source, Path.Combine(targetDirectory, Path.GetFileName(source).NotNull()), policy, createDirectories);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Rename)}")]
public static void RenameFile(AbsolutePath file, string newName, FileExistsPolicy policy = FileExistsPolicy.Fail)
{
if (Path.GetFileName(file) == newName)
Expand All @@ -241,6 +246,7 @@ public static void RenameFile(AbsolutePath file, string newName, FileExistsPolic
MoveFile(file, Path.Combine(Path.GetDirectoryName(file).NotNull(), newName), policy);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Move)}")]
public static void MoveDirectory(
AbsolutePath source,
AbsolutePath target,
Expand All @@ -264,6 +270,7 @@ public static void MoveDirectory(
}
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.MoveToDirectory)}")]
public static void MoveDirectoryToDirectory(
AbsolutePath source,
AbsolutePath targetDirectory,
Expand All @@ -273,6 +280,7 @@ public static void MoveDirectoryToDirectory(
MoveDirectory(source, Path.Combine(targetDirectory, new DirectoryInfo(source).Name), directoryPolicy, filePolicy);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Rename)}")]
public static void RenameDirectory(
string directory,
string newName,
Expand All @@ -282,6 +290,7 @@ public static void RenameDirectory(
MoveDirectory(directory, Path.Combine(Path.GetDirectoryName(directory).NotNull(), newName), directoryPolicy, filePolicy);
}

[Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.Copy)}")]
public static void CopyDirectoryRecursively(
AbsolutePath source,
AbsolutePath target,
Expand Down
2 changes: 1 addition & 1 deletion source/Nuke.Utilities.Tests/IO/FileSystemDependentTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ protected FileSystemDependentTest(ITestOutputHelper testOutputHelper)
ExecutionDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location).NotNull();
RootDirectory = Constants.TryGetRootDirectoryFrom(EnvironmentInfo.WorkingDirectory);
TestProjectDirectory = ExecutionDirectory.FindParentOrSelf(x => x.ContainsFile("*.csproj"));
TestTempDirectory = ExecutionDirectory / "temp" / $"{GetType().Name}.{TestName}";
TestTempDirectory = ExecutionDirectory / "temp" / $"{GetType().Name}.{TestName}";

TestTempDirectory.CreateOrCleanDirectory();
}
Expand Down
135 changes: 135 additions & 0 deletions source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright 2024 Maintainers of NUKE.
// Distributed under the MIT License.
// https://github.com/nuke-build/nuke/blob/master/LICENSE

using System;
using System.Linq;
using FluentAssertions;
using Nuke.Common.IO;
using Nuke.Common.Utilities.Collections;
using Xunit;
using Xunit.Abstractions;

namespace Nuke.Common.Tests;

public class MoveCopyTest : FileSystemDependentTest
{
public MoveCopyTest(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
AbsolutePathExtensions.DefaultEofLineBreak = false;
}

[Fact]
public void TestCopyFile()
{
var source = TestTempDirectory / "source.txt";
source.WriteAllText("foobar");

var target = TestTempDirectory / "target.txt";
source.Copy(target);

target.FileExists().Should().BeTrue();

new Action(() => source.Copy(target))
.Should().Throw<Exception>().WithMessage("* already exists");

new Action(() => source.Copy(target, policy: ExistsPolicy.FileFail | ExistsPolicy.FileOverwrite))
.Should().Throw<Exception>().WithMessage("Multiple file policies *");

source.WriteAllText("fizzbuzz");
source.Copy(target, policy: ExistsPolicy.FileOverwrite)
.Should().Be(target);
target.ReadAllText().Should().Be("fizzbuzz");
}

[Fact]
public void TestMoveFile()
{
var source1 = (TestTempDirectory / "source1.txt").TouchFile();
var source2 = (TestTempDirectory / "source2.txt").TouchFile();
var source3 = (TestTempDirectory / "source3.txt").TouchFile();

var target = TestTempDirectory / "target.txt";
source2.Move(target);

target.FileExists().Should().BeTrue();
source2.FileExists().Should().BeFalse();

new Action(() => source1.Move(target, policy: ExistsPolicy.FileFail))
.Should().Throw<Exception>().WithMessage("* already exists");

source1.Move(target, policy: ExistsPolicy.FileSkip).Should().Be(source1);
source1.Move(target, policy: ExistsPolicy.FileOverwriteIfNewer).Should().Be(source1);

source3.TouchFile();
source3.Move(target, policy: ExistsPolicy.FileOverwriteIfNewer).Should().Be(target);
}

[Fact]
public void TestCopyDirectory()
{
var source = TestTempDirectory / "source";
var sourceFiles = new[]
{
source / "source1.txt",
source / "source2.txt",
source / "sub" / "source3.txt",
source / "sub" / "source4.txt",
};
sourceFiles.ForEach(x => x.WriteAllText("source"));

var target = TestTempDirectory / "target";
source.Copy(target);
target.GetFiles(depth: int.MaxValue).Select(x => target.GetRelativePathTo(x).ToString())
.Should().BeEquivalentTo(sourceFiles.Select(x => source.GetRelativePathTo(x).ToString()));

target.CreateOrCleanDirectory();
var target0 = (target / "source0.txt").TouchFile();
var target3 = (target / "sub" / "source3.txt").WriteAllText("target");
var target4 = (target / "sub" / "source4.txt").WriteAllText("target");
(source / target.GetRelativePathTo(target4)).TouchFile();

new Action(() => source.Copy(target, ExistsPolicy.DirectoryFail))
.Should().Throw<Exception>().WithMessage("Policy disallows merging directories");
target.GetFiles(depth: int.MaxValue).Should().HaveCount(3);

source.Copy(target, ExistsPolicy.MergeAndSkip);
target0.FileExists().Should().BeTrue();
target3.ReadAllText().Should().Be("target");
target4.ReadAllText().Should().Be("target");

source.Copy(target, ExistsPolicy.MergeAndOverwriteIfNewer);
target3.ReadAllText().Should().Be("target");
target4.ReadAllText().Should().Be("source");

source.Copy(target, ExistsPolicy.MergeAndOverwrite);
target3.ReadAllText().Should().Be("source");
}

[Fact]
public void TestMoveDirectory()
{
var source = TestTempDirectory / "source";
var sourceFiles = new[]
{
source / "source1.txt",
source / "source2.txt",
source / "sub" / "source3.txt",
source / "sub" / "source4.txt",
};
sourceFiles.ForEach(x => x.WriteAllText("source"));

var target = TestTempDirectory / "target";
(target / "source1.txt").TouchFile();
(target / "sub" / "source3.txt").TouchFile();

new Action(() => source.Move(target)).Should().Throw<Exception>();

source.Move(target, ExistsPolicy.MergeAndSkip);
source.GetFiles(depth: int.MaxValue).Should().HaveCount(2);

source.Move(target, ExistsPolicy.MergeAndSkip, deleteRemainingFiles: true)
.Should().Be(target);
source.DirectoryExists().Should().BeFalse();
}
}
9 changes: 9 additions & 0 deletions source/Nuke.Utilities/Collections/Enumerable.WhereNotNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,13 @@ public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> enumerable)
{
return enumerable.Where(x => x != null);
}

/// <summary>
/// Filters the collection to elements that don't meet the condition.
/// </summary>
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> enumerable, Func<T, bool> condition)
where T : class
{
return enumerable.Where(x => condition == null || !condition(x));
}
}
Loading

0 comments on commit 540c5aa

Please sign in to comment.