зеркало из https://github.com/microsoft/git.git
Merge branch 'rs/pull-signed-tag' into maint
When "git merge-recursive" works on history with many criss-cross merges in "verbose" mode, the names the command assigns to the virtual merge bases could have overwritten each other by unintended reuse of the same piece of memory. * rs/pull-signed-tag: commit: use FLEX_ARRAY in struct merge_remote_desc merge-recursive: fix verbose output for multiple base trees commit: factor out set_merge_remote_desc() commit: use xstrdup() in get_merge_parent()
This commit is contained in:
Коммит
69307312d1
18
commit.c
18
commit.c
|
@ -1576,6 +1576,15 @@ int commit_tree_extended(const char *msg, size_t msg_len,
|
|||
return result;
|
||||
}
|
||||
|
||||
void set_merge_remote_desc(struct commit *commit,
|
||||
const char *name, struct object *obj)
|
||||
{
|
||||
struct merge_remote_desc *desc;
|
||||
FLEX_ALLOC_STR(desc, name, name);
|
||||
desc->obj = obj;
|
||||
commit->util = desc;
|
||||
}
|
||||
|
||||
struct commit *get_merge_parent(const char *name)
|
||||
{
|
||||
struct object *obj;
|
||||
|
@ -1585,13 +1594,8 @@ struct commit *get_merge_parent(const char *name)
|
|||
return NULL;
|
||||
obj = parse_object(oid.hash);
|
||||
commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
|
||||
if (commit && !commit->util) {
|
||||
struct merge_remote_desc *desc;
|
||||
desc = xmalloc(sizeof(*desc));
|
||||
desc->obj = obj;
|
||||
desc->name = strdup(name);
|
||||
commit->util = desc;
|
||||
}
|
||||
if (commit && !commit->util)
|
||||
set_merge_remote_desc(commit, name, obj);
|
||||
return commit;
|
||||
}
|
||||
|
||||
|
|
4
commit.h
4
commit.h
|
@ -356,9 +356,11 @@ extern void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *
|
|||
|
||||
struct merge_remote_desc {
|
||||
struct object *obj; /* the named object, could be a tag */
|
||||
const char *name;
|
||||
char name[FLEX_ARRAY];
|
||||
};
|
||||
#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
|
||||
extern void set_merge_remote_desc(struct commit *commit,
|
||||
const char *name, struct object *obj);
|
||||
|
||||
/*
|
||||
* Given "name" from the command line to merge, find the commit object
|
||||
|
|
|
@ -42,12 +42,9 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
|
|||
static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
|
||||
{
|
||||
struct commit *commit = alloc_commit_node();
|
||||
struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
|
||||
|
||||
desc->name = comment;
|
||||
desc->obj = (struct object *)commit;
|
||||
set_merge_remote_desc(commit, comment, (struct object *)commit);
|
||||
commit->tree = tree;
|
||||
commit->util = desc;
|
||||
commit->object.parsed = 1;
|
||||
return commit;
|
||||
}
|
||||
|
|
|
@ -660,4 +660,22 @@ test_expect_success 'merging with triple rename across D/F conflict' '
|
|||
git merge other
|
||||
'
|
||||
|
||||
test_expect_success 'merge-recursive remembers the names of all base trees' '
|
||||
git reset --hard HEAD &&
|
||||
|
||||
# more trees than static slots used by oid_to_hex()
|
||||
for commit in $c0 $c2 $c4 $c5 $c6 $c7
|
||||
do
|
||||
git rev-parse "$commit^{tree}"
|
||||
done >trees &&
|
||||
|
||||
# ignore the return code -- it only fails because the input is weird
|
||||
test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out &&
|
||||
|
||||
# merge-recursive prints in reverse order, but we do not care
|
||||
sort <trees >expect &&
|
||||
sed -n "s/^virtual //p" out | sort >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
Загрузка…
Ссылка в новой задаче