22 join_path ,
33 Actor ,
44 LockedFD ,
5+ LockFile ,
6+ assure_directory_exists ,
7+ to_native_path ,
58 )
69
710from gitdb .util import (
811 bin_to_hex ,
912 join ,
10- file_contents_ro_filepath
13+ file_contents_ro_filepath ,
1114 )
1215
1316from git .objects .util import (
@@ -151,7 +154,7 @@ def path(cls, ref):
151154 instance would be found. The path is not guaranteed to point to a valid
152155 file though.
153156 :param ref: SymbolicReference instance"""
154- return join (ref .repo .git_dir , "logs" , ref .path )
157+ return join (ref .repo .git_dir , "logs" , to_native_path ( ref .path ) )
155158
156159 @classmethod
157160 def iter_entries (cls , stream ):
@@ -175,6 +178,8 @@ def to_file(self, filepath):
175178 """Write the contents of the reflog instance to a file at the given filepath.
176179 :param filepath: path to file, parent directories are assumed to exist"""
177180 lfd = LockedFD (filepath )
181+ assure_directory_exists (filepath , is_file = True )
182+
178183 fp = lfd .open (write = True , stream = True )
179184 try :
180185 self ._serialize (fp )
@@ -185,22 +190,34 @@ def to_file(self, filepath):
185190 raise
186191 #END handle change
187192
188- def append_entry (self , oldbinsha , newbinsha , message , write = True ):
189- """Append a new log entry to the revlog, changing it in place.
193+ @classmethod
194+ def append_entry (cls , filepath , oldbinsha , newbinsha , message ):
195+ """Append a new log entry to the revlog at filepath.
190196 :param oldbinsha: binary sha of the previous commit
191197 :param newbinsha: binary sha of the current commit
192198 :param message: message describing the change to the reference
193199 :param write: If True, the changes will be written right away. Otherwise
194200 the change will not be written
195- :return: RefLogEntry objects which was appended to the log"""
201+ :return: RefLogEntry objects which was appended to the log
202+ :note: As we are append-only, concurrent access is not a problem as we
203+ do not interfere with readers."""
196204 if len (oldbinsha ) != 20 or len (newbinsha ) != 20 :
197205 raise ValueError ("Shas need to be given in binary format" )
198206 #END handle sha type
199- entry = RefLogEntry ((bin_to_hex (oldbinsha ), bin_to_hex (newbinsha ), Actor .committer (), (int (time .time ()), time .altzone ), message ))
200- self .append (entry )
201- if write :
202- self .write ()
203- #END handle auto-write
207+ assure_directory_exists (filepath , is_file = True )
208+ entry = RefLogEntry ((bin_to_hex (oldbinsha ), bin_to_hex (newbinsha ), Actor .committer (), (int (time .time ()), time .altzone ), message ))
209+
210+ lf = LockFile (filepath )
211+ lf ._obtain_lock_or_raise ()
212+
213+ fd = open (filepath , 'a' )
214+ try :
215+ fd .write (repr (entry ))
216+ finally :
217+ fd .close ()
218+ lf ._release_lock ()
219+ #END handle write operation
220+
204221 return entry
205222
206223 def write (self ):
0 commit comments