static int update_stages(const char *path, struct diff_filespec *o, struct diff_filespec *a, struct diff_filespec *b, int clear) { int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE; if (clear) if (remove_file_from_cache(path)) return -1; if (o) if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options)) return -1; if (a) if (add_cacheinfo(a->mode, a->sha1, path, 2, 0, options)) return -1; if (b) if (add_cacheinfo(b->mode, b->sha1, path, 3, 0, options)) return -1; return 0; }
static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { unsigned char sha1[20]; unsigned int mode; const char *path; if (!parse_new_style_cacheinfo(ctx->argv[1], &mode, sha1, &path)) { if (add_cacheinfo(mode, sha1, path, 0)) die("git update-index: --cacheinfo cannot add %s", path); ctx->argv++; ctx->argc--; return 0; } 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)) die("git update-index: --cacheinfo cannot add %s", *ctx->argv); ctx->argc -= 3; return 0; }
static int cacheinfo_callback(struct parse_opt_ctx_t *ctx, const struct option *opt, int unset) { unsigned char sha1[20]; unsigned int mode; if (ctx->argc <= 3) return error("option 'cacheinfo' expects three arguments"); if (strtoul_ui(*++ctx->argv, 8, &mode) || get_sha1_hex(*++ctx->argv, sha1) || add_cacheinfo(mode, sha1, *++ctx->argv, 0)) die("git update-index: --cacheinfo cannot add %s", *ctx->argv); ctx->argc -= 3; return 0; }
static void read_index_info(int line_termination) { struct strbuf buf = STRBUF_INIT; struct strbuf uq = STRBUF_INIT; while (strbuf_getline(&buf, stdin, line_termination) != EOF) { char *ptr, *tab; char *path_name; unsigned char sha1[20]; unsigned int mode; unsigned long ul; int stage; /* This reads lines formatted in one of three formats: * * (1) mode SP sha1 TAB path * The first format is what "git apply --index-info" * reports, and used to reconstruct a partial tree * that is used for phony merge base tree when falling * back on 3-way merge. * * (2) mode SP type SP sha1 TAB path * The second format is to stuff "git ls-tree" output * into the index file. * * (3) mode SP sha1 SP stage TAB path * This format is to put higher order stages into the * index file and matches "git ls-files --stage" output. */ errno = 0; ul = strtoul(buf.buf, &ptr, 8); if (ptr == buf.buf || *ptr != ' ' || errno || (unsigned int) ul != ul) goto bad_line; mode = ul; tab = strchr(ptr, '\t'); if (!tab || tab - ptr < 41) goto bad_line; if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') { stage = tab[-1] - '0'; ptr = tab + 1; /* point at the head of path */ tab = tab - 2; /* point at tail of sha1 */ } else { stage = 0; ptr = tab + 1; /* point at the head of path */ } if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ') goto bad_line; path_name = ptr; if (line_termination && path_name[0] == '"') { strbuf_reset(&uq); if (unquote_c_style(&uq, path_name, NULL)) { die("git update-index: bad quoting of path name"); } path_name = uq.buf; } if (!verify_path(path_name)) { fprintf(stderr, "Ignoring path %s\n", path_name); continue; } if (!mode) { /* mode == 0 means there is no such path -- remove */ if (remove_file_from_cache(path_name)) die("git update-index: unable to remove %s", ptr); } else { /* mode ' ' sha1 '\t' name * 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)) die("git update-index: unable to update %s", path_name); } continue; bad_line: die("malformed index info %s", buf.buf); } strbuf_release(&buf); strbuf_release(&uq); }
static int update_file_flags(struct merge_options *o, const unsigned char *sha, unsigned mode, const char *path, int update_cache, int update_wd) { char *real_path; char file_id[41]; int clean = 1; if (update_wd && o->collect_blocks_only) { fill_seafile_blocks (sha, o->bl); return clean; } real_path = g_build_path(PATH_SEPERATOR, o->worktree, path, NULL); if (update_wd) { char *new_path; SeafStat st; char *conflict_suffix; /* When creating a conflict directory, we use o->branch2 as conflict * suffix instead of the last changer name of path. * This is because there may be more than one conflicting file * under this directory, each has different changer. */ if (make_room_for_path(o->index, path, real_path, &new_path, o->branch2, &clean) < 0) { g_free (real_path); return clean; } g_free (real_path); /* Checkout an empty dir. */ if (S_ISDIR (mode)) { if (g_mkdir (path, 0777) < 0) g_warning ("Failed to create empty dir %s.\n", path); return 0; } /* We're checking out a clean file in recover merge. * Note that file is clean only when it's added by others. */ if (update_cache && o->recover_merge && seaf_stat(new_path, &st) == 0 && S_ISREG(st.st_mode)) { if (compare_file_content (new_path, &st, sha, o->crypt) == 0) { real_path = new_path; goto update_cache; } /* If the file was checked out and changed by user, we * don't need to check out again, since the user should * know the content of this file. */ g_free (new_path); return clean; } conflict_suffix = get_last_changer_of_file (o->remote_head, path); if (!conflict_suffix) conflict_suffix = g_strdup(o->branch2); rawdata_to_hex(sha, file_id, 20); if (seaf_fs_manager_checkout_file(seaf->fs_mgr, file_id, new_path, mode, o->crypt, conflict_suffix) < 0) { g_warning("Failed to checkout file %s.\n", file_id); g_free(new_path); g_free (conflict_suffix); return clean; } g_free (conflict_suffix); /* replace real_path with new_path. */ real_path = new_path; } update_cache: if (update_cache) add_cacheinfo(o->index, mode, sha, path, real_path, 0, update_wd, ADD_CACHE_OK_TO_ADD); g_free(real_path); return clean; }
static void update_file_flags(struct merge_options *o, const unsigned char *sha, unsigned mode, const char *path, int update_cache, int update_wd) { if (o->call_depth) update_wd = 0; if (update_wd) { enum object_type type; void *buf; unsigned long size; if (S_ISGITLINK(mode)) die("cannot read object %s '%s': It is a submodule!", sha1_to_hex(sha), path); buf = read_sha1_file(sha, &type, &size); if (!buf) die("cannot read object %s '%s'", sha1_to_hex(sha), path); if (type != OBJ_BLOB) die("blob expected for %s '%s'", sha1_to_hex(sha), path); if (S_ISREG(mode)) { struct strbuf strbuf = STRBUF_INIT; if (convert_to_working_tree(path, buf, size, &strbuf)) { free(buf); size = strbuf.len; buf = strbuf_detach(&strbuf, NULL); } } if (make_room_for_path(path) < 0) { update_wd = 0; free(buf); goto update_index; } if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) { int fd; if (mode & 0100) mode = 0777; else mode = 0666; fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); if (fd < 0) die("failed to open %s: %s", path, strerror(errno)); flush_buffer(fd, buf, size); close(fd); } else if (S_ISLNK(mode)) { char *lnk = xmemdupz(buf, size); safe_create_leading_directories_const(path); unlink(path); if (symlink(lnk, path)) die("failed to symlink %s: %s", path, strerror(errno)); free(lnk); } else die("do not know what to do with %06o %s '%s'", mode, sha1_to_hex(sha), path); free(buf); } update_index: if (update_cache) add_cacheinfo(mode, sha, path, 0, update_wd, ADD_CACHE_OK_TO_ADD); }
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; }