@@ -116,12 +116,8 @@ impl OpenRequest {
this.kind = Some(OpenRequestKind::Setting {
setting_path: Some(setting_path.to_string()),
});
- } else if let Some(repo_url) = url.strip_prefix("zed://git/clone/") {
- this.kind = Some(OpenRequestKind::GitClone {
- repo_url: urlencoding::decode(repo_url)
- .unwrap_or_else(|_| repo_url.into())
- .to_string(),
- });
+ } else if let Some(clone_path) = url.strip_prefix("zed://git/clone") {
+ this.parse_git_clone_url(clone_path)?
} else if let Some(commit_path) = url.strip_prefix("zed://git/commit/") {
this.parse_git_commit_url(commit_path)?
} else if url.starts_with("ssh://") {
@@ -152,6 +148,25 @@ impl OpenRequest {
}
}
+ fn parse_git_clone_url(&mut self, clone_path: &str) -> Result<()> {
+ // Format: /?repo=<url> or ?repo=<url>
+ let clone_path = clone_path.strip_prefix('/').unwrap_or(clone_path);
+
+ let query = clone_path
+ .strip_prefix('?')
+ .context("invalid git clone url: missing query string")?;
+
+ let repo_url = url::form_urlencoded::parse(query.as_bytes())
+ .find_map(|(key, value)| (key == "repo").then_some(value))
+ .filter(|s| !s.is_empty())
+ .context("invalid git clone url: missing repo query parameter")?
+ .to_string();
+
+ self.kind = Some(OpenRequestKind::GitClone { repo_url });
+
+ Ok(())
+ }
+
fn parse_git_commit_url(&mut self, commit_path: &str) -> Result<()> {
// Format: <sha>?repo=<path>
let (sha, query) = commit_path
@@ -1104,7 +1119,34 @@ mod tests {
let request = cx.update(|cx| {
OpenRequest::parse(
RawOpenRequest {
- urls: vec!["zed://git/clone/https://github.com/zed-industries/zed.git".into()],
+ urls: vec![
+ "zed://git/clone/?repo=https://github.com/zed-industries/zed.git".into(),
+ ],
+ ..Default::default()
+ },
+ cx,
+ )
+ .unwrap()
+ });
+
+ match request.kind {
+ Some(OpenRequestKind::GitClone { repo_url }) => {
+ assert_eq!(repo_url, "https://github.com/zed-industries/zed.git");
+ }
+ _ => panic!("Expected GitClone kind"),
+ }
+ }
+
+ #[gpui::test]
+ fn test_parse_git_clone_url_without_slash(cx: &mut TestAppContext) {
+ let _app_state = init_test(cx);
+
+ let request = cx.update(|cx| {
+ OpenRequest::parse(
+ RawOpenRequest {
+ urls: vec![
+ "zed://git/clone?repo=https://github.com/zed-industries/zed.git".into(),
+ ],
..Default::default()
},
cx,
@@ -1128,7 +1170,7 @@ mod tests {
OpenRequest::parse(
RawOpenRequest {
urls: vec![
- "zed://git/clone/https%3A%2F%2Fgithub.com%2Fzed-industries%2Fzed.git"
+ "zed://git/clone/?repo=https%3A%2F%2Fgithub.com%2Fzed-industries%2Fzed.git"
.into(),
],
..Default::default()