9
9
#include "lockfile.h"
10
10
#include "pathspec.h"
11
11
#include "dir.h"
12
+ #include "argv-array.h"
13
+ #include "run-command.h"
12
14
13
15
struct add_i_state {
14
16
struct repository * r ;
@@ -255,7 +257,7 @@ static ssize_t list_and_choose(struct prefix_item **items, int *selected,
255
257
256
258
struct adddel {
257
259
uintmax_t add , del ;
258
- unsigned seen :1 , binary :1 ;
260
+ unsigned seen :1 , unmerged : 1 , binary :1 ;
259
261
};
260
262
261
263
struct file_list {
@@ -322,6 +324,7 @@ struct collection_status {
322
324
const char * reference ;
323
325
324
326
unsigned skip_unseen :1 ;
327
+ size_t unmerged_count , binary_count ;
325
328
struct file_list * list ;
326
329
struct hashmap file_map ;
327
330
};
@@ -345,12 +348,14 @@ static void collect_changes_cb(struct diff_queue_struct *q,
345
348
struct pathname_entry * entry ;
346
349
size_t file_index ;
347
350
struct file_item * file ;
348
- struct adddel * adddel ;
351
+ struct adddel * adddel , * other_adddel ;
349
352
350
353
entry = hashmap_get_from_hash (& s -> file_map , hash , name );
351
- if (entry )
354
+ if (entry ) {
355
+ if (entry -> index == (size_t )-1 )
356
+ continue ;
352
357
file_index = entry -> index ;
353
- else if (s -> skip_unseen )
358
+ } else if (s -> skip_unseen )
354
359
continue ;
355
360
else {
356
361
FLEX_ALLOC_STR (entry , pathname , name );
@@ -363,11 +368,20 @@ static void collect_changes_cb(struct diff_queue_struct *q,
363
368
file = s -> list -> file [file_index ];
364
369
365
370
adddel = s -> phase == FROM_INDEX ? & file -> index : & file -> worktree ;
371
+ other_adddel = s -> phase == FROM_INDEX ? & file -> worktree : & file -> index ;
366
372
adddel -> seen = 1 ;
367
373
adddel -> add = stat .files [i ]-> added ;
368
374
adddel -> del = stat .files [i ]-> deleted ;
369
- if (stat .files [i ]-> is_binary )
375
+ if (stat .files [i ]-> is_binary ) {
376
+ if (!other_adddel -> binary )
377
+ s -> binary_count ++ ;
370
378
adddel -> binary = 1 ;
379
+ }
380
+ if (stat .files [i ]-> is_unmerged ) {
381
+ if (!other_adddel -> unmerged )
382
+ s -> unmerged_count ++ ;
383
+ adddel -> unmerged = 1 ;
384
+ }
371
385
}
372
386
}
373
387
@@ -379,6 +393,8 @@ enum modified_files_filter {
379
393
380
394
static int get_modified_files (struct repository * r ,
381
395
enum modified_files_filter filter ,
396
+ size_t * unmerged_count ,
397
+ size_t * binary_count ,
382
398
struct file_list * list ,
383
399
const struct pathspec * ps )
384
400
{
@@ -425,6 +441,10 @@ static int get_modified_files(struct repository *r,
425
441
}
426
442
}
427
443
hashmap_free (& s .file_map , 1 );
444
+ if (unmerged_count )
445
+ * unmerged_count = s .unmerged_count ;
446
+ if (binary_count )
447
+ * binary_count = s .binary_count ;
428
448
429
449
/* While the diffs are ordered already, we ran *two* diffs... */
430
450
QSORT (list -> file , list -> nr , file_item_cmp );
@@ -509,7 +529,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
509
529
{
510
530
reset_file_list (files );
511
531
512
- if (get_modified_files (s -> r , 0 , files , ps ) < 0 )
532
+ if (get_modified_files (s -> r , 0 , NULL , NULL , files , ps ) < 0 )
513
533
return -1 ;
514
534
515
535
if (files -> nr )
@@ -530,7 +550,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
530
550
531
551
reset_file_list (files );
532
552
533
- if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
553
+ if (get_modified_files (s -> r , WORKTREE_ONLY , NULL , NULL , files , ps ) < 0 )
534
554
return -1 ;
535
555
536
556
if (!files -> nr ) {
@@ -616,7 +636,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
616
636
struct diff_options diffopt = { NULL };
617
637
618
638
reset_file_list (files );
619
- if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
639
+ if (get_modified_files (s -> r , INDEX_ONLY , NULL , NULL , files , ps ) < 0 )
620
640
return -1 ;
621
641
622
642
if (!files -> nr ) {
@@ -774,6 +794,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
774
794
return res ;
775
795
}
776
796
797
+ static int run_patch (struct add_i_state * s , const struct pathspec * ps ,
798
+ struct file_list * files ,
799
+ struct list_and_choose_options * opts )
800
+ {
801
+ struct prefix_item * * items = (struct prefix_item * * )files -> file ;
802
+ int res = 0 , * selected = NULL ;
803
+ ssize_t count , i , j ;
804
+ size_t unmerged_count = 0 , binary_count = 0 ;
805
+
806
+ reset_file_list (files );
807
+ if (get_modified_files (s -> r , WORKTREE_ONLY , & unmerged_count ,
808
+ & binary_count , files , ps ) < 0 )
809
+ return -1 ;
810
+
811
+ if (unmerged_count || binary_count ) {
812
+ for (i = j = 0 ; i < files -> nr ; i ++ )
813
+ if (files -> file [i ]-> index .binary ||
814
+ files -> file [i ]-> worktree .binary )
815
+ free (items [i ]);
816
+ else if (files -> file [i ]-> index .unmerged ||
817
+ files -> file [i ]-> worktree .unmerged ) {
818
+ color_fprintf_ln (stderr , s -> error_color ,
819
+ _ ("ignoring unmerged: %s" ),
820
+ files -> file [i ]-> item .name );
821
+ free (items [i ]);
822
+ } else
823
+ items [j ++ ] = items [i ];
824
+ files -> nr = j ;
825
+ }
826
+
827
+ if (!files -> nr ) {
828
+ if (binary_count )
829
+ fprintf (stderr , _ ("Only binary files changed.\n" ));
830
+ else
831
+ fprintf (stderr , _ ("No changes.\n" ));
832
+ return 0 ;
833
+ }
834
+
835
+ opts -> prompt = N_ ("Patch update" );
836
+ CALLOC_ARRAY (selected , files -> nr );
837
+
838
+ count = list_and_choose (items , selected , files -> nr , s , opts );
839
+ if (count >= 0 ) {
840
+ struct argv_array args = ARGV_ARRAY_INIT ;
841
+
842
+ argv_array_pushl (& args , "git" , "add--interactive" , "--patch" ,
843
+ "--" , NULL );
844
+ for (i = 0 ; i < files -> nr ; i ++ )
845
+ if (selected [i ])
846
+ argv_array_push (& args , items [i ]-> name );
847
+ res = run_command_v_opt (args .argv , 0 );
848
+ argv_array_clear (& args );
849
+ }
850
+
851
+ free (selected );
852
+ return res ;
853
+ }
854
+
777
855
static int run_help (struct add_i_state * s , const struct pathspec * ps ,
778
856
struct file_list * files ,
779
857
struct list_and_choose_options * opts )
@@ -867,10 +945,11 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
867
945
update = { { "update" }, run_update },
868
946
revert = { { "revert" }, run_revert },
869
947
add_untracked = { { "add untracked" }, run_add_untracked },
948
+ patch = { { "patch" }, run_patch },
870
949
help = { { "help" }, run_help };
871
950
struct command_item * commands [] = {
872
951
& status , & update , & revert , & add_untracked ,
873
- & help
952
+ & patch , & help
874
953
};
875
954
876
955
struct print_file_item_data print_file_item_data = {
0 commit comments