예제 #1
0
    def mkdir(self, path) -> str:
        fpath = self.join(self.namespace_id, path)
        with self._api():
            parent = self.dirname(fpath)
            if os.path.isfile(parent) or os.path.isfile(fpath):
                raise ex.CloudFileExistsError()
            if not os.path.exists(fpath):
                os.mkdir(fpath)

            return self._fpath_to_oid(fpath)
예제 #2
0
 def __exit__(self, ty, exception, tb):
     if isinstance(exception, FileNotFoundError):
         raise ex.CloudFileNotFoundError
     if isinstance(exception, FileExistsError):
         raise ex.CloudFileExistsError
     if isinstance(exception, IsADirectoryError):
         raise ex.CloudFileExistsError("Is a dir: %s" % exception)
     if isinstance(exception, NotADirectoryError):
         raise ex.CloudFileExistsError("Not a dir: %s" % exception)
     if isinstance(exception, OSError):
         if exception.errno == errno.ENOTEMPTY:
             raise ex.CloudFileExistsError("Dir not empty: %s" % exception)
         if exception.errno == errno.ENOTDIR:
             raise ex.CloudFileExistsError("Not a dir: %s" % exception)
         if exception.errno == errno.ENOSPC:
             raise ex.CloudOutOfSpaceError("no space: %s" % exception)
         if exception.errno == errno.ENAMETOOLONG:
             raise ex.CloudFileNameError("Invalid name: %s" % exception)
         raise
예제 #3
0
 def smart_rename(self, side, oid, new_path) -> str:
     """smartsync aware rename"""
     # oid MUST exist on the specified side
     #   then, if target exists on same side, renaming on that side will fail in the rename
     #   check if target exists only on the other side, and raise the FileExists here if so
     other = other_side(side)
     other_side_new_path = self.translate(other, new_path)
     if self.providers[other].exists_path(other_side_new_path):
         other_side_adverb = "remotely" if other_side == REMOTE else "locally"
         raise ex.CloudFileExistsError(
             "Rename target %s already exists %s as %s" %
             (new_path, other_side_adverb, other_side_new_path))
     return self.providers[side].rename(oid, new_path)
예제 #4
0
    def rename(self, oid, path) -> str:
        fpath = self.join(self.namespace_id, path)
        with self._api():
            path_from = self._oid_to_fpath(oid)
            if not os.path.exists(path_from):
                raise ex.CloudFileNotFoundError
            parent = self.dirname(fpath)
            if not os.path.exists(parent):
                raise ex.CloudFileNotFoundError(parent)
            if not os.path.isdir(parent):
                raise ex.CloudFileExistsError(fpath)
            if not self.paths_match(path_from, fpath, for_display=True):
                from_dir = os.path.isdir(path_from)
                to_dir = os.path.isdir(fpath)
                has_contents = False
                if os.path.exists(fpath):
                    if to_dir:
                        has_contents = self._folder_path_has_contents(fpath)
                    if (not to_dir or to_dir != from_dir
                            or (to_dir and has_contents)):
                        if not self.paths_match(path_from, fpath):
                            raise ex.CloudFileExistsError(fpath)
                try:
                    assert os.path.exists(path_from)
                    assert os.path.exists(parent)
                    log.info("rename %s -> %s", path_from, fpath)
                    os.rename(path_from, fpath)
                except FileExistsError:
                    if not has_contents and is_windows() and to_dir:
                        # win32 doesn't allow this, so force it
                        tmpname = fpath + os.urandom(16).hex()
                        os.rename(fpath, tmpname)
                        os.rename(path_from, fpath)
                        self._rmdirs.append(tmpname)
                    else:
                        raise

            return self._fpath_to_oid(fpath)
예제 #5
0
 def delete(self, oid):
     with self._api():
         path = self._oid_to_fpath(oid)
         if os.path.isdir(path):
             log.debug("delete dir %s", path)
             if self._folder_oid_has_contents(oid):
                 raise ex.CloudFileExistsError(
                     "Cannot delete non-empty folder %s:%s" % (oid, path))
             os.rmdir(path)
         elif os.path.exists(path):
             log.debug("delete file %s", path)
             os.unlink(path)
         else:
             log.debug("delete ??? %s", path)
예제 #6
0
 def create(self, path, file_like, metadata=None) -> OInfo:
     fpath = self.join(self.namespace_id, path)
     with self._api():
         parent = self.dirname(fpath)
         if os.path.exists(fpath) or (os.path.exists(parent)
                                      and not os.path.isdir(parent)):
             raise ex.CloudFileExistsError()
         with open(fpath, "wb") as dest:
             try:
                 shutil.copyfileobj(file_like, dest)
             except Exception:
                 if os.path.exists(fpath):
                     dest.close()
                     os.unlink(fpath)
                 raise
         log.debug("create ok %s", fpath)
         self._clear_hash_cache(fpath)
         return self.__info_path(path, fpath)
예제 #7
0
 def upload(self, oid, file_like, metadata=None) -> OInfo:
     with self._api():
         fpath = self._oid_to_fpath(oid)
         if os.path.isdir(fpath):
             raise ex.CloudFileExistsError()
         if not os.path.exists(fpath):
             raise ex.CloudFileNotFoundError(oid)
         tmpdir = tempfile.gettempdir()
         tmp_file = os.path.join(tmpdir, "tmp." + os.urandom(16).hex())
         with open(tmp_file, "wb") as f:
             shutil.copyfileobj(file_like, f)
         try:
             with open(tmp_file, "rb") as src, open(fpath, "wb") as dest:
                 shutil.copyfileobj(src, dest)
         finally:
             try:
                 os.unlink(tmp_file)
             except Exception:
                 log.debug("cannot remove temp %s", tmp_file)
         self._clear_hash_cache(fpath)
         return self.info_oid(oid)