variable=value overrides done
This commit is contained in:
parent
25c6432fa3
commit
9a368fb351
2
justfile
2
justfile
@ -13,6 +13,8 @@ build:
|
|||||||
check:
|
check:
|
||||||
cargo check
|
cargo check
|
||||||
|
|
||||||
|
nop:
|
||||||
|
|
||||||
publish: clippy build
|
publish: clippy build
|
||||||
# make sure version is up to date
|
# make sure version is up to date
|
||||||
git diff --no-ext-diff --quiet --exit-code
|
git diff --no-ext-diff --quiet --exit-code
|
||||||
|
15
notes
15
notes
@ -7,13 +7,7 @@ notes
|
|||||||
- test values of interpolations
|
- test values of interpolations
|
||||||
- test results of concatination
|
- test results of concatination
|
||||||
- test string escape parsing
|
- test string escape parsing
|
||||||
|
- should it evaluate `` in recipes?
|
||||||
- --debug mode will evaluate everything and print values after assignments and interpolation expressions
|
|
||||||
. should it evaluate `` in recipes?
|
|
||||||
|
|
||||||
- set variables from the command line:
|
|
||||||
. j --set build linux
|
|
||||||
. j build=linux
|
|
||||||
|
|
||||||
- before release:
|
- before release:
|
||||||
|
|
||||||
@ -39,6 +33,8 @@ notes
|
|||||||
. clean
|
. clean
|
||||||
. update logs (repetitive git flow)
|
. update logs (repetitive git flow)
|
||||||
- full documentation
|
- full documentation
|
||||||
|
. man page
|
||||||
|
. record sessions and replay them to output docs
|
||||||
. talk about why the syntax is so unforgiving
|
. talk about why the syntax is so unforgiving
|
||||||
easier to accept a program that you once rejected than to
|
easier to accept a program that you once rejected than to
|
||||||
no longer accept a program or change its meaning
|
no longer accept a program or change its meaning
|
||||||
@ -71,4 +67,9 @@ enhancements:
|
|||||||
. just xyz/foo # xyz/justfile:foo
|
. just xyz/foo # xyz/justfile:foo
|
||||||
. just xyz/ # xyz/justfile:DEFAULT
|
. just xyz/ # xyz/justfile:DEFAULT
|
||||||
- allow setting and exporting environment variables
|
- allow setting and exporting environment variables
|
||||||
|
. export a as "HELLO_BAR"
|
||||||
|
. export a
|
||||||
|
. export HELLO_BAR = a
|
||||||
|
. export CC_FLAGS = "-g"
|
||||||
|
. will have to support crazy names
|
||||||
- indentation or slash for line continuation in plain recipes
|
- indentation or slash for line continuation in plain recipes
|
||||||
|
35
src/app.rs
35
src/app.rs
@ -1,6 +1,8 @@
|
|||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
extern crate regex;
|
||||||
|
|
||||||
use std::{io, fs, env, process};
|
use std::{io, fs, env, process};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use self::clap::{App, Arg};
|
use self::clap::{App, Arg};
|
||||||
use super::Slurp;
|
use super::Slurp;
|
||||||
|
|
||||||
@ -37,6 +39,13 @@ pub fn app() {
|
|||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.value_name("recipe")
|
.value_name("recipe")
|
||||||
.help("Show information about <recipe>"))
|
.help("Show information about <recipe>"))
|
||||||
|
.arg(Arg::with_name("set")
|
||||||
|
.long("set")
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(2)
|
||||||
|
.value_names(&["variable", "value"])
|
||||||
|
.multiple(true)
|
||||||
|
.help("set <variable> to <value>"))
|
||||||
.arg(Arg::with_name("working-directory")
|
.arg(Arg::with_name("working-directory")
|
||||||
.long("working-directory")
|
.long("working-directory")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
@ -123,15 +132,37 @@ pub fn app() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let set_count = matches.occurrences_of("set");
|
||||||
|
let mut overrides = BTreeMap::new();
|
||||||
|
if set_count > 0 {
|
||||||
|
let mut values = matches.values_of("set").unwrap();
|
||||||
|
for _ in 0..set_count {
|
||||||
|
overrides.insert(values.next().unwrap(), values.next().unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let override_re = regex::Regex::new("^([^=]+)=(.*)$").unwrap();
|
||||||
|
|
||||||
let arguments = if let Some(arguments) = matches.values_of("arguments") {
|
let arguments = if let Some(arguments) = matches.values_of("arguments") {
|
||||||
arguments.collect::<Vec<_>>()
|
let mut done = false;
|
||||||
|
let mut rest = vec![];
|
||||||
|
for argument in arguments {
|
||||||
|
if !done && override_re.is_match(argument) {
|
||||||
|
let captures = override_re.captures(argument).unwrap();
|
||||||
|
overrides.insert(captures.at(1).unwrap(), captures.at(2).unwrap());
|
||||||
|
} else {
|
||||||
|
rest.push(argument);
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rest
|
||||||
} else if let Some(recipe) = justfile.first() {
|
} else if let Some(recipe) = justfile.first() {
|
||||||
vec![recipe]
|
vec![recipe]
|
||||||
} else {
|
} else {
|
||||||
die!("Justfile contains no recipes");
|
die!("Justfile contains no recipes");
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(run_error) = justfile.run(&arguments) {
|
if let Err(run_error) = justfile.run(&overrides, &arguments) {
|
||||||
warn!("{}", run_error);
|
warn!("{}", run_error);
|
||||||
match run_error {
|
match run_error {
|
||||||
super::RunError::Code{code, .. } => process::exit(code),
|
super::RunError::Code{code, .. } => process::exit(code),
|
||||||
|
@ -349,3 +349,52 @@ a = `exit 222`",
|
|||||||
",
|
",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_override_options() {
|
||||||
|
integration_test(
|
||||||
|
"unknown_override_options",
|
||||||
|
&["--set", "foo", "bar", "a", "b", "--set", "baz", "bob", "--set", "a", "b"],
|
||||||
|
"foo:
|
||||||
|
echo hello
|
||||||
|
echo {{`exit 111`}}
|
||||||
|
a = `exit 222`",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"baz and foo set on the command line but not present in justfile\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_override_args() {
|
||||||
|
integration_test(
|
||||||
|
"unknown_override_args",
|
||||||
|
&["foo=bar", "baz=bob", "a=b", "a", "b"],
|
||||||
|
"foo:
|
||||||
|
echo hello
|
||||||
|
echo {{`exit 111`}}
|
||||||
|
a = `exit 222`",
|
||||||
|
255,
|
||||||
|
"",
|
||||||
|
"baz and foo set on the command line but not present in justfile\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn overrides_first() {
|
||||||
|
integration_test(
|
||||||
|
"unknown_override_args",
|
||||||
|
&["foo=bar", "a=b", "recipe", "baz=bar"],
|
||||||
|
r#"
|
||||||
|
foo = "foo"
|
||||||
|
a = "a"
|
||||||
|
baz = "baz"
|
||||||
|
|
||||||
|
recipe arg:
|
||||||
|
echo arg={{arg}}
|
||||||
|
echo {{foo + a + baz}}"#,
|
||||||
|
0,
|
||||||
|
"arg=baz=bar\nbarbbaz\n",
|
||||||
|
"echo arg=baz=bar\necho barbbaz\n",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
60
src/lib.rs
60
src/lib.rs
@ -197,6 +197,7 @@ impl<'a> Recipe<'a> {
|
|||||||
evaluated: BTreeMap::new(),
|
evaluated: BTreeMap::new(),
|
||||||
scope: scope,
|
scope: scope,
|
||||||
assignments: &BTreeMap::new(),
|
assignments: &BTreeMap::new(),
|
||||||
|
overrides: &BTreeMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.shebang {
|
if self.shebang {
|
||||||
@ -494,11 +495,13 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
|
|||||||
|
|
||||||
fn evaluate_assignments<'a>(
|
fn evaluate_assignments<'a>(
|
||||||
assignments: &BTreeMap<&'a str, Expression<'a>>,
|
assignments: &BTreeMap<&'a str, Expression<'a>>,
|
||||||
|
overrides: &BTreeMap<&str, &str>,
|
||||||
) -> Result<BTreeMap<&'a str, String>, RunError<'a>> {
|
) -> Result<BTreeMap<&'a str, String>, RunError<'a>> {
|
||||||
let mut evaluator = Evaluator {
|
let mut evaluator = Evaluator {
|
||||||
evaluated: BTreeMap::new(),
|
evaluated: BTreeMap::new(),
|
||||||
scope: &BTreeMap::new(),
|
scope: &BTreeMap::new(),
|
||||||
assignments: assignments,
|
assignments: assignments,
|
||||||
|
overrides: overrides,
|
||||||
};
|
};
|
||||||
|
|
||||||
for name in assignments.keys() {
|
for name in assignments.keys() {
|
||||||
@ -512,6 +515,7 @@ struct Evaluator<'a: 'b, 'b> {
|
|||||||
evaluated: BTreeMap<&'a str, String>,
|
evaluated: BTreeMap<&'a str, String>,
|
||||||
scope: &'b BTreeMap<&'a str, String>,
|
scope: &'b BTreeMap<&'a str, String>,
|
||||||
assignments: &'b BTreeMap<&'a str, Expression<'a>>,
|
assignments: &'b BTreeMap<&'a str, Expression<'a>>,
|
||||||
|
overrides: &'b BTreeMap<&'b str, &'b str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Evaluator<'a, 'b> {
|
impl<'a, 'b> Evaluator<'a, 'b> {
|
||||||
@ -538,8 +542,12 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(expression) = self.assignments.get(name) {
|
if let Some(expression) = self.assignments.get(name) {
|
||||||
|
if let Some(value) = self.overrides.get(name) {
|
||||||
|
self.evaluated.insert(name, value.to_string());
|
||||||
|
} else {
|
||||||
let value = try!(self.evaluate_expression(expression, &BTreeMap::new()));
|
let value = try!(self.evaluate_expression(expression, &BTreeMap::new()));
|
||||||
self.evaluated.insert(name, value);
|
self.evaluated.insert(name, value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(RunError::InternalError {
|
return Err(RunError::InternalError {
|
||||||
message: format!("attempted to evaluated unknown assignment {}", name)
|
message: format!("attempted to evaluated unknown assignment {}", name)
|
||||||
@ -635,19 +643,35 @@ fn mixed_whitespace(text: &str) -> bool {
|
|||||||
!(text.chars().all(|c| c == ' ') || text.chars().all(|c| c == '\t'))
|
!(text.chars().all(|c| c == ' ') || text.chars().all(|c| c == '\t'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct And<'a, T: 'a + Display>(&'a [T]);
|
||||||
struct Or <'a, T: 'a + Display>(&'a [T]);
|
struct Or <'a, T: 'a + Display>(&'a [T]);
|
||||||
|
|
||||||
|
impl<'a, T: Display> Display for And<'a, T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
conjoin(f, self.0, "and")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T: Display> Display for Or<'a, T> {
|
impl<'a, T: Display> Display for Or<'a, T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
match self.0.len() {
|
conjoin(f, self.0, "or")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conjoin<T: Display>(
|
||||||
|
f: &mut fmt::Formatter,
|
||||||
|
values: &[T],
|
||||||
|
conjunction: &str,
|
||||||
|
) -> Result<(), fmt::Error> {
|
||||||
|
match values.len() {
|
||||||
0 => {},
|
0 => {},
|
||||||
1 => try!(write!(f, "{}", self.0[0])),
|
1 => try!(write!(f, "{}", values[0])),
|
||||||
2 => try!(write!(f, "{} or {}", self.0[0], self.0[1])),
|
2 => try!(write!(f, "{} {} {}", values[0], conjunction, values[1])),
|
||||||
_ => for (i, item) in self.0.iter().enumerate() {
|
_ => for (i, item) in values.iter().enumerate() {
|
||||||
try!(write!(f, "{}", item));
|
try!(write!(f, "{}", item));
|
||||||
if i == self.0.len() - 1 {
|
if i == values.len() - 1 {
|
||||||
} else if i == self.0.len() - 2 {
|
} else if i == values.len() - 2 {
|
||||||
try!(write!(f, ", or "));
|
try!(write!(f, ", {} ", conjunction));
|
||||||
} else {
|
} else {
|
||||||
try!(write!(f, ", "))
|
try!(write!(f, ", "))
|
||||||
}
|
}
|
||||||
@ -655,7 +679,6 @@ impl<'a, T: Display> Display for Or<'a, T> {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Display for Error<'a> {
|
impl<'a> Display for Error<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
@ -783,8 +806,20 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
|||||||
self.recipes.keys().cloned().collect()
|
self.recipes.keys().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(&'a self, arguments: &[&'a str]) -> Result<(), RunError<'a>> {
|
fn run(
|
||||||
let scope = try!(evaluate_assignments(&self.assignments));
|
&'a self,
|
||||||
|
overrides: &BTreeMap<&'a str, &'a str>,
|
||||||
|
arguments: &[&'a str]
|
||||||
|
) -> Result<(), RunError<'a>> {
|
||||||
|
let unknown_overrides = overrides.keys().cloned()
|
||||||
|
.filter(|name| !self.assignments.contains_key(name))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if !unknown_overrides.is_empty() {
|
||||||
|
return Err(RunError::UnknownOverrides{overrides: unknown_overrides});
|
||||||
|
}
|
||||||
|
|
||||||
|
let scope = try!(evaluate_assignments(&self.assignments, overrides));
|
||||||
let mut ran = HashSet::new();
|
let mut ran = HashSet::new();
|
||||||
|
|
||||||
for (i, argument) in arguments.iter().enumerate() {
|
for (i, argument) in arguments.iter().enumerate() {
|
||||||
@ -878,6 +913,7 @@ enum RunError<'a> {
|
|||||||
TmpdirIoError{recipe: &'a str, io_error: io::Error},
|
TmpdirIoError{recipe: &'a str, io_error: io::Error},
|
||||||
UnknownFailure{recipe: &'a str},
|
UnknownFailure{recipe: &'a str},
|
||||||
UnknownRecipes{recipes: Vec<&'a str>},
|
UnknownRecipes{recipes: Vec<&'a str>},
|
||||||
|
UnknownOverrides{overrides: Vec<&'a str>},
|
||||||
BacktickCode{code: i32, token: Token<'a>},
|
BacktickCode{code: i32, token: Token<'a>},
|
||||||
BacktickIoError{io_error: io::Error},
|
BacktickIoError{io_error: io::Error},
|
||||||
BacktickSignal{signal: i32},
|
BacktickSignal{signal: i32},
|
||||||
@ -895,6 +931,10 @@ impl<'a> Display for RunError<'a> {
|
|||||||
try!(write!(f, "Justfile does not contain recipes: {}", recipes.join(" ")));
|
try!(write!(f, "Justfile does not contain recipes: {}", recipes.join(" ")));
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
RunError::UnknownOverrides{ref overrides} => {
|
||||||
|
try!(write!(f, "{} set on the command line but not present in justfile",
|
||||||
|
And(overrides)))
|
||||||
|
},
|
||||||
RunError::NonLeadingRecipeWithArguments{recipe} => {
|
RunError::NonLeadingRecipeWithArguments{recipe} => {
|
||||||
try!(write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe specified on the command line", recipe));
|
try!(write!(f, "Recipe `{}` takes arguments and so must be the first and only recipe specified on the command line", recipe));
|
||||||
},
|
},
|
||||||
|
60
src/unit.rs
60
src/unit.rs
@ -1,8 +1,8 @@
|
|||||||
extern crate tempdir;
|
extern crate tempdir;
|
||||||
|
|
||||||
use super::{Token, Error, ErrorKind, Justfile};
|
use super::{Token, Error, ErrorKind, Justfile, RunError};
|
||||||
|
|
||||||
use super::TokenKind::*;
|
use super::TokenKind::*;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
fn tokenize_success(text: &str, expected_summary: &str) {
|
fn tokenize_success(text: &str, expected_summary: &str) {
|
||||||
let tokens = super::tokenize(text).unwrap();
|
let tokens = super::tokenize(text).unwrap();
|
||||||
@ -562,18 +562,26 @@ fn mixed_leading_whitespace() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn write_or() {
|
fn conjoin_or() {
|
||||||
assert_eq!("1", super::Or(&[1 ]).to_string());
|
assert_eq!("1", super::Or(&[1 ]).to_string());
|
||||||
assert_eq!("1 or 2", super::Or(&[1,2 ]).to_string());
|
assert_eq!("1 or 2", super::Or(&[1,2 ]).to_string());
|
||||||
assert_eq!("1, 2, or 3", super::Or(&[1,2,3 ]).to_string());
|
assert_eq!("1, 2, or 3", super::Or(&[1,2,3 ]).to_string());
|
||||||
assert_eq!("1, 2, 3, or 4", super::Or(&[1,2,3,4]).to_string());
|
assert_eq!("1, 2, 3, or 4", super::Or(&[1,2,3,4]).to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn conjoin_and() {
|
||||||
|
assert_eq!("1", super::And(&[1 ]).to_string());
|
||||||
|
assert_eq!("1 and 2", super::And(&[1,2 ]).to_string());
|
||||||
|
assert_eq!("1, 2, and 3", super::And(&[1,2,3 ]).to_string());
|
||||||
|
assert_eq!("1, 2, 3, and 4", super::And(&[1,2,3,4]).to_string());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn unknown_recipes() {
|
fn unknown_recipes() {
|
||||||
match parse_success("a:\nb:\nc:").run(&["a", "x", "y", "z"]).unwrap_err() {
|
match parse_success("a:\nb:\nc:").run(&BTreeMap::new(), &["a", "x", "y", "z"]).unwrap_err() {
|
||||||
super::RunError::UnknownRecipes{recipes} => assert_eq!(recipes, &["x", "y", "z"]),
|
RunError::UnknownRecipes{recipes} => assert_eq!(recipes, &["x", "y", "z"]),
|
||||||
other @ _ => panic!("expected an unknown recipe error, but got: {}", other),
|
other => panic!("expected an unknown recipe error, but got: {}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,8 +747,8 @@ a:
|
|||||||
x
|
x
|
||||||
";
|
";
|
||||||
|
|
||||||
match parse_success(text).run(&["a"]).unwrap_err() {
|
match parse_success(text).run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||||
super::RunError::Code{recipe, code} => {
|
RunError::Code{recipe, code} => {
|
||||||
assert_eq!(recipe, "a");
|
assert_eq!(recipe, "a");
|
||||||
assert_eq!(code, 200);
|
assert_eq!(code, 200);
|
||||||
},
|
},
|
||||||
@ -750,12 +758,12 @@ a:
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn code_error() {
|
fn code_error() {
|
||||||
match parse_success("fail:\n @function x { return 100; }; x").run(&["fail"]).unwrap_err() {
|
match parse_success("fail:\n @function x { return 100; }; x").run(&BTreeMap::new(), &["fail"]).unwrap_err() {
|
||||||
super::RunError::Code{recipe, code} => {
|
RunError::Code{recipe, code} => {
|
||||||
assert_eq!(recipe, "fail");
|
assert_eq!(recipe, "fail");
|
||||||
assert_eq!(code, 100);
|
assert_eq!(code, 100);
|
||||||
},
|
},
|
||||||
other @ _ => panic!("expected a code run error, but got: {}", other),
|
other => panic!("expected a code run error, but got: {}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,8 +773,8 @@ fn run_args() {
|
|||||||
a return code:
|
a return code:
|
||||||
@function x { {{return}} {{code + "0"}}; }; x"#;
|
@function x { {{return}} {{code + "0"}}; }; x"#;
|
||||||
|
|
||||||
match parse_success(text).run(&["a", "return", "15"]).unwrap_err() {
|
match parse_success(text).run(&BTreeMap::new(), &["a", "return", "15"]).unwrap_err() {
|
||||||
super::RunError::Code{recipe, code} => {
|
RunError::Code{recipe, code} => {
|
||||||
assert_eq!(recipe, "a");
|
assert_eq!(recipe, "a");
|
||||||
assert_eq!(code, 150);
|
assert_eq!(code, 150);
|
||||||
},
|
},
|
||||||
@ -776,8 +784,8 @@ a return code:
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_args() {
|
fn missing_args() {
|
||||||
match parse_success("a b c d:").run(&["a", "b", "c"]).unwrap_err() {
|
match parse_success("a b c d:").run(&BTreeMap::new(), &["a", "b", "c"]).unwrap_err() {
|
||||||
super::RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
||||||
assert_eq!(recipe, "a");
|
assert_eq!(recipe, "a");
|
||||||
assert_eq!(found, 2);
|
assert_eq!(found, 2);
|
||||||
assert_eq!(expected, 3);
|
assert_eq!(expected, 3);
|
||||||
@ -788,8 +796,8 @@ fn missing_args() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_default() {
|
fn missing_default() {
|
||||||
match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}").run(&["a"]).unwrap_err() {
|
match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}").run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||||
super::RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
||||||
assert_eq!(recipe, "a");
|
assert_eq!(recipe, "a");
|
||||||
assert_eq!(found, 0);
|
assert_eq!(found, 0);
|
||||||
assert_eq!(expected, 3);
|
assert_eq!(expected, 3);
|
||||||
@ -800,11 +808,25 @@ fn missing_default() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn backtick_code() {
|
fn backtick_code() {
|
||||||
match parse_success("a:\n echo {{`function f { return 100; }; f`}}").run(&["a"]).unwrap_err() {
|
match parse_success("a:\n echo {{`function f { return 100; }; f`}}").run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||||
super::RunError::BacktickCode{code, token} => {
|
RunError::BacktickCode{code, token} => {
|
||||||
assert_eq!(code, 100);
|
assert_eq!(code, 100);
|
||||||
assert_eq!(token.lexeme, "`function f { return 100; }; f`");
|
assert_eq!(token.lexeme, "`function f { return 100; }; f`");
|
||||||
},
|
},
|
||||||
other => panic!("expected an code run error, but got: {}", other),
|
other => panic!("expected an code run error, but got: {}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_overrides() {
|
||||||
|
let mut overrides = BTreeMap::new();
|
||||||
|
overrides.insert("foo", "bar");
|
||||||
|
overrides.insert("baz", "bob");
|
||||||
|
match parse_success("a:\n echo {{`function f { return 100; }; f`}}")
|
||||||
|
.run(&overrides, &["a"]).unwrap_err() {
|
||||||
|
RunError::UnknownOverrides{overrides} => {
|
||||||
|
assert_eq!(overrides, &["baz", "foo"]);
|
||||||
|
},
|
||||||
|
other => panic!("expected an code run error, but got: {}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user