Failed attempt to not open IPA.exe window
This commit is contained in:
@@ -106,9 +106,10 @@ py -m plugin_helper
|
|||||||
py -m plugin_helper --config plugin-helper.windows.toml --profile windows installed --instance 1.44.1
|
py -m plugin_helper --config plugin-helper.windows.toml --profile windows installed --instance 1.44.1
|
||||||
```
|
```
|
||||||
|
|
||||||
On native Windows, `bootstrap` runs `IPA.exe -n` directly instead of through
|
On native Windows, `bootstrap` runs `IPA.exe "Beat Saber.exe" -n` directly
|
||||||
Proton. `bootstrap-check` accepts a recorded native bootstrap without requiring
|
instead of through Proton. `bootstrap-check` accepts a recorded native bootstrap
|
||||||
`Logs/_latest.log` when `IPA.exe -n` completed successfully.
|
without requiring `Logs/_latest.log` when `IPA.exe "Beat Saber.exe" -n`
|
||||||
|
completed successfully.
|
||||||
|
|
||||||
When no config file is present on Windows, defaults are
|
When no config file is present on Windows, defaults are
|
||||||
`~/BSManager/BSInstances` and `%LOCALAPPDATA%/plugin-helper`.
|
`~/BSManager/BSInstances` and `%LOCALAPPDATA%/plugin-helper`.
|
||||||
@@ -212,10 +213,10 @@ custom content or non-obvious user choices rather than pure cache data.
|
|||||||
arguments such as `--no-yeet fpfc` can make the game fail command-line
|
arguments such as `--no-yeet fpfc` can make the game fail command-line
|
||||||
parsing after BSIPA and plugins have already loaded.
|
parsing after BSIPA and plugins have already loaded.
|
||||||
- BSIPA is managed as a first-class bootstrap phase. The `bootstrap` command
|
- BSIPA is managed as a first-class bootstrap phase. The `bootstrap` command
|
||||||
applies the locked `bsipa` root archive, runs `IPA.exe -n` (natively on
|
applies the locked `bsipa` root archive, runs `IPA.exe "Beat Saber.exe" -n`
|
||||||
Windows or through Proton on Linux), and records every bootstrap-relevant
|
(natively on Windows or through Proton on Linux), and records every
|
||||||
file under root `IPA.exe*`, `winhttp.dll`, `Libs/`, and `IPA/`, including
|
bootstrap-relevant file under root `IPA.exe*`, `winhttp.dll`, `Libs/`, and
|
||||||
backups created during patching.
|
`IPA/`, including backups created during patching.
|
||||||
- If an instance version lock includes `bsipa`, ordinary plugin plans require a
|
- If an instance version lock includes `bsipa`, ordinary plugin plans require a
|
||||||
recorded bootstrap state plus a `Logs/_latest.log` that shows BSIPA startup.
|
recorded bootstrap state plus a `Logs/_latest.log` that shows BSIPA startup.
|
||||||
Use `bootstrap-check` before planning a batch when you want a quick gate.
|
Use `bootstrap-check` before planning a batch when you want a quick gate.
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ Windows instances.
|
|||||||
### Done
|
### Done
|
||||||
|
|
||||||
- Add native Windows bootstrap support.
|
- Add native Windows bootstrap support.
|
||||||
- `bootstrap` auto-detects Windows and runs `IPA.exe -n` directly.
|
- `bootstrap` auto-detects Windows and runs `IPA.exe "Beat Saber.exe" -n` directly.
|
||||||
- `--native` forces native mode; `--proton` remains for Linux/Proton installs.
|
- `--native` forces native mode; `--proton` remains for Linux/Proton installs.
|
||||||
- Timeout cleanup uses `process.terminate()` / `process.kill()` on Windows
|
- Timeout cleanup uses `process.terminate()` / `process.kill()` on Windows
|
||||||
instead of POSIX process groups.
|
instead of POSIX process groups.
|
||||||
- Bootstrap state records `bootstrapMode: "native"` or `"proton"`.
|
- Bootstrap state records `bootstrapMode: "native"` or `"proton"`.
|
||||||
- `bootstrap-check` accepts recorded native Windows bootstrap state without
|
- `bootstrap-check` accepts recorded native Windows bootstrap state without
|
||||||
`Logs/_latest.log` when `IPA.exe -n` completed successfully
|
`Logs/_latest.log` when `IPA.exe "Beat Saber.exe" -n` completed successfully
|
||||||
(`ipaExitCode == 0`, not timed out).
|
(`ipaExitCode == 0`, not timed out).
|
||||||
- Add Windows-aware default paths when no config is present:
|
- Add Windows-aware default paths when no config is present:
|
||||||
`~/BSManager/BSInstances` and `%LOCALAPPDATA%/plugin-helper`.
|
`~/BSManager/BSInstances` and `%LOCALAPPDATA%/plugin-helper`.
|
||||||
|
|||||||
@@ -10,5 +10,6 @@ dependencies = [
|
|||||||
{ id = "songcore", constraint = ">=3.16.0" },
|
{ id = "songcore", constraint = ">=3.16.0" },
|
||||||
{ id = "sirautil", constraint = ">=3.3.1" },
|
{ id = "sirautil", constraint = ">=3.3.1" },
|
||||||
{ id = "system-io-compression", constraint = ">=4.6.0" },
|
{ id = "system-io-compression", constraint = ">=4.6.0" },
|
||||||
|
{ id = "system-io-compression-filesystem", constraint = ">=4.7.3056" },
|
||||||
{ id = "bsipa", constraint = ">=4.3.7" },
|
{ id = "bsipa", constraint = ">=4.3.7" },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -140,11 +140,12 @@ def build_bootstrap_command(
|
|||||||
proton: Path | None = None,
|
proton: Path | None = None,
|
||||||
native: bool | None = None,
|
native: bool | None = None,
|
||||||
) -> list[str]:
|
) -> list[str]:
|
||||||
|
beat_saber_exe = ipa.with_name("Beat Saber.exe")
|
||||||
use_native = is_windows() if native is None else native
|
use_native = is_windows() if native is None else native
|
||||||
if use_native:
|
if use_native:
|
||||||
return [str(ipa), "-n"]
|
return [str(ipa), str(beat_saber_exe), "-n"]
|
||||||
proton_path = proton or _default_proton()
|
proton_path = proton or _default_proton()
|
||||||
return [str(proton_path), "run", str(ipa), "-n"]
|
return [str(proton_path), "run", str(ipa), str(beat_saber_exe), "-n"]
|
||||||
|
|
||||||
|
|
||||||
def _terminate_process(process: subprocess.Popen[str]) -> None:
|
def _terminate_process(process: subprocess.Popen[str]) -> None:
|
||||||
@@ -249,15 +250,18 @@ def run_bootstrap(
|
|||||||
ipa = instance_path / "IPA.exe"
|
ipa = instance_path / "IPA.exe"
|
||||||
if not ipa.is_file():
|
if not ipa.is_file():
|
||||||
raise FileNotFoundError(f"BSIPA archive did not install IPA.exe: {ipa}")
|
raise FileNotFoundError(f"BSIPA archive did not install IPA.exe: {ipa}")
|
||||||
|
beat_saber_exe = instance_path / "Beat Saber.exe"
|
||||||
|
if not beat_saber_exe.is_file():
|
||||||
|
raise FileNotFoundError(f"Beat Saber executable not found: {beat_saber_exe}")
|
||||||
|
|
||||||
command = build_bootstrap_command(ipa, proton=proton, native=use_native)
|
command = build_bootstrap_command(ipa, proton=proton, native=use_native)
|
||||||
if use_native:
|
if use_native:
|
||||||
tell(f"Running IPA.exe -n natively; timeout {ipa_timeout_seconds}s")
|
tell(f"Running IPA.exe \"Beat Saber.exe\" -n natively; timeout {ipa_timeout_seconds}s")
|
||||||
else:
|
else:
|
||||||
proton_path = proton or _default_proton()
|
proton_path = proton or _default_proton()
|
||||||
if not proton_path.is_file():
|
if not proton_path.is_file():
|
||||||
raise FileNotFoundError(f"Proton executable not found: {proton_path}")
|
raise FileNotFoundError(f"Proton executable not found: {proton_path}")
|
||||||
tell(f"Running IPA.exe -n through Proton; timeout {ipa_timeout_seconds}s")
|
tell(f"Running IPA.exe \"Beat Saber.exe\" -n through Proton; timeout {ipa_timeout_seconds}s")
|
||||||
|
|
||||||
completed = _run_ipa(
|
completed = _run_ipa(
|
||||||
command=command,
|
command=command,
|
||||||
@@ -265,7 +269,7 @@ def run_bootstrap(
|
|||||||
timeout_seconds=ipa_timeout_seconds,
|
timeout_seconds=ipa_timeout_seconds,
|
||||||
native=use_native,
|
native=use_native,
|
||||||
)
|
)
|
||||||
tell("Scanning bootstrap files after IPA.exe -n")
|
tell("Scanning bootstrap files after IPA.exe \"Beat Saber.exe\" -n")
|
||||||
after = scan_bootstrap_files(instance_path)
|
after = scan_bootstrap_files(instance_path)
|
||||||
delta = _files_delta(before, after)
|
delta = _files_delta(before, after)
|
||||||
state: dict[str, Any] = {
|
state: dict[str, Any] = {
|
||||||
|
|||||||
@@ -319,14 +319,17 @@ state_dir = "config-state"
|
|||||||
|
|
||||||
def test_build_bootstrap_command_native(self) -> None:
|
def test_build_bootstrap_command_native(self) -> None:
|
||||||
ipa = Path("C:/Games/Beat Saber/IPA.exe")
|
ipa = Path("C:/Games/Beat Saber/IPA.exe")
|
||||||
self.assertEqual(build_bootstrap_command(ipa, native=True), [str(ipa), "-n"])
|
self.assertEqual(
|
||||||
|
build_bootstrap_command(ipa, native=True),
|
||||||
|
[str(ipa), str(ipa.with_name("Beat Saber.exe")), "-n"],
|
||||||
|
)
|
||||||
|
|
||||||
def test_build_bootstrap_command_proton(self) -> None:
|
def test_build_bootstrap_command_proton(self) -> None:
|
||||||
ipa = Path("/tmp/1.44.1/IPA.exe")
|
ipa = Path("/tmp/1.44.1/IPA.exe")
|
||||||
proton = Path("/tmp/proton")
|
proton = Path("/tmp/proton")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
build_bootstrap_command(ipa, proton=proton, native=False),
|
build_bootstrap_command(ipa, proton=proton, native=False),
|
||||||
[str(proton), "run", str(ipa), "-n"],
|
[str(proton), "run", str(ipa), str(ipa.with_name("Beat Saber.exe")), "-n"],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_profile_config_resolves_windows_paths(self) -> None:
|
def test_profile_config_resolves_windows_paths(self) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user