use anyhow::{format_err, Context, Result};
use std::collections::HashSet;
static HOST_NAME: &str = "pypi.org";
fn get_parsed_version(version: &Option<&str>) -> thirdpass_core::extension::VersionParseResult {
let cleaned_version = match version {
Some(v) => match v.strip_prefix("==") {
Some(v) => v,
None => {
return Err(thirdpass_core::extension::VersionError::from_parse_error(v));
}
},
None => {
return Err(thirdpass_core::extension::VersionError::from_missing_version());
}
};
Ok(cleaned_version.to_string())
}
fn parse_section(
json_section: &serde_json::map::Map<std::string::String, serde_json::value::Value>,
) -> Result<HashSet<thirdpass_core::extension::Dependency>> {
let mut dependencies = HashSet::new();
for (package_name, entry) in json_section {
let version_parse_result = get_parsed_version(&entry["version"].as_str());
dependencies.insert(thirdpass_core::extension::Dependency {
name: package_name.clone(),
version: version_parse_result,
});
}
Ok(dependencies)
}
pub fn get_dependencies(
file_path: &std::path::Path,
) -> Result<HashSet<thirdpass_core::extension::Dependency>> {
let file = std::fs::File::open(file_path)?;
let reader = std::io::BufReader::new(file);
let pipfile: serde_json::Value = serde_json::from_reader(reader).context(format!(
"Failed to parse Pipfile.lock: {}",
file_path.display()
))?;
let mut all_dependencies: HashSet<thirdpass_core::extension::Dependency> = HashSet::new();
for section in ["default", "develop"] {
let json_section = pipfile[section].as_object().ok_or(format_err!(
"Failed to parse '{}' section of Pipfile.lock",
section
))?;
let dependencies = parse_section(json_section)?;
for dependency in dependencies {
all_dependencies.insert(dependency);
}
}
Ok(all_dependencies)
}
pub fn get_registry_host_name() -> String {
HOST_NAME.to_string()
}