Skip to content

Commit 2ba897b

Browse files
committed
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
1 parent ae6e26e commit 2ba897b

File tree

4 files changed

+26
-3
lines changed

4 files changed

+26
-3
lines changed

doc/source/changes.rst

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Changelog
66
=============================
77

88
* `tag.commit` will now resolve commits deeply.
9+
* `Repo` objects can now be pickled, which helps with multi-processing.
910

1011
* `DiffIndex.iter_change_type(...)` produces better results when diffing
1112
2.0.8 - Features and Bugfixes

git/cmd.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,17 @@ def _deplete_buffer(fno, handler, buf_list, wg=None):
213213

214214
def dashify(string):
215215
return string.replace('_', '-')
216+
217+
218+
def slots_to_dict(self, exclude=()):
219+
return dict((s, getattr(self, s)) for s in self.__slots__ if s not in exclude)
220+
221+
222+
def dict_to_slots_and__excluded_are_none(self, d, excluded=()):
223+
for k, v in d.items():
224+
setattr(self, k, v)
225+
for k in excluded:
226+
setattr(self, k, None)
216227

217228
## -- End Utilities -- @}
218229

@@ -235,7 +246,15 @@ class Git(LazyMixin):
235246
"""
236247
__slots__ = ("_working_dir", "cat_file_all", "cat_file_header", "_version_info",
237248
"_git_options", "_environment")
238-
249+
250+
_excluded_ = ('cat_file_all', 'cat_file_header', '_version_info')
251+
252+
def __getstate__(self):
253+
return slots_to_dict(self, exclude=self._excluded_)
254+
255+
def __setstate__(self, d):
256+
dict_to_slots_and__excluded_are_none(self, d, excluded=self._excluded_)
257+
239258
# CONFIGURATION
240259
# The size in bytes read from stdout when copying git's output to another stream
241260
max_chunk_size = 1024 * 64

git/repo/base.py

-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ class Repo(object):
9393
9494
'git_dir' is the .git repository directory, which is always set."""
9595
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
96-
__slots__ = ("working_dir", "_working_tree_dir", "git_dir", "_bare", "git", "odb")
9796

9897
# precompiled regex
9998
re_whitespace = re.compile(r'\s+')

git/test/test_repo.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#
55
# This module is part of GitPython and is released under
66
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
7+
import pickle
8+
79
from git.test.lib import (
810
patch,
911
TestBase,
@@ -104,13 +106,15 @@ def test_tree_from_revision(self):
104106

105107
# try from invalid revision that does not exist
106108
self.failUnlessRaises(BadName, self.rorepo.tree, 'hello world')
109+
110+
def test_pickleable(self):
111+
pickle.loads(pickle.dumps(self.rorepo))
107112

108113
def test_commit_from_revision(self):
109114
commit = self.rorepo.commit('0.1.4')
110115
assert commit.type == 'commit'
111116
assert self.rorepo.commit(commit) == commit
112117

113-
def test_commits(self):
114118
mc = 10
115119
commits = list(self.rorepo.iter_commits('0.1.6', max_count=mc))
116120
assert len(commits) == mc

0 commit comments

Comments
 (0)