Deduplicated, encrypted, authenticated and compressed backups
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Mounting archives as filesystems for browsing and selective file restoration, providing direct access to backup contents without full extraction.
import subprocess
import osMount archives as read-only filesystems for browsing and selective file access.
def mount_archive(repo_path: str, mount_point: str, archive_name: str = None,
foreground: bool = False, numeric_owner: bool = False,
strip_components: int = None, **options) -> None:
"""
Mount archive as filesystem.
Args:
repo_path: Path to repository
mount_point: Directory to mount at
archive_name: Specific archive to mount (optional, mounts all if not specified)
foreground: Run in foreground (default: background daemon)
numeric_owner: Show numeric user/group IDs
strip_components: Strip N leading path components
**options: Additional options like first, last, glob_archives
"""
cmd = ['borg', 'mount']
if foreground:
cmd.append('--foreground')
if numeric_owner:
cmd.append('--numeric-owner')
if strip_components:
cmd.extend(['--strip-components', str(strip_components)])
if options.get('first'):
cmd.extend(['--first', str(options['first'])])
if options.get('last'):
cmd.extend(['--last', str(options['last'])])
if options.get('glob_archives'):
cmd.extend(['--glob-archives', options['glob_archives']])
if archive_name:
cmd.append(f'{repo_path}::{archive_name}')
else:
cmd.append(repo_path)
cmd.append(mount_point)
subprocess.run(cmd, check=True)
def unmount_archive(mount_point: str) -> None:
"""
Unmount archive filesystem.
Args:
mount_point: Directory to unmount
"""
cmd = ['borg', 'umount', mount_point]
subprocess.run(cmd, check=True)Usage example:
import subprocess
import os
# Create mount point
os.makedirs('/mnt/backup', exist_ok=True)
# Mount specific archive
subprocess.run([
'borg', 'mount', '/backup/repo::documents-2023-12-01', '/mnt/backup'
], check=True)
# Browse mounted archive (now you can use regular file operations)
# files = os.listdir('/mnt/backup')
# with open('/mnt/backup/home/user/important.txt', 'r') as f:
# content = f.read()
# Unmount when done
subprocess.run(['borg', 'umount', '/mnt/backup'], check=True)
# Mount all archives (creates subdirectories for each archive)
subprocess.run(['borg', 'mount', '/backup/repo', '/mnt/all-backups'], check=True)Access mounted archives with full filesystem features including browsing, copying, and searching.
def mount_with_options(repo_path: str, mount_point: str,
archive_pattern: str = None, versions_view: bool = False,
allow_damaged_files: bool = False) -> None:
"""
Mount with advanced FUSE options.
Args:
repo_path: Path to repository
mount_point: Directory to mount at
archive_pattern: Glob pattern for archive selection
versions_view: Enable versions view (shows all versions of files)
allow_damaged_files: Allow access to damaged files
"""
cmd = ['borg', 'mount']
if archive_pattern:
cmd.extend(['--glob-archives', archive_pattern])
if versions_view:
cmd.append('--versions-view')
if allow_damaged_files:
cmd.append('--consider-damaged-chunks')
cmd.extend([repo_path, mount_point])
subprocess.run(cmd, check=True)Usage example:
import subprocess
import os
import shutil
# Mount with pattern matching
subprocess.run([
'borg', 'mount', '--glob-archives=documents-*',
'/backup/repo', '/mnt/documents'
], check=True)
# Copy specific files from mounted archive
source_path = '/mnt/documents/documents-2023-12-01/home/user/important.txt'
if os.path.exists(source_path):
shutil.copy2(source_path, '/restore/important.txt')
# Search for files in mounted archive
def find_files(mount_path, pattern):
"""Find files matching pattern in mounted archive"""
matches = []
for root, dirs, files in os.walk(mount_path):
for file in files:
if pattern in file:
matches.append(os.path.join(root, file))
return matches
# Find all PDF files
pdf_files = find_files('/mnt/documents', '.pdf')
# Unmount
subprocess.run(['borg', 'umount', '/mnt/documents'], check=True)Serve repository contents via HTTP for web-based browsing (if borg-web or similar tools are available).
def serve_web_interface(repo_path: str, host: str = '127.0.0.1',
port: int = 8080, readonly: bool = True) -> None:
"""
Serve repository via web interface (requires additional tools).
Args:
repo_path: Path to repository
host: Host interface to bind to
port: Port to serve on
readonly: Serve in read-only mode
Note: This requires additional tools like borg-web or borgmatic-web
"""
# This is a conceptual example - actual implementation depends on web interface tool
cmd = ['borg-web', '--repo', repo_path, '--host', host, '--port', str(port)]
if readonly:
cmd.append('--readonly')
subprocess.run(cmd, check=True)Utility functions for programmatically browsing mounted archives.
def browse_archive(mount_point: str, callback_func = None) -> dict:
"""
Programmatically browse mounted archive contents.
Args:
mount_point: Path to mounted archive
callback_func: Optional callback for each file/directory
Returns:
Dictionary with archive structure and file information
"""
archive_contents = {}
for root, dirs, files in os.walk(mount_point):
rel_root = os.path.relpath(root, mount_point)
archive_contents[rel_root] = {
'directories': dirs,
'files': []
}
for file in files:
file_path = os.path.join(root, file)
try:
stat = os.stat(file_path)
file_info = {
'name': file,
'size': stat.st_size,
'mtime': stat.st_mtime,
'mode': stat.st_mode
}
archive_contents[rel_root]['files'].append(file_info)
if callback_func:
callback_func(file_path, file_info)
except OSError:
# Handle potential issues with damaged files
pass
return archive_contents
def extract_files_from_mount(mount_point: str, file_patterns: list,
destination: str) -> list:
"""
Extract specific files from mounted archive.
Args:
mount_point: Path to mounted archive
file_patterns: List of file patterns to extract
destination: Destination directory for extracted files
Returns:
List of successfully extracted file paths
"""
import fnmatch
import shutil
extracted_files = []
os.makedirs(destination, exist_ok=True)
for root, dirs, files in os.walk(mount_point):
for file in files:
file_path = os.path.join(root, file)
rel_path = os.path.relpath(file_path, mount_point)
# Check if file matches any pattern
for pattern in file_patterns:
if fnmatch.fnmatch(rel_path, pattern) or fnmatch.fnmatch(file, pattern):
dest_path = os.path.join(destination, rel_path)
dest_dir = os.path.dirname(dest_path)
os.makedirs(dest_dir, exist_ok=True)
try:
shutil.copy2(file_path, dest_path)
extracted_files.append(dest_path)
except OSError as e:
print(f"Failed to extract {rel_path}: {e}")
break
return extracted_filesUsage example:
import subprocess
import os
# Mount archive
subprocess.run(['borg', 'mount', '/backup/repo::backup-2023-12-01', '/mnt/backup'], check=True)
try:
# Browse archive contents
def file_callback(path, info):
if info['size'] > 1000000: # Files larger than 1MB
print(f"Large file: {path} ({info['size']} bytes)")
contents = browse_archive('/mnt/backup', file_callback)
# Extract specific file types
extracted = extract_files_from_mount('/mnt/backup', ['*.pdf', '*.doc*'], '/restore/documents')
print(f"Extracted {len(extracted)} files")
finally:
# Always unmount
subprocess.run(['borg', 'umount', '/mnt/backup'], check=True)class MountOptions:
"""Mount operation options"""
def __init__(self):
self.repository: str # Repository path
self.archive: str # Archive name (optional)
self.mount_point: str # Mount point directory
self.foreground: bool # Run in foreground
self.numeric_owner: bool # Show numeric IDs
self.strip_components: int # Strip path components
class FileInfo:
"""File information from mounted archive"""
def __init__(self):
self.name: str # File name
self.path: str # Full path
self.size: int # File size in bytes
self.mtime: float # Modification time (timestamp)
self.mode: int # File mode/permissions
self.is_directory: bool # Is directory flag
class ArchiveStructure:
"""Archive directory structure"""
def __init__(self):
self.directories: dict # Directory tree structure
self.files: list # List of all files
self.total_size: int # Total size of all files
self.file_count: int # Total number of files
self.directory_count: int # Total number of directoriesInstall with Tessl CLI
npx tessl i tessl/pypi-borgbackup