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