Add justfile_directory()
and justfile()
(#569)
Add `justfile()` function, returning the current justfile, and `justfile_directory(), returning its parent directory.
This commit is contained in:
parent
eeb603160a
commit
61ab53dbc1
@ -402,13 +402,11 @@ impl Config {
|
|||||||
|
|
||||||
match &self.subcommand {
|
match &self.subcommand {
|
||||||
Dump => self.dump(justfile),
|
Dump => self.dump(justfile),
|
||||||
Evaluate { overrides } => {
|
Evaluate { overrides } => self.run(justfile, &search, overrides, &Vec::new()),
|
||||||
self.run(justfile, &search.working_directory, overrides, &Vec::new())
|
|
||||||
}
|
|
||||||
Run {
|
Run {
|
||||||
arguments,
|
arguments,
|
||||||
overrides,
|
overrides,
|
||||||
} => self.run(justfile, &search.working_directory, overrides, arguments),
|
} => self.run(justfile, &search, overrides, arguments),
|
||||||
List => self.list(justfile),
|
List => self.list(justfile),
|
||||||
Show { ref name } => self.show(&name, justfile),
|
Show { ref name } => self.show(&name, justfile),
|
||||||
Summary => self.summary(justfile),
|
Summary => self.summary(justfile),
|
||||||
@ -561,7 +559,7 @@ impl Config {
|
|||||||
fn run(
|
fn run(
|
||||||
&self,
|
&self,
|
||||||
justfile: Justfile,
|
justfile: Justfile,
|
||||||
working_directory: &Path,
|
search: &Search,
|
||||||
overrides: &BTreeMap<String, String>,
|
overrides: &BTreeMap<String, String>,
|
||||||
arguments: &[String],
|
arguments: &[String],
|
||||||
) -> Result<(), i32> {
|
) -> Result<(), i32> {
|
||||||
@ -569,7 +567,7 @@ impl Config {
|
|||||||
warn!("Failed to set CTRL-C handler: {}", error)
|
warn!("Failed to set CTRL-C handler: {}", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = justfile.run(&self, working_directory, overrides, arguments);
|
let result = justfile.run(&self, search, overrides, arguments);
|
||||||
|
|
||||||
if !self.quiet {
|
if !self.quiet {
|
||||||
result.eprint(self.color)
|
result.eprint(self.color)
|
||||||
|
@ -6,7 +6,7 @@ pub(crate) struct Evaluator<'src: 'run, 'run> {
|
|||||||
dotenv: &'run BTreeMap<String, String>,
|
dotenv: &'run BTreeMap<String, String>,
|
||||||
scope: Scope<'src, 'run>,
|
scope: Scope<'src, 'run>,
|
||||||
settings: &'run Settings<'run>,
|
settings: &'run Settings<'run>,
|
||||||
working_directory: &'run Path,
|
search: &'run Search,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src, 'run> Evaluator<'src, 'run> {
|
impl<'src, 'run> Evaluator<'src, 'run> {
|
||||||
@ -16,7 +16,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
dotenv: &'run BTreeMap<String, String>,
|
dotenv: &'run BTreeMap<String, String>,
|
||||||
overrides: Scope<'src, 'run>,
|
overrides: Scope<'src, 'run>,
|
||||||
settings: &'run Settings<'run>,
|
settings: &'run Settings<'run>,
|
||||||
working_directory: &'run Path,
|
search: &'run Search,
|
||||||
) -> RunResult<'src, Scope<'src, 'run>> {
|
) -> RunResult<'src, Scope<'src, 'run>> {
|
||||||
let mut evaluator = Evaluator {
|
let mut evaluator = Evaluator {
|
||||||
scope: overrides,
|
scope: overrides,
|
||||||
@ -24,7 +24,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
config,
|
config,
|
||||||
dotenv,
|
dotenv,
|
||||||
settings,
|
settings,
|
||||||
working_directory,
|
search,
|
||||||
};
|
};
|
||||||
|
|
||||||
for assignment in assignments.values() {
|
for assignment in assignments.values() {
|
||||||
@ -67,9 +67,9 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
}
|
}
|
||||||
Expression::Call { thunk } => {
|
Expression::Call { thunk } => {
|
||||||
let context = FunctionContext {
|
let context = FunctionContext {
|
||||||
invocation_directory: &self.config.invocation_directory,
|
|
||||||
working_directory: &self.working_directory,
|
|
||||||
dotenv: self.dotenv,
|
dotenv: self.dotenv,
|
||||||
|
invocation_directory: &self.config.invocation_directory,
|
||||||
|
search: self.search,
|
||||||
};
|
};
|
||||||
|
|
||||||
use Thunk::*;
|
use Thunk::*;
|
||||||
@ -127,7 +127,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
|
|
||||||
cmd.arg(raw);
|
cmd.arg(raw);
|
||||||
|
|
||||||
cmd.current_dir(self.working_directory);
|
cmd.current_dir(&self.search.working_directory);
|
||||||
|
|
||||||
cmd.export(self.dotenv, &self.scope);
|
cmd.export(self.dotenv, &self.scope);
|
||||||
|
|
||||||
@ -167,15 +167,15 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
arguments: &[&str],
|
arguments: &[&str],
|
||||||
scope: &'run Scope<'src, 'run>,
|
scope: &'run Scope<'src, 'run>,
|
||||||
settings: &'run Settings,
|
settings: &'run Settings,
|
||||||
working_directory: &'run Path,
|
search: &'run Search,
|
||||||
) -> RunResult<'src, Scope<'src, 'run>> {
|
) -> RunResult<'src, Scope<'src, 'run>> {
|
||||||
let mut evaluator = Evaluator {
|
let mut evaluator = Evaluator {
|
||||||
assignments: None,
|
assignments: None,
|
||||||
scope: Scope::child(scope),
|
scope: Scope::child(scope),
|
||||||
|
search,
|
||||||
settings,
|
settings,
|
||||||
dotenv,
|
dotenv,
|
||||||
config,
|
config,
|
||||||
working_directory,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut scope = Scope::child(scope);
|
let mut scope = Scope::child(scope);
|
||||||
@ -211,15 +211,15 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
|||||||
dotenv: &'run BTreeMap<String, String>,
|
dotenv: &'run BTreeMap<String, String>,
|
||||||
scope: &'run Scope<'src, 'run>,
|
scope: &'run Scope<'src, 'run>,
|
||||||
settings: &'run Settings,
|
settings: &'run Settings,
|
||||||
working_directory: &'run Path,
|
search: &'run Search,
|
||||||
) -> Evaluator<'src, 'run> {
|
) -> Evaluator<'src, 'run> {
|
||||||
Evaluator {
|
Evaluator {
|
||||||
assignments: None,
|
assignments: None,
|
||||||
scope: Scope::child(scope),
|
scope: Scope::child(scope),
|
||||||
|
search,
|
||||||
settings,
|
settings,
|
||||||
dotenv,
|
dotenv,
|
||||||
config,
|
config,
|
||||||
working_directory,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
use target;
|
use target;
|
||||||
|
use Function::*;
|
||||||
|
|
||||||
pub(crate) enum Function {
|
pub(crate) enum Function {
|
||||||
Nullary(fn(&FunctionContext) -> Result<String, String>),
|
Nullary(fn(&FunctionContext) -> Result<String, String>),
|
||||||
@ -10,15 +11,14 @@ pub(crate) enum Function {
|
|||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub(crate) static ref TABLE: BTreeMap<&'static str, Function> = vec![
|
pub(crate) static ref TABLE: BTreeMap<&'static str, Function> = vec![
|
||||||
("arch", Function::Nullary(arch)),
|
("arch", Nullary(arch)),
|
||||||
("os", Function::Nullary(os)),
|
("os", Nullary(os)),
|
||||||
("os_family", Function::Nullary(os_family)),
|
("os_family", Nullary(os_family)),
|
||||||
("env_var", Function::Unary(env_var)),
|
("justfile_directory", Nullary(justfile_directory)),
|
||||||
("env_var_or_default", Function::Binary(env_var_or_default)),
|
("justfile", Nullary(justfile)),
|
||||||
(
|
("invocation_directory", Nullary(invocation_directory)),
|
||||||
"invocation_directory",
|
("env_var", Unary(env_var)),
|
||||||
Function::Nullary(invocation_directory)
|
("env_var_or_default", Binary(env_var_or_default)),
|
||||||
),
|
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
@ -26,7 +26,6 @@ lazy_static! {
|
|||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub(crate) fn argc(&self) -> usize {
|
pub(crate) fn argc(&self) -> usize {
|
||||||
use self::Function::*;
|
|
||||||
match *self {
|
match *self {
|
||||||
Nullary(_) => 0,
|
Nullary(_) => 0,
|
||||||
Unary(_) => 1,
|
Unary(_) => 1,
|
||||||
@ -48,8 +47,44 @@ fn os_family(_context: &FunctionContext) -> Result<String, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn invocation_directory(context: &FunctionContext) -> Result<String, String> {
|
fn invocation_directory(context: &FunctionContext) -> Result<String, String> {
|
||||||
Platform::to_shell_path(context.working_directory, context.invocation_directory)
|
Platform::to_shell_path(
|
||||||
.map_err(|e| format!("Error getting shell path: {}", e))
|
&context.search.working_directory,
|
||||||
|
context.invocation_directory,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("Error getting shell path: {}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn justfile(context: &FunctionContext) -> Result<String, String> {
|
||||||
|
context
|
||||||
|
.search
|
||||||
|
.justfile
|
||||||
|
.to_str()
|
||||||
|
.map(str::to_owned)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"Justfile path is not valid unicode: {}",
|
||||||
|
context.search.justfile.to_string_lossy()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn justfile_directory(context: &FunctionContext) -> Result<String, String> {
|
||||||
|
let justfile_directory = context.search.justfile.parent().ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"Could not resolve justfile directory. Justfile `{}` had no parent.",
|
||||||
|
context.search.justfile.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
justfile_directory
|
||||||
|
.to_str()
|
||||||
|
.map(str::to_owned)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
format!(
|
||||||
|
"Justfile directory is not valid unicode: {}",
|
||||||
|
justfile_directory.to_string_lossy()
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
|
fn env_var(context: &FunctionContext, key: &str) -> Result<String, String> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
pub(crate) struct FunctionContext<'run> {
|
pub(crate) struct FunctionContext<'run> {
|
||||||
pub(crate) invocation_directory: &'run Path,
|
|
||||||
pub(crate) working_directory: &'run Path,
|
|
||||||
pub(crate) dotenv: &'run BTreeMap<String, String>,
|
pub(crate) dotenv: &'run BTreeMap<String, String>,
|
||||||
|
pub(crate) invocation_directory: &'run Path,
|
||||||
|
pub(crate) search: &'run Search,
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,13 @@ impl<'src> Justfile<'src> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(
|
pub(crate) fn run<'run>(
|
||||||
&'src self,
|
&'run self,
|
||||||
config: &'src Config,
|
config: &'run Config,
|
||||||
working_directory: &'src Path,
|
search: &'run Search,
|
||||||
overrides: &'src BTreeMap<String, String>,
|
overrides: &'run BTreeMap<String, String>,
|
||||||
arguments: &'src [String],
|
arguments: &'run [String],
|
||||||
) -> RunResult<'src, ()> {
|
) -> RunResult<'run, ()> {
|
||||||
let argvec: Vec<&str> = if !arguments.is_empty() {
|
let argvec: Vec<&str> = if !arguments.is_empty() {
|
||||||
arguments.iter().map(|argument| argument.as_str()).collect()
|
arguments.iter().map(|argument| argument.as_str()).collect()
|
||||||
} else if let Some(recipe) = self.first() {
|
} else if let Some(recipe) = self.first() {
|
||||||
@ -105,7 +105,7 @@ impl<'src> Justfile<'src> {
|
|||||||
&dotenv,
|
&dotenv,
|
||||||
scope,
|
scope,
|
||||||
&self.settings,
|
&self.settings,
|
||||||
working_directory,
|
search,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -172,12 +172,12 @@ impl<'src> Justfile<'src> {
|
|||||||
settings: &self.settings,
|
settings: &self.settings,
|
||||||
config,
|
config,
|
||||||
scope,
|
scope,
|
||||||
working_directory,
|
search,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ran = BTreeSet::new();
|
let mut ran = BTreeSet::new();
|
||||||
for (recipe, arguments) in grouped {
|
for (recipe, arguments) in grouped {
|
||||||
self.run_recipe(&context, recipe, arguments, &dotenv, &mut ran)?
|
self.run_recipe(&context, recipe, arguments, &dotenv, &search, &mut ran)?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -203,6 +203,7 @@ impl<'src> Justfile<'src> {
|
|||||||
recipe: &Recipe<'src>,
|
recipe: &Recipe<'src>,
|
||||||
arguments: &[&'run str],
|
arguments: &[&'run str],
|
||||||
dotenv: &BTreeMap<String, String>,
|
dotenv: &BTreeMap<String, String>,
|
||||||
|
search: &'run Search,
|
||||||
ran: &mut BTreeSet<Vec<String>>,
|
ran: &mut BTreeSet<Vec<String>>,
|
||||||
) -> RunResult<'src, ()> {
|
) -> RunResult<'src, ()> {
|
||||||
let scope = Evaluator::evaluate_parameters(
|
let scope = Evaluator::evaluate_parameters(
|
||||||
@ -212,16 +213,11 @@ impl<'src> Justfile<'src> {
|
|||||||
arguments,
|
arguments,
|
||||||
&context.scope,
|
&context.scope,
|
||||||
context.settings,
|
context.settings,
|
||||||
context.working_directory,
|
search,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut evaluator = Evaluator::recipe_evaluator(
|
let mut evaluator =
|
||||||
context.config,
|
Evaluator::recipe_evaluator(context.config, dotenv, &scope, context.settings, search);
|
||||||
dotenv,
|
|
||||||
&scope,
|
|
||||||
context.settings,
|
|
||||||
context.working_directory,
|
|
||||||
);
|
|
||||||
|
|
||||||
for Dependency { recipe, arguments } in &recipe.dependencies {
|
for Dependency { recipe, arguments } in &recipe.dependencies {
|
||||||
let mut invocation = vec![recipe.name().to_owned()];
|
let mut invocation = vec![recipe.name().to_owned()];
|
||||||
@ -236,11 +232,11 @@ impl<'src> Justfile<'src> {
|
|||||||
.skip(1)
|
.skip(1)
|
||||||
.map(String::as_ref)
|
.map(String::as_ref)
|
||||||
.collect::<Vec<&str>>();
|
.collect::<Vec<&str>>();
|
||||||
self.run_recipe(context, recipe, &arguments, dotenv, ran)?;
|
self.run_recipe(context, recipe, &arguments, dotenv, search, ran)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recipe.run(context, dotenv, scope)?;
|
recipe.run(context, dotenv, scope, search)?;
|
||||||
|
|
||||||
let mut invocation = Vec::new();
|
let mut invocation = Vec::new();
|
||||||
invocation.push(recipe.name().to_owned());
|
invocation.push(recipe.name().to_owned());
|
||||||
|
@ -69,6 +69,7 @@ impl<'src, D> Recipe<'src, D> {
|
|||||||
context: &RecipeContext<'src, 'run>,
|
context: &RecipeContext<'src, 'run>,
|
||||||
dotenv: &BTreeMap<String, String>,
|
dotenv: &BTreeMap<String, String>,
|
||||||
scope: Scope<'src, 'run>,
|
scope: Scope<'src, 'run>,
|
||||||
|
search: &'run Search,
|
||||||
) -> RunResult<'src, ()> {
|
) -> RunResult<'src, ()> {
|
||||||
let config = &context.config;
|
let config = &context.config;
|
||||||
|
|
||||||
@ -82,13 +83,8 @@ impl<'src, D> Recipe<'src, D> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut evaluator = Evaluator::recipe_evaluator(
|
let mut evaluator =
|
||||||
context.config,
|
Evaluator::recipe_evaluator(context.config, dotenv, &scope, context.settings, search);
|
||||||
dotenv,
|
|
||||||
&scope,
|
|
||||||
context.settings,
|
|
||||||
context.working_directory,
|
|
||||||
);
|
|
||||||
|
|
||||||
if self.shebang {
|
if self.shebang {
|
||||||
let mut evaluated_lines = vec![];
|
let mut evaluated_lines = vec![];
|
||||||
@ -166,12 +162,16 @@ impl<'src, D> Recipe<'src, D> {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
// create a command to run the script
|
// create a command to run the script
|
||||||
let mut command =
|
let mut command = Platform::make_shebang_command(
|
||||||
Platform::make_shebang_command(&path, context.working_directory, interpreter, argument)
|
&path,
|
||||||
.map_err(|output_error| RuntimeError::Cygpath {
|
&context.search.working_directory,
|
||||||
recipe: self.name(),
|
interpreter,
|
||||||
output_error,
|
argument,
|
||||||
})?;
|
)
|
||||||
|
.map_err(|output_error| RuntimeError::Cygpath {
|
||||||
|
recipe: self.name(),
|
||||||
|
output_error,
|
||||||
|
})?;
|
||||||
|
|
||||||
command.export(dotenv, &scope);
|
command.export(dotenv, &scope);
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ impl<'src, D> Recipe<'src, D> {
|
|||||||
|
|
||||||
let mut cmd = context.settings.shell_command(config);
|
let mut cmd = context.settings.shell_command(config);
|
||||||
|
|
||||||
cmd.current_dir(context.working_directory);
|
cmd.current_dir(&context.search.working_directory);
|
||||||
|
|
||||||
cmd.arg(command);
|
cmd.arg(command);
|
||||||
|
|
||||||
|
@ -3,6 +3,6 @@ use crate::common::*;
|
|||||||
pub(crate) struct RecipeContext<'src: 'run, 'run> {
|
pub(crate) struct RecipeContext<'src: 'run, 'run> {
|
||||||
pub(crate) config: &'run Config,
|
pub(crate) config: &'run Config,
|
||||||
pub(crate) scope: Scope<'src, 'run>,
|
pub(crate) scope: Scope<'src, 'run>,
|
||||||
pub(crate) working_directory: &'run Path,
|
pub(crate) search: &'run Search,
|
||||||
pub(crate) settings: &'run Settings<'src>,
|
pub(crate) settings: &'run Settings<'src>,
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use crate::common::*;
|
|||||||
|
|
||||||
use std::path::Component;
|
use std::path::Component;
|
||||||
|
|
||||||
const FILENAME: &str = "justfile";
|
pub(crate) const FILENAME: &str = "justfile";
|
||||||
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
|
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
|
||||||
|
|
||||||
pub(crate) struct Search {
|
pub(crate) struct Search {
|
||||||
|
@ -20,6 +20,16 @@ pub(crate) fn config(args: &[&str]) -> Config {
|
|||||||
Config::from_matches(&matches).unwrap()
|
Config::from_matches(&matches).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn search(config: &Config) -> Search {
|
||||||
|
let working_directory = config.invocation_directory.clone();
|
||||||
|
let justfile = working_directory.join(crate::search::FILENAME);
|
||||||
|
|
||||||
|
Search {
|
||||||
|
working_directory,
|
||||||
|
justfile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) use test_utilities::{tempdir, unindent};
|
pub(crate) use test_utilities::{tempdir, unindent};
|
||||||
|
|
||||||
macro_rules! analysis_error {
|
macro_rules! analysis_error {
|
||||||
@ -80,15 +90,15 @@ macro_rules! run_error {
|
|||||||
} => {
|
} => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $name() {
|
fn $name() {
|
||||||
let config = &$crate::testing::config(&$args);
|
let config = $crate::testing::config(&$args);
|
||||||
let current_dir = std::env::current_dir().unwrap();
|
let search = $crate::testing::search(&config);
|
||||||
|
|
||||||
if let Subcommand::Run{ overrides, arguments } = &config.subcommand {
|
if let Subcommand::Run{ overrides, arguments } = &config.subcommand {
|
||||||
match $crate::compiler::Compiler::compile(&$crate::testing::unindent($src))
|
match $crate::compiler::Compiler::compile(&$crate::testing::unindent($src))
|
||||||
.expect("Expected successful compilation")
|
.expect("Expected successful compilation")
|
||||||
.run(
|
.run(
|
||||||
config,
|
&config,
|
||||||
¤t_dir,
|
&search,
|
||||||
&overrides,
|
&overrides,
|
||||||
&arguments,
|
&arguments,
|
||||||
).expect_err("Expected runtime error") {
|
).expect_err("Expected runtime error") {
|
||||||
|
Loading…
Reference in New Issue
Block a user