@@ -412,6 +412,182 @@ impl Index {
412
412
unsafe { raw:: git_index_has_conflicts ( self . raw ) == 1 }
413
413
}
414
414
415
+ /// Add or update index entries to represent a conflict. Any staged entries
416
+ /// that exist at the given paths will be removed.
417
+ ///
418
+ /// The entries are the entries from the tree included in the merge. Any entry
419
+ /// may be `None` to indicate that that file was not present in the trees during
420
+ /// the merge. For example, ancestor_entry may be `None` to indicate that a file
421
+ /// was added in both branches and must be resolved.
422
+ pub fn conflict_add (
423
+ & self ,
424
+ ancestor_entry : Option < & IndexEntry > ,
425
+ our_entry : Option < & IndexEntry > ,
426
+ their_entry : Option < & IndexEntry > ,
427
+ ) -> 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
+
510
+ 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
+ } ) ;
531
+ }
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( self . raw, ancestor_raw_ptr, our_raw_ptr, their_raw_ptr) ) ;
539
+ Ok ( ( ) )
540
+ }
541
+ }
542
+
543
+ /// Remove all conflicts in the index (entries with a stage greater than 0).
544
+ pub fn conflict_cleanup ( & self ) -> Result < ( ) , Error > {
545
+ unsafe {
546
+ try_call ! ( raw:: git_index_conflict_cleanup( self . raw) ) ;
547
+ Ok ( ( ) )
548
+ }
549
+ }
550
+
551
+ /// Get the index entries that represent a conflict of a single file.
552
+ ///
553
+ /// The entries are not modifiable.
554
+ pub fn conflict_get ( & self , path : & Path ) -> Result < IndexConflict , Error > {
555
+ let path = path_to_repo_path ( path) ?;
556
+ let mut ancestor = ptr:: null ( ) ;
557
+ let mut our = ptr:: null ( ) ;
558
+ let mut their = ptr:: null ( ) ;
559
+
560
+ unsafe {
561
+ try_call ! (
562
+ raw:: git_index_conflict_get( & mut ancestor, & mut our, & mut their, self . raw, path)
563
+ ) ;
564
+ Ok ( IndexConflict {
565
+ ancestor : match ancestor. is_null ( ) {
566
+ false => Some ( IndexEntry :: from_raw ( * ancestor) ) ,
567
+ true => None ,
568
+ } ,
569
+ our : match our. is_null ( ) {
570
+ false => Some ( IndexEntry :: from_raw ( * our) ) ,
571
+ true => None ,
572
+ } ,
573
+ their : match their. is_null ( ) {
574
+ false => Some ( IndexEntry :: from_raw ( * their) ) ,
575
+ true => None ,
576
+ } ,
577
+ } )
578
+ }
579
+ }
580
+
581
+ /// Removes the index entries that represent a conflict of a single file.
582
+ pub fn conflict_remove ( & self , path : & Path ) -> Result < ( ) , Error > {
583
+ let path = path_to_repo_path ( path) ?;
584
+
585
+ unsafe {
586
+ try_call ! ( raw:: git_index_conflict_remove( self . raw, path) ) ;
587
+ Ok ( ( ) )
588
+ }
589
+ }
590
+
415
591
/// Get the full path to the index file on disk.
416
592
///
417
593
/// Returns `None` if this is an in-memory index.
0 commit comments