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 -> phase == FROM_INDEX ?
459
461
& file_item -> index : & file_item -> worktree ;
462
+ other_adddel = s -> phase == 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 ,
@@ -522,6 +536,10 @@ static int get_modified_files(struct repository *r,
522
536
}
523
537
}
524
538
hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
539
+ if (unmerged_count )
540
+ * unmerged_count = s .unmerged_count ;
541
+ if (binary_count )
542
+ * binary_count = s .binary_count ;
525
543
526
544
/* While the diffs are ordered already, we ran *two* diffs... */
527
545
string_list_sort (& files -> items );
@@ -604,7 +622,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
604
622
struct prefix_item_list * files ,
605
623
struct list_and_choose_options * opts )
606
624
{
607
- if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
625
+ if (get_modified_files (s -> r , NO_FILTER , files , ps , NULL , NULL ) < 0 )
608
626
return -1 ;
609
627
610
628
list (s , & files -> items , NULL , & opts -> list_opts );
@@ -621,7 +639,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
621
639
size_t count , i ;
622
640
struct lock_file index_lock ;
623
641
624
- if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
642
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps , NULL , NULL ) < 0 )
625
643
return -1 ;
626
644
627
645
if (!files -> items .nr ) {
@@ -700,7 +718,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
700
718
struct tree * tree ;
701
719
struct diff_options diffopt = { NULL };
702
720
703
- if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
721
+ if (get_modified_files (s -> r , INDEX_ONLY , files , ps , NULL , NULL ) < 0 )
704
722
return -1 ;
705
723
706
724
if (!files -> items .nr ) {
@@ -852,6 +870,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
852
870
return res ;
853
871
}
854
872
873
+ static int run_patch (struct add_i_state * s , const struct pathspec * ps ,
874
+ struct prefix_item_list * files ,
875
+ struct list_and_choose_options * opts )
876
+ {
877
+ int res = 0 ;
878
+ ssize_t count , i , j ;
879
+ size_t unmerged_count = 0 , binary_count = 0 ;
880
+
881
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ,
882
+ & unmerged_count , & binary_count ) < 0 )
883
+ return -1 ;
884
+
885
+ if (unmerged_count || binary_count ) {
886
+ for (i = j = 0 ; i < files -> items .nr ; i ++ ) {
887
+ struct file_item * item = files -> items .items [i ].util ;
888
+
889
+ if (item -> index .binary || item -> worktree .binary ) {
890
+ free (item );
891
+ free (files -> items .items [i ].string );
892
+ } else if (item -> index .unmerged ||
893
+ item -> worktree .unmerged ) {
894
+ color_fprintf_ln (stderr , s -> error_color ,
895
+ _ ("ignoring unmerged: %s" ),
896
+ files -> items .items [i ].string );
897
+ free (item );
898
+ free (files -> items .items [i ].string );
899
+ } else
900
+ files -> items .items [j ++ ] = files -> items .items [i ];
901
+ }
902
+ files -> items .nr = j ;
903
+ }
904
+
905
+ if (!files -> items .nr ) {
906
+ if (binary_count )
907
+ fprintf (stderr , _ ("Only binary files changed.\n" ));
908
+ else
909
+ fprintf (stderr , _ ("No changes.\n" ));
910
+ return 0 ;
911
+ }
912
+
913
+ opts -> prompt = N_ ("Patch update" );
914
+ count = list_and_choose (s , files , opts );
915
+ if (count >= 0 ) {
916
+ struct argv_array args = ARGV_ARRAY_INIT ;
917
+
918
+ argv_array_pushl (& args , "git" , "add--interactive" , "--patch" ,
919
+ "--" , NULL );
920
+ for (i = 0 ; i < files -> items .nr ; i ++ )
921
+ if (files -> selected [i ])
922
+ argv_array_push (& args ,
923
+ files -> items .items [i ].string );
924
+ res = run_command_v_opt (args .argv , 0 );
925
+ argv_array_clear (& args );
926
+ }
927
+
928
+ return res ;
929
+ }
930
+
855
931
static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
856
932
struct prefix_item_list * unused_files ,
857
933
struct list_and_choose_options * unused_opts )
@@ -949,6 +1025,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
949
1025
{ "update" , run_update },
950
1026
{ "revert" , run_revert },
951
1027
{ "add untracked" , run_add_untracked },
1028
+ { "patch" , run_patch },
952
1029
{ "help" , run_help },
953
1030
};
954
1031
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
0 commit comments