summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2010-11-24 19:36:34 +0100
committerSebastian Thiel <byronimo@gmail.com>2010-11-24 19:37:06 +0100
commit98a313305f0d554a179b93695d333199feb5266c (patch)
tree853a7029fa8c532da110b11afc2b60027e267625
parent86523260c495d9a29aa5ab29d50d30a5d1981a0c (diff)
downloadgitpython-98a313305f0d554a179b93695d333199feb5266c.tar.gz
RefLog: added entry_at method, which is a faster way of reading single entries, including test
-rw-r--r--doc/source/changes.rst1
-rw-r--r--refs/log.py31
-rw-r--r--refs/symbolic.py9
-rw-r--r--repo/fun.py2
-rw-r--r--test/test_reflog.py13
5 files changed, 55 insertions, 1 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
index 5d6848eb..7b959532 100644
--- a/doc/source/changes.rst
+++ b/doc/source/changes.rst
@@ -15,6 +15,7 @@ Changelog
* ``log_append(...)`` method added
* ``set_reference(...)`` method added (reflog support)
* ``set_commit(...)`` method added (reflog support)
+ * ``set_object(...)`` method added (reflog support)
* Intrusive Changes to ``Head`` type
diff --git a/refs/log.py b/refs/log.py
index 129803b4..6c734ad4 100644
--- a/refs/log.py
+++ b/refs/log.py
@@ -173,6 +173,37 @@ class RefLog(list, Serializable):
return
yield new_entry(line.strip())
#END endless loop
+
+ @classmethod
+ def entry_at(cls, filepath, index):
+ """:return: RefLogEntry at the given index
+ :param filepath: full path to the index file from which to read the entry
+ :param index: python list compatible index, i.e. it may be negative to
+ specifiy an entry counted from the end of the list
+
+ :raise IndexError: If the entry didn't exist
+ .. note:: This method is faster as it only parses the entry at index, skipping
+ all other lines. Nonetheless, the whole file has to be read if
+ the index is negative
+ """
+ fp = open(filepath, 'rb')
+ if index < 0:
+ return RefLogEntry.from_line(fp.readlines()[index].strip())
+ else:
+ # read until index is reached
+ for i in xrange(index+1):
+ line = fp.readline()
+ if not line:
+ break
+ #END abort on eof
+ #END handle runup
+
+ if i != index or not line:
+ raise IndexError
+ #END handle exception
+
+ return RefLogEntry.from_line(line.strip())
+ #END handle index
def to_file(self, filepath):
"""Write the contents of the reflog instance to a file at the given filepath.
diff --git a/refs/symbolic.py b/refs/symbolic.py
index f333bd46..6ba8083f 100644
--- a/refs/symbolic.py
+++ b/refs/symbolic.py
@@ -354,6 +354,15 @@ class SymbolicReference(object):
(newbinsha is None and self.commit.binsha) or newbinsha,
message)
+ def log_entry(self, index):
+ """:return: RefLogEntry at the given index
+ :param index: python list compatible positive or negative index
+
+ .. note:: This method must read part of the reflog during execution, hence
+ it should be used sparringly, or only if you need just one index.
+ In that case, it will be faster than the ``log()`` method"""
+ return RefLog.entry_at(RefLog.path(self), index)
+
@classmethod
def to_full_path(cls, path):
"""
diff --git a/repo/fun.py b/repo/fun.py
index aa938477..c523a3e1 100644
--- a/repo/fun.py
+++ b/repo/fun.py
@@ -191,7 +191,7 @@ def rev_parse(repo, rev):
#END handle revlog index
try:
- entry = ref.log()[revlog_index]
+ entry = ref.log_entry(revlog_index)
except IndexError:
raise BadObject("Invalid revlog index: %i" % revlog_index)
#END handle index out of bound
diff --git a/test/test_reflog.py b/test/test_reflog.py
index 520be590..5c4a21b8 100644
--- a/test/test_reflog.py
+++ b/test/test_reflog.py
@@ -79,6 +79,19 @@ class TestRefLog(TestBase):
assert entry.newhexsha == 'f'*40
assert entry.message == msg
assert RefLog.from_file(tfile)[-1] == entry
+
+ # index entry
+ # raises on invalid index
+ self.failUnlessRaises(IndexError, RefLog.entry_at, rlp, 10000)
+
+ # indices can be positive ...
+ assert isinstance(RefLog.entry_at(rlp, 0), RefLogEntry)
+ RefLog.entry_at(rlp, 23)
+
+ # ... and negative
+ for idx in (-1, -24):
+ RefLog.entry_at(rlp, idx)
+ #END for each index to read
# END for each reflog