summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/diff.py37
-rw-r--r--lib/git/errors.py6
-rw-r--r--lib/git/index.py72
-rw-r--r--lib/git/objects/__init__.py1
4 files changed, 100 insertions, 16 deletions
diff --git a/lib/git/diff.py b/lib/git/diff.py
index 9b884502..03e6709c 100644
--- a/lib/git/diff.py
+++ b/lib/git/diff.py
@@ -18,13 +18,18 @@ class Diffable(object):
"""
__slots__ = tuple()
- # subclasses provide additional arguments to the git-diff comamnd by supplynig
- # them in this tuple
- _diff_args = tuple()
-
- # Temporary standin for Index type until we have a real index type
+ # standin indicating you want to diff against the index
class Index(object):
pass
+
+ def _process_diff_args(self, args):
+ """
+ Returns
+ possibly altered version of the given args list.
+ 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):
"""
@@ -60,13 +65,13 @@ class Diffable(object):
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(self._diff_args[:])
+ 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
+ args.append("-M") # check for renames
else:
args.append("--raw")
@@ -87,7 +92,7 @@ class Diffable(object):
# END paths handling
kwargs['as_process'] = True
- proc = self.repo.git.diff(*args, **kwargs)
+ proc = self.repo.git.diff(*self._process_diff_args(args), **kwargs)
diff_method = Diff._index_from_raw_format
if create_patch:
@@ -96,7 +101,7 @@ class Diffable(object):
status = proc.wait()
if status != 0:
- raise GitCommandError("git-diff", status, proc.stderr )
+ raise GitCommandError(("git diff",)+tuple(args), status, proc.stderr.read())
return index
@@ -207,6 +212,20 @@ class Diff(object):
self.diff = diff
+
+ def __eq__(self, other):
+ for name in self.__slots__:
+ if getattr(self, name) != getattr(other, name):
+ 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__))
+
@property
def renamed(self):
"""
diff --git a/lib/git/errors.py b/lib/git/errors.py
index 18c58073..cde2798a 100644
--- a/lib/git/errors.py
+++ b/lib/git/errors.py
@@ -25,8 +25,8 @@ class GitCommandError(Exception):
self.stderr = stderr
self.status = status
self.command = command
-
+
def __str__(self):
- return repr("'%s' returned exit status %d: %r" %
- (' '.join(self.command), self.status, str(self.stderr)))
+ return ("'%s' returned exit status %i: %s" %
+ (' '.join(str(i) for i in self.command), self.status, self.stderr))
diff --git a/lib/git/index.py b/lib/git/index.py
index 4eabab15..4217c9a2 100644
--- a/lib/git/index.py
+++ b/lib/git/index.py
@@ -14,9 +14,11 @@ import objects
import tempfile
import os
import stat
-from git.objects import Blob, Tree
+import git.diff as diff
+
+from git.objects import Blob, Tree, Object
from git.utils import SHA1Writer, LazyMixin, ConcurrentWriteOperation
-from git.diff import Diffable
+
class _TemporaryFileSwap(object):
"""
@@ -140,7 +142,7 @@ class IndexEntry(tuple):
return IndexEntry((time, time, 0, 0, blob.mode, 0, 0, blob.size, blob.id, 0, blob.path))
-class Index(LazyMixin):
+class Index(LazyMixin, diff.Diffable):
"""
Implements an Index that can be manipulated using a native implementation in
order to save git command function calls wherever possible.
@@ -154,7 +156,7 @@ class Index(LazyMixin):
The index contains an entries dict whose keys are tuples of type IndexEntry
to facilitate access.
"""
- __slots__ = ( "repo", "version", "entries", "_extension_data" )
+ __slots__ = ( "repo", "version", "entries", "_extension_data", "_is_default_index" )
_VERSION = 2 # latest version we support
S_IFGITLINK = 0160000
@@ -168,10 +170,13 @@ class Index(LazyMixin):
self.repo = repo
self.version = self._VERSION
self._extension_data = ''
+ self._is_default_index = True
if stream is not None:
+ self._is_default_index = False
self._read_from_stream(stream)
# END read from stream immediatly
+
def _set_cache_(self, attr):
if attr == "entries":
# read the current index
@@ -187,6 +192,18 @@ class Index(LazyMixin):
def _index_path(self):
return os.path.join(self.repo.path, "index")
+
+ @property
+ def path(self):
+ """
+ Returns
+ Path to the index file we are representing or None if we are
+ a loose index that was read from a stream.
+ """
+ if self._is_default_index:
+ return self._index_path()
+ return None
+
@classmethod
def _read_entry(cls, stream):
"""Return: One entry of the given stream"""
@@ -535,4 +552,51 @@ class Index(LazyMixin):
# END write tree handling
return Tree(self.repo, tree_sha, 0, '')
+
+ def _process_diff_args(self, args):
+ try:
+ args.pop(args.index(self))
+ except IndexError:
+ pass
+ # END remove self
+ return args
+
+ def diff(self, other=diff.Diffable.Index, paths=None, create_patch=False, **kwargs):
+ """
+ Diff this index against the working copy or a Tree or Commit object
+
+ For a documentation of the parameters and return values, see
+ Diffable.diff
+
+ Note
+ Will only work with indices that represent the default git index as
+ they have not been initialized with a stream.
+ """
+ if not self._is_default_index:
+ raise AssertionError( "Cannot diff custom indices as they do not represent the default git index" )
+
+ # index against index is always empty
+ if other is self.Index:
+ return diff.DiffIndex()
+
+ # index against anything but None is a reverse diff with the respective
+ # item. Handle existing -R flags properly. Transform strings to the object
+ # so that we can call diff on it
+ if isinstance(other, basestring):
+ other = Object.new(self.repo, other)
+ # END object conversion
+
+ if isinstance(other, Object):
+ # invert the existing R flag
+ cur_val = kwargs.get('R', False)
+ kwargs['R'] = not cur_val
+ return other.diff(self.Index, paths, create_patch, **kwargs)
+ # END diff against other item handlin
+
+ # if other is not None here, something is wrong
+ if other is not None:
+ raise ValueError( "other must be None, Diffable.Index, a Tree or Commit, was %r" % other )
+
+ # diff against working copy - can be handled by superclass natively
+ return super(Index, self).diff(other, paths, create_patch, **kwargs)
diff --git a/lib/git/objects/__init__.py b/lib/git/objects/__init__.py
index 39e650b7..192750e3 100644
--- a/lib/git/objects/__init__.py
+++ b/lib/git/objects/__init__.py
@@ -2,6 +2,7 @@
Import all submodules main classes into the package space
"""
import inspect
+from base import *
from tag import *
from blob import *
from tree import *