Revert "compat: add strtok_r()"
[git/mingw.git] / builtin / add.c
blob0dd014eb96110e46e79fd6bad0bab843551fab79
1 /*
2 * "git add" builtin command
4 * Copyright (C) 2006 Linus Torvalds
5 */
6 #include "cache.h"
7 #include "builtin.h"
8 #include "dir.h"
9 #include "pathspec.h"
10 #include "exec_cmd.h"
11 #include "cache-tree.h"
12 #include "run-command.h"
13 #include "parse-options.h"
14 #include "diff.h"
15 #include "diffcore.h"
16 #include "revision.h"
17 #include "bulk-checkin.h"
19 static const char * const builtin_add_usage[] = {
20 N_("git add [options] [--] <pathspec>..."),
21 NULL
23 static int patch_interactive, add_interactive, edit_interactive;
24 static int take_worktree_changes;
26 struct update_callback_data {
27 int flags;
28 int add_errors;
31 static int fix_unmerged_status(struct diff_filepair *p,
32 struct update_callback_data *data)
34 if (p->status != DIFF_STATUS_UNMERGED)
35 return p->status;
36 if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
38 * This is not an explicit add request, and the
39 * path is missing from the working tree (deleted)
41 return DIFF_STATUS_DELETED;
42 else
44 * Either an explicit add request, or path exists
45 * in the working tree. An attempt to explicitly
46 * add a path that does not exist in the working tree
47 * will be caught as an error by the caller immediately.
49 return DIFF_STATUS_MODIFIED;
52 static void update_callback(struct diff_queue_struct *q,
53 struct diff_options *opt, void *cbdata)
55 int i;
56 struct update_callback_data *data = cbdata;
58 for (i = 0; i < q->nr; i++) {
59 struct diff_filepair *p = q->queue[i];
60 const char *path = p->one->path;
61 switch (fix_unmerged_status(p, data)) {
62 default:
63 die(_("unexpected diff status %c"), p->status);
64 case DIFF_STATUS_MODIFIED:
65 case DIFF_STATUS_TYPE_CHANGED:
66 if (add_file_to_index(&the_index, path, data->flags)) {
67 if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
68 die(_("updating files failed"));
69 data->add_errors++;
71 break;
72 case DIFF_STATUS_DELETED:
73 if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
74 break;
75 if (!(data->flags & ADD_CACHE_PRETEND))
76 remove_file_from_index(&the_index, path);
77 if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
78 printf(_("remove '%s'\n"), path);
79 break;
84 int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
86 struct update_callback_data data;
87 struct rev_info rev;
88 init_revisions(&rev, prefix);
89 setup_revisions(0, NULL, &rev, NULL);
90 init_pathspec(&rev.prune_data, pathspec);
91 rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
92 rev.diffopt.format_callback = update_callback;
93 data.flags = flags;
94 data.add_errors = 0;
95 rev.diffopt.format_callback_data = &data;
96 rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
97 run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
98 return !!data.add_errors;
101 static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
103 char *seen;
104 int i, specs;
105 struct dir_entry **src, **dst;
107 for (specs = 0; pathspec[specs]; specs++)
108 /* nothing */;
109 seen = xcalloc(specs, 1);
111 src = dst = dir->entries;
112 i = dir->nr;
113 while (--i >= 0) {
114 struct dir_entry *entry = *src++;
115 if (match_pathspec(pathspec, entry->name, entry->len,
116 prefix, seen))
117 *dst++ = entry;
119 dir->nr = dst - dir->entries;
120 add_pathspec_matches_against_index(pathspec, seen, specs);
121 return seen;
125 * Checks the index to see whether any path in pathspec refers to
126 * something inside a submodule. If so, dies with an error message.
128 static void treat_gitlinks(const char **pathspec)
130 int i;
132 if (!pathspec || !*pathspec)
133 return;
135 for (i = 0; pathspec[i]; i++)
136 pathspec[i] = check_path_for_gitlink(pathspec[i]);
139 static void refresh(int verbose, const char **pathspec)
141 char *seen;
142 int i, specs;
144 for (specs = 0; pathspec[specs]; specs++)
145 /* nothing */;
146 seen = xcalloc(specs, 1);
147 refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
148 pathspec, seen, _("Unstaged changes after refreshing the index:"));
149 for (i = 0; i < specs; i++) {
150 if (!seen[i])
151 die(_("pathspec '%s' did not match any files"), pathspec[i]);
153 free(seen);
157 * Normalizes argv relative to prefix, via get_pathspec(), and then
158 * runs die_if_path_beyond_symlink() on each path in the normalized
159 * list.
161 static const char **validate_pathspec(const char **argv, const char *prefix)
163 const char **pathspec = get_pathspec(prefix, argv);
165 if (pathspec) {
166 const char **p;
167 for (p = pathspec; *p; p++) {
168 die_if_path_beyond_symlink(*p, prefix);
172 return pathspec;
175 int run_add_interactive(const char *revision, const char *patch_mode,
176 const char **pathspec)
178 int status, ac, pc = 0;
179 const char **args;
181 if (pathspec)
182 while (pathspec[pc])
183 pc++;
185 args = xcalloc(sizeof(const char *), (pc + 5));
186 ac = 0;
187 args[ac++] = "add--interactive";
188 if (patch_mode)
189 args[ac++] = patch_mode;
190 if (revision)
191 args[ac++] = revision;
192 args[ac++] = "--";
193 if (pc) {
194 memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
195 ac += pc;
197 args[ac] = NULL;
199 status = run_command_v_opt(args, RUN_GIT_CMD);
200 free(args);
201 return status;
204 int interactive_add(int argc, const char **argv, const char *prefix, int patch)
206 const char **pathspec = NULL;
208 if (argc) {
209 pathspec = validate_pathspec(argv, prefix);
210 if (!pathspec)
211 return -1;
214 return run_add_interactive(NULL,
215 patch ? "--patch" : NULL,
216 pathspec);
219 static int edit_patch(int argc, const char **argv, const char *prefix)
221 char *file = git_pathdup("ADD_EDIT.patch");
222 const char *apply_argv[] = { "apply", "--recount", "--cached",
223 NULL, NULL };
224 struct child_process child;
225 struct rev_info rev;
226 int out;
227 struct stat st;
229 apply_argv[3] = file;
231 git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
233 if (read_cache() < 0)
234 die (_("Could not read the index"));
236 init_revisions(&rev, prefix);
237 rev.diffopt.context = 7;
239 argc = setup_revisions(argc, argv, &rev, NULL);
240 rev.diffopt.output_format = DIFF_FORMAT_PATCH;
241 DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
242 out = open(file, O_CREAT | O_WRONLY, 0666);
243 if (out < 0)
244 die (_("Could not open '%s' for writing."), file);
245 rev.diffopt.file = xfdopen(out, "w");
246 rev.diffopt.close_file = 1;
247 if (run_diff_files(&rev, 0))
248 die (_("Could not write patch"));
250 launch_editor(file, NULL, NULL);
252 if (stat(file, &st))
253 die_errno(_("Could not stat '%s'"), file);
254 if (!st.st_size)
255 die(_("Empty patch. Aborted."));
257 memset(&child, 0, sizeof(child));
258 child.git_cmd = 1;
259 child.argv = apply_argv;
260 if (run_command(&child))
261 die (_("Could not apply '%s'"), file);
263 unlink(file);
264 free(file);
265 return 0;
268 static struct lock_file lock_file;
270 static const char ignore_error[] =
271 N_("The following paths are ignored by one of your .gitignore files:\n");
273 static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
274 static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
276 static struct option builtin_add_options[] = {
277 OPT__DRY_RUN(&show_only, N_("dry run")),
278 OPT__VERBOSE(&verbose, N_("be verbose")),
279 OPT_GROUP(""),
280 OPT_BOOLEAN('i', "interactive", &add_interactive, N_("interactive picking")),
281 OPT_BOOLEAN('p', "patch", &patch_interactive, N_("select hunks interactively")),
282 OPT_BOOLEAN('e', "edit", &edit_interactive, N_("edit current diff and apply")),
283 OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
284 OPT_BOOLEAN('u', "update", &take_worktree_changes, N_("update tracked files")),
285 OPT_BOOLEAN('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
286 OPT_BOOLEAN('A', "all", &addremove, N_("add changes from all tracked and untracked files")),
287 OPT_BOOLEAN( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
288 OPT_BOOLEAN( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
289 OPT_BOOLEAN( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
290 OPT_END(),
293 static int add_config(const char *var, const char *value, void *cb)
295 if (!strcmp(var, "add.ignoreerrors") ||
296 !strcmp(var, "add.ignore-errors")) {
297 ignore_add_errors = git_config_bool(var, value);
298 return 0;
300 return git_default_config(var, value, cb);
303 static int add_files(struct dir_struct *dir, int flags)
305 int i, exit_status = 0;
307 if (dir->ignored_nr) {
308 fprintf(stderr, _(ignore_error));
309 for (i = 0; i < dir->ignored_nr; i++)
310 fprintf(stderr, "%s\n", dir->ignored[i]->name);
311 fprintf(stderr, _("Use -f if you really want to add them.\n"));
312 die(_("no files added"));
315 for (i = 0; i < dir->nr; i++)
316 if (add_file_to_cache(dir->entries[i]->name, flags)) {
317 if (!ignore_add_errors)
318 die(_("adding files failed"));
319 exit_status = 1;
321 return exit_status;
324 static void warn_pathless_add(const char *option_name, const char *short_name) {
326 * To be consistent with "git add -p" and most Git
327 * commands, we should default to being tree-wide, but
328 * this is not the original behavior and can't be
329 * changed until users trained themselves not to type
330 * "git add -u" or "git add -A". For now, we warn and
331 * keep the old behavior. Later, this warning can be
332 * turned into a die(...), and eventually we may
333 * reallow the command with a new behavior.
335 warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
336 "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
337 "To add content for the whole tree, run:\n"
338 "\n"
339 " git add %s :/\n"
340 " (or git add %s :/)\n"
341 "\n"
342 "To restrict the command to the current directory, run:\n"
343 "\n"
344 " git add %s .\n"
345 " (or git add %s .)\n"
346 "\n"
347 "With the current Git version, the command is restricted to the current directory."),
348 option_name, short_name,
349 option_name, short_name,
350 option_name, short_name);
353 int cmd_add(int argc, const char **argv, const char *prefix)
355 int exit_status = 0;
356 int newfd;
357 const char **pathspec;
358 struct dir_struct dir;
359 int flags;
360 int add_new_files;
361 int require_pathspec;
362 char *seen = NULL;
363 const char *option_with_implicit_dot = NULL;
364 const char *short_option_with_implicit_dot = NULL;
366 git_config(add_config, NULL);
368 argc = parse_options(argc, argv, prefix, builtin_add_options,
369 builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
370 if (patch_interactive)
371 add_interactive = 1;
372 if (add_interactive)
373 exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
375 if (edit_interactive)
376 return(edit_patch(argc, argv, prefix));
377 argc--;
378 argv++;
380 if (addremove && take_worktree_changes)
381 die(_("-A and -u are mutually incompatible"));
382 if (!show_only && ignore_missing)
383 die(_("Option --ignore-missing can only be used together with --dry-run"));
384 if (addremove) {
385 option_with_implicit_dot = "--all";
386 short_option_with_implicit_dot = "-A";
388 if (take_worktree_changes) {
389 option_with_implicit_dot = "--update";
390 short_option_with_implicit_dot = "-u";
392 if (option_with_implicit_dot && !argc) {
393 static const char *here[2] = { ".", NULL };
394 if (prefix)
395 warn_pathless_add(option_with_implicit_dot,
396 short_option_with_implicit_dot);
397 argc = 1;
398 argv = here;
401 add_new_files = !take_worktree_changes && !refresh_only;
402 require_pathspec = !take_worktree_changes;
404 newfd = hold_locked_index(&lock_file, 1);
406 flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
407 (show_only ? ADD_CACHE_PRETEND : 0) |
408 (intent_to_add ? ADD_CACHE_INTENT : 0) |
409 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
410 (!(addremove || take_worktree_changes)
411 ? ADD_CACHE_IGNORE_REMOVAL : 0));
413 if (require_pathspec && argc == 0) {
414 fprintf(stderr, _("Nothing specified, nothing added.\n"));
415 fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
416 return 0;
418 pathspec = validate_pathspec(argv, prefix);
420 if (read_cache() < 0)
421 die(_("index file corrupt"));
422 treat_gitlinks(pathspec);
424 if (add_new_files) {
425 int baselen;
427 /* Set up the default git porcelain excludes */
428 memset(&dir, 0, sizeof(dir));
429 if (!ignored_too) {
430 dir.flags |= DIR_COLLECT_IGNORED;
431 setup_standard_excludes(&dir);
434 /* This picks up the paths that are not tracked */
435 baselen = fill_directory(&dir, pathspec);
436 if (pathspec)
437 seen = prune_directory(&dir, pathspec, baselen);
440 if (refresh_only) {
441 refresh(verbose, pathspec);
442 goto finish;
445 if (pathspec) {
446 int i;
447 struct path_exclude_check check;
449 path_exclude_check_init(&check, &dir);
450 if (!seen)
451 seen = find_pathspecs_matching_against_index(pathspec);
452 for (i = 0; pathspec[i]; i++) {
453 if (!seen[i] && pathspec[i][0]
454 && !file_exists(pathspec[i])) {
455 if (ignore_missing) {
456 int dtype = DT_UNKNOWN;
457 if (is_path_excluded(&check, pathspec[i], -1, &dtype))
458 dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
459 } else
460 die(_("pathspec '%s' did not match any files"),
461 pathspec[i]);
464 free(seen);
465 path_exclude_check_clear(&check);
468 plug_bulk_checkin();
470 exit_status |= add_files_to_cache(prefix, pathspec, flags);
472 if (add_new_files)
473 exit_status |= add_files(&dir, flags);
475 unplug_bulk_checkin();
477 finish:
478 if (active_cache_changed) {
479 if (write_cache(newfd, active_cache, active_nr) ||
480 commit_locked_index(&lock_file))
481 die(_("Unable to write new index file"));
484 return exit_status;