refactor(release): remove playtest plugin handling and simplify ZIP creation
- Eliminated the removal of playtest plugins from the archived plugins.js during ZIP creation. - Updated documentation to reflect changes in the exclusion of playtest plugins and other tool artifacts. - Adjusted tests to ensure that the plugins.js file retains all installed plugins, including TLInspector and Forge_MZ.
This commit is contained in:
parent
74c23ebe87
commit
d7ab5b6851
4 changed files with 11 additions and 96 deletions
|
|
@ -4397,8 +4397,6 @@ class WolfWorkflowTab(QWidget):
|
|||
f" Added {result.files_added} file(s), omitted "
|
||||
f"{result.excluded_entries} tool/private item(s)."
|
||||
)
|
||||
if result.sanitized_plugin_lists:
|
||||
log(" Removed playtest plugins from the archived plugins.js.")
|
||||
return True, (
|
||||
f"Created {result.output_path.name} ({size_mb:.1f} MB) at "
|
||||
f"{result.output_path}."
|
||||
|
|
|
|||
|
|
@ -526,7 +526,7 @@ _STEP_HELP: dict[int, str] = {
|
|||
"• <b>Export ALL</b> - everything under <code>translated/</code><br><br>"
|
||||
"<b>Create Public Release ZIP</b> packages the complete game beside its folder while "
|
||||
"omitting translator workspaces, VCS metadata, documentation, backups, saves, and "
|
||||
"playtest plugins. GameUpdate files are kept."
|
||||
"other tool artifacts. GameUpdate files and all installed plugins are kept."
|
||||
),
|
||||
6: (
|
||||
"<b>Step 6 - Images (MV/MZ)</b><br><br>"
|
||||
|
|
@ -2228,7 +2228,7 @@ class WorkflowTab(QWidget):
|
|||
self._release_zip_btn = _make_btn("📦 Create Public Release ZIP", "#007acc")
|
||||
self._release_zip_btn.setToolTip(
|
||||
"Archive the detected game folder for players. Excludes DazedTL workspaces, "
|
||||
"version-control files, documentation, backups, saves, and playtest plugins; "
|
||||
"version-control files, documentation, backups, and saves; "
|
||||
"keeps GameUpdate files. The source game folder is not changed."
|
||||
)
|
||||
self._release_zip_btn.clicked.connect(self._create_public_release)
|
||||
|
|
@ -4211,8 +4211,6 @@ class WorkflowTab(QWidget):
|
|||
f"{result.files_added} file(s); omitted {result.excluded_entries} "
|
||||
"tool/private item(s)."
|
||||
)
|
||||
if result.sanitized_plugin_lists:
|
||||
message += " Removed playtest plugins from the archived plugins.js."
|
||||
self._log(f"✅ {message}")
|
||||
QMessageBox.information(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ class ReleasePackageTests(unittest.TestCase):
|
|||
prefix = "Translated Game/"
|
||||
with zipfile.ZipFile(output) as archive:
|
||||
names = set(archive.namelist())
|
||||
archived_plugins = archive.read(prefix + "js/plugins.js").decode("utf-8")
|
||||
archived_plugin_bytes = archive.read(prefix + "js/plugins.js")
|
||||
archived_plugins = archived_plugin_bytes.decode("utf-8")
|
||||
|
||||
for relative in (
|
||||
"Game.exe",
|
||||
|
|
@ -92,6 +93,8 @@ class ReleasePackageTests(unittest.TestCase):
|
|||
"gameupdate/patch.ps1",
|
||||
"gameupdate/patch-config.txt",
|
||||
"js/plugins/CorePlugin.js",
|
||||
"js/plugins/TLInspector.js",
|
||||
"js/plugins/Forge_MZ.js",
|
||||
):
|
||||
self.assertIn(prefix + relative, names)
|
||||
|
||||
|
|
@ -111,17 +114,15 @@ class ReleasePackageTests(unittest.TestCase):
|
|||
".gitignore",
|
||||
".env",
|
||||
"gameupdate/previous_patch_sha.txt",
|
||||
"js/plugins/TLInspector.js",
|
||||
"js/plugins/Forge_MZ.js",
|
||||
):
|
||||
self.assertNotIn(prefix + relative, names)
|
||||
|
||||
self.assertIn('"name":"CorePlugin"', archived_plugins)
|
||||
self.assertNotIn("TLInspector", archived_plugins)
|
||||
self.assertNotIn("Forge_MZ", archived_plugins)
|
||||
self.assertIn("TLInspector", archived_plugins)
|
||||
self.assertIn("Forge_MZ", archived_plugins)
|
||||
self.assertEqual(archived_plugin_bytes, plugins_js)
|
||||
self.assertEqual(source_plugins.read_bytes(), plugins_js)
|
||||
self.assertEqual(result.output_path, output.resolve())
|
||||
self.assertEqual(result.sanitized_plugin_lists, 1)
|
||||
self.assertEqual(progress[-1][:2], (result.files_added, result.files_added))
|
||||
|
||||
def test_release_path_must_be_outside_game_folder(self):
|
||||
|
|
|
|||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import re
|
||||
import tempfile
|
||||
import zipfile
|
||||
from dataclasses import dataclass
|
||||
|
|
@ -25,7 +23,6 @@ class ReleasePackageResult:
|
|||
files_added: int
|
||||
bytes_added: int
|
||||
excluded_entries: int
|
||||
sanitized_plugin_lists: int
|
||||
|
||||
|
||||
# These are never game payloads and should be ignored wherever they occur.
|
||||
|
|
@ -91,16 +88,10 @@ _EXCLUDED_FILE_NAMES = frozenset(
|
|||
".gitattributes",
|
||||
".gitignore",
|
||||
"desktop.ini",
|
||||
"forge_mv.bat",
|
||||
"forge_mv.js",
|
||||
"forge_mz.bat",
|
||||
"forge_mz.js",
|
||||
"patch2.ps1",
|
||||
"patch2.sh",
|
||||
"previous_patch_sha.txt",
|
||||
"thumbs.db",
|
||||
"tlinspector.bat",
|
||||
"tlinspector.js",
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -115,8 +106,6 @@ _UPDATER_ROOT_FILE_NAMES = frozenset(
|
|||
|
||||
_ROOT_DOCUMENT_SUFFIXES = frozenset({".doc", ".docx", ".markdown", ".md", ".pdf", ".rst"})
|
||||
_BACKUP_SUFFIXES = (".bak", ".backup", ".orig", ".tmp")
|
||||
_PLUGIN_LIST_PATHS = frozenset({"js/plugins.js", "www/js/plugins.js"})
|
||||
_PLAYTEST_PLUGIN_NAMES = ("TLInspector", "Forge_MV", "Forge_MZ")
|
||||
|
||||
|
||||
def default_release_zip_path(game_root: str | Path) -> Path:
|
||||
|
|
@ -205,67 +194,6 @@ def _iter_release_files(root: Path) -> tuple[list[tuple[Path, Path]], int]:
|
|||
return files, excluded
|
||||
|
||||
|
||||
def _remove_plugin_object(content: str, plugin_name: str) -> str:
|
||||
"""Remove one object from RPG Maker's JavaScript plugin-array syntax."""
|
||||
marker = re.search(rf'"name"\s*:\s*"{re.escape(plugin_name)}"', content)
|
||||
while marker:
|
||||
start = content.rfind("{", 0, marker.start())
|
||||
if start < 0:
|
||||
raise ReleasePackageError(f"Could not remove {plugin_name} from plugins.js")
|
||||
depth = 0
|
||||
end = None
|
||||
in_string = False
|
||||
escaped = False
|
||||
for index in range(start, len(content)):
|
||||
char = content[index]
|
||||
if in_string:
|
||||
if escaped:
|
||||
escaped = False
|
||||
elif char == "\\":
|
||||
escaped = True
|
||||
elif char == '"':
|
||||
in_string = False
|
||||
continue
|
||||
if char == '"':
|
||||
in_string = True
|
||||
elif char == "{":
|
||||
depth += 1
|
||||
elif char == "}":
|
||||
depth -= 1
|
||||
if depth == 0:
|
||||
end = index + 1
|
||||
break
|
||||
if end is None:
|
||||
raise ReleasePackageError(f"Could not parse {plugin_name} in plugins.js")
|
||||
|
||||
before = content[:start].rstrip()
|
||||
after = content[end:].lstrip()
|
||||
if after.startswith(","):
|
||||
after = after[1:].lstrip()
|
||||
elif before.endswith(","):
|
||||
before = before[:-1].rstrip()
|
||||
separator = "\n" if before and after and not before.endswith("\n") else ""
|
||||
content = before + separator + after
|
||||
marker = re.search(rf'"name"\s*:\s*"{re.escape(plugin_name)}"', content)
|
||||
return re.sub(r",(\s*)\];", r"\1];", content)
|
||||
|
||||
|
||||
def sanitize_plugins_js(raw: bytes) -> tuple[bytes, bool]:
|
||||
"""Remove DazedTL playtest entries while preserving the source file's BOM."""
|
||||
had_bom = raw.startswith(codecs.BOM_UTF8)
|
||||
try:
|
||||
content = raw.decode("utf-8-sig")
|
||||
except UnicodeDecodeError as exc:
|
||||
raise ReleasePackageError(f"plugins.js is not valid UTF-8: {exc}") from exc
|
||||
original = content
|
||||
for plugin_name in _PLAYTEST_PLUGIN_NAMES:
|
||||
content = _remove_plugin_object(content, plugin_name)
|
||||
if content == original:
|
||||
return raw, False
|
||||
encoded = content.encode("utf-8")
|
||||
return (codecs.BOM_UTF8 + encoded if had_bom else encoded), True
|
||||
|
||||
|
||||
def _archive_name(root: Path, relative: Path) -> str:
|
||||
return (Path(root.name or "game") / relative).as_posix()
|
||||
|
||||
|
|
@ -306,7 +234,6 @@ def create_release_zip(
|
|||
temporary = Path(temporary_name)
|
||||
files_added = 0
|
||||
bytes_added = 0
|
||||
sanitized = 0
|
||||
try:
|
||||
with zipfile.ZipFile(
|
||||
temporary,
|
||||
|
|
@ -319,16 +246,8 @@ def create_release_zip(
|
|||
if progress:
|
||||
progress(index, total, relative.as_posix())
|
||||
arcname = _archive_name(root, relative)
|
||||
if relative.as_posix().casefold() in _PLUGIN_LIST_PATHS:
|
||||
raw = source.read_bytes()
|
||||
payload, changed = sanitize_plugins_js(raw)
|
||||
info = zipfile.ZipInfo.from_file(source, arcname=arcname)
|
||||
archive.writestr(info, payload, compress_type=zipfile.ZIP_DEFLATED)
|
||||
sanitized += int(changed)
|
||||
bytes_added += len(payload)
|
||||
else:
|
||||
archive.write(source, arcname=arcname)
|
||||
bytes_added += source.stat().st_size
|
||||
archive.write(source, arcname=arcname)
|
||||
bytes_added += source.stat().st_size
|
||||
files_added += 1
|
||||
os.replace(temporary, output)
|
||||
except Exception:
|
||||
|
|
@ -340,5 +259,4 @@ def create_release_zip(
|
|||
files_added=files_added,
|
||||
bytes_added=bytes_added,
|
||||
excluded_entries=excluded,
|
||||
sanitized_plugin_lists=sanitized,
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue