diff options
Diffstat (limited to 'builtin/update-index.c')
| -rw-r--r-- | builtin/update-index.c | 317 |
1 files changed, 208 insertions, 109 deletions
diff --git a/builtin/update-index.c b/builtin/update-index.c index a8709a26ec..11dc135271 100644 --- a/builtin/update-index.c +++ b/builtin/update-index.c @@ -3,8 +3,11 @@ * * Copyright (C) Linus Torvalds, 2005 */ +#define USE_THE_INDEX_VARIABLE #include "cache.h" +#include "bulk-checkin.h" #include "config.h" +#include "hex.h" #include "lockfile.h" #include "quote.h" #include "cache-tree.h" @@ -34,6 +37,7 @@ static int verbose; static int mark_valid_only; static int mark_skip_worktree_only; static int mark_fsmonitor_only; +static int ignore_skip_worktree_entries; #define MARK_FLAG 1 #define UNMARK_FLAG 2 static struct strbuf mtime_dir = STRBUF_INIT; @@ -55,6 +59,14 @@ static void report(const char *fmt, ...) if (!verbose) return; + /* + * It is possible, though unlikely, that a caller could use the verbose + * output to synchronize with addition of objects to the object + * database. The current implementation of ODB transactions leaves + * objects invisible while a transaction is active, so flush the + * transaction here before reporting a change made by update-index. + */ + flush_odb_transaction(); va_start(vp, fmt); vprintf(fmt, vp); putchar('\n'); @@ -93,9 +105,7 @@ static int create_file(const char *path) { int fd; path = get_mtime_path(path); - fd = open(path, O_CREAT | O_RDWR, 0644); - if (fd < 0) - die_errno(_("failed to create file %s"), path); + fd = xopen(path, O_CREAT | O_RDWR, 0644); return fd; } @@ -228,16 +238,16 @@ done: static int mark_ce_flags(const char *path, int flag, int mark) { int namelen = strlen(path); - int pos = cache_name_pos(path, namelen); + int pos = index_name_pos(&the_index, path, namelen); if (0 <= pos) { - mark_fsmonitor_invalid(&the_index, active_cache[pos]); + mark_fsmonitor_invalid(&the_index, the_index.cache[pos]); if (mark) - active_cache[pos]->ce_flags |= flag; + the_index.cache[pos]->ce_flags |= flag; else - active_cache[pos]->ce_flags &= ~flag; - active_cache[pos]->ce_flags |= CE_UPDATE_IN_BASE; + the_index.cache[pos]->ce_flags &= ~flag; + the_index.cache[pos]->ce_flags |= CE_UPDATE_IN_BASE; cache_tree_invalidate_path(&the_index, path); - active_cache_changed |= CE_ENTRY_CHANGED; + the_index.cache_changed |= CE_ENTRY_CHANGED; return 0; } return -1; @@ -247,7 +257,7 @@ static int remove_one_path(const char *path) { if (!allow_remove) return error("%s: does not exist and --remove not passed", path); - if (remove_file_from_cache(path)) + if (remove_file_from_index(&the_index, path)) return error("%s: cannot remove from the index", path); return 0; } @@ -268,30 +278,29 @@ static int process_lstat_error(const char *path, int err) static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st) { - int option, size; + int option; struct cache_entry *ce; /* Was the old index entry already up-to-date? */ - if (old && !ce_stage(old) && !ce_match_stat(old, st, 0)) + if (old && !ce_stage(old) && !ie_match_stat(&the_index, old, st, 0)) return 0; - size = cache_entry_size(len); - ce = xcalloc(1, size); + ce = make_empty_cache_entry(&the_index, len); memcpy(ce->name, path, len); ce->ce_flags = create_ce_flags(0); ce->ce_namelen = len; - fill_stat_cache_info(ce, st); + fill_stat_cache_info(&the_index, ce, st); ce->ce_mode = ce_mode_from_stat(old, st->st_mode); - if (index_path(&ce->oid, path, st, + if (index_path(&the_index, &ce->oid, path, st, info_only ? 0 : HASH_WRITE_OBJECT)) { - free(ce); + discard_cache_entry(ce); return -1; } option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; - if (add_cache_entry(ce, option)) { - free(ce); + if (add_index_entry(&the_index, ce, option)) { + discard_cache_entry(ce); return error("%s: cannot add to the index - missing --add option?", path); } return 0; @@ -323,11 +332,11 @@ 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) { struct object_id oid; - int pos = cache_name_pos(path, len); + int pos = index_name_pos(&the_index, path, len); /* Exact match: file or existing gitlink */ if (pos >= 0) { - const struct cache_entry *ce = active_cache[pos]; + const struct cache_entry *ce = the_index.cache[pos]; if (S_ISGITLINK(ce->ce_mode)) { /* Do nothing to the index if there is no HEAD! */ @@ -342,8 +351,8 @@ static int process_directory(const char *path, int len, struct stat *st) /* Inexact match: is there perhaps a subdirectory match? */ pos = -pos-1; - while (pos < active_nr) { - const struct cache_entry *ce = active_cache[pos++]; + while (pos < the_index.cache_nr) { + const struct cache_entry *ce = the_index.cache[pos++]; if (strncmp(ce->name, path, len)) break; @@ -373,15 +382,16 @@ static int process_path(const char *path, struct stat *st, int stat_errno) if (has_symlink_leading_path(path, len)) return error("'%s' is beyond a symbolic link", path); - pos = cache_name_pos(path, len); - ce = pos < 0 ? NULL : active_cache[pos]; + pos = index_name_pos(&the_index, path, len); + ce = pos < 0 ? NULL : the_index.cache[pos]; if (ce && ce_skip_worktree(ce)) { /* * working directory version is assumed "good" * so updating it does not make sense. * On the other hand, removing it from index should work */ - if (allow_remove && remove_file_from_cache(path)) + if (!ignore_skip_worktree_entries && allow_remove && + remove_file_from_index(&the_index, path)) return error("%s: cannot remove from the index", path); return 0; } @@ -402,15 +412,14 @@ static int process_path(const char *path, struct stat *st, int stat_errno) static int add_cacheinfo(unsigned int mode, const struct object_id *oid, const char *path, int stage) { - int size, len, option; + int len, option; struct cache_entry *ce; if (!verify_path(path, mode)) return error("Invalid path '%s'", path); len = strlen(path); - size = cache_entry_size(len); - ce = xcalloc(1, size); + ce = make_empty_cache_entry(&the_index, len); oidcpy(&ce->oid, oid); memcpy(ce->name, path, len); @@ -421,7 +430,7 @@ static int add_cacheinfo(unsigned int mode, const struct object_id *oid, ce->ce_flags |= CE_VALID; option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; - if (add_cache_entry(ce, option)) + if (add_index_entry(&the_index, ce, option)) return error("%s: cannot add to the index - missing --add option?", path); report("add '%s'", path); @@ -433,11 +442,11 @@ static void chmod_path(char flip, const char *path) int pos; struct cache_entry *ce; - pos = cache_name_pos(path, strlen(path)); + pos = index_name_pos(&the_index, path, strlen(path)); if (pos < 0) goto fail; - ce = active_cache[pos]; - if (chmod_cache_entry(ce, flip) < 0) + ce = the_index.cache[pos]; + if (chmod_index_entry(&the_index, ce, flip) < 0) goto fail; report("chmod %cx '%s'", flip, path); @@ -480,7 +489,7 @@ static void update_one(const char *path) } if (force_remove) { - if (remove_file_from_cache(path)) + if (remove_file_from_index(&the_index, path)) die("git update-index: unable to remove %s", path); report("remove '%s'", path); return; @@ -492,6 +501,7 @@ static void update_one(const char *path) static void read_index_info(int nul_term_line) { + const int hexsz = the_hash_algo->hexsz; struct strbuf buf = STRBUF_INIT; struct strbuf uq = STRBUF_INIT; strbuf_getline_fn getline_fn; @@ -529,7 +539,7 @@ static void read_index_info(int nul_term_line) mode = ul; tab = strchr(ptr, '\t'); - if (!tab || tab - ptr < GIT_SHA1_HEXSZ + 1) + if (!tab || tab - ptr < hexsz + 1) goto bad_line; if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') { @@ -542,8 +552,8 @@ static void read_index_info(int nul_term_line) ptr = tab + 1; /* point at the head of path */ } - if (get_oid_hex(tab - GIT_SHA1_HEXSZ, &oid) || - tab[-(GIT_SHA1_HEXSZ + 1)] != ' ') + if (get_oid_hex(tab - hexsz, &oid) || + tab[-(hexsz + 1)] != ' ') goto bad_line; path_name = ptr; @@ -562,7 +572,7 @@ static void read_index_info(int nul_term_line) if (!mode) { /* mode == 0 means there is no such path -- remove */ - if (remove_file_from_cache(path_name)) + if (remove_file_from_index(&the_index, path_name)) die("git update-index: unable to remove %s", ptr); } @@ -571,7 +581,7 @@ static void read_index_info(int nul_term_line) * ptr[-1] points at tab, * ptr[-41] is at the beginning of sha1 */ - ptr[-(GIT_SHA1_HEXSZ + 2)] = ptr[-1] = 0; + ptr[-(hexsz + 2)] = ptr[-1] = 0; if (add_cacheinfo(mode, &oid, path_name, stage)) die("git update-index: unable to update %s", path_name); @@ -597,23 +607,21 @@ static struct cache_entry *read_one_ent(const char *which, struct object_id *ent, const char *path, int namelen, int stage) { - unsigned mode; + unsigned short mode; struct object_id oid; - int size; struct cache_entry *ce; - if (get_tree_entry(ent, path, &oid, &mode)) { + if (get_tree_entry(the_repository, ent, path, &oid, &mode)) { if (which) error("%s: not in %s branch.", path, which); return NULL; } - if (mode == S_IFDIR) { + if (!the_index.sparse_index && mode == S_IFDIR) { if (which) error("%s: not a blob in %s branch.", path, which); return NULL; } - size = cache_entry_size(namelen); - ce = xcalloc(1, size); + ce = make_empty_cache_entry(&the_index, namelen); oidcpy(&ce->oid, &oid); memcpy(ce->name, path, namelen); @@ -631,12 +639,12 @@ static int unresolve_one(const char *path) struct cache_entry *ce_2 = NULL, *ce_3 = NULL; /* See if there is such entry in the index. */ - pos = cache_name_pos(path, namelen); + pos = index_name_pos(&the_index, path, namelen); if (0 <= pos) { /* already merged */ - pos = unmerge_cache_entry_at(pos); - if (pos < active_nr) { - const struct cache_entry *ce = active_cache[pos]; + pos = unmerge_index_entry_at(&the_index, pos); + if (pos < the_index.cache_nr) { + const struct cache_entry *ce = the_index.cache[pos]; if (ce_stage(ce) && ce_namelen(ce) == namelen && !memcmp(ce->name, path, namelen)) @@ -649,8 +657,8 @@ static int unresolve_one(const char *path) * want to do anything in the former case. */ pos = -pos-1; - if (pos < active_nr) { - const struct cache_entry *ce = active_cache[pos]; + if (pos < the_index.cache_nr) { + const struct cache_entry *ce = the_index.cache[pos]; if (ce_namelen(ce) == namelen && !memcmp(ce->name, path, namelen)) { fprintf(stderr, @@ -672,26 +680,26 @@ static int unresolve_one(const char *path) ret = -1; goto free_return; } - if (!oidcmp(&ce_2->oid, &ce_3->oid) && + if (oideq(&ce_2->oid, &ce_3->oid) && ce_2->ce_mode == ce_3->ce_mode) { fprintf(stderr, "%s: identical in both, skipping.\n", path); goto free_return; } - remove_file_from_cache(path); - if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) { + remove_file_from_index(&the_index, path); + if (add_index_entry(&the_index, ce_2, ADD_CACHE_OK_TO_ADD)) { error("%s: cannot add our version to the index.", path); ret = -1; goto free_return; } - if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD)) + if (!add_index_entry(&the_index, ce_3, ADD_CACHE_OK_TO_ADD)) return 0; error("%s: cannot add their version to the index.", path); ret = -1; free_return: - free(ce_2); - free(ce_3); + discard_cache_entry(ce_2); + discard_cache_entry(ce_3); return ret; } @@ -725,8 +733,8 @@ static int do_unresolve(int ac, const char **av, return err; } -static int do_reupdate(int ac, const char **av, - const char *prefix, int prefix_length) +static int do_reupdate(const char **paths, + const char *prefix) { /* Read HEAD and run update-index on paths that are * merged and already different between index and HEAD. @@ -737,7 +745,7 @@ static int do_reupdate(int ac, const char **av, parse_pathspec(&pathspec, 0, PATHSPEC_PREFER_CWD, - prefix, av + 1); + prefix, paths); if (read_ref("HEAD", &head_oid)) /* If there is no HEAD, that means it is an initial @@ -745,32 +753,42 @@ static int do_reupdate(int ac, const char **av, */ has_head = 0; redo: - for (pos = 0; pos < active_nr; pos++) { - const struct cache_entry *ce = active_cache[pos]; + for (pos = 0; pos < the_index.cache_nr; pos++) { + const struct cache_entry *ce = the_index.cache[pos]; struct cache_entry *old = NULL; int save_nr; char *path; - if (ce_stage(ce) || !ce_path_match(ce, &pathspec, NULL)) + if (ce_stage(ce) || !ce_path_match(&the_index, ce, &pathspec, NULL)) continue; if (has_head) old = read_one_ent(NULL, &head_oid, ce->name, ce_namelen(ce), 0); if (old && ce->ce_mode == old->ce_mode && - !oidcmp(&ce->oid, &old->oid)) { - free(old); + oideq(&ce->oid, &old->oid)) { + discard_cache_entry(old); continue; /* unchanged */ } + + /* At this point, we know the contents of the sparse directory are + * modified with respect to HEAD, so we expand the index and restart + * to process each path individually + */ + if (S_ISSPARSEDIR(ce->ce_mode)) { + ensure_full_index(&the_index); + goto redo; + } + /* Be careful. The working tree may not have the * path anymore, in which case, under 'allow_remove', * or worse yet 'allow_replace', active_nr may decrease. */ - save_nr = active_nr; + save_nr = the_index.cache_nr; path = xstrdup(ce->name); update_one(path); free(path); - free(old); - if (save_nr != active_nr) + discard_cache_entry(old); + if (save_nr != the_index.cache_nr) goto redo; } clear_pathspec(&pathspec); @@ -785,20 +803,36 @@ struct refresh_params { static int refresh(struct refresh_params *o, unsigned int flag) { setup_work_tree(); - read_cache_preload(NULL); - *o->has_errors |= refresh_cache(o->flags | flag); + repo_read_index(the_repository); + *o->has_errors |= refresh_index(&the_index, o->flags | flag, NULL, + NULL, NULL); + if (has_racy_timestamp(&the_index)) { + /* + * Even if nothing else has changed, updating the file + * increases the chance that racy timestamps become + * non-racy, helping future run-time performance. + * We do that even in case of "errors" returned by + * refresh_index() as these are no actual errors. + * cmd_status() does the same. + */ + the_index.cache_changed |= SOMETHING_CHANGED; + } return 0; } static int refresh_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return refresh(opt->value, 0); } static int really_refresh_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); return refresh(opt->value, REFRESH_REALLY); } @@ -806,6 +840,7 @@ static int chmod_callback(const struct option *opt, const char *arg, int unset) { char *flip = opt->value; + BUG_ON_OPT_NEG(unset); if ((arg[0] != '-' && arg[0] != '+') || arg[1] != 'x' || arg[2]) return error("option 'chmod' expects \"+x\" or \"-x\""); *flip = arg[0]; @@ -815,7 +850,9 @@ static int chmod_callback(const struct option *opt, static int resolve_undo_clear_callback(const struct option *opt, const char *arg, int unset) { - resolve_undo_clear(); + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + resolve_undo_clear_index(&the_index); return 0; } @@ -826,6 +863,7 @@ static int parse_new_style_cacheinfo(const char *arg, { unsigned long ul; char *endp; + const char *p; if (!arg) return -1; @@ -836,19 +874,23 @@ static int parse_new_style_cacheinfo(const char *arg, return -1; /* not a new-style cacheinfo */ *mode = ul; endp++; - if (get_oid_hex(endp, oid) || endp[GIT_SHA1_HEXSZ] != ',') + if (parse_oid_hex(endp, oid, &p) || *p != ',') return -1; - *path = endp + GIT_SHA1_HEXSZ + 1; + *path = p + 1; return 0; } -static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result cacheinfo_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { struct object_id oid; unsigned int mode; const char *path; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + 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); @@ -866,11 +908,15 @@ static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result stdin_cacheinfo_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *nul_term_line = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); allow_add = allow_replace = allow_remove = 1; @@ -878,46 +924,57 @@ static int stdin_cacheinfo_callback(struct parse_opt_ctx_t *ctx, return 0; } -static int stdin_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int unset) +static enum parse_opt_result stdin_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *read_from_stdin = opt->value; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + if (ctx->argc != 1) return error("option '%s' must be the last argument", opt->long_name); *read_from_stdin = 1; return 0; } -static int unresolve_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int flags) +static enum parse_opt_result unresolve_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + /* consume remaining arguments. */ *has_errors = do_unresolve(ctx->argc, ctx->argv, prefix, prefix ? strlen(prefix) : 0); if (*has_errors) - active_cache_changed = 0; + the_index.cache_changed = 0; ctx->argv += ctx->argc - 1; ctx->argc = 1; return 0; } -static int reupdate_callback(struct parse_opt_ctx_t *ctx, - const struct option *opt, int flags) +static enum parse_opt_result reupdate_callback( + struct parse_opt_ctx_t *ctx, const struct option *opt, + const char *arg, int unset) { int *has_errors = opt->value; const char *prefix = startup_info->prefix; + BUG_ON_OPT_NEG(unset); + BUG_ON_OPT_ARG(arg); + /* consume remaining arguments. */ setup_work_tree(); - *has_errors = do_reupdate(ctx->argc, ctx->argv, - prefix, prefix ? strlen(prefix) : 0); + *has_errors = do_reupdate(ctx->argv + 1, prefix); if (*has_errors) - active_cache_changed = 0; + the_index.cache_changed = 0; ctx->argv += ctx->argc - 1; ctx->argc = 1; @@ -941,6 +998,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) struct parse_opt_ctx_t ctx; strbuf_getline_fn getline_fn; int parseopt_state = PARSE_OPT_UNKNOWN; + struct repository *r = the_repository; struct option options[] = { OPT_BIT('q', NULL, &refresh_args.flags, N_("continue refresh even when index needs update"), @@ -957,24 +1015,25 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) OPT_BIT(0, "unmerged", &refresh_args.flags, N_("refresh even if index contains unmerged entries"), REFRESH_UNMERGED), - {OPTION_CALLBACK, 0, "refresh", &refresh_args, NULL, + OPT_CALLBACK_F(0, "refresh", &refresh_args, NULL, N_("refresh stat information"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, - refresh_callback}, - {OPTION_CALLBACK, 0, "really-refresh", &refresh_args, NULL, + refresh_callback), + OPT_CALLBACK_F(0, "really-refresh", &refresh_args, NULL, N_("like --refresh, but ignore assume-unchanged setting"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, - really_refresh_callback}, + really_refresh_callback), {OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL, N_("<mode>,<object>,<path>"), N_("add the specified entry to the index"), PARSE_OPT_NOARG | /* disallow --cacheinfo=<mode> form */ PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - (parse_opt_cb *) cacheinfo_callback}, - {OPTION_CALLBACK, 0, "chmod", &set_executable_bit, N_("(+/-)x"), + NULL, 0, + cacheinfo_callback}, + OPT_CALLBACK_F(0, "chmod", &set_executable_bit, "(+|-)x", N_("override the executable bit of the listed files"), - PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, - chmod_callback}, + PARSE_OPT_NONEG, + chmod_callback), {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL, N_("mark files as \"not changing\""), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, @@ -987,6 +1046,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, N_("clear skip-worktree bit"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, + OPT_BOOL(0, "ignore-skip-worktree-entries", &ignore_skip_worktree_entries, + N_("do not touch index-only entries")), OPT_SET_INT(0, "info-only", &info_only, N_("add to index only; do not add content to object database"), 1), OPT_SET_INT(0, "force-remove", &force_remove, @@ -996,28 +1057,28 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL, N_("read list of paths to be updated from standard input"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) stdin_callback}, + NULL, 0, stdin_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &nul_term_line, NULL, N_("add entries from standard input to the index"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) stdin_cacheinfo_callback}, + NULL, 0, stdin_cacheinfo_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL, N_("repopulate stages #2 and #3 for the listed paths"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) unresolve_callback}, + NULL, 0, unresolve_callback}, {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL, N_("only update entries that differ from HEAD"), PARSE_OPT_NONEG | PARSE_OPT_NOARG, - (parse_opt_cb *) reupdate_callback}, + NULL, 0, reupdate_callback}, OPT_BIT(0, "ignore-missing", &refresh_args.flags, N_("ignore files missing from worktree"), REFRESH_IGNORE_MISSING), OPT_SET_INT(0, "verbose", &verbose, N_("report actions to standard output"), 1), - {OPTION_CALLBACK, 0, "clear-resolve-undo", NULL, NULL, + OPT_CALLBACK_F(0, "clear-resolve-undo", NULL, NULL, N_("(for porcelains) forget saved unresolved conflicts"), PARSE_OPT_NOARG | PARSE_OPT_NONEG, - resolve_undo_clear_callback}, + resolve_undo_clear_callback), OPT_INTEGER(0, "index-version", &preferred_index_format, N_("write index in this format")), OPT_BOOL(0, "split-index", &split_index, @@ -1046,21 +1107,32 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); + prepare_repo_settings(r); + the_repository->settings.command_requires_full_index = 0; + /* we will diagnose later if it turns out that we need to update it */ - newfd = hold_locked_index(&lock_file, 0); + newfd = repo_hold_locked_index(the_repository, &lock_file, 0); if (newfd < 0) lock_error = errno; - entries = read_cache(); + entries = repo_read_index(the_repository); if (entries < 0) die("cache corrupted"); + the_index.updated_skipworktree = 1; + /* * Custom copy of parse_options() because we want to handle * filename arguments as they come. */ parse_options_start(&ctx, argc, argv, prefix, options, PARSE_OPT_STOP_AT_NON_OPTION); + + /* + * Allow the object layer to optimize adding multiple objects in + * a batch. + */ + begin_odb_transaction(); while (ctx.argc) { if (parseopt_state != PARSE_OPT_DONE) parseopt_state = parse_options_step(&ctx, options, @@ -1071,6 +1143,8 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) case PARSE_OPT_HELP: case PARSE_OPT_ERROR: exit(129); + case PARSE_OPT_COMPLETE: + exit(0); case PARSE_OPT_NON_OPTION: case PARSE_OPT_DONE: { @@ -1106,7 +1180,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) INDEX_FORMAT_LB, INDEX_FORMAT_UB); if (the_index.version != preferred_index_format) - active_cache_changed |= SOMETHING_CHANGED; + the_index.cache_changed |= SOMETHING_CHANGED; the_index.version = preferred_index_format; } @@ -1133,6 +1207,11 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) strbuf_release(&buf); } + /* + * By now we have added all of the new objects + */ + end_odb_transaction(); + if (split_index > 0) { if (git_config_get_split_index() == 0) warning(_("core.splitIndex is set to false; " @@ -1150,11 +1229,12 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) remove_split_index(&the_index); } + prepare_repo_settings(r); switch (untracked_cache) { case UC_UNSPECIFIED: break; case UC_DISABLE: - if (git_config_get_untracked_cache() == 1) + if (r->settings.core_untracked_cache == UNTRACKED_CACHE_WRITE) warning(_("core.untrackedCache is set to true; " "remove or change it, if you really want to " "disable the untracked cache")); @@ -1166,7 +1246,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) return !test_if_untracked_cache_is_supported(); case UC_ENABLE: case UC_FORCE: - if (git_config_get_untracked_cache() == 0) + if (r->settings.core_untracked_cache == UNTRACKED_CACHE_REMOVE) warning(_("core.untrackedCache is set to false; " "remove or change it, if you really want to " "enable the untracked cache")); @@ -1178,14 +1258,33 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) } if (fsmonitor > 0) { - if (git_config_get_fsmonitor() == 0) + enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r); + enum fsmonitor_reason reason = fsm_settings__get_reason(r); + + /* + * The user wants to turn on FSMonitor using the command + * line argument. (We don't know (or care) whether that + * is the IPC or HOOK version.) + * + * Use one of the __get routines to force load the FSMonitor + * config settings into the repo-settings. That will detect + * whether the file system is compatible so that we can stop + * here with a nice error message. + */ + if (reason > FSMONITOR_REASON_OK) + die("%s", + fsm_settings__get_incompatible_msg(r, reason)); + + if (fsm_mode == FSMONITOR_MODE_DISABLED) { warning(_("core.fsmonitor is unset; " "set it if you really want to " "enable fsmonitor")); + } add_fsmonitor(&the_index); report(_("fsmonitor enabled")); } else if (!fsmonitor) { - if (git_config_get_fsmonitor() == 1) + enum fsmonitor_mode fsm_mode = fsm_settings__get_mode(r); + if (fsm_mode > FSMONITOR_MODE_DISABLED) warning(_("core.fsmonitor is set; " "remove it if you really want to " "disable fsmonitor")); @@ -1193,7 +1292,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix) report(_("fsmonitor disabled")); } - if (active_cache_changed || force_write) { + if (the_index.cache_changed || force_write) { if (newfd < 0) { if (refresh_args.flags & REFRESH_QUIET) exit(128); |
