From 1f5ec810adbdb5d94da7adcc24490106d686bfa2 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 4 Dec 2013 18:17:10 +0100 Subject: [PATCH 1/9] implementing merge with default options --- src/mergeresult.c | 161 ++++++++++++++++++++++++++++++++++++++++ src/mergeresult.h | 37 +++++++++ src/pygit2.c | 5 ++ src/repository.c | 56 +++++++++++++- src/repository.h | 4 +- src/types.h | 9 +++ test/test_repository.py | 60 ++++++++++++++- test/utils.py | 5 ++ 8 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 src/mergeresult.c create mode 100644 src/mergeresult.h diff --git a/src/mergeresult.c b/src/mergeresult.c new file mode 100644 index 000000000..c0ffddd6e --- /dev/null +++ b/src/mergeresult.c @@ -0,0 +1,161 @@ +/* + * Copyright 2010-2013 The pygit2 contributors + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#define PY_SSIZE_T_CLEAN +#include +#include "utils.h" +#include "types.h" +#include "oid.h" +#include "repository.h" +#include "mergeresult.h" + +extern PyTypeObject MergeResultType; +extern PyTypeObject IndexType; + +PyObject * +git_merge_result_to_python(git_merge_result *merge_result, Repository *repo) +{ + git_oid fastforward_oid; + MergeResult *py_merge_result; + + py_merge_result = PyObject_New(MergeResult, &MergeResultType); + + py_merge_result->is_uptodate = git_merge_result_is_uptodate(merge_result) == GIT_CVAR_TRUE; + + if (git_merge_result_is_fastforward(merge_result) == GIT_CVAR_TRUE) + { + py_merge_result->is_fastforward = GIT_CVAR_TRUE; + git_merge_result_fastforward_oid(&fastforward_oid, merge_result); + py_merge_result->fastforward_oid = git_oid_to_python((const git_oid *)&fastforward_oid); + } + else + { + py_merge_result->is_fastforward = GIT_CVAR_FALSE; + py_merge_result->fastforward_oid = NULL; + } + + py_merge_result->status = Repository_status(repo); + + return (PyObject*) py_merge_result; +} + +PyDoc_STRVAR(MergeResult_is_uptodate__doc__, "Is up to date"); + +PyObject * +MergeResult_is_uptodate__get__(MergeResult *self) +{ + if (self->is_uptodate) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(MergeResult_is_fastforward__doc__, "Is fastforward"); + +PyObject * +MergeResult_is_fastforward__get__(MergeResult *self) +{ + if (self->is_fastforward) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +PyDoc_STRVAR(MergeResult_fastforward_oid__doc__, "Fastforward Oid"); + +PyObject * +MergeResult_fastforward_oid__get__(MergeResult *self) +{ + if (self->is_fastforward == 1) + { + Py_INCREF(self->fastforward_oid); + return self->fastforward_oid; + } + else + Py_RETURN_NONE; +} + +PyDoc_STRVAR(MergeResult_status__doc__, "Merge repository status"); + +PyObject * +MergeResult_status__get__(MergeResult *self) +{ + Py_INCREF(self->status); + return self->status; +} + +PyGetSetDef MergeResult_getseters[] = { + GETTER(MergeResult, is_uptodate), + GETTER(MergeResult, is_fastforward), + GETTER(MergeResult, fastforward_oid), + GETTER(MergeResult, status), + {NULL}, +}; + +PyDoc_STRVAR(MergeResult__doc__, "MergeResult object."); + +PyTypeObject MergeResultType = { + PyVarObject_HEAD_INIT(NULL, 0) + "_pygit2.MergeResult", /* tp_name */ + sizeof(MergeResult), /* tp_basicsize */ + 0, /* tp_itemsize */ + 0, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + MergeResult__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + MergeResult_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + diff --git a/src/mergeresult.h b/src/mergeresult.h new file mode 100644 index 000000000..7aadac4aa --- /dev/null +++ b/src/mergeresult.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2013 The pygit2 contributors + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, + * as published by the Free Software Foundation. + * + * In addition to the permissions in the GNU General Public License, + * the authors give you unlimited permission to link the compiled + * version of this file into combinations with other programs, + * and to distribute those combinations without any restriction + * coming from the use of this file. (The General Public License + * restrictions do apply in other respects; for example, they cover + * modification of the file, and distribution when not linked into + * a combined executable.) + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDE_pygit2_merge_result_h +#define INCLUDE_pygit2_merge_result_h + +#define PY_SSIZE_T_CLEAN +#include +#include + +PyObject* git_merge_result_to_python(git_merge_result *merge_result, Repository *repo); + +#endif diff --git a/src/pygit2.c b/src/pygit2.c index 4bd37c1df..e1766d26e 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -67,6 +67,7 @@ extern PyTypeObject NoteIterType; extern PyTypeObject BlameType; extern PyTypeObject BlameIterType; extern PyTypeObject BlameHunkType; +extern PyTypeObject MergeResultType; @@ -428,6 +429,10 @@ moduleinit(PyObject* m) ADD_CONSTANT_INT(m, GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES) ADD_CONSTANT_INT(m, GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES) + /* Merge */ + INIT_TYPE(MergeResultType, NULL, NULL) + ADD_TYPE(m, MergeResult) + /* Global initialization of libgit2 */ git_threads_init(); diff --git a/src/repository.c b/src/repository.c index 20e2a7c50..3d4889c65 100644 --- a/src/repository.c +++ b/src/repository.c @@ -38,6 +38,7 @@ #include "remote.h" #include "branch.h" #include "blame.h" +#include "mergeresult.h" #include extern PyObject *GitError; @@ -578,6 +579,58 @@ Repository_merge_base(Repository *self, PyObject *args) return git_oid_to_python(&oid); } +PyDoc_STRVAR(Repository_merge__doc__, + "merge(oid) -> MergeResult\n" + "\n" + "Merges the given oid and returns the MergeResult.\n" + "\n" + "If the merge is fastforward the MergeResult will contain the new\n" + "fastforward oid.\n" + "If the branch is uptodate, nothing to merge, the MergeResult will\n" + "have the fastforward oid as None.\n" + "If the merge is not fastforward the MergeResult will have the status\n" + "produced by the merge, even if there are conflicts."); + +PyObject * +Repository_merge(Repository *self, PyObject *py_oid) +{ + git_merge_result *merge_result; + git_merge_head *oid_merge_head; + git_oid oid; + const git_merge_opts default_opts = GIT_MERGE_OPTS_INIT; + int err; + size_t len; + PyObject *py_merge_result; + + len = py_oid_to_git_oid(py_oid, &oid); + if (len == 0) + return NULL; + + err = git_merge_head_from_oid(&oid_merge_head, self->repo, &oid); + if (err < 0) + goto error; + + err = git_merge(&merge_result, self->repo, + (const git_merge_head **)&oid_merge_head, 1, + &default_opts); + if (err < 0) + { + git_merge_result_free(merge_result); + goto error; + } + + py_merge_result = git_merge_result_to_python(merge_result, self); + + git_merge_head_free(oid_merge_head); + git_merge_result_free(merge_result); + + return py_merge_result; + +error: + git_merge_head_free(oid_merge_head); + return Error_set(err); +} + PyDoc_STRVAR(Repository_walk__doc__, "walk(oid, sort_mode) -> iterator\n" "\n" @@ -1093,7 +1146,7 @@ PyDoc_STRVAR(Repository_status__doc__, "paths as keys and status flags as values. See pygit2.GIT_STATUS_*."); PyObject * -Repository_status(Repository *self, PyObject *args) +Repository_status(Repository *self) { PyObject *dict; int err; @@ -1551,6 +1604,7 @@ PyMethodDef Repository_methods[] = { METHOD(Repository, TreeBuilder, METH_VARARGS), METHOD(Repository, walk, METH_VARARGS), METHOD(Repository, merge_base, METH_VARARGS), + METHOD(Repository, merge, METH_O), METHOD(Repository, read, METH_O), METHOD(Repository, write, METH_VARARGS), METHOD(Repository, create_reference_direct, METH_VARARGS), diff --git a/src/repository.h b/src/repository.h index 3c6094872..735f77480 100644 --- a/src/repository.h +++ b/src/repository.h @@ -63,10 +63,12 @@ PyObject* Repository_create_reference(Repository *self, PyObject *args, PyObject* kw); PyObject* Repository_packall_references(Repository *self, PyObject *args); -PyObject* Repository_status(Repository *self, PyObject *args); +PyObject* Repository_status(Repository *self); PyObject* Repository_status_file(Repository *self, PyObject *value); PyObject* Repository_TreeBuilder(Repository *self, PyObject *args); PyObject* Repository_blame(Repository *self, PyObject *args, PyObject *kwds); +PyObject* Repository_merge(Repository *self, PyObject *py_oid); + #endif diff --git a/src/types.h b/src/types.h index 46062a456..06504fd36 100644 --- a/src/types.h +++ b/src/types.h @@ -217,5 +217,14 @@ typedef struct { char boundary; } BlameHunk; +/* git_merge */ +typedef struct { + PyObject_HEAD + int is_uptodate; + int is_fastforward; + PyObject* fastforward_oid; + PyObject* status; + +} MergeResult; #endif diff --git a/test/test_repository.py b/test/test_repository.py index 43e196be8..bcbb48fa3 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -302,6 +302,63 @@ def test_reset_mixed(self): self.assertTrue("bonjour le monde\n" in diff.patch) +class RepositoryTest_III(utils.RepoTestCaseForMerging): + + def test_merge_uptodate(self): + branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533' + branch_oid = self.repo.get(branch_head_hex).oid + merge_result = self.repo.merge(branch_oid) + self.assertTrue(merge_result.is_uptodate) + self.assertFalse(merge_result.is_fastforward) + self.assertEquals(None, merge_result.fastforward_oid) + self.assertEquals({}, merge_result.status) + + def test_merge_fastforward(self): + branch_head_hex = 'e97b4cfd5db0fb4ebabf4f203979ca4e5d1c7c87' + branch_oid = self.repo.get(branch_head_hex).oid + merge_result = self.repo.merge(branch_oid) + self.assertFalse(merge_result.is_uptodate) + self.assertTrue(merge_result.is_fastforward) + # Asking twice to assure the reference counting is correct + self.assertEquals(branch_head_hex, merge_result.fastforward_oid.hex) + self.assertEquals(branch_head_hex, merge_result.fastforward_oid.hex) + self.assertEquals({}, merge_result.status) + + def test_merge_no_fastforward_no_conflicts(self): + branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1' + branch_oid = self.repo.get(branch_head_hex).oid + merge_result = self.repo.merge(branch_oid) + self.assertFalse(merge_result.is_uptodate) + self.assertFalse(merge_result.is_fastforward) + self.assertEquals(None, merge_result.fastforward_oid) + # Asking twice to assure the reference counting is correct + self.assertEquals({'bye.txt': 1}, merge_result.status) + self.assertEquals({'bye.txt': 1}, merge_result.status) + + def test_merge_no_fastforward_conflicts(self): + branch_head_hex = '1b2bae55ac95a4be3f8983b86cd579226d0eb247' + branch_oid = self.repo.get(branch_head_hex).oid + merge_result = self.repo.merge(branch_oid) + self.assertFalse(merge_result.is_uptodate) + self.assertFalse(merge_result.is_fastforward) + self.assertEquals(None, merge_result.fastforward_oid) + # Asking twice to assure the reference counting is correct + self.assertEquals({'.gitignore': 132}, merge_result.status) + self.assertEquals({'.gitignore': 132}, merge_result.status) + + def test_merge_invalid_hex(self): + branch_head_hex = '12345678' + self.assertRaises(KeyError, self.repo.merge, branch_head_hex) + + def test_merge_already_something_in_index(self): + branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1' + branch_oid = self.repo.get(branch_head_hex).oid + with open(os.path.join(self.repo.workdir, 'inindex.txt'), 'w') as f: + f.write('new content') + self.repo.index.add('inindex.txt') + self.assertRaises(pygit2.GitError, self.repo.merge, branch_oid) + + class NewRepositoryTest(utils.NoRepoTestCase): def test_new_repo(self): @@ -376,8 +433,7 @@ def test_clone_bare_repository(self): def test_clone_remote_name(self): repo_path = "./test/data/testrepo.git/" repo = clone_repository( - repo_path, self._temp_dir, remote_name="custom_remote" - ) + repo_path, self._temp_dir, remote_name="custom_remote") self.assertFalse(repo.is_empty) self.assertEqual(repo.remotes[0].name, "custom_remote") diff --git a/test/utils.py b/test/utils.py index fb7ca58f9..4d941e5c3 100644 --- a/test/utils.py +++ b/test/utils.py @@ -146,6 +146,11 @@ class RepoTestCase(AutoRepoTestCase): repo_spec = 'tar', 'testrepo' +class RepoTestCaseForMerging(AutoRepoTestCase): + + repo_spec = 'tar', 'testrepoformerging' + + class DirtyRepoTestCase(AutoRepoTestCase): repo_spec = 'tar', 'dirtyrepo' From 9955b3e67add52465d7201eccf8a7c973f7d5420 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 4 Dec 2013 18:23:13 +0100 Subject: [PATCH 2/9] implementing merge with default options --- test/data/testrepoformerging.tar | Bin 0 -> 92160 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/data/testrepoformerging.tar diff --git a/test/data/testrepoformerging.tar b/test/data/testrepoformerging.tar new file mode 100644 index 0000000000000000000000000000000000000000..c2b145803d58e7d03505b6b7bbfc8c542ef366ad GIT binary patch literal 92160 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 literal 0 HcmV?d00001 From 1f2fdca2c145179085933ca180f44bd3774f6fd8 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 4 Dec 2013 20:04:02 +0100 Subject: [PATCH 3/9] implementing merge with default options - new test --- test/test_repository.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_repository.py b/test/test_repository.py index bcbb48fa3..c44c3df31 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -304,6 +304,9 @@ def test_reset_mixed(self): class RepositoryTest_III(utils.RepoTestCaseForMerging): + def test_merge_none(self): + self.assertRaises(TypeError, self.repo.merge, None) + def test_merge_uptodate(self): branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533' branch_oid = self.repo.get(branch_head_hex).oid From 6855a599e4faa534e0ce24215519d6099c744b57 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Wed, 4 Dec 2013 23:49:26 +0100 Subject: [PATCH 4/9] implementing merge with default options - minor change --- src/mergeresult.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mergeresult.c b/src/mergeresult.c index c0ffddd6e..dfad78bc4 100644 --- a/src/mergeresult.c +++ b/src/mergeresult.c @@ -90,7 +90,7 @@ PyDoc_STRVAR(MergeResult_fastforward_oid__doc__, "Fastforward Oid"); PyObject * MergeResult_fastforward_oid__get__(MergeResult *self) { - if (self->is_fastforward == 1) + if (self->is_fastforward) { Py_INCREF(self->fastforward_oid); return self->fastforward_oid; @@ -123,7 +123,7 @@ PyTypeObject MergeResultType = { "_pygit2.MergeResult", /* tp_name */ sizeof(MergeResult), /* tp_basicsize */ 0, /* tp_itemsize */ - 0, /* tp_dealloc */ + 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ From 3cd8fed386a3cde6612abc1bd9280991912333a5 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 9 Dec 2013 12:45:51 +0100 Subject: [PATCH 5/9] implementing merge - some fixes for the pull request: MergeRestul typedef, pep7 fixes and some error checks --- src/repository.c | 6 ++---- src/types.h | 9 +-------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/repository.c b/src/repository.c index 3d4889c65..81396f9ae 100644 --- a/src/repository.c +++ b/src/repository.c @@ -613,9 +613,8 @@ Repository_merge(Repository *self, PyObject *py_oid) err = git_merge(&merge_result, self->repo, (const git_merge_head **)&oid_merge_head, 1, &default_opts); - if (err < 0) - { - git_merge_result_free(merge_result); + if (err < 0) { + git_merge_head_free(oid_merge_head); goto error; } @@ -627,7 +626,6 @@ Repository_merge(Repository *self, PyObject *py_oid) return py_merge_result; error: - git_merge_head_free(oid_merge_head); return Error_set(err); } diff --git a/src/types.h b/src/types.h index 06504fd36..e69226b73 100644 --- a/src/types.h +++ b/src/types.h @@ -218,13 +218,6 @@ typedef struct { } BlameHunk; /* git_merge */ -typedef struct { - PyObject_HEAD - int is_uptodate; - int is_fastforward; - PyObject* fastforward_oid; - PyObject* status; - -} MergeResult; +SIMPLE_TYPE(MergeResult, git_merge_result, result) #endif From 7d9d2667e59a81514ae93192bc301374f8151fc1 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 9 Dec 2013 15:36:10 +0100 Subject: [PATCH 6/9] implementing merge: merge.rst doc and implementing MergeResult as a simple type that maps git_merge_result to it --- docs/merge.rst | 33 +++++++++++++++++++++++ src/mergeresult.c | 60 +++++++++++++++++++++-------------------- src/repository.c | 1 - test/test_repository.py | 26 ++++++++++++------ 4 files changed, 82 insertions(+), 38 deletions(-) diff --git a/docs/merge.rst b/docs/merge.rst index 55e411ac1..f2ee278af 100644 --- a/docs/merge.rst +++ b/docs/merge.rst @@ -2,4 +2,37 @@ Merge ********************************************************************** +.. contents:: + .. automethod:: pygit2.Repository.merge_base +.. automethod:: pygit2.Repository.merge + +The merge method +================= + +The method does a merge over the current working copy. +It gets an Oid object as a parameter and returns a MergeResult object. + +As its name says, it only does the merge, does not commit nor update the +branch reference in the case of a fastforward. + +For the moment, the merge does not support options, it will perform the +merge with the default ones defined in GIT_MERGE_OPTS_INIT libgit2 constant. + +Example:: + + >>> branch_head_hex = '5ebeeebb320790caf276b9fc8b24546d63316533' + >>> branch_oid = self.repo.get(branch_head_hex).oid + >>> merge_result = self.repo.merge(branch_oid) + +The MergeResult object +====================== + +Represents the result of a merge and contains this fields: + +- is_uptodate: bool, if there wasn't any merge because the repo was already + up to date +- is_fastforward: bool, whether the merge was fastforward or not +- fastforward_oid: Oid, in the case it was a fastforward, this is the + forwarded Oid. +- index: represents the repository index after the merge diff --git a/src/mergeresult.c b/src/mergeresult.c index dfad78bc4..1493d6a95 100644 --- a/src/mergeresult.c +++ b/src/mergeresult.c @@ -39,26 +39,14 @@ extern PyTypeObject IndexType; PyObject * git_merge_result_to_python(git_merge_result *merge_result, Repository *repo) { - git_oid fastforward_oid; MergeResult *py_merge_result; py_merge_result = PyObject_New(MergeResult, &MergeResultType); + if (!py_merge_result) + return NULL; - py_merge_result->is_uptodate = git_merge_result_is_uptodate(merge_result) == GIT_CVAR_TRUE; - - if (git_merge_result_is_fastforward(merge_result) == GIT_CVAR_TRUE) - { - py_merge_result->is_fastforward = GIT_CVAR_TRUE; - git_merge_result_fastforward_oid(&fastforward_oid, merge_result); - py_merge_result->fastforward_oid = git_oid_to_python((const git_oid *)&fastforward_oid); - } - else - { - py_merge_result->is_fastforward = GIT_CVAR_FALSE; - py_merge_result->fastforward_oid = NULL; - } - - py_merge_result->status = Repository_status(repo); + py_merge_result->result = merge_result; + py_merge_result->repo = repo; return (PyObject*) py_merge_result; } @@ -68,7 +56,7 @@ PyDoc_STRVAR(MergeResult_is_uptodate__doc__, "Is up to date"); PyObject * MergeResult_is_uptodate__get__(MergeResult *self) { - if (self->is_uptodate) + if (git_merge_result_is_uptodate(self->result)) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -79,7 +67,7 @@ PyDoc_STRVAR(MergeResult_is_fastforward__doc__, "Is fastforward"); PyObject * MergeResult_is_fastforward__get__(MergeResult *self) { - if (self->is_fastforward) + if (git_merge_result_is_fastforward(self->result)) Py_RETURN_TRUE; else Py_RETURN_FALSE; @@ -90,29 +78,43 @@ PyDoc_STRVAR(MergeResult_fastforward_oid__doc__, "Fastforward Oid"); PyObject * MergeResult_fastforward_oid__get__(MergeResult *self) { - if (self->is_fastforward) - { - Py_INCREF(self->fastforward_oid); - return self->fastforward_oid; + if (git_merge_result_is_fastforward(self->result)) { + git_oid fastforward_oid; + git_merge_result_fastforward_oid(&fastforward_oid, self->result); + return git_oid_to_python((const git_oid *)&fastforward_oid); } - else - Py_RETURN_NONE; + else Py_RETURN_NONE; } -PyDoc_STRVAR(MergeResult_status__doc__, "Merge repository status"); +PyDoc_STRVAR(MergeResult_index__doc__, "Merge repository index"); PyObject * -MergeResult_status__get__(MergeResult *self) +MergeResult_index__get__(MergeResult *self) { - Py_INCREF(self->status); - return self->status; + git_index *index; + Index *py_index; + int err; + + err = git_repository_index(&index, self->repo->repo); + if (err < 0) + return NULL; + + py_index = PyObject_GC_New(Index, &IndexType); + if (!py_index) { + return NULL; + } + + py_index->repo = self->repo; + py_index->index = index; + Py_INCREF(py_index); + return (PyObject*) py_index; } PyGetSetDef MergeResult_getseters[] = { GETTER(MergeResult, is_uptodate), GETTER(MergeResult, is_fastforward), GETTER(MergeResult, fastforward_oid), - GETTER(MergeResult, status), + GETTER(MergeResult, index), {NULL}, }; diff --git a/src/repository.c b/src/repository.c index 81396f9ae..f590507d8 100644 --- a/src/repository.c +++ b/src/repository.c @@ -621,7 +621,6 @@ Repository_merge(Repository *self, PyObject *py_oid) py_merge_result = git_merge_result_to_python(merge_result, self); git_merge_head_free(oid_merge_head); - git_merge_result_free(merge_result); return py_merge_result; diff --git a/test/test_repository.py b/test/test_repository.py index c44c3df31..0ba57663f 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -314,7 +314,7 @@ def test_merge_uptodate(self): self.assertTrue(merge_result.is_uptodate) self.assertFalse(merge_result.is_fastforward) self.assertEquals(None, merge_result.fastforward_oid) - self.assertEquals({}, merge_result.status) + self.assertEquals({}, self.repo.status()) def test_merge_fastforward(self): branch_head_hex = 'e97b4cfd5db0fb4ebabf4f203979ca4e5d1c7c87' @@ -325,7 +325,7 @@ def test_merge_fastforward(self): # Asking twice to assure the reference counting is correct self.assertEquals(branch_head_hex, merge_result.fastforward_oid.hex) self.assertEquals(branch_head_hex, merge_result.fastforward_oid.hex) - self.assertEquals({}, merge_result.status) + self.assertEquals({}, self.repo.status()) def test_merge_no_fastforward_no_conflicts(self): branch_head_hex = '03490f16b15a09913edb3a067a3dc67fbb8d41f1' @@ -333,10 +333,15 @@ def test_merge_no_fastforward_no_conflicts(self): merge_result = self.repo.merge(branch_oid) self.assertFalse(merge_result.is_uptodate) self.assertFalse(merge_result.is_fastforward) - self.assertEquals(None, merge_result.fastforward_oid) # Asking twice to assure the reference counting is correct - self.assertEquals({'bye.txt': 1}, merge_result.status) - self.assertEquals({'bye.txt': 1}, merge_result.status) + self.assertEquals(None, merge_result.fastforward_oid) + self.assertEquals(None, merge_result.fastforward_oid) + self.assertEquals({'bye.txt': 1}, self.repo.status()) + self.assertEquals({'bye.txt': 1}, self.repo.status()) + # Checking the index works as expected + merge_result.index.remove('bye.txt') + merge_result.index.write() + self.assertEquals({'bye.txt': 128}, self.repo.status()) def test_merge_no_fastforward_conflicts(self): branch_head_hex = '1b2bae55ac95a4be3f8983b86cd579226d0eb247' @@ -344,10 +349,15 @@ def test_merge_no_fastforward_conflicts(self): merge_result = self.repo.merge(branch_oid) self.assertFalse(merge_result.is_uptodate) self.assertFalse(merge_result.is_fastforward) - self.assertEquals(None, merge_result.fastforward_oid) # Asking twice to assure the reference counting is correct - self.assertEquals({'.gitignore': 132}, merge_result.status) - self.assertEquals({'.gitignore': 132}, merge_result.status) + self.assertEquals(None, merge_result.fastforward_oid) + self.assertEquals(None, merge_result.fastforward_oid) + self.assertEquals({'.gitignore': 132}, self.repo.status()) + self.assertEquals({'.gitignore': 132}, self.repo.status()) + # Checking the index works as expected + merge_result.index.add('.gitignore') + merge_result.index.write() + self.assertEquals({'.gitignore': 2}, self.repo.status()) def test_merge_invalid_hex(self): branch_head_hex = '12345678' From 1cf6e748e539fa3f510e39cbde28174431940855 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Mon, 9 Dec 2013 15:51:29 +0100 Subject: [PATCH 7/9] implementing merge: some small fixes in merge.rst --- docs/merge.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/merge.rst b/docs/merge.rst index f2ee278af..ec04c09ff 100644 --- a/docs/merge.rst +++ b/docs/merge.rst @@ -28,11 +28,11 @@ Example:: The MergeResult object ====================== -Represents the result of a merge and contains this fields: +Represents the result of a merge and contains these fields: - is_uptodate: bool, if there wasn't any merge because the repo was already - up to date + up to date - is_fastforward: bool, whether the merge was fastforward or not - fastforward_oid: Oid, in the case it was a fastforward, this is the - forwarded Oid. + forwarded Oid. - index: represents the repository index after the merge From 0556ab0cd8828d2876307d0cd889dcfa9797d39b Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 10 Dec 2013 16:01:48 +0100 Subject: [PATCH 8/9] implementing merge: removing index field from MergeResult --- src/mergeresult.c | 25 ------------------------- test/test_repository.py | 8 ++++---- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/mergeresult.c b/src/mergeresult.c index 1493d6a95..1ce4497e0 100644 --- a/src/mergeresult.c +++ b/src/mergeresult.c @@ -86,35 +86,10 @@ MergeResult_fastforward_oid__get__(MergeResult *self) else Py_RETURN_NONE; } -PyDoc_STRVAR(MergeResult_index__doc__, "Merge repository index"); - -PyObject * -MergeResult_index__get__(MergeResult *self) -{ - git_index *index; - Index *py_index; - int err; - - err = git_repository_index(&index, self->repo->repo); - if (err < 0) - return NULL; - - py_index = PyObject_GC_New(Index, &IndexType); - if (!py_index) { - return NULL; - } - - py_index->repo = self->repo; - py_index->index = index; - Py_INCREF(py_index); - return (PyObject*) py_index; -} - PyGetSetDef MergeResult_getseters[] = { GETTER(MergeResult, is_uptodate), GETTER(MergeResult, is_fastforward), GETTER(MergeResult, fastforward_oid), - GETTER(MergeResult, index), {NULL}, }; diff --git a/test/test_repository.py b/test/test_repository.py index 0ba57663f..11ebc4de3 100644 --- a/test/test_repository.py +++ b/test/test_repository.py @@ -339,8 +339,8 @@ def test_merge_no_fastforward_no_conflicts(self): self.assertEquals({'bye.txt': 1}, self.repo.status()) self.assertEquals({'bye.txt': 1}, self.repo.status()) # Checking the index works as expected - merge_result.index.remove('bye.txt') - merge_result.index.write() + self.repo.index.remove('bye.txt') + self.repo.index.write() self.assertEquals({'bye.txt': 128}, self.repo.status()) def test_merge_no_fastforward_conflicts(self): @@ -355,8 +355,8 @@ def test_merge_no_fastforward_conflicts(self): self.assertEquals({'.gitignore': 132}, self.repo.status()) self.assertEquals({'.gitignore': 132}, self.repo.status()) # Checking the index works as expected - merge_result.index.add('.gitignore') - merge_result.index.write() + self.repo.index.add('.gitignore') + self.repo.index.write() self.assertEquals({'.gitignore': 2}, self.repo.status()) def test_merge_invalid_hex(self): From 1938147b3dfc1103ee88ea26af24441ff63019c3 Mon Sep 17 00:00:00 2001 From: Victor Garcia Date: Tue, 10 Dec 2013 16:02:37 +0100 Subject: [PATCH 9/9] implementing merge: removing index field from merge.rst --- docs/merge.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/merge.rst b/docs/merge.rst index ec04c09ff..82c243a7d 100644 --- a/docs/merge.rst +++ b/docs/merge.rst @@ -35,4 +35,3 @@ Represents the result of a merge and contains these fields: - is_fastforward: bool, whether the merge was fastforward or not - fastforward_oid: Oid, in the case it was a fastforward, this is the forwarded Oid. -- index: represents the repository index after the merge