def join_workspace(workspace_url): try: w = find_workspace(workspace_url) except Exception as e: sublime.error_message('Error: %s' % str_e(e)) return False if not w: return False msg.debug('workspace: %s', json.dumps(w.body)) # if self.api_args: anon_perms = w.body.get('perms', {}).get('AnonymousUser', []) new_anon_perms = self.api_args.get('perms').get( 'AnonymousUser', []) # TODO: warn user about making a private workspace public if set(anon_perms) != set(new_anon_perms): msg.debug(str(anon_perms), str(new_anon_perms)) w.body['perms']['AnonymousUser'] = new_anon_perms response = api.update_workspace(workspace_url, w.body) msg.debug(str(response.body)) utils.add_workspace_to_persistent_json(w.body['owner'], w.body['name'], workspace_url, dir_to_share) self.window.run_command('floobits_join_workspace', {'workspace_url': workspace_url}) return True
def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog( '%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel( '%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message( 'Could not create directory %s: %s' % (d, str_e(e))) G.PROJECT_PATH = d if self.upload: result['upload'] = d else: result['upload'] = "" utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result))
def on_input(self, workspace_name, dir_to_share=None): if dir_to_share: self.dir_to_share = dir_to_share if workspace_name == '': return self.run(dir_to_share=self.dir_to_share) try: self.api_args['name'] = workspace_name self.api_args['owner'] = self.owner msg.debug(str(self.api_args)) r = api.create_workspace(self.host, self.api_args) except Exception as e: msg.error('Unable to create workspace: %s' % str_e(e)) return sublime.error_message('Unable to create workspace: %s' % str_e(e)) workspace_url = 'https://%s/%s/%s' % (self.host, self.owner, workspace_name) msg.log('Created workspace %s' % workspace_url) if r.code < 400: utils.add_workspace_to_persistent_json(self.owner, workspace_name, workspace_url, self.dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'upload': dir_to_share }) msg.error('Unable to create workspace: %s' % r.body) if r.code not in [400, 402, 409]: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('Unable to create workspace: %s' % r.body) kwargs = { 'dir_to_share': self.dir_to_share, 'workspace_name': workspace_name, 'api_args': self.api_args, 'owner': self.owner, 'upload': self.upload, 'host': self.host, } if r.code == 400: kwargs['workspace_name'] = re.sub('[^A-Za-z0-9_\-\.]', '-', workspace_name) kwargs['prompt'] = 'Invalid name. Workspace names must match the regex [A-Za-z0-9_\-\.]. Choose another name:' elif r.code == 402: try: r.body = r.body['detail'] except Exception: pass if sublime.ok_cancel_dialog('%s' % r.body, 'Open billing settings'): webbrowser.open('https://%s/%s/settings#billing' % (self.host, self.owner)) return else: kwargs['prompt'] = 'Workspace %s/%s already exists. Choose another name:' % (self.owner, workspace_name) return self.window.run_command('floobits_create_workspace', kwargs)
def floobits_join_workspace(workspace_url, d='', upload_path=None): editor.line_endings = _get_line_endings() msg.debug('workspace url is %s' % workspace_url) try: result = utils.parse_url(workspace_url) except Exception as e: return msg.error(str(e)) if d: utils.mkdir(d) else: try: d = utils.get_persistent_data()['workspaces'][result['owner']][result['workspace']]['path'] except Exception: d = os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) prompt = 'Save workspace files to: ' if not os.path.isdir(d): while True: d = vim_input(prompt, d, 'dir') if d == '': continue d = os.path.realpath(os.path.expanduser(d)) if os.path.isfile(d): prompt = '%s is not a directory. Enter an existing path or a path I can create: ' % d continue if not os.path.isdir(d): try: utils.mkdir(d) except Exception as e: prompt = 'Couldn\'t make dir %s: %s ' % (d, str(e)) continue break d = os.path.realpath(os.path.abspath(d) + os.sep) try: utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) except Exception as e: return msg.error('Error adding workspace to persistent.json: %s' % str(e)) G.PROJECT_PATH = d vim.command('cd %s' % G.PROJECT_PATH) msg.debug('Joining workspace %s' % workspace_url) floobits_stop_everything() try: conn = VimHandler(result['owner'], result['workspace']) if upload_path: conn.once('room_info', lambda: G.AGENT.upload(upload_path)) reactor.connect(conn, result['host'], result['port'], result['secure']) except Exception as e: msg.error(str(e)) tb = traceback.format_exc() msg.debug(tb) if not G.TIMERS: start_event_loop()
def on_input(self, workspace_name, dir_to_share=None): if dir_to_share: self.dir_to_share = dir_to_share if workspace_name == '': return self.run(dir_to_share=self.dir_to_share) try: self.api_args['name'] = workspace_name self.api_args['owner'] = self.owner msg.debug(str(self.api_args)) r = api.create_workspace(self.api_args) except Exception as e: msg.error('Unable to create workspace: %s' % unicode(e)) return sublime.error_message('Unable to create workspace: %s' % unicode(e)) workspace_url = 'https://%s/%s/%s/' % (G.DEFAULT_HOST, self.owner, workspace_name) msg.log('Created workspace %s' % workspace_url) if r.code < 400: utils.add_workspace_to_persistent_json(self.owner, workspace_name, workspace_url, self.dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': { 'get_bufs': False } }) msg.error('Unable to create workspace: %s' % r.body) if r.code not in [400, 402, 409]: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('Unable to create workspace: %s' % r.body) kwargs = { 'dir_to_share': self.dir_to_share, 'workspace_name': workspace_name, 'api_args': self.api_args, 'owner': self.owner, } if r.code == 400: kwargs['workspace_name'] = re.sub('[^A-Za-z0-9_\-\.]', '-', workspace_name) kwargs['prompt'] = 'Invalid name. Workspace names must match the regex [A-Za-z0-9_\-\.]. Choose another name:' elif r.code == 402: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('%s' % r.body) else: kwargs['prompt'] = 'Workspace %s/%s already exists. Choose another name:' % (self.owner, workspace_name) return self.window.run_command('floobits_create_workspace', kwargs)
def remote_connect(self, context, host, owner, workspace, d, join_action=utils.JOIN_ACTION.PROMPT): G.PROJECT_PATH = os.path.realpath(d) try: utils.mkdir(os.path.dirname(G.PROJECT_PATH)) except Exception as e: msg.error("Couldn't create directory", G.PROJECT_PATH, str_e(e)) return auth = G.AUTH.get(host) if not auth: success = yield self.link_account, context, host if not success: return auth = G.AUTH.get(host) if not auth: msg.error("Something went really wrong.") return try: res = api.get_workspace(host, owner, workspace) if res.code == 404: msg.error("The workspace https://%s/%s/%s does not exist" % (host, owner, workspace)) return except Exception as e: message = 'Error getting workspace https://%s/%s/%s: %s' % ( host, owner, workspace, str_e(e)) msg.error(message) editor.error_message(message) return if self.agent: try: self.agent.stop() except Exception: pass G.WORKSPACE_WINDOW = yield self.get_a_window, d self.agent = self._make_agent(context, owner, workspace, auth, join_action) self.emit("agent", self.agent) reactor.reactor.connect(self.agent, host, G.DEFAULT_PORT, True) url = self.agent.workspace_url utils.add_workspace_to_persistent_json(owner, workspace, url, d) utils.update_recent_workspaces(url)
def prejoin_workspace(self, workspace_url, dir_to_share, api_args): try: result = utils.parse_url(workspace_url) except Exception as e: msg.error(str_e(e)) return False host = result.get('host') if not api.get_basic_auth(host): raise ValueError( 'No auth credentials for %s. Please add a username and secret for %s in your ~/.floorc.json' % (host, host)) try: w = api.get_workspace_by_url(workspace_url) except Exception as e: editor.error_message('Error opening url %s: %s' % (workspace_url, str_e(e))) return False if w.code >= 400: try: d = utils.get_persistent_data() try: del d['workspaces'][result['owner']][result['name']] except Exception: pass try: del d['recent_workspaces'][workspace_url] except Exception: pass utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e)) return False msg.debug('workspace: ', json.dumps(w.body)) anon_perms = w.body.get('perms', {}).get('AnonymousUser', []) msg.debug('api args: ', api_args) new_anon_perms = api_args.get('perms', {}).get('AnonymousUser', []) # TODO: prompt/alert user if going from private to public if set(anon_perms) != set(new_anon_perms): msg.debug(str(anon_perms), str(new_anon_perms)) w.body['perms']['AnonymousUser'] = new_anon_perms response = api.update_workspace(workspace_url, w.body) msg.debug(str(response.body)) utils.add_workspace_to_persistent_json(w.body['owner'], w.body['name'], workspace_url, dir_to_share) return result
def make_dir(d): d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): make_dir = sublime.ok_cancel_dialog('%s is not a directory. Create it?' % d) if not make_dir: return self.window.show_input_panel('%s is not a directory. Enter an existing path:' % d, d, None, None, None) try: utils.mkdir(d) except Exception as e: return sublime.error_message('Could not create directory %s: %s' % (d, str(e))) G.PROJECT_PATH = d utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result))
def prejoin_workspace(self, workspace_url, dir_to_share, api_args): try: result = utils.parse_url(workspace_url) except Exception as e: msg.error(str_e(e)) return False host = result.get("host") if not api.get_basic_auth(host): raise ValueError( "No auth credentials for %s. Please add a username and secret for %s in your ~/.floorc.json" % (host, host) ) try: w = api.get_workspace_by_url(workspace_url) except Exception as e: editor.error_message("Error opening url %s: %s" % (workspace_url, str_e(e))) return False if w.code >= 400: try: d = utils.get_persistent_data() try: del d["workspaces"][result["owner"]][result["name"]] except Exception: pass try: del d["recent_workspaces"][workspace_url] except Exception: pass utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e)) return False msg.debug("workspace: ", json.dumps(w.body)) anon_perms = w.body.get("perms", {}).get("AnonymousUser", []) msg.debug("api args: ", api_args) new_anon_perms = api_args.get("perms", {}).get("AnonymousUser", []) # TODO: prompt/alert user if going from private to public if set(anon_perms) != set(new_anon_perms): msg.debug(str(anon_perms), str(new_anon_perms)) w.body["perms"]["AnonymousUser"] = new_anon_perms response = api.update_workspace(workspace_url, w.body) msg.debug(str(response.body)) utils.add_workspace_to_persistent_json(w.body["owner"], w.body["name"], workspace_url, dir_to_share) return result
def remote_connect(self, context, host, owner, workspace, d, join_action=utils.JOIN_ACTION.PROMPT): G.PROJECT_PATH = os.path.realpath(d) try: utils.mkdir(os.path.dirname(G.PROJECT_PATH)) except Exception as e: msg.error("Couldn't create directory", G.PROJECT_PATH, str_e(e)) return auth = G.AUTH.get(host) if not auth: success = yield self.link_account, context, host if not success: return auth = G.AUTH.get(host) if not auth: msg.error("Something went really wrong.") return try: res = api.get_workspace(host, owner, workspace) if res.code == 404: msg.error("The workspace https://%s/%s/%s does not exist" % (host, owner, workspace)) return except Exception as e: message = 'Error getting workspace https://%s/%s/%s: %s' % (host, owner, workspace, str_e(e)) msg.error(message) editor.error_message(message) return if self.agent: try: self.agent.stop() except Exception: pass G.WORKSPACE_WINDOW = yield self.get_a_window, d self.agent = self._make_agent(context, owner, workspace, auth, join_action) self.emit("agent", self.agent) reactor.reactor.connect(self.agent, host, G.DEFAULT_PORT, True) url = self.agent.workspace_url utils.add_workspace_to_persistent_json(owner, workspace, url, d) utils.update_recent_workspaces(url)
def join_workspace(workspace_url): try: w = find_workspace(workspace_url) except Exception as e: sublime.error_message('Error: %s' % str_e(e)) return False if not w: return False msg.debug('workspace: %s', json.dumps(w.body)) # if self.api_args: anon_perms = w.body.get('perms', {}).get('AnonymousUser', []) new_anon_perms = self.api_args.get('perms').get('AnonymousUser', []) # TODO: warn user about making a private workspace public if set(anon_perms) != set(new_anon_perms): msg.debug(str(anon_perms), str(new_anon_perms)) w.body['perms']['AnonymousUser'] = new_anon_perms response = api.update_workspace(workspace_url, w.body) msg.debug(str(response.body)) utils.add_workspace_to_persistent_json(w.body['owner'], w.body['name'], workspace_url, dir_to_share) self.window.run_command('floobits_join_workspace', {'workspace_url': workspace_url}) return True
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) ig = ignore.create_ignore_tree(G.PROJECT_PATH) G.IGNORE = ig for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id changed_bufs, missing_bufs, new_files = self._scan_dir( data['bufs'], ig, read_only) 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) # Don't auto-upload again on reconnect self.action = utils.JOIN_ACTION.PROMPT 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) if data.get('repo_info'): msg.log('Repo info:', data.get('repo_info')) # TODO: check local repo info and update remote (or prompt?) else: repo_info = repo.get_info(self.workspace_url, G.PROJECT_PATH) if repo_info and 'repo' in G.PERMS: self.send({ 'name': 'repo', 'action': 'set', 'data': repo_info, }) 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 _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 on_input(self, workspace_name, dir_to_share=None): if dir_to_share: self.dir_to_share = dir_to_share if workspace_name == '': return self.run(dir_to_share=self.dir_to_share) try: self.api_args['name'] = workspace_name self.api_args['owner'] = self.owner msg.debug(str(self.api_args)) r = api.create_workspace(self.host, self.api_args) except Exception as e: msg.error('Unable to create workspace: %s' % str_e(e)) return sublime.error_message('Unable to create workspace: %s' % str_e(e)) workspace_url = 'https://%s/%s/%s' % (self.host, self.owner, workspace_name) msg.log('Created workspace %s' % workspace_url) if r.code < 400: utils.add_workspace_to_persistent_json(self.owner, workspace_name, workspace_url, self.dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'upload': dir_to_share }) msg.error('Unable to create workspace: %s' % r.body) if r.code not in [400, 402, 409]: try: r.body = r.body['detail'] except Exception: pass return sublime.error_message('Unable to create workspace: %s' % r.body) kwargs = { 'dir_to_share': self.dir_to_share, 'workspace_name': workspace_name, 'api_args': self.api_args, 'owner': self.owner, 'upload': self.upload, 'host': self.host, } if r.code == 400: kwargs['workspace_name'] = re.sub('[^A-Za-z0-9_\-\.]', '-', workspace_name) kwargs[ 'prompt'] = 'Invalid name. Workspace names must match the regex [A-Za-z0-9_\-\.]. Choose another name:' elif r.code == 402: try: r.body = r.body['detail'] except Exception: pass if sublime.ok_cancel_dialog('%s' % r.body, 'Open billing settings'): webbrowser.open('https://%s/%s/settings#billing' % (self.host, self.owner)) return else: kwargs[ 'prompt'] = 'Workspace %s/%s already exists. Choose another name:' % ( self.owner, workspace_name) return self.window.run_command('floobits_create_workspace', kwargs)
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")
def share_dir(self, dir_to_share, perms=None): dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) workspace_name = os.path.basename(dir_to_share) G.PROJECT_PATH = os.path.realpath(dir_to_share) msg.debug('%s %s %s' % (G.USERNAME, workspace_name, G.PROJECT_PATH)) if os.path.isfile(dir_to_share): return msg.error('%s is a file. Give me a directory please.' % dir_to_share) try: utils.mkdir(dir_to_share) except Exception: return msg.error("The directory %s doesn't exist and I can't make it." % dir_to_share) floo_file = os.path.join(dir_to_share, '.floo') info = {} try: floo_info = open(floo_file, 'rb').read().decode('utf-8') info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.debug("Couldn't read the floo_info file: %s" % floo_file) workspace_url = info.get('url') if workspace_url: try: result = utils.parse_url(workspace_url) except Exception as e: msg.error(str(e)) else: workspace_name = result['workspace'] try: # TODO: blocking. beachballs sublime 2 if API is super slow api.get_workspace_by_url(workspace_url) except HTTPError: workspace_url = None workspace_name = os.path.basename(dir_to_share) else: utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, dir_to_share) workspace_url = utils.get_workspace_by_path(dir_to_share) or workspace_url if workspace_url: try: api.get_workspace_by_url(workspace_url) except HTTPError: pass else: return self.remote_connect(workspace_url, lambda this: this.protocol.create_buf(dir_to_share)) def on_done(data, choices=None): self.create_workspace({}, workspace_name, dir_to_share, owner=data.get('response'), perms=perms) orgs = api.get_orgs_can_admin() orgs = json.loads(orgs.read().decode('utf-8')) if len(orgs) == 0: return on_done({'response': G.USERNAME}) i = 0 choices = [] choices.append([G.USERNAME, i]) for o in orgs: i += 1 choices.append([o['name'], i]) self.get_input('Create workspace for [press tab for completion]: ', '', on_done, choices=choices)
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.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) ig = ignore.create_ignore_tree(G.PROJECT_PATH) G.IGNORE = ig for buf_id, buf in data['bufs'].items(): buf_id = int(buf_id) # json keys must be strings self.bufs[buf_id] = buf self.paths_to_ids[buf['path']] = buf_id changed_bufs, missing_bufs, new_files = self._scan_dir(data['bufs'], ig, read_only) 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) # Don't auto-upload again on reconnect self.action = utils.JOIN_ACTION.PROMPT 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) if data.get('repo_info'): msg.log('Repo info:', data.get('repo_info')) # TODO: check local repo info and update remote (or prompt?) else: repo_info = repo.get_info(self.workspace_url, G.PROJECT_PATH) if repo_info and 'repo' in G.PERMS: self.send({ 'name': 'repo', 'action': 'set', 'data': repo_info, }) 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 _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 floobits_join_workspace(workspace_url, d='', upload_path=None): editor.line_endings = _get_line_endings() msg.debug('workspace url is %s' % workspace_url) try: result = utils.parse_url(workspace_url) except Exception as e: return msg.error(str(e)) if d: utils.mkdir(d) else: try: d = utils.get_persistent_data()['workspaces'][result['owner']][ result['workspace']]['path'] except Exception: d = os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) prompt = 'Save workspace files to: ' if not os.path.isdir(d): while True: d = vim_input(prompt, d, 'dir') if d == '': continue d = os.path.realpath(os.path.expanduser(d)) if os.path.isfile(d): prompt = '%s is not a directory. Enter an existing path or a path I can create: ' % d continue if not os.path.isdir(d): try: utils.mkdir(d) except Exception as e: prompt = 'Couldn\'t make dir %s: %s ' % (d, str(e)) continue break d = os.path.realpath(os.path.abspath(d) + os.sep) try: utils.add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) except Exception as e: return msg.error('Error adding workspace to persistent.json: %s' % str(e)) G.PROJECT_PATH = d vim.command('cd %s' % G.PROJECT_PATH) msg.debug('Joining workspace %s' % workspace_url) floobits_stop_everything() try: conn = VimHandler(result['owner'], result['workspace']) if upload_path: conn.once('room_info', lambda: G.AGENT.upload(upload_path)) reactor.connect(conn, result['host'], result['port'], result['secure']) except Exception as e: msg.error(str(e)) tb = traceback.format_exc() msg.debug(tb) if not G.TIMERS: start_event_loop()