From 45d9dfdbfc99c59174e7c587621276b78ab7a4e9 Mon Sep 17 00:00:00 2001 From: Jan Allersma Date: Dec 14 2018 16:13:12 +0000 Subject: Implement experimental `dep-tree` command. --- diff --git a/src/backend/build.rs b/src/backend/build.rs index db2c6a7..5c8a4db 100644 --- a/src/backend/build.rs +++ b/src/backend/build.rs @@ -12,7 +12,7 @@ pub fn build(config_file: PathBuf) -> Result { Err(e) => return Err(e) } - match super::check::dep(config.clone()) { + match super::dep::check(config.clone()) { Ok(result) => println!("{}", result), Err(e) => return Err(e) } diff --git a/src/backend/check.rs b/src/backend/check.rs deleted file mode 100644 index 571c6a8..0000000 --- a/src/backend/check.rs +++ /dev/null @@ -1,142 +0,0 @@ -extern crate serde_json; - -use std::result::Result; - -pub fn json(config: String) -> Result { - let config_json: serde_json::Value; - - println!("Reading module configuration.."); - - match serde_json::from_str(&config) { - Ok(json) => config_json = json, - Err(e) => { - let mut error = String::from("JSON ERROR! "); - error.push_str(&e.line().to_string()); - error.push(':'); - error.push_str(&e.column().to_string()); - error.push(' '); - - match e.classify() { - serde_json::error::Category::Io => { - error.push_str("Weird error...."); - return Err(error); - }, - serde_json::error::Category::Syntax => { - error.push_str("Syntax error in 'beheer.json'"); - return Err(error); - }, - serde_json::error::Category::Data => { - error.push_str("Semantic error in 'beheer.json'"); - return Err(error); - }, - serde_json::error::Category::Eof => { - error.push_str("Unexpected end-of-file in 'beheer.json'"); - return Err(error); - } - } - } - } - - Ok(config_json) -} - -#[cfg(target_os="linux")] -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(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(String::from("beheer.json: all deps should be strings!")); - } - - println!("Checking for {}..\n\t{}", dep.0, dep.1); - - match dir_check(dep.0.to_string(), String::from(dep.1.as_str().unwrap())) { - Ok(_) => {}, - Err(e) => return Err(e) - } - } - } - } - Ok(String::from("Dependencies OK!")) -} - -#[cfg(target_os="macos")] -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(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(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); - } - } - } - } - Ok(String::from("Dependencies OK!")) -} - -#[cfg(target_os="windows")] -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(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(String::from("beheer.json: all deps should be strings!")); - } - - println!("Checking for {}..\n\t{}", dep.0, dep.1); - - match dir_check(dep.0.to_string(), String::from(dep.1.as_str().unwrap())) { - Ok(output) => println!("{}", output), - Err(e) => return Err(e) - } - } - } - } - Ok(String::from("Dependencies OK!")) -} - -fn dir_check(dependency: String, command: String) -> Result { - let dir = super::filesystem::get_dep_root(); - - match dir { - Ok(mut dep_dir) => { - dep_dir.push(dependency); - if !dep_dir.exists() { - dep_dir.pop(); - return super::fetch::fetch(dep_dir, command); - } - Ok(String::from("Dependency found.")) - }, - Err(e) => Err(e.to_string()) - } -} diff --git a/src/backend/config.rs b/src/backend/config.rs index 9a5c8b1..339e983 100644 --- a/src/backend/config.rs +++ b/src/backend/config.rs @@ -69,7 +69,7 @@ fn read(mut path: PathBuf) -> Result { pub fn get_json(path: PathBuf) -> Result { match read(path) { - Ok(config) => super::check::json(config), + Ok(config) => super::dep::json(config), Err(e) => Err(e.to_string()) } } diff --git a/src/backend/dep.rs b/src/backend/dep.rs new file mode 100644 index 0000000..b57c7ce --- /dev/null +++ b/src/backend/dep.rs @@ -0,0 +1,212 @@ +extern crate serde_json; + +use std::result::Result; + +pub enum OS { + all, + linux, + macos, + windows +} + +pub fn json(config: String) -> Result { + let config_json: serde_json::Value; + + println!("Reading module configuration.."); + + match serde_json::from_str(&config) { + Ok(json) => config_json = json, + Err(e) => { + let mut error = String::from("JSON ERROR! "); + error.push_str(&e.line().to_string()); + error.push(':'); + error.push_str(&e.column().to_string()); + error.push(' '); + + match e.classify() { + serde_json::error::Category::Io => { + error.push_str("Weird error...."); + return Err(error); + }, + serde_json::error::Category::Syntax => { + error.push_str("Syntax error in 'beheer.json'"); + return Err(error); + }, + serde_json::error::Category::Data => { + error.push_str("Semantic error in 'beheer.json'"); + return Err(error); + }, + serde_json::error::Category::Eof => { + error.push_str("Unexpected end-of-file in 'beheer.json'"); + return Err(error); + } + } + } + } + + Ok(config_json) +} + +pub fn dep(config: serde_json::Value, os: OS) -> Result, String> { + let mut output: Vec<(String, String)> = Vec::new(); + + match os { + OS::all => { + match dep(config.clone(), OS::linux) { + Ok(mut result) => { + let mut r: Vec<(String,String)> = result; + output.append(&mut r) + }, + Err(e) => return Err(e) + } + match dep(config.clone(), OS::macos) { + Ok(mut result) => { + let mut r: Vec<(String,String)> = result; + output.append(&mut r) + }, + Err(e) => return Err(e) + } + match dep(config.clone(), OS::windows) { + Ok(mut result) => { + let mut r: Vec<(String,String)> = result; + output.append(&mut r) + }, + Err(e) => return Err(e) + } + }, + OS::linux => match config["deps"]["linux"] { + json!(null) => return Ok(output), + ref deps => { + match deps.as_object() { + Some(object) => { + for dep in object.iter() { + if !dep.1.is_string() { + return Err(String::from("beheer.json: all deps should be strings!")) + } + output.push((dep.0.to_string(), String::from(dep.1.as_str().unwrap()))); + } + }, + None => return Err(String::from("beheer.json: 'deps->linux' should be an object.")) + } + } + }, + OS::macos => match config["deps"]["os-x"] { + json!(null) => return Ok(output), + ref deps => { + match deps.as_object() { + Some(object) => { + for dep in object.iter() { + if !dep.1.is_string() { + return Err(String::from("beheer.json: all deps should be strings!")) + } + output.push((dep.0.to_string(), String::from(dep.1.as_str().unwrap()))); + } + }, + None => return Err(String::from("beheer.json: 'deps->os-x' should be an object.")) + } + } + }, + OS::windows => match config["deps"]["windows"] { + json!(null) => return Ok(output), + ref deps => { + match deps.as_object() { + Some(object) => { + for dep in object.iter() { + if !dep.1.is_string() { + return Err(String::from("beheer.json: all deps should be strings!")) + } + output.push((dep.0.to_string(), String::from(dep.1.as_str().unwrap()))); + } + }, + None => return Err(String::from("beheer.json: 'deps->windows' should be an object.")) + } + } + } + } + Ok(output) +} + +#[cfg(target_os="linux")] +pub fn check(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + + match dep(config, OS::linux) { + Ok(ref deps) if deps.is_empty() => return Ok(String::from("No dependencies found!")), + Ok(ref deps) => { + for dep in deps.iter() { + let dep_clone = dep.clone(); + + println!("Checking for {}..\n\t{}", dep_clone.0, dep_clone.1); + + match dir_check(dep_clone.0, dep_clone.1) { + Ok(_) => {}, + Err(e) => return Err(e) + } + } + }, + Err(e) => return Err(e) + } + Ok(String::from("Dependencies OK!")) +} + +#[cfg(target_os="macos")] +pub fn check(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + + match dep(config, OS::macos) { + Ok(ref deps) if deps.is_empty() => return Ok(String::from("No dependencies found!")), + Ok(ref deps) => { + for dep in deps.iter() { + let dep_clone = dep.clone(); + + println!("Checking for {}..\n\t{}", dep_clone.0, dep_clone.1); + + match dir_check(dep_clone.0, dep_clone.1) { + Ok(_) => {}, + Err(e) => return Err(e) + } + } + }, + Err(e) => return Err(e) + } + Ok(String::from("Dependencies OK!")) +} + +#[cfg(target_os="windows")] +pub fn check(config: serde_json::Value) -> Result { + println!("Checking dependencies.."); + + match dep(config, OS::windows) { + Ok(ref deps) if deps.is_empty() => return Ok(String::from("No dependencies found!")), + Ok(ref deps) => { + for dep in deps.iter() { + let dep_clone = dep.clone(); + + println!("Checking for {}..\n\t{}", dep_clone.0, dep_clone.1); + + match dir_check(dep_clone.0, dep_clone.1) { + Ok(_) => {}, + Err(e) => return Err(e) + } + } + }, + Err(e) => return Err(e) + } + Ok(String::from("Dependencies OK!")) +} + +fn dir_check(dependency: String, command: String) -> Result { + let dir = super::filesystem::get_dep_root(); + + match dir { + Ok(mut dep_dir) => { + dep_dir.push(dependency); + if !dep_dir.exists() { + dep_dir.pop(); + return super::fetch::fetch(dep_dir, command); + } + Ok(String::from("Dependency found.")) + }, + Err(e) => Err(e.to_string()) + } +} diff --git a/src/backend/deptree.rs b/src/backend/deptree.rs new file mode 100644 index 0000000..027dd6b --- /dev/null +++ b/src/backend/deptree.rs @@ -0,0 +1,51 @@ +extern crate serde_json; + +use super::dep as backend; +use std::result::Result; +use std::option::Option; +use std::path::PathBuf; +use std::rc::Rc; +use std::fmt; + +pub struct Node { + dep_name: String, + path: PathBuf, + depends_on: Option> +} + +// Incomplete +impl fmt::Display for Node { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "Incomplete")); + Ok(()) + } +} + +pub fn print(os: backend::OS) -> Result { + let mut deps: Vec = Vec::new(); + let path: PathBuf; + + match super::filesystem::get_module_root() { + Some(p) => path = p, + None => return Err(String::from("Not in a project/dependency directory.")) + } + + let deps_json = match super::config::get_json(path) { + Ok(config) => config, + Err(e) => return Err(e) + }; + + match backend::dep(deps_json, os) { + Ok(vector) => vector.iter().for_each(|tuple| deps.push(tuple.0.clone())), + Err(e) => return Err(e) + } + + // Incomplete + let root = Node { + dep_name: String::from("root"), + path: super::filesystem::get_module_root().unwrap(), + depends_on: None + }; + + Ok(root) +} diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 7601bdb..241dd96 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -1,7 +1,8 @@ pub mod add; pub mod config; +pub mod deptree; pub mod project; pub mod filesystem; pub mod build; -pub mod check; +pub mod dep; pub mod fetch; diff --git a/src/backend/project.rs b/src/backend/project.rs index 093e329..aaaaa77 100644 --- a/src/backend/project.rs +++ b/src/backend/project.rs @@ -1,6 +1,7 @@ use std::env; use std::result::Result; use std::process::{Command, Stdio}; +use super::deptree; pub fn init(args: &mut env::Args) { let mut directory = env::current_dir().unwrap(); @@ -83,6 +84,11 @@ pub fn run(args: &mut env::Args) -> Result { exe(args) } +// Args need to be processed.. +pub fn dep_tree(args: &mut env::Args) -> Result { + deptree::print(super::dep::OS::all) +} + pub fn help() { println!("Syntax:"); println!("$ beheer [FLAG] [COMMAND [ARGUMENTS]]"); @@ -91,9 +97,10 @@ pub fn help() { println!("--help -h\t\tShow this message"); println!(""); - println!("init [DIRECTORY]\t\tInitialize new project in specified directory. Defaults to current directory."); - println!("build\t\t\t\tBuild current project."); - println!("run [ARGUMENTS]\t\t\tBuild and run current project with ARGUMENTS to run project with."); - println!("exe [ARGUMENTS]\t\t\tRun current project with ARGUMENTS. The project won't be built."); - println!("add NAME COMMAND [ARGUMENTS]\tAdd dependency with NAME to module and is built through COMMAND with ARGUMENTS."); + println!("init [DIRECTORY]\t\t Initialize new project in specified directory. Defaults to current directory."); + println!("build\t\t\t\t Build current project."); + println!("run [ARGUMENTS]\t\t\t Build and run current project with ARGUMENTS to run project with."); + println!("exe [ARGUMENTS]\t\t\t Run current project with ARGUMENTS. The project won't be built."); + println!("add NAME COMMAND [ARGUMENTS]\t Add dependency with NAME to module and is built through COMMAND with ARGUMENTS."); + println!("dep-tree [all|linux|os-x|windows] Print a tree of all dependencies used (indirectly) by a project for specified OS. Defaults to 'all'."); } diff --git a/src/main.rs b/src/main.rs index 58a7dd2..6dcd39b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,6 +50,12 @@ fn parse() { Err(e) => println!("Could not add dependency: {}", e) } } + else if &argument == "dep-tree" { + match backend::project::dep_tree(&mut argv) { + Ok(tree) => println!("{}", tree), + Err(e) => println!("Could not deduce dependency tree: {}", e) + } + } }, None => backend::project::help() }