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 ;
@@ -376,6 +377,7 @@ struct adddel {
376
377
};
377
378
378
379
struct file_item {
380
+ size_t prefix_length ;
379
381
struct adddel index , worktree ;
380
382
};
381
383
@@ -470,7 +472,7 @@ enum modified_files_filter {
470
472
471
473
static int get_modified_files (struct repository * r ,
472
474
enum modified_files_filter filter ,
473
- struct string_list * files ,
475
+ struct prefix_item_list * files ,
474
476
const struct pathspec * ps )
475
477
{
476
478
struct object_id head_oid ;
@@ -483,8 +485,8 @@ static int get_modified_files(struct repository *r,
483
485
repo_read_index_preload (r , ps , 0 ) < 0 )
484
486
return error (_ ("could not read index" ));
485
487
486
- string_list_clear (files , 1 );
487
- s .files = files ;
488
+ prefix_item_list_clear (files );
489
+ s .files = & files -> items ;
488
490
hashmap_init (& s .file_map , pathname_entry_cmp , NULL , 0 );
489
491
490
492
for (i = 0 ; i < 2 ; i ++ ) {
@@ -520,7 +522,7 @@ static int get_modified_files(struct repository *r,
520
522
hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
521
523
522
524
/* While the diffs are ordered already, we ran *two* diffs... */
523
- string_list_sort (files );
525
+ string_list_sort (& files -> items );
524
526
525
527
return 0 ;
526
528
}
@@ -555,43 +557,105 @@ static int is_valid_prefix(const char *prefix, size_t prefix_len)
555
557
}
556
558
557
559
struct print_file_item_data {
558
- const char * modified_fmt ;
559
- struct strbuf buf , index , worktree ;
560
+ const char * modified_fmt , * color , * reset ;
561
+ struct strbuf buf , name , index , worktree ;
560
562
};
561
563
562
564
static void print_file_item (int i , int selected , struct string_list_item * item ,
563
565
void * print_file_item_data )
564
566
{
565
567
struct file_item * c = item -> util ;
566
568
struct print_file_item_data * d = print_file_item_data ;
569
+ const char * highlighted = NULL ;
567
570
568
571
strbuf_reset (& d -> index );
569
572
strbuf_reset (& d -> worktree );
570
573
strbuf_reset (& d -> buf );
571
574
575
+ /* Format the item with the prefix highlighted. */
576
+ if (c -> prefix_length > 0 &&
577
+ is_valid_prefix (item -> string , c -> prefix_length )) {
578
+ strbuf_reset (& d -> name );
579
+ strbuf_addf (& d -> name , "%s%.*s%s%s" , d -> color ,
580
+ (int )c -> prefix_length , item -> string , d -> reset ,
581
+ item -> string + c -> prefix_length );
582
+ highlighted = d -> name .buf ;
583
+ }
584
+
572
585
render_adddel (& d -> worktree , & c -> worktree , _ ("nothing" ));
573
586
render_adddel (& d -> index , & c -> index , _ ("unchanged" ));
574
- strbuf_addf (& d -> buf , d -> modified_fmt ,
575
- d -> index .buf , d -> worktree .buf , item -> string );
587
+
588
+ strbuf_addf (& d -> buf , d -> modified_fmt , d -> index .buf , d -> worktree .buf ,
589
+ highlighted ? highlighted : item -> string );
576
590
577
591
printf ("%c%2d: %s" , selected ? '*' : ' ' , i + 1 , d -> buf .buf );
578
592
}
579
593
580
594
static int run_status (struct add_i_state * s , const struct pathspec * ps ,
581
- struct string_list * files , struct list_options * opts )
595
+ struct prefix_item_list * files ,
596
+ struct list_and_choose_options * opts )
582
597
{
583
598
if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
584
599
return -1 ;
585
600
586
- list (s , files , NULL , opts );
601
+ list (s , & files -> items , NULL , & opts -> list_opts );
587
602
putchar ('\n' );
588
603
589
604
return 0 ;
590
605
}
591
606
607
+ static int run_update (struct add_i_state * s , const struct pathspec * ps ,
608
+ struct prefix_item_list * files ,
609
+ struct list_and_choose_options * opts )
610
+ {
611
+ int res = 0 , fd ;
612
+ size_t count , i ;
613
+ struct lock_file index_lock ;
614
+
615
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
616
+ return -1 ;
617
+
618
+ if (!files -> items .nr ) {
619
+ putchar ('\n' );
620
+ return 0 ;
621
+ }
622
+
623
+ opts -> prompt = N_ ("Update" );
624
+ count = list_and_choose (s , files , opts );
625
+ if (count <= 0 ) {
626
+ putchar ('\n' );
627
+ return 0 ;
628
+ }
629
+
630
+ fd = repo_hold_locked_index (s -> r , & index_lock , LOCK_REPORT_ON_ERROR );
631
+ if (fd < 0 ) {
632
+ putchar ('\n' );
633
+ return -1 ;
634
+ }
635
+
636
+ for (i = 0 ; i < files -> items .nr ; i ++ ) {
637
+ const char * name = files -> items .items [i ].string ;
638
+ if (files -> selected [i ] &&
639
+ add_file_to_index (s -> r -> index , name , 0 ) < 0 ) {
640
+ res = error (_ ("could not stage '%s'" ), name );
641
+ break ;
642
+ }
643
+ }
644
+
645
+ if (!res && write_locked_index (s -> r -> index , & index_lock , COMMIT_LOCK ) < 0 )
646
+ res = error (_ ("could not write index" ));
647
+
648
+ if (!res )
649
+ printf (Q_ ("updated %d path\n" ,
650
+ "updated %d paths\n" , count ), (int )count );
651
+
652
+ putchar ('\n' );
653
+ return res ;
654
+ }
655
+
592
656
static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
593
- struct string_list * unused_files ,
594
- struct list_options * unused_opts )
657
+ struct prefix_item_list * unused_files ,
658
+ struct list_and_choose_options * unused_opts )
595
659
{
596
660
color_fprintf_ln (stdout , s -> help_color , "status - %s" ,
597
661
_ ("show paths with changes" ));
@@ -609,9 +673,29 @@ static int run_help(struct add_i_state *s, const struct pathspec *unused_ps,
609
673
return 0 ;
610
674
}
611
675
676
+ static void choose_prompt_help (struct add_i_state * s )
677
+ {
678
+ color_fprintf_ln (stdout , s -> help_color , "%s" ,
679
+ _ ("Prompt help:" ));
680
+ color_fprintf_ln (stdout , s -> help_color , "1 - %s" ,
681
+ _ ("select a single item" ));
682
+ color_fprintf_ln (stdout , s -> help_color , "3-5 - %s" ,
683
+ _ ("select a range of items" ));
684
+ color_fprintf_ln (stdout , s -> help_color , "2-3,6-9 - %s" ,
685
+ _ ("select multiple ranges" ));
686
+ color_fprintf_ln (stdout , s -> help_color , "foo - %s" ,
687
+ _ ("select item based on unique prefix" ));
688
+ color_fprintf_ln (stdout , s -> help_color , "-... - %s" ,
689
+ _ ("unselect specified items" ));
690
+ color_fprintf_ln (stdout , s -> help_color , "* - %s" ,
691
+ _ ("choose all items" ));
692
+ color_fprintf_ln (stdout , s -> help_color , " - %s" ,
693
+ _ ("(empty) finish selecting" ));
694
+ }
695
+
612
696
typedef int (* command_t )(struct add_i_state * s , const struct pathspec * ps ,
613
- struct string_list * files ,
614
- struct list_options * opts );
697
+ struct prefix_item_list * files ,
698
+ struct list_and_choose_options * opts );
615
699
616
700
struct command_item {
617
701
size_t prefix_length ;
@@ -663,18 +747,21 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
663
747
command_t command ;
664
748
} command_list [] = {
665
749
{ "status" , run_status },
750
+ { "update" , run_update },
666
751
{ "help" , run_help },
667
752
};
668
753
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
669
754
670
755
struct print_file_item_data print_file_item_data = {
671
- "%12s %12s %s" , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
756
+ "%12s %12s %s" , NULL , NULL ,
757
+ STRBUF_INIT , STRBUF_INIT , STRBUF_INIT , STRBUF_INIT
672
758
};
673
- struct list_options opts = {
674
- 0 , NULL , print_file_item , & print_file_item_data
759
+ struct list_and_choose_options opts = {
760
+ { 0 , NULL , print_file_item , & print_file_item_data },
761
+ NULL , 0 , choose_prompt_help
675
762
};
676
763
struct strbuf header = STRBUF_INIT ;
677
- struct string_list files = STRING_LIST_INIT_DUP ;
764
+ struct prefix_item_list files = PREFIX_ITEM_LIST_INIT ;
678
765
ssize_t i ;
679
766
int res = 0 ;
680
767
@@ -695,11 +782,13 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
695
782
data .color = s .prompt_color ;
696
783
data .reset = s .reset_color ;
697
784
}
785
+ print_file_item_data .color = data .color ;
786
+ print_file_item_data .reset = data .reset ;
698
787
699
788
strbuf_addstr (& header , " " );
700
789
strbuf_addf (& header , print_file_item_data .modified_fmt ,
701
790
_ ("staged" ), _ ("unstaged" ), _ ("path" ));
702
- opts .header = header .buf ;
791
+ opts .list_opts . header = header .buf ;
703
792
704
793
if (discard_index (r -> index ) < 0 ||
705
794
repo_read_index (r ) < 0 ||
@@ -723,8 +812,9 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
723
812
}
724
813
}
725
814
726
- string_list_clear (& files , 1 );
815
+ prefix_item_list_clear (& files );
727
816
strbuf_release (& print_file_item_data .buf );
817
+ strbuf_release (& print_file_item_data .name );
728
818
strbuf_release (& print_file_item_data .index );
729
819
strbuf_release (& print_file_item_data .worktree );
730
820
strbuf_release (& header );
0 commit comments