From c24f365b69fa5523559bb307febf7ea3e54afb20 Mon Sep 17 00:00:00 2001 From: Andrew Farkas <6060305+HactarCE@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:33:05 -0400 Subject: [PATCH] Fix Git permalinks not being URL-escaped (#39895) Closes #39875 Release Notes: - Fixed "open/copy permalink to line" paths not being URL-escaped Co-authored-by: Cole Miller --- Cargo.lock | 2 + crates/git/Cargo.toml | 2 + crates/git/src/hosting_provider.rs | 16 ++++- crates/git_hosting_providers/Cargo.toml | 1 + .../src/providers/bitbucket.rs | 19 ++---- .../src/providers/chromium.rs | 31 +++++----- .../src/providers/codeberg.rs | 31 +++++----- .../src/providers/gitee.rs | 31 +++++----- .../src/providers/github.rs | 60 ++++++++++++------- .../src/providers/gitlab.rs | 51 ++++++++-------- .../src/providers/sourcehut.rs | 41 ++++++------- crates/project/src/git_store.rs | 24 ++++---- 12 files changed, 169 insertions(+), 140 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 315c3db1e466ffe682067643c3a58ddd058f03db..1accdd9f0fc77352b1a055bd310a84d5194f8313 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6775,6 +6775,7 @@ dependencies = [ "futures 0.3.31", "git2", "gpui", + "itertools 0.14.0", "log", "parking_lot", "pretty_assertions", @@ -6791,6 +6792,7 @@ dependencies = [ "time", "unindent", "url", + "urlencoding", "uuid", "workspace-hack", "zed-collections", diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index 74656f1d4c86936b630cb8c1b05030f8d46ccb5c..e91b5c7c6480076481cd25b963a7d8012e67ee34 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -23,6 +23,7 @@ derive_more.workspace = true git2.workspace = true gpui.workspace = true http_client.workspace = true +itertools.workspace = true log.workspace = true parking_lot.workspace = true regex.workspace = true @@ -36,6 +37,7 @@ text.workspace = true thiserror.workspace = true time.workspace = true url.workspace = true +urlencoding.workspace = true util.workspace = true uuid.workspace = true futures.workspace = true diff --git a/crates/git/src/hosting_provider.rs b/crates/git/src/hosting_provider.rs index 51cdcda211a21459d057b80bc0d069f8ea5a77a9..225d4a3e2354fbd11e11b617ecdd9cb4202a63fe 100644 --- a/crates/git/src/hosting_provider.rs +++ b/crates/git/src/hosting_provider.rs @@ -5,9 +5,12 @@ use async_trait::async_trait; use derive_more::{Deref, DerefMut}; use gpui::{App, Global, SharedString}; use http_client::HttpClient; +use itertools::Itertools; use parking_lot::RwLock; use url::Url; +use crate::repository::RepoPath; + #[derive(Debug, PartialEq, Eq, Clone)] pub struct PullRequest { pub number: u32, @@ -55,10 +58,21 @@ pub struct BuildCommitPermalinkParams<'a> { pub struct BuildPermalinkParams<'a> { pub sha: &'a str, - pub path: &'a str, + /// URL-escaped path using unescaped `/` as the directory separator. + pub path: String, pub selection: Option>, } +impl<'a> BuildPermalinkParams<'a> { + pub fn new(sha: &'a str, path: &RepoPath, selection: Option>) -> Self { + Self { + sha, + path: path.components().map(urlencoding::encode).join("/"), + selection, + } + } +} + /// A Git hosting provider. #[async_trait] pub trait GitHostingProvider { diff --git a/crates/git_hosting_providers/Cargo.toml b/crates/git_hosting_providers/Cargo.toml index 64c7e701a4dbdcec405a6fb8b37eba8663a4d8db..dd189f64bf08dabafa18d1132bc36d36e6f5ab8e 100644 --- a/crates/git_hosting_providers/Cargo.toml +++ b/crates/git_hosting_providers/Cargo.toml @@ -30,3 +30,4 @@ workspace-hack.workspace = true indoc.workspace = true serde_json.workspace = true pretty_assertions.workspace = true +git = { workspace = true, features = ["test-support"] } diff --git a/crates/git_hosting_providers/src/providers/bitbucket.rs b/crates/git_hosting_providers/src/providers/bitbucket.rs index 26df7b567ae007553657a0075038c0762ce0063e..a6bb83b0f9d6025301db309c4d64ea39ade42076 100644 --- a/crates/git_hosting_providers/src/providers/bitbucket.rs +++ b/crates/git_hosting_providers/src/providers/bitbucket.rs @@ -126,6 +126,7 @@ impl GitHostingProvider for Bitbucket { #[cfg(test)] mod tests { + use git::repository::repo_path; use pretty_assertions::assert_eq; use super::*; @@ -182,11 +183,7 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "f00b4r", - path: "main.rs", - selection: None, - }, + BuildPermalinkParams::new("f00b4r", &repo_path("main.rs"), None), ); let expected_url = "https://bitbucket.org/zed-industries/zed/src/f00b4r/main.rs"; @@ -200,11 +197,7 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "f00b4r", - path: "main.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new("f00b4r", &repo_path("main.rs"), Some(6..6)), ); let expected_url = "https://bitbucket.org/zed-industries/zed/src/f00b4r/main.rs#lines-7"; @@ -218,11 +211,7 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "f00b4r", - path: "main.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new("f00b4r", &repo_path("main.rs"), Some(23..47)), ); let expected_url = diff --git a/crates/git_hosting_providers/src/providers/chromium.rs b/crates/git_hosting_providers/src/providers/chromium.rs index 5d940fb496be6fde2778272abe640987e3b2a4af..0826e31b309918fb0967f7b3019b53fe483837b9 100644 --- a/crates/git_hosting_providers/src/providers/chromium.rs +++ b/crates/git_hosting_providers/src/providers/chromium.rs @@ -191,6 +191,7 @@ impl GitHostingProvider for Chromium { #[cfg(test)] mod tests { + use git::repository::repo_path; use indoc::indoc; use pretty_assertions::assert_eq; @@ -218,11 +219,11 @@ mod tests { owner: Arc::from(""), repo: "chromium/src".into(), }, - BuildPermalinkParams { - sha: "fea5080b182fc92e3be0c01c5dece602fe70b588", - path: "ui/base/cursor/cursor.h", - selection: None, - }, + BuildPermalinkParams::new( + "fea5080b182fc92e3be0c01c5dece602fe70b588", + &repo_path("ui/base/cursor/cursor.h"), + None, + ), ); let expected_url = "https://chromium.googlesource.com/chromium/src/+/fea5080b182fc92e3be0c01c5dece602fe70b588/ui/base/cursor/cursor.h"; @@ -236,11 +237,11 @@ mod tests { owner: Arc::from(""), repo: "chromium/src".into(), }, - BuildPermalinkParams { - sha: "fea5080b182fc92e3be0c01c5dece602fe70b588", - path: "ui/base/cursor/cursor.h", - selection: Some(18..18), - }, + BuildPermalinkParams::new( + "fea5080b182fc92e3be0c01c5dece602fe70b588", + &repo_path("ui/base/cursor/cursor.h"), + Some(18..18), + ), ); let expected_url = "https://chromium.googlesource.com/chromium/src/+/fea5080b182fc92e3be0c01c5dece602fe70b588/ui/base/cursor/cursor.h#19"; @@ -254,11 +255,11 @@ mod tests { owner: Arc::from(""), repo: "chromium/src".into(), }, - BuildPermalinkParams { - sha: "fea5080b182fc92e3be0c01c5dece602fe70b588", - path: "ui/base/cursor/cursor.h", - selection: Some(18..30), - }, + BuildPermalinkParams::new( + "fea5080b182fc92e3be0c01c5dece602fe70b588", + &repo_path("ui/base/cursor/cursor.h"), + Some(18..30), + ), ); let expected_url = "https://chromium.googlesource.com/chromium/src/+/fea5080b182fc92e3be0c01c5dece602fe70b588/ui/base/cursor/cursor.h#19"; diff --git a/crates/git_hosting_providers/src/providers/codeberg.rs b/crates/git_hosting_providers/src/providers/codeberg.rs index 2cba745f4970de5bb22bdc84f7a76a28998c385d..4cd7dd2c04aa30973d6409300eadd9fbc980ddc4 100644 --- a/crates/git_hosting_providers/src/providers/codeberg.rs +++ b/crates/git_hosting_providers/src/providers/codeberg.rs @@ -204,6 +204,7 @@ impl GitHostingProvider for Codeberg { #[cfg(test)] mod tests { + use git::repository::repo_path; use pretty_assertions::assert_eq; use super::*; @@ -245,11 +246,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://codeberg.org/zed-industries/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs"; @@ -263,11 +264,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(6..6), + ), ); let expected_url = "https://codeberg.org/zed-industries/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L7"; @@ -281,11 +282,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(23..47), + ), ); let expected_url = "https://codeberg.org/zed-industries/zed/src/commit/faa6f979be417239b2e070dbbf6392b909224e0b/crates/editor/src/git/permalink.rs#L24-L48"; diff --git a/crates/git_hosting_providers/src/providers/gitee.rs b/crates/git_hosting_providers/src/providers/gitee.rs index 5090cd0d74d775af490976758f39fdabe062b43b..e2bcb6668240fa43120555f9b3c11a10dd1418d7 100644 --- a/crates/git_hosting_providers/src/providers/gitee.rs +++ b/crates/git_hosting_providers/src/providers/gitee.rs @@ -84,6 +84,7 @@ impl GitHostingProvider for Gitee { #[cfg(test)] mod tests { + use git::repository::repo_path; use pretty_assertions::assert_eq; use super::*; @@ -125,11 +126,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs"; @@ -143,11 +144,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", - path: "crates/editor/src/git/permalink.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new( + "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(6..6), + ), ); let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L7"; @@ -161,11 +162,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", - path: "crates/editor/src/git/permalink.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new( + "e5fe811d7ad0fc26934edd76f891d20bdc3bb194", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(23..47), + ), ); let expected_url = "https://gitee.com/zed-industries/zed/blob/e5fe811d7ad0fc26934edd76f891d20bdc3bb194/crates/editor/src/git/permalink.rs#L24-48"; diff --git a/crates/git_hosting_providers/src/providers/github.rs b/crates/git_hosting_providers/src/providers/github.rs index 28c8f7973b87d784de3497345c6db6ecb11eca1c..4f5c71830da4e5ce4112812d0737ebc878df7b76 100644 --- a/crates/git_hosting_providers/src/providers/github.rs +++ b/crates/git_hosting_providers/src/providers/github.rs @@ -259,6 +259,7 @@ impl GitHostingProvider for Github { #[cfg(test)] mod tests { + use git::repository::repo_path; use indoc::indoc; use pretty_assertions::assert_eq; @@ -400,11 +401,11 @@ mod tests { }; let permalink = Github::public_instance().build_permalink( remote, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs"; @@ -418,11 +419,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa", - path: "crates/zed/src/main.rs", - selection: None, - }, + BuildPermalinkParams::new( + "b2efec9824c45fcc90c9a7eb107a50d1772a60aa", + &repo_path("crates/zed/src/main.rs"), + None, + ), ); let expected_url = "https://github.com/zed-industries/zed/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs"; @@ -436,11 +437,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(6..6), + ), ); let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7"; @@ -454,11 +455,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(23..47), + ), ); let expected_url = "https://github.com/zed-industries/zed/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-L48"; @@ -506,4 +507,23 @@ mod tests { }; assert_eq!(github.extract_pull_request(&remote, message), None); } + + /// Regression test for issue #39875 + #[test] + fn test_git_permalink_url_escaping() { + let permalink = Github::public_instance().build_permalink( + ParsedGitRemote { + owner: "zed-industries".into(), + repo: "nonexistent".into(), + }, + BuildPermalinkParams::new( + "3ef1539900037dd3601be7149b2b39ed6d0ce3db", + &repo_path("app/blog/[slug]/page.tsx"), + Some(7..7), + ), + ); + + let expected_url = "https://github.com/zed-industries/nonexistent/blob/3ef1539900037dd3601be7149b2b39ed6d0ce3db/app/blog/%5Bslug%5D/page.tsx#L8"; + assert_eq!(permalink.to_string(), expected_url.to_string()) + } } diff --git a/crates/git_hosting_providers/src/providers/gitlab.rs b/crates/git_hosting_providers/src/providers/gitlab.rs index 969a2ff1d5951400a38946531c1da4527462169a..d18af7cccae058a7b9746f7dfe86beef8d6fda94 100644 --- a/crates/git_hosting_providers/src/providers/gitlab.rs +++ b/crates/git_hosting_providers/src/providers/gitlab.rs @@ -126,6 +126,7 @@ impl GitHostingProvider for Gitlab { #[cfg(test)] mod tests { + use git::repository::repo_path; use pretty_assertions::assert_eq; use super::*; @@ -209,11 +210,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs"; @@ -227,11 +228,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(6..6), + ), ); let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L7"; @@ -245,11 +246,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(23..47), + ), ); let expected_url = "https://gitlab.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs#L24-48"; @@ -266,11 +267,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://gitlab.some-enterprise.com/zed-industries/zed/-/blob/e6ebe7974deb6bb6cc0e2595c8ec31f0c71084b7/crates/editor/src/git/permalink.rs"; @@ -287,11 +288,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "b2efec9824c45fcc90c9a7eb107a50d1772a60aa", - path: "crates/zed/src/main.rs", - selection: None, - }, + BuildPermalinkParams::new( + "b2efec9824c45fcc90c9a7eb107a50d1772a60aa", + &repo_path("crates/zed/src/main.rs"), + None, + ), ); let expected_url = "https://gitlab-instance.big-co.com/zed-industries/zed/-/blob/b2efec9824c45fcc90c9a7eb107a50d1772a60aa/crates/zed/src/main.rs"; diff --git a/crates/git_hosting_providers/src/providers/sourcehut.rs b/crates/git_hosting_providers/src/providers/sourcehut.rs index c64f72193da4f5affde69b61e27452cb831e9501..55bff551846b5f69bad8ccaeaccf3ad55868303f 100644 --- a/crates/git_hosting_providers/src/providers/sourcehut.rs +++ b/crates/git_hosting_providers/src/providers/sourcehut.rs @@ -89,6 +89,7 @@ impl GitHostingProvider for Sourcehut { #[cfg(test)] mod tests { + use git::repository::repo_path; use pretty_assertions::assert_eq; use super::*; @@ -145,11 +146,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://git.sr.ht/~zed-industries/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs"; @@ -163,11 +164,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed.git".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: None, - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + None, + ), ); let expected_url = "https://git.sr.ht/~zed-industries/zed.git/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs"; @@ -181,11 +182,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: Some(6..6), - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(6..6), + ), ); let expected_url = "https://git.sr.ht/~zed-industries/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L7"; @@ -199,11 +200,11 @@ mod tests { owner: "zed-industries".into(), repo: "zed".into(), }, - BuildPermalinkParams { - sha: "faa6f979be417239b2e070dbbf6392b909224e0b", - path: "crates/editor/src/git/permalink.rs", - selection: Some(23..47), - }, + BuildPermalinkParams::new( + "faa6f979be417239b2e070dbbf6392b909224e0b", + &repo_path("crates/editor/src/git/permalink.rs"), + Some(23..47), + ), ); let expected_url = "https://git.sr.ht/~zed-industries/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L24-48"; diff --git a/crates/project/src/git_store.rs b/crates/project/src/git_store.rs index 4a31d5810a57bc25d388533e3f4905156e2b8522..40ed16183bf3d4d7182f4a13df97af4704720ef9 100644 --- a/crates/project/src/git_store.rs +++ b/crates/project/src/git_store.rs @@ -969,8 +969,6 @@ impl GitStore { get_permalink_in_rust_registry_src(provider_registry, file_path, selection) .context("no permalink available") }); - - // TODO remote case }; let buffer_id = buffer.read(cx).remote_id(); @@ -999,15 +997,9 @@ impl GitStore { parse_git_remote_url(provider_registry, &origin_url) .context("parsing Git remote URL")?; - let path = repo_path.as_unix_str(); - Ok(provider.build_permalink( remote, - BuildPermalinkParams { - sha: &sha, - path, - selection: Some(selection), - }, + BuildPermalinkParams::new(&sha, &repo_path, Some(selection)), )) } RepositoryState::Remote { project_id, client } => { @@ -4913,11 +4905,15 @@ fn get_permalink_in_rust_registry_src( let path = PathBuf::from(cargo_vcs_info.path_in_vcs).join(path.strip_prefix(dir).unwrap()); let permalink = provider.build_permalink( remote, - BuildPermalinkParams { - sha: &cargo_vcs_info.git.sha1, - path: &path.to_string_lossy(), - selection: Some(selection), - }, + BuildPermalinkParams::new( + &cargo_vcs_info.git.sha1, + &RepoPath( + RelPath::new(&path, PathStyle::local()) + .context("invalid path")? + .into_arc(), + ), + Some(selection), + ), ); Ok(permalink) }