Merge pull request #229 from cholin/features/diff_refactoring
refactoring Tree.diff(), Index.diff() into seperate methods and added a Repository.diff() method.
This commit is contained in:
@@ -2,27 +2,34 @@
|
|||||||
Diff
|
Diff
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
|
|
||||||
A diff shows the changes between trees, an index or the working dir::
|
.. contents::
|
||||||
|
|
||||||
>>> head = repo.revparse_single('HEAD')
|
A diff shows the changes between trees, an index or the working dir.
|
||||||
|
|
||||||
# Diff two trees
|
.. automethod:: pygit2.Repository.diff
|
||||||
>>> t0 = head.tree
|
|
||||||
>>> t1 = head.parents[0].tree
|
|
||||||
>>> diff = t1.diff(t0)
|
|
||||||
|
|
||||||
# Diff a tree with the index
|
Examples
|
||||||
>>> diff = head.tree.diff(repo.index)
|
|
||||||
|
|
||||||
# Diff a tree with the current working dir
|
.. code-block:: python
|
||||||
>>> diff = head.tree.diff()
|
|
||||||
|
# Changes between commits
|
||||||
|
>>> t0 = revparse_single('HEAD')
|
||||||
|
>>> t1 = revparse_single('HEAD^')
|
||||||
|
>>> repo.diff(t0, t1)
|
||||||
|
>>> t0.diff(t1) # equivalent
|
||||||
|
>>> repo.diff('HEAD', 'HEAD^') # equivalent
|
||||||
|
|
||||||
# Get all patches for a diff
|
# Get all patches for a diff
|
||||||
>>> t0 = repo.revparse_single('HEAD^').tree
|
>>> diff = repo.diff('HEAD^', 'HEAD~3')
|
||||||
>>> t1 = repo.revparse_single('HEAD~3').tree
|
|
||||||
>>> diff = t0.diff(t1)
|
|
||||||
>>> patches = [p for p in diff]
|
>>> patches = [p for p in diff]
|
||||||
|
|
||||||
|
# Diffing the empty tree
|
||||||
|
>>> tree = revparse_single('HEAD').tree
|
||||||
|
>>> tree.diff_to_tree()
|
||||||
|
|
||||||
|
# Diff empty tree to a tree
|
||||||
|
>>> tree = revparse_single('HEAD').tree
|
||||||
|
>>> tree.diff_to_tree(swap=True)
|
||||||
|
|
||||||
The Diff type
|
The Diff type
|
||||||
====================
|
====================
|
||||||
|
@@ -159,7 +159,9 @@ interfaces.
|
|||||||
|
|
||||||
Return an iterator over the entries of the tree.
|
Return an iterator over the entries of the tree.
|
||||||
|
|
||||||
.. automethod:: pygit2.Tree.diff
|
.. automethod:: pygit2.Tree.diff_to_tree
|
||||||
|
.. automethod:: pygit2.Tree.diff_to_workdir
|
||||||
|
.. automethod:: pygit2.Tree.diff_to_index
|
||||||
|
|
||||||
Tree entries
|
Tree entries
|
||||||
------------
|
------------
|
||||||
|
@@ -33,7 +33,8 @@ The Index type
|
|||||||
.. automethod:: pygit2.Index.write
|
.. automethod:: pygit2.Index.write
|
||||||
.. automethod:: pygit2.Index.read_tree
|
.. automethod:: pygit2.Index.read_tree
|
||||||
.. automethod:: pygit2.Index.write_tree
|
.. automethod:: pygit2.Index.write_tree
|
||||||
.. automethod:: pygit2.Index.diff
|
.. automethod:: pygit2.Index.diff_to_tree
|
||||||
|
.. automethod:: pygit2.Index.diff_to_workdir
|
||||||
|
|
||||||
|
|
||||||
The IndexEntry type
|
The IndexEntry type
|
||||||
|
@@ -31,8 +31,8 @@ from string import hexdigits
|
|||||||
# Import from pygit2
|
# Import from pygit2
|
||||||
from _pygit2 import Repository as _Repository
|
from _pygit2 import Repository as _Repository
|
||||||
from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN
|
from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN
|
||||||
from _pygit2 import GIT_CHECKOUT_SAFE_CREATE
|
from _pygit2 import GIT_CHECKOUT_SAFE_CREATE, GIT_DIFF_NORMAL
|
||||||
from _pygit2 import Reference
|
from _pygit2 import Reference, Tree, Commit, Blob
|
||||||
|
|
||||||
|
|
||||||
class Repository(_Repository):
|
class Repository(_Repository):
|
||||||
@@ -128,3 +128,90 @@ class Repository(_Repository):
|
|||||||
treeish = self[oid]
|
treeish = self[oid]
|
||||||
self.checkout_tree(treeish, strategy)
|
self.checkout_tree(treeish, strategy)
|
||||||
self.head = refname
|
self.head = refname
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Diff
|
||||||
|
#
|
||||||
|
def diff(self, a=None, b=None, cached=False, flags=GIT_DIFF_NORMAL,
|
||||||
|
context_lines=3, interhunk_lines=0):
|
||||||
|
"""
|
||||||
|
Show changes between the working tree and the index or a tree,
|
||||||
|
changes between the index and a tree, changes between two trees, or
|
||||||
|
changes between two blobs.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
|
||||||
|
cached
|
||||||
|
use staged changes instead of workdir
|
||||||
|
|
||||||
|
flag
|
||||||
|
a GIT_DIFF_* constant
|
||||||
|
|
||||||
|
context_lines
|
||||||
|
the number of unchanged lines that define the boundary
|
||||||
|
of a hunk (and to display before and after)\n"
|
||||||
|
|
||||||
|
interhunk_lines
|
||||||
|
the maximum number of unchanged lines between hunk
|
||||||
|
boundaries before the hunks will be merged into a one
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
# Changes in the working tree not yet staged for the next commit
|
||||||
|
>>> diff()
|
||||||
|
|
||||||
|
# Changes between the index and your last commit
|
||||||
|
>>> diff(cached=True)
|
||||||
|
|
||||||
|
# Changes in the working tree since your last commit
|
||||||
|
>>> diff('HEAD')
|
||||||
|
|
||||||
|
# Changes between commits
|
||||||
|
>>> t0 = revparse_single('HEAD')
|
||||||
|
>>> t1 = revparse_single('HEAD^')
|
||||||
|
>>> diff(t0, t1)
|
||||||
|
>>> diff('HEAD', 'HEAD^') # equivalent
|
||||||
|
|
||||||
|
If you want to diff a tree against an empty tree, use the low level
|
||||||
|
API (Tree.diff_to_tree()) directly.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def treeish_to_tree(obj):
|
||||||
|
try:
|
||||||
|
obj = self.revparse_single(obj)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if isinstance(obj, Commit):
|
||||||
|
return obj.tree
|
||||||
|
elif isinstance(obj, Reference):
|
||||||
|
oid = obj.resolve().target
|
||||||
|
return self[oid]
|
||||||
|
|
||||||
|
a = treeish_to_tree(a) or a
|
||||||
|
b = treeish_to_tree(b) or b
|
||||||
|
|
||||||
|
opt_keys = ['flags', 'context_lines', 'interhunk_lines']
|
||||||
|
opt_values = [flags, context_lines, interhunk_lines]
|
||||||
|
|
||||||
|
# Case 1: Diff tree to tree
|
||||||
|
if isinstance(a, Tree) and isinstance(b, Tree):
|
||||||
|
return a.diff_to_tree(b, **dict(zip(opt_keys, opt_values)))
|
||||||
|
|
||||||
|
# Case 2: Index to workdir
|
||||||
|
elif a is None and b is None:
|
||||||
|
return self.index.diff_to_workdir(*opt_values)
|
||||||
|
|
||||||
|
# Case 3: Diff tree to index or workdir
|
||||||
|
elif isinstance(a, Tree) and b is None:
|
||||||
|
if cached:
|
||||||
|
return a.diff_to_index(self.index, *opt_values)
|
||||||
|
else:
|
||||||
|
return a.diff_to_workdir(*opt_values)
|
||||||
|
|
||||||
|
# Case 4: Diff blob to blob
|
||||||
|
if isinstance(a, Blob) and isinstance(b, Blob):
|
||||||
|
raise NotImplementedError('git_diff_blob_to_blob()')
|
||||||
|
|
||||||
|
raise ValueError("Only blobs and treeish can be diffed")
|
||||||
|
38
src/diff.c
38
src/diff.c
@@ -42,6 +42,21 @@ extern PyTypeObject HunkType;
|
|||||||
|
|
||||||
PyTypeObject PatchType;
|
PyTypeObject PatchType;
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
wrap_diff(git_diff_list *diff, Repository *repo)
|
||||||
|
{
|
||||||
|
Diff *py_diff;
|
||||||
|
|
||||||
|
py_diff = PyObject_New(Diff, &DiffType);
|
||||||
|
if (py_diff) {
|
||||||
|
Py_INCREF(repo);
|
||||||
|
py_diff->repo = repo;
|
||||||
|
py_diff->list = diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (PyObject*) py_diff;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
diff_get_patch_byindex(git_diff_list* list, size_t idx)
|
diff_get_patch_byindex(git_diff_list* list, size_t idx)
|
||||||
{
|
{
|
||||||
@@ -50,9 +65,11 @@ diff_get_patch_byindex(git_diff_list* list, size_t idx)
|
|||||||
git_diff_patch* patch = NULL;
|
git_diff_patch* patch = NULL;
|
||||||
size_t i, j, hunk_amounts, lines_in_hunk, line_len, header_len;
|
size_t i, j, hunk_amounts, lines_in_hunk, line_len, header_len;
|
||||||
const char* line, *header;
|
const char* line, *header;
|
||||||
|
char line_origin;
|
||||||
int err;
|
int err;
|
||||||
Hunk *py_hunk = NULL;
|
Hunk *py_hunk = NULL;
|
||||||
Patch *py_patch = NULL;
|
Patch *py_patch = NULL;
|
||||||
|
PyObject *py_line_origin=NULL, *py_line=NULL;
|
||||||
|
|
||||||
err = git_diff_get_patch(&patch, &delta, list, idx);
|
err = git_diff_get_patch(&patch, &delta, list, idx);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@@ -84,18 +101,24 @@ diff_get_patch_byindex(git_diff_list* list, size_t idx)
|
|||||||
py_hunk->new_start = range->new_start;
|
py_hunk->new_start = range->new_start;
|
||||||
py_hunk->new_lines = range->new_lines;
|
py_hunk->new_lines = range->new_lines;
|
||||||
|
|
||||||
py_hunk->lines = PyList_New(lines_in_hunk + 1);
|
py_hunk->lines = PyList_New(lines_in_hunk);
|
||||||
PyList_SetItem(py_hunk->lines, 0,
|
for (j=0; j < lines_in_hunk; ++j) {
|
||||||
to_unicode_n(header, header_len, NULL, NULL));
|
err = git_diff_patch_get_line_in_hunk(&line_origin,
|
||||||
for (j=1; j < lines_in_hunk + 1; ++j) {
|
&line, &line_len, NULL, NULL, patch, i, j);
|
||||||
err = git_diff_patch_get_line_in_hunk(&py_hunk->origin,
|
|
||||||
&line, &line_len, NULL, NULL, patch, i, j - 1);
|
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
py_line_origin = to_unicode_n(&line_origin, 1, NULL, NULL);
|
||||||
|
py_line = to_unicode_n(line, line_len, NULL, NULL);
|
||||||
PyList_SetItem(py_hunk->lines, j,
|
PyList_SetItem(py_hunk->lines, j,
|
||||||
to_unicode_n(line, line_len, NULL, NULL));
|
Py_BuildValue("OO",
|
||||||
|
py_line_origin,
|
||||||
|
py_line
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Py_DECREF(py_line_origin);
|
||||||
|
Py_DECREF(py_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyList_SetItem((PyObject*) py_patch->hunks, i,
|
PyList_SetItem((PyObject*) py_patch->hunks, i,
|
||||||
@@ -279,7 +302,6 @@ Hunk_dealloc(Hunk *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyMemberDef Hunk_members[] = {
|
PyMemberDef Hunk_members[] = {
|
||||||
MEMBER(Hunk, origin, T_CHAR, "origin."),
|
|
||||||
MEMBER(Hunk, old_start, T_INT, "Old start."),
|
MEMBER(Hunk, old_start, T_INT, "Old start."),
|
||||||
MEMBER(Hunk, old_lines, T_INT, "Old lines."),
|
MEMBER(Hunk, old_lines, T_INT, "Old lines."),
|
||||||
MEMBER(Hunk, new_start, T_INT, "New start."),
|
MEMBER(Hunk, new_start, T_INT, "New start."),
|
||||||
|
@@ -41,4 +41,6 @@
|
|||||||
PyObject* Diff_changes(Diff *self);
|
PyObject* Diff_changes(Diff *self);
|
||||||
PyObject* Diff_patch(Diff *self);
|
PyObject* Diff_patch(Diff *self);
|
||||||
|
|
||||||
|
PyObject* wrap_diff(git_diff_list *diff, Repository *repo);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
89
src/index.c
89
src/index.c
@@ -31,6 +31,7 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "oid.h"
|
#include "oid.h"
|
||||||
|
#include "diff.h"
|
||||||
#include "index.h"
|
#include "index.h"
|
||||||
|
|
||||||
extern PyTypeObject IndexType;
|
extern PyTypeObject IndexType;
|
||||||
@@ -114,54 +115,83 @@ Index_clear(Index *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Index_diff__doc__,
|
PyDoc_STRVAR(Index_diff_to_workdir__doc__,
|
||||||
"diff([tree]) -> Diff\n"
|
"diff_to_workdir([flag, context_lines, interhunk_lines]) -> Diff\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Return a :py:class:`~pygit2.Diff` object with the differences between the\n"
|
"Return a :py:class:`~pygit2.Diff` object with the differences between the\n"
|
||||||
"index and the working copy. If a :py:class:`~pygit2.Tree` object is\n"
|
"index and the working copy.\n"
|
||||||
"passed, return the diferences between the index and the given tree.");
|
"\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"\n"
|
||||||
|
"flag: a GIT_DIFF_* constant.\n"
|
||||||
|
"\n"
|
||||||
|
"context_lines: the number of unchanged lines that define the boundary\n"
|
||||||
|
" of a hunk (and to display before and after)\n"
|
||||||
|
"\n"
|
||||||
|
"interhunk_lines: the maximum number of unchanged lines between hunk\n"
|
||||||
|
" boundaries before the hunks will be merged into a one.\n");
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
Index_diff(Index *self, PyObject *args)
|
Index_diff_to_workdir(Index *self, PyObject *args)
|
||||||
{
|
{
|
||||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
git_diff_list *diff;
|
git_diff_list *diff;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
Diff *py_diff;
|
if (!PyArg_ParseTuple(args, "|IHH", &opts.flags, &opts.context_lines,
|
||||||
PyObject *py_obj = NULL;
|
&opts.interhunk_lines))
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|O", &py_obj))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (py_obj == NULL) {
|
|
||||||
err = git_diff_index_to_workdir(
|
err = git_diff_index_to_workdir(
|
||||||
&diff,
|
&diff,
|
||||||
self->repo->repo,
|
self->repo->repo,
|
||||||
self->index,
|
self->index,
|
||||||
&opts);
|
&opts);
|
||||||
} else if (PyObject_TypeCheck(py_obj, &TreeType)) {
|
|
||||||
err = git_diff_tree_to_index(
|
|
||||||
&diff,
|
|
||||||
self->repo->repo,
|
|
||||||
((Tree *)py_obj)->tree,
|
|
||||||
self->index,
|
|
||||||
&opts);
|
|
||||||
} else {
|
|
||||||
PyErr_SetObject(PyExc_TypeError, py_obj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
py_diff = PyObject_New(Diff, &DiffType);
|
return wrap_diff(diff, self->repo);
|
||||||
if (py_diff) {
|
}
|
||||||
Py_INCREF(self->repo);
|
|
||||||
py_diff->repo = self->repo;
|
|
||||||
py_diff->list = diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (PyObject*)py_diff;
|
PyDoc_STRVAR(Index_diff_to_tree__doc__,
|
||||||
|
"diff_to_tree(tree [, flag, context_lines, interhunk_lines]) -> Diff\n"
|
||||||
|
"\n"
|
||||||
|
"Return a :py:class:`~pygit2.Diff` object with the differences between the\n"
|
||||||
|
"index and the given tree.\n"
|
||||||
|
"\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"\n"
|
||||||
|
"tree: the tree to diff.\n"
|
||||||
|
"\n"
|
||||||
|
"flag: a GIT_DIFF_* constant.\n"
|
||||||
|
"\n"
|
||||||
|
"context_lines: the number of unchanged lines that define the boundary\n"
|
||||||
|
" of a hunk (and to display before and after)\n"
|
||||||
|
"\n"
|
||||||
|
"interhunk_lines: the maximum number of unchanged lines between hunk\n"
|
||||||
|
" boundaries before the hunks will be merged into a one.\n");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Index_diff_to_tree(Index *self, PyObject *args)
|
||||||
|
{
|
||||||
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
|
git_diff_list *diff;
|
||||||
|
git_repository* repo;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
Tree *py_tree = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O!|IHH", &TreeType, &py_tree, &opts.flags,
|
||||||
|
&opts.context_lines, &opts.interhunk_lines))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
repo = git_tree_owner(py_tree->tree);
|
||||||
|
err = git_diff_tree_to_index(&diff, repo, py_tree->tree, self->index, &opts);
|
||||||
|
if (err < 0)
|
||||||
|
return Error_set(err);
|
||||||
|
|
||||||
|
return wrap_diff(diff, self->repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -393,7 +423,8 @@ PyMethodDef Index_methods[] = {
|
|||||||
METHOD(Index, add, METH_VARARGS),
|
METHOD(Index, add, METH_VARARGS),
|
||||||
METHOD(Index, remove, METH_VARARGS),
|
METHOD(Index, remove, METH_VARARGS),
|
||||||
METHOD(Index, clear, METH_NOARGS),
|
METHOD(Index, clear, METH_NOARGS),
|
||||||
METHOD(Index, diff, METH_VARARGS),
|
METHOD(Index, diff_to_workdir, METH_VARARGS),
|
||||||
|
METHOD(Index, diff_to_tree, METH_VARARGS),
|
||||||
METHOD(Index, _find, METH_O),
|
METHOD(Index, _find, METH_O),
|
||||||
METHOD(Index, read, METH_NOARGS),
|
METHOD(Index, read, METH_NOARGS),
|
||||||
METHOD(Index, write, METH_NOARGS),
|
METHOD(Index, write, METH_NOARGS),
|
||||||
|
@@ -383,6 +383,14 @@ moduleinit(PyObject* m)
|
|||||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNTRACKED)
|
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNTRACKED)
|
||||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNMODIFIED)
|
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNMODIFIED)
|
||||||
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS)
|
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_UNTRACKED_DIRS)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_DISABLE_PATHSPEC_MATCH)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_DELTAS_ARE_ICASE)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_SKIP_BINARY_CHECK)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE_TREES)
|
||||||
|
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_IGNORED_DIRS)
|
||||||
/* Flags for diff find similar */
|
/* Flags for diff find similar */
|
||||||
/* --find-renames */
|
/* --find-renames */
|
||||||
ADD_CONSTANT_INT(m, GIT_DIFF_FIND_RENAMES)
|
ADD_CONSTANT_INT(m, GIT_DIFF_FIND_RENAMES)
|
||||||
|
@@ -497,6 +497,9 @@ Repository_config__get__(Repository *self)
|
|||||||
|
|
||||||
py_config->config = config;
|
py_config->config = config;
|
||||||
self->config = (PyObject*)py_config;
|
self->config = (PyObject*)py_config;
|
||||||
|
// We need 2 refs here.
|
||||||
|
// One is returned, one is keep internally.
|
||||||
|
Py_INCREF(self->config);
|
||||||
} else {
|
} else {
|
||||||
Py_INCREF(self->config);
|
Py_INCREF(self->config);
|
||||||
}
|
}
|
||||||
|
159
src/tree.c
159
src/tree.c
@@ -33,6 +33,7 @@
|
|||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
#include "oid.h"
|
#include "oid.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "diff.h"
|
||||||
|
|
||||||
extern PyTypeObject TreeType;
|
extern PyTypeObject TreeType;
|
||||||
extern PyTypeObject DiffType;
|
extern PyTypeObject DiffType;
|
||||||
@@ -270,70 +271,138 @@ Tree_getitem(Tree *self, PyObject *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyDoc_STRVAR(Tree_diff__doc__,
|
PyDoc_STRVAR(Tree_diff_to_workdir__doc__,
|
||||||
"diff([obj, flags]) -> Diff\n"
|
"diff_to_workdir([flags, context_lines, interhunk_lines]) -> Diff\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Get changes between current tree instance with another tree, an index or\n"
|
"Show the changes between the :py:class:`~pygit2.Tree` and the workdir.\n"
|
||||||
"the working dir.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"Arguments:\n"
|
"Arguments:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"obj\n"
|
"flag: a GIT_DIFF_* constant.\n"
|
||||||
" If not given compare diff against working dir. Possible valid\n"
|
|
||||||
" arguments are instances of Tree or Index.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"flags\n"
|
"context_lines: the number of unchanged lines that define the boundary\n"
|
||||||
" TODO");
|
" of a hunk (and to display before and after)\n"
|
||||||
|
"\n"
|
||||||
|
"interhunk_lines: the maximum number of unchanged lines between hunk\n"
|
||||||
|
" boundaries before the hunks will be merged into a one.\n");
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
Tree_diff(Tree *self, PyObject *args, PyObject *kwds)
|
Tree_diff_to_workdir(Tree *self, PyObject *args)
|
||||||
{
|
{
|
||||||
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
git_diff_list *diff;
|
git_diff_list *diff;
|
||||||
git_tree* tree = NULL;
|
git_repository* repo;
|
||||||
git_index* index;
|
int err;
|
||||||
git_repository *repo;
|
|
||||||
int err, empty_tree = 0;
|
|
||||||
char *keywords[] = {"obj", "flags", "empty_tree", NULL};
|
|
||||||
|
|
||||||
Diff *py_diff;
|
if (!PyArg_ParseTuple(args, "|IHH", &opts.flags, &opts.context_lines,
|
||||||
PyObject *py_obj = NULL;
|
&opts.interhunk_lines))
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oii", keywords,
|
|
||||||
&py_obj, &opts.flags, &empty_tree))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
repo = git_tree_owner(self->tree);
|
repo = git_tree_owner(self->tree);
|
||||||
if (py_obj == NULL) {
|
|
||||||
if (empty_tree > 0)
|
|
||||||
err = git_diff_tree_to_tree(&diff, repo, self->tree, NULL, &opts);
|
|
||||||
else
|
|
||||||
err = git_diff_tree_to_workdir(&diff, repo, self->tree, &opts);
|
err = git_diff_tree_to_workdir(&diff, repo, self->tree, &opts);
|
||||||
|
|
||||||
} else if (PyObject_TypeCheck(py_obj, &TreeType)) {
|
|
||||||
tree = ((Tree *)py_obj)->tree;
|
|
||||||
err = git_diff_tree_to_tree(&diff, repo, self->tree, tree, &opts);
|
|
||||||
|
|
||||||
} else if (PyObject_TypeCheck(py_obj, &IndexType)) {
|
|
||||||
index = ((Index *)py_obj)->index;
|
|
||||||
err = git_diff_tree_to_index(&diff, repo, self->tree, index, &opts);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PyErr_SetObject(PyExc_TypeError, py_obj);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return Error_set(err);
|
return Error_set(err);
|
||||||
|
|
||||||
py_diff = PyObject_New(Diff, &DiffType);
|
return wrap_diff(diff, self->repo);
|
||||||
if (py_diff) {
|
}
|
||||||
Py_INCREF(self->repo);
|
|
||||||
py_diff->repo = self->repo;
|
|
||||||
py_diff->list = diff;
|
PyDoc_STRVAR(Tree_diff_to_index__doc__,
|
||||||
|
"diff_to_index(index, [flags, context_lines, interhunk_lines]) -> Diff\n"
|
||||||
|
"\n"
|
||||||
|
"Show the changes between the index and a given :py:class:`~pygit2.Tree`.\n"
|
||||||
|
"\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"\n"
|
||||||
|
"tree: the :py:class:`~pygit2.Tree` to diff.\n"
|
||||||
|
"\n"
|
||||||
|
"flag: a GIT_DIFF_* constant.\n"
|
||||||
|
"\n"
|
||||||
|
"context_lines: the number of unchanged lines that define the boundary\n"
|
||||||
|
" of a hunk (and to display before and after)\n"
|
||||||
|
"\n"
|
||||||
|
"interhunk_lines: the maximum number of unchanged lines between hunk\n"
|
||||||
|
" boundaries before the hunks will be merged into a one.\n");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Tree_diff_to_index(Tree *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
|
git_diff_list *diff;
|
||||||
|
git_repository* repo;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
Index *py_idx = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O!|IHH", &IndexType, &py_idx, &opts.flags,
|
||||||
|
&opts.context_lines,
|
||||||
|
&opts.interhunk_lines))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
repo = git_tree_owner(self->tree);
|
||||||
|
err = git_diff_tree_to_index(&diff, repo, self->tree, py_idx->index, &opts);
|
||||||
|
if (err < 0)
|
||||||
|
return Error_set(err);
|
||||||
|
|
||||||
|
return wrap_diff(diff, self->repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyDoc_STRVAR(Tree_diff_to_tree__doc__,
|
||||||
|
"diff_to_tree([tree, flags, context_lines, interhunk_lines, swap]) -> Diff\n"
|
||||||
|
"\n"
|
||||||
|
"Show the changes between two trees\n"
|
||||||
|
"\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"\n"
|
||||||
|
"tree: the :py:class:`~pygit2.Tree` to diff. If no tree is given the empty\n"
|
||||||
|
" tree will be used instead.\n"
|
||||||
|
"\n"
|
||||||
|
"flag: a GIT_DIFF_* constant.\n"
|
||||||
|
"\n"
|
||||||
|
"context_lines: the number of unchanged lines that define the boundary\n"
|
||||||
|
" of a hunk (and to display before and after)\n"
|
||||||
|
"\n"
|
||||||
|
"interhunk_lines: the maximum number of unchanged lines between hunk\n"
|
||||||
|
" boundaries before the hunks will be merged into a one.\n"
|
||||||
|
"\n"
|
||||||
|
"swap: instead of diffing a to b. Diff b to a.\n");
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
Tree_diff_to_tree(Tree *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
|
||||||
|
git_diff_list *diff;
|
||||||
|
git_tree *from, *to, *tmp;
|
||||||
|
git_repository* repo;
|
||||||
|
int err, swap = 0;
|
||||||
|
char *keywords[] = {"obj", "flags", "context_lines", "interhunk_lines",
|
||||||
|
"swap", NULL};
|
||||||
|
|
||||||
|
Tree *py_tree = NULL;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O!IHHi", keywords,
|
||||||
|
&TreeType, &py_tree, &opts.flags,
|
||||||
|
&opts.context_lines,
|
||||||
|
&opts.interhunk_lines, &swap))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
repo = git_tree_owner(self->tree);
|
||||||
|
to = (py_tree == NULL) ? NULL : py_tree->tree;
|
||||||
|
from = self->tree;
|
||||||
|
if (swap > 0) {
|
||||||
|
tmp = from;
|
||||||
|
from = to;
|
||||||
|
to = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PyObject*)py_diff;
|
err = git_diff_tree_to_tree(&diff, repo, from, to, &opts);
|
||||||
|
|
||||||
|
if (err < 0)
|
||||||
|
return Error_set(err);
|
||||||
|
|
||||||
|
return wrap_diff(diff, self->repo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -355,7 +424,9 @@ PyMappingMethods Tree_as_mapping = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PyMethodDef Tree_methods[] = {
|
PyMethodDef Tree_methods[] = {
|
||||||
METHOD(Tree, diff, METH_VARARGS | METH_KEYWORDS),
|
METHOD(Tree, diff_to_tree, METH_VARARGS | METH_KEYWORDS),
|
||||||
|
METHOD(Tree, diff_to_workdir, METH_VARARGS),
|
||||||
|
METHOD(Tree, diff_to_index, METH_VARARGS | METH_KEYWORDS),
|
||||||
{NULL}
|
{NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -118,7 +118,6 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
PyObject_HEAD
|
PyObject_HEAD
|
||||||
PyObject* lines;
|
PyObject* lines;
|
||||||
char origin;
|
|
||||||
int old_start;
|
int old_start;
|
||||||
int old_lines;
|
int old_lines;
|
||||||
int new_start;
|
int new_start;
|
||||||
|
@@ -33,6 +33,7 @@ import unittest
|
|||||||
import pygit2
|
import pygit2
|
||||||
from pygit2 import GIT_DIFF_INCLUDE_UNMODIFIED
|
from pygit2 import GIT_DIFF_INCLUDE_UNMODIFIED
|
||||||
from . import utils
|
from . import utils
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
COMMIT_SHA1_1 = '5fe808e8953c12735680c257f56600cb0de44b10'
|
COMMIT_SHA1_1 = '5fe808e8953c12735680c257f56600cb0de44b10'
|
||||||
@@ -60,7 +61,7 @@ index 297efb8..0000000
|
|||||||
-c/d contents
|
-c/d contents
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DIFF_INDEX_EXPECTED = [
|
DIFF_HEAD_TO_INDEX_EXPECTED = [
|
||||||
'staged_changes',
|
'staged_changes',
|
||||||
'staged_changes_file_deleted',
|
'staged_changes_file_deleted',
|
||||||
'staged_changes_file_modified',
|
'staged_changes_file_modified',
|
||||||
@@ -71,7 +72,7 @@ DIFF_INDEX_EXPECTED = [
|
|||||||
'staged_new_file_modified'
|
'staged_new_file_modified'
|
||||||
]
|
]
|
||||||
|
|
||||||
DIFF_WORKDIR_EXPECTED = [
|
DIFF_HEAD_TO_WORKDIR_EXPECTED = [
|
||||||
'file_deleted',
|
'file_deleted',
|
||||||
'modified_file',
|
'modified_file',
|
||||||
'staged_changes',
|
'staged_changes',
|
||||||
@@ -83,27 +84,50 @@ DIFF_WORKDIR_EXPECTED = [
|
|||||||
'subdir/modified_file'
|
'subdir/modified_file'
|
||||||
]
|
]
|
||||||
|
|
||||||
HUNK_EXPECTED = """@@ -1 +1 @@
|
DIFF_INDEX_TO_WORK_EXPECTED = [
|
||||||
a contents 2
|
'file_deleted',
|
||||||
a contents
|
'modified_file',
|
||||||
|
'staged_changes_file_deleted',
|
||||||
|
'staged_changes_file_modified',
|
||||||
|
'staged_new_file_deleted',
|
||||||
|
'staged_new_file_modified',
|
||||||
|
'subdir/deleted_file',
|
||||||
|
'subdir/modified_file'
|
||||||
|
]
|
||||||
|
|
||||||
|
HUNK_EXPECTED = """- a contents 2
|
||||||
|
+ a contents
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class DiffDirtyTest(utils.DirtyRepoTestCase):
|
class DiffDirtyTest(utils.DirtyRepoTestCase):
|
||||||
def test_diff_empty_index(self):
|
def test_diff_empty_index(self):
|
||||||
repo = self.repo
|
repo = self.repo
|
||||||
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
|
||||||
diff = head.tree.diff(repo.index)
|
|
||||||
|
|
||||||
|
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
||||||
|
diff = head.tree.diff_to_index(repo.index)
|
||||||
files = [patch.new_file_path for patch in diff]
|
files = [patch.new_file_path for patch in diff]
|
||||||
self.assertEqual(DIFF_INDEX_EXPECTED, files)
|
self.assertEqual(DIFF_HEAD_TO_INDEX_EXPECTED, files)
|
||||||
|
|
||||||
|
diff = repo.diff('HEAD', cached=True)
|
||||||
|
files = [patch.new_file_path for patch in diff]
|
||||||
|
self.assertEqual(DIFF_HEAD_TO_INDEX_EXPECTED, files)
|
||||||
|
|
||||||
def test_workdir_to_tree(self):
|
def test_workdir_to_tree(self):
|
||||||
repo = self.repo
|
repo = self.repo
|
||||||
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
||||||
diff = head.tree.diff()
|
|
||||||
|
|
||||||
|
diff = head.tree.diff_to_workdir()
|
||||||
files = [patch.new_file_path for patch in diff]
|
files = [patch.new_file_path for patch in diff]
|
||||||
self.assertEqual(DIFF_WORKDIR_EXPECTED, files)
|
self.assertEqual(DIFF_HEAD_TO_WORKDIR_EXPECTED, files)
|
||||||
|
|
||||||
|
diff = repo.diff('HEAD')
|
||||||
|
files = [patch.new_file_path for patch in diff]
|
||||||
|
self.assertEqual(DIFF_HEAD_TO_WORKDIR_EXPECTED, files)
|
||||||
|
|
||||||
|
def test_index_to_workdir(self):
|
||||||
|
diff = self.repo.diff()
|
||||||
|
files = [patch.new_file_path for patch in diff]
|
||||||
|
self.assertEqual(DIFF_INDEX_TO_WORK_EXPECTED, files)
|
||||||
|
|
||||||
|
|
||||||
class DiffTest(utils.BareRepoTestCase):
|
class DiffTest(utils.BareRepoTestCase):
|
||||||
@@ -111,13 +135,22 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
def test_diff_invalid(self):
|
def test_diff_invalid(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
self.assertRaises(TypeError, commit_a.tree.diff, commit_b)
|
self.assertRaises(TypeError, commit_a.tree.diff_to_tree, commit_b)
|
||||||
|
self.assertRaises(TypeError, commit_a.tree.diff_to_index, commit_b)
|
||||||
|
|
||||||
def test_diff_empty_index(self):
|
def test_diff_empty_index(self):
|
||||||
repo = self.repo
|
repo = self.repo
|
||||||
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
head = repo[repo.lookup_reference('HEAD').resolve().target]
|
||||||
diff = head.tree.diff(repo.index)
|
|
||||||
|
|
||||||
|
diff = self.repo.index.diff_to_tree(head.tree)
|
||||||
|
files = [patch.new_file_path.split('/')[0] for patch in diff]
|
||||||
|
self.assertEqual([x.name for x in head.tree], files)
|
||||||
|
|
||||||
|
diff = head.tree.diff_to_index(repo.index)
|
||||||
|
files = [patch.new_file_path.split('/')[0] for patch in diff]
|
||||||
|
self.assertEqual([x.name for x in head.tree], files)
|
||||||
|
|
||||||
|
diff = repo.diff('HEAD', cached=True)
|
||||||
files = [patch.new_file_path.split('/')[0] for patch in diff]
|
files = [patch.new_file_path.split('/')[0] for patch in diff]
|
||||||
self.assertEqual([x.name for x in head.tree], files)
|
self.assertEqual([x.name for x in head.tree], files)
|
||||||
|
|
||||||
@@ -125,8 +158,7 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
|
|
||||||
diff = commit_a.tree.diff(commit_b.tree)
|
def _test(diff):
|
||||||
|
|
||||||
# self.assertIsNotNone is 2.7 only
|
# self.assertIsNotNone is 2.7 only
|
||||||
self.assertTrue(diff is not None)
|
self.assertTrue(diff is not None)
|
||||||
# self.assertIn is 2.7 only
|
# self.assertIn is 2.7 only
|
||||||
@@ -134,7 +166,6 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
|
|
||||||
patch = diff[0]
|
patch = diff[0]
|
||||||
hunk = patch.hunks[0]
|
hunk = patch.hunks[0]
|
||||||
self.assertEqual(hunk.origin, '+')
|
|
||||||
self.assertEqual(hunk.old_start, 1)
|
self.assertEqual(hunk.old_start, 1)
|
||||||
self.assertEqual(hunk.old_lines, 1)
|
self.assertEqual(hunk.old_lines, 1)
|
||||||
self.assertEqual(hunk.new_start, 1)
|
self.assertEqual(hunk.new_start, 1)
|
||||||
@@ -143,23 +174,43 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
self.assertEqual(patch.old_file_path, 'a')
|
self.assertEqual(patch.old_file_path, 'a')
|
||||||
self.assertEqual(patch.new_file_path, 'a')
|
self.assertEqual(patch.new_file_path, 'a')
|
||||||
|
|
||||||
|
_test(commit_a.tree.diff_to_tree(commit_b.tree))
|
||||||
|
_test(self.repo.diff(COMMIT_SHA1_1, COMMIT_SHA1_2))
|
||||||
|
|
||||||
|
|
||||||
def test_diff_empty_tree(self):
|
def test_diff_empty_tree(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
diff = commit_a.tree.diff(empty_tree=True)
|
diff = commit_a.tree.diff_to_tree()
|
||||||
|
|
||||||
|
def get_context_for_lines(diff):
|
||||||
|
hunks = chain(*map(lambda x: x.hunks, [p for p in diff]))
|
||||||
|
lines = chain(*map(lambda x: x.lines, hunks))
|
||||||
|
return map(lambda x: x[0], lines)
|
||||||
|
|
||||||
entries = [p.new_file_path for p in diff]
|
entries = [p.new_file_path for p in diff]
|
||||||
self.assertAll(lambda x: commit_a.tree[x], entries)
|
self.assertAll(lambda x: commit_a.tree[x], entries)
|
||||||
|
self.assertAll(lambda x: '-' == x, get_context_for_lines(diff))
|
||||||
|
|
||||||
|
diff_swaped = commit_a.tree.diff_to_tree(swap=True)
|
||||||
|
entries = [p.new_file_path for p in diff_swaped]
|
||||||
|
self.assertAll(lambda x: commit_a.tree[x], entries)
|
||||||
|
self.assertAll(lambda x: '+' == x, get_context_for_lines(diff_swaped))
|
||||||
|
|
||||||
|
def test_diff_revparse(self):
|
||||||
|
diff = self.repo.diff('HEAD','HEAD~6')
|
||||||
|
self.assertEqual(type(diff), pygit2.Diff)
|
||||||
|
|
||||||
def test_diff_tree_opts(self):
|
def test_diff_tree_opts(self):
|
||||||
commit_c = self.repo[COMMIT_SHA1_3]
|
commit_c = self.repo[COMMIT_SHA1_3]
|
||||||
commit_d = self.repo[COMMIT_SHA1_4]
|
commit_d = self.repo[COMMIT_SHA1_4]
|
||||||
|
|
||||||
for opt in [pygit2.GIT_DIFF_IGNORE_WHITESPACE,
|
for flag in [pygit2.GIT_DIFF_IGNORE_WHITESPACE,
|
||||||
pygit2.GIT_DIFF_IGNORE_WHITESPACE_EOL]:
|
pygit2.GIT_DIFF_IGNORE_WHITESPACE_EOL]:
|
||||||
diff = commit_c.tree.diff(commit_d.tree, opt)
|
diff = commit_c.tree.diff_to_tree(commit_d.tree, flag)
|
||||||
self.assertTrue(diff is not None)
|
self.assertTrue(diff is not None)
|
||||||
self.assertEqual(0, len(diff[0].hunks))
|
self.assertEqual(0, len(diff[0].hunks))
|
||||||
|
|
||||||
diff = commit_c.tree.diff(commit_d.tree)
|
diff = commit_c.tree.diff_to_tree(commit_d.tree)
|
||||||
self.assertTrue(diff is not None)
|
self.assertTrue(diff is not None)
|
||||||
self.assertEqual(1, len(diff[0].hunks))
|
self.assertEqual(1, len(diff[0].hunks))
|
||||||
|
|
||||||
@@ -168,11 +219,11 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
commit_c = self.repo[COMMIT_SHA1_3]
|
commit_c = self.repo[COMMIT_SHA1_3]
|
||||||
|
|
||||||
diff_b = commit_a.tree.diff(commit_b.tree)
|
diff_b = commit_a.tree.diff_to_tree(commit_b.tree)
|
||||||
# self.assertIsNotNone is 2.7 only
|
# self.assertIsNotNone is 2.7 only
|
||||||
self.assertTrue(diff_b is not None)
|
self.assertTrue(diff_b is not None)
|
||||||
|
|
||||||
diff_c = commit_b.tree.diff(commit_c.tree)
|
diff_c = commit_b.tree.diff_to_tree(commit_c.tree)
|
||||||
# self.assertIsNotNone is 2.7 only
|
# self.assertIsNotNone is 2.7 only
|
||||||
self.assertTrue(diff_c is not None)
|
self.assertTrue(diff_c is not None)
|
||||||
|
|
||||||
@@ -199,13 +250,13 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
|
|
||||||
diff = commit_a.tree.diff(commit_b.tree)
|
diff = commit_a.tree.diff_to_tree(commit_b.tree)
|
||||||
self.assertEqual(diff.patch, PATCH)
|
self.assertEqual(diff.patch, PATCH)
|
||||||
|
|
||||||
def test_diff_oids(self):
|
def test_diff_oids(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
patch = commit_a.tree.diff(commit_b.tree)[0]
|
patch = commit_a.tree.diff_to_tree(commit_b.tree)[0]
|
||||||
self.assertEqual(patch.old_oid,
|
self.assertEqual(patch.old_oid,
|
||||||
'7f129fd57e31e935c6d60a0c794efe4e6927664b')
|
'7f129fd57e31e935c6d60a0c794efe4e6927664b')
|
||||||
self.assertEqual(patch.new_oid,
|
self.assertEqual(patch.new_oid,
|
||||||
@@ -214,9 +265,10 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
def test_hunk_content(self):
|
def test_hunk_content(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_1]
|
commit_a = self.repo[COMMIT_SHA1_1]
|
||||||
commit_b = self.repo[COMMIT_SHA1_2]
|
commit_b = self.repo[COMMIT_SHA1_2]
|
||||||
patch = commit_a.tree.diff(commit_b.tree)[0]
|
patch = commit_a.tree.diff_to_tree(commit_b.tree)[0]
|
||||||
hunk = patch.hunks[0]
|
hunk = patch.hunks[0]
|
||||||
self.assertEqual(HUNK_EXPECTED, ''.join(hunk.lines))
|
lines = ('{0} {1}'.format(*x) for x in hunk.lines)
|
||||||
|
self.assertEqual(HUNK_EXPECTED, ''.join(lines))
|
||||||
|
|
||||||
def test_find_similar(self):
|
def test_find_similar(self):
|
||||||
commit_a = self.repo[COMMIT_SHA1_6]
|
commit_a = self.repo[COMMIT_SHA1_6]
|
||||||
@@ -224,7 +276,8 @@ class DiffTest(utils.BareRepoTestCase):
|
|||||||
|
|
||||||
#~ Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate
|
#~ Must pass GIT_DIFF_INCLUDE_UNMODIFIED if you expect to emulate
|
||||||
#~ --find-copies-harder during rename transformion...
|
#~ --find-copies-harder during rename transformion...
|
||||||
diff = commit_a.tree.diff(commit_b.tree, GIT_DIFF_INCLUDE_UNMODIFIED)
|
diff = commit_a.tree.diff_to_tree(commit_b.tree,
|
||||||
|
GIT_DIFF_INCLUDE_UNMODIFIED)
|
||||||
self.assertAll(lambda x: x.status != 'R', diff)
|
self.assertAll(lambda x: x.status != 'R', diff)
|
||||||
diff.find_similar()
|
diff.find_similar()
|
||||||
self.assertAny(lambda x: x.status == 'R', diff)
|
self.assertAny(lambda x: x.status == 'R', diff)
|
||||||
|
Reference in New Issue
Block a user