builtin / add.con commit transport-helper: warn when refspec is not used (a93b4a0)
   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
  31static int fix_unmerged_status(struct diff_filepair *p,
  32                               struct update_callback_data *data)
  33{
  34        if (p->status != DIFF_STATUS_UNMERGED)
  35                return p->status;
  36        if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
  37                /*
  38                 * This is not an explicit add request, and the
  39                 * path is missing from the working tree (deleted)
  40                 */
  41                return DIFF_STATUS_DELETED;
  42        else
  43                /*
  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.
  48                 */
  49                return DIFF_STATUS_MODIFIED;
  50}
  51
  52static void update_callback(struct diff_queue_struct *q,
  53                            struct diff_options *opt, void *cbdata)
  54{
  55        int i;
  56        struct update_callback_data *data = cbdata;
  57
  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++;
  70                        }
  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;
  80                }
  81        }
  82}
  83
  84int add_files_to_cache(const char *prefix, const char **pathspec, int flags)
  85{
  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;
  99}
 100
 101static char *prune_directory(struct dir_struct *dir, const char **pathspec, int prefix)
 102{
 103        char *seen;
 104        int i, specs;
 105        struct dir_entry **src, **dst;
 106
 107        for (specs = 0; pathspec[specs];  specs++)
 108                /* nothing */;
 109        seen = xcalloc(specs, 1);
 110
 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;
 118        }
 119        dir->nr = dst - dir->entries;
 120        add_pathspec_matches_against_index(pathspec, seen, specs);
 121        return seen;
 122}
 123
 124/*
 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.
 127 */
 128static void treat_gitlinks(const char **pathspec)
 129{
 130        int i;
 131
 132        if (!pathspec || !*pathspec)
 133                return;
 134
 135        for (i = 0; pathspec[i]; i++)
 136                pathspec[i] = check_path_for_gitlink(pathspec[i]);
 137}
 138
 139static void refresh(int verbose, const char **pathspec)
 140{
 141        char *seen;
 142        int i, specs;
 143
 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]);
 152        }
 153        free(seen);
 154}
 155
 156/*
 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.
 160 */
 161static const char **validate_pathspec(const char **argv, const char *prefix)
 162{
 163        const char **pathspec = get_pathspec(prefix, argv);
 164
 165        if (pathspec) {
 166                const char **p;
 167                for (p = pathspec; *p; p++) {
 168                        die_if_path_beyond_symlink(*p, prefix);
 169                }
 170        }
 171
 172        return pathspec;
 173}
 174
 175int run_add_interactive(const char *revision, const char *patch_mode,
 176                        const char **pathspec)
 177{
 178        int status, ac, pc = 0;
 179        const char **args;
 180
 181        if (pathspec)
 182                while (pathspec[pc])
 183                        pc++;
 184
 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;
 196        }
 197        args[ac] = NULL;
 198
 199        status = run_command_v_opt(args, RUN_GIT_CMD);
 200        free(args);
 201        return status;
 202}
 203
 204int interactive_add(int argc, const char **argv, const char *prefix, int patch)
 205{
 206        const char **pathspec = NULL;
 207
 208        if (argc) {
 209                pathspec = validate_pathspec(argv, prefix);
 210                if (!pathspec)
 211                        return -1;
 212        }
 213
 214        return run_add_interactive(NULL,
 215                                   patch ? "--patch" : NULL,
 216                                   pathspec);
 217}
 218
 219static int edit_patch(int argc, const char **argv, const char *prefix)
 220{
 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;
 228
 229        apply_argv[3] = file;
 230
 231        git_config(git_diff_basic_config, NULL); /* no "diff" UI options */
 232
 233        if (read_cache() < 0)
 234                die (_("Could not read the index"));
 235
 236        init_revisions(&rev, prefix);
 237        rev.diffopt.context = 7;
 238
 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"));
 249
 250        launch_editor(file, NULL, NULL);
 251
 252        if (stat(file, &st))
 253                die_errno(_("Could not stat '%s'"), file);
 254        if (!st.st_size)
 255                die(_("Empty patch. Aborted."));
 256
 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);
 262
 263        unlink(file);
 264        free(file);
 265        return 0;
 266}
 267
 268static struct lock_file lock_file;
 269
 270static const char ignore_error[] =
 271N_("The following paths are ignored by one of your .gitignore files:\n");
 272
 273static int verbose = 0, show_only = 0, ignored_too = 0, refresh_only = 0;
 274static int ignore_add_errors, addremove, intent_to_add, ignore_missing = 0;
 275
 276static 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(),
 291};
 292
 293static int add_config(const char *var, const char *value, void *cb)
 294{
 295        if (!strcmp(var, "add.ignoreerrors") ||
 296            !strcmp(var, "add.ignore-errors")) {
 297                ignore_add_errors = git_config_bool(var, value);
 298                return 0;
 299        }
 300        return git_default_config(var, value, cb);
 301}
 302
 303static int add_files(struct dir_struct *dir, int flags)
 304{
 305        int i, exit_status = 0;
 306
 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"));
 313        }
 314
 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;
 320                }
 321        return exit_status;
 322}
 323
 324static void warn_pathless_add(const char *option_name, const char *short_name) {
 325        /*
 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, the behavior can be changed
 332         * to tree-wide, keeping the warning for a while, and
 333         * eventually we can drop the warning.
 334         */
 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);
 351}
 352
 353int cmd_add(int argc, const char **argv, const char *prefix)
 354{
 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;
 365
 366        git_config(add_config, NULL);
 367
 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));
 374
 375        if (edit_interactive)
 376                return(edit_patch(argc, argv, prefix));
 377        argc--;
 378        argv++;
 379
 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";
 387        }
 388        if (take_worktree_changes) {
 389                option_with_implicit_dot = "--update";
 390                short_option_with_implicit_dot = "-u";
 391        }
 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;
 399        }
 400
 401        add_new_files = !take_worktree_changes && !refresh_only;
 402        require_pathspec = !take_worktree_changes;
 403
 404        newfd = hold_locked_index(&lock_file, 1);
 405
 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));
 412
 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;
 417        }
 418        pathspec = validate_pathspec(argv, prefix);
 419
 420        if (read_cache() < 0)
 421                die(_("index file corrupt"));
 422        treat_gitlinks(pathspec);
 423
 424        if (add_new_files) {
 425                int baselen;
 426
 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);
 432                }
 433
 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);
 438        }
 439
 440        if (refresh_only) {
 441                refresh(verbose, pathspec);
 442                goto finish;
 443        }
 444
 445        if (pathspec) {
 446                int i;
 447                struct path_exclude_check check;
 448
 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]);
 462                        }
 463                }
 464                free(seen);
 465                path_exclude_check_clear(&check);
 466        }
 467
 468        plug_bulk_checkin();
 469
 470        exit_status |= add_files_to_cache(prefix, pathspec, flags);
 471
 472        if (add_new_files)
 473                exit_status |= add_files(&dir, flags);
 474
 475        unplug_bulk_checkin();
 476
 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"));
 482        }
 483
 484        return exit_status;
 485}