refactor: Add MergeDirectory() method + tests

pull/76/head
Robert Dailey 2 years ago
parent 276f59ae8c
commit d50e08b1e3

@ -0,0 +1,116 @@
using System.IO.Abstractions;
using System.IO.Abstractions.TestingHelpers;
using System.Text.RegularExpressions;
using Common.Extensions;
using FluentAssertions;
using NUnit.Framework;
namespace Common.Tests.Extensions;
[TestFixture]
[Parallelizable(ParallelScope.All)]
public class FileSystemExtensionsTest
{
private static IEnumerable<string> ReRootFiles(IFileSystem fs, IEnumerable<string> files,
string oldRoot, string newRoot)
{
return files.Select(x =>
{
var strippedPath = Regex.Replace(x, $"^{oldRoot}", newRoot);
return fs.Path.GetFullPath(strippedPath);
});
}
private static ICollection<string> NormalizePaths(IEnumerable<string> paths)
=> paths.Select(NormalizePath).ToList();
private static string NormalizePath(string path)
{
if (MockUnixSupport.IsUnixPlatform())
{
return Regex.Replace(path, @"^C:\\", "/").Replace("\\", "/");
}
return Regex.Replace(path, @"^/", @"C:\").Replace("/", "\\");
}
private static MockFileSystem NewMockFileSystem(IEnumerable<string> files, string cwd)
{
return NewMockFileSystem(files, Array.Empty<string>(), cwd);
}
private static MockFileSystem NewMockFileSystem(IEnumerable<string> files, IEnumerable<string> dirs, string cwd)
{
var dirData = dirs.Select(x => (x, (MockFileData) new MockDirectoryData()));
var fileData = files.Select(x => (x, new MockFileData("")));
return new MockFileSystem(fileData.Concat(dirData)
.ToDictionary(x => x.Item1, y => y.Item2), NormalizePath(cwd));
}
[Test]
public void Merge_directories_works()
{
var files = NormalizePaths(new[]
{
@"path1\1\file1.txt",
@"path1\1\file2.txt",
@"path1\1\2\3\4\file3.txt",
@"path1\file4.txt"
});
var dirs = NormalizePaths(new[]
{
@"path1\empty1",
@"path1\empty2",
@"path1\1\2\empty3",
@"path1\1\2\3\4\empty4"
});
var fs = NewMockFileSystem(files, dirs, @"C:\root\path");
fs.MergeDirectory("path1", "path2");
fs.AllDirectories.Select(MockUnixSupport.Path).Should()
.NotContain(x => x.Contains("path1") || x.Contains("empty"));
fs.AllFiles.Should().BeEquivalentTo(ReRootFiles(fs, files, "path1", "path2"));
}
[Test]
public void Fail_if_file_already_exists()
{
var files = NormalizePaths(new[]
{
@"path1\1\file1.txt",
@"path1\1\file2.txt",
@"path2\1\file1.txt"
});
var fs = NewMockFileSystem(files, @"C:\root\path");
var act = () => fs.MergeDirectory("path1", "path2");
act.Should().Throw<IOException>();
}
[Test]
public void Fail_if_directory_exists_where_file_goes()
{
var files = NormalizePaths(new[]
{
@"path1\1\file1"
});
var dirs = NormalizePaths(new[]
{
@"path2\1\file1"
});
var fs = NewMockFileSystem(files, dirs, @"C:\root\path");
var act = () => fs.MergeDirectory("path1", "path2");
act.Should().Throw<IOException>();
}
}

@ -0,0 +1,30 @@
using System.IO.Abstractions;
using System.Text.RegularExpressions;
namespace Common.Extensions;
public static class FileSystemExtensions
{
public static void MergeDirectory(this IFileSystem fs, string targetDir, string destDir)
{
targetDir = fs.Path.GetFullPath(targetDir);
destDir = fs.Path.GetFullPath(destDir);
var directories = fs.DirectoryInfo.FromDirectoryName(targetDir)
.EnumerateDirectories("*", SearchOption.AllDirectories)
.Append(fs.DirectoryInfo.FromDirectoryName(targetDir))
.OrderByDescending(x => x.FullName.Count(y => y is '/' or '\\'));
foreach (var dir in directories)
{
foreach (var file in dir.EnumerateFiles())
{
var newPath = Regex.Replace(file.FullName, $"^{Regex.Escape(targetDir)}", destDir);
fs.Directory.CreateDirectory(fs.Path.GetDirectoryName(newPath));
file.MoveTo(newPath);
}
dir.Delete();
}
}
}
Loading…
Cancel
Save