use crate::error::{GitowError, Result};
use crate::remote::ParsedRemote;
use super::context::{detect_provider, provider_context};
use super::types::{ProviderKind, RepoPage, provider_name};
use super::utils::encode_path_segment;
pub fn build_commit_url(remote: &ParsedRemote, sha: &str) -> String {
let kind = detect_provider(remote);
let context = provider_context(remote, kind);
match kind {
ProviderKind::GitLab => format!("{}/-/commit/{sha}", context.repo_url),
ProviderKind::BitbucketCloud | ProviderKind::BitbucketServer => {
format!("{}/commits/{sha}", context.repo_url)
}
_ => format!("{}/commit/{sha}", context.repo_url),
}
}
pub fn build_page_url(remote: &ParsedRemote, page: RepoPage, remote_ref: &str) -> Result<String> {
let kind = detect_provider(remote);
let context = provider_context(remote, kind);
let encoded_ref = encode_path_segment(remote_ref);
let url = match (kind, page) {
(ProviderKind::GitHub, RepoPage::PullRequests) => format!("{}/pulls", context.repo_url),
(ProviderKind::GitHub, RepoPage::Commits) => {
format!("{}/commits/{encoded_ref}", context.repo_url)
}
(ProviderKind::GitHub, RepoPage::Releases) => format!("{}/releases", context.repo_url),
(ProviderKind::GitLab, RepoPage::PullRequests) => {
format!("{}/-/merge_requests", context.repo_url)
}
(ProviderKind::GitLab, RepoPage::Commits) => {
format!("{}/-/commits/{encoded_ref}", context.repo_url)
}
(ProviderKind::GitLab, RepoPage::Releases) => {
format!("{}/-/releases", context.repo_url)
}
(ProviderKind::Gitea, RepoPage::PullRequests) => format!("{}/pulls", context.repo_url),
(ProviderKind::Gitea, RepoPage::Commits) => {
format!("{}/commits/branch/{encoded_ref}", context.repo_url)
}
(ProviderKind::Gitea, RepoPage::Releases) => format!("{}/releases", context.repo_url),
(ProviderKind::BitbucketCloud, RepoPage::PullRequests) => {
format!("{}/pull-requests/", context.repo_url)
}
(ProviderKind::BitbucketCloud, RepoPage::Commits) => {
format!("{}/commits/branch/{encoded_ref}", context.repo_url)
}
(ProviderKind::BitbucketServer, RepoPage::PullRequests) => {
format!("{}/pull-requests", context.repo_url)
}
(ProviderKind::BitbucketServer, RepoPage::Commits) => {
format!("{}/commits?until={encoded_ref}", context.repo_url)
}
(ProviderKind::AzureDevOps, RepoPage::PullRequests) => {
format!("{}/pullrequests", context.repo_url)
}
(ProviderKind::AzureDevOps, RepoPage::Commits) => {
format!("{}/commits?itemVersion=GB{encoded_ref}", context.repo_url)
}
(ProviderKind::AwsCodeCommit, RepoPage::PullRequests) => {
format!("{}/pull-requests", context.console_repo_url)
}
(ProviderKind::AwsCodeCommit, RepoPage::Commits) => {
format!("{}/commits", context.console_repo_url)
}
(ProviderKind::Gist, _) | (ProviderKind::Generic, _) | (_, RepoPage::Releases) => {
return Err(unsupported_page(page, kind));
}
};
Ok(url)
}
fn unsupported_page(page: RepoPage, provider: ProviderKind) -> GitowError {
GitowError::UnsupportedPage {
feature: match page {
RepoPage::PullRequests => "Pull requests".to_string(),
RepoPage::Commits => "Commits".to_string(),
RepoPage::Releases => "Releases".to_string(),
},
provider: provider_name(provider).to_string(),
}
}
#[cfg(test)]
mod tests {
use super::{RepoPage, build_page_url};
use crate::remote::ParsedRemote;
fn remote(domain: &str, path: &str) -> ParsedRemote {
ParsedRemote {
domain: domain.to_string(),
url_path: path.to_string(),
protocol: "https".to_string(),
forge: None,
config_base_url: format!("https://{domain}"),
}
}
#[test]
fn builds_gitlab_merge_requests_page() {
let url = build_page_url(
&remote("gitlab.com", "group/project"),
RepoPage::PullRequests,
"main",
)
.expect("page url");
assert_eq!(url, "https://gitlab.com/group/project/-/merge_requests");
}
#[test]
fn builds_codeberg_commits_page() {
let mut remote = remote("codeberg.org", "WhoSowSee/Soundly");
remote.forge = Some("gitea".to_string());
let url = build_page_url(&remote, RepoPage::Commits, "main").expect("page url");
assert_eq!(
url,
"https://codeberg.org/WhoSowSee/Soundly/commits/branch/main"
);
}
}