diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2015-04-08 09:50:26 +0200 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2015-04-08 09:50:26 +0200 |
commit | 8f043d8a1d7f4076350ff0c778bfa60f7aa2f7aa (patch) | |
tree | 4d2a80c70fc35bf69d5779347c5e6802c8b9d0c9 | |
parent | ab7c3223076306ca71f692ed5979199863cf45a7 (diff) | |
download | gitpython-8f043d8a1d7f4076350ff0c778bfa60f7aa2f7aa.tar.gz |
fix(index): don't write extension data by default
It turned out that the index is not actually corrupted, which is good
news. What happens is that `git` writes `TREE` extension data into the
index, which causes it to write out the given tree *as is* next time
a `git commit` is executed. When using `git add`, this extension data
is maintained automatically. However, GitPython doesn't do that ... .
Usually this is no problem at all, as you are supposed to use
`IndexFile.commit(...)` along with `IndexFile.add(...)`.
Thanks to a shortcoming in the GitPython API, the index was
automatically written out whenever files have been added, without
providing control over whether or not *extension data* will be
written along with it.
My fix consists of an additional flag in `IndexFile.add(...)`, which
causes extension data not to be written by default, so commits can be
safely done via `git commit` or `IndexFile.commit(...)`.
However, this might introduce new subtle bugs in case someone is
relying on extension data to be written. As this can be controlled
through the said flag though, a fix is easily done in that case.
Fixes #265
-rw-r--r-- | doc/source/changes.rst | 6 | ||||
-rw-r--r-- | git/index/base.py | 37 | ||||
-rw-r--r-- | git/test/test_index.py | 15 |
3 files changed, 31 insertions, 27 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 5b85e56a..52d70c0f 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -2,6 +2,12 @@ Changelog ========= +0.3.7 - Fixes +============= +* `IndexFile.add()` will now write the index without any extension data by default. However, you may override this behaviour with the new `write_extension_data` keyword argument. + + - Renamed `ignore_tree_extension_data` keyword argument in `IndexFile.write(...)` to `ignore_extension_data` + 0.3.6 - Features ================ * **DOCS** diff --git a/git/index/base.py b/git/index/base.py index 733d4a63..0553f418 100644 --- a/git/index/base.py +++ b/git/index/base.py @@ -172,16 +172,17 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): """:return: list of entries, in a sorted fashion, first by path, then by stage""" return sorted(self.entries.values(), key=lambda e: (e.path, e.stage)) - def _serialize(self, stream, ignore_tree_extension_data=False): + def _serialize(self, stream, ignore_extension_data=False): entries = self._entries_sorted() - write_cache(entries, - stream, - (ignore_tree_extension_data and None) or self._extension_data) + extension_data = self._extension_data + if ignore_extension_data: + extension_data = None + write_cache(entries, stream, extension_data) return self #} END serializable interface - def write(self, file_path=None, ignore_tree_extension_data=False): + def write(self, file_path=None, ignore_extension_data=False): """Write the current state to our file path or to the given one :param file_path: @@ -190,9 +191,10 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): Please note that this will change the file_path of this index to the one you gave. - :param ignore_tree_extension_data: + :param ignore_extension_data: If True, the TREE type extension data read in the index will not - be written to disk. Use this if you have altered the index and + be written to disk. NOTE that no extension data is actually written. + Use this if you have altered the index and would like to use git-write-tree afterwards to create a tree representing your written changes. If this data is present in the written index, git-write-tree @@ -208,7 +210,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): lfd = LockedFD(file_path or self._file_path) stream = lfd.open(write=True, stream=True) - self._serialize(stream, ignore_tree_extension_data) + self._serialize(stream, ignore_extension_data) lfd.commit() @@ -612,7 +614,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): return entries_added def add(self, items, force=True, fprogress=lambda *args: None, path_rewriter=None, - write=True): + write=True, write_extension_data=False): """Add files from the working tree, specific blobs or BaseIndexEntries to the index. @@ -689,8 +691,19 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): Please note that entry.path is relative to the git repository. :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. + 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. + + :param write_extension_data: + If True, extension data will be written back to the index. This can lead to issues in case + it is containing the 'TREE' extension, which will cause the `git commit` command to write an + old tree, instead of a new one representing the now changed index. + This doesn't matter if you use `IndexFile.commit()`, which ignores the `TREE` extension altogether. + You should set it to True if you intend to use `IndexFile.commit()` exclusively while maintaining + support for third-party extensions. Besides that, you can usually safely ignore the built-in + extensions when using GitPython on repositories that are not handled manually at all. + All current built-in extensions are listed here: + http://opensource.apple.com/source/Git/Git-26/src/git-htmldocs/technical/index-format.txt :return: List(BaseIndexEntries) representing the entries just actually added. @@ -763,7 +776,7 @@ class IndexFile(LazyMixin, diff.Diffable, Serializable): self.entries[(entry.path, 0)] = IndexEntry.from_base(entry) if write: - self.write() + self.write(ignore_extension_data=not write_extension_data) # END handle write return entries_added diff --git a/git/test/test_index.py b/git/test/test_index.py index 8124ec16..63f99f10 100644 --- a/git/test/test_index.py +++ b/git/test/test_index.py @@ -44,11 +44,8 @@ from git.index.typ import ( BaseIndexEntry, IndexEntry ) -from gitdb.test.lib import with_rw_directory from git.index.fun import hook_path -import git - class TestIndex(TestBase): @@ -768,15 +765,3 @@ class TestIndex(TestBase): except InvalidGitRepositoryError: asserted = True assert asserted, "Adding using a filename is not correctly asserted." - - @with_rw_directory - def test_index_add_corruption(self, rw_dir): - # Test for https://github.com/gitpython-developers/GitPython/issues/265 - repo = git.Repo.clone_from("git://pkgs.fedoraproject.org/GitPython", rw_dir) - assert not repo.is_dirty() - file_path = os.path.join(rw_dir, "GitPython.spec") - open(file_path, 'wb').close() - assert repo.is_dirty() - repo.index.add(['0001-GPG-signature-support-on-commit-object.patch', 'GitPython.spec', '.gitignore', 'sources']) - repo.git.commit(m="committing file") - assert not repo.is_dirty() |