Merge pull request 'Add visibleParentResolver and optimize Git file status lookup' (#42) from performance into main
This commit was merged in pull request #42.
This commit is contained in:
+35
-11
@@ -5756,6 +5756,7 @@ fn repository_files_with_status(
|
||||
repo: &Path,
|
||||
status: &GitStatus,
|
||||
) -> Result<Vec<GitRepositoryFile>, String> {
|
||||
let status_index = file_status_index(&status.files);
|
||||
let mut files = BTreeMap::<String, GitRepositoryFile>::new();
|
||||
|
||||
let tracked_output = run_git(repo, ["ls-files", "-z", "-t", "--cached", "--deleted"])?;
|
||||
@@ -5772,7 +5773,7 @@ fn repository_files_with_status(
|
||||
continue;
|
||||
}
|
||||
let path = String::from_utf8_lossy(path_bytes).into_owned();
|
||||
let status = status_for_file(&status.files, &path);
|
||||
let status = status_index.get(path.as_str()).copied().flatten();
|
||||
files.insert(
|
||||
path.clone(),
|
||||
GitRepositoryFile {
|
||||
@@ -5785,7 +5786,7 @@ fn repository_files_with_status(
|
||||
|
||||
let untracked_output = run_git(repo, ["ls-files", "-z", "--others", "--exclude-standard"])?;
|
||||
for path in parse_nul_paths(&untracked_output) {
|
||||
let status = status_for_file(&status.files, &path).or(Some(FileStatusKind::Untracked));
|
||||
let status = status_index.get(path.as_str()).copied().flatten().or(Some(FileStatusKind::Untracked));
|
||||
files.insert(
|
||||
path.clone(),
|
||||
GitRepositoryFile {
|
||||
@@ -6151,16 +6152,23 @@ fn parse_nul_paths(output: &[u8]) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn status_for_file(statuses: &[GitFileStatus], path: &str) -> Option<FileStatusKind> {
|
||||
let status = find_status(statuses, path)?;
|
||||
|
||||
if matches!(status.staged, Some(FileStatusKind::Conflicted))
|
||||
|| matches!(status.unstaged, Some(FileStatusKind::Conflicted))
|
||||
{
|
||||
return Some(FileStatusKind::Conflicted);
|
||||
fn file_status_index(statuses: &[GitFileStatus]) -> std::collections::HashMap<&str, Option<FileStatusKind>> {
|
||||
let mut index = std::collections::HashMap::with_capacity(statuses.len());
|
||||
for status in statuses {
|
||||
let kind = if matches!(status.staged, Some(FileStatusKind::Conflicted))
|
||||
|| matches!(status.unstaged, Some(FileStatusKind::Conflicted))
|
||||
{
|
||||
Some(FileStatusKind::Conflicted)
|
||||
} else {
|
||||
status.unstaged.or(status.staged)
|
||||
};
|
||||
// Match find_status: the first record wins, including rename aliases.
|
||||
index.entry(status.path.as_str()).or_insert(kind);
|
||||
if let Some(old_path) = status.old_path.as_deref() {
|
||||
index.entry(old_path).or_insert(kind);
|
||||
}
|
||||
}
|
||||
|
||||
status.unstaged.or(status.staged)
|
||||
index
|
||||
}
|
||||
|
||||
fn has_unresolved_conflicts(status: &GitStatus) -> bool {
|
||||
@@ -10115,6 +10123,22 @@ mod tests {
|
||||
assert_eq!(docs.replace("\r\n", "\n"), "docs2\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_status_index_preserves_rename_conflict_and_first_match_semantics() {
|
||||
let statuses = vec![
|
||||
GitFileStatus { path: "new".into(), old_path: Some("old".into()), staged: Some(FileStatusKind::Renamed), unstaged: Some(FileStatusKind::Modified) },
|
||||
GitFileStatus { path: "old".into(), old_path: None, staged: Some(FileStatusKind::Added), unstaged: None },
|
||||
GitFileStatus { path: "conflict".into(), old_path: None, staged: Some(FileStatusKind::Conflicted), unstaged: Some(FileStatusKind::Modified) },
|
||||
GitFileStatus { path: "empty".into(), old_path: None, staged: None, unstaged: None },
|
||||
];
|
||||
let index = file_status_index(&statuses);
|
||||
assert_eq!(index.get("new"), Some(&Some(FileStatusKind::Modified)));
|
||||
assert_eq!(index.get("old"), Some(&Some(FileStatusKind::Modified)));
|
||||
assert_eq!(index.get("conflict"), Some(&Some(FileStatusKind::Conflicted)));
|
||||
assert_eq!(index.get("empty"), Some(&None));
|
||||
assert_eq!(index.get("missing"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repository_files_include_tracked_deleted_and_untracked_entries() {
|
||||
let repo = init_temp_repo("repository_files");
|
||||
|
||||
Reference in New Issue
Block a user