1414import tempfile
1515import os
1616import stat
17- from git .objects import Blob
17+ from git .objects import Blob , Tree
18+
19+ class _TemporaryFileSwap (object ):
20+ """
21+ Utility class moving a file to a temporary location within the same directory
22+ and moving it back on to where on object deletion.
23+ """
24+ __slots__ = ("file_path" , "tmp_file_path" )
25+
26+ def __init__ (self , file_path ):
27+ self .file_path = file_path
28+ self .tmp_file_path = self .file_path + tempfile .mktemp ('' ,'' ,'' )
29+ os .rename (self .file_path , self .tmp_file_path )
30+
31+ def __del__ (self ):
32+ if os .path .isfile (self .tmp_file_path ):
33+ os .rename (self .tmp_file_path , self .file_path )
34+
1835
1936class IndexEntry (tuple ):
2037 """
@@ -335,17 +352,13 @@ def from_tree(cls, repo, *treeish, **kwargs):
335352
336353 # move current index out of the way - otherwise the merge may fail
337354 # as it considers existing entries. moving it essentially clears the index.
338- # Unfortunately there is no 'soft' way to do it
339- cur_index = os . path . join ( repo . path , 'index' )
340- moved_index = os .path .join (repo .path , 'index_moved' + tempfile . mktemp ( '' , '' , ' ' ))
355+ # Unfortunately there is no 'soft' way to do it.
356+ # The _TemporaryFileSwap assure the original file get put back
357+ index_handler = _TemporaryFileSwap ( os .path .join (repo .path , 'index ' ))
341358 try :
342- os .rename (cur_index , moved_index )
343359 repo .git .read_tree (* arg_list , ** kwargs )
344360 index = cls .from_file (repo , tmp_index )
345361 finally :
346- # put back the original index first !
347- if os .path .exists (moved_index ):
348- os .rename (moved_index , cur_index )
349362 if os .path .exists (tmp_index ):
350363 os .remove (tmp_index )
351364 # END index merge handling
@@ -354,8 +367,10 @@ def from_tree(cls, repo, *treeish, **kwargs):
354367
355368 @classmethod
356369 def _index_mode_to_tree_index_mode (cls , index_mode ):
357- """Cleanup a index_mode value.
370+ """
371+ Cleanup a index_mode value.
358372 This will return a index_mode that can be stored in a tree object.
373+
359374 ``index_mode``
360375 Index_mode to clean up.
361376 """
@@ -381,15 +396,29 @@ def iter_blobs(self, predicate = lambda t: True):
381396 for entry in self .entries .itervalues ():
382397 mode = self ._index_mode_to_tree_index_mode (entry .mode )
383398 blob = Blob (self .repo , entry .sha , mode , entry .path )
399+ blob .size = entry .size
384400 output = (entry .stage , blob )
385401 if predicate (output ):
386402 yield output
387403 # END for each entry
388404
389- def write_tree (self , stream ):
405+ def write_tree (self ):
390406 """
391- Writes the
407+ Writes the Index in self to a corresponding Tree file into the repository
408+ object database and returns it as corresponding Tree object.
409+
410+ Returns
411+ Tree object representing this index
392412 """
393- raise NotImplementedError ("TODO" )
413+ index_path = os .path .join (self .repo .path , "index" )
414+ tmp_index_mover = _TemporaryFileSwap (index_path )
415+
416+ self .to_file (self , index_path )
417+ tree_sha = self .repo .git .write_tree ()
418+
419+ # remove our index file so that the original index can move back into place
420+ # On linux it will silently overwrite, on windows it won't
421+ os .remove (index_path )
422+ return Tree (self .repo , tree_sha , 0 , '' )
394423
395424
0 commit comments