def run(self, workspace=None): if workspace is None: workspace = 'https://%s/' % G.DEFAULT_HOST for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') utils.parse_url(wurl) # TODO: check if workspace actually exists workspace = wurl break except Exception: pass self.window.show_input_panel('Workspace URL:', workspace, self.on_input, None, None)
def run(self, workspace=None): if workspace is None: workspace = 'https://%s/' % G.DEFAULT_HOST for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') utils.parse_url(wurl) # TODO: check if workspace actually exists workspace = wurl break except Exception: pass self.window.show_input_panel('Workspace URL:', workspace, self.on_input, None, None)
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info["url"]) except Exception: parsed_url = None if ( parsed_url and parsed_url["host"] == host and parsed_url["workspace"] == name and parsed_url["owner"] == owner ): self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()["workspaces"][owner][name]["path"] except Exception: d = "" if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return d = d or os.path.join(G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, "Save workspace files to: ", d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, "%s is not a directory. Create it? " % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
def join_workspace_by_url(self, context, workspace_url, possible_dirs=None): try: d = utils.parse_url(workspace_url) except Exception as e: return editor.error_message(str_e(e)) return self.join_workspace(context, d['host'], d['workspace'], d['owner'], possible_dirs)
def join_workspace_by_url(self, context, workspace_url, possible_dirs=None): try: d = utils.parse_url(workspace_url) except Exception as e: return editor.error_message(str_e(e)) return self.join_workspace(context, d['host'], d['workspace'], d['owner'], possible_dirs)
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info['url']) except Exception: parsed_url = None if parsed_url and parsed_url['host'] == host and parsed_url[ 'workspace'] == name and parsed_url['owner'] == owner: self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()['workspaces'][owner][name]['path'] except Exception: d = '' if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return # TODO: make per-host settings fully general host_share_dir = G.AUTH.get(host, {}).get('share_dir') d = d or os.path.join(host_share_dir or G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, 'Save workspace files to: ', d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, '%s is not a directory. Create it? ' % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
def join_workspace(self, context, host, name, owner, possible_dirs=None): utils.reload_settings() # legacy urls in emacs... if owner and owner[:2] == "r/": owner = owner[2:] if not utils.can_auth(): success = yield self.create_or_link_account, context, host, False if not success: return utils.reload_settings() possible_dirs = possible_dirs or [] for d in possible_dirs: info = utils.read_floo_file(d) if not info: continue try: parsed_url = utils.parse_url(info['url']) except Exception: parsed_url = None if parsed_url and parsed_url['host'] == host and parsed_url['workspace'] == name and parsed_url['owner'] == owner: self.remote_connect(context, host, owner, name, d) return try: d = utils.get_persistent_data()['workspaces'][owner][name]['path'] except Exception: d = '' if d and os.path.isdir(d): self.remote_connect(context, host, owner, name, d) return # TODO: make per-host settings fully general host_share_dir = G.AUTH.get(host, {}).get('share_dir') d = d or os.path.join(host_share_dir or G.SHARE_DIR or G.BASE_DIR, owner, name) join_action = utils.JOIN_ACTION.PROMPT while True: d = yield self.user_dir, context, 'Save workspace files to: ', d if not d: return d = os.path.realpath(os.path.expanduser(d)) if not os.path.isdir(d): y_or_n = yield self.user_y_or_n, context, '%s is not a directory. Create it? ' % d, "Create Directory" if not y_or_n: return utils.mkdir(d) if not os.path.isdir(d): msg.error("Couldn't create directory", d) continue join_action = utils.JOIN_ACTION.DOWNLOAD if os.path.isdir(d): self.remote_connect(context, host, owner, name, d, join_action) return
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 join_workspace(workspace_url, on_auth=None): global agent msg.debug("workspace url is %s" % workspace_url) try: result = utils.parse_url(workspace_url) except Exception as e: return msg.error(str(e)) G.PROJECT_PATH = os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) utils.mkdir(os.path.dirname(G.PROJECT_PATH)) d = '' # TODO: really bad prompt here prompt = "Give me a directory to sync data to (or just press enter): " if not os.path.isdir(G.PROJECT_PATH): while True: d = vim_input(prompt, d, "dir") if d == '': utils.mkdir(G.PROJECT_PATH) break d = os.path.realpath(os.path.expanduser(d)) if os.path.isfile(d): prompt = '%s is not a directory. Enter an existing path (or press enter): ' % d continue if not os.path.isdir(d): try: utils.mkdir(d) except Exception as e: prompt = "Couldn't make dir: %s because %s " % (d, str(e)) continue try: os.symlink(d, G.PROJECT_PATH) break except Exception as e: return msg.error("Couldn't create symlink from %s to %s: %s" % (d, G.PROJECT_PATH, str(e))) G.PROJECT_PATH = os.path.realpath(G.PROJECT_PATH + os.sep) vim.command('cd %s' % G.PROJECT_PATH) msg.debug("joining workspace %s" % workspace_url) stop_everything() try: start_event_loop() agent = AgentConnection(on_auth=on_auth, Protocol=Protocol, **result) # owner and workspace name are slugfields so this should be safe agent.connect() except Exception as e: msg.error(str(e)) tb = traceback.format_exc() msg.debug(tb) stop_everything()
def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e))
def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e))
def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(lambda: G.AGENT.upload(dir_to_share, on_room_info_msg)) return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return
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 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 find_workspace(workspace_url): try: api.get_workspace_by_url(workspace_url) except HTTPError: try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return False on_room_info_waterfall.add(on_room_info_msg) on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, dir_to_share) return True
def find_workspace(workspace_url): try: api.get_workspace_by_url(workspace_url) except HTTPError: try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return False on_room_info_waterfall.add(on_room_info_msg) on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, dir_to_share) return True
def find_workspace(workspace_url): if ssl is False: # No ssl module (broken Sublime Text). Just behave as if the workspace exists. return True try: api.get_workspace_by_url(workspace_url) except HTTPError: try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return False on_room_info_waterfall.add(on_room_info_msg) on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, dir_to_share) return True
def share_dir(dir_to_share): dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) dir_to_share = os.path.abspath(dir_to_share) workspace_name = os.path.basename(dir_to_share) floo_workspace_dir = os.path.join(G.COLAB_DIR, G.USERNAME, workspace_name) if os.path.isfile(dir_to_share): return msg.error('give me a directory please') if not os.path.isdir(dir_to_share): return msg.error('The directory %s doesn\'t appear to exist' % dir_to_share) floo_file = os.path.join(dir_to_share, '.floo') # look for the .floo file for hints about previous behavior info = {} try: floo_info = open(floo_file, 'rb').read().decode('utf-8') info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.warn("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'] floo_workspace_dir = os.path.join(G.COLAB_DIR, result['owner'], result['workspace']) # they have previously joined the workspace if os.path.realpath(floo_workspace_dir) == os.path.realpath( dir_to_share): # it could have been deleted, try to recreate it if possible # TODO: org or something here? if result['owner'] == G.USERNAME: try: api.create_workspace({'name': workspace_name}) msg.debug('Created workspace %s' % workspace_url) except Exception as e: msg.debug('Tried to create workspace' + str(e)) # they wanted to share teh dir, so always share it return join_workspace( workspace_url, lambda x: agent.protocol.create_buf(dir_to_share, force=True)) # link to what they want to share try: utils.mkdir(os.path.dirname(floo_workspace_dir)) os.symlink(dir_to_share, floo_workspace_dir) except OSError as e: if e.errno != 17: raise except Exception as e: return msg.error("Couldn't create symlink from %s to %s: %s" % (dir_to_share, floo_workspace_dir, str(e))) # make & join workspace create_workspace(workspace_name, floo_workspace_dir, dir_to_share)
def run(self, workspace_url, agent_conn_kwargs=None, upload=None): agent_conn_kwargs = agent_conn_kwargs or {} self.upload = upload def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path(G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': floorc = utils.load_floorc_json() subl = floorc.get('SUBLIME_EXECUTABLE') if not subl: settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('''Can't find your Sublime Text executable at %s. Please add "sublime_executable": "/path/to/subl" to your ~/.floorc.json and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(str_e(e)) def wait_empty_window(i): if i > 10: print('Too many failures trying to find an empty window. Using active window.') return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) 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)) @utils.inlined_callbacks def run_agent(owner, workspace, host, port, secure, upload): if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None try: auth = G.AUTH.get(host) if not auth: success = yield link_account, host if not success: return auth = G.AUTH.get(host) conn = SublimeConnection(owner, workspace, auth, upload) reactor.connect(conn, host, port, secure) except Exception as e: msg.error(str_e(e)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str_e(e)) utils.reload_settings() if not utils.can_auth(): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception: msg.log('%s/%s not in persistent.json' % (result['owner'], result['workspace'])) G.PROJECT_PATH = '' msg.log('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = None for w in sublime.windows(): if default_dir: break for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') if wurl == workspace_url: # TODO: check if workspace actually exists default_dir = d break except Exception: pass default_dir = default_dir or os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(upload=upload, **result))
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 run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if f == G.PROJECT_PATH: workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def truncate_chat_view(chat_view, cb): if chat_view: chat_view.set_read_only(False) chat_view.run_command('floo_view_replace_region', {'r': [0, chat_view.size()], 'data': ''}) chat_view.set_read_only(True) cb() def create_chat_view(cb): with open(os.path.join(G.BASE_DIR, 'msgs.floobits.log'), 'a') as msgs_fd: msgs_fd.write('') get_or_create_chat(lambda chat_view: truncate_chat_view(chat_view, cb)) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('Can\'t find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) # Maybe no msg view yet :( print('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() print('poll:', poll_result) set_workspace_window(lambda: create_chat_view(cb)) def open_workspace_window3(cb): G.WORKSPACE_WINDOW = get_workspace_window() if not G.WORKSPACE_WINDOW: G.WORKSPACE_WINDOW = sublime.active_window() msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) create_chat_view(cb) def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') G.AGENT.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: msg.debug("agent_conn_kwargs: %s" % str(agent_conn_kwargs)) G.AGENT = AgentConnection(owner=owner, workspace=workspace, host=host, port=port, secure=secure, on_room_info=on_room_info_waterfall.call, **agent_conn_kwargs) on_room_info_waterfall = utils.Waterfall() Listener.reset() G.AGENT.connect() except Exception as e: print(e) tb = traceback.format_exc() print(tb) 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 add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
def on_input(self, dir_to_share): file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(utils.unfuck_path(dir_to_share)) workspace_name = os.path.basename(dir_to_share) workspace_url = None print(G.COLAB_DIR, G.USERNAME, workspace_name) def find_workspace(workspace_url): try: api.get_workspace_by_url(workspace_url) except HTTPError: try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return False on_room_info_waterfall.add(on_room_info_msg) on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, dir_to_share) return True if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) else: try: utils.mkdir(dir_to_share) except Exception: return sublime.error_message( '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: print('Couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') try: result = utils.parse_url(workspace_url) except Exception: workspace_url = None if workspace_url and find_workspace(workspace_url): add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, dir_to_share) return self.window.run_command( 'floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': { 'get_bufs': False } }) for owner, workspaces in utils.get_persistent_data( )['workspaces'].items(): for name, workspace in workspaces.items(): if workspace['path'] == dir_to_share: workspace_url = workspace['url'] if find_workspace(workspace_url): return self.window.run_command( 'floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': { 'get_bufs': False } }) # make & join workspace on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, file_to_share or dir_to_share) def on_done(owner): self.window.run_command( 'floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'api_args': self.api_args, 'owner': owner[0], }) orgs = api.get_orgs_can_admin() orgs = json.loads(orgs.read().decode('utf-8')) if len(orgs) == 0: return on_done([G.USERNAME]) orgs = [[org['name'], 'Create workspace under %s' % org['name']] for org in orgs] orgs.insert(0, [G.USERNAME, 'Create workspace under %s' % G.USERNAME]) self.window.show_quick_panel( orgs, lambda index: index < 0 or on_done(orgs[index]))
def on_input(self, dir_to_share): file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(utils.unfuck_path(dir_to_share)) workspace_name = os.path.basename(dir_to_share) workspace_url = None print(G.COLAB_DIR, G.USERNAME, workspace_name) def find_workspace(workspace_url): try: api.get_workspace_by_url(workspace_url) except HTTPError: try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return False on_room_info_waterfall.add(on_room_info_msg) on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, dir_to_share) return True if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) else: try: utils.mkdir(dir_to_share) except Exception: return sublime.error_message('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: print('Couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') try: result = utils.parse_url(workspace_url) except Exception: workspace_url = None if workspace_url and find_workspace(workspace_url): add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, dir_to_share) return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': {'get_bufs': False}}) for owner, workspaces in utils.get_persistent_data()['workspaces'].items(): for name, workspace in workspaces.items(): if workspace['path'] == dir_to_share: workspace_url = workspace['url'] if find_workspace(workspace_url): return self.window.run_command('floobits_join_workspace', { 'workspace_url': workspace_url, 'agent_conn_kwargs': {'get_bufs': False}}) # make & join workspace on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(Listener.create_buf, file_to_share or dir_to_share) def on_done(owner): self.window.run_command('floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'api_args': self.api_args, 'owner': owner[0], }) orgs = api.get_orgs_can_admin() orgs = json.loads(orgs.read().decode('utf-8')) if len(orgs) == 0: return on_done([G.USERNAME]) orgs = [[org['name'], 'Create workspace under %s' % org['name']] for org in orgs] orgs.insert(0, [G.USERNAME, 'Create workspace under %s' % G.USERNAME]) self.window.show_quick_panel(orgs, lambda index: index < 0 or on_done(orgs[index]))
def run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path(G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get('sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl') if not os.path.exists(subl): return sublime.error_message('''Can't find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data({'folders': [{'path': G.PROJECT_PATH}]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(e) def wait_empty_window(i): if i > 10: print('Too many failures trying to find an empty window. Using active window.') return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) 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 run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: conn = SublimeConnection(owner, workspace, agent_conn_kwargs.get('get_bufs', True)) reactor.connect(conn, host, port, secure) conn.once('room_info', on_room_info_waterfall.call) on_room_info_waterfall = utils.Waterfall() except Exception as e: print(e) tb = traceback.format_exc() print(tb) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath(os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
def on_input(self, dir_to_share): file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(utils.unfuck_path(dir_to_share)) workspace_name = os.path.basename(dir_to_share) workspace_url = None # TODO: use prejoin_workspace instead def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e)) 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 if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: sublime.error_message( 'The directory %s doesn\'t exist and I can\'t create it.' % dir_to_share) return floo_file = os.path.join(dir_to_share, '.floo') info = {} try: floo_info = open(floo_file, 'r').read() info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.error('Couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') try: utils.parse_url(workspace_url) except Exception: workspace_url = None if workspace_url and join_workspace(workspace_url): return for owner, workspaces in utils.get_persistent_data( )['workspaces'].items(): for name, workspace in workspaces.items(): if workspace['path'] == dir_to_share: workspace_url = workspace['url'] if join_workspace(workspace_url): return auth = yield editor.select_auth, self.window, G.AUTH if not auth: return username = auth.get('username') host = auth['host'] def on_done(owner): msg.log('Colab dir: %s, Username: %s, Workspace: %s/%s' % (G.COLAB_DIR, username, owner[0], workspace_name)) self.window.run_command( 'floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'upload': file_to_share or dir_to_share, 'api_args': self.api_args, 'owner': owner[0], 'host': host, }) try: r = api.get_orgs_can_admin(host) except IOError as e: sublime.error_message('Error getting org list: %s' % str_e(e)) return if r.code >= 400 or len(r.body) == 0: on_done([username]) return orgs = [[org['name'], 'Create workspace owned by %s' % org['name']] for org in r.body] orgs.insert(0, [username, 'Create workspace owned by %s' % username]) self.window.show_quick_panel( orgs, lambda index: index < 0 or on_done(orgs[index]))
def run(self, workspace_url, agent_conn_kwargs=None): agent_conn_kwargs = agent_conn_kwargs or {} def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if f == G.PROJECT_PATH: workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def truncate_chat_view(chat_view, cb): if chat_view: chat_view.set_read_only(False) chat_view.run_command('floo_view_replace_region', { 'r': [0, chat_view.size()], 'data': '' }) chat_view.set_read_only(True) cb() def create_chat_view(cb): with open(os.path.join(G.BASE_DIR, 'msgs.floobits.log'), 'a') as msgs_fd: msgs_fd.write('') get_or_create_chat( lambda chat_view: truncate_chat_view(chat_view, cb)) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': # TODO: totally explodes if you install ST2 somewhere else settings = sublime.load_settings('Floobits.sublime-settings') subl = settings.get( 'sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl' ) if not os.path.exists(subl): return sublime.error_message( 'Can\'t find your Sublime Text executable at %s. Please add "sublime_executable /path/to/subl" to your ~/.floorc and restart Sublime Text' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) # Maybe no msg view yet :( print('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() print('poll:', poll_result) set_workspace_window(lambda: create_chat_view(cb)) def open_workspace_window3(cb): G.WORKSPACE_WINDOW = get_workspace_window() if not G.WORKSPACE_WINDOW: G.WORKSPACE_WINDOW = sublime.active_window() msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data( {'folders': [{ 'path': G.PROJECT_PATH }]}) create_chat_view(cb) def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def run_agent(owner, workspace, host, port, secure): global on_room_info_waterfall if G.AGENT: msg.debug('Stopping agent.') G.AGENT.stop() G.AGENT = None on_room_info_waterfall.add(update_recent_workspaces, {'url': workspace_url}) try: msg.debug("agent_conn_kwargs: %s" % str(agent_conn_kwargs)) G.AGENT = AgentConnection( owner=owner, workspace=workspace, host=host, port=port, secure=secure, on_room_info=on_room_info_waterfall.call, **agent_conn_kwargs) on_room_info_waterfall = utils.Waterfall() Listener.reset() G.AGENT.connect() except Exception as e: print(e) tb = traceback.format_exc() print(tb) 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 add_workspace_to_persistent_json(result['owner'], result['workspace'], workspace_url, d) open_workspace_window(lambda: run_agent(**result)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str(e)) utils.reload_settings() if not (G.USERNAME and G.SECRET): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][ result['workspace']]['path'] except Exception as e: G.PROJECT_PATH = '' print('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(**result))
def on_input(self, dir_to_share): file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(utils.unfuck_path(dir_to_share)) workspace_name = os.path.basename(dir_to_share) workspace_url = None print(G.COLAB_DIR, G.USERNAME, workspace_name) def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(lambda: G.AGENT.upload(dir_to_share, on_room_info_msg)) return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(unicode(e)) return def join_workspace(workspace_url): try: w = find_workspace(workspace_url) except Exception as e: sublime.error_message('Error: %s' % str(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', []) 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(w.body['owner'], w.body['name'], 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, 'agent_conn_kwargs': {'get_bufs': False}}) return True if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: return sublime.error_message('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, 'r').read() info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.error('Couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') try: utils.parse_url(workspace_url) except Exception: workspace_url = None if workspace_url and join_workspace(workspace_url): return for owner, workspaces in utils.get_persistent_data()['workspaces'].items(): for name, workspace in workspaces.items(): if workspace['path'] == dir_to_share: workspace_url = workspace['url'] if join_workspace(workspace_url): return # make & join workspace on_room_info_waterfall.add(ignore.create_flooignore, dir_to_share) on_room_info_waterfall.add(lambda: G.AGENT.upload(file_to_share or dir_to_share, on_room_info_msg)) def on_done(owner): self.window.run_command('floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'api_args': self.api_args, 'owner': owner[0], }) try: r = api.get_orgs_can_admin() except IOError as e: return sublime.error_message('Error getting org list: %s' % str(e)) if r.code >= 400 or len(r.body) == 0: return on_done([G.USERNAME]) orgs = [[org['name'], 'Create workspace under %s' % org['name']] for org in r.body] orgs.insert(0, [G.USERNAME, 'Create workspace under %s' % G.USERNAME]) self.window.show_quick_panel(orgs, lambda index: index < 0 or on_done(orgs[index]))
def main(): if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() default_auth = G.AUTH.get(G.DEFAULT_HOST, {}) parser = optparse.OptionParser(usage=usage) parser.add_option("-u", "--username", dest="username", default=default_auth.get('username'), help="Your Floobits username") parser.add_option("-s", "--secret", dest="secret", default=default_auth.get('secret'), help="Your Floobits secret (api key)") parser.add_option("-c", "--create", dest="create", default=False, action="store_true", help="The terminal name to create") parser.add_option("--host", dest="host", default=G.DEFAULT_HOST, help="The host to connect to. Deprecated. Use --url instead.") parser.add_option("-p", "--port", dest="port", default=G.DEFAULT_PORT, help="The port to connect to. Deprecated. Use --url instead.") parser.add_option("-w", "--workspace", dest="workspace", help="The workspace name. --owner is required with this option. Deprecated. Use --url instead.") parser.add_option("-o", "--owner", dest="owner", help="The workspace owner. --workspace is required with this option. Deprecated. Use --url instead.") parser.add_option("-l", "--list", dest="list", default=False, action="store_true", help="List all terminals in the workspace") parser.add_option("--unsafe", dest="safe", default=True, action="store_false", help="Less safe terminal. This allows other users to send enter in your terminal.") parser.add_option("--no-ssl", dest="use_ssl", default=True, action="store_false", help="Do not use this option unless you know what you are doing!") parser.add_option("--url", dest="workspace_url", default=None, help="The URL of the workspace to connect to.") parser.add_option("--resize", dest="resize", default=False, action="store_true", help="Resize your terminal to the host terminal size.") parser.add_option("-P", "--preserve-ps1", dest="set_prompt", default=True, action="store_false", help="Don't change $PS1 (bash/zsh prompt)") parser.add_option("-v", "--version", dest="version", default=False, action="store_true", help="Print version") options, args = parser.parse_args() if options.version: print('flootty %s' % version.FLOOTTY_VERSION) return default_term_name = "" if options.create: default_term_name = "ftty" term_name = args and args[0] or default_term_name if options.workspace and options.owner and options.workspace_url: # TODO: confusing parser.error("You can either specify --workspace and --owner, or --url, but not both.") if bool(options.workspace) != bool(options.owner): parser.error("You must specify a workspace and owner or neither.") for opt in ['owner', 'workspace']: if getattr(options, opt): print('%s is deprecated. Please use --url instead.' % opt) if not options.workspace or not options.owner: floo = {} if options.workspace_url: floo = utils.parse_url(options.workspace_url) else: for floo_path in walk_up(os.path.realpath('.')): try: floo = json.loads(open(os.path.join(floo_path, '.floo'), 'rb').read().decode('utf-8')) floo = utils.parse_url(floo['url']) except Exception: pass else: break options.host = floo.get('host') options.workspace = floo.get('workspace') options.owner = floo.get('owner') options.use_ssl = floo.get('secure') if not options.port: options.port = floo.get('port') if not options.host: options.host = floo.get('host') if options.host is None: options.host = G.DEFAULT_HOST if options.host != G.DEFAULT_HOST and options.secret == default_auth.get('secret'): auth = G.AUTH.get(options.host) if not auth: return die("Please add credentials for %s in ~/.floorc.json" % options.host) options.username = auth.get('username') options.secret = auth.get('secret') if not options.workspace or not options.owner: try: now_editing = get_now_editing_workspaces() except Exception as e: print(str_e(e)) else: if len(now_editing.body) == 1: options.workspace = now_editing.body[0]['name'] options.owner = now_editing.body[0]['owner'] # TODO: list possible workspaces to join if > 1 is active if options.list: if len(term_name) != 0: die("I don't understand why you gave me a positional argument.") for opt in ['workspace', 'owner', 'username', 'secret']: if not getattr(options, opt): parser.error('%s not given' % opt) color_reset = '\033[0m' if options.safe: green = '\033[92m' print('%sTerminal is safe. Other users will not be able to send [enter]%s' % (green, color_reset)) else: yellorange = '\033[93m' print('%sTerminal is unsafe. Other users will be able to send [enter]. Be wary!%s' % (yellorange, color_reset)) f = Flootty(options, term_name) G.AGENT = f atexit.register(f.cleanup) f.connect_to_internet() f.select()
def main(): utils.reload_settings() default_auth = G.AUTH.get(G.DEFAULT_HOST, {}) parser = optparse.OptionParser(usage=usage) parser.add_option("-u", "--username", dest="username", default=default_auth.get('username'), help="Your Floobits username") parser.add_option("-s", "--secret", dest="secret", default=default_auth.get('secret'), help="Your Floobits secret (api key)") parser.add_option("-c", "--create", dest="create", default=False, action="store_true", help="The terminal name to create") parser.add_option( "--host", dest="host", default=G.DEFAULT_HOST, help="The host to connect to. Deprecated. Use --url instead.") parser.add_option( "-p", "--port", dest="port", default=G.DEFAULT_PORT, help="The port to connect to. Deprecated. Use --url instead.") parser.add_option( "-w", "--workspace", dest="workspace", help= "The workspace name. --owner is required with this option. Deprecated. Use --url instead." ) parser.add_option( "-o", "--owner", dest="owner", help= "The workspace owner. --workspace is required with this option. Deprecated. Use --url instead." ) parser.add_option("-l", "--list", dest="list", default=False, action="store_true", help="List all terminals in the workspace") parser.add_option( "--unsafe", dest="safe", default=True, action="store_false", help= "Less safe terminal. This allows other users to send enter in your terminal." ) parser.add_option( "--no-ssl", dest="use_ssl", default=True, action="store_false", help="Do not use this option unless you know what you are doing!") parser.add_option("--url", dest="workspace_url", default=None, help="The URL of the workspace to connect to.") parser.add_option("--resize", dest="resize", default=False, action="store_true", help="Resize your terminal to the host terminal size.") parser.add_option( "--shell", dest="shell", default=os.environ.get("SHELL", None), help="The shell you would like to use with flootty. Defaults to $SHELL." ) parser.add_option("-P", "--preserve-ps1", dest="set_prompt", default=True, action="store_false", help="Don't change $PS1 (bash/zsh prompt)") parser.add_option("-v", "--version", dest="version", default=False, action="store_true", help="Print version") options, args = parser.parse_args() if options.version: print('flootty %s' % version.FLOOTTY_VERSION) return default_term_name = "" if options.create: default_term_name = "ftty" term_name = args and args[0] or default_term_name if options.workspace and options.owner and options.workspace_url: # TODO: confusing parser.error( "You can either specify --workspace and --owner, or --url, but not both." ) if bool(options.workspace) != bool(options.owner): parser.error("You must specify a workspace and owner or neither.") for opt in ['owner', 'workspace']: if getattr(options, opt): print('%s is deprecated. Please use --url instead.' % opt) if not options.workspace or not options.owner: floo = {} if options.workspace_url: floo = utils.parse_url(options.workspace_url) else: for floo_path in walk_up(os.path.realpath('.')): try: floo = json.loads( open(os.path.join(floo_path, '.floo'), 'rb').read().decode('utf-8')) floo = utils.parse_url(floo['url']) except Exception: pass else: break options.host = floo.get('host') options.workspace = floo.get('workspace') options.owner = floo.get('owner') options.use_ssl = floo.get('secure') if not options.port: options.port = floo.get('port') if not options.host: options.host = floo.get('host') if options.host is None: options.host = G.DEFAULT_HOST if options.host != G.DEFAULT_HOST and options.secret == default_auth.get( 'secret'): auth = G.AUTH.get(options.host) if not auth: return die("Please add credentials for %s in ~/.floorc.json" % options.host) options.username = auth.get('username') options.secret = auth.get('secret') if not options.workspace or not options.owner: try: now_editing = get_now_editing_workspaces() except Exception as e: print(str_e(e)) else: if len(now_editing.body) == 1: options.workspace = now_editing.body[0]['name'] options.owner = now_editing.body[0]['owner'] # TODO: list possible workspaces to join if > 1 is active if options.list: if len(term_name) != 0: die("I don't understand why you gave me a positional argument.") for opt in ['username', 'secret']: if not getattr(options, opt): parser.error( '%s not given. Please use --%s or add credentials to ~/.floorc.json' % (opt, opt)) for opt in ['workspace', 'owner']: if not getattr(options, opt): parser.error('%s not given' % opt) color_reset = '\033[0m' if not G.FLOOTTY_SAFE: options.safe = G.FLOOTTY_SAFE if options.safe: green = '\033[92m' print( '%sTerminal is safe. Other users will not be able to send [enter]%s' % (green, color_reset)) else: yellorange = '\033[93m' print( '%sTerminal is unsafe. Other users will be able to send [enter]. Be wary!%s' % (yellorange, color_reset)) f = Flootty(options, term_name) G.AGENT = f atexit.register(f.cleanup) f.connect_to_internet() f.select()
def on_input(self, dir_to_share): file_to_share = None dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(utils.unfuck_path(dir_to_share)) workspace_name = os.path.basename(dir_to_share) workspace_url = None # TODO: use prejoin_workspace instead def find_workspace(workspace_url): r = api.get_workspace_by_url(workspace_url) if r.code < 400: return r try: result = utils.parse_url(workspace_url) d = utils.get_persistent_data() del d['workspaces'][result['owner']][result['name']] utils.update_persistent_data(d) except Exception as e: msg.debug(str_e(e)) 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 if os.path.isfile(dir_to_share): file_to_share = dir_to_share dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: sublime.error_message('The directory %s doesn\'t exist and I can\'t create it.' % dir_to_share) return floo_file = os.path.join(dir_to_share, '.floo') info = {} try: floo_info = open(floo_file, 'r').read() info = json.loads(floo_info) except (IOError, OSError): pass except Exception: msg.error('Couldn\'t read the floo_info file: %s' % floo_file) workspace_url = info.get('url') try: utils.parse_url(workspace_url) except Exception: workspace_url = None if workspace_url and join_workspace(workspace_url): return for owner, workspaces in utils.get_persistent_data()['workspaces'].items(): for name, workspace in workspaces.items(): if workspace['path'] == dir_to_share: workspace_url = workspace['url'] if join_workspace(workspace_url): return auth = yield editor.select_auth, self.window, G.AUTH if not auth: return username = auth.get('username') host = auth['host'] def on_done(owner): msg.log('Colab dir: %s, Username: %s, Workspace: %s/%s' % (G.COLAB_DIR, username, owner[0], workspace_name)) self.window.run_command('floobits_create_workspace', { 'workspace_name': workspace_name, 'dir_to_share': dir_to_share, 'upload': file_to_share or dir_to_share, 'api_args': self.api_args, 'owner': owner[0], 'host': host, }) try: r = api.get_orgs_can_admin(host) except IOError as e: sublime.error_message('Error getting org list: %s' % str_e(e)) return if r.code >= 400 or len(r.body) == 0: on_done([username]) return orgs = [[org['name'], 'Create workspace owned by %s' % org['name']] for org in r.body] orgs.insert(0, [username, 'Create workspace owned by %s' % username]) self.window.show_quick_panel(orgs, lambda index: index < 0 or on_done(orgs[index]))
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 run(self, workspace_url, agent_conn_kwargs=None, upload=None): agent_conn_kwargs = agent_conn_kwargs or {} self.upload = upload def get_workspace_window(): workspace_window = None for w in sublime.windows(): for f in w.folders(): if utils.unfuck_path(f) == utils.unfuck_path( G.PROJECT_PATH): workspace_window = w break return workspace_window def set_workspace_window(cb): workspace_window = get_workspace_window() if workspace_window is None: return utils.set_timeout(set_workspace_window, 50, cb) G.WORKSPACE_WINDOW = workspace_window cb() def open_workspace_window(cb): if PY2: open_workspace_window2(cb) else: open_workspace_window3(cb) def open_workspace_window2(cb): if sublime.platform() == 'linux': subl = open('/proc/self/cmdline').read().split(chr(0))[0] elif sublime.platform() == 'osx': floorc = utils.load_floorc_json() subl = floorc.get('SUBLIME_EXECUTABLE') if not subl: settings = sublime.load_settings( 'Floobits.sublime-settings') subl = settings.get( 'sublime_executable', '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl' ) if not os.path.exists(subl): return sublime.error_message( '''Can't find your Sublime Text executable at %s. Please add "sublime_executable": "/path/to/subl" to your ~/.floorc.json and restart Sublime Text''' % subl) elif sublime.platform() == 'windows': subl = sys.executable else: raise Exception('WHAT PLATFORM ARE WE ON?!?!?') command = [subl] if get_workspace_window() is None: command.append('--new-window') command.append('--add') command.append(G.PROJECT_PATH) msg.debug('command:', command) p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) poll_result = p.poll() msg.debug('poll:', poll_result) set_workspace_window(cb) def open_workspace_window3(cb): def finish(w): G.WORKSPACE_WINDOW = w msg.debug('Setting project data. Path: %s' % G.PROJECT_PATH) G.WORKSPACE_WINDOW.set_project_data( {'folders': [{ 'path': G.PROJECT_PATH }]}) cb() def get_empty_window(): for w in sublime.windows(): project_data = w.project_data() try: folders = project_data.get('folders', []) if len(folders) == 0 or not folders[0].get('path'): # no project data. co-opt this window return w except Exception as e: print(str_e(e)) def wait_empty_window(i): if i > 10: print( 'Too many failures trying to find an empty window. Using active window.' ) return finish(sublime.active_window()) w = get_empty_window() if w: return finish(w) return utils.set_timeout(wait_empty_window, 50, i + 1) w = get_workspace_window() or get_empty_window() if w: return finish(w) sublime.run_command('new_window') wait_empty_window(0) 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)) @utils.inlined_callbacks def run_agent(owner, workspace, host, port, secure, upload): if G.AGENT: msg.debug('Stopping agent.') reactor.stop() G.AGENT = None try: auth = G.AUTH.get(host) if not auth: success = yield link_account, host if not success: return auth = G.AUTH.get(host) conn = SublimeConnection(owner, workspace, auth, upload) reactor.connect(conn, host, port, secure) except Exception as e: msg.error(str_e(e)) try: result = utils.parse_url(workspace_url) except Exception as e: return sublime.error_message(str_e(e)) utils.reload_settings() if not utils.can_auth(): return create_or_link_account() d = utils.get_persistent_data() try: G.PROJECT_PATH = d['workspaces'][result['owner']][ result['workspace']]['path'] except Exception: msg.log('%s/%s not in persistent.json' % (result['owner'], result['workspace'])) G.PROJECT_PATH = '' msg.log('Project path is %s' % G.PROJECT_PATH) if not os.path.isdir(G.PROJECT_PATH): default_dir = None for w in sublime.windows(): if default_dir: break for d in self.window.folders(): floo_file = os.path.join(d, '.floo') try: floo_info = open(floo_file, 'r').read() wurl = json.loads(floo_info).get('url') if wurl == workspace_url: # TODO: check if workspace actually exists default_dir = d break except Exception: pass default_dir = default_dir or os.path.realpath( os.path.join(G.COLAB_DIR, result['owner'], result['workspace'])) return self.window.show_input_panel('Save workspace in directory:', default_dir, make_dir, None, None) open_workspace_window(lambda: run_agent(upload=upload, **result))