Skip to content

Commit

Permalink
Add gz compression and use it by default
Browse files Browse the repository at this point in the history
  • Loading branch information
alxndr42 committed Mar 2, 2022
1 parent 9b2ab5e commit ca58ad0
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 33 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Enter passphrase: *****
| Option | Description |
| --- | --- |
| `--comment` | Archive comment. |
| `--compression`, `-c` | Compression for all files: `bz2` or `none` (Default: `bz2`) |
| `--compression`, `-c` | Compression for all files: `bz2`, `gz` or `none` (Default: `gz`) |
| `--mode` | Store file/directory modes. |
| `--mtime` | Store file/directory modification times. |
| `--recipient`, `-r` | Allow another public key/alias to extract. |
Expand Down
33 changes: 23 additions & 10 deletions src/icepack/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import bz2
import gzip
import json
import os
from pathlib import Path
Expand Down Expand Up @@ -95,7 +96,7 @@ def extract_entry(self, entry, base_path):
tmp_path = self._mktemp()
self._decrypt_path(age_path, tmp_path)
age_path.unlink()
self._uncompress_path(tmp_path, dst_path)
self._uncompress_path(tmp_path, dst_path, entry.compression)
tmp_path.unlink()
if self._mode and entry.mode is not None:
dst_path.chmod(entry.mode)
Expand Down Expand Up @@ -136,12 +137,18 @@ def _load_metadata(self):
meta_path.unlink()
sig_path.unlink()

def _uncompress_path(self, src_path, dst_path):
def _uncompress_path(self, src_path, dst_path, compression):
"""Uncompressed src_path to dst_path."""
with open(src_path, 'rb') as src_file:
with bz2.open(src_file, 'rb') as src:
with open(dst_path, 'wb') as dst:
copyfileobj(src, dst, _BUFFER_SIZE)
with open(dst_path, 'wb') as dst:
with open(src_path, 'rb') as src_file:
if compression == Compression.BZ2:
with bz2.open(src_file, 'rb') as src:
copyfileobj(src, dst, _BUFFER_SIZE)
elif compression == Compression.GZ:
with gzip.open(src_file, 'rb') as src:
copyfileobj(src, dst, _BUFFER_SIZE)
else:
raise Exception('Unsupported compression.')


class IcepackWriter(IcepackBase):
Expand All @@ -152,7 +159,7 @@ def __init__(
archive_path,
key_path,
comment=None,
compression=Compression.BZ2,
compression=Compression.GZ,
mode=False,
mtime=False,
recipients=None):
Expand Down Expand Up @@ -236,8 +243,14 @@ def _compress_path(self, src_path):
"""Return the temporary Path of the compressed src_path."""
tmp_path = self._mktemp()
with open(src_path, 'rb') as src:
with bz2.open(tmp_path, 'wb') as dst:
copyfileobj(src, dst, _BUFFER_SIZE)
if self._compression == Compression.BZ2:
with bz2.open(tmp_path, 'wb') as dst:
copyfileobj(src, dst, _BUFFER_SIZE)
elif self._compression == Compression.GZ:
with gzip.open(tmp_path, 'wb') as dst:
copyfileobj(src, dst, _BUFFER_SIZE)
else:
raise Exception('Unsupported compression.')
return tmp_path

def _encrypt_path(self, src_path):
Expand All @@ -255,7 +268,7 @@ def create_archive(
dst_path,
key_path,
comment=None,
compression=Compression.BZ2,
compression=Compression.GZ,
mode=False,
mtime=False,
recipients=None,
Expand Down
4 changes: 2 additions & 2 deletions src/icepack/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def init(ctx):
@click.option('--comment', help='Archive comment.')
@click.option(
'--compression', '-c',
help='Compression for all files.',
help=f'Compression for all files. (Default: {Compression.GZ})',
type=click.Choice([c.value for c in Compression]),
default=Compression.BZ2)
default=Compression.GZ)
@click.option(
'--mode',
help='Store file/directory modes.',
Expand Down
1 change: 1 addition & 0 deletions src/icepack/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Checksum(str, Enum):
class Compression(str, Enum):
"""Supported compression types."""
BZ2 = 'bz2'
GZ = 'gz'
NONE = 'none'


Expand Down
63 changes: 43 additions & 20 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,50 @@ def test_init_existing_keys(key_path):
assert secret_path.read_text() == secret_key


def test_round_trip_directory(src_path, dst_path, zip_path, key_path):
"""Test creation and extraction of a directory."""
def test_bz2_compression(src_path, dst_path, zip_path, key_path):
"""Test round-trip with "bz2" compression."""
# Create archive
args = ['-c', str(key_path), 'create', str(src_path), str(zip_path)]
args = [
'-c', str(key_path),
'create',
'--compression', 'bz2',
str(src_path), str(zip_path)]
run_cli(args)
# Extract archive
args = ['-c', str(key_path), 'extract', str(zip_path), str(dst_path)]
run_cli(args)
# Compare directories
for src in File.children(src_path):
dst = dst_path / src.relative_to(src_path.parent)
compare_paths(src, dst)


def test_gz_compression(src_path, dst_path, zip_path, key_path):
"""Test round-trip with "gz" compression."""
# Create archive
args = [
'-c', str(key_path),
'create',
'--compression', 'gz',
str(src_path), str(zip_path)]
run_cli(args)
# Extract archive
args = ['-c', str(key_path), 'extract', str(zip_path), str(dst_path)]
run_cli(args)
# Compare directories
for src in File.children(src_path):
dst = dst_path / src.relative_to(src_path.parent)
compare_paths(src, dst)


def test_none_compression(src_path, dst_path, zip_path, key_path):
"""Test round-trip with "none" compression."""
# Create archive
args = [
'-c', str(key_path),
'create',
'--compression', 'none',
str(src_path), str(zip_path)]
run_cli(args)
# Extract archive
args = ['-c', str(key_path), 'extract', str(zip_path), str(dst_path)]
Expand Down Expand Up @@ -77,23 +117,6 @@ def test_comment(src_path, dst_path, zip_path, key_path):
assert 'Hello, World!' in result.stdout


def test_none_compression(src_path, dst_path, zip_path, key_path):
"""Test round-trip with "none" compression."""
# Create archive
args = [
'-c', str(key_path),
'create', '--compression', 'none',
str(src_path), str(zip_path)]
run_cli(args)
# Extract archive
args = ['-c', str(key_path), 'extract', str(zip_path), str(dst_path)]
run_cli(args)
# Compare directories
for src in File.children(src_path):
dst = dst_path / src.relative_to(src_path.parent)
compare_paths(src, dst)


def test_mode_flag(src_path, dst_path, zip_path, key_path):
"""Test creation and extraction with --mode."""
(src_path / 'foo').chmod(0o755)
Expand Down

0 comments on commit ca58ad0

Please sign in to comment.