Commit 42e50b5e by Edward Thomson

MERGE_HEAD contents iterator

parent b449a9ae
...@@ -64,6 +64,7 @@ typedef enum { ...@@ -64,6 +64,7 @@ typedef enum {
GITERR_STASH, GITERR_STASH,
GITERR_CHECKOUT, GITERR_CHECKOUT,
GITERR_FETCHHEAD, GITERR_FETCHHEAD,
GITERR_MERGE,
} git_error_t; } git_error_t;
/** /**
......
...@@ -517,6 +517,22 @@ GIT_EXTERN(int) git_repository_fetchhead_foreach(git_repository *repo, ...@@ -517,6 +517,22 @@ GIT_EXTERN(int) git_repository_fetchhead_foreach(git_repository *repo,
git_repository_fetchhead_foreach_cb callback, git_repository_fetchhead_foreach_cb callback,
void *payload); void *payload);
typedef int (*git_repository_mergehead_foreach_cb)(const git_oid *oid,
void *payload);
/**
* If a merge is in progress, call callback 'cb' for each commit ID in the
* MERGE_HEAD file.
*
* @param repo A repository object
* @param callback Callback function
* @param apyload Pointer to callback data (optional)
* @return 0 on success, GIT_ENOTFOUND, GIT_EUSER or error
*/
GIT_EXTERN(int) git_repository_mergehead_foreach(git_repository *repo,
git_repository_mergehead_foreach_cb callback,
void *payload);
/** /**
* Calculate hash of file using repository filtering rules. * Calculate hash of file using repository filtering rules.
* *
......
...@@ -241,3 +241,56 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l ...@@ -241,3 +241,56 @@ int git_merge__bases_many(git_commit_list **out, git_revwalk *walk, git_commit_l
*out = result; *out = result;
return 0; return 0;
} }
int git_repository_mergehead_foreach(git_repository *repo,
git_repository_mergehead_foreach_cb cb,
void *payload)
{
git_buf merge_head_path = GIT_BUF_INIT, merge_head_file = GIT_BUF_INIT;
char *buffer, *line;
size_t line_num = 1;
git_oid oid;
int error = 0;
assert(repo && cb);
if ((error = git_buf_joinpath(&merge_head_path, repo->path_repository,
GIT_MERGE_HEAD_FILE)) < 0)
return error;
if ((error = git_futils_readbuffer(&merge_head_file,
git_buf_cstr(&merge_head_path))) < 0)
goto cleanup;
buffer = merge_head_file.ptr;
while ((line = git__strsep(&buffer, "\n")) != NULL) {
if (strlen(line) != GIT_OID_HEXSZ) {
giterr_set(GITERR_INVALID, "Unable to parse OID - invalid length");
error = -1;
goto cleanup;
}
if ((error = git_oid_fromstr(&oid, line)) < 0)
goto cleanup;
if (cb(&oid, payload) < 0) {
error = GIT_EUSER;
goto cleanup;
}
++line_num;
}
if (*buffer) {
giterr_set(GITERR_MERGE, "No EOL at line %d", line_num);
error = -1;
goto cleanup;
}
cleanup:
git_buf_free(&merge_head_path);
git_buf_free(&merge_head_file);
return error;
}
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "git2/types.h" #include "git2/types.h"
#include "git2/merge.h" #include "git2/merge.h"
#include "commit_list.h" #include "commit_list.h"
#include "vector.h"
#define GIT_MERGE_MSG_FILE "MERGE_MSG" #define GIT_MERGE_MSG_FILE "MERGE_MSG"
#define GIT_MERGE_MODE_FILE "MERGE_MODE" #define GIT_MERGE_MODE_FILE "MERGE_MODE"
......
#include "clar_libgit2.h"
#include "git2/repository.h"
#include "git2/merge.h"
#include "merge.h"
#include "refs.h"
#include "fileops.h"
static git_repository *repo;
static git_index *repo_index;
#define TEST_REPO_PATH "testrepo"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
#define ORIG_HEAD "bd593285fc7fe4ca18ccdbabf027f5d689101452"
#define THEIRS_SIMPLE_BRANCH "branch"
#define THEIRS_SIMPLE_OID "7cb63eed597130ba4abb87b3e544b85021905520"
#define OCTO1_BRANCH "octo1"
#define OCTO1_OID "16f825815cfd20a07a75c71554e82d8eede0b061"
#define OCTO2_BRANCH "octo2"
#define OCTO2_OID "158dc7bedb202f5b26502bf3574faa7f4238d56c"
#define OCTO3_BRANCH "octo3"
#define OCTO3_OID "50ce7d7d01217679e26c55939eef119e0c93e272"
#define OCTO4_BRANCH "octo4"
#define OCTO4_OID "54269b3f6ec3d7d4ede24dd350dd5d605495c3ae"
#define OCTO5_BRANCH "octo5"
#define OCTO5_OID "e4f618a2c3ed0669308735727df5ebf2447f022f"
// Fixture setup and teardown
void test_merge_setup__initialize(void)
{
repo = cl_git_sandbox_init(TEST_REPO_PATH);
git_repository_index(&repo_index, repo);
}
void test_merge_setup__cleanup(void)
{
git_index_free(repo_index);
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;
git_buf_printf(&file_path_buf, "%s/%s", git_repository_path(repo), filename);
cl_git_rewritefile(file_path_buf.ptr, output);
git_buf_free(&file_path_buf);
}
struct merge_head_cb_data {
const char **oid_str;
unsigned int len;
unsigned int i;
};
int merge_head_foreach_cb(git_oid *oid, void *payload)
{
git_oid expected_oid;
struct merge_head_cb_data *cb_data = payload;
git_oid_fromstr(&expected_oid, cb_data->oid_str[cb_data->i]);
cl_assert(git_oid_cmp(&expected_oid, oid) == 0);
cb_data->i++;
return 0;
}
void test_merge_setup__head_notfound(void)
{
int error;
cl_git_fail((error = git_repository_mergehead_foreach(repo,
merge_head_foreach_cb, NULL)));
cl_assert(error == GIT_ENOTFOUND);
}
void test_merge_setup__head_invalid_oid(void)
{
int error;
write_file_contents(GIT_MERGE_HEAD_FILE, "invalid-oid\n");
cl_git_fail((error = git_repository_mergehead_foreach(repo,
merge_head_foreach_cb, NULL)));
cl_assert(error == -1);
}
void test_merge_setup__head_foreach_nonewline(void)
{
int error;
write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID);
cl_git_fail((error = git_repository_mergehead_foreach(repo,
merge_head_foreach_cb, NULL)));
cl_assert(error == -1);
}
void test_merge_setup__head_foreach_one(void)
{
const char *expected = THEIRS_SIMPLE_OID;
struct merge_head_cb_data cb_data = { &expected, 1 };
write_file_contents(GIT_MERGE_HEAD_FILE, THEIRS_SIMPLE_OID "\n");
cl_git_pass(git_repository_mergehead_foreach(repo,
merge_head_foreach_cb, &cb_data));
cl_assert(cb_data.i == cb_data.len);
}
void test_merge_setup__head_foreach_octopus(void)
{
const char *expected[] = { THEIRS_SIMPLE_OID,
OCTO1_OID, OCTO2_OID, OCTO3_OID, OCTO4_OID, OCTO5_OID };
struct merge_head_cb_data cb_data = { expected, 6 };
write_file_contents(GIT_MERGE_HEAD_FILE,
THEIRS_SIMPLE_OID "\n"
OCTO1_OID "\n"
OCTO2_OID "\n"
OCTO3_OID "\n"
OCTO4_OID "\n"
OCTO5_OID "\n");
cl_git_pass(git_repository_mergehead_foreach(repo,
merge_head_foreach_cb, &cb_data));
cl_assert(cb_data.i == cb_data.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