Skip to content

Commit bcf29d2

Browse files
authored
Add no-cd setting (#2981)
1 parent f9953f9 commit bcf29d2

16 files changed

Lines changed: 197 additions & 3 deletions

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,12 @@ $ just bar
950950
/subdir
951951
```
952952

953+
Use `set no-cd`<sup>master</sup> to make all recipes in the current module
954+
default to the same behavior.
955+
956+
`set no-cd` and `set working-directory` can be overridden on a per-recipe basis
957+
with the `[no-cd]` and `[working-directory]` attributes.
958+
953959
You can override the working directory for all recipes with
954960
`set working-directory := '…'`:
955961

@@ -1043,6 +1049,7 @@ foo:
10431049
| `ignore-comments` | boolean | `false` | Ignore recipe lines beginning with `#`. |
10441050
| `no-exit-message`<sup>1.39.0</sup> | boolean | `false` | Don't print exit messages if recipes fail. |
10451051
| `lazy`<sup>1.47.0</sup> | boolean | `false` | Don't evaluate unused variables. |
1052+
| `no-cd`<sup>master</sup> | boolean | `false` | Don't change directory when executing recipes by recipe attribute. |
10461053
| `positional-arguments` | boolean | `false` | Pass positional arguments. |
10471054
| `quiet` | boolean | `false` | Disable echoing recipe lines before executing. |
10481055
| `script-interpreter`<sup>1.33.0</sup> | `[COMMAND, ARGS…]` | `['sh', '-eu']` | Set command used to invoke recipes with empty `[script]` attribute. |

src/analyzer.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,24 @@ impl<'run, 'src> Analyzer<'run, 'src> {
417417
}));
418418
}
419419

420+
if let Some(second) = Keyword::from_lexeme(set.name.lexeme()) {
421+
let first = match second {
422+
Keyword::NoCd => Keyword::WorkingDirectory,
423+
Keyword::WorkingDirectory => Keyword::NoCd,
424+
_ => {
425+
return Ok(());
426+
}
427+
};
428+
429+
if let Some(conflict) = self.sets.get(first.lexeme()) {
430+
return Err(set.name.error(NoCdAndWorkingDirectorySetting {
431+
first,
432+
first_line: conflict.name.line,
433+
second,
434+
}));
435+
}
436+
}
437+
420438
Ok(())
421439
}
422440

src/compile_error.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,17 @@ impl Display for CompileError<'_> {
254254
f,
255255
"recipe `{recipe}` has both `[no-cd]` and `[working-directory]` attributes"
256256
),
257+
NoCdAndWorkingDirectorySetting {
258+
first,
259+
first_line,
260+
second,
261+
} => write!(
262+
f,
263+
"`{}` set on line {} is incompatible with `{}`",
264+
first.lexeme(),
265+
first_line.ordinal(),
266+
second.lexeme()
267+
),
257268
OptionNameContainsEqualSign { parameter } => {
258269
write!(
259270
f,

src/compile_error_kind.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ pub(crate) enum CompileErrorKind<'src> {
114114
NoCdAndWorkingDirectoryAttribute {
115115
recipe: &'src str,
116116
},
117+
NoCdAndWorkingDirectorySetting {
118+
first: Keyword,
119+
first_line: usize,
120+
second: Keyword,
121+
},
117122
OptionNameContainsEqualSign {
118123
parameter: String,
119124
},

src/evaluator.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ impl<'src, 'run> Evaluator<'src, 'run> {
101101
Setting::Lazy(value) => {
102102
settings.lazy = value;
103103
}
104+
Setting::NoCd(value) => {
105+
settings.no_cd = value;
106+
}
104107
Setting::NoExitMessage(value) => {
105108
settings.no_exit_message = value;
106109
}

src/keyword.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub(crate) enum Keyword {
2424
Import,
2525
Lazy,
2626
Mod,
27+
NoCd,
2728
NoExitMessage,
2829
PositionalArguments,
2930
Quiet,

src/node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ impl<'src> Node<'src> for Set<'src> {
283283
| Setting::Guards(value)
284284
| Setting::IgnoreComments(value)
285285
| Setting::Lazy(value)
286+
| Setting::NoCd(value)
286287
| Setting::NoExitMessage(value)
287288
| Setting::PositionalArguments(value)
288289
| Setting::Quiet(value)

src/parser.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,7 @@ impl<'run, 'src> Parser<'run, 'src> {
14161416
Keyword::Guards => Some(Setting::Guards(self.parse_set_bool()?)),
14171417
Keyword::IgnoreComments => Some(Setting::IgnoreComments(self.parse_set_bool()?)),
14181418
Keyword::Lazy => Some(Setting::Lazy(self.parse_set_bool()?)),
1419+
Keyword::NoCd => Some(Setting::NoCd(self.parse_set_bool()?)),
14191420
Keyword::NoExitMessage => Some(Setting::NoExitMessage(self.parse_set_bool()?)),
14201421
Keyword::PositionalArguments => Some(Setting::PositionalArguments(self.parse_set_bool()?)),
14211422
Keyword::Quiet => Some(Setting::Quiet(self.parse_set_bool()?)),
@@ -2650,6 +2651,12 @@ mod tests {
26502651
tree: (justfile (set quiet false)),
26512652
}
26522653

2654+
test! {
2655+
name: set_no_cd,
2656+
text: "set no-cd := true",
2657+
tree: (justfile (set no_cd true)),
2658+
}
2659+
26532660
test! {
26542661
name: set_positional_arguments_false,
26552662
text: "set positional-arguments := false",

src/recipe.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,19 @@ impl<'src> Recipe<'src> {
169169
.contains(AttributeDiscriminant::PositionalArguments)
170170
}
171171

172-
pub(crate) fn change_directory(&self) -> bool {
173-
!self.attributes.contains(AttributeDiscriminant::NoCd)
172+
pub(crate) fn change_directory(&self, settings: &Settings) -> bool {
173+
if self
174+
.attributes
175+
.contains(AttributeDiscriminant::WorkingDirectory)
176+
{
177+
return true;
178+
}
179+
180+
if self.attributes.contains(AttributeDiscriminant::NoCd) {
181+
return false;
182+
}
183+
184+
!settings.no_cd
174185
}
175186

176187
fn print_exit_message(&self, settings: &Settings) -> bool {
@@ -186,7 +197,7 @@ impl<'src> Recipe<'src> {
186197
}
187198

188199
fn working_directory<'a>(&'a self, context: &'a ExecutionContext) -> Option<PathBuf> {
189-
if !self.change_directory() {
200+
if !self.change_directory(&context.module.settings) {
190201
return None;
191202
}
192203

src/setting.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub(crate) enum Setting<'src> {
1414
Guards(bool),
1515
IgnoreComments(bool),
1616
Lazy(bool),
17+
NoCd(bool),
1718
NoExitMessage(bool),
1819
PositionalArguments(bool),
1920
Quiet(bool),
@@ -39,6 +40,7 @@ impl<'src> Setting<'src> {
3940
| Self::Guards(value)
4041
| Self::IgnoreComments(value)
4142
| Self::Lazy(value)
43+
| Self::NoCd(value)
4244
| Self::NoExitMessage(value)
4345
| Self::PositionalArguments(value)
4446
| Self::Quiet(value)
@@ -88,6 +90,7 @@ impl Display for Setting<'_> {
8890
| Self::Guards(value)
8991
| Self::IgnoreComments(value)
9092
| Self::Lazy(value)
93+
| Self::NoCd(value)
9194
| Self::NoExitMessage(value)
9295
| Self::PositionalArguments(value)
9396
| Self::Quiet(value)

0 commit comments

Comments
 (0)