init: properly handle dvc init in directory without scm

Fixes #660
Fixes #662

Signed-off-by: Ruslan Kuprieiev <[email protected]>
This commit is contained in:
Ruslan Kuprieiev
2018-04-18 09:27:55 +03:00
parent 29a44689c5
commit a1460a6d92
6 changed files with 69 additions and 13 deletions
+5
View File
@@ -66,6 +66,11 @@ def parse_args(argv=None):
'init',
parents=[parent_parser],
help='Initialize dvc over a directory (should already be a git dir)')
init_parser.add_argument(
'--no-scm',
action='store_true',
default=False,
help="Initiate dvc in directory that is not tracked by any scm tool(e.g. git)")
init_parser.set_defaults(func=CmdInit)
# Add
+7 -2
View File
@@ -1,4 +1,5 @@
from dvc.project import Project
from dvc.project import Project, InitError
from dvc.logger import Logger
class CmdInit(object):
@@ -6,5 +7,9 @@ class CmdInit(object):
self.args = args
def run_cmd(self):
Project.init('.')
try:
Project.init('.', no_scm=self.args.no_scm)
except InitError as e:
Logger.error('Failed to initiate dvc', e)
return 1
return 0
+8
View File
@@ -0,0 +1,8 @@
from dvc.command.common.base import CmdBase
class CmdMetrics(CmdBase):
def run(self):
for branch, metric in self.project.metrics(self.args.path).items():
self.project.logger.info("{}: {}".format(branch, metric))
return 0
+16 -5
View File
@@ -10,12 +10,17 @@ from dvc.stage import Stage, Output
from dvc.config import Config
from dvc.state import State
from dvc.lock import Lock
from dvc.scm import SCM
from dvc.scm import SCM, Base
from dvc.cache import Cache
from dvc.cloud.data_cloud import DataCloud
from dvc.system import System
class InitError(DvcException):
def __init__(self, msg):
super(InitError, self).__init__(msg)
class StageNotFoundError(DvcException):
def __init__(self, path):
msg = 'Stage file {} does not exist'.format(path)
@@ -44,7 +49,7 @@ class Project(object):
self.cloud = DataCloud(cache=self.cache, state=self.state, config=self.config._config)
@staticmethod
def init(root_dir=os.curdir):
def init(root_dir=os.curdir, no_scm=False):
"""
Initiate dvc project in directory.
@@ -59,6 +64,12 @@ class Project(object):
"""
root_dir = os.path.abspath(root_dir)
dvc_dir = os.path.join(root_dir, Project.DVC_DIR)
scm = SCM(root_dir)
if type(scm) == Base and not no_scm:
msg = "{} is not tracked by any supported scm tool(e.g. git).".format(root_dir)
raise InitError(msg)
os.mkdir(dvc_dir)
config = Config.init(dvc_dir)
@@ -66,14 +77,14 @@ class Project(object):
state = State.init(root_dir, dvc_dir)
lock = Lock(dvc_dir)
scm = SCM(root_dir)
scm.ignore_list([cache.cache_dir,
state.state_file,
lock.lock_file,
config.config_local_file])
ignore_file = os.path.join(dvc_dir, scm.ignore_file())
scm.add([config.config_file, ignore_file])
scm.add([config.config_file])
if scm.ignore_file():
scm.add([os.path.join(dvc_dir, scm.ignore_file())])
return Project(root_dir)
+4 -4
View File
@@ -31,9 +31,6 @@ class Base(object):
def ignore_list(self, p_list):
return [self.ignore(path) for path in p_list]
def ignore_file(self):
return self.GITIGNORE
def add(self, paths):
pass
@@ -71,6 +68,9 @@ class Git(Base):
git_dir = os.path.join(root_dir, Git.GIT_DIR)
return os.path.isdir(git_dir)
def ignore_file(self):
return self.GITIGNORE
def _get_gitignore(self, path):
entry = os.path.basename(path)
gitignore = os.path.join(os.path.abspath(os.path.dirname(path)),
@@ -134,7 +134,7 @@ class Git(Base):
return len(self.repo.git.ls_files(path)) != 0
def SCM(root_dir=os.curdir):
def SCM(root_dir=os.curdir, no_scm=False):
if Git.is_repo(root_dir):
return Git(root_dir)
+29 -2
View File
@@ -2,9 +2,9 @@ import os
from dvc.main import main
from dvc.command.init import CmdInit
from dvc.project import Project
from dvc.project import Project, InitError
from tests.basic_env import TestGit
from tests.basic_env import TestGit, TestDir
class TestInit(TestGit):
@@ -22,3 +22,30 @@ class TestInit(TestGit):
self.assertEqual(ret, 0)
self._test_init()
class TestInitNoSCMFail(TestDir):
def test_api(self):
with self.assertRaises(InitError):
Project.init()
def test_cli(self):
ret = main(['init'])
self.assertNotEqual(ret, 0)
class TestInitNoSCM(TestDir):
def _test_init(self):
self.assertTrue(os.path.exists(Project.DVC_DIR))
self.assertTrue(os.path.isdir(Project.DVC_DIR))
def test_api(self):
Project.init(no_scm=True)
self._test_init()
def test_cli(self):
ret = main(['init', '--no-scm'])
self.assertEqual(ret, 0)
self._test_init()