1#![deny(missing_docs, rust_2018_idioms)]
3#![forbid(unsafe_code)]
4
5#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub enum Update {
9 Shallow(gix_hash::ObjectId),
11 Unshallow(gix_hash::ObjectId),
13}
14
15pub fn read(shallow_file: &std::path::Path) -> Result<Option<Vec<gix_hash::ObjectId>>, read::Error> {
21 use bstr::ByteSlice;
22 let buf = match std::fs::read(shallow_file) {
23 Ok(buf) => buf,
24 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
25 Err(err) => return Err(err.into()),
26 };
27
28 let mut commits = buf
29 .lines()
30 .map(gix_hash::ObjectId::from_hex)
31 .collect::<Result<Vec<_>, _>>()?;
32
33 commits.sort();
34 if commits.is_empty() {
35 Ok(None)
36 } else {
37 Ok(Some(commits))
38 }
39}
40
41pub mod write {
43 pub(crate) mod function {
44 use std::io::Write;
45
46 use super::Error;
47 use crate::Update;
48
49 pub fn write(
58 mut file: gix_lock::File,
59 shallow_commits: Option<Vec<gix_hash::ObjectId>>,
60 updates: &[Update],
61 ) -> Result<(), Error> {
62 let mut shallow_commits = shallow_commits.unwrap_or_default();
63 for update in updates {
64 match update {
65 Update::Shallow(id) => {
66 shallow_commits.push(*id);
67 }
68 Update::Unshallow(id) => shallow_commits.retain(|oid| oid != id),
69 }
70 }
71 if shallow_commits.is_empty() {
72 std::fs::remove_file(file.resource_path())?;
73 drop(file);
74 return Ok(());
75 }
76
77 if shallow_commits.is_empty() {
78 if let Err(err) = std::fs::remove_file(file.resource_path()) {
79 if err.kind() != std::io::ErrorKind::NotFound {
80 return Err(err.into());
81 }
82 }
83 } else {
84 shallow_commits.sort();
85 let mut buf = Vec::<u8>::new();
86 for commit in shallow_commits {
87 commit.write_hex_to(&mut buf).map_err(Error::Io)?;
88 buf.push(b'\n');
89 }
90 file.write_all(&buf).map_err(Error::Io)?;
91 file.flush()?;
92 }
93 file.commit()?;
94 Ok(())
95 }
96 }
97
98 #[derive(Debug, thiserror::Error)]
100 #[allow(missing_docs)]
101 pub enum Error {
102 #[error(transparent)]
103 Commit(#[from] gix_lock::commit::Error<gix_lock::File>),
104 #[error("Could not remove an empty shallow file")]
105 RemoveEmpty(#[from] std::io::Error),
106 #[error("Failed to write object id to shallow file")]
107 Io(std::io::Error),
108 }
109}
110pub use write::function::write;
111
112pub mod read {
114 #[derive(Debug, thiserror::Error)]
116 #[allow(missing_docs)]
117 pub enum Error {
118 #[error("Could not open shallow file for reading")]
119 Io(#[from] std::io::Error),
120 #[error("Could not decode a line in shallow file as hex-encoded object hash")]
121 DecodeHash(#[from] gix_hash::decode::Error),
122 }
123}