#![deny(missing_docs, rust_2018_idioms)]
#![forbid(unsafe_code)]
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Update {
Shallow(gix_hash::ObjectId),
Unshallow(gix_hash::ObjectId),
}
pub fn read(shallow_file: &std::path::Path) -> Result<Option<nonempty::NonEmpty<gix_hash::ObjectId>>, read::Error> {
use bstr::ByteSlice;
let buf = match std::fs::read(shallow_file) {
Ok(buf) => buf,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
Err(err) => return Err(err.into()),
};
let mut commits = buf
.lines()
.map(gix_hash::ObjectId::from_hex)
.collect::<Result<Vec<_>, _>>()?;
commits.sort();
Ok(nonempty::NonEmpty::from_vec(commits))
}
pub mod write {
pub(crate) mod function {
use std::io::Write;
use super::Error;
use crate::Update;
pub fn write(
mut file: gix_lock::File,
shallow_commits: Option<nonempty::NonEmpty<gix_hash::ObjectId>>,
updates: &[Update],
) -> Result<(), Error> {
let mut shallow_commits = shallow_commits.map(Vec::from).unwrap_or_default();
for update in updates {
match update {
Update::Shallow(id) => {
shallow_commits.push(*id);
}
Update::Unshallow(id) => shallow_commits.retain(|oid| oid != id),
}
}
if shallow_commits.is_empty() {
if let Err(err) = std::fs::remove_file(file.resource_path()) {
if err.kind() != std::io::ErrorKind::NotFound {
return Err(err.into());
}
}
drop(file);
return Ok(());
}
shallow_commits.sort();
let mut buf = Vec::<u8>::new();
for commit in shallow_commits {
commit.write_hex_to(&mut buf).map_err(Error::Io)?;
buf.push(b'\n');
}
file.write_all(&buf).map_err(Error::Io)?;
file.flush().map_err(Error::Io)?;
file.commit()?;
Ok(())
}
}
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Commit(#[from] gix_lock::commit::Error<gix_lock::File>),
#[error("Could not remove an empty shallow file")]
RemoveEmpty(#[from] std::io::Error),
#[error("Failed to write object id to shallow file")]
Io(std::io::Error),
}
}
pub use write::function::write;
pub mod read {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Could not open shallow file for reading")]
Io(#[from] std::io::Error),
#[error("Could not decode a line in shallow file as hex-encoded object hash")]
DecodeHash(#[from] gix_hash::decode::Error),
}
}