Skip to content

Commit a93eb7e

Browse files
committed
Implemented reflog reading and writing
1 parent 6e5aae2 commit a93eb7e

9 files changed

+677
-23
lines changed

Diff for: refs/log.py

+39-21
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,22 @@
77

88
from git.objects.util import (
99
Actor,
10-
parse_actor_and_date,
10+
parse_date,
1111
Serializable,
1212
utctz_to_altz,
1313
altz_to_utctz_str,
1414
)
1515

1616
import os
17-
17+
import re
1818

1919
__all__ = ["RefLog", "RefLogEntry"]
2020

2121

2222
class RefLogEntry(tuple):
2323
"""Named tuple allowing easy access to the revlog data fields"""
24-
_fmt = "%s %s %s <%s> %i %s\t%s"
24+
_fmt = "%s %s %s <%s> %i %s\t%s\n"
25+
_re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
2526
__slots__ = tuple()
2627

2728
def __repr__(self):
@@ -68,13 +69,34 @@ def new(self, oldhexsha, newhexsha, actor, time, tz_offset, message):
6869
return RefLogEntry((oldhexsha, newhexsha, actor, (time, tz_offset), message))
6970

7071
@classmethod
71-
def from_line(self, line):
72+
def from_line(cls, line):
7273
""":return: New RefLogEntry instance from the given revlog line.
7374
:param line: line without trailing newline
7475
:raise ValueError: If line could not be parsed"""
75-
raise NotImplementedError("todo")
76+
try:
77+
info, msg = line.split('\t', 2)
78+
except ValueError:
79+
raise ValueError("line is missing tab separator")
80+
#END handle first plit
81+
oldhexsha = info[:40]
82+
newhexsha = info[41:81]
83+
for hexsha in (oldhexsha, newhexsha):
84+
if not cls._re_hexsha_only.match(hexsha):
85+
raise ValueError("Invalid hexsha: %s" % hexsha)
86+
# END if hexsha re doesn't match
87+
#END for each hexsha
88+
89+
email_end = info.find('>', 82)
90+
if email_end == -1:
91+
raise ValueError("Missing token: >")
92+
#END handle missing end brace
93+
94+
actor = Actor._from_string(info[82:email_end+1])
95+
time, tz_offset = parse_date(info[email_end+2:])
96+
97+
return RefLogEntry((oldhexsha, newhexsha, actor, (time, tz_offset), msg))
98+
7699

77-
78100
class RefLog(list, Serializable):
79101
"""A reflog contains reflog entries, each of which defines a certain state
80102
of the head in question. Custom query methods allow to retrieve log entries
@@ -104,7 +126,7 @@ def from_file(cls, filepath):
104126
return inst
105127

106128
@classmethod
107-
def reflog_path(cls, ref):
129+
def path(cls, ref):
108130
"""
109131
:return: string to absolute path at which the reflog of the given ref
110132
instance would be found. The path is not guaranteed to point to a valid
@@ -123,7 +145,12 @@ def iter_entries(cls, stream):
123145
if isinstance(stream, basestring):
124146
stream = file_contents_ro_filepath(stream)
125147
#END handle stream type
126-
return (new_entry(line.strip()) for line in stream)
148+
while True:
149+
line = stream.readline()
150+
if not line:
151+
return
152+
yield new_entry(line.strip())
153+
#END endless loop
127154

128155
def to_file(self, filepath):
129156
"""Write the contents of the reflog instance to a file at the given filepath.
@@ -140,22 +167,13 @@ def to_file(self, filepath):
140167
#{ Serializable Interface
141168
def _serialize(self, stream):
142169
lm1 = len(self) - 1
143-
write = stream.write()
170+
write = stream.write
144171

145172
# write all entries
146-
for i, e in self:
147-
s = repr(e)
148-
if i != lm1:
149-
s += "\n"
150-
#END handle line separator
151-
write(s)
173+
for i, e in enumerate(self):
174+
write(repr(e))
152175
#END for each entry
153176

154177
def _deserialize(self, stream):
155-
new_entry = RefLogEntry.from_line
156-
append = self.append
157-
# NOTE: should use iter_entries, but this way it will be more direct and faster
158-
for line in stream:
159-
append(new_entry(line.strip()))
160-
#END handle deserializatoin
178+
self.extend(self.iter_entries(stream))
161179
#} END serializable interface

Diff for: test/fixtures/reflog_HEAD

+460
Large diffs are not rendered by default.

Diff for: test/fixtures/reflog_invalid_date

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <[email protected]> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
2+
82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <[email protected]> 1271229940 commit: conf.py: Adjusted version to match with the actual version

Diff for: test/fixtures/reflog_invalid_email

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <[email protected]> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
2+
82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <byronimo@gmail. 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version

Diff for: test/fixtures/reflog_invalid_newsha

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <[email protected]> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
2+
82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d Sebastian Thiel <[email protected]> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version

Diff for: test/fixtures/reflog_invalid_oldsha

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <[email protected]> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
2+
82b8902e033430000481eb3 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <[email protected]> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version

Diff for: test/fixtures/reflog_invalid_sep

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
501bf602abea7d21c3dbb409b435976e92033145 82b8902e033430000481eb355733cd7065342037 Sebastian Thiel <[email protected]> 1270634931 +0200 commit: Used this release for a first beta of the 0.2 branch of development
2+
82b8902e033430000481eb355733cd7065342037 69361d96a59381fde0ac34d19df2d4aff05fb9a9 Sebastian Thiel <[email protected]> 1271229940 +0200 commit: conf.py: Adjusted version to match with the actual version

0 commit comments

Comments
 (0)