From 3f846a1794bc1ad1a782b0e44cd0c003591ffa55 Mon Sep 17 00:00:00 2001 From: karajan1001 Date: Wed, 20 May 2020 22:53:25 +0800 Subject: [PATCH] Add a new rename command (#3794) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixed #3599 1. add new command `dvc remote rename `. 2. add tests for this new command. * Update dvc/command/remote.py Co-authored-by: Peter Rowlands (변기호) * Change about code review * For deepsource * Update dvc/command/remote.py Co-authored-by: Peter Rowlands (변기호) --- dvc/command/remote.py | 40 ++++++++++++++++++++++ tests/func/test_remote.py | 71 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/dvc/command/remote.py b/dvc/command/remote.py index 74fa2b677..5a0506c34 100644 --- a/dvc/command/remote.py +++ b/dvc/command/remote.py @@ -104,6 +104,35 @@ class CmdRemoteList(CmdRemote): return 0 +class CmdRemoteRename(CmdRemote): + def _rename_default(self, conf): + if conf["core"].get("remote") == self.args.name: + conf["core"]["remote"] = self.args.new + + def run(self): + all_config = self.config.load_config_to_level(None) + if self.args.new in all_config.get("remote", {}): + raise ConfigError( + "Rename failed. Remote name '{}' already exists.".format( + {self.args.new} + ) + ) + + with self.config.edit(self.args.level) as conf: + self._check_exists(conf) + conf["remote"][self.args.new] = conf["remote"][self.args.name] + del conf["remote"][self.args.name] + self._rename_default(conf) + + for level in reversed(self.config.LEVELS): + if level == self.args.level: + break + with self.config.edit(level) as level_conf: + self._rename_default(level_conf) + + return 0 + + def add_parser(subparsers, parent_parser): from dvc.command.config import parent_config_parser @@ -220,3 +249,14 @@ def add_parser(subparsers, parent_parser): "name", help="Name of the remote to remove." ) remote_remove_parser.set_defaults(func=CmdRemoteRemove) + REMOTE_RENAME_HELP = "Rename a DVC remote" + remote_rename_parser = remote_subparsers.add_parser( + "rename", + parents=[parent_config_parser, parent_parser], + description=append_doc_link(REMOTE_RENAME_HELP, "remote/rename"), + help=REMOTE_RENAME_HELP, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + remote_rename_parser.add_argument("name", help="Remote to be renamed") + remote_rename_parser.add_argument("new", help="New name of the remote") + remote_rename_parser.set_defaults(func=CmdRemoteRename) diff --git a/tests/func/test_remote.py b/tests/func/test_remote.py index d8217eda0..6a031742a 100644 --- a/tests/func/test_remote.py +++ b/tests/func/test_remote.py @@ -284,3 +284,74 @@ def test_remote_modify_default(dvc): assert repo_config["core"]["remote"] == remote_repo assert local_config["core"]["remote"] == remote_local + + +def test_remote_rename(dvc): + remote_name = "drive" + remote_url = "gdrive://test/test" + new_name = "new" + other_name = "other" + # prepare + assert main(["remote", "add", remote_name, remote_url]) == 0 + config = dvc.config.load_one("repo") + assert config["remote"][remote_name]["url"] == remote_url + assert new_name not in config.get("remote", {}) + + # rename failed + assert main(["remote", "rename", remote_name]) == 254 + assert main(["remote", "rename", new_name, other_name]) == 251 + config = dvc.config.load_one("repo") + assert config["remote"][remote_name]["url"] == remote_url + assert new_name not in config.get("remote", {}) + + # rename success + assert main(["remote", "rename", remote_name, new_name]) == 0 + config = dvc.config.load_one("repo") + assert remote_name not in config.get("remote", {}) + assert config["remote"][new_name]["url"] == remote_url + + +def test_remote_duplicated(dvc): + remote_name = "drive" + remote_url = "gdrive://test/test" + used_name = "overlap" + another_url = "gdrive://test/test1" + # prepare + assert main(["remote", "add", remote_name, remote_url]) == 0 + assert main(["remote", "add", "--local", used_name, another_url]) == 0 + config = dvc.config.load_one("repo") + assert config["remote"][remote_name]["url"] == remote_url + local_config = dvc.config.load_one("local") + assert local_config["remote"][used_name]["url"] == another_url + + # rename duplicated + assert main(["remote", "rename", remote_name, used_name]) == 251 + config = dvc.config.load_one("repo") + assert config["remote"][remote_name]["url"] == remote_url + local_config = dvc.config.load_one("local") + assert local_config["remote"][used_name]["url"] == another_url + + +def test_remote_default(dvc): + remote_name = "drive" + remote_url = "gdrive://test/test" + new_name = "new" + # prepare + assert main(["remote", "add", "-d", remote_name, remote_url]) == 0 + assert main(["remote", "default", "--local", remote_name]) == 0 + config = dvc.config.load_one("repo") + assert config["core"]["remote"] == remote_name + assert config["remote"][remote_name]["url"] == remote_url + assert new_name not in config.get("remote", {}) + local_config = dvc.config.load_one("local") + assert local_config["core"]["remote"] == remote_name + + # rename success + assert main(["remote", "rename", remote_name, new_name]) == 0 + config = dvc.config.load_one("repo") + assert remote_name not in config.get("remote", {}) + assert config["core"]["remote"] == new_name + assert config["remote"][new_name]["url"] == remote_url + assert remote_name not in config.get("remote", {}) + local_config = dvc.config.load_one("local") + assert local_config["core"]["remote"] == new_name