From 498a4d5d3ae3b2ee876722461abab3e6cb4966a8 Mon Sep 17 00:00:00 2001 From: skshetry <18718008+skshetry@users.noreply.github.com> Date: Fri, 17 Oct 2025 19:07:51 +0545 Subject: [PATCH] move: fix error message when dst stage file exists (#10893) --- dvc/repo/move.py | 27 ++++++++++++++++----------- tests/func/test_move.py | 10 ++++++++++ 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/dvc/repo/move.py b/dvc/repo/move.py index 11a92861e..49d2361f5 100644 --- a/dvc/repo/move.py +++ b/dvc/repo/move.py @@ -1,7 +1,6 @@ import os from typing import TYPE_CHECKING -from dvc.exceptions import MoveNotDataSourceError from dvc.repo.scm_context import scm_context from . import locked @@ -38,7 +37,9 @@ def move(self: "Repo", from_path, to_path): """ from dvc import dependency, output from dvc.dvcfile import DVC_FILE_SUFFIX + from dvc.exceptions import MoveNotDataSourceError from dvc.stage import Stage + from dvc.stage.exceptions import StageFileAlreadyExistsError from dvc_objects.fs.local import LocalFileSystem from_out = output.loads_from(Stage(self), [from_path])[0] @@ -64,16 +65,20 @@ def move(self: "Repo", from_path, to_path): ) new_wdir = os.path.abspath(os.path.join(os.curdir, os.path.dirname(to_path))) to_path = os.path.relpath(to_path, new_wdir) - new_stage = self.stage.create( - single_stage=True, - fname=new_fname, - wdir=new_wdir, - outs=[to_path], - meta=stage.meta, - frozen=stage.frozen, - always_changed=stage.always_changed, - desc=stage.desc, - ) + try: + new_stage = self.stage.create( + single_stage=True, + fname=new_fname, + wdir=new_wdir, + outs=[to_path], + meta=stage.meta, + frozen=stage.frozen, + always_changed=stage.always_changed, + desc=stage.desc, + ) + except StageFileAlreadyExistsError: + # reraise to remove `--force` hint + raise StageFileAlreadyExistsError(f"{new_fname!r} already exists") from None else: new_stage = stage to_path = os.path.relpath(to_path, stage.wdir) diff --git a/tests/func/test_move.py b/tests/func/test_move.py index 5c0ca15c6..d1702d503 100644 --- a/tests/func/test_move.py +++ b/tests/func/test_move.py @@ -6,6 +6,7 @@ import pytest from dvc.cli import main from dvc.exceptions import MoveNotDataSourceError, OutputNotFoundError +from dvc.stage.exceptions import StageFileAlreadyExistsError def test_move(tmp_dir, dvc, scm): @@ -382,3 +383,12 @@ def test_all_metadata_are_preserved(tmp_dir, dvc, make_tmp_dir, path_func): contents["deps"][0] |= {"path": expected_path} contents |= {"md5": stage.md5} assert new_dvcfile.parse() == contents + + +def test_move_dst_stage_file_already_exists(tmp_dir, dvc): + tmp_dir.dvc_gen({"foo": "foo", "bar": "bar"}) + + with pytest.raises(StageFileAlreadyExistsError) as exc_info: + dvc.move("foo", "bar") + assert str(exc_info.value) == "'bar.dvc' already exists" + assert exc_info.value.__cause__ is None