Skip to content

Commit 21764db

Browse files
committed
Support for git_merge_analysis_for_ref()
via `Repository.merge_analysis_for_ref(our_ref, their_head)`
1 parent 69d078e commit 21764db

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

src/repository.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,72 @@ Repository_merge_analysis(Repository *self, PyObject *py_id)
673673
return Py_BuildValue("(ii)", analysis, preference);
674674
}
675675

676+
PyDoc_STRVAR(Repository_merge_analysis_for_ref__doc__,
677+
"merge_analysis_for_ref(our_ref, their_head) -> (Integer, Integer)\n"
678+
"\n"
679+
"Analyzes the given branch and determines the opportunities for\n"
680+
"merging it into a reference.\n"
681+
"\n"
682+
"Parameters:\n"
683+
"\n"
684+
"our_ref\n"
685+
" The reference name (String) to perform the analysis from\n"
686+
"\n"
687+
"their_head\n"
688+
" Head (commit Oid) to merge into\n"
689+
"\n"
690+
"The first returned value is a mixture of the GIT_MERGE_ANALYSIS_NONE, _NORMAL,\n"
691+
"_UP_TO_DATE, _FASTFORWARD and _UNBORN flags.\n"
692+
"The second value is the user's preference from 'merge.ff'");
693+
694+
PyObject *
695+
Repository_merge_analysis_for_ref(Repository *self, PyObject *args)
696+
{
697+
char *our_ref_name = NULL;
698+
PyObject *py_their_head;
699+
PyObject *py_result = NULL;
700+
git_oid head_id;
701+
git_reference *our_ref;
702+
git_annotated_commit *commit;
703+
git_merge_analysis_t analysis;
704+
git_merge_preference_t preference;
705+
int err = 0;
706+
707+
if (!PyArg_ParseTuple(args, "zO",
708+
&our_ref_name,
709+
&py_their_head))
710+
return NULL;
711+
712+
err = git_reference_lookup(&our_ref, self->repo, our_ref_name);
713+
if (err < 0) {
714+
PyObject *py_err = Error_set_str(err, our_ref_name);
715+
return py_err;
716+
}
717+
718+
err = py_oid_to_git_oid_expand(self->repo, py_their_head, &head_id);
719+
if (err < 0)
720+
goto out;
721+
722+
err = git_annotated_commit_lookup(&commit, self->repo, &head_id);
723+
if (err < 0) {
724+
py_result = Error_set(err);
725+
goto out;
726+
}
727+
728+
err = git_merge_analysis_for_ref(&analysis, &preference, self->repo, our_ref, (const git_annotated_commit **) &commit, 1);
729+
git_annotated_commit_free(commit);
730+
if (err < 0) {
731+
py_result = Error_set(err);
732+
goto out;
733+
}
734+
735+
py_result = Py_BuildValue("(ii)", analysis, preference);
736+
737+
out:
738+
git_reference_free(our_ref);
739+
return py_result;
740+
}
741+
676742
PyDoc_STRVAR(Repository_merge__doc__,
677743
"merge(id)\n"
678744
"\n"
@@ -1944,6 +2010,7 @@ PyMethodDef Repository_methods[] = {
19442010
METHOD(Repository, descendant_of, METH_VARARGS),
19452011
METHOD(Repository, merge_base, METH_VARARGS),
19462012
METHOD(Repository, merge_analysis, METH_O),
2013+
METHOD(Repository, merge_analysis_for_ref, METH_VARARGS),
19472014
METHOD(Repository, merge, METH_O),
19482015
METHOD(Repository, cherrypick, METH_O),
19492016
METHOD(Repository, apply, METH_O),

src/repository.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,7 @@ PyObject* Repository_blame(Repository *self, PyObject *args, PyObject *kwds);
7979
PyObject* Repository_merge(Repository *self, PyObject *py_oid);
8080
PyObject* Repository_cherrypick(Repository *self, PyObject *py_oid);
8181
PyObject* Repository_apply(Repository *self, PyObject *py_diff);
82+
PyObject* Repository_merge_analysis(Repository *self, PyObject *py_id);
83+
PyObject* Repository_merge_analysis_for_ref(Repository *self, PyObject *args);
8284

8385
#endif

test/test_merge.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,20 +49,31 @@ def test_merge_none(self):
4949
def test_merge_analysis_uptodate(self):
5050
branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533'
5151
branch_id = self.repo.get(branch_head_hex).id
52+
5253
analysis, preference = self.repo.merge_analysis(branch_id)
54+
assert analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE
55+
assert not analysis & GIT_MERGE_ANALYSIS_FASTFORWARD
56+
assert {} == self.repo.status()
5357

58+
analysis, preference = self.repo.merge_analysis_for_ref('HEAD', branch_id)
5459
assert analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE
5560
assert not analysis & GIT_MERGE_ANALYSIS_FASTFORWARD
5661
assert {} == self.repo.status()
5762

5863
def test_merge_analysis_fastforward(self):
5964
branch_head_hex = 'e97b4cfd5db0fb4ebabf4f203979ca4e5d1c7c87'
6065
branch_id = self.repo.get(branch_head_hex).id
66+
6167
analysis, preference = self.repo.merge_analysis(branch_id)
6268
assert not analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE
6369
assert analysis & GIT_MERGE_ANALYSIS_FASTFORWARD
6470
assert {} == self.repo.status()
6571

72+
analysis, preference = self.repo.merge_analysis_for_ref('HEAD', branch_id)
73+
assert not analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE
74+
assert analysis & GIT_MERGE_ANALYSIS_FASTFORWARD
75+
assert {} == self.repo.status()
76+
6677
def test_merge_no_fastforward_no_conflicts(self):
6778
branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1'
6879
branch_id = self.repo.get(branch_head_hex).id

0 commit comments

Comments
 (0)