use std::path::Path;
use super::exclusion::GoExclusion;
use super::fault::GoSourceFault;
use super::identity::{GoModuleId, ProjectAuthority, index_of};
use super::inventory::GoFileInventory;
use super::limits::GoResolutionLimits;
use super::module::GoModule;
use super::provider::GoSourceProvider;
use super::replacement::GoReplacement;
use super::requirement::GoRequirement;
use super::snapshot::GoResolutionSnapshot;
use super::snapshot_error::GoSnapshotError;
use super::{error::GoProjectError, load, snapshot};
use pedant_types::SourceProvider;
#[derive(Debug)]
pub struct GoProject {
pub(super) root: Box<Path>,
pub(super) limits: GoResolutionLimits,
pub(super) authority: ProjectAuthority,
pub(super) main: GoModule,
pub(super) required: Box<[GoModule]>,
pub(super) requirements: Box<[GoRequirement]>,
pub(super) replacements: Box<[GoReplacement]>,
pub(super) exclusions: Box<[GoExclusion]>,
}
impl GoProject {
pub fn load(root: &Path, limits: GoResolutionLimits) -> Result<Self, GoProjectError> {
load::load_project(root, limits)
}
pub fn snapshot_resolution(&self) -> Result<GoResolutionSnapshot, GoSnapshotError> {
snapshot::build(self, &mut private_provider(self))
}
pub fn snapshot_resolution_with_provider<P>(
&self,
provider: &mut P,
) -> Result<GoResolutionSnapshot, GoSnapshotError>
where
P: SourceProvider<GoFileInventory>,
P::Error: Into<GoSourceFault>,
{
snapshot::build(self, provider)
}
pub fn root(&self) -> &Path {
&self.root
}
pub fn limits(&self) -> GoResolutionLimits {
self.limits
}
pub fn root_module(&self) -> &GoModule {
&self.main
}
pub fn modules(&self) -> impl Iterator<Item = &GoModule> {
std::iter::once(&self.main).chain(self.required.iter())
}
pub fn module(&self, id: GoModuleId) -> Option<&GoModule> {
let index = self.select(id)?;
match index.checked_sub(1) {
None => Some(&self.main),
Some(offset) => self.required.get(offset),
}
}
pub fn requirements(&self) -> &[GoRequirement] {
&self.requirements
}
pub fn module_requirements(&self, module: GoModuleId) -> impl Iterator<Item = &GoRequirement> {
self.requirements
.iter()
.filter(move |requirement| requirement.module() == module)
}
pub fn replacements(&self) -> &[GoReplacement] {
&self.replacements
}
pub fn exclusions(&self) -> &[GoExclusion] {
&self.exclusions
}
fn select(&self, id: GoModuleId) -> Option<usize> {
match id.authority() == self.authority {
true => Some(index_of(id.index())),
false => None,
}
}
}
fn private_provider(project: &GoProject) -> GoSourceProvider {
GoSourceProvider::at_project_root(project.root.to_path_buf(), project.limits)
}