sourcehut.rs

  1use url::Url;
  2
  3use git::{BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, ParsedGitRemote};
  4
  5pub struct Sourcehut;
  6
  7impl GitHostingProvider for Sourcehut {
  8    fn name(&self) -> String {
  9        "Gitee".to_string()
 10    }
 11
 12    fn base_url(&self) -> Url {
 13        Url::parse("https://git.sr.ht").unwrap()
 14    }
 15
 16    fn supports_avatars(&self) -> bool {
 17        false
 18    }
 19
 20    fn format_line_number(&self, line: u32) -> String {
 21        format!("L{line}")
 22    }
 23
 24    fn format_line_numbers(&self, start_line: u32, end_line: u32) -> String {
 25        format!("L{start_line}-{end_line}")
 26    }
 27
 28    fn parse_remote_url<'a>(&self, url: &'a str) -> Option<ParsedGitRemote<'a>> {
 29        if url.starts_with("git@git.sr.ht:") || url.starts_with("https://git.sr.ht/") {
 30            // sourcehut indicates a repo with '.git' suffix as a separate repo.
 31            // For example, "git@git.sr.ht:~username/repo" and "git@git.sr.ht:~username/repo.git"
 32            // are two distinct repositories.
 33            let repo_with_owner = url
 34                .trim_start_matches("git@git.sr.ht:~")
 35                .trim_start_matches("https://git.sr.ht/~");
 36
 37            let (owner, repo) = repo_with_owner.split_once('/')?;
 38
 39            return Some(ParsedGitRemote { owner, repo });
 40        }
 41
 42        None
 43    }
 44
 45    fn build_commit_permalink(
 46        &self,
 47        remote: &ParsedGitRemote,
 48        params: BuildCommitPermalinkParams,
 49    ) -> Url {
 50        let BuildCommitPermalinkParams { sha } = params;
 51        let ParsedGitRemote { owner, repo } = remote;
 52
 53        self.base_url()
 54            .join(&format!("~{owner}/{repo}/commit/{sha}"))
 55            .unwrap()
 56    }
 57
 58    fn build_permalink(&self, remote: ParsedGitRemote, params: BuildPermalinkParams) -> Url {
 59        let ParsedGitRemote { owner, repo } = remote;
 60        let BuildPermalinkParams {
 61            sha,
 62            path,
 63            selection,
 64        } = params;
 65
 66        let mut permalink = self
 67            .base_url()
 68            .join(&format!("~{owner}/{repo}/tree/{sha}/item/{path}"))
 69            .unwrap();
 70        permalink.set_fragment(
 71            selection
 72                .map(|selection| self.line_fragment(&selection))
 73                .as_deref(),
 74        );
 75        permalink
 76    }
 77}
 78
 79#[cfg(test)]
 80mod tests {
 81    use super::*;
 82
 83    #[test]
 84    fn test_build_sourcehut_permalink_from_ssh_url() {
 85        let remote = ParsedGitRemote {
 86            owner: "rajveermalviya",
 87            repo: "zed",
 88        };
 89        let permalink = Sourcehut.build_permalink(
 90            remote,
 91            BuildPermalinkParams {
 92                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
 93                path: "crates/editor/src/git/permalink.rs",
 94                selection: None,
 95            },
 96        );
 97
 98        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
 99        assert_eq!(permalink.to_string(), expected_url.to_string())
100    }
101
102    #[test]
103    fn test_build_sourcehut_permalink_from_ssh_url_with_git_prefix() {
104        let remote = ParsedGitRemote {
105            owner: "rajveermalviya",
106            repo: "zed.git",
107        };
108        let permalink = Sourcehut.build_permalink(
109            remote,
110            BuildPermalinkParams {
111                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
112                path: "crates/editor/src/git/permalink.rs",
113                selection: None,
114            },
115        );
116
117        let expected_url = "https://git.sr.ht/~rajveermalviya/zed.git/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs";
118        assert_eq!(permalink.to_string(), expected_url.to_string())
119    }
120
121    #[test]
122    fn test_build_sourcehut_permalink_from_ssh_url_single_line_selection() {
123        let remote = ParsedGitRemote {
124            owner: "rajveermalviya",
125            repo: "zed",
126        };
127        let permalink = Sourcehut.build_permalink(
128            remote,
129            BuildPermalinkParams {
130                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
131                path: "crates/editor/src/git/permalink.rs",
132                selection: Some(6..6),
133            },
134        );
135
136        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L7";
137        assert_eq!(permalink.to_string(), expected_url.to_string())
138    }
139
140    #[test]
141    fn test_build_sourcehut_permalink_from_ssh_url_multi_line_selection() {
142        let remote = ParsedGitRemote {
143            owner: "rajveermalviya",
144            repo: "zed",
145        };
146        let permalink = Sourcehut.build_permalink(
147            remote,
148            BuildPermalinkParams {
149                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
150                path: "crates/editor/src/git/permalink.rs",
151                selection: Some(23..47),
152            },
153        );
154
155        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/editor/src/git/permalink.rs#L24-48";
156        assert_eq!(permalink.to_string(), expected_url.to_string())
157    }
158
159    #[test]
160    fn test_build_sourcehut_permalink_from_https_url() {
161        let remote = ParsedGitRemote {
162            owner: "rajveermalviya",
163            repo: "zed",
164        };
165        let permalink = Sourcehut.build_permalink(
166            remote,
167            BuildPermalinkParams {
168                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
169                path: "crates/zed/src/main.rs",
170                selection: None,
171            },
172        );
173
174        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs";
175        assert_eq!(permalink.to_string(), expected_url.to_string())
176    }
177
178    #[test]
179    fn test_build_sourcehut_permalink_from_https_url_single_line_selection() {
180        let remote = ParsedGitRemote {
181            owner: "rajveermalviya",
182            repo: "zed",
183        };
184        let permalink = Sourcehut.build_permalink(
185            remote,
186            BuildPermalinkParams {
187                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
188                path: "crates/zed/src/main.rs",
189                selection: Some(6..6),
190            },
191        );
192
193        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L7";
194        assert_eq!(permalink.to_string(), expected_url.to_string())
195    }
196
197    #[test]
198    fn test_build_sourcehut_permalink_from_https_url_multi_line_selection() {
199        let remote = ParsedGitRemote {
200            owner: "rajveermalviya",
201            repo: "zed",
202        };
203        let permalink = Sourcehut.build_permalink(
204            remote,
205            BuildPermalinkParams {
206                sha: "faa6f979be417239b2e070dbbf6392b909224e0b",
207                path: "crates/zed/src/main.rs",
208                selection: Some(23..47),
209            },
210        );
211
212        let expected_url = "https://git.sr.ht/~rajveermalviya/zed/tree/faa6f979be417239b2e070dbbf6392b909224e0b/item/crates/zed/src/main.rs#L24-48";
213        assert_eq!(permalink.to_string(), expected_url.to_string())
214    }
215}