From 1f03c40dbe47af8a7f64f6e1200aecd4b07273b0 Mon Sep 17 00:00:00 2001 From: dberenbaum Date: Mon, 1 May 2023 09:31:34 -0400 Subject: [PATCH] add: msg for overlapping parent --- dvc/repo/add.py | 26 ++++++++++++++++++++------ tests/func/test_add.py | 16 +++++++++++++++- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/dvc/repo/add.py b/dvc/repo/add.py index cfc38be62..98a57848e 100644 --- a/dvc/repo/add.py +++ b/dvc/repo/add.py @@ -29,13 +29,20 @@ Stages = List["Stage"] logger = logging.getLogger(__name__) -OVERLAPPING_OUTPUT_FMT = ( +OVERLAPPING_CHILD_FMT = ( "Cannot add '{out}', because it is overlapping with other " "DVC tracked output: '{parent}'.\n" "To include '{out}' in '{parent}', run " "'dvc commit {parent_stage}'" ) +OVERLAPPING_PARENT_FMT = ( + "Cannot add '{parent}', because it is overlapping with other " + "DVC tracked output: '{out}'.\n" + "To include '{out}' in '{parent}', run " + "'dvc remove {out_stage}' and then 'dvc add {parent}'" +) + def check_recursive_and_fname(args): if args.recursive and args.fname: @@ -86,11 +93,18 @@ def translate_graph_error(stages: Stages) -> Iterator[None]: try: yield except OverlappingOutputPathsError as exc: - msg = OVERLAPPING_OUTPUT_FMT.format( - out=exc.overlapping_out.fs_path, - parent=exc.parent.fs_path, - parent_stage=exc.parent.stage.addressing, - ) + if exc.parent in [o for s in stages for o in s.outs]: + msg = OVERLAPPING_PARENT_FMT.format( + out=exc.overlapping_out, + parent=exc.parent, + out_stage=exc.overlapping_out.stage.addressing, + ) + else: + msg = OVERLAPPING_CHILD_FMT.format( + out=exc.overlapping_out, + parent=exc.parent, + parent_stage=exc.parent.stage.addressing, + ) raise OverlappingOutputPathsError( # noqa: B904 exc.parent, exc.overlapping_out, msg ) diff --git a/tests/func/test_add.py b/tests/func/test_add.py index 5e65cd658..d2268778d 100644 --- a/tests/func/test_add.py +++ b/tests/func/test_add.py @@ -713,7 +713,6 @@ def test_escape_gitignore_entries(tmp_dir, scm, dvc): assert ignored_fname in get_gitignore_content() -@pytest.mark.xfail(reason="error message relpath") def test_add_from_data_dir(tmp_dir, scm, dvc): tmp_dir.dvc_gen({"dir": {"file1": "file1 content"}}) @@ -728,6 +727,21 @@ def test_add_from_data_dir(tmp_dir, scm, dvc): ).format(out=os.path.join("dir", "file2")) +def test_add_parent_dir(tmp_dir, scm, dvc): + tmp_dir.gen({"dir": {"file1": "file1 content"}}) + out_path = os.path.join("dir", "file1") + dvc.add(out_path, fname=out_path + ".dvc") + + with pytest.raises(OverlappingOutputPathsError) as e: + dvc.add("dir", fname="dir.dvc") + assert str(e.value) == ( + "Cannot add 'dir', because it is overlapping with other DVC " + "tracked output: '{out}'.\n" + "To include '{out}' in 'dir', run 'dvc remove {out}.dvc' " + "and then 'dvc add dir'" + ).format(out=os.path.join("dir", "file1")) + + def test_not_raises_on_re_add(tmp_dir, dvc): tmp_dir.dvc_gen("file", "file content")