summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2016-09-11 17:40:44 +0200
committerSebastian Thiel <byronimo@gmail.com>2016-09-11 17:43:18 +0200
commit2ba897b12024fd20681b7c2f1b40bdbbccd5df59 (patch)
treefe1fca314bd72dfceadd36179867e43e9d66e341
parentae6e26ed4abac8b5e4e0a893da5546cd165d48e7 (diff)
downloadgitpython-2ba897b12024fd20681b7c2f1b40bdbbccd5df59.tar.gz
fix(repo): make it serializable with pickle
It's entirely untested if this repo still does the right thing, but I'd think it does. Fixes #504
-rw-r--r--doc/source/changes.rst1
-rw-r--r--git/cmd.py21
-rw-r--r--git/repo/base.py1
-rw-r--r--git/test/test_repo.py6
4 files changed, 26 insertions, 3 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
index 1feacab8..62f8ab45 100644
--- a/doc/source/changes.rst
+++ b/doc/source/changes.rst
@@ -6,6 +6,7 @@ Changelog
=============================
* `tag.commit` will now resolve commits deeply.
+* `Repo` objects can now be pickled, which helps with multi-processing.
* `DiffIndex.iter_change_type(...)` produces better results when diffing
2.0.8 - Features and Bugfixes
diff --git a/git/cmd.py b/git/cmd.py
index 62eef9e4..ceea2442 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -213,6 +213,17 @@ def handle_process_output(process, stdout_handler, stderr_handler, finalizer):
def dashify(string):
return string.replace('_', '-')
+
+
+def slots_to_dict(self, exclude=()):
+ return dict((s, getattr(self, s)) for s in self.__slots__ if s not in exclude)
+
+
+def dict_to_slots_and__excluded_are_none(self, d, excluded=()):
+ for k, v in d.items():
+ setattr(self, k, v)
+ for k in excluded:
+ setattr(self, k, None)
## -- End Utilities -- @}
@@ -235,7 +246,15 @@ class Git(LazyMixin):
"""
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
"_git_options", "_environment")
-
+
+ _excluded_ = ('cat_file_all', 'cat_file_header', '_version_info')
+
+ def __getstate__(self):
+ return slots_to_dict(self, exclude=self._excluded_)
+
+ def __setstate__(self, d):
+ dict_to_slots_and__excluded_are_none(self, d, excluded=self._excluded_)
+
# CONFIGURATION
# The size in bytes read from stdout when copying git's output to another stream
max_chunk_size = 1024 * 64
diff --git a/git/repo/base.py b/git/repo/base.py
index 312c01ef..0e46ee67 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -93,7 +93,6 @@ class Repo(object):
'git_dir' is the .git repository directory, which is always set."""
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
- __slots__ = ("working_dir", "_working_tree_dir", "git_dir", "_bare", "git", "odb")
# precompiled regex
re_whitespace = re.compile(r'\s+')
diff --git a/git/test/test_repo.py b/git/test/test_repo.py
index 17e990f9..e24062c1 100644
--- a/git/test/test_repo.py
+++ b/git/test/test_repo.py
@@ -4,6 +4,8 @@
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
+import pickle
+
from git.test.lib import (
patch,
TestBase,
@@ -104,13 +106,15 @@ class TestRepo(TestBase):
# try from invalid revision that does not exist
self.failUnlessRaises(BadName, self.rorepo.tree, 'hello world')
+
+ def test_pickleable(self):
+ pickle.loads(pickle.dumps(self.rorepo))
def test_commit_from_revision(self):
commit = self.rorepo.commit('0.1.4')
assert commit.type == 'commit'
assert self.rorepo.commit(commit) == commit
- def test_commits(self):
mc = 10
commits = list(self.rorepo.iter_commits('0.1.6', max_count=mc))
assert len(commits) == mc