diff options
author | Stephan Beyer <s-beyer@gmx.net> | 2008-08-12 22:13:59 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2008-08-30 20:46:54 -0700 |
commit | 73118f89b81f5a3ed1bb56e2517627d56e9ebdfb (patch) | |
tree | f564d0d2f7265be0074471baaf2e90a1a5ba771c /merge-recursive.c | |
parent | 9047ebbc229bf5b99d6c7522293b8cbd1100b747 (diff) | |
download | git-73118f89b81f5a3ed1bb56e2517627d56e9ebdfb.tar.gz |
merge-recursive.c: Add more generic merge_recursive_generic()
merge_recursive_generic() takes, in comparison to to merge_recursive(),
no commit ("struct commit *") arguments but SHA ids ("unsigned char *"),
and no commit list of bases but an array of refs ("const char **").
This makes it more generic in the case that it can also take the SHA
of a tree to merge trees without commits, for the bases, the head
and the remote.
merge_recursive_generic() also handles locking and updating of the
index, which is a common use case of merge_recursive().
This patch also rewrites builtin-merge-recursive.c to make use of
merge_recursive_generic(). By doing this, I stumbled over the
limitation of 20 bases and I've added a warning if this limitation
is exceeded.
This patch qualifies make_virtual_commit() as static again because
this function is not needed anymore outside merge-recursive.c.
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'merge-recursive.c')
-rw-r--r-- | merge-recursive.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/merge-recursive.c b/merge-recursive.c index a0cb3f47de..60d11716b3 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1303,6 +1303,59 @@ int merge_recursive(struct commit *h1, return clean; } +static struct commit *get_ref(const unsigned char *sha1, const char *name) +{ + struct object *object; + + object = deref_tag(parse_object(sha1), name, strlen(name)); + if (!object) + return NULL; + if (object->type == OBJ_TREE) + return make_virtual_commit((struct tree*)object, name); + if (object->type != OBJ_COMMIT) + return NULL; + if (parse_commit((struct commit *)object)) + return NULL; + return (struct commit *)object; +} + +int merge_recursive_generic(const char **base_list, + const unsigned char *head_sha1, const char *head_name, + const unsigned char *next_sha1, const char *next_name) +{ + int clean, index_fd; + struct lock_file *lock = xcalloc(1, sizeof(struct lock_file)); + struct commit *result; + struct commit *head_commit = get_ref(head_sha1, head_name); + struct commit *next_commit = get_ref(next_sha1, next_name); + struct commit_list *ca = NULL; + + if (base_list) { + int i; + for (i = 0; base_list[i]; ++i) { + unsigned char sha[20]; + struct commit *base; + if (get_sha1(base_list[i], sha)) + return error("Could not resolve ref '%s'", + base_list[i]); + if (!(base = get_ref(sha, base_list[i]))) + return error("Could not parse object '%s'", + base_list[i]); + commit_list_insert(base, &ca); + } + } + + index_fd = hold_locked_index(lock, 1); + clean = merge_recursive(head_commit, next_commit, + head_name, next_name, ca, &result); + if (active_cache_changed && + (write_cache(index_fd, active_cache, active_nr) || + commit_locked_index(lock))) + return error("Unable to write index."); + + return clean ? 0 : 1; +} + int merge_recursive_config(const char *var, const char *value, void *cb) { if (!strcasecmp(var, "merge.verbosity")) { |