From 1be55be246b58988426a66faa4d1803b4f02c1bc Mon Sep 17 00:00:00 2001 From: Robert Lowry Date: Sat, 12 Sep 2020 19:35:38 -0500 Subject: [PATCH 1/2] cli: add -C flag to change directories before executing commands Fixes #4025 --- dvc/cli.py | 9 +++++++++ dvc/command/base.py | 5 +++++ dvc/command/repro.py | 3 +-- tests/func/test_cli.py | 20 +++++++++++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/dvc/cli.py b/dvc/cli.py index 34e08a5481..23ef3c65fe 100644 --- a/dvc/cli.py +++ b/dvc/cli.py @@ -1,6 +1,7 @@ """DVC command line interface""" import argparse import logging +import os import sys from .command import ( @@ -191,6 +192,14 @@ def get_main_parser(): help="Show program's version.", ) + parser.add_argument( + "--cd", + default=os.path.curdir, + metavar="", + help="Change to directory before executing.", + type=str, + ) + # Sub commands subparsers = parser.add_subparsers( title="Available Commands", diff --git a/dvc/command/base.py b/dvc/command/base.py index bde1aaeeb1..67f9ac57b9 100644 --- a/dvc/command/base.py +++ b/dvc/command/base.py @@ -1,4 +1,5 @@ import logging +import os from abc import ABC, abstractmethod logger = logging.getLogger(__name__) @@ -32,6 +33,8 @@ def __init__(self, args): from dvc.repo import Repo from dvc.updater import Updater + os.chdir(args.cd) + self.repo = Repo() self.config = self.repo.config self.args = args @@ -55,3 +58,5 @@ def run(self): class CmdBaseNoRepo(CmdBase): def __init__(self, args): # pylint: disable=super-init-not-called self.args = args + + os.chdir(args.cd) diff --git a/dvc/command/repro.py b/dvc/command/repro.py index 683837b238..5301085dc0 100644 --- a/dvc/command/repro.py +++ b/dvc/command/repro.py @@ -15,8 +15,7 @@ class CmdRepro(CmdBase): def run(self): saved_dir = os.path.realpath(os.curdir) - if self.args.cwd: - os.chdir(self.args.cwd) + os.chdir(self.args.cwd) # Dirty hack so the for loop below can at least enter once if self.args.all_pipelines: diff --git a/tests/func/test_cli.py b/tests/func/test_cli.py index 76eacf43d9..c36e7f25c7 100644 --- a/tests/func/test_cli.py +++ b/tests/func/test_cli.py @@ -160,8 +160,22 @@ def test(self): class TestFindRoot(TestDvc): def test(self): - os.chdir("..") + class Cmd(CmdBase): + def run(self): + pass + + class A: + quiet = False + verbose = True + cd = os.path.pardir + args = A() + with self.assertRaises(DvcException): + Cmd(args) + + +class TestCd(TestDvc): + def test(self): class Cmd(CmdBase): def run(self): pass @@ -169,10 +183,14 @@ def run(self): class A: quiet = False verbose = True + cd = os.path.pardir + parent_dir = os.path.realpath(os.path.pardir) args = A() with self.assertRaises(DvcException): Cmd(args) + current_dir = os.path.realpath(os.path.curdir) + self.assertEqual(parent_dir, current_dir) def test_unknown_command_help(capsys): From 844ea5b3203bbdd783fe24576edc5c4a2c71f412 Mon Sep 17 00:00:00 2001 From: Robert Lowry Date: Fri, 25 Sep 2020 00:15:08 +0000 Subject: [PATCH 2/2] add deprecation notice to dvc repro help message --- dvc/command/repro.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dvc/command/repro.py b/dvc/command/repro.py index 5301085dc0..18962feb4e 100644 --- a/dvc/command/repro.py +++ b/dvc/command/repro.py @@ -96,7 +96,8 @@ def add_parser(subparsers, parent_parser): "-c", "--cwd", default=os.path.curdir, - help="Directory within your repo to reproduce from.", + help="Directory within your repo to reproduce from. Note: deprecated " + "by `dvc --cd `.", metavar="", ) repro_parser.add_argument(