mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 22:25:04 +00:00
Merge submodules
This commit is contained in:
parent
db3462ce77
commit
0ef19fe14c
@ -71,7 +71,8 @@ typedef struct {
|
||||
int name_collision:1,
|
||||
directoryfile:1,
|
||||
one_to_two:1,
|
||||
binary:1;
|
||||
binary:1,
|
||||
submodule:1;
|
||||
} checkout_conflictdata;
|
||||
|
||||
static int checkout_notify(
|
||||
@ -682,11 +683,22 @@ GIT_INLINE(bool) conflict_pathspec_match(
|
||||
return false;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) checkout_conflict_detect_submodule(checkout_conflictdata *conflict)
|
||||
{
|
||||
conflict->submodule = ((conflict->ancestor && S_ISGITLINK(conflict->ancestor->mode)) ||
|
||||
(conflict->ours && S_ISGITLINK(conflict->ours->mode)) ||
|
||||
(conflict->theirs && S_ISGITLINK(conflict->theirs->mode)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) checkout_conflict_detect_binary(git_repository *repo, checkout_conflictdata *conflict)
|
||||
{
|
||||
git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
|
||||
int error = 0;
|
||||
|
||||
if (conflict->submodule)
|
||||
return 0;
|
||||
|
||||
if (conflict->ancestor) {
|
||||
if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor->oid)) < 0)
|
||||
goto done;
|
||||
@ -740,7 +752,8 @@ static int checkout_conflicts_load(checkout_data *data, git_iterator *workdir, g
|
||||
conflict->ours = ours;
|
||||
conflict->theirs = theirs;
|
||||
|
||||
if ((error = checkout_conflict_detect_binary(data->repo, conflict)) < 0)
|
||||
if ((error = checkout_conflict_detect_submodule(conflict)) < 0 ||
|
||||
(error = checkout_conflict_detect_binary(data->repo, conflict)) < 0)
|
||||
goto done;
|
||||
|
||||
git_vector_insert(&data->conflicts, conflict);
|
||||
@ -1791,6 +1804,10 @@ static int checkout_create_conflicts(checkout_data *data)
|
||||
else if (S_ISLNK(conflict->theirs->mode))
|
||||
error = checkout_write_entry(data, conflict, conflict->ours);
|
||||
|
||||
/* If any side is a gitlink, do nothing. */
|
||||
else if (conflict->submodule)
|
||||
error = 0;
|
||||
|
||||
/* If any side is binary, write the ours side */
|
||||
else if (conflict->binary)
|
||||
error = checkout_write_entry(data, conflict, conflict->ours);
|
||||
|
14
src/merge.c
14
src/merge.c
@ -42,6 +42,7 @@
|
||||
#include "git2/sys/index.h"
|
||||
|
||||
#define GIT_MERGE_INDEX_ENTRY_EXISTS(X) ((X).mode != 0)
|
||||
#define GIT_MERGE_INDEX_ENTRY_ISFILE(X) S_ISREG((X).mode)
|
||||
|
||||
typedef enum {
|
||||
TREE_IDX_ANCESTOR = 0,
|
||||
@ -447,7 +448,6 @@ static int merge_conflict_resolve_one_removed(
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static int merge_conflict_resolve_one_renamed(
|
||||
int *resolved,
|
||||
git_merge_diff_list *diff_list,
|
||||
@ -533,6 +533,12 @@ static int merge_conflict_resolve_automerge(
|
||||
if (conflict->type == GIT_MERGE_DIFF_DIRECTORY_FILE)
|
||||
return 0;
|
||||
|
||||
/* Reject submodules. */
|
||||
if (S_ISGITLINK(conflict->ancestor_entry.mode) ||
|
||||
S_ISGITLINK(conflict->our_entry.mode) ||
|
||||
S_ISGITLINK(conflict->their_entry.mode))
|
||||
return 0;
|
||||
|
||||
/* Reject link/file conflicts. */
|
||||
if ((S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->our_entry.mode)) ||
|
||||
(S_ISLNK(conflict->ancestor_entry.mode) ^ S_ISLNK(conflict->their_entry.mode)))
|
||||
@ -1156,7 +1162,7 @@ GIT_INLINE(int) merge_diff_detect_binary(
|
||||
git_blob *ancestor_blob = NULL, *our_blob = NULL, *their_blob = NULL;
|
||||
int error = 0;
|
||||
|
||||
if (GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->ancestor_entry)) {
|
||||
if (GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->ancestor_entry)) {
|
||||
if ((error = git_blob_lookup(&ancestor_blob, repo, &conflict->ancestor_entry.oid)) < 0)
|
||||
goto done;
|
||||
|
||||
@ -1164,7 +1170,7 @@ GIT_INLINE(int) merge_diff_detect_binary(
|
||||
}
|
||||
|
||||
if (!conflict->binary &&
|
||||
GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->our_entry)) {
|
||||
GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->our_entry)) {
|
||||
if ((error = git_blob_lookup(&our_blob, repo, &conflict->our_entry.oid)) < 0)
|
||||
goto done;
|
||||
|
||||
@ -1172,7 +1178,7 @@ GIT_INLINE(int) merge_diff_detect_binary(
|
||||
}
|
||||
|
||||
if (!conflict->binary &&
|
||||
GIT_MERGE_INDEX_ENTRY_EXISTS(conflict->their_entry)) {
|
||||
GIT_MERGE_INDEX_ENTRY_ISFILE(conflict->their_entry)) {
|
||||
if ((error = git_blob_lookup(&their_blob, repo, &conflict->their_entry.oid)) < 0)
|
||||
goto done;
|
||||
|
||||
|
101
tests/merge/workdir/submodules.c
Normal file
101
tests/merge/workdir/submodules.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include "clar_libgit2.h"
|
||||
#include "git2/repository.h"
|
||||
#include "git2/merge.h"
|
||||
#include "buffer.h"
|
||||
#include "merge.h"
|
||||
#include "../merge_helpers.h"
|
||||
|
||||
static git_repository *repo;
|
||||
|
||||
#define TEST_REPO_PATH "merge-resolve"
|
||||
|
||||
#define SUBMODULE_MAIN_BRANCH "submodules"
|
||||
#define SUBMODULE_OTHER_BRANCH "submodules-branch"
|
||||
#define SUBMODULE_OTHER2_BRANCH "submodules-branch2"
|
||||
|
||||
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"
|
||||
|
||||
// Fixture setup and teardown
|
||||
void test_merge_workdir_submodules__initialize(void)
|
||||
{
|
||||
repo = cl_git_sandbox_init(TEST_REPO_PATH);
|
||||
}
|
||||
|
||||
void test_merge_workdir_submodules__cleanup(void)
|
||||
{
|
||||
cl_git_sandbox_cleanup();
|
||||
}
|
||||
|
||||
void test_merge_workdir_submodules__automerge(void)
|
||||
{
|
||||
git_reference *our_ref, *their_ref;
|
||||
git_commit *our_commit;
|
||||
git_merge_head *their_head;
|
||||
git_merge_result *result;
|
||||
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
|
||||
git_index *index;
|
||||
|
||||
struct merge_index_entry merge_index_entries[] = {
|
||||
{ 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
|
||||
{ 0100644, "950a663a6a7b2609eed1ed1ba9f41eb1a3192a9f", 0, "file1.txt" },
|
||||
{ 0100644, "343e660b9cb4bee5f407c2e33fcb9df24d9407a4", 0, "file2.txt" },
|
||||
{ 0160000, "d3d806a4bef96889117fd7ebac0e3cb5ec152932", 1, "submodule" },
|
||||
{ 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 2, "submodule" },
|
||||
{ 0160000, "ae39c77c70cb6bad18bb471912460c4e1ba0f586", 3, "submodule" },
|
||||
};
|
||||
|
||||
cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
|
||||
cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
|
||||
cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
|
||||
|
||||
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(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
|
||||
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
cl_assert(merge_test_index(index, merge_index_entries, 6));
|
||||
|
||||
git_index_free(index);
|
||||
git_merge_result_free(result);
|
||||
git_merge_head_free(their_head);
|
||||
git_commit_free(our_commit);
|
||||
git_reference_free(their_ref);
|
||||
git_reference_free(our_ref);
|
||||
}
|
||||
|
||||
void test_merge_workdir_submodules__take_changed(void)
|
||||
{
|
||||
git_reference *our_ref, *their_ref;
|
||||
git_commit *our_commit;
|
||||
git_merge_head *their_head;
|
||||
git_merge_result *result;
|
||||
git_merge_opts opts = GIT_MERGE_OPTS_INIT;
|
||||
git_index *index;
|
||||
|
||||
struct merge_index_entry merge_index_entries[] = {
|
||||
{ 0100644, "caff6b7d44973f53e3e0cf31d0d695188b19aec6", 0, ".gitmodules" },
|
||||
{ 0100644, "b438ff23300b2e0f80b84a6f30140dfa91e71423", 0, "file1.txt" },
|
||||
{ 0100644, "f27fbafdfa6693f8f7a5128506fe3e338dbfcad2", 0, "file2.txt" },
|
||||
{ 0160000, "297aa6cd028b3336c7802c7a6f49143da4e1602d", 0, "submodule" },
|
||||
};
|
||||
|
||||
cl_git_pass(git_reference_lookup(&our_ref, repo, "refs/heads/" SUBMODULE_MAIN_BRANCH));
|
||||
cl_git_pass(git_commit_lookup(&our_commit, repo, git_reference_target(our_ref)));
|
||||
cl_git_pass(git_reset(repo, (git_object *)our_commit, GIT_RESET_HARD));
|
||||
|
||||
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(&result, repo, (const git_merge_head **)&their_head, 1, &opts));
|
||||
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
cl_assert(merge_test_index(index, merge_index_entries, 4));
|
||||
|
||||
git_index_free(index);
|
||||
git_merge_result_free(result);
|
||||
git_merge_head_free(their_head);
|
||||
git_commit_free(our_commit);
|
||||
git_reference_free(their_ref);
|
||||
git_reference_free(our_ref);
|
||||
}
|
Binary file not shown.
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
Normal file
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/HEAD
Normal file
Binary file not shown.
Binary file not shown.
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/config
Normal file
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/config
Normal file
Binary file not shown.
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/index
Normal file
BIN
tests/resources/merge-resolve/.gitted/modules/submodule/index
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/resources/merge-resolve/.gitted/refs/heads/submodules
Normal file
BIN
tests/resources/merge-resolve/.gitted/refs/heads/submodules
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user