Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/SharpCompress/Archives/AbstractWritableArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.IO;
using SharpCompress.Writers;
Expand Down Expand Up @@ -141,6 +143,18 @@ public void SaveTo(Stream stream, WriterOptions options)
SaveTo(stream, options, OldEntries, newEntries);
}

public async Task SaveToAsync(
Stream stream,
WriterOptions options,
CancellationToken cancellationToken = default
)
{
//reset streams of new entries
newEntries.Cast<IWritableArchiveEntry>().ForEach(x => x.Stream.Seek(0, SeekOrigin.Begin));
await SaveToAsync(stream, options, OldEntries, newEntries, cancellationToken)
.ConfigureAwait(false);
}

protected TEntry CreateEntry(
string key,
Stream source,
Expand Down Expand Up @@ -173,6 +187,14 @@ protected abstract void SaveTo(
IEnumerable<TEntry> newEntries
);

protected abstract Task SaveToAsync(
Stream stream,
WriterOptions options,
IEnumerable<TEntry> oldEntries,
IEnumerable<TEntry> newEntries,
CancellationToken cancellationToken = default
);

public override void Dispose()
{
base.Dispose();
Expand Down
34 changes: 34 additions & 0 deletions src/SharpCompress/Archives/GZip/GZipArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.GZip;
using SharpCompress.IO;
Expand Down Expand Up @@ -136,6 +138,16 @@ public void SaveTo(FileInfo fileInfo)
SaveTo(stream, new WriterOptions(CompressionType.GZip));
}

public Task SaveToAsync(string filePath, CancellationToken cancellationToken = default) =>
SaveToAsync(new FileInfo(filePath), cancellationToken);

public async Task SaveToAsync(FileInfo fileInfo, CancellationToken cancellationToken = default)
{
using var stream = fileInfo.Open(FileMode.Create, FileAccess.Write);
await SaveToAsync(stream, new WriterOptions(CompressionType.GZip), cancellationToken)
.ConfigureAwait(false);
}

public static bool IsGZipFile(Stream stream)
{
// read the header on the first read
Expand Down Expand Up @@ -196,6 +208,28 @@ IEnumerable<GZipArchiveEntry> newEntries
}
}

protected override async Task SaveToAsync(
Stream stream,
WriterOptions options,
IEnumerable<GZipArchiveEntry> oldEntries,
IEnumerable<GZipArchiveEntry> newEntries,
CancellationToken cancellationToken = default
)
{
if (Entries.Count > 1)
{
throw new InvalidFormatException("Only one entry is allowed in a GZip Archive");
}
using var writer = new GZipWriter(stream, new GZipWriterOptions(options));
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using var entryStream = entry.OpenEntryStream();
await writer
.WriteAsync(entry.Key.NotNull("Entry Key is null"), entryStream, cancellationToken)
.ConfigureAwait(false);
}
}

protected override IEnumerable<GZipArchiveEntry> LoadEntries(IEnumerable<GZipVolume> volumes)
{
var stream = volumes.Single().Stream;
Expand Down
67 changes: 67 additions & 0 deletions src/SharpCompress/Archives/IArchiveEntryExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.IO;

Expand Down Expand Up @@ -30,6 +32,34 @@ public static void WriteTo(this IArchiveEntry archiveEntry, Stream streamToWrite
streamListener.FireEntryExtractionEnd(archiveEntry);
}

public static async Task WriteToAsync(
this IArchiveEntry archiveEntry,
Stream streamToWriteTo,
CancellationToken cancellationToken = default
)
{
if (archiveEntry.IsDirectory)
{
throw new ExtractionException("Entry is a file directory and cannot be extracted.");
}

var streamListener = (IArchiveExtractionListener)archiveEntry.Archive;
streamListener.EnsureEntriesLoaded();
streamListener.FireEntryExtractionBegin(archiveEntry);
streamListener.FireFilePartExtractionBegin(
archiveEntry.Key ?? "Key",
archiveEntry.Size,
archiveEntry.CompressedSize
);
var entryStream = archiveEntry.OpenEntryStream();
using (entryStream)
{
using Stream s = new ListeningStream(streamListener, entryStream);
await s.CopyToAsync(streamToWriteTo, 81920, cancellationToken).ConfigureAwait(false);
}
streamListener.FireEntryExtractionEnd(archiveEntry);
}

/// <summary>
/// Extract to specific directory, retaining filename
/// </summary>
Expand All @@ -45,6 +75,23 @@ public static void WriteToDirectory(
entry.WriteToFile
);

/// <summary>
/// Extract to specific directory asynchronously, retaining filename
/// </summary>
public static Task WriteToDirectoryAsync(
this IArchiveEntry entry,
string destinationDirectory,
ExtractionOptions? options = null,
CancellationToken cancellationToken = default
) =>
ExtractionMethods.WriteEntryToDirectoryAsync(
entry,
destinationDirectory,
options,
(x, opt) => entry.WriteToFileAsync(x, opt, cancellationToken),
cancellationToken
);

/// <summary>
/// Extract to specific file
/// </summary>
Expand All @@ -63,4 +110,24 @@ public static void WriteToFile(
entry.WriteTo(fs);
}
);

/// <summary>
/// Extract to specific file asynchronously
/// </summary>
public static Task WriteToFileAsync(
this IArchiveEntry entry,
string destinationFileName,
ExtractionOptions? options = null,
CancellationToken cancellationToken = default
) =>
ExtractionMethods.WriteEntryToFileAsync(
entry,
destinationFileName,
options,
async (x, fm) =>
{
using var fs = File.Open(destinationFileName, fm);
await entry.WriteToAsync(fs, cancellationToken).ConfigureAwait(false);
}
);
}
8 changes: 8 additions & 0 deletions src/SharpCompress/Archives/IWritableArchive.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Writers;

namespace SharpCompress.Archives;
Expand All @@ -18,6 +20,12 @@ IArchiveEntry AddEntry(

void SaveTo(Stream stream, WriterOptions options);

Task SaveToAsync(
Stream stream,
WriterOptions options,
CancellationToken cancellationToken = default
);

/// <summary>
/// Use this to pause entry rebuilding when adding large collections of entries. Dispose when complete. A using statement is recommended.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/SharpCompress/Archives/IWritableArchiveExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Writers;

namespace SharpCompress.Archives;
Expand Down Expand Up @@ -42,6 +44,24 @@ WriterOptions options
writableArchive.SaveTo(stream, options);
}

public static Task SaveToAsync(
this IWritableArchive writableArchive,
string filePath,
WriterOptions options,
CancellationToken cancellationToken = default
) => writableArchive.SaveToAsync(new FileInfo(filePath), options, cancellationToken);

public static async Task SaveToAsync(
this IWritableArchive writableArchive,
FileInfo fileInfo,
WriterOptions options,
CancellationToken cancellationToken = default
)
{
using var stream = fileInfo.Open(FileMode.Create, FileAccess.Write);
await writableArchive.SaveToAsync(stream, options, cancellationToken).ConfigureAwait(false);
}

public static void AddAllFromDirectory(
this IWritableArchive writableArchive,
string filePath,
Expand Down
26 changes: 26 additions & 0 deletions src/SharpCompress/Archives/Tar/TarArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Tar;
using SharpCompress.Common.Tar.Headers;
Expand Down Expand Up @@ -242,6 +244,30 @@ IEnumerable<TarArchiveEntry> newEntries
}
}

protected override async Task SaveToAsync(
Stream stream,
WriterOptions options,
IEnumerable<TarArchiveEntry> oldEntries,
IEnumerable<TarArchiveEntry> newEntries,
CancellationToken cancellationToken = default
)
{
using var writer = new TarWriter(stream, new TarWriterOptions(options));
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using var entryStream = entry.OpenEntryStream();
await writer
.WriteAsync(
entry.Key.NotNull("Entry Key is null"),
entryStream,
entry.LastModifiedTime,
entry.Size,
cancellationToken
)
.ConfigureAwait(false);
}
}

protected override IReader CreateReaderForSolidExtraction()
{
var stream = Volumes.Single().Stream;
Expand Down
20 changes: 20 additions & 0 deletions src/SharpCompress/Archives/Zip/ZipArchive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Zip;
using SharpCompress.Common.Zip.Headers;
Expand Down Expand Up @@ -317,6 +319,24 @@ IEnumerable<ZipArchiveEntry> newEntries
}
}

protected override async Task SaveToAsync(
Stream stream,
WriterOptions options,
IEnumerable<ZipArchiveEntry> oldEntries,
IEnumerable<ZipArchiveEntry> newEntries,
CancellationToken cancellationToken = default
)
{
using var writer = new ZipWriter(stream, new ZipWriterOptions(options));
foreach (var entry in oldEntries.Concat(newEntries).Where(x => !x.IsDirectory))
{
using var entryStream = entry.OpenEntryStream();
await writer
.WriteAsync(entry.Key.NotNull("Entry Key is null"), entryStream, cancellationToken)
.ConfigureAwait(false);
}
}

protected override ZipArchiveEntry CreateEntryInternal(
string filePath,
Stream source,
Expand Down
36 changes: 36 additions & 0 deletions src/SharpCompress/Writers/Tar/TarWriter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Common;
using SharpCompress.Common.Tar.Headers;
using SharpCompress.Compressors;
Expand Down Expand Up @@ -91,6 +93,40 @@ public void Write(string filename, Stream source, DateTime? modificationTime, lo
PadTo512(size.Value);
}

public override async Task WriteAsync(
string filename,
Stream source,
DateTime? modificationTime,
CancellationToken cancellationToken = default
) => await WriteAsync(filename, source, modificationTime, null, cancellationToken);

public async Task WriteAsync(
string filename,
Stream source,
DateTime? modificationTime,
long? size,
CancellationToken cancellationToken = default
)
{
if (!source.CanSeek && size is null)
{
throw new ArgumentException("Seekable stream is required if no size is given.");
}

var realSize = size ?? source.Length;

var header = new TarHeader(WriterOptions.ArchiveEncoding);

header.LastModifiedTime = modificationTime ?? TarHeader.EPOCH;
header.Name = NormalizeFilename(filename);
header.Size = realSize;
header.Write(OutputStream);
var written = await source
.TransferToAsync(OutputStream, realSize, cancellationToken)
.ConfigureAwait(false);
PadTo512(written);
}

private void PadTo512(long size)
{
var zeros = unchecked((int)(((size + 511L) & ~511L) - size));
Expand Down
Loading