diff options
Diffstat (limited to 'unpack-trees.c')
-rw-r--r-- | unpack-trees.c | 136 |
1 files changed, 89 insertions, 47 deletions
diff --git a/unpack-trees.c b/unpack-trees.c index 1ca41b1a69..8282f5e5f6 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -16,7 +16,7 @@ * situation better. See how "git checkout" and "git merge" replaces * them using setup_unpack_trees_porcelain(), for example. */ -const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = { +static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = { /* ERROR_WOULD_OVERWRITE */ "Entry '%s' would be overwritten by merge. Cannot merge.", @@ -159,7 +159,7 @@ static void display_error_msgs(struct unpack_trees_options *o) string_list_clear(rejects, 0); } if (something_displayed) - printf("Aborting\n"); + fprintf(stderr, "Aborting\n"); } /* @@ -203,7 +203,7 @@ static int check_updates(struct unpack_trees_options *o) if (ce->ce_flags & CE_WT_REMOVE) { display_progress(progress, ++cnt); - if (o->update) + if (o->update && !o->dry_run) unlink_entry(ce); continue; } @@ -217,7 +217,7 @@ static int check_updates(struct unpack_trees_options *o) if (ce->ce_flags & CE_UPDATE) { display_progress(progress, ++cnt); ce->ce_flags &= ~CE_UPDATE; - if (o->update) { + if (o->update && !o->dry_run) { errs |= checkout_entry(ce, &state, NULL); } } @@ -381,7 +381,7 @@ static void add_same_unmerged(struct cache_entry *ce, static int unpack_index_entry(struct cache_entry *ce, struct unpack_trees_options *o) { - struct cache_entry *src[5] = { NULL }; + struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, }; int ret; src[0] = ce; @@ -427,7 +427,10 @@ static int switch_cache_bottom(struct traverse_info *info) return ret; } -static int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long df_conflicts, struct name_entry *names, struct traverse_info *info) +static int traverse_trees_recursive(int n, unsigned long dirmask, + unsigned long df_conflicts, + struct name_entry *names, + struct traverse_info *info) { int i, ret, bottom; struct tree_desc t[MAX_UNPACK_TREES]; @@ -441,6 +444,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long newinfo = *info; newinfo.prev = info; + newinfo.pathspec = info->pathspec; newinfo.name = *p; newinfo.pathlen += tree_entry_len(p->path, p->sha1) + 1; newinfo.conflicts |= df_conflicts; @@ -590,7 +594,7 @@ static int unpack_nondirectories(int n, unsigned long mask, static int unpack_failed(struct unpack_trees_options *o, const char *message) { discard_index(&o->result); - if (!o->gently) { + if (!o->gently && !o->exiting_early) { if (message) return error("%s", message); return -1; @@ -811,43 +815,45 @@ 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, + char *prefix, int prefix_len, + 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, char *prefix, int prefix_len, char *basename, int select_mask, int clear_mask, - struct exclude_list *el) + struct exclude_list *el, int defval) { - struct cache_entry **cache_end = cache + nr; + struct cache_entry **cache_end; int dtype = DT_DIR; int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el); prefix[prefix_len++] = '/'; - /* included, no clearing for any entries under this directory */ - if (!ret) { - for (; cache != cache_end; cache++) { - struct cache_entry *ce = *cache; - if (strncmp(ce->name, prefix, prefix_len)) - break; - } - return nr - (cache_end - cache); - } + /* If undecided, use matching result of parent dir in defval */ + if (ret < 0) + ret = defval; - /* excluded, clear all selected entries under this directory. */ - if (ret == 1) { - for (; cache != cache_end; cache++) { - struct cache_entry *ce = *cache; - if (select_mask && !(ce->ce_flags & select_mask)) - continue; - if (strncmp(ce->name, prefix, prefix_len)) - break; - ce->ce_flags &= ~clear_mask; - } - return nr - (cache_end - cache); + for (cache_end = cache; cache_end != cache + nr; cache_end++) { + struct cache_entry *ce = *cache_end; + if (strncmp(ce->name, prefix, prefix_len)) + break; } - return 0; + /* + * TODO: check el, if there are no patterns that may conflict + * 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. + */ + return clear_ce_flags_1(cache, cache_end - cache, + prefix, prefix_len, + select_mask, clear_mask, + el, ret); } /* @@ -868,7 +874,7 @@ static int clear_ce_flags_dir(struct cache_entry **cache, int nr, static int clear_ce_flags_1(struct cache_entry **cache, int nr, char *prefix, int prefix_len, int select_mask, int clear_mask, - struct exclude_list *el) + struct exclude_list *el, int defval) { struct cache_entry **cache_end = cache + nr; @@ -879,7 +885,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, while(cache != cache_end) { struct cache_entry *ce = *cache; const char *name, *slash; - int len, dtype; + int len, dtype, ret; if (select_mask && !(ce->ce_flags & select_mask)) { cache++; @@ -908,7 +914,7 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, prefix, prefix_len + len, prefix + prefix_len, select_mask, clear_mask, - el); + el, defval); /* clear_c_f_dir eats a whole dir already? */ if (processed) { @@ -919,13 +925,16 @@ static int clear_ce_flags_1(struct cache_entry **cache, int nr, prefix[prefix_len + len++] = '/'; cache += clear_ce_flags_1(cache, cache_end - cache, prefix, prefix_len + len, - select_mask, clear_mask, el); + select_mask, clear_mask, el, defval); continue; } /* Non-directory */ dtype = ce_to_dtype(ce); - if (excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el) > 0) + ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el); + if (ret < 0) + ret = defval; + if (ret > 0) ce->ce_flags &= ~clear_mask; cache++; } @@ -940,7 +949,7 @@ static int clear_ce_flags(struct cache_entry **cache, int nr, return clear_ce_flags_1(cache, nr, prefix, 0, select_mask, clear_mask, - el); + el, 0); } /* @@ -1032,6 +1041,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options info.fn = unpack_callback; info.data = o; info.show_all_errors = o->show_all_errors; + info.pathspec = o->pathspec; if (o->prefix) { /* @@ -1081,6 +1091,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options */ mark_new_skip_worktree(o->el, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE); + ret = 0; for (i = 0; i < o->result.cache_nr; i++) { struct cache_entry *ce = o->result.cache[i]; @@ -1093,17 +1104,29 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options * correct CE_NEW_SKIP_WORKTREE */ if (ce->ce_flags & CE_ADDED && - verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) - return -1; + verify_absent(ce, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) { + if (!o->show_all_errors) + goto return_failed; + ret = -1; + } if (apply_sparse_checkout(ce, o)) { + if (!o->show_all_errors) + goto return_failed; ret = -1; - goto done; } if (!ce_skip_worktree(ce)) empty_worktree = 0; } + if (ret < 0) + goto return_failed; + /* + * Sparse checkout is meant to narrow down checkout area + * but it does not make sense to narrow down to empty working + * tree. This is usually a mistake in sparse checkout rules. + * Do not allow users to do that. + */ if (o->result.cache_nr && empty_worktree) { ret = unpack_failed(o, "Sparse checkout leaves no entry on working directory"); goto done; @@ -1124,6 +1147,8 @@ return_failed: display_error_msgs(o); mark_all_ce_unused(o->src_index); ret = unpack_failed(o, NULL); + if (o->exiting_early) + ret = 0; goto done; } @@ -1157,11 +1182,22 @@ static int verify_uptodate_1(struct cache_entry *ce, { struct stat st; - if (o->index_only || (!((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) && (o->reset || ce_uptodate(ce)))) + if (o->index_only) + return 0; + + /* + * CE_VALID and CE_SKIP_WORKTREE cheat, we better check again + * if this entry is truly up-to-date because this file may be + * overwritten. + */ + if ((ce->ce_flags & CE_VALID) || ce_skip_worktree(ce)) + ; /* keep checking */ + else if (o->reset || ce_uptodate(ce)) return 0; if (!lstat(ce->name, &st)) { - unsigned changed = ie_match_stat(o->src_index, ce, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE); + int flags = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE; + unsigned changed = ie_match_stat(o->src_index, ce, &st, flags); if (!changed) return 0; /* @@ -1374,16 +1410,22 @@ static int verify_absent_1(struct cache_entry *ce, char path[PATH_MAX + 1]; memcpy(path, ce->name, len); path[len] = 0; - lstat(path, &st); + if (lstat(path, &st)) + return error("cannot stat '%s': %s", path, + strerror(errno)); return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st, error_type, o); - } else if (!lstat(ce->name, &st)) + } else if (lstat(ce->name, &st)) { + if (errno != ENOENT) + return error("cannot stat '%s': %s", ce->name, + strerror(errno)); + return 0; + } else { return check_ok_to_remove(ce->name, ce_namelen(ce), - ce_to_dtype(ce), ce, &st, - error_type, o); - - return 0; + ce_to_dtype(ce), ce, &st, + error_type, o); + } } static int verify_absent(struct cache_entry *ce, |