prepare for multi-crate repos

This commit is contained in:
Sam Rijs 2018-01-27 12:17:50 +11:00
parent 28f5cf7ba2
commit eb1bd1b698
4 changed files with 43 additions and 14 deletions

View file

@ -26,7 +26,7 @@ pub struct Api {
impl Api {
pub fn new(engine: Engine) -> Api {
let mut router = Router::new();
router.add("/api/v1/analyze/:site/:qual/:name", Route::AnalyzeDependencies);
router.add("/repo/:site/:qual/:name/dependencies.json", Route::AnalyzeDependencies);
Api { engine, router: Arc::new(router) }
}
@ -40,7 +40,7 @@ struct AnalyzeDependenciesResponseDetail {
}
#[derive(Debug, Serialize)]
struct AnalyzeDependenciesResponse {
struct AnalyzeDependenciesResponseSingle {
dependencies: BTreeMap<String, AnalyzeDependenciesResponseDetail>,
#[serde(rename="dev-dependencies")]
dev_dependencies: BTreeMap<String, AnalyzeDependenciesResponseDetail>,
@ -48,6 +48,11 @@ struct AnalyzeDependenciesResponse {
build_dependencies: BTreeMap<String, AnalyzeDependenciesResponseDetail>
}
#[derive(Debug, Serialize)]
struct AnalyzeDependenciesResponse {
crates: BTreeMap<String, AnalyzeDependenciesResponseSingle>
}
impl Service for Api {
type Request = Request;
type Response = Response;
@ -96,30 +101,33 @@ impl Api {
response.set_body(format!("{:?}", err));
future::Either::A(future::ok(response))
},
Ok(dependencies) => {
let response_struct = AnalyzeDependenciesResponse {
dependencies: dependencies.main.into_iter()
Ok(analysis_outcome) => {
let single = AnalyzeDependenciesResponseSingle {
dependencies: analysis_outcome.deps.main.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
dev_dependencies: dependencies.dev.into_iter()
dev_dependencies: analysis_outcome.deps.dev.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect(),
build_dependencies: dependencies.build.into_iter()
build_dependencies: analysis_outcome.deps.build.into_iter()
.map(|(name, analyzed)| (name.into(), AnalyzeDependenciesResponseDetail {
outdated: analyzed.is_outdated(),
required: analyzed.required,
latest: analyzed.latest
})).collect()
};
let multi = AnalyzeDependenciesResponse {
crates: vec![(analysis_outcome.name.into(), single)].into_iter().collect()
};
let mut response = Response::new()
.with_header(ContentType::json())
.with_body(serde_json::to_string(&response_struct).unwrap());
.with_body(serde_json::to_string(&multi).unwrap());
future::Either::B(future::ok(response))
}
}

View file

@ -31,15 +31,20 @@ pub enum AnalyzeDependenciesError {
const FETCH_RELEASES_CONCURRENCY: usize = 10;
pub struct AnalyzeDependenciesOutcome {
pub name: CrateName,
pub deps: AnalyzedDependencies
}
impl Engine {
pub fn analyze_dependencies(&self, repo_path: RepoPath) ->
impl Future<Item=AnalyzedDependencies, Error=AnalyzeDependenciesError>
impl Future<Item=AnalyzeDependenciesOutcome, Error=AnalyzeDependenciesError>
{
let manifest_future = self.retrieve_manifest(&repo_path);
let engine = self.clone();
manifest_future.and_then(move |manifest| {
let CrateManifest::Crate(deps) = manifest;
let CrateManifest::Crate(crate_name, deps) = manifest;
let analyzer = DependencyAnalyzer::new(&deps);
let main_deps = deps.main.into_iter().map(|(name, _)| name);
@ -48,10 +53,17 @@ impl Engine {
let release_futures = engine.fetch_releases(main_deps.chain(dev_deps).chain(build_deps));
stream::iter_ok(release_futures)
let analyzed_deps_future = stream::iter_ok(release_futures)
.buffer_unordered(FETCH_RELEASES_CONCURRENCY)
.fold(analyzer, |mut analyzer, releases| { analyzer.process(releases); Ok(analyzer) })
.map(|analyzer| analyzer.finalize())
.map(|analyzer| analyzer.finalize());
analyzed_deps_future.map(move |analyzed_deps| {
AnalyzeDependenciesOutcome {
name: crate_name,
deps: analyzed_deps
}
})
})
}

View file

@ -96,5 +96,5 @@ impl AnalyzedDependencies {
#[derive(Debug)]
pub enum CrateManifest {
Crate(CrateDeps)
Crate(CrateName, CrateDeps)
}

View file

@ -26,8 +26,14 @@ enum CargoTomlDependency {
Complex(CargoTomlComplexDependency)
}
#[derive(Serialize, Deserialize, Debug)]
struct CargoTomlPackage {
name: String
}
#[derive(Serialize, Deserialize, Debug)]
struct CargoToml {
package: CargoTomlPackage,
#[serde(default)]
dependencies: BTreeMap<String, CargoTomlDependency>,
#[serde(rename = "dev-dependencies")]
@ -65,6 +71,9 @@ pub fn parse_manifest_toml(input: &str) -> Result<CrateManifest, ManifestParseEr
let cargo_toml = toml::de::from_str::<CargoToml>(input)
.map_err(ManifestParseError::Serde)?;
let crate_name = cargo_toml.package.name.parse()
.map_err(ManifestParseError::Name)?;
let dependencies = cargo_toml.dependencies
.into_iter().filter_map(convert_dependency).collect::<Result<BTreeMap<_, _>, _>>()?;
let dev_dependencies = cargo_toml.dev_dependencies
@ -78,5 +87,5 @@ pub fn parse_manifest_toml(input: &str) -> Result<CrateManifest, ManifestParseEr
build: build_dependencies
};
Ok(CrateManifest::Crate(deps))
Ok(CrateManifest::Crate(crate_name, deps))
}