diff options
55 files changed, 337 insertions, 245 deletions
@@ -76,10 +76,12 @@ static int parse_ignorewhitespace_option(struct apply_state *state, } int init_apply_state(struct apply_state *state, + struct repository *repo, const char *prefix) { memset(state, 0, sizeof(*state)); state->prefix = prefix; + state->repo = repo; state->apply = 1; state->line_termination = '\n'; state->p_value = 1; @@ -3374,14 +3376,17 @@ static struct patch *previous_patch(struct apply_state *state, return previous; } -static int verify_index_match(const struct cache_entry *ce, struct stat *st) +static int verify_index_match(struct apply_state *state, + const struct cache_entry *ce, + struct stat *st) { if (S_ISGITLINK(ce->ce_mode)) { if (!S_ISDIR(st->st_mode)) return -1; return 0; } - return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); + return ie_match_stat(state->repo->index, ce, st, + CE_MATCH_IGNORE_VALID | CE_MATCH_IGNORE_SKIP_WORKTREE); } #define SUBMODULE_PATCH_WITHOUT_INDEX 1 @@ -3514,17 +3519,17 @@ static int load_current(struct apply_state *state, if (!patch->is_new) BUG("patch to %s is not a creation", patch->old_name); - pos = cache_name_pos(name, strlen(name)); + pos = index_name_pos(state->repo->index, name, strlen(name)); if (pos < 0) return error(_("%s: does not exist in index"), name); - ce = active_cache[pos]; + ce = state->repo->index->cache[pos]; if (lstat(name, &st)) { if (errno != ENOENT) return error_errno("%s", name); - if (checkout_target(&the_index, ce, &st)) + if (checkout_target(state->repo->index, ce, &st)) return -1; } - if (verify_index_match(ce, &st)) + if (verify_index_match(state, ce, &st)) return error(_("%s: does not match index"), name); status = load_patch_target(state, &buf, ce, &st, patch, name, mode); @@ -3683,18 +3688,19 @@ static int check_preimage(struct apply_state *state, } if (state->check_index && !previous) { - int pos = cache_name_pos(old_name, strlen(old_name)); + int pos = index_name_pos(state->repo->index, old_name, + strlen(old_name)); if (pos < 0) { if (patch->is_new < 0) goto is_new; return error(_("%s: does not exist in index"), old_name); } - *ce = active_cache[pos]; + *ce = state->repo->index->cache[pos]; if (stat_ret < 0) { - if (checkout_target(&the_index, *ce, st)) + if (checkout_target(state->repo->index, *ce, st)) return -1; } - if (!state->cached && verify_index_match(*ce, st)) + if (!state->cached && verify_index_match(state, *ce, st)) return error(_("%s: does not match index"), old_name); if (state->cached) st_mode = (*ce)->ce_mode; @@ -3738,7 +3744,7 @@ static int check_to_create(struct apply_state *state, struct stat nst; if (state->check_index && - cache_name_pos(new_name, strlen(new_name)) >= 0 && + index_name_pos(state->repo->index, new_name, strlen(new_name)) >= 0 && !ok_if_exists) return EXISTS_IN_INDEX; if (state->cached) @@ -3827,7 +3833,8 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na if (state->check_index) { struct cache_entry *ce; - ce = cache_file_exists(name->buf, name->len, ignore_case); + ce = index_file_exists(state->repo->index, name->buf, + name->len, ignore_case); if (ce && S_ISLNK(ce->ce_mode)) return 1; } else { @@ -4002,9 +4009,10 @@ static int check_patch_list(struct apply_state *state, struct patch *patch) static int read_apply_cache(struct apply_state *state) { if (state->index_file) - return read_cache_from(state->index_file); + return read_index_from(state->repo->index, state->index_file, + get_git_dir()); else - return read_cache(); + return read_index(state->repo->index); } /* This function tries to read the object name from the current index */ @@ -4015,10 +4023,10 @@ static int get_current_oid(struct apply_state *state, const char *path, if (read_apply_cache(state) < 0) return -1; - pos = cache_name_pos(path, strlen(path)); + pos = index_name_pos(state->repo->index, path, strlen(path)); if (pos < 0) return -1; - oidcpy(oid, &active_cache[pos]->oid); + oidcpy(oid, &state->repo->index->cache[pos]->oid); return 0; } @@ -4246,7 +4254,7 @@ static void patch_stats(struct apply_state *state, struct patch *patch) static int remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) { if (state->update_index && !state->ita_only) { - if (remove_file_from_cache(patch->old_name) < 0) + if (remove_file_from_index(state->repo->index, patch->old_name) < 0) return error(_("unable to remove %s from index"), patch->old_name); } if (!state->cached) { @@ -4267,7 +4275,7 @@ static int add_index_file(struct apply_state *state, struct cache_entry *ce; int namelen = strlen(path); - ce = make_empty_cache_entry(&the_index, namelen); + ce = make_empty_cache_entry(state->repo->index, namelen); memcpy(ce->name, path, namelen); ce->ce_mode = create_ce_mode(mode); ce->ce_flags = create_ce_flags(0); @@ -4299,7 +4307,7 @@ static int add_index_file(struct apply_state *state, "for newly created file %s"), path); } } - if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) { + if (add_index_entry(state->repo->index, ce, ADD_CACHE_OK_TO_ADD) < 0) { discard_cache_entry(ce); return error(_("unable to add cache entry for %s"), path); } @@ -4313,7 +4321,9 @@ static int add_index_file(struct apply_state *state, * 0 if everything went well * 1 if a recoverable error happened */ -static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) +static int try_create_file(struct apply_state *state, const char *path, + unsigned int mode, const char *buf, + unsigned long size) { int fd, res; struct strbuf nbuf = STRBUF_INIT; @@ -4335,7 +4345,7 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, if (fd < 0) return 1; - if (convert_to_working_tree(path, buf, size, &nbuf)) { + if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf)) { size = nbuf.len; buf = nbuf.buf; } @@ -4371,7 +4381,7 @@ static int create_one_file(struct apply_state *state, if (state->cached) return 0; - res = try_create_file(path, mode, buf, size); + res = try_create_file(state, path, mode, buf, size); if (res < 0) return -1; if (!res) @@ -4380,7 +4390,7 @@ static int create_one_file(struct apply_state *state, if (errno == ENOENT) { if (safe_create_leading_directories(path)) return 0; - res = try_create_file(path, mode, buf, size); + res = try_create_file(state, path, mode, buf, size); if (res < 0) return -1; if (!res) @@ -4402,7 +4412,7 @@ static int create_one_file(struct apply_state *state, for (;;) { char newpath[PATH_MAX]; mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr); - res = try_create_file(newpath, mode, buf, size); + res = try_create_file(state, newpath, mode, buf, size); if (res < 0) return -1; if (!res) { @@ -4432,17 +4442,17 @@ static int add_conflicted_stages_file(struct apply_state *state, namelen = strlen(patch->new_name); mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644); - remove_file_from_cache(patch->new_name); + remove_file_from_index(state->repo->index, patch->new_name); for (stage = 1; stage < 4; stage++) { if (is_null_oid(&patch->threeway_stage[stage - 1])) continue; - ce = make_empty_cache_entry(&the_index, namelen); + ce = make_empty_cache_entry(state->repo->index, namelen); memcpy(ce->name, patch->new_name, namelen); ce->ce_mode = create_ce_mode(mode); ce->ce_flags = create_ce_flags(stage); ce->ce_namelen = namelen; oidcpy(&ce->oid, &patch->threeway_stage[stage - 1]); - if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) { + if (add_index_entry(state->repo->index, ce, ADD_CACHE_OK_TO_ADD) < 0) { discard_cache_entry(ce); return error(_("unable to add cache entry for %s"), patch->new_name); @@ -4891,7 +4901,7 @@ int apply_all_patches(struct apply_state *state, } if (state->update_index) { - res = write_locked_index(&the_index, &state->lock_file, COMMIT_LOCK); + res = write_locked_index(state->repo->index, &state->lock_file, COMMIT_LOCK); if (res) { error(_("Unable to write new index file")); res = -128; @@ -1,6 +1,8 @@ #ifndef APPLY_H #define APPLY_H +struct repository; + enum apply_ws_error_action { nowarn_ws_error, warn_on_ws_error, @@ -62,6 +64,7 @@ struct apply_state { int unsafe_paths; /* Other non boolean parameters */ + struct repository *repo; const char *index_file; enum apply_verbosity apply_verbosity; const char *fake_ancestor; @@ -116,6 +119,7 @@ int apply_parse_options(int argc, const char **argv, int *force_apply, int *options, const char * const *apply_usage); int init_apply_state(struct apply_state *state, + struct repository *repo, const char *prefix); void clear_apply_state(struct apply_state *state); int check_apply_state(struct apply_state *state, int force_apply); diff --git a/archive-tar.c b/archive-tar.c index 0bc50f6e89..7a535cba24 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -277,7 +277,7 @@ static int write_tar_entry(struct archiver_args *args, memcpy(header.name, path, pathlen); if (S_ISREG(mode) && !args->convert && - oid_object_info(the_repository, oid, &size) == OBJ_BLOB && + oid_object_info(args->repo, oid, &size) == OBJ_BLOB && size > big_file_threshold) buffer = NULL; else if (S_ISLNK(mode) || S_ISREG(mode)) { diff --git a/archive-zip.c b/archive-zip.c index 024267ff0f..5a62351ab1 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -326,7 +326,7 @@ static int write_zip_entry(struct archiver_args *args, compressed_size = 0; buffer = NULL; } else if (S_ISREG(mode) || S_ISLNK(mode)) { - enum object_type type = oid_object_info(the_repository, oid, + enum object_type type = oid_object_info(args->repo, oid, &size); method = 0; @@ -79,7 +79,7 @@ void *object_file_to_archive(const struct archiver_args *args, size_t size = 0; strbuf_attach(&buf, buffer, *sizep, *sizep + 1); - convert_to_working_tree(path, buf.buf, buf.len, &buf); + convert_to_working_tree(args->repo->index, path, buf.buf, buf.len, &buf); if (commit) format_subst(commit, buf.buf, buf.len, &buf); buffer = strbuf_detach(&buf, &size); @@ -104,12 +104,13 @@ struct archiver_context { struct directory *bottom; }; -static const struct attr_check *get_archive_attrs(const char *path) +static const struct attr_check *get_archive_attrs(struct index_state *istate, + const char *path) { static struct attr_check *check; if (!check) check = attr_check_initl("export-ignore", "export-subst", NULL); - return git_check_attr(path, check) ? NULL : check; + return git_check_attr(istate, path, check) ? NULL : check; } static int check_attr_export_ignore(const struct attr_check *check) @@ -145,7 +146,7 @@ static int write_archive_entry(const struct object_id *oid, const char *base, if (!S_ISDIR(mode)) { const struct attr_check *check; - check = get_archive_attrs(path_without_prefix); + check = get_archive_attrs(args->repo->index, path_without_prefix); if (check_attr_export_ignore(check)) return 0; args->convert = check_attr_export_subst(check); @@ -220,7 +221,7 @@ static int queue_or_write_archive_entry(const struct object_id *oid, /* Borrow base, but restore its original value when done. */ strbuf_addstr(base, filename); strbuf_addch(base, '/'); - check = get_archive_attrs(base->buf); + check = get_archive_attrs(c->args->repo->index, base->buf); strbuf_setlen(base, baselen); if (check_attr_export_ignore(check)) @@ -268,13 +269,13 @@ int write_archive_entries(struct archiver_args *args, memset(&opts, 0, sizeof(opts)); opts.index_only = 1; opts.head_idx = -1; - opts.src_index = &the_index; - opts.dst_index = &the_index; + opts.src_index = args->repo->index; + opts.dst_index = args->repo->index; opts.fn = oneway_merge; init_tree_desc(&t, args->tree->buffer, args->tree->size); if (unpack_trees(1, &t, &opts)) return -1; - git_attr_set_direction(GIT_ATTR_INDEX, &the_index); + git_attr_set_direction(GIT_ATTR_INDEX); } err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, @@ -304,33 +305,43 @@ static const struct archiver *lookup_archiver(const char *name) return NULL; } +struct path_exists_context { + struct pathspec pathspec; + struct archiver_args *args; +}; + static int reject_entry(const struct object_id *oid, struct strbuf *base, const char *filename, unsigned mode, int stage, void *context) { int ret = -1; + struct path_exists_context *ctx = context; + if (S_ISDIR(mode)) { struct strbuf sb = STRBUF_INIT; strbuf_addbuf(&sb, base); strbuf_addstr(&sb, filename); - if (!match_pathspec(context, sb.buf, sb.len, 0, NULL, 1)) + if (!match_pathspec(ctx->args->repo->index, + &ctx->pathspec, + sb.buf, sb.len, 0, NULL, 1)) ret = READ_TREE_RECURSIVE; strbuf_release(&sb); } return ret; } -static int path_exists(struct tree *tree, const char *path) +static int path_exists(struct archiver_args *args, const char *path) { const char *paths[] = { path, NULL }; - struct pathspec pathspec; + struct path_exists_context ctx; int ret; - parse_pathspec(&pathspec, 0, 0, "", paths); - pathspec.recursive = 1; - ret = read_tree_recursive(tree, "", 0, 0, &pathspec, - reject_entry, &pathspec); - clear_pathspec(&pathspec); + ctx.args = args; + parse_pathspec(&ctx.pathspec, 0, 0, "", paths); + ctx.pathspec.recursive = 1; + ret = read_tree_recursive(args->tree, "", 0, 0, &ctx.pathspec, + reject_entry, &ctx); + clear_pathspec(&ctx.pathspec); return ret != 0; } @@ -348,7 +359,7 @@ static void parse_pathspec_arg(const char **pathspec, ar_args->pathspec.recursive = 1; if (pathspec) { while (*pathspec) { - if (**pathspec && !path_exists(ar_args->tree, *pathspec)) + if (**pathspec && !path_exists(ar_args, *pathspec)) die(_("pathspec '%s' did not match any files"), *pathspec); pathspec++; } @@ -510,6 +521,7 @@ static int parse_archive_args(int argc, const char **argv, } int write_archive(int argc, const char **argv, const char *prefix, + struct repository *repo, const char *name_hint, int remote) { const struct archiver *ar = NULL; @@ -521,6 +533,7 @@ int write_archive(int argc, const char **argv, const char *prefix, init_tar_archiver(); init_zip_archiver(); + args.repo = repo; argc = parse_archive_args(argc, argv, &ar, &args, name_hint, remote); if (!startup_info->have_repository) { /* @@ -3,7 +3,10 @@ #include "pathspec.h" +struct repository; + struct archiver_args { + struct repository *repo; const char *base; size_t baselen; struct tree *tree; @@ -17,6 +20,16 @@ struct archiver_args { int compression_level; }; +/* main api */ + +extern int write_archive(int argc, const char **argv, const char *prefix, + struct repository *repo, + const char *name_hint, int remote); + +const char *archive_format_from_filename(const char *filename); + +/* archive backend stuff */ + #define ARCHIVER_WANT_COMPRESSION_LEVELS 1 #define ARCHIVER_REMOTE 2 struct archiver { @@ -36,9 +49,6 @@ typedef int (*write_archive_entry_fn_t)(struct archiver_args *args, unsigned int mode); extern int write_archive_entries(struct archiver_args *args, write_archive_entry_fn_t write_entry); -extern int write_archive(int argc, const char **argv, const char *prefix, const char *name_hint, int remote); - -const char *archive_format_from_filename(const char *filename); extern void *object_file_to_archive(const struct archiver_args *args, const char *path, const struct object_id *oid, unsigned int mode, enum object_type *type, @@ -708,10 +708,8 @@ static struct attr_stack *read_attr_from_array(const char **list) * another thread could potentially be calling into the attribute system. */ static enum git_attr_direction direction; -static struct index_state *use_index; -void git_attr_set_direction(enum git_attr_direction new_direction, - struct index_state *istate) +void git_attr_set_direction(enum git_attr_direction new_direction) { if (is_bare_repository() && new_direction != GIT_ATTR_INDEX) BUG("non-INDEX attr direction in a bare repo"); @@ -720,7 +718,6 @@ void git_attr_set_direction(enum git_attr_direction new_direction, drop_all_attr_stacks(); direction = new_direction; - use_index = istate; } static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) @@ -743,13 +740,18 @@ static struct attr_stack *read_attr_from_file(const char *path, int macro_ok) return res; } -static struct attr_stack *read_attr_from_index(const char *path, int macro_ok) +static struct attr_stack *read_attr_from_index(const struct index_state *istate, + const char *path, + int macro_ok) { struct attr_stack *res; char *buf, *sp; int lineno = 0; - buf = read_blob_data_from_index(use_index ? use_index : &the_index, path, NULL); + if (!istate) + return NULL; + + buf = read_blob_data_from_index(istate, path, NULL); if (!buf) return NULL; @@ -768,15 +770,16 @@ static struct attr_stack *read_attr_from_index(const char *path, int macro_ok) return res; } -static struct attr_stack *read_attr(const char *path, int macro_ok) +static struct attr_stack *read_attr(const struct index_state *istate, + const char *path, int macro_ok) { struct attr_stack *res = NULL; if (direction == GIT_ATTR_INDEX) { - res = read_attr_from_index(path, macro_ok); + res = read_attr_from_index(istate, path, macro_ok); } else if (!is_bare_repository()) { if (direction == GIT_ATTR_CHECKOUT) { - res = read_attr_from_index(path, macro_ok); + res = read_attr_from_index(istate, path, macro_ok); if (!res) res = read_attr_from_file(path, macro_ok); } else if (direction == GIT_ATTR_CHECKIN) { @@ -788,7 +791,7 @@ static struct attr_stack *read_attr(const char *path, int macro_ok) * We allow operation in a sparsely checked out * work tree, so read from it. */ - res = read_attr_from_index(path, macro_ok); + res = read_attr_from_index(istate, path, macro_ok); } } @@ -859,7 +862,8 @@ static void push_stack(struct attr_stack **attr_stack_p, } } -static void bootstrap_attr_stack(struct attr_stack **stack) +static void bootstrap_attr_stack(const struct index_state *istate, + struct attr_stack **stack) { struct attr_stack *e; @@ -883,7 +887,7 @@ static void bootstrap_attr_stack(struct attr_stack **stack) } /* root directory */ - e = read_attr(GITATTRIBUTES_FILE, 1); + e = read_attr(istate, GITATTRIBUTES_FILE, 1); push_stack(stack, e, xstrdup(""), 0); /* info frame */ @@ -896,7 +900,8 @@ static void bootstrap_attr_stack(struct attr_stack **stack) push_stack(stack, e, NULL, 0); } -static void prepare_attr_stack(const char *path, int dirlen, +static void prepare_attr_stack(const struct index_state *istate, + const char *path, int dirlen, struct attr_stack **stack) { struct attr_stack *info; @@ -917,7 +922,7 @@ static void prepare_attr_stack(const char *path, int dirlen, * .gitattributes in deeper directories to shallower ones, * and finally use the built-in set as the default. */ - bootstrap_attr_stack(stack); + bootstrap_attr_stack(istate, stack); /* * Pop the "info" one that is always at the top of the stack. @@ -973,7 +978,7 @@ static void prepare_attr_stack(const char *path, int dirlen, strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len)); strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE); - next = read_attr(pathbuf.buf, 0); + next = read_attr(istate, pathbuf.buf, 0); /* reset the pathbuf to not include "/.gitattributes" */ strbuf_setlen(&pathbuf, len); @@ -1095,7 +1100,9 @@ static void determine_macros(struct all_attrs_item *all_attrs, * If check->check_nr is non-zero, only attributes in check[] are collected. * Otherwise all attributes are collected. */ -static void collect_some_attrs(const char *path, struct attr_check *check) +static void collect_some_attrs(const struct index_state *istate, + const char *path, + struct attr_check *check) { int i, pathlen, rem, dirlen; const char *cp, *last_slash = NULL; @@ -1114,7 +1121,7 @@ static void collect_some_attrs(const char *path, struct attr_check *check) dirlen = 0; } - prepare_attr_stack(path, dirlen, &check->stack); + prepare_attr_stack(istate, path, dirlen, &check->stack); all_attrs_init(&g_attr_hashmap, check); determine_macros(check->all_attrs, check->stack); @@ -1136,11 +1143,13 @@ static void collect_some_attrs(const char *path, struct attr_check *check) fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem); } -int git_check_attr(const char *path, struct attr_check *check) +int git_check_attr(const struct index_state *istate, + const char *path, + struct attr_check *check) { int i; - collect_some_attrs(path, check); + collect_some_attrs(istate, path, check); for (i = 0; i < check->nr; i++) { size_t n = check->items[i].attr->attr_nr; @@ -1153,12 +1162,13 @@ int git_check_attr(const char *path, struct attr_check *check) return 0; } -void git_all_attrs(const char *path, struct attr_check *check) +void git_all_attrs(const struct index_state *istate, + const char *path, struct attr_check *check) { int i; attr_check_reset(check); - collect_some_attrs(path, check); + collect_some_attrs(istate, path, check); for (i = 0; i < check->all_attrs_nr; i++) { const char *name = check->all_attrs[i].attr->name; @@ -1,6 +1,8 @@ #ifndef ATTR_H #define ATTR_H +struct index_state; + /* An attribute is a pointer to this opaque structure */ struct git_attr; @@ -60,21 +62,22 @@ void attr_check_free(struct attr_check *check); */ const char *git_attr_name(const struct git_attr *); -int git_check_attr(const char *path, struct attr_check *check); +int git_check_attr(const struct index_state *istate, + const char *path, struct attr_check *check); /* * Retrieve all |