def restore_file_from_copy(self, file_name, copy_hash, events_file_id, search_by_id=False): try: old_hash = self._quiet_processor.create_file_from_copy( file_name, copy_hash, silent=True, events_file_id=events_file_id, search_by_id=search_by_id, wrong_file_id=self.Exceptions.WrongFileId, copy_does_not_exists=self.Exceptions.CopyDoesNotExists) except AssertionError: self._on_event_arrived( FsEvent(DELETE, op.dirname( self._path_converter.create_abspath(file_name)), True, is_offline=True, quiet=True)) raise return old_hash
def move_file(self, src, dst, is_offline=True): src_full_path = self._path_converter.create_abspath(src) dst_full_path = self._path_converter.create_abspath(dst) is_offline = True if op.isdir(src_full_path) else is_offline src_hard_path = self._quiet_processor.get_hard_path( src_full_path, is_offline) dst_hard_path = self._quiet_processor.get_hard_path( dst_full_path, is_offline) if not op.exists(src_hard_path): raise self.Exceptions.FileNotFound(src_full_path) elif op.exists(dst_hard_path): raise self.Exceptions.FileAlreadyExists(dst_full_path) dst_parent_folder_path = op.dirname(dst_full_path) if not op.exists(dst_parent_folder_path): self._on_event_arrived( FsEvent(DELETE, dst_parent_folder_path, True, is_offline=True, quiet=True)) try: os.rename(src_hard_path, dst_hard_path) except OSError as e: logger.warning("Can't move file (dir) %s. Reason: %s", src_full_path, e) if e.errno == errno.EACCES: self._quiet_processor.access_denied() raise self.Exceptions.AccessDenied(src_full_path) else: raise e
def _on_new_event(self, fs_event): dirname = FilePath(op.dirname(fs_event.src)) if dirname != self._root and not op.exists(dirname): self.event_spawned( FsEvent(DELETE, dirname, True, is_offline=fs_event.is_offline, quiet=fs_event.quiet, event_time=fs_event.time)) self.event_suppressed(fs_event) else: self.event_passed(fs_event)
def create_directory(self, path, events_file_id): full_path = self._path_converter.create_abspath(path) try: self._quiet_processor.create_directory( full_path, events_file_id=events_file_id, wrong_file_id=self.Exceptions.WrongFileId) except AssertionError: self._on_event_arrived( FsEvent(DELETE, op.dirname(full_path), True, is_offline=True, quiet=True)) raise
def _process(self, fs_event): src_path = fs_event.src[: -len(FILE_LINK_SUFFIX)] if fs_event.is_link \ else fs_event.src dst_path = fs_event.dst[: -len(FILE_LINK_SUFFIX)] if fs_event.is_link \ else fs_event.dst if not self._check_file_exists_on_fs(fs_event.src) \ and self._check_file_exists_in_storage(src_path) \ and self._check_file_exists_on_fs(fs_event.dst) \ and not self._check_file_exists_in_storage(dst_path): self.event_passed(fs_event) if not fs_event.is_dir: self.event_spawned( FsEvent(event_type=MODIFY, src=fs_event.dst, is_dir=fs_event.is_dir)) return fs_event.event_type = CREATE if fs_event.is_dir else MODIFY self.event_spawned( FsEvent(event_type=fs_event.event_type, src=fs_event.dst, is_dir=fs_event.is_dir)) fs_event.dst = None self.event_returned(fs_event)
def accept_move(self, src, dst, is_directory=False, events_file_id=None, is_offline=True): src_full_path = self._path_converter.create_abspath(src) dst_full_path = self._path_converter.create_abspath(dst) try: object_type = 'directory' if is_directory else 'file' logger.debug("Moving '%s' %s to '%s'...", src, object_type, dst) if is_directory: self._quiet_processor.move_directory( src_full_path, dst_full_path, events_file_id, self.Exceptions.FileAlreadyExists, self.Exceptions.FileNotFound, wrong_file_id=self.Exceptions.WrongFileId) else: self._quiet_processor.move_file( src_full_path, dst_full_path, events_file_id, self.Exceptions.FileAlreadyExists, self.Exceptions.FileNotFound, wrong_file_id=self.Exceptions.WrongFileId, is_offline=is_offline) logger.info("'%s' %s is moved to '%s'", src, object_type, dst) self.file_removed_from_indexing.emit(FilePath(src_full_path), True) except AssertionError: self._on_event_arrived( FsEvent(DELETE, op.dirname(dst_full_path), True, is_offline=True, quiet=True)) raise
def create_empty_file(self, file_name, file_hash, events_file_id, search_by_id=False, is_offline=True): try: self._quiet_processor.create_empty_file( file_name, file_hash, silent=True, events_file_id=events_file_id, search_by_id=search_by_id, wrong_file_id=self.Exceptions.WrongFileId, is_offline=is_offline) except AssertionError: self._on_event_arrived( FsEvent(DELETE, op.dirname( self._path_converter.create_abspath(file_name)), True, is_offline=True, quiet=True)) raise
def apply_patch(self, filename, patch, new_hash, old_hash, events_file_id): ''' Applies given patch for the file specified @param filename Name of file relative to sync directory [unicode] @param patch Patch data [dict] ''' full_fn = self._path_converter.create_abspath(filename) try: self._apply_patch(full_fn, patch, new_hash, old_hash, events_file_id=events_file_id) except AssertionError: self._on_event_arrived( FsEvent(DELETE, op.dirname(full_fn), True, is_offline=True, quiet=True)) raise
def _check_root(self, root, process_modifies): """ Check given root path for offline events @param root Path (absolute) to be checked [unicode] """ if FilePath(root) in self._special_dirs: return logger.info("Checking root '%s' folder for offline changes...", root) self._start_time = time.time() logger.debug("Obtaining known files from storage...") known_files = set(self._storage.get_known_files()) if not self._active or not self._started: return logger.debug("Known files: %s", len(known_files)) logger.debug("Obtaining actual files and folders from filesystem...") actual_folders, actual_files = get_files_dir_list( root, exclude_dirs=self._root_handlers[root][0].hidden_dirs, exclude_files=self._root_handlers[root][0].hidden_files) if not self._active or not self._started: return logger.debug("Actual folders: %s", len(actual_folders)) logger.debug("Actual files: %s", len(actual_files)) actual_files = set(map(FilePath, actual_files)) - self._special_files actual_folders = set(map(FilePath, actual_folders)) if not self._active or not self._started: return self._offline_stats['file_COUNT'] = len(actual_files) logger.debug("Finding files that were created...") files_created = actual_files.difference(known_files) if not self._active or not self._started: return logger.debug("Finding files that were deleted...") files_deleted = known_files.difference(actual_files) if not self._active or not self._started: return for path in files_deleted.copy(): if not self._active or not self._started: return path_plus_suffix = path + FILE_LINK_SUFFIX if path_plus_suffix in files_created: files_deleted.discard(path) files_created.discard(path_plus_suffix) logger.debug("Obtaining known folders from storage...") known_folders = set(self._storage.get_known_folders()) if not self._active or not self._started: return logger.debug("Known folders: %s", len(known_folders)) logger.debug("Finding folders that were created...") folders_created = sorted(actual_folders.difference(known_folders), key=len, reverse=True) if not self._active or not self._started: return logger.debug("Finding folders that were deleted...") folders_deleted = sorted(known_folders.difference(actual_folders), key=len, reverse=True) if not self._active or not self._started: return logger.info("Folders found: %s (created: %s, deleted: %s)", len(actual_folders), len(folders_created), len(folders_deleted)) self._offline_stats['dir_COUNT'] = len(actual_folders) logger.debug("Appending deleted files to processing...") for filename in files_deleted: if not self._active or not self._started: return self._emit_offline_event( FsEvent(event_type=DELETE, src=filename, is_dir=False, is_offline=True)) logger.debug("Appending deleted folders to processing...") for foldername in folders_deleted: if not self._active or not self._started: return self._emit_offline_event( FsEvent(event_type=DELETE, src=foldername, is_dir=True, is_offline=True)) logger.debug("Appending created files to processing...") for filename in files_created: if not self._active or not self._started: return self._emit_offline_event( FsEvent(event_type=CREATE, src=filename, is_dir=False, is_offline=True)) logger.debug("Appending created folders to processing...") for foldername in folders_created: if not self._active or not self._started: return self._emit_offline_event( FsEvent(event_type=CREATE, src=foldername, is_dir=True, is_offline=True)) self._processed_offline_changes = True self.is_processing_offline = False logger.debug("Emitting ofline events processed signal") self.processed_offline_changes.emit() if not process_modifies: return logger.debug("Finding files with possible modifications...") same_files = actual_files.intersection(known_files) if not self._active or not self._started: return logger.info( "Files found: %s (created: %s, deleted: %s, remaining: %s)", len(actual_files), len(files_created), len(files_deleted), len(same_files)) logger.debug("Appending possible modified files to processing...") for filename in same_files: if not self._active or not self._started: return # Actual file modification will be checked by event filters # applied in WatchdogHandler instance self._emit_offline_event( FsEvent( event_type=MODIFY, src=filename, is_dir=False, is_offline=True, quiet=True, )) logger.debug("work complete")