gix_diff/index/
change.rs

1use std::borrow::Cow;
2
3use bstr::BStr;
4use gix_object::tree;
5
6use crate::{
7    index::{Change, ChangeRef},
8    rewrites,
9    rewrites::tracker::ChangeKind,
10    tree::visit::Relation,
11};
12
13impl ChangeRef<'_, '_> {
14    /// Copy everything into an owned version of this instance.
15    pub fn into_owned(self) -> Change {
16        match self {
17            ChangeRef::Addition {
18                location,
19                index,
20                entry_mode,
21                id,
22            } => ChangeRef::Addition {
23                location: Cow::Owned(location.into_owned()),
24                index,
25                entry_mode,
26                id: Cow::Owned(id.into_owned()),
27            },
28            ChangeRef::Deletion {
29                location,
30                index,
31                entry_mode,
32                id,
33            } => ChangeRef::Deletion {
34                location: Cow::Owned(location.into_owned()),
35                index,
36                entry_mode,
37                id: Cow::Owned(id.into_owned()),
38            },
39            ChangeRef::Modification {
40                location,
41                previous_index,
42                previous_entry_mode,
43                previous_id,
44                index,
45                entry_mode,
46                id,
47            } => ChangeRef::Modification {
48                location: Cow::Owned(location.into_owned()),
49                previous_index,
50                previous_entry_mode,
51                previous_id: Cow::Owned(previous_id.into_owned()),
52                index,
53                entry_mode,
54                id: Cow::Owned(id.into_owned()),
55            },
56            ChangeRef::Rewrite {
57                source_location,
58                source_index,
59                source_entry_mode,
60                source_id,
61                location,
62                index,
63                entry_mode,
64                id,
65                copy,
66            } => ChangeRef::Rewrite {
67                source_location: Cow::Owned(source_location.into_owned()),
68                source_index,
69                source_entry_mode,
70                source_id: Cow::Owned(source_id.into_owned()),
71                location: Cow::Owned(location.into_owned()),
72                index,
73                entry_mode,
74                id: Cow::Owned(id.into_owned()),
75                copy,
76            },
77        }
78    }
79}
80
81impl ChangeRef<'_, '_> {
82    /// Return all shared fields among all variants: `(location, index, entry_mode, id)`
83    ///
84    /// In case of rewrites, the fields return to the current change.
85    ///
86    /// Note that there are also more specific accessors in case you only need to access to one of
87    /// these fields individually.
88    ///
89    /// See [`ChangeRef::location()`], [`ChangeRef::index()`], [`ChangeRef::entry_mode()`] and
90    /// [`ChangeRef::id()`].
91    pub fn fields(&self) -> (&BStr, usize, gix_index::entry::Mode, &gix_hash::oid) {
92        match self {
93            ChangeRef::Addition {
94                location,
95                index,
96                entry_mode,
97                id,
98                ..
99            }
100            | ChangeRef::Deletion {
101                location,
102                index,
103                entry_mode,
104                id,
105                ..
106            }
107            | ChangeRef::Modification {
108                location,
109                index,
110                entry_mode,
111                id,
112                ..
113            }
114            | ChangeRef::Rewrite {
115                location,
116                index,
117                entry_mode,
118                id,
119                ..
120            } => (location.as_ref(), *index, *entry_mode, id),
121        }
122    }
123
124    /// Return the `location`, in the case of rewrites referring to the current change.
125    pub fn location(&self) -> &BStr {
126        match self {
127            ChangeRef::Addition { location, .. }
128            | ChangeRef::Deletion { location, .. }
129            | ChangeRef::Modification { location, .. }
130            | ChangeRef::Rewrite { location, .. } => location.as_ref(),
131        }
132    }
133
134    /// Return the `index`, in the case of rewrites referring to the current change.
135    pub fn index(&self) -> usize {
136        match self {
137            ChangeRef::Addition { index, .. }
138            | ChangeRef::Deletion { index, .. }
139            | ChangeRef::Modification { index, .. }
140            | ChangeRef::Rewrite { index, .. } => *index,
141        }
142    }
143
144    /// Return the `entry_mode`, in the case of rewrites referring to the current change.
145    pub fn entry_mode(&self) -> gix_index::entry::Mode {
146        match self {
147            ChangeRef::Addition { entry_mode, .. }
148            | ChangeRef::Deletion { entry_mode, .. }
149            | ChangeRef::Modification { entry_mode, .. }
150            | ChangeRef::Rewrite { entry_mode, .. } => *entry_mode,
151        }
152    }
153
154    /// Return the `id`, in the case of rewrites referring to the current change.
155    pub fn id(&self) -> &gix_hash::oid {
156        match self {
157            ChangeRef::Addition { id, .. }
158            | ChangeRef::Deletion { id, .. }
159            | ChangeRef::Modification { id, .. }
160            | ChangeRef::Rewrite { id, .. } => id,
161        }
162    }
163}
164
165impl rewrites::tracker::Change for ChangeRef<'_, '_> {
166    fn id(&self) -> &gix_hash::oid {
167        match self {
168            ChangeRef::Addition { id, .. } | ChangeRef::Deletion { id, .. } | ChangeRef::Modification { id, .. } => {
169                id.as_ref()
170            }
171            ChangeRef::Rewrite { .. } => {
172                unreachable!("BUG")
173            }
174        }
175    }
176
177    fn relation(&self) -> Option<Relation> {
178        None
179    }
180
181    fn kind(&self) -> ChangeKind {
182        match self {
183            ChangeRef::Addition { .. } => ChangeKind::Addition,
184            ChangeRef::Deletion { .. } => ChangeKind::Deletion,
185            ChangeRef::Modification { .. } => ChangeKind::Modification,
186            ChangeRef::Rewrite { .. } => {
187                unreachable!("BUG: rewrites can't be determined ahead of time")
188            }
189        }
190    }
191
192    fn entry_mode(&self) -> tree::EntryMode {
193        match self {
194            ChangeRef::Addition { entry_mode, .. }
195            | ChangeRef::Deletion { entry_mode, .. }
196            | ChangeRef::Modification { entry_mode, .. }
197            | ChangeRef::Rewrite { entry_mode, .. } => {
198                entry_mode
199                    .to_tree_entry_mode()
200                    // Default is for the impossible case - just don't let it participate in rename tracking.
201                    .unwrap_or(tree::EntryKind::Tree.into())
202            }
203        }
204    }
205
206    fn id_and_entry_mode(&self) -> (&gix_hash::oid, tree::EntryMode) {
207        match self {
208            ChangeRef::Addition { id, entry_mode, .. }
209            | ChangeRef::Deletion { id, entry_mode, .. }
210            | ChangeRef::Modification { id, entry_mode, .. }
211            | ChangeRef::Rewrite { id, entry_mode, .. } => {
212                (
213                    id,
214                    entry_mode
215                        .to_tree_entry_mode()
216                        // Default is for the impossible case - just don't let it participate in rename tracking.
217                        .unwrap_or(tree::EntryKind::Tree.into()),
218                )
219            }
220        }
221    }
222}