From 97088d98b1fc175e6ca957ad1e73dab40d97822f Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Tue, 25 Jul 2017 02:29:49 -0700 Subject: [PATCH] Target cmd. First commit. --- dvc/command/init.py | 27 ++++++++++++++-------- dvc/command/run.py | 2 +- dvc/command/target.py | 54 +++++++++++++++++++++++++++++++++++++++++++ dvc/config.py | 21 +++++++++++++---- dvc/main.py | 5 +++- 5 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 dvc/command/target.py diff --git a/dvc/command/init.py b/dvc/command/init.py index 933f0e446..fbe38f7bf 100644 --- a/dvc/command/init.py +++ b/dvc/command/init.py @@ -20,6 +20,7 @@ class CmdInit(CmdBase): DataDir = {} CacheDir = {} StateDir = {} +TargetFile = {} # Supported clouds: AWS, GCP Cloud = AWS @@ -67,12 +68,13 @@ ProjectName = self.add_string_arg(parser, '--data-dir', 'Data directory.', 'data') self.add_string_arg(parser, '--cache-dir', 'Cache directory.', '.cache') self.add_string_arg(parser, '--state-dir', 'State directory.', '.state') + self.add_string_arg(parser, '--target-file', 'Target file.', Config.TARGET_FILE_DEFAULT) pass - def get_not_existing_dir(self, dir): + def get_not_existing_path(self, dir): path = Path(os.path.join(self.git.git_dir, dir)) if path.exists(): - raise InitError('Directory "{}" already exist'.format(path.name)) + raise InitError('Path "{}" already exist'.format(path.name)) return path def get_not_existing_conf_file_name(self): @@ -91,33 +93,38 @@ ProjectName = )) return 1 - data_dir_path = self.get_not_existing_dir(self.parsed_args.data_dir) - cache_dir_path = self.get_not_existing_dir(self.parsed_args.cache_dir) - state_dir_path = self.get_not_existing_dir(self.parsed_args.state_dir) + data_dir_path = self.get_not_existing_path(self.parsed_args.data_dir) + cache_dir_path = self.get_not_existing_path(self.parsed_args.cache_dir) + state_dir_path = self.get_not_existing_path(self.parsed_args.state_dir) + target_file_path = self.get_not_existing_path(self.parsed_args.target_file) self.settings.config.set(self.parsed_args.data_dir, self.parsed_args.cache_dir, - self.parsed_args.state_dir) + self.parsed_args.state_dir, + target_file_path) conf_file_name = self.get_not_existing_conf_file_name() data_dir_path.mkdir() cache_dir_path.mkdir() state_dir_path.mkdir() - Logger.info('Directories {}/, {}/ and {}/ were created'.format( + target_file_path.touch() + Logger.info('Directories {}/, {}/, {}/ and target file {} were created'.format( data_dir_path.name, cache_dir_path.name, - state_dir_path.name)) + state_dir_path.name, + target_file_path.name)) self.create_empty_file() conf_file = open(conf_file_name, 'wt') conf_file.write(self.CONFIG_TEMPLATE.format(data_dir_path.name, cache_dir_path.name, - state_dir_path.name)) + state_dir_path.name, + target_file_path.name)) conf_file.close() - message = 'DVC init. data dir {}, cache dir {}, state dir {}'.format( + message = 'DVC init. data dir {}, cache dir {}, state dir {}, '.format( data_dir_path.name, cache_dir_path.name, state_dir_path.name diff --git a/dvc/command/run.py b/dvc/command/run.py index 1c3bf5107..4e2d2d5a4 100644 --- a/dvc/command/run.py +++ b/dvc/command/run.py @@ -78,7 +78,7 @@ class CmdRun(CmdBase): def run_command(self, cmd_args, data_items_from_args, not_data_items_from_args, stdout=None, stderr=None, shell=False): - Logger.debug('Run command with args: {}. Data items from args: {}. stdout={}, stderr={}, shell={}'.format( + Logger.debug(u'Run command with args: {}. Data items from args: {}. stdout={}, stderr={}, shell={}'.format( ' '.join(cmd_args), ', '.join([x.data.dvc for x in data_items_from_args]), stdout, diff --git a/dvc/command/target.py b/dvc/command/target.py new file mode 100644 index 000000000..4dc44a407 --- /dev/null +++ b/dvc/command/target.py @@ -0,0 +1,54 @@ +import os + +from dvc.command.base import CmdBase, DvcLock +from dvc.logger import Logger +from dvc.runtime import Runtime +from dvc.state_file import StateFile + + +class CmdTarget(CmdBase): + def __init__(self, settings): + super(CmdTarget, self).__init__(settings) + + def define_args(self, parser): + self.set_no_git_actions(parser) + + parser.add_argument('-u', '--unset', action='store_true', default=False, + help='Reset target.') + + parser.add_argument('target', metavar='', help='Target data item.') + pass + + def run(self): + with DvcLock(self.is_locker, self.git): + return self.change_target(self.parsed_args.target, not self.parsed_args.unset) + + def change_target(self, target, unset): + if target and unset: + Logger.error('Unable to set target {} and unset it in a single command'.format(target)) + return 1 + + if not target and not unset: + Logger.error('Target is not defined') + return 1 + + target_conf_file_path = self.settings.path_factory.path(self.settings.config.target_file) + + if unset: + if os.path.exists(target_conf_file_path.relative): + if not os.path.isfile(target_conf_file_path.relative): + Logger.error('Target conf file {} exists but it is not a regular file'.format( + target_conf_file_path.relative)) + return 1 + os.remove(target_conf_file_path.relative) + open(target_conf_file_path.relative, 'a').close() + else: + with open(target_conf_file_path.relative, 'w') as fd: + target_data_item = self.settings.path_factory.existing_data_item(target) + fd.write(target_data_item.data_dvc_short) + + return 0 + + +if __name__ == '__main__': + Runtime.run(CmdTarget, False) diff --git a/dvc/config.py b/dvc/config.py index aab9ae924..3866f9f57 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -11,13 +11,20 @@ class ConfigError(DvcException): class ConfigI(object): - def __init__(self, data_dir=None, cache_dir=None, state_dir=None): - self.set(data_dir, cache_dir, state_dir) + TARGET_FILE_DEFAULT = '.target' - def set(self, data_dir, cache_dir, state_dir): + def __init__(self, data_dir=None, cache_dir=None, state_dir=None, target_file=None): + self._data_dir = None + self._cache_dir = None + self._state_dir = None + self._target_file = None + self.set(data_dir, cache_dir, state_dir, target_file) + + def set(self, data_dir, cache_dir, state_dir, target_file): self._data_dir = data_dir self._cache_dir = cache_dir self._state_dir = state_dir + self._target_file = target_file @property def data_dir(self): @@ -31,9 +38,14 @@ class ConfigI(object): def state_dir(self): return self._state_dir + @property + def target_file(self): + return self._target_file + class Config(ConfigI): CONFIG = 'dvc.conf' + def __init__(self, conf_file, conf_pseudo_file=None): """ Params: @@ -55,7 +67,8 @@ class Config(ConfigI): super(Config, self).__init__(self._config['Global']['DataDir'], self._config['Global']['CacheDir'], - self._config['Global']['StateDir']) + self._config['Global']['StateDir'], + self._config['Global'].get('TargetFile', Config.TARGET_FILE_DEFAULT)) pass @property diff --git a/dvc/main.py b/dvc/main.py index 82d5b5f07..0be2d2012 100644 --- a/dvc/main.py +++ b/dvc/main.py @@ -16,9 +16,10 @@ from dvc.command.repro import CmdRepro from dvc.command.data_sync import CmdDataSync from dvc.command.lock import CmdLock from dvc.command.gc import CmdGC +from dvc.command.target import CmdTarget from dvc.command.test import CmdTest -VERSION = '0.8.6' +VERSION = '0.8.7' def print_usage(): usage = ('', @@ -70,6 +71,8 @@ def main(): Runtime.run(CmdLock) elif cmd == 'gc': Runtime.run(CmdGC) + elif cmd == 'target': + Runtime.run(CmdTarget) elif cmd == 'cloud-run': print('cloud-run unimplemented') elif cmd == 'cloud-instance-create':