use anyhow::{anyhow, bail};
use crate::{
changelog::{self, Changelog},
errors::Result,
repository::{CommitId, PathMatcher, RepoPath, RepoPathBuf},
rewriters::Rewriter,
version::Version,
};
pub type ProjectId = usize;
#[derive(Debug)]
pub struct Project {
ident: ProjectId,
qnames: Vec<String>,
pub user_facing_name: String,
pub version: Version,
pub rewriters: Vec<Box<dyn Rewriter>>,
prefix: RepoPathBuf,
pub repo_paths: PathMatcher,
pub changelog: Box<dyn Changelog>,
pub internal_deps: Vec<Dependency>,
}
impl Project {
pub fn ident(&self) -> ProjectId {
self.ident
}
pub fn qualified_names(&self) -> &Vec<String> {
&self.qnames
}
pub fn prefix(&self) -> &RepoPath {
&self.prefix
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Dependency {
pub ident: ProjectId,
pub literal: String,
pub cranko_requirement: DepRequirement,
pub resolved_version: Option<Version>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DepRequirement {
Commit(CommitId),
Manual(String),
Unavailable,
}
impl std::fmt::Display for DepRequirement {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
DepRequirement::Commit(cid) => write!(f, "{} (commit)", cid),
DepRequirement::Manual(t) => write!(f, "{} (manual)", t),
DepRequirement::Unavailable => write!(f, "(unavailable)"),
}
}
}
#[derive(Debug)]
pub struct ProjectBuilder {
pub qnames: Vec<String>,
pub version: Option<Version>,
pub prefix: Option<RepoPathBuf>,
pub rewriters: Vec<Box<dyn Rewriter>>,
pub internal_deps: Vec<DependencyBuilder>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DependencyBuilder {
pub target: DependencyTarget,
pub literal: String,
pub cranko_requirement: DepRequirement,
pub resolved_version: Option<Version>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum DependencyTarget {
Text(String),
Ident(ProjectId),
}
impl ProjectBuilder {
#[doc(hidden)]
pub(crate) fn new() -> Self {
ProjectBuilder {
qnames: Vec::new(),
version: None,
prefix: None,
rewriters: Vec::new(),
internal_deps: Vec::new(),
}
}
#[doc(hidden)]
pub(crate) fn finalize(
self,
ident: ProjectId,
user_facing_name: String,
internal_deps: Vec<Dependency>,
) -> Result<Project> {
if self.qnames.is_empty() {
bail!(
"could not load project `{}`: never figured out its naming",
user_facing_name
);
}
let version = self.version.ok_or_else(|| {
anyhow!(
"could not load project `{}`: never figured out its version",
user_facing_name
)
})?;
let prefix = self.prefix.ok_or_else(|| {
anyhow!(
"could not load project `{}`: never figured out its directory prefix",
user_facing_name
)
})?;
Ok(Project {
ident,
qnames: self.qnames,
user_facing_name,
version,
prefix: prefix.clone(),
rewriters: self.rewriters,
repo_paths: PathMatcher::new_include(prefix),
changelog: changelog::default(),
internal_deps,
})
}
}