mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-07-13 12:36:52 +00:00
Entry can be null and remove other ! usages
This commit is contained in:
@@ -120,6 +120,10 @@ public abstract class AbstractWritableArchive<TEntry, TVolume>
|
||||
{
|
||||
foreach (var path in Entries.Select(x => x.Key))
|
||||
{
|
||||
if (path is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var p = path.Replace('/', '\\');
|
||||
if (p.Length > 0 && p[0] == '\\')
|
||||
{
|
||||
|
||||
@@ -184,7 +184,7 @@ public class GZipArchive : AbstractWritableArchive<GZipArchiveEntry, GZipVolume>
|
||||
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
|
||||
{
|
||||
using var entryStream = entry.OpenEntryStream();
|
||||
writer.Write(entry.Key, entryStream, entry.LastModifiedTime);
|
||||
writer.Write(entry.Key.NotNull("Entry Key is null"), entryStream, entry.LastModifiedTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,15 +17,11 @@ public static class IArchiveEntryExtensions
|
||||
streamListener.EnsureEntriesLoaded();
|
||||
streamListener.FireEntryExtractionBegin(archiveEntry);
|
||||
streamListener.FireFilePartExtractionBegin(
|
||||
archiveEntry.Key,
|
||||
archiveEntry.Key ?? "Key",
|
||||
archiveEntry.Size,
|
||||
archiveEntry.CompressedSize
|
||||
);
|
||||
var entryStream = archiveEntry.OpenEntryStream();
|
||||
if (entryStream is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
using (entryStream)
|
||||
{
|
||||
using Stream s = new ListeningStream(streamListener, entryStream);
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Common;
|
||||
|
||||
namespace SharpCompress.Archives;
|
||||
@@ -59,7 +58,7 @@ public static class IArchiveExtensions
|
||||
}
|
||||
|
||||
// Create each directory
|
||||
var path = Path.Combine(destination, entry.Key);
|
||||
var path = Path.Combine(destination, entry.Key.NotNull("Entry Key is null"));
|
||||
if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
@@ -14,7 +14,7 @@ public abstract class Entry : IEntry
|
||||
/// <summary>
|
||||
/// The string key of the file internal to the Archive.
|
||||
/// </summary>
|
||||
public abstract string Key { get; }
|
||||
public abstract string? Key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The target of a symlink entry internal to the Archive. Will be null if not a symlink.
|
||||
@@ -71,11 +71,11 @@ public abstract class Entry : IEntry
|
||||
/// </summary>
|
||||
public abstract bool IsSplitAfter { get; }
|
||||
|
||||
public int VolumeIndexFirst => Parts?.FirstOrDefault()?.Index ?? 0;
|
||||
public int VolumeIndexLast => Parts?.LastOrDefault()?.Index ?? 0;
|
||||
public int VolumeIndexFirst => Parts.FirstOrDefault()?.Index ?? 0;
|
||||
public int VolumeIndexLast => Parts.LastOrDefault()?.Index ?? 0;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString() => Key;
|
||||
public override string ToString() => Key ?? "Entry";
|
||||
|
||||
internal abstract IEnumerable<FilePart> Parts { get; }
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ internal static class ExtractionMethods
|
||||
|
||||
options ??= new ExtractionOptions() { Overwrite = true };
|
||||
|
||||
var file = Path.GetFileName(entry.Key);
|
||||
var file = Path.GetFileName(entry.Key.NotNull("Entry Key is null")).NotNull("File is null");
|
||||
if (options.ExtractFullPath)
|
||||
{
|
||||
var folder = Path.GetDirectoryName(entry.Key)!;
|
||||
var folder = Path.GetDirectoryName(entry.Key.NotNull("Entry Key is null")).NotNull("Directory is null");
|
||||
var destdir = Path.GetFullPath(Path.Combine(fullDestinationDirectoryPath, folder));
|
||||
|
||||
if (!Directory.Exists(destdir))
|
||||
|
||||
@@ -8,7 +8,7 @@ public abstract class FilePart
|
||||
|
||||
internal ArchiveEncoding ArchiveEncoding { get; }
|
||||
|
||||
internal abstract string FilePartName { get; }
|
||||
internal abstract string? FilePartName { get; }
|
||||
public int Index { get; set; }
|
||||
|
||||
internal abstract Stream GetCompressedStream();
|
||||
|
||||
@@ -14,7 +14,7 @@ public class GZipEntry : Entry
|
||||
|
||||
public override long Crc => _filePart.Crc ?? 0;
|
||||
|
||||
public override string Key => _filePart.FilePartName;
|
||||
public override string? Key => _filePart.FilePartName;
|
||||
|
||||
public override string? LinkTarget => null;
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ internal sealed class GZipFilePart : FilePart
|
||||
internal uint? Crc { get; private set; }
|
||||
internal uint? UncompressedSize { get; private set; }
|
||||
|
||||
internal override string FilePartName => _name!;
|
||||
internal override string? FilePartName => _name;
|
||||
|
||||
internal override Stream GetCompressedStream() =>
|
||||
new DeflateStream(_stream, CompressionMode.Decompress, CompressionLevel.Default);
|
||||
|
||||
@@ -9,7 +9,7 @@ public interface IEntry
|
||||
long CompressedSize { get; }
|
||||
long Crc { get; }
|
||||
DateTime? CreatedTime { get; }
|
||||
string Key { get; }
|
||||
string? Key { get; }
|
||||
string? LinkTarget { get; }
|
||||
bool IsDirectory { get; }
|
||||
bool IsEncrypted { get; }
|
||||
|
||||
@@ -6,5 +6,5 @@ public interface IVolume : IDisposable
|
||||
{
|
||||
int Index { get; }
|
||||
|
||||
string FileName { get; }
|
||||
string? FileName { get; }
|
||||
}
|
||||
|
||||
@@ -70,11 +70,11 @@ internal sealed class RarCryptoWrapper : Stream
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (_rijndael != null)
|
||||
if (disposing)
|
||||
{
|
||||
_rijndael.Dispose();
|
||||
_rijndael = null!;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ internal class ArchiveDatabase
|
||||
_packSizes.Clear();
|
||||
_packCrCs.Clear();
|
||||
_folders.Clear();
|
||||
_numUnpackStreamsVector = null!;
|
||||
_numUnpackStreamsVector = null;
|
||||
_files.Clear();
|
||||
|
||||
_packStreamStartPositions.Clear();
|
||||
|
||||
@@ -32,7 +32,7 @@ public abstract class Volume : IVolume
|
||||
|
||||
public virtual int Index { get; internal set; }
|
||||
|
||||
public string FileName => (_actualStream as FileStream)?.Name!;
|
||||
public string? FileName => (_actualStream as FileStream)?.Name;
|
||||
|
||||
/// <summary>
|
||||
/// RarArchive is part of a multi-part archive.
|
||||
|
||||
@@ -11,8 +11,8 @@ public class SourceStream : Stream
|
||||
private long _prevSize;
|
||||
private readonly List<FileInfo> _files;
|
||||
private readonly List<Stream> _streams;
|
||||
private readonly Func<int, FileInfo?> _getFilePart;
|
||||
private readonly Func<int, Stream?> _getStreamPart;
|
||||
private readonly Func<int, FileInfo?>? _getFilePart;
|
||||
private readonly Func<int, Stream?>? _getStreamPart;
|
||||
private int _stream;
|
||||
|
||||
public SourceStream(FileInfo file, Func<int, FileInfo?> getPart, ReaderOptions options)
|
||||
@@ -38,8 +38,8 @@ public class SourceStream : Stream
|
||||
if (!IsFileMode)
|
||||
{
|
||||
_streams.Add(stream!);
|
||||
_getStreamPart = getStreamPart!;
|
||||
_getFilePart = _ => null!;
|
||||
_getStreamPart = getStreamPart;
|
||||
_getFilePart = _ => null;
|
||||
if (stream is FileStream fileStream)
|
||||
{
|
||||
_files.Add(new FileInfo(fileStream.Name));
|
||||
@@ -49,8 +49,8 @@ public class SourceStream : Stream
|
||||
{
|
||||
_files.Add(file!);
|
||||
_streams.Add(_files[0].OpenRead());
|
||||
_getFilePart = getFilePart!;
|
||||
_getStreamPart = _ => null!;
|
||||
_getFilePart = getFilePart;
|
||||
_getStreamPart = _ => null;
|
||||
}
|
||||
_stream = 0;
|
||||
_prevSize = 0;
|
||||
@@ -78,7 +78,7 @@ public class SourceStream : Stream
|
||||
{
|
||||
if (IsFileMode)
|
||||
{
|
||||
var f = _getFilePart(_streams.Count);
|
||||
var f = _getFilePart.NotNull("GetFilePart is null")(_streams.Count);
|
||||
if (f == null)
|
||||
{
|
||||
_stream = _streams.Count - 1;
|
||||
@@ -90,7 +90,7 @@ public class SourceStream : Stream
|
||||
}
|
||||
else
|
||||
{
|
||||
var s = _getStreamPart(_streams.Count);
|
||||
var s = _getStreamPart.NotNull("GetStreamPart is null")(_streams.Count);
|
||||
if (s == null)
|
||||
{
|
||||
_stream = _streams.Count - 1;
|
||||
|
||||
@@ -35,7 +35,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
|
||||
/// <summary>
|
||||
/// Current volume that the current entry resides in
|
||||
/// </summary>
|
||||
public abstract TVolume Volume { get; }
|
||||
public abstract TVolume? Volume { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Current file entry
|
||||
@@ -109,7 +109,7 @@ public abstract class AbstractReader<TEntry, TVolume> : IReader, IReaderExtracti
|
||||
return entriesForCurrentReadStream.MoveNext();
|
||||
}
|
||||
|
||||
protected virtual Stream RequestInitialStream() => Volume.Stream;
|
||||
protected virtual Stream RequestInitialStream() => Volume.NotNull("Volume isn't loaded.").Stream;
|
||||
|
||||
internal virtual bool NextEntryForCurrentStream() => entriesForCurrentReadStream!.MoveNext();
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ public abstract class RarReader : AbstractReader<RarReaderEntry, RarVolume>
|
||||
internal Lazy<IRarUnpack> UnpackV1 { get; } = new(() => new Compressors.Rar.UnpackV1.Unpack());
|
||||
|
||||
internal RarReader(ReaderOptions options)
|
||||
: base(options, ArchiveType.Rar) { }
|
||||
: base(options, ArchiveType.Rar)
|
||||
{
|
||||
}
|
||||
|
||||
internal abstract void ValidateArchive(RarVolume archive);
|
||||
|
||||
public override RarVolume Volume => volume!;
|
||||
public override RarVolume? Volume => volume;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a RarReader for Non-seeking usage with a single volume
|
||||
|
||||
@@ -9,6 +9,22 @@ namespace SharpCompress;
|
||||
[CLSCompliant(false)]
|
||||
public static class Utility
|
||||
{
|
||||
public static T NotNull<T>(this T? item, string message) where T : class
|
||||
{
|
||||
if (item is null)
|
||||
{
|
||||
throw new InvalidOperationException(message);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
public static T NotNull<T>(this T? item) where T : class
|
||||
{
|
||||
if (item is null)
|
||||
{
|
||||
throw new InvalidOperationException("Item is null");
|
||||
}
|
||||
return item;
|
||||
}
|
||||
public static ReadOnlyCollection<T> ToReadOnly<T>(this ICollection<T> items) => new(items);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -19,7 +19,7 @@ public class GZipArchiveTests : ArchiveTests
|
||||
using (var archive = ArchiveFactory.Open(stream))
|
||||
{
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
||||
|
||||
var size = entry.Size;
|
||||
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"));
|
||||
@@ -41,7 +41,7 @@ public class GZipArchiveTests : ArchiveTests
|
||||
using (var archive = GZipArchive.Open(stream))
|
||||
{
|
||||
var entry = archive.Entries.First();
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key));
|
||||
entry.WriteToFile(Path.Combine(SCRATCH_FILES_PATH, entry.Key.NotNull()));
|
||||
|
||||
var size = entry.Size;
|
||||
var scratch = new FileInfo(Path.Combine(SCRATCH_FILES_PATH, "Tar.tar"));
|
||||
@@ -94,6 +94,7 @@ public class GZipArchiveTests : ArchiveTests
|
||||
using (var entryStream = archiveEntry.OpenEntryStream())
|
||||
{
|
||||
var result = TarArchive.IsTarFile(entryStream);
|
||||
Assert.True(result);
|
||||
}
|
||||
Assert.Equal(size, tarStream.Length);
|
||||
using (var entryStream = archiveEntry.OpenEntryStream())
|
||||
|
||||
@@ -209,7 +209,7 @@ public class RarReaderTests : ReaderTests
|
||||
{
|
||||
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
|
||||
using var entryStream = reader.OpenEntryStream();
|
||||
var file = Path.GetFileName(reader.Entry.Key);
|
||||
var file = Path.GetFileName(reader.Entry.Key).NotNull();
|
||||
var folder =
|
||||
Path.GetDirectoryName(reader.Entry.Key)
|
||||
?? throw new ArgumentNullException();
|
||||
@@ -293,7 +293,7 @@ public class RarReaderTests : ReaderTests
|
||||
using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true });
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (reader.Entry.Key.Contains("jpg"))
|
||||
if (reader.Entry.Key.NotNull().Contains("jpg"))
|
||||
{
|
||||
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
|
||||
reader.WriteEntryToDirectory(
|
||||
@@ -316,7 +316,7 @@ public class RarReaderTests : ReaderTests
|
||||
using var reader = ReaderFactory.Open(stream, new ReaderOptions { LookForHeader = true });
|
||||
while (reader.MoveToNextEntry())
|
||||
{
|
||||
if (reader.Entry.Key.Contains("jpg"))
|
||||
if (reader.Entry.Key.NotNull().Contains("jpg"))
|
||||
{
|
||||
Assert.Equal(CompressionType.Rar, reader.Entry.CompressionType);
|
||||
reader.WriteEntryToDirectory(
|
||||
|
||||
@@ -216,8 +216,8 @@ public class TestBase : IDisposable
|
||||
while (archive1.MoveToNextEntry())
|
||||
{
|
||||
Assert.True(archive2.MoveToNextEntry());
|
||||
archive1Entries.Add(archive1.Entry.Key);
|
||||
archive2Entries.Add(archive2.Entry.Key);
|
||||
archive1Entries.Add(archive1.Entry.Key.NotNull());
|
||||
archive2Entries.Add(archive2.Entry.Key.NotNull());
|
||||
}
|
||||
Assert.False(archive2.MoveToNextEntry());
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ public class ZipArchiveTests : ArchiveTests
|
||||
);
|
||||
Assert.Null(
|
||||
((IArchive)vfs).Entries.FirstOrDefault(v =>
|
||||
v.Key.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)
|
||||
v.Key.NotNull().EndsWith("jpg", StringComparison.OrdinalIgnoreCase)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user