@@ -559,11 +559,51 @@ def _preprocess_add_items(self, items):
559559# END for each item
560560return (paths ,entries )
561561
562+ def _store_path (self ,filepath ,fprogress ):
563+ """Store file at filepath in the database and return the base index entry
564+ Needs the git_working_dir decorator active ! This must be assured in the calling code"""
565+ st = os .lstat (filepath )# handles non-symlinks as well
566+ stream = None
567+ if S_ISLNK (st .st_mode ):
568+ stream = StringIO (os .readlink (filepath ))
569+ else :
570+ stream = open (filepath ,'rb' )
571+ # END handle stream
572+ fprogress (filepath ,False ,filepath )
573+ istream = self .repo .odb .store (IStream (Blob .type ,st .st_size ,stream ))
574+ fprogress (filepath ,True ,filepath )
575+ return BaseIndexEntry ((stat_mode_to_index_mode (st .st_mode ),
576+ istream .binsha ,0 ,to_native_path_linux (filepath )))
577+
562578@git_working_dir
563- def add (self ,items ,force = True ,fprogress = lambda * args :None ,path_rewriter = None ,
579+ def _entries_for_paths (self ,paths ,path_rewriter ,fprogress ,entries ):
580+ entries_added = list ()
581+ if path_rewriter :
582+ for path in paths :
583+ abspath = os .path .abspath (path )
584+ gitrelative_path = abspath [len (self .repo .working_tree_dir )+ 1 :]
585+ blob = Blob (self .repo ,Blob .NULL_BIN_SHA ,
586+ stat_mode_to_index_mode (os .stat (abspath ).st_mode ),
587+ to_native_path_linux (gitrelative_path ))
588+ # TODO: variable undefined
589+ entries .append (BaseIndexEntry .from_blob (blob ))
590+ # END for each path
591+ del (paths [:])
592+ # END rewrite paths
593+
594+ # HANDLE PATHS
595+ assert len (entries_added )== 0
596+ for filepath in self ._iter_expand_paths (paths ):
597+ entries_added .append (self ._store_path (filepath ,fprogress ))
598+ # END for each filepath
599+ # END path handling
600+ return entries_added
601+
602+
603+ def add (self ,items ,force = True ,fprogress = lambda * args :None ,path_rewriter = None ,
564604write = True ):
565605"""Add files from the working tree, specific blobs or BaseIndexEntries
566- to the index.
606+ to the index.
567607
568608 :param items:
569609 Multiple types of items are supported, types can be mixed within one call.
@@ -591,7 +631,7 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
591631 must be a path relative to our repository.
592632
593633 If their sha is null ( 40*0 ), their path must exist in the file system
594- relative to the git repository as an object will be created from
634+ relative to the git repository as an object will be created from
595635 the data at the path.
596636 The handling now very much equals the way string paths are processed, except that
597637 the mode you have set will be kept. This allows you to create symlinks
@@ -636,7 +676,7 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
636676 :param write:
637677 If True, the index will be written once it was altered. Otherwise
638678 the changes only exist in memory and are not available to git commands.
639-
679+
640680 :return:
641681 List(BaseIndexEntries) representing the entries just actually added.
642682
@@ -648,70 +688,43 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
648688# sort the entries into strings and Entries, Blobs are converted to entries
649689# automatically
650690# paths can be git-added, for everything else we use git-update-index
651- entries_added = list ()
652691paths ,entries = self ._preprocess_add_items (items )
653- if paths and path_rewriter :
654- for path in paths :
655- abspath = os .path .abspath (path )
656- gitrelative_path = abspath [len (self .repo .working_tree_dir )+ 1 :]
657- blob = Blob (self .repo ,Blob .NULL_BIN_SHA ,
658- stat_mode_to_index_mode (os .stat (abspath ).st_mode ),
659- to_native_path_linux (gitrelative_path ))
660- entries .append (BaseIndexEntry .from_blob (blob ))
661- # END for each path
662- del (paths [:])
663- # END rewrite paths
664-
665- def store_path (filepath ):
666- """Store file at filepath in the database and return the base index entry"""
667- st = os .lstat (filepath )# handles non-symlinks as well
668- stream = None
669- if S_ISLNK (st .st_mode ):
670- stream = StringIO (os .readlink (filepath ))
671- else :
672- stream = open (filepath ,'rb' )
673- # END handle stream
674- fprogress (filepath ,False ,filepath )
675- istream = self .repo .odb .store (IStream (Blob .type ,st .st_size ,stream ))
676- fprogress (filepath ,True ,filepath )
677- return BaseIndexEntry ((stat_mode_to_index_mode (st .st_mode ),
678- istream .binsha ,0 ,to_native_path_linux (filepath )))
679- # END utility method
680-
681- # HANDLE PATHS
692+ entries_added = list ()
693+ # This code needs a working tree, therefore we try not to run it unless required.
694+ # That way, we are OK on a bare repository as well.
695+ # If there are no paths, the rewriter has nothing to do either
682696if paths :
683- assert len (entries_added )== 0
684- added_files = list ()
685- for filepath in self ._iter_expand_paths (paths ):
686- entries_added .append (store_path (filepath ))
687- # END for each filepath
688- # END path handling
697+ entries_added .extend (self ._entries_for_paths (paths ,path_rewriter ,fprogress ,entries ))
689698
690699# HANDLE ENTRIES
691700if entries :
692- null_mode_entries = [e for e in entries if e .mode == 0 ]
701+ null_mode_entries = [e for e in entries if e .mode == 0 ]
693702if null_mode_entries :
694703raise ValueError ("At least one Entry has a null-mode - please use index.remove to remove files for clarity" )
695704# END null mode should be remove
696705
697706# HANLDE ENTRY OBJECT CREATION
698707# create objects if required, otherwise go with the existing shas
699- null_entries_indices = [i for i ,e in enumerate (entries )if e .binsha == Object .NULL_BIN_SHA ]
708+ null_entries_indices = [i for i ,e in enumerate (entries )if e .binsha == Object .NULL_BIN_SHA ]
700709if null_entries_indices :
701- for ei in null_entries_indices :
702- null_entry = entries [ei ]
703- new_entry = store_path (null_entry .path )
704-
705- # update null entry
706- entries [ei ]= BaseIndexEntry ((null_entry .mode ,new_entry .binsha ,null_entry .stage ,null_entry .path ))
707- # END for each entry index
710+ @git_working_dir
711+ def handle_null_entries (self ):
712+ for ei in null_entries_indices :
713+ null_entry = entries [ei ]
714+ new_entry = self ._store_path (null_entry .path ,fprogress )
715+
716+ # update null entry
717+ entries [ei ]= BaseIndexEntry ((null_entry .mode ,new_entry .binsha ,null_entry .stage ,null_entry .path ))
718+ # END for each entry index
719+ # end closure
720+ handle_null_entries (self )
708721# END null_entry handling
709722
710723# REWRITE PATHS
711724# If we have to rewrite the entries, do so now, after we have generated
712725# all object sha's
713726if path_rewriter :
714- for i ,e in enumerate (entries ):
727+ for i ,e in enumerate (entries ):
715728entries [i ]= BaseIndexEntry ((e .mode ,e .binsha ,e .stage ,path_rewriter (e )))
716729# END for each entry
717730# END handle path rewriting
@@ -731,11 +744,11 @@ def store_path(filepath):
731744# add the new entries to this instance
732745for entry in entries_added :
733746self .entries [(entry .path ,0 )]= IndexEntry .from_base (entry )
734-
747+
735748if write :
736749self .write ()
737750# END handle write
738-
751+
739752return entries_added
740753
741754def _items_to_rela_paths (self ,items ):