mirror of
https://github.com/deps-rs/deps.rs.git
synced 2024-11-22 10:26:30 +00:00
support path-based internal dependencies
This commit is contained in:
parent
c135edc2a1
commit
52e3fc4d28
12 changed files with 142 additions and 78 deletions
|
@ -12,6 +12,7 @@ hyper-tls = "0.1.2"
|
||||||
lazy_static = "1.0.0"
|
lazy_static = "1.0.0"
|
||||||
maud = "0.17.2"
|
maud = "0.17.2"
|
||||||
ordermap = "0.4.0"
|
ordermap = "0.4.0"
|
||||||
|
relative-path = { version = "0.3.7", features = ["serde"] }
|
||||||
route-recognizer = "0.1.12"
|
route-recognizer = "0.1.12"
|
||||||
semver = { version = "0.9.0", features = ["serde"] }
|
semver = { version = "0.9.0", features = ["serde"] }
|
||||||
serde = "1.0.27"
|
serde = "1.0.27"
|
||||||
|
|
|
@ -16,9 +16,15 @@ impl AnalyzeDependenciesFuture {
|
||||||
pub fn new(engine: &Engine, deps: CrateDeps) -> Self {
|
pub fn new(engine: &Engine, deps: CrateDeps) -> Self {
|
||||||
let analyzer = DependencyAnalyzer::new(&deps);
|
let analyzer = DependencyAnalyzer::new(&deps);
|
||||||
|
|
||||||
let main_deps = deps.main.into_iter().map(|(name, _)| name);
|
let main_deps = deps.main.into_iter().filter_map(|(name, dep)| {
|
||||||
let dev_deps = deps.dev.into_iter().map(|(name, _)| name);
|
if dep.is_external() { Some(name) } else { None }
|
||||||
let build_deps = deps.build.into_iter().map(|(name, _)| name);
|
});
|
||||||
|
let dev_deps = deps.dev.into_iter().filter_map(|(name, dep)| {
|
||||||
|
if dep.is_external() { Some(name) } else { None }
|
||||||
|
});
|
||||||
|
let build_deps = deps.build.into_iter().filter_map(|(name, dep)| {
|
||||||
|
if dep.is_external() { Some(name) } else { None }
|
||||||
|
});
|
||||||
|
|
||||||
let release_futures = engine.fetch_releases(main_deps.chain(dev_deps).chain(build_deps));
|
let release_futures = engine.fetch_releases(main_deps.chain(dev_deps).chain(build_deps));
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use futures::{Async, Future, Poll, Stream};
|
use futures::{Async, Future, Poll, Stream};
|
||||||
use futures::stream::FuturesOrdered;
|
use futures::stream::FuturesOrdered;
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
|
|
||||||
use ::models::repo::RepoPath;
|
use ::models::repo::RepoPath;
|
||||||
|
|
||||||
|
@ -15,11 +15,11 @@ pub struct CrawlManifestFuture {
|
||||||
repo_path: RepoPath,
|
repo_path: RepoPath,
|
||||||
engine: Engine,
|
engine: Engine,
|
||||||
crawler: ManifestCrawler,
|
crawler: ManifestCrawler,
|
||||||
futures: FuturesOrdered<Box<Future<Item=(PathBuf, String), Error=Error>>>
|
futures: FuturesOrdered<Box<Future<Item=(RelativePathBuf, String), Error=Error>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrawlManifestFuture {
|
impl CrawlManifestFuture {
|
||||||
pub fn new(engine: &Engine, repo_path: RepoPath, entry_point: PathBuf) -> Self {
|
pub fn new(engine: &Engine, repo_path: RepoPath, entry_point: RelativePathBuf) -> Self {
|
||||||
let future: Box<Future<Item=_, Error=_>> = Box::new(engine.retrieve_manifest_at_path(&repo_path, &entry_point)
|
let future: Box<Future<Item=_, Error=_>> = Box::new(engine.retrieve_manifest_at_path(&repo_path, &entry_point)
|
||||||
.map(move |contents| (entry_point, contents)));
|
.map(move |contents| (entry_point, contents)));
|
||||||
let engine = engine.clone();
|
let engine = engine.clone();
|
||||||
|
|
|
@ -55,12 +55,13 @@ impl DependencyAnalyzer {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{CrateDeps, CrateRelease, DependencyAnalyzer};
|
use models::crates::{CrateDep, CrateDeps, CrateRelease};
|
||||||
|
use super::DependencyAnalyzer;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn tracks_latest_without_matching() {
|
fn tracks_latest_without_matching() {
|
||||||
let mut deps = CrateDeps::default();
|
let mut deps = CrateDeps::default();
|
||||||
deps.main.insert("hyper".parse().unwrap(), "^0.11.0".parse().unwrap());
|
deps.main.insert("hyper".parse().unwrap(), CrateDep::External("^0.11.0".parse().unwrap()));
|
||||||
|
|
||||||
let mut analyzer = DependencyAnalyzer::new(&deps);
|
let mut analyzer = DependencyAnalyzer::new(&deps);
|
||||||
analyzer.process(vec![
|
analyzer.process(vec![
|
||||||
|
@ -77,7 +78,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn tracks_latest_that_matches() {
|
fn tracks_latest_that_matches() {
|
||||||
let mut deps = CrateDeps::default();
|
let mut deps = CrateDeps::default();
|
||||||
deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap());
|
deps.main.insert("hyper".parse().unwrap(), CrateDep::External("^0.10.0".parse().unwrap()));
|
||||||
|
|
||||||
let mut analyzer = DependencyAnalyzer::new(&deps);
|
let mut analyzer = DependencyAnalyzer::new(&deps);
|
||||||
analyzer.process(vec![
|
analyzer.process(vec![
|
||||||
|
@ -95,7 +96,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn skips_yanked_releases() {
|
fn skips_yanked_releases() {
|
||||||
let mut deps = CrateDeps::default();
|
let mut deps = CrateDeps::default();
|
||||||
deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap());
|
deps.main.insert("hyper".parse().unwrap(), CrateDep::External("^0.10.0".parse().unwrap()));
|
||||||
|
|
||||||
let mut analyzer = DependencyAnalyzer::new(&deps);
|
let mut analyzer = DependencyAnalyzer::new(&deps);
|
||||||
analyzer.process(vec![
|
analyzer.process(vec![
|
||||||
|
@ -112,7 +113,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn skips_prereleases() {
|
fn skips_prereleases() {
|
||||||
let mut deps = CrateDeps::default();
|
let mut deps = CrateDeps::default();
|
||||||
deps.main.insert("hyper".parse().unwrap(), "^0.10.0".parse().unwrap());
|
deps.main.insert("hyper".parse().unwrap(), CrateDep::External("^0.10.0".parse().unwrap()));
|
||||||
|
|
||||||
let mut analyzer = DependencyAnalyzer::new(&deps);
|
let mut analyzer = DependencyAnalyzer::new(&deps);
|
||||||
analyzer.process(vec![
|
analyzer.process(vec![
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
use ordermap::map::OrderMap;
|
use ordermap::map::OrderMap;
|
||||||
|
|
||||||
use ::parsers::manifest::parse_manifest_toml;
|
use ::parsers::manifest::parse_manifest_toml;
|
||||||
use ::models::crates::{CrateDeps, CrateName, CrateManifest};
|
use ::models::crates::{CrateDep, CrateDeps, CrateName, CrateManifest};
|
||||||
|
|
||||||
pub struct ManifestCrawlerOutput {
|
pub struct ManifestCrawlerOutput {
|
||||||
pub crates: OrderMap<CrateName, CrateDeps>
|
pub crates: OrderMap<CrateName, CrateDeps>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ManifestCrawlerStepOutput {
|
pub struct ManifestCrawlerStepOutput {
|
||||||
pub paths_of_interest: Vec<PathBuf>
|
pub paths_of_interest: Vec<RelativePathBuf>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ManifestCrawler {
|
pub struct ManifestCrawler {
|
||||||
manifests: HashMap<PathBuf, CrateManifest>,
|
manifests: HashMap<RelativePathBuf, CrateManifest>,
|
||||||
leaf_crates: OrderMap<CrateName, CrateDeps>
|
leaf_crates: OrderMap<CrateName, CrateDeps>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl ManifestCrawler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(&mut self, path: PathBuf, raw_manifest: String) -> Result<ManifestCrawlerStepOutput, Error> {
|
pub fn step(&mut self, path: RelativePathBuf, raw_manifest: String) -> Result<ManifestCrawlerStepOutput, Error> {
|
||||||
let manifest = parse_manifest_toml(&raw_manifest)?;
|
let manifest = parse_manifest_toml(&raw_manifest)?;
|
||||||
self.manifests.insert(path.clone(), manifest.clone());
|
self.manifests.insert(path.clone(), manifest.clone());
|
||||||
|
|
||||||
|
@ -38,28 +38,45 @@ impl ManifestCrawler {
|
||||||
|
|
||||||
match manifest {
|
match manifest {
|
||||||
CrateManifest::Package(name, deps) => {
|
CrateManifest::Package(name, deps) => {
|
||||||
self.leaf_crates.insert(name, deps);
|
self.process_package(&path, name, deps, &mut output);
|
||||||
},
|
},
|
||||||
CrateManifest::Workspace { members } => {
|
CrateManifest::Workspace { members } => {
|
||||||
for mut member in members {
|
self.process_workspace(&path, &members, &mut output);
|
||||||
if !member.ends_with("*") {
|
|
||||||
output.paths_of_interest.push(path.clone().join(member));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
CrateManifest::Mixed { name, deps, members } => {
|
CrateManifest::Mixed { name, deps, members } => {
|
||||||
self.leaf_crates.insert(name, deps);
|
self.process_package(&path, name, deps, &mut output);
|
||||||
for mut member in members {
|
self.process_workspace(&path, &members, &mut output);
|
||||||
if !member.ends_with("*") {
|
|
||||||
output.paths_of_interest.push(path.clone().join(member));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_interest(&mut self, base_path: &RelativePathBuf, path: &RelativePathBuf, output: &mut ManifestCrawlerStepOutput) {
|
||||||
|
let full_path = base_path.join_normalized(path);
|
||||||
|
if !self.manifests.contains_key(&full_path) {
|
||||||
|
output.paths_of_interest.push(full_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_package(&mut self, base_path: &RelativePathBuf, name: CrateName, deps: CrateDeps, output: &mut ManifestCrawlerStepOutput) {
|
||||||
|
for (_, dep) in deps.main.iter().chain(deps.dev.iter()).chain(deps.build.iter()) {
|
||||||
|
if let &CrateDep::Internal(ref path) = dep {
|
||||||
|
self.register_interest(base_path, path, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.leaf_crates.insert(name, deps);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_workspace(&mut self, base_path: &RelativePathBuf, members: &[RelativePathBuf], output: &mut ManifestCrawlerStepOutput) {
|
||||||
|
for mut path in members {
|
||||||
|
if !path.ends_with("*") {
|
||||||
|
self.register_interest(base_path, path, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn finalize(self) -> ManifestCrawlerOutput {
|
pub fn finalize(self) -> ManifestCrawlerOutput {
|
||||||
ManifestCrawlerOutput {
|
ManifestCrawlerOutput {
|
||||||
crates: self.leaf_crates
|
crates: self.leaf_crates
|
||||||
|
@ -69,8 +86,10 @@ impl ManifestCrawler {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use relative_path::RelativePath;
|
||||||
use semver::VersionReq;
|
use semver::VersionReq;
|
||||||
|
|
||||||
|
use models::crates::CrateDep;
|
||||||
use super::ManifestCrawler;
|
use super::ManifestCrawler;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -103,21 +122,21 @@ quickcheck = "0.5"
|
||||||
codegen = "0.0.1"
|
codegen = "0.0.1"
|
||||||
"#;
|
"#;
|
||||||
let mut crawler = ManifestCrawler::new();
|
let mut crawler = ManifestCrawler::new();
|
||||||
let step_output = crawler.step("/Cargo.toml".into(), manifest.to_string()).unwrap();
|
let step_output = crawler.step("".into(), manifest.to_string()).unwrap();
|
||||||
assert_eq!(step_output.paths_of_interest.len(), 0);
|
assert_eq!(step_output.paths_of_interest.len(), 0);
|
||||||
let output = crawler.finalize();
|
let output = crawler.finalize();
|
||||||
assert_eq!(output.crates.len(), 1);
|
assert_eq!(output.crates.len(), 1);
|
||||||
assert_eq!(output.crates["more-complex"].main.len(), 2);
|
assert_eq!(output.crates["more-complex"].main.len(), 2);
|
||||||
assert_eq!(output.crates["more-complex"].main.get("foo").unwrap(),
|
assert_eq!(output.crates["more-complex"].main.get("foo").unwrap(),
|
||||||
&VersionReq::parse("0.30.0").unwrap());
|
&CrateDep::External(VersionReq::parse("0.30.0").unwrap()));
|
||||||
assert_eq!(output.crates["more-complex"].main.get("bar").unwrap(),
|
assert_eq!(output.crates["more-complex"].main.get("bar").unwrap(),
|
||||||
&VersionReq::parse("1.2.0").unwrap());
|
&CrateDep::External(VersionReq::parse("1.2.0").unwrap()));
|
||||||
assert_eq!(output.crates["more-complex"].dev.len(), 1);
|
assert_eq!(output.crates["more-complex"].dev.len(), 1);
|
||||||
assert_eq!(output.crates["more-complex"].dev.get("quickcheck").unwrap(),
|
assert_eq!(output.crates["more-complex"].dev.get("quickcheck").unwrap(),
|
||||||
&VersionReq::parse("0.5").unwrap());
|
&CrateDep::External(VersionReq::parse("0.5").unwrap()));
|
||||||
assert_eq!(output.crates["more-complex"].build.len(), 1);
|
assert_eq!(output.crates["more-complex"].build.len(), 1);
|
||||||
assert_eq!(output.crates["more-complex"].build.get("codegen").unwrap(),
|
assert_eq!(output.crates["more-complex"].build.get("codegen").unwrap(),
|
||||||
&VersionReq::parse("0.0.1").unwrap());
|
&CrateDep::External(VersionReq::parse("0.0.1").unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -131,11 +150,11 @@ members = [
|
||||||
]
|
]
|
||||||
"#;
|
"#;
|
||||||
let mut crawler = ManifestCrawler::new();
|
let mut crawler = ManifestCrawler::new();
|
||||||
let step_output = crawler.step("/".into(), manifest.to_string()).unwrap();
|
let step_output = crawler.step("".into(), manifest.to_string()).unwrap();
|
||||||
assert_eq!(step_output.paths_of_interest.len(), 3);
|
assert_eq!(step_output.paths_of_interest.len(), 3);
|
||||||
assert_eq!(step_output.paths_of_interest[0].to_str().unwrap(), "/lib/");
|
assert_eq!(step_output.paths_of_interest[0].as_str(), "lib");
|
||||||
assert_eq!(step_output.paths_of_interest[1].to_str().unwrap(), "/codegen/");
|
assert_eq!(step_output.paths_of_interest[1].as_str(), "codegen");
|
||||||
assert_eq!(step_output.paths_of_interest[2].to_str().unwrap(), "/contrib/");
|
assert_eq!(step_output.paths_of_interest[2].as_str(), "contrib");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -148,9 +167,9 @@ members = [
|
||||||
]
|
]
|
||||||
"#;
|
"#;
|
||||||
let mut crawler = ManifestCrawler::new();
|
let mut crawler = ManifestCrawler::new();
|
||||||
let step_output = crawler.step("/".into(), manifest.to_string()).unwrap();
|
let step_output = crawler.step("".into(), manifest.to_string()).unwrap();
|
||||||
assert_eq!(step_output.paths_of_interest.len(), 1);
|
assert_eq!(step_output.paths_of_interest.len(), 1);
|
||||||
assert_eq!(step_output.paths_of_interest[0].to_str().unwrap(), "/lib/");
|
assert_eq!(step_output.paths_of_interest[0].as_str(), "lib");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -180,19 +199,21 @@ features = ["use_std"]
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut crawler = ManifestCrawler::new();
|
let mut crawler = ManifestCrawler::new();
|
||||||
let step_output = crawler.step("/".into(), futures_manifest.to_string()).unwrap();
|
let step_output = crawler.step("".into(), futures_manifest.to_string()).unwrap();
|
||||||
assert_eq!(step_output.paths_of_interest.len(), 1);
|
assert_eq!(step_output.paths_of_interest.len(), 1);
|
||||||
assert_eq!(step_output.paths_of_interest[0].to_str().unwrap(), "/futures-cpupool");
|
assert_eq!(step_output.paths_of_interest[0].as_str(), "futures-cpupool");
|
||||||
let step_output = crawler.step("/futures-cpupool".into(), futures_cpupool_manifest.to_string()).unwrap();
|
let step_output = crawler.step("futures-cpupool".into(), futures_cpupool_manifest.to_string()).unwrap();
|
||||||
assert_eq!(step_output.paths_of_interest.len(), 0);
|
assert_eq!(step_output.paths_of_interest.len(), 0);
|
||||||
let output = crawler.finalize();
|
let output = crawler.finalize();
|
||||||
assert_eq!(output.crates.len(), 2);
|
assert_eq!(output.crates.len(), 2);
|
||||||
assert_eq!(output.crates["futures"].main.len(), 0);
|
assert_eq!(output.crates["futures"].main.len(), 0);
|
||||||
assert_eq!(output.crates["futures"].dev.len(), 0);
|
assert_eq!(output.crates["futures"].dev.len(), 0);
|
||||||
assert_eq!(output.crates["futures"].build.len(), 0);
|
assert_eq!(output.crates["futures"].build.len(), 0);
|
||||||
assert_eq!(output.crates["futures-cpupool"].main.len(), 1);
|
assert_eq!(output.crates["futures-cpupool"].main.len(), 2);
|
||||||
assert_eq!(output.crates["futures-cpupool"].main.get("num_cpus").unwrap(),
|
assert_eq!(output.crates["futures-cpupool"].main.get("num_cpus").unwrap(),
|
||||||
&VersionReq::parse("1.0").unwrap());
|
&CrateDep::External(VersionReq::parse("1.0").unwrap()));
|
||||||
|
assert_eq!(output.crates["futures-cpupool"].main.get("futures").unwrap(),
|
||||||
|
&CrateDep::Internal(RelativePath::new("..").to_relative_path_buf()));
|
||||||
assert_eq!(output.crates["futures-cpupool"].dev.len(), 0);
|
assert_eq!(output.crates["futures-cpupool"].dev.len(), 0);
|
||||||
assert_eq!(output.crates["futures-cpupool"].build.len(), 0);
|
assert_eq!(output.crates["futures-cpupool"].build.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -9,6 +8,7 @@ use futures::future::join_all;
|
||||||
use hyper::Client;
|
use hyper::Client;
|
||||||
use hyper::client::HttpConnector;
|
use hyper::client::HttpConnector;
|
||||||
use hyper_tls::HttpsConnector;
|
use hyper_tls::HttpsConnector;
|
||||||
|
use relative_path::{RelativePath, RelativePathBuf};
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
use tokio_service::Service;
|
use tokio_service::Service;
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ impl Engine {
|
||||||
pub fn analyze_dependencies(&self, repo_path: RepoPath) ->
|
pub fn analyze_dependencies(&self, repo_path: RepoPath) ->
|
||||||
impl Future<Item=AnalyzeDependenciesOutcome, Error=Error>
|
impl Future<Item=AnalyzeDependenciesOutcome, Error=Error>
|
||||||
{
|
{
|
||||||
let entry_point = PathBuf::from("/");
|
let entry_point = RelativePath::new("/").to_relative_path_buf();
|
||||||
let manifest_future = CrawlManifestFuture::new(self, repo_path, entry_point);
|
let manifest_future = CrawlManifestFuture::new(self, repo_path, entry_point);
|
||||||
|
|
||||||
let engine = self.clone();
|
let engine = self.clone();
|
||||||
|
@ -95,10 +95,11 @@ impl Engine {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retrieve_manifest_at_path<P: AsRef<Path>>(&self, repo_path: &RepoPath, path: &P) ->
|
fn retrieve_manifest_at_path(&self, repo_path: &RepoPath, path: &RelativePathBuf) ->
|
||||||
impl Future<Item=String, Error=Error>
|
impl Future<Item=String, Error=Error>
|
||||||
{
|
{
|
||||||
retrieve_file_at_path(self.client.clone(), &repo_path, &path.as_ref().join("Cargo.toml")).from_err()
|
let manifest_path = path.join(RelativePath::new("Cargo.toml"));
|
||||||
|
retrieve_file_at_path(self.client.clone(), &repo_path, &manifest_path).from_err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use futures::{Future, Stream, IntoFuture, future};
|
use futures::{Future, Stream, IntoFuture, future};
|
||||||
use hyper::{Error as HyperError, Method, Request, Response};
|
use hyper::{Error as HyperError, Method, Request, Response, Uri};
|
||||||
use tokio_service::Service;
|
use tokio_service::Service;
|
||||||
use semver::Version;
|
use semver::Version;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
@ -43,15 +43,15 @@ pub fn query_crate<S>(service: S, crate_name: CrateName) ->
|
||||||
where S: Service<Request=Request, Response=Response, Error=HyperError>
|
where S: Service<Request=Request, Response=Response, Error=HyperError>
|
||||||
{
|
{
|
||||||
let uri_future = format!("{}/crates/{}/versions", CRATES_API_BASE_URI, crate_name.as_ref())
|
let uri_future = format!("{}/crates/{}/versions", CRATES_API_BASE_URI, crate_name.as_ref())
|
||||||
.parse().into_future().from_err();
|
.parse::<Uri>().into_future().from_err();
|
||||||
|
|
||||||
uri_future.and_then(move |uri| {
|
uri_future.and_then(move |uri| {
|
||||||
let request = Request::new(Method::Get, uri);
|
let request = Request::new(Method::Get, uri.clone());
|
||||||
|
|
||||||
service.call(request).from_err().and_then(move |response| {
|
service.call(request).from_err().and_then(move |response| {
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
if !status.is_success() {
|
if !status.is_success() {
|
||||||
future::Either::A(future::err(format_err!("Status code: {}", status)))
|
future::Either::A(future::err(format_err!("Status code {} for URI {}", status, uri)))
|
||||||
} else {
|
} else {
|
||||||
let body_future = response.body().concat2().from_err();
|
let body_future = response.body().concat2().from_err();
|
||||||
let decode_future = body_future.and_then(|body| {
|
let decode_future = body_future.and_then(|body| {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use futures::{Future, IntoFuture, Stream, future};
|
use futures::{Future, IntoFuture, Stream, future};
|
||||||
use hyper::{Error as HyperError, Method, Request, Response, Uri};
|
use hyper::{Error as HyperError, Method, Request, Response, Uri};
|
||||||
use hyper::header::UserAgent;
|
use hyper::header::UserAgent;
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
use tokio_service::Service;
|
use tokio_service::Service;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
|
@ -12,11 +11,11 @@ use ::models::repo::{Repository, RepoPath};
|
||||||
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";
|
const GITHUB_USER_CONTENT_BASE_URI: &'static str = "https://raw.githubusercontent.com";
|
||||||
|
|
||||||
pub fn retrieve_file_at_path<S, P: AsRef<Path>>(service: S, repo_path: &RepoPath, path: &P) ->
|
pub fn retrieve_file_at_path<S>(service: S, repo_path: &RepoPath, path: &RelativePathBuf) ->
|
||||||
impl Future<Item=String, Error=Error>
|
impl Future<Item=String, Error=Error>
|
||||||
where S: Service<Request=Request, Response=Response, Error=HyperError>
|
where S: Service<Request=Request, Response=Response, Error=HyperError>
|
||||||
{
|
{
|
||||||
let path_str = path.as_ref().to_str().expect("failed to convert path to str");
|
let path_str: &str = path.as_ref();
|
||||||
let uri_future = format!("{}/{}/{}/master/{}",
|
let uri_future = format!("{}/{}/{}/master/{}",
|
||||||
GITHUB_USER_CONTENT_BASE_URI,
|
GITHUB_USER_CONTENT_BASE_URI,
|
||||||
repo_path.qual.as_ref(),
|
repo_path.qual.as_ref(),
|
||||||
|
@ -83,7 +82,7 @@ impl<S> Service for GetPopularRepos<S>
|
||||||
service.call(request).from_err().and_then(|response| {
|
service.call(request).from_err().and_then(|response| {
|
||||||
let status = response.status();
|
let status = response.status();
|
||||||
if !status.is_success() {
|
if !status.is_success() {
|
||||||
future::Either::A(future::err(format_err!("Status code: {}", status)))
|
future::Either::A(future::err(format_err!("Status code {} for popular repo search", status)))
|
||||||
} else {
|
} else {
|
||||||
let body_future = response.body().concat2().from_err();
|
let body_future = response.body().concat2().from_err();
|
||||||
let decode_future = body_future
|
let decode_future = body_future
|
||||||
|
|
|
@ -11,6 +11,7 @@ extern crate hyper_tls;
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
extern crate maud;
|
extern crate maud;
|
||||||
extern crate ordermap;
|
extern crate ordermap;
|
||||||
|
extern crate relative_path;
|
||||||
extern crate route_recognizer;
|
extern crate route_recognizer;
|
||||||
extern crate semver;
|
extern crate semver;
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
use semver::{Version, VersionReq};
|
use semver::{Version, VersionReq};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
@ -50,11 +50,27 @@ pub struct CrateRelease {
|
||||||
pub yanked: bool
|
pub yanked: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum CrateDep {
|
||||||
|
External(VersionReq),
|
||||||
|
Internal(RelativePathBuf)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CrateDep {
|
||||||
|
pub fn is_external(&self) -> bool {
|
||||||
|
if let &CrateDep::External(_) = self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct CrateDeps {
|
pub struct CrateDeps {
|
||||||
pub main: BTreeMap<CrateName, VersionReq>,
|
pub main: BTreeMap<CrateName, CrateDep>,
|
||||||
pub dev: BTreeMap<CrateName, VersionReq>,
|
pub dev: BTreeMap<CrateName, CrateDep>,
|
||||||
pub build: BTreeMap<CrateName, VersionReq>
|
pub build: BTreeMap<CrateName, CrateDep>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -87,14 +103,26 @@ pub struct AnalyzedDependencies {
|
||||||
|
|
||||||
impl AnalyzedDependencies {
|
impl AnalyzedDependencies {
|
||||||
pub fn new(deps: &CrateDeps) -> AnalyzedDependencies {
|
pub fn new(deps: &CrateDeps) -> AnalyzedDependencies {
|
||||||
let main = deps.main.iter().map(|(name, req)| {
|
let main = deps.main.iter().filter_map(|(name, dep)| {
|
||||||
(name.clone(), AnalyzedDependency::new(req.clone()))
|
if let &CrateDep::External(ref req) = dep {
|
||||||
|
Some((name.clone(), AnalyzedDependency::new(req.clone())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let dev = deps.dev.iter().map(|(name, req)| {
|
let dev = deps.dev.iter().filter_map(|(name, dep)| {
|
||||||
(name.clone(), AnalyzedDependency::new(req.clone()))
|
if let &CrateDep::External(ref req) = dep {
|
||||||
|
Some((name.clone(), AnalyzedDependency::new(req.clone())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
let build = deps.build.iter().map(|(name, req)| {
|
let build = deps.build.iter().filter_map(|(name, dep)| {
|
||||||
(name.clone(), AnalyzedDependency::new(req.clone()))
|
if let &CrateDep::External(ref req) = dep {
|
||||||
|
Some((name.clone(), AnalyzedDependency::new(req.clone())))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}).collect();
|
}).collect();
|
||||||
AnalyzedDependencies { main, dev, build }
|
AnalyzedDependencies { main, dev, build }
|
||||||
}
|
}
|
||||||
|
@ -113,6 +141,6 @@ impl AnalyzedDependencies {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum CrateManifest {
|
pub enum CrateManifest {
|
||||||
Package(CrateName, CrateDeps),
|
Package(CrateName, CrateDeps),
|
||||||
Workspace { members: Vec<PathBuf> },
|
Workspace { members: Vec<RelativePathBuf> },
|
||||||
Mixed { name: CrateName, deps: CrateDeps, members: Vec<PathBuf> }
|
Mixed { name: CrateName, deps: CrateDeps, members: Vec<RelativePathBuf> }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
use relative_path::RelativePathBuf;
|
||||||
use semver::VersionReq;
|
use semver::VersionReq;
|
||||||
use toml;
|
use toml;
|
||||||
|
|
||||||
use ::models::crates::{CrateName, CrateDeps, CrateManifest};
|
use ::models::crates::{CrateName, CrateDep, CrateDeps, CrateManifest};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct CargoTomlComplexDependency {
|
struct CargoTomlComplexDependency {
|
||||||
git: Option<String>,
|
git: Option<String>,
|
||||||
path: Option<String>,
|
path: Option<RelativePathBuf>,
|
||||||
version: Option<String>
|
version: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ struct CargoTomlPackage {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
struct CargoTomlWorkspace {
|
struct CargoTomlWorkspace {
|
||||||
members: Vec<PathBuf>
|
members: Vec<RelativePathBuf>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
@ -47,22 +47,28 @@ struct CargoToml {
|
||||||
build_dependencies: BTreeMap<String, CargoTomlDependency>
|
build_dependencies: BTreeMap<String, CargoTomlDependency>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_dependency(cargo_dep: (String, CargoTomlDependency)) -> Option<Result<(CrateName, VersionReq), Error>> {
|
fn convert_dependency(cargo_dep: (String, CargoTomlDependency)) -> Option<Result<(CrateName, CrateDep), Error>> {
|
||||||
match cargo_dep {
|
match cargo_dep {
|
||||||
(name, CargoTomlDependency::Simple(string)) => {
|
(name, CargoTomlDependency::Simple(string)) => {
|
||||||
Some(name.parse::<CrateName>().map_err(|err| err.into()).and_then(|parsed_name| {
|
Some(name.parse::<CrateName>().map_err(|err| err.into()).and_then(|parsed_name| {
|
||||||
string.parse::<VersionReq>().map_err(|err| err.into())
|
string.parse::<VersionReq>().map_err(|err| err.into())
|
||||||
.map(|version| (parsed_name, version))
|
.map(|version| (parsed_name, CrateDep::External(version)))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
(name, CargoTomlDependency::Complex(cplx)) => {
|
(name, CargoTomlDependency::Complex(cplx)) => {
|
||||||
if cplx.git.is_some() || cplx.path.is_some() {
|
if cplx.git.is_some() {
|
||||||
None
|
None
|
||||||
|
} else if cplx.path.is_some() {
|
||||||
|
cplx.path.map(|path| {
|
||||||
|
name.parse::<CrateName>().map_err(|err| err.into()).map(|parsed_name| {
|
||||||
|
(parsed_name, CrateDep::Internal(path))
|
||||||
|
})
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
cplx.version.map(|string| {
|
cplx.version.map(|string| {
|
||||||
name.parse::<CrateName>().map_err(|err| err.into()).and_then(|parsed_name| {
|
name.parse::<CrateName>().map_err(|err| err.into()).and_then(|parsed_name| {
|
||||||
string.parse::<VersionReq>().map_err(|err| err.into())
|
string.parse::<VersionReq>().map_err(|err| err.into())
|
||||||
.map(|version| (parsed_name, version))
|
.map(|version| (parsed_name, CrateDep::External(version)))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn dependency_tables(crate_name: CrateName, deps: AnalyzedDependencies) -> Marku
|
||||||
}
|
}
|
||||||
|
|
||||||
@if deps.main.is_empty() && deps.dev.is_empty() && deps.build.is_empty() {
|
@if deps.main.is_empty() && deps.dev.is_empty() && deps.build.is_empty() {
|
||||||
p class="notification has-text-centered" "No dependencies! 🙌"
|
p class="notification has-text-centered" "No external dependencies! 🙌"
|
||||||
}
|
}
|
||||||
|
|
||||||
@if !deps.main.is_empty() {
|
@if !deps.main.is_empty() {
|
||||||
|
|
Loading…
Reference in a new issue