internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: iterative/dvc

Issue:
state: limit db size and add a file size limit



Discussion:

Resolving patch:
diff --git a/dvc/remote/local.py b/dvc/remote/local.py
--- a/dvc/remote/local.py
+++ b/dvc/remote/local.py
@@ -158,11 +158,6 @@ def collect_dir_cache(self, dname):
                     progress.update_target(title, processed, total)
                     processed += 1
 
-                # FIXME: we could've used md5 = state.update(path, dump=False)
-                # here, but it is around twice as slow(on ssd, don't know about
-                # hdd) for a directory with small files. What we could do here
-                # is introduce some kind of a limit for file size, after which
-                # we would actually register it in our state file.
                 md5 = self.state.update(path, dump=False)
                 dir_info.append({self.PARAM_RELPATH: relpath,
                                  self.PARAM_MD5: md5})
diff --git a/dvc/state.py b/dvc/state.py
--- a/dvc/state.py
+++ b/dvc/state.py
@@ -43,6 +43,8 @@ class StateDuplicateError(DvcException):
 class State(object):
     STATE_FILE = 'state'
     STATE_LOCK_FILE = 'state.lock'
+    STATE_ENTRY_LIMIT = 10000
+    STATE_SIZE_LIMIT = 7 * 1024 * 1024
 
     def __init__(self, project):
         self.project = project
@@ -116,6 +118,14 @@ def mtime(path):
     def inode(path):
         return str(System.inode(path))
 
+    def _check_db_size(self):
+        if len(self._db.keys()) > self.STATE_ENTRY_LIMIT:
+            msg = "Entry limit size '{}' has been reached for '{}'. "
+            msg += "Dropping current state cache."
+            self.project.logger.debug(msg.format(self.STATE_ENTRY_LIMIT,
+                                                 self.state_file))
+            self._db = {}
+
     def _do_update(self, path, dump=True):
         if not os.path.exists(path):
             return (None, None)
@@ -128,15 +138,21 @@ def _do_update(self, path, dump=True):
             return (md5, None)
 
         md5, info = self._collect(path)
-        state = StateEntry(md5, mtime)
-        d = state.dumpd()
 
-        with self._lock:
-            with self._lock_file:
-                self._db[inode] = d
+        if os.path.getsize(path) > self.STATE_SIZE_LIMIT:
+            msg = "Saving info about '{}' to state file."
+            self.project.logger.debug(msg.format(path))
 
-                if dump:
-                    self._dump()
+            state = StateEntry(md5, mtime)
+            d = state.dumpd()
+
+            with self._lock:
+                with self._lock_file:
+                    self._check_db_size()
+                    self._db[inode] = d
+
+                    if dump:
+                        self._dump()
 
         return (md5, info)
 


Test patch:
Repository: iterative/dvc

Issue:
repro: don't check for missing dependencies when running with `--dry`
https://discuss.dvc.org/t/creating-an-aggregate-dvc-file/93/5


Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -377,8 +377,6 @@ def _check_missing_deps(self):
             raise MissingDep(missing)
 
     def run(self, dry=False):
-        self._check_missing_deps()
-
         if self.locked:
             msg = u'Verifying outputs in locked stage \'{}\''
             self.project.logger.info(msg.format(self.relpath))
@@ -401,6 +399,7 @@ def run(self, dry=False):
             self.project.logger.info(msg)
 
             if not dry:
+                self._check_missing_deps()
                 p = subprocess.Popen(self.cmd,
                                      cwd=self.cwd,
                                      shell=True,


Test patch:
diff --git a/tests/test_repro.py b/tests/test_repro.py
--- a/tests/test_repro.py
+++ b/tests/test_repro.py
@@ -146,6 +146,42 @@ def test(self):
         self.assertFalse(filecmp.cmp(self.file1, self.BAR, shallow=False))
 
 
+class TestReproDryNoExec(TestDvc):
+    def test(self):
+        deps = []
+        for d in range(3):
+            idir = 'idir{}'.format(d)
+            odir = 'odir{}'.format(d)
+
+            deps.append('-d')
+            deps.append(odir)
+
+            os.mkdir(idir)
+
+            f = os.path.join(idir, 'file')
+            with open(f, 'w+') as fobj:
+                fobj.write(str(d))
+
+            if os.name == 'nt':
+                cp = 'copy'
+            else:
+                cp = 'cp'
+
+            ret = main(['run',
+                        '--no-exec',
+                        '-d', idir,
+                        '-o', odir,
+                        "python -c 'import shutil; "
+                        "shutil.copytree(\"{}\", \"{}\")'".format(idir, odir)])
+            self.assertEqual(ret, 0)
+
+        ret = main(['run', '--no-exec', '-f', 'Dvcfile'] + deps)
+        self.assertEqual(ret, 0)
+
+        ret = main(['repro', '--dry'])
+        self.assertEqual(ret, 0)
+
+
 class TestReproChangedDeepData(TestReproChangedData):
     def setUp(self):
         super(TestReproChangedDeepData, self).setUp()
Repository: iterative/dvc

Issue:
dvc: speedup stage collection by not visiting output dirs of the stages
Right now dvc will walk through all directories and files in the repo to find dvc files. In cases when there are some giant directories, it vastly slows down every dvc command. Need to stop visiting those directories.


Discussion:

Resolving patch:
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -746,12 +746,28 @@ def pipelines(self):
 
     def stages(self):
         stages = []
+        outs = []
         for root, dirs, files in os.walk(self.root_dir):
             for fname in files:
                 path = os.path.join(root, fname)
                 if not Stage.is_stage_file(path):
                     continue
-                stages.append(Stage.load(self, path))
+                stage = Stage.load(self, path)
+                for out in stage.outs:
+                    outs.append(out.path + out.sep)
+                stages.append(stage)
+
+            def filter_dirs(dname):
+                path = os.path.join(root, dname)
+                if path == self.dvc_dir or path == self.scm.dir:
+                    return False
+                for out in outs:
+                    if path == os.path.normpath(out) or path.startswith(out):
+                        return False
+                return True
+
+            dirs[:] = list(filter(filter_dirs, dirs))
+
         return stages
 
     def active_stages(self):
diff --git a/dvc/scm.py b/dvc/scm.py
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -99,6 +99,10 @@ def is_repo(root_dir):
         git_dir = os.path.join(root_dir, Git.GIT_DIR)
         return os.path.isdir(git_dir)
 
+    @property
+    def dir(self):
+        return self.repo.git_dir
+
     def ignore_file(self):
         return self.GITIGNORE
 


Test patch:
Repository: iterative/dvc

Issue:
run: check that -f doesn't contain any subdirectories
https://github.com/iterative/dvc/issues/1109#issue-359263079


Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -36,10 +36,8 @@ def __init__(self, fname):
 
 
 class StageFileBadNameError(DvcException):
-    def __init__(self, fname):
-        msg = "Bad stage filename '{}'. Stage files should be named " \
-              "'Dvcfile' or have a '.dvc' suffix(e.g. '{}.dvc')."
-        super(StageFileBadNameError, self).__init__(msg.format(fname, fname))
+    def __init__(self, msg):
+        super(StageFileBadNameError, self).__init__(msg)
 
 
 class MissingDep(DvcException):
@@ -283,6 +281,11 @@ def loads(project=None,
                                         use_cache=False, metric=True)
         stage.deps = dependency.loads_from(stage, deps)
 
+        if fname is not None and os.path.basename(fname) != fname:
+            msg = "Stage file name '{}' should not contain subdirectories. " \
+                  "Use '-c|--cwd' to change location of the stage file."
+            raise StageFileBadNameError(msg.format(fname))
+
         fname, cwd = Stage._stage_fname_cwd(fname, cwd, stage.outs, add=add)
 
         cwd = os.path.abspath(cwd)
@@ -304,7 +307,10 @@ def loads(project=None,
     @staticmethod
     def _check_dvc_filename(fname):
         if not Stage.is_stage_filename(fname):
-            raise StageFileBadNameError(os.path.relpath(fname))
+            msg = "Bad stage filename '{}'. Stage files should be named " \
+                  "'Dvcfile' or have a '.dvc' suffix(e.g. '{}.dvc')."
+            raise StageFileBadNameError(msg.format(os.path.relpath(fname),
+                                                   os.path.basename(fname)))
 
     @staticmethod
     def _check_dvc_file(fname):


Test patch:
diff --git a/tests/test_run.py b/tests/test_run.py
--- a/tests/test_run.py
+++ b/tests/test_run.py
@@ -16,7 +16,7 @@ def test(self):
         deps = [self.FOO, self.CODE]
         outs = [os.path.join(self.dvc.root_dir, 'out')]
         outs_no_cache = []
-        fname = os.path.join(self.dvc.root_dir, 'out.dvc')
+        fname = 'out.dvc'
         cwd = os.curdir
 
         self.dvc.add(self.FOO)
@@ -76,6 +76,15 @@ def test(self):
                          fname='empty',
                          cwd=os.curdir)
 
+        with self.assertRaises(StageFileBadNameError):
+            self.dvc.run(cmd='',
+                         deps=[],
+                         outs=[],
+                         outs_no_cache=[],
+                         fname=os.path.join(self.DATA_DIR, 'empty.dvc'),
+                         cwd=os.curdir)
+
+
 
 class TestRunNoExec(TestDvc):
     def test(self):
Repository: iterative/dvc

Issue:
bug when running on a symlinked repo
https://travis-ci.org/iterative/dvc/jobs/430603417


Discussion:

Resolving patch:
diff --git a/dvc/scm.py b/dvc/scm.py
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -109,10 +109,9 @@ def ignore_file(self):
         return self.GITIGNORE
 
     def _get_gitignore(self, path):
+        assert os.path.isabs(path)
         entry = os.path.basename(path)
-        gitignore = os.path.join(os.path.abspath(os.path.dirname(path)),
-                                 self.GITIGNORE)
-        gitignore = os.path.abspath(os.path.realpath(gitignore))
+        gitignore = os.path.join(os.path.dirname(path), self.GITIGNORE)
 
         if not gitignore.startswith(self.root_dir):
             raise FileNotInRepoError(path)


Test patch:
diff --git a/tests/test_scm.py b/tests/test_scm.py
--- a/tests/test_scm.py
+++ b/tests/test_scm.py
@@ -35,13 +35,14 @@ def _count_gitignore(self):
 
     def test(self):
         git = Git(self._root_dir)
+        foo = os.path.join(self._root_dir, self.FOO)
 
-        git.ignore('foo')
+        git.ignore(foo)
         self.assertTrue(os.path.isfile(Git.GITIGNORE))
         self.assertEqual(self._count_gitignore(), 1)
 
-        git.ignore('foo')
+        git.ignore(foo)
         self.assertEqual(self._count_gitignore(), 1)
 
-        git.ignore_remove('foo')
+        git.ignore_remove(foo)
         self.assertEqual(self._count_gitignore(), 0)
Repository: iterative/dvc

Issue:
dag: support submodules
I.e. when you use another dvc project as a sub project. Also should work with git submodules, which is essentially the same thing.


Discussion:

Resolving patch:
diff --git a/dvc/scm.py b/dvc/scm.py
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -22,6 +22,10 @@ def __init__(self, root_dir=os.curdir, project=None):
     def is_repo(root_dir):
         return True
 
+    @staticmethod
+    def is_submodule(root_dir):
+        return True
+
     def ignore(self, path):
         pass
 
@@ -98,8 +102,15 @@ def __init__(self, root_dir=os.curdir, project=None):
 
     @staticmethod
     def is_repo(root_dir):
-        git_dir = os.path.join(root_dir, Git.GIT_DIR)
-        return os.path.isdir(git_dir)
+        return os.path.isdir(Git._get_git_dir(root_dir))
+
+    @staticmethod
+    def is_submodule(root_dir):
+        return os.path.isfile(Git._get_git_dir(root_dir))
+
+    @staticmethod
+    def _get_git_dir(root_dir):
+        return os.path.join(root_dir, Git.GIT_DIR)
 
     @property
     def dir(self):
@@ -211,7 +222,7 @@ def install(self):
 
 
 def SCM(root_dir, no_scm=False, project=None):
-    if Git.is_repo(root_dir):
+    if Git.is_repo(root_dir) or Git.is_submodule(root_dir):
         return Git(root_dir, project=project)
 
     return Base(root_dir, project=project)


Test patch:
diff --git a/tests/basic_env.py b/tests/basic_env.py
--- a/tests/basic_env.py
+++ b/tests/basic_env.py
@@ -61,6 +61,15 @@ def setUp(self):
         self.git.index.commit('add code')
 
 
+class TestGitSubmodule(TestGit):
+    def setUp(self):
+        super(TestGitSubmodule, self).setUp()
+        subrepo = Repo.init()
+        subrepo_path = 'subrepo'
+        self.git.create_submodule(subrepo_path, subrepo_path, subrepo.git_dir)
+        self._pushd(subrepo_path)
+
+
 class TestDvc(TestGit):
     def setUp(self):
         super(TestDvc, self).setUp()
diff --git a/tests/test_scm.py b/tests/test_scm.py
--- a/tests/test_scm.py
+++ b/tests/test_scm.py
@@ -4,7 +4,7 @@
 
 from dvc.scm import SCM, Base, Git
 
-from tests.basic_env import TestDir, TestGit
+from tests.basic_env import TestDir, TestGit, TestGitSubmodule
 
 
 class TestSCM(TestDir):
@@ -27,6 +27,20 @@ def test_commit(self):
         self.assertTrue('foo' in self.git.git.ls_files())
 
 
+class TestSCMGitSubmodule(TestGitSubmodule):
+    def test_git_submodule(self):
+        self.assertIsInstance(SCM(os.curdir), Git)
+
+    def test_is_submodule(self):
+        self.assertTrue(Git.is_submodule(os.curdir))
+
+    def test_commit_in_submodule(self):
+        G = Git(self._root_dir)
+        G.add(['foo'])
+        G.commit('add')
+        self.assertTrue('foo' in self.git.git.ls_files())
+
+
 class TestIgnore(TestGit):
     def _count_gitignore(self):
         with open(Git.GITIGNORE, 'r') as fd:
Repository: iterative/dvc

Issue:
push/pull: properly join name on windows
https://github.com/iterative/dvc/issues/1059#issuecomment-418795833


Discussion:

Resolving patch:
diff --git a/dvc/remote/local.py b/dvc/remote/local.py
--- a/dvc/remote/local.py
+++ b/dvc/remote/local.py
@@ -443,8 +443,8 @@ def _collect(self, checksum_infos, push=False):
             for i in self.load_dir_cache(md5):
                 if info.get('branch'):
                     i['branch'] = info['branch']
-                i[self.PARAM_PATH] = posixpath.join(info[self.PARAM_PATH],
-                                                    i[self.PARAM_RELPATH])
+                i[self.PARAM_PATH] = os.path.join(info[self.PARAM_PATH],
+                                                  i[self.PARAM_RELPATH])
                 collected.append(i.copy())
 
         collected.extend(checksum_infos)


Test patch:
Repository: iterative/dvc

Issue:
osx: build binary package on the oldest osx version that we need to support
https://github.com/iterative/homebrew-dvc/issues/7


Discussion:

Resolving patch:
diff --git a/dvc/reflink_ffi.py b/dvc/reflink_ffi.py
new file mode 100644
--- /dev/null
+++ b/dvc/reflink_ffi.py
@@ -0,0 +1,88 @@
+import platform
+from cffi import FFI
+
+
+WINDOWS_SRC = """
+int reflink(char *src, char *dst)
+{
+    return -1;
+}
+"""
+
+DARWIN_SRC = """
+#include <AvailabilityMacros.h>
+/* NOTE: sys/clonefile.h is available since OS X 10.12 */
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
+#include <sys/clonefile.h> /* for clonefile(2) */
+#include <errno.h>
+int reflink(char *src, char *dst)
+{
+    return clonefile(src, dst, 0);
+}
+#else
+int reflink(char *src, char *dst)
+{
+    return -1;
+}
+#endif
+"""
+
+LINUX_SRC = """
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <assert.h>
+#include <errno.h>
+int reflink(char *src, char *dst)
+{
+    int ret = -1;
+#ifdef FICLONE
+    int src_fd = -1;
+    int dst_fd = -1;
+
+    src_fd = open(src, O_RDONLY);
+    if (src_fd < 0)
+        return ret;
+
+    dst_fd = open(dst, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+    if (src_fd < 0) {
+        close(src_fd);
+        return ret;
+    }
+
+    ret = ioctl(dst_fd, FICLONE, src_fd);
+    if (ret != 0)
+        unlink(dst);
+
+out:
+    if (src_fd >= 0)
+        close(src_fd);
+    if (dst_fd >= 0)
+        close(dst_fd);
+#endif
+    return ret;
+}
+"""
+
+ffibuilder = FFI()
+
+ffibuilder.cdef("""
+int reflink(char *src, char *dst);
+""")
+
+system = platform.system()
+if system == 'Windows':
+    src = WINDOWS_SRC
+elif system == 'Linux':
+    src = LINUX_SRC
+elif system == 'Darwin':
+    src = DARWIN_SRC
+else:
+    raise NotImplementedError
+
+ffibuilder.set_source("reflink", src)
+
+if __file__ == '__main__':
+    ffibuilder.compile(verbose=True)
diff --git a/dvc/system.py b/dvc/system.py
--- a/dvc/system.py
+++ b/dvc/system.py
@@ -1,6 +1,5 @@
 import os
 import ctypes
-import reflink
 
 if os.name == 'nt':
     import ntfsutils.hardlink as winlink
@@ -36,7 +35,15 @@ def symlink(source, link_name):
 
     @staticmethod
     def reflink(source, link_name):
-        return reflink.reflink(source, link_name)
+        from dvc.reflink import reflink
+        from dvc.exceptions import DvcException
+
+        ret = reflink(source, link_name)
+        if ret != 0:
+            raise DvcException("Failed to reflink '{}' -> '{}' returned "
+                               "non-zero code '{}'".format(source,
+                                                           link_name,
+                                                           ret))
 
     # FIXME
     # Temporary fix while waiting for the PR to be merged and released:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -21,10 +21,10 @@
     "pyasn1>=0.4.1",
     "schema>=0.6.7",
     "jsonpath-rw==1.4.0",
-    "reflink==0.2.0",
     "requests>=2.18.4",
     "grandalf==0.6",
     "asciicanvas==0.0.3",
+    "cffi",
 ]
 
 # Extra dependencies for remote integrations


Test patch:
Repository: iterative/dvc

Issue:
ssh: don't ask several times for a password
https://github.com/iterative/dvc/issues/1124#issuecomment-423740624


Discussion:

Resolving patch:
diff --git a/dvc/remote/local.py b/dvc/remote/local.py
--- a/dvc/remote/local.py
+++ b/dvc/remote/local.py
@@ -553,6 +553,12 @@ def _do_pull(self,
 
         progress.update_target(title, 60, 100)
 
+        # NOTE: dummy call to try to establish a connection
+        # to see if we need to ask user for a password.
+        remote.exists(remote.md5s_to_path_infos(['000']))
+
+        progress.update_target(title, 70, 100)
+
         assert len(path_infos) == len(cache) == len(md5s) == len(names)
 
         chunks = list(zip(to_chunks(path_infos, jobs),


Test patch:
Repository: iterative/dvc

Issue:
s3: Support AWS credential settings from environment variables
dvc should also load credential information from system environment variables as awscli does.

Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-environment.html

For example: we should be able to run `dvc pull` despite absence of AWS profiles in _~/.aws_ if we had set the following environment variables:

```
$ export AWS_ACCESS_KEY_ID=somekey
$ export AWS_SECRET_ACCESS_KEY=somekey
$ export AWS_DEFAULT_REGION=someregion
```

The following command works:
``` 
aws s3 ls s3://bucketname
```

But this one does not:
```
dvc pull
```

A usecase for this is doing `dvc pull` in docker image building process, which would be much easier if if we can override configuration via environment variables. 


Discussion:
Hi @jeepkd !

Good point! I was sure that we support this already since this is how we pass creds in our travis tests, but turns out we write it to `.aws/` first. Will send a patch soon.

Thanks,
Ruslan

Resolving patch:
diff --git a/dvc/remote/s3.py b/dvc/remote/s3.py
--- a/dvc/remote/s3.py
+++ b/dvc/remote/s3.py
@@ -47,7 +47,9 @@ def __init__(self, project, config):
                                            '').lstrip('/')
         self.url = config.get(Config.SECTION_REMOTE_URL, storagepath)
         self.region = config.get(Config.SECTION_AWS_REGION, None)
-        self.profile = config.get(Config.SECTION_AWS_PROFILE, 'default')
+        self.profile = os.getenv('AWS_PROFILE',
+                                 config.get(Config.SECTION_AWS_PROFILE,
+                                            'default'))
         self.endpoint_url = config.get(Config.SECTION_AWS_ENDPOINT_URL, None)
 
         credentialpath = config.get(Config.SECTION_AWS_CREDENTIALPATH, None)
@@ -62,6 +64,12 @@ def __init__(self, project, config):
         self.aws_access_key_id = creds.get('aws_access_key_id', None)
         self.aws_secret_access_key = creds.get('aws_secret_access_key', None)
 
+        self.region = os.getenv('AWS_DEFAULT_REGION', self.region)
+        self.aws_access_key_id = os.getenv('AWS_ACCESS_KEY_ID',
+                                           self.aws_access_key_id)
+        self.aws_secret_access_key = os.getenv('AWS_SECRET_ACCESS_KEY',
+                                               self.aws_secret_access_key)
+
     @property
     def bucket(self):
         return urlparse(self.url).netloc


Test patch:
Repository: iterative/dvc

Issue:
stage: properly report StageFileFormatError



Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -19,8 +19,9 @@ def __init__(self, stage):
 
 
 class StageFileFormatError(DvcException):
-    def __init__(self):
-        super(StageFileFormatError, self).__init__('Stage file format error')
+    def __init__(self, fname, e):
+        msg = "Stage file '{}' format error: {}".format(fname, str(e))
+        super(StageFileFormatError, self).__init__(msg)
 
 
 class StageFileDoesNotExistError(DvcException):
@@ -207,17 +208,15 @@ def reproduce(self, force=False, dry=False, interactive=False):
         return self
 
     @staticmethod
-    def validate(d):
+    def validate(d, fname=None):
         try:
             Schema(Stage.SCHEMA).validate(d)
         except SchemaError as exc:
-            Logger.debug(str(exc))
-            raise StageFileFormatError()
+            raise StageFileFormatError(fname, exc)
 
     @staticmethod
     def loadd(project, d, path):
-        Stage.validate(d)
-
+        Stage.validate(d, fname=os.path.relpath(path))
         path = os.path.abspath(path)
         cwd = os.path.dirname(path)
         cmd = d.get(Stage.PARAM_CMD, None)


Test patch:
Repository: iterative/dvc

Issue:
dvc: add a link to our chat into error msgs/exceptions
Kudos @shcheklein 


Discussion:
I've made redirects https://dvc.org/chat and https://dvc.org/help . README and documentation links have been updated to use these links.

Consider adding this link to the update message, may be other service messages as well. 
When I logged in, it redirects me to the Invite page. Is there a way to go directly to the chat room?
@dmpetrov good question, I don't know, we should reach out to discord and may be even ask to accept us to the partnership program

Resolving patch:
diff --git a/dvc/logger.py b/dvc/logger.py
--- a/dvc/logger.py
+++ b/dvc/logger.py
@@ -105,7 +105,9 @@ def error(msg, exc=None):
         if Logger.logger().getEffectiveLevel() == logging.DEBUG and exc:
             str_tb = str_tb if str_tb else traceback.format_exc()
             Logger.logger().error(prefix + str_tb)
-        return Logger.logger().error(prefix + msg + str_exc)
+        chat = "\n\nHaving any troubles? Hit us up at dvc.org/support, " \
+               "we are always happy to help!"
+        return Logger.logger().error(prefix + msg + str_exc + chat)
 
     @staticmethod
     def warn(msg):


Test patch: