fix(clew): extract full archives by default
This commit is contained in:
@@ -12,7 +12,8 @@ bazel run //src/clew -- \
|
|||||||
```
|
```
|
||||||
|
|
||||||
The first version copies loose `.rpy` files and collects compiled script files.
|
The first version copies loose `.rpy` files and collects compiled script files.
|
||||||
It extracts `.rpy`, `.rpyc`, and `.rpymc` files from `.rpa` archives.
|
It extracts all files from `.rpa` archives.
|
||||||
|
Use `--suffix` to limit archive extraction to selected file suffixes.
|
||||||
It writes output under `source/`, `work/`, and `logs/`.
|
It writes output under `source/`, `work/`, and `logs/`.
|
||||||
|
|
||||||
Use `--force` to replace those Clew-managed directories.
|
Use `--force` to replace those Clew-managed directories.
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from rpycdec.rpa import extract_rpa
|
|||||||
|
|
||||||
LOGGER = logging.getLogger("clew")
|
LOGGER = logging.getLogger("clew")
|
||||||
MANAGED_DIRS = ("source", "work", "logs")
|
MANAGED_DIRS = ("source", "work", "logs")
|
||||||
SCRIPT_SUFFIXES = (".rpy", ".rpyc", ".rpymc")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args(argv: list[str]) -> argparse.Namespace:
|
def parse_args(argv: list[str]) -> argparse.Namespace:
|
||||||
@@ -36,6 +35,11 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Replace Clew-managed output directories.",
|
help="Replace Clew-managed output directories.",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--suffix",
|
||||||
|
action="append",
|
||||||
|
help="Extract only archive paths with this suffix.",
|
||||||
|
)
|
||||||
return parser.parse_args(argv)
|
return parser.parse_args(argv)
|
||||||
|
|
||||||
|
|
||||||
@@ -131,19 +135,45 @@ def archive_destination_prefix(archive_relative: Path) -> Path:
|
|||||||
return parent
|
return parent
|
||||||
|
|
||||||
|
|
||||||
def extract_archive(archive: Path, game_root: Path, source_dir: Path, work_dir: Path) -> None:
|
def normalize_suffixes(suffixes: list[str] | None) -> list[str] | None:
|
||||||
|
if suffixes is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
normalized = []
|
||||||
|
for suffix in suffixes:
|
||||||
|
if not suffix:
|
||||||
|
fail("suffix must not be empty")
|
||||||
|
if not suffix.startswith("."):
|
||||||
|
suffix = f".{suffix}"
|
||||||
|
normalized.append(suffix)
|
||||||
|
return normalized
|
||||||
|
|
||||||
|
|
||||||
|
def extract_archive(
|
||||||
|
archive: Path,
|
||||||
|
game_root: Path,
|
||||||
|
source_dir: Path,
|
||||||
|
work_dir: Path,
|
||||||
|
suffixes: list[str] | None,
|
||||||
|
) -> None:
|
||||||
archive_relative = relative_to(game_root, archive)
|
archive_relative = relative_to(game_root, archive)
|
||||||
output_dir = archive_work_path(work_dir, archive_relative)
|
output_dir = archive_work_path(work_dir, archive_relative)
|
||||||
output_dir.mkdir(parents=True, exist_ok=True)
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
LOGGER.info("extracting archive: %s", archive_relative)
|
LOGGER.info("extracting archive: %s", archive_relative)
|
||||||
with archive.open("rb") as handle:
|
with archive.open("rb") as handle:
|
||||||
extract_rpa(handle, output_dir=str(output_dir), suffixes=list(SCRIPT_SUFFIXES))
|
extract_rpa(handle, output_dir=str(output_dir), suffixes=suffixes)
|
||||||
LOGGER.info("extracted archive: %s", archive_relative)
|
LOGGER.info("extracted archive: %s", archive_relative)
|
||||||
|
|
||||||
destination_prefix = archive_destination_prefix(archive_relative)
|
destination_prefix = archive_destination_prefix(archive_relative)
|
||||||
for source_file in sorted(output_dir.rglob("*.rpy")):
|
for source_file in sorted(output_dir.rglob("*.rpy")):
|
||||||
copy_source_file(source_file, output_dir, source_dir, "archived", destination_prefix)
|
copy_source_file(
|
||||||
|
source_file,
|
||||||
|
output_dir,
|
||||||
|
source_dir,
|
||||||
|
"archived",
|
||||||
|
destination_prefix,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def configure_logging(logs_dir: Path) -> None:
|
def configure_logging(logs_dir: Path) -> None:
|
||||||
@@ -166,6 +196,7 @@ def run(args: argparse.Namespace) -> None:
|
|||||||
if not game_root.is_dir():
|
if not game_root.is_dir():
|
||||||
fail(f"game root is not a directory: {game_root}")
|
fail(f"game root is not a directory: {game_root}")
|
||||||
|
|
||||||
|
suffixes = normalize_suffixes(args.suffix)
|
||||||
source_dir, work_dir, logs_dir = prepare_output(output_root, args.force)
|
source_dir, work_dir, logs_dir = prepare_output(output_root, args.force)
|
||||||
configure_logging(logs_dir)
|
configure_logging(logs_dir)
|
||||||
|
|
||||||
@@ -180,7 +211,7 @@ def run(args: argparse.Namespace) -> None:
|
|||||||
|
|
||||||
LOGGER.info("scanning archives")
|
LOGGER.info("scanning archives")
|
||||||
for archive in sorted(game_root.rglob("*.rpa")):
|
for archive in sorted(game_root.rglob("*.rpa")):
|
||||||
extract_archive(archive, game_root, source_dir, work_dir)
|
extract_archive(archive, game_root, source_dir, work_dir, suffixes)
|
||||||
|
|
||||||
LOGGER.info("done")
|
LOGGER.info("done")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user