Index: pkg/http/test/utils.dart |
diff --git a/pkg/http/test/utils.dart b/pkg/http/test/utils.dart |
index 6bbe139a7adbc856d7ec3b1b9603f67a225342c3..15909782edc5d39ca1d5a8a9d492e74d746c21d1 100644 |
--- a/pkg/http/test/utils.dart |
+++ b/pkg/http/test/utils.dart |
@@ -138,6 +138,41 @@ String cleanUpLiteral(String text) { |
return lines.join('\n'); |
} |
+// TODO(nweiz): Remove this when issue 9252 is fixed. |
+/// Asynchronously recursively deletes [dir]. Returns a [Future] that completes |
+/// when the deletion is done. |
+Future deleteDir(String dir) => |
+ _attemptRetryable(() => new Directory(dir).delete(recursive: true)); |
+ |
+/// On Windows, we sometimes get failures where the directory is still in use |
+/// when we try to do something with it. This is usually because the OS hasn't |
+/// noticed yet that a process using that directory has closed. To be a bit |
+/// more resilient, we wait and retry a few times. |
+/// |
+/// Takes a [callback] which returns a future for the operation being attempted. |
+/// If that future completes with an error, it will slepp and then [callback] |
+/// will be invoked again to retry the operation. It will try a few times before |
+/// giving up. |
+Future _attemptRetryable(Future callback()) { |
+ // Only do lame retry logic on Windows. |
+ if (Platform.operatingSystem != 'windows') return callback(); |
+ |
+ var attempts = 0; |
+ makeAttempt(_) { |
+ attempts++; |
+ return callback().catchError((e) { |
+ if (attempts >= 10) { |
+ throw 'Could not complete operation. Gave up after $attempts attempts.'; |
+ } |
+ |
+ return new Future.delayed(new Duration(milliseconds: 500)) |
+ .then(makeAttempt); |
+ }); |
+ } |
+ |
+ return makeAttempt(null); |
+} |
+ |
/// A matcher that matches JSON that parses to a value that matches the inner |
/// matcher. |
Matcher parse(matcher) => new _Parse(matcher); |