Commit 9c06b250 by Edward Thomson Committed by Edward Thomson

merge setup

parent 5b3d52ce
......@@ -23,13 +23,13 @@
GIT_BEGIN_DECL
/**
* Flags for tree_many diff options. A combination of these flags can be
* passed in via the `flags` value in the `git_diff_tree_many_options`.
* Flags for `git_mrege_tree` options. A combination of these flags can be
* passed in via the `flags` vlaue in the `git_merge_tree_opts`.
*/
typedef enum {
/** Detect renames */
GIT_MERGE_TREE_FIND_RENAMES = (1 << 0),
} git_merge_tree_flags;
} git_merge_tree_flag_t;
/**
* Automerge options for `git_merge_trees_opts`.
......@@ -44,7 +44,7 @@ typedef enum {
typedef struct {
unsigned int version;
git_merge_tree_flags flags;
git_merge_tree_flag_t flags;
/** Similarity to consider a file renamed (default 50) */
unsigned int rename_threshold;
......@@ -96,6 +96,57 @@ GIT_EXTERN(int) git_merge_base_many(
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
* the merge.
*
......
......@@ -168,6 +168,9 @@ typedef struct git_reference git_reference;
/** Iterator for references */
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. */
typedef enum {
......
......@@ -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 */
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;
}
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(
git_repository *repo,
git_merge_tree_opts *opts,
......@@ -1617,14 +1596,550 @@ done:
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;
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);
if (head->commit != NULL)
git_object_free((git_object *)head->commit);
if (head->ref_name != NULL)
git__free(head->ref_name);
if (head->remote_url != NULL)
git__free(head->remote_url);
git__free(head);
}
......@@ -107,12 +107,25 @@ typedef struct {
git_delta_t their_status;
} 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(
git_commit_list **out,
git_revwalk *walk,
git_commit_list_node *one,
git_vector *twos);
/*
* Three-way tree differencing
*/
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,
......@@ -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);
/* 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
......@@ -8,28 +8,28 @@
static git_repository *repo;
static git_index *repo_index;
#define TEST_REPO_PATH "testrepo"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
#define TEST_REPO_PATH "merge-resolve"
#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_OID "7cb63eed597130ba4abb87b3e544b85021905520"
#define THEIRS_SIMPLE_BRANCH "branch"
#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520"
#define OCTO1_BRANCH "octo1"
#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061"
#define OCTO1_BRANCH "octo1"
#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061"
#define OCTO2_BRANCH "octo2"
#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c"
#define OCTO2_BRANCH "octo2"
#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c"
#define OCTO3_BRANCH "octo3"
#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272"
#define OCTO3_BRANCH "octo3"
#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272"
#define OCTO4_BRANCH "octo4"
#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae"
#define OCTO4_BRANCH "octo4"
#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae"
#define OCTO5_BRANCH "octo5"
#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f"
#define OCTO5_BRANCH "octo5"
#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f"
// Fixture setup and teardown
void test_merge_workdir_setup__initialize(void)
......@@ -44,6 +44,22 @@ void test_merge_workdir_setup__cleanup(void)
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)
{
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 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 {
const char **oid_str;
unsigned int len;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment