Skip to content

Commit 3afb175

Browse files
Catch expected exceptions thrown by DirectoryHelper
The DirectoryHelper.DeleteDirectory() method throws exceptions. Affected tests will be reported as FAILED although this happens during cleanup after the test was run. This commit deals with those exceptions by retrying to delete the directory up to four times, which removes directories in all but rare cases. The method catches DirectoryNotFoundException, IOException, and UnauthorizedAccessException and will only log a trace message if it can't finally delete the directory. It will rethrow any other type of exception. Closes libgit2#970.
1 parent a0776fa commit 3afb175

File tree

2 files changed

+43
-20
lines changed

2 files changed

+43
-20
lines changed

LibGit2Sharp.Tests/TestHelpers/BaseFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public string SandboxAssumeUnchangedTestRepo()
156156
{
157157
return Sandbox(AssumeUnchangedRepoWorkingDirPath);
158158
}
159-
159+
160160
public string SandboxSubmoduleSmallTestRepo()
161161
{
162162
var submoduleTarget = Path.Combine(ResourcesDirectory.FullName, "submodule_target_wd");

LibGit2Sharp.Tests/TestHelpers/DirectoryHelper.cs

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Collections.Generic;
33
using System.Diagnostics;
44
using System.IO;
5+
using System.Linq;
6+
using System.Threading;
57

68
namespace LibGit2Sharp.Tests.TestHelpers
79
{
@@ -47,40 +49,61 @@ public static void DeleteDirectory(string directoryPath)
4749

4850
if (!Directory.Exists(directoryPath))
4951
{
50-
Trace.WriteLine(
51-
string.Format("Directory '{0}' is missing and can't be removed.",
52-
directoryPath));
53-
52+
Trace.WriteLine(string.Format("Directory '{0}' is missing and can't be removed.", directoryPath));
5453
return;
5554
}
55+
NormalizeAttributes(directoryPath);
56+
TryDeleteDirectory(directoryPath, 5, 16, 2);
57+
}
5658

59+
private static void NormalizeAttributes(string directoryPath)
60+
{
5761
string[] files = Directory.GetFiles(directoryPath);
5862
string[] dirs = Directory.GetDirectories(directoryPath);
5963

6064
foreach (string file in files)
6165
{
6266
File.SetAttributes(file, FileAttributes.Normal);
63-
File.Delete(file);
6467
}
65-
6668
foreach (string dir in dirs)
6769
{
68-
DeleteDirectory(dir);
70+
NormalizeAttributes(dir);
6971
}
70-
7172
File.SetAttributes(directoryPath, FileAttributes.Normal);
72-
try
73-
{
74-
Directory.Delete(directoryPath, false);
75-
}
76-
catch (IOException)
73+
}
74+
75+
private static Type[] whitelist = new[] { typeof(DirectoryNotFoundException), typeof(IOException), typeof(UnauthorizedAccessException) };
76+
77+
private static void TryDeleteDirectory(string directoryPath, int maxAttempts, int initialTimeout, int timeoutFactor)
78+
{
79+
for (int attempt = 1; attempt <= maxAttempts; attempt++)
7780
{
78-
Trace.WriteLine(string.Format("{0}The directory '{1}' could not be deleted!" +
79-
"{0}Most of the time, this is due to an external process accessing the files in the temporary repositories created during the test runs, and keeping a handle on the directory, thus preventing the deletion of those files." +
80-
"{0}Known and common causes include:" +
81-
"{0}- Windows Search Indexer (go to the Indexing Options, in the Windows Control Panel, and exclude the bin folder of LibGit2Sharp.Tests)" +
82-
"{0}- Antivirus (exclude the bin folder of LibGit2Sharp.Tests from the paths scanned by your real-time antivirus){0}",
83-
Environment.NewLine, Path.GetFullPath(directoryPath)));
81+
try
82+
{
83+
Directory.Delete(directoryPath, true);
84+
return;
85+
}
86+
catch (Exception ex)
87+
{
88+
if (!whitelist.Contains(ex.GetType()))
89+
{
90+
throw;
91+
}
92+
93+
if (attempt < maxAttempts)
94+
{
95+
Thread.Sleep(initialTimeout * (int)Math.Pow(timeoutFactor, attempt - 1));
96+
continue;
97+
}
98+
99+
Trace.WriteLine(string.Format("{0}The directory '{1}' could not be deleted due to a {2}: {3}" +
100+
"{0}Most of the time, this is due to an external process accessing the files in the temporary repositories created during the test runs, and keeping a handle on the directory, thus preventing the deletion of those files." +
101+
"{0}Known and common causes include:" +
102+
"{0}- Windows Search Indexer (go to the Indexing Options, in the Windows Control Panel, and exclude the bin folder of LibGit2Sharp.Tests)" +
103+
"{0}- Antivirus (exclude the bin folder of LibGit2Sharp.Tests from the paths scanned by your real-time antivirus)" +
104+
"{0}- TortoiseGit (change the 'Icon Overlays' settings, e.g., adding the bin folder of LibGit2Sharp.Tests to 'Exclude paths' and appending an '*' to exclude all subfolders as well)",
105+
Environment.NewLine, Path.GetFullPath(directoryPath), ex.GetType(), ex.Message));
106+
}
84107
}
85108
}
86109
}

0 commit comments

Comments
 (0)