diff --git a/dvc/remote/ssh/connection.py b/dvc/remote/ssh/connection.py index 6bcd2ed3e..5bdf58f97 100644 --- a/dvc/remote/ssh/connection.py +++ b/dvc/remote/ssh/connection.py @@ -1,6 +1,7 @@ import os import posixpath import logging +import errno import stat from contextlib import contextmanager @@ -96,10 +97,13 @@ class SSHConnection: def makedirs(self, path): self._sftp_connect() - if self.isdir(path): + # Single stat call will say whether this is a dir, a file or a link + st_mode = self.st_mode(path) + + if stat.S_ISDIR(st_mode): return - if self.isfile(path) or self.islink(path): + if stat.S_ISREG(st_mode) or stat.S_ISLNK(st_mode): raise DvcException( "a file with the same name '{}' already exists".format(path) ) @@ -110,7 +114,13 @@ class SSHConnection: self.makedirs(head) if tail: - self._sftp.mkdir(path) + try: + self._sftp.mkdir(path) + except IOError as e: + # Since paramiko errors are very vague we need to recheck + # whether it's because path already exists or something else + if e.errno == errno.EACCES or not self.exists(path): + raise def walk(self, directory, topdown=True): # NOTE: original os.walk() implementation [1] with default options was