diff --git a/dvc/cli.py b/dvc/cli.py index 722d01119..5381426a4 100644 --- a/dvc/cli.py +++ b/dvc/cli.py @@ -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 diff --git a/dvc/command/init.py b/dvc/command/init.py index 7397d5907..c6623abb0 100644 --- a/dvc/command/init.py +++ b/dvc/command/init.py @@ -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 diff --git a/dvc/command/metrics.py b/dvc/command/metrics.py new file mode 100644 index 000000000..68c69980c --- /dev/null +++ b/dvc/command/metrics.py @@ -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 diff --git a/dvc/project.py b/dvc/project.py index b2b3552b4..62627f58d 100644 --- a/dvc/project.py +++ b/dvc/project.py @@ -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) diff --git a/dvc/scm.py b/dvc/scm.py index cc1475903..5667c9d55 100644 --- a/dvc/scm.py +++ b/dvc/scm.py @@ -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) diff --git a/tests/test_init.py b/tests/test_init.py index 4f286f06e..f22571442 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -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()