Merge remote-tracking branch 'pks/bare-conflicts'
This commit is contained in:
@@ -657,8 +657,34 @@ typedef struct {
|
|||||||
git_merge_file_favor_t file_favor;
|
git_merge_file_favor_t file_favor;
|
||||||
} git_merge_options;
|
} git_merge_options;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int automergeable;
|
||||||
|
const char *path;
|
||||||
|
unsigned int mode;
|
||||||
|
const char *ptr;
|
||||||
|
size_t len;
|
||||||
|
} git_merge_file_result;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GIT_MERGE_FILE_DEFAULT = 0,
|
||||||
|
GIT_MERGE_FILE_STYLE_MERGE = 1,
|
||||||
|
GIT_MERGE_FILE_STYLE_DIFF3 = 2,
|
||||||
|
GIT_MERGE_FILE_SIMPLIFY_ALNUM = 4,
|
||||||
|
} git_merge_file_flags_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int version;
|
||||||
|
const char *ancestor_label;
|
||||||
|
const char *our_label;
|
||||||
|
const char *their_label;
|
||||||
|
git_merge_file_favor_t favor;
|
||||||
|
git_merge_file_flags_t flags;
|
||||||
|
} git_merge_file_options;
|
||||||
|
|
||||||
#define GIT_MERGE_OPTIONS_VERSION ...
|
#define GIT_MERGE_OPTIONS_VERSION ...
|
||||||
|
|
||||||
int git_merge_init_options(git_merge_options *opts, unsigned int version);
|
int git_merge_init_options(git_merge_options *opts, unsigned int version);
|
||||||
int git_merge_commits(git_index **out, git_repository *repo, const git_commit *our_commit, const git_commit *their_commit, const git_merge_options *opts);
|
int git_merge_commits(git_index **out, git_repository *repo, const git_commit *our_commit, const git_commit *their_commit, const git_merge_options *opts);
|
||||||
int git_merge_trees(git_index **out, git_repository *repo, const git_tree *ancestor_tree, const git_tree *our_tree, const git_tree *their_tree, const git_merge_options *opts);
|
int git_merge_trees(git_index **out, git_repository *repo, const git_tree *ancestor_tree, const git_tree *our_tree, const git_tree *their_tree, const git_merge_options *opts);
|
||||||
|
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);
|
||||||
|
void git_merge_file_result_free(git_merge_file_result *result);
|
||||||
|
@@ -526,6 +526,40 @@ class Repository(_Repository):
|
|||||||
|
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
|
def merge_file_from_index(self, ancestor, ours, theirs):
|
||||||
|
"""merge_file_from_index(ancestor, ours, theirs) -> str
|
||||||
|
|
||||||
|
Merge files from index.
|
||||||
|
|
||||||
|
Return a :py:class:`str` object with the merge result
|
||||||
|
containing possible conflicts.
|
||||||
|
|
||||||
|
ancestor
|
||||||
|
The index entry which will be used as a common
|
||||||
|
ancestor.
|
||||||
|
ours
|
||||||
|
The index entry to take as "ours" or base.
|
||||||
|
theirs
|
||||||
|
The index entry which will be merged into "ours"
|
||||||
|
"""
|
||||||
|
cmergeresult = ffi.new('git_merge_file_result *')
|
||||||
|
|
||||||
|
cancestor = ancestor._to_c()[0] if ancestor is not None else ffi.NULL
|
||||||
|
cours = ours._to_c()[0] if ours is not None else ffi.NULL
|
||||||
|
ctheirs = theirs._to_c()[0] if theirs is not None else ffi.NULL
|
||||||
|
|
||||||
|
err = C.git_merge_file_from_index(
|
||||||
|
cmergeresult, self._repo,
|
||||||
|
cancestor, cours, ctheirs,
|
||||||
|
ffi.NULL);
|
||||||
|
check_error(err)
|
||||||
|
|
||||||
|
ret = ffi.string(cmergeresult.ptr,
|
||||||
|
cmergeresult.len).decode()
|
||||||
|
C.git_merge_file_result_free(cmergeresult)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
def merge_commits(self, ours, theirs, favor='normal'):
|
def merge_commits(self, ours, theirs, favor='normal'):
|
||||||
"""Merge two arbitrary commits
|
"""Merge two arbitrary commits
|
||||||
|
|
||||||
|
@@ -198,6 +198,39 @@ class RepositoryTest(utils.BareRepoTestCase):
|
|||||||
written_sha1 = self.repo.create_blob(data)
|
written_sha1 = self.repo.create_blob(data)
|
||||||
self.assertEqual(hashed_sha1, written_sha1)
|
self.assertEqual(hashed_sha1, written_sha1)
|
||||||
|
|
||||||
|
def test_conflicts_in_bare_repository(self):
|
||||||
|
def create_conflict_file(repo, branch, content):
|
||||||
|
oid = repo.create_blob(content)
|
||||||
|
tb = repo.TreeBuilder()
|
||||||
|
tb.insert('conflict', oid, pygit2.GIT_FILEMODE_BLOB)
|
||||||
|
tree = tb.write()
|
||||||
|
|
||||||
|
sig = pygit2.Signature('Author', 'author@example.com')
|
||||||
|
commit = repo.create_commit(branch.name, sig, sig,
|
||||||
|
'Conflict', tree, [branch.target])
|
||||||
|
self.assertIsNotNone(commit)
|
||||||
|
return commit
|
||||||
|
|
||||||
|
b1 = self.repo.create_branch('b1', self.repo.head.peel())
|
||||||
|
c1 = create_conflict_file(self.repo, b1, 'Conflict 1')
|
||||||
|
b2 = self.repo.create_branch('b2', self.repo.head.peel())
|
||||||
|
c2 = create_conflict_file(self.repo, b2, 'Conflict 2')
|
||||||
|
|
||||||
|
index = self.repo.merge_commits(c1, c2)
|
||||||
|
self.assertIsNotNone(index.conflicts)
|
||||||
|
|
||||||
|
# ConflictCollection does not allow calling len(...) on it directly so
|
||||||
|
# we have to calculate length by iterating over its entries
|
||||||
|
self.assertEqual(sum(1 for _ in index.conflicts), 1)
|
||||||
|
|
||||||
|
(a, t, o) = index.conflicts['conflict']
|
||||||
|
diff = self.repo.merge_file_from_index(a, t, o)
|
||||||
|
self.assertEqual(diff, '''<<<<<<< conflict
|
||||||
|
Conflict 1
|
||||||
|
=======
|
||||||
|
Conflict 2
|
||||||
|
>>>>>>> conflict
|
||||||
|
''')
|
||||||
|
|
||||||
class RepositoryTest_II(utils.RepoTestCase):
|
class RepositoryTest_II(utils.RepoTestCase):
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user