diff --git a/cli/src/cli_util.rs b/cli/src/cli_util.rs index 29df46758..8f8d71eaa 100644 --- a/cli/src/cli_util.rs +++ b/cli/src/cli_util.rs @@ -43,7 +43,7 @@ use jj_lib::hex_util::to_reverse_hex; use jj_lib::id_prefix::IdPrefixContext; use jj_lib::local_working_copy::{ CheckoutStats, LocalWorkingCopy, LockedLocalWorkingCopy, ResetError, SnapshotError, - SnapshotOptions, TreeStateError, + SnapshotOptions, WorkingCopyStateError, }; use jj_lib::matchers::{EverythingMatcher, Matcher, PrefixMatcher, Visit}; use jj_lib::merged_tree::{MergedTree, MergedTreeBuilder}; @@ -189,7 +189,7 @@ impl From for CommandError { WorkspaceInitError::Backend(err) => { user_error(format!("Failed to access the repository: {err}")) } - WorkspaceInitError::TreeState(err) => { + WorkspaceInitError::WorkingCopyState(err) => { CommandError::InternalError(format!("Failed to access the repository: {err}")) } } @@ -395,9 +395,9 @@ impl From for CommandError { } } -impl From for CommandError { - fn from(err: TreeStateError) -> Self { - CommandError::InternalError(format!("Failed to access tree state: {err}")) +impl From for CommandError { + fn from(err: WorkingCopyStateError) -> Self { + CommandError::InternalError(format!("Failed to access working copy state: {err}")) } } diff --git a/lib/src/local_working_copy.rs b/lib/src/local_working_copy.rs index 5262edf87..80c2447f2 100644 --- a/lib/src/local_working_copy.rs +++ b/lib/src/local_working_copy.rs @@ -1356,6 +1356,13 @@ impl TreeState { } } +#[derive(Debug, Error)] +#[error("{message}: {err:?}")] +pub struct WorkingCopyStateError { + message: String, + err: Box, +} + /// Working copy state stored in "checkout" file. #[derive(Clone, Debug)] struct CheckoutState { @@ -1403,7 +1410,7 @@ impl LocalWorkingCopy { state_path: PathBuf, operation_id: OperationId, workspace_id: WorkspaceId, - ) -> Result { + ) -> Result { let proto = crate::protos::working_copy::Checkout { operation_id: operation_id.to_bytes(), workspace_id: workspace_id.as_str().to_string(), @@ -1416,7 +1423,12 @@ impl LocalWorkingCopy { .unwrap(); file.write_all(&proto.encode_to_vec()).unwrap(); let tree_state = - TreeState::init(store.clone(), working_copy_path.clone(), state_path.clone())?; + TreeState::init(store.clone(), working_copy_path.clone(), state_path.clone()).map_err( + |err| WorkingCopyStateError { + message: "Failed to initialize working copy state".to_string(), + err: err.into(), + }, + )?; Ok(LocalWorkingCopy { store, working_copy_path, @@ -1478,30 +1490,35 @@ impl LocalWorkingCopy { } #[instrument(skip_all)] - fn tree_state(&self) -> Result<&TreeState, TreeStateError> { - self.tree_state.get_or_try_init(|| { - TreeState::load( - self.store.clone(), - self.working_copy_path.clone(), - self.state_path.clone(), - ) - }) + fn tree_state(&self) -> Result<&TreeState, WorkingCopyStateError> { + self.tree_state + .get_or_try_init(|| { + TreeState::load( + self.store.clone(), + self.working_copy_path.clone(), + self.state_path.clone(), + ) + }) + .map_err(|err| WorkingCopyStateError { + message: "Failed to read working copy state".to_string(), + err: err.into(), + }) } - fn tree_state_mut(&mut self) -> Result<&mut TreeState, TreeStateError> { + fn tree_state_mut(&mut self) -> Result<&mut TreeState, WorkingCopyStateError> { self.tree_state()?; // ensure loaded Ok(self.tree_state.get_mut().unwrap()) } - pub fn current_tree_id(&self) -> Result<&MergedTreeId, TreeStateError> { + pub fn current_tree_id(&self) -> Result<&MergedTreeId, WorkingCopyStateError> { Ok(self.tree_state()?.current_tree_id()) } - pub fn file_states(&self) -> Result<&BTreeMap, TreeStateError> { + pub fn file_states(&self) -> Result<&BTreeMap, WorkingCopyStateError> { Ok(self.tree_state()?.file_states()) } - pub fn sparse_patterns(&self) -> Result<&[RepoPath], TreeStateError> { + pub fn sparse_patterns(&self) -> Result<&[RepoPath], WorkingCopyStateError> { Ok(self.tree_state()?.sparse_patterns()) } @@ -1514,7 +1531,7 @@ impl LocalWorkingCopy { }); } - pub fn start_mutation(&mut self) -> Result { + pub fn start_mutation(&mut self) -> Result { let lock_path = self.state_path.join("working_copy.lock"); let lock = FileLock::lock(lock_path); @@ -1568,8 +1585,13 @@ impl LocalWorkingCopy { #[cfg(feature = "watchman")] pub fn query_watchman( &self, - ) -> Result<(watchman::Clock, Option>), TreeStateError> { - self.tree_state()?.query_watchman() + ) -> Result<(watchman::Clock, Option>), WorkingCopyStateError> { + self.tree_state()? + .query_watchman() + .map_err(|err| WorkingCopyStateError { + message: "Failed to query watchman".to_string(), + err: err.into(), + }) } } @@ -1650,7 +1672,7 @@ impl LockedLocalWorkingCopy<'_> { Ok(()) } - pub fn sparse_patterns(&self) -> Result<&[RepoPath], TreeStateError> { + pub fn sparse_patterns(&self) -> Result<&[RepoPath], WorkingCopyStateError> { self.wc.sparse_patterns() } @@ -1673,10 +1695,16 @@ impl LockedLocalWorkingCopy<'_> { } #[instrument(skip_all)] - pub fn finish(mut self, operation_id: OperationId) -> Result<(), TreeStateError> { + pub fn finish(mut self, operation_id: OperationId) -> Result<(), WorkingCopyStateError> { assert!(self.tree_state_dirty || &self.old_tree_id == self.wc.current_tree_id()?); if self.tree_state_dirty { - self.wc.tree_state_mut()?.save()?; + self.wc + .tree_state_mut()? + .save() + .map_err(|err| WorkingCopyStateError { + message: "Failed to write working copy state".to_string(), + err: Box::new(err), + })?; } if self.old_operation_id != operation_id { self.wc.checkout_state_mut().operation_id = operation_id; diff --git a/lib/src/workspace.rs b/lib/src/workspace.rs index a8175f54b..14f99d686 100644 --- a/lib/src/workspace.rs +++ b/lib/src/workspace.rs @@ -27,7 +27,7 @@ use crate::file_util::{IoResultExt as _, PathError}; use crate::git_backend::GitBackend; use crate::index::IndexStore; use crate::local_backend::LocalBackend; -use crate::local_working_copy::{LocalWorkingCopy, TreeStateError}; +use crate::local_working_copy::{LocalWorkingCopy, WorkingCopyStateError}; use crate::op_heads_store::OpHeadsStore; use crate::op_store::{OpStore, WorkspaceId}; use crate::repo::{ @@ -47,7 +47,7 @@ pub enum WorkspaceInitError { #[error(transparent)] CheckOutCommit(#[from] CheckOutCommitError), #[error(transparent)] - TreeState(#[from] TreeStateError), + WorkingCopyState(#[from] WorkingCopyStateError), #[error(transparent)] Path(#[from] PathError), #[error(transparent)]