def plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath(os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) # Sublime plugin API stuff can't be called right off the bat if not utils.can_auth(): utils.set_timeout(create_or_link_account, 1) utils.set_timeout(global_tick, 1)
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 plugin_loaded(): global called_plugin_loaded if called_plugin_loaded: return called_plugin_loaded = True print('Floobits: Called plugin_loaded.') if not os.path.exists(G.FLOORC_JSON_PATH): migrations.migrate_floorc() utils.reload_settings() # TODO: one day this can be removed (once all our users have updated) old_colab_dir = os.path.realpath( os.path.expanduser(os.path.join('~', '.floobits'))) if os.path.isdir(old_colab_dir) and not os.path.exists(G.BASE_DIR): print('Renaming %s to %s' % (old_colab_dir, G.BASE_DIR)) os.rename(old_colab_dir, G.BASE_DIR) os.symlink(G.BASE_DIR, old_colab_dir) try: utils.normalize_persistent_data() except Exception as e: print('Floobits: Error normalizing persistent data:', str_e(e)) # Keep on truckin' I guess d = utils.get_persistent_data() G.AUTO_GENERATED_ACCOUNT = d.get('auto_generated_account', False) # Sublime plugin API stuff can't be called right off the bat if not utils.can_auth(): utils.set_timeout(create_or_link_account, 1) utils.set_timeout(global_tick, 1)
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_check_credentials(): msg.debug('Print checking credentials.') if utils.can_auth(): return if not utils.has_browser(): msg.log('You need a Floobits account to use the Floobits plugin. Go to https://floobits.com to sign up.') return yield VUI.create_or_link_account, None, G.DEFAULT_HOST, False
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 run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): self.api_args = api_args utils.reload_settings() if not utils.can_auth(): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message('Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: folders = self.window.folders() if folders: dir_to_share = folders[0] else: dir_to_share = os.path.expanduser(os.path.join('~', 'share_me')) self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def run(self, dir_to_share=None, paths=None, current_file=False, api_args=None): self.api_args = api_args utils.reload_settings() if not utils.can_auth(): return create_or_link_account() if paths: if len(paths) != 1: return sublime.error_message( 'Only one folder at a time, please. :(') return self.on_input(paths[0]) if dir_to_share is None: folders = self.window.folders() if folders: dir_to_share = folders[0] else: dir_to_share = os.path.expanduser(os.path.join( '~', 'share_me')) self.window.show_input_panel('Directory to share:', dir_to_share, self.on_input, None, None)
def share_dir(self, context, dir_to_share, api_args): utils.reload_settings() if not utils.can_auth(): success = yield self.create_or_link_account, context, G.DEFAULT_HOST, False if not success: return utils.reload_settings() dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) workspace_name = os.path.basename(dir_to_share) msg.debug('', workspace_name, dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: msg.error("The directory", dir_to_share, "doesn't exist and I can't create it.") return info = utils.read_floo_file(dir_to_share) def prejoin(workspace_url): try: return self.prejoin_workspace(workspace_url, dir_to_share, api_args) except ValueError: pass workspace_url = info.get('url') if workspace_url: parsed_url = prejoin(workspace_url) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return parsed_url = utils.get_workspace_by_path(dir_to_share, prejoin) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return host = yield self._get_host, context if not host: return try: r = api.get_orgs_can_admin(host) except IOError as e: editor.error_message('Error getting org list: %s' % str_e(e)) return choices = [G.AUTH[host]['username']] if r.code >= 400: editor.error_message('Error getting org list: %s' % r.body) elif r.body: choices += [org['name'] for org in r.body] if len(choices) == 1: owner = choices[0] else: little = ['Create workspace owned by %s' % s for s in choices] ( owner, index ) = yield self.user_select, context, 'Create workspace owned by', choices, little if not owner: return self.create_workspace(context, host, owner, workspace_name, api_args, dir_to_share)
def share_dir(self, context, dir_to_share, api_args): utils.reload_settings() if not utils.can_auth(): success = yield self.create_or_link_account, context, G.DEFAULT_HOST, False if not success: return utils.reload_settings() dir_to_share = os.path.expanduser(dir_to_share) dir_to_share = os.path.realpath(dir_to_share) dir_to_share = utils.unfuck_path(dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) workspace_name = os.path.basename(dir_to_share) msg.debug('', workspace_name, dir_to_share) if os.path.isfile(dir_to_share): dir_to_share = os.path.dirname(dir_to_share) try: utils.mkdir(dir_to_share) except Exception: msg.error("The directory", dir_to_share, "doesn't exist and I can't create it.") return info = utils.read_floo_file(dir_to_share) def prejoin(workspace_url): try: return self.prejoin_workspace(workspace_url, dir_to_share, api_args) except ValueError: pass workspace_url = info.get('url') if workspace_url: parsed_url = prejoin(workspace_url) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return parsed_url = utils.get_workspace_by_path(dir_to_share, prejoin) if parsed_url: self.remote_connect(context, parsed_url['host'], parsed_url['owner'], parsed_url['workspace'], dir_to_share) return host = yield self._get_host, context if not host: return try: r = api.get_orgs_can_admin(host) except IOError as e: editor.error_message('Error getting org list: %s' % str_e(e)) return choices = [G.AUTH[host]['username']] if r.code >= 400: editor.error_message('Error getting org list: %s' % r.body) elif r.body: choices += [org['name'] for org in r.body] if len(choices) == 1: owner = choices[0] else: little = ['Create workspace owned by %s' % s for s in choices] (owner, index) = yield self.user_select, context, 'Create workspace owned by', choices, little if not owner: return self.create_workspace(context, host, owner, workspace_name, api_args, dir_to_share)
def is_enabled(self): return utils.can_auth()
def is_enabled(self, *args, **kwargs): return utils.can_auth()
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 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))