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 ;
@@ -248,7 +250,7 @@ static ssize_t list_and_choose(struct prefix_item **items, int *selected,
248
250
249
251
struct adddel {
250
252
uintmax_t add , del ;
251
- unsigned seen :1 , binary :1 ;
253
+ unsigned seen :1 , unmerged : 1 , binary :1 ;
252
254
};
253
255
254
256
struct file_list {
@@ -315,6 +317,7 @@ struct collection_status {
315
317
const char * reference ;
316
318
317
319
unsigned skip_unseen :1 ;
320
+ size_t unmerged_count , binary_count ;
318
321
struct file_list * list ;
319
322
struct hashmap file_map ;
320
323
};
@@ -338,12 +341,14 @@ static void collect_changes_cb(struct diff_queue_struct *q,
338
341
struct pathname_entry * entry ;
339
342
size_t file_index ;
340
343
struct file_item * file ;
341
- struct adddel * adddel ;
344
+ struct adddel * adddel , * other_adddel ;
342
345
343
346
entry = hashmap_get_from_hash (& s -> file_map , hash , name );
344
- if (entry )
347
+ if (entry ) {
348
+ if (entry -> index == (size_t )-1 )
349
+ continue ;
345
350
file_index = entry -> index ;
346
- else if (s -> skip_unseen )
351
+ } else if (s -> skip_unseen )
347
352
continue ;
348
353
else {
349
354
FLEX_ALLOC_STR (entry , pathname , name );
@@ -356,11 +361,20 @@ static void collect_changes_cb(struct diff_queue_struct *q,
356
361
file = s -> list -> file [file_index ];
357
362
358
363
adddel = s -> phase == FROM_INDEX ? & file -> index : & file -> worktree ;
364
+ other_adddel = s -> phase == FROM_INDEX ? & file -> worktree : & file -> index ;
359
365
adddel -> seen = 1 ;
360
366
adddel -> add = stat .files [i ]-> added ;
361
367
adddel -> del = stat .files [i ]-> deleted ;
362
- if (stat .files [i ]-> is_binary )
368
+ if (stat .files [i ]-> is_binary ) {
369
+ if (!other_adddel -> binary )
370
+ s -> binary_count ++ ;
363
371
adddel -> binary = 1 ;
372
+ }
373
+ if (stat .files [i ]-> is_unmerged ) {
374
+ if (!other_adddel -> unmerged )
375
+ s -> unmerged_count ++ ;
376
+ adddel -> unmerged = 1 ;
377
+ }
364
378
}
365
379
}
366
380
@@ -372,6 +386,8 @@ enum modified_files_filter {
372
386
373
387
static int get_modified_files (struct repository * r ,
374
388
enum modified_files_filter filter ,
389
+ size_t * unmerged_count ,
390
+ size_t * binary_count ,
375
391
struct file_list * list ,
376
392
const struct pathspec * ps )
377
393
{
@@ -418,6 +434,10 @@ static int get_modified_files(struct repository *r,
418
434
}
419
435
}
420
436
hashmap_free (& s .file_map , 1 );
437
+ if (unmerged_count )
438
+ * unmerged_count = s .unmerged_count ;
439
+ if (binary_count )
440
+ * binary_count = s .binary_count ;
421
441
422
442
/* While the diffs are ordered already, we ran *two* diffs... */
423
443
QSORT (list -> file , list -> nr , file_item_cmp );
@@ -502,7 +522,7 @@ static int run_status(struct add_i_state *s, const struct pathspec *ps,
502
522
{
503
523
reset_file_list (files );
504
524
505
- if (get_modified_files (s -> r , 0 , files , ps ) < 0 )
525
+ if (get_modified_files (s -> r , 0 , NULL , NULL , files , ps ) < 0 )
506
526
return -1 ;
507
527
508
528
if (files -> nr )
@@ -523,7 +543,7 @@ static int run_update(struct add_i_state *s, const struct pathspec *ps,
523
543
524
544
reset_file_list (files );
525
545
526
- if (get_modified_files (s -> r , WORKTREE_ONLY , files , ps ) < 0 )
546
+ if (get_modified_files (s -> r , WORKTREE_ONLY , NULL , NULL , files , ps ) < 0 )
527
547
return -1 ;
528
548
529
549
if (!files -> nr ) {
@@ -609,7 +629,7 @@ static int run_revert(struct add_i_state *s, const struct pathspec *ps,
609
629
struct diff_options diffopt = { NULL };
610
630
611
631
reset_file_list (files );
612
- if (get_modified_files (s -> r , INDEX_ONLY , files , ps ) < 0 )
632
+ if (get_modified_files (s -> r , INDEX_ONLY , NULL , NULL , files , ps ) < 0 )
613
633
return -1 ;
614
634
615
635
if (!files -> nr ) {
@@ -767,6 +787,64 @@ static int run_add_untracked(struct add_i_state *s, const struct pathspec *ps,
767
787
return res ;
768
788
}
769
789
790
+ static int run_patch (struct add_i_state * s , const struct pathspec * ps ,
791
+ struct file_list * files ,
792
+ struct list_and_choose_options * opts )
793
+ {
794
+ struct prefix_item * * items = (struct prefix_item * * )files -> file ;
795
+ int res = 0 , * selected = NULL ;
796
+ ssize_t count , i , j ;
797
+ size_t unmerged_count = 0 , binary_count = 0 ;
798
+
799
+ reset_file_list (files );
800
+ if (get_modified_files (s -> r , WORKTREE_ONLY , & unmerged_count ,
801
+ & binary_count , files , ps ) < 0 )
802
+ return -1 ;
803
+
804
+ if (unmerged_count || binary_count ) {
805
+ for (i = j = 0 ; i < files -> nr ; i ++ )
806
+ if (files -> file [i ]-> index .binary ||
807
+ files -> file [i ]-> worktree .binary )
808
+ free (items [i ]);
809
+ else if (files -> file [i ]-> index .unmerged ||
810
+ files -> file [i ]-> worktree .unmerged ) {
811
+ color_fprintf_ln (stderr , s -> error_color ,
812
+ _ ("ignoring unmerged: %s" ),
813
+ files -> file [i ]-> item .name );
814
+ free (items [i ]);
815
+ } else
816
+ items [j ++ ] = items [i ];
817
+ files -> nr = j ;
818
+ }
819
+
820
+ if (!files -> nr ) {
821
+ if (binary_count )
822
+ fprintf (stderr , _ ("Only binary files changed.\n" ));
823
+ else
824
+ fprintf (stderr , _ ("No changes.\n" ));
825
+ return 0 ;
826
+ }
827
+
828
+ opts -> prompt = N_ ("Patch update" );
829
+ CALLOC_ARRAY (selected , files -> nr );
830
+
831
+ count = list_and_choose (items , selected , files -> nr , s , opts );
832
+ if (count >= 0 ) {
833
+ struct argv_array args = ARGV_ARRAY_INIT ;
834
+
835
+ argv_array_pushl (& args , "git" , "add--interactive" , "--patch" ,
836
+ "--" , NULL );
837
+ for (i = 0 ; i < files -> nr ; i ++ )
838
+ if (selected [i ])
839
+ argv_array_push (& args , items [i ]-> name );
840
+ res = run_command_v_opt (args .argv , 0 );
841
+ argv_array_clear (& args );
842
+ }
843
+
844
+ free (selected );
845
+ return res ;
846
+ }
847
+
770
848
static int run_help (struct add_i_state * s , const struct pathspec * ps ,
771
849
struct file_list * files ,
772
850
struct list_and_choose_options * opts )
@@ -860,10 +938,11 @@ int run_add_i(struct repository *r, const struct pathspec *ps)
860
938
update = { { "update" }, run_update },
861
939
revert = { { "revert" }, run_revert },
862
940
add_untracked = { { "add untracked" }, run_add_untracked },
941
+ patch = { { "patch" }, run_patch },
863
942
help = { { "help" }, run_help };
864
943
struct command_item * commands [] = {
865
944
& status , & update , & revert , & add_untracked ,
866
- & help
945
+ & patch , & help
867
946
};
868
947
869
948
struct print_file_item_data print_file_item_data = {
0 commit comments