From 56c86f1ab14fbe944c4d453380b63e8d6be4d57b Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 31 Mar 2024 04:10:42 +0200 Subject: [PATCH 1/5] feat(utilities): implement AbsolutePath copy/move --- source/Nuke.Common/IO/FileSystemTasks.cs | 9 + .../IO/FileSystemDependentTest.cs | 2 +- .../Nuke.Utilities.Tests/IO/MoveCopyTest.cs | 136 +++++++++++ .../Collections/Enumerable.WhereNotNull.cs | 9 + .../IO/AbsolutePath.MoveCopy.cs | 226 ++++++++++++++++-- 5 files changed, 360 insertions(+), 22 deletions(-) create mode 100644 source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs diff --git a/source/Nuke.Common/IO/FileSystemTasks.cs b/source/Nuke.Common/IO/FileSystemTasks.cs index 48e9c24d4..a2062784f 100644 --- a/source/Nuke.Common/IO/FileSystemTasks.cs +++ b/source/Nuke.Common/IO/FileSystemTasks.cs @@ -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)) @@ -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, @@ -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)) @@ -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, @@ -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) @@ -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, @@ -264,6 +270,7 @@ public static void MoveDirectory( } } + [Obsolete($"Use {nameof(AbsolutePath)}.{nameof(AbsolutePathExtensions.MoveToDirectory)}")] public static void MoveDirectoryToDirectory( AbsolutePath source, AbsolutePath targetDirectory, @@ -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, @@ -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, diff --git a/source/Nuke.Utilities.Tests/IO/FileSystemDependentTest.cs b/source/Nuke.Utilities.Tests/IO/FileSystemDependentTest.cs index 927d2dce1..8e721a507 100644 --- a/source/Nuke.Utilities.Tests/IO/FileSystemDependentTest.cs +++ b/source/Nuke.Utilities.Tests/IO/FileSystemDependentTest.cs @@ -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(); } diff --git a/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs new file mode 100644 index 000000000..c9e332022 --- /dev/null +++ b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs @@ -0,0 +1,136 @@ +// 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().WithMessage("* already exists"); + + new Action(() => source.Copy(target, policy: ExistsPolicy.FileFail | ExistsPolicy.FileOverwrite)) + .Should().Throw().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"; + var source2 = TestTempDirectory / "source2.txt"; + var source3 = TestTempDirectory / "source3.txt"; + source1.WriteAllText(nameof(source1)); + source2.WriteAllText(nameof(source2)); + source3.WriteAllText(nameof(source3)); + + 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().WithMessage("* already exists"); + + source1.Move(target, policy: ExistsPolicy.FileSkip).Should().Be(source1); + source1.Move(target, policy: ExistsPolicy.FileOverwriteIfNewer).Should().Be(source1); + 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().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(); + + 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(); + } +} diff --git a/source/Nuke.Utilities/Collections/Enumerable.WhereNotNull.cs b/source/Nuke.Utilities/Collections/Enumerable.WhereNotNull.cs index 7e480da59..4ee4180ae 100644 --- a/source/Nuke.Utilities/Collections/Enumerable.WhereNotNull.cs +++ b/source/Nuke.Utilities/Collections/Enumerable.WhereNotNull.cs @@ -18,4 +18,13 @@ public static IEnumerable WhereNotNull(this IEnumerable enumerable) { return enumerable.Where(x => x != null); } + + /// + /// Filters the collection to elements that don't meet the condition. + /// + public static IEnumerable WhereNot(this IEnumerable enumerable, Func condition) + where T : class + { + return enumerable.Where(x => condition == null || !condition(x)); + } } diff --git a/source/Nuke.Utilities/IO/AbsolutePath.MoveCopy.cs b/source/Nuke.Utilities/IO/AbsolutePath.MoveCopy.cs index 7535a7a54..ec1c3e931 100644 --- a/source/Nuke.Utilities/IO/AbsolutePath.MoveCopy.cs +++ b/source/Nuke.Utilities/IO/AbsolutePath.MoveCopy.cs @@ -4,73 +4,257 @@ using System; using System.IO; +using System.Linq; +using Nuke.Common.Utilities.Collections; namespace Nuke.Common.IO; +[Flags] +public enum ExistsPolicy +{ + DirectoryFail = 1, + DirectoryMerge = 2, + FileFail = 4, + FileSkip = 8, + FileOverwrite = 16, + FileOverwriteIfNewer = 32, + + Fail = DirectoryFail | FileFail, + MergeAndSkip = DirectoryMerge | FileSkip, + MergeAndOverwrite = DirectoryMerge | FileOverwrite, + MergeAndOverwriteIfNewer = DirectoryMerge | FileOverwriteIfNewer +} + partial class AbsolutePathExtensions { /// /// Renames the file or directory. /// - public static AbsolutePath Rename(this AbsolutePath path, string newName) + public static AbsolutePath Rename( + this AbsolutePath source, + string newName, + ExistsPolicy policy = ExistsPolicy.Fail) { - return path.Move(path.Parent / newName); + return source.Move(source.Parent / newName, policy); } /// /// Renames the file or directory. /// - public static AbsolutePath Rename(this AbsolutePath path, Func newName) + public static AbsolutePath Rename( + this AbsolutePath source, + Func newName, + ExistsPolicy policy = ExistsPolicy.Fail) { - return path.Rename(newName.Invoke(path)); + return source.Rename(newName.Invoke(source), policy); } /// /// Renames the file without changing the extension. /// - public static AbsolutePath RenameWithoutExtension(this AbsolutePath path, string newName) + public static AbsolutePath RenameWithoutExtension( + this AbsolutePath source, + string newName, + ExistsPolicy policy = ExistsPolicy.Fail) { - Assert.True(path.FileExists()); - return path.Move(path.Parent / newName + path.Extension); + return source.Move(source.Parent / newName + source.Extension, policy); } /// /// Renames the file without changing the extension. /// - public static AbsolutePath RenameWithoutExtension(this AbsolutePath path, Func newName) + public static AbsolutePath RenameWithoutExtension( + this AbsolutePath source, + Func newName, + ExistsPolicy policy = ExistsPolicy.Fail) { - return path.RenameWithoutExtension(newName.Invoke(path)); + return source.RenameWithoutExtension(newName.Invoke(source), policy); } /// /// Moves the file or directory to another directory. /// - public static AbsolutePath MoveToDirectory(this AbsolutePath path, AbsolutePath directory) + public static AbsolutePath MoveToDirectory( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true) { - Assert.True(directory.Exists()); - return path.Move(directory / path.Name); + return source.Move(target / source.Name, policy, createDirectories); } /// /// Moves the file or directory. /// - public static AbsolutePath Move(this AbsolutePath path, Func newPath) + public static AbsolutePath Move( + this AbsolutePath source, + Func newPath, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true) { - return path.Move(newPath.Invoke(path)); + return source.Move(newPath.Invoke(source), policy, createDirectories); } /// /// Moves the file or directory. /// - public static AbsolutePath Move(this AbsolutePath path, AbsolutePath newPath) + public static AbsolutePath Move( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true, + bool deleteRemainingFiles = false) + { + Assert.True(source.DirectoryExists() || source.FileExists()); + + if (source.DirectoryExists()) + return MoveDirectory(source, target, policy, createDirectories, deleteRemainingFiles); + + if (source.FileExists()) + return MoveFile(source, target, policy, createDirectories); + + throw new Exception("Unreachable"); + } + + /// + /// Copies the file or directory to another directory. + /// + public static AbsolutePath CopyToDirectory( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + Func excludeDirectory = null, + Func excludeFile = null, + bool createDirectories = true) + { + return source.Copy(target / source.Name, policy, excludeDirectory, excludeFile, createDirectories); + } + + /// + /// Copies the file or directory. + /// + public static AbsolutePath Copy( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + Func excludeDirectory = null, + Func excludeFile = null, + bool createDirectories = true) + { + Assert.True(source.DirectoryExists() || source.FileExists()); + + if (source.DirectoryExists()) + return CopyDirectory(source, target, policy, excludeDirectory, excludeFile, createDirectories); + + if (source.FileExists()) + return CopyFile(source, target, policy, createDirectories); + + throw new Exception("Unreachable"); + } + + private static AbsolutePath MoveFile( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true) + { + return HandleFile(source, target, policy, createDirectories, () => + { + target.DeleteFile(); + File.Move(source, target); + }); + } + + private static AbsolutePath CopyFile( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true) + { + return HandleFile(source, target, policy, createDirectories, () => + { + File.Copy(source, target, overwrite: true); + }); + } + + private static AbsolutePath HandleFile( + AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy, + bool createDirectories, + Action action) + { + if (File.Exists(target) && !Permitted()) + return source; + + if (createDirectories) + target.Parent.CreateDirectory(); + + action.Invoke(); + return target; + + bool Permitted() + { + var filePolicies = ExistsPolicy.FileFail | ExistsPolicy.FileSkip | ExistsPolicy.FileOverwrite | ExistsPolicy.FileOverwriteIfNewer; + return (policy & filePolicies) switch + { + ExistsPolicy.FileFail => throw new Exception($"File '{target}' already exists"), + ExistsPolicy.FileSkip => false, + ExistsPolicy.FileOverwrite => true, + ExistsPolicy.FileOverwriteIfNewer => File.GetLastWriteTimeUtc(target) < File.GetLastWriteTimeUtc(source), + _ => throw new ArgumentOutOfRangeException(nameof(policy), policy, message: "Multiple file policies set") + }; + } + } + + private static AbsolutePath MoveDirectory( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + bool createDirectories = true, + bool deleteRemainingFiles = false) + { + return HandleDirectory(source, target, policy, createDirectories, () => + { + source.GetDirectories().ForEach(x => x.MoveDirectory(target / source.GetRelativePathTo(x), policy)); + source.GetFiles().ForEach(x => x.MoveFile(target / source.GetRelativePathTo(x), policy)); + + if (!source.ToDirectoryInfo().EnumerateFileSystemInfos().Any() || deleteRemainingFiles) + source.DeleteDirectory(); + }); + } + + private static AbsolutePath CopyDirectory( + this AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy = ExistsPolicy.Fail, + Func excludeDirectory = null, + Func excludeFile = null, + bool createDirectories = true) + { + return HandleDirectory(source, target, policy, createDirectories, () => + { + source.GetDirectories().WhereNot(excludeDirectory).ForEach(x => x.CopyDirectory(target / source.GetRelativePathTo(x), policy, excludeDirectory, excludeFile)); + source.GetFiles().WhereNot(excludeFile).ForEach(x => x.CopyFile(target / source.GetRelativePathTo(x), policy)); + }); + } + + private static AbsolutePath HandleDirectory( + AbsolutePath source, + AbsolutePath target, + ExistsPolicy policy, + bool createDirectories, + Action action) { - Assert.True(path.DirectoryExists() || path.FileExists()); + Assert.DirectoryExists(source); + Assert.False(source.Contains(target), $"Target directory '{target}' must not be in source directory '{source}'"); + Assert.True(!Directory.Exists(target) || (policy.HasFlag(ExistsPolicy.DirectoryMerge) && !policy.HasFlag(ExistsPolicy.DirectoryFail)), + "Policy disallows merging directories"); - if (path.DirectoryExists()) - Directory.Move(path, newPath); - else if (path.FileExists()) - File.Move(path, newPath); + if (createDirectories) + target.CreateDirectory(); - return path; + action.Invoke(); + return target; } } From f97cb2440a18fe41941cb946bc66adc20f29631f Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 31 Mar 2024 04:18:21 +0200 Subject: [PATCH 2/5] chore: update FileSystemTasks usages --- build/Build.GlobalSolution.cs | 11 ++++------- source/Nuke.Common/Tools/ReSharper/ReSharperTasks.cs | 8 +++----- source/Nuke.Common/Utilities/TemplateUtility.cs | 10 ++-------- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/build/Build.GlobalSolution.cs b/build/Build.GlobalSolution.cs index c601c8838..4e2107570 100644 --- a/build/Build.GlobalSolution.cs +++ b/build/Build.GlobalSolution.cs @@ -15,7 +15,6 @@ using Nuke.Common.Utilities; using Nuke.Utilities.Text.Yaml; using static Nuke.Common.ControlFlow; -using static Nuke.Common.IO.FileSystemTasks; using static Nuke.Common.ProjectModel.SolutionModelTasks; using static Nuke.Common.Tools.Git.GitTasks; @@ -67,18 +66,16 @@ IEnumerable ExternalRepositories if ((RootDirectory / $"{Solution.FileName}.DotSettings").FileExists()) { - CopyFile( - source: RootDirectory / $"{Solution.FileName}.DotSettings", + (RootDirectory / $"{Solution.FileName}.DotSettings").Copy( target: RootDirectory / $"{global.FileName}.DotSettings", - FileExistsPolicy.Overwrite); + policy: ExistsPolicy.FileOverwrite); } if ((RootDirectory / $"{Solution.FileName}.DotSettings.user").FileExists()) { - CopyFile( - source: RootDirectory / $"{Solution.FileName}.DotSettings.user", + (RootDirectory / $"{Solution.FileName}.DotSettings.user").Copy( target: RootDirectory / $"{global.FileName}.DotSettings.user", - FileExistsPolicy.Overwrite); + policy: ExistsPolicy.FileOverwrite); } }); } diff --git a/source/Nuke.Common/Tools/ReSharper/ReSharperTasks.cs b/source/Nuke.Common/Tools/ReSharper/ReSharperTasks.cs index 67b246bf3..23f8375b8 100644 --- a/source/Nuke.Common/Tools/ReSharper/ReSharperTasks.cs +++ b/source/Nuke.Common/Tools/ReSharper/ReSharperTasks.cs @@ -26,11 +26,9 @@ private static void PreProcess(ref T toolSettings) where T : ReSharperSetting var wave = GetWave(toolSettings).NotNull("wave != null"); var shadowDirectory = GetShadowDirectory(toolSettings, wave); - FileSystemTasks.CopyDirectoryRecursively( - Path.GetDirectoryName(toolSettings.ProcessToolPath).NotNull(), - shadowDirectory, - DirectoryExistsPolicy.Merge, - FileExistsPolicy.OverwriteIfNewer); + ((AbsolutePath)toolSettings.ProcessToolPath.NotNull()).Copy( + target: shadowDirectory, + policy: ExistsPolicy.MergeAndOverwriteIfNewer); toolSettings.Plugins .Select(x => (Plugin: x.Key, Version: x.Value == ReSharperPluginLatest ? null : x.Value)) diff --git a/source/Nuke.Common/Utilities/TemplateUtility.cs b/source/Nuke.Common/Utilities/TemplateUtility.cs index f8fc14758..7dc604d5c 100644 --- a/source/Nuke.Common/Utilities/TemplateUtility.cs +++ b/source/Nuke.Common/Utilities/TemplateUtility.cs @@ -88,20 +88,14 @@ private static void FillTemplateDirectoryRecursivelyInternal( FillTemplateFile(file, tokens); if (ShouldMove(file)) - FileSystemTasks.RenameFile(file, file.Name.Replace(tokens), FileExistsPolicy.OverwriteIfNewer); + file.Rename(file.Name.Replace(tokens), ExistsPolicy.FileOverwriteIfNewer); } directory.GetDirectories() .ForEach(x => FillTemplateDirectoryRecursivelyInternal(x, tokens, excludeDirectory, excludeFile)); if (ShouldMove(directory)) - { - FileSystemTasks.RenameDirectory( - directory, - directory.Name.Replace(tokens), - DirectoryExistsPolicy.Merge, - FileExistsPolicy.OverwriteIfNewer); - } + directory.Rename(directory.Name.Replace(tokens), ExistsPolicy.MergeAndOverwriteIfNewer); } public static void FillTemplateFile( From ea39775885afa1db8975feee64f770bdb2d3d3fb Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 31 Mar 2024 04:42:54 +0200 Subject: [PATCH 3/5] fix --- source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs index c9e332022..f0a559698 100644 --- a/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs +++ b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs @@ -63,6 +63,8 @@ public void TestMoveFile() 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); } From 6eb779618e22b0cdf1fa27538b305f750b698d88 Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sun, 31 Mar 2024 04:45:21 +0200 Subject: [PATCH 4/5] fix --- source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs index f0a559698..85f1c74b2 100644 --- a/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs +++ b/source/Nuke.Utilities.Tests/IO/MoveCopyTest.cs @@ -45,12 +45,9 @@ public void TestCopyFile() [Fact] public void TestMoveFile() { - var source1 = TestTempDirectory / "source1.txt"; - var source2 = TestTempDirectory / "source2.txt"; - var source3 = TestTempDirectory / "source3.txt"; - source1.WriteAllText(nameof(source1)); - source2.WriteAllText(nameof(source2)); - source3.WriteAllText(nameof(source3)); + 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); From dcad169a348431c9788b84b8bdda2ff4ebca553f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rnset?= Date: Sat, 13 Apr 2024 20:25:27 +0200 Subject: [PATCH 5/5] Update GitHub actions step- uses: actions/checkout from @v3 to @v4 to switch from Node v 16 to v 20 --- .github/workflows/alpha-deployment.yml | 2 +- .github/workflows/macos-latest.yml | 2 +- .github/workflows/ubuntu-latest.yml | 2 +- .github/workflows/windows-latest.yml | 2 +- ...d-triggers_attribute=GitHubActionsAttribute.verified.txt | 6 +++--- ...e-triggers_attribute=GitHubActionsAttribute.verified.txt | 6 +++--- .../Configuration/GitHubActionsCheckoutStep.cs | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/alpha-deployment.yml b/.github/workflows/alpha-deployment.yml index 69b7d54e5..3ea38c32c 100644 --- a/.github/workflows/alpha-deployment.yml +++ b/.github/workflows/alpha-deployment.yml @@ -26,7 +26,7 @@ jobs: name: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: 'Cache: .nuke/temp, ~/.nuget/packages' diff --git a/.github/workflows/macos-latest.yml b/.github/workflows/macos-latest.yml index 9db41a37b..248a66a28 100644 --- a/.github/workflows/macos-latest.yml +++ b/.github/workflows/macos-latest.yml @@ -30,7 +30,7 @@ jobs: name: macos-latest runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: 'Cache: .nuke/temp, ~/.nuget/packages' diff --git a/.github/workflows/ubuntu-latest.yml b/.github/workflows/ubuntu-latest.yml index 06b3edcd3..d5b513b19 100644 --- a/.github/workflows/ubuntu-latest.yml +++ b/.github/workflows/ubuntu-latest.yml @@ -30,7 +30,7 @@ jobs: name: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: 'Cache: .nuke/temp, ~/.nuget/packages' diff --git a/.github/workflows/windows-latest.yml b/.github/workflows/windows-latest.yml index b8b183eeb..03f6a7639 100644 --- a/.github/workflows/windows-latest.yml +++ b/.github/workflows/windows-latest.yml @@ -30,7 +30,7 @@ jobs: name: windows-latest runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: 'Cache: .nuke/temp, ~/.nuget/packages' diff --git a/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=detailed-triggers_attribute=GitHubActionsAttribute.verified.txt b/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=detailed-triggers_attribute=GitHubActionsAttribute.verified.txt index baa10b88e..03017e6f0 100644 --- a/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=detailed-triggers_attribute=GitHubActionsAttribute.verified.txt +++ b/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=detailed-triggers_attribute=GitHubActionsAttribute.verified.txt @@ -53,7 +53,7 @@ jobs: group: ${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.run_id }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive lfs: true @@ -96,7 +96,7 @@ jobs: group: ${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.run_id }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive lfs: true @@ -139,7 +139,7 @@ jobs: group: ${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.run_id }} cancel-in-progress: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive lfs: true diff --git a/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=simple-triggers_attribute=GitHubActionsAttribute.verified.txt b/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=simple-triggers_attribute=GitHubActionsAttribute.verified.txt index 740323d94..81771b54a 100644 --- a/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=simple-triggers_attribute=GitHubActionsAttribute.verified.txt +++ b/source/Nuke.Common.Tests/CI/ConfigurationGenerationTest.Test_testName=simple-triggers_attribute=GitHubActionsAttribute.verified.txt @@ -27,7 +27,7 @@ jobs: name: macos-latest runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: 'Cache: .nuke/temp, ~/.nuget/packages' uses: actions/cache@v4 with: @@ -59,7 +59,7 @@ jobs: name: ubuntu-latest runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: 'Cache: .nuke/temp, ~/.nuget/packages' uses: actions/cache@v4 with: @@ -91,7 +91,7 @@ jobs: name: windows-latest runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: 'Cache: .nuke/temp, ~/.nuget/packages' uses: actions/cache@v4 with: diff --git a/source/Nuke.Common/CI/GitHubActions/Configuration/GitHubActionsCheckoutStep.cs b/source/Nuke.Common/CI/GitHubActions/Configuration/GitHubActionsCheckoutStep.cs index 213acf17d..3cd11beab 100644 --- a/source/Nuke.Common/CI/GitHubActions/Configuration/GitHubActionsCheckoutStep.cs +++ b/source/Nuke.Common/CI/GitHubActions/Configuration/GitHubActionsCheckoutStep.cs @@ -18,7 +18,7 @@ public class GitHubActionsCheckoutStep : GitHubActionsStep public override void Write(CustomFileWriter writer) { - writer.WriteLine("- uses: actions/checkout@v3"); + writer.WriteLine("- uses: actions/checkout@v4"); if (Submodules.HasValue || Lfs.HasValue || FetchDepth.HasValue) {