@@ -561,6 +561,117 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
561
561
return res ;
562
562
}
563
563
564
+ static void revert_from_diff (struct diff_queue_struct * q ,
565
+ struct diff_options * opt , void * data )
566
+ {
567
+ int i , add_flags = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE ;
568
+
569
+ for (i = 0 ; i < q -> nr ; i ++ ) {
570
+ struct diff_filespec * one = q -> queue [i ]-> one ;
571
+ struct cache_entry * ce ;
572
+
573
+ if (!(one -> mode && !is_null_oid (& one -> oid ))) {
574
+ remove_file_from_index (opt -> repo -> index , one -> path );
575
+ printf (_ ("note: %s is untracked now.\n" ), one -> path );
576
+ } else {
577
+ ce = make_cache_entry (opt -> repo -> index , one -> mode ,
578
+ & one -> oid , one -> path , 0 , 0 );
579
+ if (!ce )
580
+ die (_ ("make_cache_entry failed for path '%s'" ),
581
+ one -> path );
582
+ add_index_entry (opt -> repo -> index , ce , add_flags );
583
+ }
584
+ }
585
+ }
586
+
587
+ static int run_revert (struct add_i_state * s , const struct pathspec * ps ,
588
+ struct file_list * files ,
589
+ struct list_and_choose_options * opts )
590
+ {
591
+ int res = 0 , fd , * selected = NULL ;
592
+ size_t count , i , j ;
593
+
594
+ struct object_id oid ;
595
+ int is_initial = !resolve_ref_unsafe ("HEAD" , RESOLVE_REF_READING , & oid ,
596
+ NULL );
597
+ struct lock_file index_lock ;
598
+ const char * * paths ;
599
+ struct tree * tree ;
600
+ struct diff_options diffopt = { NULL };
601
+
602
+ reset_file_list (files );
603
+ if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
604
+ return -1 ;
605
+
606
+ if (!files -> nr ) {
607
+ putchar ('\n' );
608
+ return 0 ;
609
+ }
610
+
611
+ opts -> prompt = N_ ("Revert" );
612
+ CALLOC_ARRAY (selected , files -> nr );
613
+
614
+ count = list_and_choose ((struct prefix_item * * )files -> file ,
615
+ selected , files -> nr , s , opts );
616
+ if (count <= 0 )
617
+ goto finish_revert ;
618
+
619
+ fd = repo_hold_locked_index (s -> r , & index_lock , LOCK_REPORT_ON_ERROR );
620
+ if (fd < 0 ) {
621
+ res = -1 ;
622
+ goto finish_revert ;
623
+ }
624
+
625
+ if (is_initial )
626
+ oidcpy (& oid , s -> r -> hash_algo -> empty_tree );
627
+ else {
628
+ tree = parse_tree_indirect (& oid );
629
+ if (!tree ) {
630
+ res = error (_ ("Could not parse HEAD^{tree}" ));
631
+ goto finish_revert ;
632
+ }
633
+ oidcpy (& oid , & tree -> object .oid );
634
+ }
635
+
636
+ ALLOC_ARRAY (paths , count + 1 );
637
+ for (i = j = 0 ; i < files -> nr ; i ++ )
638
+ if (selected [i ])
639
+ paths [j ++ ] = files -> file [i ]-> item .name ;
640
+ paths [j ] = NULL ;
641
+
642
+ parse_pathspec (& diffopt .pathspec , 0 ,
643
+ PATHSPEC_PREFER_FULL | PATHSPEC_LITERAL_PATH ,
644
+ NULL , paths );
645
+
646
+ diffopt .output_format = DIFF_FORMAT_CALLBACK ;
647
+ diffopt .format_callback = revert_from_diff ;
648
+ diffopt .flags .override_submodule_config = 1 ;
649
+ diffopt .repo = s -> r ;
650
+
651
+ if (do_diff_cache (& oid , & diffopt ))
652
+ res = -1 ;
653
+ else {
654
+ diffcore_std (& diffopt );
655
+ diff_flush (& diffopt );
656
+ }
657
+ free (paths );
658
+ clear_pathspec (& diffopt .pathspec );
659
+
660
+ if (!res && write_locked_index (s -> r -> index , & index_lock ,
661
+ COMMIT_LOCK ) < 0 )
662
+ res = -1 ;
663
+ else
664
+ res = repo_refresh_and_write_index (s -> r , REFRESH_QUIET , 1 );
665
+ if (!res )
666
+ printf (Q_ ("reverted %d path\n" ,
667
+ "reverted %d paths\n" , count ), (int )count );
668
+
669
+ finish_revert :
670
+ putchar ('\n' );
671
+ free (selected );
672
+ return res ;
673
+ }
674
+
564
675
static int run_help (struct add_i_state * s , const struct pathspec * ps ,
565
676
struct file_list * files ,
566
677
struct list_and_choose_options * opts )
@@ -652,9 +763,10 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
652
763
struct command_item
653
764
status = { { "status" }, run_status },
654
765
update = { { "update" }, run_update },
766
+ revert = { { "revert" }, run_revert },
655
767
help = { { "help" }, run_help };
656
768
struct command_item * commands [] = {
657
- & status , & update ,
769
+ & status , & update , & revert ,
658
770
& help
659
771
};
660
772
0 commit comments