use anyhow::bail;
use semver::{Prerelease, Version};
use toml_edit::{value, Document, Formatted, Item, Value};
pub struct Manifest {
path: String,
doc: Option<Document>,
}
impl Manifest {
pub fn new(path: &str) -> Self {
Self {
path: path.to_owned(),
doc: None,
}
}
pub fn load(&mut self) -> anyhow::Result<()> {
let toml = std::fs::read_to_string(&self.path)?;
let doc = match toml.parse::<Document>() {
Ok(doc) => doc,
Err(e) => bail!("Couldn't load manifest from >>{}<< {}", &self.path, &e),
};
self.doc = Some(doc);
Ok(())
}
pub fn save(&mut self) -> anyhow::Result<()> {
if let Some(doc) = &self.doc {
std::fs::write(&self.path, doc.to_string()).unwrap();
}
Ok(())
}
fn get_formatted_version(&self) -> anyhow::Result<Formatted<String>> {
if let Some(doc) = &self.doc {
let fs = match &doc["package"]["version"] {
Item::Value(Value::String(s)) => s, _ => bail!("Unsupported version format!"),
};
Ok(fs.clone())
} else {
bail!("No manifest loaded!");
}
}
pub fn get_version(&self) -> anyhow::Result<Version> {
let fs = self.get_formatted_version()?;
let v = fs.value();
let version = Version::parse(&v).unwrap();
return Ok(version);
}
pub fn get_pretty_version(&self) -> anyhow::Result<String> {
let v = self.get_version()?;
Ok(v.to_string())
}
pub fn set_version(&mut self, version: &Version) -> anyhow::Result<()> {
let fs = self.get_formatted_version()?;
if let Some(doc) = &mut self.doc {
let mut ni = value(version.to_string());
match &mut ni {
Item::Value(Value::String(s)) => {
let d = s.decor_mut();
let od = fs.decor();
match (od.prefix(), od.suffix()) {
(Some(p), Some(s)) => {
d.set_prefix(p);
d.set_suffix(s);
},
_ => {},
}
},
_ => {},
}
doc["package"]["version"] = ni;
} else {
bail!("No manifest loaded!");
}
Ok(())
}
pub fn bump_patch_version(&mut self) -> anyhow::Result<()> {
let old_version = self.get_version()?;
let mut new_version = old_version.clone();
new_version.patch = old_version.patch + 1;
self.set_version(&new_version)?;
Ok(())
}
pub fn bump_minor_version(&mut self) -> anyhow::Result<()> {
let old_version = self.get_version()?;
let mut new_version = old_version.clone();
new_version.patch = 0;
new_version.minor = old_version.minor + 1;
self.set_version(&new_version)?;
Ok(())
}
pub fn bump_major_version(&mut self) -> anyhow::Result<()> {
let old_version = self.get_version()?;
let mut new_version = old_version.clone();
new_version.patch = 0;
new_version.minor = 0;
new_version.major = old_version.major + 1;
self.set_version(&new_version)?;
Ok(())
}
pub fn set_version_suffix(&mut self, suffix: &str) -> anyhow::Result<()> {
let old_version = self.get_version()?;
let mut new_version = old_version.clone();
new_version.pre = Prerelease::new(suffix).unwrap();
self.set_version(&new_version)?;
Ok(())
}
}