diff --git a/.github/ci.yml b/.github/ci.yml new file mode 100644 index 0000000..8af4bd2 --- /dev/null +++ b/.github/ci.yml @@ -0,0 +1,53 @@ +name: NET + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + BuildConfig: Release + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + + - name: Cancel previous builds in PR + uses: styfle/cancel-workflow-action@0.12.1 + + - name: 'Checkout Code' + uses: actions/checkout@v4 + with: + fetch-depth: 0 # avoid shallow clone so nbgv can do its work. + + - name: 'Install .NET SDK' + uses: actions/setup-dotnet@v4 + with: + global-json-file: ./global.json + + - name: Versioning + uses: dotnet/nbgv@master + id: nbgv + + - name: Version Info + run: | + echo 'SemVer2: ${{ steps.nbgv.outputs.SemVer2 }}' + + - name: Build with dotnet + run: dotnet build + --configuration ${{ env.BuildConfig }} + /p:Version=${{ steps.nbgv.outputs.AssemblyVersion }} + + - name: Test with dotnet + run: dotnet test + + - name: Pack NuGet + run: dotnet pack + --configuration ${{ env.BuildConfig }} + /p:ContinuousIntegrationBuild=true + /p:Version=${{ steps.nbgv.outputs.NuGetPackageVersion }} \ No newline at end of file diff --git a/Directory.Packages.props b/Directory.Packages.props index 6f78d8a..488d4af 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -21,6 +21,13 @@ + + + all + runtime; build; native; contentfiles; analyzers + + + diff --git a/LICENSE b/LICENSE index 3100cbd..b79461d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -# MIT License +MIT License Copyright (c) 2013-2024 Benjamin Abt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/src/QuickIO/DirectoryAlreadyExistsException.cs b/src/QuickIO/DirectoryAlreadyExistsException.cs index 3de86dd..0933a4a 100644 --- a/src/QuickIO/DirectoryAlreadyExistsException.cs +++ b/src/QuickIO/DirectoryAlreadyExistsException.cs @@ -1,16 +1,23 @@ namespace SchwabenCode.QuickIO; /// -/// This error is raised if you want to create for example a folder which already exists. +/// Represents an exception that is thrown when an operation encounters an existing directory +/// that was expected to be unique or non-existent. /// +/// +/// This exception is typically used in scenarios involving directory creation where +/// a unique directory path is required. It provides detailed information about the conflicting +/// directory path, assisting in error handling and debugging. +/// [Serializable] public class DirectoryAlreadyExistsException : QuickIOBaseException { /// - /// Creates an instance of + /// Initializes a new instance of the class + /// with a specified error message and the directory path that caused the exception. /// - /// Error message - /// Affected directory path + /// The error message that explains the reason for the exception. + /// The directory path that already exists and caused the exception to be thrown. public DirectoryAlreadyExistsException(string message, string path) : base(message, path) { } } diff --git a/src/QuickIO/DirectoryNotEmptyException.cs b/src/QuickIO/DirectoryNotEmptyException.cs index b5aa9c9..5b68ed1 100644 --- a/src/QuickIO/DirectoryNotEmptyException.cs +++ b/src/QuickIO/DirectoryNotEmptyException.cs @@ -1,16 +1,23 @@ namespace SchwabenCode.QuickIO; /// -/// This error is raised if a folder that is not empty should be deleted. +/// Represents an exception that is thrown when an operation fails because a directory +/// that was expected to be empty is not. /// +/// +/// This exception is typically used in scenarios where a directory must be empty +/// for a specific operation to proceed, such as deletion or renaming. It provides detailed +/// information about the non-empty directory path, aiding in error handling and debugging. +/// [Serializable] public class DirectoryNotEmptyException : QuickIOBaseException { /// - /// Creates an instance of + /// Initializes a new instance of the class + /// with a specified error message and the directory path that caused the exception. /// - /// Error message - /// Affected directory path + /// The error message that explains the reason for the exception. + /// The directory path that is not empty and caused the exception to be thrown. public DirectoryNotEmptyException(string message, string path) : base(message, path) { diff --git a/src/QuickIO/FileAlreadyExistsException.cs b/src/QuickIO/FileAlreadyExistsException.cs index 1f8898d..d222e11 100644 --- a/src/QuickIO/FileAlreadyExistsException.cs +++ b/src/QuickIO/FileAlreadyExistsException.cs @@ -3,28 +3,34 @@ namespace SchwabenCode.QuickIO; /// -/// This error is raised if a file should be created that already exists. -/// +/// Represents an exception that is thrown when an operation encounters an existing file +/// that was expected to be unique or non-existent. +/// +/// +/// This exception is typically used in scenarios involving file creation where a unique +/// file path is required. It provides detailed information about the conflicting file path, +/// assisting in error handling and debugging. +/// [Serializable] public class FileAlreadyExistsException : QuickIOBaseException { /// - /// Creates an instance of + /// Initializes a new instance of the class + /// with the file path that caused the exception. The error message is automatically + /// generated based on the Win32 error code for "file already exists." /// - /// Affected file path + /// The file path that already exists and caused the exception to be thrown. public FileAlreadyExistsException(string path) : base(Win32ErrorCodes.FormatMessage(Win32ErrorCodes.ERROR_ALREADY_EXISTS), path) - { - } + { } /// - /// Creates an instance of + /// Initializes a new instance of the class + /// with a specified error message and the file path that caused the exception. /// - /// Error message - /// Affected file path + /// The error message that explains the reason for the exception. + /// The file path that already exists and caused the exception to be thrown. public FileAlreadyExistsException(string message, string path) : base(message, path) - { - } + { } } - diff --git a/src/QuickIO/FileSystemIsBusyException.cs b/src/QuickIO/FileSystemIsBusyException.cs index 29c5e4b..8406306 100644 --- a/src/QuickIO/FileSystemIsBusyException.cs +++ b/src/QuickIO/FileSystemIsBusyException.cs @@ -1,16 +1,21 @@ namespace SchwabenCode.QuickIO; /// -/// This error is raised if file system is busy and further operations are not able to execute +/// Represents an exception that is thrown when a file system operation fails because the target file or directory is currently in use or locked by another process. /// +/// +/// This exception is typically used in scenarios where operations like deleting, moving, or modifying files and directories cannot be completed +/// because they are being accessed by other processes. It provides detailed information about the busy path, aiding in error handling and debugging. +/// [Serializable] public class FileSystemIsBusyException : QuickIOBaseException { /// - /// Creates an instance of + /// Initializes a new instance of the class + /// with a specified error message and the path that caused the exception. /// - /// Error message - /// Affected directory path + /// The error message that explains the reason for the exception. + /// The file or directory path that is currently in use and caused the exception to be thrown. public FileSystemIsBusyException(string message, string path) : base(message, path) { diff --git a/src/QuickIO/InvalidPathException.cs b/src/QuickIO/InvalidPathException.cs index e4d4e0f..0bbfac4 100644 --- a/src/QuickIO/InvalidPathException.cs +++ b/src/QuickIO/InvalidPathException.cs @@ -3,25 +3,33 @@ namespace SchwabenCode.QuickIO; /// -/// Invalid Path Exception +/// Represents an exception that is thrown when a provided file or directory path is invalid. /// +/// +/// This exception is typically used in scenarios where a path does not conform to the expected format, +/// such as containing illegal characters or being otherwise malformed. It provides detailed information +/// about the invalid path, assisting in error handling and debugging. +/// [Serializable] public class InvalidPathException : QuickIOBaseException { /// - /// Invalid Path Exception + /// Initializes a new instance of the class + /// with the path that caused the exception. The error message is automatically generated + /// based on the Win32 error code for "invalid name." /// - /// Invalid Path + /// The file or directory path that is invalid and caused the exception to be thrown. public InvalidPathException(string path) : base(Win32ErrorCodes.FormatMessage(Win32ErrorCodes.ERROR_INVALID_NAME), path) { } /// - /// Invalid Path Exception + /// Initializes a new instance of the class + /// with a specified error message and the path that caused the exception. /// - /// Error Message - /// Invalid Path + /// The error message that explains the reason for the exception. + /// The file or directory path that is invalid and caused the exception to be thrown. public InvalidPathException(string message, string path) : base(message, path) { diff --git a/src/QuickIO/PathAlreadyExistsException.cs b/src/QuickIO/PathAlreadyExistsException.cs index e4cd848..30debef 100644 --- a/src/QuickIO/PathAlreadyExistsException.cs +++ b/src/QuickIO/PathAlreadyExistsException.cs @@ -1,20 +1,24 @@ -using System.Diagnostics.Contracts; - + namespace SchwabenCode.QuickIO; /// -/// Exception if path does not exist. +/// Represents an exception that is thrown when an operation encounters an existing path +/// that was expected to be unique or non-existent. /// +/// +/// This exception is typically used in scenarios involving file or directory creation +/// where a unique path is required. The exception provides detailed information about +/// the conflicting path, allowing for better error handling and debugging. +/// [Serializable] public class PathAlreadyExistsException : QuickIOBaseException { /// - /// Exception if path does not exist. + /// Initializes a new instance of the class + /// with a specified error message and the path that caused the exception. /// + /// The error message that explains the reason for the exception. + /// The path that already exists and caused the exception to be thrown. public PathAlreadyExistsException(string message, string path) - : base(message, path) - { - Contract.Requires(!string.IsNullOrWhiteSpace(message)); - Contract.Requires(!string.IsNullOrWhiteSpace(path)); - } + : base(message, path) { } } diff --git a/src/QuickIO/PathNotFoundException.cs b/src/QuickIO/PathNotFoundException.cs index 8690b4b..15afc6a 100644 --- a/src/QuickIO/PathNotFoundException.cs +++ b/src/QuickIO/PathNotFoundException.cs @@ -3,24 +3,32 @@ namespace SchwabenCode.QuickIO; /// -/// Exception if path does not exist. +/// Represents an exception that is thrown when an operation fails due to a specified +/// path not being found. /// +/// +/// This exception is typically used in scenarios involving file or directory access where +/// the specified path does not exist. It provides detailed information about the missing +/// path, aiding in error handling and debugging. +/// [Serializable] public class PathNotFoundException : QuickIOBaseException { /// - /// Exception if path does not exist. + /// Initializes a new instance of the class + /// with a specified path that caused the exception. The error message is automatically + /// generated based on the Win32 error code for "path not found." /// + /// The path that was not found and caused the exception to be thrown. public PathNotFoundException(string path) - : base(Win32ErrorCodes.FormatMessage(Win32ErrorCodes.ERROR_PATH_NOT_FOUND), path) - { - } + : base(Win32ErrorCodes.FormatMessage(Win32ErrorCodes.ERROR_PATH_NOT_FOUND), path) { } /// - /// Exception if path does not exist. + /// Initializes a new instance of the class + /// with a specified error message and the path that caused the exception. /// + /// The error message that explains the reason for the exception. + /// The path that was not found and caused the exception to be thrown. public PathNotFoundException(string message, string path) - : base(message, path) - { - } + : base(message, path) { } } diff --git a/src/QuickIO/QuickIO.cs b/src/QuickIO/QuickIO.cs index 289d139..7b44b2c 100644 --- a/src/QuickIO/QuickIO.cs +++ b/src/QuickIO/QuickIO.cs @@ -1,4 +1,5 @@ -using SchwabenCode.QuickIO.Internal; +using System.Diagnostics.CodeAnalysis; +using SchwabenCode.QuickIO.Internal; namespace SchwabenCode.QuickIO; @@ -15,7 +16,7 @@ public static partial class QuickIO /// /// Searched for file but found folder. /// Path is invalid. - public static bool FileExists(string path) + public static bool FileExists([NotNullWhen(true)] string path) { return QuickIOFile.Exists(path); } diff --git a/src/QuickIO/QuickIO.csproj b/src/QuickIO/QuickIO.csproj index 2d28999..59a68a6 100644 --- a/src/QuickIO/QuickIO.csproj +++ b/src/QuickIO/QuickIO.csproj @@ -1,5 +1,14 @@  + + + QuickIO.NET + true + readme.md + LICENSE.txt + + + TextTemplatingFileGenerator @@ -176,8 +185,4 @@ QuickIOFile_Root_Async.tt - - - - diff --git a/src/QuickIO/QuickIODirectoryInfo_Async.cs b/src/QuickIO/QuickIODirectoryInfo_Async.cs deleted file mode 100644 index 02fbad3..0000000 --- a/src/QuickIO/QuickIODirectoryInfo_Async.cs +++ /dev/null @@ -1,20 +0,0 @@ -namespace SchwabenCode.QuickIO; - -/// -/// Provides properties and instance methods for directories -/// -public sealed partial class QuickIODirectoryInfo -{ - - /// - /// Returns true if directory exists. Result starts a file system call and is not cached. - /// - /// Path exists but it's a file.. - public override Task ExistsAsync - { - get - { - return QuickIODirectory.ExistsAsync(this); - } - } -} diff --git a/src/QuickIO/QuickIOFile.cs b/src/QuickIO/QuickIOFile.cs index f6835e0..de1cc6a 100644 --- a/src/QuickIO/QuickIOFile.cs +++ b/src/QuickIO/QuickIOFile.cs @@ -1,4 +1,5 @@ -using SchwabenCode.QuickIO.Compatibility; +using System.Diagnostics.CodeAnalysis; +using SchwabenCode.QuickIO.Compatibility; using SchwabenCode.QuickIO.Internal; namespace SchwabenCode.QuickIO; @@ -233,19 +234,6 @@ public static bool Exists(QuickIOFileInfo fileInfo) return InternalFileExists(fileInfo.FullNameUnc); } - /// - /// Checks whether the specified file exists. - /// - /// The the file to check. - /// true if the caller has the required permissions and path contains the name of an existing file; otherwise, false - /// The original Exists method returns also false on null! http://msdn.microsoft.com/en-us/library/system.io.file.exists(v=vs.110).aspx - /// Searched for file but found folder. - /// Path is invalid. - public static Task ExistsAsync(QuickIOFileInfo fileInfo) - { - return NETCompatibility.AsyncExtensions.GetAsyncResult(() => Exists(fileInfo)); - } - /// /// Moves a specified file to a new location, providing the option to give a new file name. /// @@ -256,6 +244,7 @@ public static void Move(string sourceFileName, string destinationFileName) { InternalQuickIO.MoveFile(sourceFileName, destinationFileName); } + /// /// Moves a specified file to a new location, providing the option to give a new file name. /// @@ -311,12 +300,16 @@ public static Task MoveAsync(QuickIOPathInfo sourceFileInfo, QuickIODirectoryInf return NETCompatibility.AsyncExtensions.ExecuteAsync(() => Move(sourceFileInfo, destinationFolder)); } - #region Internal Directory - private static bool InternalFileExists(string uncPath) + private static bool InternalFileExists([NotNullWhen(true)] string? uncPath) { + if (uncPath is null || uncPath.Length is 0) + { + return false; + } + uint attrs = InternalQuickIO.SafeGetAttributes( uncPath, out _ ); - if (Equals(attrs, 0xffffffff)) + if (Equals(attrs, 0xffff_ffff)) { return false; } @@ -326,8 +319,7 @@ private static bool InternalFileExists(string uncPath) return true; } - throw new UnmatchedFileSystemEntryTypeException(QuickIOFileSystemEntryType.File, QuickIOFileSystemEntryType.Directory, uncPath); + throw new UnmatchedFileSystemEntryTypeException( + QuickIOFileSystemEntryType.File, QuickIOFileSystemEntryType.Directory, uncPath); } - #endregion - } diff --git a/src/QuickIO/QuickIOFileInfo_Async.cs b/src/QuickIO/QuickIOFileInfo_Async.cs deleted file mode 100644 index a7e9ef9..0000000 --- a/src/QuickIO/QuickIOFileInfo_Async.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace SchwabenCode.QuickIO; - -public sealed partial class QuickIOFileInfo -{ - - /// - /// Returns true if file exists. Uncached. - /// - /// Path exists but it's a directory. - public override Task ExistsAsync - { - get - { - return QuickIOFile.ExistsAsync(this); - } - } - -} diff --git a/src/QuickIO/QuickIOFileSystemEntryBase.cs b/src/QuickIO/QuickIOFileSystemEntryBase.cs index 8246fdb..dc395f7 100644 --- a/src/QuickIO/QuickIOFileSystemEntryBase.cs +++ b/src/QuickIO/QuickIOFileSystemEntryBase.cs @@ -22,12 +22,6 @@ public abstract class QuickIOFileSystemEntryBase /// public abstract bool Exists { get; } - /// - /// Returns true if exists - /// - public abstract Task ExistsAsync { get; } - - /// /// True if file is readonly. Cached. /// diff --git a/src/QuickIO/Transfer/Contracts/IQuickIOTransferJobContract.cs b/src/QuickIO/Transfer/Contracts/IQuickIOTransferJobContract.cs index 3122fb4..7cc53ed 100644 --- a/src/QuickIO/Transfer/Contracts/IQuickIOTransferJobContract.cs +++ b/src/QuickIO/Transfer/Contracts/IQuickIOTransferJobContract.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics.Contracts; + namespace SchwabenCode.QuickIO.Transfer.Contracts; /// diff --git a/src/QuickIO/Transfer/Contracts/IQuickIOTransferObserverContract.cs b/src/QuickIO/Transfer/Contracts/IQuickIOTransferObserverContract.cs index 73b1763..cf18ee5 100644 --- a/src/QuickIO/Transfer/Contracts/IQuickIOTransferObserverContract.cs +++ b/src/QuickIO/Transfer/Contracts/IQuickIOTransferObserverContract.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics.Contracts; + namespace SchwabenCode.QuickIO.Transfer.Contracts; /// diff --git a/src/QuickIO/Transfer/Contracts/IQuickIOTransferWriteJobContract.cs b/src/QuickIO/Transfer/Contracts/IQuickIOTransferWriteJobContract.cs index a556af8..41fabbd 100644 --- a/src/QuickIO/Transfer/Contracts/IQuickIOTransferWriteJobContract.cs +++ b/src/QuickIO/Transfer/Contracts/IQuickIOTransferWriteJobContract.cs @@ -1,6 +1,7 @@ using System.ComponentModel; using System.Diagnostics.Contracts; + namespace SchwabenCode.QuickIO.Transfer.Contracts; /// diff --git a/src/QuickIO/Transfer/IQuickIOTransferJob.cs b/src/QuickIO/Transfer/IQuickIOTransferJob.cs index 90a257c..dddb8b1 100644 --- a/src/QuickIO/Transfer/IQuickIOTransferJob.cs +++ b/src/QuickIO/Transfer/IQuickIOTransferJob.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.Contracts; + +using System.Diagnostics.Contracts; using SchwabenCode.QuickIO.Transfer.Contracts; namespace SchwabenCode.QuickIO.Transfer; diff --git a/src/QuickIO/Transfer/IQuickIOTransferWriteJob.cs b/src/QuickIO/Transfer/IQuickIOTransferWriteJob.cs index 12e1356..5145da8 100644 --- a/src/QuickIO/Transfer/IQuickIOTransferWriteJob.cs +++ b/src/QuickIO/Transfer/IQuickIOTransferWriteJob.cs @@ -1,4 +1,5 @@ -using System.Diagnostics.Contracts; + +using System.Diagnostics.Contracts; using SchwabenCode.QuickIO.Transfer.Contracts; namespace SchwabenCode.QuickIO.Transfer; diff --git a/src/QuickIO/readme.md b/src/QuickIO/readme.md new file mode 100644 index 0000000..cccacd8 --- /dev/null +++ b/src/QuickIO/readme.md @@ -0,0 +1,8 @@ +# QuickIO.NET +**by [Benjamin Abt](http://www.benjamin-abt.com) - [SchwabenCode.com](http://www.schwabencode.com)** + +QuickIO is a library that extends and accelerates .NET methods for file operations by not using the .NET abstraction for file operations, but by communicating directly with the Win32 API and avoiding unnecessary early overhead. + +## GitHub + +See https://github.com/SchwabenCode/QuickIO \ No newline at end of file