git: Fix remote URL parsing for partial clones (#63331)

Git adds the clone filter after `(fetch)` in `git remote -v` for partial
clones. Zed expected `(fetch)` at the end of the line, so it dropped
these remotes. This fixes that.

**Before:**

Only regular fetch entries were recognized:

```text
origin  https://github.com/zed-industries/zed.git (fetch)
```

**After:**

Fetch entries containing partial-clone filter metadata are also
recognized:
 
```text
origin  https://github.com/zed-industries/zed.git (fetch) [blob:none]
```

Release Notes:

- Fixed Zed failing to recognize Git remotes in partial clones.
This commit is contained in:
Smit Barmase authored and GitHub committed 2026-08-28 09:04:21 +00:00
1 parent c90f1fedc9
commit 4b3ef3e45a
1 file changed
+55 -9
+55 -9
View File
@@ -1379,6 +1379,19 @@ pub async fn get_git_committer(cx: &AsyncApp) -> GitCommitter {
.await
}
fn parse_remote_urls(stdout: &str) -> HashMap<String, String> {
let mut urls = HashMap::default();
for line in stdout.lines() {
if let Some((line, suffix)) = line.rsplit_once(" (fetch)")
&& (suffix.is_empty() || suffix.starts_with(" [") && suffix.ends_with(']'))
&& let Some((name, url)) = line.split_once(char::is_whitespace)
{
urls.insert(name.to_string(), url.trim_start().to_string());
}
}
urls
}
impl GitRepository for RealGitRepository {
fn path(&self) -> PathBuf {
self.git_dir.clone()
@@ -1735,17 +1748,11 @@ impl GitRepository for RealGitRepository {
let git = self.git_binary();
self.executor
.spawn(async move {
let mut urls = HashMap::default();
if let Ok(stdout) = git.run(&["remote", "-v"]).await {
for line in stdout.lines() {
if let Some(line) = line.strip_suffix(" (fetch)")
&& let Some((name, url)) = line.split_once(char::is_whitespace)
{
urls.insert(name.to_string(), url.trim_start().to_string());
}
}
parse_remote_urls(&stdout)
} else {
HashMap::default()
}
urls
})
.boxed()
}
@@ -6681,6 +6688,39 @@ mod tests {
}
}
#[test]
fn test_parse_remote_urls() {
let stdout = concat!(
"origin\thttps://github.com/zed-industries/zed.git (fetch) [blob:none]\n",
"origin\thttps://github.com/zed-industries/zed.git (push)\n",
"upstream\t/Users/user/My Projects/upstream.git (fetch)\n",
"upstream\t/Users/user/My Projects/upstream.git (push)\n",
"a\t/x (fetch) dir (fetch)\n",
"a\t/x (fetch) dir (push)\n",
"archive\t/tmp/remote [archive].git (fetch)\n",
"archive\t/tmp/remote [archive].git (push)\n",
);
let remote_urls = parse_remote_urls(stdout);
assert_eq!(remote_urls.len(), 4);
assert_eq!(
remote_urls.get("origin").map(String::as_str),
Some("https://github.com/zed-industries/zed.git")
);
assert_eq!(
remote_urls.get("upstream").map(String::as_str),
Some("/Users/user/My Projects/upstream.git")
);
assert_eq!(
remote_urls.get("a").map(String::as_str),
Some("/x (fetch) dir")
);
assert_eq!(
remote_urls.get("archive").map(String::as_str),
Some("/tmp/remote [archive].git")
);
}
#[gpui::test]
async fn test_remote_urls(cx: &mut TestAppContext) {
disable_git_global_config();
@@ -6717,6 +6757,12 @@ mod tests {
])
.await
.unwrap();
git.run(&["config", "remote.origin.promisor", "true"])
.await
.unwrap();
git.run(&["config", "remote.origin.partialclonefilter", "blob:none"])
.await
.unwrap();
let remote_urls = repo.remote_urls().await;
assert_eq!(remote_urls.len(), 2);