Clean up some code paths

This commit is contained in:
Adam Hathcock
2026-02-12 08:50:18 +00:00
parent 33e9c78626
commit b2f1d007c6
6 changed files with 110 additions and 97 deletions

View File

@@ -2,12 +2,9 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Options;
using SharpCompress.Factories;
using SharpCompress.IO;
using SharpCompress.Readers;
namespace SharpCompress.Archives;

View File

@@ -37,12 +37,9 @@ public partial class TarArchive
)
{
fileInfo.NotNull(nameof(fileInfo));
return new TarArchive(
new SourceStream(
fileInfo,
i => ArchiveVolumeFactory.GetFilePart(i, fileInfo),
readerOptions ?? new ReaderOptions() { LeaveStreamOpen = false }
)
return OpenArchive(
[fileInfo],
readerOptions ?? new ReaderOptions() { LeaveStreamOpen = false }
);
}
@@ -90,9 +87,7 @@ public partial class TarArchive
throw new ArgumentException("Stream must be seekable", nameof(stream));
}
return new TarArchive(
new SourceStream(stream, i => null, readerOptions ?? new ReaderOptions())
);
return OpenArchive([stream], readerOptions);
}
public static IWritableAsyncArchive<TarWriterOptions> OpenAsyncArchive(

View File

@@ -1,5 +1,13 @@
using System.IO;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
using SharpCompress.Compressors.Deflate;
using SharpCompress.Compressors.LZMA;
using SharpCompress.Compressors.ZStandard;
using SharpCompress.IO;
namespace SharpCompress.Readers.Tar;
@@ -38,4 +46,74 @@ public partial class TarReader
fileInfo.NotNull(nameof(fileInfo));
return OpenReader(fileInfo.OpenRead(), readerOptions);
}
/// <summary>
/// Opens a TarReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
options ??= new ReaderOptions();
var sharpCompressStream = SharpCompressStream.Create(
stream,
bufferSize: options.RewindableBufferSize
);
long pos = sharpCompressStream.Position;
if (GZipArchive.IsGZipFile(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new GZipStream(sharpCompressStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.GZip);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (BZip2Stream.IsBZip2(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = BZip2Stream.Create(
sharpCompressStream,
CompressionMode.Decompress,
false
);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.BZip2);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (ZStandardStream.IsZStandard(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new ZStandardStream(sharpCompressStream);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.ZStandard);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (LZipStream.IsLZipFile(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new LZipStream(sharpCompressStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.LZip);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.None);
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpCompress.Archives.GZip;
using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Common.Tar;
using SharpCompress.Compressors;
@@ -45,80 +43,6 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
};
}
#region OpenReader
/// <summary>
/// Opens a TarReader for Non-seeking usage with a single volume
/// </summary>
/// <param name="stream"></param>
/// <param name="options"></param>
/// <returns></returns>
public static IReader OpenReader(Stream stream, ReaderOptions? options = null)
{
stream.NotNull(nameof(stream));
options = options ?? new ReaderOptions();
var sharpCompressStream = SharpCompressStream.Create(
stream,
bufferSize: options.RewindableBufferSize
);
long pos = sharpCompressStream.Position;
if (GZipArchive.IsGZipFile(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new GZipStream(sharpCompressStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.GZip);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (BZip2Stream.IsBZip2(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = BZip2Stream.Create(
sharpCompressStream,
CompressionMode.Decompress,
false
);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.BZip2);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (ZStandardStream.IsZStandard(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new ZStandardStream(sharpCompressStream);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.ZStandard);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
if (LZipStream.IsLZipFile(sharpCompressStream))
{
sharpCompressStream.Position = pos;
var testStream = new LZipStream(sharpCompressStream, CompressionMode.Decompress);
if (TarArchive.IsTarFile(testStream))
{
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.LZip);
}
throw new InvalidFormatException("Not a tar file.");
}
sharpCompressStream.Position = pos;
return new TarReader(sharpCompressStream, options, CompressionType.None);
}
#endregion OpenReader
protected override IEnumerable<TarEntry> GetEntries(Stream stream) =>
TarEntry.GetEntries(
StreamingMode.Streaming,
@@ -127,6 +51,4 @@ public partial class TarReader : AbstractReader<TarEntry, TarVolume>
Options.ArchiveEncoding,
Options
);
// GetEntriesAsync moved to TarReader.Async.cs
}

View File

@@ -253,7 +253,7 @@ public class TarArchiveAsyncTests : ArchiveTests
var numberOfEntries = 0;
await using (
var archiveFactory = TarArchive.OpenAsyncArchive(new AsyncOnlyStream(memoryStream))
var archiveFactory = await ArchiveFactory.OpenAsyncArchive(new AsyncOnlyStream(memoryStream))
)
{
await foreach (var entry in archiveFactory.EntriesAsync)

View File

@@ -7,6 +7,7 @@ using SharpCompress.Archives.Tar;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Readers.Tar;
using SharpCompress.Test.Mocks;
using SharpCompress.Writers;
using SharpCompress.Writers.Tar;
using Xunit;
@@ -23,6 +24,26 @@ public class TarArchiveTests : ArchiveTests
[Fact]
public void TarArchivePathRead() => ArchiveFileRead("Tar.tar");
[Fact]
public void TarArchiveStreamRead_Autodetect_CompressedTar()
{
using Stream stream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar.gz"));
using var archive = ArchiveFactory.OpenArchive(stream);
Assert.Equal(ArchiveType.Tar, archive.Type);
Assert.NotEmpty(archive.Entries);
}
[Fact]
public void TarArchiveStreamRead_Throws_On_NonSeekable_Stream()
{
using Stream stream = new ForwardOnlyStream(
File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "Tar.tar"))
);
Assert.Throws<ArgumentException>(() => ArchiveFactory.OpenArchive(stream));
}
[Fact]
public void Tar_FileName_Exactly_100_Characters()
{
@@ -53,7 +74,7 @@ public class TarArchiveTests : ArchiveTests
// Step 2: check if the written tar file can be read correctly
var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
using (var archive2 = TarArchive.OpenArchive(unmodified))
using (var archive2 = ArchiveFactory.OpenArchive(unmodified))
{
Assert.Equal(1, archive2.Entries.Count());
Assert.Contains(filename, archive2.Entries.Select(entry => entry.Key));
@@ -72,7 +93,7 @@ public class TarArchiveTests : ArchiveTests
public void Tar_NonUstarArchiveWithLongNameDoesNotSkipEntriesAfterTheLongOne()
{
var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "very long filename.tar");
using var archive = TarArchive.OpenArchive(unmodified);
using var archive = ArchiveFactory.OpenArchive(unmodified);
Assert.Equal(5, archive.Entries.Count());
Assert.Contains("very long filename/", archive.Entries.Select(entry => entry.Key));
Assert.Contains(
@@ -119,7 +140,7 @@ public class TarArchiveTests : ArchiveTests
// Step 2: check if the written tar file can be read correctly
var unmodified = Path.Combine(SCRATCH2_FILES_PATH, archive);
using (var archive2 = TarArchive.OpenArchive(unmodified))
using (var archive2 = ArchiveFactory.OpenArchive(unmodified))
{
Assert.Equal(1, archive2.Entries.Count());
Assert.Contains(longFilename, archive2.Entries.Select(entry => entry.Key));
@@ -138,7 +159,7 @@ public class TarArchiveTests : ArchiveTests
public void Tar_UstarArchivePathReadLongName()
{
var unmodified = Path.Combine(TEST_ARCHIVES_PATH, "ustar with long names.tar");
using var archive = TarArchive.OpenArchive(unmodified);
using var archive = ArchiveFactory.OpenArchive(unmodified);
Assert.Equal(6, archive.Entries.Count());
Assert.Contains("Directory/", archive.Entries.Select(entry => entry.Key));
Assert.Contains(
@@ -285,9 +306,9 @@ public class TarArchiveTests : ArchiveTests
var numberOfEntries = 0;
using (var archiveFactory = TarArchive.OpenArchive(memoryStream))
using (var archive = ArchiveFactory.OpenArchive(memoryStream))
{
foreach (var entry in archiveFactory.Entries)
foreach (var entry in archive.Entries)
{
++numberOfEntries;