Support distributions that ship a full .img (Raspberry Pi OS, moode, RetroPie, Manjaro ARM) rather than a rootfs tarball, by loop-mounting the image and copying its boot + root partitions into a fresh LUKS container. - distributions.yml/catalog.py/choosers.py: raspios catalog (lite64/desktop64/ lite32 via the stable _latest redirects) + choose_raspios. - plan.py: source_url override so a _latest redirect downloads under an .img.xz name that decompress_command recognises. - transfer.py: transfer_disk_image (loop-mount -> repartition -> LUKS -> rsync copy with progress, cp fallback -> fix boot fstab); transfer_image gains interactive= and routes encrypted non-arch images here; download_image gains force_prompt. - loopimg.py: losetup attach/detach/partition helper. - fsutil.drop_fstab_mount + register_encrypted_root: replace a stock image's existing / fstab line instead of colliding with it. - encryption.configure_encryption returns the onion address. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
39 lines
1.2 KiB
Python
39 lines
1.2 KiB
Python
"""The image setup plan collected from the user's answers."""
|
|
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
DEFAULT_BOOT_SIZE = "+500M"
|
|
|
|
|
|
@dataclass
|
|
class ImagePlan:
|
|
operation_system: str = "linux"
|
|
distribution: str | None = None
|
|
base_download_url: str | None = None
|
|
image_name: str | None = None
|
|
# Direct download URL when it cannot be derived as base_download_url + image_name
|
|
# (Raspberry Pi OS ships behind a "_latest" redirect but must land under a
|
|
# .img.xz name so decompress_command recognises it).
|
|
source_url: str | None = None
|
|
image_checksum: str | None = None
|
|
boot_size: str = ""
|
|
luks_memory_cost: str | None = None
|
|
raspberry_pi_version: str | None = None
|
|
encrypt_system: bool = False
|
|
tor_unlock: bool = False
|
|
root_filesystem: str = ""
|
|
image_folder: Path = field(default_factory=Path)
|
|
|
|
@property
|
|
def download_url(self) -> str | None:
|
|
if self.source_url is not None:
|
|
return self.source_url
|
|
if self.base_download_url is None or self.image_name is None:
|
|
return None
|
|
return f"{self.base_download_url}{self.image_name}"
|
|
|
|
@property
|
|
def image_path(self) -> Path:
|
|
return self.image_folder / self.image_name
|