mirror of
https://github.com/FelipePrado0/SpartanPort.git
synced 2026-11-07 10:45:59 -10:00
Feat(Launcher): route --run and --play to the runner
This commit is contained in:
1 parent
2e64e4dd81
commit
5d030c3269
6 files changed
+94
-20
No files matched your search
@@ -2,6 +2,7 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
pub mod core;
|
||||
pub mod runner;
|
||||
pub mod startup;
|
||||
pub mod ui;
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
use std::ffi::OsString;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use spartanport_launcher::core::env::environment_of;
|
||||
use spartanport_launcher::core::paths::{default_port_dir, Paths};
|
||||
use spartanport_launcher::core::platform;
|
||||
use spartanport_launcher::runner::{self, RunContext};
|
||||
use spartanport_launcher::startup::{self, Route};
|
||||
use spartanport_launcher::{ui, APP_NAME, VERSION};
|
||||
|
||||
@@ -22,6 +24,17 @@ fn main() {
|
||||
let port_dir = default_port_dir(&exe_dir);
|
||||
match startup::route(&args) {
|
||||
Route::Version => println!("{APP_NAME} {VERSION}"),
|
||||
// `Route::Play` routes like `Run` until the play role exists.
|
||||
Route::Run | Route::Play => {
|
||||
let paths = Paths::from_env(&port_dir, &|key| std::env::var(key).ok());
|
||||
let context = RunContext {
|
||||
port_dir: &paths.port_dir,
|
||||
env: environment_of(std::env::vars_os()),
|
||||
args: args.iter().skip(1).cloned().collect(),
|
||||
out: &mut std::io::stdout(),
|
||||
};
|
||||
std::process::exit(runner::run(context))
|
||||
}
|
||||
Route::Python => {
|
||||
// The Python launcher of the port folder (`SPARTAN_PORT_DIR` included).
|
||||
let paths = Paths::from_env(&port_dir, &|key| std::env::var(key).ok());
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//! The runner (Python `run.py`): starts the game under the probe and reports what it saw.
|
||||
|
||||
use std::ffi::OsString;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
/// What one run needs from the program around it.
|
||||
pub struct RunContext<'a> {
|
||||
pub port_dir: &'a Path,
|
||||
pub env: IndexMap<String, String>,
|
||||
pub args: Vec<OsString>,
|
||||
pub out: &'a mut dyn Write,
|
||||
}
|
||||
|
||||
/// Runs the runner and returns its exit code.
|
||||
pub fn run(context: RunContext<'_>) -> i32 {
|
||||
let probe = if cfg!(windows) {
|
||||
"spartanport-probe.exe"
|
||||
} else {
|
||||
"spartanport-probe"
|
||||
};
|
||||
// A closed stdout is nothing to report on: the code says it.
|
||||
let _ = writeln!(
|
||||
context.out,
|
||||
"{probe} not found: build it with build.sh or use a packaged build."
|
||||
);
|
||||
1
|
||||
}
|
||||
@@ -21,8 +21,11 @@ use crate::APP_NAME;
|
||||
pub enum Route {
|
||||
/// `--version`: the name and the version.
|
||||
Version,
|
||||
/// `--run`, `--script`, `--install-update` or `--play`: the Python launcher does these until
|
||||
/// the Rust runner exists.
|
||||
/// `--run`: the Rust runner.
|
||||
Run,
|
||||
/// `--play`: the Rust runner's play role.
|
||||
Play,
|
||||
/// `--script` or `--install-update`: the Python launcher does these.
|
||||
Python,
|
||||
/// Anything else: the window.
|
||||
Launcher,
|
||||
@@ -32,18 +35,18 @@ pub enum Route {
|
||||
/// counts anywhere, as in the Python `main`.
|
||||
pub fn route<S: AsRef<OsStr>>(args: &[S]) -> Route {
|
||||
let is = |arg: &S, flag: &str| arg.as_ref() == OsStr::new(flag);
|
||||
let leading = ["--run", "--script", "--install-update"];
|
||||
if args
|
||||
.first()
|
||||
.is_some_and(|first| leading.iter().any(|flag| is(first, flag)))
|
||||
{
|
||||
return Route::Python;
|
||||
match args.first() {
|
||||
Some(first) if is(first, "--run") => return Route::Run,
|
||||
Some(first) if is(first, "--script") || is(first, "--install-update") => {
|
||||
return Route::Python;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if args.iter().any(|arg| is(arg, "--version")) {
|
||||
return Route::Version;
|
||||
}
|
||||
if args.iter().any(|arg| is(arg, "--play")) {
|
||||
return Route::Python;
|
||||
return Route::Play;
|
||||
}
|
||||
Route::Launcher
|
||||
}
|
||||
|
||||
@@ -16,11 +16,15 @@ fn walk(root: impl AsRef<Path>) -> Vec<PathBuf> {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn core_never_mentions_iced() {
|
||||
let root = concat!(env!("CARGO_MANIFEST_DIR"), "/src/core");
|
||||
for entry in walk(root) {
|
||||
let text = std::fs::read_to_string(&entry).unwrap();
|
||||
assert!(!text.contains("iced"), "{entry:?} imports iced");
|
||||
fn core_and_runner_never_mention_iced() {
|
||||
for root in [
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/core"),
|
||||
concat!(env!("CARGO_MANIFEST_DIR"), "/src/runner"),
|
||||
] {
|
||||
for entry in walk(root) {
|
||||
let text = std::fs::read_to_string(&entry).unwrap();
|
||||
assert!(!text.contains("iced"), "{entry:?} imports iced");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,7 @@ fn arguments_route_to_python() {
|
||||
let none: [&str; 0] = [];
|
||||
assert_eq!(route(&none), Route::Launcher);
|
||||
assert_eq!(route(&["--version"]), Route::Version);
|
||||
// The Python roles: what follows `--run`, `--script` and `--install-update` is theirs.
|
||||
assert_eq!(route(&["--run"]), Route::Python);
|
||||
assert_eq!(route(&["--run", "--fps", "60"]), Route::Python);
|
||||
// The Python roles: what follows `--script` and `--install-update` is theirs.
|
||||
assert_eq!(
|
||||
route(&["--script", "prepare.py", "--version"]),
|
||||
Route::Python
|
||||
@@ -29,14 +27,39 @@ fn arguments_route_to_python() {
|
||||
route(&["--install-update", "a.zip", "C:\\Port"]),
|
||||
Route::Python
|
||||
);
|
||||
// `--play` counts anywhere, as in the Python `main`.
|
||||
assert_eq!(route(&["--play"]), Route::Python);
|
||||
assert_eq!(route(&["--fullscreen", "--play"]), Route::Python);
|
||||
// Anything else opens the window; the Python ignores unknown arguments too.
|
||||
assert_eq!(route(&["--fullscreen"]), Route::Launcher);
|
||||
assert_eq!(route(&["play"]), Route::Launcher);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_and_play_are_their_own_routes() {
|
||||
assert_eq!(route(&["--run"]), Route::Run);
|
||||
assert_eq!(route(&["--run", "--timeout", "5"]), Route::Run);
|
||||
// `--play` counts anywhere, as in the Python `main`.
|
||||
assert_eq!(route(&["--play"]), Route::Play);
|
||||
assert_eq!(route(&["--fullscreen", "--play"]), Route::Play);
|
||||
assert_eq!(route(&["--script", "x.py"]), Route::Python);
|
||||
assert_eq!(route(&["--install-update", "--run"]), Route::Python);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_without_a_probe_fails_with_the_python_message() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let out = std::process::Command::new(LAUNCHER)
|
||||
.arg("--run")
|
||||
.env("SPARTAN_PORT_DIR", dir.path())
|
||||
.output()
|
||||
.unwrap();
|
||||
assert_eq!(out.status.code(), Some(1));
|
||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||
assert!(stdout.contains("spartanport-probe"), "{stdout}");
|
||||
assert!(
|
||||
stdout.contains("not found: build it with build.sh"),
|
||||
"{stdout}"
|
||||
);
|
||||
}
|
||||
|
||||
/// The launcher program cargo built for these tests.
|
||||
const LAUNCHER: &str = env!("CARGO_BIN_EXE_spartanport-launcher");
|
||||
|
||||
|
||||
Reference in new issue
Block a user