7070
7171
7272class IndexFile (LazyMixin ,diff .Diffable ,Serializable ):
73-
7473"""
7574 Implements an Index that can be manipulated using a native implementation in
7675 order to save git command function calls wherever possible.
@@ -561,8 +560,48 @@ def _preprocess_add_items(self, items):
561560return (paths ,entries )
562561
563562@git_working_dir
564- def add (self ,items ,force = True ,fprogress = lambda * args :None ,path_rewriter = None ,
565- write = True ):
563+ def _store_path (self ,filepath ,fprogress ):
564+ """Store file at filepath in the database and return the base index entry"""
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+
578+ @git_working_dir
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 ,
604+ write = True ):
566605"""Add files from the working tree, specific blobs or BaseIndexEntries
567606 to the index.
568607
@@ -637,7 +676,7 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
637676 :param write:
638677 If True, the index will be written once it was altered. Otherwise
639678 the changes only exist in memory and are not available to git commands.
640-
679+
641680 :return:
642681 List(BaseIndexEntries) representing the entries just actually added.
643682
@@ -649,61 +688,29 @@ def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=Non
649688# sort the entries into strings and Entries, Blobs are converted to entries
650689# automatically
651690# paths can be git-added, for everything else we use git-update-index
652- entries_added = list ()
653691paths ,entries = self ._preprocess_add_items (items )
654- if paths and path_rewriter :
655- for path in paths :
656- abspath = os .path .abspath (path )
657- gitrelative_path = abspath [len (self .repo .working_tree_dir )+ 1 :]
658- blob = Blob (self .repo ,Blob .NULL_BIN_SHA ,
659- stat_mode_to_index_mode (os .stat (abspath ).st_mode ),
660- to_native_path_linux (gitrelative_path ))
661- entries .append (BaseIndexEntry .from_blob (blob ))
662- # END for each path
663- del (paths [:])
664- # END rewrite paths
665-
666- def store_path (filepath ):
667- """Store file at filepath in the database and return the base index entry"""
668- st = os .lstat (filepath )# handles non-symlinks as well
669- stream = None
670- if S_ISLNK (st .st_mode ):
671- stream = StringIO (os .readlink (filepath ))
672- else :
673- stream = open (filepath ,'rb' )
674- # END handle stream
675- fprogress (filepath ,False ,filepath )
676- istream = self .repo .odb .store (IStream (Blob .type ,st .st_size ,stream ))
677- fprogress (filepath ,True ,filepath )
678- return BaseIndexEntry ((stat_mode_to_index_mode (st .st_mode ),
679- istream .binsha ,0 ,to_native_path_linux (filepath )))
680- # END utility method
681-
682- # 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
683696if paths :
684- assert len (entries_added )== 0
685- added_files = list ()
686- for filepath in self ._iter_expand_paths (paths ):
687- entries_added .append (store_path (filepath ))
688- # END for each filepath
689- # END path handling
697+ entries_added .extend (self ._entries_for_paths (paths ,path_rewriter ,fprogress ,entries ))
690698
691699# HANDLE ENTRIES
692700if entries :
693- 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 ]
694702if null_mode_entries :
695- raise ValueError (
696- "At least one Entry has a null-mode - please use index.remove to remove files for clarity" )
703+ raise ValueError ("At least one Entry has a null-mode - please use index.remove to remove files for clarity" )
697704# END null mode should be remove
698705
699706# HANLDE ENTRY OBJECT CREATION
700707# create objects if required, otherwise go with the existing shas
701- 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 ]
702709if null_entries_indices :
703710for ei in null_entries_indices :
704711null_entry = entries [ei ]
705- new_entry = store_path (null_entry .path )
706-
712+ new_entry = self . _store_path (null_entry .path , fprogress )
713+
707714# update null entry
708715entries [ei ]= BaseIndexEntry ((null_entry .mode ,new_entry .binsha ,null_entry .stage ,null_entry .path ))
709716# END for each entry index
@@ -713,7 +720,7 @@ def store_path(filepath):
713720# If we have to rewrite the entries, do so now, after we have generated
714721# all object sha's
715722if path_rewriter :
716- for i ,e in enumerate (entries ):
723+ for i ,e in enumerate (entries ):
717724entries [i ]= BaseIndexEntry ((e .mode ,e .binsha ,e .stage ,path_rewriter (e )))
718725# END for each entry
719726# END handle path rewriting
@@ -733,11 +740,11 @@ def store_path(filepath):
733740# add the new entries to this instance
734741for entry in entries_added :
735742self .entries [(entry .path ,0 )]= IndexEntry .from_base (entry )
736-
743+
737744if write :
738745self .write ()
739746# END handle write
740-
747+
741748return entries_added
742749
743750def _items_to_rela_paths (self ,items ):