diff --git a/dvc/cli.py b/dvc/cli.py index 2ba52bb3f..b40c51ed1 100644 --- a/dvc/cli.py +++ b/dvc/cli.py @@ -226,6 +226,17 @@ def parse_args(argv=None): 'remove', parents=[parent_parser], help='Remove outputs of DVC file.') + remove_parser_group = remove_parser.add_mutually_exclusive_group() + remove_parser_group.add_argument('-o', + '--outs', + action='store_true', + default=True, + help='Only remove DVC file outputs.') + remove_parser_group.add_argument('-p', + '--purge', + action='store_true', + default=False, + help='Remove DVC file and all its outputs') remove_parser.add_argument('targets', nargs='+', help='DVC files.') diff --git a/dvc/command/remove.py b/dvc/command/remove.py index 228e3a365..aea78dfdb 100644 --- a/dvc/command/remove.py +++ b/dvc/command/remove.py @@ -4,9 +4,10 @@ from dvc.command.common.base import CmdBase class CmdRemove(CmdBase): def run(self): + outs_only = not self.args.purge for target in self.args.targets: try: - self.project.remove(target) + self.project.remove(target, outs_only=outs_only) except DvcException as ex: self.project.logger.error('Failed to remove {}', ex) return 1 diff --git a/dvc/project.py b/dvc/project.py index c6f3ae832..05a6c3d36 100644 --- a/dvc/project.py +++ b/dvc/project.py @@ -123,13 +123,15 @@ class Project(object): stage.dump() return stage - def remove(self, target): + def remove(self, target, outs_only=False): if not Stage.is_stage_file(target): raise StageNotFoundError(target) stage = Stage.load(self, target) - for out in stage.outs: - out.remove() + if outs_only: + stage.remove_outs() + else: + stage.remove() return stage diff --git a/tests/test_remove.py b/tests/test_remove.py index b6503feab..7ae68f6ee 100644 --- a/tests/test_remove.py +++ b/tests/test_remove.py @@ -11,12 +11,18 @@ from tests.basic_env import TestDvc class TestRemove(TestDvc): def test(self): stage = self.dvc.add(self.FOO) - stage_removed = self.dvc.remove(stage.path) + stage_removed = self.dvc.remove(stage.path, outs_only=True) self.assertIsInstance(stage_removed, Stage) self.assertEqual(stage.path, stage_removed.path) self.assertFalse(os.path.isfile(self.FOO)) + stage_removed = self.dvc.remove(stage.path) + self.assertIsInstance(stage_removed, Stage) + self.assertEqual(stage.path, stage_removed.path) + self.assertFalse(os.path.isfile(self.FOO)) + self.assertFalse(os.path.exists(stage.path)) + class TestRemoveNonExistentFile(TestDvc): def test(self): @@ -30,7 +36,7 @@ class TestRemoveDirectory(TestDvc): stage_removed = self.dvc.remove(stage_add.path) self.assertEqual(stage_add.path, stage_removed.path) self.assertFalse(os.path.exists(self.DATA_DIR)) - self.assertTrue(os.path.exists(stage_removed.path)) + self.assertFalse(os.path.exists(stage_removed.path)) class TestCmdRemove(TestDvc):