66#include "revision.h"
77#include "refs.h"
88#include "string-list.h"
9+ #include "lockfile.h"
910
1011struct add_i_state {
1112 struct repository * r ;
@@ -377,6 +378,7 @@ struct adddel {
377378};
378379
379380struct file_item {
381+ size_t prefix_length ;
380382 struct adddel index , worktree ;
381383};
382384
@@ -471,7 +473,7 @@ enum modified_files_filter {
471473
472474static int get_modified_files (struct repository * r ,
473475 enum modified_files_filter filter ,
474- struct string_list * files ,
476+ struct prefix_item_list * files ,
475477 const struct pathspec * ps )
476478{
477479 struct object_id head_oid ;
@@ -484,8 +486,8 @@ static int get_modified_files(struct repository *r,
484486 repo_read_index_preload (r , ps , 0 ) < 0 )
485487 return error (_ ("could not read index" ));
486488
487- string_list_clear (files , 1 );
488- s .files = files ;
489+ prefix_item_list_clear (files );
490+ s .files = & files -> items ;
489491 hashmap_init (& s .file_map , pathname_entry_cmp , NULL , 0 );
490492
491493 for (i = 0 ; i < 2 ; i ++ ) {
@@ -524,7 +526,7 @@ static int get_modified_files(struct repository *r,
524526 hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
525527
526528 /* While the diffs are ordered already, we ran *two* diffs... */
527- string_list_sort (files );
529+ string_list_sort (& files -> items );
528530
529531 return 0 ;
530532}
@@ -559,43 +561,105 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
559561}
560562
561563struct print_file_item_data {
562- const char * modified_fmt ;
563- struct strbuf buf , index , worktree ;
564+ const char * modified_fmt , * color , * reset ;
565+ struct strbuf buf , name , index , worktree ;
564566};
565567
566568static void print_file_item (int i , int selected , struct string_list_item * item ,
567569 void * print_file_item_data )
568570{
569571 struct file_item * c = item -> util ;
570572 struct print_file_item_data * d = print_file_item_data ;
573+ const char * highlighted = NULL ;
571574
572575 strbuf_reset (& d -> index );
573576 strbuf_reset (& d -> worktree );
574577 strbuf_reset (& d -> buf );
575578
579+ /* Format the item with the prefix highlighted. */
580+ if (c -> prefix_length > 0 &&
581+ is_valid_prefix (item -> string , c -> prefix_length )) {
582+ strbuf_reset (& d -> name );
583+ strbuf_addf (& d -> name , "%s%.*s%s%s" , d -> color ,
584+ (int )c -> prefix_length , item -> string , d -> reset ,
585+ item -> string + c -> prefix_length );
586+ highlighted = d -> name .buf ;
587+ }
588+
576589 render_adddel (& d -> worktree , & c -> worktree , _ ("nothing" ));
577590 render_adddel (& d -> index , & c -> index , _ ("unchanged" ));
578- strbuf_addf (& d -> buf , d -> modified_fmt ,
579- d -> index .buf , d -> worktree .buf , item -> string );
591+
592+ strbuf_addf (& d -> buf , d -> modified_fmt , d -> index .buf , d -> worktree .buf ,
593+ highlighted ? highlighted : item -> string );
580594
581595 printf ("%c%2d: %s" , selected ? '*' : ' ' , i + 1 , d -> buf .buf );
582596}
583597
584598static int run_status (struct add_i_state * s , const struct pathspec * ps ,
585- struct string_list * files , struct list_options * opts )
599+ struct prefix_item_list * files ,
600+ struct list_and_choose_options * opts )
586601{
587602 if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
588603 return -1 ;
589604
590- list (s , files , NULL , opts );
605+ list (s , & files -> items , NULL , & opts -> list_opts );
591606 putchar ('\n' );
592607
593608 return 0 ;
594609}
595610
611+ static int run_update (struct add_i_state * s , const struct pathspec * ps ,
612+ struct prefix_item_list * files ,
613+ struct list_and_choose_options * opts )
614+ {
615+ int res = 0 , fd ;
616+ size_t count , i ;
617+ struct lock_file index_lock ;
618+
619+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
620+ return -1 ;
621+
622+ if (!files -> items .nr ) {
623+ putchar ('\n' );
624+ return 0 ;
625+ }
626+
627+ opts -> prompt = N_ ("Update" );
628+ count = list_and_choose (s , files , opts );
629+ if (count <= 0 ) {
630+ putchar ('\n' );
631+ return 0 ;
632+ }
633+
634+ fd = repo_hold_locked_index (s -> r , & index_lock , LOCK_REPORT_ON_ERROR );
635+ if (fd < 0 ) {
636+ putchar ('\n' );
637+ return -1 ;
638+ }
639+
640+ for (i = 0 ; i < files -> items .nr ; i ++ ) {
641+ const char * name = files -> items .items [i ].string ;
642+ if (files -> selected [i ] &&
643+ add_file_to_index (s -> r -> index , name , 0 ) < 0 ) {
644+ res = error (_ ("could not stage '%s'" ), name );
645+ break ;
646+ }
647+ }
648+
649+ if (!res && write_locked_index (s -> r -> index , & index_lock , COMMIT_LOCK ) < 0 )
650+ res = error (_ ("could not write index" ));
651+
652+ if (!res )
653+ printf (Q_ ("updated %d path\n" ,
654+ "updated %d paths\n" , count ), (int )count );
655+
656+ putchar ('\n' );
657+ return res ;
658+ }
659+
596660static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
597- struct string_list * unused_files ,
598- struct list_options * unused_opts )
661+ struct prefix_item_list * unused_files ,
662+ struct list_and_choose_options * unused_opts )
599663{
600664 color_fprintf_ln (stdout , s -> help_color , "status - %s" ,
601665 _ ("show paths with changes" ));
@@ -613,9 +677,29 @@ static int run_help(struct add_i_state *s, const struct pathspec *unused_ps,
613677 return 0 ;
614678}
615679
680+ static void choose_prompt_help (struct add_i_state * s )
681+ {
682+ color_fprintf_ln (stdout , s -> help_color , "%s" ,
683+ _ ("Prompt help:" ));
684+ color_fprintf_ln (stdout , s -> help_color , "1 - %s" ,
685+ _ ("select a single item" ));
686+ color_fprintf_ln (stdout , s -> help_color , "3-5 - %s" ,
687+ _ ("select a range of items" ));
688+ color_fprintf_ln (stdout , s -> help_color , "2-3,6-9 - %s" ,
689+ _ ("select multiple ranges" ));
690+ color_fprintf_ln (stdout , s -> help_color , "foo - %s" ,
691+ _ ("select item based on unique prefix" ));
692+ color_fprintf_ln (stdout , s -> help_color , "-... - %s" ,
693+ _ ("unselect specified items" ));
694+ color_fprintf_ln (stdout , s -> help_color , "* - %s" ,
695+ _ ("choose all items" ));
696+ color_fprintf_ln (stdout , s -> help_color , " - %s" ,
697+ _ ("(empty) finish selecting" ));
698+ }
699+
616700typedef int (* command_t )(struct add_i_state * s , const struct pathspec * ps ,
617- struct string_list * files ,
618- struct list_options * opts );
701+ struct prefix_item_list * files ,
702+ struct list_and_choose_options * opts );
619703
620704struct command_item {
621705 size_t prefix_length ;
@@ -667,18 +751,21 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
667751 command_t command ;
668752 } command_list [] = {
669753 { "status" , run_status },
754+ { "update" , run_update },
670755 { "help" , run_help },
671756 };
672757 struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
673758
674759 struct print_file_item_data print_file_item_data = {
675- "%12s %12s %s" , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
760+ "%12s %12s %s" , NULL , NULL ,
761+ STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
676762 };
677- struct list_options opts = {
678- 0 , NULL , print_file_item , & print_file_item_data
763+ struct list_and_choose_options opts = {
764+ { 0 , NULL , print_file_item , & print_file_item_data },
765+ NULL , 0 , choose_prompt_help
679766 };
680767 struct strbuf header = STRBUF_INIT ;
681- struct string_list files = STRING_LIST_INIT_DUP ;
768+ struct prefix_item_list files = PREFIX_ITEM_LIST_INIT ;
682769 ssize_t i ;
683770 int res = 0 ;
684771
@@ -699,11 +786,13 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
699786 data .color = s .prompt_color ;
700787 data .reset = s .reset_color ;
701788 }
789+ print_file_item_data .color = data .color ;
790+ print_file_item_data .reset = data .reset ;
702791
703792 strbuf_addstr (& header , " " );
704793 strbuf_addf (& header , print_file_item_data .modified_fmt ,
705794 _ ("staged" ), _ ("unstaged" ), _ ("path" ));
706- opts .header = header .buf ;
795+ opts .list_opts . header = header .buf ;
707796
708797 if (discard_index (r -> index ) < 0 ||
709798 repo_read_index (r ) < 0 ||
@@ -727,8 +816,9 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
727816 }
728817 }
729818
730- string_list_clear (& files , 1 );
819+ prefix_item_list_clear (& files );
731820 strbuf_release (& print_file_item_data .buf );
821+ strbuf_release (& print_file_item_data .name );
732822 strbuf_release (& print_file_item_data .index );
733823 strbuf_release (& print_file_item_data .worktree );
734824 strbuf_release (& header );
0 commit comments