@@ -28,6 +28,9 @@ struct update_callback_data {
28
28
int add_errors ;
29
29
const char * implicit_dot ;
30
30
size_t implicit_dot_len ;
31
+
32
+ /* only needed for 2.0 transition preparation */
33
+ int warn_add_would_remove ;
31
34
};
32
35
33
36
static const char * option_with_implicit_dot ;
@@ -93,6 +96,24 @@ static int fix_unmerged_status(struct diff_filepair *p,
93
96
return DIFF_STATUS_MODIFIED ;
94
97
}
95
98
99
+ static const char * add_would_remove_warning = N_ (
100
+ "You ran 'git add' with neither '-A (--all)' or '--no-all', whose\n"
101
+ "behaviour will change in Git 2.0 with respect to paths you removed from\n"
102
+ "your working tree. Paths like '%s' that are\n"
103
+ "removed are ignored with this version of Git.\n"
104
+ "\n"
105
+ "* 'git add --no-all <pathspec>', which is the current default, ignores\n"
106
+ " paths you removed from your working tree.\n"
107
+ "\n"
108
+ "* 'git add --all <pathspec>' will let you also record the removals.\n"
109
+ "\n"
110
+ "Run 'git status' to check the paths you removed from your working tree.\n" );
111
+
112
+ static void warn_add_would_remove (const char * path )
113
+ {
114
+ warning (_ (add_would_remove_warning ), path );
115
+ }
116
+
96
117
static void update_callback (struct diff_queue_struct * q ,
97
118
struct diff_options * opt , void * cbdata )
98
119
{
@@ -130,6 +151,10 @@ static void update_callback(struct diff_queue_struct *q,
130
151
}
131
152
break ;
132
153
case DIFF_STATUS_DELETED :
154
+ if (data -> warn_add_would_remove ) {
155
+ warn_add_would_remove (path );
156
+ data -> warn_add_would_remove = 0 ;
157
+ }
133
158
if (data -> flags & ADD_CACHE_IGNORE_REMOVAL )
134
159
break ;
135
160
if (!(data -> flags & ADD_CACHE_PRETEND ))
@@ -141,32 +166,28 @@ static void update_callback(struct diff_queue_struct *q,
141
166
}
142
167
}
143
168
144
- int add_files_to_cache (const char * prefix , const char * * pathspec , int flags )
169
+ static void update_files_in_cache (const char * prefix , const char * * pathspec ,
170
+ struct update_callback_data * data )
145
171
{
146
- struct update_callback_data data ;
147
172
struct rev_info rev ;
148
173
149
- memset (& data , 0 , sizeof (data ));
150
- data .flags = flags & ~ADD_CACHE_IMPLICIT_DOT ;
151
- if ((flags & ADD_CACHE_IMPLICIT_DOT ) && prefix ) {
152
- /*
153
- * Check for modified files throughout the worktree so
154
- * update_callback has a chance to warn about changes
155
- * outside the cwd.
156
- */
157
- data .implicit_dot = prefix ;
158
- data .implicit_dot_len = strlen (prefix );
159
- pathspec = NULL ;
160
- }
161
-
162
174
init_revisions (& rev , prefix );
163
175
setup_revisions (0 , NULL , & rev , NULL );
164
176
init_pathspec (& rev .prune_data , pathspec );
165
177
rev .diffopt .output_format = DIFF_FORMAT_CALLBACK ;
166
178
rev .diffopt .format_callback = update_callback ;
167
- rev .diffopt .format_callback_data = & data ;
179
+ rev .diffopt .format_callback_data = data ;
168
180
rev .max_count = 0 ; /* do not compare unmerged paths with stage #2 */
169
181
run_diff_files (& rev , DIFF_RACY_IS_MODIFIED );
182
+ }
183
+
184
+ int add_files_to_cache (const char * prefix , const char * * pathspec , int flags )
185
+ {
186
+ struct update_callback_data data ;
187
+
188
+ memset (& data , 0 , sizeof (data ));
189
+ data .flags = flags ;
190
+ update_files_in_cache (prefix , pathspec , & data );
170
191
return !!data .add_errors ;
171
192
}
172
193
@@ -354,23 +375,27 @@ static struct lock_file lock_file;
354
375
static const char ignore_error [] =
355
376
N_ ("The following paths are ignored by one of your .gitignore files:\n" );
356
377
357
- static int verbose = 0 , show_only = 0 , ignored_too = 0 , refresh_only = 0 ;
358
- static int ignore_add_errors , addremove , intent_to_add , ignore_missing = 0 ;
378
+ static int verbose , show_only , ignored_too , refresh_only ;
379
+ static int ignore_add_errors , intent_to_add , ignore_missing ;
380
+
381
+ #define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
382
+ static int addremove = ADDREMOVE_DEFAULT ;
383
+ static int addremove_explicit = -1 ; /* unspecified */
359
384
360
385
static struct option builtin_add_options [] = {
361
386
OPT__DRY_RUN (& show_only , N_ ("dry run" )),
362
387
OPT__VERBOSE (& verbose , N_ ("be verbose" )),
363
388
OPT_GROUP ("" ),
364
- OPT_BOOLEAN ('i' , "interactive" , & add_interactive , N_ ("interactive picking" )),
365
- OPT_BOOLEAN ('p' , "patch" , & patch_interactive , N_ ("select hunks interactively" )),
366
- OPT_BOOLEAN ('e' , "edit" , & edit_interactive , N_ ("edit current diff and apply" )),
389
+ OPT_BOOL ('i' , "interactive" , & add_interactive , N_ ("interactive picking" )),
390
+ OPT_BOOL ('p' , "patch" , & patch_interactive , N_ ("select hunks interactively" )),
391
+ OPT_BOOL ('e' , "edit" , & edit_interactive , N_ ("edit current diff and apply" )),
367
392
OPT__FORCE (& ignored_too , N_ ("allow adding otherwise ignored files" )),
368
- OPT_BOOLEAN ('u' , "update" , & take_worktree_changes , N_ ("update tracked files" )),
369
- OPT_BOOLEAN ('N' , "intent-to-add" , & intent_to_add , N_ ("record only the fact that the path will be added later" )),
370
- OPT_BOOLEAN ('A' , "all" , & addremove , N_ ("add changes from all tracked and untracked files" )),
371
- OPT_BOOLEAN ( 0 , "refresh" , & refresh_only , N_ ("don't add, only refresh the index" )),
372
- OPT_BOOLEAN ( 0 , "ignore-errors" , & ignore_add_errors , N_ ("just skip files which cannot be added because of errors" )),
373
- OPT_BOOLEAN ( 0 , "ignore-missing" , & ignore_missing , N_ ("check if - even missing - files are ignored in dry run" )),
393
+ OPT_BOOL ('u' , "update" , & take_worktree_changes , N_ ("update tracked files" )),
394
+ OPT_BOOL ('N' , "intent-to-add" , & intent_to_add , N_ ("record only the fact that the path will be added later" )),
395
+ OPT_BOOL ('A' , "all" , & addremove_explicit , N_ ("add changes from all tracked and untracked files" )),
396
+ OPT_BOOL ( 0 , "refresh" , & refresh_only , N_ ("don't add, only refresh the index" )),
397
+ OPT_BOOL ( 0 , "ignore-errors" , & ignore_add_errors , N_ ("just skip files which cannot be added because of errors" )),
398
+ OPT_BOOL ( 0 , "ignore-missing" , & ignore_missing , N_ ("check if - even missing - files are ignored in dry run" )),
374
399
OPT_END (),
375
400
};
376
401
@@ -416,6 +441,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
416
441
int require_pathspec ;
417
442
char * seen = NULL ;
418
443
int implicit_dot = 0 ;
444
+ struct update_callback_data update_data ;
419
445
420
446
git_config (add_config , NULL );
421
447
@@ -431,8 +457,29 @@ int cmd_add(int argc, const char **argv, const char *prefix)
431
457
argc -- ;
432
458
argv ++ ;
433
459
460
+ if (0 <= addremove_explicit )
461
+ addremove = addremove_explicit ;
462
+ else if (take_worktree_changes && ADDREMOVE_DEFAULT )
463
+ addremove = 0 ; /* "-u" was given but not "-A" */
464
+
434
465
if (addremove && take_worktree_changes )
435
466
die (_ ("-A and -u are mutually incompatible" ));
467
+
468
+ /*
469
+ * Warn when "git add pathspec..." was given without "-u" or "-A"
470
+ * and pathspec... covers a removed path.
471
+ */
472
+ memset (& update_data , 0 , sizeof (update_data ));
473
+ if (!take_worktree_changes && addremove_explicit < 0 )
474
+ update_data .warn_add_would_remove = 1 ;
475
+
476
+ if (!take_worktree_changes && addremove_explicit < 0 && argc )
477
+ /*
478
+ * Turn "git add pathspec..." to "git add -A pathspec..."
479
+ * in Git 2.0 but not yet
480
+ */
481
+ ; /* addremove = 1; */
482
+
436
483
if (!show_only && ignore_missing )
437
484
die (_ ("Option --ignore-missing can only be used together with --dry-run" ));
438
485
if (addremove ) {
@@ -521,8 +568,20 @@ int cmd_add(int argc, const char **argv, const char *prefix)
521
568
522
569
plug_bulk_checkin ();
523
570
524
- exit_status |= add_files_to_cache (prefix , pathspec , flags );
571
+ if ((flags & ADD_CACHE_IMPLICIT_DOT ) && prefix ) {
572
+ /*
573
+ * Check for modified files throughout the worktree so
574
+ * update_callback has a chance to warn about changes
575
+ * outside the cwd.
576
+ */
577
+ update_data .implicit_dot = prefix ;
578
+ update_data .implicit_dot_len = strlen (prefix );
579
+ pathspec = NULL ;
580
+ }
581
+ update_data .flags = flags & ~ADD_CACHE_IMPLICIT_DOT ;
582
+ update_files_in_cache (prefix , pathspec , & update_data );
525
583
584
+ exit_status |= !!update_data .add_errors ;
526
585
if (add_new_files )
527
586
exit_status |= add_files (& dir , flags );
528
587
0 commit comments