8
8
#include "string-list.h"
9
9
#include "lockfile.h"
10
10
#include "dir.h"
11
+ #include "run-command.h"
11
12
12
13
struct add_i_state {
13
14
struct repository * r ;
@@ -375,7 +376,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
375
376
376
377
struct adddel {
377
378
uintmax_t add , del ;
378
- unsigned seen :1 , binary :1 ;
379
+ unsigned seen :1 , unmerged : 1 , binary :1 ;
379
380
};
380
381
381
382
struct file_item {
@@ -415,6 +416,7 @@ struct collection_status {
415
416
const char * reference ;
416
417
417
418
unsigned skip_unseen :1 ;
419
+ size_t unmerged_count , binary_count ;
418
420
struct string_list * files ;
419
421
struct hashmap file_map ;
420
422
};
@@ -437,7 +439,7 @@ static void collect_changes_cb(struct diff_queue_struct *q,
437
439
int hash = strhash (name );
438
440
struct pathname_entry * entry ;
439
441
struct file_item * file_item ;
440
- struct adddel * adddel ;
442
+ struct adddel * adddel , * other_adddel ;
441
443
442
444
entry = hashmap_get_entry_from_hash (& s -> file_map , hash , name ,
443
445
struct pathname_entry , ent );
@@ -457,11 +459,21 @@ static void collect_changes_cb(struct diff_queue_struct *q,
457
459
file_item = entry -> item ;
458
460
adddel = s -> mode == FROM_INDEX ?
459
461
& file_item -> index : & file_item -> worktree ;
462
+ other_adddel = s -> mode == FROM_INDEX ?
463
+ & file_item -> worktree : & file_item -> index ;
460
464
adddel -> seen = 1 ;
461
465
adddel -> add = stat .files [i ]-> added ;
462
466
adddel -> del = stat .files [i ]-> deleted ;
463
- if (stat .files [i ]-> is_binary )
467
+ if (stat .files [i ]-> is_binary ) {
468
+ if (!other_adddel -> binary )
469
+ s -> binary_count ++ ;
464
470
adddel -> binary = 1 ;
471
+ }
472
+ if (stat .files [i ]-> is_unmerged ) {
473
+ if (!other_adddel -> unmerged )
474
+ s -> unmerged_count ++ ;
475
+ adddel -> unmerged = 1 ;
476
+ }
465
477
}
466
478
free_diffstat_info (& stat );
467
479
}
@@ -475,7 +487,9 @@ enum modified_files_filter {
475
487
static int get_modified_files (struct repository * r ,
476
488
enum modified_files_filter filter ,
477
489
struct prefix_item_list * files ,
478
- const struct pathspec * ps )
490
+ const struct pathspec * ps ,
491
+ size_t * unmerged_count ,
492
+ size_t * binary_count )
479
493
{
480
494
struct object_id head_oid ;
481
495
int is_initial = !resolve_ref_unsafe ("HEAD" , RESOLVE_REF_READING ,
@@ -525,6 +539,10 @@ static int get_modified_files(struct repository *r,
525
539
clear_pathspec (& rev .prune_data );
526
540
}
527
541
hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
542
+ if (unmerged_count )
543
+ * unmerged_count = s .unmerged_count ;
544
+ if (binary_count )
545
+ * binary_count = s .binary_count ;
528
546
529
547
/* While the diffs are ordered already, we ran *two* diffs... */
530
548
string_list_sort (& files -> items );
@@ -607,7 +625,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
607
625
struct prefix_item_list * files ,
608
626
struct list_and_choose_options * opts )
609
627
{
610
- if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
628
+ if (get_modified_files (s -> r , NO_FILTER , files , ps , NULL , NULL ) < 0 )
611
629
return -1 ;
612
630
613
631
list (s , & files -> items , NULL , & opts -> list_opts );
@@ -624,7 +642,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
624
642
size_t count , i ;
625
643
struct lock_file index_lock ;
626
644
627
- if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
645
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps , NULL , NULL ) < 0 )
628
646
return -1 ;
629
647
630
648
if (!files -> items .nr ) {
@@ -703,7 +721,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
703
721
struct tree * tree ;
704
722
struct diff_options diffopt = { NULL };
705
723
706
- if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
724
+ if (get_modified_files (s -> r , INDEX_ONLY , files , ps , NULL , NULL ) < 0 )
707
725
return -1 ;
708
726
709
727
if (!files -> items .nr ) {
@@ -855,6 +873,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
855
873
return res ;
856
874
}
857
875
876
+ static int run_patch (struct add_i_state * s , const struct pathspec * ps ,
877
+ struct prefix_item_list * files ,
878
+ struct list_and_choose_options * opts )
879
+ {
880
+ int res = 0 ;
881
+ ssize_t count , i , j ;
882
+ size_t unmerged_count = 0 , binary_count = 0 ;
883
+
884
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ,
885
+ & unmerged_count , & binary_count ) < 0 )
886
+ return -1 ;
887
+
888
+ if (unmerged_count || binary_count ) {
889
+ for (i = j = 0 ; i < files -> items .nr ; i ++ ) {
890
+ struct file_item * item = files -> items .items [i ].util ;
891
+
892
+ if (item -> index .binary || item -> worktree .binary ) {
893
+ free (item );
894
+ free (files -> items .items [i ].string );
895
+ } else if (item -> index .unmerged ||
896
+ item -> worktree .unmerged ) {
897
+ color_fprintf_ln (stderr , s -> error_color ,
898
+ _ ("ignoring unmerged: %s" ),
899
+ files -> items .items [i ].string );
900
+ free (item );
901
+ free (files -> items .items [i ].string );
902
+ } else
903
+ files -> items .items [j ++ ] = files -> items .items [i ];
904
+ }
905
+ files -> items .nr = j ;
906
+ }
907
+
908
+ if (!files -> items .nr ) {
909
+ if (binary_count )
910
+ fprintf (stderr , _ ("Only binary files changed.\n" ));
911
+ else
912
+ fprintf (stderr , _ ("No changes.\n" ));
913
+ return 0 ;
914
+ }
915
+
916
+ opts -> prompt = N_ ("Patch update" );
917
+ count = list_and_choose (s , files , opts );
918
+ if (count >= 0 ) {
919
+ struct argv_array args = ARGV_ARRAY_INIT ;
920
+
921
+ argv_array_pushl (& args , "git" , "add--interactive" , "--patch" ,
922
+ "--" , NULL );
923
+ for (i = 0 ; i < files -> items .nr ; i ++ )
924
+ if (files -> selected [i ])
925
+ argv_array_push (& args ,
926
+ files -> items .items [i ].string );
927
+ res = run_command_v_opt (args .argv , 0 );
928
+ argv_array_clear (& args );
929
+ }
930
+
931
+ return res ;
932
+ }
933
+
858
934
static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
859
935
struct prefix_item_list * unused_files ,
860
936
struct list_and_choose_options * unused_opts )
@@ -952,6 +1028,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
952
1028
{ "update" , run_update },
953
1029
{ "revert" , run_revert },
954
1030
{ "add untracked" , run_add_untracked },
1031
+ { "patch" , run_patch },
955
1032
{ "help" , run_help },
956
1033
};
957
1034
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
0 commit comments