int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags) { int fd = lock_file(lk, path, flags); if (fd < 0 && (flags & LOCK_DIE_ON_ERROR)) unable_to_lock_index_die(path, errno); return fd; }
int hold_lock_file_for_append(struct lock_file *lk, const char *path, int flags) { int fd, orig_fd; fd = lock_file(lk, path, flags); if (fd < 0) { if (flags & LOCK_DIE_ON_ERROR) unable_to_lock_index_die(path, errno); return fd; } orig_fd = open(path, O_RDONLY); if (orig_fd < 0) { if (errno != ENOENT) { if (flags & LOCK_DIE_ON_ERROR) die("cannot open '%s' for copying", path); close(fd); return error("cannot open '%s' for copying", path); } } else if (copy_fd(orig_fd, fd)) { if (flags & LOCK_DIE_ON_ERROR) exit(128); close(fd); return -1; } return fd; }
int cmd_update_index(int argc, const char **argv, const char *prefix) { int newfd, entries, has_errors = 0, line_termination = '\n'; int read_from_stdin = 0; int prefix_length = prefix ? strlen(prefix) : 0; char set_executable_bit = 0; struct refresh_params refresh_args = {0, &has_errors}; int lock_error = 0; struct lock_file *lock_file; struct parse_opt_ctx_t ctx; int parseopt_state = PARSE_OPT_UNKNOWN; struct option options[] = { OPT_BIT('q', NULL, &refresh_args.flags, "continue refresh even when index needs update", REFRESH_QUIET), OPT_BIT(0, "ignore-submodules", &refresh_args.flags, "refresh: ignore submodules", REFRESH_IGNORE_SUBMODULES), OPT_SET_INT(0, "add", &allow_add, "do not ignore new files", 1), OPT_SET_INT(0, "replace", &allow_replace, "let files replace directories and vice-versa", 1), OPT_SET_INT(0, "remove", &allow_remove, "notice files missing from worktree", 1), OPT_BIT(0, "unmerged", &refresh_args.flags, "refresh even if index contains unmerged entries", REFRESH_UNMERGED), {OPTION_CALLBACK, 0, "refresh", &refresh_args, NULL, "refresh stat information", PARSE_OPT_NOARG | PARSE_OPT_NONEG, refresh_callback}, {OPTION_CALLBACK, 0, "really-refresh", &refresh_args, NULL, "like --refresh, but ignore assume-unchanged setting", PARSE_OPT_NOARG | PARSE_OPT_NONEG, really_refresh_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "cacheinfo", NULL, "<mode> <object> <path>", "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, "(+/-)x", "override the executable bit of the listed files", PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP, chmod_callback}, {OPTION_SET_INT, 0, "assume-unchanged", &mark_valid_only, NULL, "mark files as \"not changing\"", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, {OPTION_SET_INT, 0, "no-assume-unchanged", &mark_valid_only, NULL, "clear assumed-unchanged bit", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, {OPTION_SET_INT, 0, "skip-worktree", &mark_skip_worktree_only, NULL, "mark files as \"index-only\"", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, MARK_FLAG}, {OPTION_SET_INT, 0, "no-skip-worktree", &mark_skip_worktree_only, NULL, "clear skip-worktree bit", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, UNMARK_FLAG}, OPT_SET_INT(0, "info-only", &info_only, "add to index only; do not add content to object database", 1), OPT_SET_INT(0, "force-remove", &force_remove, "remove named paths even if present in worktree", 1), OPT_SET_INT('z', NULL, &line_termination, "with --stdin: input lines are terminated by null bytes", '\0'), {OPTION_LOWLEVEL_CALLBACK, 0, "stdin", &read_from_stdin, NULL, "read list of paths to be updated from standard input", PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) stdin_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "index-info", &line_termination, NULL, "add entries from standard input to the index", PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) stdin_cacheinfo_callback}, {OPTION_LOWLEVEL_CALLBACK, 0, "unresolve", &has_errors, NULL, "repopulate stages #2 and #3 for the listed paths", PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) unresolve_callback}, {OPTION_LOWLEVEL_CALLBACK, 'g', "again", &has_errors, NULL, "only update entries that differ from HEAD", PARSE_OPT_NONEG | PARSE_OPT_NOARG, (parse_opt_cb *) reupdate_callback}, OPT_BIT(0, "ignore-missing", &refresh_args.flags, "ignore files missing from worktree", REFRESH_IGNORE_MISSING), OPT_SET_INT(0, "verbose", &verbose, "report actions to standard output", 1), {OPTION_CALLBACK, 0, "clear-resolve-undo", NULL, NULL, "(for porcelains) forget saved unresolved conflicts", PARSE_OPT_NOARG | PARSE_OPT_NONEG, resolve_undo_clear_callback}, OPT_END() }; if (argc == 2 && !strcmp(argv[1], "-h")) usage(update_index_usage[0]); git_config(git_default_config, NULL); /* We can't free this memory, it becomes part of a linked list parsed atexit() */ lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_locked_index(lock_file, 0); if (newfd < 0) lock_error = errno; entries = read_cache(); if (entries < 0) die("cache corrupted"); /* * 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); while (ctx.argc) { if (parseopt_state != PARSE_OPT_DONE) parseopt_state = parse_options_step(&ctx, options, update_index_usage); if (!ctx.argc) break; switch (parseopt_state) { case PARSE_OPT_HELP: exit(129); case PARSE_OPT_NON_OPTION: case PARSE_OPT_DONE: { const char *path = ctx.argv[0]; const char *p; setup_work_tree(); p = prefix_path(prefix, prefix_length, path); update_one(p, NULL, 0); if (set_executable_bit) chmod_path(set_executable_bit, p); if (p < path || p > path + strlen(path)) free((char *)p); ctx.argc--; ctx.argv++; break; } case PARSE_OPT_UNKNOWN: if (ctx.argv[0][1] == '-') error("unknown option '%s'", ctx.argv[0] + 2); else error("unknown switch '%c'", *ctx.opt); usage_with_options(update_index_usage, options); } } argc = parse_options_end(&ctx); if (read_from_stdin) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; setup_work_tree(); while (strbuf_getline(&buf, stdin, line_termination) != EOF) { const char *p; if (line_termination && buf.buf[0] == '"') { strbuf_reset(&nbuf); if (unquote_c_style(&nbuf, buf.buf, NULL)) die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } p = prefix_path(prefix, prefix_length, buf.buf); update_one(p, NULL, 0); if (set_executable_bit) chmod_path(set_executable_bit, p); if (p < buf.buf || p > buf.buf + buf.len) free((char *)p); } strbuf_release(&nbuf); strbuf_release(&buf); } if (active_cache_changed) { if (newfd < 0) { if (refresh_args.flags & REFRESH_QUIET) exit(128); unable_to_lock_index_die(get_index_file(), lock_error); } if (write_cache(newfd, active_cache, active_nr) || commit_locked_index(lock_file)) die("Unable to write new index file"); } rollback_lock_file(lock_file); return has_errors ? 1 : 0; }
int cmd_update_index(int argc, const char **argv, const char *prefix) { int i, newfd, entries, has_errors = 0, line_termination = '\n'; int allow_options = 1; int read_from_stdin = 0; int prefix_length = prefix ? strlen(prefix) : 0; char set_executable_bit = 0; unsigned int refresh_flags = 0; int lock_error = 0; struct lock_file *lock_file; git_config(git_default_config, NULL); /* We can't free this memory, it becomes part of a linked list parsed atexit() */ lock_file = xcalloc(1, sizeof(struct lock_file)); newfd = hold_locked_index(lock_file, 0); if (newfd < 0) lock_error = errno; entries = read_cache(); if (entries < 0) die("cache corrupted"); for (i = 1 ; i < argc; i++) { const char *path = argv[i]; const char *p; if (allow_options && *path == '-') { if (!strcmp(path, "--")) { allow_options = 0; continue; } if (!strcmp(path, "-q")) { refresh_flags |= REFRESH_QUIET; continue; } if (!strcmp(path, "--ignore-submodules")) { refresh_flags |= REFRESH_IGNORE_SUBMODULES; continue; } if (!strcmp(path, "--add")) { allow_add = 1; continue; } if (!strcmp(path, "--replace")) { allow_replace = 1; continue; } if (!strcmp(path, "--remove")) { allow_remove = 1; continue; } if (!strcmp(path, "--unmerged")) { refresh_flags |= REFRESH_UNMERGED; continue; } if (!strcmp(path, "--refresh")) { setup_work_tree(); has_errors |= refresh_cache(refresh_flags); continue; } if (!strcmp(path, "--really-refresh")) { setup_work_tree(); has_errors |= refresh_cache(REFRESH_REALLY | refresh_flags); continue; } if (!strcmp(path, "--cacheinfo")) { unsigned char sha1[20]; unsigned int mode; if (i+3 >= argc) die("git update-index: --cacheinfo <mode> <sha1> <path>"); if (strtoul_ui(argv[i+1], 8, &mode) || get_sha1_hex(argv[i+2], sha1) || add_cacheinfo(mode, sha1, argv[i+3], 0)) die("git update-index: --cacheinfo" " cannot add %s", argv[i+3]); i += 3; continue; } if (!strcmp(path, "--chmod=-x") || !strcmp(path, "--chmod=+x")) { if (argc <= i+1) die("git update-index: %s <path>", path); set_executable_bit = path[8]; continue; } if (!strcmp(path, "--assume-unchanged")) { mark_valid_only = MARK_VALID; continue; } if (!strcmp(path, "--no-assume-unchanged")) { mark_valid_only = UNMARK_VALID; continue; } if (!strcmp(path, "--info-only")) { info_only = 1; continue; } if (!strcmp(path, "--force-remove")) { force_remove = 1; continue; } if (!strcmp(path, "-z")) { line_termination = 0; continue; } if (!strcmp(path, "--stdin")) { if (i != argc - 1) die("--stdin must be at the end"); read_from_stdin = 1; break; } if (!strcmp(path, "--index-info")) { if (i != argc - 1) die("--index-info must be at the end"); allow_add = allow_replace = allow_remove = 1; read_index_info(line_termination); break; } if (!strcmp(path, "--unresolve")) { has_errors = do_unresolve(argc - i, argv + i, prefix, prefix_length); if (has_errors) active_cache_changed = 0; goto finish; } if (!strcmp(path, "--again") || !strcmp(path, "-g")) { setup_work_tree(); has_errors = do_reupdate(argc - i, argv + i, prefix, prefix_length); if (has_errors) active_cache_changed = 0; goto finish; } if (!strcmp(path, "--ignore-missing")) { refresh_flags |= REFRESH_IGNORE_MISSING; continue; } if (!strcmp(path, "--verbose")) { verbose = 1; continue; } if (!strcmp(path, "-h") || !strcmp(path, "--help")) usage(update_index_usage); die("unknown option %s", path); } setup_work_tree(); p = prefix_path(prefix, prefix_length, path); update_one(p, NULL, 0); if (set_executable_bit) chmod_path(set_executable_bit, p); if (p < path || p > path + strlen(path)) free((char*)p); } if (read_from_stdin) { struct strbuf buf = STRBUF_INIT, nbuf = STRBUF_INIT; setup_work_tree(); while (strbuf_getline(&buf, stdin, line_termination) != EOF) { const char *p; if (line_termination && buf.buf[0] == '"') { strbuf_reset(&nbuf); if (unquote_c_style(&nbuf, buf.buf, NULL)) die("line is badly quoted"); strbuf_swap(&buf, &nbuf); } p = prefix_path(prefix, prefix_length, buf.buf); update_one(p, NULL, 0); if (set_executable_bit) chmod_path(set_executable_bit, p); if (p < buf.buf || p > buf.buf + buf.len) free((char *)p); } strbuf_release(&nbuf); strbuf_release(&buf); } finish: if (active_cache_changed) { if (newfd < 0) { if (refresh_flags & REFRESH_QUIET) exit(128); unable_to_lock_index_die(get_index_file(), lock_error); } if (write_cache(newfd, active_cache, active_nr) || commit_locked_index(lock_file)) die("Unable to write new index file"); } rollback_lock_file(lock_file); return has_errors ? 1 : 0; }