2 using System.Collections.Generic;
4 using System.IO.Compression;
8 using System.Threading.Tasks;
20 public const string CurrentDirectory =
".";
25 public const int DefaultBufferSize = 4096;
35 var tasks =
new List<Task>();
38 if (!dir.Attributes.HasFlag(FileAttributes.Directory) || dir.Attributes.HasFlag(FileAttributes.ReparsePoint))
44 foreach (var subDir
in dir.EnumerateDirectories())
46 cancellationToken.ThrowIfCancellationRequested();
47 tasks.Add(NormalizeAndDelete(subDir, cancellationToken));
50 foreach (var file
in dir.EnumerateFiles())
52 cancellationToken.ThrowIfCancellationRequested();
53 file.Attributes = FileAttributes.Normal;
57 await Task.WhenAll(tasks).ConfigureAwait(
false);
58 cancellationToken.ThrowIfCancellationRequested();
67 static FileStream OpenWriteStream(
string path) =>
new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize,
true);
77 IEnumerable<Task>
CopyDirectoryImpl(
string src,
string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
79 var dir =
new DirectoryInfo(src);
80 var atLeastOneSubDir =
false;
81 foreach (var I
in dir.EnumerateDirectories())
83 if (ignore != null && ignore.Contains(I.Name))
85 foreach (var J
in CopyDirectoryImpl(I.FullName, Path.Combine(dest, I.Name), null, cancellationToken))
87 atLeastOneSubDir =
true;
92 async Task CopyThisDirectory()
94 if (!atLeastOneSubDir)
95 await CreateDirectory(dest, cancellationToken).ConfigureAwait(
false);
97 var tasks =
new List<Task>();
99 await dir.EnumerateFiles().ToAsyncEnumerable().ForEachAsync(fileInfo =>
101 if (ignore != null && ignore.Contains(fileInfo.Name))
103 tasks.Add(CopyFile(fileInfo.FullName, Path.Combine(dest, fileInfo.Name), cancellationToken));
104 }).ConfigureAwait(
false);
106 await Task.WhenAll(tasks).ConfigureAwait(
false);
109 yield
return CopyThisDirectory();
113 public async Task
CopyDirectory(
string src,
string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
116 throw new ArgumentNullException(nameof(src));
118 throw new ArgumentNullException(nameof(src));
120 src = ResolvePath(src);
121 dest = ResolvePath(dest);
122 foreach (var directoryCopy
in CopyDirectoryImpl(src, dest, ignore, cancellationToken))
123 await directoryCopy.ConfigureAwait(
false);
130 throw new ArgumentNullException(nameof(paths));
131 return Path.Combine(paths);
135 public async Task
CopyFile(
string src,
string dest, CancellationToken cancellationToken)
138 throw new ArgumentNullException(nameof(src));
140 throw new ArgumentNullException(nameof(dest));
141 using var srcStream =
new FileStream(ResolvePath(src), FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize,
true);
142 using var destStream =
new FileStream(ResolvePath(dest), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize,
true);
143 await srcStream.CopyToAsync(destStream, 81920, cancellationToken).ConfigureAwait(
false);
147 public Task CreateDirectory(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.CreateDirectory(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
152 path = ResolvePath(path);
153 var di =
new DirectoryInfo(path);
155 return Task.CompletedTask;
157 return Task.Factory.StartNew(
158 () => NormalizeAndDelete(di, cancellationToken),
160 TaskCreationOptions.LongRunning,
161 TaskScheduler.Current);
165 public Task DeleteFile(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Delete(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
168 public Task<bool> FileExists(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
171 public Task<bool> DirectoryExists(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
174 public string GetDirectoryName(
string path) => Path.GetDirectoryName(path ??
throw new ArgumentNullException(nameof(path)));
177 public string GetFileName(
string path) => Path.GetFileName(path ??
throw new ArgumentNullException(nameof(path)));
180 public string GetFileNameWithoutExtension(
string path) => Path.GetFileNameWithoutExtension(path ??
throw new ArgumentNullException(nameof(path)));
183 public Task<List<string>> GetFilesWithExtension(
string path,
string extension,
bool recursive, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
185 path = ResolvePath(path);
186 if (extension == null)
187 throw new ArgumentNullException(extension);
188 var results =
new List<string>();
189 foreach (var I
in Directory.EnumerateFiles(
192 recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
194 cancellationToken.ThrowIfCancellationRequested();
199 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
202 public Task MoveFile(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
204 if (destination == null)
205 throw new ArgumentNullException(nameof(destination));
206 source = ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
207 destination = ResolvePath(destination);
208 File.Move(source, destination);
209 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
212 public Task MoveDirectory(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
214 if (destination == null)
215 throw new ArgumentNullException(nameof(destination));
216 source = ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
217 destination = ResolvePath(destination);
218 Directory.Move(source, destination);
219 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
222 public async Task<byte[]>
ReadAllBytes(
string path, CancellationToken cancellationToken)
224 path = ResolvePath(path);
225 using var file =
new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize,
true);
227 buf =
new byte[file.Length];
228 await file.ReadAsync(buf, 0, (
int)file.Length, cancellationToken).ConfigureAwait(
false);
233 public string ResolvePath() => ResolvePath(CurrentDirectory);
236 public virtual string ResolvePath(
string path) => Path.GetFullPath(path ??
throw new ArgumentNullException(nameof(path)));
239 public async Task
WriteAllBytes(
string path, byte[] contents, CancellationToken cancellationToken)
241 path = ResolvePath(path);
242 using var file = OpenWriteStream(path);
243 await file.WriteAsync(contents, 0, contents.Length, cancellationToken).ConfigureAwait(
false);
247 public Task<IReadOnlyList<string>> GetDirectories(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
249 path = ResolvePath(path);
250 var results =
new List<string>();
251 cancellationToken.ThrowIfCancellationRequested();
252 foreach (var I
in Directory.EnumerateDirectories(path))
255 cancellationToken.ThrowIfCancellationRequested();
258 return (IReadOnlyList<string>)results;
259 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
262 public Task<IReadOnlyList<string>> GetFiles(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
264 path = ResolvePath(path);
265 var results =
new List<string>();
266 cancellationToken.ThrowIfCancellationRequested();
267 foreach (var I
in Directory.EnumerateFiles(path))
270 cancellationToken.ThrowIfCancellationRequested();
273 return (IReadOnlyList<string>)results;
274 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
277 public async Task<byte[]>
DownloadFile(Uri url, CancellationToken cancellationToken)
280 using var wc =
new WebClient();
281 var tcs =
new TaskCompletionSource<byte[]>();
282 wc.DownloadDataCompleted += (a, b) =>
285 tcs.TrySetException(b.Error);
286 else if (b.Cancelled)
287 tcs.TrySetCanceled();
289 tcs.TrySetResult(b.Result);
291 wc.DownloadDataAsync(url);
292 using (cancellationToken.Register(() =>
295 tcs.TrySetCanceled();
297 return await tcs.Task.ConfigureAwait(
false);
301 public Task ZipToDirectory(
string path, byte[] zipFileBytes, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
303 path = ResolvePath(path);
304 if (zipFileBytes == null)
305 throw new ArgumentNullException(nameof(zipFileBytes));
307 using var ms =
new MemoryStream(zipFileBytes);
308 using var archive =
new ZipArchive(ms, ZipArchiveMode.Read);
309 archive.ExtractToDirectory(path);
310 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
313 public bool PathContainsParentAccess(
string path) => path?.Split(
new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }).Any(x => x ==
"..") ??
throw new ArgumentNullException(nameof(path));
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
string ConcatPath(params string[] paths)
Combines an array of strings into a path
Use server authentication
async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest
static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
Recursively empty a directory
async Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
async Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
IIOManager that resolves paths to Environment.CurrentDirectory
Interface for using filesystems