From 7865ddd1284336d101f83fe3993129cd6f9b21e1 Mon Sep 17 00:00:00 2001 From: "Mr. Outis" Date: Sun, 28 Oct 2018 21:14:32 -0600 Subject: [PATCH] remove: Add confirmation when trying to purge (#1269) Close #1228 --- dvc/cli.py | 6 ++++++ dvc/command/remove.py | 24 +++++++++++++++++++++++- tests/test_remove.py | 22 ++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/dvc/cli.py b/dvc/cli.py index 495dca064..a40f2eb20 100644 --- a/dvc/cli.py +++ b/dvc/cli.py @@ -501,6 +501,12 @@ def parse_args(argv=None): action='store_true', default=False, help='Remove DVC file and all its outputs.') + remove_parser.add_argument( + '-f', + '--force', + action='store_true', + default=False, + help='Force purge.') remove_parser.add_argument( 'targets', nargs='+', diff --git a/dvc/command/remove.py b/dvc/command/remove.py index f37d1bb8c..41de21e2f 100644 --- a/dvc/command/remove.py +++ b/dvc/command/remove.py @@ -4,10 +4,32 @@ from dvc.logger import Logger class CmdRemove(CmdBase): + def _is_outs_only(self, target): + if not self.args.purge: + return True + + if self.args.force: + return False + + msg = ( + u'Are you sure you want to remove {} with its outputs?' + .format(target) + ) + + confirmed = self.project.prompt.prompt(msg) + + if confirmed: + return False + + raise DvcException( + u'Cannot purge without a confirmation from the user.' + u" Use '-f' to force." + ) + def run(self): - outs_only = not self.args.purge for target in self.args.targets: try: + outs_only = self._is_outs_only(target) self.project.remove(target, outs_only=outs_only) except DvcException as ex: Logger.error('Failed to remove {}'.format(target), ex) diff --git a/tests/test_remove.py b/tests/test_remove.py index 49b44c7df..66729f15e 100644 --- a/tests/test_remove.py +++ b/tests/test_remove.py @@ -2,9 +2,11 @@ import os from dvc.main import main from dvc.stage import Stage, StageFileDoesNotExistError +from dvc.exceptions import DvcException from dvc.command.remove import CmdRemove from tests.basic_env import TestDvc +from mock import patch class TestRemove(TestDvc): @@ -57,3 +59,23 @@ class TestCmdRemove(TestDvc): ret = main(['remove', 'non-existing-dvc-file']) self.assertNotEqual(ret, 0) + +class TestRemovePurge(TestDvc): + def test(self): + dvcfile = self.dvc.add(self.FOO)[0].path + ret = main(['remove', '--purge', '--force', dvcfile]) + + self.assertEqual(ret, 0) + self.assertFalse(os.path.exists(self.FOO)) + self.assertFalse(os.path.exists(dvcfile)) + + @patch('dvc.prompt.Prompt.prompt') + def test_force(self, mock_prompt): + mock_prompt.return_value = False + + dvcfile = self.dvc.add(self.FOO)[0].path + ret = main(['remove', '--purge', dvcfile]) + + mock_prompt.assert_called() + self.assertEqual(ret, 1) + self.assertRaises(DvcException)