mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-04 19:50:19 +00:00
commit
f7ceef06eb
@ -23,13 +23,13 @@
|
|||||||
GIT_BEGIN_DECL
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flags for tree_many diff options. A combination of these flags can be
|
* Flags for `git_mrege_tree` options. A combination of these flags can be
|
||||||
* passed in via the `flags` value in the `git_diff_tree_many_options`.
|
* passed in via the `flags` vlaue in the `git_merge_tree_opts`.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
/** Detect renames */
|
/** Detect renames */
|
||||||
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
|
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
|
||||||
} git_merge_tree_flags;
|
} git_merge_tree_flag_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Automerge options for `git_merge_trees_opts`.
|
* Automerge options for `git_merge_trees_opts`.
|
||||||
@ -44,7 +44,7 @@ typedef enum {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
git_merge_tree_flags flags;
|
git_merge_tree_flag_t flags;
|
||||||
|
|
||||||
/** Similarity to consider a file renamed (default 50) */
|
/** Similarity to consider a file renamed (default 50) */
|
||||||
unsigned int rename_threshold;
|
unsigned int rename_threshold;
|
||||||
@ -95,6 +95,57 @@ GIT_EXTERN(int) git_merge_base_many(
|
|||||||
const git_oid input_array[],
|
const git_oid input_array[],
|
||||||
size_t length);
|
size_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a `git_merge_head` from the given reference
|
||||||
|
*
|
||||||
|
* @param out pointer to store the git_merge_head result in
|
||||||
|
* @param repo repository that contains the given reference
|
||||||
|
* @param ref reference to use as a merge input
|
||||||
|
* @return zero on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_merge_head_from_ref(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
git_reference *ref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a `git_merge_head` from the given fetch head data
|
||||||
|
*
|
||||||
|
* @param out pointer to store the git_merge_head result in
|
||||||
|
* @param repo repository that contains the given commit
|
||||||
|
* @param branch_name name of the (remote) branch
|
||||||
|
* @param remote_url url of the remote
|
||||||
|
* @param oid the commit object id to use as a merge input
|
||||||
|
* @return zero on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_merge_head_from_fetchhead(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *branch_name,
|
||||||
|
const char *remote_url,
|
||||||
|
const git_oid *oid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a `git_merge_head` from the given commit id
|
||||||
|
*
|
||||||
|
* @param out pointer to store the git_merge_head result in
|
||||||
|
* @param repo repository that contains the given commit
|
||||||
|
* @param oid the commit object id to use as a merge input
|
||||||
|
* @return zero on success, -1 on failure.
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_merge_head_from_oid(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const git_oid *oid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frees a `git_merge_head`
|
||||||
|
*
|
||||||
|
* @param the merge head to free
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(void) git_merge_head_free(
|
||||||
|
git_merge_head *head);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two trees, producing a `git_index` that reflects the result of
|
* Merge two trees, producing a `git_index` that reflects the result of
|
||||||
* the merge.
|
* the merge.
|
||||||
|
@ -168,6 +168,9 @@ typedef struct git_reference git_reference;
|
|||||||
/** Iterator for references */
|
/** Iterator for references */
|
||||||
typedef struct git_reference_iterator git_reference_iterator;
|
typedef struct git_reference_iterator git_reference_iterator;
|
||||||
|
|
||||||
|
/** Merge heads, the input to merge */
|
||||||
|
typedef struct git_merge_head git_merge_head;
|
||||||
|
|
||||||
|
|
||||||
/** Basic type of any Git reference. */
|
/** Basic type of any Git reference. */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
595
src/merge.c
595
src/merge.c
@ -54,39 +54,6 @@ struct merge_diff_df_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int git_repository_merge_cleanup(git_repository *repo)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
git_buf merge_head_path = GIT_BUF_INIT,
|
|
||||||
merge_mode_path = GIT_BUF_INIT,
|
|
||||||
merge_msg_path = GIT_BUF_INIT;
|
|
||||||
|
|
||||||
assert(repo);
|
|
||||||
|
|
||||||
if (git_buf_joinpath(&merge_head_path, repo->path_repository, GIT_MERGE_HEAD_FILE) < 0 ||
|
|
||||||
git_buf_joinpath(&merge_mode_path, repo->path_repository, GIT_MERGE_MODE_FILE) < 0 ||
|
|
||||||
git_buf_joinpath(&merge_msg_path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (git_path_isfile(merge_head_path.ptr)) {
|
|
||||||
if ((error = p_unlink(merge_head_path.ptr)) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (git_path_isfile(merge_mode_path.ptr))
|
|
||||||
(void)p_unlink(merge_mode_path.ptr);
|
|
||||||
|
|
||||||
if (git_path_isfile(merge_msg_path.ptr))
|
|
||||||
(void)p_unlink(merge_msg_path.ptr);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
git_buf_free(&merge_msg_path);
|
|
||||||
git_buf_free(&merge_mode_path);
|
|
||||||
git_buf_free(&merge_head_path);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Merge base computation */
|
/* Merge base computation */
|
||||||
|
|
||||||
int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_array[], size_t length)
|
int git_merge_base_many(git_oid *out, git_repository *repo, const git_oid input_array[], size_t length)
|
||||||
@ -1380,6 +1347,18 @@ git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo)
|
|||||||
return diff_list;
|
return diff_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void git_merge_diff_list__free(git_merge_diff_list *diff_list)
|
||||||
|
{
|
||||||
|
if (!diff_list)
|
||||||
|
return;
|
||||||
|
|
||||||
|
git_vector_free(&diff_list->staged);
|
||||||
|
git_vector_free(&diff_list->conflicts);
|
||||||
|
git_vector_free(&diff_list->resolved);
|
||||||
|
git_pool_clear(&diff_list->pool);
|
||||||
|
git__free(diff_list);
|
||||||
|
}
|
||||||
|
|
||||||
static int merge_tree_normalize_opts(
|
static int merge_tree_normalize_opts(
|
||||||
git_repository *repo,
|
git_repository *repo,
|
||||||
git_merge_tree_opts *opts,
|
git_merge_tree_opts *opts,
|
||||||
@ -1617,14 +1596,550 @@ done:
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_merge_diff_list__free(git_merge_diff_list *diff_list)
|
/* Merge setup / cleanup */
|
||||||
|
|
||||||
|
static int write_orig_head(
|
||||||
|
git_repository *repo,
|
||||||
|
const git_merge_head *our_head)
|
||||||
{
|
{
|
||||||
if (!diff_list)
|
git_filebuf file = GIT_FILEBUF_INIT;
|
||||||
|
git_buf file_path = GIT_BUF_INIT;
|
||||||
|
char orig_oid_str[GIT_OID_HEXSZ + 1];
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert(repo && our_head);
|
||||||
|
|
||||||
|
git_oid_tostr(orig_oid_str, GIT_OID_HEXSZ+1, &our_head->oid);
|
||||||
|
|
||||||
|
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_ORIG_HEAD_FILE)) == 0 &&
|
||||||
|
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) == 0 &&
|
||||||
|
(error = git_filebuf_printf(&file, "%s\n", orig_oid_str)) == 0)
|
||||||
|
error = git_filebuf_commit(&file, 0666);
|
||||||
|
|
||||||
|
if (error < 0)
|
||||||
|
git_filebuf_cleanup(&file);
|
||||||
|
|
||||||
|
git_buf_free(&file_path);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_merge_head(
|
||||||
|
git_repository *repo,
|
||||||
|
const git_merge_head *heads[],
|
||||||
|
size_t heads_len)
|
||||||
|
{
|
||||||
|
git_filebuf file = GIT_FILEBUF_INIT;
|
||||||
|
git_buf file_path = GIT_BUF_INIT;
|
||||||
|
char merge_oid_str[GIT_OID_HEXSZ + 1];
|
||||||
|
size_t i;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert(repo && heads);
|
||||||
|
|
||||||
|
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_HEAD_FILE)) < 0 ||
|
||||||
|
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < heads_len; i++) {
|
||||||
|
git_oid_tostr(merge_oid_str, GIT_OID_HEXSZ+1, &heads[i]->oid);
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(&file, "%s\n", merge_oid_str)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = git_filebuf_commit(&file, 0666);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (error < 0)
|
||||||
|
git_filebuf_cleanup(&file);
|
||||||
|
|
||||||
|
git_buf_free(&file_path);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_merge_mode(git_repository *repo, unsigned int flags)
|
||||||
|
{
|
||||||
|
git_filebuf file = GIT_FILEBUF_INIT;
|
||||||
|
git_buf file_path = GIT_BUF_INIT;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
/* For future expansion */
|
||||||
|
GIT_UNUSED(flags);
|
||||||
|
|
||||||
|
assert(repo);
|
||||||
|
|
||||||
|
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 ||
|
||||||
|
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
error = git_filebuf_commit(&file, 0666);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (error < 0)
|
||||||
|
git_filebuf_cleanup(&file);
|
||||||
|
|
||||||
|
git_buf_free(&file_path);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct merge_msg_entry {
|
||||||
|
const git_merge_head *merge_head;
|
||||||
|
bool written;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int msg_entry_is_branch(
|
||||||
|
const struct merge_msg_entry *entry,
|
||||||
|
git_vector *entries)
|
||||||
|
{
|
||||||
|
GIT_UNUSED(entries);
|
||||||
|
|
||||||
|
return (entry->written == 0 &&
|
||||||
|
entry->merge_head->remote_url == NULL &&
|
||||||
|
entry->merge_head->ref_name != NULL &&
|
||||||
|
git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msg_entry_is_tracking(
|
||||||
|
const struct merge_msg_entry *entry,
|
||||||
|
git_vector *entries)
|
||||||
|
{
|
||||||
|
GIT_UNUSED(entries);
|
||||||
|
|
||||||
|
return (entry->written == 0 &&
|
||||||
|
entry->merge_head->remote_url == NULL &&
|
||||||
|
entry->merge_head->ref_name != NULL &&
|
||||||
|
git__strncmp(GIT_REFS_REMOTES_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_REMOTES_DIR)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msg_entry_is_tag(
|
||||||
|
const struct merge_msg_entry *entry,
|
||||||
|
git_vector *entries)
|
||||||
|
{
|
||||||
|
GIT_UNUSED(entries);
|
||||||
|
|
||||||
|
return (entry->written == 0 &&
|
||||||
|
entry->merge_head->remote_url == NULL &&
|
||||||
|
entry->merge_head->ref_name != NULL &&
|
||||||
|
git__strncmp(GIT_REFS_TAGS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_TAGS_DIR)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msg_entry_is_remote(
|
||||||
|
const struct merge_msg_entry *entry,
|
||||||
|
git_vector *entries)
|
||||||
|
{
|
||||||
|
if (entry->written == 0 &&
|
||||||
|
entry->merge_head->remote_url != NULL &&
|
||||||
|
entry->merge_head->ref_name != NULL &&
|
||||||
|
git__strncmp(GIT_REFS_HEADS_DIR, entry->merge_head->ref_name, strlen(GIT_REFS_HEADS_DIR)) == 0)
|
||||||
|
{
|
||||||
|
struct merge_msg_entry *existing;
|
||||||
|
|
||||||
|
/* Match only branches from the same remote */
|
||||||
|
if (entries->length == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
existing = git_vector_get(entries, 0);
|
||||||
|
|
||||||
|
return (git__strcmp(existing->merge_head->remote_url,
|
||||||
|
entry->merge_head->remote_url) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msg_entry_is_oid(
|
||||||
|
const struct merge_msg_entry *merge_msg_entry)
|
||||||
|
{
|
||||||
|
return (merge_msg_entry->written == 0 &&
|
||||||
|
merge_msg_entry->merge_head->ref_name == NULL &&
|
||||||
|
merge_msg_entry->merge_head->remote_url == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_entry_written(
|
||||||
|
const struct merge_msg_entry *merge_msg_entry)
|
||||||
|
{
|
||||||
|
return (merge_msg_entry->written == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_entries(
|
||||||
|
git_vector *v,
|
||||||
|
const struct merge_msg_entry *entries,
|
||||||
|
size_t len,
|
||||||
|
int (*match)(const struct merge_msg_entry *entry, git_vector *entries))
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
int matches, total = 0;
|
||||||
|
|
||||||
|
git_vector_clear(v);
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if ((matches = match(&entries[i], v)) < 0)
|
||||||
|
return matches;
|
||||||
|
else if (!matches)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
git_vector_insert(v, (struct merge_msg_entry *)&entries[i]);
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_write_entries(
|
||||||
|
git_filebuf *file,
|
||||||
|
git_vector *entries,
|
||||||
|
const char *item_name,
|
||||||
|
const char *item_plural_name,
|
||||||
|
size_t ref_name_skip,
|
||||||
|
const char *source,
|
||||||
|
char sep)
|
||||||
|
{
|
||||||
|
struct merge_msg_entry *entry;
|
||||||
|
size_t i;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
if (entries->length == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (sep && (error = git_filebuf_printf(file, "%c ", sep)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(file, "%s ",
|
||||||
|
(entries->length == 1) ? item_name : item_plural_name)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
git_vector_foreach(entries, i, entry) {
|
||||||
|
if (i > 0 &&
|
||||||
|
(error = git_filebuf_printf(file, "%s", (i == entries->length - 1) ? " and " : ", ")) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(file, "'%s'", entry->merge_head->ref_name + ref_name_skip)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
entry->written = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
error = git_filebuf_printf(file, " of %s", source);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_write_branches(
|
||||||
|
git_filebuf *file,
|
||||||
|
git_vector *entries,
|
||||||
|
char sep)
|
||||||
|
{
|
||||||
|
return merge_msg_write_entries(file, entries,
|
||||||
|
"branch", "branches", strlen(GIT_REFS_HEADS_DIR), NULL, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_write_tracking(
|
||||||
|
git_filebuf *file,
|
||||||
|
git_vector *entries,
|
||||||
|
char sep)
|
||||||
|
{
|
||||||
|
return merge_msg_write_entries(file, entries,
|
||||||
|
"remote-tracking branch", "remote-tracking branches", 0, NULL, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_write_tags(
|
||||||
|
git_filebuf *file,
|
||||||
|
git_vector *entries,
|
||||||
|
char sep)
|
||||||
|
{
|
||||||
|
return merge_msg_write_entries(file, entries,
|
||||||
|
"tag", "tags", strlen(GIT_REFS_TAGS_DIR), NULL, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int merge_msg_write_remotes(
|
||||||
|
git_filebuf *file,
|
||||||
|
git_vector *entries,
|
||||||
|
char sep)
|
||||||
|
{
|
||||||
|
const char *source;
|
||||||
|
|
||||||
|
if (entries->length == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
source = ((struct merge_msg_entry *)entries->contents[0])->merge_head->remote_url;
|
||||||
|
|
||||||
|
return merge_msg_write_entries(file, entries,
|
||||||
|
"branch", "branches", strlen(GIT_REFS_HEADS_DIR), source, sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int write_merge_msg(
|
||||||
|
git_repository *repo,
|
||||||
|
const git_merge_head *heads[],
|
||||||
|
size_t heads_len)
|
||||||
|
{
|
||||||
|
git_filebuf file = GIT_FILEBUF_INIT;
|
||||||
|
git_buf file_path = GIT_BUF_INIT;
|
||||||
|
char oid_str[GIT_OID_HEXSZ + 1];
|
||||||
|
struct merge_msg_entry *entries;
|
||||||
|
git_vector matching = GIT_VECTOR_INIT;
|
||||||
|
size_t i;
|
||||||
|
char sep = 0;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert(repo && heads);
|
||||||
|
|
||||||
|
entries = git__calloc(heads_len, sizeof(struct merge_msg_entry));
|
||||||
|
GITERR_CHECK_ALLOC(entries);
|
||||||
|
|
||||||
|
if (git_vector_init(&matching, heads_len, NULL) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for (i = 0; i < heads_len; i++)
|
||||||
|
entries[i].merge_head = heads[i];
|
||||||
|
|
||||||
|
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MSG_FILE)) < 0 ||
|
||||||
|
(error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE)) < 0 ||
|
||||||
|
(error = git_filebuf_write(&file, "Merge ", 6)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is to emulate the format of MERGE_MSG by core git.
|
||||||
|
*
|
||||||
|
* Core git will write all the commits specified by OID, in the order
|
||||||
|
* provided, until the first named branch or tag is reached, at which
|
||||||
|
* point all branches will be written in the order provided, then all
|
||||||
|
* tags, then all remote tracking branches and finally all commits that
|
||||||
|
* were specified by OID that were not already written.
|
||||||
|
*
|
||||||
|
* Yes. Really.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < heads_len; i++) {
|
||||||
|
if (!msg_entry_is_oid(&entries[i]))
|
||||||
|
break;
|
||||||
|
|
||||||
|
git_oid_fmt(oid_str, &entries[i].merge_head->oid);
|
||||||
|
oid_str[GIT_OID_HEXSZ] = '\0';
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(&file, "%scommit '%s'", (i > 0) ? "; " : "", oid_str)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
entries[i].written = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i)
|
||||||
|
sep = ';';
|
||||||
|
|
||||||
|
if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_branch)) < 0 ||
|
||||||
|
(error = merge_msg_write_branches(&file, &matching, sep)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (matching.length)
|
||||||
|
sep =',';
|
||||||
|
|
||||||
|
if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tracking)) < 0 ||
|
||||||
|
(error = merge_msg_write_tracking(&file, &matching, sep)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (matching.length)
|
||||||
|
sep =',';
|
||||||
|
|
||||||
|
if ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_tag)) < 0 ||
|
||||||
|
(error = merge_msg_write_tags(&file, &matching, sep)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (matching.length)
|
||||||
|
sep =',';
|
||||||
|
|
||||||
|
/* We should never be called with multiple remote branches, but handle
|
||||||
|
* it in case we are... */
|
||||||
|
while ((error = merge_msg_entries(&matching, entries, heads_len, msg_entry_is_remote)) > 0) {
|
||||||
|
if ((error = merge_msg_write_remotes(&file, &matching, sep)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (matching.length)
|
||||||
|
sep =',';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < heads_len; i++) {
|
||||||
|
if (merge_msg_entry_written(&entries[i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
git_oid_fmt(oid_str, &entries[i].merge_head->oid);
|
||||||
|
oid_str[GIT_OID_HEXSZ] = '\0';
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(&file, "; commit '%s'", oid_str)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = git_filebuf_printf(&file, "\n")) < 0 ||
|
||||||
|
(error = git_filebuf_commit(&file, 0666)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (error < 0)
|
||||||
|
git_filebuf_cleanup(&file);
|
||||||
|
|
||||||
|
git_buf_free(&file_path);
|
||||||
|
|
||||||
|
git_vector_free(&matching);
|
||||||
|
git__free(entries);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge__setup(
|
||||||
|
git_repository *repo,
|
||||||
|
const git_merge_head *our_head,
|
||||||
|
const git_merge_head *heads[],
|
||||||
|
size_t heads_len,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert (repo && our_head && heads);
|
||||||
|
|
||||||
|
if ((error = write_orig_head(repo, our_head)) == 0 &&
|
||||||
|
(error = write_merge_head(repo, heads, heads_len)) == 0 &&
|
||||||
|
(error = write_merge_mode(repo, flags)) == 0) {
|
||||||
|
error = write_merge_msg(repo, heads, heads_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_repository_merge_cleanup(git_repository *repo)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
git_buf merge_head_path = GIT_BUF_INIT,
|
||||||
|
merge_mode_path = GIT_BUF_INIT,
|
||||||
|
merge_msg_path = GIT_BUF_INIT;
|
||||||
|
|
||||||
|
assert(repo);
|
||||||
|
|
||||||
|
if (git_buf_joinpath(&merge_head_path, repo->path_repository, GIT_MERGE_HEAD_FILE) < 0 ||
|
||||||
|
git_buf_joinpath(&merge_mode_path, repo->path_repository, GIT_MERGE_MODE_FILE) < 0 ||
|
||||||
|
git_buf_joinpath(&merge_msg_path, repo->path_repository, GIT_MERGE_MSG_FILE) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (git_path_isfile(merge_head_path.ptr)) {
|
||||||
|
if ((error = p_unlink(merge_head_path.ptr)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (git_path_isfile(merge_mode_path.ptr))
|
||||||
|
(void)p_unlink(merge_mode_path.ptr);
|
||||||
|
|
||||||
|
if (git_path_isfile(merge_msg_path.ptr))
|
||||||
|
(void)p_unlink(merge_msg_path.ptr);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
git_buf_free(&merge_msg_path);
|
||||||
|
git_buf_free(&merge_mode_path);
|
||||||
|
git_buf_free(&merge_head_path);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Merge heads are the input to merge */
|
||||||
|
|
||||||
|
static int merge_head_init(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *ref_name,
|
||||||
|
const char *remote_url,
|
||||||
|
const git_oid *oid)
|
||||||
|
{
|
||||||
|
git_merge_head *head;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert(out && oid);
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
head = git__calloc(1, sizeof(git_merge_head));
|
||||||
|
GITERR_CHECK_ALLOC(head);
|
||||||
|
|
||||||
|
if (ref_name) {
|
||||||
|
head->ref_name = git__strdup(ref_name);
|
||||||
|
GITERR_CHECK_ALLOC(head->ref_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remote_url) {
|
||||||
|
head->remote_url = git__strdup(remote_url);
|
||||||
|
GITERR_CHECK_ALLOC(head->remote_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
git_oid_cpy(&head->oid, oid);
|
||||||
|
|
||||||
|
if ((error = git_commit_lookup(&head->commit, repo, &head->oid)) < 0) {
|
||||||
|
git_merge_head_free(head);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = head;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge_head_from_ref(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
git_reference *ref)
|
||||||
|
{
|
||||||
|
git_reference *resolved;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
assert(out && repo && ref);
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
if ((error = git_reference_resolve(&resolved, ref)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = merge_head_init(out, repo, git_reference_name(ref), NULL,
|
||||||
|
git_reference_target(resolved));
|
||||||
|
|
||||||
|
git_reference_free(resolved);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge_head_from_oid(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const git_oid *oid)
|
||||||
|
{
|
||||||
|
assert(out && repo && oid);
|
||||||
|
|
||||||
|
return merge_head_init(out, repo, NULL, NULL, oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_merge_head_from_fetchhead(
|
||||||
|
git_merge_head **out,
|
||||||
|
git_repository *repo,
|
||||||
|
const char *branch_name,
|
||||||
|
const char *remote_url,
|
||||||
|
const git_oid *oid)
|
||||||
|
{
|
||||||
|
assert(repo && branch_name && remote_url && oid);
|
||||||
|
|
||||||
|
return merge_head_init(out, repo, branch_name, remote_url, oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void git_merge_head_free(git_merge_head *head)
|
||||||
|
{
|
||||||
|
if (head == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
git_vector_free(&diff_list->staged);
|
if (head->commit != NULL)
|
||||||
git_vector_free(&diff_list->conflicts);
|
git_object_free((git_object *)head->commit);
|
||||||
git_vector_free(&diff_list->resolved);
|
|
||||||
git_pool_clear(&diff_list->pool);
|
if (head->ref_name != NULL)
|
||||||
git__free(diff_list);
|
git__free(head->ref_name);
|
||||||
|
|
||||||
|
if (head->remote_url != NULL)
|
||||||
|
git__free(head->remote_url);
|
||||||
|
|
||||||
|
git__free(head);
|
||||||
}
|
}
|
||||||
|
22
src/merge.h
22
src/merge.h
@ -107,12 +107,25 @@ typedef struct {
|
|||||||
git_delta_t their_status;
|
git_delta_t their_status;
|
||||||
} git_merge_diff;
|
} git_merge_diff;
|
||||||
|
|
||||||
|
/** Internal structure for merge inputs */
|
||||||
|
struct git_merge_head {
|
||||||
|
char *ref_name;
|
||||||
|
char *remote_url;
|
||||||
|
|
||||||
|
git_oid oid;
|
||||||
|
git_commit *commit;
|
||||||
|
};
|
||||||
|
|
||||||
int git_merge__bases_many(
|
int git_merge__bases_many(
|
||||||
git_commit_list **out,
|
git_commit_list **out,
|
||||||
git_revwalk *walk,
|
git_revwalk *walk,
|
||||||
git_commit_list_node *one,
|
git_commit_list_node *one,
|
||||||
git_vector *twos);
|
git_vector *twos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Three-way tree differencing
|
||||||
|
*/
|
||||||
|
|
||||||
git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo);
|
git_merge_diff_list *git_merge_diff_list__alloc(git_repository *repo);
|
||||||
|
|
||||||
int git_merge_diff_list__find_differences(git_merge_diff_list *merge_diff_list,
|
int git_merge_diff_list__find_differences(git_merge_diff_list *merge_diff_list,
|
||||||
@ -124,4 +137,13 @@ int git_merge_diff_list__find_renames(git_repository *repo, git_merge_diff_list
|
|||||||
|
|
||||||
void git_merge_diff_list__free(git_merge_diff_list *diff_list);
|
void git_merge_diff_list__free(git_merge_diff_list *diff_list);
|
||||||
|
|
||||||
|
/* Merge metadata setup */
|
||||||
|
|
||||||
|
int git_merge__setup(
|
||||||
|
git_repository *repo,
|
||||||
|
const git_merge_head *our_head,
|
||||||
|
const git_merge_head *their_heads[],
|
||||||
|
size_t their_heads_len,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,28 +8,28 @@
|
|||||||
static git_repository *repo;
|
static git_repository *repo;
|
||||||
static git_index *repo_index;
|
static git_index *repo_index;
|
||||||
|
|
||||||
#define TEST_REPO_PATH "testrepo"
|
#define TEST_REPO_PATH "merge-resolve"
|
||||||
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
|
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
|
||||||
|
|
||||||
#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452"
|
#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452"
|
||||||
|
|
||||||
#define THEIRS_SIMPLE_BRANCH "branch"
|
#define THEIRS_SIMPLE_BRANCH "branch"
|
||||||
#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520"
|
#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520"
|
||||||
|
|
||||||
#define OCTO1_BRANCH "octo1"
|
#define OCTO1_BRANCH "octo1"
|
||||||
#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061"
|
#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061"
|
||||||
|
|
||||||
#define OCTO2_BRANCH "octo2"
|
#define OCTO2_BRANCH "octo2"
|
||||||
#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c"
|
#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c"
|
||||||
|
|
||||||
#define OCTO3_BRANCH "octo3"
|
#define OCTO3_BRANCH "octo3"
|
||||||
#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272"
|
#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272"
|
||||||
|
|
||||||
#define OCTO4_BRANCH "octo4"
|
#define OCTO4_BRANCH "octo4"
|
||||||
#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae"
|
#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae"
|
||||||
|
|
||||||
#define OCTO5_BRANCH "octo5"
|
#define OCTO5_BRANCH "octo5"
|
||||||
#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f"
|
#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f"
|
||||||
|
|
||||||
// Fixture setup and teardown
|
// Fixture setup and teardown
|
||||||
void test_merge_workdir_setup__initialize(void)
|
void test_merge_workdir_setup__initialize(void)
|
||||||
@ -44,6 +44,22 @@ void test_merge_workdir_setup__cleanup(void)
|
|||||||
cl_git_sandbox_cleanup();
|
cl_git_sandbox_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool test_file_contents(const char *filename, const char *expected)
|
||||||
|
{
|
||||||
|
git_buf file_path_buf = GIT_BUF_INIT, file_buf = GIT_BUF_INIT;
|
||||||
|
bool equals;
|
||||||
|
|
||||||
|
git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename);
|
||||||
|
|
||||||
|
cl_git_pass(git_futils_readbuffer(&file_buf, file_path_buf.ptr));
|
||||||
|
equals = (strcmp(file_buf.ptr, expected) == 0);
|
||||||
|
|
||||||
|
git_buf_free(&file_path_buf);
|
||||||
|
git_buf_free(&file_buf);
|
||||||
|
|
||||||
|
return equals;
|
||||||
|
}
|
||||||
|
|
||||||
static void write_file_contents(const char *filename, const char *output)
|
static void write_file_contents(const char *filename, const char *output)
|
||||||
{
|
{
|
||||||
git_buf file_path_buf = GIT_BUF_INIT;
|
git_buf file_path_buf = GIT_BUF_INIT;
|
||||||
@ -55,6 +71,816 @@ static void write_file_contents(const char *filename, const char *output)
|
|||||||
git_buf_free(&file_path_buf);
|
git_buf_free(&file_path_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* git merge --no-ff octo1 */
|
||||||
|
void test_merge_workdir_setup__one_branch(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[1];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge --no-ff 16f825815cfd20a07a75c71554e82d8eede0b061 */
|
||||||
|
void test_merge_workdir_setup__one_oid(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[1];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 octo2 */
|
||||||
|
void test_merge_workdir_setup__two_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 octo2 octo3 */
|
||||||
|
void test_merge_workdir_setup__three_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_reference *octo3_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
git_reference_free(octo3_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 158dc7bedb202f5b26502bf3574faa7f4238d56c 50ce7d7d01217679e26c55939eef119e0c93e272 */
|
||||||
|
void test_merge_workdir_setup__three_oids(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c */
|
||||||
|
void test_merge_workdir_setup__branches_and_oids_1(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 158dc7bedb202f5b26502bf3574faa7f4238d56c octo3 54269b3f6ec3d7d4ede24dd350dd5d605495c3ae */
|
||||||
|
void test_merge_workdir_setup__branches_and_oids_2(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_reference *octo3_ref;
|
||||||
|
git_oid octo4_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[4];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[3], repo, &octo4_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "'; commit '" OCTO2_OID "'; commit '" OCTO4_OID "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo3_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
git_merge_head_free(their_heads[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 */
|
||||||
|
void test_merge_workdir_setup__branches_and_oids_3(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_reference *octo4_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[4];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "'; commit '" OCTO3_OID "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
git_reference_free(octo4_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
git_merge_head_free(their_heads[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 octo2 50ce7d7d01217679e26c55939eef119e0c93e272 octo4 octo5 */
|
||||||
|
void test_merge_workdir_setup__branches_and_oids_4(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_reference *octo4_ref;
|
||||||
|
git_reference *octo5_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[5];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo5_ref, repo, GIT_REFS_HEADS_DIR OCTO5_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[4], repo, octo5_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 5, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n" OCTO5_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "', '" OCTO4_BRANCH "' and '" OCTO5_BRANCH "'; commit '" OCTO3_OID "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
git_reference_free(octo4_ref);
|
||||||
|
git_reference_free(octo5_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
git_merge_head_free(their_heads[3]);
|
||||||
|
git_merge_head_free(their_heads[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 octo1 octo1 */
|
||||||
|
void test_merge_workdir_setup__three_same_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_1_ref;
|
||||||
|
git_reference *octo1_2_ref;
|
||||||
|
git_reference *octo1_3_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_2_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo1_2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo1_3_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO1_BRANCH "' and '" OCTO1_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_1_ref);
|
||||||
|
git_reference_free(octo1_2_ref);
|
||||||
|
git_reference_free(octo1_3_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 16f825815cfd20a07a75c71554e82d8eede0b061 */
|
||||||
|
void test_merge_workdir_setup__three_same_oids(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_1_oid;
|
||||||
|
git_oid octo1_2_oid;
|
||||||
|
git_oid octo1_3_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[0], repo, &octo1_1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_2_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[1], repo, &octo1_2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&their_heads[2], repo, &octo1_3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_remote_tracking_branch(const char *branch_name, const char *oid_str)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
git_buf remotes_path = GIT_BUF_INIT,
|
||||||
|
origin_path = GIT_BUF_INIT,
|
||||||
|
filename = GIT_BUF_INIT,
|
||||||
|
data = GIT_BUF_INIT;
|
||||||
|
|
||||||
|
if ((error = git_buf_puts(&remotes_path, git_repository_path(repo))) < 0 ||
|
||||||
|
(error = git_buf_puts(&remotes_path, GIT_REFS_REMOTES_DIR)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!git_path_exists(git_buf_cstr(&remotes_path)) &&
|
||||||
|
(error = p_mkdir(git_buf_cstr(&remotes_path), 0777)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((error = git_buf_puts(&origin_path, git_buf_cstr(&remotes_path))) < 0 ||
|
||||||
|
(error = git_buf_puts(&origin_path, "origin")) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if (!git_path_exists(git_buf_cstr(&origin_path)) &&
|
||||||
|
(error = p_mkdir(git_buf_cstr(&origin_path), 0777)) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
if ((error = git_buf_puts(&filename, git_buf_cstr(&origin_path))) < 0 ||
|
||||||
|
(error = git_buf_puts(&filename, "/")) < 0 ||
|
||||||
|
(error = git_buf_puts(&filename, branch_name)) < 0 ||
|
||||||
|
(error = git_buf_puts(&data, oid_str)) < 0 ||
|
||||||
|
(error = git_buf_puts(&data, "\n")) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
cl_git_rewritefile(git_buf_cstr(&filename), git_buf_cstr(&data));
|
||||||
|
|
||||||
|
done:
|
||||||
|
git_buf_free(&remotes_path);
|
||||||
|
git_buf_free(&origin_path);
|
||||||
|
git_buf_free(&filename);
|
||||||
|
git_buf_free(&data);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge refs/remotes/origin/octo1 */
|
||||||
|
void test_merge_workdir_setup__remote_tracking_one_branch(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[1];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 */
|
||||||
|
void test_merge_workdir_setup__remote_tracking_two_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "' and 'refs/remotes/origin/" OCTO2_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge refs/remotes/origin/octo1 refs/remotes/origin/octo2 refs/remotes/origin/octo3 */
|
||||||
|
void test_merge_workdir_setup__remote_tracking_three_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_reference *octo3_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO3_BRANCH, OCTO3_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO3_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branches 'refs/remotes/origin/" OCTO1_BRANCH "', 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO3_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
git_reference_free(octo3_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 refs/remotes/origin/octo2 */
|
||||||
|
void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO2_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge refs/remotes/origin/octo1 octo2 */
|
||||||
|
void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO1_BRANCH, OCTO1_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO2_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git merge octo1 refs/remotes/origin/octo2 octo3 refs/remotes/origin/octo4 */
|
||||||
|
void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branches(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_reference *octo1_ref;
|
||||||
|
git_reference *octo2_ref;
|
||||||
|
git_reference *octo3_ref;
|
||||||
|
git_reference *octo4_ref;
|
||||||
|
git_merge_head *our_head, *their_heads[4];
|
||||||
|
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO2_BRANCH, OCTO2_OID));
|
||||||
|
cl_git_pass(create_remote_tracking_branch(OCTO4_BRANCH, OCTO4_OID));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[1], repo, octo2_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[2], repo, octo3_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO4_BRANCH));
|
||||||
|
cl_git_pass(git_merge_head_from_ref(&their_heads[3], repo, octo4_ref));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "', remote-tracking branches 'refs/remotes/origin/" OCTO2_BRANCH "' and 'refs/remotes/origin/" OCTO4_BRANCH "'\n"));
|
||||||
|
|
||||||
|
git_reference_free(octo1_ref);
|
||||||
|
git_reference_free(octo2_ref);
|
||||||
|
git_reference_free(octo3_ref);
|
||||||
|
git_reference_free(octo4_ref);
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
git_merge_head_free(their_heads[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git pull origin branch octo1 */
|
||||||
|
void test_merge_workdir_setup__pull_one(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_1_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[1];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git pull origin octo1 octo2 */
|
||||||
|
void test_merge_workdir_setup__pull_two(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[2];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git pull origin octo1 octo2 octo3 */
|
||||||
|
void test_merge_workdir_setup__pull_three(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.url/repo.git", &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.url/repo.git", &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.url/repo.git", &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.url/repo.git\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_merge_workdir_setup__three_remotes(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[3];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.third/repo.git", &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "' of http://remote.first/repo.git, branch '" OCTO2_BRANCH "' of http://remote.second/repo.git, branch '" OCTO3_BRANCH "' of http://remote.third/repo.git\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_merge_workdir_setup__two_remotes(void)
|
||||||
|
{
|
||||||
|
git_oid our_oid;
|
||||||
|
git_oid octo1_oid;
|
||||||
|
git_oid octo2_oid;
|
||||||
|
git_oid octo3_oid;
|
||||||
|
git_oid octo4_oid;
|
||||||
|
git_merge_head *our_head, *their_heads[4];
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
|
||||||
|
cl_git_pass(git_merge_head_from_oid(&our_head, repo, &our_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[0], repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH, "http://remote.first/repo.git", &octo1_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[1], repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH, "http://remote.second/repo.git", &octo2_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[2], repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH, "http://remote.first/repo.git", &octo3_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID));
|
||||||
|
cl_git_pass(git_merge_head_from_fetchhead(&their_heads[3], repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH, "http://remote.second/repo.git", &octo4_oid));
|
||||||
|
|
||||||
|
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0));
|
||||||
|
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n" OCTO4_OID "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, ""));
|
||||||
|
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "' of http://remote.first/repo.git, branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "' of http://remote.second/repo.git\n"));
|
||||||
|
|
||||||
|
git_merge_head_free(our_head);
|
||||||
|
git_merge_head_free(their_heads[0]);
|
||||||
|
git_merge_head_free(their_heads[1]);
|
||||||
|
git_merge_head_free(their_heads[2]);
|
||||||
|
git_merge_head_free(their_heads[3]);
|
||||||
|
}
|
||||||
|
|
||||||
struct merge_head_cb_data {
|
struct merge_head_cb_data {
|
||||||
const char **oid_str;
|
const char **oid_str;
|
||||||
unsigned int len;
|
unsigned int len;
|
||||||
|
Loading…
Reference in New Issue
Block a user