Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a880c5f

Browse files
authored
Merge pull request #1124 from larsks/feature/replace
add replace method to git.Commit
2 parents e1cd58b + 36811a2 commit a880c5f

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

‎git/objects/commit.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,41 @@ def __init__(self, repo, binsha, tree=None, author=None, authored_date=None, aut
136136
def _get_intermediate_items(cls, commit):
137137
return commit.parents
138138

139+
@classmethod
140+
def _calculate_sha_(cls, repo, commit):
141+
'''Calculate the sha of a commit.
142+
143+
:param repo: Repo object the commit should be part of
144+
:param commit: Commit object for which to generate the sha
145+
'''
146+
147+
stream = BytesIO()
148+
commit._serialize(stream)
149+
streamlen = stream.tell()
150+
stream.seek(0)
151+
152+
istream = repo.odb.store(IStream(cls.type, streamlen, stream))
153+
return istream.binsha
154+
155+
def replace(self, **kwargs):
156+
'''Create new commit object from existing commit object.
157+
158+
Any values provided as keyword arguments will replace the
159+
corresponding attribute in the new object.
160+
'''
161+
162+
attrs = {k: getattr(self, k) for k in self.__slots__}
163+
164+
for attrname in kwargs:
165+
if attrname not in self.__slots__:
166+
raise ValueError('invalid attribute name')
167+
168+
attrs.update(kwargs)
169+
new_commit = self.__class__(self.repo, self.NULL_BIN_SHA, **attrs)
170+
new_commit.binsha = self._calculate_sha_(self.repo, new_commit)
171+
172+
return new_commit
173+
139174
def _set_cache_(self, attr):
140175
if attr in Commit.__slots__:
141176
# read the data in a chunk, its faster - then provide a file wrapper
@@ -375,13 +410,7 @@ def create_from_tree(cls, repo, tree, message, parent_commits=None, head=False,
375410
committer, committer_time, committer_offset,
376411
message, parent_commits, conf_encoding)
377412

378-
stream = BytesIO()
379-
new_commit._serialize(stream)
380-
streamlen = stream.tell()
381-
stream.seek(0)
382-
383-
istream = repo.odb.store(IStream(cls.type, streamlen, stream))
384-
new_commit.binsha = istream.binsha
413+
new_commit.binsha = cls._calculate_sha_(repo, new_commit)
385414

386415
if head:
387416
# need late import here, importing git at the very beginning throws

‎test/test_commit.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ def test_bake(self):
101101
assert isinstance(commit.author_tz_offset, int) and isinstance(commit.committer_tz_offset, int)
102102
self.assertEqual(commit.message, "Added missing information to docstrings of commit and stats module\n")
103103

104+
def test_replace_no_changes(self):
105+
old_commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
106+
new_commit = old_commit.replace()
107+
108+
for attr in old_commit.__slots__:
109+
assert getattr(new_commit, attr) == getattr(old_commit, attr)
110+
111+
def test_replace_new_sha(self):
112+
commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
113+
new_commit = commit.replace(message='Added replace method')
114+
115+
assert new_commit.hexsha == 'fc84cbecac1bd4ba4deaac07c1044889edd536e6'
116+
assert new_commit.message == 'Added replace method'
117+
118+
def test_replace_invalid_attribute(self):
119+
commit = self.rorepo.commit('2454ae89983a4496a445ce347d7a41c0bb0ea7ae')
120+
121+
with self.assertRaises(ValueError):
122+
commit.replace(badattr='This will never work')
123+
104124
def test_stats(self):
105125
commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')
106126
stats = commit.stats

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /