Skip to content

Commit 3d41542

Browse files
stefanbellergitster
authored andcommitted
unpack-trees: support super-prefix option
In the future we want to support working tree operations within submodules, e.g. "git checkout --recurse-submodules", which will update the submodule to the commit as recorded in its superproject. In the submodule the unpack-tree operation is carried out as usual, but the reporting to the user needs to prefix any path with the superproject. The mechanism for this is the super-prefix. (see 74866d7, git: make super-prefix option) Add support for the super-prefix option for commands that unpack trees by wrapping any path output in unpacking trees in the newly introduced super_prefixed function. This new function prefixes any path with the super-prefix if there is one. Assuming the submodule case doesn't happen in the majority of the cases, we'd want to have a fast behavior for no super prefix, i.e. no reallocation/copying, but just returning path. Another aspect of introducing the `super_prefixed` function is to consider who owns the memory and if this is the right place where the path gets modified. As the super prefix ought to change the output behavior only and not the actual unpack tree part, it is fine to be that late in the line. As we get passed in 'const char *path', we cannot change the path itself, which means in case of a super prefix we have to copy over the path. We need two static buffers in that function as the error messages contain at most two paths. For testing purposes enable it in read-tree, which has no output of paths other than an unpack-trees.c. These are all converted in this patch. Signed-off-by: Stefan Beller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 83587d5 commit 3d41542

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

git.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ static struct cmd_struct commands[] = {
471471
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
472472
{ "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
473473
{ "push", cmd_push, RUN_SETUP },
474-
{ "read-tree", cmd_read_tree, RUN_SETUP },
474+
{ "read-tree", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},
475475
{ "receive-pack", cmd_receive_pack },
476476
{ "reflog", cmd_reflog, RUN_SETUP },
477477
{ "remote", cmd_remote, RUN_SETUP },

t/t1001-read-tree-m-2way.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ test_expect_success 'a/b (untracked) vs a, plus c/d case test.' '
363363
test -f a/b
364364
'
365365

366+
test_expect_success 'read-tree supports the super-prefix' '
367+
cat <<-EOF >expect &&
368+
error: Updating '\''fictional/a'\'' would lose untracked files in it
369+
EOF
370+
test_must_fail git --super-prefix fictional/ read-tree -u -m "$treeH" "$treeM" 2>actual &&
371+
test_cmp expect actual
372+
'
373+
366374
test_expect_success 'a/b vs a, plus c/d case setup.' '
367375
rm -f .git/index &&
368376
rm -fr a &&

unpack-trees.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,41 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
5252
? ((o)->msgs[(type)]) \
5353
: (unpack_plumbing_errors[(type)]) )
5454

55+
static const char *super_prefixed(const char *path)
56+
{
57+
/*
58+
* It is necessary and sufficient to have two static buffers
59+
* here, as the return value of this function is fed to
60+
* error() using the unpack_*_errors[] templates we see above.
61+
*/
62+
static struct strbuf buf[2] = {STRBUF_INIT, STRBUF_INIT};
63+
static int super_prefix_len = -1;
64+
static unsigned idx = ARRAY_SIZE(buf) - 1;
65+
66+
if (super_prefix_len < 0) {
67+
const char *super_prefix = get_super_prefix();
68+
if (!super_prefix) {
69+
super_prefix_len = 0;
70+
} else {
71+
int i;
72+
for (i = 0; i < ARRAY_SIZE(buf); i++)
73+
strbuf_addstr(&buf[i], super_prefix);
74+
super_prefix_len = buf[0].len;
75+
}
76+
}
77+
78+
if (!super_prefix_len)
79+
return path;
80+
81+
if (++idx >= ARRAY_SIZE(buf))
82+
idx = 0;
83+
84+
strbuf_setlen(&buf[idx], super_prefix_len);
85+
strbuf_addstr(&buf[idx], path);
86+
87+
return buf[idx].buf;
88+
}
89+
5590
void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
5691
const char *cmd)
5792
{
@@ -172,7 +207,7 @@ static int add_rejected_path(struct unpack_trees_options *o,
172207
const char *path)
173208
{
174209
if (!o->show_all_errors)
175-
return error(ERRORMSG(o, e), path);
210+
return error(ERRORMSG(o, e), super_prefixed(path));
176211

177212
/*
178213
* Otherwise, insert in a list for future display by
@@ -196,7 +231,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
196231
something_displayed = 1;
197232
for (i = 0; i < rejects->nr; i++)
198233
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
199-
error(ERRORMSG(o, e), path.buf);
234+
error(ERRORMSG(o, e), super_prefixed(path.buf));
200235
strbuf_release(&path);
201236
}
202237
string_list_clear(rejects, 0);
@@ -1918,7 +1953,9 @@ int bind_merge(const struct cache_entry * const *src,
19181953
o->merge_size);
19191954
if (a && old)
19201955
return o->gently ? -1 :
1921-
error(ERRORMSG(o, ERROR_BIND_OVERLAP), a->name, old->name);
1956+
error(ERRORMSG(o, ERROR_BIND_OVERLAP),
1957+
super_prefixed(a->name),
1958+
super_prefixed(old->name));
19221959
if (!a)
19231960
return keep_entry(old, o);
19241961
else

0 commit comments

Comments
 (0)