summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index 7c9ecf665d..0e1a196ace 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -102,21 +102,28 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
opts->unpack_rejects[i].strdup_strings = 1;
}
-static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
- unsigned int set, unsigned int clear)
+static void do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
+ unsigned int set, unsigned int clear)
{
- unsigned int size = ce_size(ce);
- struct cache_entry *new = xmalloc(size);
-
clear |= CE_HASHED | CE_UNHASHED;
if (set & CE_REMOVE)
set |= CE_WT_REMOVE;
+ ce->next = NULL;
+ ce->ce_flags = (ce->ce_flags & ~clear) | set;
+ add_index_entry(&o->result, ce,
+ ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
+}
+
+static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
+ unsigned int set, unsigned int clear)
+{
+ unsigned int size = ce_size(ce);
+ struct cache_entry *new = xmalloc(size);
+
memcpy(new, ce, size);
- new->next = NULL;
- new->ce_flags = (new->ce_flags & ~clear) | set;
- add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
+ do_add_entry(o, new, set, clear);
}
/*
@@ -532,7 +539,8 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
struct cache_entry *ce = xcalloc(1, cache_entry_size(len));
ce->ce_mode = create_ce_mode(n->mode);
- ce->ce_flags = create_ce_flags(len, stage);
+ ce->ce_flags = create_ce_flags(stage);
+ ce->ce_namelen = len;
hashcpy(ce->sha1, n->sha1);
make_traverse_path(ce->name, info, n);
@@ -587,7 +595,7 @@ static int unpack_nondirectories(int n, unsigned long mask,
for (i = 0; i < n; i++)
if (src[i] && src[i] != o->df_conflict_entry)
- add_entry(o, src[i], 0, 0);
+ do_add_entry(o, src[i], 0, 0);
return 0;
}
@@ -772,7 +780,7 @@ static int unpack_callback(int n, unsigned long mask, unsigned long dirmask, str
if (unpack_nondirectories(n, mask, dirmask, src, names, info) < 0)
return -1;
- if (src[0]) {
+ if (o->merge && src[0]) {
if (ce_stage(src[0]))
mark_ce_used_same_name(src[0], o);
else
@@ -829,7 +837,8 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
{
struct cache_entry **cache_end;
int dtype = DT_DIR;
- int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el);
+ int ret = is_excluded_from_list(prefix, prefix_len,
+ basename, &dtype, el);
prefix[prefix_len++] = '/';
@@ -848,7 +857,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
* with ret (iow, we know in advance the incl/excl
* decision for the entire directory), clear flag here without
* calling clear_ce_flags_1(). That function will call
- * the expensive excluded_from_list() on every entry.
+ * the expensive is_excluded_from_list() on every entry.
*/
return clear_ce_flags_1(cache, cache_end - cache,
prefix, prefix_len,
@@ -931,7 +940,8 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr,
/* Non-directory */
dtype = ce_to_dtype(ce);
- ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el);
+ ret = is_excluded_from_list(ce->name, ce_namelen(ce),
+ name, &dtype, el);
if (ret < 0)
ret = defval;
if (ret > 0)
@@ -1016,10 +1026,15 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
o->el = &el;
}
+ if (o->dir) {
+ o->path_exclude_check = xmalloc(sizeof(struct path_exclude_check));
+ path_exclude_check_init(o->path_exclude_check, o->dir);
+ }
memset(&o->result, 0, sizeof(o->result));
o->result.initialized = 1;
o->result.timestamp.sec = o->src_index->timestamp.sec;
o->result.timestamp.nsec = o->src_index->timestamp.nsec;
+ o->result.version = o->src_index->version;
o->merge_size = len;
mark_all_ce_unused(o->src_index);
@@ -1139,7 +1154,11 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
*o->dst_index = o->result;
done:
- free_excludes(&el);
+ clear_exclude_list(&el);
+ if (o->path_exclude_check) {
+ path_exclude_check_clear(o->path_exclude_check);
+ free(o->path_exclude_check);
+ }
return ret;
return_failed:
@@ -1202,7 +1221,7 @@ static int verify_uptodate_1(struct cache_entry *ce,
return 0;
/*
* NEEDSWORK: the current default policy is to allow
- * submodule to be out of sync wrt the supermodule
+ * submodule to be out of sync wrt the superproject
* index. This needs to be tightened later for
* submodules that are marked to be automatically
* checked out.
@@ -1280,7 +1299,7 @@ static int verify_clean_subdirectory(struct cache_entry *ce,
* First let's make sure we do not have a local modification
* in that directory.
*/
- namelen = strlen(ce->name);
+ namelen = ce_namelen(ce);
for (i = locate_in_src_index(ce, o);
i < o->src_index->cache_nr;
i++) {
@@ -1355,7 +1374,8 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
if (ignore_case && icase_exists(o, name, len, st))
return 0;
- if (o->dir && excluded(o->dir, name, &dtype))
+ if (o->dir &&
+ is_path_excluded(o->path_exclude_check, name, -1, &dtype))
/*
* ce->name is explicitly excluded, so it is Ok to
* overwrite it.
@@ -1785,7 +1805,7 @@ int bind_merge(struct cache_entry **src,
struct cache_entry *a = src[1];
if (o->merge_size != 1)
- return error("Cannot do a bind merge of %d trees\n",
+ return error("Cannot do a bind merge of %d trees",
o->merge_size);
if (a && old)
return o->gently ? -1 :
@@ -1816,7 +1836,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
if (old && same(old, a)) {
int update = 0;
- if (o->reset && !ce_uptodate(old) && !ce_skip_worktree(old)) {
+ if (o->reset && o->update && !ce_uptodate(old) && !ce_skip_worktree(old)) {
struct stat st;
if (lstat(old->name, &st) ||
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))