Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing merge with default options #295

Merged
merged 9 commits into from
Dec 10, 2013
32 changes: 32 additions & 0 deletions docs/merge.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,36 @@
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 these 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.
138 changes: 138 additions & 0 deletions src/mergeresult.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* 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 <Python.h>
#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)
{
MergeResult *py_merge_result;

py_merge_result = PyObject_New(MergeResult, &MergeResultType);
if (!py_merge_result)
return NULL;

py_merge_result->result = merge_result;
py_merge_result->repo = repo;

return (PyObject*) py_merge_result;
}

PyDoc_STRVAR(MergeResult_is_uptodate__doc__, "Is up to date");

PyObject *
MergeResult_is_uptodate__get__(MergeResult *self)
{
if (git_merge_result_is_uptodate(self->result))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}

PyDoc_STRVAR(MergeResult_is_fastforward__doc__, "Is fastforward");

PyObject *
MergeResult_is_fastforward__get__(MergeResult *self)
{
if (git_merge_result_is_fastforward(self->result))
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
}

PyDoc_STRVAR(MergeResult_fastforward_oid__doc__, "Fastforward Oid");

PyObject *
MergeResult_fastforward_oid__get__(MergeResult *self)
{
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;
}

PyGetSetDef MergeResult_getseters[] = {
GETTER(MergeResult, is_uptodate),
GETTER(MergeResult, is_fastforward),
GETTER(MergeResult, fastforward_oid),
{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 */
};

37 changes: 37 additions & 0 deletions src/mergeresult.h
Original file line number Diff line number Diff line change
@@ -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 <Python.h>
#include <git2.h>

PyObject* git_merge_result_to_python(git_merge_result *merge_result, Repository *repo);

#endif
5 changes: 5 additions & 0 deletions src/pygit2.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ extern PyTypeObject NoteIterType;
extern PyTypeObject BlameType;
extern PyTypeObject BlameIterType;
extern PyTypeObject BlameHunkType;
extern PyTypeObject MergeResultType;



Expand Down Expand Up @@ -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();

Expand Down
53 changes: 52 additions & 1 deletion src/repository.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "remote.h"
#include "branch.h"
#include "blame.h"
#include "mergeresult.h"
#include <git2/odb_backend.h>

extern PyObject *GitError;
Expand Down Expand Up @@ -578,6 +579,55 @@ 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_head_free(oid_merge_head);
goto error;
}

py_merge_result = git_merge_result_to_python(merge_result, self);

git_merge_head_free(oid_merge_head);

return py_merge_result;

error:
return Error_set(err);
}

PyDoc_STRVAR(Repository_walk__doc__,
"walk(oid, sort_mode) -> iterator\n"
"\n"
Expand Down Expand Up @@ -1093,7 +1143,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;
Expand Down Expand Up @@ -1551,6 +1601,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),
Expand Down
4 changes: 3 additions & 1 deletion src/repository.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,7 @@ typedef struct {
char boundary;
} BlameHunk;

/* git_merge */
SIMPLE_TYPE(MergeResult, git_merge_result, result)

#endif
Binary file added test/data/testrepoformerging.tar
Binary file not shown.
Loading