aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGuillaume Pasquet <dev@etenil.net>2022-03-26 06:22:34 +0000
committerGuillaume Pasquet <dev@etenil.net>2022-03-26 06:22:34 +0000
commit08339229db6da6e76726162ba325a625b558cfb6 (patch)
treeca4b87529858d9d9cf3f15dbd42f2ff5ccabc1b8 /src
parent4d76e3d4c852967430b30cff4f6567cb8d7e9235 (diff)
Feature/16 dependencies
Diffstat (limited to 'src')
-rw-r--r--src/barbfile.rs76
-rw-r--r--src/executor.rs16
-rw-r--r--src/main.rs45
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),
}