mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 14:03:42 +02:00
Only add executables from itch (#48)
The Itch db can refer to multiple files, before the first one added was selected, now the first one that is executable is selected.
This commit is contained in:
Generated
+10
@@ -95,6 +95,7 @@ dependencies = [
|
|||||||
"fltk",
|
"fltk",
|
||||||
"fltk-theme",
|
"fltk-theme",
|
||||||
"futures",
|
"futures",
|
||||||
|
"is_executable",
|
||||||
"nom 7.0.0",
|
"nom 7.0.0",
|
||||||
"nom_locate",
|
"nom_locate",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
@@ -599,6 +600,15 @@ version = "2.3.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
|
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_executable"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ toml = { version = "^0.5.8", optional = true }
|
|||||||
futures = { version = "^0.3.17" }
|
futures = { version = "^0.3.17" }
|
||||||
dashmap = { version = "^4.0.2", features = ["serde"] }
|
dashmap = { version = "^4.0.2", features = ["serde"] }
|
||||||
fltk-theme = {version ="0.4" , optional = true }
|
fltk-theme = {version ="0.4" , optional = true }
|
||||||
|
is_executable = "1.0.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
fl2rust = { version = "0.4", optional = true }
|
fl2rust = { version = "0.4", optional = true }
|
||||||
|
|||||||
@@ -4,10 +4,18 @@ use nom::{
|
|||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub(crate) struct DbPaths {
|
pub(crate) struct DbPaths {
|
||||||
pub(crate) base_path: String,
|
pub(crate) base_path: String,
|
||||||
pub(crate) path: String,
|
pub(crate) paths: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
struct Candidate{
|
||||||
|
pub path:String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_butler_db<'a>(content: &'a [u8]) -> nom::IResult<&[u8], Vec<DbPaths>> {
|
pub(crate) fn parse_butler_db<'a>(content: &'a [u8]) -> nom::IResult<&[u8], Vec<DbPaths>> {
|
||||||
@@ -22,20 +30,35 @@ fn parse_path<'a>(i: &'a [u8]) -> nom::IResult<&[u8], DbPaths> {
|
|||||||
let (i, base_path) = take_until(suffix)(i)?;
|
let (i, base_path) = take_until(suffix)(i)?;
|
||||||
let base_path = String::from_utf8_lossy(base_path).to_string();
|
let base_path = String::from_utf8_lossy(base_path).to_string();
|
||||||
|
|
||||||
let prefix = ":[{\"path\":\"";
|
let prefix = "\"candidates\":[";
|
||||||
let suffix = "\",\"depth";
|
let suffix = "]}";
|
||||||
let (i, _taken) = take_until(prefix)(i)?;
|
let (i, _taken) = take_until(prefix)(i)?;
|
||||||
let (i, _taken) = tag(prefix)(i)?;
|
let (i, _taken) = tag(prefix)(i)?;
|
||||||
let (i, path) = take_until(suffix)(i)?;
|
let (i, candidates_json) = take_until(suffix)(i)?;
|
||||||
let path = String::from_utf8_lossy(path).to_string();
|
let candidates_json = format!("[{}]",String::from_utf8_lossy(candidates_json).to_string());
|
||||||
|
|
||||||
IResult::Ok((
|
let candidates = serde_json::from_str::<Vec<Candidate>>(&candidates_json);
|
||||||
|
match candidates{
|
||||||
|
Ok(candidates) => {
|
||||||
|
return IResult::Ok((
|
||||||
i,
|
i,
|
||||||
DbPaths {
|
DbPaths {
|
||||||
base_path,
|
base_path,
|
||||||
path,
|
paths: candidates.iter().map(|c| c.path.clone()).collect(),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
},
|
||||||
|
Err(_err) => {
|
||||||
|
//we found a basepath, but no executables
|
||||||
|
return IResult::Ok((
|
||||||
|
i,
|
||||||
|
DbPaths {
|
||||||
|
base_path,
|
||||||
|
paths: vec![],
|
||||||
|
},
|
||||||
|
))
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -52,26 +75,26 @@ mod tests {
|
|||||||
assert_eq!(paths.len(), 6);
|
assert_eq!(paths.len(), 6);
|
||||||
|
|
||||||
assert_eq!(paths[0].base_path, "/home/philip/.config/itch/apps/islands");
|
assert_eq!(paths[0].base_path, "/home/philip/.config/itch/apps/islands");
|
||||||
assert_eq!(paths[0].path, "Islands_Linux.x86_64");
|
assert_eq!(paths[0].paths[0], "Islands_Linux.x86_64");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
paths[1].base_path,
|
paths[1].base_path,
|
||||||
"/home/philip/.config/itch/apps/night-in-the-woods"
|
"/home/philip/.config/itch/apps/night-in-the-woods"
|
||||||
);
|
);
|
||||||
assert_eq!(paths[1].path, "Night in the Woods.x86_64");
|
assert_eq!(paths[1].paths[0], "Night in the Woods.x86_64");
|
||||||
assert_eq!(paths[2].base_path, "/home/philip/.config/itch/apps/islands");
|
assert_eq!(paths[2].base_path, "/home/philip/.config/itch/apps/islands");
|
||||||
assert_eq!(paths[2].path, "Islands_Linux.x86_64");
|
assert_eq!(paths[2].paths[0], "Islands_Linux.x86_64");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
paths[3].base_path,
|
paths[3].base_path,
|
||||||
"/home/philip/.config/itch/apps/overland"
|
"/home/philip/.config/itch/apps/overland"
|
||||||
);
|
);
|
||||||
assert_eq!(paths[3].path, "Overland.x86_64");
|
assert_eq!(paths[3].paths[0], "Overland.x86_64");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
paths[4].base_path,
|
paths[4].base_path,
|
||||||
"/home/philip/.config/itch/apps/night-in-the-woods"
|
"/home/philip/.config/itch/apps/night-in-the-woods"
|
||||||
);
|
);
|
||||||
assert_eq!(paths[4].path, "Night in the Woods.x86_64");
|
assert_eq!(paths[4].paths[0], "Night in the Woods.x86_64");
|
||||||
assert_eq!(paths[5].base_path, "/home/philip/.config/itch/apps/islands");
|
assert_eq!(paths[5].base_path, "/home/philip/.config/itch/apps/islands");
|
||||||
assert_eq!(paths[5].path, "Islands_Linux.x86_64");
|
assert_eq!(paths[5].paths[0], "Islands_Linux.x86_64");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -83,7 +106,7 @@ mod tests {
|
|||||||
assert_eq!(paths.len(), 94);
|
assert_eq!(paths.len(), 94);
|
||||||
|
|
||||||
assert_eq!(paths[0].base_path, "/home/deck/.config/itch/apps/risetoruins");
|
assert_eq!(paths[0].base_path, "/home/deck/.config/itch/apps/risetoruins");
|
||||||
assert_eq!(paths[0].path, "Core.jar");
|
assert_eq!(paths[0].paths[0], "Core.jar");
|
||||||
//The parser finds douplicates
|
//The parser finds douplicates
|
||||||
assert_eq!(paths[0], paths[1]);
|
assert_eq!(paths[0], paths[1]);
|
||||||
assert_eq!(paths[1], paths[2]);
|
assert_eq!(paths[1], paths[2]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use super::{ItchGame, ItchSettings};
|
|||||||
use crate::platform::{Platform, SettingsValidity};
|
use crate::platform::{Platform, SettingsValidity};
|
||||||
use failure::*;
|
use failure::*;
|
||||||
use flate2::read::GzDecoder;
|
use flate2::read::GzDecoder;
|
||||||
|
use is_executable::IsExecutable;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -48,9 +49,12 @@ impl Platform<ItchGame, ItchErrors> for ItchPlatform {
|
|||||||
}),
|
}),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
//This is done dedupe
|
//This is done to paths dedupe
|
||||||
let paths: HashSet<&DbPaths> = paths.iter().collect();
|
let paths: HashSet<&DbPaths> = paths.iter().collect();
|
||||||
let res = paths.iter().filter_map(|e| dbpath_to_game(*e)).collect();
|
let res = paths
|
||||||
|
.iter()
|
||||||
|
.filter_map(|e| dbpath_to_game(*e))
|
||||||
|
.collect();
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +82,12 @@ fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let executable = paths
|
||||||
|
.paths
|
||||||
|
.iter()
|
||||||
|
.find(|p| Path::new(&paths.base_path).join(&p).is_executable());
|
||||||
|
match executable {
|
||||||
|
Some(executable) => {
|
||||||
let gz_bytes = std::fs::read(&recipt).unwrap();
|
let gz_bytes = std::fs::read(&recipt).unwrap();
|
||||||
let mut d = GzDecoder::new(gz_bytes.as_slice());
|
let mut d = GzDecoder::new(gz_bytes.as_slice());
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
@@ -86,9 +96,12 @@ fn dbpath_to_game(paths: &DbPaths) -> Option<ItchGame> {
|
|||||||
let receipt_op: Option<Receipt> = serde_json::from_str(&s).ok();
|
let receipt_op: Option<Receipt> = serde_json::from_str(&s).ok();
|
||||||
receipt_op.map(|re| ItchGame {
|
receipt_op.map(|re| ItchGame {
|
||||||
install_path: paths.base_path.to_owned(),
|
install_path: paths.base_path.to_owned(),
|
||||||
executable: paths.path.to_owned(),
|
executable: executable.to_owned(),
|
||||||
title: re.game.title,
|
title: re.game.title,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
|
|||||||
Reference in New Issue
Block a user