Skip to content

Adds support for several compression algorithms #42

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 42 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
37b7cc2
progress on zlib
santisq Apr 15, 2025
35b45b5
progress on deflate
santisq Apr 15, 2025
8759f03
progress on brotli
santisq Apr 15, 2025
89d7ef8
replaces existing logic for Gzip adding package SharpZipLib
santisq Apr 15, 2025
1c15427
bunch of alias renaming
santisq Apr 15, 2025
73de2b5
few improvements on existing classes
santisq Apr 15, 2025
2c8e6b0
few improvements on existing classes
santisq Apr 15, 2025
43ea188
hides CompressionLevel parameter for ConvertToBrotliStringCommand
santisq Apr 18, 2025
48c929c
adds base class CommandToCompressedFileBase to use in all compression…
santisq Apr 18, 2025
60745ea
adds base class CommandToCompressedFileBase to use in all compression…
santisq Apr 18, 2025
448840c
adds warning if CompressionLevel on Brotli commands
santisq Apr 18, 2025
c904428
Brotli has SetQuality method :facepalm:
santisq Apr 18, 2025
9e2371f
Brotli has SetQuality method :facepalm:
santisq Apr 18, 2025
08d5f13
better naming for ext. methods
santisq Apr 18, 2025
6470492
extension method to create compressed brotli stream
santisq Apr 18, 2025
43616cf
huge update
santisq Jun 17, 2025
72a45f1
fixing tests
santisq Jun 17, 2025
9fb9375
adding to and from compression tests
santisq Jun 17, 2025
be1707d
adding some compresstararchive tests
santisq Jun 17, 2025
01df67c
adding some compresstararchive tests
santisq Jun 17, 2025
a6e001e
missing .test.ps1 file name on test file
santisq Jun 17, 2025
6cbe59c
chagning Brotli.NET to BrotliSharpLib :pray:
santisq Jun 17, 2025
51f14ca
updating changelog
santisq Jun 17, 2025
02f9350
starting with expandtararchivecommand
santisq Jun 18, 2025
53734f4
done with expandtararchive
santisq Jun 19, 2025
727e159
some code improvements. simplifications...
santisq Jun 19, 2025
45484e9
adding tests
santisq Jun 19, 2025
93a994b
adding tests
santisq Jun 21, 2025
5787df4
adding tests
santisq Jun 21, 2025
0097c37
adding tests
santisq Jun 21, 2025
06ec32c
adds gettarentrycommand tests
santisq Jun 21, 2025
f1abe36
corrects a few tests
santisq Jun 21, 2025
822adae
corrects a few tests
santisq Jun 21, 2025
985bf60
bug...
santisq Jun 21, 2025
68e1af6
bug...
santisq Jun 21, 2025
63d30c7
adding tests for GetTarEntryContent command
santisq Jun 22, 2025
e7c1563
adding tests for GetTarEntryContent command
santisq Jun 22, 2025
41b36dd
typo..
santisq Jun 22, 2025
148d655
typo..
santisq Jun 22, 2025
655c24a
adds expandtarentry command tests
santisq Jun 22, 2025
d5dbc54
i tink done with tests
santisq Jun 22, 2025
438ca51
i tink done with tests
santisq Jun 22, 2025
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
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# CHANGELOG

## 06/17/2025

- Added commands supporting several algorithms to compress and decompress strings:
- `ConvertFrom-BrotliString` & `ConvertTo-BrotliString` (using to BrotliSharpLib)
- `ConvertFrom-DeflateString` & `ConvertTo-DeflateString` (from CLR)
- `ConvertFrom-ZlibString` & `ConvertTo-ZlibString` (custom implementation)
- Added commands for `.tar` entry management with a reduced set of operations compared to `zip` entry management:
- `Get-TarEntry`: Lists entries, serving as the main entry point for `TarEntry` cmdlets.
- `Get-TarEntryContent`: Retrieves the content of a tar entry.
- `Expand-TarEntry`: Extracts a tar entry to a file.
- Added commands to compress files and folders into `.tar` archives and extract `.tar` archives with various compression algorithms:
- `Compress-TarArchive` and `Expand-TarArchive`: Supported compression algorithms include `gz`, `bz2`, `zst`, `lz`, and `none` (no compression).
- Removed commands:
- `Compress-GzipArchive` and `Expand-GzipArchive`: These were deprecated as they only supported single-file compression, which is now better handled by the module’s `.tar` archive functionality.

This update was made possible by the following projects. If you find them helpful, please consider starring their repositories:

- [SharpZipLib](https://github.com/icsharpcode/SharpZipLib)
- [SharpCompress](https://github.com/adamhathcock/sharpcompress)
- [BrotliSharpLib](https://github.com/master131/BrotliSharpLib)

## 01/10/2025

- Code improvements.
Expand Down
2 changes: 1 addition & 1 deletion build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ if (-not ('ProjectBuilder.ProjectInfo' -as [type])) {
}
}

$projectInfo = [ProjectBuilder.ProjectInfo]::Create($PSScriptRoot, $Configuration)
$projectInfo = [ProjectBuilder.ProjectInfo]::Create($PSScriptRoot, $Configuration, $PSVersionTable.PSVersion)
$projectInfo.GetRequirements() | Import-Module -DisableNameChecking -Force

$ErrorActionPreference = $prev
Expand Down
6 changes: 3 additions & 3 deletions docs/en-US/Get-ZipEntryContent.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Gets the content of a zip entry.

```powershell
Get-ZipEntryContent
-ZipEntry <ZipEntryFile[]>
-Entry <ZipEntryFile[]>
[-Encoding <Encoding>]
[-Raw]
[<CommonParameters>]
Expand All @@ -27,7 +27,7 @@ Get-ZipEntryContent

```powershell
Get-ZipEntryContent
-ZipEntry <ZipEntryFile[]>
-Entry <ZipEntryFile[]>
[-Raw]
[-AsByteStream]
[-BufferSize <Int32>]
Expand Down Expand Up @@ -183,7 +183,7 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -ZipEntry
### -Entry

The entry or entries to get the content from. This parameter can be and is meant to be bound from pipeline however can be also used as a named parameter.

Expand Down
57 changes: 56 additions & 1 deletion module/PSCompression.Format.ps1xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<View>
<Name>zipentryview</Name>
<ViewSelectedBy>
<TypeName>PSCompression.ZipEntryBase</TypeName>
<TypeName>PSCompression.Abstractions.ZipEntryBase</TypeName>
</ViewSelectedBy>
<GroupBy>
<ScriptBlock>[PSCompression.Internal._Format]::GetDirectoryPath($_)</ScriptBlock>
Expand Down Expand Up @@ -68,5 +68,60 @@
</TableRowEntries>
</TableControl>
</View>
<View>
<Name>tarentryview</Name>
<ViewSelectedBy>
<TypeName>PSCompression.Abstractions.TarEntryBase</TypeName>
</ViewSelectedBy>
<GroupBy>
<ScriptBlock>[PSCompression.Internal._Format]::GetDirectoryPath($_)</ScriptBlock>
<Label>Directory</Label>
</GroupBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Type</Label>
<Width>10</Width>
<Alignment>Left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>LastWriteTime</Label>
<Width>26</Width>
<Alignment>Right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Size</Label>
<Width>15</Width>
<Alignment>Right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Name</Label>
<Alignment>Left</Alignment>
</TableColumnHeader>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Type</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>[PSCompression.Internal._Format]::GetFormattedDate($_.LastWriteTime)</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>
if ($_ -is [PSCompression.TarEntryFile]) {
[PSCompression.Internal._Format]::GetFormattedLength($_.Length)
}
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Name</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>
40 changes: 30 additions & 10 deletions module/PSCompression.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
RootModule = 'bin/netstandard2.0/PSCompression.dll'

# Version number of this module.
ModuleVersion = '2.1.0'
ModuleVersion = '3.0.0'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -83,24 +83,40 @@
'Expand-ZipEntry'
'ConvertTo-GzipString'
'ConvertFrom-GzipString'
'Expand-GzipArchive'
'Compress-GzipArchive'
'Compress-ZipArchive'
'Rename-ZipEntry'
'ConvertFrom-ZLibString'
'ConvertTo-ZLibString'
'ConvertFrom-DeflateString'
'ConvertTo-DeflateString'
'ConvertFrom-BrotliString'
'ConvertTo-BrotliString'
'Compress-TarArchive'
'Get-TarEntry'
'Get-TarEntryContent'
'Expand-TarEntry'
'Expand-TarArchive'
)

# Variables to export from this module
VariablesToExport = @()

# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
AliasesToExport = @(
'gziptofile'
'gzipfromfile'
'gziptostring'
'gzipfromstring'
'zip'
'ziparchive'
'gze'
'togzipstring'
'fromgzipstring'
'zipcompress'
'fromzlibstring'
'tozlibstring'
'fromdeflatestring'
'todeflatestring'
'frombrotlistring'
'tobrotlistring'
'zipge'
'zipgc'
'tarcompress'
'targe'
'targc'
)

# DSC resources to export from this module
Expand All @@ -122,6 +138,10 @@
'zip-compression'
'gzip'
'gzip-compression'
'zlib'
'zlib-compression'
'deflate'
'deflate-compression'
'compression'
'csharp'
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using PSCompression.Exceptions;
using PSCompression.Extensions;

namespace PSCompression;
namespace PSCompression.Abstractions;

[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class CommandWithPathBase : PSCmdlet
Expand Down
31 changes: 31 additions & 0 deletions src/PSCompression/Abstractions/EntryBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.IO;

namespace PSCompression.Abstractions;

public abstract class EntryBase(string source)
{
protected Stream? _stream;

protected string? _formatDirectoryPath;

internal string? FormatDirectoryPath { get => _formatDirectoryPath ??= GetFormatDirectoryPath(); }

internal bool FromStream { get => _stream is not null; }

public string Source { get; } = source;

public abstract string Name { get; protected set; }

public abstract string RelativePath { get; }

public abstract DateTime LastWriteTime { get; }

public abstract long Length { get; internal set; }

public abstract EntryType Type { get; }

protected abstract string GetFormatDirectoryPath();

public override string ToString() => RelativePath;
}
70 changes: 70 additions & 0 deletions src/PSCompression/Abstractions/ExpandEntryCommandBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using System;
using System.IO;
using System.Management.Automation;
using PSCompression.Extensions;
using PSCompression.Exceptions;
using System.ComponentModel;

namespace PSCompression.Abstractions;

[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class ExpandEntryCommandBase<T> : PSCmdlet
where T : EntryBase
{
[Parameter(Mandatory = true, ValueFromPipeline = true)]
public T[] InputObject { get; set; } = null!;

[Parameter(Position = 0)]
[ValidateNotNullOrEmpty]
public string? Destination { get; set; }

[Parameter]
public SwitchParameter Force { get; set; }

[Parameter]
public SwitchParameter PassThru { get; set; }

protected override void BeginProcessing()
{
Destination = Destination is null
// PowerShell is retarded and decided to mix up ProviderPath & Path
? SessionState.Path.CurrentFileSystemLocation.ProviderPath
: Destination.ResolvePath(this);

if (File.Exists(Destination))
{
ThrowTerminatingError(ExceptionHelper.NotDirectoryPath(
Destination, nameof(Destination)));
}

Check warning on line 38 in src/PSCompression/Abstractions/ExpandEntryCommandBase.cs

View check run for this annotation

Codecov / codecov/patch

src/PSCompression/Abstractions/ExpandEntryCommandBase.cs#L38

Added line #L38 was not covered by tests

Directory.CreateDirectory(Destination);
}

protected override void ProcessRecord()
{
Dbg.Assert(Destination is not null);

foreach (T entry in InputObject)
{
try
{
FileSystemInfo info = Extract(entry);

if (PassThru)
{
WriteObject(info.AppendPSProperties());
}
}
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;

Check warning on line 60 in src/PSCompression/Abstractions/ExpandEntryCommandBase.cs

View check run for this annotation

Codecov / codecov/patch

src/PSCompression/Abstractions/ExpandEntryCommandBase.cs#L59-L60

Added lines #L59 - L60 were not covered by tests
}
catch (Exception exception)
{
WriteError(exception.ToExtractEntryError(entry));
}

Check warning on line 65 in src/PSCompression/Abstractions/ExpandEntryCommandBase.cs

View check run for this annotation

Codecov / codecov/patch

src/PSCompression/Abstractions/ExpandEntryCommandBase.cs#L65

Added line #L65 was not covered by tests
}
}

protected abstract FileSystemInfo Extract(T entry);
}
65 changes: 65 additions & 0 deletions src/PSCompression/Abstractions/FromCompressedStringCommandBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;
using System.ComponentModel;
using System.IO;
using System.Management.Automation;
using System.Text;
using PSCompression.Exceptions;
using PSCompression.Extensions;

namespace PSCompression.Abstractions;

[EditorBrowsable(EditorBrowsableState.Never)]
public abstract class FromCompressedStringCommandBase : PSCmdlet
{
protected delegate Stream DecompressionStreamFactory(Stream inputStream);

[Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0)]
public string[] InputObject { get; set; } = null!;

[Parameter]
[ArgumentCompleter(typeof(EncodingCompleter))]
[EncodingTransformation]
[ValidateNotNullOrEmpty]
public Encoding Encoding { get; set; } = new UTF8Encoding();

[Parameter]
public SwitchParameter Raw { get; set; }

private void Decompress(
string base64string,
DecompressionStreamFactory decompressionStreamFactory)
{
using MemoryStream inStream = new(Convert.FromBase64String(base64string));
using Stream decompressStream = decompressionStreamFactory(inStream);
using StreamReader reader = new(decompressStream, Encoding);

if (Raw)
{
reader.WriteAllTextToPipeline(this);
return;
}

reader.WriteLinesToPipeline(this);
}

protected abstract Stream CreateDecompressionStream(Stream inputStream);

protected override void ProcessRecord()
{
foreach (string line in InputObject)
{
try
{
Decompress(line, CreateDecompressionStream);
}
catch (Exception _) when (_ is PipelineStoppedException or FlowControlException)
{
throw;

Check warning on line 57 in src/PSCompression/Abstractions/FromCompressedStringCommandBase.cs

View check run for this annotation

Codecov / codecov/patch

src/PSCompression/Abstractions/FromCompressedStringCommandBase.cs#L56-L57

Added lines #L56 - L57 were not covered by tests
}
catch (Exception exception)
{
WriteError(exception.ToEnumerationError(line));
}

Check warning on line 62 in src/PSCompression/Abstractions/FromCompressedStringCommandBase.cs

View check run for this annotation

Codecov / codecov/patch

src/PSCompression/Abstractions/FromCompressedStringCommandBase.cs#L62

Added line #L62 was not covered by tests
}
}
}
Loading