diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2014-11-17 11:27:40 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2014-11-17 11:27:40 +0100 |
commit | ca4c1b87b3fdedd98a0b9e7a8cf02033b5aaa1c8 (patch) | |
tree | 210d461a1a498e782dc587a36a12d495b81ee697 | |
parent | cebda2d5941410cad07b30c4e6b3fc1823d593a4 (diff) | |
parent | 4d4138c16299ce51541cb752672da1ae467cc5ff (diff) | |
download | gitpython-ca4c1b87b3fdedd98a0b9e7a8cf02033b5aaa1c8.tar.gz |
Merge branch 'master' of https://github.com/moshevds/GitPython into moshevds-master
Fixed an issue with path_rewriter code branch, but there is more to do
Conflicts:
git/index/base.py
git/test/test_index.py
-rw-r--r-- | git/index/base.py | 105 | ||||
-rw-r--r-- | git/test/test_index.py | 34 |
2 files changed, 90 insertions, 49 deletions
diff --git a/git/index/base.py b/git/index/base.py index c200f05f..1dada729 100644 --- a/git/index/base.py +++ b/git/index/base.py @@ -70,7 +70,6 @@ __all__ = ('IndexFile', 'CheckoutError') class IndexFile(LazyMixin, diff.Diffable, Serializable): - """ Implements an Index that can be manipulated using a native implementation in order to save git command function calls wherever possible. @@ -561,8 +560,48 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): return (paths, entries) @git_working_dir - def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=None, - write=True): + def _store_path(self, filepath, fprogress): + """Store file at filepath in the database and return the base index entry""" + st = os.lstat(filepath) # handles non-symlinks as well + stream = None + if S_ISLNK(st.st_mode): + stream = StringIO(os.readlink(filepath)) + else: + stream = open(filepath, 'rb') + # END handle stream + fprogress(filepath, False, filepath) + istream = self.repo.odb.store(IStream(Blob.type, st.st_size, stream)) + fprogress(filepath, True, filepath) + return BaseIndexEntry((stat_mode_to_index_mode(st.st_mode), + istream.binsha, 0, to_native_path_linux(filepath))) + + @git_working_dir + def _entries_for_paths(self, paths, path_rewriter, fprogress, entries): + entries_added = list() + if path_rewriter: + for path in paths: + abspath = os.path.abspath(path) + gitrelative_path = abspath[len(self.repo.working_tree_dir)+1:] + blob = Blob(self.repo, Blob.NULL_BIN_SHA, + stat_mode_to_index_mode(os.stat(abspath).st_mode), + to_native_path_linux(gitrelative_path)) + # TODO: variable undefined + entries.append(BaseIndexEntry.from_blob(blob)) + # END for each path + del(paths[:]) + # END rewrite paths + + # HANDLE PATHS + assert len(entries_added) == 0 + for filepath in self._iter_expand_paths(paths): + entries_added.append(self._store_path(filepath, fprogress)) + # END for each filepath + # END path handling + return entries_added + + + def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=None, + write=True): """Add files from the working tree, specific blobs or BaseIndexEntries to the index. @@ -637,7 +676,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): :param write: If True, the index will be written once it was altered. Otherwise the changes only exist in memory and are not available to git commands. - + :return: List(BaseIndexEntries) representing the entries just actually added. @@ -649,61 +688,29 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): # sort the entries into strings and Entries, Blobs are converted to entries # automatically # paths can be git-added, for everything else we use git-update-index - entries_added = list() paths, entries = self._preprocess_add_items(items) - if paths and path_rewriter: - for path in paths: - abspath = os.path.abspath(path) - gitrelative_path = abspath[len(self.repo.working_tree_dir) + 1:] - blob = Blob(self.repo, Blob.NULL_BIN_SHA, - stat_mode_to_index_mode(os.stat(abspath).st_mode), - to_native_path_linux(gitrelative_path)) - entries.append(BaseIndexEntry.from_blob(blob)) - # END for each path - del(paths[:]) - # END rewrite paths - - def store_path(filepath): - """Store file at filepath in the database and return the base index entry""" - st = os.lstat(filepath) # handles non-symlinks as well - stream = None - if S_ISLNK(st.st_mode): - stream = StringIO(os.readlink(filepath)) - else: - stream = open(filepath, 'rb') - # END handle stream - fprogress(filepath, False, filepath) - istream = self.repo.odb.store(IStream(Blob.type, st.st_size, stream)) - fprogress(filepath, True, filepath) - return BaseIndexEntry((stat_mode_to_index_mode(st.st_mode), - istream.binsha, 0, to_native_path_linux(filepath))) - # END utility method - - # HANDLE PATHS + entries_added = list() + # This code needs a working tree, therefore we try not to run it unless required. + # That way, we are OK on a bare repository as well. + # If there are no paths, the rewriter has nothing to do either if paths: - assert len(entries_added) == 0 - added_files = list() - for filepath in self._iter_expand_paths(paths): - entries_added.append(store_path(filepath)) - # END for each filepath - # END path handling + entries_added.extend(self._entries_for_paths(paths, path_rewriter, fprogress, entries)) # HANDLE ENTRIES if entries: - null_mode_entries = [e for e in entries if e.mode == 0] + null_mode_entries = [ e for e in entries if e.mode == 0 ] if null_mode_entries: - raise ValueError( - "At least one Entry has a null-mode - please use index.remove to remove files for clarity") + raise ValueError("At least one Entry has a null-mode - please use index.remove to remove files for clarity") # END null mode should be remove # HANLDE ENTRY OBJECT CREATION # create objects if required, otherwise go with the existing shas - null_entries_indices = [i for i, e in enumerate(entries) if e.binsha == Object.NULL_BIN_SHA] + null_entries_indices = [ i for i,e in enumerate(entries) if e.binsha == Object.NULL_BIN_SHA ] if null_entries_indices: for ei in null_entries_indices: null_entry = entries[ei] - new_entry = store_path(null_entry.path) - + new_entry = self._store_path(null_entry.path, fprogress) + # update null entry entries[ei] = BaseIndexEntry((null_entry.mode, new_entry.binsha, null_entry.stage, null_entry.path)) # END for each entry index @@ -713,7 +720,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): # If we have to rewrite the entries, do so now, after we have generated # all object sha's if path_rewriter: - for i, e in enumerate(entries): + for i,e in enumerate(entries): entries[i] = BaseIndexEntry((e.mode, e.binsha, e.stage, path_rewriter(e))) # END for each entry # END handle path rewriting @@ -733,11 +740,11 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): # add the new entries to this instance for entry in entries_added: self.entries[(entry.path, 0)] = IndexEntry.from_base(entry) - + if write: self.write() # END handle write - + return entries_added def _items_to_rela_paths(self, items): diff --git a/git/test/test_index.py b/git/test/test_index.py index 76d43cbf..a4e26977 100644 --- a/git/test/test_index.py +++ b/git/test/test_index.py @@ -20,6 +20,11 @@ import shutil import time from stat import * +from StringIO import StringIO +from gitdb.base import IStream +from git.objects import Blob +from git.index.typ import BaseIndexEntry + class TestIndex(TestBase): @@ -671,3 +676,32 @@ class TestIndex(TestBase): index = IndexFile.new(self.rorepo, *args) assert isinstance(index, IndexFile) # END for each arg tuple + + @with_rw_repo('HEAD', bare=True) + def test_index_bare_add(self, rw_bare_repo): + # Something is wrong after cloning to a bare repo, reading the + # property rw_bare_repo.working_tree_dir will return '/tmp' + # instead of throwing the Exception we are expecting. This is + # a quick hack to make this test fail when expected. + rw_bare_repo._working_tree_dir = None + contents = 'This is a StringIO file' + filesize = len(contents) + fileobj = StringIO(contents) + filename = 'my-imaginary-file' + istream = rw_bare_repo.odb.store( + IStream(Blob.type, filesize, fileobj)) + entry = BaseIndexEntry((100644, istream.binsha, 0, filename)) + try: + rw_bare_repo.index.add([entry]) + except AssertionError, e: + self.fail("Adding to the index of a bare repo is not allowed.") + + # Adding using a path should still require a non-bare repository. + asserted = False + path = os.path.join('git', 'test', 'test_index.py') + try: + rw_bare_repo.index.add([path]) + except Exception, e: + asserted = "does not have a working tree" in e.message + assert asserted, "Adding using a filename is not correctly asserted." + |