builtin / add.con commit Merge branch 'ar/t4150-remove-cruft' (7caf4cf)
   1/*
   2 * "git add" builtin command
   3 *
   4 * Copyright (C) 2006 Linus Torvalds
   5 */
   6#define USE_THE_INDEX_COMPATIBILITY_MACROS
   7#include "cache.h"
   8#include "config.h"
   9#include "builtin.h"
  10#include "lockfile.h"
  11#include "dir.h"
  12#include "pathspec.h"
  13#include "exec-cmd.h"
  14#include "cache-tree.h"
  15#include "run-command.h"
  16#include "parse-options.h"
  17#include "diff.h"
  18#include "diffcore.h"
  19#include "revision.h"
  20#include "bulk-checkin.h"
  21#include "argv-array.h"
  22#include "submodule.h"
  23
  24static const char * const builtin_add_usage[] = {
  25        N_("git add [<options>] [--] <pathspec>..."),
  26        NULL
  27};
  28static int patch_interactive, add_interactive, edit_interactive;
  29static int take_worktree_changes;
  30static int add_renormalize;
  31
  32struct update_callback_data {
  33        int flags;
  34        int add_errors;
  35};
  36
  37static void chmod_pathspec(struct pathspec *pathspec, char flip)
  38{
  39        int i;
  40
  41        for (i = 0; i < active_nr; i++) {
  42                struct cache_entry *ce = active_cache[i];
  43
  44                if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
  45                        continue;
  46
  47                if (chmod_cache_entry(ce, flip) < 0)
  48                        fprintf(stderr, "cannot chmod %cx '%s'\n", flip, ce->name);
  49        }
  50}
  51
  52static int fix_unmerged_status(struct diff_filepair *p,
  53                               struct update_callback_data *data)
  54{
  55        if (p->status != DIFF_STATUS_UNMERGED)
  56                return p->status;
  57        if (!(data->flags & ADD_CACHE_IGNORE_REMOVAL) && !p->two->mode)
  58                /*
  59                 * This is not an explicit add request, and the
  60                 * path is missing from the working tree (deleted)
  61                 */
  62                return DIFF_STATUS_DELETED;
  63        else
  64                /*
  65                 * Either an explicit add request, or path exists
  66                 * in the working tree.  An attempt to explicitly
  67                 * add a path that does not exist in the working tree
  68                 * will be caught as an error by the caller immediately.
  69                 */
  70                return DIFF_STATUS_MODIFIED;
  71}
  72
  73static void update_callback(struct diff_queue_struct *q,
  74                            struct diff_options *opt, void *cbdata)
  75{
  76        int i;
  77        struct update_callback_data *data = cbdata;
  78
  79        for (i = 0; i < q->nr; i++) {
  80                struct diff_filepair *p = q->queue[i];
  81                const char *path = p->one->path;
  82                switch (fix_unmerged_status(p, data)) {
  83                default:
  84                        die(_("unexpected diff status %c"), p->status);
  85                case DIFF_STATUS_MODIFIED:
  86                case DIFF_STATUS_TYPE_CHANGED:
  87                        if (add_file_to_index(&the_index, path, data->flags)) {
  88                                if (!(data->flags & ADD_CACHE_IGNORE_ERRORS))
  89                                        die(_("updating files failed"));
  90                                data->add_errors++;
  91                        }
  92                        break;
  93                case DIFF_STATUS_DELETED:
  94                        if (data->flags & ADD_CACHE_IGNORE_REMOVAL)
  95                                break;
  96                        if (!(data->flags & ADD_CACHE_PRETEND))
  97                                remove_file_from_index(&the_index, path);
  98                        if (data->flags & (ADD_CACHE_PRETEND|ADD_CACHE_VERBOSE))
  99                                printf(_("remove '%s'\n"), path);
 100                        break;
 101                }
 102        }
 103}
 104
 105int add_files_to_cache(const char *prefix,
 106                       const struct pathspec *pathspec, int flags)
 107{
 108        struct update_callback_data data;
 109        struct rev_info rev;
 110
 111        memset(&data, 0, sizeof(data));
 112        data.flags = flags;
 113
 114        repo_init_revisions(the_repository, &rev, prefix);
 115        setup_revisions(0, NULL, &rev, NULL);
 116        if (pathspec)
 117                copy_pathspec(&rev.prune_data, pathspec);
 118        rev.diffopt.output_format = DIFF_FORMAT_CALLBACK;
 119        rev.diffopt.format_callback = update_callback;
 120        rev.diffopt.format_callback_data = &data;
 121        rev.diffopt.flags.override_submodule_config = 1;
 122        rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
 123        run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 124        clear_pathspec(&rev.prune_data);
 125        return !!data.add_errors;
 126}
 127
 128static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
 129{
 130        int i, retval = 0;
 131
 132        for (i = 0; i < active_nr; i++) {
 133                struct cache_entry *ce = active_cache[i];
 134
 135                if (ce_stage(ce))
 136                        continue; /* do not touch unmerged paths */
 137                if (!S_ISREG(ce->ce_mode) && !S_ISLNK(ce->ce_mode))
 138                        continue; /* do not touch non blobs */
 139                if (pathspec && !ce_path_match(&the_index, ce, pathspec, NULL))
 140                        continue;
 141                retval |= add_file_to_cache(ce->name, flags | ADD_CACHE_RENORMALIZE);
 142        }
 143
 144        return retval;
 145}
 146
 147static char *prune_directory(struct dir_struct *dir, struct pathspec *pathspec, int prefix)
 148{
 149        char *seen;
 150        int i;
 151        struct dir_entry **src, **dst;
 152
 153        seen = xcalloc(pathspec->nr, 1);
 154
 155        src = dst = dir->entries;
 156        i = dir->nr;
 157        while (--i >= 0) {
 158                struct dir_entry *entry = *src++;
 159                if (dir_path_match(&the_index, entry, pathspec, prefix, seen))
 160                        *dst++ = entry;
 161        }
 162        dir->nr = dst - dir->entries;
 163        add_pathspec_matches_against_index(pathspec, &the_index, seen);
 164        return seen;
 165}
 166
 167static void refresh(int verbose, const struct pathspec *pathspec)
 168{
 169        char *seen;
 170        int i;
 171
 172        seen = xcalloc(pathspec->nr, 1);
 173        refresh_index(&the_index, verbose ? REFRESH_IN_PORCELAIN : REFRESH_QUIET,
 174                      pathspec, seen, _("Unstaged changes after refreshing the index:"));
 175        for (i = 0; i < pathspec->nr; i++) {
 176                if (!seen[i])
 177                        die(_("pathspec '%s' did not match any files"),
 178                            pathspec->items[i].match);
 179        }
 180        free(seen);
 181}
 182
 183int run_add_interactive(const char *revision, const char *patch_mode,
 184                        const struct pathspec *pathspec)
 185{
 186        int status, i;
 187        struct argv_array argv = ARGV_ARRAY_INIT;
 188
 189        argv_array_push(&argv, "add--interactive");
 190        if (patch_mode)
 191                argv_array_push(&argv, patch_mode);
 192        if (revision)
 193                argv_array_push(&argv, revision);
 194        argv_array_push(&argv, "--");
 195        for (i = 0; i < pathspec->nr; i++)
 196                /* pass original pathspec, to be re-parsed */
 197                argv_array_push(&argv, pathspec->items[i].original);
 198
 199        status = run_command_v_opt(argv.argv, RUN_GIT_CMD);
 200        argv_array_clear(&argv);
 201        return status;
 202}
 203
 204int interactive_add(int argc, const char **argv, const char *prefix, int patch)
 205{
 206        struct pathspec pathspec;
 207
 208        parse_pathspec(&pathspec, 0,
 209                       PATHSPEC_PREFER_FULL |
 210                       PATHSPEC_SYMLINK_LEADING_PATH |
 211                       PATHSPEC_PREFIX_ORIGIN,
 212                       prefix, argv);
 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 = CHILD_PROCESS_INIT;
 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        repo_init_revisions(the_repository, &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        rev.diffopt.use_color = 0;
 242        rev.diffopt.flags.ignore_dirty_submodules = 1;
 243        out = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0666);
 244        if (out < 0)
 245                die(_("Could not open '%s' for writing."), file);
 246        rev.diffopt.file = xfdopen(out, "w");
 247        rev.diffopt.close_file = 1;
 248        if (run_diff_files(&rev, 0))
 249                die(_("Could not write patch"));
 250
 251        if (launch_editor(file, NULL, NULL))
 252                die(_("editing patch failed"));
 253
 254        if (stat(file, &st))
 255                die_errno(_("Could not stat '%s'"), file);
 256        if (!st.st_size)
 257                die(_("Empty patch. Aborted."));
 258
 259        child.git_cmd = 1;
 260        child.argv = apply_argv;
 261        if (run_command(&child))
 262                die(_("Could not apply '%s'"), file);
 263
 264        unlink(file);
 265        free(file);
 266        return 0;
 267}
 268
 269static const char ignore_error[] =
 270N_("The following paths are ignored by one of your .gitignore files:\n");
 271
 272static int verbose, show_only, ignored_too, refresh_only;
 273static int ignore_add_errors, intent_to_add, ignore_missing;
 274static int warn_on_embedded_repo = 1;
 275
 276#define ADDREMOVE_DEFAULT 1
 277static int addremove = ADDREMOVE_DEFAULT;
 278static int addremove_explicit = -1; /* unspecified */
 279
 280static char *chmod_arg;
 281
 282static int ignore_removal_cb(const struct option *opt, const char *arg, int unset)
 283{
 284        /* if we are told to ignore, we are not adding removals */
 285        *(int *)opt->value = !unset ? 0 : 1;
 286        return 0;
 287}
 288
 289static struct option builtin_add_options[] = {
 290        OPT__DRY_RUN(&show_only, N_("dry run")),
 291        OPT__VERBOSE(&verbose, N_("be verbose")),
 292        OPT_GROUP(""),
 293        OPT_BOOL('i', "interactive", &add_interactive, N_("interactive picking")),
 294        OPT_BOOL('p', "patch", &patch_interactive, N_("select hunks interactively")),
 295        OPT_BOOL('e', "edit", &edit_interactive, N_("edit current diff and apply")),
 296        OPT__FORCE(&ignored_too, N_("allow adding otherwise ignored files"), 0),
 297        OPT_BOOL('u', "update", &take_worktree_changes, N_("update tracked files")),
 298        OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
 299        OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
 300        OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
 301        { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
 302          NULL /* takes no arguments */,
 303          N_("ignore paths removed in the working tree (same as --no-all)"),
 304          PARSE_OPT_NOARG, ignore_removal_cb },
 305        OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the index")),
 306        OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files which cannot be added because of errors")),
 307        OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even missing - files are ignored in dry run")),
 308        OPT_STRING(0, "chmod", &chmod_arg, "(+|-)x",
 309                   N_("override the executable bit of the listed files")),
 310        OPT_HIDDEN_BOOL(0, "warn-embedded-repo", &warn_on_embedded_repo,
 311                        N_("warn when adding an embedded repository")),
 312        OPT_END(),
 313};
 314
 315static int add_config(const char *var, const char *value, void *cb)
 316{
 317        if (!strcmp(var, "add.ignoreerrors") ||
 318            !strcmp(var, "add.ignore-errors")) {
 319                ignore_add_errors = git_config_bool(var, value);
 320                return 0;
 321        }
 322        return git_default_config(var, value, cb);
 323}
 324
 325static const char embedded_advice[] = N_(
 326"You've added another git repository inside your current repository.\n"
 327"Clones of the outer repository will not contain the contents of\n"
 328"the embedded repository and will not know how to obtain it.\n"
 329"If you meant to add a submodule, use:\n"
 330"\n"
 331"       git submodule add <url> %s\n"
 332"\n"
 333"If you added this path by mistake, you can remove it from the\n"
 334"index with:\n"
 335"\n"
 336"       git rm --cached %s\n"
 337"\n"
 338"See \"git help submodule\" for more information."
 339);
 340
 341static void check_embedded_repo(const char *path)
 342{
 343        struct strbuf name = STRBUF_INIT;
 344
 345        if (!warn_on_embedded_repo)
 346                return;
 347        if (!ends_with(path, "/"))
 348                return;
 349
 350        /* Drop trailing slash for aesthetics */
 351        strbuf_addstr(&name, path);
 352        strbuf_strip_suffix(&name, "/");
 353
 354        warning(_("adding embedded git repository: %s"), name.buf);
 355        if (advice_add_embedded_repo) {
 356                advise(embedded_advice, name.buf, name.buf);
 357                /* there may be multiple entries; advise only once */
 358                advice_add_embedded_repo = 0;
 359        }
 360
 361        strbuf_release(&name);
 362}
 363
 364static int add_files(struct dir_struct *dir, int flags)
 365{
 366        int i, exit_status = 0;
 367
 368        if (dir->ignored_nr) {
 369                fprintf(stderr, _(ignore_error));
 370                for (i = 0; i < dir->ignored_nr; i++)
 371                        fprintf(stderr, "%s\n", dir->ignored[i]->name);
 372                fprintf(stderr, _("Use -f if you really want to add them.\n"));
 373                exit_status = 1;
 374        }
 375
 376        for (i = 0; i < dir->nr; i++) {
 377                check_embedded_repo(dir->entries[i]->name);
 378                if (add_file_to_index(&the_index, dir->entries[i]->name, flags)) {
 379                        if (!ignore_add_errors)
 380                                die(_("adding files failed"));
 381                        exit_status = 1;
 382                }
 383        }
 384        return exit_status;
 385}
 386
 387int cmd_add(int argc, const char **argv, const char *prefix)
 388{
 389        int exit_status = 0;
 390        struct pathspec pathspec;
 391        struct dir_struct dir;
 392        int flags;
 393        int add_new_files;
 394        int require_pathspec;
 395        char *seen = NULL;
 396        struct lock_file lock_file = LOCK_INIT;
 397
 398        git_config(add_config, NULL);
 399
 400        argc = parse_options(argc, argv, prefix, builtin_add_options,
 401                          builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
 402        if (patch_interactive)
 403                add_interactive = 1;
 404        if (add_interactive)
 405                exit(interactive_add(argc - 1, argv + 1, prefix, patch_interactive));
 406
 407        if (edit_interactive)
 408                return(edit_patch(argc, argv, prefix));
 409        argc--;
 410        argv++;
 411
 412        if (0 <= addremove_explicit)
 413                addremove = addremove_explicit;
 414        else if (take_worktree_changes && ADDREMOVE_DEFAULT)
 415                addremove = 0; /* "-u" was given but not "-A" */
 416
 417        if (addremove && take_worktree_changes)
 418                die(_("-A and -u are mutually incompatible"));
 419
 420        if (!take_worktree_changes && addremove_explicit < 0 && argc)
 421                /* Turn "git add pathspec..." to "git add -A pathspec..." */
 422                addremove = 1;
 423
 424        if (!show_only && ignore_missing)
 425                die(_("Option --ignore-missing can only be used together with --dry-run"));
 426
 427        if (chmod_arg && ((chmod_arg[0] != '-' && chmod_arg[0] != '+') ||
 428                          chmod_arg[1] != 'x' || chmod_arg[2]))
 429                die(_("--chmod param '%s' must be either -x or +x"), chmod_arg);
 430
 431        add_new_files = !take_worktree_changes && !refresh_only && !add_renormalize;
 432        require_pathspec = !(take_worktree_changes || (0 < addremove_explicit));
 433
 434        hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR);
 435
 436        flags = ((verbose ? ADD_CACHE_VERBOSE : 0) |
 437                 (show_only ? ADD_CACHE_PRETEND : 0) |
 438                 (intent_to_add ? ADD_CACHE_INTENT : 0) |
 439                 (ignore_add_errors ? ADD_CACHE_IGNORE_ERRORS : 0) |
 440                 (!(addremove || take_worktree_changes)
 441                  ? ADD_CACHE_IGNORE_REMOVAL : 0));
 442
 443        if (require_pathspec && argc == 0) {
 444                fprintf(stderr, _("Nothing specified, nothing added.\n"));
 445                fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
 446                return 0;
 447        }
 448
 449        /*
 450         * Check the "pathspec '%s' did not match any files" block
 451         * below before enabling new magic.
 452         */
 453        parse_pathspec(&pathspec, PATHSPEC_ATTR,
 454                       PATHSPEC_PREFER_FULL |
 455                       PATHSPEC_SYMLINK_LEADING_PATH,
 456                       prefix, argv);
 457
 458        if (read_cache_preload(&pathspec) < 0)
 459                die(_("index file corrupt"));
 460
 461        die_in_unpopulated_submodule(&the_index, prefix);
 462        die_path_inside_submodule(&the_index, &pathspec);
 463
 464        if (add_new_files) {
 465                int baselen;
 466
 467                /* Set up the default git porcelain excludes */
 468                memset(&dir, 0, sizeof(dir));
 469                if (!ignored_too) {
 470                        dir.flags |= DIR_COLLECT_IGNORED;
 471                        setup_standard_excludes(&dir);
 472                }
 473
 474                /* This picks up the paths that are not tracked */
 475                baselen = fill_directory(&dir, &the_index, &pathspec);
 476                if (pathspec.nr)
 477                        seen = prune_directory(&dir, &pathspec, baselen);
 478        }
 479
 480        if (refresh_only) {
 481                refresh(verbose, &pathspec);
 482                goto finish;
 483        }
 484
 485        if (pathspec.nr) {
 486                int i;
 487
 488                if (!seen)
 489                        seen = find_pathspecs_matching_against_index(&pathspec, &the_index);
 490
 491                /*
 492                 * file_exists() assumes exact match
 493                 */
 494                GUARD_PATHSPEC(&pathspec,
 495                               PATHSPEC_FROMTOP |
 496                               PATHSPEC_LITERAL |
 497                               PATHSPEC_GLOB |
 498                               PATHSPEC_ICASE |
 499                               PATHSPEC_EXCLUDE);
 500
 501                for (i = 0; i < pathspec.nr; i++) {
 502                        const char *path = pathspec.items[i].match;
 503                        if (pathspec.items[i].magic & PATHSPEC_EXCLUDE)
 504                                continue;
 505                        if (!seen[i] && path[0] &&
 506                            ((pathspec.items[i].magic &
 507                              (PATHSPEC_GLOB | PATHSPEC_ICASE)) ||
 508                             !file_exists(path))) {
 509                                if (ignore_missing) {
 510                                        int dtype = DT_UNKNOWN;
 511                                        if (is_excluded(&dir, &the_index, path, &dtype))
 512                                                dir_add_ignored(&dir, &the_index,
 513                                                                path, pathspec.items[i].len);
 514                                } else
 515                                        die(_("pathspec '%s' did not match any files"),
 516                                            pathspec.items[i].original);
 517                        }
 518                }
 519                free(seen);
 520        }
 521
 522        plug_bulk_checkin();
 523
 524        if (add_renormalize)
 525                exit_status |= renormalize_tracked_files(&pathspec, flags);
 526        else
 527                exit_status |= add_files_to_cache(prefix, &pathspec, flags);
 528
 529        if (add_new_files)
 530                exit_status |= add_files(&dir, flags);
 531
 532        if (chmod_arg && pathspec.nr)
 533                chmod_pathspec(&pathspec, chmod_arg[0]);
 534        unplug_bulk_checkin();
 535
 536finish:
 537        if (write_locked_index(&the_index, &lock_file,
 538                               COMMIT_LOCK | SKIP_IF_UNCHANGED))
 539                die(_("Unable to write new index file"));
 540
 541        UNLEAK(pathspec);
 542        UNLEAK(dir);
 543        return exit_status;
 544}