From 1a3c2e2f1dc5add94b5b7ff4ba4c26df55c7a011 Mon Sep 17 00:00:00 2001 From: Nick Hanley Date: Thu, 16 Mar 2023 12:22:24 -0400 Subject: [PATCH] feat(repl): add `DENO_REPL_HISTORY` to change history file path (#18047) --- cli/args/flags.rs | 3 ++ cli/cache/deno_dir.rs | 14 +++++++-- cli/tests/integration/repl_tests.rs | 46 +++++++++++++++++++++++++++++ cli/tools/repl/editor.rs | 38 ++++++++++++++---------- 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 883a4d0342..c1e422da31 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -593,6 +593,9 @@ static ENV_VARIABLES_HELP: &str = r#"ENVIRONMENT VARIABLES: DENO_DIR Set the cache directory DENO_INSTALL_ROOT Set deno install's output directory (defaults to $HOME/.deno/bin) + DENO_REPL_HISTORY Set REPL history file path + History file is disabled when the value is empty + (defaults to $DENO_DIR/deno_history.txt) DENO_NO_PACKAGE_JSON Disables auto-resolution of package.json DENO_NO_PROMPT Set to disable permission prompts on access (alternative to passing --no-prompt on invocation) diff --git a/cli/cache/deno_dir.rs b/cli/cache/deno_dir.rs index 86f3e00b5d..2cee0e7a70 100644 --- a/cli/cache/deno_dir.rs +++ b/cli/cache/deno_dir.rs @@ -2,6 +2,7 @@ use super::DiskCache; +use std::env; use std::path::PathBuf; /// `DenoDir` serves as coordinator for multiple `DiskCache`s containing them @@ -109,8 +110,17 @@ impl DenoDir { } /// Path used for the REPL history file. - pub fn repl_history_file_path(&self) -> PathBuf { - self.root.join("deno_history.txt") + /// Can be overridden or disabled by setting `DENO_REPL_HISTORY` environment variable. + pub fn repl_history_file_path(&self) -> Option { + if let Some(deno_repl_history) = env::var_os("DENO_REPL_HISTORY") { + if deno_repl_history.is_empty() { + None + } else { + Some(PathBuf::from(deno_repl_history)) + } + } else { + Some(self.root.join("deno_history.txt")) + } } /// Folder path used for downloading new versions of deno. diff --git a/cli/tests/integration/repl_tests.rs b/cli/tests/integration/repl_tests.rs index aafb3bb483..52510a637c 100644 --- a/cli/tests/integration/repl_tests.rs +++ b/cli/tests/integration/repl_tests.rs @@ -654,6 +654,52 @@ fn missing_deno_dir() { assert!(err.is_empty()); } +#[test] +fn custom_history_path() { + use std::fs::read; + let temp_dir = TempDir::new(); + let history_path = temp_dir.path().join("history.txt"); + let (out, err) = util::run_and_collect_output( + true, + "repl", + Some(vec!["1"]), + Some(vec![ + ( + "DENO_REPL_HISTORY".to_owned(), + history_path.to_str().unwrap().to_owned(), + ), + ("NO_COLOR".to_owned(), "1".to_owned()), + ]), + false, + ); + assert!(read(&history_path).is_ok()); + assert_ends_with!(out, "1\n"); + assert!(err.is_empty()); +} + +#[test] +fn disable_history_file() { + let deno_dir = util::new_deno_dir(); + let default_history_path = deno_dir.path().join("deno_history.txt"); + let (out, err) = util::run_and_collect_output( + true, + "repl", + Some(vec!["1"]), + Some(vec![ + ( + "DENO_DIR".to_owned(), + deno_dir.path().to_str().unwrap().to_owned(), + ), + ("DENO_REPL_HISTORY".to_owned(), "".to_owned()), + ("NO_COLOR".to_owned(), "1".to_owned()), + ]), + false, + ); + assert!(!default_history_path.try_exists().unwrap()); + assert_ends_with!(out, "1\n"); + assert!(err.is_empty()); +} + #[test] fn save_last_eval() { let (out, err) = util::run_and_collect_output( diff --git a/cli/tools/repl/editor.rs b/cli/tools/repl/editor.rs index 98e528614a..e1cda21e11 100644 --- a/cli/tools/repl/editor.rs +++ b/cli/tools/repl/editor.rs @@ -401,7 +401,7 @@ impl Highlighter for EditorHelper { #[derive(Clone)] pub struct ReplEditor { inner: Arc>>, - history_file_path: PathBuf, + history_file_path: Option, errored_on_history_save: Arc, should_exit_on_interrupt: Arc, } @@ -409,7 +409,7 @@ pub struct ReplEditor { impl ReplEditor { pub fn new( helper: EditorHelper, - history_file_path: PathBuf, + history_file_path: Option, ) -> Result { let editor_config = Config::builder() .completion_type(CompletionType::List) @@ -418,7 +418,9 @@ impl ReplEditor { let mut editor = Editor::with_config(editor_config).expect("Failed to create editor."); editor.set_helper(Some(helper)); - editor.load_history(&history_file_path).unwrap_or(()); + if let Some(history_file_path) = &history_file_path { + editor.load_history(history_file_path).unwrap_or(()); + } editor.bind_sequence( KeyEvent(KeyCode::Char('s'), Modifiers::CTRL), EventHandler::Simple(Cmd::Newline), @@ -435,13 +437,15 @@ impl ReplEditor { })), ); - let history_file_dir = history_file_path.parent().unwrap(); - std::fs::create_dir_all(history_file_dir).with_context(|| { - format!( - "Unable to create directory for the history file: {}", - history_file_dir.display() - ) - })?; + if let Some(history_file_path) = &history_file_path { + let history_file_dir = history_file_path.parent().unwrap(); + std::fs::create_dir_all(history_file_dir).with_context(|| { + format!( + "Unable to create directory for the history file: {}", + history_file_dir.display() + ) + })?; + } Ok(ReplEditor { inner: Arc::new(Mutex::new(editor)), @@ -457,13 +461,15 @@ impl ReplEditor { pub fn update_history(&self, entry: String) { self.inner.lock().add_history_entry(entry); - if let Err(e) = self.inner.lock().append_history(&self.history_file_path) { - if self.errored_on_history_save.load(Relaxed) { - return; - } + if let Some(history_file_path) = &self.history_file_path { + if let Err(e) = self.inner.lock().append_history(history_file_path) { + if self.errored_on_history_save.load(Relaxed) { + return; + } - self.errored_on_history_save.store(true, Relaxed); - eprintln!("Unable to save history file: {e}"); + self.errored_on_history_save.store(true, Relaxed); + eprintln!("Unable to save history file: {e}"); + } } }