mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-06 23:09:55 +01:00
dvc: remove data dir
From now on, we're no longer tied to fixed data dir, so we can track individual data items without forcing user to use separate dir for them. This way we add much more flexibility for dvc, so users can use their own project structure. Fixes #68 Signed-off-by: Ruslan Kuprieiev <[email protected]>
This commit is contained in:
+3
-10
@@ -16,8 +16,6 @@ class InitError(DvcException):
|
||||
|
||||
class CmdInit(CmdBase):
|
||||
CONFIG_TEMPLATE = '''[Global]
|
||||
DataDir = {}
|
||||
|
||||
# Default target
|
||||
Target =
|
||||
|
||||
@@ -92,28 +90,23 @@ ProjectName =
|
||||
return 1
|
||||
|
||||
config_dir_path = self.get_not_existing_path(Config.CONFIG_DIR)
|
||||
data_dir_path = self.get_not_existing_path(self.parsed_args.data_dir)
|
||||
cache_dir_path = self.get_not_existing_path(Config.CONFIG_DIR, Config.CACHE_DIR)
|
||||
state_dir_path = self.get_not_existing_path(Config.CONFIG_DIR, Config.STATE_DIR)
|
||||
|
||||
self.settings.config.set(self.parsed_args.data_dir)
|
||||
|
||||
conf_file_name = self.get_not_existing_conf_file_name()
|
||||
|
||||
config_dir_path.mkdir()
|
||||
data_dir_path.mkdir()
|
||||
cache_dir_path.mkdir()
|
||||
state_dir_path.mkdir()
|
||||
Logger.info('Directories {}/, {}/, {}/, {}/ were created'.format(
|
||||
Logger.info('Directories {}/, {}/, {}/ were created'.format(
|
||||
config_dir_path.name,
|
||||
data_dir_path.name,
|
||||
os.path.join(config_dir_path.name, cache_dir_path.name),
|
||||
os.path.join(config_dir_path.name, state_dir_path.name)))
|
||||
|
||||
self.create_empty_file()
|
||||
|
||||
conf_file = open(conf_file_name, 'wt')
|
||||
conf_file.write(self.CONFIG_TEMPLATE.format(data_dir_path.name))
|
||||
conf_file.write(self.CONFIG_TEMPLATE)
|
||||
conf_file.close()
|
||||
|
||||
self.git.modify_gitignore([os.path.join(config_dir_path.name, cache_dir_path.name),
|
||||
@@ -123,7 +116,7 @@ ProjectName =
|
||||
return self.commit_if_needed(message)
|
||||
|
||||
def create_empty_file(self):
|
||||
empty_data_path = os.path.join(self.parsed_args.data_dir, self.EMPTY_FILE_NAME)
|
||||
empty_data_path = os.path.join(self.settings.git.git_dir_abs, self.EMPTY_FILE_NAME)
|
||||
|
||||
data_item = self.settings.path_factory.data_item(empty_data_path)
|
||||
open(empty_data_path, 'w').close()
|
||||
|
||||
@@ -3,7 +3,6 @@ import json
|
||||
from dvc.command.base import CmdBase, DvcLock
|
||||
from dvc.logger import Logger
|
||||
from dvc.state_file import StateFile
|
||||
from dvc.path.data_item import NotInDataDirError
|
||||
|
||||
class CmdMerge(CmdBase):
|
||||
def __init__(self, settings):
|
||||
|
||||
@@ -6,7 +6,7 @@ from dvc.command.import_file import CmdImportFile
|
||||
from dvc.command.run import CmdRun
|
||||
from dvc.logger import Logger
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.path.data_item import NotInDataDirError
|
||||
from dvc.path.data_item import DataDirError
|
||||
from dvc.state_file import StateFile
|
||||
from dvc.system import System
|
||||
|
||||
@@ -64,8 +64,8 @@ class CmdRepro(CmdRun):
|
||||
|
||||
data_item_list, external_files_names = self.settings.path_factory.to_data_items(target)
|
||||
if external_files_names:
|
||||
Logger.error('Files from outside of the data directory "{}" could not be reproduced: {}'.
|
||||
format(self.config.data_dir, ' '.join(external_files_names)))
|
||||
Logger.error('Files from outside of the repo could not be reproduced: {}'.
|
||||
format(' '.join(external_files_names)))
|
||||
return 1
|
||||
|
||||
if self.repro_data_items(data_item_list, recursive, force):
|
||||
@@ -303,7 +303,7 @@ class ReproChange(object):
|
||||
for input_file in self.state.input_files:
|
||||
try:
|
||||
data_item = self._settings.path_factory.data_item(input_file)
|
||||
except NotInDataDirError:
|
||||
except DataDirError:
|
||||
raise ReproError(u'The dependency file "{}" is not a data item'.format(input_file))
|
||||
except Exception as ex:
|
||||
raise ReproError(u'Unable to reproduced the dependency file "{}": {}'.format(
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ from dvc.command.base import CmdBase, DvcLock
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.git_wrapper import GitWrapper
|
||||
from dvc.logger import Logger
|
||||
from dvc.path.data_item import NotInDataDirError, NotInGitDirError
|
||||
from dvc.path.data_item import DataDirError, NotInGitDirError
|
||||
from dvc.repository_change import RepositoryChange
|
||||
from dvc.state_file import StateFile
|
||||
from dvc.utils import cached_property
|
||||
|
||||
@@ -34,7 +34,7 @@ class CmdShowPipeline(Traverse):
|
||||
|
||||
def draw_targets(self, target):
|
||||
if not target:
|
||||
target = self.settings.config.data_dir
|
||||
target = '.'
|
||||
return self.draw(self.g, target, target)
|
||||
|
||||
for t in self.parsed_args.target:
|
||||
@@ -49,7 +49,7 @@ class CmdShowPipeline(Traverse):
|
||||
|
||||
def run(self):
|
||||
saved_targets = self.settings.parsed_args.target
|
||||
self.settings.parsed_args.target = [self.settings.config.data_dir]
|
||||
self.settings.parsed_args.target = ['.']
|
||||
|
||||
ret = super(CmdShowPipeline, self).run()
|
||||
|
||||
@@ -70,7 +70,7 @@ class CmdShowPipeline(Traverse):
|
||||
name = data_item.data.relative
|
||||
state = StateFile.load(data_item, self.git)
|
||||
|
||||
if name == os.path.join(self.settings.config.data_dir, CmdInit.EMPTY_FILE_NAME):
|
||||
if name == os.path.join('.', CmdInit.EMPTY_FILE_NAME):
|
||||
return
|
||||
|
||||
self.g.add_node(name)
|
||||
|
||||
@@ -44,10 +44,6 @@ class Traverse(CmdBase):
|
||||
msg = '[TraverseFileTree] Directory "%s" cannot be traversed. Use --recurcive flag.'
|
||||
raise TraverseError(msg % target)
|
||||
|
||||
if self._do_not_start_from_root and self.settings.path_factory.data_item(target).data_dvc_short == '':
|
||||
# The entire data directory
|
||||
raise TraverseError('[Traverse] Root data directory "%s" cannot be traversed' % target)
|
||||
|
||||
self._traverse_dir(target)
|
||||
else:
|
||||
self.process_file(target)
|
||||
|
||||
+4
-12
@@ -22,23 +22,16 @@ class ConfigI(object):
|
||||
STATE_DIR = 'state'
|
||||
CACHE_DIR = 'cache'
|
||||
|
||||
def __init__(self, data_dir=None, cloud=None, conf_parser=None):
|
||||
self._data_dir = None
|
||||
def __init__(self, cloud=None, conf_parser=None):
|
||||
self._conf_parser = None
|
||||
self._cloud = None
|
||||
self.set(data_dir, cloud, conf_parser)
|
||||
self.set(cloud, conf_parser)
|
||||
|
||||
def set(self, data_dir, cloud=None, conf_parser=None):
|
||||
def set(self, cloud=None, conf_parser=None):
|
||||
""" Set config params """
|
||||
self._data_dir = data_dir
|
||||
self._cloud = cloud
|
||||
self._conf_parser = conf_parser
|
||||
|
||||
@property
|
||||
def data_dir(self):
|
||||
""" Directory with data files """
|
||||
return self._data_dir
|
||||
|
||||
@property
|
||||
def cache_dir(self):
|
||||
""" Directory with cached data files """
|
||||
@@ -82,8 +75,7 @@ class Config(ConfigI):
|
||||
level = self._config['Global']['LogLevel']
|
||||
Logger.set_level(level)
|
||||
|
||||
super(Config, self).__init__(self._config['Global']['DataDir'],
|
||||
self._config['Global']['Cloud'],
|
||||
super(Config, self).__init__(self._config['Global']['Cloud'],
|
||||
self._config)
|
||||
|
||||
@property
|
||||
|
||||
+12
-24
@@ -13,22 +13,21 @@ class DataItemError(DvcException):
|
||||
super(DataItemError, self).__init__('Data item error: {}'.format(msg))
|
||||
|
||||
|
||||
class NotInDataDirError(DvcException):
|
||||
def __init__(self, file, data_dir, pattern='the file "{}" is not in the data directory "{}"'):
|
||||
msg = pattern.format(file, data_dir)
|
||||
super(NotInDataDirError, self).__init__(msg)
|
||||
class DataDirError(DvcException):
|
||||
def __init__(self, msg):
|
||||
super(DataDirError, self).__init__(msg)
|
||||
|
||||
|
||||
class DataItemInStatusDirError(NotInDataDirError):
|
||||
def __init__(self, file, data_dir):
|
||||
pattern = 'the file "{}" is in state directory, not in the data directory "{}"'
|
||||
super(DataItemInStatusDirError, self).__init__(file, data_dir, pattern)
|
||||
class DataItemInStatusDirError(DataDirError):
|
||||
def __init__(self, file):
|
||||
msg = 'File "{}" is in state directory'.format(file)
|
||||
super(DataItemInStatusDirError, self).__init__(msg)
|
||||
|
||||
|
||||
class NotInGitDirError(NotInDataDirError):
|
||||
class NotInGitDirError(DataDirError):
|
||||
def __init__(self, file, git_dir):
|
||||
pattern = 'the file "{}" is not in git directory "{}"'
|
||||
super(NotInGitDirError, self).__init__(file, git_dir, pattern)
|
||||
msg = 'File "{}" is not in git directory "{}"'.format(file, git_dir)
|
||||
super(NotInGitDirError, self).__init__(msg)
|
||||
|
||||
|
||||
class DataItem(object):
|
||||
@@ -46,11 +45,8 @@ class DataItem(object):
|
||||
raise NotInGitDirError(data_file, self._git.git_dir_abs)
|
||||
|
||||
if self._data.abs.startswith(self.state_dir_abs):
|
||||
raise DataItemInStatusDirError(data_file, self._config.data_dir)
|
||||
raise DataItemInStatusDirError(data_file)
|
||||
|
||||
if not self._data.abs.startswith(self.data_dir_abs) or \
|
||||
not self._data.dvc.startswith(self._config.data_dir):
|
||||
raise NotInDataDirError(data_file, self._config.data_dir)
|
||||
pass
|
||||
|
||||
def copy(self, cache_file=None):
|
||||
@@ -72,14 +68,10 @@ class DataItem(object):
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def data_dvc_short(self):
|
||||
return self._data.dvc[len(self._config.data_dir)+1:]
|
||||
|
||||
@cached_property
|
||||
def state(self):
|
||||
state_dir = os.path.join(self._git.git_dir_abs, self._config.state_dir)
|
||||
state_file = os.path.join(state_dir, self.data_dvc_short + self.STATE_FILE_SUFFIX)
|
||||
state_file = os.path.join(state_dir, self.data.dvc + self.STATE_FILE_SUFFIX)
|
||||
return Path(state_file, self._git)
|
||||
|
||||
@cached_property
|
||||
@@ -117,10 +109,6 @@ class DataItem(object):
|
||||
resolved_cache = os.path.realpath(self._data.relative)
|
||||
return Path(resolved_cache, self._git)
|
||||
|
||||
@cached_property
|
||||
def data_dir_abs(self):
|
||||
return os.path.join(self._git.git_dir_abs, self._config.data_dir)
|
||||
|
||||
@cached_property
|
||||
def state_dir_abs(self):
|
||||
return os.path.join(self._git.git_dir_abs, self._config.state_dir)
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
|
||||
from dvc.path.data_item import DataItem, DataItemError, NotInDataDirError
|
||||
from dvc.path.data_item import DataItem, DataItemError, DataDirError
|
||||
from dvc.path.path import Path
|
||||
from dvc.path.stated_data_item import StatedDataItem
|
||||
from dvc.system import System
|
||||
@@ -26,7 +26,7 @@ class PathFactory(object):
|
||||
return self.existing_data_item(path.relative)
|
||||
|
||||
def is_data_item(self, fname):
|
||||
data = os.path.relpath(os.path.realpath(fname), self._config.data_dir)
|
||||
data = os.path.relpath(os.path.realpath(fname), self._git.git_dir_abs)
|
||||
state = os.path.join(self._config.state_dir, data + DataItem.STATE_FILE_SUFFIX)
|
||||
return os.path.isfile(state)
|
||||
|
||||
@@ -44,7 +44,7 @@ class PathFactory(object):
|
||||
try:
|
||||
data_item = DataItem(file, self._git, self._config)
|
||||
result.append(data_item)
|
||||
except NotInDataDirError:
|
||||
except DataDirError:
|
||||
externally_created_files.append(file)
|
||||
|
||||
return result, externally_created_files
|
||||
|
||||
@@ -36,4 +36,4 @@ class StatedDataItem(DataItem):
|
||||
return self.is_new or self.is_modified or self.is_removed
|
||||
|
||||
def __repr__(self):
|
||||
return u'({}, {})'.format(self.state, self.data_dvc_short)
|
||||
return u'({}, {})'.format(self.state, self.data.dvc)
|
||||
|
||||
@@ -4,7 +4,7 @@ from dvc.exceptions import DvcException
|
||||
from dvc.git_wrapper import GitWrapper
|
||||
from dvc.executor import Executor
|
||||
from dvc.logger import Logger
|
||||
from dvc.path.data_item import NotInDataDirError, DataItemInStatusDirError
|
||||
from dvc.path.data_item import DataDirError, DataItemInStatusDirError
|
||||
from dvc.path.stated_data_item import StatedDataItem
|
||||
from dvc.utils import cached_property
|
||||
|
||||
@@ -76,7 +76,7 @@ class RepositoryChange(object):
|
||||
item.data.dvc))
|
||||
except DataItemInStatusDirError:
|
||||
self._created_status_files.append(file)
|
||||
except NotInDataDirError:
|
||||
except DataDirError:
|
||||
self._externally_created_files.append(file)
|
||||
pass
|
||||
|
||||
@@ -116,7 +116,7 @@ class RepositoryChange(object):
|
||||
|
||||
def data_file_timesteps(self):
|
||||
res = set()
|
||||
for root, dirs, files in os.walk(self._settings.config.data_dir):
|
||||
for root, dirs, files in os.walk('.'):
|
||||
for file in files:
|
||||
filename = os.path.join(root, file)
|
||||
if os.path.exists(filename):
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import json
|
||||
import re
|
||||
|
||||
from dvc.exceptions import DvcException
|
||||
from dvc.path.data_item import NotInDataDirError
|
||||
from dvc.path.data_item import DataDirError
|
||||
from dvc.system import System
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ class StateFile(object):
|
||||
try:
|
||||
data_item = self.settings.path_factory.data_item(arg)
|
||||
result.append(data_item.data.dvc)
|
||||
except NotInDataDirError:
|
||||
except DataDirError:
|
||||
result.append(arg)
|
||||
|
||||
return result
|
||||
|
||||
Reference in New Issue
Block a user