From d0d738c99b6fb427e5c0be1da5d41d11b64480df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saugat=20Pachhai=20=28=E0=A4=B8=E0=A5=8C=E0=A4=97=E0=A4=BE?= =?UTF-8?q?=E0=A4=A4=29?= Date: Thu, 25 Aug 2022 18:30:09 +0545 Subject: [PATCH] data status: make untracked files to be relative paths --- dvc/repo/data.py | 31 +++++++++++++++++++++++------- tests/func/test_data_status.py | 35 ++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/dvc/repo/data.py b/dvc/repo/data.py index 2d84361eec..d77d2fedf9 100644 --- a/dvc/repo/data.py +++ b/dvc/repo/data.py @@ -1,6 +1,15 @@ import os from collections import defaultdict -from typing import TYPE_CHECKING, Any, Dict, List, Optional, TypedDict, cast +from typing import ( + TYPE_CHECKING, + Any, + Dict, + Iterable, + List, + Optional, + TypedDict, + cast, +) from dvc.ui import ui @@ -250,15 +259,23 @@ class Status(TypedDict): git: GitInfo -def _transform_git_paths_to_dvc(repo: "Repo", files: List[str]): +def _transform_git_paths_to_dvc(repo: "Repo", files: Iterable[str]): """Transform files rel. to Git root to DVC root, and drop outside files.""" rel = repo.fs.path.relpath(repo.root_dir, repo.scm.root_dir).rstrip("/") - if rel in (os.curdir, ""): - return files - prefix = rel + os.sep - length = len(prefix) - return [file[length:] for file in files if file.startswith(prefix)] + # if we have repo root in a different location than scm's root, + # i.e. subdir repo, all git_paths need to be transformed rel. to the DVC + # repo root and anything outside need to be filtered out. + if rel not in (os.curdir, ""): + prefix = rel + os.sep + length = len(prefix) + files = (file[length:] for file in files if file.startswith(prefix)) + + start = repo.fs.path.relpath(repo.fs.path.getcwd(), repo.root_dir) + if start in (os.curdir, ""): + return list(files) + # we need to convert repo relative paths to curdir relative. + return [repo.fs.path.relpath(file, start) for file in files] def status(repo: "Repo", untracked_files: str = "no", **kwargs: Any) -> Status: diff --git a/tests/func/test_data_status.py b/tests/func/test_data_status.py index 47508e23b1..5ea8913ee9 100644 --- a/tests/func/test_data_status.py +++ b/tests/func/test_data_status.py @@ -1,6 +1,9 @@ from os.path import join +import pytest + from dvc.repo import Repo +from dvc.repo.data import _transform_git_paths_to_dvc from dvc.testing.tmp_dir import make_subrepo from dvc.utils.fs import remove @@ -14,6 +17,38 @@ } +@pytest.mark.parametrize("path", [None, ("sub", "repo")]) +def test_git_to_dvc_path_wdir_transformation(tmp_dir, scm, path): + struct = {"dir": {"foo": "foo", "bar": "bar"}, "file": "file", "dir2": {}} + tmp_dir.gen(struct) + + subdir = tmp_dir.joinpath(*path) if path else tmp_dir + make_subrepo(subdir, scm) + dvc = subdir.dvc + + with subdir.chdir(): + subdir.gen(struct) + _, _, untracked = scm.status(untracked_files="all") + untracked = sorted(untracked, reverse=True) + assert _transform_git_paths_to_dvc(dvc, untracked) == [ + "file", + join("dir", "foo"), + join("dir", "bar"), + ] + with (subdir / "dir").chdir(): + assert _transform_git_paths_to_dvc(dvc, untracked) == [ + join("..", "file"), + "foo", + "bar", + ] + with (subdir / "dir2").chdir(): + assert _transform_git_paths_to_dvc(dvc, untracked) == [ + join("..", "file"), + join("..", "dir", "foo"), + join("..", "dir", "bar"), + ] + + def test_file(M, tmp_dir, dvc, scm): tmp_dir.dvc_gen("foo", "foo", commit="add foo") tmp_dir.dvc_gen("foo", "foobar")