Skip to content

Commit

Permalink
fix directory copier is not recursive
Browse files Browse the repository at this point in the history
  • Loading branch information
AnakinRaW committed Apr 7, 2024
1 parent 0d721c7 commit 6d3665b
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/CommonUtilities.FileSystem/src/DirectoryCopier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ private bool CopyOrMoveDirectory(

private IEnumerable<CopyInformation> GetFiles(string source, string destination, bool isMove, Predicate<string>? fileFilter)
{
foreach (var file in _fileSystem.Directory.GetFiles(source, "*", SearchOption.TopDirectoryOnly))
foreach (var file in _fileSystem.Directory.GetFiles(source, "*", SearchOption.AllDirectories))
{
if (fileFilter is not null && !fileFilter(file))
continue;
Expand Down
57 changes: 55 additions & 2 deletions src/CommonUtilities.FileSystem/src/Extensions/FileExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ public static void DeleteIfInTemp(this IFile _, string file)
/// <param name="retryCount">Number of retry attempts tempts until the operation fails.</param>
/// <param name="retryDelay">Delay time in ms between each new attempt.</param>
/// <param name="errorAction">Callback which gets always triggered if an attempt failed.</param>
/// <returns><see langword="false"/> if the operation failed. <see langword="true"/> otherwise.</returns>
public static void DeleteWithRetry(this IFileInfo file, int retryCount = 2, int retryDelay = 500, Func<Exception, int, bool>? errorAction = null)
{
if (file == null)
Expand All @@ -204,7 +203,6 @@ public static void DeleteWithRetry(this IFileInfo file, int retryCount = 2, int
/// <param name="retryCount">Number of retry attempts tempts until the operation fails.</param>
/// <param name="retryDelay">Delay time in ms between each new attempt.</param>
/// <param name="errorAction">Callback which gets always triggered if an attempt failed.</param>
/// <returns><see langword="false"/> if the operation failed. <see langword="true"/> otherwise.</returns>
public static void DeleteWithRetry(this IFile _, string file, int retryCount = 2, int retryDelay = 500, Func<Exception, int, bool>? errorAction = null)
{
if (file == null)
Expand Down Expand Up @@ -233,6 +231,61 @@ public static void DeleteWithRetry(this IFile _, string file, int retryCount = 2
});
}

/// <summary>
/// Tries to delete a file.
/// </summary>
/// <param name="file">The file to delete.</param>
/// <param name="retryCount">Number of retry attempts tempts until the operation fails.</param>
/// <param name="retryDelay">Delay time in ms between each new attempt.</param>
/// <param name="errorAction">Callback which gets always triggered if an attempt failed.</param>
/// <returns><see langword="true"/> if the file is successfully deleted; otherwise, <see langword="false"/>.</returns>
public static bool TryDeleteWithRetry(this IFileInfo file, int retryCount = 2, int retryDelay = 500, Func<Exception, int, bool>? errorAction = null)
{
if (file == null)
throw new ArgumentNullException(nameof(file));

return file.FileSystem.File.TryDeleteWithRetry(file.FullName, retryCount, retryDelay, errorAction);
}

/// <summary>
/// Tries to delete a file.
/// </summary>
/// <param name="_"></param>
/// <param name="file">The file to delete.</param>
/// <param name="retryCount">Number of retry attempts tempts until the operation fails.</param>
/// <param name="retryDelay">Delay time in ms between each new attempt.</param>
/// <param name="errorAction">Callback which gets always triggered if an attempt failed.</param>
/// <returns><see langword="true"/> if the file is successfully deleted; otherwise, <see langword="false"/>.</returns>
public static bool TryDeleteWithRetry(this IFile _, string file, int retryCount = 2, int retryDelay = 500, Func<Exception, int, bool>? errorAction = null)
{
if (file == null)
throw new ArgumentNullException(nameof(file));

if (!_.Exists(file))
return true;

return FileSystemUtilities.ExecuteFileSystemActionWithRetry(retryCount, retryDelay, () => _.Delete(file), false,
(ex, attempt) =>
{
if (ex is UnauthorizedAccessException)
{
if (attempt == 0)
{
var attributes = _.GetAttributes(file);
if (attributes.HasFlag(FileAttributes.ReadOnly))
{
_.SetAttributes(file, attributes & ~FileAttributes.ReadOnly);
errorAction?.Invoke(ex, attempt);
return true;
}
}
}
errorAction?.Invoke(ex, attempt);
return false;
});
}

/// <summary>
/// Creates a temporary, hidden file which gets deleted once the returned stream is disposed.
/// </summary>
Expand Down
14 changes: 12 additions & 2 deletions src/CommonUtilities.FileSystem/test/DirectoryCopierTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public void Test_CopyDirectory()
.WithFile("test/1.txt").Which(f => f.HasStringContent("1"))
.WithFile("test/2.txt").Which(f => f.HasStringContent("2"))
.WithFile("test/3.txt").Which(f => f.HasStringContent("3"))
.WithFile("test/sub/4.txt").Which(f => f.HasStringContent("4"))
.WithFile("other/3.txt").Which(f => f.HasStringContent("99"));

var copier = new DirectoryCopier(_fileSystem);
Expand All @@ -65,6 +66,7 @@ public void Test_CopyDirectory()
Assert.Equal(1.0, progressValue);

Assert.True(_fileSystem.File.Exists("other/1.txt"));
Assert.True(_fileSystem.File.Exists("other/sub/4.txt"));
Assert.Equal("3", _fileSystem.File.ReadAllText("other/3.txt"));

//fsStream.Dispose();
Expand All @@ -85,6 +87,7 @@ public async Task Test_CopyDirectoryAsync()
.WithFile("test/1.txt").Which(f => f.HasStringContent("1"))
.WithFile("test/2.txt").Which(f => f.HasStringContent("2"))
.WithFile("test/3.txt").Which(f => f.HasStringContent("3"))
.WithFile("test/sub/4.txt").Which(f => f.HasStringContent("4"))
.WithFile("other/3.txt").Which(f => f.HasStringContent("99"));

var copier = new DirectoryCopier(_fileSystem);
Expand All @@ -102,6 +105,7 @@ public async Task Test_CopyDirectoryAsync()
Assert.Equal(1.0, progressValue);

Assert.True(_fileSystem.File.Exists("other/1.txt"));
Assert.True(_fileSystem.File.Exists("other/sub/4.txt"));
Assert.Equal("3", _fileSystem.File.ReadAllText("other/3.txt"));

//fsStream.Dispose();
Expand All @@ -121,6 +125,7 @@ public void Test_MoveDirectory()
.WithFile("test/1.txt").Which(f => f.HasStringContent("1"))
.WithFile("test/2.txt").Which(f => f.HasStringContent("2"))
.WithFile("test/3.txt").Which(f => f.HasStringContent("3"))
.WithFile("test/sub/4.txt").Which(f => f.HasStringContent("4"))
.WithFile("other/3.txt").Which(f => f.HasStringContent("99"));

var copier = new DirectoryCopier(_fileSystem);
Expand All @@ -136,9 +141,10 @@ public void Test_MoveDirectory()
Assert.True(delSuc);
Assert.False(_fileSystem.Directory.Exists("test"));

var destinationFiles = _fileSystem.Directory.GetFiles("other");
Assert.Equal(2, destinationFiles.Length);
var destinationFiles = _fileSystem.Directory.GetFiles("other", "*", SearchOption.AllDirectories);
Assert.Equal(3, destinationFiles.Length);
Assert.True(_fileSystem.File.Exists("other/1.txt"));
Assert.True(_fileSystem.File.Exists("other/sub/4.txt"));
Assert.Equal("3", _fileSystem.File.ReadAllText("other/3.txt"));
return;

Expand All @@ -156,6 +162,7 @@ public void Test_MoveDirectory_CannotDeleteSource()
.WithFile("test/1.txt").Which(f => f.HasStringContent("1"))
.WithFile("test/2.txt").Which(f => f.HasStringContent("2"))
.WithFile("test/3.txt").Which(f => f.HasStringContent("3"))
.WithFile("test/sub/4.txt").Which(f => f.HasStringContent("4"))
.WithFile("other/3.txt").Which(f => f.HasStringContent("99"));

var copier = new DirectoryCopier(_fileSystem);
Expand All @@ -175,6 +182,7 @@ public void Test_MoveDirectory_CannotDeleteSource()

Assert.True(_fileSystem.File.Exists("other/1.txt"));
Assert.True(_fileSystem.File.Exists("other/2.txt"));
Assert.True(_fileSystem.File.Exists("other/sub/4.txt"));
Assert.Equal("3", _fileSystem.File.ReadAllText("other/3.txt"));

fs.Dispose();
Expand All @@ -187,6 +195,7 @@ public async Task Test_MoveDirectoryAsync()
.WithFile("test/1.txt").Which(f => f.HasStringContent("1"))
.WithFile("test/2.txt").Which(f => f.HasStringContent("2"))
.WithFile("test/3.txt").Which(f => f.HasStringContent("3"))
.WithFile("test/sub/4.txt").Which(f => f.HasStringContent("4"))
.WithFile("other/3.txt").Which(f => f.HasStringContent("99"));

var copier = new DirectoryCopier(_fileSystem);
Expand All @@ -205,6 +214,7 @@ public async Task Test_MoveDirectoryAsync()

Assert.True(_fileSystem.File.Exists("other/1.txt"));
Assert.True(_fileSystem.File.Exists("other/2.txt"));
Assert.True(_fileSystem.File.Exists("other/sub/4.txt"));
Assert.Equal("3", _fileSystem.File.ReadAllText("other/3.txt"));
}

Expand Down
Loading

0 comments on commit 6d3665b

Please sign in to comment.