mirror of
https://github.com/deps-rs/deps.rs.git
synced 2024-11-24 11:06:31 +00:00
Support for self-hosted Gitea (#164)
deps.rs is now available for self-hosted Gitea at `/repo/gitea/<DOMAIN>/owner/repo`, e. g. `/repo/gitea/git.example.org/deps-rs/deps.rs`, `/repo/gitea/git.example.org:1234/deps-rs/deps.rs`, `/repo/gitea/http://unsafe-gitea.org/deps-rs/deps.rs`. This _should_ also include support for Gitea hosted in subdirectories, e. g. `www.example.org/gitea`, though I haven't tested this yet. If no protocol (`https://`/`http://`) is specified, `https://` is automatically added to the beginning of the gitea server's URL. However I could also change this to only accept https. Another option might be the use of URL-encoding. I am open for feedback, feel free to suggest changes. Implementation notes: - The Router now matches `/repo/*site/:qual/:name` instead of `/repo/:site/:qual/:name` to allow for an arbitrary number of `/`s before qual and name. - `RepoSite` now has a new variant `Gitea(GiteaDomain)`. - `RepoSite` no longer implements `Copy`. However this should not be problematic because `Copy`ing was only used for `to_base_uri`, `to_usercontent_base_uri` and `to_usercontent_repo_suffix` which now accept `&self` references. - `RepoSite` no longer implements `AsRef` and now uses `Display` instead. - updated test `correct_raw_url_generation` - updated readme Related to #84, #141
This commit is contained in:
parent
a991fa8eb1
commit
ba7647dcff
5 changed files with 88 additions and 28 deletions
|
@ -13,7 +13,7 @@ We currently support projects and crates hosted on crates.io, Github, Gitlab, Bi
|
||||||
To analyze the state of your dependencies you can use the following URLs:
|
To analyze the state of your dependencies you can use the following URLs:
|
||||||
|
|
||||||
- for projects on crates.io: `https://deps.rs/crate/<NAME>`
|
- for projects on crates.io: `https://deps.rs/crate/<NAME>`
|
||||||
- for projects on Github, Gitlab, Bitbucket, SourceHut, or Codeberg: `https://deps.rs/repo/<HOSTER>/<USER>/<REPO>` (where `<HOSTER>` is either `github`, `gitlab`, `bitbucket`, `sourcehut`, or `codeberg`)
|
- for projects on Github, Gitlab, Bitbucket, SourceHut, Codeberg, or Gitea: `https://deps.rs/repo/<HOSTER>/<USER>/<REPO>` (where `<HOSTER>` is either `github`, `gitlab`, `bitbucket`, `sourcehut`, `codeberg`, or `gitea/<DOMAIN>`)
|
||||||
|
|
||||||
## Badges
|
## Badges
|
||||||
|
|
||||||
|
|
|
@ -42,49 +42,52 @@ impl fmt::Display for RepoPath {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"{} => {}/{}",
|
"{} => {}/{}",
|
||||||
self.site.as_ref(),
|
self.site.to_string(),
|
||||||
self.qual.as_ref(),
|
self.qual.as_ref(),
|
||||||
self.name.as_ref()
|
self.name.as_ref()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
pub enum RepoSite {
|
pub enum RepoSite {
|
||||||
Github,
|
Github,
|
||||||
Gitlab,
|
Gitlab,
|
||||||
Bitbucket,
|
Bitbucket,
|
||||||
Sourcehut,
|
Sourcehut,
|
||||||
Codeberg,
|
Codeberg,
|
||||||
|
Gitea(GiteaDomain),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepoSite {
|
impl RepoSite {
|
||||||
pub fn to_base_uri(self) -> &'static str {
|
pub fn to_base_uri(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
RepoSite::Github => "https://github.com",
|
RepoSite::Github => "https://github.com",
|
||||||
RepoSite::Gitlab => "https://gitlab.com",
|
RepoSite::Gitlab => "https://gitlab.com",
|
||||||
RepoSite::Bitbucket => "https://bitbucket.org",
|
RepoSite::Bitbucket => "https://bitbucket.org",
|
||||||
RepoSite::Sourcehut => "https://git.sr.ht",
|
RepoSite::Sourcehut => "https://git.sr.ht",
|
||||||
RepoSite::Codeberg => "https://codeberg.org",
|
RepoSite::Codeberg => "https://codeberg.org",
|
||||||
|
RepoSite::Gitea(domain) => domain.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_usercontent_base_uri(self) -> &'static str {
|
pub fn to_usercontent_base_uri(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
RepoSite::Github => "https://raw.githubusercontent.com",
|
RepoSite::Github => "https://raw.githubusercontent.com",
|
||||||
RepoSite::Gitlab => "https://gitlab.com",
|
RepoSite::Gitlab => "https://gitlab.com",
|
||||||
RepoSite::Bitbucket => "https://bitbucket.org",
|
RepoSite::Bitbucket => "https://bitbucket.org",
|
||||||
RepoSite::Sourcehut => "https://git.sr.ht",
|
RepoSite::Sourcehut => "https://git.sr.ht",
|
||||||
RepoSite::Codeberg => "https://codeberg.org",
|
RepoSite::Codeberg => "https://codeberg.org",
|
||||||
|
RepoSite::Gitea(domain) => domain.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_usercontent_repo_suffix(self) -> &'static str {
|
pub fn to_usercontent_repo_suffix(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
RepoSite::Github => "HEAD",
|
RepoSite::Github => "HEAD",
|
||||||
RepoSite::Gitlab | RepoSite::Bitbucket => "raw/HEAD",
|
RepoSite::Gitlab | RepoSite::Bitbucket => "raw/HEAD",
|
||||||
RepoSite::Sourcehut => "blob/HEAD",
|
RepoSite::Sourcehut => "blob/HEAD",
|
||||||
RepoSite::Codeberg => "raw",
|
RepoSite::Codeberg | RepoSite::Gitea(_) => "raw",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +96,12 @@ impl FromStr for RepoSite {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(input: &str) -> Result<RepoSite, Error> {
|
fn from_str(input: &str) -> Result<RepoSite, Error> {
|
||||||
|
if let Some((site, domain)) = input.split_once("/") {
|
||||||
|
match site {
|
||||||
|
"gitea" => Ok(RepoSite::Gitea(domain.parse()?)),
|
||||||
|
_ => Err(anyhow!("unknown repo site identifier")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
match input {
|
match input {
|
||||||
"github" => Ok(RepoSite::Github),
|
"github" => Ok(RepoSite::Github),
|
||||||
"gitlab" => Ok(RepoSite::Gitlab),
|
"gitlab" => Ok(RepoSite::Gitlab),
|
||||||
|
@ -103,15 +112,48 @@ impl FromStr for RepoSite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AsRef<str> for RepoSite {
|
impl fmt::Display for RepoSite {
|
||||||
fn as_ref(&self) -> &str {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
RepoSite::Github => "github",
|
RepoSite::Github => write!(f, "github"),
|
||||||
RepoSite::Gitlab => "gitlab",
|
RepoSite::Gitlab => write!(f, "gitlab"),
|
||||||
RepoSite::Bitbucket => "bitbucket",
|
RepoSite::Bitbucket => write!(f, "bitbucket"),
|
||||||
RepoSite::Sourcehut => "sourcehut",
|
RepoSite::Sourcehut => write!(f, "sourcehut"),
|
||||||
RepoSite::Codeberg => "codeberg",
|
RepoSite::Codeberg => write!(f, "codeberg"),
|
||||||
|
RepoSite::Gitea(s) => write!(f, "gitea/{s}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
|
||||||
|
pub struct GiteaDomain(String);
|
||||||
|
|
||||||
|
impl FromStr for GiteaDomain {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(input: &str) -> Result<GiteaDomain, Error> {
|
||||||
|
if input.starts_with("https://") || input.starts_with("http://") {
|
||||||
|
Ok(GiteaDomain(input.to_string()))
|
||||||
|
} else {
|
||||||
|
Ok(GiteaDomain(format!("https://{input}")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for GiteaDomain {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.0.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for GiteaDomain {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
if self.0.starts_with("https://") {
|
||||||
|
f.write_str(&self.0["https://".len()..])
|
||||||
|
} else {
|
||||||
|
self.0.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,5 +257,21 @@ mod tests {
|
||||||
let exp = format!("https://codeberg.org/deps-rs/deps.rs/raw/{}", expected);
|
let exp = format!("https://codeberg.org/deps-rs/deps.rs/raw/{}", expected);
|
||||||
assert_eq!(out.to_string(), exp);
|
assert_eq!(out.to_string(), exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (input, expected) in &paths {
|
||||||
|
let repo = RepoPath::from_parts("gitea/gitea.com", "deps-rs", "deps.rs").unwrap();
|
||||||
|
let out = repo.to_usercontent_file_url(RelativePath::new(input));
|
||||||
|
|
||||||
|
let exp = format!("https://gitea.com/deps-rs/deps.rs/raw/{}", expected);
|
||||||
|
assert_eq!(out.to_string(), exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (input, expected) in &paths {
|
||||||
|
let repo = RepoPath::from_parts("gitea/example.com/git", "deps-rs", "deps.rs").unwrap();
|
||||||
|
let out = repo.to_usercontent_file_url(RelativePath::new(input));
|
||||||
|
|
||||||
|
let exp = format!("https://example.com/git/deps-rs/deps.rs/raw/{}", expected);
|
||||||
|
assert_eq!(out.to_string(), exp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,11 +58,11 @@ impl App {
|
||||||
router.add("/static/logo.svg", Route::Static(StaticFile::FaviconPng));
|
router.add("/static/logo.svg", Route::Static(StaticFile::FaviconPng));
|
||||||
|
|
||||||
router.add(
|
router.add(
|
||||||
"/repo/:site/:qual/:name",
|
"/repo/*site/:qual/:name",
|
||||||
Route::RepoStatus(StatusFormat::Html),
|
Route::RepoStatus(StatusFormat::Html),
|
||||||
);
|
);
|
||||||
router.add(
|
router.add(
|
||||||
"/repo/:site/:qual/:name/status.svg",
|
"/repo/*site/:qual/:name/status.svg",
|
||||||
Route::RepoStatus(StatusFormat::Svg),
|
Route::RepoStatus(StatusFormat::Svg),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,12 @@ fn popular_table(popular_repos: Vec<Repository>, popular_crates: Vec<CratePath>)
|
||||||
@for repo in popular_repos.into_iter().take(10) {
|
@for repo in popular_repos.into_iter().take(10) {
|
||||||
tr {
|
tr {
|
||||||
td {
|
td {
|
||||||
a href=(format!("{}/repo/{}/{}/{}", &super::SELF_BASE_URL as &str, repo.path.site.as_ref(), repo.path.qual.as_ref(), repo.path.name.as_ref())) {
|
a href=(format!("{}/repo/{}/{}/{}", &super::SELF_BASE_URL as &str, repo.path.site, repo.path.qual.as_ref(), repo.path.name.as_ref())) {
|
||||||
(format!("{} / {}", repo.path.qual.as_ref(), repo.path.name.as_ref()))
|
(format!("{} / {}", repo.path.qual.as_ref(), repo.path.name.as_ref()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
td class="has-text-right" {
|
td class="has-text-right" {
|
||||||
img src=(format!("{}/repo/{}/{}/{}/status.svg", &super::SELF_BASE_URL as &str, repo.path.site.as_ref(), repo.path.qual.as_ref(), repo.path.name.as_ref()));
|
img src=(format!("{}/repo/{}/{}/{}/status.svg", &super::SELF_BASE_URL as &str, repo.path.site, repo.path.qual.as_ref(), repo.path.name.as_ref()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,9 +127,11 @@ fn get_site_icon(site: &RepoSite) -> (FaType, &'static str) {
|
||||||
RepoSite::Github => (FaType::Brands, "github"),
|
RepoSite::Github => (FaType::Brands, "github"),
|
||||||
RepoSite::Gitlab => (FaType::Brands, "gitlab"),
|
RepoSite::Gitlab => (FaType::Brands, "gitlab"),
|
||||||
RepoSite::Bitbucket => (FaType::Brands, "bitbucket"),
|
RepoSite::Bitbucket => (FaType::Brands, "bitbucket"),
|
||||||
// FIXME: There is no brands/{sourcehut, codeberg} icon, so just use a
|
// FIXME: There is no brands/{sourcehut, codeberg, gitea} icon, so just use a
|
||||||
// regular circle which looks close enough.
|
// regular circle which looks close enough.
|
||||||
RepoSite::Sourcehut | RepoSite::Codeberg => (FaType::Regular, "circle"),
|
RepoSite::Sourcehut | RepoSite::Codeberg | RepoSite::Gitea(_) => {
|
||||||
|
(FaType::Regular, "circle")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +336,7 @@ fn render_success(
|
||||||
let self_path = match subject_path {
|
let self_path = match subject_path {
|
||||||
SubjectPath::Repo(ref repo_path) => format!(
|
SubjectPath::Repo(ref repo_path) => format!(
|
||||||
"repo/{}/{}/{}",
|
"repo/{}/{}/{}",
|
||||||
repo_path.site.as_ref(),
|
repo_path.site,
|
||||||
repo_path.qual.as_ref(),
|
repo_path.qual.as_ref(),
|
||||||
repo_path.name.as_ref()
|
repo_path.name.as_ref()
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue