4242bce6d8c4aa075c7523c970ed2442788f5ae3
   1/*
   2 * "git add" builtin command
   3 *
   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"
  18
  19static const char * const builtin_add_usage[] = {
  20        N_("git add [options] [--] <pathspec>..."),
  21        NULL
  22};
  23static int patch_interactive, add_interactive, edit_interactive;
  24static int take_worktree_changes;
  25
  26struct update_callback_data {
  27        int flags;
  28        int add_errors;
  29
  30        /* only needed for 2.0 transition preparation */
  31        int warn_add_would_remove;
  32};
  33
  34static int fix_unmerged_status(struct diff_filepair *p,
  35                               struct update_callback_data *data)
  36{
  37        if (p->status != DIFF_STATUS_UNMERGED)
  38                return p->status;
  39        if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
  40                /*
  41                 * This is not an explicit add request, and the
  42                 * path is missing from the working tree (deleted)
  43                 */
  44                return DIFF_STATUS_DELETED;
  45        else
  46                /*
  47                 * Either an explicit add request, or path exists
  48                 * in the working tree.  An attempt to explicitly
  49                 * add a path that does not exist in the working tree
  50                 * will be caught as an error by the caller immediately.
  51                 */
  52                return DIFF_STATUS_MODIFIED;
  53}
  54
  55static void warn_add_would_remove(const char *path)
  56{
  57        warning(_("In Git 2.0, 'git add <pathspec>...' will also update the\n"
  58                  "index for paths removed from the working tree that match\n"
  59                  "the given pathspec. If you want to 'add' only changed\n"
  60                  "or newly created paths, say 'git add --no-all <pathspec>...'"
  61                  " instead.\n\n"
  62                  "'%s' would be removed from the index without --no-all."),
  63                path);
  64}
  65
  66static void update_callback(struct diff_queue_struct *q,
  67                            struct diff_options *opt, void *cbdata)
  68{
  69        int i;
  70        struct update_callback_data *data = cbdata;
  71
  72        for (i = 0; i < q->nr; i++) {
  73                struct diff_filepair *p = q->queue[i];
  74                const char *path = p->one->path;
  75                switch (fix_unmerged_status(p, data)) {
  76                default:
  77                        die(_("unexpected diff status %c"), p->status);
  78                case DIFF_STATUS_MODIFIED:
  79                case DIFF_STATUS_TYPE_CHANGED:
  80                        if (add_file_to_index(&the_index, path, data->flags)) {
  81                                if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
  82                                        die(_("updating files failed"));
  83                                data->add_errors++;
  84                        }
  85                        break;
  86                case DIFF_STATUS_DELETED:
  87                        if (data->warn_add_would_remove) {
  88                                warn_add_would_remove(path);
  89                                data->warn_add_would_remove = 0;
  90                        }
  91                        if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
  92                                break;
  93                        if (!(data->flags & ADD_CACHE_PRETEND))
  94                                remove_file_from_index(&the_index, path);
  95                        if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
  96                                printf(_("remove '%s'\n"), path);
  97                        break;
  98                }
  99        }
 100}
 101
 102static void update_files_in_cache(const char *prefix, const char **pathspec,
 103                                  struct update_callback_data *data)
 104{
 105        struct rev_info rev;
 106        init_revisions(&rev, prefix);
 107        setup_revisions(0, NULL, &rev, NULL);
 108        init_pathspec(&rev.prune_data, pathspec);
 109        rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
 110        rev.diffopt.format_callback = update_callback;
 111        rev.diffopt.format_callback_data = data;
 112        rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
 113        run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 114}
 115
 116int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
 117{
 118        struct update_callback_data data;
 119
 120        memset(&data, 0, sizeof(data));
 121        data.flags = flags;
 122        update_files_in_cache(prefix, pathspec, &data);
 123        return !!data.add_errors;
 124}
 125
 126static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
 127{
 128        char *seen;
 129        int i, specs;
 130        struct dir_entry **src, **dst;
 131
 132        for (specs = 0; pathspec[specs];  specs++)
 133                /* nothing */;
 134        seen = xcalloc(specs, 1);
 135
 136        src = dst = dir->entries;
 137        i = dir->nr;
 138        while (--i >= 0) {
 139                struct dir_entry *entry = *src++;
 140                if (match_pathspec(pathspec, entry->name, entry->len,
 141                                   prefix, seen))
 142                        *dst++ = entry;
 143        }
 144        dir->nr = dst - dir->entries;
 145        add_pathspec_matches_against_index(pathspec, seen, specs);
 146        return seen;
 147}
 148
 149/*
 150 * Checks the index to see whether any path in pathspec refers to
 151 * something inside a submodule.  If so, dies with an error message.
 152 */
 153static void treat_gitlinks(const char **pathspec)
 154{
 155        int i;
 156
 157        if (!pathspec || !*pathspec)
 158                return;
 159
 160        for (i = 0; pathspec[i]; i++)
 161                pathspec[i] = check_path_for_gitlink(pathspec[i]);
 162}
 163
 164static void refresh(int verbose, const char **pathspec)
 165{
 166        char *seen;
 167        int i, specs;
 168
 169        for (specs = 0; pathspec[specs];  specs++)
 170                /* nothing */;
 171        seen = xcalloc(specs, 1);
 172        refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
 173                      pathspec, seen, _("Unstaged changes after refreshing the index:"));
 174        for (i = 0; i < specs; i++) {
 175                if (!seen[i])
 176                        die(_("pathspec '%s' did not match any files"), pathspec[i]);
 177        }
 178        free(seen);
 179}
 180
 181/*
 182 * Normalizes argv relative to prefix, via get_pathspec(), and then
 183 * runs die_if_path_beyond_symlink() on each path in the normalized
 184 * list.
 185 */
 186static const char **validate_pathspec(const char **argv, const char *prefix)
 187{
 188        const char **pathspec = get_pathspec(prefix, argv);
 189
 190        if (pathspec) {
 191                const char **p;
 192                for (p = pathspec; *p; p++) {
 193                        die_if_path_beyond_symlink(*p, prefix);
 194                }
 195        }
 196
 197        return pathspec;
 198}
 199
 200int run_add_interactive(const char *revision, const char *patch_mode,
 201                        const char **pathspec)
 202{
 203        int status, ac, pc = 0;
 204        const char **args;
 205
 206        if (pathspec)
 207                while (pathspec[pc])
 208                        pc++;
 209
 210        args = xcalloc(sizeof(const char *), (pc + 5));
 211        ac = 0;
 212        args[ac++] = "add--interactive";
 213        if (patch_mode)
 214                args[ac++] = patch_mode;
 215        if (revision)
 216                args[ac++] = revision;
 217        args[ac++] = "--";
 218        if (pc) {
 219                memcpy(&(args[ac]), pathspec, sizeof(const char *) * pc);
 220                ac += pc;
 221        }
 222        args[ac] = NULL;
 223
 224        status = run_command_v_opt(args, RUN_GIT_CMD);
 225        free(args);
 226        return status;
 227}
 228
 229int interactive_add(int argc, const char **argv, const char *prefix, int patch)
 230{
 231        const char **pathspec = NULL;
 232
 233        if (argc) {
 234                pathspec = validate_pathspec(argv, prefix);
 235                if (!pathspec)
 236                        return -1;
 237        }
 238
 239        return run_add_interactive(NULL,
 240                                   patch ? "--patch" : NULL,
 241                                   pathspec);
 242}
 243
 244static int edit_patch(int argc, const char **argv, const char *prefix)
 245{
 246        char *file = git_pathdup("ADD_EDIT.patch");
 247        const char *apply_argv[] = { "apply", "--recount", "--cached",
 248                NULL, NULL };
 249        struct child_process child;
 250        struct rev_info rev;
 251        int out;
 252        struct stat st;
 253
 254        apply_argv[3] = file;
 255
 256        git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
 257
 258        if (read_cache() < 0)
 259                die (_("Could not read the index"));
 260
 261        init_revisions(&rev, prefix);
 262        rev.diffopt.context = 7;
 263
 264        argc = setup_revisions(argc, argv, &rev, NULL);
 265        rev.diffopt.output_format = DIFF_FORMAT_PATCH;
 266        DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
 267        out = open(file, O_CREAT | O_WRONLY, 0666);
 268        if (out < 0)
 269                die (_("Could not open '%s' for writing."), file);
 270        rev.diffopt.file = xfdopen(out, "w");
 271        rev.diffopt.close_file = 1;
 272        if (run_diff_files(&rev, 0))
 273                die (_("Could not write patch"));
 274
 275        launch_editor(file, NULL, NULL);
 276
 277        if (stat(file, &st))
 278                die_errno(_("Could not stat '%s'"), file);
 279        if (!st.st_size)
 280                die(_("Empty patch. Aborted."));
 281
 282        memset(&child, 0, sizeof(child));
 283        child.git_cmd = 1;
 284        child.argv = apply_argv;
 285        if (run_command(&child))
 286                die (_("Could not apply '%s'"), file);
 287
 288        unlink(file);
 289        free(file);
 290        return 0;
 291}
 292
 293static struct lock_file lock_file;
 294
 295static const char ignore_error[] =
 296N_("The following paths are ignored by one of your .gitignore files:\n");
 297
 298static int verbose, show_only, ignored_too, refresh_only;
 299static int ignore_add_errors, intent_to_add, ignore_missing;
 300
 301#define ADDREMOVE_DEFAULT 0 /* Change to 1 in Git 2.0 */
 302static int addremove = ADDREMOVE_DEFAULT;
 303static int addremove_explicit = -1; /* unspecified */
 304
 305static struct option builtin_add_options[] = {
 306        OPT__DRY_RUN(&show_only, N_("dry run")),
 307        OPT__VERBOSE(&verbose, N_("be verbose")),
 308        OPT_GROUP(""),
 309        OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
 310        OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
 311        OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
 312        OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files")),
 313        OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
 314        OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
 315        OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
 316        OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
 317        OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
 318        OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
 319        OPT_END(),
 320};
 321
 322static int add_config(const char *var, const char *value, void *cb)
 323{
 324        if (!strcmp(var, "add.ignoreerrors") ||
 325            !strcmp(var, "add.ignore-errors")) {
 326                ignore_add_errors = git_config_bool(var, value);
 327                return 0;
 328        }
 329        return git_default_config(var, value, cb);
 330}
 331
 332static int add_files(struct dir_struct *dir, int flags)
 333{
 334        int i, exit_status = 0;
 335
 336        if (dir->ignored_nr) {
 337                fprintf(stderr, _(ignore_error));
 338                for (i = 0; i < dir->ignored_nr; i++)
 339                        fprintf(stderr, "%s\n", dir->ignored[i]->name);
 340                fprintf(stderr, _("Use -f if you really want to add them.\n"));
 341                die(_("no files added"));
 342        }
 343
 344        for (i = 0; i < dir->nr; i++)
 345                if (add_file_to_cache(dir->entries[i]->name, flags)) {
 346                        if (!ignore_add_errors)
 347                                die(_("adding files failed"));
 348                        exit_status = 1;
 349                }
 350        return exit_status;
 351}
 352
 353static void warn_pathless_add(const char *option_name, const char *short_name) {
 354        /*
 355         * To be consistent with "git add -p" and most Git
 356         * commands, we should default to being tree-wide, but
 357         * this is not the original behavior and can't be
 358         * changed until users trained themselves not to type
 359         * "git add -u" or "git add -A". For now, we warn and
 360         * keep the old behavior. Later, this warning can be
 361         * turned into a die(...), and eventually we may
 362         * reallow the command with a new behavior.
 363         */
 364        warning(_("The behavior of 'git add %s (or %s)' with no path argument from a\n"
 365                  "subdirectory of the tree will change in Git 2.0 and should not be used anymore.\n"
 366                  "To add content for the whole tree, run:\n"
 367                  "\n"
 368                  "  git add %s :/\n"
 369                  "  (or git add %s :/)\n"
 370                  "\n"
 371                  "To restrict the command to the current directory, run:\n"
 372                  "\n"
 373                  "  git add %s .\n"
 374                  "  (or git add %s .)\n"
 375                  "\n"
 376                  "With the current Git version, the command is restricted to the current directory."),
 377                option_name, short_name,
 378                option_name, short_name,
 379                option_name, short_name);
 380}
 381
 382int cmd_add(int argc, const char **argv, const char *prefix)
 383{
 384        int exit_status = 0;
 385        int newfd;
 386        const char **pathspec;
 387        struct dir_struct dir;
 388        int flags;
 389        int add_new_files;
 390        int require_pathspec;
 391        char *seen = NULL;
 392        const char *option_with_implicit_dot = NULL;
 393        const char *short_option_with_implicit_dot = NULL;
 394        struct update_callback_data update_data;
 395
 396        git_config(add_config, NULL);
 397
 398        argc = parse_options(argc, argv, prefix, builtin_add_options,
 399                          builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
 400        if (patch_interactive)
 401                add_interactive = 1;
 402        if (add_interactive)
 403                exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
 404
 405        if (edit_interactive)
 406                return(edit_patch(argc, argv, prefix));
 407        argc--;
 408        argv++;
 409
 410        if (0 <= addremove_explicit)
 411                addremove = addremove_explicit;
 412        else if (take_worktree_changes && ADDREMOVE_DEFAULT)
 413                addremove = 0; /* "-u" was given but not "-A" */
 414
 415        if (addremove && take_worktree_changes)
 416                die(_("-A and -u are mutually incompatible"));
 417
 418        /*
 419         * Warn when "git add pathspec..." was given without "-u" or "-A"
 420         * and pathspec... covers a removed path.
 421         */
 422        memset(&update_data, 0, sizeof(update_data));
 423        if (!take_worktree_changes && addremove_explicit < 0)
 424                update_data.warn_add_would_remove = 1;
 425
 426        if (!take_worktree_changes && addremove_explicit < 0 && argc)
 427                /*
 428                 * Turn "git add pathspec..." to "git add -A pathspec..."
 429                 * in Git 2.0 but not yet
 430                 */
 431                ; /* addremove = 1; */
 432
 433        if (!show_only && ignore_missing)
 434                die(_("Option --ignore-missing can only be used together with --dry-run"));
 435        if (addremove) {
 436                option_with_implicit_dot = "--all";
 437                short_option_with_implicit_dot = "-A";
 438        }
 439        if (take_worktree_changes) {
 440                option_with_implicit_dot = "--update";
 441                short_option_with_implicit_dot = "-u";
 442        }
 443        if (option_with_implicit_dot && !argc) {
 444                static const char *here[2] = { ".", NULL };
 445                if (prefix)
 446                        warn_pathless_add(option_with_implicit_dot,
 447                                          short_option_with_implicit_dot);
 448                argc = 1;
 449                argv = here;
 450        }
 451
 452        add_new_files = !take_worktree_changes && !refresh_only;
 453        require_pathspec = !take_worktree_changes;
 454
 455        newfd = hold_locked_index(&lock_file, 1);
 456
 457        flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
 458                 (show_only ? ADD_CACHE_PRETEND : 0) |
 459                 (intent_to_add ? ADD_CACHE_INTENT : 0) |
 460                 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
 461                 (!(addremove || take_worktree_changes)
 462                  ? ADD_CACHE_IGNORE_REMOVAL : 0));
 463
 464        if (require_pathspec && argc == 0) {
 465                fprintf(stderr, _("Nothing specified, nothing added.\n"));
 466                fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
 467                return 0;
 468        }
 469        pathspec = validate_pathspec(argv, prefix);
 470
 471        if (read_cache() < 0)
 472                die(_("index file corrupt"));
 473        treat_gitlinks(pathspec);
 474
 475        if (add_new_files) {
 476                int baselen;
 477
 478                /* Set up the default git porcelain excludes */
 479                memset(&dir, 0, sizeof(dir));
 480                if (!ignored_too) {
 481                        dir.flags |= DIR_COLLECT_IGNORED;
 482                        setup_standard_excludes(&dir);
 483                }
 484
 485                /* This picks up the paths that are not tracked */
 486                baselen = fill_directory(&dir, pathspec);
 487                if (pathspec)
 488                        seen = prune_directory(&dir, pathspec, baselen);
 489        }
 490
 491        if (refresh_only) {
 492                refresh(verbose, pathspec);
 493                goto finish;
 494        }
 495
 496        if (pathspec) {
 497                int i;
 498                struct path_exclude_check check;
 499
 500                path_exclude_check_init(&check, &dir);
 501                if (!seen)
 502                        seen = find_pathspecs_matching_against_index(pathspec);
 503                for (i = 0; pathspec[i]; i++) {
 504                        if (!seen[i] && pathspec[i][0]
 505                            && !file_exists(pathspec[i])) {
 506                                if (ignore_missing) {
 507                                        int dtype = DT_UNKNOWN;
 508                                        if (is_path_excluded(&check, pathspec[i], -1, &dtype))
 509                                                dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
 510                                } else
 511                                        die(_("pathspec '%s' did not match any files"),
 512                                            pathspec[i]);
 513                        }
 514                }
 515                free(seen);
 516                path_exclude_check_clear(&check);
 517        }
 518
 519        plug_bulk_checkin();
 520
 521        update_data.flags = flags;
 522        update_files_in_cache(prefix, pathspec, &update_data);
 523
 524        exit_status |= !!update_data.add_errors;
 525        if (add_new_files)
 526                exit_status |= add_files(&dir, flags);
 527
 528        unplug_bulk_checkin();
 529
 530 finish:
 531        if (active_cache_changed) {
 532                if (write_cache(newfd, active_cache, active_nr) ||
 533                    commit_locked_index(&lock_file))
 534                        die(_("Unable to write new index file"));
 535        }
 536
 537        return exit_status;
 538}