Skip to content

Commit

Permalink
git: is_tracked: use ls_files instead of walking the index (iterative…
Browse files Browse the repository at this point in the history
…#3677)

Current implementation doesn't work with directories, which results in
hard-to-debug bugs like iterative#3561. The bug that made us walk through index
manually is now fixed in gitpython, so we can simply use `ls_files` from
now on. Added some tests to prevent this from happening in the future.

Fixes iterative#3561
  • Loading branch information
efiop authored Apr 24, 2020
1 parent ae9bc91 commit e2981d2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 5 deletions.
6 changes: 1 addition & 5 deletions dvc/scm/git/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,7 @@ def untracked_files(self):
return [os.path.join(self.repo.working_dir, fname) for fname in files]

def is_tracked(self, path):
# it is equivalent to `bool(self.repo.git.ls_files(path))` by
# functionality, but ls_files fails on unicode filenames
path = relpath(path, self.root_dir)
# There are 4 stages, see BaseIndexEntry.stage
return any((path, i) in self.repo.index.entries for i in (0, 1, 2, 3))
return bool(self.repo.git.ls_files(path))

def is_dirty(self):
return self.repo.is_dirty()
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/scm/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,37 @@ def test_walk_with_submodules(tmp_dir, scm, git_dir):
# currently we don't walk through submodules
assert not dirs
assert set(files) == {".gitmodules", "submodule"}


def test_is_tracked(tmp_dir, scm):
tmp_dir.scm_gen(
{
"tracked": "tracked",
"dir": {"data": "data", "subdir": {"subdata": "subdata"}},
},
commit="add dirs and files",
)
tmp_dir.gen({"untracked": "untracked", "dir": {"untracked": "untracked"}})

# sanity check
assert (tmp_dir / "untracked").exists()
assert (tmp_dir / "tracked").exists()
assert (tmp_dir / "dir" / "untracked").exists()
assert (tmp_dir / "dir" / "data").exists()
assert (tmp_dir / "dir" / "subdir" / "subdata").exists()

assert not scm.is_tracked("untracked")
assert not scm.is_tracked(os.path.join("dir", "untracked"))

assert scm.is_tracked("tracked")
assert scm.is_tracked("dir")
assert scm.is_tracked(os.path.join("dir", "data"))
assert scm.is_tracked(os.path.join("dir", "subdir"))
assert scm.is_tracked(os.path.join("dir", "subdir", "subdata"))


def test_is_tracked_unicode(tmp_dir, scm):
tmp_dir.scm_gen("ṭṝḁḉḵḗḋ", "tracked", commit="add unicode")
tmp_dir.gen("ṳṋṭṝḁḉḵḗḋ", "untracked")
assert scm.is_tracked("ṭṝḁḉḵḗḋ")
assert not scm.is_tracked("ṳṋṭṝḁḉḵḗḋ")

0 comments on commit e2981d2

Please sign in to comment.