1- use crate :: { bstr:: BStr , diff:: blob:: DiffLineStats , Id } ;
1+ use crate :: bstr:: BString ;
2+ use crate :: ext:: ObjectIdExt ;
3+ use crate :: object:: tree:: diff:: ChangeDetached ;
4+ use crate :: { bstr:: BStr , diff:: blob:: DiffLineStats , Id , Repository } ;
25
36/// An event emitted when finding differences between two trees.
47#[ derive( Debug , Clone , Copy ) ]
@@ -67,6 +70,99 @@ pub enum Event<'a, 'old, 'new> {
6770 } ,
6871}
6972
73+ /// An event emitted when finding differences between two trees.
74+ #[ derive( Debug , Clone ) ]
75+ pub enum EventDetached {
76+ /// An entry was added, like the addition of a file or directory.
77+ Addition {
78+ /// The mode of the added entry.
79+ entry_mode : gix_object:: tree:: EntryMode ,
80+ /// The object id of the added entry.
81+ id : gix_hash:: ObjectId ,
82+ } ,
83+ /// An entry was deleted, like the deletion of a file or directory.
84+ Deletion {
85+ /// The mode of the deleted entry.
86+ entry_mode : gix_object:: tree:: EntryMode ,
87+ /// The object id of the deleted entry.
88+ id : gix_hash:: ObjectId ,
89+ } ,
90+ /// An entry was modified, e.g. changing the contents of a file adjusts its object id and turning
91+ /// a file into a symbolic link adjusts its mode.
92+ Modification {
93+ /// The mode of the entry before the modification.
94+ previous_entry_mode : gix_object:: tree:: EntryMode ,
95+ /// The object id of the entry before the modification.
96+ previous_id : gix_hash:: ObjectId ,
97+
98+ /// The mode of the entry after the modification.
99+ entry_mode : gix_object:: tree:: EntryMode ,
100+ /// The object id after the modification.
101+ id : gix_hash:: ObjectId ,
102+ } ,
103+ /// Entries are considered rewritten if they are not trees and they, according to some understanding of identity, were renamed
104+ /// or copied.
105+ /// In case of renames, this means they originally appeared as [`Deletion`][Event::Deletion] signalling their source as well as an
106+ /// [`Addition`][Event::Addition] acting as destination.
107+ ///
108+ /// In case of copies, the `copy` flag is true and typically represents a perfect copy of a source was made.
109+ ///
110+ /// This variant can only be encountered if [rewrite tracking][super::Platform::track_rewrites()] is enabled.
111+ ///
112+ /// Note that mode changes may have occurred as well, i.e. changes from executable to non-executable or vice-versa.
113+ Rewrite {
114+ /// The location of the source of the rename operation.
115+ ///
116+ /// It may be empty if neither [file names][super::Platform::track_filename()] nor [file paths][super::Platform::track_path()]
117+ /// are tracked.
118+ source_location : BString ,
119+ /// The mode of the entry before the rename.
120+ source_entry_mode : gix_object:: tree:: EntryMode ,
121+ /// The object id of the entry before the rename.
122+ ///
123+ /// Note that this is the same as `id` if we require the [similarity to be 100%][super::Rewrites::percentage], but may
124+ /// be different otherwise.
125+ source_id : gix_hash:: ObjectId ,
126+ /// Information about the diff we performed to detect similarity and match the `source_id` with the current state at `id`.
127+ /// It's `None` if `source_id` is equal to `id`, as identity made an actual diff computation unnecessary.
128+ diff : Option < DiffLineStats > ,
129+ /// The mode of the entry after the rename.
130+ /// It could differ but still be considered a rename as we are concerned only about content.
131+ entry_mode : gix_object:: tree:: EntryMode ,
132+ /// The object id after the rename.
133+ id : gix_hash:: ObjectId ,
134+ /// If true, this rewrite is created by copy, and `source_id` is pointing to its source. Otherwise, it's a rename, and `source_id`
135+ /// points to a deleted object, as renames are tracked as deletions and additions of the same or similar content.
136+ copy : bool ,
137+ } ,
138+ }
139+
140+ /// Lifecycle
141+ impl super :: Change < ' _ , ' _ , ' _ > {
142+ /// Detach the repository instance to obtain a fully-owned version
143+ pub fn detach ( self ) -> ChangeDetached {
144+ ChangeDetached {
145+ location : self . location . to_owned ( ) ,
146+ event : self . event . detach ( ) ,
147+ }
148+ }
149+ }
150+
151+ /// Lifecycle
152+ impl ChangeDetached {
153+ /// Return an attached version of this instance that uses `old_repo` for previous values and `new_repo` for current values.
154+ pub fn attach < ' old , ' new > (
155+ & self ,
156+ old_repo : & ' old Repository ,
157+ new_repo : & ' new Repository ,
158+ ) -> super :: Change < ' _ , ' old , ' new > {
159+ super :: Change {
160+ location : self . location . as_ref ( ) ,
161+ event : self . event . attach ( old_repo, new_repo) ,
162+ }
163+ }
164+ }
165+
70166impl < ' a , ' old , ' new > super :: Change < ' a , ' old , ' new > {
71167 /// Produce a platform for performing a line-diff no matter whether the underlying [Event] is an addition, modification,
72168 /// deletion or rewrite.
@@ -86,6 +182,95 @@ impl<'a, 'old, 'new> super::Change<'a, 'old, 'new> {
86182 }
87183}
88184
185+ /// Lifecycle
186+ impl Event < ' _ , ' _ , ' _ > {
187+ /// Detach the repository instance to obtain a fully-owned version
188+ pub fn detach ( self ) -> EventDetached {
189+ match self {
190+ Event :: Addition { entry_mode, id } => EventDetached :: Addition {
191+ entry_mode,
192+ id : id. detach ( ) ,
193+ } ,
194+ Event :: Deletion { entry_mode, id } => EventDetached :: Deletion {
195+ entry_mode,
196+ id : id. detach ( ) ,
197+ } ,
198+ Event :: Modification {
199+ previous_entry_mode,
200+ previous_id,
201+ entry_mode,
202+ id,
203+ } => EventDetached :: Modification {
204+ previous_entry_mode,
205+ previous_id : previous_id. detach ( ) ,
206+ entry_mode,
207+ id : id. detach ( ) ,
208+ } ,
209+ Event :: Rewrite {
210+ source_location,
211+ source_entry_mode,
212+ source_id,
213+ diff,
214+ entry_mode,
215+ id,
216+ copy,
217+ } => EventDetached :: Rewrite {
218+ source_location : source_location. to_owned ( ) ,
219+ source_entry_mode,
220+ source_id : source_id. detach ( ) ,
221+ diff,
222+ entry_mode,
223+ id : id. detach ( ) ,
224+ copy,
225+ } ,
226+ }
227+ }
228+ }
229+
230+ impl EventDetached {
231+ /// Return an attached version of this instance that uses `old_repo` for previous values and `new_repo` for current values.
232+ pub fn attach < ' old , ' new > ( & self , old_repo : & ' old Repository , new_repo : & ' new Repository ) -> Event < ' _ , ' old , ' new > {
233+ match self {
234+ EventDetached :: Addition { entry_mode, id } => Event :: Addition {
235+ entry_mode : * entry_mode,
236+ id : id. attach ( new_repo) ,
237+ } ,
238+ EventDetached :: Deletion { entry_mode, id } => Event :: Deletion {
239+ entry_mode : * entry_mode,
240+ id : id. attach ( old_repo) ,
241+ } ,
242+ EventDetached :: Modification {
243+ previous_entry_mode,
244+ previous_id,
245+ entry_mode,
246+ id,
247+ } => Event :: Modification {
248+ previous_entry_mode : * previous_entry_mode,
249+ previous_id : previous_id. attach ( old_repo) ,
250+ entry_mode : * entry_mode,
251+ id : id. attach ( new_repo) ,
252+ } ,
253+ EventDetached :: Rewrite {
254+ source_location,
255+ source_entry_mode,
256+ source_id,
257+ diff,
258+ entry_mode,
259+ id,
260+ copy,
261+ } => Event :: Rewrite {
262+ source_location : source_location. as_ref ( ) ,
263+ source_entry_mode : * source_entry_mode,
264+ source_id : source_id. attach ( old_repo) ,
265+ diff : * diff,
266+ entry_mode : * entry_mode,
267+ id : id. attach ( new_repo) ,
268+ copy : * copy,
269+ } ,
270+ }
271+ }
272+ }
273+
89274impl < ' a , ' old , ' new > Event < ' a , ' old , ' new > {
90275 /// Return the current mode of this instance.
91276 pub fn entry_mode ( & self ) -> gix_object:: tree:: EntryMode {
0 commit comments