Skip to content

Commit 98a3133

Browse files
committed
RefLog: added entry_at method, which is a faster way of reading single entries, including test
1 parent 8652326 commit 98a3133

File tree

5 files changed

+55
-1
lines changed

5 files changed

+55
-1
lines changed

doc/source/changes.rst

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Changelog
1515
* ``log_append(...)`` method added
1616
* ``set_reference(...)`` method added (reflog support)
1717
* ``set_commit(...)`` method added (reflog support)
18+
* ``set_object(...)`` method added (reflog support)
1819

1920
* Intrusive Changes to ``Head`` type
2021

refs/log.py

+31
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@ def iter_entries(cls, stream):
173173
return
174174
yield new_entry(line.strip())
175175
#END endless loop
176+
177+
@classmethod
178+
def entry_at(cls, filepath, index):
179+
""":return: RefLogEntry at the given index
180+
:param filepath: full path to the index file from which to read the entry
181+
:param index: python list compatible index, i.e. it may be negative to
182+
specifiy an entry counted from the end of the list
183+
184+
:raise IndexError: If the entry didn't exist
185+
.. note:: This method is faster as it only parses the entry at index, skipping
186+
all other lines. Nonetheless, the whole file has to be read if
187+
the index is negative
188+
"""
189+
fp = open(filepath, 'rb')
190+
if index < 0:
191+
return RefLogEntry.from_line(fp.readlines()[index].strip())
192+
else:
193+
# read until index is reached
194+
for i in xrange(index+1):
195+
line = fp.readline()
196+
if not line:
197+
break
198+
#END abort on eof
199+
#END handle runup
200+
201+
if i != index or not line:
202+
raise IndexError
203+
#END handle exception
204+
205+
return RefLogEntry.from_line(line.strip())
206+
#END handle index
176207

177208
def to_file(self, filepath):
178209
"""Write the contents of the reflog instance to a file at the given filepath.

refs/symbolic.py

+9
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,15 @@ def log_append(self, oldbinsha, message, newbinsha=None):
354354
(newbinsha is None and self.commit.binsha) or newbinsha,
355355
message)
356356

357+
def log_entry(self, index):
358+
""":return: RefLogEntry at the given index
359+
:param index: python list compatible positive or negative index
360+
361+
.. note:: This method must read part of the reflog during execution, hence
362+
it should be used sparringly, or only if you need just one index.
363+
In that case, it will be faster than the ``log()`` method"""
364+
return RefLog.entry_at(RefLog.path(self), index)
365+
357366
@classmethod
358367
def to_full_path(cls, path):
359368
"""

repo/fun.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ def rev_parse(repo, rev):
191191
#END handle revlog index
192192

193193
try:
194-
entry = ref.log()[revlog_index]
194+
entry = ref.log_entry(revlog_index)
195195
except IndexError:
196196
raise BadObject("Invalid revlog index: %i" % revlog_index)
197197
#END handle index out of bound

test/test_reflog.py

+13
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@ def test_base(self):
7979
assert entry.newhexsha == 'f'*40
8080
assert entry.message == msg
8181
assert RefLog.from_file(tfile)[-1] == entry
82+
83+
# index entry
84+
# raises on invalid index
85+
self.failUnlessRaises(IndexError, RefLog.entry_at, rlp, 10000)
86+
87+
# indices can be positive ...
88+
assert isinstance(RefLog.entry_at(rlp, 0), RefLogEntry)
89+
RefLog.entry_at(rlp, 23)
90+
91+
# ... and negative
92+
for idx in (-1, -24):
93+
RefLog.entry_at(rlp, idx)
94+
#END for each index to read
8295
# END for each reflog
8396

8497

0 commit comments

Comments
 (0)