use anyhow::Result;
use openmoat_core::DEFAULT_POLICY;
use crate::context::read_policy;
use crate::home::Home;
mod merge;
pub use merge::Merge;
const DEFAULT_V0_3_0: &str = include_str!("upgrade/default-v0.3.0.yaml");
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Base {
Recorded,
Assumed,
Unrelated,
}
pub struct Plan {
pub base: Base,
pub current: String,
pub merge: Merge,
}
impl Plan {
pub fn for_home(home: &Home) -> Result<Self> {
let current = read_policy(&home.policy_path())?;
let base_path = home.policy_base_path();
let (base, source) = if base_path.is_file() {
(read_policy(&base_path)?, Base::Recorded)
} else {
(DEFAULT_V0_3_0.to_owned(), Base::Assumed)
};
let base = line_endings_of(¤t, &base);
let new = line_endings_of(¤t, DEFAULT_POLICY);
let mut merge = merge::merge(&base, ¤t, &new);
let source = if source == Base::Assumed && merge.kept * 2 < merge.base_lines {
merge = merge::merge(&base, ¤t, &base);
Base::Unrelated
} else {
source
};
Ok(Self {
base: source,
current,
merge,
})
}
pub fn applicable(&self) -> usize {
self.merge.applied().count()
}
}
pub fn available(home: &Home) -> Option<String> {
let count = Plan::for_home(home).ok()?.applicable();
(count > 0).then(|| {
let plural = if count == 1 { "" } else { "s" };
let version = env!("CARGO_PKG_VERSION");
format!("{count} change{plural} from the OpenMoat {version} default")
})
}
fn line_endings_of(like: &str, text: &str) -> String {
let lf = text.replace("\r\n", "\n");
if like.contains("\r\n") {
lf.replace('\n', "\r\n")
} else {
lf
}
}
#[cfg(test)]
mod tests;