Example #1
0
 def smart_unsync_oid(self, remote_oid):
     ent: SyncEntry = self.state.lookup_oid(REMOTE, remote_oid)
     if not ent:
         raise ex.CloudFileNotFoundError(remote_oid)
     self._smart_unsync_ent(ent)
     ent = self.state.smart_unsync_oid(remote_oid)
     return ent[LOCAL].path
Example #2
0
 def _smart_unsync(self, ents, source_id) -> Optional[SyncEntry]:
     if not ents:
         raise ex.CloudFileNotFoundError(source_id)
     for ent in ents:
         if ent in self.requestset:
             self._smart_unsync_ent(ent)
             return ent
     return None
Example #3
0
 def smart_sync_path(self, remote_path) -> List[SyncEntry]:
     # We are automatically syncing all folders, so we don't need to worry about parent folders existing
     #   although this could be a concern before the initial sync with a bed is complete,
     #   parent_conflict handling should take care of it
     ents = self.lookup_path(REMOTE, remote_path)
     if not ents:
         raise ex.CloudFileNotFoundError(remote_path)
     for ent in ents:
         self._smart_sync_ent(ent)
     return ents
Example #4
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)
Example #5
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)
Example #6
0
 def listdir(self, oid) -> typing.Generator[DirInfo, None, None]:
     with self._api():
         fpath = self._oid_to_fpath(oid)
         try:
             with os.scandir(fpath) as it:
                 for entry in it:
                     entry_path = entry.path
                     ohash = self._fast_hash_path(entry_path)
                     otype = OType.DIRECTORY if entry.is_dir(
                     ) else OType.FILE
                     name = self.is_subpath(fpath, entry_path).lstrip("/")
                     path = self._trim_ns(entry_path)
                     stat_result = os.stat(entry_path)
                     mtime = int(stat_result.st_mtime)
                     size = stat_result.st_size if otype == OType.FILE else 0
                     yield DirInfo(otype=otype,
                                   oid=self._fpath_to_oid(entry_path),
                                   hash=ohash,
                                   path=path,
                                   name=name,
                                   size=size,
                                   mtime=mtime)
         except NotADirectoryError:
             raise ex.CloudFileNotFoundError("not a directory")