summaryrefslogtreecommitdiff
path: root/unpack-trees.c
diff options
context:
space:
mode:
Diffstat (limited to 'unpack-trees.c')
-rw-r--r--unpack-trees.c133
1 files changed, 87 insertions, 46 deletions
diff --git a/unpack-trees.c b/unpack-trees.c
index aea9aa749f..3a8ee19fe8 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -52,6 +52,41 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
? ((o)->msgs[(type)]) \
: (unpack_plumbing_errors[(type)]) )
+static const char *super_prefixed(const char *path)
+{
+ /*
+ * It is necessary and sufficient to have two static buffers
+ * here, as the return value of this function is fed to
+ * error() using the unpack_*_errors[] templates we see above.
+ */
+ static struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};
+ static int super_prefix_len = -1;
+ static unsigned idx = ARRAY_SIZE(buf) - 1;
+
+ if (super_prefix_len < 0) {
+ const char *super_prefix = get_super_prefix();
+ if (!super_prefix) {
+ super_prefix_len = 0;
+ } else {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(buf); i++)
+ strbuf_addstr(&buf[i], super_prefix);
+ super_prefix_len = buf[0].len;
+ }
+ }
+
+ if (!super_prefix_len)
+ return path;
+
+ if (++idx >= ARRAY_SIZE(buf))
+ idx = 0;
+
+ strbuf_setlen(&buf[idx], super_prefix_len);
+ strbuf_addstr(&buf[idx], path);
+
+ return buf[idx].buf;
+}
+
void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
const char *cmd)
{
@@ -62,55 +97,55 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
if (!strcmp(cmd, "checkout"))
msg = advice_commit_before_merge
? _("Your local changes to the following files would be overwritten by checkout:\n%%s"
- "Please commit your changes or stash them before you can switch branches.")
+ "Please commit your changes or stash them before you switch branches.")
: _("Your local changes to the following files would be overwritten by checkout:\n%%s");
else if (!strcmp(cmd, "merge"))
msg = advice_commit_before_merge
? _("Your local changes to the following files would be overwritten by merge:\n%%s"
- "Please commit your changes or stash them before you can merge.")
+ "Please commit your changes or stash them before you merge.")
: _("Your local changes to the following files would be overwritten by merge:\n%%s");
else
msg = advice_commit_before_merge
? _("Your local changes to the following files would be overwritten by %s:\n%%s"
- "Please commit your changes or stash them before you can %s.")
+ "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] =
xstrfmt(msg, cmd, cmd);
msgs[ERROR_NOT_UPTODATE_DIR] =
- _("Updating the following directories would lose untracked files in it:\n%s");
+ _("Updating the following directories would lose untracked files in them:\n%s");
if (!strcmp(cmd, "checkout"))
msg = advice_commit_before_merge
? _("The following untracked working tree files would be removed by checkout:\n%%s"
- "Please move or remove them before you can switch branches.")
+ "Please move or remove them before you switch branches.")
: _("The following untracked working tree files would be removed by checkout:\n%%s");
else if (!strcmp(cmd, "merge"))
msg = advice_commit_before_merge
? _("The following untracked working tree files would be removed by merge:\n%%s"
- "Please move or remove them before you can merge.")
+ "Please move or remove them before you merge.")
: _("The following untracked working tree files would be removed by merge:\n%%s");
else
msg = advice_commit_before_merge
? _("The following untracked working tree files would be removed by %s:\n%%s"
- "Please move or remove them before you can %s.")
+ "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] = xstrfmt(msg, cmd, cmd);
if (!strcmp(cmd, "checkout"))
msg = advice_commit_before_merge
? _("The following untracked working tree files would be overwritten by checkout:\n%%s"
- "Please move or remove them before you can switch branches.")
+ "Please move or remove them before you switch branches.")
: _("The following untracked working tree files would be overwritten by checkout:\n%%s");
else if (!strcmp(cmd, "merge"))
msg = advice_commit_before_merge
? _("The following untracked working tree files would be overwritten by merge:\n%%s"
- "Please move or remove them before you can merge.")
+ "Please move or remove them before you merge.")
: _("The following untracked working tree files would be overwritten by merge:\n%%s");
else
msg = advice_commit_before_merge
? _("The following untracked working tree files would be overwritten by %s:\n%%s"
- "Please move or remove them before you can %s.")
+ "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] = xstrfmt(msg, cmd, cmd);
@@ -123,9 +158,9 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] =
_("Cannot update sparse checkout: the following entries are not up-to-date:\n%s");
msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] =
- _("The following Working tree files would be overwritten by sparse checkout update:\n%s");
+ _("The following working tree files would be overwritten by sparse checkout update:\n%s");
msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
- _("The following Working tree files would be removed by sparse checkout update:\n%s");
+ _("The following working tree files would be removed by sparse checkout update:\n%s");
opts->show_all_errors = 1;
/* rejected paths may not have a static buffer */
@@ -172,7 +207,7 @@ static int add_rejected_path(struct unpack_trees_options *o,
const char *path)
{
if (!o->show_all_errors)
- return error(ERRORMSG(o, e), path);
+ return error(ERRORMSG(o, e), super_prefixed(path));
/*
* Otherwise, insert in a list for future display by
@@ -196,7 +231,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
something_displayed = 1;
for (i = 0; i < rejects->nr; i++)
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
- error(ERRORMSG(o, e), path.buf);
+ error(ERRORMSG(o, e), super_prefixed(path.buf));
strbuf_release(&path);
}
string_list_clear(rejects, 0);
@@ -218,29 +253,42 @@ static void unlink_entry(const struct cache_entry *ce)
schedule_dir_for_removal(ce->name, ce_namelen(ce));
}
-static struct checkout state;
-static int check_updates(struct unpack_trees_options *o)
+static struct progress *get_progress(struct unpack_trees_options *o)
{
unsigned cnt = 0, total = 0;
+ struct index_state *index = &o->result;
+
+ if (!o->update || !o->verbose_update)
+ return NULL;
+
+ for (; cnt < index->cache_nr; cnt++) {
+ const struct cache_entry *ce = index->cache[cnt];
+ if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE))
+ total++;
+ }
+
+ return start_progress_delay(_("Checking out files"),
+ total, 50, 1);
+}
+
+static int check_updates(struct unpack_trees_options *o)
+{
+ unsigned cnt = 0;
+ int errs = 0;
struct progress *progress = NULL;
struct index_state *index = &o->result;
+ struct checkout state = CHECKOUT_INIT;
int i;
- int errs = 0;
- if (o->update && o->verbose_update) {
- for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
- const struct cache_entry *ce = index->cache[cnt];
- if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE))
- total++;
- }
+ state.force = 1;
+ state.quiet = 1;
+ state.refresh_cache = 1;
+ state.istate = index;
- progress = start_progress_delay(_("Checking out files"),
- total, 50, 1);
- cnt = 0;
- }
+ progress = get_progress(o);
if (o->update)
- git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
+ git_attr_set_direction(GIT_ATTR_CHECKOUT, index);
for (i = 0; i < index->cache_nr; i++) {
const struct cache_entry *ce = index->cache[i];
@@ -248,10 +296,9 @@ static int check_updates(struct unpack_trees_options *o)
display_progress(progress, ++cnt);
if (o->update && !o->dry_run)
unlink_entry(ce);
- continue;
}
}
- remove_marked_cache_entries(&o->result);
+ remove_marked_cache_entries(index);
remove_scheduled_dirs();
for (i = 0; i < index->cache_nr; i++) {
@@ -509,7 +556,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
for (i = 0; i < n; i++, dirmask >>= 1) {
const unsigned char *sha1 = NULL;
if (dirmask & 1)
- sha1 = names[i].sha1;
+ sha1 = names[i].oid->hash;
buf[i] = fill_tree_descriptor(t+i, sha1);
}
@@ -625,7 +672,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info, con
ce->ce_mode = create_ce_mode(n->mode);
ce->ce_flags = create_ce_flags(stage);
ce->ce_namelen = len;
- hashcpy(ce->sha1, n->sha1);
+ oidcpy(&ce->oid, n->oid);
make_traverse_path(ce->name, info, n);
return ce;
@@ -1097,12 +1144,6 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
if (len > MAX_UNPACK_TREES)
die("unpack_trees takes at most %d trees", MAX_UNPACK_TREES);
- memset(&state, 0, sizeof(state));
- state.base_dir = "";
- state.force = 1;
- state.quiet = 1;
- state.refresh_cache = 1;
- state.istate = &o->result;
memset(&el, 0, sizeof(el));
if (!core_apply_sparse_checkout || !o->update)
@@ -1287,7 +1328,7 @@ static int same(const struct cache_entry *a, const struct cache_entry *b)
if ((a->ce_flags | b->ce_flags) & CE_CONFLICTED)
return 0;
return a->ce_mode == b->ce_mode &&
- !hashcmp(a->sha1, b->sha1);
+ !oidcmp(&a->oid, &b->oid);
}
@@ -1393,7 +1434,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
/* If we are not going to update the submodule, then
* we don't care.
*/
- if (!hashcmp(sha1, ce->sha1))
+ if (!hashcmp(sha1, ce->oid.hash))
return 0;
return verify_clean_submodule(ce, error_type, o);
}
@@ -1533,8 +1574,7 @@ static int verify_absent_1(const struct cache_entry *ce,
path = xmemdupz(ce->name, len);
if (lstat(path, &st))
- ret = error("cannot stat '%s': %s", path,
- strerror(errno));
+ ret = error_errno("cannot stat '%s'", path);
else
ret = check_ok_to_remove(path, len, DT_UNKNOWN, NULL,
&st, error_type, o);
@@ -1542,8 +1582,7 @@ static int verify_absent_1(const struct cache_entry *ce,
return ret;
} else if (lstat(ce->name, &st)) {
if (errno != ENOENT)
- return error("cannot stat '%s': %s", ce->name,
- strerror(errno));
+ return error_errno("cannot stat '%s'", ce->name);
return 0;
} else {
return check_ok_to_remove(ce->name, ce_namelen(ce),
@@ -1667,7 +1706,7 @@ static void show_stage_entry(FILE *o,
fprintf(o, "%s%06o %s %d\t%s\n",
label,
ce->ce_mode,
- sha1_to_hex(ce->sha1),
+ oid_to_hex(&ce->oid),
ce_stage(ce),
ce->name);
}
@@ -1921,7 +1960,9 @@ int bind_merge(const struct cache_entry * const *src,
o->merge_size);
if (a && old)
return o->gently ? -1 :
- error(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name);
+ error(ERRORMSG(o, ERROR_BIND_OVERLAP),
+ super_prefixed(a->name),
+ super_prefixed(old->name));
if (!a)
return keep_entry(old, o);
else