summaryrefslogtreecommitdiff
path: root/git/diff.py
diff options
context:
space:
mode:
Diffstat (limited to 'git/diff.py')
-rw-r--r--git/diff.py99
1 files changed, 49 insertions, 50 deletions
diff --git a/git/diff.py b/git/diff.py
index e90fc1cf..b4d2bae8 100644
--- a/git/diff.py
+++ b/git/diff.py
@@ -11,21 +11,21 @@ from exc import GitCommandError
from gitdb.util import hex_to_bin
-
+
__all__ = ('Diffable', 'DiffIndex', 'Diff')
-
+
class Diffable(object):
"""Common interface for all object that can be diffed against another object of compatible type.
-
+
:note:
Subclasses require a repo member as it is the case for Object instances, for practical
reasons we do not derive from Object."""
__slots__ = tuple()
-
+
# standin indicating you want to diff against the index
class Index(object):
pass
-
+
def _process_diff_args(self, args):
"""
:return:
@@ -33,7 +33,7 @@ class Diffable(object):
Method is called right before git command execution.
Subclasses can use it to alter the behaviour of the superclass"""
return args
-
+
def diff(self, other=Index, paths=None, create_patch=False, **kwargs):
"""Creates diffs between two items being trees, trees and index or an
index and the working tree.
@@ -60,16 +60,16 @@ class Diffable(object):
R=True to swap both sides of the diff.
:return: git.DiffIndex
-
+
:note:
Rename detection will only work if create_patch is True.
-
+
On a bare repository, 'other' needs to be provided as Index or as
as Tree/Commit, or a git command error will occour"""
args = list()
args.append( "--abbrev=40" ) # we need full shas
args.append( "--full-index" ) # get full index paths, not only filenames
-
+
if create_patch:
args.append("-p")
args.append("-M") # check for renames
@@ -79,7 +79,7 @@ class Diffable(object):
# in any way, assure we don't see colored output,
# fixes https://github.com/gitpython-developers/GitPython/issues/172
args.append('--no-color')
-
+
if paths is not None and not isinstance(paths, (tuple,list)):
paths = [ paths ]
@@ -87,23 +87,23 @@ class Diffable(object):
args.insert(0, other)
if other is self.Index:
args.insert(0, "--cached")
-
+
args.insert(0,self)
-
+
# paths is list here or None
if paths:
args.append("--")
args.extend(paths)
# END paths handling
-
+
kwargs['as_process'] = True
proc = self.repo.git.diff(*self._process_diff_args(args), **kwargs)
-
+
diff_method = Diff._index_from_raw_format
if create_patch:
diff_method = Diff._index_from_patch_format
index = diff_method(self.repo, proc.stdout)
-
+
status = proc.wait()
return index
@@ -111,7 +111,7 @@ class Diffable(object):
class DiffIndex(list):
"""Implements an Index for diffs, allowing a list of Diffs to be queried by
the diff properties.
-
+
The class improves the diff handling convenience"""
# change type invariant identifying possible ways a blob can have changed
# A = Added
@@ -119,23 +119,23 @@ class DiffIndex(list):
# R = Renamed
# M = modified
change_type = ("A", "D", "R", "M")
-
-
+
+
def iter_change_type(self, change_type):
"""
:return:
iterator yieling Diff instances that match the given change_type
-
+
:param change_type:
Member of DiffIndex.change_type, namely:
-
+
* 'A' for added paths
* 'D' for deleted paths
* 'R' for renamed paths
* 'M' for paths with modified data"""
if change_type not in self.change_type:
raise ValueError( "Invalid change type: %s" % change_type )
-
+
for diff in self:
if change_type == "A" and diff.new_file:
yield diff
@@ -146,37 +146,37 @@ class DiffIndex(list):
elif change_type == "M" and diff.a_blob and diff.b_blob and diff.a_blob != diff.b_blob:
yield diff
# END for each diff
-
+
class Diff(object):
"""A Diff contains diff information between two Trees.
-
+
It contains two sides a and b of the diff, members are prefixed with
"a" and "b" respectively to inidcate that.
-
+
Diffs keep information about the changed blob objects, the file mode, renames,
deletions and new files.
-
+
There are a few cases where None has to be expected as member variable value:
-
+
``New File``::
-
+
a_mode is None
a_blob is None
-
+
``Deleted File``::
-
+
b_mode is None
b_blob is None
-
+
``Working Tree Blobs``
-
+
When comparing to working trees, the working tree blob will have a null hexsha
as a corresponding object does not yet exist. The mode will be null as well.
But the path will be available though.
If it is listed in a diff the working tree version of the file must
be different to the version in the index or tree, and hence has been modified."""
-
+
# precompiled regex
re_header = re.compile(r"""
#^diff[ ]--git
@@ -194,22 +194,22 @@ class Diff(object):
# can be used for comparisons
NULL_HEX_SHA = "0"*40
NULL_BIN_SHA = "\0"*20
-
+
__slots__ = ("a_blob", "b_blob", "a_mode", "b_mode", "new_file", "deleted_file",
"rename_from", "rename_to", "diff")
def __init__(self, repo, a_path, b_path, a_blob_id, b_blob_id, a_mode,
b_mode, new_file, deleted_file, rename_from,
rename_to, diff):
-
+
self.a_mode = a_mode
self.b_mode = b_mode
-
+
if self.a_mode:
self.a_mode = mode_str_to_int(self.a_mode)
if self.b_mode:
self.b_mode = mode_str_to_int(self.b_mode)
-
+
if a_blob_id is None:
self.a_blob = None
else:
@@ -218,14 +218,14 @@ class Diff(object):
self.b_blob = None
else:
self.b_blob = Blob(repo, hex_to_bin(b_blob_id), mode=self.b_mode, path=b_path)
-
+
self.new_file = new_file
self.deleted_file = deleted_file
-
+
# be clear and use None instead of empty strings
self.rename_from = rename_from or None
self.rename_to = rename_to or None
-
+
self.diff = diff
@@ -235,10 +235,10 @@ class Diff(object):
return False
# END for each name
return True
-
+
def __ne__(self, other):
return not ( self == other )
-
+
def __hash__(self):
return hash(tuple(getattr(self,n) for n in self.__slots__))
@@ -248,7 +248,7 @@ class Diff(object):
h %= self.a_blob.path
elif self.b_blob:
h %= self.b_blob.path
-
+
msg = ''
l = None # temp line
ll = 0 # line length
@@ -261,10 +261,10 @@ class Diff(object):
ll = max(len(l), ll)
msg += l
# END for each blob
-
+
# add headline
h += '\n' + '='*ll
-
+
if self.deleted_file:
msg += '\nfile deleted in rhs'
if self.new_file:
@@ -278,7 +278,7 @@ class Diff(object):
msg += self.diff
msg += '\n---'
# END diff info
-
+
return h + msg
@property
@@ -310,7 +310,7 @@ class Diff(object):
new_file, deleted_file, rename_from, rename_to, diff[header.end():]))
return index
-
+
@classmethod
def _index_from_raw_format(cls, repo, stream):
"""Create a new DiffIndex from the given stream which must be in raw format.
@@ -331,7 +331,7 @@ class Diff(object):
b_path = path
deleted_file = False
new_file = False
-
+
# NOTE: We cannot conclude from the existance of a blob to change type
# as diffs with the working do not have blobs yet
if change_type == 'D':
@@ -341,11 +341,10 @@ class Diff(object):
a_blob_id = None
new_file = True
# END add/remove handling
-
+
diff = Diff(repo, a_path, b_path, a_blob_id, b_blob_id, old_mode, new_mode,
new_file, deleted_file, None, None, '')
index.append(diff)
# END for each line
-
- return index
+ return index