def on_rename_buf(self, data): new = utils.get_full_path(data['path']) old = utils.get_full_path(data['old_path']) new_dir = os.path.dirname(new) if new_dir: utils.mkdir(new_dir) view = self.get_view(data['id']) self.FLOO_BUFS[data['id']]['path'] = data['path'] if view: view.rename(new) else: os.rename(old, new)
def on_rename_buf(self, data): buf = self.FLOO_BUFS[int(data['id'])] # This can screw up if someone else renames the buffer around the same time as us. Oh well. buf = self.get_buf_by_path(utils.get_full_path(data['path'])) if not buf: return super(Protocol, self).on_rename_buf(data) msg.debug('We already renamed %s. Skipping' % buf['path'])
def on_create_buf(self, data): super(Protocol, self).on_create_buf(data) emacs.put('create_buf', { 'full_path': utils.get_full_path(data['path']), 'path': data['path'], 'username': data.get('username', ''), })
def delete_buf(self, path): """deletes a path""" if not path: return path = utils.get_full_path(path) if not self.is_shared(path): msg.error('Skipping deleting %s because it is not in shared path %s.' % (path, G.PROJECT_PATH)) return if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): # Don't care about hidden stuff dirnames[:] = [d for d in dirnames if d[0] != '.'] for f in filenames: f_path = os.path.join(dirpath, f) if f[0] == '.': msg.log('Not deleting buf for hidden file %s' % f_path) else: self.delete_buf(f_path) return buf_to_delete = None rel_path = utils.to_rel_path(path) buf_to_delete = self.get_buf_by_path(rel_path) if buf_to_delete is None: msg.error('%s is not in this workspace' % path) return msg.log('deleting buffer ', rel_path) event = { 'name': 'delete_buf', 'id': buf_to_delete['id'], } self.agent.put(event)
def on_delete_buf(self, data): buf_id = int(data['id']) del self.FLOO_BUFS[buf_id] del self.FLOO_PATHS_TO_BUFS[data['path']] path = utils.get_full_path(data['path']) utils.rm(path) msg.warn('deleted %s because %s told me too.' % (path, data.get('username', 'the internet')))
def set_text(self, text): self.emacs_buf = text emacs.put('get_buf', { 'id': self.buf['id'], 'full_path': utils.get_full_path(self.buf['path']), 'buf': text, })
def _on_buffer_list_change(self, req): added = req.get('added') or {} for path, text in added.items(): buf = self.get_buf_by_path(path) buf_id = buf and int(buf.get('id')) d = buf and 'buf' in buf and self.agent.on_load.get(buf_id) if d: self.emacs_bufs[path][0] = buf['buf'] else: self.emacs_bufs[path][0] = text if not buf: msg.debug('no buf for path %s' % path) if 'create_buf' in G.PERMS and utils.is_shared( path) and G.IGNORE and not G.IGNORE.is_ignored(path): self.agent._upload(path, text=text) elif path in self.emacs_bufs: del self.emacs_bufs[path] continue view = self.views.get(buf_id) if view is None: self.get_view(buf_id) elif view.is_loading(): view._emacs_buf = self.emacs_bufs[path] else: msg.debug( 'view for buf %s already exists. this is not good. we got out of sync' % buf['path']) if d: del self.agent.on_load[buf_id] for _, f in d.items(): f() deleted = req.get('deleted') or [] for path in deleted: if self.emacs_bufs.get(path) is None: msg.debug( 'emacs deleted %s but we already deleted it from emacs_bufs' % path) if path in self.emacs_bufs: del self.emacs_bufs[path] buf = self.get_buf_by_path(path) if buf and buf['id'] in self.views: del self.views[buf['id']] seen = set() current = req.get('current') or [] for path in current: if self.emacs_bufs.get(path) is None: msg.debug( 'We should have buffer %s in emacs_bufs but we don\'t' % path) else: seen.add(path) for buf_id, view in self.views.items(): if utils.get_full_path(view.buf['path']) not in seen: msg.debug( 'We should not have buffer %s in our views but we do.' % view.buf['path'])
def apply_patches(self, buf, patches, username): self.emacs_buf = buf['buf'] self._emacs.send({ 'name': 'edit', 'id': self.buf['id'], 'full_path': utils.get_full_path(self.buf['path']), 'edits': patches[2], })
def __init__(self, buf, emacs_buf=None): self.buf = buf self._emacs_buf = emacs_buf if emacs_buf is None: emacs.put('create_view', { 'full_path': utils.get_full_path(buf['path']), 'id': buf['id'], })
def set_text(self, text): self.emacs_buf = text self._emacs.send({ 'name': 'get_buf', 'id': self.buf['id'], 'full_path': utils.get_full_path(self.buf['path']), 'buf': text, })
def save_buf(buf): path = utils.get_full_path(buf['path']) utils.mkdir(os.path.split(path)[0]) with open(path, 'wb') as fd: if buf['encoding'] == 'utf8': fd.write(buf['buf'].encode('utf-8')) else: fd.write(buf['buf'])
def on_rename_buf(self, data): buf_id = int(data['id']) new = utils.get_full_path(data['path']) old = utils.get_full_path(data['old_path']) new_dir = os.path.dirname(new) if new_dir: utils.mkdir(new_dir) buf = self.FLOO_BUFS[buf_id] old_path = buf['path'] del self.FLOO_PATHS_TO_BUFS[old_path] self.FLOO_PATHS_TO_BUFS[new] = buf_id self.FLOO_BUFS[buf_id]['path'] = new view = self.get_view(buf_id) if view: view.rename(new) else: os.rename(old, new)
def on_delete_buf(self, data): # TODO: somehow tell the user about this. maybe delete on disk too? del self.FLOO_BUFS[data['id']] path = utils.get_full_path(data['path']) if not G.DELETE_LOCAL_FILES: msg.log('Not deleting %s because delete_local_files is disabled' % path) return utils.rm(path) msg.warn('deleted %s because %s told me to.' % (path, data.get('username', 'the internet')))
def stomp_local(data): d = data['response'] for buf_id in bufs_to_get: if d: self.agent.send_get_buf(buf_id) else: buf = self.FLOO_BUFS[buf_id] # TODO: this is inefficient. we just read the file 20 lines ago self.create_buf(utils.get_full_path(buf['path'])) finish_room_info()
def __init__(self, emacs, buf, emacs_buf=None): self.buf = buf self._emacs_buf = emacs_buf self._emacs = emacs if emacs_buf is None: emacs.send({ 'name': 'create_view', 'full_path': utils.get_full_path(buf['path']), 'id': buf['id'], })
def get_view(self, buf_id): """Warning: side effects!""" view = self.views.get(buf_id) if view: return view buf = self.FLOO_BUFS[buf_id] full_path = utils.get_full_path(buf['path']) emacs_buf = self.emacs_bufs.get(full_path) if emacs_buf: view = self.create_view(buf, emacs_buf) return view
def on_highlight(self, data): super(Protocol, self).on_highlight(data) buf = self.FLOO_BUFS[data['id']] # TODO: save highlights for when user opens the buffer in emacs emacs.put('highlight', { 'id': buf['id'], 'full_path': utils.get_full_path(buf['path']), 'ranges': data['ranges'], 'user_id': data['user_id'], 'username': data.get('username', 'unknown user'), })
def _firmware_file_check(self, firmware_file, **kw): target_file = utils.get_full_path(self.cwd, firmware_file) self.firmware_file = target_file if (not os.access(target_file, os.F_OK) or not os.access(target_file, os.R_OK)): error = 'Cannot access %s. Check the management ' \ 'node and/or service nodes.' % target_file self.callback.error(error) raise Exception('Invalid firmware file %s' % target_file)
def get_view(self, buf_id): """Warning: side effects!""" # return self.agent.get_view(buf_id) view = self.views.get(buf_id) if view: return view buf = self.agent.bufs[buf_id] full_path = utils.get_full_path(buf['path']) emacs_buf = self.emacs_bufs.get(full_path) if emacs_buf: view = self.create_view(buf, emacs_buf) return view
def get_view(self, buf_id): """Warning: side effects!""" # return self.agent.get_view(buf_id) view = self.views.get(buf_id) if view: return view buf = self.agent.bufs[buf_id] full_path = utils.get_full_path(buf["path"]) emacs_buf = self.emacs_bufs.get(full_path) if emacs_buf: view = self.create_view(buf, emacs_buf) return view
def _on_buffer_list_change(self, req): added = req.get('added') or {} for path, text in added.items(): buf = self.get_buf_by_path(path) buf_id = buf and int(buf.get('id')) d = buf and 'buf' in buf and self.agent.on_load.get(buf_id) if d: self.emacs_bufs[path][0] = buf['buf'] else: self.emacs_bufs[path][0] = text if not buf: msg.debug('no buf for path %s' % path) if 'create_buf' in G.PERMS and utils.is_shared(path) and G.IGNORE and not G.IGNORE.is_ignored(path): self.agent._upload(path, text=text) elif path in self.emacs_bufs: del self.emacs_bufs[path] continue view = self.views.get(buf_id) if view is None: self.get_view(buf_id) elif view.is_loading(): view._emacs_buf = self.emacs_bufs[path] else: msg.debug('view for buf %s already exists. this is not good. we got out of sync' % buf['path']) if d: del self.agent.on_load[buf_id] for _, f in d.items(): f() deleted = req.get('deleted') or [] for path in deleted: if self.emacs_bufs.get(path) is None: msg.debug('emacs deleted %s but we already deleted it from emacs_bufs' % path) if path in self.emacs_bufs: del self.emacs_bufs[path] buf = self.get_buf_by_path(path) if buf and buf['id'] in self.views: del self.views[buf['id']] seen = set() current = req.get('current') or [] for path in current: if self.emacs_bufs.get(path) is None: msg.debug('We should have buffer %s in emacs_bufs but we don\'t' % path) else: seen.add(path) for buf_id, view in self.views.items(): if utils.get_full_path(view.buf['path']) not in seen: msg.debug('We should not have buffer %s in our views but we do.' % view.buf['path'])
def on_delete_buf(self, data): buf_id = int(data['id']) buf = self.FLOO_BUFS[buf_id] path = buf['path'] try: super(Protocol, self).on_delete_buf(data) except Exception as e: msg.debug('Unable to delete buf %s: %s' % (path, str(e))) else: emacs.put('delete_buf', { 'full_path': utils.get_full_path(path), 'path': path, 'username': data.get('username', ''), })
def on_room_info(self, data): # Success! Reset counter self.workspace_info = data self.perms = data['perms'] if 'patch' not in data['perms']: msg.log('We don\'t have patch permission. Setting buffers to read-only') utils.mkdir(G.PROJECT_PATH) floo_json = { 'url': utils.to_workspace_url({ 'host': self.agent.host, 'owner': self.agent.owner, 'port': self.agent.port, 'workspace': self.agent.workspace, 'secure': self.agent.secure, }) } with open(os.path.join(G.PROJECT_PATH, '.floo'), 'w') as floo_fd: floo_fd.write(json.dumps(floo_json, indent=4, sort_keys=True)) for buf_id, buf in data['bufs'].iteritems(): 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.FLOO_BUFS[buf_id] = buf self.FLOO_PATHS_TO_BUFS[buf_path] = buf_id try: buf_fd = open(buf_path, 'r') buf_buf = buf_fd.read().decode('utf-8') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() if md5 == buf['md5']: msg.debug('md5 sums match. not getting buffer') buf['buf'] = buf_buf else: raise Exception('different md5') except Exception: try: open(buf_path, "a").close() except Exception as e: msg.debug("couldn't touch file: %s becuase %s" % (buf_path, e)) self.agent.send_get_buf(buf_id) msg.debug(G.PROJECT_PATH) self.agent.on_auth()
def on_room_info(self, data): # Success! Reset counter self.workspace_info = data self.perms = data['perms'] if 'patch' not in data['perms']: msg.log('We don\'t have patch permission. Setting buffers to read-only') utils.mkdir(G.PROJECT_PATH) floo_json = { 'url': utils.to_workspace_url({ 'host': self.agent.host, 'owner': self.agent.owner, 'port': self.agent.port, 'workspace': self.agent.workspace, 'secure': self.agent.secure, }) } with open(os.path.join(G.PROJECT_PATH, '.floo'), 'w') as floo_fd: floo_fd.write(json.dumps(floo_json, indent=4, sort_keys=True)) for buf_id, buf in data['bufs'].iteritems(): 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.FLOO_BUFS[buf_id] = buf try: buf_fd = open(buf_path, 'r') buf_buf = buf_fd.read().decode('utf-8') md5 = hashlib.md5(buf_buf.encode('utf-8')).hexdigest() if md5 == buf['md5']: msg.debug('md5 sums match. not getting buffer') buf['buf'] = buf_buf else: raise Exception('different md5') except Exception: try: open(buf_path, "a").close() except Exception as e: msg.debug("couldn't touch file: %s becuase %s" % (buf_path, e)) self.agent.send_get_buf(buf_id) msg.debug(G.PROJECT_PATH) self.agent.on_auth()
def pre_get_firm_info(self, task, target_file=None, **kw): if not target_file: return target_file = utils.get_full_path(self.cwd, target_file) version = purpose = None with open(target_file, 'r') as fh: for line in fh: if 'version=' in line: version = line.split('=')[-1].strip() if 'purpose=' in line: purpose = line.split('=')[-1].strip() if version and purpose: break self.callback.info('TAR %s Firmware Product Version: %s' \ % (purpose, version))
def pre_get_firm_info(self, task, target_file=None, **kw): if not target_file: return target_file = utils.get_full_path(self.cwd, target_file) version = purpose = None with open(target_file, encoding="utf8", errors='ignore') as fh: for line in fh: if 'version=' in line: version = line.split('=')[-1].strip() if 'purpose=' in line: purpose = line.split('=')[-1].strip() if version and purpose: break self.callback.info('TAR %s Firmware Product Version: %s' \ % (purpose, version))
def apply_patches(self, buf, patches): cursor_offset = self.get_cursor_offset() msg.debug('cursor offset is %s bytes' % cursor_offset) self.emacs_buf = patches[0] emacs.put('edit', { 'id': self.buf['id'], 'full_path': utils.get_full_path(self.buf['path']), 'edits': patches[2], }) for patch in patches[2]: offset = patch[0] length = patch[1] patch_text = patch[2] if cursor_offset > offset: new_offset = len(patch_text) - length cursor_offset += new_offset self.set_cursor_position(cursor_offset)
def _on_buffer_list_change(self, req): added = req.get("added") or {} msg.log("buffer_list_change:\n%s" % req) for path, text in added.iteritems(): buf = self.get_buf_by_path(path) self.emacs_bufs[path][0] = text if not buf: msg.debug("no buf for path %s" % path) if "create_buf" in G.PERMS and not ignore.is_ignored(path): self.agent._upload(path, text=text) else: del self.emacs_bufs[path] continue view = self.views.get(buf["id"]) if view is None: self.get_view(buf["id"]) elif view.is_loading(): view._emacs_buf = self.emacs_bufs[path] else: msg.debug("view for buf %s already exists. this is not good. we got out of sync" % buf["path"]) deleted = req.get("deleted") or [] for path in deleted: if self.emacs_bufs.get(path) is None: msg.debug("emacs deleted %s but we already deleted it from emacs_bufs" % path) del self.emacs_bufs[path] buf = self.get_buf_by_path(path) if buf: del self.views[buf["id"]] seen = set() current = req.get("current") or [] for path in current: if self.emacs_bufs.get(path) is None: msg.debug("We should have buffer %s in emacs_bufs but we don't" % path) else: seen.add(path) for buf_id, view in self.views.iteritems(): if utils.get_full_path(view.buf["path"]) not in seen: msg.debug("We should not have buffer %s in our views but we do." % view.buf["path"])
def delete_buf(self, path, unlink=False): if not utils.is_shared(path): msg.error('Skipping deleting ', path, ' because it is not in shared path ', G.PROJECT_PATH, '.') return if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): # TODO: rexamine this assumption # Don't care about hidden stuff dirnames[:] = [d for d in dirnames if d[0] != '.'] for f in filenames: f_path = os.path.join(dirpath, f) if f[0] == '.': msg.log('Not deleting buf for hidden file ', f_path) else: self.delete_buf(f_path, unlink) return buf_to_delete = self.get_buf_by_path(path) if buf_to_delete is None: msg.error(path, ' is not in this workspace') if unlink: try: path = utils.get_full_path(path) msg.log('deleting ', utils.to_rel_path(path)) utils.rm(path) except Exception as e: msg.debug('Error deleting ', path, ': ', str_e(e)) return msg.log('deleting buffer ', utils.to_rel_path(path)) event = { 'name': 'delete_buf', 'id': buf_to_delete['id'], 'unlink': unlink, } def done(d): self._on_delete_buf(event) self.send(event, done)
def pre_flash_process(self, task, directory, no_host_reboot, **kw): if not os.path.exists(XCAT_LOG_RFLASH_DIR): os.makedirs(XCAT_LOG_RFLASH_DIR) directory = utils.get_full_path(self.cwd, directory) tmp_dict = {'BMC': [], 'Host': []} for filename in os.listdir(directory): if filename.endswith('.tar'): filename = os.path.join(directory, filename) try: version = self._get_firmware_version(filename) except Exception as e: continue self.firmware.update(version) for key, value in version.items(): tmp_dict[ value['purpose'] ].append(filename) self.firmware[key].update({'file': filename}) bmc_file_num = len(tmp_dict['BMC']) host_file_num = len(tmp_dict['Host']) error = None if not bmc_file_num: error = 'No BMC tar file found in %s' % directory elif not host_file_num: error = 'No HOST tar file found in %s' % directory elif bmc_file_num > 1: error = 'More than 1 BMC tar file %s found in %s' \ % (' '.join(tmp_dict['BMC']), directory) elif host_file_num > 1: error = 'More than 1 HOST tar file %s found in %s' \ % (' '.join(tmp_dict['Host']), directory) if error: self.callback.error(error) raise Exception('No or More tar file found') self.callback.info('Attempting to upload %s and %s, please wait..' \ % (tmp_dict['BMC'][0], tmp_dict['Host'][0])) self.nodes_num = len(self.inventory)
def pre_flash_process(self, task, directory, no_host_reboot, **kw): if not os.path.exists(XCAT_LOG_RFLASH_DIR): os.makedirs(XCAT_LOG_RFLASH_DIR) directory = utils.get_full_path(self.cwd, directory) tmp_dict = {'BMC': [], 'Host': []} for filename in os.listdir(directory): if filename.endswith('.tar'): filename = os.path.join(directory, filename) try: version = self._get_firmware_version(filename) except Exception as e: continue self.firmware.update(version) for key, value in version.items(): tmp_dict[value['purpose']].append(filename) self.firmware[key].update({'file': filename}) bmc_file_num = len(tmp_dict['BMC']) host_file_num = len(tmp_dict['Host']) error = None if not bmc_file_num: error = 'No BMC tar file found in %s' % directory elif not host_file_num: error = 'No HOST tar file found in %s' % directory elif bmc_file_num > 1: error = 'More than 1 BMC tar file %s found in %s' \ % (' '.join(tmp_dict['BMC']), directory) elif host_file_num > 1: error = 'More than 1 HOST tar file %s found in %s' \ % (' '.join(tmp_dict['Host']), directory) if error: self.callback.error(error) raise Exception('No or More tar file found') self.callback.info('Attempting to upload %s and %s, please wait..' \ % (tmp_dict['BMC'][0], tmp_dict['Host'][0])) self.nodes_num = len(self.inventory)
def delete_buf(self, path): """deletes a path""" if not path: return path = utils.get_full_path(path) if not utils.is_shared(path): msg.error('Skipping deleting %s because it is not in shared path %s.' % (path, G.PROJECT_PATH)) return if os.path.isdir(path): for dirpath, dirnames, filenames in os.walk(path): # Don't care about hidden stuff dirnames[:] = [d for d in dirnames if d[0] != '.'] for f in filenames: f_path = os.path.join(dirpath, f) if f[0] == '.': msg.log('Not deleting buf for hidden file %s' % f_path) else: self.delete_buf(f_path) return buf_to_delete = None rel_path = utils.to_rel_path(path) for buf_id, buf in self.FLOO_BUFS.items(): if rel_path == buf['path']: buf_to_delete = buf break if buf_to_delete is None: msg.error('%s is not in this workspace' % path) return msg.log('deleting buffer ', rel_path) event = { 'name': 'delete_buf', 'id': buf_to_delete['id'], } self.agent.put(event)
def on_emacs_buffer_list_change(self, req): added = req.get('added') or {} for path, text in added.iteritems(): buf = self.get_buf_by_path(path) self.emacs_bufs[path][0] = text if not buf: msg.debug('no buf for path %s' % path) self.create_buf(path, text=text) continue view = self.views.get(buf['id']) if view is None: self.get_view(buf['id']) elif view.is_loading(): view._emacs_buf = self.emacs_bufs[path] else: msg.debug('view for buf %s already exists. this is not good. we got out of sync' % buf['path']) deleted = req.get('deleted') or [] for path in deleted: if self.emacs_bufs.get(path) is None: msg.debug('emacs deleted %s but we already deleted it from emacs_bufs' % path) del self.emacs_bufs[path] buf = self.get_buf_by_path(path) if buf: del self.views[buf['id']] seen = set() current = req.get('current') or [] for path in current: if self.emacs_bufs.get(path) is None: msg.debug('We should have buffer %s in emacs_bufs but we don\'t' % path) else: seen.add(path) for buf_id, view in self.views.iteritems(): if utils.get_full_path(view.buf['path']) not in seen: msg.debug('We should not have buffer %s in our views but we do.' % view.buf['path'])
def create_view(buf): path = utils.get_full_path(buf['path']) view = G.WORKSPACE_WINDOW.open_file(path) if view: msg.debug('Created view', view.name() or view.file_name()) return view
def focus(self, offset): emacs.put('focus', { 'id': self.buf['id'], 'full_path': utils.get_full_path(self.buf['path']), 'offset': offset, })
def handler(self, name, data): if name == 'patch': Listener.apply_patch(data) elif name == 'get_buf': buf_id = data['id'] buf = listener.BUFS.get(buf_id) if not buf: return msg.warn( 'no buf found: %s. Hopefully you didn\'t need that' % data) timeout_id = buf.get('timeout_id') if timeout_id: utils.cancel_timeout(timeout_id) if data['encoding'] == 'base64': data['buf'] = base64.b64decode(data['buf']) # forced_patch doesn't exist in data, so this is equivalent to buf['forced_patch'] = False listener.BUFS[buf_id] = data view = listener.get_view(buf_id) if view: Listener.update_view(data, view) else: listener.save_buf(data) elif name == 'create_buf': if data['encoding'] == 'base64': data['buf'] = base64.b64decode(data['buf']) listener.BUFS[data['id']] = data listener.PATHS_TO_IDS[data['path']] = data['id'] listener.save_buf(data) cb = listener.CREATE_BUF_CBS.get(data['path']) if cb: del listener.CREATE_BUF_CBS[data['path']] try: cb(data['id']) except Exception as e: print(e) elif name == 'rename_buf': del listener.PATHS_TO_IDS[data['old_path']] listener.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) os.rename(old, new) view = listener.get_view(data['id']) if view: view.retarget(new) listener.BUFS[data['id']]['path'] = data['path'] elif name == 'delete_buf': path = utils.get_full_path(data['path']) listener.delete_buf(data['id']) 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)) elif name == 'room_info': Listener.reset() G.JOINED_WORKSPACE = True # Success! Reset counter self.reconnect_delay = self.INITIAL_RECONNECT_DELAY self.retries = self.MAX_RETRIES self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: msg.log('No patch permission. Setting buffers to read-only') if sublime.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?' ): self.put({'name': 'request_perms', 'perms': ['edit_room']}) project_json = {'folders': [{'path': G.PROJECT_PATH}]} utils.mkdir(G.PROJECT_PATH) with open(os.path.join(G.PROJECT_PATH, '.sublime-project'), 'wb') as project_fd: project_fd.write( json.dumps(project_json, indent=4, sort_keys=True).encode('utf-8')) floo_json = { 'url': utils.to_workspace_url({ 'host': self.host, 'owner': self.owner, 'port': self.port, 'workspace': self.workspace, 'secure': self.secure, }) } with open(os.path.join(G.PROJECT_PATH, '.floo'), 'w') as floo_fd: floo_fd.write(json.dumps(floo_json, indent=4, sort_keys=True)) 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) listener.BUFS[buf_id] = buf listener.PATHS_TO_IDS[buf['path']] = buf_id # TODO: stupidly inefficient view = listener.get_view(buf_id) if view and not view.is_loading( ) and buf['encoding'] == 'utf8': view_text = listener.get_text(view) 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.buffer_id()] = view_md5 elif self.get_bufs: Listener.get_buf(buf_id) #TODO: maybe send patch here? 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.get_bufs: Listener.get_buf(buf_id) except Exception as e: msg.debug('Error calculating md5:', e) Listener.get_buf(buf_id) msg.log('Successfully joined workspace %s/%s' % (self.owner, self.workspace)) 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) if self.on_room_info: self.on_room_info() self.on_room_info = None elif name == 'user_info': user_id = str(data['user_id']) user_info = data['user_info'] self.workspace_info['users'][user_id] = user_info if user_id == str(self.workspace_info['user_id']): G.PERMS = user_info['perms'] elif name == 'join': msg.log('%s joined the workspace' % data['username']) user_id = str(data['user_id']) self.workspace_info['users'][user_id] = data elif name == 'part': msg.log('%s left the workspace' % data['username']) user_id = str(data['user_id']) try: del self.workspace_info['users'][user_id] except Exception as e: print('Unable to delete user %s from user list' % (data)) region_key = 'floobits-highlight-%s' % (user_id) for window in sublime.windows(): for view in window.views(): view.erase_regions(region_key) elif name == 'highlight': region_key = 'floobits-highlight-%s' % (data['user_id']) Listener.highlight(data['id'], region_key, data['username'], data['ranges'], data.get('ping', False)) elif name == 'set_temp_data': hangout_data = data.get('data', {}) hangout = hangout_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) elif name == 'saved': try: buf = listener.BUFS[data['id']] username = self.get_username_by_id(data['user_id']) msg.log('%s saved buffer %s' % (username, buf['path'])) except Exception as e: msg.error(str(e)) elif name == 'request_perms': print(data) user_id = str(data.get('user_id')) username = self.get_username_by_id(user_id) if not username: return msg.debug( 'Unknown user for id %s. Not handling request_perms event.' % user_id) perm_mapping = { 'edit_room': 'edit', 'admin_room': 'admin', } perms = data.get('perms') perms_str = ''.join([perm_mapping.get(p) for p in perms]) prompt = 'User %s is requesting %s permission for this room.' % ( username, perms_str) message = data.get('message') if message: prompt += '\n\n%s says: %s' % (username, message) prompt += '\n\nDo you want to grant them permission?' confirm = bool(sublime.ok_cancel_dialog(prompt)) if confirm: action = 'add' else: action = 'reject' self.put({ 'name': 'perms', 'action': action, 'user_id': user_id, 'perms': perms }) elif name == 'perms': action = data['action'] user_id = str(data['user_id']) user = self.workspace_info['users'].get(user_id) if user is None: msg.log('No user for id %s. Not handling perms event' % user_id) return perms = set(user['perms']) if action == 'add': perms |= set(data['perms']) elif action == 'remove': perms -= set(data['perms']) else: return user['perms'] = list(perms) if user_id == self.workspace_info['user_id']: G.PERMS = perms elif name == 'msg': self.on_msg(data) else: msg.debug('unknown name!', name, 'data:', data)
def save_buf(self, buf): path = utils.get_full_path(buf['path']) utils.mkdir(os.path.split(path)[0]) with open(path, 'wb') as fd: fd.write(buf['buf'].encode('utf-8')) return path
def get_view_text_by_path(self, rel_path): full_path = utils.get_full_path(rel_path) emacs_buf = self.emacs_bufs.get(full_path) if emacs_buf: return emacs_buf[0]
def handler(self, name, data): if name == 'patch': Listener.apply_patch(data) elif name == 'get_buf': buf_id = data['id'] buf = listener.BUFS.get(buf_id) if not buf: return msg.warn('no buf found: %s. Hopefully you didn\'t need that' % data) timeout_id = buf.get('timeout_id') if timeout_id: utils.cancel_timeout(timeout_id) if data['encoding'] == 'base64': data['buf'] = base64.b64decode(data['buf']) # forced_patch doesn't exist in data, so this is equivalent to buf['forced_patch'] = False listener.BUFS[buf_id] = data view = listener.get_view(buf_id) if view: Listener.update_view(data, view) else: listener.save_buf(data) elif name == 'create_buf': if data['encoding'] == 'base64': data['buf'] = base64.b64decode(data['buf']) listener.BUFS[data['id']] = data listener.PATHS_TO_IDS[data['path']] = data['id'] listener.save_buf(data) cb = listener.CREATE_BUF_CBS.get(data['path']) if cb: del listener.CREATE_BUF_CBS[data['path']] try: cb(data['id']) except Exception as e: print(e) elif name == 'rename_buf': del listener.PATHS_TO_IDS[data['old_path']] listener.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) os.rename(old, new) view = listener.get_view(data['id']) if view: view.retarget(new) listener.BUFS[data['id']]['path'] = data['path'] elif name == 'delete_buf': path = utils.get_full_path(data['path']) listener.delete_buf(data['id']) 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)) elif name == 'room_info': Listener.reset() G.JOINED_WORKSPACE = True # Success! Reset counter self.reconnect_delay = self.INITIAL_RECONNECT_DELAY self.retries = self.MAX_RETRIES self.workspace_info = data G.PERMS = data['perms'] if 'patch' not in data['perms']: msg.log('No patch permission. Setting buffers to read-only') if sublime.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?'): self.put({'name': 'request_perms', 'perms': ['edit_room']}) project_json = { 'folders': [ {'path': G.PROJECT_PATH} ] } utils.mkdir(G.PROJECT_PATH) with open(os.path.join(G.PROJECT_PATH, '.sublime-project'), 'wb') as project_fd: project_fd.write(json.dumps(project_json, indent=4, sort_keys=True).encode('utf-8')) floo_json = { 'url': utils.to_workspace_url({ 'host': self.host, 'owner': self.owner, 'port': self.port, 'workspace': self.workspace, 'secure': self.secure, }) } with open(os.path.join(G.PROJECT_PATH, '.floo'), 'w') as floo_fd: floo_fd.write(json.dumps(floo_json, indent=4, sort_keys=True)) 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) listener.BUFS[buf_id] = buf listener.PATHS_TO_IDS[buf['path']] = buf_id # TODO: stupidly inefficient view = listener.get_view(buf_id) if view and not view.is_loading() and buf['encoding'] == 'utf8': view_text = listener.get_text(view) 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.buffer_id()] = view_md5 elif self.get_bufs: Listener.get_buf(buf_id) #TODO: maybe send patch here? 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.get_bufs: Listener.get_buf(buf_id) except Exception as e: msg.debug('Error calculating md5:', e) Listener.get_buf(buf_id) msg.log('Successfully joined workspace %s/%s' % (self.owner, self.workspace)) 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) if self.on_room_info: self.on_room_info() self.on_room_info = None elif name == 'user_info': user_id = str(data['user_id']) user_info = data['user_info'] self.workspace_info['users'][user_id] = user_info if user_id == str(self.workspace_info['user_id']): G.PERMS = user_info['perms'] elif name == 'join': msg.log('%s joined the workspace' % data['username']) user_id = str(data['user_id']) self.workspace_info['users'][user_id] = data elif name == 'part': msg.log('%s left the workspace' % data['username']) user_id = str(data['user_id']) try: del self.workspace_info['users'][user_id] except Exception as e: print('Unable to delete user %s from user list' % (data)) region_key = 'floobits-highlight-%s' % (user_id) for window in sublime.windows(): for view in window.views(): view.erase_regions(region_key) elif name == 'highlight': region_key = 'floobits-highlight-%s' % (data['user_id']) Listener.highlight(data['id'], region_key, data['username'], data['ranges'], data.get('ping', False)) elif name == 'set_temp_data': hangout_data = data.get('data', {}) hangout = hangout_data.get('hangout', {}) hangout_url = hangout.get('url') if hangout_url: self.prompt_join_hangout(hangout_url) elif name == 'saved': try: buf = listener.BUFS[data['id']] username = self.get_username_by_id(data['user_id']) msg.log('%s saved buffer %s' % (username, buf['path'])) except Exception as e: msg.error(str(e)) elif name == 'request_perms': print(data) user_id = str(data.get('user_id')) username = self.get_username_by_id(user_id) if not username: return msg.debug('Unknown user for id %s. Not handling request_perms event.' % user_id) perm_mapping = { 'edit_room': 'edit', 'admin_room': 'admin', } perms = data.get('perms') perms_str = ''.join([perm_mapping.get(p) for p in perms]) prompt = 'User %s is requesting %s permission for this room.' % (username, perms_str) message = data.get('message') if message: prompt += '\n\n%s says: %s' % (username, message) prompt += '\n\nDo you want to grant them permission?' confirm = bool(sublime.ok_cancel_dialog(prompt)) if confirm: action = 'add' else: action = 'reject' self.put({ 'name': 'perms', 'action': action, 'user_id': user_id, 'perms': perms }) elif name == 'perms': action = data['action'] user_id = str(data['user_id']) user = self.workspace_info['users'].get(user_id) if user is None: msg.log('No user for id %s. Not handling perms event' % user_id) return perms = set(user['perms']) if action == 'add': perms |= set(data['perms']) elif action == 'remove': perms -= set(data['perms']) else: return user['perms'] = list(perms) if user_id == self.workspace_info['user_id']: G.PERMS = perms elif name == 'msg': self.on_msg(data) else: msg.debug('unknown name!', name, 'data:', data)
def full_path(self): return utils.get_full_path(self.buf['path'])