use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ProjectManifest {
pub name: String,
pub namespace: String,
pub version: String,
#[serde(default)]
pub modules: HashMap<String, String>,
#[serde(default)]
pub externals: HashMap<String, String>,
}
impl ProjectManifest {
pub fn new(name: &str, namespace: &str) -> Self {
Self {
name: name.to_string(),
namespace: namespace.to_string(),
version: "1.0.0".to_string(),
modules: HashMap::new(),
externals: HashMap::new(),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ModuleManifest {
pub name: String,
pub version: String,
pub description: String,
pub license: String,
pub entry: String,
#[serde(default)]
pub archive: Option<String>,
#[serde(default)]
pub deprecated: bool,
#[serde(default)]
pub deprecation_message: Option<String>,
#[serde(default)]
pub files: Vec<String>,
#[serde(default)]
pub dependencies: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct LockFile {
pub modules: HashMap<String, HashMap<String, LockedModule>>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LockedModule {
pub entry: String,
pub files: Vec<String>,
#[serde(default)]
pub resolved_deps: HashMap<String, String>,
}
#[derive(Debug, Clone)]
pub struct ResolvedModule {
pub manifest: ModuleManifest,
pub resolved_deps: HashMap<String, String>,
}
pub fn parse_dep_spec(spec: &str) -> (&str, Option<&str>) {
if let Some(pos) = spec.rfind('@') {
if pos > 0 {
return (&spec[..pos], Some(&spec[pos + 1..]));
}
}
(spec, None)
}
pub fn is_breaking_change(a: &str, b: &str) -> bool {
let major_a = a.split('.').next().and_then(|s| s.parse::<u32>().ok());
let major_b = b.split('.').next().and_then(|s| s.parse::<u32>().ok());
major_a != major_b
}
pub fn semver_cmp(a: &str, b: &str) -> std::cmp::Ordering {
let parse = |v: &str| -> Vec<u64> {
v.split('.').filter_map(|s| s.parse().ok()).collect()
};
parse(a).cmp(&parse(b))
}