mirror of
https://github.com/martinvonz/jj.git
synced 2024-11-13 14:15:02 +03:00
working_copy: return Result
from WorkingCopy::tree_state
/WorkingCopy::tree_state_mut
This commit is contained in:
parent
60f1d7e307
commit
6d7998f8c5
@ -15,6 +15,7 @@
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::error::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::fs::{DirEntry, File, Metadata, OpenOptions};
|
||||
@ -299,6 +300,8 @@ pub enum SnapshotError {
|
||||
InvalidUtf8SymlinkTarget { path: PathBuf, target: PathBuf },
|
||||
#[error("Internal backend error: {0}")]
|
||||
InternalBackendError(#[from] BackendError),
|
||||
#[error(transparent)]
|
||||
TreeStateError(#[from] TreeStateError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@ -374,6 +377,8 @@ pub enum ResetError {
|
||||
},
|
||||
#[error("Internal error: {0}")]
|
||||
InternalBackendError(#[from] BackendError),
|
||||
#[error(transparent)]
|
||||
TreeStateError(#[from] TreeStateError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
@ -398,6 +403,8 @@ pub enum TreeStateError {
|
||||
path: PathBuf,
|
||||
source: tempfile::PersistError,
|
||||
},
|
||||
#[error("Filesystem monitor error: {0}")]
|
||||
Fsmonitor(Box<dyn Error + Send + Sync>),
|
||||
}
|
||||
|
||||
impl TreeState {
|
||||
@ -580,10 +587,16 @@ impl TreeState {
|
||||
#[tokio::main]
|
||||
pub async fn query_watchman(
|
||||
&self,
|
||||
) -> Result<(watchman::Clock, Option<Vec<PathBuf>>), watchman::Error> {
|
||||
let fsmonitor = watchman::Fsmonitor::init(&self.working_copy_path).await?;
|
||||
) -> Result<(watchman::Clock, Option<Vec<PathBuf>>), TreeStateError> {
|
||||
let fsmonitor = watchman::Fsmonitor::init(&self.working_copy_path)
|
||||
.await
|
||||
.map_err(|err| TreeStateError::Fsmonitor(Box::new(err)))?;
|
||||
let previous_clock = self.watchman_clock.clone().map(watchman::Clock::from);
|
||||
fsmonitor.query_changed_files(previous_clock).await
|
||||
let changed_files = fsmonitor
|
||||
.query_changed_files(previous_clock)
|
||||
.await
|
||||
.map_err(|err| TreeStateError::Fsmonitor(Box::new(err)))?;
|
||||
Ok(changed_files)
|
||||
}
|
||||
|
||||
/// Look for changes to the working copy. If there are any changes, create
|
||||
@ -1306,33 +1319,31 @@ impl WorkingCopy {
|
||||
&self.checkout_state().workspace_id
|
||||
}
|
||||
|
||||
fn tree_state(&self) -> &TreeState {
|
||||
self.tree_state
|
||||
.get_or_try_init(|| {
|
||||
TreeState::load(
|
||||
self.store.clone(),
|
||||
self.working_copy_path.clone(),
|
||||
self.state_path.clone(),
|
||||
)
|
||||
})
|
||||
.unwrap() // FIXME: propagate error
|
||||
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_mut(&mut self) -> &mut TreeState {
|
||||
self.tree_state(); // ensure loaded
|
||||
self.tree_state.get_mut().unwrap()
|
||||
fn tree_state_mut(&mut self) -> Result<&mut TreeState, TreeStateError> {
|
||||
self.tree_state()?; // ensure loaded
|
||||
Ok(self.tree_state.get_mut().unwrap())
|
||||
}
|
||||
|
||||
pub fn current_tree_id(&self) -> &TreeId {
|
||||
self.tree_state().current_tree_id()
|
||||
pub fn current_tree_id(&self) -> Result<&TreeId, TreeStateError> {
|
||||
Ok(self.tree_state()?.current_tree_id())
|
||||
}
|
||||
|
||||
pub fn file_states(&self) -> &BTreeMap<RepoPath, FileState> {
|
||||
self.tree_state().file_states()
|
||||
pub fn file_states(&self) -> Result<&BTreeMap<RepoPath, FileState>, TreeStateError> {
|
||||
Ok(self.tree_state()?.file_states())
|
||||
}
|
||||
|
||||
pub fn sparse_patterns(&self) -> &[RepoPath] {
|
||||
self.tree_state().sparse_patterns()
|
||||
pub fn sparse_patterns(&self) -> Result<&[RepoPath], TreeStateError> {
|
||||
Ok(self.tree_state()?.sparse_patterns())
|
||||
}
|
||||
|
||||
fn save(&mut self) {
|
||||
@ -1343,7 +1354,7 @@ impl WorkingCopy {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn start_mutation(&mut self) -> LockedWorkingCopy {
|
||||
pub fn start_mutation(&mut self) -> Result<LockedWorkingCopy, TreeStateError> {
|
||||
let lock_path = self.state_path.join("working_copy.lock");
|
||||
let lock = FileLock::lock(lock_path);
|
||||
|
||||
@ -1353,16 +1364,16 @@ impl WorkingCopy {
|
||||
// has changed.
|
||||
self.tree_state.take();
|
||||
let old_operation_id = self.operation_id().clone();
|
||||
let old_tree_id = self.current_tree_id().clone();
|
||||
let old_tree_id = self.current_tree_id()?.clone();
|
||||
|
||||
LockedWorkingCopy {
|
||||
Ok(LockedWorkingCopy {
|
||||
wc: self,
|
||||
lock,
|
||||
old_operation_id,
|
||||
old_tree_id,
|
||||
tree_state_dirty: false,
|
||||
closed: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn check_out(
|
||||
@ -1371,7 +1382,7 @@ impl WorkingCopy {
|
||||
old_tree_id: Option<&TreeId>,
|
||||
new_tree: &Tree,
|
||||
) -> Result<CheckoutStats, CheckoutError> {
|
||||
let mut locked_wc = self.start_mutation();
|
||||
let mut locked_wc = self.start_mutation()?;
|
||||
// Check if the current working-copy commit has changed on disk compared to what
|
||||
// the caller expected. It's safe to check out another commit
|
||||
// regardless, but it's probably not what the caller wanted, so we let
|
||||
@ -1390,8 +1401,8 @@ impl WorkingCopy {
|
||||
#[cfg(feature = "watchman")]
|
||||
pub fn query_watchman(
|
||||
&self,
|
||||
) -> Result<(watchman::Clock, Option<Vec<PathBuf>>), watchman::Error> {
|
||||
self.tree_state().query_watchman()
|
||||
) -> Result<(watchman::Clock, Option<Vec<PathBuf>>), TreeStateError> {
|
||||
self.tree_state()?.query_watchman()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1419,7 +1430,7 @@ impl LockedWorkingCopy<'_> {
|
||||
}
|
||||
|
||||
pub fn reset_watchman(&mut self) -> Result<(), SnapshotError> {
|
||||
self.wc.tree_state_mut().reset_watchman();
|
||||
self.wc.tree_state_mut()?.reset_watchman();
|
||||
self.tree_state_dirty = true;
|
||||
Ok(())
|
||||
}
|
||||
@ -1428,7 +1439,7 @@ impl LockedWorkingCopy<'_> {
|
||||
// because the TreeState may be long-lived if the library is used in a
|
||||
// long-lived process.
|
||||
pub fn snapshot(&mut self, options: SnapshotOptions) -> Result<TreeId, SnapshotError> {
|
||||
let tree_state = self.wc.tree_state_mut();
|
||||
let tree_state = self.wc.tree_state_mut()?;
|
||||
self.tree_state_dirty |= tree_state.snapshot(options)?;
|
||||
Ok(tree_state.current_tree_id().clone())
|
||||
}
|
||||
@ -1436,18 +1447,18 @@ impl LockedWorkingCopy<'_> {
|
||||
pub fn check_out(&mut self, new_tree: &Tree) -> Result<CheckoutStats, CheckoutError> {
|
||||
// TODO: Write a "pending_checkout" file with the new TreeId so we can
|
||||
// continue an interrupted update if we find such a file.
|
||||
let stats = self.wc.tree_state_mut().check_out(new_tree)?;
|
||||
let stats = self.wc.tree_state_mut()?.check_out(new_tree)?;
|
||||
self.tree_state_dirty = true;
|
||||
Ok(stats)
|
||||
}
|
||||
|
||||
pub fn reset(&mut self, new_tree: &Tree) -> Result<(), ResetError> {
|
||||
self.wc.tree_state_mut().reset(new_tree)?;
|
||||
self.wc.tree_state_mut()?.reset(new_tree)?;
|
||||
self.tree_state_dirty = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn sparse_patterns(&self) -> &[RepoPath] {
|
||||
pub fn sparse_patterns(&self) -> Result<&[RepoPath], TreeStateError> {
|
||||
self.wc.sparse_patterns()
|
||||
}
|
||||
|
||||
@ -1459,16 +1470,16 @@ impl LockedWorkingCopy<'_> {
|
||||
// continue an interrupted update if we find such a file.
|
||||
let stats = self
|
||||
.wc
|
||||
.tree_state_mut()
|
||||
.tree_state_mut()?
|
||||
.set_sparse_patterns(new_sparse_patterns)?;
|
||||
self.tree_state_dirty = true;
|
||||
Ok(stats)
|
||||
}
|
||||
|
||||
pub fn finish(mut self, operation_id: OperationId) -> Result<(), TreeStateError> {
|
||||
assert!(self.tree_state_dirty || &self.old_tree_id == self.wc.current_tree_id());
|
||||
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()?;
|
||||
}
|
||||
if self.old_operation_id != operation_id {
|
||||
self.wc.checkout_state_mut().operation_id = operation_id;
|
||||
|
@ -44,8 +44,8 @@ fn test_root(use_git: bool) {
|
||||
let repo = &test_workspace.repo;
|
||||
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
assert_eq!(wc.sparse_patterns(), vec![RepoPath::root()]);
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
assert_eq!(wc.sparse_patterns().unwrap(), vec![RepoPath::root()]);
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -205,7 +205,7 @@ fn test_checkout_file_transitions(use_git: bool) {
|
||||
.unwrap();
|
||||
|
||||
// Check that the working copy is clean.
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -340,17 +340,17 @@ fn test_reset() {
|
||||
|
||||
// Test the setup: the file should exist on disk and in the tree state.
|
||||
assert!(ignored_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(wc.file_states().contains_key(&ignored_path));
|
||||
assert!(wc.file_states().unwrap().contains_key(&ignored_path));
|
||||
|
||||
// After we reset to the commit without the file, it should still exist on disk,
|
||||
// but it should not be in the tree state, and it should not get added when we
|
||||
// commit the working copy (because it's ignored).
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
locked_wc.reset(&tree_without_file).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
assert!(ignored_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(!wc.file_states().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
assert!(!wc.file_states().unwrap().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -360,12 +360,12 @@ fn test_reset() {
|
||||
// After we reset to the commit without the file, it should still exist on disk,
|
||||
// but it should not be in the tree state, and it should not get added when we
|
||||
// commit the working copy (because it's ignored).
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
locked_wc.reset(&tree_without_file).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
assert!(ignored_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(!wc.file_states().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
assert!(!wc.file_states().unwrap().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -374,12 +374,12 @@ fn test_reset() {
|
||||
|
||||
// Now test the opposite direction: resetting to a commit where the file is
|
||||
// tracked. The file should become tracked (even though it's ignored).
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
locked_wc.reset(&tree_with_file).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
assert!(ignored_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(wc.file_states().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
assert!(wc.file_states().unwrap().contains_key(&ignored_path));
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -410,27 +410,27 @@ fn test_checkout_discard() {
|
||||
|
||||
// Test the setup: the file should exist on disk and in the tree state.
|
||||
assert!(file1_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(wc.file_states().contains_key(&file1_path));
|
||||
assert!(wc.file_states().unwrap().contains_key(&file1_path));
|
||||
|
||||
// Start a checkout
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
locked_wc.check_out(&tree2).unwrap();
|
||||
// The change should be reflected in the working copy but not saved
|
||||
assert!(!file1_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(file2_path.to_fs_path(&workspace_root).is_file());
|
||||
let reloaded_wc = WorkingCopy::load(store.clone(), workspace_root.clone(), state_path.clone());
|
||||
assert!(reloaded_wc.file_states().contains_key(&file1_path));
|
||||
assert!(!reloaded_wc.file_states().contains_key(&file2_path));
|
||||
assert!(reloaded_wc.file_states().unwrap().contains_key(&file1_path));
|
||||
assert!(!reloaded_wc.file_states().unwrap().contains_key(&file2_path));
|
||||
locked_wc.discard();
|
||||
|
||||
// The change should remain in the working copy, but not in memory and not saved
|
||||
assert!(wc.file_states().contains_key(&file1_path));
|
||||
assert!(!wc.file_states().contains_key(&file2_path));
|
||||
assert!(wc.file_states().unwrap().contains_key(&file1_path));
|
||||
assert!(!wc.file_states().unwrap().contains_key(&file2_path));
|
||||
assert!(!file1_path.to_fs_path(&workspace_root).is_file());
|
||||
assert!(file2_path.to_fs_path(&workspace_root).is_file());
|
||||
let reloaded_wc = WorkingCopy::load(store.clone(), workspace_root, state_path);
|
||||
assert!(reloaded_wc.file_states().contains_key(&file1_path));
|
||||
assert!(!reloaded_wc.file_states().contains_key(&file2_path));
|
||||
assert!(reloaded_wc.file_states().unwrap().contains_key(&file1_path));
|
||||
assert!(!reloaded_wc.file_states().unwrap().contains_key(&file2_path));
|
||||
}
|
||||
|
||||
#[test_case(false ; "local backend")]
|
||||
@ -457,7 +457,7 @@ fn test_snapshot_racy_timestamps(use_git: bool) {
|
||||
.unwrap();
|
||||
file.write_all(format!("contents {i}").as_bytes()).unwrap();
|
||||
}
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -491,7 +491,7 @@ fn test_snapshot_special_file() {
|
||||
|
||||
// Snapshot the working copy with the socket file
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -503,14 +503,14 @@ fn test_snapshot_special_file() {
|
||||
vec![file1_path.clone(), file2_path.clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
wc.file_states().keys().cloned().collect_vec(),
|
||||
wc.file_states().unwrap().keys().cloned().collect_vec(),
|
||||
vec![file1_path, file2_path.clone()]
|
||||
);
|
||||
|
||||
// Replace a regular file by a socket and snapshot the working copy again
|
||||
std::fs::remove_file(&file1_disk_path).unwrap();
|
||||
UnixListener::bind(&file1_disk_path).unwrap();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -522,7 +522,7 @@ fn test_snapshot_special_file() {
|
||||
vec![file2_path.clone()]
|
||||
);
|
||||
assert_eq!(
|
||||
wc.file_states().keys().cloned().collect_vec(),
|
||||
wc.file_states().unwrap().keys().cloned().collect_vec(),
|
||||
vec![file2_path]
|
||||
);
|
||||
}
|
||||
@ -552,7 +552,7 @@ fn test_gitignores(use_git: bool) {
|
||||
testutils::write_working_copy_file(&workspace_root, &subdir_modified_path, "1");
|
||||
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id1 = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -584,7 +584,7 @@ fn test_gitignores(use_git: bool) {
|
||||
testutils::write_working_copy_file(&workspace_root, &subdir_modified_path, "2");
|
||||
testutils::write_working_copy_file(&workspace_root, &subdir_ignored_path, "2");
|
||||
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id2 = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -675,7 +675,7 @@ fn test_gitignores_ignored_directory_already_tracked(use_git: bool) {
|
||||
|
||||
// Check that the file is still in the tree created by snapshotting the working
|
||||
// copy (that it didn't get removed because the directory is ignored)
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -707,7 +707,11 @@ fn test_dotgit_ignored(use_git: bool) {
|
||||
&RepoPath::from_internal_string(".git/file"),
|
||||
"contents",
|
||||
);
|
||||
let mut locked_wc = test_workspace.workspace.working_copy_mut().start_mutation();
|
||||
let mut locked_wc = test_workspace
|
||||
.workspace
|
||||
.working_copy_mut()
|
||||
.start_mutation()
|
||||
.unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -721,7 +725,11 @@ fn test_dotgit_ignored(use_git: bool) {
|
||||
&RepoPath::from_internal_string(".git"),
|
||||
"contents",
|
||||
);
|
||||
let mut locked_wc = test_workspace.workspace.working_copy_mut().start_mutation();
|
||||
let mut locked_wc = test_workspace
|
||||
.workspace
|
||||
.working_copy_mut()
|
||||
.start_mutation()
|
||||
.unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -777,7 +785,7 @@ fn test_gitsubmodule() {
|
||||
|
||||
// Check that the files present in the submodule are not tracked
|
||||
// when we snapshot
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -831,7 +839,7 @@ fn test_fsmonitor() {
|
||||
let workspace_root = test_workspace.workspace.workspace_root().clone();
|
||||
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
assert_eq!(wc.sparse_patterns(), vec![RepoPath::root()]);
|
||||
assert_eq!(wc.sparse_patterns().unwrap(), vec![RepoPath::root()]);
|
||||
|
||||
let foo_path = RepoPath::from_internal_string("foo");
|
||||
let bar_path = RepoPath::from_internal_string("bar");
|
||||
@ -861,14 +869,14 @@ fn test_fsmonitor() {
|
||||
};
|
||||
|
||||
{
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = snapshot(&mut locked_wc, &[]);
|
||||
assert_eq!(tree_id, *repo.store().empty_tree_id());
|
||||
locked_wc.discard();
|
||||
}
|
||||
|
||||
{
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = snapshot(&mut locked_wc, &[&foo_path]);
|
||||
insta::assert_snapshot!(testutils::dump_tree(repo.store(), &tree_id), @r###"
|
||||
tree 205f6b799e7d5c2524468ca006a0131aa57ecce7
|
||||
@ -878,7 +886,7 @@ fn test_fsmonitor() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = snapshot(
|
||||
&mut locked_wc,
|
||||
&[&foo_path, &bar_path, &nested_path, &ignored_path],
|
||||
@ -895,7 +903,7 @@ fn test_fsmonitor() {
|
||||
{
|
||||
testutils::write_working_copy_file(&workspace_root, &foo_path, "updated foo\n");
|
||||
testutils::write_working_copy_file(&workspace_root, &bar_path, "updated bar\n");
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = snapshot(&mut locked_wc, &[&foo_path]);
|
||||
insta::assert_snapshot!(testutils::dump_tree(repo.store(), &tree_id), @r###"
|
||||
tree 2f57ab8f48ae62e3137079f2add9878dfa1d1bcc
|
||||
@ -908,7 +916,7 @@ fn test_fsmonitor() {
|
||||
|
||||
{
|
||||
std::fs::remove_file(foo_path.to_fs_path(&workspace_root)).unwrap();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let tree_id = snapshot(&mut locked_wc, &[&foo_path]);
|
||||
insta::assert_snapshot!(testutils::dump_tree(repo.store(), &tree_id), @r###"
|
||||
tree 34b83765131477e1a7d72160079daec12c6144e3
|
||||
|
@ -72,7 +72,10 @@ fn test_concurrent_checkout(use_git: bool) {
|
||||
// Check that the tree2 is still checked out on disk.
|
||||
let workspace3 =
|
||||
Workspace::load(&settings, &workspace1_root, &StoreFactories::default()).unwrap();
|
||||
assert_eq!(workspace3.working_copy().current_tree_id(), &tree_id2);
|
||||
assert_eq!(
|
||||
workspace3.working_copy().current_tree_id().unwrap(),
|
||||
&tree_id2
|
||||
);
|
||||
}
|
||||
|
||||
#[test_case(false ; "local backend")]
|
||||
@ -133,7 +136,7 @@ fn test_checkout_parallel(use_git: bool) {
|
||||
// different tree than the one we just checked out, but since
|
||||
// write_tree() should take the same lock as check_out(), write_tree()
|
||||
// should never produce a different tree.
|
||||
let mut locked_wc = workspace.working_copy_mut().start_mutation();
|
||||
let mut locked_wc = workspace.working_copy_mut().start_mutation().unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
|
@ -52,7 +52,7 @@ fn test_sparse_checkout() {
|
||||
wc.check_out(repo.op_id().clone(), None, &tree).unwrap();
|
||||
|
||||
// Set sparse patterns to only dir1/
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let sparse_patterns = vec![dir1_path];
|
||||
let stats = locked_wc
|
||||
.set_sparse_patterns(sparse_patterns.clone())
|
||||
@ -65,7 +65,7 @@ fn test_sparse_checkout() {
|
||||
removed_files: 3
|
||||
}
|
||||
);
|
||||
assert_eq!(locked_wc.sparse_patterns(), sparse_patterns);
|
||||
assert_eq!(locked_wc.sparse_patterns().unwrap(), sparse_patterns);
|
||||
assert!(!root_file1_path.to_fs_path(&working_copy_path).exists());
|
||||
assert!(!root_file2_path.to_fs_path(&working_copy_path).exists());
|
||||
assert!(dir1_file1_path.to_fs_path(&working_copy_path).exists());
|
||||
@ -78,10 +78,10 @@ fn test_sparse_checkout() {
|
||||
// Write the new state to disk
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
assert_eq!(
|
||||
wc.file_states().keys().collect_vec(),
|
||||
wc.file_states().unwrap().keys().collect_vec(),
|
||||
vec![&dir1_file1_path, &dir1_file2_path, &dir1_subdir1_file1_path]
|
||||
);
|
||||
assert_eq!(wc.sparse_patterns(), sparse_patterns);
|
||||
assert_eq!(wc.sparse_patterns().unwrap(), sparse_patterns);
|
||||
|
||||
// Reload the state to check that it was persisted
|
||||
let mut wc = WorkingCopy::load(
|
||||
@ -90,13 +90,13 @@ fn test_sparse_checkout() {
|
||||
wc.state_path().to_path_buf(),
|
||||
);
|
||||
assert_eq!(
|
||||
wc.file_states().keys().collect_vec(),
|
||||
wc.file_states().unwrap().keys().collect_vec(),
|
||||
vec![&dir1_file1_path, &dir1_file2_path, &dir1_subdir1_file1_path]
|
||||
);
|
||||
assert_eq!(wc.sparse_patterns(), sparse_patterns);
|
||||
assert_eq!(wc.sparse_patterns().unwrap(), sparse_patterns);
|
||||
|
||||
// Set sparse patterns to file2, dir1/subdir1/ and dir2/
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let sparse_patterns = vec![root_file1_path.clone(), dir1_subdir1_path, dir2_path];
|
||||
let stats = locked_wc
|
||||
.set_sparse_patterns(sparse_patterns.clone())
|
||||
@ -109,7 +109,7 @@ fn test_sparse_checkout() {
|
||||
removed_files: 2
|
||||
}
|
||||
);
|
||||
assert_eq!(locked_wc.sparse_patterns(), sparse_patterns);
|
||||
assert_eq!(locked_wc.sparse_patterns().unwrap(), sparse_patterns);
|
||||
assert!(root_file1_path.to_fs_path(&working_copy_path).exists());
|
||||
assert!(!root_file2_path.to_fs_path(&working_copy_path).exists());
|
||||
assert!(!dir1_file1_path.to_fs_path(&working_copy_path).exists());
|
||||
@ -120,7 +120,7 @@ fn test_sparse_checkout() {
|
||||
assert!(dir2_file1_path.to_fs_path(&working_copy_path).exists());
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
assert_eq!(
|
||||
wc.file_states().keys().collect_vec(),
|
||||
wc.file_states().unwrap().keys().collect_vec(),
|
||||
vec![&dir1_subdir1_file1_path, &dir2_file1_path, &root_file1_path]
|
||||
);
|
||||
}
|
||||
@ -152,7 +152,7 @@ fn test_sparse_commit() {
|
||||
wc.check_out(repo.op_id().clone(), None, &tree).unwrap();
|
||||
|
||||
// Set sparse patterns to only dir1/
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let sparse_patterns = vec![dir1_path.clone()];
|
||||
locked_wc.set_sparse_patterns(sparse_patterns).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
@ -166,7 +166,7 @@ fn test_sparse_commit() {
|
||||
|
||||
// Create a tree from the working copy. Only dir1/file1 should be updated in the
|
||||
// tree.
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -180,14 +180,14 @@ fn test_sparse_commit() {
|
||||
assert_eq!(diff[0].0, dir1_file1_path);
|
||||
|
||||
// Set sparse patterns to also include dir2/
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let sparse_patterns = vec![dir1_path, dir2_path];
|
||||
locked_wc.set_sparse_patterns(sparse_patterns).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
|
||||
// Create a tree from the working copy. Only dir1/file1 and dir2/file1 should be
|
||||
// updated in the tree.
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
@ -217,7 +217,7 @@ fn test_sparse_commit_gitignore() {
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
|
||||
// Set sparse patterns to only dir1/
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let sparse_patterns = vec![dir1_path.clone()];
|
||||
locked_wc.set_sparse_patterns(sparse_patterns).unwrap();
|
||||
locked_wc.finish(repo.op_id().clone()).unwrap();
|
||||
@ -230,7 +230,7 @@ fn test_sparse_commit_gitignore() {
|
||||
|
||||
// Create a tree from the working copy. Only dir1/file2 should be updated in the
|
||||
// tree because dir1/file1 is ignored.
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let mut locked_wc = wc.start_mutation().unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
|
@ -749,7 +749,7 @@ impl WorkspaceCommandHelper {
|
||||
tx.mut_repo()
|
||||
.check_out(workspace_id, &self.settings, &new_git_head_commit)?;
|
||||
let mut locked_working_copy =
|
||||
self.workspace.working_copy_mut().start_mutation();
|
||||
self.workspace.working_copy_mut().start_mutation()?;
|
||||
// The working copy was presumably updated by the git command that updated
|
||||
// HEAD, so we just need to reset our working copy
|
||||
// state to it without updating working copy files.
|
||||
@ -825,7 +825,7 @@ impl WorkspaceCommandHelper {
|
||||
return Err(user_error("Nothing checked out in this workspace"));
|
||||
};
|
||||
|
||||
let locked_working_copy = self.workspace.working_copy_mut().start_mutation();
|
||||
let locked_working_copy = self.workspace.working_copy_mut().start_mutation()?;
|
||||
|
||||
Ok((locked_working_copy, wc_commit))
|
||||
}
|
||||
@ -1104,7 +1104,7 @@ impl WorkspaceCommandHelper {
|
||||
let base_ignores = self.base_ignores();
|
||||
|
||||
// Compare working-copy tree and operation with repo's, and reload as needed.
|
||||
let mut locked_wc = self.workspace.working_copy_mut().start_mutation();
|
||||
let mut locked_wc = self.workspace.working_copy_mut().start_mutation()?;
|
||||
let old_op_id = locked_wc.old_operation_id().clone();
|
||||
let (repo, wc_commit) = match check_stale_working_copy(&locked_wc, &wc_commit, &repo) {
|
||||
Ok(None) => (repo, wc_commit),
|
||||
@ -1816,7 +1816,7 @@ pub fn update_working_copy(
|
||||
Some(stats)
|
||||
} else {
|
||||
// Record new operation id which represents the latest working-copy state
|
||||
let locked_wc = wc.start_mutation();
|
||||
let locked_wc = wc.start_mutation()?;
|
||||
locked_wc.finish(repo.op_id().clone())?;
|
||||
None
|
||||
};
|
||||
|
@ -103,8 +103,8 @@ pub fn cmd_debug(
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
let wc = workspace_command.working_copy();
|
||||
writeln!(ui, "Current operation: {:?}", wc.operation_id())?;
|
||||
writeln!(ui, "Current tree: {:?}", wc.current_tree_id())?;
|
||||
for (file, state) in wc.file_states() {
|
||||
writeln!(ui, "Current tree: {:?}", wc.current_tree_id()?)?;
|
||||
for (file, state) in wc.file_states()? {
|
||||
writeln!(
|
||||
ui,
|
||||
"{:?} {:13?} {:10?} {:?}",
|
||||
@ -238,13 +238,11 @@ fn cmd_debug_watchman(
|
||||
let repo = workspace_command.repo().clone();
|
||||
match subcommand {
|
||||
DebugWatchmanSubcommand::QueryClock => {
|
||||
let (clock, _changed_files) =
|
||||
workspace_command.working_copy().query_watchman().unwrap();
|
||||
let (clock, _changed_files) = workspace_command.working_copy().query_watchman()?;
|
||||
ui.write(&format!("Clock: {clock:?}"))?;
|
||||
}
|
||||
DebugWatchmanSubcommand::QueryChangedFiles => {
|
||||
let (_clock, changed_files) =
|
||||
workspace_command.working_copy().query_watchman().unwrap();
|
||||
let (_clock, changed_files) = workspace_command.working_copy().query_watchman()?;
|
||||
ui.write(&format!("Changed files: {changed_files:?}"))?;
|
||||
}
|
||||
DebugWatchmanSubcommand::ResetClock => {
|
||||
|
@ -3559,7 +3559,7 @@ fn cmd_sparse_list(
|
||||
_args: &SparseListArgs,
|
||||
) -> Result<(), CommandError> {
|
||||
let workspace_command = command.workspace_helper(ui)?;
|
||||
for path in workspace_command.working_copy().sparse_patterns() {
|
||||
for path in workspace_command.working_copy().sparse_patterns()? {
|
||||
let ui_path = workspace_command.format_file_path(path);
|
||||
writeln!(ui, "{ui_path}")?;
|
||||
}
|
||||
@ -3596,7 +3596,7 @@ fn cmd_sparse_set(
|
||||
new_patterns.insert(RepoPath::root());
|
||||
} else {
|
||||
if !args.clear {
|
||||
new_patterns.extend(locked_wc.sparse_patterns().iter().cloned());
|
||||
new_patterns.extend(locked_wc.sparse_patterns()?.iter().cloned());
|
||||
for path in paths_to_remove {
|
||||
new_patterns.remove(&path);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user