diff --git a/cpclib-bndbuild/src/builder.rs b/cpclib-bndbuild/src/builder.rs index f7657118..3b8311db 100644 --- a/cpclib-bndbuild/src/builder.rs +++ b/cpclib-bndbuild/src/builder.rs @@ -9,7 +9,7 @@ use minijinja::{context, Environment, Error, ErrorKind}; use crate::rules::{self, Graph, Rule}; use crate::BndBuilderError; -pub const EXPECTED_FILENAMES: &'static[&'static str] = &["bndbuild.yml", "build.bnd"]; +pub const EXPECTED_FILENAMES: &'static [&'static str] = &["bndbuild.yml", "build.bnd"]; self_cell::self_cell! { /// WARNING the BndBuilder changes the current working directory. @@ -21,10 +21,8 @@ self_cell::self_cell! { } } - - pub struct BndBuilder { - inner: BndBuilderInner, + inner: BndBuilderInner } impl Deref for BndBuilder { @@ -52,11 +50,12 @@ impl BndBuilder { pub fn from_path>(fname: P) -> Result<(Utf8PathBuf, Self), BndBuilderError> { let (p, content) = Self::decode_from_fname(fname)?; - Self::from_string(content) - .map(|build| (p, build)) + Self::from_string(content).map(|build| (p, build)) } - pub fn decode_from_fname>(fname: P) -> Result<(Utf8PathBuf, String), BndBuilderError> { + pub fn decode_from_fname>( + fname: P + ) -> Result<(Utf8PathBuf, String), BndBuilderError> { Self::decode_from_fname_with_definitions(fname, &Vec::<(String, String)>::new()) } @@ -98,8 +97,7 @@ impl BndBuilder { let working_directory = if path.is_dir() { Some(path) } else { None }; let rdr = BufReader::new(file); - Self::decode_from_reader(rdr, working_directory, definitions) - .map(|s| (fname.to_owned(), s)) + Self::decode_from_reader(rdr, working_directory, definitions).map(|s| (fname.to_owned(), s)) } pub fn save>(&self, path: P) -> std::io::Result<()> { diff --git a/cpclib-bndbuild/src/executor.rs b/cpclib-bndbuild/src/executor.rs index 2d578cf8..5e1160aa 100644 --- a/cpclib-bndbuild/src/executor.rs +++ b/cpclib-bndbuild/src/executor.rs @@ -27,9 +27,7 @@ pub static XFER_RUNNER: LazyLock = LazyLock::new(|| XferRunner::defa pub fn execute(task: &Task) -> Result<(), String> { match task { - Task::Emulator(e,_ ) => { - EmulatorRunner{emu:e.clone()}.run(task.args()) - }, + Task::Emulator(e, _) => EmulatorRunner { emu: e.clone() }.run(task.args()), Task::Basm(_) => BASM_RUNNER.run(task.args()), Task::BndBuild(_) => BNDBUILD_RUNNER.run(task.args()), Task::Cp(_) => CP_RUNNER.run(task.args()), diff --git a/cpclib-bndbuild/src/lib.rs b/cpclib-bndbuild/src/lib.rs index d2ed4ba5..937ffbde 100644 --- a/cpclib-bndbuild/src/lib.rs +++ b/cpclib-bndbuild/src/lib.rs @@ -115,7 +115,8 @@ pub fn process_matches(cmd: Command, matches: &ArgMatches) -> Result<(), BndBuil // Get the file let fname = if let Some(fname) = matches.get_one::("file") { fname.as_str() - } else { + } + else { let mut selected = &EXPECTED_FILENAMES[1]; for fname in EXPECTED_FILENAMES { if Utf8Path::new(fname).exists() { diff --git a/cpclib-bndbuild/src/runners/emulator.rs b/cpclib-bndbuild/src/runners/emulator.rs index 42977265..e4bbf360 100644 --- a/cpclib-bndbuild/src/runners/emulator.rs +++ b/cpclib-bndbuild/src/runners/emulator.rs @@ -1,26 +1,27 @@ -use std::{ io::{Cursor, Read}}; +use std::io::{Cursor, Read}; -use cpclib_common::{camino::Utf8PathBuf, itertools::Itertools}; +use cpclib_common::camino::Utf8PathBuf; +use cpclib_common::itertools::Itertools; use directories::ProjectDirs; -use ureq::Response; use flate2::read::GzDecoder; use tar::Archive; - -use crate::{runners::r#extern::ExternRunner, task::{ACE_CMDS, CPCEC_CMDS, WINAPE_CMDS}}; +use ureq::Response; use super::Runner; +use crate::runners::r#extern::ExternRunner; +use crate::task::{ACE_CMDS, CPCEC_CMDS, WINAPE_CMDS}; -#[derive(Clone, Debug, PartialEq,Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Emulator { Ace(AceVersion), - Cpcec(CpcecVersion), - Winape(WinapeVersion) + Cpcec(CpcecVersion), + Winape(WinapeVersion) } impl Default for Emulator { - fn default() -> Self { - Emulator::Ace(AceVersion::default()) - } + fn default() -> Self { + Emulator::Ace(AceVersion::default()) + } } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -29,264 +30,255 @@ pub enum AceVersion { } impl Default for AceVersion { - fn default() -> Self { - AceVersion::WakePoint - } + fn default() -> Self { + AceVersion::WakePoint + } } - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum CpcecVersion { - v20240505 + v20240505 } impl Default for CpcecVersion { - fn default() -> Self { - CpcecVersion::v20240505 - } + fn default() -> Self { + CpcecVersion::v20240505 + } } - #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum WinapeVersion { - v2_0b2 + v2_0b2 } impl Default for WinapeVersion { - fn default() -> Self { - WinapeVersion::v2_0b2 - } + fn default() -> Self { + WinapeVersion::v2_0b2 + } } - - pub enum ArchiveFormat { - TarGz, - Zip + TarGz, + Zip } pub struct EmulatorConfiguration { download_url: &'static str, folder: &'static str, - exec_fname: &'static str, - archive_format: ArchiveFormat + exec_fname: &'static str, + archive_format: ArchiveFormat } impl Emulator { pub fn configuration(&self) -> EmulatorConfiguration { match self { Emulator::Ace(version) => version.configuration(), - Emulator::Cpcec(version) => version.configuration(), - Emulator::Winape(version) => version.configuration(), + Emulator::Cpcec(version) => version.configuration(), + Emulator::Winape(version) => version.configuration() } } } cfg_match! { - cfg(target_os = "linux") => - { - - impl AceVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - AceVersion::WakePoint => - EmulatorConfiguration { - download_url: "http://www.roudoudou.com/ACE-DL/BZen.tar.gz", // we assume a modern CPU - folder : "AceWakePoint", - archive_format: ArchiveFormat::TarGz, - exec_fname: "AceDL" - } - } - } - } - - impl CpcecVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - CpcecVersion::v20240505 => { - EmulatorConfiguration { - download_url: "http://cngsoft.no-ip.org/cpcec-20240505.zip", - folder: "cpcec20240505", - archive_format: ArchiveFormat::Zip, - exec_fname: "CPCEC.EXE" // TODO see how to handle the fact it is windows file. Do we need to compile the linux version ? - } - }, - } - } - } - - - impl WinapeVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - WinapeVersion::v2_0b2 => { - EmulatorConfiguration { - download_url: "http://www.winape.net/download/WinAPE20B2.zip", - folder: "winape_2_0b2", - archive_format: ArchiveFormat::Zip, - exec_fname: "WinApe.exe" - } - }, - } - } - } - - } - cfg(target_os = "windows") => - { - impl AceVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - AceVersion::WakePoint => EmulatorConfiguration{ - download_url: "http://www.roudoudou.com/ACE-DL/BWIN64.zip", // we assume a 64bits machine - folder : "AceWakePoint", - archive_format: ArchiveFormat::Zip, - exec_fname: "AceDL.exe" - }} - } - } - - impl CpcecVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - CpcecVersion::v20240505 => { - EmulatorConfiguration { - download_url: "http://cngsoft.no-ip.org/cpcec-20240505.zip", - folder: "cpcec20240505", - archive_format: ArchiveFormat::Zip, - exec_fname: "CPCEC.EXE" - } - }, - } - } - } - - impl WinapeVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - WinapeVersion::v2_0b2 => { - EmulatorConfiguration { - download_url: "http://www.winape.net/download/WinAPE20B2.zip", - folder: "winape_2_0b2", - archive_format: ArchiveFormat::Zip, - exec_fname: "WinApe.exe" - } - }, - } - } - } - } - cfg(target_os = "macos") => - { - impl AceVersion { - pub fn configuration(&self) -> EmulatorConfiguration { - match self { - AceVersion::WakePoint => EmulatorConfiguration{ - download_url: "http://www.roudoudou.com/ACE-DL/BMAC.zip", - folder : "TODO", - archive_format: ArchiveFormat::Zip, - exec_fname: "TODO" - }} - } - } - } - _ => { - } -} + cfg(target_os = "linux") => + { + + impl AceVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + AceVersion::WakePoint => + EmulatorConfiguration { + download_url: "http://www.roudoudou.com/ACE-DL/BZen.tar.gz", // we assume a modern CPU + folder : "AceWakePoint", + archive_format: ArchiveFormat::TarGz, + exec_fname: "AceDL" + } + } + } + } + impl CpcecVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + CpcecVersion::v20240505 => { + EmulatorConfiguration { + download_url: "http://cngsoft.no-ip.org/cpcec-20240505.zip", + folder: "cpcec20240505", + archive_format: ArchiveFormat::Zip, + exec_fname: "CPCEC.EXE" // TODO see how to handle the fact it is windows file. Do we need to compile the linux version ? + } + }, + } + } + } -impl EmulatorConfiguration { - pub fn is_cached(&self) -> bool { - self.cache_folder().exists() - } - - pub fn cache_folder(&self) -> Utf8PathBuf { - let proj_dirs = ProjectDirs::from("net.cpcscene", "benediction", "bnd build").unwrap(); - let base_cache = proj_dirs.cache_dir(); - - if !base_cache.exists() { - std::fs::create_dir_all(base_cache); - } - - base_cache.join(self.folder).try_into().unwrap() - } - - pub fn exec_fname(&self) -> Utf8PathBuf { - self.cache_folder().join(self.exec_fname) - } - - pub fn install(&self) { - // get the file - let dest = self.cache_folder(); - - - - let resp = self.download().unwrap(); - let mut input = resp.into_reader(); - - // uncompress it - match self.archive_format { - ArchiveFormat::TarGz => { - let gz = GzDecoder::new(input); - let mut archive = Archive::new(gz); - archive.unpack(dest).unwrap(); - } - ArchiveFormat::Zip => { - let mut buffer = Vec::new(); - input.read_to_end(&mut buffer).unwrap(); - dbg!(&dest); - zip_extract::extract(Cursor::new(buffer), dest.as_std_path(), true).unwrap(); - }, - } - - } - - fn download(&self) -> Result { - ureq::get(&self.download_url) - .call() - } + + impl WinapeVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + WinapeVersion::v2_0b2 => { + EmulatorConfiguration { + download_url: "http://www.winape.net/download/WinAPE20B2.zip", + folder: "winape_2_0b2", + archive_format: ArchiveFormat::Zip, + exec_fname: "WinApe.exe" + } + }, + } + } + } + + } + cfg(target_os = "windows") => + { + impl AceVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + AceVersion::WakePoint => EmulatorConfiguration{ + download_url: "http://www.roudoudou.com/ACE-DL/BWIN64.zip", // we assume a 64bits machine + folder : "AceWakePoint", + archive_format: ArchiveFormat::Zip, + exec_fname: "AceDL.exe" + }} + } + } + + impl CpcecVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + CpcecVersion::v20240505 => { + EmulatorConfiguration { + download_url: "http://cngsoft.no-ip.org/cpcec-20240505.zip", + folder: "cpcec20240505", + archive_format: ArchiveFormat::Zip, + exec_fname: "CPCEC.EXE" + } + }, + } + } + } + + impl WinapeVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + WinapeVersion::v2_0b2 => { + EmulatorConfiguration { + download_url: "http://www.winape.net/download/WinAPE20B2.zip", + folder: "winape_2_0b2", + archive_format: ArchiveFormat::Zip, + exec_fname: "WinApe.exe" + } + }, + } + } + } + } + cfg(target_os = "macos") => + { + impl AceVersion { + pub fn configuration(&self) -> EmulatorConfiguration { + match self { + AceVersion::WakePoint => EmulatorConfiguration{ + download_url: "http://www.roudoudou.com/ACE-DL/BMAC.zip", + folder : "TODO", + archive_format: ArchiveFormat::Zip, + exec_fname: "TODO" + }} + } + } + } + _ => { + } } +impl EmulatorConfiguration { + pub fn is_cached(&self) -> bool { + self.cache_folder().exists() + } + + pub fn cache_folder(&self) -> Utf8PathBuf { + let proj_dirs = ProjectDirs::from("net.cpcscene", "benediction", "bnd build").unwrap(); + let base_cache = proj_dirs.cache_dir(); + + if !base_cache.exists() { + std::fs::create_dir_all(base_cache); + } + + base_cache.join(self.folder).try_into().unwrap() + } + + pub fn exec_fname(&self) -> Utf8PathBuf { + self.cache_folder().join(self.exec_fname) + } + + pub fn install(&self) { + // get the file + let dest = self.cache_folder(); + + let resp = self.download().unwrap(); + let mut input = resp.into_reader(); + + // uncompress it + match self.archive_format { + ArchiveFormat::TarGz => { + let gz = GzDecoder::new(input); + let mut archive = Archive::new(gz); + archive.unpack(dest).unwrap(); + }, + ArchiveFormat::Zip => { + let mut buffer = Vec::new(); + input.read_to_end(&mut buffer).unwrap(); + dbg!(&dest); + zip_extract::extract(Cursor::new(buffer), dest.as_std_path(), true).unwrap(); + } + } + } + fn download(&self) -> Result { + ureq::get(&self.download_url).call() + } +} -pub struct EmulatorRunner {pub(crate) emu: Emulator} +pub struct EmulatorRunner { + pub(crate) emu: Emulator +} impl Runner for EmulatorRunner { fn inner_run>(&self, itr: &[S]) -> Result<(), String> { - let cfg = self.emu.configuration(); - - // ensure the emulator exists - if !cfg.is_cached() { - println!("> Install emulator"); - cfg.install(); - } - assert!(cfg.is_cached()); - - // Build the command - let mut command = Vec::with_capacity(1+itr.len()); - let fname = cfg.exec_fname(); - - #[cfg(target_os="linux")] - { - if fname.as_str().to_lowercase().ends_with(".exe") { - command.push("wine"); - } - } - - command.push(fname.as_str()); - for arg in itr.into_iter() { - command.push(arg.as_ref()); - } - - // Delegate it to the appropriate luncher - ExternRunner::default().inner_run(&command) + let cfg = self.emu.configuration(); + + // ensure the emulator exists + if !cfg.is_cached() { + println!("> Install emulator"); + cfg.install(); + } + assert!(cfg.is_cached()); + + // Build the command + let mut command = Vec::with_capacity(1 + itr.len()); + let fname = cfg.exec_fname(); + + #[cfg(target_os = "linux")] + { + if fname.as_str().to_lowercase().ends_with(".exe") { + command.push("wine"); + } + } + + command.push(fname.as_str()); + for arg in itr.into_iter() { + command.push(arg.as_ref()); + } + + // Delegate it to the appropriate luncher + ExternRunner::default().inner_run(&command) } fn get_command(&self) -> &str { match self.emu { - Emulator::Ace(_) => &ACE_CMDS[0], - Emulator::Cpcec(_) => &CPCEC_CMDS[0], - Emulator::Winape(_) => &WINAPE_CMDS[0], - } + Emulator::Ace(_) => &ACE_CMDS[0], + Emulator::Cpcec(_) => &CPCEC_CMDS[0], + Emulator::Winape(_) => &WINAPE_CMDS[0] + } } } diff --git a/cpclib-bndbuild/src/task.rs b/cpclib-bndbuild/src/task.rs index c6a1fe43..97fca126 100644 --- a/cpclib-bndbuild/src/task.rs +++ b/cpclib-bndbuild/src/task.rs @@ -20,7 +20,6 @@ pub enum Task { Xfer(StandardTask) } - pub const ACE_CMDS: &[&'static str] = &["ace", "acedl"]; pub const WINAPE_CMDS: &[&'static str] = &["winape"]; pub const CPCEC_CMDS: &[&'static str] = &["cpcec"]; @@ -47,14 +46,16 @@ impl Display for Task { Task::ImgConverter(s) => (&IMG2CPC_CMDS[0], s), Task::Rm(s) => (&RM_CMDS[0], s), Task::Xfer(s) => (&XFER_CMDS[0], s), - Task::Emulator(e, s) => ( - match e { - Emulator::Ace(_) => &ACE_CMDS[0], - Emulator::Cpcec(_) => &CPCEC_CMDS[0], - Emulator::Winape(_) => &WINAPE_CMDS[0], - }, - s - ), + Task::Emulator(e, s) => { + ( + match e { + Emulator::Ace(_) => &ACE_CMDS[0], + Emulator::Cpcec(_) => &CPCEC_CMDS[0], + Emulator::Winape(_) => &WINAPE_CMDS[0] + }, + s + ) + }, }; write!( @@ -88,15 +89,20 @@ impl<'de> Deserialize<'de> for Task { ignore_error: ignore }; - if ACE_CMDS.iter().contains(&code) { Ok(Task::Emulator(Emulator::Ace(AceVersion::default()), std)) } else if CPCEC_CMDS.iter().contains(&code) { - Ok(Task::Emulator(Emulator::Cpcec(CpcecVersion::default()), std)) + Ok(Task::Emulator( + Emulator::Cpcec(CpcecVersion::default()), + std + )) } else if WINAPE_CMDS.iter().contains(&code) { - Ok(Task::Emulator(Emulator::Winape(WinapeVersion::default()), std)) + Ok(Task::Emulator( + Emulator::Winape(WinapeVersion::default()), + std + )) } else if BASM_CMDS.iter().contains(&code) { Ok(Task::Basm(std)) @@ -175,7 +181,7 @@ impl Task { | Task::Disc(t) | Task::BndBuild(t) | Task::Cp(t) - | Task::Emulator(_, t)=> t + | Task::Emulator(_, t) => t } } @@ -190,8 +196,7 @@ impl Task { | Task::Disc(t) | Task::BndBuild(t) | Task::Cp(t) - | Task::Emulator(_, t)=> t - + | Task::Emulator(_, t) => t } } @@ -214,7 +219,7 @@ impl Task { Task::Basm(_) => false, // wrong when displaying stuff Task::Rm(_) => false, Task::Echo(_) => true, - Task::Emulator(_, _) => true, + Task::Emulator(..) => true, Task::Xfer(_) => true, // wrong when downloading files Task::ImgConverter(_) => false, Task::Extern(_) => false, diff --git a/cpclib-visual-bndbuild/src/lib.rs b/cpclib-visual-bndbuild/src/lib.rs index 4409208f..64501e83 100644 --- a/cpclib-visual-bndbuild/src/lib.rs +++ b/cpclib-visual-bndbuild/src/lib.rs @@ -298,7 +298,9 @@ impl BndBuildApp { match cpclib_bndbuild::BndBuilder::from_path(path) { Ok((ref path, builder)) => { self.filename = Some(path.into()); - self.file_content = std::fs::read_to_string(path).ok().map(|s| s.replace('\r',"")); // read a second time, but the file exists + self.file_content = std::fs::read_to_string(path) + .ok() + .map(|s| s.replace('\r', "")); // read a second time, but the file exists self.builder_and_layers = BuilderAndCache::from(builder).into();