working_copy: record sparse patterns in the tree state (#52)

This patch makes room for sparse patterns in the `TreeState` proto
message. We also start setting that value to a list of just the
pattern `.` when we create new working copies. Old working copies
without the sparse patterns are also interpreted as having that single
pattern. Note that this absence of sparse patterns is different from a
present list of no patterns. The latter is a valid state and means
that no paths are included in the sparse checkout.
This commit is contained in:
Martin von Zweigbergk 2022-02-06 14:44:30 -08:00 committed by Martin von Zweigbergk
parent ed2d2f8a4f
commit ceb6c152a1
3 changed files with 59 additions and 0 deletions

View file

@ -29,9 +29,14 @@ message FileState {
bytes conflict_id = 4;
}
message SparsePatterns {
repeated string prefixes = 1;
}
message TreeState {
bytes tree_id = 1;
map<string, FileState> file_states = 2;
SparsePatterns sparse_patterns = 3;
}
message Checkout {

View file

@ -84,6 +84,8 @@ pub struct TreeState {
state_path: PathBuf,
tree_id: TreeId,
file_states: BTreeMap<RepoPath, FileState>,
// Currently only path prefixes
sparse_patterns: Vec<RepoPath>,
own_mtime: MillisSinceEpoch,
}
@ -132,6 +134,20 @@ fn file_states_from_proto(
file_states
}
fn sparse_patterns_from_proto(proto: &crate::protos::working_copy::TreeState) -> Vec<RepoPath> {
let mut sparse_patterns = vec![];
if proto.has_sparse_patterns() {
for prefix in &proto.get_sparse_patterns().prefixes {
sparse_patterns.push(RepoPath::from_internal_string(prefix.as_str()));
}
} else {
// For compatibility with old working copies.
// TODO: Delete this is late 2022 or so.
sparse_patterns.push(RepoPath::root());
}
sparse_patterns
}
fn create_parent_dirs(disk_path: &Path) {
fs::create_dir_all(disk_path.parent().unwrap())
.unwrap_or_else(|_| panic!("failed to create parent directories for {:?}", &disk_path));
@ -206,6 +222,10 @@ impl TreeState {
&self.file_states
}
pub fn sparse_patterns(&self) -> &Vec<RepoPath> {
&self.sparse_patterns
}
pub fn init(store: Arc<Store>, working_copy_path: PathBuf, state_path: PathBuf) -> TreeState {
let mut wc = TreeState::empty(store, working_copy_path, state_path);
wc.save();
@ -222,6 +242,7 @@ impl TreeState {
state_path,
tree_id,
file_states: BTreeMap::new(),
sparse_patterns: vec![RepoPath::root()],
own_mtime: MillisSinceEpoch(0),
}
}
@ -256,6 +277,7 @@ impl TreeState {
Message::parse_from_reader(&mut file).unwrap();
self.tree_id = TreeId::new(proto.tree_id.clone());
self.file_states = file_states_from_proto(&proto);
self.sparse_patterns = sparse_patterns_from_proto(&proto);
}
fn save(&mut self) {
@ -267,6 +289,13 @@ impl TreeState {
file_state_to_proto(file_state),
);
}
let mut sparse_patterns = crate::protos::working_copy::SparsePatterns::new();
for path in &self.sparse_patterns {
sparse_patterns
.prefixes
.push(path.to_internal_file_string());
}
proto.set_sparse_patterns(sparse_patterns);
let mut temp_file = NamedTempFile::new_in(&self.state_path).unwrap();
proto.write_to_writer(temp_file.as_file_mut()).unwrap();
@ -555,6 +584,10 @@ impl TreeState {
Ok(stats)
}
pub fn set_sparse_patterns(&mut self, sparse_patterns: Vec<RepoPath>) {
self.sparse_patterns = sparse_patterns;
}
fn update(
&mut self,
old_tree: &Tree,
@ -800,6 +833,14 @@ impl WorkingCopy {
self.tree_state().as_ref().unwrap().file_states().clone()
}
pub fn sparse_patterns(&self) -> Vec<RepoPath> {
self.tree_state()
.as_ref()
.unwrap()
.sparse_patterns()
.clone()
}
fn save(&mut self) {
let mut proto = crate::protos::working_copy::Checkout::new();
proto.operation_id = self.operation_id().to_bytes();
@ -894,6 +935,18 @@ impl LockedWorkingCopy<'_> {
self.wc.tree_state().as_mut().unwrap().reset(new_tree)
}
pub fn sparse_patterns(&self) -> Vec<RepoPath> {
self.wc.sparse_patterns()
}
pub fn set_sparse_patterns(&mut self, new_sparse_patterns: Vec<RepoPath>) {
self.wc
.tree_state()
.as_mut()
.unwrap()
.set_sparse_patterns(new_sparse_patterns)
}
pub fn finish(mut self, operation_id: OperationId) {
self.wc.tree_state().as_mut().unwrap().save();
self.wc.operation_id.replace(Some(operation_id));

View file

@ -39,6 +39,7 @@ 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();
let new_tree_id = locked_wc.write_tree(GitIgnoreFile::empty());
locked_wc.discard();