Add is_dependency() function (#2139)

This commit is contained in:
Greg Shuflin 2024-06-08 18:17:55 -07:00 committed by GitHub
parent 3236154d8d
commit 5ac98c020d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 50 additions and 8 deletions

View File

@ -1426,6 +1426,12 @@ $ just
- `env(key)`<sup>1.15.0</sup> — Alias for `env_var(key)`. - `env(key)`<sup>1.15.0</sup> — Alias for `env_var(key)`.
- `env(key, default)`<sup>1.15.0</sup> — Alias for `env_var_or_default(key, default)`. - `env(key, default)`<sup>1.15.0</sup> — Alias for `env_var_or_default(key, default)`.
#### Invocation Information
- `is_dependency()` - Returns the string `true` if the current recipe is being
run as a dependency of another recipe, rather than being run directly,
otherwise returns the string `false`.
#### Invocation Directory #### Invocation Directory
- `invocation_directory()` - Retrieves the absolute path to the current - `invocation_directory()` - Retrieves the absolute path to the current

View File

@ -3,6 +3,7 @@ use super::*;
pub(crate) struct Evaluator<'src: 'run, 'run> { pub(crate) struct Evaluator<'src: 'run, 'run> {
pub(crate) assignments: Option<&'run Table<'src, Assignment<'src>>>, pub(crate) assignments: Option<&'run Table<'src, Assignment<'src>>>,
pub(crate) context: ExecutionContext<'src, 'run>, pub(crate) context: ExecutionContext<'src, 'run>,
pub(crate) is_dependency: bool,
pub(crate) scope: Scope<'src, 'run>, pub(crate) scope: Scope<'src, 'run>,
} }
@ -49,6 +50,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
context, context,
assignments: Some(&module.assignments), assignments: Some(&module.assignments),
scope, scope,
is_dependency: false,
}; };
for assignment in module.assignments.values() { for assignment in module.assignments.values() {
@ -280,10 +282,11 @@ impl<'src, 'run> Evaluator<'src, 'run> {
pub(crate) fn evaluate_parameters( pub(crate) fn evaluate_parameters(
context: &ExecutionContext<'src, 'run>, context: &ExecutionContext<'src, 'run>,
is_dependency: bool,
arguments: &[String], arguments: &[String],
parameters: &[Parameter<'src>], parameters: &[Parameter<'src>],
) -> RunResult<'src, (Scope<'src, 'run>, Vec<String>)> { ) -> RunResult<'src, (Scope<'src, 'run>, Vec<String>)> {
let mut evaluator = Self::new(context, context.scope); let mut evaluator = Self::new(context, is_dependency, context.scope);
let mut positional = Vec::new(); let mut positional = Vec::new();
@ -324,11 +327,13 @@ impl<'src, 'run> Evaluator<'src, 'run> {
pub(crate) fn new( pub(crate) fn new(
context: &ExecutionContext<'src, 'run>, context: &ExecutionContext<'src, 'run>,
is_dependency: bool,
scope: &'run Scope<'src, 'run>, scope: &'run Scope<'src, 'run>,
) -> Self { ) -> Self {
Self { Self {
context: *context,
assignments: None, assignments: None,
context: *context,
is_dependency,
scope: scope.child(), scope: scope.child(),
} }
} }

View File

@ -59,6 +59,7 @@ pub(crate) fn get(name: &str) -> Option<Function> {
"home_directory" => Nullary(|_| dir("home", dirs::home_dir)), "home_directory" => Nullary(|_| dir("home", dirs::home_dir)),
"invocation_directory" => Nullary(invocation_directory), "invocation_directory" => Nullary(invocation_directory),
"invocation_directory_native" => Nullary(invocation_directory_native), "invocation_directory_native" => Nullary(invocation_directory_native),
"is_dependency" => Nullary(is_dependency),
"join" => BinaryPlus(join), "join" => BinaryPlus(join),
"just_executable" => Nullary(just_executable), "just_executable" => Nullary(just_executable),
"just_pid" => Nullary(just_pid), "just_pid" => Nullary(just_pid),
@ -341,6 +342,10 @@ fn invocation_directory_native(context: Context) -> Result<String, String> {
}) })
} }
fn is_dependency(context: Context) -> Result<String, String> {
Ok(context.evaluator.is_dependency.to_string())
}
fn prepend(_context: Context, prefix: &str, s: &str) -> Result<String, String> { fn prepend(_context: Context, prefix: &str, s: &str) -> Result<String, String> {
Ok( Ok(
s.split_whitespace() s.split_whitespace()

View File

@ -257,6 +257,7 @@ impl<'src> Justfile<'src> {
&context, &context,
&mut ran, &mut ran,
invocation.recipe, invocation.recipe,
false,
)?; )?;
} }
@ -385,6 +386,7 @@ impl<'src> Justfile<'src> {
context: &ExecutionContext<'src, '_>, context: &ExecutionContext<'src, '_>,
ran: &mut Ran<'src>, ran: &mut Ran<'src>,
recipe: &Recipe<'src>, recipe: &Recipe<'src>,
is_dependency: bool,
) -> RunResult<'src> { ) -> RunResult<'src> {
if ran.has_run(&recipe.namepath, arguments) { if ran.has_run(&recipe.namepath, arguments) {
return Ok(()); return Ok(());
@ -397,11 +399,11 @@ impl<'src> Justfile<'src> {
} }
let (outer, positional) = let (outer, positional) =
Evaluator::evaluate_parameters(context, arguments, &recipe.parameters)?; Evaluator::evaluate_parameters(context, is_dependency, arguments, &recipe.parameters)?;
let scope = outer.child(); let scope = outer.child();
let mut evaluator = Evaluator::new(context, &scope); let mut evaluator = Evaluator::new(context, true, &scope);
if !context.config.no_dependencies { if !context.config.no_dependencies {
for Dependency { recipe, arguments } in recipe.dependencies.iter().take(recipe.priors) { for Dependency { recipe, arguments } in recipe.dependencies.iter().take(recipe.priors) {
@ -410,11 +412,11 @@ impl<'src> Justfile<'src> {
.map(|argument| evaluator.evaluate_expression(argument)) .map(|argument| evaluator.evaluate_expression(argument))
.collect::<RunResult<Vec<String>>>()?; .collect::<RunResult<Vec<String>>>()?;
Self::run_recipe(&arguments, context, ran, recipe)?; Self::run_recipe(&arguments, context, ran, recipe, true)?;
} }
} }
recipe.run(context, &scope, &positional)?; recipe.run(context, &scope, &positional, is_dependency)?;
if !context.config.no_dependencies { if !context.config.no_dependencies {
let mut ran = Ran::default(); let mut ran = Ran::default();
@ -426,7 +428,7 @@ impl<'src> Justfile<'src> {
evaluated.push(evaluator.evaluate_expression(argument)?); evaluated.push(evaluator.evaluate_expression(argument)?);
} }
Self::run_recipe(&evaluated, context, &mut ran, recipe)?; Self::run_recipe(&evaluated, context, &mut ran, recipe, true)?;
} }
} }

View File

@ -149,6 +149,7 @@ impl<'src, D> Recipe<'src, D> {
context: &ExecutionContext<'src, 'run>, context: &ExecutionContext<'src, 'run>,
scope: &Scope<'src, 'run>, scope: &Scope<'src, 'run>,
positional: &[String], positional: &[String],
is_dependency: bool,
) -> RunResult<'src, ()> { ) -> RunResult<'src, ()> {
let config = &context.config; let config = &context.config;
@ -162,7 +163,7 @@ impl<'src, D> Recipe<'src, D> {
); );
} }
let evaluator = Evaluator::new(context, scope); let evaluator = Evaluator::new(context, is_dependency, scope);
if self.shebang { if self.shebang {
self.run_shebang(context, scope, positional, config, evaluator) self.run_shebang(context, scope, positional, config, evaluator)

View File

@ -1027,3 +1027,26 @@ import
) )
.run(); .run();
} }
#[test]
fn is_dependency() {
let justfile = "
alpha: beta
@echo 'alpha {{is_dependency()}}'
beta: && gamma
@echo 'beta {{is_dependency()}}'
gamma:
@echo 'gamma {{is_dependency()}}'
";
Test::new()
.args(["alpha"])
.justfile(justfile)
.stdout("beta true\ngamma true\nalpha false\n")
.run();
Test::new()
.args(["beta"])
.justfile(justfile)
.stdout("beta false\ngamma true\n")
.run();
}