Skip to content

Commit

Permalink
Allow enabling unstable features with set unstable (#2237)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey committed Jul 8, 2024
1 parent 5648142 commit d6669e0
Show file tree
Hide file tree
Showing 20 changed files with 136 additions and 46 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,11 +379,11 @@ There will never be a `just` 2.0. Any desirable backwards-incompatible changes
will be opt-in on a per-`justfile` basis, so users may migrate at their
leisure.

Features that aren't yet ready for stabilization are gated behind the
`--unstable` flag. Features enabled by `--unstable` may change in backwards
incompatible ways at any time. Unstable features can also be enabled by setting
the environment variable `JUST_UNSTABLE` to any value other than `false`, `0`,
or the empty string.
Features that aren't yet ready for stabilization are marked as unstable and may
be changed or removed at any time. Using unstable features produces an error by
default, which can be suppressed with by passing the `--unstable` flag,
`set unstable`, or setting the environment variable `JUST_UNSTABLE`, to any
value other than `false`, `0`, or the empty string.

Editor Support
--------------
Expand Down Expand Up @@ -820,6 +820,7 @@ foo:
| `positional-arguments` | boolean | `false` | Pass positional arguments. |
| `shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. |
| `tempdir` | string | - | Create temporary directories in `tempdir` instead of the system default temporary directory. |
| `unstable`<sup>master</sup> | boolean | `false` | Enable unstable features. |
| `windows-powershell` | boolean | `false` | Use PowerShell on Windows as default shell. (Deprecated. Use `windows-shell` instead. |
| `windows-shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. |

Expand Down Expand Up @@ -3154,8 +3155,8 @@ Missing source files for optional imports do not produce an error.
### Modules<sup>1.19.0</sup>

A `justfile` can declare modules using `mod` statements. `mod` statements are
currently unstable, so you'll need to use the `--unstable` flag, or set the
`JUST_UNSTABLE` environment variable to use them.
currently unstable, so you'll need to use the `--unstable` flag,
`set unstable`, or set the `JUST_UNSTABLE` environment variable to use them.

If you have the following `justfile`:

Expand Down
5 changes: 5 additions & 0 deletions src/analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ impl<'src> Analyzer<'src> {

let mut warnings = Vec::new();

let mut unstable = BTreeSet::new();

let mut modules: Table<Justfile> = Table::new();

let mut unexports: HashSet<String> = HashSet::new();
Expand Down Expand Up @@ -92,6 +94,8 @@ impl<'src> Analyzer<'src> {
doc,
..
} => {
unstable.insert(Unstable::Modules);

if let Some(absolute) = absolute {
define(*name, "module", false)?;
modules.insert(Self::analyze(
Expand Down Expand Up @@ -194,6 +198,7 @@ impl<'src> Analyzer<'src> {
settings,
source: root.into(),
unexports,
unstable,
warnings,
})
}
Expand Down
14 changes: 7 additions & 7 deletions src/argument_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mod tests {
fs::write(&path, "mod foo").unwrap();
fs::create_dir(tempdir.path().join("foo")).unwrap();
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
let compilation = Compiler::compile(true, &loader, &path).unwrap();
let compilation = Compiler::compile(&loader, &path).unwrap();

assert_eq!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "bar"]).unwrap(),
Expand All @@ -271,7 +271,7 @@ mod tests {
fs::write(&path, "mod foo").unwrap();
fs::create_dir(tempdir.path().join("foo")).unwrap();
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
let compilation = Compiler::compile(true, &loader, &path).unwrap();
let compilation = Compiler::compile(&loader, &path).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "zzz"]).unwrap_err(),
Expand All @@ -289,7 +289,7 @@ mod tests {
tempdir.write("foo.just", "bar:");

let loader = Loader::new();
let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo::zzz"]).unwrap_err(),
Expand All @@ -307,7 +307,7 @@ mod tests {
tempdir.write("foo.just", "bar:");

let loader = Loader::new();
let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo::bar::baz"]).unwrap_err(),
Expand All @@ -323,7 +323,7 @@ mod tests {
tempdir.write("justfile", "");

let loader = Loader::new();
let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
Expand All @@ -337,7 +337,7 @@ mod tests {
tempdir.write("justfile", "foo bar:");

let loader = Loader::new();
let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
Expand All @@ -355,7 +355,7 @@ mod tests {
tempdir.write("foo.just", "bar:");

let loader = Loader::new();
let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();

assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
Expand Down
15 changes: 4 additions & 11 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ pub(crate) struct Compiler;

impl Compiler {
pub(crate) fn compile<'src>(
unstable: bool,
loader: &'src Loader,
root: &Path,
) -> RunResult<'src, Compilation<'src>> {
let mut asts = HashMap::<PathBuf, Ast>::new();
let mut loaded = Vec::new();
let mut paths = HashMap::<PathBuf, PathBuf>::new();
let mut srcs = HashMap::<PathBuf, &str>::new();
let mut loaded = Vec::new();

let mut stack = Vec::new();
stack.push(Source::root(root));
Expand Down Expand Up @@ -42,12 +41,6 @@ impl Compiler {
relative,
..
} => {
if !unstable {
return Err(Error::Unstable {
message: "Modules are currently unstable.".into(),
});
}

let parent = current.path.parent().unwrap();

let import = if let Some(relative) = relative {
Expand Down Expand Up @@ -112,9 +105,9 @@ impl Compiler {

Ok(Compilation {
asts,
srcs,
justfile,
root: root.into(),
srcs,
})
}

Expand Down Expand Up @@ -225,7 +218,7 @@ recipe_b: recipe_c
let loader = Loader::new();

let justfile_a_path = tmp.path().join("justfile");
let compilation = Compiler::compile(false, &loader, &justfile_a_path).unwrap();
let compilation = Compiler::compile(&loader, &justfile_a_path).unwrap();

assert_eq!(compilation.root_src(), justfile_a);
}
Expand All @@ -242,7 +235,7 @@ recipe_b: recipe_c
let loader = Loader::new();

let justfile_a_path = tmp.path().join("justfile");
let loader_output = Compiler::compile(false, &loader, &justfile_a_path).unwrap_err();
let loader_output = Compiler::compile(&loader, &justfile_a_path).unwrap_err();

assert_matches!(loader_output, Error::CircularImport { current, import }
if current == tmp.path().join("subdir").join("b").lexiclean() &&
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ impl<'src> ColorDisplay for Error<'src> {
}
}
Unstable { message } => {
write!(f, "{message} Invoke `just` with the `--unstable` flag to enable unstable features.")?;
write!(f, "{message} Invoke `just` with `--unstable`, set the `JUST_UNSTABLE` environment variable, or add `set unstable` to your `justfile` to enable unstable features.")?;
}
WriteJustfile { justfile, io_error } => {
let justfile = justfile.display();
Expand Down
18 changes: 18 additions & 0 deletions src/justfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub(crate) struct Justfile<'src> {
pub(crate) source: PathBuf,
pub(crate) unexports: HashSet<String>,
pub(crate) warnings: Vec<Warning>,
#[serde(skip)]
pub(crate) unstable: BTreeSet<Unstable>,
}

impl<'src> Justfile<'src> {
Expand Down Expand Up @@ -225,6 +227,22 @@ impl<'src> Justfile<'src> {
Ok(())
}

pub(crate) fn check_unstable(&self, config: &Config) -> RunResult<'src> {
if !config.unstable && !self.settings.unstable {
if let Some(unstable) = self.unstable.iter().next() {
return Err(Error::Unstable {
message: unstable.message(),
});
}
}

for module in self.modules.values() {
module.check_unstable(config)?;
}

Ok(())
}

pub(crate) fn get_alias(&self, name: &str) -> Option<&Alias<'src>> {
self.aliases.get(name)
}
Expand Down
1 change: 1 addition & 0 deletions src/keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub(crate) enum Keyword {
Tempdir,
True,
Unexport,
Unstable,
WindowsPowershell,
WindowsShell,
X,
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ pub(crate) use {
shell::Shell, show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind,
string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table,
thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency,
unresolved_recipe::UnresolvedRecipe, use_color::UseColor, variables::Variables,
verbosity::Verbosity, warning::Warning,
unresolved_recipe::UnresolvedRecipe, unstable::Unstable, use_color::UseColor,
variables::Variables, verbosity::Verbosity, warning::Warning,
},
camino::Utf8Path,
clap::ValueEnum,
Expand Down Expand Up @@ -204,6 +204,7 @@ mod token_kind;
mod unindent;
mod unresolved_dependency;
mod unresolved_recipe;
mod unstable;
mod use_color;
mod variables;
mod verbosity;
Expand Down
1 change: 1 addition & 0 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ impl<'src> Node<'src> for Set<'src> {
| Setting::Fallback(value)
| Setting::PositionalArguments(value)
| Setting::Quiet(value)
| Setting::Unstable(value)
| Setting::WindowsPowerShell(value)
| Setting::IgnoreComments(value) => {
set.push_mut(value.to_string());
Expand Down
1 change: 1 addition & 0 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,6 +936,7 @@ impl<'run, 'src> Parser<'run, 'src> {
Keyword::IgnoreComments => Some(Setting::IgnoreComments(self.parse_set_bool()?)),
Keyword::PositionalArguments => Some(Setting::PositionalArguments(self.parse_set_bool()?)),
Keyword::Quiet => Some(Setting::Quiet(self.parse_set_bool()?)),
Keyword::Unstable => Some(Setting::Unstable(self.parse_set_bool()?)),
Keyword::WindowsPowershell => Some(Setting::WindowsPowerShell(self.parse_set_bool()?)),
_ => None,
};
Expand Down
2 changes: 2 additions & 0 deletions src/setting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(crate) enum Setting<'src> {
Quiet(bool),
Shell(Shell<'src>),
Tempdir(String),
Unstable(bool),
WindowsPowerShell(bool),
WindowsShell(Shell<'src>),
}
Expand All @@ -31,6 +32,7 @@ impl<'src> Display for Setting<'src> {
| Self::IgnoreComments(value)
| Self::PositionalArguments(value)
| Self::Quiet(value)
| Self::Unstable(value)
| Self::WindowsPowerShell(value) => write!(f, "{value}"),
Self::Shell(shell) | Self::WindowsShell(shell) => write!(f, "{shell}"),
Self::DotenvFilename(value) | Self::DotenvPath(value) | Self::Tempdir(value) => {
Expand Down
4 changes: 4 additions & 0 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub(crate) struct Settings<'src> {
pub(crate) quiet: bool,
pub(crate) shell: Option<Shell<'src>>,
pub(crate) tempdir: Option<String>,
pub(crate) unstable: bool,
pub(crate) windows_powershell: bool,
pub(crate) windows_shell: Option<Shell<'src>>,
}
Expand Down Expand Up @@ -66,6 +67,9 @@ impl<'src> Settings<'src> {
Setting::Shell(shell) => {
settings.shell = Some(shell);
}
Setting::Unstable(unstable) => {
settings.unstable = unstable;
}
Setting::WindowsPowerShell(windows_powershell) => {
settings.windows_powershell = windows_powershell;
}
Expand Down
4 changes: 3 additions & 1 deletion src/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,9 @@ impl Subcommand {
loader: &'src Loader,
search: &Search,
) -> RunResult<'src, Compilation<'src>> {
let compilation = Compiler::compile(config.unstable, loader, &search.justfile)?;
let compilation = Compiler::compile(loader, &search.justfile)?;

compilation.justfile.check_unstable(config)?;

if config.verbosity.loud() {
for warning in &compilation.justfile.warnings {
Expand Down
2 changes: 1 addition & 1 deletion src/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod full {
pub fn summary(path: &Path) -> io::Result<Result<Summary, String>> {
let loader = Loader::new();

match Compiler::compile(false, &loader, path) {
match Compiler::compile(&loader, path) {
Ok(compilation) => Ok(Ok(Summary::new(&compilation.justfile))),
Err(error) => Ok(Err(if let Error::Compile { compile_error } = error {
compile_error.to_string()
Expand Down
12 changes: 12 additions & 0 deletions src/unstable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#[derive(Copy, Clone, Debug, PartialEq, Ord, Eq, PartialOrd)]
pub(crate) enum Unstable {
Modules,
}

impl Unstable {
pub(crate) fn message(self) -> String {
match self {
Self::Modules => "Modules are currently unstable.".into(),
}
}
}
5 changes: 1 addition & 4 deletions tests/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ test! {
name: unstable_not_passed,
justfile: "",
args: ("--fmt"),
stderr: "
error: The `--fmt` command is currently unstable. \
Invoke `just` with the `--unstable` flag to enable unstable features.
",
stderr_regex: "error: The `--fmt` command is currently unstable..*",
status: EXIT_FAILURE,
}

Expand Down
Loading

0 comments on commit d6669e0

Please sign in to comment.