diff --git a/dvc/config.py b/dvc/config.py index 0f1bafac67..8a4904bd00 100644 --- a/dvc/config.py +++ b/dvc/config.py @@ -137,6 +137,7 @@ class RelPath(str): Optional("analytics", default=True): Bool, Optional("hardlink_lock", default=False): Bool, Optional("no_scm", default=False): Bool, + Optional("autostage", default=False): Bool, Optional("experiments", default=False): Bool, Optional("check_update", default=True): Bool, }, diff --git a/dvc/repo/scm_context.py b/dvc/repo/scm_context.py index c0b0ffb5b5..ec9585bb7f 100644 --- a/dvc/repo/scm_context.py +++ b/dvc/repo/scm_context.py @@ -3,7 +3,11 @@ def run(repo, *args, **kw): try: result = method(repo, *args, **kw) repo.scm.reset_ignores() - repo.scm.remind_to_track() + autostage = repo.config.get("core", {}).get("autostage", False) + if autostage: + repo.scm.track_changed_files() + else: + repo.scm.remind_to_track() repo.scm.reset_tracked_files() return result except Exception: diff --git a/dvc/scm/base.py b/dvc/scm/base.py index 1bde8f7443..699c602e69 100644 --- a/dvc/scm/base.py +++ b/dvc/scm/base.py @@ -154,6 +154,11 @@ def remind_to_track(self): Method to remind user to track newly created files handled by scm """ + def track_changed_files(self): + """ + Method to stage files that have changed + """ + def track_file(self, path): """ Method to add file to mechanism that will remind user diff --git a/dvc/scm/git.py b/dvc/scm/git.py index b777488ac8..a3317218ea 100644 --- a/dvc/scm/git.py +++ b/dvc/scm/git.py @@ -381,6 +381,12 @@ def remind_to_track(self): "\tgit add {files}".format(files=files) ) + def track_changed_files(self): + if not self.files_to_track: + return + + self.add(self.files_to_track) + def track_file(self, path): self.files_to_track.add(path) diff --git a/tests/unit/scm/test_scm.py b/tests/unit/scm/test_scm.py index 4fb590fc54..1121d4df5c 100644 --- a/tests/unit/scm/test_scm.py +++ b/tests/unit/scm/test_scm.py @@ -17,6 +17,7 @@ def test_should_successfully_perform_method(self): method = mock.Mock() wrapped = scm_context(method) + self.repo_mock.configure_mock(config={}) wrapped(self.repo_mock) self.assertEqual(1, method.call_count) @@ -25,6 +26,20 @@ def test_should_successfully_perform_method(self): self.assertEqual(0, self.scm_mock.cleanup_ignores.call_count) + def test_should_check_autostage(self): + method = mock.Mock() + wrapped = scm_context(method) + + config_autostage_attrs = {"config": {"core": {"autostage": True}}} + self.repo_mock.configure_mock(**config_autostage_attrs) + wrapped(self.repo_mock) + + self.assertEqual(1, method.call_count) + self.assertEqual(1, self.scm_mock.reset_ignores.call_count) + self.assertEqual(1, self.scm_mock.track_changed_files.call_count) + + self.assertEqual(0, self.scm_mock.cleanup_ignores.call_count) + def test_should_throw_and_cleanup(self): method = mock.Mock(side_effect=Exception("some problem")) wrapped = scm_context(method)