| 32 | 32 | | pub service: GitService, |
| 33 | 33 | | } |
| 34 | 34 | | |
| 35 | + | impl GitRequest { |
| 36 | + | /// The same request for the repository of the same name under |
| 37 | + | /// `namespace`: where a workspace alias leads. |
| 38 | + | pub fn under(&self, namespace: &str) -> GitRequest { |
| 39 | + | GitRequest { |
| 40 | + | path: RepoPath { |
| 41 | + | namespace: namespace.to_owned(), |
| 42 | + | name: self.path.name.clone(), |
| 43 | + | }, |
| 44 | + | endpoint: self.endpoint, |
| 45 | + | service: self.service, |
| 46 | + | } |
| 47 | + | } |
| 48 | + | } |
| 49 | + | |
| 35 | 50 | | /// Parses `/<namespace>/<name>[.git]/<endpoint>`, or returns `None` if the |
| 36 | 51 | | /// request is not git's. |
| 37 | 52 | | pub fn parse(url: &Url) -> Option<GitRequest> { |
| ⋯ |
| 216 | 231 | | Ok(current.and_then(|slug| with_namespace(url, &slug))) |
| 217 | 232 | | } |
| 218 | 233 | | |
| 234 | + | /// The request under the workspace its first segment is an alias of |
| 235 | + | /// (identity's aliases.rs: `g1t` for `flagon-io`), if it is one. Answered |
| 236 | + | /// in place rather than redirected: a push does not follow a redirect. |
| 237 | + | pub async fn aliased(git: &GitRequest, identity: &Fetcher) -> Result<Option<GitRequest>> { |
| 238 | + | let slug: Option<String> = g1t_kit::call( |
| 239 | + | identity, |
| 240 | + | "resolve_alias", |
| 241 | + | &g1t_contracts::identity::SlugArgs { |
| 242 | + | slug: git.path.namespace.clone(), |
| 243 | + | }, |
| 244 | + | ) |
| 245 | + | .await?; |
| 246 | + | Ok(slug.map(|slug| git.under(&slug))) |
| 247 | + | } |
| 248 | + | |
| 219 | 249 | | /// `url` with its repository, the first two path segments, replaced by |
| 220 | 250 | | /// `to`: where a request for a transferred repository's old path goes. |
| 221 | 251 | | /// Keeps whether the old address ended in `.git`. |
| ⋯ |
| 1050 | 1080 | | |
| 1051 | 1081 | | #[cfg(test)] |
| 1052 | 1082 | | mod tests { |
| 1053 | | − | use super::{Acknowledged, Pushed, RepoPath, Url, ZERO_ID, acknowledged, framed, negotiating, pack_bytes, pushed_branches, refusal, server_timing, transferred, with_head, with_namespace}; |
| 1083 | + | use super::{Acknowledged, GitService, Pushed, RepoPath, Url, ZERO_ID, acknowledged, framed, negotiating, pack_bytes, parse, pushed_branches, refusal, server_timing, transferred, with_head, with_namespace}; |
| 1054 | 1084 | | |
| 1055 | 1085 | | #[test] |
| 1056 | 1086 | | fn server_timing_names_each_step_and_the_total() { |
| ⋯ |
| 1159 | 1189 | | } |
| 1160 | 1190 | | |
| 1161 | 1191 | | #[test] |
| 1192 | + | fn an_alias_is_answered_as_its_workspaces_repository() { |
| 1193 | + | for (address, service) in [ |
| 1194 | + | ("https://g1t.sh/g1t/g1t.git/info/refs?service=git-upload-pack", GitService::UploadPack), |
| 1195 | + | ("https://g1t.sh/g1t/g1t.git/git-receive-pack", GitService::ReceivePack), |
| 1196 | + | ("https://g1t.sh/g1t/g1t/git-upload-pack", GitService::UploadPack), |
| 1197 | + | ] { |
| 1198 | + | let git = parse(&Url::parse(address).unwrap()).unwrap(); |
| 1199 | + | assert_eq!(git.path.namespace, "g1t", "{address}"); |
| 1200 | + | let canonical = git.under("flagon-io"); |
| 1201 | + | assert_eq!( |
| 1202 | + | canonical.path, |
| 1203 | + | RepoPath { |
| 1204 | + | namespace: "flagon-io".into(), |
| 1205 | + | name: "g1t".into(), |
| 1206 | + | }, |
| 1207 | + | "{address}" |
| 1208 | + | ); |
| 1209 | + | assert_eq!(canonical.service, service); |
| 1210 | + | assert_eq!(canonical.endpoint, git.endpoint); |
| 1211 | + | } |
| 1212 | + | } |
| 1213 | + | |
| 1214 | + | #[test] |
| 1162 | 1215 | | fn a_renamed_workspace_keeps_the_rest_of_the_address() { |
| 1163 | 1216 | | let url = worker::Url::parse( |
| 1164 | 1217 | | "https://g1t.sh/acme/rocket.git/info/refs?service=git-upload-pack", |