From 14e9e25b6a06f587c1a50829e72c829ae59a87c2 Mon Sep 17 00:00:00 2001 From: Jan Allersma Date: Dec 10 2018 20:57:08 +0000 Subject: Implement `run` and `build` commands. * Replace all std::io::Result with std::result::Result. --- diff --git a/src/backend/build.rs b/src/backend/build.rs index d75299f..db2c6a7 100644 --- a/src/backend/build.rs +++ b/src/backend/build.rs @@ -1,12 +1,65 @@ -use std::io::Result; +extern crate serde_json; -pub fn build(config: String) -> Result { - println!("Building project.."); +use std::result::Result; +use std::path::PathBuf; +use std::env; + +pub fn build(config_file: PathBuf) -> Result { + let config; + + match super::config::get_json(config_file) { + Ok(result) => config = result, + Err(e) => return Err(e) + } - match super::check::dep(config) { + match super::check::dep(config.clone()) { + Ok(result) => println!("{}", result), + Err(e) => return Err(e) + } + + match build_module(config) { Ok(result) => println!("{}", result), Err(e) => return Err(e) } Ok(String::from("Build succeeded!")) } + +#[cfg(target_os="linux")] +fn build_module(config: serde_json::Value) -> Result { + println!("Building project.."); + + let build_cmd = &config["build"]["linux"]; + + if !build_cmd.is_string() { + return Err(String::from("beheer.json: 'build->linux' should be a string.")); + } + + super::fetch::fetch(env::current_dir().unwrap(), String::from(build_cmd.as_str().unwrap())) +} + +#[cfg(target_os="macos")] +fn build_module(config: serde_json::Value) -> Result { + println!("Building project.."); + + let build_cmd = &config["build"]["os-x"]; + + if !build_cmd.is_string() { + return Err(String::from("beheer.json: 'build->os-x' should be a string.")); + } + + super::fetch::fetch(env::get_current_dir().unwrap(), String::from(build_cmd.as_str().unwrap())) +} + +#[cfg(target_os="windows")] +fn build_module(config: serde_json::Value) -> Result { + println!("Building project.."); + + let build_cmd = &config["build"]["windows"]; + + if !build_cmd.is_string() { + return Err(String::from("beheer.json: 'build->windows' should be a string.")); + } + + super::fetch::fetch(env::get_current_dir().unwrap(), String::from(build_cmd.as_str().unwrap())) +} diff --git a/src/backend/check.rs b/src/backend/check.rs index 08d2bca..260e822 100644 --- a/src/backend/check.rs +++ b/src/backend/check.rs @@ -1,11 +1,11 @@ extern crate serde_json; -use std::io::{Result, Error, ErrorKind}; +use std::result::Result; -pub fn dep(config: String) -> Result { +pub fn json(config: String) -> Result { let config_json: serde_json::Value; - println!("Checking dependencies.."); + println!("Reading module configuration.."); match serde_json::from_str(&config) { Ok(json) => config_json = json, @@ -19,40 +19,42 @@ pub fn dep(config: String) -> Result { match e.classify() { serde_json::error::Category::Io => { error.push_str("Weird error...."); - return Err(Error::new(ErrorKind::Other, error)); + return Err(error); }, serde_json::error::Category::Syntax => { error.push_str("Syntax error in 'beheer.json'"); - return Err(Error::new(ErrorKind::InvalidInput, error)); + return Err(error); }, serde_json::error::Category::Data => { error.push_str("Semantic error in 'beheer.json'"); - return Err(Error::new(ErrorKind::InvalidData, error)); + return Err(error); }, serde_json::error::Category::Eof => { error.push_str("Unexpected end-of-file in 'beheer.json'"); - return Err(Error::new(ErrorKind::UnexpectedEof, error)); + return Err(error); } } } } - config_check(config_json) + Ok(config_json) } #[cfg(target_os="linux")] -fn config_check(config: serde_json::Value) -> Result { +pub fn dep(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + match config["deps"]["linux"] { json!(null) => return Ok(String::from("No dependencies found!")), ref deps => { if !deps.is_object() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: 'deps->linux' should be an object.")); + return Err(String::from("beheer.json: 'deps->linux' should be an object.")); } for dep in deps.as_object().unwrap().iter() { if !dep.1.is_string() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: all deps should be strings!")); + return Err(String::from("beheer.json: all deps should be strings!")); } println!("Checking for {}..\n\t{}", dep.0, dep.1); @@ -68,18 +70,20 @@ fn config_check(config: serde_json::Value) -> Result { } #[cfg(target_os="macos")] -fn config_check(config: serde_json::Value) -> Result { +pub fn dep(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + match config["deps"]["os-x"] { json!(null) => return Ok(String::from("No dependencies found!")), ref sys_deps => { if !sys_deps.is_object() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: 'deps->os-x' should be an object.")); + return Err(String::from("beheer.json: 'deps->os-x' should be an object.")); } for dep in deps.as_object().unwrap().iter() { if !dep.1.is_string() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: all deps should be strings!")); + return Err(String::from("beheer.json: all deps should be strings!")); } println!("Checking for {}..\n\t{}", dep.0, dep.1); @@ -94,23 +98,26 @@ fn config_check(config: serde_json::Value) -> Result { } #[cfg(target_os="windows")] -fn config_check(config: serde_json::Value) -> Result { +pub fn dep(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + match config["deps"]["windows"] { json!(null) => return Ok(String::from("No dependencies found!")), ref sys_deps => { if !sys_deps.is_object() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: 'deps->windows' should be an object.")); + return Err(String::from("beheer.json: 'deps->windows' should be an object.")); } for dep in deps.as_object().unwrap().iter() { if !dep.1.is_string() { - return Err(Error::new(ErrorKind::InvalidData, "beheer.json: all deps should be strings!")); + return Err(String::from("beheer.json: all deps should be strings!")); } println!("Checking for {}..\n\t{}", dep.0, dep.1); - if dir_check(dep.0.to_string(), String::from(dep.1.as_str().unwrap())) == Err(e) { - return Err(e); + match dir_check(dep.0.to_string(), String::from(dep.1.as_str().unwrap())) { + Ok(output) => println!("{}", output), + Err(e) => return Err(e) } } } @@ -118,18 +125,18 @@ fn config_check(config: serde_json::Value) -> Result { Ok(String::from("Dependencies OK!")) } -fn dir_check(dependency: String, command: String) -> Result<()> { +fn dir_check(dependency: String, command: String) -> Result { let dir = super::filesystem::get_dep_dir(); match dir { Ok(mut dep_dir) => { dep_dir.push(dependency); - if !dep_dir.is_dir() { + if !dep_dir.exists() { dep_dir.pop(); - super::fetch::fetch(dep_dir, command); + return super::fetch::fetch(dep_dir, command); } - Ok(()) + Ok(String::from("Dependency found.")) }, - Err(e) => Err(e) + Err(e) => Err(e.to_string()) } } diff --git a/src/backend/config.rs b/src/backend/config.rs index 28e0742..20ae5d1 100644 --- a/src/backend/config.rs +++ b/src/backend/config.rs @@ -1,10 +1,11 @@ extern crate serde_json; -use std::io::{Result, Error, ErrorKind, Write, Read}; +use std::io::{Error, ErrorKind, Write, Read}; use std::fs::File; use std::path::PathBuf; +use std::result::Result; -pub fn create(mut path: PathBuf) -> Result<()> { +pub fn create(mut path: PathBuf) -> Result<(), Error> { let content = json!({ "project-name": path.file_name().unwrap().to_str().unwrap(), "version": 0.1, @@ -37,17 +38,24 @@ pub fn create(mut path: PathBuf) -> Result<()> { Ok(()) } -pub fn read(mut path: PathBuf) -> Result { +fn read(mut path: PathBuf) -> Result { let mut config = String::new(); path.push("beheer.json"); match File::open(path.to_str().unwrap()) { Ok(mut file) => { - file.read_to_string(&mut config)?; + file.read_to_string(&mut config).unwrap(); }, - Err(e) => return Err(e) + Err(e) => return Err(e.to_string()) } Ok(config) } + +pub fn get_json(path: PathBuf) -> Result { + match read(path) { + Ok(config) => super::check::json(config), + Err(e) => Err(e.to_string()) + } +} diff --git a/src/backend/fetch.rs b/src/backend/fetch.rs index 613e432..2ef99f1 100644 --- a/src/backend/fetch.rs +++ b/src/backend/fetch.rs @@ -1,10 +1,14 @@ use std::process::Command; use std::path; +use std::result::Result; -pub fn fetch(dep: path::PathBuf, command: String) { +pub fn fetch(dep: path::PathBuf, command: String) -> Result { let mut args: Vec<&str> = command.split(' ').collect(); let command = args.remove(0); let out = Command::new(command).current_dir(dep).args(args).output().expect(""); - println!("{:#?}", out.stderr); + match out.status.success() { + true => Ok(String::from_utf8_lossy(&out.stdout).to_string()), + false => Err(String::from_utf8_lossy(&out.stderr).to_string()) + } } diff --git a/src/backend/filesystem.rs b/src/backend/filesystem.rs index 71578e5..7b57573 100644 --- a/src/backend/filesystem.rs +++ b/src/backend/filesystem.rs @@ -43,9 +43,9 @@ pub fn get_dep_dir() -> Result { Some(mut path) => { path.push("dep"); if !path.is_dir() { - println!("No dep folder found. Creating folder.."); + println!("\tNo dep folder found. Creating folder.."); match fs::create_dir(path.clone()) { - Ok(_) => println!("Created dir {}.", path.clone().to_str().unwrap()), + Ok(_) => println!("\tCreated dir {}.", path.clone().to_str().unwrap()), Err(e) => return Err(e) } } diff --git a/src/backend/project.rs b/src/backend/project.rs index 38495ac..8640ea4 100644 --- a/src/backend/project.rs +++ b/src/backend/project.rs @@ -1,5 +1,6 @@ use std::env; -use std::io::{Result, Error, ErrorKind}; +use std::result::Result; +use std::process::{Command, Stdio}; pub fn init(args: &mut env::Args) { let mut directory = env::current_dir().unwrap(); @@ -14,15 +15,67 @@ pub fn init(args: &mut env::Args) { } } -pub fn build() -> Result { +pub fn build() -> Result { match super::filesystem::get_project_root() { - Some(dir) => { - match super::config::read(dir) { - Ok(configfile) => return super::build::build(configfile), - Err(e) => Err(e) + Some(dir) => super::build::build(dir), + None => Err(String::from("not in a project (sub)directory.")) + } +} + +pub fn run(args: &mut env::Args) -> Result { + let output_dir; + let mut args = String::new(); + + println!("Building project.."); + + match build() { + Ok(output) => println!("{}", output), + Err(e) => return Err(e) + } + + match super::filesystem::get_project_root() { + Some(dir) => output_dir = dir, + None => return Err(String::from("not in a project (sub)directory.")) + } + + match super::config::get_json(output_dir) { + Ok(config) => { + if cfg!(target_os = "linux") { + match config["run"]["linux"].as_str() { + Some(string) => args = String::from(string), + None => return Err(String::from("beheer.json: 'run->linux' should be a string.")) + } + } + if cfg!(target_os = "macos") { + match config["run"]["os-x"].as_str() { + Some(string) => args = String::from(string), + None => return Err(String::from("beheer.json: 'run->os-x' should be a string.")) + } + } + if cfg!(target_os = "windows") { + match config["run"]["windows"].as_str() { + Some(string) => args = String::from(string), + None => return Err(String::from("beheer.json: 'run->windows' should be a string.")) + } } }, - None => Err(Error::new(ErrorKind::NotFound, "not in a project (sub)directory.")) + Err(e) => return Err(e) + } + + println!("Running project.."); + + let mut arguments: Vec<&str> = args.split(' ').collect(); + let command = arguments.remove(0); + let out = Command::new(command) + .args(arguments) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .output() + .expect(""); + + match out.status.success() { + true => Ok(String::from_utf8_lossy(&out.stdout).to_string()), + false => Err(String::from_utf8_lossy(&out.stderr).to_string()) } } diff --git a/src/main.rs b/src/main.rs index 103a172..fa8f0d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,12 @@ fn parse() { Err(e) => println!("Build failed: {}", e) } } + else if &argument == "run" { + match backend::project::run(&mut argv) { + Ok(_) => {}, + Err(e) => println!("Running project failed: {}", e) + } + } }, None => backend::project::help() }