gix_lock/
commit.rs

1use std::path::PathBuf;
2
3use crate::{File, Marker};
4
5mod error {
6    use std::{
7        fmt,
8        fmt::{Debug, Display},
9    };
10
11    /// The error returned by various [`commit(…)`][super::Marker::commit()] methods
12    #[derive(Debug)]
13    pub struct Error<T: Debug> {
14        /// The io error that prevented the attempt to succeed
15        pub error: std::io::Error,
16        /// The marker or file which was used in the attempt to persist it
17        pub instance: T,
18    }
19
20    impl<T: Debug> Display for Error<T> {
21        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22            Display::fmt(&self.error, f)
23        }
24    }
25
26    impl<T: Debug> std::error::Error for Error<T> {
27        fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
28            self.error.source()
29        }
30    }
31}
32pub use error::Error;
33
34impl Marker {
35    /// Commit the changes written to the previously open file and overwrite the original file atomically, returning the resource path
36    /// on success.
37    ///
38    /// This fails for markers which weren't created with [`File::close()`]
39    pub fn commit(mut self) -> Result<PathBuf, Error<Self>> {
40        if !self.created_from_file {
41            return Err(Error {
42                error: std::io::Error::new(
43                    std::io::ErrorKind::Other,
44                    "refusing to commit marker that was never opened",
45                ),
46                instance: self,
47            });
48        }
49        let resource_path = self.resource_path();
50        match self.inner.persist(&resource_path) {
51            Ok(_) => Ok(resource_path),
52            Err(err) => Err(Error {
53                error: err.error,
54                instance: {
55                    self.inner = err.handle;
56                    self
57                },
58            }),
59        }
60    }
61}
62
63impl File {
64    /// Commit the changes written to this lock file and overwrite the original file atomically, returning the resource path
65    /// and an open file handle on success.
66    pub fn commit(mut self) -> Result<(PathBuf, Option<std::fs::File>), Error<Self>> {
67        let resource_path = self.resource_path();
68        match self.inner.persist(&resource_path) {
69            Ok(possibly_file) => Ok((resource_path, possibly_file)),
70            Err(err) => Err(Error {
71                error: err.error,
72                instance: {
73                    self.inner = err.handle;
74                    self
75                },
76            }),
77        }
78    }
79}