diff --git a/examples/custom-backend/main.rs b/examples/custom-backend/main.rs index 03d138c95..3dfe04a9c 100644 --- a/examples/custom-backend/main.rs +++ b/examples/custom-backend/main.rs @@ -45,12 +45,12 @@ fn create_store_factories() -> StoreFactories { fn run_custom_command( ui: &mut Ui, - _command_helper: &CommandHelper, + command_helper: &CommandHelper, command: CustomCommands, ) -> Result<(), CommandError> { match command { CustomCommands::InitJit => { - let wc_path = ui.cwd(); + let wc_path = command_helper.cwd(); // Initialize a workspace with the custom backend Workspace::init_with_backend(ui.settings(), wc_path, |store_path| { Box::new(JitBackend::init(store_path)) diff --git a/src/cli_util.rs b/src/cli_util.rs index e07fa135b..abeb8451d 100644 --- a/src/cli_util.rs +++ b/src/cli_util.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::collections::{HashSet, VecDeque}; -use std::env::{ArgsOs, VarError}; +use std::env::{self, ArgsOs, VarError}; use std::ffi::{OsStr, OsString}; use std::fmt::Debug; use std::iter; @@ -260,6 +260,7 @@ impl TracingSubscription { pub struct CommandHelper { app: clap::Command, + cwd: PathBuf, string_args: Vec, global_args: GlobalArgs, store_factories: StoreFactories, @@ -268,12 +269,14 @@ pub struct CommandHelper { impl CommandHelper { pub fn new( app: clap::Command, + cwd: PathBuf, string_args: Vec, global_args: GlobalArgs, store_factories: StoreFactories, ) -> Self { Self { app, + cwd, string_args, global_args, store_factories, @@ -284,6 +287,10 @@ impl CommandHelper { &self.app } + pub fn cwd(&self) -> &Path { + &self.cwd + } + pub fn string_args(&self) -> &Vec { &self.string_args } @@ -301,7 +308,7 @@ impl CommandHelper { pub fn load_workspace(&self, ui: &Ui) -> Result { let wc_path_str = self.global_args.repository.as_deref().unwrap_or("."); - let wc_path = ui.cwd().join(wc_path_str); + let wc_path = self.cwd.join(wc_path_str); Workspace::load(ui.settings(), &wc_path, &self.store_factories).map_err(|err| match err { WorkspaceLoadError::NoWorkspaceHere(wc_path) => { let message = format!("There is no jj repo in \"{wc_path_str}\""); @@ -383,6 +390,7 @@ jj init --git-repo=.", WorkspaceCommandHelper::new( ui, workspace, + self.cwd.clone(), self.string_args.clone(), &self.global_args, repo, @@ -408,6 +416,7 @@ impl WorkspaceCommandHelper { pub fn new( ui: &mut Ui, workspace: Workspace, + cwd: PathBuf, string_args: Vec, global_args: &GlobalArgs, repo: Arc, @@ -426,7 +435,7 @@ impl WorkspaceCommandHelper { working_copy_shared_with_git = git_workdir == workspace.workspace_root().as_path(); } Ok(Self { - cwd: ui.cwd().to_owned(), + cwd, string_args, global_args: global_args.clone(), settings, @@ -1764,11 +1773,13 @@ impl CliRunner { } pub fn run(self, ui: &mut Ui) -> Result<(), CommandError> { + let cwd = env::current_dir().unwrap(); // TODO: maybe map_err to CommandError? ui.reset(crate::config::read_config()?); let string_args = expand_args(ui, &self.app, std::env::args_os())?; let (matches, args) = parse_args(ui, &self.app, &self.tracing_subscription, &string_args)?; let command_helper = CommandHelper::new( self.app, + cwd, string_args, args.global_args, self.store_factories.unwrap_or_default(), diff --git a/src/commands.rs b/src/commands.rs index 59b616a0b..aa6e5a199 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -1130,7 +1130,7 @@ fn cmd_init(ui: &mut Ui, command: &CommandHelper, args: &InitArgs) -> Result<(), if command.global_args().repository.is_some() { return Err(user_error("'--repository' cannot be used with 'init'")); } - let wc_path = ui.cwd().join(&args.destination); + let wc_path = command.cwd().join(&args.destination); match fs::create_dir(&wc_path) { Ok(()) => {} Err(_) if wc_path.is_dir() => {} @@ -1141,7 +1141,7 @@ fn cmd_init(ui: &mut Ui, command: &CommandHelper, args: &InitArgs) -> Result<(), .map_err(|e| user_error(format!("Failed to create workspace: {e}")))?; // raced? if let Some(git_store_str) = &args.git_repo { - let mut git_store_path = ui.cwd().join(git_store_str); + let mut git_store_path = command.cwd().join(git_store_str); git_store_path = git_store_path .canonicalize() .map_err(|_| user_error(format!("{} doesn't exist", git_store_path.display())))?; @@ -1190,7 +1190,7 @@ Set `ui.allow-init-native` to allow initializing a repo with the native backend. } Workspace::init_local(ui.settings(), &wc_path)?; }; - let cwd = ui.cwd().canonicalize().unwrap(); + let cwd = command.cwd().canonicalize().unwrap(); let relative_wc_path = file_util::relative_path(&cwd, &wc_path); writeln!(ui, "Initialized repo in \"{}\"", relative_wc_path.display())?; if args.git && wc_path.join(".git").exists() { @@ -3430,7 +3430,7 @@ fn cmd_workspace_add( args: &WorkspaceAddArgs, ) -> Result<(), CommandError> { let old_workspace_command = command.workspace_helper(ui)?; - let destination_path = ui.cwd().join(&args.destination); + let destination_path = command.cwd().join(&args.destination); if destination_path.exists() { return Err(user_error("Workspace already exists")); } else { @@ -3469,6 +3469,7 @@ fn cmd_workspace_add( let mut new_workspace_command = WorkspaceCommandHelper::new( ui, new_workspace, + command.cwd().to_owned(), command.string_args().clone(), command.global_args(), repo, @@ -3793,13 +3794,13 @@ fn cmd_git_clone( if command.global_args().repository.is_some() { return Err(user_error("'--repository' cannot be used with 'git clone'")); } - let source = absolute_git_source(ui.cwd(), &args.source); + let source = absolute_git_source(command.cwd(), &args.source); let wc_path_str = args .destination .as_deref() .or_else(|| clone_destination_for_source(&source)) .ok_or_else(|| user_error("No destination specified and wasn't able to guess it"))?; - let wc_path = ui.cwd().join(wc_path_str); + let wc_path = command.cwd().join(wc_path_str); let wc_path_existed = wc_path.exists(); if wc_path_existed { if !is_empty_dir(&wc_path) { diff --git a/src/ui.rs b/src/ui.rs index a5d43b9a6..f5c15c614 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::io::{Stderr, Stdout, Write}; -use std::path::{Path, PathBuf}; use std::process::{Child, ChildStdin, Stdio}; use std::str::FromStr; use std::{fmt, io, mem}; @@ -28,7 +27,6 @@ pub struct Ui { color: bool, paginate: PaginationChoice, progress_indicator: bool, - cwd: PathBuf, formatter_factory: FormatterFactory, output: UiOutput, settings: UserSettings, @@ -123,13 +121,11 @@ impl Default for Ui { impl Ui { pub fn new() -> Ui { let settings = UserSettings::from_config(crate::config::default_config()); - let cwd = std::env::current_dir().unwrap(); let color = use_color(color_setting(&settings)); let progress_indicator = progress_indicator_setting(&settings); let formatter_factory = FormatterFactory::prepare(&settings, color); Ui { color, - cwd, formatter_factory, paginate: PaginationChoice::Auto, progress_indicator, @@ -177,10 +173,6 @@ impl Ui { self.color } - pub fn cwd(&self) -> &Path { - &self.cwd - } - pub fn settings(&self) -> &UserSettings { &self.settings }