Skip to content

Commit

Permalink
git: Support git repos with .git folder above project root (#11550)
Browse files Browse the repository at this point in the history
TODOs:

- [x] Add assertions to the test to ensure that the git status is
propagated
- [x] Get collaboration working
- [x] Test opening a git repository inside another git repository
- [x] Test opening the sub-folder of a repository that itself contains
another git repository in a subfolder

Fixes:
- Fixes #10154
- Fixes #8418
- Fixes #8275
- Fixes #7816
- Fixes #6762
- Fixes #4419
- Fixes #4672
- Fixes #5161

Release Notes:

- Added support for opening subfolders of git repositories and treating
them as part of a repository (show git status in project panel, show git
diff in gutter, git blame works, ...)
([#4672](#4672)).

Demo video:


https://github.com/zed-industries/zed/assets/1185253/afc1cdc3-372c-404e-99ea-15708589251c
  • Loading branch information
mrnugget authored May 14, 2024
1 parent 9f0a202 commit db89353
Show file tree
Hide file tree
Showing 3 changed files with 331 additions and 72 deletions.
43 changes: 19 additions & 24 deletions crates/project/src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7536,13 +7536,12 @@ impl Project {
.flatten()
.chain(current_buffers)
.filter_map(|(buffer, path, abs_path)| {
let (work_directory, repo) =
snapshot.repository_and_work_directory_for_path(&path)?;
let repo_entry = snapshot.get_local_repo(&repo)?;
Some((buffer, path, abs_path, work_directory, repo_entry))
let (repo_entry, local_repo_entry) = snapshot.repo_for_path(&path)?;
Some((buffer, path, abs_path, repo_entry, local_repo_entry))
})
.map(|(buffer, path, abs_path, work_directory, repo_entry)| {
.map(|(buffer, path, abs_path, repo, local_repo_entry)| {
let fs = fs.clone();
let snapshot = snapshot.clone();
async move {
let abs_path_metadata = fs
.metadata(&abs_path)
Expand All @@ -7557,8 +7556,11 @@ impl Project {
{
None
} else {
let relative_path = path.strip_prefix(&work_directory).ok()?;
repo_entry.repo().lock().load_index_text(relative_path)
let relative_path = repo.relativize(&snapshot, &path).ok()?;
local_repo_entry
.repo()
.lock()
.load_index_text(&relative_path)
};
Some((buffer, base_text))
}
Expand Down Expand Up @@ -7931,24 +7933,17 @@ impl Project {
.context("worktree was not local")?
.snapshot();

let (work_directory, repo) = match worktree
.repository_and_work_directory_for_path(&buffer_project_path.path)
{
Some(work_dir_repo) => work_dir_repo,
None => anyhow::bail!(NoRepositoryError {}),
};

let repo_entry = match worktree.get_local_repo(&repo) {
Some(repo_entry) => repo_entry,
None => anyhow::bail!(NoRepositoryError {}),
};
let (repo_entry, local_repo_entry) =
match worktree.repo_for_path(&buffer_project_path.path) {
Some(repo_for_path) => repo_for_path,
None => anyhow::bail!(NoRepositoryError {}),
};

let repo = repo_entry.repo().clone();
let relative_path = repo_entry
.relativize(&worktree, &buffer_project_path.path)
.context("failed to relativize buffer path")?;

let relative_path = buffer_project_path
.path
.strip_prefix(&work_directory)?
.to_path_buf();
let repo = local_repo_entry.repo().clone();

let content = match version {
Some(version) => buffer.rope_for_version(&version).clone(),
Expand All @@ -7962,7 +7957,7 @@ impl Project {
let (repo, relative_path, content) = blame_params?;
let lock = repo.lock();
lock.blame(&relative_path, content)
.with_context(|| format!("Failed to blame {relative_path:?}"))
.with_context(|| format!("Failed to blame {:?}", relative_path.0))
})
} else {
let project_id = self.remote_id();
Expand Down
Loading

0 comments on commit db89353

Please sign in to comment.