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…
Reference in new issue