1use gix_hash::ObjectId;
2use gix_object::{tree, tree::EntryMode};
3
4pub type ChangeId = u32;
8
9#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
11pub enum Relation {
12    Parent(ChangeId),
18    ChildOfParent(ChangeId),
20}
21
22#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
24pub enum Change {
25    Addition {
27        entry_mode: tree::EntryMode,
29        oid: ObjectId,
31        relation: Option<Relation>,
33    },
34    Deletion {
36        entry_mode: tree::EntryMode,
38        oid: ObjectId,
40        relation: Option<Relation>,
42    },
43    Modification {
46        previous_entry_mode: tree::EntryMode,
48        previous_oid: ObjectId,
50
51        entry_mode: tree::EntryMode,
53        oid: ObjectId,
55    },
56}
57
58impl Change {
59    pub fn oid(&self) -> &gix_hash::oid {
61        match self {
62            Change::Addition { oid, .. } | Change::Deletion { oid, .. } | Change::Modification { oid, .. } => oid,
63        }
64    }
65    pub fn entry_mode(&self) -> EntryMode {
67        match self {
68            Change::Addition { entry_mode, .. }
69            | Change::Deletion { entry_mode, .. }
70            | Change::Modification { entry_mode, .. } => *entry_mode,
71        }
72    }
73    pub fn oid_and_entry_mode(&self) -> (&gix_hash::oid, EntryMode) {
75        match self {
76            Change::Addition {
77                oid,
78                entry_mode,
79                relation: _,
80            }
81            | Change::Deletion {
82                oid,
83                entry_mode,
84                relation: _,
85            }
86            | Change::Modification { oid, entry_mode, .. } => (oid, *entry_mode),
87        }
88    }
89}
90
91#[derive(Default, Clone, Copy, PartialOrd, PartialEq, Ord, Eq, Hash)]
93pub enum Action {
94    #[default]
96    Continue,
97    Cancel,
99}
100
101impl Action {
102    pub fn cancelled(&self) -> bool {
104        matches!(self, Action::Cancel)
105    }
106}
107
108#[cfg(feature = "blob")]
109mod change_impls {
110    use gix_hash::oid;
111    use gix_object::tree::EntryMode;
112
113    use crate::{
114        rewrites::tracker::ChangeKind,
115        tree::visit::{Change, Relation},
116    };
117
118    impl crate::rewrites::tracker::Change for crate::tree::visit::Change {
119        fn id(&self) -> &oid {
120            match self {
121                Change::Addition { oid, .. } | Change::Deletion { oid, .. } | Change::Modification { oid, .. } => oid,
122            }
123        }
124
125        fn relation(&self) -> Option<Relation> {
126            match self {
127                Change::Addition { relation, .. } | Change::Deletion { relation, .. } => *relation,
128                Change::Modification { .. } => None,
129            }
130        }
131
132        fn kind(&self) -> ChangeKind {
133            match self {
134                Change::Addition { .. } => ChangeKind::Addition,
135                Change::Deletion { .. } => ChangeKind::Deletion,
136                Change::Modification { .. } => ChangeKind::Modification,
137            }
138        }
139
140        fn entry_mode(&self) -> EntryMode {
141            match self {
142                Change::Addition { entry_mode, .. }
143                | Change::Deletion { entry_mode, .. }
144                | Change::Modification { entry_mode, .. } => *entry_mode,
145            }
146        }
147
148        fn id_and_entry_mode(&self) -> (&oid, EntryMode) {
149            match self {
150                Change::Addition { entry_mode, oid, .. }
151                | Change::Deletion { entry_mode, oid, .. }
152                | Change::Modification { entry_mode, oid, .. } => (oid, *entry_mode),
153            }
154        }
155    }
156}
157
158#[cfg(test)]
159mod tests {
160    use super::*;
161
162    #[test]
163    fn size_of_change() {
164        let actual = std::mem::size_of::<Change>();
165        assert!(
166            actual <= 48,
167            "{actual} <= 48: this type shouldn't grow without us knowing"
168        );
169    }
170}