Skip Git tracking for invisible worktrees (#55760)
Release Notes: - N/A or Added/Fixed/Improved ...
This commit is contained in:
1 parent
2ae08181de
commit
f0bdd3c4af
3 files changed
+109
-52
No files matched your search
@@ -1495,13 +1495,6 @@ impl GitStore {
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if !worktree.read(cx).is_visible() {
|
||||
log::debug!(
|
||||
"not adding repositories for local worktree {:?} because it's not visible",
|
||||
worktree.read(cx).abs_path()
|
||||
);
|
||||
return;
|
||||
}
|
||||
self.update_repositories_from_worktree(
|
||||
*worktree_id,
|
||||
project_environment.clone(),
|
||||
|
||||
@@ -414,9 +414,13 @@ impl Worktree {
|
||||
None
|
||||
};
|
||||
|
||||
let root_repo_common_dir = discover_root_repo_common_dir(&abs_path, fs.as_ref())
|
||||
.await
|
||||
.map(SanitizedPath::from_arc);
|
||||
let root_repo_common_dir = if visible {
|
||||
discover_root_repo_common_dir(&abs_path, fs.as_ref())
|
||||
.await
|
||||
.map(SanitizedPath::from_arc)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(cx.new(move |cx: &mut Context<Worktree>| {
|
||||
let mut snapshot = LocalSnapshot {
|
||||
@@ -1147,6 +1151,7 @@ impl LocalWorktree {
|
||||
let next_entry_id = self.next_entry_id.clone();
|
||||
let fs = self.fs.clone();
|
||||
let scanning_enabled = self.scanning_enabled;
|
||||
let track_git_repositories = self.visible;
|
||||
let settings = self.settings.clone();
|
||||
let (scan_states_tx, mut scan_states_rx) = mpsc::unbounded();
|
||||
let background_scanner = cx.background_spawn({
|
||||
@@ -1185,6 +1190,7 @@ impl LocalWorktree {
|
||||
share_private_files,
|
||||
settings,
|
||||
watcher,
|
||||
track_git_repositories,
|
||||
is_single_file,
|
||||
};
|
||||
|
||||
@@ -3936,6 +3942,7 @@ struct BackgroundScanner {
|
||||
watcher: Arc<dyn Watcher>,
|
||||
settings: WorktreeSettings,
|
||||
share_private_files: bool,
|
||||
track_git_repositories: bool,
|
||||
/// Whether this is a single-file worktree (root is a file, not a directory).
|
||||
/// Used to determine if we should give up after repeated canonicalization failures.
|
||||
is_single_file: bool,
|
||||
@@ -3961,7 +3968,7 @@ impl BackgroundScanner {
|
||||
// If the worktree root does not contain a git repository, then find
|
||||
// the git repository in an ancestor directory. Find any gitignore files
|
||||
// in ancestor directories.
|
||||
let repo = if scanning_enabled {
|
||||
let repo = if scanning_enabled && self.track_git_repositories {
|
||||
let (ignores, exclude, repo) =
|
||||
discover_ancestor_git_repo(self.fs.clone(), &root_abs_path).await;
|
||||
let mut state = self.state.lock().await;
|
||||
@@ -3989,6 +3996,7 @@ impl BackgroundScanner {
|
||||
|
||||
let containing_git_repository = if let Some((ancestor_dot_git, work_directory)) = repo
|
||||
&& scanning_enabled
|
||||
&& self.track_git_repositories
|
||||
{
|
||||
maybe!(async {
|
||||
self.state
|
||||
@@ -4015,6 +4023,7 @@ impl BackgroundScanner {
|
||||
let mut global_gitignore_events = if let Some(global_gitignore_path) =
|
||||
&global_gitignore_file
|
||||
&& scanning_enabled
|
||||
&& self.track_git_repositories
|
||||
{
|
||||
let is_file = self.fs.is_file(&global_gitignore_path).await;
|
||||
self.state.lock().await.snapshot.global_gitignore = if is_file {
|
||||
@@ -4352,14 +4361,16 @@ impl BackgroundScanner {
|
||||
|
||||
let mut dot_git_paths = None;
|
||||
|
||||
for ancestor in abs_path.as_path().ancestors() {
|
||||
if is_dot_git(ancestor, self.fs.as_ref()).await {
|
||||
let path_in_git_dir = abs_path
|
||||
.as_path()
|
||||
.strip_prefix(ancestor)
|
||||
.expect("stripping off the ancestor");
|
||||
dot_git_paths = Some((ancestor.to_owned(), path_in_git_dir.to_owned()));
|
||||
break;
|
||||
if self.track_git_repositories {
|
||||
for ancestor in abs_path.as_path().ancestors() {
|
||||
if is_dot_git(ancestor, self.fs.as_ref()).await {
|
||||
let path_in_git_dir = abs_path
|
||||
.as_path()
|
||||
.strip_prefix(ancestor)
|
||||
.expect("stripping off the ancestor");
|
||||
dot_git_paths = Some((ancestor.to_owned(), path_in_git_dir.to_owned()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4384,9 +4395,10 @@ impl BackgroundScanner {
|
||||
}
|
||||
}
|
||||
|
||||
if abs_path
|
||||
.as_path()
|
||||
.ends_with(Path::new(DOT_GIT).join(REPO_EXCLUDE))
|
||||
if self.track_git_repositories
|
||||
&& abs_path
|
||||
.as_path()
|
||||
.ends_with(Path::new(DOT_GIT).join(REPO_EXCLUDE))
|
||||
{
|
||||
if let Some(repository) = snapshot.git_repositories.values().find(|repo| {
|
||||
repo.common_dir_abs_path.join(REPO_EXCLUDE) == abs_path.as_path()
|
||||
@@ -4437,7 +4449,9 @@ impl BackgroundScanner {
|
||||
continue;
|
||||
};
|
||||
|
||||
if abs_path.file_name() == Some(OsStr::new(GITIGNORE)) {
|
||||
if self.track_git_repositories
|
||||
&& abs_path.file_name() == Some(OsStr::new(GITIGNORE))
|
||||
{
|
||||
for (_, repo) in snapshot
|
||||
.git_repositories
|
||||
.iter()
|
||||
@@ -4774,29 +4788,33 @@ impl BackgroundScanner {
|
||||
continue;
|
||||
};
|
||||
|
||||
if child_name == DOT_GIT {
|
||||
let mut state = self.state.lock().await;
|
||||
state
|
||||
.insert_git_repository(
|
||||
child_path.clone(),
|
||||
self.fs.as_ref(),
|
||||
self.watcher.as_ref(),
|
||||
)
|
||||
.await;
|
||||
} else if child_name == GITIGNORE {
|
||||
match build_gitignore(&child_abs_path, self.fs.as_ref()).await {
|
||||
Ok(ignore) => {
|
||||
let ignore = Arc::new(ignore);
|
||||
ignore_stack = ignore_stack
|
||||
.append(IgnoreKind::Gitignore(job.abs_path.clone()), ignore.clone());
|
||||
new_ignore = Some(ignore);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"error loading .gitignore file {:?} - {:?}",
|
||||
child_name,
|
||||
error
|
||||
);
|
||||
if self.track_git_repositories {
|
||||
if child_name == DOT_GIT {
|
||||
let mut state = self.state.lock().await;
|
||||
state
|
||||
.insert_git_repository(
|
||||
child_path.clone(),
|
||||
self.fs.as_ref(),
|
||||
self.watcher.as_ref(),
|
||||
)
|
||||
.await;
|
||||
} else if child_name == GITIGNORE {
|
||||
match build_gitignore(&child_abs_path, self.fs.as_ref()).await {
|
||||
Ok(ignore) => {
|
||||
let ignore = Arc::new(ignore);
|
||||
ignore_stack = ignore_stack.append(
|
||||
IgnoreKind::Gitignore(job.abs_path.clone()),
|
||||
ignore.clone(),
|
||||
);
|
||||
new_ignore = Some(ignore);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"error loading .gitignore file {:?} - {:?}",
|
||||
child_name,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5004,11 +5022,12 @@ impl BackgroundScanner {
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut new_ancestor_repo = if relative_paths.iter().any(|path| path.is_empty()) {
|
||||
Some(discover_ancestor_git_repo(self.fs.clone(), &root_abs_path).await)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut new_ancestor_repo =
|
||||
if self.track_git_repositories && relative_paths.iter().any(|path| path.is_empty()) {
|
||||
Some(discover_ancestor_git_repo(self.fs.clone(), &root_abs_path).await)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut state = self.state.lock().await;
|
||||
let doing_recursive_update = scan_queue_tx.is_some();
|
||||
@@ -5054,7 +5073,8 @@ impl BackgroundScanner {
|
||||
|
||||
if let (Some(scan_queue_tx), true) = (&scan_queue_tx, is_dir) {
|
||||
if state.should_scan_directory(&fs_entry)
|
||||
|| (fs_entry.path.is_empty()
|
||||
|| (self.track_git_repositories
|
||||
&& fs_entry.path.is_empty()
|
||||
&& abs_path.file_name() == Some(OsStr::new(DOT_GIT)))
|
||||
{
|
||||
state
|
||||
|
||||
@@ -3283,6 +3283,50 @@ async fn test_root_repo_common_dir(executor: BackgroundExecutor, cx: &mut TestAp
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_invisible_worktree_does_not_track_ancestor_git_repository(
|
||||
executor: BackgroundExecutor,
|
||||
cx: &mut TestAppContext,
|
||||
) {
|
||||
init_test(cx);
|
||||
|
||||
let fs = FakeFs::new(executor);
|
||||
fs.insert_tree(
|
||||
path!("/repo"),
|
||||
json!({
|
||||
".git": {},
|
||||
"project": {
|
||||
"file.txt": "content",
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await;
|
||||
|
||||
let worktree = Worktree::local(
|
||||
path!("/repo/project").as_ref(),
|
||||
false,
|
||||
fs.clone(),
|
||||
Arc::default(),
|
||||
true,
|
||||
WorktreeId::from_proto(0),
|
||||
&mut cx.to_async(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
worktree
|
||||
.update(cx, |worktree, _| {
|
||||
worktree.as_local().unwrap().scan_complete()
|
||||
})
|
||||
.await;
|
||||
cx.run_until_parked();
|
||||
|
||||
worktree.read_with(cx, |worktree, _| {
|
||||
let local_worktree = worktree.as_local().unwrap();
|
||||
assert!(local_worktree.repositories().is_empty());
|
||||
assert_eq!(local_worktree.root_repo_common_dir(), None);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_linked_worktree_git_file_event_does_not_panic(
|
||||
executor: BackgroundExecutor,
|
||||
|
||||
Reference in new issue
Block a user