88#include "string-list.h"
99#include "lockfile.h"
1010#include "dir.h"
11+ #include "run-command.h"
1112
1213struct add_i_state {
1314 struct repository * r ;
@@ -375,7 +376,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
375376
376377struct adddel {
377378 uintmax_t add , del ;
378- unsigned seen :1 , binary :1 ;
379+ unsigned seen :1 , unmerged : 1 , binary :1 ;
379380};
380381
381382struct file_item {
@@ -415,6 +416,7 @@ struct collection_status {
415416 const char * reference ;
416417
417418 unsigned skip_unseen :1 ;
419+ size_t unmerged_count , binary_count ;
418420 struct string_list * files ;
419421 struct hashmap file_map ;
420422};
@@ -437,7 +439,7 @@ static void collect_changes_cb(struct diff_queue_struct *q,
437439 int hash = strhash (name );
438440 struct pathname_entry * entry ;
439441 struct file_item * file_item ;
440- struct adddel * adddel ;
442+ struct adddel * adddel , * other_adddel ;
441443
442444 entry = hashmap_get_entry_from_hash (& s -> file_map , hash , name ,
443445 struct pathname_entry , ent );
@@ -457,11 +459,21 @@ static void collect_changes_cb(struct diff_queue_struct *q,
457459 file_item = entry -> item ;
458460 adddel = s -> mode == FROM_INDEX ?
459461 & file_item -> index : & file_item -> worktree ;
462+ other_adddel = s -> mode == FROM_INDEX ?
463+ & file_item -> worktree : & file_item -> index ;
460464 adddel -> seen = 1 ;
461465 adddel -> add = stat .files [i ]-> added ;
462466 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 ++ ;
464470 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+ }
465477 }
466478 free_diffstat_info (& stat );
467479}
@@ -475,7 +487,9 @@ enum modified_files_filter {
475487static int get_modified_files (struct repository * r ,
476488 enum modified_files_filter filter ,
477489 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 )
479493{
480494 struct object_id head_oid ;
481495 int is_initial = !resolve_ref_unsafe ("HEAD" , RESOLVE_REF_READING ,
@@ -525,6 +539,10 @@ static int get_modified_files(struct repository *r,
525539 clear_pathspec (& rev .prune_data );
526540 }
527541 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 ;
528546
529547 /* While the diffs are ordered already, we ran *two* diffs... */
530548 string_list_sort (& files -> items );
@@ -607,7 +625,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
607625 struct prefix_item_list * files ,
608626 struct list_and_choose_options * opts )
609627{
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 )
611629 return -1 ;
612630
613631 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,
624642 size_t count , i ;
625643 struct lock_file index_lock ;
626644
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 )
628646 return -1 ;
629647
630648 if (!files -> items .nr ) {
@@ -703,7 +721,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
703721 struct tree * tree ;
704722 struct diff_options diffopt = { NULL };
705723
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 )
707725 return -1 ;
708726
709727 if (!files -> items .nr ) {
@@ -855,6 +873,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
855873 return res ;
856874}
857875
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+
858934static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
859935 struct prefix_item_list * unused_files ,
860936 struct list_and_choose_options * unused_opts )
@@ -952,6 +1028,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
9521028 { "update" , run_update },
9531029 { "revert" , run_revert },
9541030 { "add untracked" , run_add_untracked },
1031+ { "patch" , run_patch },
9551032 { "help" , run_help },
9561033 };
9571034 struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
0 commit comments