diff options
Diffstat (limited to 'unpack-trees.c')
-rw-r--r-- | unpack-trees.c | 100 |
1 files changed, 61 insertions, 39 deletions
diff --git a/unpack-trees.c b/unpack-trees.c index 3a85a02a77..f25089b878 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -16,6 +16,7 @@ #include "submodule.h" #include "submodule-config.h" #include "fsmonitor.h" +#include "object-store.h" #include "fetch-object.h" /* @@ -203,20 +204,11 @@ static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE); } -static struct cache_entry *dup_entry(const struct cache_entry *ce) -{ - unsigned int size = ce_size(ce); - struct cache_entry *new_entry = xmalloc(size); - - memcpy(new_entry, ce, size); - return new_entry; -} - static void add_entry(struct unpack_trees_options *o, const struct cache_entry *ce, unsigned int set, unsigned int clear) { - do_add_entry(o, dup_entry(ce), set, clear); + do_add_entry(o, dup_cache_entry(ce, &o->result), set, clear); } /* @@ -361,7 +353,7 @@ static int check_updates(struct unpack_trees_options *o) progress = get_progress(o); if (o->update) - git_attr_set_direction(GIT_ATTR_CHECKOUT, index); + git_attr_set_direction(GIT_ATTR_CHECKOUT); if (should_update_submodules() && o->update && !o->dry_run) load_gitmodules_file(index, NULL); @@ -421,7 +413,7 @@ static int check_updates(struct unpack_trees_options *o) stop_progress(&progress); errs |= finish_delayed_checkout(&state); if (o->update) - git_attr_set_direction(GIT_ATTR_CHECKIN, NULL); + git_attr_set_direction(GIT_ATTR_CHECKIN); return errs != 0; } @@ -797,10 +789,17 @@ static int ce_in_traverse_path(const struct cache_entry *ce, return (info->pathlen < ce_namelen(ce)); } -static struct cache_entry *create_ce_entry(const struct traverse_info *info, const struct name_entry *n, int stage) +static struct cache_entry *create_ce_entry(const struct traverse_info *info, + const struct name_entry *n, + int stage, + struct index_state *istate, + int is_transient) { int len = traverse_path_len(info, n); - struct cache_entry *ce = xcalloc(1, cache_entry_size(len)); + struct cache_entry *ce = + is_transient ? + make_empty_transient_cache_entry(len) : + make_empty_cache_entry(istate, len); ce->ce_mode = create_ce_mode(n->mode); ce->ce_flags = create_ce_flags(stage); @@ -846,7 +845,15 @@ static int unpack_nondirectories(int n, unsigned long mask, stage = 3; else stage = 2; - src[i + o->merge] = create_ce_entry(info, names + i, stage); + + /* + * If the merge bit is set, then the cache entries are + * discarded in the following block. In this case, + * construct "transient" cache_entries, as they are + * not stored in the index. otherwise construct the + * cache entry from the index aware logic. + */ + src[i + o->merge] = create_ce_entry(info, names + i, stage, &o->result, o->merge); } if (o->merge) { @@ -855,7 +862,7 @@ static int unpack_nondirectories(int n, unsigned long mask, for (i = 0; i < n; i++) { struct cache_entry *ce = src[i + o->merge]; if (ce != o->df_conflict_entry) - free(ce); + discard_cache_entry(ce); } return rc; } @@ -1085,13 +1092,15 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str return mask; } -static int clear_ce_flags_1(struct cache_entry **cache, int nr, +static int clear_ce_flags_1(struct index_state *istate, + struct cache_entry **cache, int nr, struct strbuf *prefix, int select_mask, int clear_mask, struct exclude_list *el, int defval); /* Whole directory matching */ -static int clear_ce_flags_dir(struct cache_entry **cache, int nr, +static int clear_ce_flags_dir(struct index_state *istate, + struct cache_entry **cache, int nr, struct strbuf *prefix, char *basename, int select_mask, int clear_mask, @@ -1100,7 +1109,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr, struct cache_entry **cache_end; int dtype = DT_DIR; int ret = is_excluded_from_list(prefix->buf, prefix->len, - basename, &dtype, el, &the_index); + basename, &dtype, el, istate); int rc; strbuf_addch(prefix, '/'); @@ -1122,7 +1131,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr, * calling clear_ce_flags_1(). That function will call * the expensive is_excluded_from_list() on every entry. */ - rc = clear_ce_flags_1(cache, cache_end - cache, + rc = clear_ce_flags_1(istate, cache, cache_end - cache, prefix, select_mask, clear_mask, el, ret); @@ -1145,7 +1154,8 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr, * cache[0]->name[0..(prefix_len-1)] * Top level path has prefix_len zero. */ -static int clear_ce_flags_1(struct cache_entry **cache, int nr, +static int clear_ce_flags_1(struct index_state *istate, + struct cache_entry **cache, int nr, struct strbuf *prefix, int select_mask, int clear_mask, struct exclude_list *el, int defval) @@ -1179,7 +1189,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, len = slash - name; strbuf_add(prefix, name, len); - processed = clear_ce_flags_dir(cache, cache_end - cache, + processed = clear_ce_flags_dir(istate, cache, cache_end - cache, prefix, prefix->buf + prefix->len - len, select_mask, clear_mask, @@ -1193,7 +1203,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, } strbuf_addch(prefix, '/'); - cache += clear_ce_flags_1(cache, cache_end - cache, + cache += clear_ce_flags_1(istate, cache, cache_end - cache, prefix, select_mask, clear_mask, el, defval); strbuf_setlen(prefix, prefix->len - len - 1); @@ -1203,7 +1213,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, /* Non-directory */ dtype = ce_to_dtype(ce); ret = is_excluded_from_list(ce->name, ce_namelen(ce), - name, &dtype, el, &the_index); + name, &dtype, el, istate); if (ret < 0) ret = defval; if (ret > 0) @@ -1213,15 +1223,17 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, return nr - (cache_end - cache); } -static int clear_ce_flags(struct cache_entry **cache, int nr, - int select_mask, int clear_mask, - struct exclude_list *el) +static int clear_ce_flags(struct index_state *istate, + int select_mask, int clear_mask, + struct exclude_list *el) { static struct strbuf prefix = STRBUF_INIT; strbuf_reset(&prefix); - return clear_ce_flags_1(cache, nr, + return clear_ce_flags_1(istate, + istate->cache, + istate->cache_nr, &prefix, select_mask, clear_mask, el, 0); @@ -1231,7 +1243,7 @@ static int clear_ce_flags(struct cache_entry **cache, int nr, * Set/Clear CE_NEW_SKIP_WORKTREE according to $GIT_DIR/info/sparse-checkout */ static void mark_new_skip_worktree(struct exclude_list *el, - struct index_state *the_index, + struct index_state *istate, int select_flag, int skip_wt_flag) { int i; @@ -1240,13 +1252,13 @@ static void mark_new_skip_worktree(struct exclude_list *el, * 1. Pretend the narrowest worktree: only unmerged entries * are checked out */ - for (i = 0; i < the_index->cache_nr; i++) { - struct cache_entry *ce = the_index->cache[i]; + for (i = 0; i < istate->cache_nr; i++) { + struct cache_entry *ce = istate->cache[i]; if (select_flag && !(ce->ce_flags & select_flag)) continue; - if (!ce_stage(ce)) + if (!ce_stage(ce) && !(ce->ce_flags & CE_CONFLICTED)) ce->ce_flags |= skip_wt_flag; else ce->ce_flags &= ~skip_wt_flag; @@ -1256,8 +1268,7 @@ static void mark_new_skip_worktree(struct exclude_list *el, * 2. Widen worktree according to sparse-checkout file. * Matched entries will have skip_wt_flag cleared (i.e. "in") */ - clear_ce_flags(the_index->cache, the_index->cache_nr, - select_flag, skip_wt_flag, el); + clear_ce_flags(istate, select_flag, skip_wt_flag, el); } static int verify_absent(const struct cache_entry *, @@ -1545,6 +1556,17 @@ static int verify_uptodate_sparse(const struct cache_entry *ce, return verify_uptodate_1(ce, o, ERROR_SPARSE_NOT_UPTODATE_FILE); } +/* + * TODO: We should actually invalidate o->result, not src_index [1]. + * But since cache tree and untracked cache both are not copied to + * o->result until unpacking is complete, we invalidate them on + * src_index instead with the assumption that they will be copied to + * dst_index at the end. + * + * [1] src_index->cache_tree is also used in unpack_callback() so if + * we invalidate o->result, we need to update it to use + * o->result.cache_tree as well. + */ static void invalidate_ce_path(const struct cache_entry *ce, struct unpack_trees_options *o) { @@ -1636,7 +1658,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce, memset(&d, 0, sizeof(d)); if (o->dir) d.exclude_per_dir = o->dir->exclude_per_dir; - i = read_directory(&d, &the_index, pathbuf, namelen+1, NULL); + i = read_directory(&d, o->src_index, pathbuf, namelen+1, NULL); if (i) return o->gently ? -1 : add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name); @@ -1678,7 +1700,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype, return 0; if (o->dir && - is_excluded(o->dir, &the_index, name, &dtype)) + is_excluded(o->dir, o->src_index, name, &dtype)) /* * ce->name is explicitly excluded, so it is Ok to * overwrite it. @@ -1787,7 +1809,7 @@ static int merged_entry(const struct cache_entry *ce, struct unpack_trees_options *o) { int update = CE_UPDATE; - struct cache_entry *merge = dup_entry(ce); + struct cache_entry *merge = dup_cache_entry(ce, &o->result); if (!old) { /* @@ -1807,7 +1829,7 @@ static int merged_entry(const struct cache_entry *ce, if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) { - free(merge); + discard_cache_entry(merge); return -1; } invalidate_ce_path(merge, o); @@ -1833,7 +1855,7 @@ static int merged_entry(const struct cache_entry *ce, update = 0; } else { if (verify_uptodate(old, o)) { - free(merge); + discard_cache_entry(merge); return -1; } /* Migrate old flags over */ |