Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions git/index/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1480,12 +1480,11 @@ def reset(

return self

# FIXME: This is documented to accept the same parameters as Diffable.diff, but this
# does not handle NULL_TREE for `other`. (The suppressed mypy error is about this.)
def diff(
self,
other: Union[ # type: ignore[override]
other: Union[
Literal[git_diff.DiffConstants.INDEX],
Literal[git_diff.DiffConstants.NULL_TREE],
"Tree",
"Commit",
str,
Expand All @@ -1512,6 +1511,44 @@ def diff(
if other is self.INDEX:
return git_diff.DiffIndex()

if other is git_diff.NULL_TREE:
args: List[Union[PathLike, str]] = [
"--cached",
"4b825dc642cb6eb9a060e54bf8d69288fbee4904",
"--abbrev=40",
"--full-index",
]
Comment on lines +1515 to +1520

if not any(x in kwargs for x in ("find_renames", "no_renames", "M")):
args.append("-M")

if create_patch:
args.append("-p")
args.append("--no-ext-diff")
else:
args.append("--raw")
args.append("-z")

args.append("--no-color")

if paths is not None and not isinstance(paths, (tuple, list)):
paths = [paths]

if paths:
args.append("--")
args.extend(paths)

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

diff_method = (
git_diff.Diff._index_from_patch_format if create_patch else git_diff.Diff._index_from_raw_format
)
index = diff_method(self.repo, proc)

proc.wait()
return index

# Index against anything but None is a reverse diff with the respective item.
# Handle existing -R flags properly.
# Transform strings to the object so that we can call diff on it.
Expand Down
30 changes: 29 additions & 1 deletion test/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import ddt
import pytest

from git import BlobFilter, Diff, Git, IndexFile, Object, Repo, Tree
from git import BlobFilter, Diff, Git, IndexFile, NULL_TREE, Object, Repo, Tree
from git.exc import (
CheckoutError,
GitCommandError,
Expand Down Expand Up @@ -555,6 +555,34 @@ def test_index_file_diffing(self, rw_repo):
rval = index.checkout("lib")
assert len(list(rval)) > 1

@with_rw_directory
def test_index_file_diff_null_tree_with_initial_index(self, rw_dir):
repo = Repo.init(rw_dir)
filename = ".gitkeep"
file_path = osp.join(repo.working_tree_dir, filename)
with open(file_path, "w") as fp:
fp.write("# Initial file\n")

index = repo.index
index.add([filename])
index.write()

index = IndexFile(repo)
assert not index.diff(None)

diff = index.diff(NULL_TREE)
self.assertEqual(len(diff), 1)
self.assertEqual(diff[0].change_type, "A")
assert diff[0].new_file
self.assertEqual(diff[0].b_path, filename)

self.assertEqual(len(index.diff(NULL_TREE, paths=filename)), 1)
self.assertEqual(len(index.diff(NULL_TREE, paths="missing")), 0)

patch = index.diff(NULL_TREE, create_patch=True)
self.assertEqual(len(patch), 1)
self.assertIn(b"+# Initial file", patch[0].diff)

def _count_existing(self, repo, files):
"""Return count of files that actually exist in the repository directory."""
existing = 0
Expand Down
Loading