# pyarchive

Multi-format project archiver supporting ZIP, TAR, 7z, and NSIS formats with configurable compression levels.

## Overview

PyArchive is a comprehensive Python archiving tool designed to package project build outputs into various archive formats. It follows modern design patterns and provides a clean, type-safe API for creating distribution packages.

## Design Patterns

This module implements several established design patterns:

- **Dataclass Pattern**: Configuration management with automatic persistence
- **Frozen Dataclass Pattern**: Immutable archiver instances for thread safety
- **Strategy Pattern**: Different archive format implementations
- **Factory Pattern**: Dynamic archive function selection based on format
- **Builder Pattern**: NSIS script generation with modular components
- **Singleton Pattern**: Global logging configuration
- **Enum Pattern**: Type-safe format definitions

## Features

- **Multiple Archive Formats**: Supports 7 different compression formats
- **Configurable Compression**: Adjustable compression levels (0-9)
- **Flexible Filtering**: Customizable ignore patterns
- **Batch Processing**: Archive multiple projects at once
- **Permission Preservation**: Maintain file permissions in TAR formats
- **Cross-platform**: Works on Windows, macOS, and Linux

## Supported Formats

| Format  | Description                          | Extension    | Compression |
| ------- | ------------------------------------ | ------------ | ----------- |
| `zip`   | ZIP archive with DEFLATE compression | `.zip`       | Yes         |
| `tar`   | TAR archive (no compression)         | `.tar`       | No          |
| `gztar` | TAR with gzip compression            | `.tar.gz`    | Yes         |
| `bztar` | TAR with bzip2 compression           | `.tar.bz2`   | Yes         |
| `xztar` | TAR with xz compression              | `.tar.xz`    | Yes         |
| `7z`    | 7-Zip archive (high compression)     | `.7z`        | Yes         |
| `nsis`  | NSIS Windows installer               | `-setup.exe` | Yes         |

## Installation

```bash
# Install via pip
pip install pyarchive

# Or install in development mode
pip install -e .
```

## Usage

### Command Line Interface

```bash
# Basic usage - archive all projects in current directory as ZIP
pyarchive

# Specify directory and format
pyarchive /path/to/projects --format gztar

# Archive specific projects only
pyarchive --project myproject1 myproject2 --format zip

# High compression level
pyarchive --compression-level 9 --format xztar

# Verbose output
pyarchive --verbose --format bztar

# Preserve file permissions (TAR formats)
pyarchive --format tar --preserve-permissions

# Custom ignore patterns
pyarchive --ignore "*.tmp" "temp/*" --format zip
```

### Command Line Options

```bash
positional arguments:
  directory             Directory to archive for projects. (default: current directory)

optional arguments:
  -h, --help            show this help message and exit
  --debug, -d           Debug mode
  --verbose, -v         Verbose output during archiving
  --format FORMAT, -f FORMAT
                        Archive format (default: zip)
  --compression-level {0,1,2,3,4,5,6,7,8,9}, -c {0,1,2,3,4,5,6,7,8,9}
                        Compression level (0-9, default: 6)
  --preserve-permissions, -P
                        Preserve file permissions (TAR formats only)
  --project PROJECT [PROJECT ...], -p PROJECT [PROJECT ...]
                        Specific project(s) to archive (default: all projects)
  --ignore IGNORE [IGNORE ...]
                        Additional ignore patterns
```

### Python API

```python
from pathlib import Path
from sfi.pyarchive.pyarchive import (
    PyArchiver,
    PyArchiveConfig,
    ArchiveFormat
)

# Basic usage with default configuration
archiver = PyArchiver(root_dir=Path("./projects"))
success, total = archiver.archive_projects(format="zip")
print(f"Archived {success}/{total} projects")

# Advanced usage with custom configuration
config = PyArchiveConfig(
    compression_level=9,
    verbose=True,
    preserve_permissions=True,
    output_dir="custom_build",
    dist_dir="custom_dist"
)

archiver = PyArchiver(root_dir=Path("./projects"), config=config)

# Archive specific projects
success, total = archiver.archive_projects(
    format="gztar",
    projects_to_archive=["myproject1", "myproject2"],
    ignore_patterns={"*.log", "__pycache__"}
)

# Get archive information without creating it
project = archiver.projects["myproject"]
info = archiver.get_archive_info(project, format="zip")
print(f"Output: {info['output_file']}")
print(f"Source size: {info.get('source_size_mb', 0)} MB")

# Using format enumeration
for fmt in ArchiveFormat:
    print(f"{fmt.value}: {fmt.description}")
```

### Configuration Persistence

PyArchive automatically saves and loads configuration from `~/.pysfi/pyarchive.json`:

```python
# Configuration is automatically saved on exit
config = PyArchiveConfig(compression_level=8, verbose=True)
archiver = PyArchiver(root_dir=Path("."), config=config)
# Config will be persisted automatically

# Manual save
config.save()
```

### Error Handling

PyArchive provides custom exceptions for better error handling:

```python
from sfi.pyarchive.pyarchive import (
    PyArchiver,
    ArchiveError,
    ArchiveFormatError,
    ArchiveCommandError,
    ArchiveCreationError
)

try:
    archiver = PyArchiver(root_dir=Path("./projects"))
    success, total = archiver.archive_projects(format="zip")
    
    if success < total:
        print(f"Warning: Only {success}/{total} projects archived successfully")
        
except ArchiveFormatError as e:
    print(f"Unsupported format: {e}")
except ArchiveCommandError as e:
    print(f"External command not available: {e}")
except ArchiveError as e:
    print(f"Archive operation failed: {e}")
```

## Format Comparison

Different formats offer various trade-offs between compression ratio, speed, and compatibility:

| Format  | Speed  | Compression | Compatibility  | Best For              |
| ------- | ------ | ----------- | -------------- | --------------------- |
| `zip`   | Fast   | Medium      | Universal      | General purpose       |
| `tar`   | Fast   | None        | Unix/Linux     | Uncompressed archives |
| `gztar` | Medium | Good        | Universal      | Balanced compression  |
| `bztar` | Slow   | Very Good   | Universal      | High compression      |
| `xztar` | Slow   | Excellent   | Modern systems | Maximum compression   |
| `7z`    | Slow   | Excellent   | Windows/Linux  | High compression      |
| `nsis`  | Slow   | Good        | Windows only   | Windows installers    |

## Examples

### Archive All Projects with Different Formats

```bash
# Create ZIP archives (fast, good compatibility)
pyarchive --format zip

# Create highly compressed XZ archives (slow, excellent compression)
pyarchive --format xztar --compression-level 9

# Create 7-Zip archives (good balance of speed and compression)
pyarchive --format 7z --compression-level 7
```

### Selective Archiving

```bash
# Archive only specific projects
pyarchive --project docscan img2pdf --format gztar

# Archive with custom ignore patterns
pyarchive --ignore "*.pyc" "__pycache__" "*.log" --format zip
```

### Production Usage

```bash
# Production build with maximum compression
pyarchive --format xztar --compression-level 9 --verbose

# Quick backup with medium compression
pyarchive --format gztar --compression-level 6

# Windows deployment package
pyarchive --format nsis --compression-level 7
```

## Configuration

The tool uses sensible defaults but can be customized:

- **Default format**: `zip`
- **Default compression level**: `6`
- **Default ignore patterns**: Common build artifacts and cache files
- **Output directory**: `build/` subdirectory in project root

## Requirements

- Python 3.8+
- For 7z format: 7-Zip must be installed and in PATH
- For NSIS format: NSIS (Nullsoft Scriptable Install System) must be installed and in PATH

## Integration with Other Tools

`pyarchive` works seamlessly with other pysfi tools:

```bash
# Typical workflow
pypack build          # Build projects
pyarchive --format zip # Archive built projects
```

## License

MIT License - see LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues.
