gix_index/file/
write.rs

1use crate::{write, File, Version};
2
3/// The error produced by [`File::write()`].
4#[derive(Debug, thiserror::Error)]
5#[allow(missing_docs)]
6pub enum Error {
7    #[error(transparent)]
8    Io(#[from] gix_hash::io::Error),
9    #[error("Could not acquire lock for index file")]
10    AcquireLock(#[from] gix_lock::acquire::Error),
11    #[error("Could not commit lock for index file")]
12    CommitLock(#[from] gix_lock::commit::Error<gix_lock::File>),
13}
14
15impl File {
16    /// Write the index to `out` with `options`, to be readable by [`File::at()`], returning the version that was actually written
17    /// to retain all information of this index.
18    pub fn write_to(
19        &self,
20        mut out: impl std::io::Write,
21        options: write::Options,
22    ) -> Result<(Version, gix_hash::ObjectId), gix_hash::io::Error> {
23        let _span = gix_features::trace::detail!("gix_index::File::write_to()", skip_hash = options.skip_hash);
24        let (version, hash) = if options.skip_hash {
25            let out: &mut dyn std::io::Write = &mut out;
26            let version = self.state.write_to(out, options)?;
27            (version, self.state.object_hash.null())
28        } else {
29            let mut hasher = gix_hash::io::Write::new(&mut out, self.state.object_hash);
30            let out: &mut dyn std::io::Write = &mut hasher;
31            let version = self.state.write_to(out, options)?;
32            (version, hasher.hash.try_finalize()?)
33        };
34        out.write_all(hash.as_slice())?;
35        Ok((version, hash))
36    }
37
38    /// Write ourselves to the path we were read from after acquiring a lock, using `options`.
39    ///
40    /// Note that the hash produced will be stored which is why we need to be mutable.
41    pub fn write(&mut self, options: write::Options) -> Result<(), Error> {
42        let _span = gix_features::trace::detail!("gix_index::File::write()", path = ?self.path);
43        let mut lock = std::io::BufWriter::with_capacity(
44            64 * 1024,
45            gix_lock::File::acquire_to_update_resource(&self.path, gix_lock::acquire::Fail::Immediately, None)?,
46        );
47        let (version, digest) = self.write_to(&mut lock, options)?;
48        match lock.into_inner() {
49            Ok(lock) => lock.commit()?,
50            Err(err) => return Err(Error::Io(err.into_error().into())),
51        };
52        self.state.version = version;
53        self.checksum = Some(digest);
54        Ok(())
55    }
56}