From 194be9c9b550b39544216adbe1e4ad440ab3caf2 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 12:21:22 -0500 Subject: [PATCH 1/6] Add `Gitlab` to the RepoSite enum --- src/models/repo.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/models/repo.rs b/src/models/repo.rs index d70a1c1..daef7cd 100644 --- a/src/models/repo.rs +++ b/src/models/repo.rs @@ -27,13 +27,15 @@ impl RepoPath { #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] pub enum RepoSite { - Github + Github, + Gitlab, } impl RepoSite { pub fn to_base_uri(&self) -> &'static str { match self { - &RepoSite::Github => "https://github.com" + &RepoSite::Github => "https://github.com", + &RepoSite::Gitlab => "https://gitlab.com" } } } @@ -44,6 +46,7 @@ impl FromStr for RepoSite { fn from_str(input: &str) -> Result { match input { "github" => Ok(RepoSite::Github), + "gitlab" => Ok(RepoSite::Gitlab), _ => Err(format_err!("unknown repo site identifier")) } } @@ -52,7 +55,8 @@ impl FromStr for RepoSite { impl AsRef for RepoSite { fn as_ref(&self) -> &str { match self { - &RepoSite::Github => "github" + &RepoSite::Github => "github", + &RepoSite::Gitlab => "gitlab" } } } From dff2a92aa55c32bdf473815a5f92d318cf363a5b Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 12:22:03 -0500 Subject: [PATCH 2/6] move `RetrieveFileAtPath` to src/interactors/mod Also add functions to both the `github` and `gitlab` modules for constructing the Uri to the manifest --- src/interactors/github.rs | 48 ++++++--------------------------- src/interactors/gitlab.rs | 23 ++++++++++++++++ src/interactors/mod.rs | 56 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 40 deletions(-) create mode 100644 src/interactors/gitlab.rs diff --git a/src/interactors/github.rs b/src/interactors/github.rs index 363605b..d97e321 100644 --- a/src/interactors/github.rs +++ b/src/interactors/github.rs @@ -11,46 +11,14 @@ use ::models::repo::{Repository, RepoPath}; const GITHUB_API_BASE_URI: &'static str = "https://api.github.com"; const GITHUB_USER_CONTENT_BASE_URI: &'static str = "https://raw.githubusercontent.com"; -#[derive(Debug, Clone)] -pub struct RetrieveFileAtPath(pub S); - -impl Service for RetrieveFileAtPath - where S: Service + Clone + 'static, - S::Future: 'static -{ - type Request = (RepoPath, RelativePathBuf); - type Response = String; - type Error = Error; - type Future = Box>; - - fn call(&self, req: Self::Request) -> Self::Future { - let service = self.0.clone(); - - let (repo_path, path) = req; - let path_str: &str = path.as_ref(); - let uri_future = format!("{}/{}/{}/HEAD/{}", - GITHUB_USER_CONTENT_BASE_URI, - repo_path.qual.as_ref(), - repo_path.name.as_ref(), - path_str - ).parse::().into_future().from_err(); - - Box::new(uri_future.and_then(move |uri| { - let request = Request::new(Method::Get, uri.clone()); - - service.call(request).from_err().and_then(move |response| { - let status = response.status(); - if !status.is_success() { - future::Either::A(future::err(format_err!("Status code {} for URI {}", status, uri))) - } else { - let body_future = response.body().concat2().from_err(); - let decode_future = body_future - .and_then(|body| String::from_utf8(body.to_vec()).map_err(|err| err.into())); - future::Either::B(decode_future) - } - }) - })) - } +pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result { + 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::()?) } #[derive(Deserialize)] diff --git a/src/interactors/gitlab.rs b/src/interactors/gitlab.rs new file mode 100644 index 0000000..6947563 --- /dev/null +++ b/src/interactors/gitlab.rs @@ -0,0 +1,23 @@ +use hyper::Uri; +use relative_path::RelativePathBuf; + +use ::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 { + let path_str: &str = path.as_ref(); + // gitlab will return a 308 if the Uri ends with, say, `.../raw/master//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 + }; + format!("{}/{}/{}/raw/master/{}", + GITLAB_USER_CONTENT_BASE_URI, + repo_path.qual.as_ref(), + repo_path.name.as_ref(), + slash_path + ).parse::() +} diff --git a/src/interactors/mod.rs b/src/interactors/mod.rs index bccf822..3224f8f 100644 --- a/src/interactors/mod.rs +++ b/src/interactors/mod.rs @@ -1,2 +1,58 @@ +use failure::Error; +use futures::{Future, IntoFuture, Stream, future}; +use hyper::{Error as HyperError, Method, Request, Response}; +use relative_path::RelativePathBuf; +use tokio_service::Service; + +use ::models::repo::{RepoSite, RepoPath}; + pub mod crates; pub mod github; +pub mod gitlab; + + +#[derive(Debug, Clone)] +pub struct RetrieveFileAtPath(pub S); + +impl Service for RetrieveFileAtPath + where S: Service + Clone + 'static, + S::Future: 'static +{ + type Request = (RepoPath, RelativePathBuf); + type Response = String; + type Error = Error; + type Future = Box>; + + fn call(&self, req: Self::Request) -> Self::Future { + let service = self.0.clone(); + + 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) + }, + }; + let uri_future = uri.into_future().from_err(); + + Box::new(uri_future.and_then(move |uri| { + let request = Request::new(Method::Get, uri.clone()); + + service.call(request).from_err().and_then(move |response| { + let status = response.status(); + if !status.is_success() { + future::Either::A(future::err(format_err!("Status code {} for URI {}", status, uri))) + } else { + let body_future = response.body().concat2().from_err(); + let decode_future = body_future + .and_then(|body| String::from_utf8(body.to_vec()).map_err(|err| err.into())); + future::Either::B(decode_future) + } + }) + })) + } +} + + From a46a0960cfa351029010641ba9af364c0366c8fe Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 12:22:49 -0500 Subject: [PATCH 3/6] Make engine use RetrieveFilePath from interactors/mod.rs --- src/engine/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/mod.rs b/src/engine/mod.rs index b9f78a6..ca33033 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -21,7 +21,8 @@ use ::models::repo::{Repository, RepoPath}; use ::models::crates::{CrateName, CrateRelease, AnalyzedDependencies}; use ::interactors::crates::QueryCrate; -use ::interactors::github::{GetPopularRepos, RetrieveFileAtPath}; +use ::interactors::RetrieveFileAtPath; +use ::interactors::github::{GetPopularRepos}; use self::futures::AnalyzeDependenciesFuture; use self::futures::CrawlManifestFuture; From b828de404e97b4cba7e090df96a9877ae055fb79 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 12:32:34 -0500 Subject: [PATCH 4/6] Add gitlab icon to UI --- src/server/views/html/status.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/server/views/html/status.rs b/src/server/views/html/status.rs index 87c9f79..49ac18f 100644 --- a/src/server/views/html/status.rs +++ b/src/server/views/html/status.rs @@ -5,7 +5,7 @@ use ordermap::OrderMap; use ::engine::AnalyzeDependenciesOutcome; use ::models::crates::{CrateName, AnalyzedDependency, AnalyzedDependencies}; -use ::models::repo::RepoPath; +use ::models::repo::{RepoSite, RepoPath}; use ::server::assets; fn dependency_tables(crate_name: CrateName, deps: AnalyzedDependencies) -> Markup { @@ -84,7 +84,15 @@ fn dependency_table(title: &str, deps: OrderMap) } } +fn get_site_icon(repo_site: &RepoSite) -> &'static str { + match *repo_site { + RepoSite::Github => "fa-github", + RepoSite::Gitlab => "fa-gitlab", + } +} + fn render_failure(repo_path: RepoPath) -> Markup { + let site_icon = get_site_icon(&repo_path.site); html! { section class="hero is-light" { div class="hero-head" (super::render_navbar()) @@ -92,7 +100,7 @@ fn render_failure(repo_path: RepoPath) -> Markup { div class="container" { h1 class="title is-1" { a href=(format!("{}/{}/{}", repo_path.site.to_base_uri(), repo_path.qual.as_ref(), repo_path.name.as_ref())) { - i class="fa fa-github" "" + i class=(format!("fa {}", site_icon)) "" (format!(" {} / {}", repo_path.qual.as_ref(), repo_path.name.as_ref())) } } @@ -114,6 +122,7 @@ fn render_failure(repo_path: RepoPath) -> Markup { fn render_success(analysis_outcome: AnalyzeDependenciesOutcome, repo_path: RepoPath) -> Markup { let self_path = format!("repo/{}/{}/{}", repo_path.site.as_ref(), repo_path.qual.as_ref(), repo_path.name.as_ref()); let status_base_url = format!("{}/{}", &super::SELF_BASE_URL as &str, self_path); + let site_icon = get_site_icon(&repo_path.site); let (hero_class, status_asset) = if analysis_outcome.any_outdated() { ("is-warning", assets::BADGE_OUTDATED_SVG.as_ref()) @@ -130,7 +139,7 @@ fn render_success(analysis_outcome: AnalyzeDependenciesOutcome, repo_path: RepoP div class="container" { h1 class="title is-1" { a href=(format!("{}/{}/{}", repo_path.site.to_base_uri(), repo_path.qual.as_ref(), repo_path.name.as_ref())) { - i class="fa fa-github" "" + i class=(format!("fa {}", site_icon)) "" (format!(" {} / {}", repo_path.qual.as_ref(), repo_path.name.as_ref())) } } From b8a0fc7a8b9b7e4f4c2f6d03ea3dca152315d417 Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 22:28:29 -0500 Subject: [PATCH 5/6] Use failure::Error instead of hyper::error::UriError --- src/interactors/github.rs | 2 +- src/interactors/gitlab.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/interactors/github.rs b/src/interactors/github.rs index d97e321..3e90bbd 100644 --- a/src/interactors/github.rs +++ b/src/interactors/github.rs @@ -11,7 +11,7 @@ use ::models::repo::{Repository, RepoPath}; 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 { +pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result { let path_str: &str = path.as_ref(); Ok(format!("{}/{}/{}/HEAD/{}", GITHUB_USER_CONTENT_BASE_URI, diff --git a/src/interactors/gitlab.rs b/src/interactors/gitlab.rs index 6947563..04f5cd1 100644 --- a/src/interactors/gitlab.rs +++ b/src/interactors/gitlab.rs @@ -1,11 +1,12 @@ use hyper::Uri; use relative_path::RelativePathBuf; +use failure::Error; use ::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 { +pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result { let path_str: &str = path.as_ref(); // gitlab will return a 308 if the Uri ends with, say, `.../raw/master//Cargo.toml`, so make // sure that last slash isn't doubled @@ -14,10 +15,10 @@ pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result< } else { path_str }; - format!("{}/{}/{}/raw/master/{}", + Ok(format!("{}/{}/{}/raw/master/{}", GITLAB_USER_CONTENT_BASE_URI, repo_path.qual.as_ref(), repo_path.name.as_ref(), slash_path - ).parse::() + ).parse::()?) } From c5d53d7f2c585dacbcd74dc8acd4cce352d8adbd Mon Sep 17 00:00:00 2001 From: Paul Woolcock Date: Mon, 12 Feb 2018 22:30:15 -0500 Subject: [PATCH 6/6] change master -> HEAD --- src/interactors/gitlab.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interactors/gitlab.rs b/src/interactors/gitlab.rs index 04f5cd1..25e5eac 100644 --- a/src/interactors/gitlab.rs +++ b/src/interactors/gitlab.rs @@ -8,14 +8,14 @@ const GITLAB_USER_CONTENT_BASE_URI: &'static str = "https://gitlab.com"; pub fn get_manifest_uri(repo_path: &RepoPath, path: &RelativePathBuf) -> Result { let path_str: &str = path.as_ref(); - // gitlab will return a 308 if the Uri ends with, say, `.../raw/master//Cargo.toml`, so make + // 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/master/{}", + Ok(format!("{}/{}/{}/raw/HEAD/{}", GITLAB_USER_CONTENT_BASE_URI, repo_path.qual.as_ref(), repo_path.name.as_ref(),