diff options
author | Guillaume Pasquet <dev@etenil.net> | 2022-03-26 06:22:34 +0000 |
---|---|---|
committer | Guillaume Pasquet <dev@etenil.net> | 2022-03-26 06:22:34 +0000 |
commit | 08339229db6da6e76726162ba325a625b558cfb6 (patch) | |
tree | ca4b87529858d9d9cf3f15dbd42f2ff5ccabc1b8 /src | |
parent | 4d76e3d4c852967430b30cff4f6567cb8d7e9235 (diff) |
Feature/16 dependencies
Diffstat (limited to 'src')
-rw-r--r-- | src/barbfile.rs | 76 | ||||
-rw-r--r-- | src/executor.rs | 16 | ||||
-rw-r--r-- | src/main.rs | 45 |
3 files changed, 119 insertions, 18 deletions
diff --git a/src/barbfile.rs b/src/barbfile.rs index 858d035..54ee031 100644 --- a/src/barbfile.rs +++ b/src/barbfile.rs @@ -4,6 +4,10 @@ use serde_json::Value; use std::str::FromStr; use std::string::ToString; use std::{error::Error, fmt}; +use std::cmp::{Eq, PartialEq, PartialOrd, Ord, Ordering}; +use std::fs; +use std::path::Path; + #[cfg(feature = "jq")] use jq_rs; @@ -150,6 +154,7 @@ impl BarbFilter { &self.name } + #[cfg(test)] pub fn filter(&self) -> &String { &self.filter } @@ -201,22 +206,23 @@ struct BarbPreamble { pub url: String, pub headers: Vec<Header>, pub filters: Vec<BarbFilter>, - //pub filter: Option<BarbFilter>, + pub dependency: Option<String>, } impl BarbPreamble { - fn new(method: Method, url: String, headers: Vec<Header>, filters: Vec<BarbFilter>) -> Self { + fn new(method: Method, url: String, headers: Vec<Header>, filters: Vec<BarbFilter>, dependency: Option<String>) -> Self { BarbPreamble { method, url, headers, - //filter: Vec<BarbFilter>, filters, + dependency, } } } pub struct BarbFile { + file_name: String, preamble: BarbPreamble, body: Option<String>, } @@ -245,6 +251,38 @@ impl BarbFile { pub fn body(&self) -> &Option<String> { &self.body } + + pub fn dependency(&self) -> Option<String> { + let dep = self.preamble.dependency.as_ref()?; + let dep_path = Path::new(dep); + + if !dep_path.is_absolute() { + let my_path = Path::new(&self.file_name).parent().or(Some(Path::new("")))?; + return Some(String::from(my_path.join(dep_path).to_str()?)); + } + + Some(String::from(dep_path.to_str()?)) + } +} + +impl PartialEq for BarbFile { + fn eq(&self, other: &Self) -> bool { + self.file_name == other.file_name + } +} + +impl Eq for BarbFile {} + +impl PartialOrd for BarbFile { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + Some(self.cmp(other)) + } +} + +impl Ord for BarbFile { + fn cmp(&self, other: &Self) -> Ordering { + self.file_name.cmp(&other.file_name) + } } fn decode_url_line(line: &str) -> Result<(Method, String), BarbParseError> { @@ -264,6 +302,18 @@ fn decode_header(line: &str) -> Result<Header, BarbParseError> { }) } +impl BarbFile { + pub fn from_file(file_name: String) -> Result<Self, BarbParseError> { + let mut bfile = Self::from_str( + fs::read_to_string(file_name.as_str()) + .map_err(|_| BarbParseError {})? + .as_str() + ).map_err(|_| BarbParseError {})?; + bfile.file_name = file_name; + Ok(bfile) + } +} + impl FromStr for BarbFile { type Err = BarbParseError; @@ -272,6 +322,7 @@ impl FromStr for BarbFile { let (method, url) = decode_url_line(lines.next().ok_or(BarbParseError {})?)?; let mut headers: Vec<Header> = vec![]; let mut filters: Vec<BarbFilter> = vec![]; + let mut dependency: Option<String> = None; for line in &mut lines { if line == "" { @@ -283,6 +334,10 @@ impl FromStr for BarbFile { headers.push(decode_header(line).map_err(|_| BarbParseError {})?); } + if let Some('>') = line.chars().nth(1) { + dependency = line.get(2..).map(|x| String::from(x)); + } + if BarbFilter::is_match(String::from(line)) { match BarbFilter::from_str(line) { Ok(filter) => filters.push(filter), @@ -294,7 +349,8 @@ impl FromStr for BarbFile { let body = lines.fold(String::from(""), |acc, x| acc + x); Ok(BarbFile { - preamble: BarbPreamble::new(method, url, headers, filters), + file_name: String::from(""), + preamble: BarbPreamble::new(method, url, headers, filters, dependency), body: if body == "" { None } else { Some(body) }, }) } @@ -419,4 +475,16 @@ mod tests { let subject = String::from(r#"{"status": "OK"}"#); assert_eq!(path_f.apply(&subject).unwrap(), String::from("OK")); } + + #[test] + fn test_parse_dependency() { + let bfile = BarbFile::from_str("#GET^http://test.com\n#>blah.barb").unwrap(); + assert_eq!(bfile.dependency().as_ref().unwrap(), &String::from("blah.barb")); + } + + #[test] + fn test_parse_mult_dependency_keeps_last() { + let bfile = BarbFile::from_str("#GET^http://test.com\n#>blah.barb\n#>foo.barb\n#>bar.barb").unwrap(); + assert_eq!(bfile.dependency().as_ref().unwrap(), &String::from("bar.barb")); + } } diff --git a/src/executor.rs b/src/executor.rs index 763b0e6..0a6e855 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -2,8 +2,6 @@ use crate::barbfile::{BarbFile, BarbFilter}; use crate::output::BarbOutput; use regex::Regex; use std::collections::HashMap; -use std::fs; -use std::str::FromStr; use ureq; use ureq::Error as UreqError; @@ -16,10 +14,10 @@ impl Context { where I: Iterator<Item = (String, String)>, { - let mut toto = HashMap::new(); - toto.extend(vars); + let mut tmp_vars = HashMap::new(); + tmp_vars.extend(vars); - Context { vars: toto } + Context { vars: tmp_vars } } #[cfg(test)] @@ -129,16 +127,10 @@ impl Executor { pub fn execute( &mut self, - file_name: &String, + bfile: &BarbFile, output: &BarbOutput, filter: &Option<String>, ) -> Result<(), String> { - let bfile = BarbFile::from_str( - fs::read_to_string(file_name.as_str()) - .map_err(|_| format!("Failed to read file '{}'", file_name))? - .as_str(), - ) - .map_err(|_| format!("Failed to parse file '{}'", file_name))?; let response = self.run(&bfile, self.make_req(&bfile, output))?; //let response = executor.execute(&bfile, &output)?; diff --git a/src/main.rs b/src/main.rs index 6dfb7d3..0cd839c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod barbfile; mod executor; mod output; +use barbfile::BarbFile; use clap::Parser; use dotenv::dotenv; use executor::{Context, Executor}; @@ -47,14 +48,54 @@ impl Args { } } +fn read_file_barb(file_name: &String) -> Result<BarbFile, String> { + BarbFile::from_file(file_name.to_string()) + .map_err(|_| String::from(format!("Failed to parse file {}", file_name))) +} + fn main() { let args = Args::parse(); dotenv().ok(); let mut executor = Executor::new(Context::new(env::vars())); let output = args.output(); - for file in args.files_iter() { - match executor.execute(file, &output, args.jq_filter()) { + let files: Vec<Result<BarbFile, String>> = args.files_iter() + .map(read_file_barb) + .collect(); + + let (maybe_deps, errors): (Vec<Result<BarbFile, String>>, Vec<Result<BarbFile, String>>) = files.iter() + .map(|x| match x.as_ref().ok() { + Some(bfile) => bfile.dependency(), + None => None + }) + .filter(|x| x.is_some()) + .map(|x| read_file_barb(&String::from(x.unwrap()))) + .partition(|x| x.is_ok()); + + for e in errors { + println!("{}", e.err().unwrap()); + } + + let mut dependencies = maybe_deps.iter() + .map(|x| x.as_ref().unwrap()) + .collect::<Vec<&BarbFile>>(); + dependencies.sort(); + dependencies.dedup(); + + for dep in dependencies { + match executor.execute(&dep, &output, args.jq_filter()) { + Ok(()) => (), + Err(err) => println!("{}", err), + } + } + + for bfile in files { + if let Err(e) = bfile { + println!("{}", e); + continue; + } + + match executor.execute(&bfile.unwrap(), &output, args.jq_filter()) { Ok(()) => (), Err(err) => println!("{}", err), } |