@@ -85,85 +85,41 @@ pub struct IndexEntry {
8585 pub path : Vec < u8 > ,
8686}
8787
88- // We cannot return raw::git_index_entry instances directly, as they rely on
89- // a CString which is owned by the function. To make the pointer to the CString
90- // valid during usage of raw::git_index_entry, we supply the index entry in a
91- // callback where pointers to the CString are valid.
92- fn try_raw_entries < const N : usize > (
93- entries : & [ Option < & IndexEntry > ; N ] ,
94- cb : impl FnOnce ( & [ * const raw:: git_index_entry ; N ] ) -> Result < ( ) , Error > ,
95- ) -> Result < ( ) , Error > {
96- let mut paths: [ Option < CString > ; N ] = unsafe { std:: mem:: MaybeUninit :: uninit ( ) . assume_init ( ) } ;
97- for ( path, entry) in paths. iter_mut ( ) . zip ( entries. iter ( ) ) {
98- let c_path = if let Some ( entry) = entry {
99- Some ( CString :: new ( & entry. path [ ..] ) ?)
88+ impl IndexEntry {
89+ // Expecting c_path to contain a CString with the contents of self.path
90+ fn to_raw ( & self , c_path : & CString ) -> raw:: git_index_entry {
91+ // libgit2 encodes the length of the path in the lower bits of the
92+ // `flags` entry, so mask those out and recalculate here to ensure we
93+ // don't corrupt anything.
94+ let mut flags = self . flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
95+
96+ if self . path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
97+ flags |= self . path . len ( ) as u16 ;
10098 } else {
101- None
102- } ;
103-
104- let path_ptr: * mut Option < CString > = path;
105- unsafe {
106- path_ptr. write ( c_path) ;
99+ flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
107100 }
108- }
109-
110- let mut raw_entries: [ Option < raw:: git_index_entry > ; N ] =
111- unsafe { std:: mem:: MaybeUninit :: uninit ( ) . assume_init ( ) } ;
112- for ( raw_entry, ( entry, path) ) in raw_entries. iter_mut ( ) . zip ( entries. iter ( ) . zip ( & paths) ) {
113- let c_raw_entry = if let Some ( entry) = entry {
114- // libgit2 encodes the length of the path in the lower bits of the
115- // `flags` entry, so mask those out and recalculate here to ensure we
116- // don't corrupt anything.
117- let mut flags = entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
118-
119- if entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
120- flags |= entry. path . len ( ) as u16 ;
121- } else {
122- flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
123- }
124101
125- Some ( raw:: git_index_entry {
126- dev : entry. dev ,
127- ino : entry. ino ,
128- mode : entry. mode ,
129- uid : entry. uid ,
130- gid : entry. gid ,
131- file_size : entry. file_size ,
132- id : unsafe { * entry. id . raw ( ) } ,
133- flags,
134- flags_extended : entry. flags_extended ,
135- path : path. as_ref ( ) . unwrap ( ) . as_ptr ( ) ,
136- mtime : raw:: git_index_time {
137- seconds : entry. mtime . seconds ( ) ,
138- nanoseconds : entry. mtime . nanoseconds ( ) ,
139- } ,
140- ctime : raw:: git_index_time {
141- seconds : entry. ctime . seconds ( ) ,
142- nanoseconds : entry. ctime . nanoseconds ( ) ,
143- } ,
144- } )
145- } else {
146- None
147- } ;
148-
149- let raw_entry_ptr: * mut Option < raw:: git_index_entry > = raw_entry;
150- unsafe {
151- raw_entry_ptr. write ( c_raw_entry) ;
152- }
153- }
154-
155- let mut raw_entry_ptrs: [ * const raw:: git_index_entry ; N ] =
156- unsafe { std:: mem:: MaybeUninit :: uninit ( ) . assume_init ( ) } ;
157- for ( raw_entry_ptr, raw_entry) in raw_entry_ptrs. iter_mut ( ) . zip ( raw_entries. iter ( ) ) {
158- let c_raw_entry_ptr = raw_entry. as_ref ( ) . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
159-
160- let raw_entry_ptr_ptr: * mut * const raw:: git_index_entry = raw_entry_ptr;
161- unsafe {
162- raw_entry_ptr_ptr. write ( c_raw_entry_ptr) ;
102+ raw:: git_index_entry {
103+ dev : self . dev ,
104+ ino : self . ino ,
105+ mode : self . mode ,
106+ uid : self . uid ,
107+ gid : self . gid ,
108+ file_size : self . file_size ,
109+ id : unsafe { * self . id . raw ( ) } ,
110+ flags,
111+ flags_extended : self . flags_extended ,
112+ path : c_path. as_ptr ( ) ,
113+ mtime : raw:: git_index_time {
114+ seconds : self . mtime . seconds ( ) ,
115+ nanoseconds : self . mtime . nanoseconds ( ) ,
116+ } ,
117+ ctime : raw:: git_index_time {
118+ seconds : self . ctime . seconds ( ) ,
119+ nanoseconds : self . ctime . nanoseconds ( ) ,
120+ } ,
163121 }
164122 }
165-
166- cb ( & raw_entry_ptrs)
167123}
168124
169125impl Index {
@@ -226,12 +182,13 @@ impl Index {
226182 /// given 'source_entry', it will be replaced. Otherwise, the 'source_entry'
227183 /// will be added.
228184 pub fn add ( & mut self , entry : & IndexEntry ) -> Result < ( ) , Error > {
229- try_raw_entries ( & [ Some ( entry) ] , |raws| {
230- unsafe {
231- try_call ! ( raw:: git_index_add( self . raw, raws[ 0 ] ) ) ;
232- }
233- Ok ( ( ) )
234- } )
185+ let c_path = CString :: new ( & entry. path [ ..] ) ?;
186+ let raw_entry = entry. to_raw ( & c_path) ;
187+
188+ unsafe {
189+ try_call ! ( raw:: git_index_add( self . raw, & raw_entry) ) ;
190+ }
191+ Ok ( ( ) )
235192 }
236193
237194 /// Add or update an index entry from a buffer in memory
@@ -252,14 +209,17 @@ impl Index {
252209 /// no longer be marked as conflicting. The data about the conflict will be
253210 /// moved to the "resolve undo" (REUC) section.
254211 pub fn add_frombuffer ( & mut self , entry : & IndexEntry , data : & [ u8 ] ) -> Result < ( ) , Error > {
255- try_raw_entries ( & [ Some ( entry) ] , |raws| {
256- unsafe {
257- let ptr = data. as_ptr ( ) as * const c_void ;
258- let len = data. len ( ) as size_t ;
259- try_call ! ( raw:: git_index_add_frombuffer( self . raw, raws[ 0 ] , ptr, len) ) ;
260- }
261- Ok ( ( ) )
262- } )
212+ let c_path = CString :: new ( & entry. path [ ..] ) ?;
213+ let raw_entry = entry. to_raw ( & c_path) ;
214+
215+ unsafe {
216+ let ptr = data. as_ptr ( ) as * const c_void ;
217+ let len = data. len ( ) as size_t ;
218+ try_call ! ( raw:: git_index_add_frombuffer(
219+ self . raw, & raw_entry, ptr, len
220+ ) ) ;
221+ }
222+ Ok ( ( ) )
263223 }
264224
265225 /// Add or update an index entry from a file on disk
@@ -443,18 +403,58 @@ impl Index {
443403 our_entry : Option < & IndexEntry > ,
444404 their_entry : Option < & IndexEntry > ,
445405 ) -> Result < ( ) , Error > {
446- try_raw_entries (
447- & [ ancestor_entry, our_entry, their_entry] ,
448- |raw_entries| unsafe {
449- try_call ! ( raw:: git_index_conflict_add(
450- self . raw,
451- raw_entries[ 0 ] ,
452- raw_entries[ 1 ] ,
453- raw_entries[ 2 ]
454- ) ) ;
455- Ok ( ( ) )
456- } ,
457- )
406+ let ancestor_c_path = if let Some ( entry) = ancestor_entry {
407+ Some ( CString :: new ( & entry. path [ ..] ) ?)
408+ } else {
409+ None
410+ } ;
411+ let our_c_path = if let Some ( entry) = our_entry {
412+ Some ( CString :: new ( & entry. path [ ..] ) ?)
413+ } else {
414+ None
415+ } ;
416+ let their_c_path = if let Some ( entry) = their_entry {
417+ Some ( CString :: new ( & entry. path [ ..] ) ?)
418+ } else {
419+ None
420+ } ;
421+
422+ let mut raw_ancestor_entry = None ;
423+ let mut raw_our_entry = None ;
424+ let mut raw_their_entry = None ;
425+
426+ if let Some ( entry) = ancestor_entry {
427+ let c_path = ancestor_c_path. as_ref ( ) . unwrap ( ) ;
428+ raw_ancestor_entry = Some ( entry. to_raw ( & c_path) ) ;
429+ }
430+ if let Some ( entry) = our_entry {
431+ let c_path = our_c_path. as_ref ( ) . unwrap ( ) ;
432+ raw_our_entry = Some ( entry. to_raw ( & c_path) ) ;
433+ }
434+ if let Some ( entry) = their_entry {
435+ let c_path = their_c_path. as_ref ( ) . unwrap ( ) ;
436+ raw_their_entry = Some ( entry. to_raw ( & c_path) ) ;
437+ }
438+
439+ let raw_ancestor_entry_ptr = raw_ancestor_entry
440+ . as_ref ( )
441+ . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
442+ let raw_our_entry_ptr = raw_our_entry
443+ . as_ref ( )
444+ . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
445+ let raw_their_entry_ptr = raw_their_entry
446+ . as_ref ( )
447+ . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
448+
449+ unsafe {
450+ try_call ! ( raw:: git_index_conflict_add(
451+ self . raw,
452+ raw_ancestor_entry_ptr,
453+ raw_our_entry_ptr,
454+ raw_their_entry_ptr
455+ ) ) ;
456+ }
457+ Ok ( ( ) )
458458 }
459459
460460 /// Remove all conflicts in the index (entries with a stage greater than 0).
0 commit comments