From 1abc8267959b76c5689bfcbd8f2b77284cea0084 Mon Sep 17 00:00:00 2001 From: mtkennerly Date: Wed, 19 Jun 2024 23:44:13 -0400 Subject: [PATCH] #209: Fix Lutris configpath handling --- CHANGELOG.md | 6 ++ src/scan/launchers/lutris.rs | 70 ++++++++++++++++-- .../games/windows-game-1683516078.yaml | 34 +++++++++ .../games/windows-game-1683516079.yaml | 5 ++ tests/launchers/lutris-merged/pga.db | Bin 0 -> 32768 bytes 5 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 tests/launchers/lutris-merged/games/windows-game-1683516078.yaml create mode 100644 tests/launchers/lutris-merged/games/windows-game-1683516079.yaml create mode 100644 tests/launchers/lutris-merged/pga.db diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f0b0008..a24a0f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## Unreleased + +* Fixed: + * For Lutris roots, after reading `pga.db`, + Ludusavi did not properly combine that data with the data from the `games/*.yml` files. + ## v0.24.1 (2024-06-15) * Fixed: diff --git a/src/scan/launchers/lutris.rs b/src/scan/launchers/lutris.rs index 63487dde..386ca719 100644 --- a/src/scan/launchers/lutris.rs +++ b/src/scan/launchers/lutris.rs @@ -24,6 +24,16 @@ impl From for Error { mod spec { use super::*; + /// For `games/foo.yml`, this would be `foo`. + #[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct BareName(pub String); + + impl std::fmt::Display for BareName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", &self.0) + } + } + #[derive(serde::Deserialize)] pub struct Data { pub game: Game, @@ -105,8 +115,10 @@ pub fn scan(root: &RootsConfig, title_finder: &TitleFinder) -> HashMap { for (spec, db_pending) in db_games { - let spec_pending = read_spec(&spec); - log::trace!("Evaluating game from DB: {db_pending:?} + from spec: {spec_pending:?}"); + let spec_pending = find_spec(&spec, &root.path); + log::trace!( + "Evaluating game, bare name: {spec}, from DB: {db_pending:?} + from spec: {spec_pending:?}" + ); if let Some((title, game)) = db_pending.merge(spec_pending).evaluate(title_finder) { log::trace!("Evaluated to '{title}': {game:?}"); @@ -148,7 +160,7 @@ pub fn scan(root: &RootsConfig, title_finder: &TitleFinder) -> HashMap Result, Error> { +fn scan_db(root: &RootsConfig) -> Result, Error> { #[derive(Debug)] struct Row { name: Option, @@ -164,7 +176,7 @@ fn scan_db(root: &RootsConfig) -> Result, Error> { return Err(Error::NoDatabase); } - let mut games = HashMap::::new(); + let mut games = HashMap::::new(); let Ok(file) = db_file.as_std_path_buf() else { return Ok(games); @@ -189,7 +201,11 @@ fn scan_db(root: &RootsConfig) -> Result, Error> { log::trace!("Row = {row:?}"); let spec = if let Some(spec) = row.configpath { - StrictPath::new(spec) + if spec.trim().is_empty() { + log::warn!("Ignoring row with empty `configpath`"); + continue; + } + spec::BareName(spec) } else { log::warn!("Ignoring row without `configpath`"); continue; @@ -205,7 +221,9 @@ fn scan_db(root: &RootsConfig) -> Result, Error> { if pending.platform.is_some_and(|x| x == Os::Windows) && row.runner.is_some_and(|x| x == "wine") { if let Some(directory) = row.directory { - pending.prefix = Some(StrictPath::new(directory)); + if !directory.trim().is_empty() { + pending.prefix = Some(StrictPath::new(directory)); + } } } @@ -220,6 +238,16 @@ fn scan_db(root: &RootsConfig) -> Result, Error> { Ok(games) } +fn find_spec(name: &spec::BareName, root: &StrictPath) -> Option { + for candidate in root.joined(&format!("games/{name}.y*ml")).glob() { + if candidate.is_file() { + return read_spec(&candidate); + } + } + + None +} + fn read_spec(file: &StrictPath) -> Option { log::debug!("Inspecting Lutris game file: {:?}", file); @@ -300,6 +328,12 @@ mod tests { windows-game: files: /file1.txt: {} + Windows Game 1: + files: + /file1.txt: {} + Windows Game 2: + files: + /file1.txt: {} windows-game-with-absolute-exe: files: /file1.txt: {} @@ -363,6 +397,30 @@ mod tests { ); } + #[test] + fn scan_finds_all_games_with_spec_and_database_merged() { + let root = RootsConfig { + path: StrictPath::new(format!("{}/tests/launchers/lutris-merged", repo())), + store: Store::Lutris, + }; + let games = scan(&root, &title_finder()); + assert_eq!( + hash_map! { + "Windows Game 1".to_string(): hash_set![LauncherGame { + install_dir: Some(StrictPath::new("/home/deck/Games/service/windows-game/drive_c/game".to_string())), + prefix: Some(StrictPath::new("/home/deck/Games/service/windows-game-1".to_string())), + platform: Some(Os::Windows), + }], + "Windows Game 2".to_string(): hash_set![LauncherGame { + install_dir: Some(StrictPath::new("/home/deck/Games/service".to_string())), + prefix: Some(StrictPath::new("/home/deck/Games/service/windows-game-2".to_string())), + platform: Some(Os::Windows), + }], + }, + games, + ); + } + #[test] fn can_scan_spec_with_absolute_exe() { let spec = spec::Data { diff --git a/tests/launchers/lutris-merged/games/windows-game-1683516078.yaml b/tests/launchers/lutris-merged/games/windows-game-1683516078.yaml new file mode 100644 index 00000000..39eec8e7 --- /dev/null +++ b/tests/launchers/lutris-merged/games/windows-game-1683516078.yaml @@ -0,0 +1,34 @@ +game: + args: '' + exe: /home/deck/Games/service/windows-game/drive_c/game/YookaLaylee64.exe + prefix: /home/deck/Games/service/windows-game + working_dir: /home/deck/Games/service/windows-game/drive_c/game +game_slug: windows-game +name: Windows Game +requires: null +script: + files: [] # omitted + game: + args: '' + exe: $GAMEDIR/drive_c/game/YookaLaylee64.exe + prefix: $GAMEDIR + working_dir: $GAMEDIR/drive_c/game + installer: + - task: + arch: win64 + prefix: /home/deck/Games/service/windows-game + wine_path: /home/deck/.var/app/net.lutris.Lutris/data/lutris/runners/wine/lutris-7.2-2-x86_64/bin/wine + - mkdir: $GAMEDIR/drive_c/game + - move: ~ # omitted + system: {} + wine: + version: lutris-7.2-2-x86_64 +service: service +service_id: ... +slug: windows-game +system: {} +variables: {} +version: Service Name +wine: + version: lutris-7.2-2-x86_64 +year: null diff --git a/tests/launchers/lutris-merged/games/windows-game-1683516079.yaml b/tests/launchers/lutris-merged/games/windows-game-1683516079.yaml new file mode 100644 index 00000000..249e4b5f --- /dev/null +++ b/tests/launchers/lutris-merged/games/windows-game-1683516079.yaml @@ -0,0 +1,5 @@ +game: + exe: /home/deck/Games/service/game.exe + prefix: /home/deck/Games/service/windows-game-2 +system: {} +wine: {} diff --git a/tests/launchers/lutris-merged/pga.db b/tests/launchers/lutris-merged/pga.db new file mode 100644 index 0000000000000000000000000000000000000000..10c25f24ec59ca7dc18d0e3545633202f7c397ae GIT binary patch literal 32768 zcmeI%&u-H&90zb`D@%cOz+nnv7wl zNIb(N-T@wh7vKnYPMo=M!O7gFnJ5z1>Kmzz|0MP=AKM2fj~=f3lGEK#>@!Ih$XQ|- z~23n!4(^0$$;(%v`MnT-trM?@sbutKBp-#pk&?%2g z<_A&ll2{5qa{Bj|-)|VEWm(3Dx7lP%pJXf-d|EU-=>AaWLu*Hp1pyaXe-+wcg12R^ zBw#YxuIdm)+-`HBGyDyA<216~M*&dd)s4bCB~5q_njt7!|dNVP?Zizzaoi6`f4et zWx8IWd%oxKcGgFJynFMfKj;I^y5TD>n2=7>Z)Nv;e&mM2OBQo7P0A%TO~1Z+O z=;=Q?s^{Cu=c*BxacAo&6jjA*d*ME>dE9+bOTvt5`XxXuf1i%=Q@*qp{eSew7*7ZR2tWV=5P$##AOHafKmY;| F_yZ8o#;^bY literal 0 HcmV?d00001