Fix url generation to git hosted Cargo.toml file (#57)

This commit is contained in:
Paolo Barbolini 2020-10-01 22:49:11 +02:00 committed by GitHub
parent 0fa8e46425
commit 871e9acd74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 85 additions and 69 deletions

View file

@ -1,21 +0,0 @@
use anyhow::Error;
use hyper::Uri;
use relative_path::RelativePathBuf;
use crate::models::repo::RepoPath;
const BITBUCKET_USER_CONTENT_BASE_URI: &'static str = "https://bitbucket.org";
pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result<Uri, Error> {
let path_str: &str = path.as_ref();
let url = format!(
"{}/{}/{}/raw/HEAD/{}",
BITBUCKET_USER_CONTENT_BASE_URI,
repo_path.qual.as_ref(),
repo_path.name.as_ref(),
path_str
);
Ok(url.parse::<Uri>()?)
}

View file

@ -8,25 +8,11 @@ use futures::{
use hyper::{ use hyper::{
body, header::USER_AGENT, service::Service, Body, Error as HyperError, Request, Response, Uri, body, header::USER_AGENT, service::Service, Body, Error as HyperError, Request, Response, Uri,
}; };
use relative_path::RelativePathBuf;
use serde::Deserialize; use serde::Deserialize;
use crate::models::repo::{RepoPath, Repository}; use crate::models::repo::{RepoPath, Repository};
const GITHUB_API_BASE_URI: &'static str = "https://api.github.com"; const GITHUB_API_BASE_URI: &'static str = "https://api.github.com";
const GITHUB_USER_CONTENT_BASE_URI: &'static str = "https://raw.githubusercontent.com";
pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result<Uri, Error> {
let path_str: &str = path.as_ref();
Ok(format!(
"{}/{}/{}/HEAD/{}",
GITHUB_USER_CONTENT_BASE_URI,
repo_path.qual.as_ref(),
repo_path.name.as_ref(),
path_str
)
.parse::<Uri>()?)
}
#[derive(Deserialize)] #[derive(Deserialize)]
struct GithubSearchResponse { struct GithubSearchResponse {

View file

@ -1,26 +0,0 @@
use anyhow::Error;
use hyper::Uri;
use relative_path::RelativePathBuf;
use crate::models::repo::RepoPath;
const GITLAB_USER_CONTENT_BASE_URI: &'static str = "https://gitlab.com";
pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result<Uri, Error> {
let path_str: &str = path.as_ref();
// gitlab will return a 308 if the Uri ends with, say, `.../raw/HEAD//Cargo.toml`, so make
// sure that last slash isn't doubled
let slash_path = if path_str.starts_with("/") {
&path_str[1..]
} else {
path_str
};
Ok(format!(
"{}/{}/{}/raw/HEAD/{}",
GITLAB_USER_CONTENT_BASE_URI,
repo_path.qual.as_ref(),
repo_path.name.as_ref(),
slash_path
)
.parse::<Uri>()?)
}

View file

@ -11,12 +11,10 @@ use hyper::{
}; };
use relative_path::RelativePathBuf; use relative_path::RelativePathBuf;
use crate::models::repo::{RepoPath, RepoSite}; use crate::models::repo::RepoPath;
pub mod bitbucket;
pub mod crates; pub mod crates;
pub mod github; pub mod github;
pub mod gitlab;
pub mod rustsec; pub mod rustsec;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -37,12 +35,8 @@ where
fn call(&mut self, req: (RepoPath, RelativePathBuf)) -> Self::Future { fn call(&mut self, req: (RepoPath, RelativePathBuf)) -> Self::Future {
let (repo_path, path) = req; let (repo_path, path) = req;
let uri = match &repo_path.site {
RepoSite::Github => github::get_manifest_uri(&repo_path, &path),
RepoSite::Gitlab => gitlab::get_manifest_uri(&repo_path, &path),
RepoSite::Bitbucket => bitbucket::get_manifest_uri(&repo_path, &path),
};
let uri = repo_path.to_usercontent_file_uri(&path);
let uri = match uri { let uri = match uri {
Ok(uri) => uri, Ok(uri) => uri,
Err(error) => return Box::pin(err(error)), Err(error) => return Box::pin(err(error)),

View file

@ -1,6 +1,8 @@
use std::str::FromStr; use std::str::FromStr;
use anyhow::{anyhow, ensure, Error}; use anyhow::{anyhow, ensure, Error};
use hyper::Uri;
use relative_path::RelativePath;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Repository { pub struct Repository {
@ -23,6 +25,19 @@ impl RepoPath {
name: name.parse()?, name: name.parse()?,
}) })
} }
pub fn to_usercontent_file_uri(&self, path: &RelativePath) -> Result<Uri, Error> {
let url = format!(
"{}/{}/{}/{}/{}",
self.site.to_usercontent_base_uri(),
self.qual.as_ref(),
self.name.as_ref(),
self.site.to_usercontent_repo_suffix(),
path.normalize()
);
Ok(url.parse::<Uri>()?)
}
} }
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
@ -40,6 +55,21 @@ impl RepoSite {
&RepoSite::Bitbucket => "https://bitbucket.org", &RepoSite::Bitbucket => "https://bitbucket.org",
} }
} }
pub fn to_usercontent_base_uri(&self) -> &'static str {
match self {
RepoSite::Github => "https://raw.githubusercontent.com",
RepoSite::Gitlab => "https://gitlab.com",
RepoSite::Bitbucket => "https://bitbucket.org",
}
}
pub fn to_usercontent_repo_suffix(&self) -> &'static str {
match self {
RepoSite::Github => "HEAD",
RepoSite::Gitlab | RepoSite::Bitbucket => "raw/HEAD",
}
}
} }
impl FromStr for RepoSite { impl FromStr for RepoSite {
@ -108,3 +138,56 @@ impl AsRef<str> for RepoName {
self.0.as_ref() self.0.as_ref()
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn correct_raw_url_generation() {
let paths = [
("Cargo.toml", "Cargo.toml"),
("/Cargo.toml", "Cargo.toml"),
("libs/badge/Cargo.toml", "libs/badge/Cargo.toml"),
("/libs/badge/Cargo.toml", "libs/badge/Cargo.toml"),
("src/../libs/badge/Cargo.toml", "libs/badge/Cargo.toml"),
("/src/../libs/badge/Cargo.toml", "libs/badge/Cargo.toml"),
];
for (input, expected) in &paths {
let repo = RepoPath::from_parts("github", "deps-rs", "deps.rs").unwrap();
let out = repo
.to_usercontent_file_uri(RelativePath::new(input))
.unwrap();
let exp = format!(
"https://raw.githubusercontent.com/deps-rs/deps.rs/HEAD/{}",
expected
);
assert_eq!(out.to_string(), exp);
}
for (input, expected) in &paths {
let repo = RepoPath::from_parts("gitlab", "deps-rs", "deps.rs").unwrap();
let out = repo
.to_usercontent_file_uri(RelativePath::new(input))
.unwrap();
let exp = format!("https://gitlab.com/deps-rs/deps.rs/raw/HEAD/{}", expected);
assert_eq!(out.to_string(), exp);
}
for (input, expected) in &paths {
let repo = RepoPath::from_parts("bitbucket", "deps-rs", "deps.rs").unwrap();
let out = repo
.to_usercontent_file_uri(RelativePath::new(input))
.unwrap();
let exp = format!(
"https://bitbucket.org/deps-rs/deps.rs/raw/HEAD/{}",
expected
);
assert_eq!(out.to_string(), exp);
}
}
}