From 18e5da679bbc8762afbf0855bb55b9e8b2fa58c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Camille=20Favier?= Date: Thu, 21 Jul 2022 12:20:52 +0200 Subject: [PATCH] Don't panic during export (#501) --- flake-info/src/bin/flake-info.rs | 43 +++++++++++------- flake-info/src/data/export.rs | 76 ++++++++++++++++++-------------- flake-info/src/elastic.rs | 1 + flake-info/src/lib.rs | 13 +++--- 4 files changed, 80 insertions(+), 53 deletions(-) diff --git a/flake-info/src/bin/flake-info.rs b/flake-info/src/bin/flake-info.rs index 55c0f36..2ac8154 100644 --- a/flake-info/src/bin/flake-info.rs +++ b/flake-info/src/bin/flake-info.rs @@ -228,10 +228,7 @@ async fn run_command( gc, } => { let source = Source::Git { url: flake }; - let exports = flake_info::process_flake(&source, &kind, temp_store, extra) - .map_err(FlakeInfoError::Flake)?; - - let info = flake_info::get_flake_info(source.to_flake_ref(), temp_store, extra) + let (info, exports) = flake_info::process_flake(&source, &kind, temp_store, extra) .map_err(FlakeInfoError::Flake)?; let ident = ( @@ -288,19 +285,21 @@ async fn run_command( .iter() .map(|source| match source { Source::Nixpkgs(nixpkgs) => flake_info::process_nixpkgs(source, &kind) + .with_context(|| { + format!("While processing nixpkgs archive {}", source.to_flake_ref()) + }) .map(|result| (result, nixpkgs.git_ref.to_owned())), - _ => flake_info::process_flake(source, &kind, temp_store, &extra).and_then( - |result| { - flake_info::get_flake_info(source.to_flake_ref(), temp_store, extra) - .map(|info| (result, info.revision.unwrap_or("latest".into()))) - }, - ), + _ => flake_info::process_flake(source, &kind, temp_store, &extra) + .with_context(|| { + format!("While processing flake {}", source.to_flake_ref()) + }) + .map(|(info, result)| (result, info.revision.unwrap_or("latest".into()))), }) .partition::, _>(Result::is_ok); let (exports, hashes) = exports_and_hashes .into_iter() - .map(|result| result.unwrap()) + .map(|result| result.unwrap()) // each result is_ok .fold( (Vec::new(), Vec::new()), |(mut exports, mut hashes), (export, hash)| { @@ -312,7 +311,7 @@ async fn run_command( let errors = errors .into_iter() - .map(Result::unwrap_err) + .map(Result::unwrap_err) // each result is_err .collect::>(); if !errors.is_empty() { @@ -425,17 +424,28 @@ struct NixosChannels { #[derive(Clone, Debug, Deserialize)] struct Channel { - branch: String + branch: String, } impl NixosChannels { fn check_channel(&self, channel: &String) -> Result<(), FlakeInfoError> { - self.channels.iter().find(|c| &c.branch == channel).map_or_else(|| Ok(()), |_| Err(FlakeInfoError::UnknownNixOSChannel(channel.clone(), self.clone()))) + self.channels + .iter() + .find(|c| &c.branch == channel) + .map_or_else( + || Ok(()), + |_| { + Err(FlakeInfoError::UnknownNixOSChannel( + channel.clone(), + self.clone(), + )) + }, + ) } } impl FromStr for NixosChannels { - type Err=serde_json::Error; + type Err = serde_json::Error; fn from_str(s: &str) -> Result { serde_json::from_str(s) @@ -445,5 +455,6 @@ impl FromStr for NixosChannels { lazy_static! { static ref NIXOS_CHANNELS: NixosChannels = std::env::var("NIXOS_CHANNELS") .unwrap_or("".to_string()) - .parse().unwrap(); + .parse() + .unwrap(); } diff --git a/flake-info/src/data/export.rs b/flake-info/src/data/export.rs index 81520fc..2b423c8 100644 --- a/flake-info/src/data/export.rs +++ b/flake-info/src/data/export.rs @@ -1,10 +1,17 @@ /// This module defines the unified putput format as expected by the elastic search /// Additionally, we implement converseions from the two possible input formats, i.e. /// Flakes, or Nixpkgs. -use std::{convert::TryInto, path::PathBuf}; +use std::{ + convert::{TryFrom, TryInto}, + path::PathBuf, +}; -use super::{import::{DocValue, ModulePath}, pandoc::PandocExt}; +use super::{ + import::{DocValue, ModulePath}, + pandoc::PandocExt, +}; use crate::data::import::NixOption; +use anyhow::Context; use log::error; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -117,9 +124,11 @@ pub enum Derivation { // ----- Conversions -impl From<(import::FlakeEntry, super::Flake)> for Derivation { - fn from((d, f): (import::FlakeEntry, super::Flake)) -> Self { - match d { +impl TryFrom<(import::FlakeEntry, super::Flake)> for Derivation { + type Error = anyhow::Error; + + fn try_from((d, f): (import::FlakeEntry, super::Flake)) -> Result { + Ok(match d { import::FlakeEntry::Package { attribute_name, name, @@ -187,14 +196,16 @@ impl From<(import::FlakeEntry, super::Flake)> for Derivation { app_bin: bin, app_type, }, - import::FlakeEntry::Option(option) => option.into(), - } + import::FlakeEntry::Option(option) => option.try_into()?, + }) } } -impl From for Derivation { - fn from(entry: import::NixpkgsEntry) -> Self { - match entry { +impl TryFrom for Derivation { + type Error = anyhow::Error; + + fn try_from(entry: import::NixpkgsEntry) -> Result { + Ok(match entry { import::NixpkgsEntry::Derivation { attribute, package } => { let package_attr_set: Vec<_> = attribute.split(".").collect(); let package_attr_set: String = (if package_attr_set.len() > 1 { @@ -230,8 +241,7 @@ impl From for Derivation { let package_maintainers_set = package_maintainers .iter() - .filter(|m| m.name.is_some()) - .map(|m| m.name.to_owned().unwrap()) + .flat_map(|m| m.name.to_owned()) .collect(); let position: Option = package.meta.position.map(|p| { @@ -276,13 +286,15 @@ impl From for Derivation { package_position: position, } } - import::NixpkgsEntry::Option(option) => option.into(), - } + import::NixpkgsEntry::Option(option) => option.try_into()?, + }) } } -impl From for Derivation { - fn from( +impl TryFrom for Derivation { + type Error = anyhow::Error; + + fn try_from( NixOption { declarations, description, @@ -292,26 +304,26 @@ impl From for Derivation { example, flake, }: import::NixOption, - ) -> Self { + ) -> Result { let description = description .as_ref() .map(PandocExt::render) .transpose() - .expect(&format!("Could not render descript of `{}`", name)); + .with_context(|| format!("While rendering the description for option `{}`", name))?; let option_default = default; // .map(TryInto::try_into) // .transpose() - // .expect(&format!("Could not render option_default of `{}`", name)); + // .with_context(|| format!("While rendering the default for option `{}`", name))?; let option_example = example; // .map(TryInto::try_into) // .transpose() - // .expect(&format!("Could not render option_example of `{}`", name)); + // .with_context(|| format!("While rendering the example for option `{}`", name))?; let option_type = option_type; // .map(TryInto::try_into) // .transpose() - // .expect(&format!("Could not render option_type of `{}`", name)); + // .with_context(|| format!("While rendering the type for option `{}`", name))?; - Derivation::Option { + Ok(Derivation::Option { option_source: declarations.get(0).map(Clone::clone), option_name: name.clone(), option_name_reverse: Reverse(name.clone()), @@ -323,7 +335,7 @@ impl From for Derivation { option_type, option_name_query: AttributeQuery::new(&name), option_name_query_reverse: Reverse(AttributeQuery::new(&name)), - } + }) } } @@ -387,19 +399,19 @@ pub struct Export { impl Export { /// Construct Export from Flake and Flake entry - pub fn flake(flake: Flake, item: import::FlakeEntry) -> Self { - Self { + pub fn flake(flake: Flake, item: import::FlakeEntry) -> anyhow::Result { + Ok(Self { flake: Some(flake.clone()), - item: Derivation::from((item, flake)), - } + item: Derivation::try_from((item, flake))?, + }) } /// Construct Export from NixpkgsEntry - pub fn nixpkgs(item: import::NixpkgsEntry) -> Self { - Self { + pub fn nixpkgs(item: import::NixpkgsEntry) -> anyhow::Result { + Ok(Self { flake: None, - item: Derivation::from(item), - } + item: Derivation::try_from(item)?, + }) } } @@ -423,7 +435,7 @@ mod tests { "visible":true }"#).unwrap(); - let option: Derivation = option.into(); + let option: Derivation = option.try_into().unwrap(); println!("{}", serde_json::to_string_pretty(&option).unwrap()); } diff --git a/flake-info/src/elastic.rs b/flake-info/src/elastic.rs index 9cd1324..5184094 100644 --- a/flake-info/src/elastic.rs +++ b/flake-info/src/elastic.rs @@ -499,6 +499,7 @@ mod tests { let exports = sources .iter() .flat_map(|s| process_flake(s, &Kind::All, false, &[])) + .map(|(info, exports)| exports) .flatten() .collect::>(); println!("{}", serde_json::to_string(&exports[1]).unwrap()); diff --git a/flake-info/src/lib.rs b/flake-info/src/lib.rs index 7e5a97b..65dc6f1 100644 --- a/flake-info/src/lib.rs +++ b/flake-info/src/lib.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use anyhow::Result; -use data::{import::Kind, Export, Source}; +use data::{import::Kind, Export, Flake, Source}; pub mod commands; pub mod data; @@ -17,7 +17,7 @@ pub fn process_flake( kind: &data::import::Kind, temp_store: bool, extra: &[String], -) -> Result> { +) -> Result<(Flake, Vec)> { let mut info = commands::get_flake_info(source.to_flake_ref(), temp_store, extra)?; info.source = Some(source.clone()); let packages = commands::get_derivation_info(source.to_flake_ref(), *kind, temp_store, extra)?; @@ -27,9 +27,9 @@ pub fn process_flake( let exports: Vec = packages .into_iter() .map(|p| Export::flake(info.clone(), p)) - .collect(); + .collect::>>()?; - Ok(exports) + Ok((info, exports)) } pub fn process_nixpkgs(nixpkgs: &Source, kind: &Kind) -> Result, anyhow::Error> { @@ -48,6 +48,9 @@ pub fn process_nixpkgs(nixpkgs: &Source, kind: &Kind) -> Result, any let mut all = drvs; all.append(&mut options); - let exports = all.into_iter().map(Export::nixpkgs).collect(); + let exports = all + .into_iter() + .map(Export::nixpkgs) + .collect::>>()?; Ok(exports) }