diff --git a/portablemc/cli/__init__.py b/portablemc/cli/__init__.py index 6be85600..8b86018e 100644 --- a/portablemc/cli/__init__.py +++ b/portablemc/cli/__init__.py @@ -306,11 +306,11 @@ def cmd_search_handler(ns: SearchNs, kind: str, table: OutputTable): def cmd_start(ns: StartNs): version_parts = ns.version.split(":") - + # If no split, the kind of version is "standard": parts have at least 2 elements. if len(version_parts) == 1: version_parts = ["standard", version_parts[0]] - + # No handler means that the format is invalid. version = cmd_start_handler(ns, version_parts[0], version_parts[1:]) if version is None: @@ -376,33 +376,28 @@ def filter_libraries(libs: Dict[LibrarySpecifier, Any]) -> None: env = version.install(watcher=StartWatcher(ns)) - if ns.verbose >= 1 and len(env.fixes): - ns.out.task("INFO", "start.fixes") - ns.out.finish() + if ns.verbose >= 1: for fix, fix_value in env.fixes.items(): - ns.out.task(None, f"start.fix.{fix}", value=fix_value) + ns.out.task("INFO", f"start.fix.{fix}", value=fix_value) ns.out.finish() - # If not dry run, run it! - if not ns.dry: - - # Included binaries - if ns.include_bin is not None: - for bin_path in ns.include_bin: - if not bin_path.is_file(): - ns.out.task("FAILED", "start.additional_binary_not_found", path=bin_path) - ns.out.finish() - sys.exit(EXIT_FAILURE) - env.native_libs.append(bin_path) + # Included binaries + if ns.include_bin is not None: + for bin_path in ns.include_bin: + if not bin_path.is_file(): + ns.out.task("FAILED", "start.additional_binary_not_found", path=bin_path) + ns.out.finish() + sys.exit(EXIT_FAILURE) + env.native_libs.append(bin_path) - # Extend JVM arguments with given arguments, or defaults - if ns.jvm_args is None: - env.jvm_args.extend(DEFAULT_JVM_ARGS) - elif len(ns.jvm_args): - env.jvm_args.extend(ns.jvm_args.split()) - - env.run(CliRunner(ns)) - + # Extend JVM arguments with given arguments, or defaults + if ns.jvm_args is None: + env.jvm_args.extend(DEFAULT_JVM_ARGS) + elif len(ns.jvm_args): + env.jvm_args.extend(ns.jvm_args.split()) + + # This CliRunner will abort running if in dry mode. + env.run(CliRunner(ns)) sys.exit(EXIT_OK) except VersionNotFoundError as error: @@ -453,6 +448,10 @@ def cmd_start_handler(ns: StartNs, kind: str, parts: List[str]) -> Optional[Vers version = parts[0] or "release" ns.socket_error_tips.append("version_manifest") + + if ns.verbose >= 1: + ns.out.task("INFO", "start.global_version", kind=kind, version=version, remaining=" ".join(parts[1:])) + ns.out.finish() if kind == "standard": if len(parts) != 1: @@ -465,9 +464,9 @@ def cmd_start_handler(ns: StartNs, kind: str, parts: List[str]) -> Optional[Vers return None # Legacy fabric has a special case because it will never be supported for - # versions past 1.12.2, it is not made for latest release version. + # versions past 1.13.2, it is not made for latest release version. if kind == "legacyfabric" and version == "release": - version = "1.12.2" + version = "1.13.2" if kind == "fabric": constructor = FabricVersion.with_fabric @@ -800,7 +799,7 @@ def finish_task(key: str, **kwargs) -> None: ns.out.finish() def features(e: FeaturesEvent) -> None: - if ns.verbose >= 1 and len(e.features): + if ns.verbose >= 1: ns.out.task("INFO", "start.features", features=", ".join(e.features)) ns.out.finish() @@ -896,16 +895,21 @@ def download_complete(self, e: DownloadCompleteEvent) -> None: class CliRunner(StreamRunner): - def __init__(self, ns: RootNs) -> None: + def __init__(self, ns: StartNs) -> None: super().__init__() self.ns = ns - def process_create(self, args: List[str], work_dir: Path) -> Popen: + def process_create(self, args: List[str], work_dir: Path) -> Optional[Popen]: - self.ns.out.print("\n") - if self.ns.verbose >= 1: + if not self.ns.dry or self.ns.verbose >= 2: + self.ns.out.print("\n") + + if self.ns.verbose >= 2: self.ns.out.print(" ".join(args) + "\n") + if self.ns.dry: + return None + return super().process_create(args, work_dir) def process_stream_event(self, event: Any) -> None: diff --git a/portablemc/cli/lang.py b/portablemc/cli/lang.py index eb2091ca..62668a2f 100644 --- a/portablemc/cli/lang.py +++ b/portablemc/cli/lang.py @@ -192,6 +192,7 @@ def get(key: str, **kwargs) -> str: "logout.success": "Logged out {email}", "logout.unknown_session": "No session for {email}", # Command start + "start.global_version": "Global version: {kind} {version} {remaining}", "start.version.invalid_id": "Invalid version id, expected: {expected}", "start.version.invalid_id_unknown_kind": "Invalid version id, unknown kind: {kind}.", "start.version.loading": "Loading version {version}... ", @@ -200,7 +201,7 @@ def get(key: str, **kwargs) -> str: "start.version.loaded.fetched": "Loaded version {version} (fetched)", "start.version.not_found": "Version {version} not found", "start.version.too_much_parents": "Too much parents while resolving versions.", - "start.features": "Features: {features}", + "start.features": "Features: [{features}]", "start.jar.found": "Checked version jar", "start.jar.not_found": "Version jar not found", "start.assets.resolving": "Checking assets version {index_version}... ", @@ -223,7 +224,6 @@ def get(key: str, **kwargs) -> str: "use --jvm argument to manually set the path to your JVM executable.", f"start.jvm.not_found_error.{JvmNotFoundError.BUILTIN_INVALID_VERSION}": f"The builtin JVM ({jvm_bin_filename}) is not compatible " "with selected game version.", - "start.fixes": "Applied the following fixes:", f"start.fix.{Version.FIX_LEGACY_PROXY}": "Using legacy proxy for online resources: {value}", f"start.fix.{Version.FIX_LEGACY_MERGE_SORT}": "Using legacy merge sort: {value}", f"start.fix.{Version.FIX_LEGACY_RESOLUTION}": "Included resolution into game arguments: {value}", diff --git a/portablemc/standard.py b/portablemc/standard.py index 3d4b22be..bac001f6 100644 --- a/portablemc/standard.py +++ b/portablemc/standard.py @@ -1561,17 +1561,20 @@ def run(self, env: Environment) -> None: *replace_list_vars(env.game_args, replacements) ], env.context.work_dir) - self.process_wait(process) + if process is not None: + self.process_wait(process) finally: # Any error while setting up the binary directory cause it to be deleted. shutil.rmtree(bin_dir, ignore_errors=True) - def process_create(self, args: List[str], work_dir: Path) -> Popen: + def process_create(self, args: List[str], work_dir: Path) -> Optional[Popen]: """This function is called when process needs to be created with the given arguments in the given working directory. The default implementation does nothing special but this can be used to create the process with enabled output piping, to later use in `process_wait`. + + None can be returned to abort starting the game. """ return Popen(args, cwd=work_dir) @@ -1597,7 +1600,7 @@ class StreamRunner(StandardRunner): its completion. """ - def process_create(self, args: List[str], work_dir: Path) -> Popen: + def process_create(self, args: List[str], work_dir: Path) -> Optional[Popen]: return Popen(args, cwd=work_dir, stdout=PIPE, stderr=STDOUT, bufsize=1, universal_newlines=True, encoding="utf-8", errors="replace") def process_wait(self, process: Popen) -> None: