@matheusbsbs / matheus-bagliano / commits / 108da0db12
Fork 0

git add: Add the "--ignore-missing" option for the dry run

Sometimes it is useful to know if a file or directory will be ignored before it is added to the work tree. An example is "git submodule add", where it would be really nice to be able to fail with an appropriate error message before the submodule is cloned and checked out. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jens Lehmann committed Jul 10, 2010 at 00:18 UTC 108da0db1277fc2f4820d0a47c02b2c63111f7a5
5 files changed +47 -6
Documentation/git-add.txt
+8 -1
@@ -57,7 +57,8 @@ OPTIONS
57
58 -n::
59 --dry-run::
60 - Don't actually add the file(s), just show if they exist.
60 + Don't actually add the file(s), just show if they exist and/or will
61 + be ignored.
62
63 -v::
64 --verbose::
@@ -131,6 +132,12 @@ subdirectories.
132 them, do not abort the operation, but continue adding the
133 others. The command shall still exit with non-zero status.
134
135 +--ignore-missing::
136 + This option can only be used together with --dry-run. By using
137 + this option the user can check if any of the given files would
138 + be ignored, no matter if they are already present in the work
139 + tree or not.
140 +
141 \--::
142 This option can be used to separate command-line options from
143 the list of files, (useful when filenames might be mistaken
builtin/add.c
+12 -4
@@ -310,7 +310,7 @@ static const char ignore_error[] =
310 "The following paths are ignored by one of your .gitignore files:\n";
311
312 static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
313 -static int ignore_add_errors, addremove, intent_to_add;
313 +static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
314
315 static struct option builtin_add_options[] = {
316 OPT__DRY_RUN(&show_only),
@@ -325,6 +325,7 @@ static struct option builtin_add_options[] = {
325 OPT_BOOLEAN('A', "all", &addremove, "add all, noticing removal of tracked files"),
326 OPT_BOOLEAN( 0 , "refresh", &refresh_only, "don't add, only refresh the index"),
327 OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, "just skip files which cannot be added because of errors"),
328 + OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, "check if - even missing - files are ignored in dry run"),
329 OPT_END(),
330 };
331
@@ -385,6 +386,8 @@ int cmd_add(int argc, const char **argv, const char *prefix)
386
387 if (addremove && take_worktree_changes)
388 die("-A and -u are mutually incompatible");
389 + if (!show_only && ignore_missing)
390 + die("Option --ignore-missing can only be used together with --dry-run");
391 if ((addremove || take_worktree_changes) && !argc) {
392 static const char *here[2] = { ".", NULL };
393 argc = 1;
@@ -441,9 +444,14 @@ int cmd_add(int argc, const char **argv, const char *prefix)
444 seen = find_used_pathspec(pathspec);
445 for (i = 0; pathspec[i]; i++) {
446 if (!seen[i] && pathspec[i][0]
444 - && !file_exists(pathspec[i]))
445 - die("pathspec '%s' did not match any files",
446 - pathspec[i]);
447 + && !file_exists(pathspec[i])) {
448 + if (ignore_missing) {
449 + if (excluded(&dir, pathspec[i], DT_UNKNOWN))
450 + dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
451 + } else
452 + die("pathspec '%s' did not match any files",
453 + pathspec[i]);
454 + }
455 }
456 free(seen);
457 }
dir.c
+1 -1
@@ -453,7 +453,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
453 return dir->entries[dir->nr++] = dir_entry_new(pathname, len);
454 }
455
456 -static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
456 +struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
457 {
458 if (!cache_name_is_other(pathname, len))
459 return NULL;
dir.h
+1
@@ -72,6 +72,7 @@ extern int read_directory(struct dir_struct *, const char *path, int len, const
72 extern int excluded_from_list(const char *pathname, int pathlen, const char *basename,
73 int *dtype, struct exclude_list *el);
74 extern int excluded(struct dir_struct *, const char *, int *);
75 +struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len);
76 extern int add_excludes_from_file_to_list(const char *fname, const char *base, int baselen,
77 char **buf_p, struct exclude_list *which, int check_index);
78 extern void add_excludes_from_file(struct dir_struct *, const char *fname);
t/t3700-add.sh
+25
@@ -260,4 +260,29 @@ test_expect_success '"add non-existent" should fail' '
260 ! (git ls-files | grep "non-existent")
261 '
262
263 +test_expect_success 'git add --dry-run of existing changed file' "
264 + echo new >>track-this &&
265 + git add --dry-run track-this >actual 2>&1 &&
266 + echo \"add 'track-this'\" | test_cmp - actual
267 +"
268 +
269 +test_expect_success 'git add --dry-run of non-existing file' "
270 + echo ignored-file >>.gitignore &&
271 + ! (git add --dry-run track-this ignored-file >actual 2>&1) &&
272 + echo \"fatal: pathspec 'ignored-file' did not match any files\" | test_cmp - actual
273 +"
274 +
275 +cat >expect <<EOF
276 +The following paths are ignored by one of your .gitignore files:
277 +ignored-file
278 +Use -f if you really want to add them.
279 +fatal: no files added
280 +add 'track-this'
281 +EOF
282 +
283 +test_expect_success 'git add --dry-run --ignore-missing of non-existing file' '
284 + !(git add --dry-run --ignore-missing track-this ignored-file >actual 2>&1) &&
285 + test_cmp expect actual
286 +'
287 +
288 test_done