Commit 85a41fc4 by Vicent Marti

Merge pull request #2183 from ethomson/merge_refactor

Refactor the `git_merge` API
parents f57cc638 58c2b1c4
...@@ -23,6 +23,43 @@ ...@@ -23,6 +23,43 @@
GIT_BEGIN_DECL GIT_BEGIN_DECL
/** /**
* The file inputs to `git_merge_file`. Callers should populate the
* `git_merge_file_input` structure with descriptions of the files in
* each side of the conflict for use in producing the merge file.
*/
typedef struct {
unsigned int version;
/** Pointer to the contents of the file. */
const char *ptr;
/** Size of the contents pointed to in `ptr`. */
size_t size;
/** File name of the conflicted file, or `NULL` to not merge the path. */
const char *path;
/** File mode of the conflicted file, or `0` to not merge the mode. */
unsigned int mode;
} git_merge_file_input;
#define GIT_MERGE_FILE_INPUT_VERSION 1
#define GIT_MERGE_FILE_INPUT_INIT {GIT_MERGE_FILE_INPUT_VERSION}
/**
* Initializes a `git_merge_file_input` with default values. Equivalent to
* creating an instance with GIT_MERGE_FILE_INPUT_INIT.
*
* @param opts the `git_merge_file_input` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_MERGE_FILE_INPUT_VERSION` here.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_merge_file_init_input(
git_merge_file_input *opts,
int version);
/**
* Flags for `git_merge_tree` options. A combination of these flags can be * Flags for `git_merge_tree` options. A combination of these flags can be
* passed in via the `flags` value in the `git_merge_tree_opts`. * passed in via the `flags` value in the `git_merge_tree_opts`.
*/ */
...@@ -71,6 +108,86 @@ typedef enum { ...@@ -71,6 +108,86 @@ typedef enum {
GIT_MERGE_FILE_FAVOR_UNION = 3, GIT_MERGE_FILE_FAVOR_UNION = 3,
} git_merge_file_favor_t; } git_merge_file_favor_t;
typedef enum {
/* Defaults */
GIT_MERGE_FILE_DEFAULT = 0,
/* Create standard conflicted merge files */
GIT_MERGE_FILE_STYLE_MERGE = (1 << 0),
/* Create diff3-style files */
GIT_MERGE_FILE_STYLE_DIFF3 = (1 << 1),
/* Condense non-alphanumeric regions for simplified diff file */
GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 2),
} git_merge_file_flags_t;
typedef struct {
unsigned int version;
/**
* Label for the ancestor file side of the conflict which will be prepended
* to labels in diff3-format merge files.
*/
const char *ancestor_label;
/**
* Label for our file side of the conflict which will be prepended
* to labels in merge files.
*/
const char *our_label;
/**
* Label for their file side of the conflict which will be prepended
* to labels in merge files.
*/
const char *their_label;
/** The file to favor in region conflicts. */
git_merge_file_favor_t favor;
/** Merge file flags. */
git_merge_file_flags_t flags;
} git_merge_file_options;
#define GIT_MERGE_FILE_OPTIONS_VERSION 1
#define GIT_MERGE_FILE_OPTIONS_INIT {GIT_MERGE_FILE_OPTIONS_VERSION}
/**
* Initializes a `git_merge_file_options` with default values. Equivalent to
* creating an instance with GIT_MERGE_FILE_OPTIONS_INIT.
*
* @param opts the `git_merge_file_options` instance to initialize.
* @param version the version of the struct; you should pass
* `GIT_MERGE_FILE_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure.
*/
GIT_EXTERN(int) git_merge_file_init_options(
git_merge_file_options *opts,
int version);
typedef struct {
/**
* True if the output was automerged, false if the output contains
* conflict markers.
*/
unsigned int automergeable;
/**
* The path that the resultant merge file should use, or NULL if a
* filename conflict would occur.
*/
char *path;
/** The mode that the resultant merge file should use. */
unsigned int mode;
/** The contents of the merge. */
unsigned char *ptr;
/** The length of the merge contents. */
size_t len;
} git_merge_file_result;
typedef struct { typedef struct {
unsigned int version; unsigned int version;
...@@ -99,75 +216,73 @@ typedef struct { ...@@ -99,75 +216,73 @@ typedef struct {
/** Flags for handling conflicting content. */ /** Flags for handling conflicting content. */
git_merge_file_favor_t file_favor; git_merge_file_favor_t file_favor;
} git_merge_tree_opts; } git_merge_options;
#define GIT_MERGE_TREE_OPTS_VERSION 1 #define GIT_MERGE_OPTIONS_VERSION 1
#define GIT_MERGE_TREE_OPTS_INIT {GIT_MERGE_TREE_OPTS_VERSION} #define GIT_MERGE_OPTIONS_INIT {GIT_MERGE_OPTIONS_VERSION}
/** /**
* Initializes a `git_merge_tree_opts` with default values. Equivalent to * Initializes a `git_merge_options` with default values. Equivalent to
* creating an instance with GIT_MERGE_TREE_OPTS_INIT. * creating an instance with GIT_MERGE_OPTIONS_INIT.
* *
* @param opts the `git_merge_tree_opts` instance to initialize. * @param opts the `git_merge_options` instance to initialize.
* @param version the version of the struct; you should pass * @param version the version of the struct; you should pass
* `GIT_MERGE_TREE_OPTS_VERSION` here. * `GIT_MERGE_OPTIONS_VERSION` here.
* @return Zero on success; -1 on failure. * @return Zero on success; -1 on failure.
*/ */
GIT_EXTERN(int) git_merge_tree_init_opts( GIT_EXTERN(int) git_merge_init_options(
git_merge_tree_opts* opts, git_merge_options *opts,
int version); int version);
/** /**
* Option flags for `git_merge`. * The results of `git_merge_analysis` indicate the merge opportunities.
*/ */
typedef enum { typedef enum {
/** No merge is possible. (Unused.) */
GIT_MERGE_ANALYSIS_NONE = 0,
/** /**
* The default behavior is to allow fast-forwards, returning * A "normal" merge; both HEAD and the given merge input have diverged
* immediately with the commit ID to fast-forward to. * from their common ancestor. The divergent commits must be merged.
*/ */
GIT_MERGE_DEFAULT = 0, GIT_MERGE_ANALYSIS_NORMAL = (1 << 0),
/** /**
* Do not fast-forward; perform a merge and prepare a merge result even * All given merge inputs are reachable from HEAD, meaning the
* if the inputs are eligible for fast-forwarding. * repository is up-to-date and no merge needs to be performed.
*/ */
GIT_MERGE_NO_FASTFORWARD = 1, GIT_MERGE_ANALYSIS_UP_TO_DATE = (1 << 1),
/** /**
* Ensure that the inputs are eligible for fast-forwarding, error if * The given merge input is a fast-forward from HEAD and no merge
* a merge needs to be performed. * needs to be performed. Instead, the client can check out the
* given merge input.
*/ */
GIT_MERGE_FASTFORWARD_ONLY = 2, GIT_MERGE_ANALYSIS_FASTFORWARD = (1 << 2),
} git_merge_flags_t;
typedef struct {
unsigned int version;
/** Options for handling the commit-level merge. */
git_merge_flags_t merge_flags;
/** Options for handling the merges of individual files. */
git_merge_tree_opts merge_tree_opts;
/** Options for writing the merge result to the working directory. */
git_checkout_options checkout_opts;
} git_merge_opts;
#define GIT_MERGE_OPTS_VERSION 1 /**
#define GIT_MERGE_OPTS_INIT {GIT_MERGE_OPTS_VERSION, 0, GIT_MERGE_TREE_OPTS_INIT, GIT_CHECKOUT_OPTIONS_INIT} * The HEAD of the current repository is "unborn" and does not point to
* a valid commit. No merge can be performed, but the caller may wish
* to simply set HEAD to the target commit(s).
*/
GIT_MERGE_ANALYSIS_UNBORN = (1 << 3),
} git_merge_analysis_t;
/** /**
* Initializes a `git_merge_opts` with default values. Equivalent to creating * Analyzes the given branch(es) and determines the opportunities for
* an instance with GIT_MERGE_OPTS_INIT. * merging them into the HEAD of the repository.
* *
* @param opts the `git_merge_opts` instance to initialize. * @param analysis_out analysis enumeration that the result is written into
* @param version the version of the struct; you should pass * @param repo the repository to merge
* `GIT_MERGE_OPTS_VERSION` here. * @param their_heads the heads to merge into
* @return Zero on success; -1 on failure. * @param their_heads_len the number of heads to merge
* @return 0 on success or error code
*/ */
GIT_EXTERN(int) git_merge_init_opts( GIT_EXTERN(int) git_merge_analysis(
git_merge_opts* opts, git_merge_analysis_t *analysis_out,
int version); git_repository *repo,
const git_merge_head **their_heads,
size_t their_heads_len);
/** /**
* Find a merge base between two commits * Find a merge base between two commits
...@@ -269,6 +384,58 @@ GIT_EXTERN(void) git_merge_head_free( ...@@ -269,6 +384,58 @@ GIT_EXTERN(void) git_merge_head_free(
git_merge_head *head); git_merge_head *head);
/** /**
* Merge two files as they exist in the in-memory data structures, using
* the given common ancestor as the baseline, producing a
* `git_merge_file_result` that reflects the merge result. The
* `git_merge_file_result` must be freed with `git_merge_file_result_free`.
*
* Note that this function does not reference a repository and any
* configuration must be passed as `git_merge_file_options`.
*
* @param out The git_merge_file_result to be filled in
* @param ancestor The contents of the ancestor file
* @param ours The contents of the file in "our" side
* @param theirs The contents of the file in "their" side
* @param opts The merge file options or `NULL` for defaults
* @return 0 on success or error code
*/
GIT_EXTERN(int) git_merge_file(
git_merge_file_result *out,
const git_merge_file_input *ancestor,
const git_merge_file_input *ours,
const git_merge_file_input *theirs,
const git_merge_file_options *opts);
/**
* Merge two files as they exist in the index, using the given common
* ancestor as the baseline, producing a `git_merge_file_result` that
* reflects the merge result. The `git_merge_file_result` must be freed with
* `git_merge_file_result_free`.
*
* @param out The git_merge_file_result to be filled in
* @param repo The repository
* @param ancestor The index entry for the ancestor file (stage level 1)
* @param our_path The index entry for our file (stage level 2)
* @param their_path The index entry for their file (stage level 3)
* @param opts The merge file options or NULL
* @return 0 on success or error code
*/
GIT_EXTERN(int) git_merge_file_from_index(
git_merge_file_result *out,
git_repository *repo,
const git_index_entry *ancestor,
const git_index_entry *ours,
const git_index_entry *theirs,
const git_merge_file_options *opts);
/**
* Frees a `git_merge_file_result`.
*
* @param result The result to free or `NULL`
*/
GIT_EXTERN(void) git_merge_file_result_free(git_merge_file_result *result);
/**
* 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 index may be written as-is to the working directory * the merge. The index may be written as-is to the working directory
* or checked out. If the index is to be converted to a tree, the caller * or checked out. If the index is to be converted to a tree, the caller
...@@ -290,7 +457,7 @@ GIT_EXTERN(int) git_merge_trees( ...@@ -290,7 +457,7 @@ GIT_EXTERN(int) git_merge_trees(
const git_tree *ancestor_tree, const git_tree *ancestor_tree,
const git_tree *our_tree, const git_tree *our_tree,
const git_tree *their_tree, const git_tree *their_tree,
const git_merge_tree_opts *opts); const git_merge_options *opts);
/** /**
* Merge two commits, producing a `git_index` that reflects the result of * Merge two commits, producing a `git_index` that reflects the result of
...@@ -312,81 +479,27 @@ GIT_EXTERN(int) git_merge_commits( ...@@ -312,81 +479,27 @@ GIT_EXTERN(int) git_merge_commits(
git_repository *repo, git_repository *repo,
const git_commit *our_commit, const git_commit *our_commit,
const git_commit *their_commit, const git_commit *their_commit,
const git_merge_tree_opts *opts); const git_merge_options *opts);
/** /**
* Merges the given commit(s) into HEAD and either returns immediately * Merges the given commit(s) into HEAD, writing the results into the working
* if there was no merge to perform (the specified commits have already * directory. Any changes are staged for commit and any conflicts are written
* been merged or would produce a fast-forward) or performs the merge * to the index. Callers should inspect the repository's index after this
* and writes the results into the working directory. * completes, resolve any conflicts and prepare a commit.
*
* Callers should inspect the `git_merge_result`:
*
* If `git_merge_result_is_uptodate` is true, there is no work to perform.
* *
* If `git_merge_result_is_fastforward` is true, the caller should update
* any necessary references to the commit ID returned by
* `git_merge_result_fastforward_id` and check that out in order to complete
* the fast-forward.
*
* Otherwise, callers should inspect the resulting index, resolve any
* conflicts and prepare a commit.
*
* The resultant `git_merge_result` should be free with
* `git_merge_result_free`.
*
* @param out the results of the merge
* @param repo the repository to merge * @param repo the repository to merge
* @param merge_heads the heads to merge into * @param merge_heads the heads to merge into
* @param merge_heads_len the number of heads to merge * @param merge_heads_len the number of heads to merge
* @param opts merge options * @param merge_opts merge options
* @param checkout_opts checkout options
* @return 0 on success or error code * @return 0 on success or error code
*/ */
GIT_EXTERN(int) git_merge( GIT_EXTERN(int) git_merge(
git_merge_result **out,
git_repository *repo, git_repository *repo,
const git_merge_head **their_heads, const git_merge_head **their_heads,
size_t their_heads_len, size_t their_heads_len,
const git_merge_opts *opts); const git_merge_options *merge_opts,
const git_checkout_options *checkout_opts);
/**
* Returns true if a merge is "up-to-date", meaning that the commit(s)
* that were provided to `git_merge` are already included in `HEAD`
* and there is no work to do.
*
* @return true if the merge is up-to-date, false otherwise
*/
GIT_EXTERN(int) git_merge_result_is_uptodate(git_merge_result *merge_result);
/**
* Returns true if a merge is eligible to be "fast-forwarded", meaning that
* the commit that was provided to `git_merge` need not be merged, it can
* simply be checked out, because the current `HEAD` is the merge base of
* itself and the given commit. To perform the fast-forward, the caller
* should check out the results of `git_merge_result_fastforward_id`.
*
* This will never be true if `GIT_MERGE_NO_FASTFORWARD` is supplied as
* a merge option.
*
* @return true if the merge is fast-forwardable, false otherwise
*/
GIT_EXTERN(int) git_merge_result_is_fastforward(git_merge_result *merge_result);
/**
* Gets the fast-forward OID if the merge was a fastforward.
*
* @param out pointer to populate with the OID of the fast-forward
* @param merge_result the results of the merge
* @return 0 on success or error code
*/
GIT_EXTERN(int) git_merge_result_fastforward_id(git_oid *out, git_merge_result *merge_result);
/**
* Frees a `git_merge_result`.
*
* @param result merge result to free
*/
GIT_EXTERN(void) git_merge_result_free(git_merge_result *merge_result);
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -26,12 +26,12 @@ typedef struct { ...@@ -26,12 +26,12 @@ typedef struct {
/** For merge commits, the "mainline" is treated as the parent. */ /** For merge commits, the "mainline" is treated as the parent. */
unsigned int mainline; unsigned int mainline;
git_merge_tree_opts merge_tree_opts; git_merge_options merge_opts;
git_checkout_options checkout_opts; git_checkout_options checkout_opts;
} git_revert_options; } git_revert_options;
#define GIT_REVERT_OPTIONS_VERSION 1 #define GIT_REVERT_OPTIONS_VERSION 1
#define GIT_REVERT_OPTIONS_INIT {GIT_REVERT_OPTIONS_VERSION, 0, GIT_MERGE_TREE_OPTS_INIT, GIT_CHECKOUT_OPTIONS_INIT} #define GIT_REVERT_OPTIONS_INIT {GIT_REVERT_OPTIONS_VERSION, 0, GIT_MERGE_OPTIONS_INIT, GIT_CHECKOUT_OPTIONS_INIT}
/** /**
* Initializes a `git_revert_options` with default values. Equivalent to * Initializes a `git_revert_options` with default values. Equivalent to
...@@ -66,7 +66,7 @@ int git_revert_commit( ...@@ -66,7 +66,7 @@ int git_revert_commit(
git_commit *revert_commit, git_commit *revert_commit,
git_commit *our_commit, git_commit *our_commit,
unsigned int mainline, unsigned int mainline,
const git_merge_tree_opts *merge_tree_opts); const git_merge_options *merge_options);
/** /**
* Reverts the given commit, producing changes in the working directory. * Reverts the given commit, producing changes in the working directory.
......
...@@ -1681,29 +1681,20 @@ static int checkout_write_merge( ...@@ -1681,29 +1681,20 @@ static int checkout_write_merge(
{ {
git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT, git_buf our_label = GIT_BUF_INIT, their_label = GIT_BUF_INIT,
path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT; path_suffixed = GIT_BUF_INIT, path_workdir = GIT_BUF_INIT;
git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT; git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT, git_merge_file_result result = {0};
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT;
git_filebuf output = GIT_FILEBUF_INIT; git_filebuf output = GIT_FILEBUF_INIT;
int error = 0; int error = 0;
if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3) if (data->opts.checkout_strategy & GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)
merge_file_opts.style = GIT_MERGE_FILE_STYLE_DIFF3; opts.flags |= GIT_MERGE_FILE_STYLE_DIFF3;
if ((conflict->ancestor &&
(error = git_merge_file_input_from_index_entry(
&ancestor, data->repo, conflict->ancestor)) < 0) ||
(error = git_merge_file_input_from_index_entry(
&ours, data->repo, conflict->ours)) < 0 ||
(error = git_merge_file_input_from_index_entry(
&theirs, data->repo, conflict->theirs)) < 0)
goto done;
ancestor.label = data->opts.ancestor_label ? data->opts.ancestor_label : "ancestor"; opts.ancestor_label = data->opts.ancestor_label ?
ours.label = data->opts.our_label ? data->opts.our_label : "ours"; data->opts.ancestor_label : "ancestor";
theirs.label = data->opts.their_label ? data->opts.their_label : "theirs"; opts.our_label = data->opts.our_label ?
data->opts.our_label : "ours";
opts.their_label = data->opts.their_label ?
data->opts.their_label : "theirs";
/* If all the paths are identical, decorate the diff3 file with the branch /* If all the paths are identical, decorate the diff3 file with the branch
* names. Otherwise, append branch_name:path. * names. Otherwise, append branch_name:path.
...@@ -1712,16 +1703,17 @@ static int checkout_write_merge( ...@@ -1712,16 +1703,17 @@ static int checkout_write_merge(
strcmp(conflict->ours->path, conflict->theirs->path) != 0) { strcmp(conflict->ours->path, conflict->theirs->path) != 0) {
if ((error = conflict_entry_name( if ((error = conflict_entry_name(
&our_label, ours.label, conflict->ours->path)) < 0 || &our_label, opts.our_label, conflict->ours->path)) < 0 ||
(error = conflict_entry_name( (error = conflict_entry_name(
&their_label, theirs.label, conflict->theirs->path)) < 0) &their_label, opts.their_label, conflict->theirs->path)) < 0)
goto done; goto done;
ours.label = git_buf_cstr(&our_label); opts.our_label = git_buf_cstr(&our_label);
theirs.label = git_buf_cstr(&their_label); opts.their_label = git_buf_cstr(&their_label);
} }
if ((error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0) if ((error = git_merge_file_from_index(&result, data->repo,
conflict->ancestor, conflict->ours, conflict->theirs, &opts)) < 0)
goto done; goto done;
if (result.path == NULL || result.mode == 0) { if (result.path == NULL || result.mode == 0) {
...@@ -1739,7 +1731,7 @@ static int checkout_write_merge( ...@@ -1739,7 +1731,7 @@ static int checkout_write_merge(
if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 || if ((error = git_futils_mkpath2file(path_workdir.ptr, 0755)) < 0 ||
(error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 || (error = git_filebuf_open(&output, path_workdir.ptr, GIT_FILEBUF_DO_NOT_BUFFER, result.mode)) < 0 ||
(error = git_filebuf_write(&output, result.data, result.len)) < 0 || (error = git_filebuf_write(&output, result.ptr, result.len)) < 0 ||
(error = git_filebuf_commit(&output)) < 0) (error = git_filebuf_commit(&output)) < 0)
goto done; goto done;
...@@ -1747,9 +1739,6 @@ done: ...@@ -1747,9 +1739,6 @@ done:
git_buf_free(&our_label); git_buf_free(&our_label);
git_buf_free(&their_label); git_buf_free(&their_label);
git_merge_file_input_free(&ancestor);
git_merge_file_input_free(&ours);
git_merge_file_input_free(&theirs);
git_merge_file_result_free(&result); git_merge_file_result_free(&result);
git_buf_free(&path_workdir); git_buf_free(&path_workdir);
git_buf_free(&path_suffixed); git_buf_free(&path_suffixed);
......
...@@ -300,7 +300,7 @@ static void index_entry_free(git_index_entry *entry) ...@@ -300,7 +300,7 @@ static void index_entry_free(git_index_entry *entry)
git__free(entry); git__free(entry);
} }
static unsigned int index_create_mode(unsigned int mode) unsigned int git_index__create_mode(unsigned int mode)
{ {
if (S_ISLNK(mode)) if (S_ISLNK(mode))
return S_IFLNK; return S_IFLNK;
...@@ -320,9 +320,9 @@ static unsigned int index_merge_mode( ...@@ -320,9 +320,9 @@ static unsigned int index_merge_mode(
if (index->distrust_filemode && S_ISREG(mode)) if (index->distrust_filemode && S_ISREG(mode))
return (existing && S_ISREG(existing->mode)) ? return (existing && S_ISREG(existing->mode)) ?
existing->mode : index_create_mode(0666); existing->mode : git_index__create_mode(0666);
return index_create_mode(mode); return git_index__create_mode(mode);
} }
void git_index__set_ignore_case(git_index *index, bool ignore_case) void git_index__set_ignore_case(git_index *index, bool ignore_case)
...@@ -619,7 +619,7 @@ void git_index_entry__init_from_stat( ...@@ -619,7 +619,7 @@ void git_index_entry__init_from_stat(
entry->dev = st->st_rdev; entry->dev = st->st_rdev;
entry->ino = st->st_ino; entry->ino = st->st_ino;
entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ? entry->mode = (!trust_mode && S_ISREG(st->st_mode)) ?
index_create_mode(0666) : index_create_mode(st->st_mode); git_index__create_mode(0666) : git_index__create_mode(st->st_mode);
entry->uid = st->st_uid; entry->uid = st->st_uid;
entry->gid = st->st_gid; entry->gid = st->st_gid;
entry->file_size = st->st_size; entry->file_size = st->st_size;
......
...@@ -60,4 +60,6 @@ extern int git_index__find( ...@@ -60,4 +60,6 @@ extern int git_index__find(
extern void git_index__set_ignore_case(git_index *index, bool ignore_case); extern void git_index__set_ignore_case(git_index *index, bool ignore_case);
extern unsigned int git_index__create_mode(unsigned int mode);
#endif #endif
...@@ -545,11 +545,9 @@ static int merge_conflict_resolve_automerge( ...@@ -545,11 +545,9 @@ static int merge_conflict_resolve_automerge(
const git_merge_diff *conflict, const git_merge_diff *conflict,
unsigned int merge_file_favor) unsigned int merge_file_favor)
{ {
git_merge_file_options merge_file_opts = GIT_MERGE_FILE_OPTIONS_INIT; const git_index_entry *ancestor = NULL, *ours = NULL, *theirs = NULL;
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT, git_merge_file_options opts = GIT_MERGE_FILE_OPTIONS_INIT;
ours = GIT_MERGE_FILE_INPUT_INIT, git_merge_file_result result = {0};
theirs = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_result result = GIT_MERGE_FILE_RESULT_INIT;
git_index_entry *index_entry; git_index_entry *index_entry;
git_odb *odb = NULL; git_odb *odb = NULL;
git_oid automerge_oid; git_oid automerge_oid;
...@@ -559,7 +557,9 @@ static int merge_conflict_resolve_automerge( ...@@ -559,7 +557,9 @@ static int merge_conflict_resolve_automerge(
*resolved = 0; *resolved = 0;
merge_file_opts.favor = merge_file_favor; if (!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ||
!GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry))
return 0;
/* Reject D/F conflicts */ /* Reject D/F conflicts */
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE) if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
...@@ -590,13 +590,19 @@ static int merge_conflict_resolve_automerge( ...@@ -590,13 +590,19 @@ static int merge_conflict_resolve_automerge(
if (conflict->binary) if (conflict->binary)
return 0; return 0;
ancestor = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry) ?
&conflict->ancestor_entry : NULL;
ours = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry) ?
&conflict->our_entry : NULL;
theirs = GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry) ?
&conflict->their_entry : NULL;
opts.favor = merge_file_favor;
if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 || if ((error = git_repository_odb(&odb, diff_list->repo)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ancestor, diff_list->repo, &conflict->ancestor_entry)) < 0 || (error = git_merge_file_from_index(&result, diff_list->repo, ancestor, ours, theirs, &opts)) < 0 ||
(error = git_merge_file_input_from_index_entry(&ours, diff_list->repo, &conflict->our_entry)) < 0 ||
(error = git_merge_file_input_from_index_entry(&theirs, diff_list->repo, &conflict->their_entry)) < 0 ||
(error = git_merge_files(&result, &ancestor, &ours, &theirs, &merge_file_opts)) < 0 ||
!result.automergeable || !result.automergeable ||
(error = git_odb_write(&automerge_oid, odb, result.data, result.len, GIT_OBJ_BLOB)) < 0) (error = git_odb_write(&automerge_oid, odb, result.ptr, result.len, GIT_OBJ_BLOB)) < 0)
goto done; goto done;
if ((index_entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL) if ((index_entry = git_pool_malloc(&diff_list->pool, sizeof(git_index_entry))) == NULL)
...@@ -615,9 +621,6 @@ static int merge_conflict_resolve_automerge( ...@@ -615,9 +621,6 @@ static int merge_conflict_resolve_automerge(
*resolved = 1; *resolved = 1;
done: done:
git_merge_file_input_free(&ancestor);
git_merge_file_input_free(&ours);
git_merge_file_input_free(&theirs);
git_merge_file_result_free(&result); git_merge_file_result_free(&result);
git_odb_free(odb); git_odb_free(odb);
...@@ -667,7 +670,7 @@ static int index_entry_similarity_exact( ...@@ -667,7 +670,7 @@ static int index_entry_similarity_exact(
git_index_entry *b, git_index_entry *b,
size_t b_idx, size_t b_idx,
void **cache, void **cache,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
GIT_UNUSED(repo); GIT_UNUSED(repo);
GIT_UNUSED(a_idx); GIT_UNUSED(a_idx);
...@@ -685,7 +688,7 @@ static int index_entry_similarity_calc( ...@@ -685,7 +688,7 @@ static int index_entry_similarity_calc(
void **out, void **out,
git_repository *repo, git_repository *repo,
git_index_entry *entry, git_index_entry *entry,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
git_blob *blob; git_blob *blob;
git_diff_file diff_file = {{{0}}}; git_diff_file diff_file = {{{0}}};
...@@ -725,7 +728,7 @@ static int index_entry_similarity_inexact( ...@@ -725,7 +728,7 @@ static int index_entry_similarity_inexact(
git_index_entry *b, git_index_entry *b,
size_t b_idx, size_t b_idx,
void **cache, void **cache,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
int score = 0; int score = 0;
int error = 0; int error = 0;
...@@ -762,9 +765,9 @@ static int merge_diff_mark_similarity( ...@@ -762,9 +765,9 @@ static int merge_diff_mark_similarity(
git_merge_diff_list *diff_list, git_merge_diff_list *diff_list,
struct merge_diff_similarity *similarity_ours, struct merge_diff_similarity *similarity_ours,
struct merge_diff_similarity *similarity_theirs, struct merge_diff_similarity *similarity_theirs,
int (*similarity_fn)(git_repository *, git_index_entry *, size_t, git_index_entry *, size_t, void **, const git_merge_tree_opts *), int (*similarity_fn)(git_repository *, git_index_entry *, size_t, git_index_entry *, size_t, void **, const git_merge_options *),
void **cache, void **cache,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
size_t i, j; size_t i, j;
git_merge_diff *conflict_src, *conflict_tgt; git_merge_diff *conflict_src, *conflict_tgt;
...@@ -865,7 +868,7 @@ static void merge_diff_mark_rename_conflict( ...@@ -865,7 +868,7 @@ static void merge_diff_mark_rename_conflict(
bool theirs_renamed, bool theirs_renamed,
size_t theirs_source_idx, size_t theirs_source_idx,
git_merge_diff *target, git_merge_diff *target,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
git_merge_diff *ours_source = NULL, *theirs_source = NULL; git_merge_diff *ours_source = NULL, *theirs_source = NULL;
...@@ -935,7 +938,7 @@ static void merge_diff_list_coalesce_renames( ...@@ -935,7 +938,7 @@ static void merge_diff_list_coalesce_renames(
git_merge_diff_list *diff_list, git_merge_diff_list *diff_list,
struct merge_diff_similarity *similarity_ours, struct merge_diff_similarity *similarity_ours,
struct merge_diff_similarity *similarity_theirs, struct merge_diff_similarity *similarity_theirs,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
size_t i; size_t i;
bool ours_renamed = 0, theirs_renamed = 0; bool ours_renamed = 0, theirs_renamed = 0;
...@@ -1025,7 +1028,7 @@ static void merge_diff_list_count_candidates( ...@@ -1025,7 +1028,7 @@ static void merge_diff_list_count_candidates(
int git_merge_diff_list__find_renames( int git_merge_diff_list__find_renames(
git_repository *repo, git_repository *repo,
git_merge_diff_list *diff_list, git_merge_diff_list *diff_list,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
struct merge_diff_similarity *similarity_ours, *similarity_theirs; struct merge_diff_similarity *similarity_ours, *similarity_theirs;
void **cache = NULL; void **cache = NULL;
...@@ -1453,10 +1456,10 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list) ...@@ -1453,10 +1456,10 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list)
git__free(diff_list); git__free(diff_list);
} }
static int merge_tree_normalize_opts( static int merge_normalize_opts(
git_repository *repo, git_repository *repo,
git_merge_tree_opts *opts, git_merge_options *opts,
const git_merge_tree_opts *given) const git_merge_options *given)
{ {
git_config *cfg = NULL; git_config *cfg = NULL;
int error = 0; int error = 0;
...@@ -1467,9 +1470,9 @@ static int merge_tree_normalize_opts( ...@@ -1467,9 +1470,9 @@ static int merge_tree_normalize_opts(
return error; return error;
if (given != NULL) if (given != NULL)
memcpy(opts, given, sizeof(git_merge_tree_opts)); memcpy(opts, given, sizeof(git_merge_options));
else { else {
git_merge_tree_opts init = GIT_MERGE_TREE_OPTS_INIT; git_merge_options init = GIT_MERGE_OPTIONS_INIT;
memcpy(opts, &init, sizeof(init)); memcpy(opts, &init, sizeof(init));
opts->flags = GIT_MERGE_TREE_FIND_RENAMES; opts->flags = GIT_MERGE_TREE_FIND_RENAMES;
...@@ -1637,10 +1640,10 @@ int git_merge_trees( ...@@ -1637,10 +1640,10 @@ int git_merge_trees(
const git_tree *ancestor_tree, const git_tree *ancestor_tree,
const git_tree *our_tree, const git_tree *our_tree,
const git_tree *their_tree, const git_tree *their_tree,
const git_merge_tree_opts *given_opts) const git_merge_options *given_opts)
{ {
git_merge_diff_list *diff_list; git_merge_diff_list *diff_list;
git_merge_tree_opts opts; git_merge_options opts;
git_merge_diff *conflict; git_merge_diff *conflict;
git_vector changes; git_vector changes;
size_t i; size_t i;
...@@ -1650,9 +1653,9 @@ int git_merge_trees( ...@@ -1650,9 +1653,9 @@ int git_merge_trees(
*out = NULL; *out = NULL;
GITERR_CHECK_VERSION(given_opts, GIT_MERGE_TREE_OPTS_VERSION, "git_merge_tree_opts"); GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTIONS_VERSION, "git_merge_options");
if ((error = merge_tree_normalize_opts(repo, &opts, given_opts)) < 0) if ((error = merge_normalize_opts(repo, &opts, given_opts)) < 0)
return error; return error;
diff_list = git_merge_diff_list__alloc(repo); diff_list = git_merge_diff_list__alloc(repo);
...@@ -1691,7 +1694,7 @@ int git_merge_commits( ...@@ -1691,7 +1694,7 @@ int git_merge_commits(
git_repository *repo, git_repository *repo,
const git_commit *our_commit, const git_commit *our_commit,
const git_commit *their_commit, const git_commit *their_commit,
const git_merge_tree_opts *opts) const git_merge_options *opts)
{ {
git_oid ancestor_oid; git_oid ancestor_oid;
git_commit *ancestor_commit = NULL; git_commit *ancestor_commit = NULL;
...@@ -1777,31 +1780,20 @@ cleanup: ...@@ -1777,31 +1780,20 @@ cleanup:
return error; return error;
} }
static int write_merge_mode(git_repository *repo, unsigned int flags) static int write_merge_mode(git_repository *repo)
{ {
git_filebuf file = GIT_FILEBUF_INIT; git_filebuf file = GIT_FILEBUF_INIT;
git_buf file_path = GIT_BUF_INIT; git_buf file_path = GIT_BUF_INIT;
int error = 0; int error = 0;
/* For future expansion */
GIT_UNUSED(flags);
assert(repo); assert(repo);
if ((error = git_buf_joinpath(&file_path, repo->path_repository, GIT_MERGE_MODE_FILE)) < 0 || 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, GIT_MERGE_FILE_MODE)) < 0) (error = git_filebuf_open(&file, file_path.ptr, GIT_FILEBUF_FORCE, GIT_MERGE_FILE_MODE)) < 0)
goto cleanup; goto cleanup;
/* if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0)
* no-ff is the only thing allowed here at present. One would goto cleanup;
* presume they would be space-delimited when there are more, but
* this needs to be revisited.
*/
if (flags & GIT_MERGE_NO_FASTFORWARD) {
if ((error = git_filebuf_write(&file, "no-ff", 5)) < 0)
goto cleanup;
}
error = git_filebuf_commit(&file); error = git_filebuf_commit(&file);
...@@ -2117,6 +2109,25 @@ cleanup: ...@@ -2117,6 +2109,25 @@ cleanup:
return error; return error;
} }
int git_merge__setup(
git_repository *repo,
const git_merge_head *our_head,
const git_merge_head *heads[],
size_t heads_len)
{
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)) == 0) {
error = write_merge_msg(repo, heads, heads_len);
}
return error;
}
/* Merge branches */ /* Merge branches */
static int merge_ancestor_head( static int merge_ancestor_head(
...@@ -2150,37 +2161,6 @@ on_error: ...@@ -2150,37 +2161,6 @@ on_error:
return error; return error;
} }
GIT_INLINE(bool) merge_check_uptodate(
git_merge_result *result,
const git_merge_head *ancestor_head,
const git_merge_head *their_head)
{
if (git_oid_cmp(&ancestor_head->oid, &their_head->oid) == 0) {
result->is_uptodate = 1;
return true;
}
return false;
}
GIT_INLINE(bool) merge_check_fastforward(
git_merge_result *result,
const git_merge_head *ancestor_head,
const git_merge_head *our_head,
const git_merge_head *their_head,
unsigned int flags)
{
if ((flags & GIT_MERGE_NO_FASTFORWARD) == 0 &&
git_oid_cmp(&ancestor_head->oid, &our_head->oid) == 0) {
result->is_fastforward = 1;
git_oid_cpy(&result->fastforward_oid, &their_head->oid);
return true;
}
return false;
}
const char *merge_their_label(const char *branchname) const char *merge_their_label(const char *branchname)
{ {
const char *slash; const char *slash;
...@@ -2194,10 +2174,10 @@ const char *merge_their_label(const char *branchname) ...@@ -2194,10 +2174,10 @@ const char *merge_their_label(const char *branchname)
return slash+1; return slash+1;
} }
static int merge_normalize_opts( static int merge_normalize_checkout_opts(
git_repository *repo, git_repository *repo,
git_merge_opts *opts, git_checkout_options *checkout_opts,
const git_merge_opts *given, const git_checkout_options *given_checkout_opts,
const git_merge_head *ancestor_head, const git_merge_head *ancestor_head,
const git_merge_head *our_head, const git_merge_head *our_head,
size_t their_heads_len, size_t their_heads_len,
...@@ -2209,38 +2189,38 @@ static int merge_normalize_opts( ...@@ -2209,38 +2189,38 @@ static int merge_normalize_opts(
GIT_UNUSED(repo); GIT_UNUSED(repo);
if (given != NULL) if (given_checkout_opts != NULL)
memcpy(opts, given, sizeof(git_merge_opts)); memcpy(checkout_opts, given_checkout_opts, sizeof(git_checkout_options));
else { else {
git_merge_opts default_opts = GIT_MERGE_OPTS_INIT; git_checkout_options default_checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
memcpy(opts, &default_opts, sizeof(git_merge_opts)); memcpy(checkout_opts, &default_checkout_opts, sizeof(git_checkout_options));
} }
if (!opts->checkout_opts.checkout_strategy) if (!checkout_opts->checkout_strategy)
opts->checkout_opts.checkout_strategy = default_checkout_strategy; checkout_opts->checkout_strategy = default_checkout_strategy;
/* TODO: for multiple ancestors in merge-recursive, this is "merged common ancestors" */ /* TODO: for multiple ancestors in merge-recursive, this is "merged common ancestors" */
if (!opts->checkout_opts.ancestor_label) { if (!checkout_opts->ancestor_label) {
if (ancestor_head && ancestor_head->commit) if (ancestor_head && ancestor_head->commit)
opts->checkout_opts.ancestor_label = git_commit_summary(ancestor_head->commit); checkout_opts->ancestor_label = git_commit_summary(ancestor_head->commit);
else else
opts->checkout_opts.ancestor_label = "ancestor"; checkout_opts->ancestor_label = "ancestor";
} }
if (!opts->checkout_opts.our_label) { if (!checkout_opts->our_label) {
if (our_head && our_head->ref_name) if (our_head && our_head->ref_name)
opts->checkout_opts.our_label = our_head->ref_name; checkout_opts->our_label = our_head->ref_name;
else else
opts->checkout_opts.our_label = "ours"; checkout_opts->our_label = "ours";
} }
if (!opts->checkout_opts.their_label) { if (!checkout_opts->their_label) {
if (their_heads_len == 1 && their_heads[0]->ref_name) if (their_heads_len == 1 && their_heads[0]->ref_name)
opts->checkout_opts.their_label = merge_their_label(their_heads[0]->ref_name); checkout_opts->their_label = merge_their_label(their_heads[0]->ref_name);
else if (their_heads_len == 1) else if (their_heads_len == 1)
opts->checkout_opts.their_label = their_heads[0]->oid_str; checkout_opts->their_label = their_heads[0]->oid_str;
else else
opts->checkout_opts.their_label = "theirs"; checkout_opts->their_label = "theirs";
} }
return error; return error;
...@@ -2500,71 +2480,128 @@ static int merge_state_cleanup(git_repository *repo) ...@@ -2500,71 +2480,128 @@ static int merge_state_cleanup(git_repository *repo)
return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files)); return git_repository__cleanup_files(repo, state_files, ARRAY_SIZE(state_files));
} }
int git_merge( static int merge_heads(
git_merge_result **out, git_merge_head **ancestor_head_out,
git_merge_head **our_head_out,
git_repository *repo, git_repository *repo,
const git_merge_head **their_heads, const git_merge_head **their_heads,
size_t their_heads_len, size_t their_heads_len)
const git_merge_opts *given_opts)
{ {
git_merge_result *result; git_merge_head *ancestor_head = NULL, *our_head = NULL;
git_merge_opts opts;
git_reference *our_ref = NULL; git_reference *our_ref = NULL;
int error = 0;
*ancestor_head_out = NULL;
*our_head_out = NULL;
if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0)
goto done;
if ((error = git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)) < 0 ||
(error = git_merge_head_from_ref(&our_head, repo, our_ref)) < 0)
goto done;
if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0) {
if (error != GIT_ENOTFOUND)
goto done;
giterr_clear();
error = 0;
}
*ancestor_head_out = ancestor_head;
*our_head_out = our_head;
done:
if (error < 0) {
git_merge_head_free(ancestor_head);
git_merge_head_free(our_head);
}
git_reference_free(our_ref);
return error;
}
int git_merge_analysis(
git_merge_analysis_t *out,
git_repository *repo,
const git_merge_head **their_heads,
size_t their_heads_len)
{
git_merge_head *ancestor_head = NULL, *our_head = NULL; git_merge_head *ancestor_head = NULL, *our_head = NULL;
git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL;
git_index *index_new = NULL, *index_repo = NULL;
size_t i;
int error = 0; int error = 0;
assert(out && repo && their_heads); assert(out && repo && their_heads);
*out = NULL; *out = GIT_MERGE_ANALYSIS_NONE;
GITERR_CHECK_VERSION(given_opts, GIT_MERGE_OPTS_VERSION, "git_merge_opts"); if (git_repository_head_unborn(repo)) {
*out = GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_UNBORN;
goto done;
}
if (their_heads_len != 1) { if (their_heads_len != 1) {
giterr_set(GITERR_MERGE, "Can only merge a single branch"); giterr_set(GITERR_MERGE, "Can only merge a single branch");
return -1; error = -1;
goto done;
} }
result = git__calloc(1, sizeof(git_merge_result)); if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0)
GITERR_CHECK_ALLOC(result); goto done;
their_trees = git__calloc(their_heads_len, sizeof(git_tree *)); /* We're up-to-date if we're trying to merge our own common ancestor. */
GITERR_CHECK_ALLOC(their_trees); if (ancestor_head && git_oid_equal(&ancestor_head->oid, &their_heads[0]->oid))
*out = GIT_MERGE_ANALYSIS_UP_TO_DATE;
if ((error = git_repository__ensure_not_bare(repo, "merge")) < 0) /* We're fastforwardable if we're our own common ancestor. */
goto on_error; else if (ancestor_head && git_oid_equal(&ancestor_head->oid, &our_head->oid))
*out = GIT_MERGE_ANALYSIS_FASTFORWARD | GIT_MERGE_ANALYSIS_NORMAL;
if ((error = git_reference_lookup(&our_ref, repo, GIT_HEAD_FILE)) < 0 || /* Otherwise, just a normal merge is possible. */
(error = git_merge_head_from_ref(&our_head, repo, our_ref)) < 0) else
goto on_error; *out = GIT_MERGE_ANALYSIS_NORMAL;
if ((error = merge_ancestor_head(&ancestor_head, repo, our_head, their_heads, their_heads_len)) < 0 && done:
error != GIT_ENOTFOUND) git_merge_head_free(ancestor_head);
goto on_error; git_merge_head_free(our_head);
return error;
}
if ((error = merge_normalize_opts(repo, &opts, given_opts, ancestor_head, our_head, their_heads_len, their_heads)) < 0) int git_merge(
goto on_error; git_repository *repo,
const git_merge_head **their_heads,
size_t their_heads_len,
const git_merge_options *merge_opts,
const git_checkout_options *given_checkout_opts)
{
git_reference *our_ref = NULL;
git_checkout_options checkout_opts;
git_merge_head *ancestor_head = NULL, *our_head = NULL;
git_tree *ancestor_tree = NULL, *our_tree = NULL, **their_trees = NULL;
git_index *index_new = NULL, *index_repo = NULL;
size_t i;
int error = 0;
if (their_heads_len == 1 && assert(repo && their_heads);
ancestor_head != NULL &&
(merge_check_uptodate(result, ancestor_head, their_heads[0]) || if (their_heads_len != 1) {
merge_check_fastforward(result, ancestor_head, our_head, their_heads[0], opts.merge_flags))) { giterr_set(GITERR_MERGE, "Can only merge a single branch");
*out = result; return -1;
goto done;
} }
/* If FASTFORWARD_ONLY is specified, fail. */ their_trees = git__calloc(their_heads_len, sizeof(git_tree *));
if ((opts.merge_flags & GIT_MERGE_FASTFORWARD_ONLY) == GITERR_CHECK_ALLOC(their_trees);
GIT_MERGE_FASTFORWARD_ONLY) {
giterr_set(GITERR_MERGE, "Not a fast-forward."); if ((error = merge_heads(&ancestor_head, &our_head, repo, their_heads, their_heads_len)) < 0)
error = GIT_ENONFASTFORWARD; goto on_error;
if ((error = merge_normalize_checkout_opts(repo, &checkout_opts, given_checkout_opts,
ancestor_head, our_head, their_heads_len, their_heads)) < 0)
goto on_error; goto on_error;
}
/* Write the merge files to the repository. */ /* Write the merge files to the repository. */
if ((error = git_merge__setup(repo, our_head, their_heads, their_heads_len, opts.merge_flags)) < 0) if ((error = git_merge__setup(repo, our_head, their_heads, their_heads_len)) < 0)
goto on_error; goto on_error;
if (ancestor_head != NULL && if (ancestor_head != NULL &&
...@@ -2581,22 +2618,18 @@ int git_merge( ...@@ -2581,22 +2618,18 @@ int git_merge(
/* TODO: recursive, octopus, etc... */ /* TODO: recursive, octopus, etc... */
if ((error = git_merge_trees(&index_new, repo, ancestor_tree, our_tree, their_trees[0], &opts.merge_tree_opts)) < 0 || if ((error = git_merge_trees(&index_new, repo, ancestor_tree, our_tree, their_trees[0], merge_opts)) < 0 ||
(error = git_merge__indexes(repo, index_new)) < 0 || (error = git_merge__indexes(repo, index_new)) < 0 ||
(error = git_repository_index(&index_repo, repo)) < 0 || (error = git_repository_index(&index_repo, repo)) < 0 ||
(error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0) (error = git_checkout_index(repo, index_repo, &checkout_opts)) < 0)
goto on_error; goto on_error;
result->index = index_new;
*out = result;
goto done; goto done;
on_error: on_error:
merge_state_cleanup(repo); merge_state_cleanup(repo);
git_index_free(index_new); git_index_free(index_new);
git__free(result);
done: done:
git_index_free(index_repo); git_index_free(index_repo);
...@@ -2617,61 +2650,6 @@ done: ...@@ -2617,61 +2650,6 @@ done:
return error; 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;
}
/* Merge result data */
int git_merge_result_is_uptodate(git_merge_result *merge_result)
{
assert(merge_result);
return merge_result->is_uptodate;
}
int git_merge_result_is_fastforward(git_merge_result *merge_result)
{
assert(merge_result);
return merge_result->is_fastforward;
}
int git_merge_result_fastforward_id(git_oid *out, git_merge_result *merge_result)
{
assert(out && merge_result);
git_oid_cpy(out, &merge_result->fastforward_oid);
return 0;
}
void git_merge_result_free(git_merge_result *merge_result)
{
if (merge_result == NULL)
return;
git_index_free(merge_result->index);
merge_result->index = NULL;
git__free(merge_result);
}
/* Merge heads are the input to merge */ /* Merge heads are the input to merge */
static int merge_head_init( static int merge_head_init(
...@@ -2776,25 +2754,37 @@ void git_merge_head_free(git_merge_head *head) ...@@ -2776,25 +2754,37 @@ void git_merge_head_free(git_merge_head *head)
git__free(head); git__free(head);
} }
int git_merge_init_opts(git_merge_opts* opts, int version) int git_merge_init_options(git_merge_options *opts, int version)
{ {
if (version != GIT_MERGE_OPTS_VERSION) { if (version != GIT_MERGE_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_opts", version); giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_options", version);
return -1; return -1;
} else { } else {
git_merge_opts o = GIT_MERGE_OPTS_INIT; git_merge_options default_opts = GIT_MERGE_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o)); memcpy(opts, &default_opts, sizeof(git_merge_options));
return 0;
}
}
int git_merge_file_init_input(git_merge_file_input *input, int version)
{
if (version != GIT_MERGE_FILE_INPUT_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_file_input", version);
return -1;
} else {
git_merge_file_input i = GIT_MERGE_FILE_INPUT_INIT;
memcpy(input, &i, sizeof(i));
return 0; return 0;
} }
} }
int git_merge_tree_init_opts(git_merge_tree_opts* opts, int version) int git_merge_file_init_options(git_merge_file_options *opts, int version)
{ {
if (version != GIT_MERGE_TREE_OPTS_VERSION) { if (version != GIT_MERGE_FILE_OPTIONS_VERSION) {
giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_tree_opts", version); giterr_set(GITERR_INVALID, "Invalid version %d for git_merge_file_options", version);
return -1; return -1;
} else { } else {
git_merge_tree_opts o = GIT_MERGE_TREE_OPTS_INIT; git_merge_file_options o = GIT_MERGE_FILE_OPTIONS_INIT;
memcpy(opts, &o, sizeof(o)); memcpy(opts, &o, sizeof(o));
return 0; return 0;
} }
......
...@@ -120,16 +120,6 @@ struct git_merge_head { ...@@ -120,16 +120,6 @@ struct git_merge_head {
git_commit *commit; git_commit *commit;
}; };
/** Internal structure for merge results */
struct git_merge_result {
bool is_uptodate;
bool is_fastforward;
git_oid fastforward_oid;
git_index *index;
};
int git_merge__bases_many( int git_merge__bases_many(
git_commit_list **out, git_commit_list **out,
git_revwalk *walk, git_revwalk *walk,
...@@ -147,7 +137,7 @@ int git_merge_diff_list__find_differences(git_merge_diff_list *merge_diff_list, ...@@ -147,7 +137,7 @@ int git_merge_diff_list__find_differences(git_merge_diff_list *merge_diff_list,
const git_tree *ours_tree, const git_tree *ours_tree,
const git_tree *theirs_tree); const git_tree *theirs_tree);
int git_merge_diff_list__find_renames(git_repository *repo, git_merge_diff_list *merge_diff_list, const git_merge_tree_opts *opts); int git_merge_diff_list__find_renames(git_repository *repo, git_merge_diff_list *merge_diff_list, const git_merge_options *opts);
void git_merge_diff_list__free(git_merge_diff_list *diff_list); void git_merge_diff_list__free(git_merge_diff_list *diff_list);
...@@ -156,9 +146,8 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list); ...@@ -156,9 +146,8 @@ void git_merge_diff_list__free(git_merge_diff_list *diff_list);
int git_merge__setup( int git_merge__setup(
git_repository *repo, git_repository *repo,
const git_merge_head *our_head, const git_merge_head *our_head,
const git_merge_head *their_heads[], const git_merge_head *heads[],
size_t their_heads_len, size_t heads_len);
unsigned int flags);
int git_merge__indexes(git_repository *repo, git_index *index_new); int git_merge__indexes(git_repository *repo, git_index *index_new);
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "common.h" #include "common.h"
#include "repository.h" #include "repository.h"
#include "merge_file.h" #include "merge_file.h"
#include "posix.h"
#include "fileops.h"
#include "index.h"
#include "git2/repository.h" #include "git2/repository.h"
#include "git2/object.h" #include "git2/object.h"
...@@ -22,17 +25,17 @@ GIT_INLINE(const char *) merge_file_best_path( ...@@ -22,17 +25,17 @@ GIT_INLINE(const char *) merge_file_best_path(
const git_merge_file_input *ours, const git_merge_file_input *ours,
const git_merge_file_input *theirs) const git_merge_file_input *theirs)
{ {
if (!GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) { if (!ancestor) {
if (strcmp(ours->path, theirs->path) == 0) if (ours && theirs && strcmp(ours->path, theirs->path) == 0)
return ours->path; return ours->path;
return NULL; return NULL;
} }
if (strcmp(ancestor->path, ours->path) == 0) if (ours && strcmp(ancestor->path, ours->path) == 0)
return theirs->path; return theirs ? theirs->path : NULL;
else if(strcmp(ancestor->path, theirs->path) == 0) else if(theirs && strcmp(ancestor->path, theirs->path) == 0)
return ours->path; return ours ? ours->path : NULL;
return NULL; return NULL;
} }
...@@ -47,136 +50,230 @@ GIT_INLINE(int) merge_file_best_mode( ...@@ -47,136 +50,230 @@ GIT_INLINE(int) merge_file_best_mode(
* assume executable. Otherwise, if any mode changed from the ancestor, * assume executable. Otherwise, if any mode changed from the ancestor,
* use that one. * use that one.
*/ */
if (!GIT_MERGE_FILE_SIDE_EXISTS(ancestor)) { if (!ancestor) {
if (ours->mode == GIT_FILEMODE_BLOB_EXECUTABLE || if ((ours && ours->mode == GIT_FILEMODE_BLOB_EXECUTABLE) ||
theirs->mode == GIT_FILEMODE_BLOB_EXECUTABLE) (theirs && theirs->mode == GIT_FILEMODE_BLOB_EXECUTABLE))
return GIT_FILEMODE_BLOB_EXECUTABLE; return GIT_FILEMODE_BLOB_EXECUTABLE;
return GIT_FILEMODE_BLOB; return GIT_FILEMODE_BLOB;
} } else if (ours && theirs) {
if (ancestor->mode == ours->mode)
return theirs->mode;
if (ancestor->mode == ours->mode)
return theirs->mode;
else if(ancestor->mode == theirs->mode)
return ours->mode; return ours->mode;
}
return 0; return 0;
} }
int git_merge_file_input_from_index_entry( int git_merge_file__input_from_index(
git_merge_file_input *input, git_merge_file_input *input_out,
git_repository *repo, git_odb_object **odb_object_out,
git_odb *odb,
const git_index_entry *entry) const git_index_entry *entry)
{ {
git_odb *odb = NULL;
int error = 0; int error = 0;
assert(input && repo && entry); assert(input_out && odb_object_out && odb && entry);
if (entry->mode == 0)
return 0;
if ((error = git_repository_odb(&odb, repo)) < 0 || if ((error = git_odb_read(odb_object_out, odb, &entry->id)) < 0)
(error = git_odb_read(&input->odb_object, odb, &entry->id)) < 0)
goto done; goto done;
input->mode = entry->mode; input_out->path = entry->path;
input->path = git__strdup(entry->path); input_out->mode = entry->mode;
input->mmfile.size = git_odb_object_size(input->odb_object); input_out->ptr = (char *)git_odb_object_data(*odb_object_out);
input->mmfile.ptr = (char *)git_odb_object_data(input->odb_object); input_out->size = git_odb_object_size(*odb_object_out);
if (input->label == NULL)
input->label = entry->path;
done: done:
git_odb_free(odb);
return error; return error;
} }
int git_merge_file_input_from_diff_file( static void merge_file_normalize_opts(
git_merge_file_input *input, git_merge_file_options *out,
git_repository *repo, const git_merge_file_options *given_opts)
const git_diff_file *file)
{ {
git_odb *odb = NULL; if (given_opts)
int error = 0; memcpy(out, given_opts, sizeof(git_merge_file_options));
else {
assert(input && repo && file); git_merge_file_options default_opts = GIT_MERGE_FILE_OPTIONS_INIT;
memcpy(out, &default_opts, sizeof(git_merge_file_options));
if (file->mode == 0) }
return 0;
if ((error = git_repository_odb(&odb, repo)) < 0 ||
(error = git_odb_read(&input->odb_object, odb, &file->id)) < 0)
goto done;
input->mode = file->mode;
input->path = git__strdup(file->path);
input->mmfile.size = git_odb_object_size(input->odb_object);
input->mmfile.ptr = (char *)git_odb_object_data(input->odb_object);
if (input->label == NULL)
input->label = file->path;
done:
git_odb_free(odb);
return error;
} }
int git_merge_files( static int git_merge_file__from_inputs(
git_merge_file_result *out, git_merge_file_result *out,
git_merge_file_input *ancestor, const git_merge_file_input *ancestor,
git_merge_file_input *ours, const git_merge_file_input *ours,
git_merge_file_input *theirs, const git_merge_file_input *theirs,
git_merge_file_options *opts) const git_merge_file_options *given_opts)
{ {
xmparam_t xmparam; xmparam_t xmparam;
mmfile_t ancestor_mmfile = {0}, our_mmfile = {0}, their_mmfile = {0};
mmbuffer_t mmbuffer; mmbuffer_t mmbuffer;
git_merge_file_options options = GIT_MERGE_FILE_OPTIONS_INIT;
const char *path;
int xdl_result; int xdl_result;
int error = 0; int error = 0;
assert(out && ancestor && ours && theirs);
memset(out, 0x0, sizeof(git_merge_file_result)); memset(out, 0x0, sizeof(git_merge_file_result));
if (!GIT_MERGE_FILE_SIDE_EXISTS(ours) || !GIT_MERGE_FILE_SIDE_EXISTS(theirs)) merge_file_normalize_opts(&options, given_opts);
return 0;
memset(&xmparam, 0x0, sizeof(xmparam_t)); memset(&xmparam, 0x0, sizeof(xmparam_t));
xmparam.ancestor = ancestor->label;
xmparam.file1 = ours->label;
xmparam.file2 = theirs->label;
out->path = merge_file_best_path(ancestor, ours, theirs); if (ancestor) {
out->mode = merge_file_best_mode(ancestor, ours, theirs); xmparam.ancestor = (options.ancestor_label) ?
options.ancestor_label : ancestor->path;
ancestor_mmfile.ptr = (char *)ancestor->ptr;
ancestor_mmfile.size = ancestor->size;
}
if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_OURS) xmparam.file1 = (options.our_label) ?
options.our_label : ours->path;
our_mmfile.ptr = (char *)ours->ptr;
our_mmfile.size = ours->size;
xmparam.file2 = (options.their_label) ?
options.their_label : theirs->path;
their_mmfile.ptr = (char *)theirs->ptr;
their_mmfile.size = theirs->size;
if (options.favor == GIT_MERGE_FILE_FAVOR_OURS)
xmparam.favor = XDL_MERGE_FAVOR_OURS; xmparam.favor = XDL_MERGE_FAVOR_OURS;
else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_THEIRS) else if (options.favor == GIT_MERGE_FILE_FAVOR_THEIRS)
xmparam.favor = XDL_MERGE_FAVOR_THEIRS; xmparam.favor = XDL_MERGE_FAVOR_THEIRS;
else if (opts && opts->favor == GIT_MERGE_FILE_FAVOR_UNION) else if (options.favor == GIT_MERGE_FILE_FAVOR_UNION)
xmparam.favor = XDL_MERGE_FAVOR_UNION; xmparam.favor = XDL_MERGE_FAVOR_UNION;
xmparam.level = xmparam.level = (options.flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM) ?
(opts && (opts->flags & GIT_MERGE_FILE_SIMPLIFY_ALNUM)) ?
XDL_MERGE_ZEALOUS_ALNUM : XDL_MERGE_ZEALOUS; XDL_MERGE_ZEALOUS_ALNUM : XDL_MERGE_ZEALOUS;
if (opts && opts->style == GIT_MERGE_FILE_STYLE_DIFF3) if (options.flags & GIT_MERGE_FILE_STYLE_DIFF3)
xmparam.style = XDL_MERGE_DIFF3; xmparam.style = XDL_MERGE_DIFF3;
if ((xdl_result = xdl_merge(&ancestor->mmfile, &ours->mmfile, if ((xdl_result = xdl_merge(&ancestor_mmfile, &our_mmfile,
&theirs->mmfile, &xmparam, &mmbuffer)) < 0) { &their_mmfile, &xmparam, &mmbuffer)) < 0) {
giterr_set(GITERR_MERGE, "Failed to merge files."); giterr_set(GITERR_MERGE, "Failed to merge files.");
error = -1; error = -1;
goto done; goto done;
} }
if ((path = merge_file_best_path(ancestor, ours, theirs)) != NULL &&
(out->path = strdup(path)) == NULL) {
error = -1;
goto done;
}
out->automergeable = (xdl_result == 0); out->automergeable = (xdl_result == 0);
out->data = (unsigned char *)mmbuffer.ptr; out->ptr = (unsigned char *)mmbuffer.ptr;
out->len = mmbuffer.size; out->len = mmbuffer.size;
out->mode = merge_file_best_mode(ancestor, ours, theirs);
done: done:
if (error < 0)
git_merge_file_result_free(out);
return error; return error;
} }
static git_merge_file_input *git_merge_file__normalize_inputs(
git_merge_file_input *out,
const git_merge_file_input *given)
{
memcpy(out, given, sizeof(git_merge_file_input));
if (!out->path)
out->path = "file.txt";
if (!out->mode)
out->mode = 0100644;
return out;
}
int git_merge_file(
git_merge_file_result *out,
const git_merge_file_input *ancestor,
const git_merge_file_input *ours,
const git_merge_file_input *theirs,
const git_merge_file_options *options)
{
git_merge_file_input inputs[3] = { {0} };
assert(out && ours && theirs);
memset(out, 0x0, sizeof(git_merge_file_result));
if (ancestor)
ancestor = git_merge_file__normalize_inputs(&inputs[0], ancestor);
ours = git_merge_file__normalize_inputs(&inputs[1], ours);
theirs = git_merge_file__normalize_inputs(&inputs[2], theirs);
return git_merge_file__from_inputs(out, ancestor, ours, theirs, options);
}
int git_merge_file_from_index(
git_merge_file_result *out,
git_repository *repo,
const git_index_entry *ancestor,
const git_index_entry *ours,
const git_index_entry *theirs,
const git_merge_file_options *options)
{
git_merge_file_input inputs[3] = { {0} },
*ancestor_input = NULL, *our_input = NULL, *their_input = NULL;
git_odb *odb = NULL;
git_odb_object *odb_object[3] = { 0 };
int error = 0;
assert(out && repo && ours && theirs);
memset(out, 0x0, sizeof(git_merge_file_result));
if ((error = git_repository_odb(&odb, repo)) < 0)
goto done;
if (ancestor) {
if ((error = git_merge_file__input_from_index(
&inputs[0], &odb_object[0], odb, ancestor)) < 0)
goto done;
ancestor_input = &inputs[0];
}
if ((error = git_merge_file__input_from_index(
&inputs[1], &odb_object[1], odb, ours)) < 0)
goto done;
our_input = &inputs[1];
if ((error = git_merge_file__input_from_index(
&inputs[2], &odb_object[2], odb, theirs)) < 0)
goto done;
their_input = &inputs[2];
if ((error = git_merge_file__from_inputs(out,
ancestor_input, our_input, their_input, options)) < 0)
goto done;
done:
git_odb_object_free(odb_object[0]);
git_odb_object_free(odb_object[1]);
git_odb_object_free(odb_object[2]);
git_odb_free(odb);
return error;
}
void git_merge_file_result_free(git_merge_file_result *result)
{
if (result == NULL)
return;
git__free(result->path);
/* xdiff uses malloc() not git_malloc, so we use free(), not git_free() */
free(result->ptr);
}
...@@ -11,82 +11,4 @@ ...@@ -11,82 +11,4 @@
#include "git2/merge.h" #include "git2/merge.h"
typedef struct {
const char *label;
char *path;
unsigned int mode;
mmfile_t mmfile;
git_odb_object *odb_object;
} git_merge_file_input;
#define GIT_MERGE_FILE_INPUT_INIT {0}
typedef struct {
bool automergeable;
const char *path;
int mode;
unsigned char *data;
size_t len;
} git_merge_file_result;
#define GIT_MERGE_FILE_RESULT_INIT {0}
typedef enum {
/* Condense non-alphanumeric regions for simplified diff file */
GIT_MERGE_FILE_SIMPLIFY_ALNUM = (1 << 0),
} git_merge_file_flags_t;
typedef enum {
/* Create standard conflicted merge files */
GIT_MERGE_FILE_STYLE_MERGE = 0,
/* Create diff3-style files */
GIT_MERGE_FILE_STYLE_DIFF3 = 1,
} git_merge_file_style_t;
typedef struct {
git_merge_file_favor_t favor;
git_merge_file_flags_t flags;
git_merge_file_style_t style;
} git_merge_file_options;
#define GIT_MERGE_FILE_OPTIONS_INIT {0}
int git_merge_file_input_from_index_entry(
git_merge_file_input *input,
git_repository *repo,
const git_index_entry *entry);
int git_merge_file_input_from_diff_file(
git_merge_file_input *input,
git_repository *repo,
const git_diff_file *file);
int git_merge_files(
git_merge_file_result *out,
git_merge_file_input *ancestor,
git_merge_file_input *ours,
git_merge_file_input *theirs,
git_merge_file_options *opts);
GIT_INLINE(void) git_merge_file_input_free(git_merge_file_input *input)
{
assert(input);
git__free(input->path);
git_odb_object_free(input->odb_object);
}
GIT_INLINE(void) git_merge_file_result_free(git_merge_file_result *filediff)
{
if (filediff == NULL)
return;
/* xdiff uses malloc() not git_malloc, so we use free(), not git_free() */
if (filediff->data != NULL)
free(filediff->data);
}
#endif #endif
...@@ -121,7 +121,7 @@ int git_revert_commit( ...@@ -121,7 +121,7 @@ int git_revert_commit(
git_commit *revert_commit, git_commit *revert_commit,
git_commit *our_commit, git_commit *our_commit,
unsigned int mainline, unsigned int mainline,
const git_merge_tree_opts *merge_tree_opts) const git_merge_options *merge_opts)
{ {
git_commit *parent_commit = NULL; git_commit *parent_commit = NULL;
git_tree *parent_tree = NULL, *our_tree = NULL, *revert_tree = NULL; git_tree *parent_tree = NULL, *our_tree = NULL, *revert_tree = NULL;
...@@ -152,7 +152,7 @@ int git_revert_commit( ...@@ -152,7 +152,7 @@ int git_revert_commit(
(error = git_commit_tree(&our_tree, our_commit)) < 0) (error = git_commit_tree(&our_tree, our_commit)) < 0)
goto done; goto done;
error = git_merge_trees(out, repo, revert_tree, our_tree, parent_tree, merge_tree_opts); error = git_merge_trees(out, repo, revert_tree, our_tree, parent_tree, merge_opts);
done: done:
git_tree_free(parent_tree); git_tree_free(parent_tree);
...@@ -198,7 +198,7 @@ int git_revert( ...@@ -198,7 +198,7 @@ int git_revert(
(error = write_merge_msg(repo, commit_oidstr, commit_msg)) < 0 || (error = write_merge_msg(repo, commit_oidstr, commit_msg)) < 0 ||
(error = git_repository_head(&our_ref, repo)) < 0 || (error = git_repository_head(&our_ref, repo)) < 0 ||
(error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 || (error = git_reference_peel((git_object **)&our_commit, our_ref, GIT_OBJ_COMMIT)) < 0 ||
(error = git_revert_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_tree_opts)) < 0 || (error = git_revert_commit(&index_new, repo, commit, our_commit, opts.mainline, &opts.merge_opts)) < 0 ||
(error = git_merge__indexes(repo, index_new)) < 0 || (error = git_merge__indexes(repo, index_new)) < 0 ||
(error = git_repository_index(&index_repo, repo)) < 0 || (error = git_repository_index(&index_repo, repo)) < 0 ||
(error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0) (error = git_checkout_index(repo, index_repo, &opts.checkout_opts)) < 0)
......
#include "clar_libgit2.h"
#include "git2/repository.h"
#include "git2/merge.h"
#include "buffer.h"
#include "merge.h"
#include "merge_helpers.h"
#include "refs.h"
#include "fileops.h"
#define TEST_REPO_PATH "merge-resolve"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
static git_repository *repo;
static git_index *repo_index;
// Fixture setup and teardown
void test_merge_files__initialize(void)
{
git_config *cfg;
repo = cl_git_sandbox_init(TEST_REPO_PATH);
git_repository_index(&repo_index, repo);
/* Ensure that the user's merge.conflictstyle doesn't interfere */
cl_git_pass(git_repository_config(&cfg, repo));
cl_git_pass(git_config_set_string(cfg, "merge.conflictstyle", "merge"));
git_config_free(cfg);
}
void test_merge_files__cleanup(void)
{
git_index_free(repo_index);
cl_git_sandbox_cleanup();
}
void test_merge_files__automerge_from_bufs(void)
{
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_result result = {0};
const char *expected = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
ancestor.ptr = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n";
ancestor.size = strlen(ancestor.ptr);
ancestor.path = "testfile.txt";
ancestor.mode = 0100755;
ours.ptr = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n";
ours.size = strlen(ours.ptr);
ours.path = "testfile.txt";
ours.mode = 0100755;
theirs.ptr = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
theirs.size = strlen(theirs.ptr);
theirs.path = "testfile.txt";
theirs.mode = 0100755;
cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, 0));
cl_assert_equal_i(1, result.automergeable);
cl_assert_equal_s("testfile.txt", result.path);
cl_assert_equal_i(0100755, result.mode);
cl_assert_equal_i(strlen(expected), result.len);
cl_assert_equal_strn(expected, result.ptr, result.len);
git_merge_file_result_free(&result);
}
void test_merge_files__automerge_use_best_path_and_mode(void)
{
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_result result = {0};
const char *expected = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
ancestor.ptr = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n";
ancestor.size = strlen(ancestor.ptr);
ancestor.path = "testfile.txt";
ancestor.mode = 0100755;
ours.ptr = "Zero\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n";
ours.size = strlen(ours.ptr);
ours.path = "testfile.txt";
ours.mode = 0100644;
theirs.ptr = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\nTen\n";
theirs.size = strlen(theirs.ptr);
theirs.path = "theirs.txt";
theirs.mode = 0100755;
cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, 0));
cl_assert_equal_i(1, result.automergeable);
cl_assert_equal_s("theirs.txt", result.path);
cl_assert_equal_i(0100644, result.mode);
cl_assert_equal_i(strlen(expected), result.len);
cl_assert_equal_strn(expected, result.ptr, result.len);
git_merge_file_result_free(&result);
}
void test_merge_files__conflict_from_bufs(void)
{
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT,
ours = GIT_MERGE_FILE_INPUT_INIT,
theirs = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_result result = {0};
const char *expected = "<<<<<<< testfile.txt\nAloha!\nOurs.\n=======\nHi!\nTheirs.\n>>>>>>> theirs.txt\n";
size_t expected_len = strlen(expected);
ancestor.ptr = "Hello!\nAncestor!\n";
ancestor.size = strlen(ancestor.ptr);
ancestor.path = "testfile.txt";
ancestor.mode = 0100755;
ours.ptr = "Aloha!\nOurs.\n";
ours.size = strlen(ours.ptr);
ours.path = "testfile.txt";
ours.mode = 0100644;
theirs.ptr = "Hi!\nTheirs.\n";
theirs.size = strlen(theirs.ptr);
theirs.path = "theirs.txt";
theirs.mode = 0100755;
cl_git_pass(git_merge_file(&result, &ancestor, &ours, &theirs, NULL));
cl_assert_equal_i(0, result.automergeable);
cl_assert_equal_s("theirs.txt", result.path);
cl_assert_equal_i(0100644, result.mode);
cl_assert_equal_i(expected_len, result.len);
cl_assert_equal_strn(expected, result.ptr, expected_len);
git_merge_file_result_free(&result);
}
void test_merge_files__automerge_from_index(void)
{
git_merge_file_result result = {0};
git_index_entry ancestor, ours, theirs;
git_oid_fromstr(&ancestor.id, "6212c31dab5e482247d7977e4f0dd3601decf13b");
ancestor.path = "automergeable.txt";
ancestor.mode = 0100644;
git_oid_fromstr(&ours.id, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf");
ours.path = "automergeable.txt";
ours.mode = 0100755;
git_oid_fromstr(&theirs.id, "058541fc37114bfc1dddf6bd6bffc7fae5c2e6fe");
theirs.path = "newname.txt";
theirs.mode = 0100644;
cl_git_pass(git_merge_file_from_index(&result, repo,
&ancestor, &ours, &theirs, 0));
cl_assert_equal_i(1, result.automergeable);
cl_assert_equal_s("newname.txt", result.path);
cl_assert_equal_i(0100755, result.mode);
cl_assert_equal_i(strlen(AUTOMERGEABLE_MERGED_FILE), result.len);
cl_assert_equal_strn(AUTOMERGEABLE_MERGED_FILE, result.ptr, result.len);
git_merge_file_result_free(&result);
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
int merge_trees_from_branches( int merge_trees_from_branches(
git_index **index, git_repository *repo, git_index **index, git_repository *repo,
const char *ours_name, const char *theirs_name, const char *ours_name, const char *theirs_name,
git_merge_tree_opts *opts) git_merge_options *opts)
{ {
git_commit *our_commit, *their_commit, *ancestor_commit = NULL; git_commit *our_commit, *their_commit, *ancestor_commit = NULL;
git_tree *our_tree, *their_tree, *ancestor_tree = NULL; git_tree *our_tree, *their_tree, *ancestor_tree = NULL;
...@@ -55,7 +55,7 @@ int merge_trees_from_branches( ...@@ -55,7 +55,7 @@ int merge_trees_from_branches(
int merge_commits_from_branches( int merge_commits_from_branches(
git_index **index, git_repository *repo, git_index **index, git_repository *repo,
const char *ours_name, const char *theirs_name, const char *ours_name, const char *theirs_name,
git_merge_tree_opts *opts) git_merge_options *opts)
{ {
git_commit *our_commit, *their_commit; git_commit *our_commit, *their_commit;
git_oid our_oid, their_oid; git_oid our_oid, their_oid;
...@@ -79,7 +79,9 @@ int merge_commits_from_branches( ...@@ -79,7 +79,9 @@ int merge_commits_from_branches(
return 0; return 0;
} }
int merge_branches(git_merge_result **result, git_repository *repo, const char *ours_branch, const char *theirs_branch, git_merge_opts *opts) int merge_branches(git_repository *repo,
const char *ours_branch, const char *theirs_branch,
git_merge_options *merge_opts, git_checkout_options *checkout_opts)
{ {
git_reference *head_ref, *theirs_ref; git_reference *head_ref, *theirs_ref;
git_merge_head *theirs_head; git_merge_head *theirs_head;
...@@ -93,7 +95,7 @@ int merge_branches(git_merge_result **result, git_repository *repo, const char * ...@@ -93,7 +95,7 @@ int merge_branches(git_merge_result **result, git_repository *repo, const char *
cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch)); cl_git_pass(git_reference_lookup(&theirs_ref, repo, theirs_branch));
cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref)); cl_git_pass(git_merge_head_from_ref(&theirs_head, repo, theirs_ref));
cl_git_pass(git_merge(result, repo, (const git_merge_head **)&theirs_head, 1, opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)&theirs_head, 1, merge_opts, checkout_opts));
git_reference_free(head_ref); git_reference_free(head_ref);
git_reference_free(theirs_ref); git_reference_free(theirs_ref);
......
...@@ -4,6 +4,49 @@ ...@@ -4,6 +4,49 @@
#include "merge.h" #include "merge.h"
#include "git2/merge.h" #include "git2/merge.h"
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
#define AUTOMERGEABLE_MERGED_FILE_CRLF \
"this file is changed in master\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is changed in branch\r\n"
#define CONFLICTING_MERGE_FILE \
"<<<<<<< HEAD\n" \
"this file is changed in master and branch\n" \
"=======\n" \
"this file is changed in branch and master\n" \
">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
#define CONFLICTING_DIFF3_FILE \
"<<<<<<< HEAD\n" \
"this file is changed in master and branch\n" \
"||||||| initial\n" \
"this file is a conflict\n" \
"=======\n" \
"this file is changed in branch and master\n" \
">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
#define CONFLICTING_UNION_FILE \
"this file is changed in master and branch\n" \
"this file is changed in branch and master\n"
struct merge_index_entry { struct merge_index_entry {
uint16_t mode; uint16_t mode;
char oid_str[41]; char oid_str[41];
...@@ -42,15 +85,16 @@ struct merge_index_conflict_data { ...@@ -42,15 +85,16 @@ struct merge_index_conflict_data {
int merge_trees_from_branches( int merge_trees_from_branches(
git_index **index, git_repository *repo, git_index **index, git_repository *repo,
const char *ours_name, const char *theirs_name, const char *ours_name, const char *theirs_name,
git_merge_tree_opts *opts); git_merge_options *opts);
int merge_commits_from_branches( int merge_commits_from_branches(
git_index **index, git_repository *repo, git_index **index, git_repository *repo,
const char *ours_name, const char *theirs_name, const char *ours_name, const char *theirs_name,
git_merge_tree_opts *opts); git_merge_options *opts);
int merge_branches(git_merge_result **result, git_repository *repo, int merge_branches(git_repository *repo,
const char *ours_branch, const char *theirs_branch, git_merge_opts *opts); const char *ours_branch, const char *theirs_branch,
git_merge_options *merge_opts, git_checkout_options *checkout_opts);
int merge_test_diff_list(git_merge_diff_list *diff_list, const struct merge_index_entry expected[], size_t expected_len); int merge_test_diff_list(git_merge_diff_list *diff_list, const struct merge_index_entry expected[], size_t expected_len);
......
...@@ -54,28 +54,6 @@ static git_repository *repo; ...@@ -54,28 +54,6 @@ static git_repository *repo;
"", \ "", \
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" }
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
#define AUTOMERGEABLE_MERGED_FILE_CRLF \
"this file is changed in master\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is changed in branch\r\n"
// Fixture setup and teardown // Fixture setup and teardown
void test_merge_trees_automerge__initialize(void) void test_merge_trees_automerge__initialize(void)
{ {
...@@ -91,7 +69,7 @@ void test_merge_trees_automerge__automerge(void) ...@@ -91,7 +69,7 @@ void test_merge_trees_automerge__automerge(void)
{ {
git_index *index; git_index *index;
const git_index_entry *entry; const git_index_entry *entry;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
git_blob *blob; git_blob *blob;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -131,7 +109,7 @@ void test_merge_trees_automerge__automerge(void) ...@@ -131,7 +109,7 @@ void test_merge_trees_automerge__automerge(void)
void test_merge_trees_automerge__favor_ours(void) void test_merge_trees_automerge__favor_ours(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
ADDED_IN_MASTER_INDEX_ENTRY, ADDED_IN_MASTER_INDEX_ENTRY,
...@@ -162,7 +140,7 @@ void test_merge_trees_automerge__favor_ours(void) ...@@ -162,7 +140,7 @@ void test_merge_trees_automerge__favor_ours(void)
void test_merge_trees_automerge__favor_theirs(void) void test_merge_trees_automerge__favor_theirs(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
ADDED_IN_MASTER_INDEX_ENTRY, ADDED_IN_MASTER_INDEX_ENTRY,
...@@ -193,7 +171,7 @@ void test_merge_trees_automerge__favor_theirs(void) ...@@ -193,7 +171,7 @@ void test_merge_trees_automerge__favor_theirs(void)
void test_merge_trees_automerge__unrelated(void) void test_merge_trees_automerge__unrelated(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" },
......
...@@ -8,17 +8,6 @@ static git_repository *repo; ...@@ -8,17 +8,6 @@ static git_repository *repo;
#define TEST_REPO_PATH "merge-resolve" #define TEST_REPO_PATH "merge-resolve"
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
void test_merge_trees_commits__initialize(void) void test_merge_trees_commits__initialize(void)
{ {
repo = cl_git_sandbox_init(TEST_REPO_PATH); repo = cl_git_sandbox_init(TEST_REPO_PATH);
...@@ -33,7 +22,7 @@ void test_merge_trees_commits__automerge(void) ...@@ -33,7 +22,7 @@ void test_merge_trees_commits__automerge(void)
{ {
git_index *index; git_index *index;
const git_index_entry *entry; const git_index_entry *entry;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
git_blob *blob; git_blob *blob;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -82,7 +71,7 @@ void test_merge_trees_commits__automerge(void) ...@@ -82,7 +71,7 @@ void test_merge_trees_commits__automerge(void)
void test_merge_trees_commits__no_ancestor(void) void test_merge_trees_commits__no_ancestor(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" },
...@@ -109,7 +98,7 @@ void test_merge_trees_commits__no_ancestor(void) ...@@ -109,7 +98,7 @@ void test_merge_trees_commits__no_ancestor(void)
void test_merge_trees_commits__df_conflict(void) void test_merge_trees_commits__df_conflict(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" }, { 0100644, "49130a28ef567af9a6a6104c38773fedfa5f9742", 2, "dir-10" },
......
...@@ -27,7 +27,7 @@ void test_merge_trees_renames__cleanup(void) ...@@ -27,7 +27,7 @@ void test_merge_trees_renames__cleanup(void)
void test_merge_trees_renames__index(void) void test_merge_trees_renames__index(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts *opts = NULL; git_merge_options *opts = NULL;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
...@@ -205,7 +205,7 @@ void test_merge_trees_renames__index(void) ...@@ -205,7 +205,7 @@ void test_merge_trees_renames__index(void)
void test_merge_trees_renames__no_rename_index(void) void test_merge_trees_renames__no_rename_index(void)
{ {
git_index *index; git_index *index;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
......
...@@ -44,7 +44,7 @@ static void test_find_differences( ...@@ -44,7 +44,7 @@ static void test_find_differences(
git_oid ancestor_oid, ours_oid, theirs_oid; git_oid ancestor_oid, ours_oid, theirs_oid;
git_tree *ancestor_tree, *ours_tree, *theirs_tree; git_tree *ancestor_tree, *ours_tree, *theirs_tree;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.target_limit = 1000; opts.target_limit = 1000;
opts.rename_threshold = 50; opts.rename_threshold = 50;
......
...@@ -31,7 +31,7 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs ...@@ -31,7 +31,7 @@ static int merge_trivial(git_index **index, const char *ours, const char *theirs
git_tree *our_tree, *their_tree, *ancestor_tree; git_tree *our_tree, *their_tree, *ancestor_tree;
git_oid our_oid, their_oid, ancestor_oid; git_oid our_oid, their_oid, ancestor_oid;
git_buf branch_buf = GIT_BUF_INIT; git_buf branch_buf = GIT_BUF_INIT;
git_merge_tree_opts opts = GIT_MERGE_TREE_OPTS_INIT; git_merge_options opts = GIT_MERGE_OPTIONS_INIT;
git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours);
cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr));
......
#include "clar_libgit2.h"
#include "git2/repository.h"
#include "git2/merge.h"
#include "git2/sys/index.h"
#include "merge.h"
#include "../merge_helpers.h"
#include "refs.h"
#include "posix.h"
static git_repository *repo;
static git_index *repo_index;
#define TEST_REPO_PATH "merge-resolve"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
#define UPTODATE_BRANCH "master"
#define PREVIOUS_BRANCH "previous"
#define FASTFORWARD_BRANCH "ff_branch"
#define FASTFORWARD_ID "fd89f8cffb663ac89095a0f9764902e93ceaca6a"
#define NOFASTFORWARD_BRANCH "branch"
#define NOFASTFORWARD_ID "7cb63eed597130ba4abb87b3e544b85021905520"
// Fixture setup and teardown
void test_merge_workdir_analysis__initialize(void)
{
repo = cl_git_sandbox_init(TEST_REPO_PATH);
git_repository_index(&repo_index, repo);
}
void test_merge_workdir_analysis__cleanup(void)
{
git_index_free(repo_index);
cl_git_sandbox_cleanup();
}
static git_merge_analysis_t analysis_from_branch(const char *branchname)
{
git_buf refname = GIT_BUF_INIT;
git_reference *their_ref;
git_merge_head *their_head;
git_merge_analysis_t analysis;
git_buf_printf(&refname, "%s%s", GIT_REFS_HEADS_DIR, branchname);
cl_git_pass(git_reference_lookup(&their_ref, repo, git_buf_cstr(&refname)));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
cl_git_pass(git_merge_analysis(&analysis, repo, (const git_merge_head **)&their_head, 1));
git_buf_free(&refname);
git_merge_head_free(their_head);
git_reference_free(their_ref);
return analysis;
}
void test_merge_workdir_analysis__fastforward(void)
{
git_merge_analysis_t analysis;
analysis = analysis_from_branch(FASTFORWARD_BRANCH);
cl_assert_equal_i(GIT_MERGE_ANALYSIS_FASTFORWARD, (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD));
cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, (analysis & GIT_MERGE_ANALYSIS_NORMAL));
}
void test_merge_workdir_analysis__no_fastforward(void)
{
git_merge_analysis_t analysis;
analysis = analysis_from_branch(NOFASTFORWARD_BRANCH);
cl_assert_equal_i(GIT_MERGE_ANALYSIS_NORMAL, analysis);
}
void test_merge_workdir_analysis__uptodate(void)
{
git_merge_analysis_t analysis;
analysis = analysis_from_branch(UPTODATE_BRANCH);
cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, analysis);
}
void test_merge_workdir_analysis__uptodate_merging_prev_commit(void)
{
git_merge_analysis_t analysis;
analysis = analysis_from_branch(PREVIOUS_BRANCH);
cl_assert_equal_i(GIT_MERGE_ANALYSIS_UP_TO_DATE, analysis);
}
void test_merge_workdir_analysis__unborn(void)
{
git_merge_analysis_t analysis;
git_buf master = GIT_BUF_INIT;
git_buf_joinpath(&master, git_repository_path(repo), "refs/heads/master");
p_unlink(git_buf_cstr(&master));
analysis = analysis_from_branch(NOFASTFORWARD_BRANCH);
cl_assert_equal_i(GIT_MERGE_ANALYSIS_FASTFORWARD, (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD));
cl_assert_equal_i(GIT_MERGE_ANALYSIS_UNBORN, (analysis & GIT_MERGE_ANALYSIS_UNBORN));
git_buf_free(&master);
}
...@@ -86,19 +86,20 @@ static void set_core_autocrlf_to(git_repository *repo, bool value) ...@@ -86,19 +86,20 @@ static void set_core_autocrlf_to(git_repository *repo, bool value)
git_config_free(cfg); git_config_free(cfg);
} }
static int merge_branch(git_merge_result **result, int merge_file_favor, int checkout_strategy) static int merge_branch(int merge_file_favor, int checkout_strategy)
{ {
git_oid their_oids[1]; git_oid their_oids[1];
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_opts opts = GIT_MERGE_OPTS_INIT; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
int error; int error;
cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID)); cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = merge_file_favor; merge_opts.file_favor = merge_file_favor;
opts.checkout_opts.checkout_strategy = checkout_strategy; checkout_opts.checkout_strategy = checkout_strategy;
error = git_merge(result, repo, (const git_merge_head **)their_heads, 1, &opts); error = git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
...@@ -176,7 +177,6 @@ static void stage_content(char *content[]) ...@@ -176,7 +177,6 @@ static void stage_content(char *content[])
{ {
git_reference *head; git_reference *head;
git_object *head_object; git_object *head_object;
git_merge_result *result = NULL;
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
char *filename, *text; char *filename, *text;
size_t i; size_t i;
...@@ -197,7 +197,6 @@ static void stage_content(char *content[]) ...@@ -197,7 +197,6 @@ static void stage_content(char *content[])
cl_git_pass(git_index_add_bypath(repo_index, filename)); cl_git_pass(git_index_add_bypath(repo_index, filename));
} }
git_merge_result_free(result);
git_object_free(head_object); git_object_free(head_object);
git_reference_free(head); git_reference_free(head);
git_buf_free(&path); git_buf_free(&path);
...@@ -207,7 +206,6 @@ static int merge_dirty_files(char *dirty_files[]) ...@@ -207,7 +206,6 @@ static int merge_dirty_files(char *dirty_files[])
{ {
git_reference *head; git_reference *head;
git_object *head_object; git_object *head_object;
git_merge_result *result = NULL;
int error; int error;
cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_repository_head(&head, repo));
...@@ -216,9 +214,8 @@ static int merge_dirty_files(char *dirty_files[]) ...@@ -216,9 +214,8 @@ static int merge_dirty_files(char *dirty_files[])
write_files(dirty_files); write_files(dirty_files);
error = merge_branch(&result, 0, 0); error = merge_branch(0, 0);
git_merge_result_free(result);
git_object_free(head_object); git_object_free(head_object);
git_reference_free(head); git_reference_free(head);
...@@ -229,7 +226,6 @@ static int merge_differently_filtered_files(char *files[]) ...@@ -229,7 +226,6 @@ static int merge_differently_filtered_files(char *files[])
{ {
git_reference *head; git_reference *head;
git_object *head_object; git_object *head_object;
git_merge_result *result = NULL;
int error; int error;
cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_repository_head(&head, repo));
...@@ -241,9 +237,8 @@ static int merge_differently_filtered_files(char *files[]) ...@@ -241,9 +237,8 @@ static int merge_differently_filtered_files(char *files[])
cl_git_pass(git_index_write(repo_index)); cl_git_pass(git_index_write(repo_index));
error = merge_branch(&result, 0, 0); error = merge_branch(0, 0);
git_merge_result_free(result);
git_object_free(head_object); git_object_free(head_object);
git_reference_free(head); git_reference_free(head);
...@@ -251,17 +246,9 @@ static int merge_differently_filtered_files(char *files[]) ...@@ -251,17 +246,9 @@ static int merge_differently_filtered_files(char *files[])
} }
static int merge_staged_files(char *staged_files[]) static int merge_staged_files(char *staged_files[])
{ {
git_merge_result *result = NULL;
int error;
stage_random_files(staged_files); stage_random_files(staged_files);
return merge_branch(0, 0);
error = merge_branch(&result, 0, 0);
git_merge_result_free(result);
return error;
} }
void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void) void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void)
...@@ -296,7 +283,6 @@ void test_merge_workdir_dirty__staged_files_in_index_disallowed(void) ...@@ -296,7 +283,6 @@ void test_merge_workdir_dirty__staged_files_in_index_disallowed(void)
void test_merge_workdir_dirty__identical_staged_files_allowed(void) void test_merge_workdir_dirty__identical_staged_files_allowed(void)
{ {
git_merge_result *result;
char **content; char **content;
size_t i; size_t i;
...@@ -306,9 +292,7 @@ void test_merge_workdir_dirty__identical_staged_files_allowed(void) ...@@ -306,9 +292,7 @@ void test_merge_workdir_dirty__identical_staged_files_allowed(void)
stage_content(content); stage_content(content);
git_index_write(repo_index); git_index_write(repo_index);
cl_git_pass(merge_branch(&result, 0, 0)); cl_git_pass(merge_branch(0, 0));
git_merge_result_free(result);
} }
} }
......
#include "clar_libgit2.h"
#include "git2/repository.h"
#include "git2/merge.h"
#include "git2/sys/index.h"
#include "merge.h"
#include "../merge_helpers.h"
#include "refs.h"
static git_repository *repo;
static git_index *repo_index;
#define TEST_REPO_PATH "merge-resolve"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
#define THEIRS_FASTFORWARD_BRANCH "ff_branch"
#define THEIRS_FASTFORWARD_ID "fd89f8cffb663ac89095a0f9764902e93ceaca6a"
#define THEIRS_NOFASTFORWARD_BRANCH "branch"
#define THEIRS_NOFASTFORWARD_ID "7cb63eed597130ba4abb87b3e544b85021905520"
// Fixture setup and teardown
void test_merge_workdir_fastforward__initialize(void)
{
repo = cl_git_sandbox_init(TEST_REPO_PATH);
git_repository_index(&repo_index, repo);
}
void test_merge_workdir_fastforward__cleanup(void)
{
git_index_free(repo_index);
cl_git_sandbox_cleanup();
}
static git_merge_result *merge_fastforward_branch(int flags)
{
git_reference *their_ref;
git_merge_head *their_heads[1];
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
opts.merge_flags = flags;
cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_FASTFORWARD_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts));
git_merge_head_free(their_heads[0]);
git_reference_free(their_ref);
return result;
}
void test_merge_workdir_fastforward__fastforward(void)
{
git_merge_result *result;
git_oid expected, ff_oid;
cl_git_pass(git_oid_fromstr(&expected, THEIRS_FASTFORWARD_ID));
cl_assert(result = merge_fastforward_branch(0));
cl_assert(git_merge_result_is_fastforward(result));
cl_git_pass(git_merge_result_fastforward_id(&ff_oid, result));
cl_assert(git_oid_cmp(&ff_oid, &expected) == 0);
git_merge_result_free(result);
}
void test_merge_workdir_fastforward__fastforward_only(void)
{
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
git_reference *their_ref;
git_merge_head *their_head;
int error;
opts.merge_flags = GIT_MERGE_FASTFORWARD_ONLY;
cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_REFS_HEADS_DIR THEIRS_NOFASTFORWARD_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
cl_git_fail((error = git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts)));
cl_assert(error == GIT_ENONFASTFORWARD);
git_merge_head_free(their_head);
git_reference_free(their_ref);
}
void test_merge_workdir_fastforward__no_fastforward(void)
{
git_merge_result *result;
struct merge_index_entry merge_index_entries[] = {
{ 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" },
{ 0100644, "ee3fa1b8c00aff7fe02065fdb50864bb0d932ccf", 0, "automergeable.txt" },
{ 0100644, "ab6c44a2e84492ad4b41bb6bac87353e9d02ac8b", 0, "changed-in-branch.txt" },
{ 0100644, "bd9cb4cd0a770cb9adcb5fce212142ef40ea1c35", 0, "changed-in-master.txt" },
{ 0100644, "4e886e602529caa9ab11d71f86634bd1b6e0de10", 0, "conflicting.txt" },
{ 0100644, "364bbe4ce80c7bd31e6307dce77d46e3e1759fb3", 0, "new-in-ff.txt" },
{ 0100644, "dfe3f22baa1f6fce5447901c3086bae368de6bdd", 0, "removed-in-branch.txt" },
{ 0100644, "c8f06f2e3bb2964174677e91f0abead0e43c9e5d", 0, "unchanged.txt" },
};
cl_assert(result = merge_fastforward_branch(GIT_MERGE_NO_FASTFORWARD));
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(git_index_reuc_entrycount(repo_index) == 0);
git_merge_result_free(result);
}
void test_merge_workdir_fastforward__uptodate(void)
{
git_reference *their_ref;
git_merge_head *their_heads[1];
git_merge_result *result;
cl_git_pass(git_reference_lookup(&their_ref, repo, GIT_HEAD_FILE));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL));
cl_assert(git_merge_result_is_uptodate(result));
git_merge_head_free(their_heads[0]);
git_reference_free(their_ref);
git_merge_result_free(result);
}
void test_merge_workdir_fastforward__uptodate_merging_prev_commit(void)
{
git_oid their_oid;
git_merge_head *their_heads[1];
git_merge_result *result;
cl_git_pass(git_oid_fromstr(&their_oid, "c607fc30883e335def28cd686b51f6cfa02b06ec"));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oid));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, NULL));
cl_assert(git_merge_result_is_uptodate(result));
git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
}
...@@ -34,8 +34,7 @@ void test_merge_workdir_renames__cleanup(void) ...@@ -34,8 +34,7 @@ void test_merge_workdir_renames__cleanup(void)
void test_merge_workdir_renames__renames(void) void test_merge_workdir_renames__renames(void)
{ {
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
...@@ -64,20 +63,18 @@ void test_merge_workdir_renames__renames(void) ...@@ -64,20 +63,18 @@ void test_merge_workdir_renames__renames(void)
{ 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" },
}; };
opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.merge_tree_opts.rename_threshold = 50; merge_opts.rename_threshold = 50;
cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL));
cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); cl_assert(merge_test_workdir(repo, merge_index_entries, 24));
git_merge_result_free(result);
} }
void test_merge_workdir_renames__ours(void) void test_merge_workdir_renames__ours(void)
{ {
git_index *index; git_index *index;
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" }, { 0100644, "68c6c84b091926c7d90aa6a79b2bc3bb6adccd8e", 0, "0a-no-change.txt" },
...@@ -102,23 +99,21 @@ void test_merge_workdir_renames__ours(void) ...@@ -102,23 +99,21 @@ void test_merge_workdir_renames__ours(void)
{ 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" }, { 0100644, "b42712cfe99a1a500b2a51fe984e0b8a7702ba11", 0, "7-both-renamed.txt" },
}; };
opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.merge_tree_opts.rename_threshold = 50; merge_opts.rename_threshold = 50;
opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS;
cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, &checkout_opts));
cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_write(index)); cl_git_pass(git_index_write(index));
cl_assert(merge_test_workdir(repo, merge_index_entries, 20)); cl_assert(merge_test_workdir(repo, merge_index_entries, 20));
git_merge_result_free(result);
git_index_free(index); git_index_free(index);
} }
void test_merge_workdir_renames__similar(void) void test_merge_workdir_renames__similar(void)
{ {
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
/* /*
* Note: this differs slightly from the core git merge result - there, 4a is * Note: this differs slightly from the core git merge result - there, 4a is
...@@ -152,12 +147,10 @@ void test_merge_workdir_renames__similar(void) ...@@ -152,12 +147,10 @@ void test_merge_workdir_renames__similar(void)
{ 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" }, { 0100644, "b69fe837e4cecfd4c9a40cdca7c138468687df07", 0, "7-both-renamed.txt~rename_conflict_theirs" },
}; };
opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.merge_tree_opts.rename_threshold = 50; merge_opts.rename_threshold = 50;
cl_git_pass(merge_branches(&result, repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &opts)); cl_git_pass(merge_branches(repo, GIT_REFS_HEADS_DIR BRANCH_RENAME_OURS, GIT_REFS_HEADS_DIR BRANCH_RENAME_THEIRS, &merge_opts, NULL));
cl_assert(merge_test_workdir(repo, merge_index_entries, 24)); cl_assert(merge_test_workdir(repo, merge_index_entries, 24));
git_merge_result_free(result);
} }
...@@ -71,7 +71,7 @@ static void write_file_contents(const char *filename, const char *output) ...@@ -71,7 +71,7 @@ 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 octo1 */ /* git merge --no-ff octo1 */
void test_merge_workdir_setup__one_branch(void) void test_merge_workdir_setup__one_branch(void)
{ {
git_oid our_oid; git_oid our_oid;
...@@ -84,33 +84,7 @@ void test_merge_workdir_setup__one_branch(void) ...@@ -84,33 +84,7 @@ void test_merge_workdir_setup__one_branch(void)
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1));
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 octo1 */
void test_merge_workdir_setup__no_fastforward(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_id(&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, GIT_MERGE_NO_FASTFORWARD));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
...@@ -118,12 +92,12 @@ void test_merge_workdir_setup__no_fastforward(void) ...@@ -118,12 +92,12 @@ void test_merge_workdir_setup__no_fastforward(void)
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'\n"));
git_reference_free(octo1_ref); git_reference_free(octo1_ref);
git_merge_head_free(our_head); git_merge_head_free(our_head);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
} }
/* git merge 16f825815cfd20a07a75c71554e82d8eede0b061 */ /* git merge --no-ff 16f825815cfd20a07a75c71554e82d8eede0b061 */
void test_merge_workdir_setup__one_oid(void) void test_merge_workdir_setup__one_oid(void)
{ {
git_oid our_oid; git_oid our_oid;
...@@ -136,11 +110,11 @@ void test_merge_workdir_setup__one_oid(void) ...@@ -136,11 +110,11 @@ void test_merge_workdir_setup__one_oid(void)
cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID)); cl_git_pass(git_oid_fromstr(&octo1_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid)); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &octo1_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1, 0)); cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'\n"));
git_merge_head_free(our_head); git_merge_head_free(our_head);
...@@ -164,11 +138,11 @@ void test_merge_workdir_setup__two_branches(void) ...@@ -164,11 +138,11 @@ void test_merge_workdir_setup__two_branches(void)
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "'\n")); 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(octo1_ref);
...@@ -200,11 +174,11 @@ void test_merge_workdir_setup__three_branches(void) ...@@ -200,11 +174,11 @@ void test_merge_workdir_setup__three_branches(void)
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_HEADS_DIR OCTO3_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO2_BRANCH "' and '" OCTO3_BRANCH "'\n")); 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(octo1_ref);
...@@ -238,11 +212,11 @@ void test_merge_workdir_setup__three_oids(void) ...@@ -238,11 +212,11 @@ void test_merge_workdir_setup__three_oids(void)
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID)); cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid)); cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo3_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3, 0)); cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO2_OID "'; commit '" OCTO3_OID "'\n")); 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(our_head);
...@@ -268,11 +242,11 @@ void test_merge_workdir_setup__branches_and_oids_1(void) ...@@ -268,11 +242,11 @@ void test_merge_workdir_setup__branches_and_oids_1(void)
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID)); cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid)); cl_git_pass(git_merge_head_from_id(&their_heads[1], repo, &octo2_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2, 0)); cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n")); cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "'; commit '" OCTO2_OID "'\n"));
git_reference_free(octo1_ref); git_reference_free(octo1_ref);
...@@ -307,11 +281,11 @@ void test_merge_workdir_setup__branches_and_oids_2(void) ...@@ -307,11 +281,11 @@ void test_merge_workdir_setup__branches_and_oids_2(void)
cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID)); cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[3], repo, &octo4_oid)); cl_git_pass(git_merge_head_from_id(&their_heads[3], repo, &octo4_oid));
cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4, 0)); cl_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4));
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_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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO3_BRANCH "'; commit '" OCTO2_OID "'; commit '" OCTO4_OID "'\n")); 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(octo1_ref);
...@@ -349,11 +323,11 @@ void test_merge_workdir_setup__branches_and_oids_3(void) ...@@ -349,11 +323,11 @@ void test_merge_workdir_setup__branches_and_oids_3(void)
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_HEADS_DIR OCTO4_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4));
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_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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; branches '" OCTO2_BRANCH "' and '" OCTO4_BRANCH "'; commit '" OCTO3_OID "'\n")); 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(octo2_ref);
...@@ -395,11 +369,11 @@ void test_merge_workdir_setup__branches_and_oids_4(void) ...@@ -395,11 +369,11 @@ void test_merge_workdir_setup__branches_and_oids_4(void)
cl_git_pass(git_reference_lookup(&octo5_ref, repo, GIT_REFS_HEADS_DIR OCTO5_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 5));
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_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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(octo2_ref);
...@@ -435,11 +409,11 @@ void test_merge_workdir_setup__three_same_branches(void) ...@@ -435,11 +409,11 @@ void test_merge_workdir_setup__three_same_branches(void)
cl_git_pass(git_reference_lookup(&octo1_3_ref, repo, GIT_REFS_HEADS_DIR OCTO1_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "', '" OCTO1_BRANCH "' and '" OCTO1_BRANCH "'\n")); 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_1_ref);
...@@ -473,11 +447,11 @@ void test_merge_workdir_setup__three_same_oids(void) ...@@ -473,11 +447,11 @@ void test_merge_workdir_setup__three_same_oids(void)
cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID)); cl_git_pass(git_oid_fromstr(&octo1_3_oid, OCTO1_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[2], repo, &octo1_3_oid)); cl_git_pass(git_merge_head_from_id(&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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO1_OID "\n" OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge commit '" OCTO1_OID "'; commit '" OCTO1_OID "'; commit '" OCTO1_OID "'\n")); 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(our_head);
...@@ -544,11 +518,11 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void) ...@@ -544,11 +518,11 @@ void test_merge_workdir_setup__remote_tracking_one_branch(void)
cl_git_pass(git_reference_lookup(&octo1_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO1_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); 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_reference_free(octo1_ref);
...@@ -577,11 +551,11 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void) ...@@ -577,11 +551,11 @@ void test_merge_workdir_setup__remote_tracking_two_branches(void)
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(octo1_ref);
...@@ -617,11 +591,11 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void) ...@@ -617,11 +591,11 @@ void test_merge_workdir_setup__remote_tracking_three_branches(void)
cl_git_pass(git_reference_lookup(&octo3_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO3_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(octo1_ref);
...@@ -653,11 +627,11 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void) ...@@ -653,11 +627,11 @@ void test_merge_workdir_setup__normal_branch_and_remote_tracking_branch(void)
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO2_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO1_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO2_BRANCH "'\n")); 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(octo1_ref);
...@@ -687,11 +661,11 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void) ...@@ -687,11 +661,11 @@ void test_merge_workdir_setup__remote_tracking_branch_and_normal_branch(void)
cl_git_pass(git_reference_lookup(&octo2_ref, repo, GIT_REFS_HEADS_DIR OCTO2_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch '" OCTO2_BRANCH "', remote-tracking branch 'refs/remotes/origin/" OCTO1_BRANCH "'\n")); 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(octo1_ref);
...@@ -730,11 +704,11 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche ...@@ -730,11 +704,11 @@ void test_merge_workdir_setup__two_remote_tracking_branch_and_two_normal_branche
cl_git_pass(git_reference_lookup(&octo4_ref, repo, GIT_REFS_REMOTES_DIR "origin/" OCTO4_BRANCH)); 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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4));
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_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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(octo1_ref);
...@@ -762,11 +736,11 @@ void test_merge_workdir_setup__pull_one(void) ...@@ -762,11 +736,11 @@ void test_merge_workdir_setup__pull_one(void)
cl_git_pass(git_oid_fromstr(&octo1_1_oid, OCTO1_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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 1));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branch 'octo1' of http://remote.url/repo.git\n")); 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(our_head);
...@@ -790,11 +764,11 @@ void test_merge_workdir_setup__pull_two(void) ...@@ -790,11 +764,11 @@ void test_merge_workdir_setup__pull_two(void)
cl_git_pass(git_oid_fromstr(&octo2_oid, OCTO2_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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 2));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
cl_assert(test_file_contents(GIT_MERGE_MSG_FILE, "Merge branches '" OCTO1_BRANCH "' and '" OCTO2_BRANCH "' of http://remote.url/repo.git\n")); 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(our_head);
...@@ -823,11 +797,11 @@ void test_merge_workdir_setup__pull_three(void) ...@@ -823,11 +797,11 @@ void test_merge_workdir_setup__pull_three(void)
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(our_head);
...@@ -856,11 +830,11 @@ void test_merge_workdir_setup__three_remotes(void) ...@@ -856,11 +830,11 @@ void test_merge_workdir_setup__three_remotes(void)
cl_git_pass(git_oid_fromstr(&octo3_oid, OCTO3_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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 3));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n" OCTO2_OID "\n" OCTO3_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(our_head);
...@@ -893,11 +867,11 @@ void test_merge_workdir_setup__two_remotes(void) ...@@ -893,11 +867,11 @@ void test_merge_workdir_setup__two_remotes(void)
cl_git_pass(git_oid_fromstr(&octo4_oid, OCTO4_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_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_git_pass(git_merge__setup(repo, our_head, (const git_merge_head **)their_heads, 4));
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_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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "")); cl_assert(test_file_contents(GIT_MERGE_MODE_FILE, "no-ff"));
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")); 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(our_head);
...@@ -996,10 +970,6 @@ void test_merge_workdir_setup__retained_after_success(void) ...@@ -996,10 +970,6 @@ void test_merge_workdir_setup__retained_after_success(void)
git_oid our_oid; git_oid our_oid;
git_reference *octo1_ref; git_reference *octo1_ref;
git_merge_head *our_head, *their_heads[1]; git_merge_head *our_head, *their_heads[1];
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD;
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
...@@ -1008,7 +978,7 @@ void test_merge_workdir_setup__retained_after_success(void) ...@@ -1008,7 +978,7 @@ void test_merge_workdir_setup__retained_after_success(void)
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref)); cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, octo1_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)&their_heads[0], 1, NULL, NULL));
cl_assert(test_file_contents(GIT_MERGE_HEAD_FILE, OCTO1_OID "\n")); 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_ORIG_HEAD_FILE, ORIG_HEAD "\n"));
...@@ -1019,7 +989,6 @@ void test_merge_workdir_setup__retained_after_success(void) ...@@ -1019,7 +989,6 @@ void test_merge_workdir_setup__retained_after_success(void)
git_merge_head_free(our_head); git_merge_head_free(our_head);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
} }
void test_merge_workdir_setup__removed_after_failure(void) void test_merge_workdir_setup__removed_after_failure(void)
...@@ -1027,10 +996,6 @@ void test_merge_workdir_setup__removed_after_failure(void) ...@@ -1027,10 +996,6 @@ void test_merge_workdir_setup__removed_after_failure(void)
git_oid our_oid; git_oid our_oid;
git_reference *octo1_ref; git_reference *octo1_ref;
git_merge_head *our_head, *their_heads[1]; git_merge_head *our_head, *their_heads[1];
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
opts.merge_flags |= GIT_MERGE_NO_FASTFORWARD;
cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD)); cl_git_pass(git_oid_fromstr(&our_oid, ORIG_HEAD));
cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid)); cl_git_pass(git_merge_head_from_id(&our_head, repo, &our_oid));
...@@ -1042,7 +1007,7 @@ void test_merge_workdir_setup__removed_after_failure(void) ...@@ -1042,7 +1007,7 @@ void test_merge_workdir_setup__removed_after_failure(void)
"Conflicting file!\n\nMerge will fail!\n"); "Conflicting file!\n\nMerge will fail!\n");
cl_git_fail(git_merge( cl_git_fail(git_merge(
&result, repo, (const git_merge_head **)&their_heads[0], 1, &opts)); repo, (const git_merge_head **)&their_heads[0], 1, NULL, NULL));
cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE)); cl_assert(!git_path_exists("merge-resolve/" GIT_MERGE_HEAD_FILE));
cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE)); cl_assert(!git_path_exists("merge-resolve/" GIT_ORIG_HEAD_FILE));
...@@ -1053,5 +1018,4 @@ void test_merge_workdir_setup__removed_after_failure(void) ...@@ -1053,5 +1018,4 @@ void test_merge_workdir_setup__removed_after_failure(void)
git_merge_head_free(our_head); git_merge_head_free(our_head);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
} }
...@@ -71,47 +71,6 @@ static git_index *repo_index; ...@@ -71,47 +71,6 @@ static git_index *repo_index;
"", \ "", \
"5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" } "5c3b68a71fc4fa5d362fd3875e53137c6a5ab7a5" }
#define AUTOMERGEABLE_MERGED_FILE \
"this file is changed in master\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is automergeable\n" \
"this file is changed in branch\n"
#define AUTOMERGEABLE_MERGED_FILE_CRLF \
"this file is changed in master\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is automergeable\r\n" \
"this file is changed in branch\r\n"
#define CONFLICTING_MERGE_FILE \
"<<<<<<< HEAD\n" \
"this file is changed in master and branch\n" \
"=======\n" \
"this file is changed in branch and master\n" \
">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
#define CONFLICTING_DIFF3_FILE \
"<<<<<<< HEAD\n" \
"this file is changed in master and branch\n" \
"||||||| initial\n" \
"this file is a conflict\n" \
"=======\n" \
"this file is changed in branch and master\n" \
">>>>>>> 7cb63eed597130ba4abb87b3e544b85021905520\n"
#define CONFLICTING_UNION_FILE \
"this file is changed in master and branch\n" \
"this file is changed in branch and master\n"
// Fixture setup and teardown // Fixture setup and teardown
void test_merge_workdir_simple__initialize(void) void test_merge_workdir_simple__initialize(void)
...@@ -133,23 +92,21 @@ void test_merge_workdir_simple__cleanup(void) ...@@ -133,23 +92,21 @@ void test_merge_workdir_simple__cleanup(void)
cl_git_sandbox_cleanup(); cl_git_sandbox_cleanup();
} }
static git_merge_result *merge_simple_branch(int merge_file_favor, int checkout_strategy) static void merge_simple_branch(int merge_file_favor, int checkout_strategy)
{ {
git_oid their_oids[1]; git_oid their_oids[1];
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID)); cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_SIMPLE_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = merge_file_favor; merge_opts.file_favor = merge_file_favor;
opts.checkout_opts.checkout_strategy = checkout_strategy; checkout_opts.checkout_strategy = checkout_strategy;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts));
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
return result;
} }
static void set_core_autocrlf_to(git_repository *repo, bool value) static void set_core_autocrlf_to(git_repository *repo, bool value)
...@@ -166,7 +123,6 @@ void test_merge_workdir_simple__automerge(void) ...@@ -166,7 +123,6 @@ void test_merge_workdir_simple__automerge(void)
{ {
git_index *index; git_index *index;
const git_index_entry *entry; const git_index_entry *entry;
git_merge_result *result;
git_buf automergeable_buf = GIT_BUF_INIT; git_buf automergeable_buf = GIT_BUF_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -191,8 +147,7 @@ void test_merge_workdir_simple__automerge(void) ...@@ -191,8 +147,7 @@ void test_merge_workdir_simple__automerge(void)
set_core_autocrlf_to(repo, false); set_core_autocrlf_to(repo, false);
cl_assert(result = merge_simple_branch(0, 0)); merge_simple_branch(0, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&automergeable_buf, cl_git_pass(git_futils_readbuffer(&automergeable_buf,
TEST_REPO_PATH "/automergeable.txt")); TEST_REPO_PATH "/automergeable.txt"));
...@@ -202,8 +157,6 @@ void test_merge_workdir_simple__automerge(void) ...@@ -202,8 +157,6 @@ void test_merge_workdir_simple__automerge(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
git_repository_index(&index, repo); git_repository_index(&index, repo);
cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL);
...@@ -217,8 +170,6 @@ void test_merge_workdir_simple__automerge_crlf(void) ...@@ -217,8 +170,6 @@ void test_merge_workdir_simple__automerge_crlf(void)
#ifdef GIT_WIN32 #ifdef GIT_WIN32
git_index *index; git_index *index;
const git_index_entry *entry; const git_index_entry *entry;
git_merge_result *result;
git_buf automergeable_buf = GIT_BUF_INIT; git_buf automergeable_buf = GIT_BUF_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -242,8 +193,7 @@ void test_merge_workdir_simple__automerge_crlf(void) ...@@ -242,8 +193,7 @@ void test_merge_workdir_simple__automerge_crlf(void)
set_core_autocrlf_to(repo, true); set_core_autocrlf_to(repo, true);
cl_assert(result = merge_simple_branch(0, 0)); merge_simple_branch(0, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&automergeable_buf, cl_git_pass(git_futils_readbuffer(&automergeable_buf,
TEST_REPO_PATH "/automergeable.txt")); TEST_REPO_PATH "/automergeable.txt"));
...@@ -253,8 +203,6 @@ void test_merge_workdir_simple__automerge_crlf(void) ...@@ -253,8 +203,6 @@ void test_merge_workdir_simple__automerge_crlf(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
git_repository_index(&index, repo); git_repository_index(&index, repo);
cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL); cl_assert((entry = git_index_get_bypath(index, "automergeable.txt", 0)) != NULL);
...@@ -266,7 +214,6 @@ void test_merge_workdir_simple__automerge_crlf(void) ...@@ -266,7 +214,6 @@ void test_merge_workdir_simple__automerge_crlf(void)
void test_merge_workdir_simple__mergefile(void) void test_merge_workdir_simple__mergefile(void)
{ {
git_merge_result *result;
git_buf conflicting_buf = GIT_BUF_INIT; git_buf conflicting_buf = GIT_BUF_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -288,8 +235,7 @@ void test_merge_workdir_simple__mergefile(void) ...@@ -288,8 +235,7 @@ void test_merge_workdir_simple__mergefile(void)
REMOVED_IN_MASTER_REUC_ENTRY REMOVED_IN_MASTER_REUC_ENTRY
}; };
cl_assert(result = merge_simple_branch(0, 0)); merge_simple_branch(0, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, cl_git_pass(git_futils_readbuffer(&conflicting_buf,
TEST_REPO_PATH "/conflicting.txt")); TEST_REPO_PATH "/conflicting.txt"));
...@@ -298,13 +244,10 @@ void test_merge_workdir_simple__mergefile(void) ...@@ -298,13 +244,10 @@ void test_merge_workdir_simple__mergefile(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__diff3(void) void test_merge_workdir_simple__diff3(void)
{ {
git_merge_result *result;
git_buf conflicting_buf = GIT_BUF_INIT; git_buf conflicting_buf = GIT_BUF_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -326,8 +269,7 @@ void test_merge_workdir_simple__diff3(void) ...@@ -326,8 +269,7 @@ void test_merge_workdir_simple__diff3(void)
REMOVED_IN_MASTER_REUC_ENTRY REMOVED_IN_MASTER_REUC_ENTRY
}; };
cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3)); merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_DIFF3);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, cl_git_pass(git_futils_readbuffer(&conflicting_buf,
TEST_REPO_PATH "/conflicting.txt")); TEST_REPO_PATH "/conflicting.txt"));
...@@ -336,13 +278,10 @@ void test_merge_workdir_simple__diff3(void) ...@@ -336,13 +278,10 @@ void test_merge_workdir_simple__diff3(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__union(void) void test_merge_workdir_simple__union(void)
{ {
git_merge_result *result;
git_buf conflicting_buf = GIT_BUF_INIT; git_buf conflicting_buf = GIT_BUF_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -365,8 +304,7 @@ void test_merge_workdir_simple__union(void) ...@@ -365,8 +304,7 @@ void test_merge_workdir_simple__union(void)
set_core_autocrlf_to(repo, false); set_core_autocrlf_to(repo, false);
cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0)); merge_simple_branch(GIT_MERGE_FILE_FAVOR_UNION, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, cl_git_pass(git_futils_readbuffer(&conflicting_buf,
TEST_REPO_PATH "/conflicting.txt")); TEST_REPO_PATH "/conflicting.txt"));
...@@ -375,13 +313,10 @@ void test_merge_workdir_simple__union(void) ...@@ -375,13 +313,10 @@ void test_merge_workdir_simple__union(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__diff3_from_config(void) void test_merge_workdir_simple__diff3_from_config(void)
{ {
git_merge_result *result;
git_config *config; git_config *config;
git_buf conflicting_buf = GIT_BUF_INIT; git_buf conflicting_buf = GIT_BUF_INIT;
...@@ -407,8 +342,7 @@ void test_merge_workdir_simple__diff3_from_config(void) ...@@ -407,8 +342,7 @@ void test_merge_workdir_simple__diff3_from_config(void)
cl_git_pass(git_repository_config(&config, repo)); cl_git_pass(git_repository_config(&config, repo));
cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3")); cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
cl_assert(result = merge_simple_branch(0, 0)); merge_simple_branch(0, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, cl_git_pass(git_futils_readbuffer(&conflicting_buf,
TEST_REPO_PATH "/conflicting.txt")); TEST_REPO_PATH "/conflicting.txt"));
...@@ -418,13 +352,11 @@ void test_merge_workdir_simple__diff3_from_config(void) ...@@ -418,13 +352,11 @@ void test_merge_workdir_simple__diff3_from_config(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
git_config_free(config); git_config_free(config);
} }
void test_merge_workdir_simple__merge_overrides_config(void) void test_merge_workdir_simple__merge_overrides_config(void)
{ {
git_merge_result *result;
git_config *config; git_config *config;
git_buf conflicting_buf = GIT_BUF_INIT; git_buf conflicting_buf = GIT_BUF_INIT;
...@@ -450,8 +382,7 @@ void test_merge_workdir_simple__merge_overrides_config(void) ...@@ -450,8 +382,7 @@ void test_merge_workdir_simple__merge_overrides_config(void)
cl_git_pass(git_repository_config(&config, repo)); cl_git_pass(git_repository_config(&config, repo));
cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3")); cl_git_pass(git_config_set_string(config, "merge.conflictstyle", "diff3"));
cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_MERGE)); merge_simple_branch(0, GIT_CHECKOUT_CONFLICT_STYLE_MERGE);
cl_assert(!git_merge_result_is_fastforward(result));
cl_git_pass(git_futils_readbuffer(&conflicting_buf, cl_git_pass(git_futils_readbuffer(&conflicting_buf,
TEST_REPO_PATH "/conflicting.txt")); TEST_REPO_PATH "/conflicting.txt"));
...@@ -461,14 +392,11 @@ void test_merge_workdir_simple__merge_overrides_config(void) ...@@ -461,14 +392,11 @@ void test_merge_workdir_simple__merge_overrides_config(void)
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
git_merge_result_free(result);
git_config_free(config); git_config_free(config);
} }
void test_merge_workdir_simple__checkout_ours(void) void test_merge_workdir_simple__checkout_ours(void)
{ {
git_merge_result *result;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
ADDED_IN_MASTER_INDEX_ENTRY, ADDED_IN_MASTER_INDEX_ENTRY,
AUTOMERGEABLE_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY,
...@@ -488,21 +416,16 @@ void test_merge_workdir_simple__checkout_ours(void) ...@@ -488,21 +416,16 @@ void test_merge_workdir_simple__checkout_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY REMOVED_IN_MASTER_REUC_ENTRY
}; };
cl_assert(result = merge_simple_branch(0, GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS)); merge_simple_branch(0, GIT_CHECKOUT_SAFE | GIT_CHECKOUT_USE_OURS);
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 8)); cl_assert(merge_test_index(repo_index, merge_index_entries, 8));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 3));
cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt")); cl_assert(git_path_exists(TEST_REPO_PATH "/conflicting.txt"));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__favor_ours(void) void test_merge_workdir_simple__favor_ours(void)
{ {
git_merge_result *result;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
ADDED_IN_MASTER_INDEX_ENTRY, ADDED_IN_MASTER_INDEX_ENTRY,
AUTOMERGEABLE_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY,
...@@ -519,19 +442,14 @@ void test_merge_workdir_simple__favor_ours(void) ...@@ -519,19 +442,14 @@ void test_merge_workdir_simple__favor_ours(void)
REMOVED_IN_MASTER_REUC_ENTRY, REMOVED_IN_MASTER_REUC_ENTRY,
}; };
cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_OURS, 0)); merge_simple_branch(GIT_MERGE_FILE_FAVOR_OURS, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__favor_theirs(void) void test_merge_workdir_simple__favor_theirs(void)
{ {
git_merge_result *result;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
ADDED_IN_MASTER_INDEX_ENTRY, ADDED_IN_MASTER_INDEX_ENTRY,
AUTOMERGEABLE_INDEX_ENTRY, AUTOMERGEABLE_INDEX_ENTRY,
...@@ -548,13 +466,10 @@ void test_merge_workdir_simple__favor_theirs(void) ...@@ -548,13 +466,10 @@ void test_merge_workdir_simple__favor_theirs(void)
REMOVED_IN_MASTER_REUC_ENTRY, REMOVED_IN_MASTER_REUC_ENTRY,
}; };
cl_assert(result = merge_simple_branch(GIT_MERGE_FILE_FAVOR_THEIRS, 0)); merge_simple_branch(GIT_MERGE_FILE_FAVOR_THEIRS, 0);
cl_assert(!git_merge_result_is_fastforward(result));
cl_assert(merge_test_index(repo_index, merge_index_entries, 6)); cl_assert(merge_test_index(repo_index, merge_index_entries, 6));
cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4)); cl_assert(merge_test_reuc(repo_index, merge_reuc_entries, 4));
git_merge_result_free(result);
} }
void test_merge_workdir_simple__directory_file(void) void test_merge_workdir_simple__directory_file(void)
...@@ -562,8 +477,7 @@ void test_merge_workdir_simple__directory_file(void) ...@@ -562,8 +477,7 @@ void test_merge_workdir_simple__directory_file(void)
git_reference *head; git_reference *head;
git_oid their_oids[1], head_commit_id; git_oid their_oids[1], head_commit_id;
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
git_commit *head_commit; git_commit *head_commit;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -597,23 +511,21 @@ void test_merge_workdir_simple__directory_file(void) ...@@ -597,23 +511,21 @@ void test_merge_workdir_simple__directory_file(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE)); cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_DIRECTORY_FILE));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = 0; merge_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 20)); cl_assert(merge_test_index(repo_index, merge_index_entries, 20));
git_reference_free(head); git_reference_free(head);
git_commit_free(head_commit); git_commit_free(head_commit);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
} }
void test_merge_workdir_simple__unrelated(void) void test_merge_workdir_simple__unrelated(void)
{ {
git_oid their_oids[1]; git_oid their_oids[1];
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" },
...@@ -630,21 +542,19 @@ void test_merge_workdir_simple__unrelated(void) ...@@ -630,21 +542,19 @@ void test_merge_workdir_simple__unrelated(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT)); cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_PARENT));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = 0; merge_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 9)); cl_assert(merge_test_index(repo_index, merge_index_entries, 9));
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
} }
void test_merge_workdir_simple__unrelated_with_conflicts(void) void test_merge_workdir_simple__unrelated_with_conflicts(void)
{ {
git_oid their_oids[1]; git_oid their_oids[1];
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_result *result; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" }, { 0100644, "233c0919c998ed110a4b6ff36f353aec8b713487", 0, "added-in-master.txt" },
...@@ -663,13 +573,12 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void) ...@@ -663,13 +573,12 @@ void test_merge_workdir_simple__unrelated_with_conflicts(void)
cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID)); cl_git_pass(git_oid_fromstr(&their_oids[0], THEIRS_UNRELATED_OID));
cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0]));
opts.merge_tree_opts.file_favor = 0; merge_opts.file_favor = 0;
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 11)); cl_assert(merge_test_index(repo_index, merge_index_entries, 11));
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
} }
void test_merge_workdir_simple__binary(void) void test_merge_workdir_simple__binary(void)
...@@ -677,9 +586,7 @@ void test_merge_workdir_simple__binary(void) ...@@ -677,9 +586,7 @@ void test_merge_workdir_simple__binary(void)
git_oid our_oid, their_oid, our_file_oid; git_oid our_oid, their_oid, our_file_oid;
git_commit *our_commit; git_commit *our_commit;
git_merge_head *their_head; git_merge_head *their_head;
git_merge_result *result;
const git_index_entry *binary_entry; const git_index_entry *binary_entry;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
{ 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" }, { 0100644, "1c51d885170f57a0c4e8c69ff6363d91a5b51f85", 1, "binary" },
...@@ -695,7 +602,7 @@ void test_merge_workdir_simple__binary(void) ...@@ -695,7 +602,7 @@ void test_merge_workdir_simple__binary(void)
cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid)); cl_git_pass(git_merge_head_from_id(&their_head, repo, &their_oid));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 3)); cl_assert(merge_test_index(repo_index, merge_index_entries, 3));
...@@ -706,6 +613,5 @@ void test_merge_workdir_simple__binary(void) ...@@ -706,6 +613,5 @@ void test_merge_workdir_simple__binary(void)
cl_assert(git_oid_cmp(&binary_entry->id, &our_file_oid) == 0); cl_assert(git_oid_cmp(&binary_entry->id, &our_file_oid) == 0);
git_merge_head_free(their_head); git_merge_head_free(their_head);
git_merge_result_free(result);
git_commit_free(our_commit); git_commit_free(our_commit);
} }
...@@ -31,8 +31,6 @@ void test_merge_workdir_submodules__automerge(void) ...@@ -31,8 +31,6 @@ void test_merge_workdir_submodules__automerge(void)
git_reference *our_ref, *their_ref; git_reference *our_ref, *their_ref;
git_commit *our_commit; git_commit *our_commit;
git_merge_head *their_head; git_merge_head *their_head;
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
git_index *index; git_index *index;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -51,13 +49,12 @@ void test_merge_workdir_submodules__automerge(void) ...@@ -51,13 +49,12 @@ void test_merge_workdir_submodules__automerge(void)
cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH)); cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL));
cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_repository_index(&index, repo));
cl_assert(merge_test_index(index, merge_index_entries, 6)); cl_assert(merge_test_index(index, merge_index_entries, 6));
git_index_free(index); git_index_free(index);
git_merge_result_free(result);
git_merge_head_free(their_head); git_merge_head_free(their_head);
git_commit_free(our_commit); git_commit_free(our_commit);
git_reference_free(their_ref); git_reference_free(their_ref);
...@@ -69,8 +66,6 @@ void test_merge_workdir_submodules__take_changed(void) ...@@ -69,8 +66,6 @@ void test_merge_workdir_submodules__take_changed(void)
git_reference *our_ref, *their_ref; git_reference *our_ref, *their_ref;
git_commit *our_commit; git_commit *our_commit;
git_merge_head *their_head; git_merge_head *their_head;
git_merge_result *result;
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
git_index *index; git_index *index;
struct merge_index_entry merge_index_entries[] = { struct merge_index_entry merge_index_entries[] = {
...@@ -87,13 +82,12 @@ void test_merge_workdir_submodules__take_changed(void) ...@@ -87,13 +82,12 @@ void test_merge_workdir_submodules__take_changed(void)
cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH)); cl_git_pass(git_reference_lookup(&their_ref, repo, "refs/heads/" SUBMODULE_OTHER2_BRANCH));
cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref)); cl_git_pass(git_merge_head_from_ref(&their_head, repo, their_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)&their_head, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)&their_head, 1, NULL, NULL));
cl_git_pass(git_repository_index(&index, repo)); cl_git_pass(git_repository_index(&index, repo));
cl_assert(merge_test_index(index, merge_index_entries, 4)); cl_assert(merge_test_index(index, merge_index_entries, 4));
git_index_free(index); git_index_free(index);
git_merge_result_free(result);
git_merge_head_free(their_head); git_merge_head_free(their_head);
git_commit_free(our_commit); git_commit_free(our_commit);
git_reference_free(their_ref); git_reference_free(their_ref);
......
...@@ -34,8 +34,6 @@ static int merge_trivial(const char *ours, const char *theirs) ...@@ -34,8 +34,6 @@ static int merge_trivial(const char *ours, const char *theirs)
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
git_reference *our_ref, *their_ref; git_reference *our_ref, *their_ref;
git_merge_head *their_heads[1]; git_merge_head *their_heads[1];
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
git_merge_result *result;
checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE;
...@@ -49,13 +47,12 @@ static int merge_trivial(const char *ours, const char *theirs) ...@@ -49,13 +47,12 @@ static int merge_trivial(const char *ours, const char *theirs)
cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr));
cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref));
cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, NULL, NULL));
git_buf_free(&branch_buf); git_buf_free(&branch_buf);
git_reference_free(our_ref); git_reference_free(our_ref);
git_reference_free(their_ref); git_reference_free(their_ref);
git_merge_head_free(their_heads[0]); git_merge_head_free(their_heads[0]);
git_merge_result_free(result);
return 0; return 0;
} }
......
c607fc30883e335def28cd686b51f6cfa02b06ec
...@@ -398,8 +398,8 @@ void test_revert_workdir__rename_1_of_2(void) ...@@ -398,8 +398,8 @@ void test_revert_workdir__rename_1_of_2(void)
{ 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 2, "file6.txt" }, { 0100644, "0f5bfcf58c558d865da6be0281d7795993646cee", 2, "file6.txt" },
}; };
opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.merge_tree_opts.rename_threshold = 50; opts.merge_opts.rename_threshold = 50;
git_oid_fromstr(&head_oid, "cef56612d71a6af8d8015691e4865f7fece905b5"); git_oid_fromstr(&head_oid, "cef56612d71a6af8d8015691e4865f7fece905b5");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid)); cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
...@@ -432,8 +432,8 @@ void test_revert_workdir__rename(void) ...@@ -432,8 +432,8 @@ void test_revert_workdir__rename(void)
{ "file4.txt", "file5.txt", "" }, { "file4.txt", "file5.txt", "" },
}; };
opts.merge_tree_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES; opts.merge_opts.flags |= GIT_MERGE_TREE_FIND_RENAMES;
opts.merge_tree_opts.rename_threshold = 50; opts.merge_opts.rename_threshold = 50;
git_oid_fromstr(&head_oid, "55568c8de5322ff9a95d72747a239cdb64a19965"); git_oid_fromstr(&head_oid, "55568c8de5322ff9a95d72747a239cdb64a19965");
cl_git_pass(git_commit_lookup(&head, repo, &head_oid)); cl_git_pass(git_commit_lookup(&head, repo, &head_oid));
......
...@@ -65,15 +65,20 @@ void test_structinit_structinit__compare(void) ...@@ -65,15 +65,20 @@ void test_structinit_structinit__compare(void)
git_diff_find_options, GIT_DIFF_FIND_OPTIONS_VERSION, \ git_diff_find_options, GIT_DIFF_FIND_OPTIONS_VERSION, \
GIT_DIFF_FIND_OPTIONS_INIT, git_diff_find_init_options); GIT_DIFF_FIND_OPTIONS_INIT, git_diff_find_init_options);
/* merge_tree */ /* merge_file_input */
CHECK_MACRO_FUNC_INIT_EQUAL( \
git_merge_file_input, GIT_MERGE_FILE_INPUT_VERSION, \
GIT_MERGE_FILE_INPUT_INIT, git_merge_file_init_input);
/* merge_file */
CHECK_MACRO_FUNC_INIT_EQUAL( \ CHECK_MACRO_FUNC_INIT_EQUAL( \
git_merge_tree_opts, GIT_MERGE_TREE_OPTS_VERSION, \ git_merge_file_options, GIT_MERGE_FILE_OPTIONS_VERSION, \
GIT_MERGE_TREE_OPTS_INIT, git_merge_tree_init_opts); GIT_MERGE_FILE_OPTIONS_INIT, git_merge_file_init_options);
/* merge */ /* merge_tree */
CHECK_MACRO_FUNC_INIT_EQUAL( \ CHECK_MACRO_FUNC_INIT_EQUAL( \
git_merge_opts, GIT_MERGE_OPTS_VERSION, \ git_merge_options, GIT_MERGE_OPTIONS_VERSION, \
GIT_MERGE_OPTS_INIT, git_merge_init_opts); GIT_MERGE_OPTIONS_INIT, git_merge_init_options);
/* push */ /* push */
CHECK_MACRO_FUNC_INIT_EQUAL( \ CHECK_MACRO_FUNC_INIT_EQUAL( \
......
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