forked from mirrors/jj
working_copy: extract a function for updating the file state and tree if dirty
This commit is contained in:
parent
730c442462
commit
7c12014513
1 changed files with 64 additions and 59 deletions
|
@ -41,6 +41,7 @@ use crate::matchers::EverythingMatcher;
|
||||||
use crate::repo_path::{RepoPath, RepoPathComponent, RepoPathJoin};
|
use crate::repo_path::{RepoPath, RepoPathComponent, RepoPathJoin};
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
use crate::tree::Diff;
|
use crate::tree::Diff;
|
||||||
|
use crate::tree_builder::TreeBuilder;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum FileType {
|
pub enum FileType {
|
||||||
|
@ -298,8 +299,7 @@ impl TreeState {
|
||||||
|
|
||||||
let mut work = vec![(RepoPath::root(), self.working_copy_path.clone(), git_ignore)];
|
let mut work = vec![(RepoPath::root(), self.working_copy_path.clone(), git_ignore)];
|
||||||
let mut tree_builder = self.store.tree_builder(self.tree_id.clone());
|
let mut tree_builder = self.store.tree_builder(self.tree_id.clone());
|
||||||
let mut deleted_files: HashSet<&RepoPath> = self.file_states.keys().collect();
|
let mut deleted_files: HashSet<_> = self.file_states.keys().cloned().collect();
|
||||||
let mut modified_files = BTreeMap::new();
|
|
||||||
while !work.is_empty() {
|
while !work.is_empty() {
|
||||||
let (dir, disk_dir, git_ignore) = work.pop().unwrap();
|
let (dir, disk_dir, git_ignore) = work.pop().unwrap();
|
||||||
let git_ignore = TreeState::try_chain_gitignore(
|
let git_ignore = TreeState::try_chain_gitignore(
|
||||||
|
@ -335,74 +335,79 @@ impl TreeState {
|
||||||
}
|
}
|
||||||
work.push((sub_path, entry.path(), git_ignore.clone()));
|
work.push((sub_path, entry.path(), git_ignore.clone()));
|
||||||
} else {
|
} else {
|
||||||
let disk_file = entry.path();
|
|
||||||
deleted_files.remove(&sub_path);
|
deleted_files.remove(&sub_path);
|
||||||
let current_file_state = self.file_states.get(&sub_path);
|
self.update_file_state(
|
||||||
|
sub_path,
|
||||||
|
entry.path(),
|
||||||
|
git_ignore.as_ref(),
|
||||||
|
&mut tree_builder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for file in &deleted_files {
|
||||||
|
self.file_states.remove(file);
|
||||||
|
tree_builder.remove(file.clone());
|
||||||
|
}
|
||||||
|
self.tree_id = tree_builder.write_tree();
|
||||||
|
self.save();
|
||||||
|
&self.tree_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_file_state(
|
||||||
|
&mut self,
|
||||||
|
repo_path: RepoPath,
|
||||||
|
disk_path: PathBuf,
|
||||||
|
git_ignore: &GitIgnoreFile,
|
||||||
|
tree_builder: &mut TreeBuilder,
|
||||||
|
) {
|
||||||
|
let current_file_state = self.file_states.get(&repo_path);
|
||||||
if current_file_state.is_none()
|
if current_file_state.is_none()
|
||||||
&& git_ignore.matches_file(&sub_path.to_internal_file_string())
|
&& git_ignore.matches_file(&repo_path.to_internal_file_string())
|
||||||
{
|
{
|
||||||
// If it wasn't already tracked and it matches the ignored paths, then
|
// If it wasn't already tracked and it matches the ignored paths, then
|
||||||
// ignore it.
|
// ignore it.
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
let new_file_state = file_state(&disk_file).unwrap();
|
let new_file_state = file_state(&disk_path).unwrap();
|
||||||
let clean;
|
let clean;
|
||||||
let executable;
|
let executable;
|
||||||
match current_file_state {
|
match current_file_state {
|
||||||
None => {
|
None => {
|
||||||
// untracked
|
// untracked
|
||||||
clean = false;
|
clean = false;
|
||||||
executable =
|
executable = new_file_state.file_type == FileType::Normal { executable: true };
|
||||||
new_file_state.file_type == FileType::Normal { executable: true };
|
|
||||||
}
|
}
|
||||||
Some(current_entry) => {
|
Some(current_entry) => {
|
||||||
clean = current_entry == &new_file_state
|
clean = current_entry == &new_file_state && current_entry.mtime < self.read_time;
|
||||||
&& current_entry.mtime < self.read_time;
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
// On Windows, we preserve the state we had recorded
|
// On Windows, we preserve the state we had recorded
|
||||||
// when we wrote the file.
|
// when we wrote the file.
|
||||||
executable =
|
executable = current_entry.file_type == FileType::Normal { executable: true }
|
||||||
current_entry.file_type == FileType::Normal { executable: true }
|
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
executable = new_file_state.file_type
|
executable = new_file_state.file_type == FileType::Normal { executable: true }
|
||||||
== FileType::Normal { executable: true }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !clean {
|
if !clean {
|
||||||
let file_value = match new_file_state.file_type {
|
let file_value = match new_file_state.file_type {
|
||||||
FileType::Normal { .. } => {
|
FileType::Normal { .. } => {
|
||||||
let id = self.write_file_to_store(&sub_path, &disk_file);
|
let id = self.write_file_to_store(&repo_path, &disk_path);
|
||||||
TreeValue::Normal { id, executable }
|
TreeValue::Normal { id, executable }
|
||||||
}
|
}
|
||||||
FileType::Symlink => {
|
FileType::Symlink => {
|
||||||
let id = self.write_symlink_to_store(&sub_path, &disk_file);
|
let id = self.write_symlink_to_store(&repo_path, &disk_path);
|
||||||
TreeValue::Symlink(id)
|
TreeValue::Symlink(id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tree_builder.set(sub_path.clone(), file_value);
|
tree_builder.set(repo_path.clone(), file_value);
|
||||||
modified_files.insert(sub_path, new_file_state);
|
self.file_states.insert(repo_path, new_file_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let deleted_files: Vec<RepoPath> = deleted_files.iter().cloned().cloned().collect();
|
|
||||||
|
|
||||||
for file in &deleted_files {
|
|
||||||
self.file_states.remove(file);
|
|
||||||
tree_builder.remove(file.clone());
|
|
||||||
}
|
|
||||||
for (file, file_state) in modified_files {
|
|
||||||
self.file_states.insert(file, file_state);
|
|
||||||
}
|
|
||||||
self.tree_id = tree_builder.write_tree();
|
|
||||||
self.save();
|
|
||||||
&self.tree_id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_file(
|
fn write_file(
|
||||||
&self,
|
&self,
|
||||||
|
|
Loading…
Reference in a new issue