Repository: casey/just
Pull request #869 (2021-06-12 22:26:09)

Add `--unstable` flag
Add an `--unstable` flag, indicating that `just` should enable unstable
features. Make `--fmt` only run if `--unstable` is passed.


Patch:
diff --git a/completions/just.bash b/completions/just.bash
index 1e152b89..e97b3e95 100644
--- a/completions/just.bash
+++ b/completions/just.bash
@@ -20,7 +20,7 @@ _just() {
 
     case "${cmd}" in
         just)
-            opts=" -q -u -v -e -l -h -V -f -d -c -s  --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --verbose --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show  <ARGUMENTS>... "
+            opts=" -q -u -v -e -l -h -V -f -d -c -s  --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --unstable --verbose --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show  <ARGUMENTS>... "
                 if [[ ${cur} == -* ]] ; then
                     COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                     return 0
diff --git a/completions/just.elvish b/completions/just.elvish
index 05ebf707..2d24cc30 100644
--- a/completions/just.elvish
+++ b/completions/just.elvish
@@ -40,6 +40,7 @@ edit:completion:arg-completer[just] = [@words]{
             cand --clear-shell-args 'Clear shell arguments'
             cand -u 'Return list and summary entries in source order'
             cand --unsorted 'Return list and summary entries in source order'
+            cand --unstable 'Enable unstable features'
             cand -v 'Use verbose output'
             cand --verbose 'Use verbose output'
             cand --choose 'Select one or more recipes to run using a binary. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`'
diff --git a/completions/just.fish b/completions/just.fish
index 887910cb..92d3b5f6 100644
--- a/completions/just.fish
+++ b/completions/just.fish
@@ -29,6 +29,7 @@ complete -c just -n "__fish_use_subcommand" -s q -l quiet -d 'Suppress all outpu
 complete -c just -n "__fish_use_subcommand" -l shell-command -d 'Invoke <COMMAND> with the shell used to run recipe lines and backticks'
 complete -c just -n "__fish_use_subcommand" -l clear-shell-args -d 'Clear shell arguments'
 complete -c just -n "__fish_use_subcommand" -s u -l unsorted -d 'Return list and summary entries in source order'
+complete -c just -n "__fish_use_subcommand" -l unstable -d 'Enable unstable features'
 complete -c just -n "__fish_use_subcommand" -s v -l verbose -d 'Use verbose output'
 complete -c just -n "__fish_use_subcommand" -l choose -d 'Select one or more recipes to run using a binary. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`'
 complete -c just -n "__fish_use_subcommand" -l dump -d 'Print entire justfile'
diff --git a/completions/just.powershell b/completions/just.powershell
index ed917621..f9fa0090 100644
--- a/completions/just.powershell
+++ b/completions/just.powershell
@@ -45,6 +45,7 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock {
             [CompletionResult]::new('--clear-shell-args', 'clear-shell-args', [CompletionResultType]::ParameterName, 'Clear shell arguments')
             [CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order')
             [CompletionResult]::new('--unsorted', 'unsorted', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order')
+            [CompletionResult]::new('--unstable', 'unstable', [CompletionResultType]::ParameterName, 'Enable unstable features')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Use verbose output')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Use verbose output')
             [CompletionResult]::new('--choose', 'choose', [CompletionResultType]::ParameterName, 'Select one or more recipes to run using a binary. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`')
diff --git a/completions/just.zsh b/completions/just.zsh
index 5d832461..bc57f54e 100644
--- a/completions/just.zsh
+++ b/completions/just.zsh
@@ -41,6 +41,7 @@ _just() {
 '--clear-shell-args[Clear shell arguments]' \
 '-u[Return list and summary entries in source order]' \
 '--unsorted[Return list and summary entries in source order]' \
+'--unstable[Enable unstable features]' \
 '*-v[Use verbose output]' \
 '*--verbose[Use verbose output]' \
 '--choose[Select one or more recipes to run using a binary. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`]' \
diff --git a/src/config.rs b/src/config.rs
index 79533b59..346b351c 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -25,10 +25,11 @@ pub(crate) struct Config {
   pub(crate) search_config:        SearchConfig,
   pub(crate) shell:                String,
   pub(crate) shell_args:           Vec<String>,
-  pub(crate) shell_present:        bool,
   pub(crate) shell_command:        bool,
+  pub(crate) shell_present:        bool,
   pub(crate) subcommand:           Subcommand,
   pub(crate) unsorted:             bool,
+  pub(crate) unstable:             bool,
   pub(crate) verbosity:            Verbosity,
 }
 
@@ -92,6 +93,7 @@ mod arg {
   pub(crate) const SHELL_ARG: &str = "SHELL-ARG";
   pub(crate) const SHELL_COMMAND: &str = "SHELL-COMMAND";
   pub(crate) const UNSORTED: &str = "UNSORTED";
+  pub(crate) const UNSTABLE: &str = "UNSTABLE";
   pub(crate) const VERBOSE: &str = "VERBOSE";
   pub(crate) const WORKING_DIRECTORY: &str = "WORKING-DIRECTORY";
 
@@ -218,6 +220,11 @@ impl Config {
           .short("u")
           .help("Return list and summary entries in source order"),
       )
+      .arg(
+        Arg::with_name(arg::UNSTABLE)
+          .long("unstable")
+          .help("Enable unstable features"),
+      )
       .arg(
         Arg::with_name(arg::VERBOSE)
           .short("v")
@@ -506,6 +513,7 @@ impl Config {
       load_dotenv: !matches.is_present(arg::NO_DOTENV),
       shell_command: matches.is_present(arg::SHELL_COMMAND),
       unsorted: matches.is_present(arg::UNSORTED),
+      unstable: matches.is_present(arg::UNSTABLE),
       list_heading: matches
         .value_of(arg::LIST_HEADING)
         .unwrap_or("Available recipes:\n")
@@ -728,7 +736,15 @@ impl Config {
   }
 
   fn format(&self, ast: Module, search: &Search) -> Result<(), i32> {
-    if let Err(error) = File::open(&search.justfile).and_then(|mut file| write!(file, "{}", ast)) {
+    if !self.unstable {
+      eprintln!(
+        "The `--fmt` command is currently unstable. Pass the `--unstable` flag to enable it."
+      );
+      return Err(EXIT_FAILURE);
+    }
+
+    if let Err(error) = File::create(&search.justfile).and_then(|mut file| write!(file, "{}", ast))
+    {
       if self.verbosity.loud() {
         eprintln!(
           "Failed to write justfile to `{}`: {}",
@@ -963,6 +979,7 @@ FLAGS:
                                  backticks
         --summary             List names of available recipes
     -u, --unsorted            Return list and summary entries in source order
+        --unstable            Enable unstable features
         --variables           List names of variables
     -v, --verbose             Use verbose output
 


Test patch:
diff --git a/tests/fmt.rs b/tests/fmt.rs
index 056f285e..cd70f081 100644
--- a/tests/fmt.rs
+++ b/tests/fmt.rs
@@ -1,3 +1,39 @@
+use crate::common::*;
+
+test! {
+  name: unstable_not_passed,
+  justfile: "",
+  args: ("--fmt"),
+  stderr: "
+    The `--fmt` command is currently unstable. Pass the `--unstable` flag to enable it.
+  ",
+  status: EXIT_FAILURE,
+}
+
+#[test]
+fn unstable_passed() {
+  let tmp = tempdir();
+
+  let justfile = tmp.path().join("justfile");
+
+  fs::write(&justfile, "x    :=    'hello'   ").unwrap();
+
+  let output = Command::new(executable_path("just"))
+    .current_dir(tmp.path())
+    .arg("--fmt")
+    .arg("--unstable")
+    .output()
+    .unwrap();
+
+  if !output.status.success() {
+    eprintln!("{}", String::from_utf8_lossy(&output.stderr));
+    eprintln!("{}", String::from_utf8_lossy(&output.stdout));
+    panic!("justfile failed with status: {}", output.status);
+  }
+
+  assert_eq!(fs::read_to_string(&justfile).unwrap(), "x := 'hello'\n",);
+}
+
 test! {
   name: alias_good,
   justfile: "