2using System.Collections.Generic;
4using System.IO.Compression;
7using System.Threading.Tasks;
41 cancellationToken.ThrowIfCancellationRequested();
44 if (!dir.Attributes.HasFlag(FileAttributes.Directory) || dir.Attributes.HasFlag(FileAttributes.ReparsePoint))
50 foreach (var subDir
in dir.EnumerateDirectories())
53 foreach (var file
in dir.EnumerateFiles())
55 cancellationToken.ThrowIfCancellationRequested();
58 file.Attributes = FileAttributes.Normal;
61 catch (FileNotFoundException)
67 cancellationToken.ThrowIfCancellationRequested();
73 IEnumerable<string> ignore,
74 Func<string, string, Task> postCopyCallback,
78 CancellationToken cancellationToken)
80 ArgumentNullException.ThrowIfNull(src);
81 ArgumentNullException.ThrowIfNull(src);
83 if (taskThrottle.HasValue && taskThrottle < 1)
84 throw new ArgumentOutOfRangeException(nameof(taskThrottle), taskThrottle,
"taskThrottle must be at least 1!");
89 using var semaphore = taskThrottle.HasValue ?
new SemaphoreSlim(taskThrottle.Value) :
null;
90 await Task.WhenAll(
CopyDirectoryImpl(src, dest, ignore, postCopyCallback, semaphore, cancellationToken));
94 public string ConcatPath(params
string[] paths) => Path.Combine(paths);
97 public async Task
CopyFile(
string src,
string dest, CancellationToken cancellationToken)
99 ArgumentNullException.ThrowIfNull(src);
100 ArgumentNullException.ThrowIfNull(dest);
103 await
using var srcStream =
new FileStream(
107 FileShare.Read | FileShare.Delete,
109 FileOptions.Asynchronous | FileOptions.SequentialScan);
113 await srcStream.CopyToAsync(destStream, 81920, cancellationToken);
123 var di =
new DirectoryInfo(path);
125 return Task.CompletedTask;
127 return Task.Factory.StartNew(
131 TaskScheduler.Current);
144 public string GetDirectoryName(
string path) => Path.GetDirectoryName(path ??
throw new ArgumentNullException(nameof(path)));
147 public string GetFileName(
string path) => Path.GetFileName(path ??
throw new ArgumentNullException(nameof(path)));
150 public string GetFileNameWithoutExtension(
string path) => Path.GetFileNameWithoutExtension(path ??
throw new ArgumentNullException(nameof(path)));
153 public Task<List<string>>
GetFilesWithExtension(
string path,
string extension,
bool recursive, CancellationToken cancellationToken) => Task.Factory.StartNew(
157 if (extension ==
null)
158 throw new ArgumentNullException(extension);
159 var results =
new List<string>();
160 foreach (var fileName
in Directory.EnumerateFiles(
163 recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
165 cancellationToken.ThrowIfCancellationRequested();
166 results.Add(fileName);
173 TaskScheduler.Current);
176 public Task
MoveFile(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(
179 ArgumentNullException.ThrowIfNull(destination);
180 source =
ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
182 File.Move(source, destination);
186 TaskScheduler.Current);
189 public Task
MoveDirectory(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(
192 ArgumentNullException.ThrowIfNull(destination);
193 source =
ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
195 Directory.Move(source, destination);
199 TaskScheduler.Current);
202 public async Task<byte[]>
ReadAllBytes(
string path, CancellationToken cancellationToken)
205 await
using var file =
new FileStream(
209 FileShare.ReadWrite | FileShare.Delete,
211 FileOptions.Asynchronous | FileOptions.SequentialScan);
213 buf =
new byte[file.Length];
214 await file.ReadAsync(buf, cancellationToken);
222 public virtual string ResolvePath(
string path) => Path.GetFullPath(path ??
throw new ArgumentNullException(nameof(path)));
225 public async Task
WriteAllBytes(
string path,
byte[] contents, CancellationToken cancellationToken)
228 await file.WriteAsync(contents, cancellationToken);
235 return new FileStream(
239 FileShare.Read | FileShare.Delete,
241 FileOptions.Asynchronous | FileOptions.SequentialScan);
245 public Task<IReadOnlyList<string>>
GetDirectories(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(
249 var results =
new List<string>();
250 cancellationToken.ThrowIfCancellationRequested();
251 foreach (var directoryName
in Directory.EnumerateDirectories(path))
253 results.Add(directoryName);
254 cancellationToken.ThrowIfCancellationRequested();
257 return (IReadOnlyList<string>)results;
261 TaskScheduler.Current);
264 public Task<IReadOnlyList<string>>
GetFiles(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(
268 var results =
new List<string>();
269 cancellationToken.ThrowIfCancellationRequested();
270 foreach (var fileName
in Directory.EnumerateFiles(path))
272 results.Add(fileName);
273 cancellationToken.ThrowIfCancellationRequested();
276 return (IReadOnlyList<string>)results;
280 TaskScheduler.Current);
283 public Task
ZipToDirectory(
string path,
Stream zipFile, CancellationToken cancellationToken) => Task.Factory.StartNew(
287 ArgumentNullException.ThrowIfNull(zipFile);
290#warning Check if zip file seeking has been addressesed. See https:
294 if (!zipFile.CanSeek)
295 throw new ArgumentException(
"Stream does not support seeking!", nameof(zipFile));
297 using var archive =
new ZipArchive(zipFile, ZipArchiveMode.Read,
true);
298 archive.ExtractToDirectory(path);
302 TaskScheduler.Current);
309 Path.DirectorySeparatorChar,
310 Path.AltDirectorySeparatorChar,
313 ??
throw new ArgumentNullException(nameof(path));
316 public Task<DateTimeOffset>
GetLastModified(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(
319 path =
ResolvePath(path ??
throw new ArgumentNullException(nameof(path)));
320 var fileInfo =
new FileInfo(path);
321 return new DateTimeOffset(fileInfo.LastWriteTimeUtc);
325 TaskScheduler.Current);
332 FileShare.Read | FileShare.Delete | (shareWrite ? FileShare.Write : FileShare.None),
349 IEnumerable<string> ignore,
350 Func<string, string, Task> postCopyCallback,
351 SemaphoreSlim semaphore,
352 CancellationToken cancellationToken)
354 var dir =
new DirectoryInfo(src);
355 Task subdirCreationTask =
null;
356 foreach (var subDirectory
in dir.EnumerateDirectories())
358 if (ignore !=
null && ignore.Contains(subDirectory.Name))
361 var checkingSubdirCreationTask =
true;
362 foreach (var copyTask
in CopyDirectoryImpl(subDirectory.FullName, Path.Combine(dest, subDirectory.Name),
null, postCopyCallback, semaphore, cancellationToken))
364 if (subdirCreationTask ==
null)
366 subdirCreationTask = copyTask;
367 yield
return subdirCreationTask;
369 else if (!checkingSubdirCreationTask)
370 yield
return copyTask;
372 checkingSubdirCreationTask =
false;
376 foreach (var fileInfo
in dir.EnumerateFiles())
378 if (subdirCreationTask ==
null)
381 yield
return subdirCreationTask;
384 if (ignore !=
null && ignore.Contains(fileInfo.Name))
387 var sourceFile = fileInfo.FullName;
388 var destFile =
ConcatPath(dest, fileInfo.Name);
390 async Task CopyThisFile()
392 await subdirCreationTask.WithToken(cancellationToken);
393 using var lockContext = semaphore !=
null
396 await
CopyFile(sourceFile, destFile, cancellationToken);
397 if (postCopyCallback !=
null)
398 await postCopyCallback(sourceFile, destFile);
401 yield
return CopyThisFile();
IIOManager that resolves paths to Environment.CurrentDirectory.
async Task CopyDirectory(IEnumerable< string > ignore, Func< string, string, Task > postCopyCallback, string src, string dest, int? taskThrottle, CancellationToken cancellationToken)
Copies a directory from src to dest . A Task representing the running operation.
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd....
virtual string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
Task MoveFile(string source, string destination, CancellationToken cancellationToken)
Moves a file at source to destination . A Task representing the running operation.
string ResolvePath()
Retrieve the full path of the current working directory. The full path of the current working directo...
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path . A Task representing the running operation.
FileStream CreateAsyncSequentialWriteStream(string path)
Creates an asynchronous FileStream for sequential writing. The open FileStream.
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path . A Task<TResult> resulting in the directories in path .
Task< List< string > > GetFilesWithExtension(string path, string extension, bool recursive, CancellationToken cancellationToken)
Gets a list of files in path with the given extension . A Task resulting in a list of paths to files...
Task< IReadOnlyList< string > > GetFiles(string path, CancellationToken cancellationToken)
Returns file names in a given path . A Task<TResult> resulting in the files in path .
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists. A Task resulting in true if the file at path exists,...
Task MoveDirectory(string source, string destination, CancellationToken cancellationToken)
Moves a directory at source to destination . A Task representing the running operation.
string GetFileNameWithoutExtension(string path)
Gets the file name portion of a path with. The file name portion of path .
Task ZipToDirectory(string path, Stream zipFile, CancellationToken cancellationToken)
Extract a set of zipFile to a given path . A Task representing the running operation.
Task< DateTimeOffset > GetLastModified(string path, CancellationToken cancellationToken)
Get the DateTimeOffset of when a given path was last modified. A Task<TResult> resulting in the Date...
FileStream GetFileStream(string path, bool shareWrite)
Gets the Stream for a given file path . The FileStream of the file.This function is sychronous.
const int DefaultBufferSize
Default FileStream buffer size used by .NET.
const string CurrentDirectory
Path to the current working directory for the IIOManager.
string GetDirectoryName(string path)
Gets the directory portion of a given path . The directory portion of the given path .
bool PathContainsParentAccess(string path)
Check if a path contains the '..' parent directory accessor. true if path contains a '....
string ConcatPath(params string[] paths)
Combines an array of strings into a path. The combined path.
async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest . A Task representing the running operation.
const TaskCreationOptions BlockingTaskCreationOptions
The TaskCreationOptions used to spawn Tasks for potentially long running, blocking operations.
static void NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
Recursively empty a directory.
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array. A Task that results in the contents of a...
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path . A Task representing the running operation.
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, Func< string, string, Task > postCopyCallback, SemaphoreSlim semaphore, CancellationToken cancellationToken)
Copies a directory from src to dest .
string GetFileName(string path)
Gets the file name portion of a path . The file name portion of path .
async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content. A Task representing the runnin...
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists. A Task resulting in true if the directory at path exists,...
Async lock context helper.
static async ValueTask< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore .
Interface for using filesystems.