diff --git a/cli/examples/custom-working-copy/main.rs b/cli/examples/custom-working-copy/main.rs index 40bdcf4b48..d75d07c374 100644 --- a/cli/examples/custom-working-copy/main.rs +++ b/cli/examples/custom-working-copy/main.rs @@ -241,8 +241,8 @@ impl LockedWorkingCopy for LockedConflictsWorkingCopy { self.inner.reset(commit) } - fn reset_to_empty(&mut self) -> Result<(), ResetError> { - self.inner.reset_to_empty() + fn recover(&mut self, commit: &Commit) -> Result<(), ResetError> { + self.inner.recover(commit) } fn sparse_patterns(&self) -> Result<&[RepoPathBuf], WorkingCopyStateError> { diff --git a/cli/src/commands/workspace.rs b/cli/src/commands/workspace.rs index b90793564a..d2a4328f4b 100644 --- a/cli/src/commands/workspace.rs +++ b/cli/src/commands/workspace.rs @@ -324,7 +324,7 @@ fn create_and_check_out_recovery_commit( mut_repo.set_wc_commit(workspace_id, new_commit.id().clone())?; let repo = tx.commit("recovery commit"); - locked_workspace.locked_wc().reset_to_empty()?; + locked_workspace.locked_wc().recover(&new_commit)?; locked_workspace.finish(repo.op_id().clone())?; writeln!( diff --git a/cli/tests/test_workspaces.rs b/cli/tests/test_workspaces.rs index 1e23cf69fd..5af482b51c 100644 --- a/cli/tests/test_workspaces.rs +++ b/cli/tests/test_workspaces.rs @@ -494,7 +494,7 @@ fn test_workspaces_current_op_discarded_by_other() { insta::assert_snapshot!(stdout, @""); insta::assert_snapshot!(get_log_output(&test_env, &main_path), @r###" - ◉ 8fd911b4e595 secondary@ + ◉ b93a924213f3 secondary@ ◉ ec4904a30161 │ @ 74769415363f default@ ├─╯ @@ -511,14 +511,12 @@ fn test_workspaces_current_op_discarded_by_other() { "###); let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["st"]); insta::assert_snapshot!(stderr, @""); - // TODO: The file outside the sparse patterns should still be there insta::assert_snapshot!(stdout, @r###" Working copy changes: A added D deleted M modified - D sparse - Working copy : kmkuslsw 8fd911b4 (no description set) + Working copy : kmkuslsw b93a9242 (no description set) Parent commit: rzvqmyuk ec4904a3 (empty) (no description set) "###); // The modified file should have the same contents it had before (not reset to @@ -530,7 +528,7 @@ fn test_workspaces_current_op_discarded_by_other() { let (stdout, stderr) = test_env.jj_cmd_ok(&secondary_path, &["obslog"]); insta::assert_snapshot!(stderr, @""); insta::assert_snapshot!(stdout, @r###" - @ kmkuslsw test.user@example.com 2001-02-03 04:05:18.000 +07:00 secondary@ 8fd911b4 + @ kmkuslsw test.user@example.com 2001-02-03 04:05:18.000 +07:00 secondary@ b93a9242 │ (no description set) ◉ kmkuslsw hidden test.user@example.com 2001-02-03 04:05:18.000 +07:00 30ee0d1f (empty) (no description set) diff --git a/lib/src/local_working_copy.rs b/lib/src/local_working_copy.rs index 03c39c3d22..1ec388a1fb 100644 --- a/lib/src/local_working_copy.rs +++ b/lib/src/local_working_copy.rs @@ -1457,9 +1457,10 @@ impl TreeState { Ok(()) } - pub fn reset_to_empty(&mut self) { + pub async fn recover(&mut self, new_tree: &MergedTree) -> Result<(), ResetError> { self.file_states.clear(); self.tree_id = self.store.empty_merged_tree_id(); + self.reset(new_tree).await } } @@ -1778,14 +1779,16 @@ impl LockedWorkingCopy for LockedLocalWorkingCopy { Ok(()) } - fn reset_to_empty(&mut self) -> Result<(), ResetError> { + fn recover(&mut self, commit: &Commit) -> Result<(), ResetError> { + let new_tree = commit.tree()?; self.wc .tree_state_mut() .map_err(|err| ResetError::Other { message: "Failed to read the working copy state".to_string(), err: err.into(), })? - .reset_to_empty(); + .recover(&new_tree) + .block_on()?; self.tree_state_dirty = true; Ok(()) } diff --git a/lib/src/working_copy.rs b/lib/src/working_copy.rs index 39c3b95631..072895e50b 100644 --- a/lib/src/working_copy.rs +++ b/lib/src/working_copy.rs @@ -107,8 +107,9 @@ pub trait LockedWorkingCopy { /// Update to another commit without touching the files in the working copy. fn reset(&mut self, commit: &Commit) -> Result<(), ResetError>; - /// Update to the empty tree without touching the files in the working copy. - fn reset_to_empty(&mut self) -> Result<(), ResetError>; + /// Update to another commit without touching the files in the working copy, + /// without assuming that the previous tree exists. + fn recover(&mut self, commit: &Commit) -> Result<(), ResetError>; /// See `WorkingCopy::sparse_patterns()` fn sparse_patterns(&self) -> Result<&[RepoPathBuf], WorkingCopyStateError>;