forked from mirrors/jj
refactor(working_copy): create SnapshotOptions
struct
Required in a later commit.
This commit is contained in:
parent
85d87e2658
commit
092dce0625
7 changed files with 94 additions and 40 deletions
|
@ -324,6 +324,20 @@ fn suppress_file_exists_error(orig_err: CheckoutError) -> Result<(), CheckoutErr
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SnapshotOptions<'a> {
|
||||
pub base_ignores: Arc<GitIgnoreFile>,
|
||||
pub progress: Option<&'a SnapshotProgress<'a>>,
|
||||
}
|
||||
|
||||
impl<'a> SnapshotOptions<'a> {
|
||||
pub fn empty_for_test() -> Self {
|
||||
SnapshotOptions {
|
||||
base_ignores: GitIgnoreFile::empty(),
|
||||
progress: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ResetError {
|
||||
// The current working-copy commit was deleted, maybe by an overly aggressive GC that happened
|
||||
|
@ -475,11 +489,12 @@ impl TreeState {
|
|||
|
||||
/// Look for changes to the working copy. If there are any changes, create
|
||||
/// a new tree from it.
|
||||
pub fn snapshot(
|
||||
&mut self,
|
||||
base_ignores: Arc<GitIgnoreFile>,
|
||||
progress: Option<&SnapshotProgress<'_>>,
|
||||
) -> Result<bool, SnapshotError> {
|
||||
pub fn snapshot(&mut self, options: SnapshotOptions) -> Result<bool, SnapshotError> {
|
||||
let SnapshotOptions {
|
||||
base_ignores,
|
||||
progress,
|
||||
} = options;
|
||||
|
||||
let sparse_matcher = self.sparse_matcher();
|
||||
let mut work = vec![(
|
||||
RepoPath::root(),
|
||||
|
@ -1214,13 +1229,9 @@ impl LockedWorkingCopy<'_> {
|
|||
// The base_ignores are passed in here rather than being set on the TreeState
|
||||
// because the TreeState may be long-lived if the library is used in a
|
||||
// long-lived process.
|
||||
pub fn snapshot(
|
||||
&mut self,
|
||||
base_ignores: Arc<GitIgnoreFile>,
|
||||
progress: Option<&SnapshotProgress<'_>>,
|
||||
) -> Result<TreeId, SnapshotError> {
|
||||
pub fn snapshot(&mut self, options: SnapshotOptions) -> Result<TreeId, SnapshotError> {
|
||||
let tree_state = self.wc.tree_state_mut();
|
||||
self.tree_state_dirty |= tree_state.snapshot(base_ignores, progress)?;
|
||||
self.tree_state_dirty |= tree_state.snapshot(options)?;
|
||||
Ok(tree_state.current_tree_id().clone())
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ use std::sync::Arc;
|
|||
use itertools::Itertools;
|
||||
use jujutsu_lib::backend::{TreeId, TreeValue};
|
||||
use jujutsu_lib::conflicts::Conflict;
|
||||
use jujutsu_lib::gitignore::GitIgnoreFile;
|
||||
#[cfg(unix)]
|
||||
use jujutsu_lib::op_store::OperationId;
|
||||
use jujutsu_lib::op_store::WorkspaceId;
|
||||
|
@ -31,7 +30,7 @@ use jujutsu_lib::repo::{ReadonlyRepo, Repo};
|
|||
use jujutsu_lib::repo_path::{RepoPath, RepoPathComponent, RepoPathJoin};
|
||||
use jujutsu_lib::settings::UserSettings;
|
||||
use jujutsu_lib::tree_builder::TreeBuilder;
|
||||
use jujutsu_lib::working_copy::WorkingCopy;
|
||||
use jujutsu_lib::working_copy::{SnapshotOptions, WorkingCopy};
|
||||
use test_case::test_case;
|
||||
use testutils::{write_random_commit, TestWorkspace};
|
||||
|
||||
|
@ -46,7 +45,9 @@ fn test_root(use_git: bool) {
|
|||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
assert_eq!(wc.sparse_patterns(), vec![RepoPath::root()]);
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
let wc_commit_id = repo
|
||||
.view()
|
||||
|
@ -204,7 +205,9 @@ fn test_checkout_file_transitions(use_git: bool) {
|
|||
|
||||
// Check that the working copy is clean.
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
assert_eq!(new_tree_id, right_tree_id);
|
||||
|
||||
|
@ -347,7 +350,9 @@ fn test_reset() {
|
|||
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();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
assert_eq!(new_tree_id, *tree_without_file.id());
|
||||
locked_wc.discard();
|
||||
|
||||
|
@ -360,7 +365,9 @@ fn test_reset() {
|
|||
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();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
assert_eq!(new_tree_id, *tree_without_file.id());
|
||||
locked_wc.discard();
|
||||
|
||||
|
@ -372,7 +379,9 @@ fn test_reset() {
|
|||
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();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
assert_eq!(new_tree_id, *tree_with_file.id());
|
||||
locked_wc.discard();
|
||||
}
|
||||
|
@ -448,7 +457,9 @@ fn test_snapshot_racy_timestamps(use_git: bool) {
|
|||
file.write_all(format!("contents {i}").as_bytes()).unwrap();
|
||||
}
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
assert_ne!(new_tree_id, previous_tree_id);
|
||||
previous_tree_id = new_tree_id;
|
||||
|
@ -480,7 +491,9 @@ 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 tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(OperationId::from_hex("abc123"));
|
||||
let tree = store.get_tree(&RepoPath::root(), &tree_id).unwrap();
|
||||
// Only the regular files should be in the tree
|
||||
|
@ -497,7 +510,9 @@ fn test_snapshot_special_file() {
|
|||
std::fs::remove_file(&file1_disk_path).unwrap();
|
||||
UnixListener::bind(&file1_disk_path).unwrap();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(OperationId::from_hex("abc123"));
|
||||
let tree = store.get_tree(&RepoPath::root(), &tree_id).unwrap();
|
||||
// Only the regular file should be in the tree
|
||||
|
@ -537,7 +552,9 @@ fn test_gitignores(use_git: bool) {
|
|||
|
||||
let wc = test_workspace.workspace.working_copy_mut();
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let new_tree_id1 = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id1 = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(repo.op_id().clone());
|
||||
let tree1 = repo
|
||||
.store()
|
||||
|
@ -567,7 +584,9 @@ fn test_gitignores(use_git: bool) {
|
|||
testutils::write_working_copy_file(&workspace_root, &subdir_ignored_path, "2");
|
||||
|
||||
let mut locked_wc = wc.start_mutation();
|
||||
let new_tree_id2 = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id2 = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
let tree2 = repo
|
||||
.store()
|
||||
|
@ -656,7 +675,9 @@ 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 new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
let new_tree = repo
|
||||
.store()
|
||||
|
@ -686,7 +707,9 @@ fn test_dotgit_ignored(use_git: bool) {
|
|||
"contents",
|
||||
);
|
||||
let mut locked_wc = test_workspace.workspace.working_copy_mut().start_mutation();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
assert_eq!(new_tree_id, *repo.store().empty_tree_id());
|
||||
locked_wc.discard();
|
||||
std::fs::remove_dir_all(&dotgit_path).unwrap();
|
||||
|
@ -698,7 +721,9 @@ fn test_dotgit_ignored(use_git: bool) {
|
|||
"contents",
|
||||
);
|
||||
let mut locked_wc = test_workspace.workspace.working_copy_mut().start_mutation();
|
||||
let new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
assert_eq!(new_tree_id, *repo.store().empty_tree_id());
|
||||
locked_wc.discard();
|
||||
}
|
||||
|
@ -752,7 +777,9 @@ 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 new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
assert_eq!(new_tree_id, tree_id);
|
||||
|
||||
|
|
|
@ -16,10 +16,9 @@ use std::cmp::max;
|
|||
use std::thread;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use jujutsu_lib::gitignore::GitIgnoreFile;
|
||||
use jujutsu_lib::repo::{Repo, StoreFactories};
|
||||
use jujutsu_lib::repo_path::RepoPath;
|
||||
use jujutsu_lib::working_copy::CheckoutError;
|
||||
use jujutsu_lib::working_copy::{CheckoutError, SnapshotOptions};
|
||||
use jujutsu_lib::workspace::Workspace;
|
||||
use test_case::test_case;
|
||||
use testutils::TestWorkspace;
|
||||
|
@ -135,7 +134,9 @@ fn test_checkout_parallel(use_git: bool) {
|
|||
// 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 new_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let new_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.discard();
|
||||
assert!(tree_ids.contains(&new_tree_id));
|
||||
});
|
||||
|
|
|
@ -13,11 +13,10 @@
|
|||
// limitations under the License.
|
||||
|
||||
use itertools::Itertools;
|
||||
use jujutsu_lib::gitignore::GitIgnoreFile;
|
||||
use jujutsu_lib::matchers::EverythingMatcher;
|
||||
use jujutsu_lib::repo::Repo;
|
||||
use jujutsu_lib::repo_path::RepoPath;
|
||||
use jujutsu_lib::working_copy::{CheckoutStats, WorkingCopy};
|
||||
use jujutsu_lib::working_copy::{CheckoutStats, SnapshotOptions, WorkingCopy};
|
||||
use testutils::TestWorkspace;
|
||||
|
||||
#[test]
|
||||
|
@ -168,7 +167,9 @@ 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 modified_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(repo.op_id().clone());
|
||||
let modified_tree = repo
|
||||
.store()
|
||||
|
@ -187,7 +188,9 @@ fn test_sparse_commit() {
|
|||
// 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 modified_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(repo.op_id().clone());
|
||||
let modified_tree = repo
|
||||
.store()
|
||||
|
@ -228,7 +231,9 @@ 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 modified_tree_id = locked_wc.snapshot(GitIgnoreFile::empty(), None).unwrap();
|
||||
let modified_tree_id = locked_wc
|
||||
.snapshot(SnapshotOptions::empty_for_test())
|
||||
.unwrap();
|
||||
locked_wc.finish(repo.op_id().clone());
|
||||
let modified_tree = repo
|
||||
.store()
|
||||
|
|
|
@ -55,7 +55,7 @@ use jujutsu_lib::transaction::Transaction;
|
|||
use jujutsu_lib::tree::{Tree, TreeMergeError};
|
||||
use jujutsu_lib::view::RefName;
|
||||
use jujutsu_lib::working_copy::{
|
||||
CheckoutStats, LockedWorkingCopy, ResetError, SnapshotError, WorkingCopy,
|
||||
CheckoutStats, LockedWorkingCopy, ResetError, SnapshotError, SnapshotOptions, WorkingCopy,
|
||||
};
|
||||
use jujutsu_lib::workspace::{Workspace, WorkspaceInitError, WorkspaceLoadError, WorkspaceLoader};
|
||||
use jujutsu_lib::{dag_walk, file_util, git, revset};
|
||||
|
@ -1091,7 +1091,10 @@ See https://github.com/martinvonz/jj/blob/main/docs/working-copy.md#stale-workin
|
|||
};
|
||||
self.user_repo = ReadonlyUserRepo::new(repo);
|
||||
let progress = crate::progress::snapshot_progress(ui);
|
||||
let new_tree_id = locked_wc.snapshot(base_ignores, progress.as_ref().map(|x| x as _))?;
|
||||
let new_tree_id = locked_wc.snapshot(SnapshotOptions {
|
||||
base_ignores,
|
||||
progress: progress.as_ref().map(|x| x as _),
|
||||
})?;
|
||||
drop(progress);
|
||||
if new_tree_id != *wc_commit.tree_id() {
|
||||
let mut tx = start_repo_transaction(
|
||||
|
|
|
@ -47,6 +47,7 @@ use jujutsu_lib::revset::{
|
|||
use jujutsu_lib::rewrite::{back_out_commit, merge_commit_trees, rebase_commit, DescendantRebaser};
|
||||
use jujutsu_lib::settings::UserSettings;
|
||||
use jujutsu_lib::tree::{merge_trees, Tree};
|
||||
use jujutsu_lib::working_copy::SnapshotOptions;
|
||||
use jujutsu_lib::workspace::Workspace;
|
||||
use jujutsu_lib::{file_util, revset};
|
||||
use maplit::{hashmap, hashset};
|
||||
|
@ -1308,7 +1309,10 @@ fn cmd_untrack(
|
|||
locked_working_copy.reset(&new_tree)?;
|
||||
// Commit the working copy again so we can inform the user if paths couldn't be
|
||||
// untracked because they're not ignored.
|
||||
let wc_tree_id = locked_working_copy.snapshot(base_ignores, None)?;
|
||||
let wc_tree_id = locked_working_copy.snapshot(SnapshotOptions {
|
||||
base_ignores,
|
||||
progress: None,
|
||||
})?;
|
||||
if wc_tree_id != new_tree_id {
|
||||
let wc_tree = store.get_tree(&RepoPath::root(), &wc_tree_id)?;
|
||||
let added_back = wc_tree.entries_matching(matcher.as_ref()).collect_vec();
|
||||
|
|
|
@ -29,7 +29,7 @@ use jujutsu_lib::repo_path::RepoPath;
|
|||
use jujutsu_lib::settings::{ConfigResultExt as _, UserSettings};
|
||||
use jujutsu_lib::store::Store;
|
||||
use jujutsu_lib::tree::Tree;
|
||||
use jujutsu_lib::working_copy::{CheckoutError, SnapshotError, TreeState};
|
||||
use jujutsu_lib::working_copy::{CheckoutError, SnapshotError, SnapshotOptions, TreeState};
|
||||
use regex::{Captures, Regex};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -366,7 +366,10 @@ pub fn edit_diff(
|
|||
std::fs::remove_file(instructions_path).ok();
|
||||
}
|
||||
|
||||
right_tree_state.snapshot(base_ignores, None)?;
|
||||
right_tree_state.snapshot(SnapshotOptions {
|
||||
base_ignores,
|
||||
progress: None,
|
||||
})?;
|
||||
Ok(right_tree_state.current_tree_id().clone())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue