use crate::dependent_version_content::{
PlanError, PolicyIncomplete, TrackedMode, TrackedPath, WorkspaceContent,
};
use crate::dependent_version_manifest::{ManifestFacts, read_manifest_facts, strict_text};
use crate::dependent_version_paths::{is_workspace_manifest_path, package_directory};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ManifestState {
pub path: Vec<u8>,
pub mode: TrackedMode,
pub directory: Vec<u8>,
pub bytes: Vec<u8>,
pub text: String,
pub facts: ManifestFacts,
pub base_version: Option<Vec<u16>>,
}
struct RawManifest {
tracked: TrackedPath,
current: Vec<u8>,
base: Option<Vec<u8>>,
}
pub fn read_manifest_states(
content: &mut dyn WorkspaceContent,
tracked: &[TrackedPath],
) -> Result<Vec<ManifestState>, PlanError> {
let mut raw: Vec<RawManifest> = Vec::new();
for entry in tracked {
if is_workspace_manifest_path(&entry.path) {
raw.push(RawManifest {
tracked: entry.clone(),
current: content.candidate_bytes(&entry.path)?,
base: content.base_bytes(&entry.path)?,
});
}
}
for manifest in &raw {
strict_text(&manifest.tracked.path, &manifest.current)?;
if let Some(base) = &manifest.base {
strict_text(&manifest.tracked.path, base)?;
}
}
let mut states: Vec<ManifestState> = Vec::new();
for manifest in raw {
states.push(manifest_state(manifest)?);
}
return Ok(states);
}
fn manifest_state(manifest: RawManifest) -> Result<ManifestState, PolicyIncomplete> {
let path: &[u8] = &manifest.tracked.path;
let mut base_version: Option<Vec<u16>> = None;
if let Some(base) = &manifest.base {
base_version = read_manifest_facts(path, strict_text(path, base)?)?.version;
}
let text: String = String::from(strict_text(path, &manifest.current)?);
let facts: ManifestFacts = read_manifest_facts(path, &text)?;
return Ok(ManifestState {
path: path.to_vec(),
mode: manifest.tracked.mode,
directory: package_directory(path).to_vec(),
text,
facts,
base_version,
bytes: manifest.current,
});
}
pub fn bumped_names(states: &[ManifestState]) -> Vec<String> {
return states
.iter()
.filter(|state: &&ManifestState| {
return state.base_version.is_some() && state.facts.version != state.base_version;
})
.map(|state: &ManifestState| return state.facts.name.clone())
.collect();
}
pub fn duplicate_name(states: &[ManifestState]) -> Option<PolicyIncomplete> {
for (index, later) in states.iter().enumerate() {
if let Some(earlier) = states[..index]
.iter()
.find(|state: &&ManifestState| return state.facts.name == later.facts.name)
{
return Some(PolicyIncomplete::DuplicateName {
name: later.facts.name.clone(),
first: earlier.path.clone(),
second: later.path.clone(),
});
}
}
return None;
}
#[cfg(test)]
#[path = "dependent_version_states_tests.rs"]
mod tests;