mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-06 20:42:10 +00:00
working_copy: get conflict id from the current tree
This prepares for allowing the base tree to be a conflict at the root-tree level (#1624). We could remove the `Conflict` variant completely. I tried doing that and it slowed down `jj diff` by ~3% in the Linux repo with a clean working copy with only mtime bumped on all files.
This commit is contained in:
parent
3ca42908ee
commit
dc8a207737
3 changed files with 20 additions and 21 deletions
|
@ -29,7 +29,7 @@ message FileState {
|
||||||
uint64 size = 2;
|
uint64 size = 2;
|
||||||
FileType file_type = 3;
|
FileType file_type = 3;
|
||||||
// Set only if file_type is Conflict
|
// Set only if file_type is Conflict
|
||||||
bytes conflict_id = 4;
|
bytes conflict_id = 4 [deprecated = true];
|
||||||
}
|
}
|
||||||
|
|
||||||
message SparsePatterns {
|
message SparsePatterns {
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub struct FileState {
|
||||||
#[prost(enumeration = "FileType", tag = "3")]
|
#[prost(enumeration = "FileType", tag = "3")]
|
||||||
pub file_type: i32,
|
pub file_type: i32,
|
||||||
/// Set only if file_type is Conflict
|
/// Set only if file_type is Conflict
|
||||||
|
#[deprecated]
|
||||||
#[prost(bytes = "vec", tag = "4")]
|
#[prost(bytes = "vec", tag = "4")]
|
||||||
pub conflict_id: ::prost::alloc::vec::Vec<u8>,
|
pub conflict_id: ::prost::alloc::vec::Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub enum FileType {
|
||||||
Normal { executable: bool },
|
Normal { executable: bool },
|
||||||
Symlink,
|
Symlink,
|
||||||
GitSubmodule,
|
GitSubmodule,
|
||||||
Conflict { id: ConflictId },
|
Conflict,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
|
@ -82,9 +82,9 @@ impl FileState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn for_conflict(id: ConflictId, size: u64, metadata: &Metadata) -> Self {
|
fn for_conflict(size: u64, metadata: &Metadata) -> Self {
|
||||||
FileState {
|
FileState {
|
||||||
file_type: FileType::Conflict { id },
|
file_type: FileType::Conflict,
|
||||||
mtime: mtime_from_metadata(metadata),
|
mtime: mtime_from_metadata(metadata),
|
||||||
size,
|
size,
|
||||||
}
|
}
|
||||||
|
@ -130,10 +130,7 @@ fn file_state_from_proto(proto: crate::protos::working_copy::FileState) -> FileS
|
||||||
crate::protos::working_copy::FileType::Normal => FileType::Normal { executable: false },
|
crate::protos::working_copy::FileType::Normal => FileType::Normal { executable: false },
|
||||||
crate::protos::working_copy::FileType::Executable => FileType::Normal { executable: true },
|
crate::protos::working_copy::FileType::Executable => FileType::Normal { executable: true },
|
||||||
crate::protos::working_copy::FileType::Symlink => FileType::Symlink,
|
crate::protos::working_copy::FileType::Symlink => FileType::Symlink,
|
||||||
crate::protos::working_copy::FileType::Conflict => {
|
crate::protos::working_copy::FileType::Conflict => FileType::Conflict,
|
||||||
let id = ConflictId::new(proto.conflict_id);
|
|
||||||
FileType::Conflict { id }
|
|
||||||
}
|
|
||||||
crate::protos::working_copy::FileType::GitSubmodule => FileType::GitSubmodule,
|
crate::protos::working_copy::FileType::GitSubmodule => FileType::GitSubmodule,
|
||||||
};
|
};
|
||||||
FileState {
|
FileState {
|
||||||
|
@ -149,10 +146,7 @@ fn file_state_to_proto(file_state: &FileState) -> crate::protos::working_copy::F
|
||||||
FileType::Normal { executable: false } => crate::protos::working_copy::FileType::Normal,
|
FileType::Normal { executable: false } => crate::protos::working_copy::FileType::Normal,
|
||||||
FileType::Normal { executable: true } => crate::protos::working_copy::FileType::Executable,
|
FileType::Normal { executable: true } => crate::protos::working_copy::FileType::Executable,
|
||||||
FileType::Symlink => crate::protos::working_copy::FileType::Symlink,
|
FileType::Symlink => crate::protos::working_copy::FileType::Symlink,
|
||||||
FileType::Conflict { id } => {
|
FileType::Conflict => crate::protos::working_copy::FileType::Conflict,
|
||||||
proto.conflict_id = id.to_bytes();
|
|
||||||
crate::protos::working_copy::FileType::Conflict
|
|
||||||
}
|
|
||||||
FileType::GitSubmodule => crate::protos::working_copy::FileType::GitSubmodule,
|
FileType::GitSubmodule => crate::protos::working_copy::FileType::GitSubmodule,
|
||||||
};
|
};
|
||||||
proto.file_type = file_type as i32;
|
proto.file_type = file_type as i32;
|
||||||
|
@ -494,6 +488,7 @@ impl TreeState {
|
||||||
base_ignores,
|
base_ignores,
|
||||||
)];
|
)];
|
||||||
|
|
||||||
|
let current_tree = self.store.get_tree(&RepoPath::root(), &self.tree_id)?;
|
||||||
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<_> = self
|
let mut deleted_files: HashSet<_> = self
|
||||||
.file_states
|
.file_states
|
||||||
|
@ -546,6 +541,7 @@ impl TreeState {
|
||||||
sub_path,
|
sub_path,
|
||||||
&entry,
|
&entry,
|
||||||
git_ignore.as_ref(),
|
git_ignore.as_ref(),
|
||||||
|
¤t_tree,
|
||||||
&mut tree_builder,
|
&mut tree_builder,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -586,6 +582,7 @@ impl TreeState {
|
||||||
repo_path: RepoPath,
|
repo_path: RepoPath,
|
||||||
dir_entry: &DirEntry,
|
dir_entry: &DirEntry,
|
||||||
git_ignore: &GitIgnoreFile,
|
git_ignore: &GitIgnoreFile,
|
||||||
|
current_tree: &Tree,
|
||||||
tree_builder: &mut TreeBuilder,
|
tree_builder: &mut TreeBuilder,
|
||||||
) -> Result<(), SnapshotError> {
|
) -> Result<(), SnapshotError> {
|
||||||
let maybe_current_file_state = self.file_states.get_mut(&repo_path);
|
let maybe_current_file_state = self.file_states.get_mut(&repo_path);
|
||||||
|
@ -638,7 +635,7 @@ impl TreeState {
|
||||||
// conflict and the contents are now a file, then we take interpret that as if
|
// conflict and the contents are now a file, then we take interpret that as if
|
||||||
// it is still a conflict.
|
// it is still a conflict.
|
||||||
if !clean
|
if !clean
|
||||||
&& matches!(current_file_state.file_type, FileType::Conflict { .. })
|
&& current_file_state.file_type == FileType::Conflict
|
||||||
&& matches!(new_file_state.file_type, FileType::Normal { .. })
|
&& matches!(new_file_state.file_type, FileType::Normal { .. })
|
||||||
{
|
{
|
||||||
// If the only change is that the type changed from conflict to regular file,
|
// If the only change is that the type changed from conflict to regular file,
|
||||||
|
@ -649,11 +646,14 @@ impl TreeState {
|
||||||
{
|
{
|
||||||
clean = true;
|
clean = true;
|
||||||
} else {
|
} else {
|
||||||
|
let current_tree_value = current_tree.path_value(&repo_path);
|
||||||
// If the file contained a conflict before and is now a normal file on disk
|
// If the file contained a conflict before and is now a normal file on disk
|
||||||
// (new_file_state cannot be a Conflict at this point), we try to parse
|
// (new_file_state cannot be a Conflict at this point), we try to parse
|
||||||
// any conflict markers in the file into a conflict.
|
// any conflict markers in the file into a conflict.
|
||||||
if let (FileType::Conflict { id }, FileType::Normal { executable: _ }) =
|
if let (
|
||||||
(¤t_file_state.file_type, &new_file_state.file_type)
|
Some(TreeValue::Conflict(conflict_id)),
|
||||||
|
FileType::Normal { executable: _ },
|
||||||
|
) = (¤t_tree_value, &new_file_state.file_type)
|
||||||
{
|
{
|
||||||
let mut file = File::open(&disk_path).unwrap();
|
let mut file = File::open(&disk_path).unwrap();
|
||||||
let mut content = vec![];
|
let mut content = vec![];
|
||||||
|
@ -661,14 +661,12 @@ impl TreeState {
|
||||||
if let Some(new_conflict_id) = update_conflict_from_content(
|
if let Some(new_conflict_id) = update_conflict_from_content(
|
||||||
self.store.as_ref(),
|
self.store.as_ref(),
|
||||||
&repo_path,
|
&repo_path,
|
||||||
id,
|
conflict_id,
|
||||||
&content,
|
&content,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
{
|
{
|
||||||
new_file_state.file_type = FileType::Conflict {
|
new_file_state.file_type = FileType::Conflict;
|
||||||
id: new_conflict_id.clone(),
|
|
||||||
};
|
|
||||||
*current_file_state = new_file_state;
|
*current_file_state = new_file_state;
|
||||||
tree_builder.set(repo_path, TreeValue::Conflict(new_conflict_id));
|
tree_builder.set(repo_path, TreeValue::Conflict(new_conflict_id));
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -801,7 +799,7 @@ impl TreeState {
|
||||||
let metadata = file
|
let metadata = file
|
||||||
.metadata()
|
.metadata()
|
||||||
.map_err(|err| CheckoutError::for_stat_error(err, disk_path))?;
|
.map_err(|err| CheckoutError::for_stat_error(err, disk_path))?;
|
||||||
Ok(FileState::for_conflict(id.clone(), size, &metadata))
|
Ok(FileState::for_conflict(size, &metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(windows, allow(unused_variables))]
|
#[cfg_attr(windows, allow(unused_variables))]
|
||||||
|
@ -982,7 +980,7 @@ impl TreeState {
|
||||||
let file_type = match after {
|
let file_type = match after {
|
||||||
TreeValue::File { id: _, executable } => FileType::Normal { executable },
|
TreeValue::File { id: _, executable } => FileType::Normal { executable },
|
||||||
TreeValue::Symlink(_id) => FileType::Symlink,
|
TreeValue::Symlink(_id) => FileType::Symlink,
|
||||||
TreeValue::Conflict(id) => FileType::Conflict { id },
|
TreeValue::Conflict(_id) => FileType::Conflict,
|
||||||
TreeValue::GitSubmodule(_id) => {
|
TreeValue::GitSubmodule(_id) => {
|
||||||
println!("ignoring git submodule at {path:?}");
|
println!("ignoring git submodule at {path:?}");
|
||||||
FileType::GitSubmodule
|
FileType::GitSubmodule
|
||||||
|
|
Loading…
Reference in a new issue