Skip to content

Add support for diffing against root commit #408

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Apr 19, 2016
Prev Previous commit
Next Next commit
Support "root" as a special value in .diff() calls
This enabled getting diff patches for root commits.
  • Loading branch information
nvie committed Apr 14, 2016
commit 5de21c7fa2bdd5cd50c4f62ba848af54589167d0
14 changes: 10 additions & 4 deletions git/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs):
If None, we will be compared to the working tree.
If Treeish, it will be compared against the respective tree
If Index ( type ), it will be compared against the index.
If the string 'root', it will compare the empty tree against this tree.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using the string 'root', I am afraid that it would permanently block usage of a similarly named treeish, which could be the name of a tag or ref for example.
How would you circumvent this problem (or is it maybe not a problem at all) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very good argument against it indeed. Rather than using a special string here, I've now opted for a special object, a little bit like the Index class. New usage:

from git import NULL_TREE
commit.diff(NULL_TREE)

Fixed in 82b533f. What do you think of this API?

It defaults to Index to assure the method will not by-default fail
on bare repositories.

Expand Down Expand Up @@ -87,10 +88,15 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs):
if paths is not None and not isinstance(paths, (tuple, list)):
paths = [paths]

if other is not None and other is not self.Index:
args.insert(0, other)
diff_cmd = self.repo.git.diff
if other is self.Index:
args.insert(0, "--cached")
args.insert(0, '--cached')
elif other == 'root':
args.insert(0, '--root')
diff_cmd = self.repo.git.diff_tree
elif other is not None:
args.insert(0, other)
diff_cmd = self.repo.git.diff_tree

args.insert(0, self)

Expand All @@ -101,7 +107,7 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs):
# END paths handling

kwargs['as_process'] = True
proc = self.repo.git.diff(*self._process_diff_args(args), **kwargs)
proc = diff_cmd(*self._process_diff_args(args), **kwargs)

diff_method = Diff._index_from_raw_format
if create_patch:
Expand Down
10 changes: 10 additions & 0 deletions git/test/fixtures/diff_initial
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- /dev/null
+++ b/CHANGES
@@ -0,0 +1,7 @@
+=======
+CHANGES
+=======
+
+0.1.0
+=====
+initial release
17 changes: 16 additions & 1 deletion git/test/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,21 @@ def test_diff_index_raw_format(self):
assert res[0].deleted_file
assert res[0].b_path == ''

def test_diff_initial_commit(self):
initial_commit = self.rorepo.commit('33ebe7acec14b25c5f84f35a664803fcab2f7781')

# Without creating a patch...
diff_index = initial_commit.diff('root')
assert diff_index[0].b_path == 'CHANGES'
assert diff_index[0].new_file
assert diff_index[0].diff == ''

# ...and with creating a patch
diff_index = initial_commit.diff('root', create_patch=True)
assert diff_index[0].b_path == 'CHANGES'
assert diff_index[0].new_file
assert diff_index[0].diff == fixture('diff_initial')

def test_diff_patch_format(self):
# test all of the 'old' format diffs for completness - it should at least
# be able to deal with it
Expand All @@ -149,7 +164,7 @@ def test_diff_interface(self):
diff_item = commit.tree
# END use tree every second item

for other in (None, commit.Index, commit.parents[0]):
for other in (None, 'root', commit.Index, commit.parents[0]):
for paths in (None, "CHANGES", ("CHANGES", "lib")):
for create_patch in range(2):
diff_index = diff_item.diff(other=other, paths=paths, create_patch=create_patch)
Expand Down