6
6
#include "revision.h"
7
7
#include "refs.h"
8
8
#include "string-list.h"
9
+ #include "lockfile.h"
9
10
10
11
struct add_i_state {
11
12
struct repository * r ;
@@ -377,6 +378,7 @@ struct adddel {
377
378
};
378
379
379
380
struct file_item {
381
+ size_t prefix_length ;
380
382
struct adddel index , worktree ;
381
383
};
382
384
@@ -471,7 +473,7 @@ enum modified_files_filter {
471
473
472
474
static int get_modified_files (struct repository * r ,
473
475
enum modified_files_filter filter ,
474
- struct string_list * files ,
476
+ struct prefix_item_list * files ,
475
477
const struct pathspec * ps )
476
478
{
477
479
struct object_id head_oid ;
@@ -484,8 +486,8 @@ static int get_modified_files(struct repository *r,
484
486
repo_read_index_preload (r , ps , 0 ) < 0 )
485
487
return error (_ ("could not read index" ));
486
488
487
- string_list_clear (files , 1 );
488
- s .files = files ;
489
+ prefix_item_list_clear (files );
490
+ s .files = & files -> items ;
489
491
hashmap_init (& s .file_map , pathname_entry_cmp , NULL , 0 );
490
492
491
493
for (i = 0 ; i < 2 ; i ++ ) {
@@ -524,7 +526,7 @@ static int get_modified_files(struct repository *r,
524
526
hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
525
527
526
528
/* While the diffs are ordered already, we ran *two* diffs... */
527
- string_list_sort (files );
529
+ string_list_sort (& files -> items );
528
530
529
531
return 0 ;
530
532
}
@@ -559,43 +561,105 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
559
561
}
560
562
561
563
struct 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 ;
564
566
};
565
567
566
568
static void print_file_item (int i , int selected , struct string_list_item * item ,
567
569
void * print_file_item_data )
568
570
{
569
571
struct file_item * c = item -> util ;
570
572
struct print_file_item_data * d = print_file_item_data ;
573
+ const char * highlighted = NULL ;
571
574
572
575
strbuf_reset (& d -> index );
573
576
strbuf_reset (& d -> worktree );
574
577
strbuf_reset (& d -> buf );
575
578
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
+
576
589
render_adddel (& d -> worktree , & c -> worktree , _ ("nothing" ));
577
590
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 );
580
594
581
595
printf ("%c%2d: %s" , selected ? '*' : ' ' , i + 1 , d -> buf .buf );
582
596
}
583
597
584
598
static 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 )
586
601
{
587
602
if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
588
603
return -1 ;
589
604
590
- list (s , files , NULL , opts );
605
+ list (s , & files -> items , NULL , & opts -> list_opts );
591
606
putchar ('\n' );
592
607
593
608
return 0 ;
594
609
}
595
610
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
+
596
660
static 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 )
599
663
{
600
664
color_fprintf_ln (stdout , s -> help_color , "status - %s" ,
601
665
_ ("show paths with changes" ));
@@ -613,9 +677,29 @@ static int run_help(struct add_i_state *s, const struct pathspec *unused_ps,
613
677
return 0 ;
614
678
}
615
679
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
+
616
700
typedef 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 );
619
703
620
704
struct command_item {
621
705
size_t prefix_length ;
@@ -667,18 +751,21 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
667
751
command_t command ;
668
752
} command_list [] = {
669
753
{ "status" , run_status },
754
+ { "update" , run_update },
670
755
{ "help" , run_help },
671
756
};
672
757
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
673
758
674
759
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
676
762
};
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
679
766
};
680
767
struct strbuf header = STRBUF_INIT ;
681
- struct string_list files = STRING_LIST_INIT_DUP ;
768
+ struct prefix_item_list files = PREFIX_ITEM_LIST_INIT ;
682
769
ssize_t i ;
683
770
int res = 0 ;
684
771
@@ -699,11 +786,13 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
699
786
data .color = s .prompt_color ;
700
787
data .reset = s .reset_color ;
701
788
}
789
+ print_file_item_data .color = data .color ;
790
+ print_file_item_data .reset = data .reset ;
702
791
703
792
strbuf_addstr (& header , " " );
704
793
strbuf_addf (& header , print_file_item_data .modified_fmt ,
705
794
_ ("staged" ), _ ("unstaged" ), _ ("path" ));
706
- opts .header = header .buf ;
795
+ opts .list_opts . header = header .buf ;
707
796
708
797
if (discard_index (r -> index ) < 0 ||
709
798
repo_read_index (r ) < 0 ||
@@ -727,8 +816,9 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
727
816
}
728
817
}
729
818
730
- string_list_clear (& files , 1 );
819
+ prefix_item_list_clear (& files );
731
820
strbuf_release (& print_file_item_data .buf );
821
+ strbuf_release (& print_file_item_data .name );
732
822
strbuf_release (& print_file_item_data .index );
733
823
strbuf_release (& print_file_item_data .worktree );
734
824
strbuf_release (& header );
0 commit comments