Skip to content

Commit dc96bd9

Browse files
committed
list: show fallback recipes when fallback is enabled
When `set fallback` is active and `just --list` is run, the output now also includes recipes from parent justfiles, displayed under a "Fallback recipes from <path>" heading. This walks up the directory tree, loading each parent justfile until one without fallback is found. Fixes #1500
1 parent 2eebdbb commit dc96bd9

File tree

3 files changed

+87
-3
lines changed

3 files changed

+87
-3
lines changed

src/search.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const DEFAULT_JUSTFILE_NAME: &str = JUSTFILE_NAMES[0];
44
pub(crate) const JUSTFILE_NAMES: [&str; 2] = ["justfile", ".justfile"];
55
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
66

7-
#[derive(Debug)]
7+
#[derive(Debug, Clone)]
88
pub(crate) struct Search {
99
pub(crate) justfile: PathBuf,
1010
pub(crate) working_directory: PathBuf,

src/subcommand.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl Subcommand {
100100
Dump => Self::dump(config, compilation)?,
101101
Format => Self::format(config, &search, compilation)?,
102102
Groups => Self::groups(config, justfile),
103-
List { path } => Self::list(config, justfile, path)?,
103+
List { path } => Self::list(config, loader, &search, justfile, path)?,
104104
Run { arguments } => Self::run(config, loader, search, compilation, arguments)?,
105105
Show { path } => Self::show(config, justfile, path)?,
106106
Summary => Self::summary(config, justfile),
@@ -440,7 +440,13 @@ impl Subcommand {
440440
Ok(())
441441
}
442442

443-
fn list(config: &Config, mut module: &Justfile, path: &ModulePath) -> RunResult<'static> {
443+
fn list<'src>(
444+
config: &Config,
445+
loader: &'src Loader,
446+
search: &Search,
447+
mut module: &Justfile,
448+
path: &ModulePath,
449+
) -> RunResult<'src> {
444450
for name in &path.path {
445451
module = module
446452
.modules
@@ -452,6 +458,56 @@ impl Subcommand {
452458

453459
Self::list_module(config, module, 0);
454460

461+
// If fallback is enabled and we're at the top level, also list
462+
// recipes from parent justfiles so users can see the full set of
463+
// available recipes.
464+
let fallback = module.settings.fallback
465+
&& matches!(
466+
config.search_config,
467+
SearchConfig::FromInvocationDirectory | SearchConfig::FromSearchDirectory { .. }
468+
);
469+
470+
if fallback && path.path.is_empty() {
471+
let mut parent_search = search.clone();
472+
473+
while let Ok(next) = parent_search.search_parent_directory(config.ceiling.as_deref()) {
474+
parent_search = next;
475+
476+
let parent_path = parent_search
477+
.justfile
478+
.parent()
479+
.unwrap_or_else(|| Path::new("."));
480+
481+
if let Ok(compilation) = Self::compile(config, loader, &parent_search) {
482+
let parent_justfile = &compilation.justfile;
483+
484+
let has_recipes = !parent_justfile
485+
.public_recipes(config)
486+
.is_empty()
487+
;
488+
489+
if has_recipes {
490+
println!();
491+
println!(
492+
"{}",
493+
config.color.stdout().doc().paint(&format!(
494+
"# Fallback recipes from {}",
495+
parent_path.display()
496+
))
497+
);
498+
Self::list_module(config, parent_justfile, 0);
499+
}
500+
501+
// Stop walking if this parent doesn't also have fallback
502+
if !parent_justfile.settings.fallback {
503+
break;
504+
}
505+
} else {
506+
break;
507+
}
508+
}
509+
}
510+
455511
Ok(())
456512
}
457513

tests/fallback.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,3 +368,31 @@ fn works_with_modules() {
368368
.stdout("BAZ\n")
369369
.success();
370370
}
371+
372+
#[test]
373+
fn list_shows_fallback_recipes() {
374+
Test::new()
375+
.justfile(
376+
"
377+
# A parent recipe
378+
parent-recipe:
379+
echo parent
380+
",
381+
)
382+
.write(
383+
"sub/justfile",
384+
unindent(
385+
"
386+
set fallback
387+
388+
# A child recipe
389+
child-recipe:
390+
echo child
391+
",
392+
),
393+
)
394+
.args(["--list"])
395+
.current_dir("sub")
396+
.stdout_regex("(?s).*child-recipe.*Fallback.*parent-recipe.*")
397+
.success();
398+
}

0 commit comments

Comments
 (0)