Bump version, add --debug
This commit is contained in:
parent
9a368fb351
commit
cc683cbb04
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "j"
|
||||
version = "0.2.7"
|
||||
version = "0.2.8"
|
||||
authors = ["Casey Rodarmor <casey@rodarmor.com>"]
|
||||
license = "WTFPL/MIT/Apache-2.0"
|
||||
description = "a command runner"
|
||||
|
19
notes
19
notes
@ -1,15 +1,8 @@
|
||||
notes
|
||||
-----
|
||||
todo
|
||||
----
|
||||
|
||||
- --debug tests that:
|
||||
- should consider renaming it to --evaluate if it actually evaluates stuff
|
||||
- test values of assignments
|
||||
- test values of interpolations
|
||||
- test results of concatination
|
||||
- test string escape parsing
|
||||
- should it evaluate `` in recipes?
|
||||
|
||||
- before release:
|
||||
before release
|
||||
--------------
|
||||
|
||||
- where can users get help?
|
||||
- irc, email, github, mailing list
|
||||
@ -54,7 +47,8 @@ notes
|
||||
. irc
|
||||
. r/rust
|
||||
|
||||
enhancements:
|
||||
enhancements
|
||||
------------
|
||||
|
||||
- lazy assignment: don't evaluate unused assignments
|
||||
- use cow strings where we currently use String
|
||||
@ -66,6 +60,7 @@ enhancements:
|
||||
. just ../foo # ../justfile:foo
|
||||
. just xyz/foo # xyz/justfile:foo
|
||||
. just xyz/ # xyz/justfile:DEFAULT
|
||||
. path prefix is starting dir, so just ../foo can run ../../justfile:foo
|
||||
- allow setting and exporting environment variables
|
||||
. export a as "HELLO_BAR"
|
||||
. export a
|
||||
|
23
src/app.rs
23
src/app.rs
@ -23,16 +23,19 @@ macro_rules! die {
|
||||
|
||||
pub fn app() {
|
||||
let matches = App::new("j")
|
||||
.version("0.2.7")
|
||||
.author("Casey R. <casey@rodarmor.com>")
|
||||
.version("0.2.8")
|
||||
.author("Casey Rodarmor <casey@rodarmor.com>")
|
||||
.about("Just a command runner - https://github.com/casey/j")
|
||||
.arg(Arg::with_name("list")
|
||||
.short("l")
|
||||
.long("list")
|
||||
.help("Lists available recipes"))
|
||||
.arg(Arg::with_name("debug")
|
||||
.long("debug")
|
||||
.help("Prints the justfile with debugging information, such as evaluated expression and assignment"))
|
||||
.arg(Arg::with_name("dry-run")
|
||||
.long("dry-run")
|
||||
.help("Print recipe text without executing"))
|
||||
.arg(Arg::with_name("evaluate")
|
||||
.long("evaluate")
|
||||
.help("Print evaluated variables"))
|
||||
.arg(Arg::with_name("show")
|
||||
.short("s")
|
||||
.long("show")
|
||||
@ -108,11 +111,6 @@ pub fn app() {
|
||||
|
||||
let justfile = super::parse(&text).unwrap_or_else(|error| die!("{}", error));
|
||||
|
||||
if matches.is_present("debug") {
|
||||
println!("{:#}", justfile);
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
if matches.is_present("list") {
|
||||
if justfile.count() == 0 {
|
||||
warn!("Justfile contains no recipes");
|
||||
@ -162,7 +160,10 @@ pub fn app() {
|
||||
die!("Justfile contains no recipes");
|
||||
};
|
||||
|
||||
if let Err(run_error) = justfile.run(&overrides, &arguments) {
|
||||
let dry_run = matches.is_present("dry-run");
|
||||
let evaluate = matches.is_present("evaluate");
|
||||
|
||||
if let Err(run_error) = justfile.run(&overrides, &arguments, dry_run, evaluate) {
|
||||
warn!("{}", run_error);
|
||||
match run_error {
|
||||
super::RunError::Code{code, .. } => process::exit(code),
|
||||
|
@ -398,3 +398,62 @@ recipe arg:
|
||||
"echo arg=baz=bar\necho barbbaz\n",
|
||||
);
|
||||
}
|
||||
|
||||
// shebangs are printed
|
||||
|
||||
#[test]
|
||||
fn dry_run() {
|
||||
integration_test(
|
||||
"dry_run",
|
||||
&["--dry-run", "shebang", "command"],
|
||||
r#"
|
||||
var = `echo stderr 1>&2; echo backtick`
|
||||
|
||||
command:
|
||||
@touch /this/is/not/a/file
|
||||
{{var}}
|
||||
echo {{`echo command interpolation`}}
|
||||
|
||||
shebang:
|
||||
#!/bin/sh
|
||||
touch /this/is/not/a/file
|
||||
{{var}}
|
||||
echo {{`echo shebang interpolation`}}"#,
|
||||
0,
|
||||
"",
|
||||
"stderr
|
||||
#!/bin/sh
|
||||
touch /this/is/not/a/file
|
||||
backtick
|
||||
echo shebang interpolation
|
||||
touch /this/is/not/a/file
|
||||
backtick
|
||||
echo command interpolation
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluate() {
|
||||
integration_test(
|
||||
"evaluate",
|
||||
&["--evaluate"],
|
||||
r#"
|
||||
foo = "a\t"
|
||||
baz = "c"
|
||||
bar = "b\t"
|
||||
abc = foo + bar + baz
|
||||
|
||||
wut:
|
||||
touch /this/is/not/a/file
|
||||
"#,
|
||||
0,
|
||||
r#"abc = "a b c"
|
||||
bar = "b "
|
||||
baz = "c"
|
||||
foo = "a "
|
||||
"#,
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
|
43
src/lib.rs
43
src/lib.rs
@ -188,7 +188,8 @@ impl<'a> Recipe<'a> {
|
||||
fn run(
|
||||
&self,
|
||||
arguments: &[&'a str],
|
||||
scope: &BTreeMap<&'a str, String>
|
||||
scope: &BTreeMap<&'a str, String>,
|
||||
dry_run: bool,
|
||||
) -> Result<(), RunError<'a>> {
|
||||
let argument_map = arguments .iter().enumerate()
|
||||
.map(|(i, argument)| (self.arguments[i], *argument)).collect();
|
||||
@ -206,6 +207,13 @@ impl<'a> Recipe<'a> {
|
||||
evaluated_lines.push(try!(evaluator.evaluate_line(&line, &argument_map)));
|
||||
}
|
||||
|
||||
if dry_run {
|
||||
for line in evaluated_lines {
|
||||
warn!("{}", line);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let tmp = try!(
|
||||
tempdir::TempDir::new("j")
|
||||
.map_err(|error| RunError::TmpdirIoError{recipe: self.name, io_error: error})
|
||||
@ -266,11 +274,16 @@ impl<'a> Recipe<'a> {
|
||||
for line in &self.lines {
|
||||
let evaluated = &try!(evaluator.evaluate_line(&line, &argument_map));
|
||||
let mut command = evaluated.as_str();
|
||||
if !command.starts_with('@') {
|
||||
warn!("{}", command);
|
||||
} else {
|
||||
let quiet = command.starts_with('@');
|
||||
if quiet {
|
||||
command = &command[1..];
|
||||
}
|
||||
if dry_run || !quiet {
|
||||
warn!("{}", command);
|
||||
}
|
||||
if dry_run {
|
||||
continue;
|
||||
}
|
||||
let status = process::Command::new("sh")
|
||||
.arg("-cu")
|
||||
.arg(command)
|
||||
@ -809,7 +822,9 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
fn run(
|
||||
&'a self,
|
||||
overrides: &BTreeMap<&'a str, &'a str>,
|
||||
arguments: &[&'a str]
|
||||
arguments: &[&'a str],
|
||||
dry_run: bool,
|
||||
evaluate: bool,
|
||||
) -> Result<(), RunError<'a>> {
|
||||
let unknown_overrides = overrides.keys().cloned()
|
||||
.filter(|name| !self.assignments.contains_key(name))
|
||||
@ -820,6 +835,13 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
}
|
||||
|
||||
let scope = try!(evaluate_assignments(&self.assignments, overrides));
|
||||
if evaluate {
|
||||
for (name, value) in scope {
|
||||
println!("{} = \"{}\"", name, value);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut ran = HashSet::new();
|
||||
|
||||
for (i, argument) in arguments.iter().enumerate() {
|
||||
@ -836,7 +858,7 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
expected: recipe.arguments.len(),
|
||||
});
|
||||
}
|
||||
try!(self.run_recipe(recipe, rest, &scope, &mut ran));
|
||||
try!(self.run_recipe(recipe, rest, &scope, &mut ran, dry_run));
|
||||
return Ok(());
|
||||
}
|
||||
} else {
|
||||
@ -854,7 +876,7 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
return Err(RunError::UnknownRecipes{recipes: missing});
|
||||
}
|
||||
for recipe in arguments.iter().map(|name| &self.recipes[name]) {
|
||||
try!(self.run_recipe(recipe, &[], &scope, &mut ran));
|
||||
try!(self.run_recipe(recipe, &[], &scope, &mut ran, dry_run));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -864,14 +886,15 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
recipe: &Recipe<'a>,
|
||||
arguments: &[&'a str],
|
||||
scope: &BTreeMap<&'c str, String>,
|
||||
ran: &mut HashSet<&'a str>
|
||||
ran: &mut HashSet<&'a str>,
|
||||
dry_run: bool,
|
||||
) -> Result<(), RunError> {
|
||||
for dependency_name in &recipe.dependencies {
|
||||
if !ran.contains(dependency_name) {
|
||||
try!(self.run_recipe(&self.recipes[dependency_name], &[], scope, ran));
|
||||
try!(self.run_recipe(&self.recipes[dependency_name], &[], scope, ran, dry_run));
|
||||
}
|
||||
}
|
||||
try!(recipe.run(arguments, &scope));
|
||||
try!(recipe.run(arguments, &scope, dry_run));
|
||||
ran.insert(recipe.name);
|
||||
Ok(())
|
||||
}
|
||||
|
16
src/unit.rs
16
src/unit.rs
@ -579,7 +579,7 @@ fn conjoin_and() {
|
||||
|
||||
#[test]
|
||||
fn unknown_recipes() {
|
||||
match parse_success("a:\nb:\nc:").run(&BTreeMap::new(), &["a", "x", "y", "z"]).unwrap_err() {
|
||||
match parse_success("a:\nb:\nc:").run(&BTreeMap::new(), &["a", "x", "y", "z"], false, false).unwrap_err() {
|
||||
RunError::UnknownRecipes{recipes} => assert_eq!(recipes, &["x", "y", "z"]),
|
||||
other => panic!("expected an unknown recipe error, but got: {}", other),
|
||||
}
|
||||
@ -747,7 +747,7 @@ a:
|
||||
x
|
||||
";
|
||||
|
||||
match parse_success(text).run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||
match parse_success(text).run(&BTreeMap::new(), &["a"], false, false).unwrap_err() {
|
||||
RunError::Code{recipe, code} => {
|
||||
assert_eq!(recipe, "a");
|
||||
assert_eq!(code, 200);
|
||||
@ -758,7 +758,7 @@ a:
|
||||
|
||||
#[test]
|
||||
fn code_error() {
|
||||
match parse_success("fail:\n @function x { return 100; }; x").run(&BTreeMap::new(), &["fail"]).unwrap_err() {
|
||||
match parse_success("fail:\n @function x { return 100; }; x").run(&BTreeMap::new(), &["fail"], false, false).unwrap_err() {
|
||||
RunError::Code{recipe, code} => {
|
||||
assert_eq!(recipe, "fail");
|
||||
assert_eq!(code, 100);
|
||||
@ -773,7 +773,7 @@ fn run_args() {
|
||||
a return code:
|
||||
@function x { {{return}} {{code + "0"}}; }; x"#;
|
||||
|
||||
match parse_success(text).run(&BTreeMap::new(), &["a", "return", "15"]).unwrap_err() {
|
||||
match parse_success(text).run(&BTreeMap::new(), &["a", "return", "15"], false, false).unwrap_err() {
|
||||
RunError::Code{recipe, code} => {
|
||||
assert_eq!(recipe, "a");
|
||||
assert_eq!(code, 150);
|
||||
@ -784,7 +784,7 @@ a return code:
|
||||
|
||||
#[test]
|
||||
fn missing_args() {
|
||||
match parse_success("a b c d:").run(&BTreeMap::new(), &["a", "b", "c"]).unwrap_err() {
|
||||
match parse_success("a b c d:").run(&BTreeMap::new(), &["a", "b", "c"], false, false).unwrap_err() {
|
||||
RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
||||
assert_eq!(recipe, "a");
|
||||
assert_eq!(found, 2);
|
||||
@ -796,7 +796,7 @@ fn missing_args() {
|
||||
|
||||
#[test]
|
||||
fn missing_default() {
|
||||
match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}").run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||
match parse_success("a b c d:\n echo {{b}}{{c}}{{d}}").run(&BTreeMap::new(), &["a"], false, false).unwrap_err() {
|
||||
RunError::ArgumentCountMismatch{recipe, found, expected} => {
|
||||
assert_eq!(recipe, "a");
|
||||
assert_eq!(found, 0);
|
||||
@ -808,7 +808,7 @@ fn missing_default() {
|
||||
|
||||
#[test]
|
||||
fn backtick_code() {
|
||||
match parse_success("a:\n echo {{`function f { return 100; }; f`}}").run(&BTreeMap::new(), &["a"]).unwrap_err() {
|
||||
match parse_success("a:\n echo {{`function f { return 100; }; f`}}").run(&BTreeMap::new(), &["a"], false, false).unwrap_err() {
|
||||
RunError::BacktickCode{code, token} => {
|
||||
assert_eq!(code, 100);
|
||||
assert_eq!(token.lexeme, "`function f { return 100; }; f`");
|
||||
@ -823,7 +823,7 @@ fn unknown_overrides() {
|
||||
overrides.insert("foo", "bar");
|
||||
overrides.insert("baz", "bob");
|
||||
match parse_success("a:\n echo {{`function f { return 100; }; f`}}")
|
||||
.run(&overrides, &["a"]).unwrap_err() {
|
||||
.run(&overrides, &["a"], false, false).unwrap_err() {
|
||||
RunError::UnknownOverrides{overrides} => {
|
||||
assert_eq!(overrides, &["baz", "foo"]);
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user