Skip to content

Commit

Permalink
Merge branch 'daveaglick-GH260' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
devlead committed Oct 20, 2016
2 parents edd401b + e5a9f7b commit cf7cc86
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 0 deletions.
97 changes: 97 additions & 0 deletions src/Cake.Common.Tests/Unit/IO/DirectoryAliasesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,5 +1207,102 @@ public void Should_Return_Absolute_Directory_Path()
Assert.Equal("/Working/build", result.FullPath);
}
}

public sealed class TheMoveDirectoryMethod
{
[Fact]
public void Should_Throw_If_Context_Is_Null()
{
// Given, When
var source = new DirectoryPath("./source");
var target = new DirectoryPath("./target");

var result = Record.Exception(() =>
DirectoryAliases.MoveDirectory(null, source, target));

// Then
Assert.IsArgumentNullException(result, "context");
}

[Fact]
public void Should_Throw_If_Source_Directory_Path_Is_Null()
{
// Given
var context = Substitute.For<ICakeContext>();
var target = new DirectoryPath("./target");

// When
var result = Record.Exception(() =>
DirectoryAliases.MoveDirectory(context, null, target));

// Then
Assert.IsArgumentNullException(result, "directoryPath");
}

[Fact]
public void Should_Throw_If_Target_Directory_Path_Is_Null()
{
// Given
var context = Substitute.For<ICakeContext>();
var source = new DirectoryPath("./source");

// When
var result = Record.Exception(() =>
DirectoryAliases.MoveDirectory(context, source, null));

// Then
Assert.IsArgumentNullException(result, "targetDirectoryPath");
}

[Fact]
public void Should_Recursively_Move_Files_And_Directory()
{
// Given
var context = Substitute.For<ICakeContext>();
var environment = FakeEnvironment.CreateUnixEnvironment();
var fileSystem = new FakeFileSystem(environment);
CreateFileStructure(fileSystem);
context.FileSystem.Returns(fileSystem);
var sourcePath = new DirectoryPath("/Temp");
var destinationPath = new DirectoryPath("/Temp2");

// When
DirectoryAliases.MoveDirectory(context, sourcePath, destinationPath);

// Then
Assert.False(fileSystem.GetDirectory("/Temp/Stuff").Exists);
Assert.False(fileSystem.GetDirectory("/Temp/Things").Exists);
Assert.True(fileSystem.GetDirectory("/Temp2/Stuff").Exists);
Assert.True(fileSystem.GetDirectory("/Temp2/Things").Exists);

Assert.False(fileSystem.GetFile("/Temp/Stuff/file1.txt").Exists);
Assert.False(fileSystem.GetFile("/Temp/Stuff/file2.txt").Exists);
Assert.False(fileSystem.GetFile("/Temp/Things/file1.txt").Exists);
Assert.True(fileSystem.GetFile("/Temp2/Stuff/file1.txt").Exists);
Assert.True(fileSystem.GetFile("/Temp2/Stuff/file2.txt").Exists);
Assert.True(fileSystem.GetFile("/Temp2/Things/file1.txt").Exists);
}

private static void CreateFileStructure(FakeFileSystem ffs)
{
Action<string> dir = path => ffs.CreateDirectory(path);
Action<string> file = path => ffs.CreateFile(path);

dir("/Temp");
{
file("/Temp/file1.txt");
file("/Temp/file2.txt");
dir("/Temp/Stuff");
{
file("/Temp/Stuff/file1.txt");
file("/Temp/Stuff/file2.txt");
}
dir("/Temp/Things");
{
file("/Temp/Things/file1.txt");
}
}
}
}
}
}
18 changes: 18 additions & 0 deletions src/Cake.Common/IO/DirectoryAliases.cs
Original file line number Diff line number Diff line change
Expand Up @@ -439,5 +439,23 @@ public static DirectoryPath MakeAbsolute(this ICakeContext context, DirectoryPat

return path.MakeAbsolute(context.Environment);
}

/// <summary>
/// Moves an existing directory to a new location, providing the option to specify a new directory name.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="directoryPath">The directory path.</param>
/// <param name="targetDirectoryPath">The target directory path.</param>
/// <example>
/// <code>
/// MoveDirectory("mydir", "newparent/newdir");
/// </code>
/// </example>
[CakeMethodAlias]
[CakeAliasCategory("Move")]
public static void MoveDirectory(this ICakeContext context, DirectoryPath directoryPath, DirectoryPath targetDirectoryPath)
{
DirectoryMover.MoveDirectory(context, directoryPath, targetDirectoryPath);
}
}
}
49 changes: 49 additions & 0 deletions src/Cake.Common/IO/DirectoryMover.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Licensed to the .NET Foundation under one or more agreements.
// 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 System.Collections.Generic;
using System.Globalization;
using System.IO;
using Cake.Core;
using Cake.Core.Diagnostics;
using Cake.Core.IO;

namespace Cake.Common.IO
{
internal static class DirectoryMover
{
public static void MoveDirectory(ICakeContext context, DirectoryPath directoryPath, DirectoryPath targetDirectoryPath)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (directoryPath == null)
{
throw new ArgumentNullException(nameof(directoryPath));
}
if (targetDirectoryPath == null)
{
throw new ArgumentNullException(nameof(targetDirectoryPath));
}

directoryPath = directoryPath.MakeAbsolute(context.Environment);
targetDirectoryPath = targetDirectoryPath.MakeAbsolute(context.Environment);

// Get the directory and verify it exist.
var directory = context.FileSystem.GetDirectory(directoryPath);
if (!directory.Exists)
{
const string format = "The directory '{0}' does not exist.";
var message = string.Format(CultureInfo.InvariantCulture, format, directoryPath.FullPath);
throw new DirectoryNotFoundException(message);
}

// Move the directory.
context.Log.Verbose("Moving directory {0} to {1}", directoryPath.GetDirectoryName(), targetDirectoryPath);
directory.Move(targetDirectoryPath);
}
}
}
10 changes: 10 additions & 0 deletions src/Cake.Core/IO/Directory.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 System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -31,6 +32,15 @@ public void Create()
_directory.Create();
}

public void Move(DirectoryPath destination)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
_directory.MoveTo(destination.FullPath);
}

public void Delete(bool recursive)
{
_directory.Delete(recursive);
Expand Down
6 changes: 6 additions & 0 deletions src/Cake.Core/IO/IDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ public interface IDirectory : IFileSystemInfo
/// </summary>
void Create();

/// <summary>
/// Moves the directory to the specified destination path.
/// </summary>
/// <param name="destination">The destination path.</param>
void Move(DirectoryPath destination);

/// <summary>
/// Deletes the directory.
/// </summary>
Expand Down
9 changes: 9 additions & 0 deletions src/Cake.Testing/FakeDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,15 @@ public void Create()
_tree.CreateDirectory(this);
}

/// <summary>
/// Moves the directory to the specified destination path.
/// </summary>
/// <param name="destination">The destination path.</param>
public void Move(DirectoryPath destination)
{
_tree.MoveDirectory(this, destination);
}

/// <summary>
/// Deletes the directory.
/// </summary>
Expand Down
68 changes: 68 additions & 0 deletions src/Cake.Testing/FakeFileSystemTree.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,5 +262,73 @@ public void MoveFile(FakeFile fakeFile, FilePath destination)
// Delete the original file.
fakeFile.Delete();
}

public void MoveDirectory(FakeDirectory fakeDirectory, DirectoryPath destination)
{
var root = new Stack<FakeDirectory>();
var result = new Stack<FakeDirectory>();

if (string.IsNullOrEmpty(destination.FullPath))
{
throw new ArgumentException("The destination directory is empty.");
}

if (fakeDirectory.Path.Equals(destination))
{
throw new IOException("The directory being moved and the destination directory have the same name.");
}

if (FindDirectory(destination) != null)
{
throw new IOException("The destination directory already exists.");
}

string destinationParentPathStr = string.Join("/", destination.Segments.Take(destination.Segments.Length - 1).DefaultIfEmpty("/"));
DirectoryPath destinationParentPath = new DirectoryPath(destinationParentPathStr == string.Empty ? "/" : destinationParentPathStr);
if (FindDirectory(destinationParentPath) == null)
{
throw new DirectoryNotFoundException("The parent destination directory " + destinationParentPath.FullPath + " could not be found.");
}

if (fakeDirectory.Exists)
{
root.Push(fakeDirectory);
}

// Create destination directories and move files
while (root.Count > 0)
{
var node = root.Pop();
result.Push(node);

// Create destination directory
DirectoryPath relativePath = fakeDirectory.Path.GetRelativePath(node.Path);
DirectoryPath destinationPath = destination.Combine(relativePath);
CreateDirectory(destinationPath);

var files = node.Content.Files.Select(x => x).ToArray();
foreach (var file in files)
{
// Move the file.
MoveFile(file.Value, destinationPath.CombineWithFilePath(file.Key.GetFilename()));
}

var directories = node.Content.Directories;
foreach (var child in directories)
{
root.Push(child.Value);
}
}

// Delete source directories
while (result.Count > 0)
{
var directory = result.Pop();

// Delete the directory.
directory.Parent.Content.Remove(directory);
directory.Exists = false;
}
}
}
}

0 comments on commit cf7cc86

Please sign in to comment.