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

Issue:
dvc run empty dependency
```
$ dvc run -o data/Posts.xml tar zxf data/Posts.xml.tgz -C data/
CmdRun error: 'NoneType' object is not iterable
```


Discussion:

Resolving patch:
diff --git a/dvc/state_file.py b/dvc/state_file.py
--- a/dvc/state_file.py
+++ b/dvc/state_file.py
@@ -212,8 +212,4 @@ def save(self):
             self.PARAM_CACHE_TIMESTAMP   : self.cache_timestamp
         }
 
-        file_dir = os.path.dirname(self.data_item.local_state.relative)
-        if not os.path.isdir(file_dir):
-            os.makedirs(file_dir)
-
         self._save(self.data_item.local_state.relative, res)


Test patch:
Repository: iterative/dvc

Issue:
Running DVC outside of Git dir
We should handle all the cases like this.

```
cd /
$ dvc repro
No handlers could be found for logger "dvc"
```


Discussion:
Oops, this is accidental degradation. Not long ago it said:
(python3-dvc) ➜  ~ cd /
(python3-dvc) ➜  / dvc repro
Initialization error: Not a dvc repository (or any parent up to mount point /)

Will fix soon and cover by a test.

Resolving patch:
diff --git a/dvc/logger.py b/dvc/logger.py
--- a/dvc/logger.py
+++ b/dvc/logger.py
@@ -25,15 +25,19 @@ class Logger(object):
     }
 
     def __init__(self, config=None):
+        self.init(config)
+
+    @staticmethod
+    def init(config=None):
         sh = logging.StreamHandler(sys.stdout)
-        sh.setFormatter(logging.Formatter(self.FMT))
+        sh.setFormatter(logging.Formatter(Logger.FMT))
         sh.setLevel(logging.DEBUG)
 
-        self.logger().addHandler(sh)
+        Logger.logger().addHandler(sh)
         level = None
         if config:
             level = config['Global'].get('LogLevel', None)
-        self.set_level(level)
+        Logger.set_level(level)
 
     @staticmethod
     def logger():
diff --git a/dvc/main.py b/dvc/main.py
--- a/dvc/main.py
+++ b/dvc/main.py
@@ -2,6 +2,8 @@
 from dvc.cli import parse_args
 
 def main(argv=None):
+    Logger.init()
+
     args = parse_args(argv)
 
     try:


Test patch:
Repository: iterative/dvc

Issue:
dvc run: regular output files should not be in .gitignore
Please add a corresponded unit-test. See examples in class `TestGitIgnoreWhenCheckout` file `test_checkout.py`.


Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -293,7 +293,8 @@ def changed(self):
     def remove_outs(self):
         for out in self.outs:
             out.remove()
-            self.project.scm.ignore_remove(out.path)
+            if out.use_cache:
+                self.project.scm.ignore_remove(out.path)
 
     def remove(self):
         self.remove_outs()
@@ -353,7 +354,8 @@ def save(self):
         for out in self.outs:
             out.update()
             out.save()
-            self.project.scm.ignore(out.path)
+            if out.use_cache:
+                self.project.scm.ignore(out.path)
 
     def run(self):
         if not self.is_data_source:


Test patch:
diff --git a/tests/test_checkout.py b/tests/test_checkout.py
--- a/tests/test_checkout.py
+++ b/tests/test_checkout.py
@@ -75,6 +75,7 @@ class TestGitIgnoreBasic(CheckoutBase):
     def test(self):
         fname1 = 'file_1'
         fname2 = 'file_2'
+        fname3 = 'file_3'
 
         self.dvc.scm.add(self.dvc.scm.untracked_files())
         self.dvc.scm.commit('add all files')
@@ -83,15 +84,18 @@ def test(self):
 
         self.commit_data_file(fname1)
         self.commit_data_file(fname2)
+        self.dvc.run(cmd='python {} {} {}'.format(self.CODE, self.FOO, fname3),
+                     deps=[self.CODE, self.FOO],
+                     outs_no_cache=[fname3])
 
         self.assertTrue(os.path.exists(self.GIT_IGNORE))
 
         ignored = self.read_ignored()
 
-        self.assertEqual(len(ignored), 2)   # FAILS!!!
+        self.assertEqual(len(ignored), 2)
 
         self.assertIn(fname1, ignored)
-        self.assertIn(fname2, ignored)      # FAILS!!!
+        self.assertIn(fname2, ignored)
 
 
 class TestGitIgnoreWhenCheckout(CheckoutBase):
@@ -120,4 +124,4 @@ def test(self):
         self.dvc.scm.checkout(branch_1)
         main(['checkout'])
         ignored = self.read_ignored()
-        self.assertIn(fname_branch, ignored)    # FAILS!!!
+        self.assertIn(fname_branch, ignored)
Repository: iterative/dvc

Issue:
dvc add dir: file exist
First, take a look at #447 

If a directory was already added then I got an error message:
```
$ cp -r data/SO raw  # <-- from #447
$ rm data/SO
$ dvc add raw
Unexpected error: [Errno 17] File exists: '/Users/dmitry/src/myrepo_1/.dvc/cache/ee3887acb78d695e2ac68dc85e05e2a1'
```

Is it because a directory 

Also, two minor issues:
1. Full file path.
2. Should be "Directory was already added", not "File exists".

One more related error:

```
$ rm raw/Tags.xml
$ dvc add raw

Unexpected error: [Errno 17] File exists
```


Discussion:

Resolving patch:
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -284,10 +284,17 @@ def save(self):
                 md5 = file_md5(path)[0]
                 cache = self.project.cache.get(md5)
                 cache_info = os.path.join(self.cache, relpath)
+                cache_dir = os.path.dirname(cache_info)
 
-                self.hardlink(path, cache)
+                if os.path.exists(cache):
+                    self._remove(path, None)
+                    self.hardlink(cache, path)
+                else:
+                    self.hardlink(path, cache)
+
+                if not os.path.exists(cache_dir):
+                    os.makedirs(cache_dir)
 
-                os.makedirs(os.path.dirname(cache_info))
                 with open(cache_info, 'w') as fd:
                     yaml.safe_dump({self.PARAM_MD5: md5}, fd, default_flow_style=False)
 


Test patch:
diff --git a/tests/test_add.py b/tests/test_add.py
--- a/tests/test_add.py
+++ b/tests/test_add.py
@@ -1,4 +1,5 @@
 import os
+import stat
 import shutil
 import filecmp
 from checksumdir import dirhash
@@ -59,6 +60,25 @@ def test(self):
             self.dvc.add(fname)
 
 
+class TestAddDirWithExistingCache(TestDvc):
+    def test(self):
+        dname = 'a'
+        fname = os.path.join(dname, 'b')
+        os.mkdir(dname)
+        shutil.copyfile(self.FOO, fname)
+
+        self.dvc.add(self.FOO)
+        self.dvc.add(dname)
+
+
+class TestAddModifiedDir(TestDvc):
+    def test(self):
+        self.dvc.add(self.DATA_DIR)
+        os.chmod(self.DATA, stat.S_IWRITE)
+        os.unlink(self.DATA)
+        self.dvc.add(self.DATA_DIR)
+
+
 class TestCmdAdd(TestDvc):
     def test(self):
         ret = main(['add',
Repository: iterative/dvc

Issue:
dvc add dir: file exist
First, take a look at #447 

If a directory was already added then I got an error message:
```
$ cp -r data/SO raw  # <-- from #447
$ rm data/SO
$ dvc add raw
Unexpected error: [Errno 17] File exists: '/Users/dmitry/src/myrepo_1/.dvc/cache/ee3887acb78d695e2ac68dc85e05e2a1'
```

Is it because a directory 

Also, two minor issues:
1. Full file path.
2. Should be "Directory was already added", not "File exists".

One more related error:

```
$ rm raw/Tags.xml
$ dvc add raw

Unexpected error: [Errno 17] File exists
```


Discussion:
Not closing this one yet.

Resolving patch:
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -51,7 +51,7 @@ def __init__(self, project, path, md5=None):
         self.path = os.path.abspath(os.path.realpath(path))
 
         if not self.path.startswith(self.project.root_dir):
-            raise CmdOutputOutsideOfRepoError(self.path)
+            raise CmdOutputOutsideOfRepoError(self.rel_path)
 
         self.md5 = md5
 
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -152,7 +152,7 @@ def _reproduce_stages(self, stages, node, force):
             try:
                 result += self._reproduce_stage(stages, n, force)
             except Exception as ex:
-                raise ReproductionError(n, ex)
+                raise ReproductionError(stages[n].relpath, ex)
         return result
 
     def checkout(self):
diff --git a/dvc/stage.py b/dvc/stage.py
--- a/dvc/stage.py
+++ b/dvc/stage.py
@@ -9,7 +9,7 @@
 
 class StageCmdFailedError(DvcException):
     def __init__(self, stage):
-        msg = 'Stage {} cmd {} failed'.format(stage.path, stage.cmd)
+        msg = 'Stage {} cmd {} failed'.format(stage.relpath, stage.cmd)
         super(StageCmdFailedError, self).__init__(msg)
 
 


Test patch:
Repository: iterative/dvc

Issue:
Write-only files in cache
```
$ cd .dvc
$ tar zcf cache.tgz cache/
tar: cache/b5/05341994fa176901c5a851f793ddfb: Cannot open: Permission denied
tar: cache/42/060e4315ee4fca052630749325f17d: Cannot open: Permission denied
tar: Exiting with failure status due to previous errors

$ ll cache/b5/05341994fa176901c5a851f793ddfb
--w------- 1 ubuntu ubuntu 16801304 Mar  3 00:53 cache/b5/05341994fa176901c5a851f793ddfb
```


Discussion:
Probably forgot to set permissions back on cache file after chmod() on data file.

Resolving patch:
diff --git a/dvc/command/checkout.py b/dvc/command/checkout.py
--- a/dvc/command/checkout.py
+++ b/dvc/command/checkout.py
@@ -14,10 +14,11 @@ def run(self):
     def remove_untracked_hardlinks(self):
         untracked = self.project.scm.untracked_files()
 
-        for file in self.project.cache.find_cache(untracked).keys():
+        for file, md5 in self.project.cache.find_cache(untracked).items():
             Logger.info(u'Remove \'{}\''.format(file))
             os.chmod(file, stat.S_IWRITE)
             os.remove(file)
+            os.chmod(self.project.cache.get(md5), stat.S_IREAD)
 
             dir = os.path.dirname(file)
             if len(dir) != 0 and not os.listdir(dir):


Test patch:
Repository: iterative/dvc

Issue:
dvc repro reproduces directories all the time
The directory was just created by `dvc run` and next `dvc repro` reproduces the directory one more time.

```
$ dvc repro -v dir1.dvc
Data /home/ubuntu/src/myrepo_test/data/file.txt with cache /home/ubuntu/src/myrepo_test/.dvc/cache/2db7e560e41eb16f6a78cb13d2645836 didn't change
/home/ubuntu/src/myrepo_test/data/file.txt.dvc didn't change
Data /home/ubuntu/src/myrepo_test/dir1 with cache /home/ubuntu/src/myrepo_test/.dvc/cache/3908923f1bc06b1f1279aad916f5cdbf changed
/home/ubuntu/src/myrepo_test/dir1.dvc changed
Data /home/ubuntu/src/myrepo_test/dir1 with cache /home/ubuntu/src/myrepo_test/.dvc/cache/3908923f1bc06b1f1279aad916f5cdbf changed
/home/ubuntu/src/myrepo_test/dir1.dvc changed
Removing '/home/ubuntu/src/myrepo_test/dir1/.head'
Removing '/home/ubuntu/src/myrepo_test/dir1/.tail'
Reproducing 'dir1.dvc':
	./headdir.sh data/file.txt dir1
...
```

Details:
```
# headdir.sh
f=`basename $2`
head -n 3 $1 > $2/${f}.head
tail -n 3 $1 > $2/${f}.tail
```

`dvc run -d data/file.txt -o dir1 ./headdir.sh data/file.txt dir1`


Discussion:
Yeah, I was able to reproduce this issue. Already working on it.

Resolving patch:
diff --git a/dvc/config.py b/dvc/config.py
--- a/dvc/config.py
+++ b/dvc/config.py
@@ -30,30 +30,10 @@ class Config(object):
 
 StoragePath = dvc/tutorial
 
-# Default settings for AWS instances:
-Type = t2.nano
-Image = ami-2d39803a
-
-SpotPrice = 
-SpotTimeout = 300
-
-KeyPairName = dvc-key
-KeyPairDir = ~/.ssh
-SecurityGroup = dvc-sg
-
-Region = us-east-1
-Zone = us-east-1a
-SubnetId = 
-
-Volume = my-100gb-drive-io
-
-Monitoring = false
-EbsOptimized = false
-AllDisksAsRAID0 = false
-
 [GCP]
 StoragePath = 
 ProjectName = 
+
 '''
 
     def __init__(self, dvc_dir):
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -195,14 +195,22 @@ def _changed_dir(self):
         if not os.path.isdir(self.path) or not os.path.isfile(self.cache):
             return True
 
-        dir_info = self._collect_dir()
-        dir_info_cached = self.load_dir_cache(self.cache)
+        dir_info = self._collect_dir() # slow!
+        dir_info_cached = self.load_dir_cache(self.cache) # slow. why?
 
-        if dir_info != dir_info_cached:
+        if not self.are_dir_info_equal(dir_info, dir_info_cached):
             return True
 
         return False
 
+    @staticmethod
+    def are_dir_info_equal(dir_info1, dir_info2):
+        return Output.dir_info_dict(dir_info1) == Output.dir_info_dict(dir_info2)
+
+    @staticmethod
+    def dir_info_dict(dir_info):
+        return {i['relpath']: i['md5'] for i in dir_info}
+
     def changed(self):
         ret = True
 


Test patch:
Repository: iterative/dvc

Issue:
repro: missing cache should not break repo
1) One directory in dvc cache was removed. As a result, I cannot reproduce the directory. It basically breaks the entire repository.

```
$ dvc repro
Failed to reproduce 'Dvcfile': Failed to reproduce 'train.dvc': [Errno 2] No such file or directory: '/home/ubuntu/src/dvc_tutorial/.dvc/cache/0d/d437f2f04fbf54355beab021494baa'
```

2) The same issue for dvc checkout. Not sure about right behaviour - needs to be discussed.

```
$ dvc checkout
'data/plot_loss.jpeg': cache file not found
'data/plot_acc.jpeg': cache file not found
'data/cats_and_dogs_small': cache file not found
Unexpected error: [Errno 2] No such file or directory: '/home/ubuntu/src/dvc_tutorial/.dvc/cache/da/49cf17236a5f2b4cf7046518b272d8'
```

3) (minor) It is better to replace the full path to the relative in the error message.


Discussion:

Resolving patch:
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -237,12 +237,22 @@ def hardlink(self, src, link):
 
     @staticmethod
     def load_dir_cache(path):
-        with open(path, 'r') as fd:
-            d = yaml.safe_load(fd)
+        if os.path.isabs(path):
+            relpath = os.path.relpath(path)
+        else:
+            relpath = path
+
+        try:
+            with open(path, 'r') as fd:
+                d = yaml.safe_load(fd)
+        except Exception as exc:
+            msg = u'Failed to load dir cache \'{}\''
+            Logger.error(msg.format(relpath), exc)
+            return []
 
         if not isinstance(d, list):
             msg = u'Dir cache file format error \'{}\': skipping the file'
-            Logger.error(msg.format(path))
+            Logger.error(msg.format(relpath))
             return []
 
         return d


Test patch:
Repository: iterative/dvc

Issue:
state: Use fileID instead of st_ino on windows



Discussion:

Resolving patch:
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -95,7 +95,7 @@ def mtime(self):
         return os.path.getmtime(self.path)
 
     def inode(self):
-        return os.stat(self.path).st_ino
+        return System.inode(self.path)
 
     def save(self):
         if not os.path.exists(self.path):
diff --git a/dvc/system.py b/dvc/system.py
--- a/dvc/system.py
+++ b/dvc/system.py
@@ -6,6 +6,7 @@
 
 if os.name == 'nt':
     import ntfsutils.hardlink as winlink
+    from ntfsutils.fs import *
 
 
 class System(object):
@@ -23,6 +24,29 @@ def hardlink(source, link_name):
 
         return winlink.create(source, link_name)
 
+    @staticmethod
+    def _getfileinfo(path):
+        # FIXME: current implementation from ntfsutils doesn't support dirs,
+        # and until https://github.com/sid0/ntfs/pull/10 is not merged and
+        # pip package not updated, we have to use our own version.
+        hfile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, None, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, None)
+        if hfile is None:
+            raise WinError()
+        info = BY_HANDLE_FILE_INFORMATION()
+        rv = GetFileInformationByHandle(hfile, info)
+        CloseHandle(hfile)
+        if rv == 0:
+            raise WinError()
+        return info
+
+    @staticmethod
+    def inode(path):
+        if System.is_unix():
+            return os.stat(path).st_ino
+
+        info = System._getfileinfo(path)
+        return hash((info.dwVolumeSerialNumber, info.nFileIndexHigh, info.nFileIndexLow))
+
     @staticmethod
     def samefile(path1, path2):
         if not os.path.exists(path1) or not os.path.exists(path2):


Test patch:
Repository: iterative/dvc

Issue:
Rename CredentialSection to Profile or smth in dvc config for AWS



Discussion:

Resolving patch:
diff --git a/dvc/cloud/credentials_aws.py b/dvc/cloud/credentials_aws.py
--- a/dvc/cloud/credentials_aws.py
+++ b/dvc/cloud/credentials_aws.py
@@ -8,7 +8,7 @@
 class AWSCredentials(object):
     def __init__(self, cloud_config):
         self._conf_credpath = cloud_config.get('CredentialPath', None)
-        self._conf_credsect = cloud_config.get('CredentialSection', 'default')
+        self._conf_credsect = cloud_config.get('Profile', 'default')
 
     @property
     def access_key_id(self):
diff --git a/dvc/config.py b/dvc/config.py
--- a/dvc/config.py
+++ b/dvc/config.py
@@ -26,7 +26,7 @@ class Config(object):
 
 [AWS]
 CredentialPath = ~/.aws/credentials
-CredentialSection = default
+Profile = default
 
 StoragePath = dvc/tutorial
 


Test patch:
Repository: iterative/dvc

Issue:
Print warning when corrupted cache is detected



Discussion:

Resolving patch:
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -165,7 +165,7 @@ def loads_from(cls, project, s_list, use_cache=False, cwd=os.curdir):
     def _changed_cache(self, cache):
         md5 = self.project.state.update(cache)
         if md5 != self.project.cache.path_to_md5(cache):
-            self.project.logger.debug('Corrupted cache file {}'.format(cache))
+            self.project.logger.warn('Corrupted cache file {}'.format(os.path.relpath(cache)))
             os.unlink(cache)
             return True
 


Test patch:
Repository: iterative/dvc

Issue:
dvc repro --force does not work
It looks like the flag was just ignored.


Discussion:
Will take a look shortly.

Resolving patch:
diff --git a/dvc/project.py b/dvc/project.py
--- a/dvc/project.py
+++ b/dvc/project.py
@@ -125,7 +125,7 @@ def run(self,
         return stage
 
     def _reproduce_stage(self, stages, node, force):
-        if not stages[node].changed():
+        if not stages[node].changed() and not force:
             return []
 
         stages[node].reproduce(force=force)


Test patch:
diff --git a/tests/test_repro.py b/tests/test_repro.py
--- a/tests/test_repro.py
+++ b/tests/test_repro.py
@@ -25,6 +25,12 @@ def setUp(self):
                      cmd='python {} {} {}'.format(self.CODE, self.FOO, self.file1))
 
 
+class TestReproForce(TestRepro):
+    def test(self):
+        stages = self.dvc.reproduce(self.file1_stage, force=True)
+        self.assertEqual(len(stages), 2)
+
+
 class TestReproChangedCode(TestRepro):
     def test(self):
         self.swap_code()
Repository: iterative/dvc

Issue:
Deb package errors

```
$ sudo dpkg -i dvc_0.9.0_amd64.deb
$ dvc --version
Traceback (most recent call last):
  File "dvc/__main__.py", line 3, in <module>
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "/home/travis/virtualenv/python3.5.3/lib/python3.5/site-packages/PyInstaller/loader/pyimod03_importers.py", line 631, in exec_module
  File "dvc/main.py", line 2, in <module>
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
...
```


Discussion:
Also, after following dvc installation `pip install git+git://github.com/dataversioncontrol/dvc` it does not work:
```
$ dvc
-bash: /usr/bin/dvc: No such file or directory
```

The package might have issues as well.
Looking into it. Btw, could you please paste the full logs and not just pieces in the future? It would really save time.
oh... sorry.
sounds good!

Do you need an access to a "clean" Linux machine? I have one running in GCP right now.
@dmpetrov Thank you for offering, but I already have mine setup on digitalocean. The problem there is a missing pyinstaller hook, I'll add it later today.

Resolving patch:
diff --git a/scripts/hooks/hook-google.api.core.py b/scripts/hooks/hook-google.api.py
similarity index 100%
rename from scripts/hooks/hook-google.api.core.py
rename to scripts/hooks/hook-google.api.py
diff --git a/scripts/hooks/hook-google.cloud.py b/scripts/hooks/hook-google.cloud.py
--- a/scripts/hooks/hook-google.cloud.py
+++ b/scripts/hooks/hook-google.cloud.py
@@ -1,2 +1,3 @@
 from PyInstaller.utils.hooks import copy_metadata
 datas = copy_metadata('google-cloud-core')
+hiddenimports = ['google.api']


Test patch:
Repository: iterative/dvc

Issue:
Catch gitpython exception when git executable is not found



Discussion:

Resolving patch:
diff --git a/dvc/scm.py b/dvc/scm.py
--- a/dvc/scm.py
+++ b/dvc/scm.py
@@ -1,5 +1,4 @@
 import os
-import git
 
 from dvc.exceptions import DvcException
 
@@ -61,6 +60,7 @@ class Git(Base):
     def __init__(self, root_dir=os.curdir):
         super(Git, self).__init__(root_dir)
 
+        import git
         try:
             self.repo = git.Repo(root_dir)
         except InvalidGitRepositoryError:


Test patch:
Repository: iterative/dvc

Issue:
Empty md5 sum errors
When md5 sum is empty in DVC-file:
```
$ dvc checkout
'data/eval.txt': cache file not found
'data/model.p': cache file not found
```

This happens if I resolve DVC-file merge conflicts by replacing md5 checksums to empty. 


Discussion:

Resolving patch:
diff --git a/dvc/output.py b/dvc/output.py
--- a/dvc/output.py
+++ b/dvc/output.py
@@ -287,7 +287,8 @@ def checkout(self):
             return
 
         if not self.cache or not os.path.exists(self.cache):
-            self.project.logger.warn(u'\'{}\': cache file not found'.format(self.rel_path))
+            if self.cache:
+                self.project.logger.warn(u'\'{}({})\': cache file not found'.format(self.rel_cache, self.rel_path))
             self.remove()
             return
 


Test patch:
Repository: iterative/dvc

Issue:
Add dynamic version
We need to dynamically set dvc version depending on whether it is a git repo build(e.g. 0.9.0-ee94b66f) or a legitimate release(e.g. 0.9.0). 


Discussion:

Resolving patch:
diff --git a/dvc/__init__.py b/dvc/__init__.py
--- a/dvc/__init__.py
+++ b/dvc/__init__.py
@@ -3,5 +3,20 @@
 ----
 Make your data science projects reproducible and shareable.
 """
+import os
+
 VERSION = '0.9.3'
+
+if os.getenv('APPVEYOR_REPO_TAG', '').lower() != 'true' and os.getenv('TRAVIS_TAG', '') == '':
+    # Dynamically update version
+    try:
+        import git
+        repo = git.Repo(os.curdir, search_parent_directories=True)
+        sha = repo.head.object.hexsha
+        short_sha = repo.git.rev_parse(sha, short=6)
+        dirty = '.mod' if repo.is_dirty() else ''
+        VERSION = '{}+{}{}'.format(VERSION, short_sha, dirty)
+    except:
+        pass
+
 __version__ = VERSION


Test patch: