Skip to main content

ephemeris_files/
diff.rs

1use std::fmt;
2
3use similar::TextDiff;
4
5use crate::{FilesError, Operation, Plan};
6
7impl fmt::Display for Operation {
8    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9        match self {
10            Self::Create { path, entry: _ } => write!(f, "create {path}"),
11            Self::Replace { path, entry: _ } => write!(f, "replace {path}"),
12            Self::Delete { path } => write!(f, "delete {path}"),
13        }
14    }
15}
16
17impl Operation {
18    /// The unified diff of this operation against the content `plan` was
19    /// built against.
20    ///
21    /// Returns `None` when either side is not UTF-8 or nothing differs.
22    ///
23    /// # Errors
24    ///
25    /// Returns an error when the current content cannot be read.
26    pub fn unified_diff(&self, plan: &Plan) -> Result<Option<String>, FilesError> {
27        let path = self.path();
28        let (old, new, old_name, new_name) = match self {
29            Self::Create { entry, path: _ } => (
30                Vec::new(),
31                entry.content.clone(),
32                "/dev/null".to_owned(),
33                format!("b/{path}"),
34            ),
35            Self::Replace { entry, path: _ } => (
36                plan.current_content(path)?.unwrap_or_default(),
37                entry.content.clone(),
38                format!("a/{path}"),
39                format!("b/{path}"),
40            ),
41            Self::Delete { path: _ } => (
42                plan.current_content(path)?.unwrap_or_default(),
43                Vec::new(),
44                format!("a/{path}"),
45                "/dev/null".to_owned(),
46            ),
47        };
48        let (Ok(old), Ok(new)) = (str::from_utf8(&old), str::from_utf8(&new)) else {
49            return Ok(None);
50        };
51        let diff = TextDiff::from_lines(old, new)
52            .unified_diff()
53            .header(&old_name, &new_name)
54            .to_string();
55        Ok((!diff.is_empty()).then_some(diff))
56    }
57}