Merge pull request #1330 from adamhathcock/adam/fix-lang-version
Add Polysharp and adjustments that do not break legacy frameworks
This commit is contained in:
commit
192a947524
22 changed files with 266 additions and 96 deletions
|
|
@ -204,6 +204,7 @@ SharpCompress supports multiple archive and compression formats:
|
|||
- Preserve existing public method signatures and behavior when possible.
|
||||
- If a breaking change is unavoidable, document it and provide a migration path.
|
||||
- Add or update tests that cover backward compatibility expectations.
|
||||
- Avoid exposing public `init` setters, positional records, `required` members, or other metadata that forces consumers onto newer C# language versions; validate older-consumer compatibility with tests when changing exported APIs.
|
||||
|
||||
### Stream Ownership and Position Checklist
|
||||
- Verify `LeaveStreamOpen` behavior for externally owned streams.
|
||||
|
|
|
|||
|
|
@ -18,5 +18,6 @@
|
|||
Include="Microsoft.VisualStudio.Threading.Analyzers"
|
||||
Version="17.14.15"
|
||||
/>
|
||||
<GlobalPackageReference Include="PolySharp" Version="1.15.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"SimpleExec": {
|
||||
"type": "Direct",
|
||||
"requested": "[13.0.0, )",
|
||||
|
|
|
|||
|
|
@ -10,13 +10,29 @@ namespace SharpCompress.Archives;
|
|||
/// <see cref="ArchiveFactory.GetArchiveInformationAsync(System.IO.Stream,System.Threading.CancellationToken)"/>
|
||||
/// to obtain an instance of this record.
|
||||
/// </remarks>
|
||||
/// <param name="Type">
|
||||
/// The type of archive detected, or <see langword="null"/> when the format is not a registered well-known type.
|
||||
/// </param>
|
||||
/// <param name="SupportsRandomAccess">
|
||||
/// <see langword="true"/> when this archive format supports random access via the <see cref="IArchive"/> API,
|
||||
/// meaning the full file listing can be retrieved without decompressing the entire archive.
|
||||
/// <see langword="false"/> when only the <see cref="SharpCompress.Readers.IReader"/> API is available,
|
||||
/// which reads entries sequentially and can only report per-entry progress.
|
||||
/// </param>
|
||||
public record ArchiveInformation(ArchiveType? Type, bool SupportsRandomAccess);
|
||||
public record ArchiveInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of archive detected, or <see langword="null"/> when the format is not a registered well-known type.
|
||||
/// </summary>
|
||||
public ArchiveType? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// <see langword="true"/> when this archive format supports random access via the <see cref="IArchive"/> API,
|
||||
/// meaning the full file listing can be retrieved without decompressing the entire archive.
|
||||
/// <see langword="false"/> when only the <see cref="SharpCompress.Readers.IReader"/> API is available,
|
||||
/// which reads entries sequentially and can only report per-entry progress.
|
||||
/// </summary>
|
||||
public bool SupportsRandomAccess { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new archive information instance.
|
||||
/// </summary>
|
||||
/// <param name="type">The detected archive type.</param>
|
||||
/// <param name="supportsRandomAccess">Whether the detected format supports random access.</param>
|
||||
public ArchiveInformation(ArchiveType? type, bool supportsRandomAccess)
|
||||
{
|
||||
Type = type;
|
||||
SupportsRandomAccess = supportsRandomAccess;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace SharpCompress.Common;
|
|||
/// Options for configuring extraction behavior when extracting archive entries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use the <c>with</c> expression to create modified copies:
|
||||
/// Configure extraction behavior with constructors, property setters, or the <c>with</c> expression:
|
||||
/// <code>
|
||||
/// var options = new ExtractionOptions { Overwrite = false };
|
||||
/// options = options with { PreserveFileTime = true };
|
||||
|
|
@ -19,24 +19,24 @@ public sealed record ExtractionOptions : IExtractionOptions
|
|||
/// Overwrite target if it exists.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
public bool Overwrite { get; init; } = true;
|
||||
public bool Overwrite { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Extract with internal directory structure.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
public bool ExtractFullPath { get; init; } = true;
|
||||
public bool ExtractFullPath { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Preserve file time.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
public bool PreserveFileTime { get; init; } = true;
|
||||
public bool PreserveFileTime { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Preserve windows file attributes.
|
||||
/// </summary>
|
||||
public bool PreserveAttributes { get; init; }
|
||||
public bool PreserveAttributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for writing symbolic links to disk.
|
||||
|
|
@ -44,10 +44,10 @@ public sealed record ExtractionOptions : IExtractionOptions
|
|||
/// The second parameter is the target path (what the symlink refers to).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <b>Breaking change:</b> Changed from field to init-only property in version 0.40.0.
|
||||
/// <b>Breaking change:</b> Changed from field to property in version 0.40.0.
|
||||
/// If no handler is provided, symbolic links are silently skipped during extraction.
|
||||
/// </remarks>
|
||||
public Action<string, string>? SymbolicLinkHandler { get; init; }
|
||||
public Action<string, string>? SymbolicLinkHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ExtractionOptions instance with default values.
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ namespace SharpCompress.Common.Options;
|
|||
|
||||
public interface IEncodingOptions
|
||||
{
|
||||
IArchiveEncoding ArchiveEncoding { get; init; }
|
||||
IArchiveEncoding ArchiveEncoding { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,29 +11,29 @@ public interface IExtractionOptions
|
|||
/// Overwrite target if it exists.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
bool Overwrite { get; init; }
|
||||
bool Overwrite { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extract with internal directory structure.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
bool ExtractFullPath { get; init; }
|
||||
bool ExtractFullPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preserve file time.
|
||||
/// <para><b>Breaking change:</b> Default changed from false to true in version 0.40.0.</para>
|
||||
/// </summary>
|
||||
bool PreserveFileTime { get; init; }
|
||||
bool PreserveFileTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preserve windows file attributes.
|
||||
/// </summary>
|
||||
bool PreserveAttributes { get; init; }
|
||||
bool PreserveAttributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for writing symbolic links to disk.
|
||||
/// The first parameter is the source path (where the symlink is created).
|
||||
/// The second parameter is the target path (what the symlink refers to).
|
||||
/// </summary>
|
||||
Action<string, string>? SymbolicLinkHandler { get; init; }
|
||||
Action<string, string>? SymbolicLinkHandler { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ namespace SharpCompress.Common.Options;
|
|||
|
||||
public interface IProgressOptions
|
||||
{
|
||||
IProgress<ProgressReport>? Progress { get; init; }
|
||||
IProgress<ProgressReport>? Progress { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,37 +8,37 @@ public interface IReaderOptions : IStreamOptions, IEncodingOptions, IProgressOpt
|
|||
/// <summary>
|
||||
/// Look for RarArchive (Check for self-extracting archives or cases where RarArchive isn't at the start of the file)
|
||||
/// </summary>
|
||||
bool LookForHeader { get; init; }
|
||||
bool LookForHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Password for encrypted archives.
|
||||
/// </summary>
|
||||
string? Password { get; init; }
|
||||
string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disable checking for incomplete archives.
|
||||
/// </summary>
|
||||
bool DisableCheckIncomplete { get; init; }
|
||||
bool DisableCheckIncomplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Buffer size for stream operations.
|
||||
/// </summary>
|
||||
int BufferSize { get; init; }
|
||||
int BufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provide a hint for the extension of the archive being read, can speed up finding the correct decoder.
|
||||
/// </summary>
|
||||
string? ExtensionHint { get; init; }
|
||||
string? ExtensionHint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the rewindable buffer for non-seekable streams.
|
||||
/// </summary>
|
||||
int? RewindableBufferSize { get; init; }
|
||||
int? RewindableBufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom providers.
|
||||
/// Use this to provide alternative decompression implementations.
|
||||
/// </summary>
|
||||
CompressionProviderRegistry Providers { get; init; }
|
||||
CompressionProviderRegistry Providers { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@ namespace SharpCompress.Common.Options;
|
|||
|
||||
public interface IStreamOptions
|
||||
{
|
||||
bool LeaveStreamOpen { get; init; }
|
||||
bool LeaveStreamOpen { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,17 +12,17 @@ public interface IWriterOptions : IStreamOptions, IEncodingOptions, IProgressOpt
|
|||
/// <summary>
|
||||
/// The compression type to use for the archive.
|
||||
/// </summary>
|
||||
CompressionType CompressionType { get; init; }
|
||||
CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to be used when the compression type supports variable levels.
|
||||
/// </summary>
|
||||
int CompressionLevel { get; init; }
|
||||
int CompressionLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom providers, such as
|
||||
/// System.IO.Compression for Deflate/GZip on modern .NET.
|
||||
/// </summary>
|
||||
CompressionProviderRegistry Providers { get; init; }
|
||||
CompressionProviderRegistry Providers { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,22 +12,22 @@ public sealed record CompressionContext
|
|||
/// <summary>
|
||||
/// The size of the input data, or -1 if unknown.
|
||||
/// </summary>
|
||||
public long InputSize { get; init; } = -1;
|
||||
public long InputSize { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The expected output size, or -1 if unknown.
|
||||
/// </summary>
|
||||
public long OutputSize { get; init; } = -1;
|
||||
public long OutputSize { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Properties bytes for the compression format (e.g., LZMA properties).
|
||||
/// </summary>
|
||||
public byte[]? Properties { get; init; }
|
||||
public byte[]? Properties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the underlying stream supports seeking.
|
||||
/// </summary>
|
||||
public bool CanSeek { get; init; }
|
||||
public bool CanSeek { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional format-specific options.
|
||||
|
|
@ -38,7 +38,7 @@ public sealed record CompressionContext
|
|||
/// Examples of valid FormatOptions values include compression properties (e.g., LZMA properties),
|
||||
/// format flags, or algorithm-specific configuration.
|
||||
/// </remarks>
|
||||
public object? FormatOptions { get; init; }
|
||||
public object? FormatOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a CompressionContext from a stream.
|
||||
|
|
@ -51,7 +51,7 @@ public sealed record CompressionContext
|
|||
/// <summary>
|
||||
/// Reader options for accessing archive metadata such as header encoding.
|
||||
/// </summary>
|
||||
public IReaderOptions? ReaderOptions { get; init; }
|
||||
public IReaderOptions? ReaderOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new <see cref="CompressionContext"/> with the specified reader options.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace SharpCompress.Readers;
|
|||
/// Options for configuring reader behavior when opening archives.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use preset properties and fluent helpers for common configurations:
|
||||
/// Use preset properties, setters, and fluent helpers for common configurations:
|
||||
/// <code>
|
||||
/// var options = ReaderOptions.ForExternalStream
|
||||
/// .WithPassword("secret")
|
||||
|
|
@ -53,43 +53,43 @@ public sealed record ReaderOptions : IReaderOptions
|
|||
/// </code>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public bool LeaveStreamOpen { get; init; } = false;
|
||||
public bool LeaveStreamOpen { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// Look for RarArchive (Check for self-extracting archives or cases where RarArchive isn't at the start of the file)
|
||||
/// </summary>
|
||||
public bool LookForHeader { get; init; }
|
||||
public bool LookForHeader { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Password for encrypted archives.
|
||||
/// </summary>
|
||||
public string? Password { get; init; }
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disable checking for incomplete archives.
|
||||
/// </summary>
|
||||
public bool DisableCheckIncomplete { get; init; }
|
||||
public bool DisableCheckIncomplete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Buffer size for stream operations.
|
||||
/// </summary>
|
||||
public int BufferSize { get; init; } = Constants.BufferSize;
|
||||
public int BufferSize { get; set; } = Constants.BufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// Provide a hint for the extension of the archive being read, can speed up finding the correct decoder. Should be without the leading period in the form like: tar.gz or zip
|
||||
/// </summary>
|
||||
public string? ExtensionHint { get; init; }
|
||||
public string? ExtensionHint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking extraction operations.
|
||||
/// When set, progress updates will be reported as entries are extracted.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the rewindable buffer for non-seekable streams.
|
||||
|
|
@ -133,14 +133,14 @@ public sealed record ReaderOptions : IReaderOptions
|
|||
/// using var reader = ReaderFactory.OpenReader(networkStream, options);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public int? RewindableBufferSize { get; init; }
|
||||
public int? RewindableBufferSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations, such as
|
||||
/// System.IO.Compression for Deflate/GZip on modern .NET.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace SharpCompress.Writers.GZip;
|
|||
/// Options for configuring GZip writer behavior.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use factory methods for creation:
|
||||
/// Use factory methods, property setters, or fluent helpers for creation:
|
||||
/// <code>
|
||||
/// var options = WriterOptions.ForGZip().WithLeaveStreamOpen(false).WithCompressionLevel(9);
|
||||
/// </code>
|
||||
|
|
@ -27,7 +27,7 @@ public sealed record GZipWriterOptions : IWriterOptions
|
|||
public CompressionType CompressionType
|
||||
{
|
||||
get => CompressionType.GZip;
|
||||
init
|
||||
set
|
||||
{
|
||||
if (value != CompressionType.GZip)
|
||||
{
|
||||
|
|
@ -46,7 +46,7 @@ public sealed record GZipWriterOptions : IWriterOptions
|
|||
public int CompressionLevel
|
||||
{
|
||||
get => _compressionLevel;
|
||||
init
|
||||
set
|
||||
{
|
||||
CompressionLevelValidation.Validate(CompressionType.GZip, value);
|
||||
_compressionLevel = value;
|
||||
|
|
@ -56,24 +56,24 @@ public sealed record GZipWriterOptions : IWriterOptions
|
|||
/// <summary>
|
||||
/// SharpCompress will keep the supplied streams open. Default is true.
|
||||
/// </summary>
|
||||
public bool LeaveStreamOpen { get; init; } = true;
|
||||
public bool LeaveStreamOpen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations, such as
|
||||
/// System.IO.Compression for GZip on modern .NET.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public sealed record SevenZipWriterOptions : IWriterOptions
|
|||
public CompressionType CompressionType
|
||||
{
|
||||
get => _compressionType;
|
||||
init
|
||||
set
|
||||
{
|
||||
if (value != CompressionType.LZMA && value != CompressionType.LZMA2)
|
||||
{
|
||||
|
|
@ -39,41 +39,41 @@ public sealed record SevenZipWriterOptions : IWriterOptions
|
|||
public int CompressionLevel
|
||||
{
|
||||
get => _compressionLevel;
|
||||
init => _compressionLevel = value;
|
||||
set => _compressionLevel = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SharpCompress will keep the supplied streams open. Default is true.
|
||||
/// </summary>
|
||||
public bool LeaveStreamOpen { get; init; } = true;
|
||||
public bool LeaveStreamOpen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to compress the archive header itself using LZMA.
|
||||
/// Default is true, matching standard 7-Zip behavior.
|
||||
/// </summary>
|
||||
public bool CompressHeader { get; init; } = true;
|
||||
public bool CompressHeader { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Custom LZMA encoder properties. Null uses defaults (1MB dictionary, 32 fast bytes).
|
||||
/// </summary>
|
||||
public LzmaEncoderProperties? LzmaProperties { get; init; }
|
||||
public LzmaEncoderProperties? LzmaProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new SevenZipWriterOptions instance with LZMA2 compression (default).
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace SharpCompress.Writers.Tar;
|
|||
/// Options for configuring Tar writer behavior.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use the <c>with</c> expression to create modified copies:
|
||||
/// Configure tar writing with constructors, property setters, or the <c>with</c> expression:
|
||||
/// <code>
|
||||
/// var options = new TarWriterOptions(CompressionType.GZip, true);
|
||||
/// options = options with { HeaderFormat = TarHeaderWriteFormat.V7 };
|
||||
|
|
@ -22,45 +22,44 @@ public sealed record TarWriterOptions : IWriterOptions
|
|||
/// <summary>
|
||||
/// The compression type to use for the archive.
|
||||
/// </summary>
|
||||
public CompressionType CompressionType { get; init; }
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to be used when the compression type supports variable levels.
|
||||
/// </summary>
|
||||
public int CompressionLevel { get; init; }
|
||||
public int CompressionLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SharpCompress will keep the supplied streams open. Default is true.
|
||||
/// </summary>
|
||||
public bool LeaveStreamOpen { get; init; } = true;
|
||||
public bool LeaveStreamOpen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if archive should be finalized (by 2 empty blocks) on close.
|
||||
/// </summary>
|
||||
public bool FinalizeArchiveOnClose { get; init; } = true;
|
||||
public bool FinalizeArchiveOnClose { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// The format to use when writing tar headers.
|
||||
/// </summary>
|
||||
public TarHeaderWriteFormat HeaderFormat { get; init; } =
|
||||
TarHeaderWriteFormat.GNU_TAR_LONG_LINK;
|
||||
public TarHeaderWriteFormat HeaderFormat { get; set; } = TarHeaderWriteFormat.GNU_TAR_LONG_LINK;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new TarWriterOptions instance with the specified compression type and finalization option.
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace SharpCompress.Writers;
|
|||
/// Options for configuring writer behavior when creating archives.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use factory methods for creation:
|
||||
/// Use factory methods, property setters, or fluent helpers for creation:
|
||||
/// <code>
|
||||
/// var options = WriterOptions.ForZip().WithLeaveStreamOpen(false).WithCompressionLevel(9);
|
||||
/// </code>
|
||||
|
|
@ -20,7 +20,7 @@ public sealed record WriterOptions : IWriterOptions
|
|||
/// <summary>
|
||||
/// The compression type to use for the archive.
|
||||
/// </summary>
|
||||
public CompressionType CompressionType { get; init; }
|
||||
public CompressionType CompressionType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The compression level to be used when the compression type supports variable levels.
|
||||
|
|
@ -33,7 +33,7 @@ public sealed record WriterOptions : IWriterOptions
|
|||
public int CompressionLevel
|
||||
{
|
||||
get;
|
||||
init
|
||||
set
|
||||
{
|
||||
CompressionLevelValidation.Validate(CompressionType, value);
|
||||
field = value;
|
||||
|
|
@ -43,25 +43,25 @@ public sealed record WriterOptions : IWriterOptions
|
|||
/// <summary>
|
||||
/// SharpCompress will keep the supplied streams open. Default is true.
|
||||
/// </summary>
|
||||
public bool LeaveStreamOpen { get; init; } = true;
|
||||
public bool LeaveStreamOpen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// When set, progress updates will be reported as entries are written.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations, such as
|
||||
/// System.IO.Compression for Deflate/GZip on modern .NET.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace SharpCompress.Writers.Zip;
|
|||
/// Options for configuring Zip writer behavior.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class is immutable. Use the <c>with</c> expression to create modified copies:
|
||||
/// Configure zip writing with constructors, property setters, or the <c>with</c> expression:
|
||||
/// <code>
|
||||
/// var options = new ZipWriterOptions(CompressionType.Zip);
|
||||
/// options = options with { UseZip64 = true };
|
||||
|
|
@ -30,7 +30,7 @@ public sealed record ZipWriterOptions : IWriterOptions
|
|||
public CompressionType CompressionType
|
||||
{
|
||||
get => _compressionType;
|
||||
init => _compressionType = value;
|
||||
set => _compressionType = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -39,7 +39,7 @@ public sealed record ZipWriterOptions : IWriterOptions
|
|||
public int CompressionLevel
|
||||
{
|
||||
get => _compressionLevel;
|
||||
init
|
||||
set
|
||||
{
|
||||
CompressionLevelValidation.Validate(CompressionType, value);
|
||||
_compressionLevel = value;
|
||||
|
|
@ -49,29 +49,29 @@ public sealed record ZipWriterOptions : IWriterOptions
|
|||
/// <summary>
|
||||
/// SharpCompress will keep the supplied streams open. Default is true.
|
||||
/// </summary>
|
||||
public bool LeaveStreamOpen { get; init; } = true;
|
||||
public bool LeaveStreamOpen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Encoding to use for archive entry names.
|
||||
/// </summary>
|
||||
public IArchiveEncoding ArchiveEncoding { get; init; } = new ArchiveEncoding();
|
||||
public IArchiveEncoding ArchiveEncoding { get; set; } = new ArchiveEncoding();
|
||||
|
||||
/// <summary>
|
||||
/// An optional progress reporter for tracking compression operations.
|
||||
/// </summary>
|
||||
public IProgress<ProgressReport>? Progress { get; init; }
|
||||
public IProgress<ProgressReport>? Progress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Registry of compression providers.
|
||||
/// Defaults to <see cref="CompressionProviderRegistry.Default" /> but can be replaced with custom implementations.
|
||||
/// </summary>
|
||||
public CompressionProviderRegistry Providers { get; init; } =
|
||||
public CompressionProviderRegistry Providers { get; set; } =
|
||||
CompressionProviderRegistry.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Optional comment for the archive.
|
||||
/// </summary>
|
||||
public string? ArchiveComment { get; init; }
|
||||
public string? ArchiveComment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets a value indicating if zip64 support is enabled.
|
||||
|
|
@ -80,7 +80,7 @@ public sealed record ZipWriterOptions : IWriterOptions
|
|||
/// Archives larger than 4GiB are supported as long as all streams
|
||||
/// are less than 4GiB in length.
|
||||
/// </summary>
|
||||
public bool UseZip64 { get; init; }
|
||||
public bool UseZip64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new ZipWriterOptions instance with the specified compression type.
|
||||
|
|
|
|||
|
|
@ -36,6 +36,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"System.Text.Encoding.CodePages": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
|
|
@ -139,6 +145,12 @@
|
|||
"Microsoft.NETCore.Platforms": "1.1.0"
|
||||
}
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"System.Text.Encoding.CodePages": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
|
|
@ -235,6 +247,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"System.Text.Encoding.CodePages": {
|
||||
"type": "Direct",
|
||||
"requested": "[8.0.0, )",
|
||||
|
|
@ -268,9 +286,9 @@
|
|||
"net10.0": {
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"type": "Direct",
|
||||
"requested": "[10.0.6, )",
|
||||
"resolved": "10.0.6",
|
||||
"contentHash": "QKuvS0LWX4fjFqeDkyM7Kqt8P3wYTiPD4nwU+9y59n0sCiG714fxDgbbN82vDnzq89AF/PiHl92TP2C4aFDUQA=="
|
||||
"requested": "[10.0.7, )",
|
||||
"resolved": "10.0.7",
|
||||
"contentHash": "AA/yhzFHNtQZXLdqjzujPy25G8EWwGWsAnxOE2zYSBoT/8QHP6ketN3CToD3DFreO653ipUwnKHo22B8AlBMCw=="
|
||||
},
|
||||
"Microsoft.NETFramework.ReferenceAssemblies": {
|
||||
"type": "Direct",
|
||||
|
|
@ -297,6 +315,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "10.0.102",
|
||||
|
|
@ -339,6 +363,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "10.0.102",
|
||||
|
|
@ -387,6 +417,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"Microsoft.Build.Tasks.Git": {
|
||||
"type": "Transitive",
|
||||
"resolved": "10.0.102",
|
||||
|
|
|
|||
|
|
@ -55,6 +55,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"BenchmarkDotNet.Annotations": {
|
||||
"type": "Transitive",
|
||||
"resolved": "0.15.8",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Common;
|
||||
|
|
@ -228,6 +231,65 @@ public class OptionsUsabilityTests : TestBase
|
|||
Assert.True(preserveMetadata.PreserveAttributes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Public_Api_Does_Not_Expose_CSharp_9_Required_Metadata()
|
||||
{
|
||||
var assembly = typeof(ReaderOptions).Assembly;
|
||||
const string RequiredMemberAttributeName =
|
||||
"System.Runtime.CompilerServices.RequiredMemberAttribute";
|
||||
const string SetsRequiredMembersAttributeName =
|
||||
"System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute";
|
||||
var initOnlyProperties = assembly
|
||||
.GetExportedTypes()
|
||||
.SelectMany(type =>
|
||||
type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(property => property.SetMethod?.IsPublic == true)
|
||||
.Where(property =>
|
||||
property
|
||||
.SetMethod!.ReturnParameter.GetRequiredCustomModifiers()
|
||||
.Contains(typeof(IsExternalInit))
|
||||
)
|
||||
.Select(property => $"{type.FullName}.{property.Name}")
|
||||
)
|
||||
.ToArray();
|
||||
|
||||
Assert.Empty(initOnlyProperties);
|
||||
|
||||
var requiredMembers = assembly
|
||||
.GetExportedTypes()
|
||||
.SelectMany(type =>
|
||||
type.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
|
||||
.Where(member =>
|
||||
member
|
||||
.GetCustomAttributesData()
|
||||
.Any(attribute =>
|
||||
attribute.AttributeType.FullName == RequiredMemberAttributeName
|
||||
)
|
||||
)
|
||||
.Select(member => $"{type.FullName}.{member.Name}")
|
||||
)
|
||||
.ToArray();
|
||||
|
||||
Assert.Empty(requiredMembers);
|
||||
|
||||
var constructorsWithRequiredMembers = assembly
|
||||
.GetExportedTypes()
|
||||
.SelectMany(type =>
|
||||
type.GetConstructors(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(constructor =>
|
||||
constructor
|
||||
.GetCustomAttributesData()
|
||||
.Any(attribute =>
|
||||
attribute.AttributeType.FullName == SetsRequiredMembersAttributeName
|
||||
)
|
||||
)
|
||||
.Select(_ => $"{type.FullName}.ctor")
|
||||
)
|
||||
.ToArray();
|
||||
|
||||
Assert.Empty(constructorsWithRequiredMembers);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReaderOptions_Factory_ForEncryptedArchive_Sets_Password()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,6 +45,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"xunit.runner.visualstudio": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.5, )",
|
||||
|
|
@ -309,6 +315,30 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
".NETFramework,Version=v4.8/win-x86": {
|
||||
"Microsoft.Win32.Registry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==",
|
||||
"dependencies": {
|
||||
"System.Security.AccessControl": "5.0.0",
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Security.AccessControl": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==",
|
||||
"dependencies": {
|
||||
"System.Security.Principal.Windows": "5.0.0"
|
||||
}
|
||||
},
|
||||
"System.Security.Principal.Windows": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA=="
|
||||
}
|
||||
},
|
||||
"net10.0": {
|
||||
"AwesomeAssertions": {
|
||||
"type": "Direct",
|
||||
|
|
@ -351,6 +381,12 @@
|
|||
"resolved": "17.14.15",
|
||||
"contentHash": "mXQPJsbuUD2ydq4/ffd8h8tSOFCXec+2xJOVNCvXjuMOq/+5EKHq3D2m2MC2+nUaXeFMSt66VS/J4HdKBixgcw=="
|
||||
},
|
||||
"PolySharp": {
|
||||
"type": "Direct",
|
||||
"requested": "[1.15.0, )",
|
||||
"resolved": "1.15.0",
|
||||
"contentHash": "FbU0El+EEjdpuIX4iDbeS7ki1uzpJPx8vbqOzEtqnl1GZeAGJfq+jCbxeJL2y0EPnUNk8dRnnqR2xnYXg9Tf+g=="
|
||||
},
|
||||
"xunit.runner.visualstudio": {
|
||||
"type": "Direct",
|
||||
"requested": "[3.1.5, )",
|
||||
|
|
@ -521,6 +557,13 @@
|
|||
"resolved": "8.0.0",
|
||||
"contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw=="
|
||||
}
|
||||
},
|
||||
"net10.0/win-x86": {
|
||||
"Microsoft.Win32.Registry": {
|
||||
"type": "Transitive",
|
||||
"resolved": "5.0.0",
|
||||
"contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue