diff --git a/src/PhotoArchiver.Console/Logging/FileLoggerProvider.cs b/src/PhotoArchiver.Console/Logging/FileLoggerProvider.cs index 709e166..e9f91cd 100644 --- a/src/PhotoArchiver.Console/Logging/FileLoggerProvider.cs +++ b/src/PhotoArchiver.Console/Logging/FileLoggerProvider.cs @@ -1,6 +1,7 @@ using Microsoft.Extensions.Logging; using System; using System.IO; +using System.Threading; namespace PhotoArchiver.Logging; @@ -31,16 +32,11 @@ public ILogger CreateLogger(string categoryName) public void Dispose() { } - private sealed class FileLogger : ILogger + private sealed class FileLogger(string fileName) : ILogger { - public FileLogger(string fileName) - { - FileName = fileName; - } - - public string FileName { get; } + public string FileName { get; } = fileName; - private static readonly object SyncRoot = new(); + private static readonly Lock SyncRoot = new(); private static readonly IDisposable Scope = new NullScope(); diff --git a/src/PhotoArchiver.Console/Progress/WindowsTaskbarProgressIndicator.cs b/src/PhotoArchiver.Console/Progress/WindowsTaskbarProgressIndicator.cs index f867995..4618529 100644 --- a/src/PhotoArchiver.Console/Progress/WindowsTaskbarProgressIndicator.cs +++ b/src/PhotoArchiver.Console/Progress/WindowsTaskbarProgressIndicator.cs @@ -25,15 +25,8 @@ public WindowsTaskbarProgressIndicator() public void Initialize(long allBytes, long allItems) { - if (allBytes < 0) - { - throw new ArgumentOutOfRangeException(nameof(allBytes)); - } - - if (allItems < 0) - { - throw new ArgumentOutOfRangeException(nameof(allItems)); - } + ArgumentOutOfRangeException.ThrowIfNegative(allBytes); + ArgumentOutOfRangeException.ThrowIfNegative(allItems); AllBytes = allBytes; TaskbarProgress.SetState(WindowHandle, TaskbarProgress.TaskbarStates.Normal); @@ -46,10 +39,7 @@ public void ToIndeterminateState() public void SetBytesProgress(long processed) { - if (processed < 0) - { - throw new ArgumentOutOfRangeException(nameof(processed)); - } + ArgumentOutOfRangeException.ThrowIfNegative(processed); if (processed > AllBytes) { diff --git a/src/PhotoArchiver/Archiver.Download.cs b/src/PhotoArchiver/Archiver.Download.cs index 4185064..001e796 100644 --- a/src/PhotoArchiver/Archiver.Download.cs +++ b/src/PhotoArchiver/Archiver.Download.cs @@ -216,7 +216,7 @@ private async Task DownloadCoreAsync(IFile file, BlobItem blob, // compute downloaded file hash using var verifyStream = await file.OpenReadAsync(cancellationToken); using var hashAlgorithm = MD5.Create(); - var hash = hashAlgorithm.ComputeHash(verifyStream); + var hash = await hashAlgorithm.ComputeHashAsync(verifyStream, cancellationToken); // compare if (!blobHash.AsSpan().SequenceEqual(hash)) @@ -243,7 +243,7 @@ private async Task DownloadCoreAsync(IFile file, BlobItem blob, private static bool Match(BlobItem blob, DownloadOptions options) { - if (options.Tags?.Any() ?? false) + if (options.Tags?.Count > 0) { if (blob.Metadata.TryGetValue("Tags", out var tags)) { @@ -255,7 +255,7 @@ private static bool Match(BlobItem blob, DownloadOptions options) } } - if (options.People?.Any() ?? false) + if (options.People?.Count > 0) { if (blob.Metadata.TryGetValue("People", out var people)) { diff --git a/src/PhotoArchiver/Archiver.Upload.cs b/src/PhotoArchiver/Archiver.Upload.cs index 478ac8e..b5e7789 100644 --- a/src/PhotoArchiver/Archiver.Upload.cs +++ b/src/PhotoArchiver/Archiver.Upload.cs @@ -20,7 +20,6 @@ namespace PhotoArchiver; using Progress; using Storage; -using System.Threading; using Thumbnails; using Upload; @@ -28,12 +27,17 @@ public partial class Archiver { public async Task ArchiveAsync(IDirectory directory, IProgressIndicator progressIndicator, CancellationToken cancellationToken) { + var files = directory.GetFilesAsync(cancellationToken); + var query = files; + // set up filter - var matcher = new Matcher().AddInclude(Options.SearchPattern); - var files = await directory.GetFilesAsync(cancellationToken); + if (Options.SearchPattern != null) + { + var matcher = new Matcher().AddInclude(Options.SearchPattern); + query = query.Where(f => matcher.Match(directory.Path, f.Path).HasMatches); + } - var query = files.Where(f => matcher.Match(directory.Path, f.Path).HasMatches) - .OrderBy(f => f.Path) + query = query.OrderBy(f => f.Path) .Where(f => !IgnoredFileNames.Contains(f.Name)) .Where(f => !IgnoredExtensions.Contains(f.GetExtension())); @@ -47,7 +51,7 @@ public async Task ArchiveAsync(IDirectory directory, IProgressInd query = query.Take(Options.Take.Value); } - return await ArchiveAsync(query.ToList(), progressIndicator, cancellationToken); + return await ArchiveAsync(await query.ToListAsync(cancellationToken), progressIndicator, cancellationToken); } [SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "")] @@ -66,7 +70,9 @@ public async Task ArchiveAsync(IReadOnlyList files, IProgr var processedBytes = 0L; var allBytes = 0L; foreach (var f in files) + { allBytes += await f.GetSizeAsync(cancellationToken); + } // enumerate files in directory progressIndicator.Initialize(allBytes, files.Count); @@ -349,10 +355,10 @@ public async Task ArchiveAsync(IReadOnlyList files, IProgr // check for exists Logger.LogTrace($"Checking for {blob} exists..."); CostEstimator.AddOther(); - if (await blob.ExistsAsync()) + if (await blob.ExistsAsync(cancellationToken)) { Logger.LogTrace($"Fetching attributes for {blob}..."); - var properties = (await blob.GetPropertiesAsync()).Value; + var properties = (await blob.GetPropertiesAsync(cancellationToken: cancellationToken)).Value; CostEstimator.AddOther(); // compare file size diff --git a/src/PhotoArchiver/Files/IDirectory.cs b/src/PhotoArchiver/Files/IDirectory.cs index 8d0503e..35b36cc 100644 --- a/src/PhotoArchiver/Files/IDirectory.cs +++ b/src/PhotoArchiver/Files/IDirectory.cs @@ -6,7 +6,7 @@ public interface IDirectory string Path { get; } - Task> GetFilesAsync(CancellationToken cancellationToken); + IAsyncEnumerable GetFilesAsync(CancellationToken cancellationToken); Task GetFileAsync(string name, CancellationToken cancellationToken); diff --git a/src/PhotoArchiver/Files/SystemIODirectory.cs b/src/PhotoArchiver/Files/SystemIODirectory.cs index 0e83adc..b116284 100644 --- a/src/PhotoArchiver/Files/SystemIODirectory.cs +++ b/src/PhotoArchiver/Files/SystemIODirectory.cs @@ -1,4 +1,6 @@ -namespace PhotoArchiver.Files; +using System.Runtime.CompilerServices; + +namespace PhotoArchiver.Files; public class SystemIODirectory : IDirectory { @@ -31,8 +33,13 @@ public Task GetFileAsync(string name, CancellationToken cancellationToken return Task.FromResult(new SystemIOFile(new FileInfo(System.IO.Path.Combine(Directory.FullName, name))) as IFile); } - public Task> GetFilesAsync(CancellationToken cancellationToken) +#pragma warning disable CS1998 + public async IAsyncEnumerable GetFilesAsync([EnumeratorCancellation] CancellationToken cancellationToken) { - return Task.FromResult(Directory.GetFiles("*", SearchOption.AllDirectories).Select(f => new SystemIOFile(f)).ToList() as IReadOnlyList); + foreach (var fileInfo in Directory.GetFiles("*", SearchOption.AllDirectories)) + { + yield return new SystemIOFile(fileInfo); + } } +#pragma warning restore CS1998 } diff --git a/src/PhotoArchiver/Progress/StorageProgressShim.cs b/src/PhotoArchiver/Progress/StorageProgressShim.cs index a49e2bd..67fb7af 100644 --- a/src/PhotoArchiver/Progress/StorageProgressShim.cs +++ b/src/PhotoArchiver/Progress/StorageProgressShim.cs @@ -1,18 +1,9 @@ namespace PhotoArchiver.Progress; -public sealed class StorageProgressShim : IProgress +public sealed record StorageProgressShim(IProgressIndicator ProgressIndicator, long SnapshotBytes) : IProgress { - public StorageProgressShim(IProgressIndicator progressIndicator, long snaphotBytes) - { - ProgressIndicator = progressIndicator; - SnaphotBytes = snaphotBytes; - } - - public IProgressIndicator ProgressIndicator { get; } - public long SnaphotBytes { get; } - public void Report(long value) { - ProgressIndicator.SetBytesProgress(SnaphotBytes + value); + ProgressIndicator.SetBytesProgress(SnapshotBytes + value); } } diff --git a/src/PhotoArchiver/Thumbnails/ThumbnailOptions.cs b/src/PhotoArchiver/Thumbnails/ThumbnailOptions.cs index 4ff7d8d..aec3ff3 100644 --- a/src/PhotoArchiver/Thumbnails/ThumbnailOptions.cs +++ b/src/PhotoArchiver/Thumbnails/ThumbnailOptions.cs @@ -16,7 +16,7 @@ public class ThumbnailOptions public bool Force { get; set; } = false; - public bool IsEnabled() => MaxWidth != null && MaxHeight != null; + public bool IsEnabled() => this is { MaxHeight: > 0, MaxWidth: > 0 }; [SuppressMessage("Usage", "CA2208:Instantiate argument exceptions correctly", Justification = "")] diff --git a/src/PhotoArchiver/Upload/UploadResult.cs b/src/PhotoArchiver/Upload/UploadResult.cs index 86374d1..13a2f18 100644 --- a/src/PhotoArchiver/Upload/UploadResult.cs +++ b/src/PhotoArchiver/Upload/UploadResult.cs @@ -11,5 +11,5 @@ public enum UploadResult public static partial class UploadResultExtensions { - public static bool IsSuccessful(this UploadResult result) => result == UploadResult.Uploaded || result == UploadResult.AlreadyExists; + public static bool IsSuccessful(this UploadResult result) => result is UploadResult.Uploaded or UploadResult.AlreadyExists; }