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 ;
@@ -374,7 +375,7 @@ static ssize_t list_and_choose(struct add_i_state *s,
374
375
375
376
struct adddel {
376
377
uintmax_t add , del ;
377
- unsigned seen :1 , binary :1 ;
378
+ unsigned seen :1 , unmerged : 1 , binary :1 ;
378
379
};
379
380
380
381
struct file_item {
@@ -414,6 +415,7 @@ struct collection_status {
414
415
const char * reference ;
415
416
416
417
unsigned skip_unseen :1 ;
418
+ size_t unmerged_count , binary_count ;
417
419
struct string_list * files ;
418
420
struct hashmap file_map ;
419
421
};
@@ -436,7 +438,7 @@ static void collect_changes_cb(struct diff_queue_struct *q,
436
438
int hash = strhash (name );
437
439
struct pathname_entry * entry ;
438
440
struct file_item * file_item ;
439
- struct adddel * adddel ;
441
+ struct adddel * adddel , * other_adddel ;
440
442
441
443
entry = hashmap_get_entry_from_hash (& s -> file_map , hash , name ,
442
444
struct pathname_entry , ent );
@@ -456,11 +458,21 @@ static void collect_changes_cb(struct diff_queue_struct *q,
456
458
file_item = entry -> item ;
457
459
adddel = s -> phase == FROM_INDEX ?
458
460
& file_item -> index : & file_item -> worktree ;
461
+ other_adddel = s -> phase == FROM_INDEX ?
462
+ & file_item -> worktree : & file_item -> index ;
459
463
adddel -> seen = 1 ;
460
464
adddel -> add = stat .files [i ]-> added ;
461
465
adddel -> del = stat .files [i ]-> deleted ;
462
- if (stat .files [i ]-> is_binary )
466
+ if (stat .files [i ]-> is_binary ) {
467
+ if (!other_adddel -> binary )
468
+ s -> binary_count ++ ;
463
469
adddel -> binary = 1 ;
470
+ }
471
+ if (stat .files [i ]-> is_unmerged ) {
472
+ if (!other_adddel -> unmerged )
473
+ s -> unmerged_count ++ ;
474
+ adddel -> unmerged = 1 ;
475
+ }
464
476
}
465
477
free_diffstat_info (& stat );
466
478
}
@@ -474,7 +486,9 @@ enum modified_files_filter {
474
486
static int get_modified_files (struct repository * r ,
475
487
enum modified_files_filter filter ,
476
488
struct prefix_item_list * files ,
477
- const struct pathspec * ps )
489
+ const struct pathspec * ps ,
490
+ size_t * unmerged_count ,
491
+ size_t * binary_count )
478
492
{
479
493
struct object_id head_oid ;
480
494
int is_initial = !resolve_ref_unsafe ("HEAD" , RESOLVE_REF_READING ,
@@ -521,6 +535,10 @@ static int get_modified_files(struct repository *r,
521
535
}
522
536
}
523
537
hashmap_free_entries (& s .file_map , struct pathname_entry , ent );
538
+ if (unmerged_count )
539
+ * unmerged_count = s .unmerged_count ;
540
+ if (binary_count )
541
+ * binary_count = s .binary_count ;
524
542
525
543
/* While the diffs are ordered already, we ran *two* diffs... */
526
544
string_list_sort (& files -> items );
@@ -603,7 +621,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
603
621
struct prefix_item_list * files ,
604
622
struct list_and_choose_options * opts )
605
623
{
606
- if (get_modified_files (s -> r , NO_FILTER , files , ps ) < 0 )
624
+ if (get_modified_files (s -> r , NO_FILTER , files , ps , NULL , NULL ) < 0 )
607
625
return -1 ;
608
626
609
627
list (s , & files -> items , NULL , & opts -> list_opts );
@@ -620,7 +638,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
620
638
size_t count , i ;
621
639
struct lock_file index_lock ;
622
640
623
- if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
641
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps , NULL , NULL ) < 0 )
624
642
return -1 ;
625
643
626
644
if (!files -> items .nr ) {
@@ -699,7 +717,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
699
717
struct tree * tree ;
700
718
struct diff_options diffopt = { NULL };
701
719
702
- if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
720
+ if (get_modified_files (s -> r , INDEX_ONLY , files , ps , NULL , NULL ) < 0 )
703
721
return -1 ;
704
722
705
723
if (!files -> items .nr ) {
@@ -851,6 +869,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
851
869
return res ;
852
870
}
853
871
872
+ static int run_patch (struct add_i_state * s , const struct pathspec * ps ,
873
+ struct prefix_item_list * files ,
874
+ struct list_and_choose_options * opts )
875
+ {
876
+ int res = 0 ;
877
+ ssize_t count , i , j ;
878
+ size_t unmerged_count = 0 , binary_count = 0 ;
879
+
880
+ if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ,
881
+ & unmerged_count , & binary_count ) < 0 )
882
+ return -1 ;
883
+
884
+ if (unmerged_count || binary_count ) {
885
+ for (i = j = 0 ; i < files -> items .nr ; i ++ ) {
886
+ struct file_item * item = files -> items .items [i ].util ;
887
+
888
+ if (item -> index .binary || item -> worktree .binary ) {
889
+ free (item );
890
+ free (files -> items .items [i ].string );
891
+ } else if (item -> index .unmerged ||
892
+ item -> worktree .unmerged ) {
893
+ color_fprintf_ln (stderr , s -> error_color ,
894
+ _ ("ignoring unmerged: %s" ),
895
+ files -> items .items [i ].string );
896
+ free (item );
897
+ free (files -> items .items [i ].string );
898
+ } else
899
+ files -> items .items [j ++ ] = files -> items .items [i ];
900
+ }
901
+ files -> items .nr = j ;
902
+ }
903
+
904
+ if (!files -> items .nr ) {
905
+ if (binary_count )
906
+ fprintf (stderr , _ ("Only binary files changed.\n" ));
907
+ else
908
+ fprintf (stderr , _ ("No changes.\n" ));
909
+ return 0 ;
910
+ }
911
+
912
+ opts -> prompt = N_ ("Patch update" );
913
+ count = list_and_choose (s , files , opts );
914
+ if (count >= 0 ) {
915
+ struct argv_array args = ARGV_ARRAY_INIT ;
916
+
917
+ argv_array_pushl (& args , "git" , "add--interactive" , "--patch" ,
918
+ "--" , NULL );
919
+ for (i = 0 ; i < files -> items .nr ; i ++ )
920
+ if (files -> selected [i ])
921
+ argv_array_push (& args ,
922
+ files -> items .items [i ].string );
923
+ res = run_command_v_opt (args .argv , 0 );
924
+ argv_array_clear (& args );
925
+ }
926
+
927
+ return res ;
928
+ }
929
+
854
930
static int run_help (struct add_i_state * s , const struct pathspec * unused_ps ,
855
931
struct prefix_item_list * unused_files ,
856
932
struct list_and_choose_options * unused_opts )
@@ -948,6 +1024,7 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
948
1024
{ "update" , run_update },
949
1025
{ "revert" , run_revert },
950
1026
{ "add untracked" , run_add_untracked },
1027
+ { "patch" , run_patch },
951
1028
{ "help" , run_help },
952
1029
};
953
1030
struct prefix_item_list commands = PREFIX_ITEM_LIST_INIT ;
0 commit comments