Add Repository.merge_commits()
This allows you to merge arbitrary commits, returning an index, which is useful when dealing with bare repos in which we want to merge.
This commit is contained in:
@@ -5,6 +5,7 @@ typedef ... git_push;
|
||||
typedef ... git_cred;
|
||||
typedef ... git_object;
|
||||
typedef ... git_tree;
|
||||
typedef ... git_commit;
|
||||
typedef ... git_index;
|
||||
typedef ... git_diff;
|
||||
typedef ... git_index_conflict_iterator;
|
||||
@@ -274,6 +275,18 @@ typedef struct {
|
||||
const char *new_prefix;
|
||||
} git_diff_options;
|
||||
|
||||
typedef struct {
|
||||
int (*file_signature)(
|
||||
void **out, const git_diff_file *file,
|
||||
const char *fullpath, void *payload);
|
||||
int (*buffer_signature)(
|
||||
void **out, const git_diff_file *file,
|
||||
const char *buf, size_t buflen, void *payload);
|
||||
void (*free_signature)(void *sig, void *payload);
|
||||
int (*similarity)(int *score, void *siga, void *sigb, void *payload);
|
||||
void *payload;
|
||||
} git_diff_similarity_metric;
|
||||
|
||||
int git_diff_init_options(git_diff_options *opts, unsigned int version);
|
||||
int git_diff_index_to_workdir(git_diff **diff, git_repository *repo, git_index *index, const git_diff_options *opts);
|
||||
int git_diff_tree_to_index(git_diff **diff, git_repository *repo, git_tree *old_tree, git_index *index, const git_diff_options *opts);
|
||||
@@ -578,3 +591,23 @@ const git_blame_hunk *git_blame_get_hunk_byindex(git_blame *blame, uint32_t inde
|
||||
const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, uint32_t lineno);
|
||||
int git_blame_file(git_blame **out, git_repository *repo, const char *path, git_blame_options *options);
|
||||
void git_blame_free(git_blame *blame);
|
||||
|
||||
/*
|
||||
* Merging
|
||||
*/
|
||||
|
||||
typedef enum { ... } git_merge_tree_flag_t;
|
||||
|
||||
typedef enum { ... } git_merge_file_favor_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
git_merge_tree_flag_t flags;
|
||||
unsigned int rename_threshold;
|
||||
unsigned int target_limit;
|
||||
git_diff_similarity_metric *metric;
|
||||
git_merge_file_favor_t file_favor;
|
||||
} git_merge_options;
|
||||
|
||||
|
||||
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);
|
||||
|
@@ -508,6 +508,45 @@ class Repository(_Repository):
|
||||
return Index.from_c(self, cindex)
|
||||
|
||||
#
|
||||
# Merging
|
||||
#
|
||||
def merge_commits(self, ours, theirs):
|
||||
"""Merge two arbitrary commits
|
||||
|
||||
Arguments:
|
||||
|
||||
ours
|
||||
The commit to take as "ours" or base.
|
||||
theirs
|
||||
The commit which will be merged into "ours"
|
||||
|
||||
Both can be any object which peels to a commit or the id
|
||||
(string or Oid) of an object which peels to a commit.
|
||||
|
||||
Returns an index with the result of the merge
|
||||
|
||||
"""
|
||||
|
||||
ours_ptr = ffi.new('git_commit **')
|
||||
theirs_ptr = ffi.new('git_commit **')
|
||||
cindex = ffi.new('git_index **')
|
||||
|
||||
if is_string(ours) or isinstance(ours, Oid):
|
||||
ours = self[ours]
|
||||
if is_string(theirs) or isinstance(theirs, Oid):
|
||||
theirs = self[theirs]
|
||||
|
||||
ours = ours.peel(Commit)
|
||||
theirs = theirs.peel(Commit)
|
||||
|
||||
ffi.buffer(ours_ptr)[:] = ours._pointer[:]
|
||||
ffi.buffer(theirs_ptr)[:] = theirs._pointer[:]
|
||||
|
||||
err = C.git_merge_commits(cindex, self._repo, ours_ptr[0], theirs_ptr[0], ffi.NULL)
|
||||
check_error(err)
|
||||
|
||||
return Index.from_c(self, cindex)
|
||||
#
|
||||
# Utility for writing a tree into an archive
|
||||
#
|
||||
def write_archive(self, treeish, archive, timestamp=None):
|
||||
|
@@ -141,3 +141,20 @@ class MergeTestWithConflicts(utils.RepoTestCaseForMerging):
|
||||
del idx.conflicts['.gitignore']
|
||||
self.assertRaises(KeyError, conflicts.__getitem__, '.gitignore')
|
||||
self.assertTrue(idx.conflicts is None)
|
||||
|
||||
class MergeCommitsTest(utils.RepoTestCaseForMerging):
|
||||
|
||||
def test_merge_commits(self):
|
||||
branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1'
|
||||
branch_id = self.repo.get(branch_head_hex).id
|
||||
|
||||
merge_index = self.repo.merge_commits(self.repo.head.target, branch_head_hex)
|
||||
self.assertTrue(merge_index.conflicts is None)
|
||||
merge_commits_tree = merge_index.write_tree(self.repo)
|
||||
|
||||
self.repo.merge(branch_id)
|
||||
index = self.repo.index
|
||||
self.assertTrue(index.conflicts is None)
|
||||
merge_tree = index.write_tree()
|
||||
|
||||
self.assertEqual(merge_tree, merge_commits_tree)
|
||||
|
Reference in New Issue
Block a user