diff options
Diffstat (limited to 'unpack-trees.c')
-rw-r--r-- | unpack-trees.c | 92 |
1 files changed, 69 insertions, 23 deletions
diff --git a/unpack-trees.c b/unpack-trees.c index 436598d210..f88a69f8e7 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -1,5 +1,5 @@ #include "cache.h" -#include "argv-array.h" +#include "strvec.h" #include "repository.h" #include "config.h" #include "dir.h" @@ -16,6 +16,8 @@ #include "fsmonitor.h" #include "object-store.h" #include "promisor-remote.h" +#include "entry.h" +#include "parallel-checkout.h" /* * Error messages expected by scripts out of plumbing commands such as @@ -106,7 +108,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, const char **msgs = opts->msgs; const char *msg; - argv_array_init(&opts->msgs_to_free); + strvec_init(&opts->msgs_to_free); if (!strcmp(cmd, "checkout")) msg = advice_commit_before_merge @@ -124,7 +126,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, "Please commit your changes or stash them before you %s.") : _("Your local changes to the following files would be overwritten by %s:\n%%s"); msgs[ERROR_WOULD_OVERWRITE] = msgs[ERROR_NOT_UPTODATE_FILE] = - argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd); + strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd); msgs[ERROR_NOT_UPTODATE_DIR] = _("Updating the following directories would lose untracked files in them:\n%s"); @@ -145,7 +147,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, "Please move or remove them before you %s.") : _("The following untracked working tree files would be removed by %s:\n%%s"); msgs[ERROR_WOULD_LOSE_UNTRACKED_REMOVED] = - argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd); + strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd); if (!strcmp(cmd, "checkout")) msg = advice_commit_before_merge @@ -163,7 +165,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, "Please move or remove them before you %s.") : _("The following untracked working tree files would be overwritten by %s:\n%%s"); msgs[ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN] = - argv_array_pushf(&opts->msgs_to_free, msg, cmd, cmd); + strvec_pushf(&opts->msgs_to_free, msg, cmd, cmd); /* * Special case: ERROR_BIND_OVERLAP refers to a pair of paths, we @@ -189,7 +191,7 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts, void clear_unpack_trees_porcelain(struct unpack_trees_options *opts) { - argv_array_clear(&opts->msgs_to_free); + strvec_clear(&opts->msgs_to_free); memset(opts->msgs, 0, sizeof(opts->msgs)); } @@ -397,7 +399,7 @@ static int check_updates(struct unpack_trees_options *o, int errs = 0; struct progress *progress; struct checkout state = CHECKOUT_INIT; - int i; + int i, pc_workers, pc_threshold; trace_performance_enter(); state.force = 1; @@ -440,7 +442,6 @@ static int check_updates(struct unpack_trees_options *o, if (should_update_submodules()) load_gitmodules_file(index, &state); - enable_delayed_checkout(&state); if (has_promisor_remote()) { /* * Prefetch the objects that are to be checked out in the loop @@ -463,18 +464,31 @@ static int check_updates(struct unpack_trees_options *o, to_fetch.oid, to_fetch.nr); oid_array_clear(&to_fetch); } + + get_parallel_checkout_configs(&pc_workers, &pc_threshold); + + enable_delayed_checkout(&state); + if (pc_workers > 1) + init_parallel_checkout(); for (i = 0; i < index->cache_nr; i++) { struct cache_entry *ce = index->cache[i]; if (ce->ce_flags & CE_UPDATE) { + size_t last_pc_queue_size = pc_queue_size(); + if (ce->ce_flags & CE_WT_REMOVE) BUG("both update and delete flags are set on %s", ce->name); - display_progress(progress, ++cnt); ce->ce_flags &= ~CE_UPDATE; errs |= checkout_entry(ce, &state, NULL, NULL); + + if (last_pc_queue_size == pc_queue_size()) + display_progress(progress, ++cnt); } } + if (pc_workers > 1) + errs |= run_parallel_checkout(&state, pc_workers, pc_threshold, + progress, &cnt); stop_progress(&progress); errs |= finish_delayed_checkout(&state, NULL); git_attr_set_direction(GIT_ATTR_CHECKIN); @@ -749,9 +763,13 @@ static int index_pos_by_traverse_info(struct name_entry *names, strbuf_make_traverse_path(&name, info, names->path, names->pathlen); strbuf_addch(&name, '/'); pos = index_name_pos(o->src_index, name.buf, name.len); - if (pos >= 0) - BUG("This is a directory and should not exist in index"); - pos = -pos - 1; + if (pos >= 0) { + if (!o->src_index->sparse_index || + !(o->src_index->cache[pos]->ce_flags & CE_SKIP_WORKTREE)) + BUG("This is a directory and should not exist in index"); + } else { + pos = -pos - 1; + } if (pos >= o->src_index->cache_nr || !starts_with(o->src_index->cache[pos]->name, name.buf) || (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf))) @@ -1020,7 +1038,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, size_t len = traverse_path_len(info, tree_entry_len(n)); struct cache_entry *ce = is_transient ? - make_empty_transient_cache_entry(len) : + make_empty_transient_cache_entry(len, NULL) : make_empty_cache_entry(istate, len); ce->ce_mode = create_ce_mode(n->mode); @@ -1552,14 +1570,10 @@ static void mark_new_skip_worktree(struct pattern_list *pl, static void populate_from_existing_patterns(struct unpack_trees_options *o, struct pattern_list *pl) { - char *sparse = git_pathdup("info/sparse-checkout"); - - pl->use_cone_patterns = core_sparse_checkout_cone; - if (add_patterns_from_file_to_list(sparse, "", 0, pl, NULL) < 0) + if (get_sparse_checkout_patterns(pl) < 0) o->skip_sparse_checkout = 1; else o->pl = pl; - free(sparse); } @@ -1574,6 +1588,7 @@ static int verify_absent(const struct cache_entry *, */ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options *o) { + struct repository *repo = the_repository; int i, ret; static struct cache_entry *dfc; struct pattern_list pl; @@ -1583,6 +1598,14 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES); trace_performance_enter(); + trace2_region_enter("unpack_trees", "unpack_trees", the_repository); + + prepare_repo_settings(repo); + if (repo->settings.command_requires_full_index) { + ensure_full_index(o->src_index); + ensure_full_index(o->dst_index); + } + if (!core_apply_sparse_checkout || !o->update) o->skip_sparse_checkout = 1; if (!o->skip_sparse_checkout && !o->pl) { @@ -1614,8 +1637,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options o->merge_size = len; mark_all_ce_unused(o->src_index); - if (o->src_index->fsmonitor_last_update) - o->result.fsmonitor_last_update = o->src_index->fsmonitor_last_update; + o->result.fsmonitor_last_update = + xstrdup_or_null(o->src_index->fsmonitor_last_update); /* * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries @@ -1656,7 +1679,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options } trace_performance_enter(); + trace2_region_enter("unpack_trees", "traverse_trees", the_repository); ret = traverse_trees(o->src_index, len, t, &info); + trace2_region_leave("unpack_trees", "traverse_trees", the_repository); trace_performance_leave("traverse_trees"); if (ret < 0) goto return_failed; @@ -1725,8 +1750,6 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options if (!ret) { if (git_env_bool("GIT_TEST_CHECK_CACHE_TREE", 0)) cache_tree_verify(the_repository, &o->result); - if (!o->result.cache_tree) - o->result.cache_tree = cache_tree(); if (!cache_tree_fully_valid(o->result.cache_tree)) cache_tree_update(&o->result, WRITE_TREE_SILENT | @@ -1744,6 +1767,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options done: if (free_pattern_list) clear_pattern_list(&pl); + trace2_region_leave("unpack_trees", "unpack_trees", the_repository); trace_performance_leave("unpack_trees"); return ret; @@ -2098,7 +2122,7 @@ static int verify_absent_1(const struct cache_entry *ce, if (o->index_only || o->reset || !o->update) return 0; - len = check_leading_path(ce->name, ce_namelen(ce)); + len = check_leading_path(ce->name, ce_namelen(ce), 0); if (!len) return 0; else if (len > 0) { @@ -2564,3 +2588,25 @@ int oneway_merge(const struct cache_entry * const *src, } return merged_entry(a, old, o); } + +/* + * Merge worktree and untracked entries in a stash entry. + * + * Ignore all index entries. Collapse remaining trees but make sure that they + * don't have any conflicting files. + */ +int stash_worktree_untracked_merge(const struct cache_entry * const *src, + struct unpack_trees_options *o) +{ + const struct cache_entry *worktree = src[1]; + const struct cache_entry *untracked = src[2]; + + if (o->merge_size != 2) + BUG("invalid merge_size: %d", o->merge_size); + + if (worktree && untracked) + return error(_("worktree and untracked commit have duplicate entries: %s"), + super_prefixed(worktree->name)); + + return merged_entry(worktree ? worktree : untracked, NULL, o); +} |