summaryrefslogtreecommitdiff
path: root/lib/git/blob.py
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-11 22:50:44 +0200
committerSebastian Thiel <byronimo@gmail.com>2009-10-11 22:50:44 +0200
commit3c0a65226f038c58fc6d6ed525f38fc00b3579b7 (patch)
treea5b715a490d9cbd8f45eabc1968374c96bdea1c0 /lib/git/blob.py
parent9c0c2fc4ee2d8a5d0a2de50ba882657989dedc51 (diff)
parentc68459a17ff59043d29c90020fffe651b2164e6a (diff)
downloadgitpython-3c0a65226f038c58fc6d6ed525f38fc00b3579b7.tar.gz
Merge branch 'hierarchyfix' into improvements
* hierarchyfix: Added remaining tests for new base classes and removed some methods whose existance was doubtful or unsafe Fixed remaining tests to deal with the changes commit: fixed failing commit tests as the mocked git command would always return the same thing which does not work anymore - re-implemented it in a more dynamic manner, but in the end tests will have to be revised anyway mode-only change for test system - this should be in a separate repository in fact so that changes are a little more self-contained and not depending on the actual source repository fixed issue in Ref.name implementation which would not handle components properly lazymixin system now supports per-attribute baking, it is up to the class whether it bakes more. This also leads to more efficient use of memory as values are only cached and set when required - the baking system does not require an own tracking variable anymore, and values are only to be cached once - then python will natively find the cache without involving any additional overhead. This works by using __getattr__ instead of __get_attribute__ which would always be called put Tree and Blob onto a new base class suitable to deal with IndexObjects blob tests fixed to deal with changes to the Blob type converted all spaces to tabs ( 4 spaces = 1 tab ) just to allow me and my editor to work with the files properly. Can convert it back for releaes Re-designed the tag testing - it does not use fixtures anymore but dyamically checks the existance of tags within the repository - it basically tests the interface and checks that expected return types are actually returned Intermediate commit: commit,tree and blob objects now derive from object - test is in place which still fails on purpose. Need to integrate tags which can be objects or just a special form of a ref Renamed lazy.py to base.py to have a file for base classes - lazy not yet changed to allow proper rename tracking
Diffstat (limited to 'lib/git/blob.py')
-rw-r--r--lib/git/blob.py282
1 files changed, 111 insertions, 171 deletions
diff --git a/lib/git/blob.py b/lib/git/blob.py
index 1e8aa12b..1fafb128 100644
--- a/lib/git/blob.py
+++ b/lib/git/blob.py
@@ -10,177 +10,117 @@ import re
import time
from actor import Actor
from commit import Commit
-
-class Blob(object):
- """A Blob encapsulates a git blob object"""
- DEFAULT_MIME_TYPE = "text/plain"
-
- # precompiled regex
- re_whitespace = re.compile(r'\s+')
- re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
- re_author_committer_start = re.compile(r'^(author|committer)')
- re_tab_full_line = re.compile(r'^\t(.*)$')
-
- def __init__(self, repo, id, mode=None, path=None):
- """
- Create an unbaked Blob containing just the specified attributes
-
- ``repo``
- is the Repo
-
- ``id``
- is the git object id
-
- ``mode``
- is the file mode
-
- ``path``
- is the path to the file
-
- Returns
- git.Blob
- """
- self.repo = repo
- self.id = id
- self.mode = mode
- self.path = path
-
- self._size = None
- self.data_stored = None
-
- @property
- def size(self):
- """
- The size of this blob in bytes
-
- Returns
- int
-
- NOTE
- The size will be cached after the first access
- """
- if self._size is None:
- self._size = int(self.repo.git.cat_file(self.id, s=True).rstrip())
- return self._size
-
- @property
- def data(self):
- """
- The binary contents of this blob.
-
- Returns
- str
-
- NOTE
- The data will be cached after the first access.
- """
- self.data_stored = self.data_stored or self.repo.git.cat_file(self.id, p=True, with_raw_output=True)
- return self.data_stored
-
- @property
- def mime_type(self):
- """
- The mime type of this file (based on the filename)
-
- Returns
- str
-
- NOTE
- Defaults to 'text/plain' in case the actual file type is unknown.
- """
- guesses = None
- if self.path:
- guesses = mimetypes.guess_type(self.path)
- return guesses and guesses[0] or self.DEFAULT_MIME_TYPE
-
- @property
- def basename(self):
- """
- Returns
- The basename of the Blobs file path
- """
- return os.path.basename(self.path)
-
- @classmethod
- def blame(cls, repo, commit, file):
- """
- The blame information for the given file at the given commit
-
- Returns
- list: [git.Commit, list: [<line>]]
- A list of tuples associating a Commit object with a list of lines that
- changed within the given commit. The Commit objects will be given in order
- of appearance.
- """
- data = repo.git.blame(commit, '--', file, p=True)
- commits = {}
- blames = []
- info = None
-
- for line in data.splitlines():
- parts = cls.re_whitespace.split(line, 1)
- firstpart = parts[0]
- if cls.re_hexsha_only.search(firstpart):
- # handles
- # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
- # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
- digits = parts[-1].split(" ")
- if len(digits) == 3:
+import base
+
+class Blob(base.IndexObject):
+ """A Blob encapsulates a git blob object"""
+ DEFAULT_MIME_TYPE = "text/plain"
+ type = "blob"
+
+ __slots__ = tuple()
+
+ # precompiled regex
+ re_whitespace = re.compile(r'\s+')
+ re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
+ re_author_committer_start = re.compile(r'^(author|committer)')
+ re_tab_full_line = re.compile(r'^\t(.*)$')
+
+ @property
+ def mime_type(self):
+ """
+ The mime type of this file (based on the filename)
+
+ Returns
+ str
+
+ NOTE
+ Defaults to 'text/plain' in case the actual file type is unknown.
+ """
+ guesses = None
+ if self.path:
+ guesses = mimetypes.guess_type(self.path)
+ return guesses and guesses[0] or self.DEFAULT_MIME_TYPE
+
+ @classmethod
+ def blame(cls, repo, commit, file):
+ """
+ The blame information for the given file at the given commit
+
+ Returns
+ list: [git.Commit, list: [<line>]]
+ A list of tuples associating a Commit object with a list of lines that
+ changed within the given commit. The Commit objects will be given in order
+ of appearance.
+ """
+ data = repo.git.blame(commit, '--', file, p=True)
+ commits = {}
+ blames = []
+ info = None
+
+ for line in data.splitlines(False):
+ parts = cls.re_whitespace.split(line, 1)
+ firstpart = parts[0]
+ if cls.re_hexsha_only.search(firstpart):
+ # handles
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
+ # 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2
+ digits = parts[-1].split(" ")
+ if len(digits) == 3:
info = {'id': firstpart}
blames.append([None, []])
# END blame data initialization
- else:
- m = cls.re_author_committer_start.search(firstpart)
- if m:
- # handles:
- # author Tom Preston-Werner
- # author-mail <tom@mojombo.com>
- # author-time 1192271832
- # author-tz -0700
- # committer Tom Preston-Werner
- # committer-mail <tom@mojombo.com>
- # committer-time 1192271832
- # committer-tz -0700 - IGNORED BY US
- role = m.group(0)
- if firstpart.endswith('-mail'):
- info["%s_email" % role] = parts[-1]
- elif firstpart.endswith('-time'):
- info["%s_date" % role] = time.gmtime(int(parts[-1]))
- elif role == firstpart:
- info[role] = parts[-1]
- # END distinguish mail,time,name
- else:
- # handle
- # filename lib/grit.rb
- # summary add Blob
- # <and rest>
- if firstpart.startswith('filename'):
- info['filename'] = parts[-1]
- elif firstpart.startswith('summary'):
- info['summary'] = parts[-1]
- elif firstpart == '':
- if info:
- sha = info['id']
- c = commits.get(sha)
- if c is None:
- c = Commit( repo, id=sha,
- author=Actor.from_string(info['author'] + ' ' + info['author_email']),
- authored_date=info['author_date'],
- committer=Actor.from_string(info['committer'] + ' ' + info['committer_email']),
- committed_date=info['committer_date'],
- message=info['summary'])
- commits[sha] = c
- # END if commit objects needs initial creation
- m = cls.re_tab_full_line.search(line)
- text, = m.groups()
- blames[-1][0] = c
- blames[-1][1].append( text )
- info = None
- # END if we collected commit info
- # END distinguish filename,summary,rest
- # END distinguish author|committer vs filename,summary,rest
- # END distinguish hexsha vs other information
- return blames
-
- def __repr__(self):
- return '<git.Blob "%s">' % self.id
+ else:
+ m = cls.re_author_committer_start.search(firstpart)
+ if m:
+ # handles:
+ # author Tom Preston-Werner
+ # author-mail <tom@mojombo.com>
+ # author-time 1192271832
+ # author-tz -0700
+ # committer Tom Preston-Werner
+ # committer-mail <tom@mojombo.com>
+ # committer-time 1192271832
+ # committer-tz -0700 - IGNORED BY US
+ role = m.group(0)
+ if firstpart.endswith('-mail'):
+ info["%s_email" % role] = parts[-1]
+ elif firstpart.endswith('-time'):
+ info["%s_date" % role] = time.gmtime(int(parts[-1]))
+ elif role == firstpart:
+ info[role] = parts[-1]
+ # END distinguish mail,time,name
+ else:
+ # handle
+ # filename lib/grit.rb
+ # summary add Blob
+ # <and rest>
+ if firstpart.startswith('filename'):
+ info['filename'] = parts[-1]
+ elif firstpart.startswith('summary'):
+ info['summary'] = parts[-1]
+ elif firstpart == '':
+ if info:
+ sha = info['id']
+ c = commits.get(sha)
+ if c is None:
+ c = Commit( repo, id=sha,
+ author=Actor.from_string(info['author'] + ' ' + info['author_email']),
+ authored_date=info['author_date'],
+ committer=Actor.from_string(info['committer'] + ' ' + info['committer_email']),
+ committed_date=info['committer_date'],
+ message=info['summary'])
+ commits[sha] = c
+ # END if commit objects needs initial creation
+ m = cls.re_tab_full_line.search(line)
+ text, = m.groups()
+ blames[-1][0] = c
+ blames[-1][1].append( text )
+ info = None
+ # END if we collected commit info
+ # END distinguish filename,summary,rest
+ # END distinguish author|committer vs filename,summary,rest
+ # END distinguish hexsha vs other information
+ return blames
+
+ def __repr__(self):
+ return '<git.Blob "%s">' % self.id