diff --git a/dvc/output/base.py b/dvc/output/base.py index 37d30a210c..97edd60fa2 100644 --- a/dvc/output/base.py +++ b/dvc/output/base.py @@ -239,6 +239,12 @@ def ignore(self): self.repo.scm.ignore(self.fspath) + def ignore_remove(self): + if not self.use_scm_ignore: + return + + self.repo.scm.ignore_remove(self.fspath) + def save(self): if not self.exists: raise self.DoesNotExistError(self) @@ -336,8 +342,8 @@ def remove(self, ignore_remove=False): if self.scheme != "local": return - if ignore_remove and self.use_scm_ignore: - self.repo.scm.ignore_remove(self.fspath) + if ignore_remove: + self.ignore_remove() def move(self, out): if self.scheme == "local" and self.use_scm_ignore: diff --git a/dvc/stage/__init__.py b/dvc/stage/__init__.py index 85615c43f8..c39969babf 100644 --- a/dvc/stage/__init__.py +++ b/dvc/stage/__init__.py @@ -286,12 +286,17 @@ def unprotect_outs(self): for out in self.outs: out.unprotect() + def ignore_remove_outs(self): + for out in self.outs: + out.ignore_remove() + @rwlocked(write=["outs"]) def remove(self, force=False, remove_outs=True, purge=True): if remove_outs: self.remove_outs(ignore_remove=True, force=force) else: self.unprotect_outs() + self.ignore_remove_outs() if purge: self.dvcfile.remove_stage(self) diff --git a/tests/func/test_remove.py b/tests/func/test_remove.py index ac6057e65e..e5f3ef4ff7 100644 --- a/tests/func/test_remove.py +++ b/tests/func/test_remove.py @@ -7,14 +7,19 @@ from dvc.stage.exceptions import StageFileDoesNotExistError from dvc.system import System from dvc.utils.fs import remove +from tests.utils import get_gitignore_content @pytest.mark.parametrize("remove_outs", [True, False]) -def test_remove(tmp_dir, dvc, run_copy, remove_outs): +def test_remove(tmp_dir, scm, dvc, run_copy, remove_outs): (stage1,) = tmp_dir.dvc_gen("foo", "foo") stage2 = run_copy("foo", "bar", single_stage=True) stage3 = run_copy("bar", "foobar", name="copy-bar-foobar") + assert "/foo" in get_gitignore_content() + assert "/bar" in get_gitignore_content() + assert "/foobar" in get_gitignore_content() + for stage in [stage1, stage2, stage3]: dvc.remove(stage.addressing, outs=remove_outs) out_exists = (out.exists for out in stage.outs) @@ -24,6 +29,8 @@ def test_remove(tmp_dir, dvc, run_copy, remove_outs): else: assert all(out_exists) + assert not any(out in get_gitignore_content() for out in stage.outs) + def test_remove_non_existent_file(tmp_dir, dvc): with pytest.raises(StageFileDoesNotExistError):