Imported Upstream version 2.13.7
[platform/upstream/git.git] / builtin / update-index.c
index 1c94ca5..1921659 100644 (file)
@@ -125,12 +125,16 @@ static int test_if_untracked_cache_is_supported(void)
        struct stat st;
        struct stat_data base;
        int fd, ret = 0;
+       char *cwd;
 
        strbuf_addstr(&mtime_dir, "mtime-test-XXXXXX");
        if (!mkdtemp(mtime_dir.buf))
                die_errno("Could not make temporary directory");
 
-       fprintf(stderr, _("Testing mtime in '%s' "), xgetcwd());
+       cwd = xgetcwd();
+       fprintf(stderr, _("Testing mtime in '%s' "), cwd);
+       free(cwd);
+
        atexit(remove_test_directory);
        xstat_mtime_dir(&st);
        fill_stat_data(&base, &st);
@@ -255,7 +259,7 @@ static int process_lstat_error(const char *path, int err)
 {
        if (err == ENOENT || err == ENOTDIR)
                return remove_one_path(path);
-       return error("lstat(\"%s\"): %s", path, strerror(errno));
+       return error("lstat(\"%s\"): %s", path, strerror(err));
 }
 
 static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st)
@@ -275,7 +279,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
        fill_stat_cache_info(ce, st);
        ce->ce_mode = ce_mode_from_stat(old, st->st_mode);
 
-       if (index_path(ce->sha1, path, st,
+       if (index_path(ce->oid.hash, path, st,
                       info_only ? 0 : HASH_WRITE_OBJECT)) {
                free(ce);
                return -1;
@@ -312,7 +316,7 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
  */
 static int process_directory(const char *path, int len, struct stat *st)
 {
-       unsigned char sha1[20];
+       struct object_id oid;
        int pos = cache_name_pos(path, len);
 
        /* Exact match: file or existing gitlink */
@@ -321,7 +325,7 @@ static int process_directory(const char *path, int len, struct stat *st)
                if (S_ISGITLINK(ce->ce_mode)) {
 
                        /* Do nothing to the index if there is no HEAD! */
-                       if (resolve_gitlink_ref(path, "HEAD", sha1) < 0)
+                       if (resolve_gitlink_ref(path, "HEAD", oid.hash) < 0)
                                return 0;
 
                        return add_one_path(ce, path, len, st);
@@ -347,17 +351,16 @@ static int process_directory(const char *path, int len, struct stat *st)
        }
 
        /* No match - should we add it as a gitlink? */
-       if (!resolve_gitlink_ref(path, "HEAD", sha1))
+       if (!resolve_gitlink_ref(path, "HEAD", oid.hash))
                return add_one_path(NULL, path, len, st);
 
        /* Error out. */
        return error("%s: is a directory - add files inside instead", path);
 }
 
-static int process_path(const char *path)
+static int process_path(const char *path, struct stat *st, int stat_errno)
 {
        int pos, len;
-       struct stat st;
        const struct cache_entry *ce;
 
        len = strlen(path);
@@ -381,29 +384,29 @@ static int process_path(const char *path)
         * First things first: get the stat information, to decide
         * what to do about the pathname!
         */
-       if (lstat(path, &st) < 0)
-               return process_lstat_error(path, errno);
+       if (stat_errno)
+               return process_lstat_error(path, stat_errno);
 
-       if (S_ISDIR(st.st_mode))
-               return process_directory(path, len, &st);
+       if (S_ISDIR(st->st_mode))
+               return process_directory(path, len, st);
 
-       return add_one_path(ce, path, len, &st);
+       return add_one_path(ce, path, len, st);
 }
 
-static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
+static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
                         const char *path, int stage)
 {
        int size, len, option;
        struct cache_entry *ce;
 
-       if (!verify_path(path))
+       if (!verify_path(path, mode))
                return error("Invalid path '%s'", path);
 
        len = strlen(path);
        size = cache_entry_size(len);
        ce = xcalloc(1, size);
 
-       hashcpy(ce->sha1, sha1);
+       oidcpy(&ce->oid, oid);
        memcpy(ce->name, path, len);
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = len;
@@ -419,30 +422,18 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
        return 0;
 }
 
-static void chmod_path(int flip, const char *path)
+static void chmod_path(char flip, const char *path)
 {
        int pos;
        struct cache_entry *ce;
-       unsigned int mode;
 
        pos = cache_name_pos(path, strlen(path));
        if (pos < 0)
                goto fail;
        ce = active_cache[pos];
-       mode = ce->ce_mode;
-       if (!S_ISREG(mode))
+       if (chmod_cache_entry(ce, flip) < 0)
                goto fail;
-       switch (flip) {
-       case '+':
-               ce->ce_mode |= 0111; break;
-       case '-':
-               ce->ce_mode &= ~0111; break;
-       default:
-               goto fail;
-       }
-       cache_tree_invalidate_path(&the_index, path);
-       ce->ce_flags |= CE_UPDATE_IN_BASE;
-       active_cache_changed |= CE_ENTRY_CHANGED;
+
        report("chmod %cx '%s'", flip, path);
        return;
  fail:
@@ -451,7 +442,17 @@ static void chmod_path(int flip, const char *path)
 
 static void update_one(const char *path)
 {
-       if (!verify_path(path)) {
+       int stat_errno = 0;
+       struct stat st;
+
+       if (mark_valid_only || mark_skip_worktree_only || force_remove)
+               st.st_mode = 0;
+       else if (lstat(path, &st) < 0) {
+               st.st_mode = 0;
+               stat_errno = errno;
+       } /* else stat is valid */
+
+       if (!verify_path(path, st.st_mode)) {
                fprintf(stderr, "Ignoring path %s\n", path);
                return;
        }
@@ -472,7 +473,7 @@ static void update_one(const char *path)
                report("remove '%s'", path);
                return;
        }
-       if (process_path(path))
+       if (process_path(path, &st, stat_errno))
                die("Unable to process path %s", path);
        report("add '%s'", path);
 }
@@ -487,7 +488,7 @@ static void read_index_info(int nul_term_line)
        while (getline_fn(&buf, stdin) != EOF) {
                char *ptr, *tab;
                char *path_name;
-               unsigned char sha1[20];
+               struct object_id oid;
                unsigned int mode;
                unsigned long ul;
                int stage;
@@ -516,7 +517,7 @@ static void read_index_info(int nul_term_line)
                mode = ul;
 
                tab = strchr(ptr, '\t');
-               if (!tab || tab - ptr < 41)
+               if (!tab || tab - ptr < GIT_SHA1_HEXSZ + 1)
                        goto bad_line;
 
                if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') {
@@ -529,7 +530,8 @@ static void read_index_info(int nul_term_line)
                        ptr = tab + 1; /* point at the head of path */
                }
 
-               if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
+               if (get_oid_hex(tab - GIT_SHA1_HEXSZ, &oid) ||
+                       tab[-(GIT_SHA1_HEXSZ + 1)] != ' ')
                        goto bad_line;
 
                path_name = ptr;
@@ -541,7 +543,7 @@ static void read_index_info(int nul_term_line)
                        path_name = uq.buf;
                }
 
-               if (!verify_path(path_name)) {
+               if (!verify_path(path_name, mode)) {
                        fprintf(stderr, "Ignoring path %s\n", path_name);
                        continue;
                }
@@ -557,8 +559,8 @@ static void read_index_info(int nul_term_line)
                         * ptr[-1] points at tab,
                         * ptr[-41] is at the beginning of sha1
                         */
-                       ptr[-42] = ptr[-1] = 0;
-                       if (add_cacheinfo(mode, sha1, path_name, stage))
+                       ptr[-(GIT_SHA1_HEXSZ + 2)] = ptr[-1] = 0;
+                       if (add_cacheinfo(mode, &oid, path_name, stage))
                                die("git update-index: unable to update %s",
                                    path_name);
                }
@@ -576,19 +578,19 @@ static const char * const update_index_usage[] = {
        NULL
 };
 
-static unsigned char head_sha1[20];
-static unsigned char merge_head_sha1[20];
+static struct object_id head_oid;
+static struct object_id merge_head_oid;
 
 static struct cache_entry *read_one_ent(const char *which,
-                                       unsigned char *ent, const char *path,
+                                       struct object_id *ent, const char *path,
                                        int namelen, int stage)
 {
        unsigned mode;
-       unsigned char sha1[20];
+       struct object_id oid;
        int size;
        struct cache_entry *ce;
 
-       if (get_tree_entry(ent, path, sha1, &mode)) {
+       if (get_tree_entry(ent->hash, path, oid.hash, &mode)) {
                if (which)
                        error("%s: not in %s branch.", path, which);
                return NULL;
@@ -601,7 +603,7 @@ static struct cache_entry *read_one_ent(const char *which,
        size = cache_entry_size(namelen);
        ce = xcalloc(1, size);
 
-       hashcpy(ce->sha1, sha1);
+       oidcpy(&ce->oid, &oid);
        memcpy(ce->name, path, namelen);
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = namelen;
@@ -651,14 +653,14 @@ static int unresolve_one(const char *path)
         * stuff HEAD version in stage #2,
         * stuff MERGE_HEAD version in stage #3.
         */
-       ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
-       ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);
+       ce_2 = read_one_ent("our", &head_oid, path, namelen, 2);
+       ce_3 = read_one_ent("their", &merge_head_oid, path, namelen, 3);
 
        if (!ce_2 || !ce_3) {
                ret = -1;
                goto free_return;
        }
-       if (!hashcmp(ce_2->sha1, ce_3->sha1) &&
+       if (!oidcmp(&ce_2->oid, &ce_3->oid) &&
            ce_2->ce_mode == ce_3->ce_mode) {
                fprintf(stderr, "%s: identical in both, skipping.\n",
                        path);
@@ -683,9 +685,9 @@ static int unresolve_one(const char *path)
 
 static void read_head_pointers(void)
 {
-       if (read_ref("HEAD", head_sha1))
+       if (read_ref("HEAD", head_oid.hash))
                die("No HEAD -- no initial commit yet?");
-       if (read_ref("MERGE_HEAD", merge_head_sha1)) {
+       if (read_ref("MERGE_HEAD", merge_head_oid.hash)) {
                fprintf(stderr, "Not in the middle of a merge.\n");
                exit(0);
        }
@@ -725,7 +727,7 @@ static int do_reupdate(int ac, const char **av,
                       PATHSPEC_PREFER_CWD,
                       prefix, av + 1);
 
-       if (read_ref("HEAD", head_sha1))
+       if (read_ref("HEAD", head_oid.hash))
                /* If there is no HEAD, that means it is an initial
                 * commit.  Update everything in the index.
                 */
@@ -740,10 +742,10 @@ static int do_reupdate(int ac, const char **av,
                if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL))
                        continue;
                if (has_head)
-                       old = read_one_ent(NULL, head_sha1,
+                       old = read_one_ent(NULL, &head_oid,
                                           ce->name, ce_namelen(ce), 0);
                if (old && ce->ce_mode == old->ce_mode &&
-                   !hashcmp(ce->sha1, old->sha1)) {
+                   !oidcmp(&ce->oid, &old->oid)) {
                        free(old);
                        continue; /* unchanged */
                }
@@ -759,7 +761,7 @@ static int do_reupdate(int ac, const char **av,
                if (save_nr != active_nr)
                        goto redo;
        }
-       free_pathspec(&pathspec);
+       clear_pathspec(&pathspec);
        return 0;
 }
 
@@ -807,7 +809,7 @@ static int resolve_undo_clear_callback(const struct option *opt,
 
 static int parse_new_style_cacheinfo(const char *arg,
                                     unsigned int *mode,
-                                    unsigned char sha1[],
+                                    struct object_id *oid,
                                     const char **path)
 {
        unsigned long ul;
@@ -822,21 +824,21 @@ static int parse_new_style_cacheinfo(const char *arg,
                return -1; /* not a new-style cacheinfo */
        *mode = ul;
        endp++;
-       if (get_sha1_hex(endp, sha1) || endp[40] != ',')
+       if (get_oid_hex(endp, oid) || endp[GIT_SHA1_HEXSZ] != ',')
                return -1;
-       *path = endp + 41;
+       *path = endp + GIT_SHA1_HEXSZ + 1;
        return 0;
 }
 
 static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
                                const struct option *opt, int unset)
 {
-       unsigned char sha1[20];
+       struct object_id oid;
        unsigned int mode;
        const char *path;
 
-       if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, sha1, &path)) {
-               if (add_cacheinfo(mode, sha1, path, 0))
+       if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, &oid, &path)) {
+               if (add_cacheinfo(mode, &oid, path, 0))
                        die("git update-index: --cacheinfo cannot add %s", path);
                ctx->argv++;
                ctx->argc--;
@@ -845,8 +847,8 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx,
        if (ctx->argc <= 3)
                return error("option 'cacheinfo' expects <mode>,<sha1>,<path>");
        if (strtoul_ui(*++ctx->argv, 8, &mode) ||
-           get_sha1_hex(*++ctx->argv, sha1) ||
-           add_cacheinfo(mode, sha1, *++ctx->argv, 0))
+           get_oid_hex(*++ctx->argv, &oid) ||
+           add_cacheinfo(mode, &oid, *++ctx->argv, 0))
                die("git update-index: --cacheinfo cannot add %s", *ctx->argv);
        ctx->argc -= 3;
        return 0;
@@ -1023,6 +1025,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        /* We can't free this memory, it becomes part of a linked list parsed atexit() */
        lock_file = xcalloc(1, sizeof(struct lock_file));
 
+       /* we will diagnose later if it turns out that we need to update it */
        newfd = hold_locked_index(lock_file, 0);
        if (newfd < 0)
                lock_error = errno;
@@ -1109,17 +1112,20 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        }
 
        if (split_index > 0) {
-               init_split_index(&the_index);
-               the_index.cache_changed |= SPLIT_INDEX_ORDERED;
-       } else if (!split_index && the_index.split_index) {
-               /*
-                * can't discard_split_index(&the_index); because that
-                * will destroy split_index->base->cache[], which may
-                * be shared with the_index.cache[]. So yeah we're
-                * leaking a bit here.
-                */
-               the_index.split_index = NULL;
-               the_index.cache_changed |= SOMETHING_CHANGED;
+               if (git_config_get_split_index() == 0)
+                       warning(_("core.splitIndex is set to false; "
+                                 "remove or change it, if you really want to "
+                                 "enable split index"));
+               if (the_index.split_index)
+                       the_index.cache_changed |= SPLIT_INDEX_ORDERED;
+               else
+                       add_split_index(&the_index);
+       } else if (!split_index) {
+               if (git_config_get_split_index() == 1)
+                       warning(_("core.splitIndex is set to true; "
+                                 "remove or change it, if you really want to "
+                                 "disable split index"));
+               remove_split_index(&the_index);
        }
 
        switch (untracked_cache) {
@@ -1127,9 +1133,9 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
                break;
        case UC_DISABLE:
                if (git_config_get_untracked_cache() == 1)
-                       warning("core.untrackedCache is set to true; "
-                               "remove or change it, if you really want to "
-                               "disable the untracked cache");
+                       warning(_("core.untrackedCache is set to true; "
+                                 "remove or change it, if you really want to "
+                                 "disable the untracked cache"));
                remove_untracked_cache(&the_index);
                report(_("Untracked cache disabled"));
                break;
@@ -1139,14 +1145,14 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        case UC_ENABLE:
        case UC_FORCE:
                if (git_config_get_untracked_cache() == 0)
-                       warning("core.untrackedCache is set to false; "
-                               "remove or change it, if you really want to "
-                               "enable the untracked cache");
+                       warning(_("core.untrackedCache is set to false; "
+                                 "remove or change it, if you really want to "
+                                 "enable the untracked cache"));
                add_untracked_cache(&the_index);
                report(_("Untracked cache enabled for '%s'"), get_git_work_tree());
                break;
        default:
-               die("Bug: bad untracked_cache value: %d", untracked_cache);
+               die("BUG: bad untracked_cache value: %d", untracked_cache);
        }
 
        if (active_cache_changed) {