@@ -85,6 +85,70 @@ pub struct IndexEntry {
85
85
pub path : Vec < u8 > ,
86
86
}
87
87
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 (
93
+ entries : & [ Option < & IndexEntry > ] ,
94
+ cb : impl FnOnce ( & [ * const raw:: git_index_entry ] ) -> Result < ( ) , Error > ,
95
+ ) -> Result < ( ) , Error > {
96
+ let paths = entries. iter ( )
97
+ . map ( |entry| {
98
+ if let Some ( entry) = entry {
99
+ CString :: new ( & entry. path [ ..] ) . map ( |ok| Some ( ok) )
100
+ } else {
101
+ Ok ( None )
102
+ }
103
+ } )
104
+ . collect :: < Result < Vec < Option < CString > > , std:: ffi:: NulError > > ( ) ?;
105
+
106
+ let raw_entries = entries. iter ( ) . zip ( & paths) . map ( |( entry, path) | {
107
+ if let Some ( entry) = entry {
108
+ // libgit2 encodes the length of the path in the lower bits of the
109
+ // `flags` entry, so mask those out and recalculate here to ensure we
110
+ // don't corrupt anything.
111
+ let mut flags = entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
112
+
113
+ if entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
114
+ flags |= entry. path . len ( ) as u16 ;
115
+ } else {
116
+ flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
117
+ }
118
+
119
+ unsafe {
120
+ Some ( raw:: git_index_entry {
121
+ dev : entry. dev ,
122
+ ino : entry. ino ,
123
+ mode : entry. mode ,
124
+ uid : entry. uid ,
125
+ gid : entry. gid ,
126
+ file_size : entry. file_size ,
127
+ id : * entry. id . raw ( ) ,
128
+ flags,
129
+ flags_extended : entry. flags_extended ,
130
+ path : path. as_ref ( ) . unwrap ( ) . as_ptr ( ) ,
131
+ mtime : raw:: git_index_time {
132
+ seconds : entry. mtime . seconds ( ) ,
133
+ nanoseconds : entry. mtime . nanoseconds ( ) ,
134
+ } ,
135
+ ctime : raw:: git_index_time {
136
+ seconds : entry. ctime . seconds ( ) ,
137
+ nanoseconds : entry. ctime . nanoseconds ( ) ,
138
+ } ,
139
+ } )
140
+ }
141
+ } else {
142
+ None
143
+ }
144
+ } ) . collect :: < Vec < _ > > ( ) ;
145
+ let raw_entry_ptrs = raw_entries. iter ( )
146
+ . map ( |opt| opt. as_ref ( ) . map_or_else ( std:: ptr:: null, |ptr| ptr) )
147
+ . collect :: < Vec < _ > > ( ) ;
148
+
149
+ cb ( & raw_entry_ptrs)
150
+ }
151
+
88
152
impl Index {
89
153
/// Creates a new in-memory index.
90
154
///
@@ -145,43 +209,12 @@ impl Index {
145
209
/// given 'source_entry', it will be replaced. Otherwise, the 'source_entry'
146
210
/// will be added.
147
211
pub fn add ( & mut self , entry : & IndexEntry ) -> Result < ( ) , Error > {
148
- let path = CString :: new ( & entry. path [ ..] ) ?;
149
-
150
- // libgit2 encodes the length of the path in the lower bits of the
151
- // `flags` entry, so mask those out and recalculate here to ensure we
152
- // don't corrupt anything.
153
- let mut flags = entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
154
-
155
- if entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
156
- flags |= entry. path . len ( ) as u16 ;
157
- } else {
158
- flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
159
- }
160
-
161
- unsafe {
162
- let raw = raw:: git_index_entry {
163
- dev : entry. dev ,
164
- ino : entry. ino ,
165
- mode : entry. mode ,
166
- uid : entry. uid ,
167
- gid : entry. gid ,
168
- file_size : entry. file_size ,
169
- id : * entry. id . raw ( ) ,
170
- flags,
171
- flags_extended : entry. flags_extended ,
172
- path : path. as_ptr ( ) ,
173
- mtime : raw:: git_index_time {
174
- seconds : entry. mtime . seconds ( ) ,
175
- nanoseconds : entry. mtime . nanoseconds ( ) ,
176
- } ,
177
- ctime : raw:: git_index_time {
178
- seconds : entry. ctime . seconds ( ) ,
179
- nanoseconds : entry. ctime . nanoseconds ( ) ,
180
- } ,
181
- } ;
182
- try_call ! ( raw:: git_index_add( self . raw, & raw) ) ;
212
+ try_raw_entries ( & [ Some ( entry) ] , |raws| {
213
+ unsafe {
214
+ try_call ! ( raw:: git_index_add( self . raw, raws[ 0 ] ) ) ;
215
+ }
183
216
Ok ( ( ) )
184
- }
217
+ } )
185
218
}
186
219
187
220
/// Add or update an index entry from a buffer in memory
@@ -202,46 +235,14 @@ impl Index {
202
235
/// no longer be marked as conflicting. The data about the conflict will be
203
236
/// moved to the "resolve undo" (REUC) section.
204
237
pub fn add_frombuffer ( & mut self , entry : & IndexEntry , data : & [ u8 ] ) -> Result < ( ) , Error > {
205
- let path = CString :: new ( & entry. path [ ..] ) ?;
206
-
207
- // libgit2 encodes the length of the path in the lower bits of the
208
- // `flags` entry, so mask those out and recalculate here to ensure we
209
- // don't corrupt anything.
210
- let mut flags = entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
211
-
212
- if entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
213
- flags |= entry. path . len ( ) as u16 ;
214
- } else {
215
- flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
216
- }
217
-
218
- unsafe {
219
- let raw = raw:: git_index_entry {
220
- dev : entry. dev ,
221
- ino : entry. ino ,
222
- mode : entry. mode ,
223
- uid : entry. uid ,
224
- gid : entry. gid ,
225
- file_size : entry. file_size ,
226
- id : * entry. id . raw ( ) ,
227
- flags,
228
- flags_extended : entry. flags_extended ,
229
- path : path. as_ptr ( ) ,
230
- mtime : raw:: git_index_time {
231
- seconds : entry. mtime . seconds ( ) ,
232
- nanoseconds : entry. mtime . nanoseconds ( ) ,
233
- } ,
234
- ctime : raw:: git_index_time {
235
- seconds : entry. ctime . seconds ( ) ,
236
- nanoseconds : entry. ctime . nanoseconds ( ) ,
237
- } ,
238
- } ;
239
-
240
- let ptr = data. as_ptr ( ) as * const c_void ;
241
- let len = data. len ( ) as size_t ;
242
- try_call ! ( raw:: git_index_add_frombuffer( self . raw, & raw, ptr, len) ) ;
238
+ try_raw_entries ( & [ Some ( entry) ] , |raws| {
239
+ unsafe {
240
+ let ptr = data. as_ptr ( ) as * const c_void ;
241
+ let len = data. len ( ) as size_t ;
242
+ try_call ! ( raw:: git_index_add_frombuffer( self . raw, raws[ 0 ] , ptr, len) ) ;
243
+ }
243
244
Ok ( ( ) )
244
- }
245
+ } )
245
246
}
246
247
247
248
/// Add or update an index entry from a file on disk
@@ -425,124 +426,17 @@ impl Index {
425
426
our_entry : Option < & IndexEntry > ,
426
427
their_entry : Option < & IndexEntry > ,
427
428
) -> Result < ( ) , Error > {
428
- let mut ancestor_raw: Option < raw:: git_index_entry > = None ;
429
- let mut our_raw: Option < raw:: git_index_entry > = None ;
430
- let mut their_raw: Option < raw:: git_index_entry > = None ;
431
-
432
- if let Some ( ancestor_entry) = ancestor_entry {
433
- let ancestor_path = CString :: new ( & ancestor_entry. path [ ..] ) ?;
434
- let mut ancestor_flags = ancestor_entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
435
-
436
- if ancestor_entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
437
- ancestor_flags |= ancestor_entry. path . len ( ) as u16 ;
438
- } else {
439
- ancestor_flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
440
- }
441
-
442
- unsafe {
443
- ancestor_raw = Some ( raw:: git_index_entry {
444
- dev : ancestor_entry. dev ,
445
- ino : ancestor_entry. ino ,
446
- mode : ancestor_entry. mode ,
447
- uid : ancestor_entry. uid ,
448
- gid : ancestor_entry. gid ,
449
- file_size : ancestor_entry. file_size ,
450
- id : * ancestor_entry. id . raw ( ) ,
451
- flags : ancestor_flags,
452
- flags_extended : ancestor_entry. flags_extended ,
453
- path : ancestor_path. as_ptr ( ) ,
454
- mtime : raw:: git_index_time {
455
- seconds : ancestor_entry. mtime . seconds ( ) ,
456
- nanoseconds : ancestor_entry. mtime . nanoseconds ( ) ,
457
- } ,
458
- ctime : raw:: git_index_time {
459
- seconds : ancestor_entry. ctime . seconds ( ) ,
460
- nanoseconds : ancestor_entry. ctime . nanoseconds ( ) ,
461
- } ,
462
- } ) ;
463
- }
464
- }
465
-
466
- if let Some ( our_entry) = our_entry {
467
- let our_path = CString :: new ( & our_entry. path [ ..] ) ?;
468
- let mut our_flags = our_entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
469
-
470
- if our_entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
471
- our_flags |= our_entry. path . len ( ) as u16 ;
472
- } else {
473
- our_flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
474
- }
475
-
476
- unsafe {
477
- our_raw = Some ( raw:: git_index_entry {
478
- dev : our_entry. dev ,
479
- ino : our_entry. ino ,
480
- mode : our_entry. mode ,
481
- uid : our_entry. uid ,
482
- gid : our_entry. gid ,
483
- file_size : our_entry. file_size ,
484
- id : * our_entry. id . raw ( ) ,
485
- flags : our_flags,
486
- flags_extended : our_entry. flags_extended ,
487
- path : our_path. as_ptr ( ) ,
488
- mtime : raw:: git_index_time {
489
- seconds : our_entry. mtime . seconds ( ) ,
490
- nanoseconds : our_entry. mtime . nanoseconds ( ) ,
491
- } ,
492
- ctime : raw:: git_index_time {
493
- seconds : our_entry. ctime . seconds ( ) ,
494
- nanoseconds : our_entry. ctime . nanoseconds ( ) ,
495
- } ,
496
- } ) ;
497
- }
498
- }
499
-
500
- if let Some ( their_entry) = their_entry {
501
- let their_path = CString :: new ( & their_entry. path [ ..] ) ?;
502
- let mut their_flags = their_entry. flags & !raw:: GIT_INDEX_ENTRY_NAMEMASK ;
503
-
504
- if their_entry. path . len ( ) < raw:: GIT_INDEX_ENTRY_NAMEMASK as usize {
505
- their_flags |= their_entry. path . len ( ) as u16 ;
506
- } else {
507
- their_flags |= raw:: GIT_INDEX_ENTRY_NAMEMASK ;
508
- }
509
-
429
+ try_raw_entries ( & [ ancestor_entry, our_entry, their_entry] , |raw_entries| {
510
430
unsafe {
511
- their_raw = Some ( raw:: git_index_entry {
512
- dev : their_entry. dev ,
513
- ino : their_entry. ino ,
514
- mode : their_entry. mode ,
515
- uid : their_entry. uid ,
516
- gid : their_entry. gid ,
517
- file_size : their_entry. file_size ,
518
- id : * their_entry. id . raw ( ) ,
519
- flags : their_flags,
520
- flags_extended : their_entry. flags_extended ,
521
- path : their_path. as_ptr ( ) ,
522
- mtime : raw:: git_index_time {
523
- seconds : their_entry. mtime . seconds ( ) ,
524
- nanoseconds : their_entry. mtime . nanoseconds ( ) ,
525
- } ,
526
- ctime : raw:: git_index_time {
527
- seconds : their_entry. ctime . seconds ( ) ,
528
- nanoseconds : their_entry. ctime . nanoseconds ( ) ,
529
- } ,
530
- } ) ;
431
+ try_call ! ( raw:: git_index_conflict_add(
432
+ self . raw,
433
+ raw_entries[ 0 ] ,
434
+ raw_entries[ 1 ] ,
435
+ raw_entries[ 2 ]
436
+ ) ) ;
437
+ Ok ( ( ) )
531
438
}
532
- }
533
-
534
- let ancestor_raw_ptr = ancestor_raw. as_ref ( ) . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
535
- let our_raw_ptr = our_raw. as_ref ( ) . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
536
- let their_raw_ptr = their_raw. as_ref ( ) . map_or_else ( std:: ptr:: null, |ptr| ptr) ;
537
- unsafe {
538
- try_call ! ( raw:: git_index_conflict_add(
539
- self . raw,
540
- ancestor_raw_ptr,
541
- our_raw_ptr,
542
- their_raw_ptr
543
- ) ) ;
544
- Ok ( ( ) )
545
- }
439
+ } )
546
440
}
547
441
548
442
/// Remove all conflicts in the index (entries with a stage greater than 0).
0 commit comments