def __upload(rel_path_or_buf): # Its a buf! if type(rel_path_or_buf) == dict: return self._upload(utils.get_full_path(rel_path_or_buf['path']), rel_path_or_buf.get('buf')) # Its a rel path! buf_id = self.paths_to_ids.get(rel_path_or_buf) text = self.bufs.get(buf_id, {}).get('buf') # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else. if text is not None: return len(text) return self._upload(utils.get_full_path(rel_path_or_buf), self.get_view_text_by_path(rel_path_or_buf))
def _on_rename_buf(self, data): del self.paths_to_ids[data['old_path']] self.paths_to_ids[data['path']] = data['id'] new = utils.get_full_path(data['path']) old = utils.get_full_path(data['old_path']) new_dir = os.path.split(new)[0] if new_dir: utils.mkdir(new_dir) view = self.get_view(data['id']) if view: view.rename(new) else: os.rename(old, new) self.bufs[data['id']]['path'] = data['path']
def _on_rename_buf(self, data): # This can screw up if someone else renames the buffer around the same time as us. Oh well. msg.debug('asdf %s' % data) buf = self.get_buf_by_path(utils.get_full_path(data['old_path'])) if buf: return super(AgentConnection, self)._on_rename_buf(data) msg.debug('We already renamed %s. Skipping' % data['old_path'])
def __upload(rel_path): buf_id = self.paths_to_ids.get(rel_path) text = self.bufs.get(buf_id, {}).get('buf') # Only upload stuff that's not in self.bufs (new bufs). We already took care of everything else. if text is not None: return len(text) return self._upload(utils.get_full_path(rel_path), self.get_view_text_by_path(rel_path))
def _scan_dir(self, bufs, ig, read_only): changed_bufs = [] missing_bufs = [] new_files = set() if not read_only: new_files = set([utils.to_rel_path(x) for x in ig.list_paths()]) for buf_id, buf in bufs.items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer ', buf['path']) else: changed_bufs.append(buf) buf['md5'] = view_md5 continue try: if buf['encoding'] == 'utf8': if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace( '\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer ', buf['path']) else: msg.debug('md5 differs. possibly getting buffer later ', buf['path']) changed_bufs.append(buf) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e)) missing_bufs.append(buf) return changed_bufs, missing_bufs, new_files
def _on_delete_buf(self, data): path = utils.get_full_path(data['path']) try: utils.rm(path) except Exception: pass user_id = data.get('user_id') username = self.get_username_by_id(user_id) msg.log('%s deleted %s' % (username, path))
def _on_rename_buf(self, data): del self.paths_to_ids[data['old_path']] self.paths_to_ids[data['path']] = data['id'] new = utils.get_full_path(data['path']) old = utils.get_full_path(data['old_path']) new_dir = os.path.split(new)[0] if new_dir: utils.mkdir(new_dir) view = self.get_view(data['id']) if view: view.rename(new) else: try: os.rename(old, new) except Exception as e: msg.debug('Error moving ', old, 'to', new, str_e(e)) utils.save_buf(self.bufs[data.id]) self.bufs[data['id']]['path'] = data['path']
def _scan_dir(self, bufs, ig, read_only): changed_bufs = [] missing_bufs = [] new_files = set() if not read_only: new_files = set([utils.to_rel_path(x) for x in ig.list_paths()]) for buf_id, buf in bufs.items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer ', buf['path']) else: changed_bufs.append(buf) buf['md5'] = view_md5 continue try: if buf['encoding'] == 'utf8': if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer ', buf['path']) else: msg.debug('md5 differs. possibly getting buffer later ', buf['path']) changed_bufs.append(buf) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e)) missing_bufs.append(buf) return changed_bufs, missing_bufs, new_files
def _on_create_buf(self, data): if data['encoding'] == 'base64': data['buf'] = base64.b64decode(data['buf']) self.bufs[data['id']] = data self.paths_to_ids[data['path']] = data['id'] abs_path = utils.get_full_path(data['path']) self.to_emacs('create_buf', { 'full_path': utils.get_full_path(data['path']), 'path': data['path'], 'username': data.get('username', ''), }) if abs_path not in self.emacs_handler.emacs_bufs: utils.save_buf(data) return text = self.emacs_handler.emacs_bufs.get(abs_path)[0] if text == data['buf']: return self.emacs_handler.bufs_changed.append(data['id'])
def _on_highlight(self, data): buf = self.bufs[data['id']] # TODO: save highlights for when user opens the buffer in emacs self.to_emacs('highlight', { 'full_path': utils.get_full_path(buf['path']), 'ranges': data['ranges'], 'user_id': data['user_id'], 'username': data.get('username', 'unknown user'), 'following': data.get('following', False), 'ping': data.get('ping', False) })
def _on_delete_buf(self, data): buf_id = int(data['id']) buf = self.bufs[buf_id] path = buf['path'] try: super(AgentConnection, self)._on_delete_buf(data) except Exception as e: msg.debug('Unable to delete buf %s: %s' % (path, str(e))) else: self.to_emacs('delete_buf', { 'full_path': utils.get_full_path(path), 'path': path, 'username': data.get('username', ''), })
def _on_delete_buf(self, data): buf_id = data['id'] try: buf = self.bufs.get(buf_id) if buf: del self.paths_to_ids[buf['path']] del self.bufs[buf_id] except KeyError: msg.debug('KeyError deleting buf id ', buf_id) # TODO: if data['unlink'] == True, add to ignore? action = 'removed' path = utils.get_full_path(data['path']) if data.get('unlink', False): action = 'deleted' try: utils.rm(path) except Exception as e: msg.debug('Error deleting ', path, ': ', str_e(e)) user_id = data.get('user_id') username = self.get_username_by_id(user_id) msg.log(username, ' ', action, ' ', path)
def _rate_limited_upload(self, paths_iter, total_bytes, bytes_uploaded=0.0, upload_func=None): reactor.tick() upload_func = upload_func or (lambda x: self._upload(utils.get_full_path(x))) if len(self.proto) > 0: self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 10, paths_iter, total_bytes, bytes_uploaded, upload_func) return bar_len = 20 try: p = next(paths_iter) size = upload_func(p) bytes_uploaded += size try: percent = (bytes_uploaded / total_bytes) except ZeroDivisionError: percent = 0.5 bar = ' |' + ('|' * int(bar_len * percent)) + (' ' * int((1 - percent) * bar_len)) + '|' editor.status_message('Uploading... %2.2f%% %s' % (percent * 100, bar)) except StopIteration: editor.status_message('Uploading... 100% ' + ('|' * bar_len) + '| complete') msg.log('All done uploading') return self.upload_timeout = utils.set_timeout(self._rate_limited_upload, 50, paths_iter, total_bytes, bytes_uploaded, upload_func)
def __upload_buf(buf): return self._upload(utils.get_full_path(buf['path']), buf.get('buf'))
def _on_room_info(self, data): self.reset() self.joined_workspace = True self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.''' msg.log('No patch permission. Setting buffers to read-only') if 'request_perm' in data['perms']: should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?' if should_send: self.send({ 'name': 'request_perms', 'perms': ['edit_room'] }) else: editor.error_message(no_perms_msg) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) changed_bufs = [] missing_bufs = [] for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer %s' % buf['path']) else: changed_bufs.append(buf_id) buf['md5'] = view_md5 else: try: if buf['encoding'] == "utf8": if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace( '\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer %s' % buf['path']) else: msg.debug( 'md5 differs. possibly getting buffer later %s' % buf['path']) changed_bufs.append(buf_id) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for %s, %s' % (buf['path'], e)) missing_bufs.append(buf_id) stomp_local = self.should_get_bufs if stomp_local and (changed_bufs or missing_bufs): changed = [self.bufs[buf_id] for buf_id in changed_bufs] missing = [self.bufs[buf_id] for buf_id in missing_bufs] choice = yield self.stomp_prompt, changed, missing if choice not in [0, 1]: self.stop() return stomp_local = bool(choice) for buf_id in changed_bufs: buf = self.bufs[buf_id] if stomp_local: self.get_buf(buf_id, buf.get('view')) self.save_on_get_bufs.add(buf_id) else: self._upload(utils.get_full_path(buf['path']), buf['buf']) for buf_id in missing_bufs: buf = self.bufs[buf_id] if stomp_local: self.get_buf(buf_id, buf.get('view')) self.save_on_get_bufs.add(buf_id) else: self.send({ 'name': 'delete_buf', 'id': buf['id'], }) success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) self.emit("room_info")
def _on_room_info(self, data): self.reset() G.JOINED_WORKSPACE = True self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: msg.log('No patch permission. Setting buffers to read-only') should_send = yield self.ok_cancel_dialog, 'You don\'t have permission to edit this workspace. All files will be read-only.\n\nDo you want to request edit permission?' if should_send: self.send({'name': 'request_perms', 'perms': ['edit_room']}) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) changed_bufs = [] missing_bufs = [] for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer %s' % buf['path']) buf['buf'] = view_text G.VIEW_TO_HASH[view.native_id] = view_md5 elif self.should_get_bufs: changed_bufs.append(buf_id) else: try: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer %s' % buf['path']) if buf['encoding'] == 'utf8': buf_buf = buf_buf.decode('utf-8') buf['buf'] = buf_buf elif self.should_get_bufs: changed_bufs.append(buf_id) except Exception as e: msg.debug('Error calculating md5:', e) missing_bufs.append(buf_id) if changed_bufs and self.should_get_bufs: if len(changed_bufs) > 4: prompt = '%s local files are different from the workspace. Overwrite your local files?' % len(changed_bufs) else: prompt = 'Overwrite the following local files?\n' for buf_id in changed_bufs: prompt += '\n%s' % self.bufs[buf_id]['path'] stomp_local = yield self.ok_cancel_dialog, prompt for buf_id in changed_bufs: if stomp_local: self.get_buf(buf_id) self.save_on_get_bufs.add(buf_id) else: buf = self.bufs[buf_id] # TODO: this is inefficient. we just read the file 20 lines ago self.upload(utils.get_full_path(buf['path'])) for buf_id in missing_bufs: self.get_buf(buf_id) success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) self.emit("room_info")
def _upload_file_by_path(self, rel_path): return self._upload(utils.get_full_path(rel_path), self.get_view_text_by_path(rel_path))
def _on_room_info(self, data): self.reset() self.joined_workspace = True self.workspace_info = data G.PERMS = data['perms'] self.proto.reset_retries() if G.OUTBOUND_FILTERING: msg.error('Detected outbound port blocking! See https://floobits.com/help/network for more info.') read_only = False if 'patch' not in data['perms']: read_only = True no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.''' msg.log('No patch permission. Setting buffers to read-only') if 'request_perm' in data['perms']: should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?' # TODO: wait for perms to be OK'd/denied before uploading or bailing if should_send: self.send({'name': 'request_perms', 'perms': ['edit_room']}) else: if G.EXPERT_MODE: editor.status_message(no_perms_msg) else: editor.error_message(no_perms_msg) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) utils.update_recent_workspaces(self.workspace_url) changed_bufs = [] missing_bufs = [] new_files = set() ig = ignore.create_ignore_tree(G.PROJECT_PATH) G.IGNORE = ig if not read_only: new_files = set([utils.to_rel_path(x) for x in ig.list_paths()]) for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer ', buf['path']) else: changed_bufs.append(buf) buf['md5'] = view_md5 continue try: if buf['encoding'] == 'utf8': if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer ', buf['path']) else: msg.debug('md5 differs. possibly getting buffer later ', buf['path']) changed_bufs.append(buf) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e)) missing_bufs.append(buf) ignored = [] for p, buf_id in self.paths_to_ids.items(): if p not in new_files: ignored.append(p) new_files.discard(p) if self.action == utils.JOIN_ACTION.UPLOAD: yield self._initial_upload, ig, missing_bufs, changed_bufs # TODO: maybe use org name here who = 'Your friends' anon_perms = G.AGENT.workspace_info.get('anon_perms') if 'get_buf' in anon_perms: who = 'Anyone' _msg = 'You are sharing:\n\n%s\n\n%s can join your workspace at:\n\n%s' % (G.PROJECT_PATH, who, G.AGENT.workspace_url) # Workaround for horrible Sublime Text bug utils.set_timeout(editor.message_dialog, 0, _msg) elif changed_bufs or missing_bufs or new_files: # TODO: handle readonly here if self.action == utils.JOIN_ACTION.PROMPT: stomp_local = yield self.stomp_prompt, changed_bufs, missing_bufs, list(new_files), ignored if stomp_local not in [0, 1]: self.stop() return elif self.action == utils.JOIN_ACTION.DOWNLOAD: stomp_local = True else: # This should never happen assert False return if stomp_local: for buf in changed_bufs: self.get_buf(buf['id'], buf.get('view')) self.save_on_get_bufs.add(buf['id']) for buf in missing_bufs: self.get_buf(buf['id'], buf.get('view')) self.save_on_get_bufs.add(buf['id']) else: yield self._initial_upload, ig, missing_bufs, changed_bufs success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) self.emit("room_info")
def _on_room_info(self, data): self.reset() self.joined_workspace = True self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.''' msg.log('No patch permission. Setting buffers to read-only') if 'request_perm' in data['perms']: should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?' if should_send: self.send({'name': 'request_perms', 'perms': ['edit_room']}) else: editor.error_message(no_perms_msg) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) changed_bufs = [] missing_bufs = [] for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer %s' % buf['path']) else: changed_bufs.append(buf_id) buf['md5'] = view_md5 else: try: if buf['encoding'] == "utf8": if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace('\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer %s' % buf['path']) else: msg.debug('md5 differs. possibly getting buffer later %s' % buf['path']) changed_bufs.append(buf_id) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for %s, %s' % (buf['path'], e)) missing_bufs.append(buf_id) stomp_local = self.should_get_bufs if stomp_local and (changed_bufs or missing_bufs): changed = [self.bufs[buf_id] for buf_id in changed_bufs] missing = [self.bufs[buf_id] for buf_id in missing_bufs] choice = yield self.stomp_prompt, changed, missing if choice not in [0, 1]: self.stop() return stomp_local = bool(choice) for buf_id in changed_bufs: buf = self.bufs[buf_id] if stomp_local: self.get_buf(buf_id, buf.get('view')) self.save_on_get_bufs.add(buf_id) else: self._upload(utils.get_full_path(buf['path']), buf['buf']) for buf_id in missing_bufs: buf = self.bufs[buf_id] if stomp_local: self.get_buf(buf_id, buf.get('view')) self.save_on_get_bufs.add(buf_id) else: self.send({ 'name': 'delete_buf', 'id': buf['id'], }) success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) self.emit("room_info")
def _scan_dir(self, bufs, ig, read_only): status_msg = 'Comparing local files against workspace...' editor.status_message(status_msg) update_status_msg = getattr(self, 'update_status_msg', None) if update_status_msg: try: update_status_msg(self, status_msg) except Exception as e: pass changed_bufs = [] missing_bufs = [] new_files = set() if not read_only: new_files = set([utils.to_rel_path(x) for x in ig.list_paths()]) for buf_id, buf in bufs.items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer ', buf['path']) else: changed_bufs.append(buf) buf['md5'] = view_md5 continue try: if buf['encoding'] == 'utf8': if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace( '\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer ', buf['path']) else: msg.debug('md5 differs. possibly getting buffer later ', buf['path']) changed_bufs.append(buf) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e)) missing_bufs.append(buf) editor.status_message( 'Comparing local files against workspace... done.') return changed_bufs, missing_bufs, new_files
def _on_room_info(self, data): self.reset() G.JOINED_WORKSPACE = True self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: msg.log('No patch permission. Setting buffers to read-only') should_send = yield self.ok_cancel_dialog, '''You don't have permission to edit this workspace. All files will be read-only. Do you want to request edit permission?''' if should_send: self.send({'name': 'request_perms', 'perms': ['edit_room']}) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) changed_bufs = [] missing_bufs = [] for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer %s' % buf['path']) buf['buf'] = view_text G.VIEW_TO_HASH[view.native_id] = view_md5 elif self.should_get_bufs: changed_bufs.append(buf_id) else: try: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer %s' % buf['path']) if buf['encoding'] == 'utf8': buf_buf = buf_buf.decode('utf-8') buf['buf'] = buf_buf elif self.should_get_bufs: changed_bufs.append(buf_id) except Exception as e: msg.debug('Error calculating md5:', e) missing_bufs.append(buf_id) if changed_bufs and self.should_get_bufs: if len(changed_bufs) > 4: prompt = '%s local files are different from the workspace. Overwrite your local files?' % len(changed_bufs) else: prompt = 'Overwrite the following local files?\n' for buf_id in changed_bufs: prompt += '\n%s' % self.bufs[buf_id]['path'] stomp_local = yield self.ok_cancel_dialog, prompt for buf_id in changed_bufs: if stomp_local: self.get_buf(buf_id) self.save_on_get_bufs.add(buf_id) else: buf = self.bufs[buf_id] # TODO: this is inefficient. we just read the file 20 lines ago self.upload(utils.get_full_path(buf['path'])) for buf_id in missing_bufs: self.get_buf(buf_id) success_msg = 'Successfully joined workspace %s/%s' % (self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) self.emit("room_info")
def _on_room_info(self, data): self.joined_workspace = True self.workspace_info = data G.PERMS = data['perms'] self.proto.reset_retries() if G.OUTBOUND_FILTERING: msg.error( 'Detected outbound port blocking! See https://floobits.com/help/network for more info.' ) read_only = False if 'patch' not in data['perms']: read_only = True no_perms_msg = '''You don't have permission to edit this workspace. All files will be read-only.''' msg.log('No patch permission. Setting buffers to read-only') if 'request_perm' in data['perms']: should_send = yield self.ok_cancel_dialog, no_perms_msg + '\nDo you want to request edit permission?' # TODO: wait for perms to be OK'd/denied before uploading or bailing if should_send: self.send({ 'name': 'request_perms', 'perms': ['edit_room'] }) else: if G.EXPERT_MODE: editor.status_message(no_perms_msg) else: editor.error_message(no_perms_msg) floo_json = { 'url': utils.to_workspace_url({ 'owner': self.owner, 'workspace': self.workspace, 'host': self.proto.host, 'port': self.proto.port, 'secure': self.proto.secure, }) } utils.update_floo_file(os.path.join(G.PROJECT_PATH, '.floo'), floo_json) utils.update_recent_workspaces(self.workspace_url) changed_bufs = [] missing_bufs = [] new_files = set() ig = ignore.create_ignore_tree(G.PROJECT_PATH) G.IGNORE = ig if not read_only: new_files = set([utils.to_rel_path(x) for x in ig.list_paths()]) for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings buf_path = utils.get_full_path(buf['path']) new_dir = os.path.dirname(buf_path) utils.mkdir(new_dir) self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id view = self.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = view.get_text() view_md5 = hashlib.md5(view_text.encode('utf-8')).hexdigest() buf['buf'] = view_text buf['view'] = view G.VIEW_TO_HASH[view.native_id] = view_md5 if view_md5 == buf['md5']: msg.debug('md5 sum matches view. not getting buffer ', buf['path']) else: changed_bufs.append(buf) buf['md5'] = view_md5 continue try: if buf['encoding'] == 'utf8': if io: buf_fd = io.open(buf_path, 'Urt', encoding='utf8') buf_buf = buf_fd.read() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read().decode('utf-8').replace( '\r\n', '\n') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() else: buf_fd = open(buf_path, 'rb') buf_buf = buf_fd.read() md5 = hashlib.md5(buf_buf).hexdigest() buf_fd.close() buf['buf'] = buf_buf if md5 == buf['md5']: msg.debug('md5 sum matches. not getting buffer ', buf['path']) else: msg.debug('md5 differs. possibly getting buffer later ', buf['path']) changed_bufs.append(buf) buf['md5'] = md5 except Exception as e: msg.debug('Error calculating md5 for ', buf['path'], ', ', str_e(e)) missing_bufs.append(buf) ignored = [] for p, buf_id in self.paths_to_ids.items(): if p not in new_files: ignored.append(p) new_files.discard(p) if self.action == utils.JOIN_ACTION.UPLOAD: yield self._initial_upload, ig, missing_bufs, changed_bufs # TODO: maybe use org name here who = 'Your friends' anon_perms = G.AGENT.workspace_info.get('anon_perms') if 'get_buf' in anon_perms: who = 'Anyone' _msg = 'You are sharing:\n\n%s\n\n%s can join your workspace at:\n\n%s' % ( G.PROJECT_PATH, who, G.AGENT.workspace_url) # Workaround for horrible Sublime Text bug utils.set_timeout(editor.message_dialog, 0, _msg) elif changed_bufs or missing_bufs or new_files: # TODO: handle readonly here if self.action == utils.JOIN_ACTION.PROMPT: stomp_local = yield self.stomp_prompt, changed_bufs, missing_bufs, list( new_files), ignored if stomp_local not in [0, 1]: self.stop() return elif self.action == utils.JOIN_ACTION.DOWNLOAD: stomp_local = True else: # This should never happen assert False return if stomp_local: for buf in changed_bufs: self.get_buf(buf['id'], buf.get('view')) self.save_on_get_bufs.add(buf['id']) for buf in missing_bufs: self.get_buf(buf['id'], buf.get('view')) self.save_on_get_bufs.add(buf['id']) else: yield self._initial_upload, ig, missing_bufs, changed_bufs success_msg = '%s@%s/%s: Joined!' % (self.username, self.owner, self.workspace) msg.log(success_msg) editor.status_message(success_msg) data = utils.get_persistent_data() data['recent_workspaces'].insert(0, {"url": self.workspace_url}) utils.update_persistent_data(data) utils.add_workspace_to_persistent_json(self.owner, self.workspace, self.workspace_url, G.PROJECT_PATH) temp_data = data.get('temp_data', {}) hangout = temp_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) self.emit("room_info")