def test_build_go_missing(self): ensure_not_ui_thread() shell, _ = shellenv.get_env() search_path = path.expanduser('~') with GolangBuildMock(shell=shell, env={'PATH': search_path}): file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go') def _run_build(view, result_queue): notify_user( 'Press the "Open Documentation" button when prompted about go not being found in the PATH' ) view.window().run_command('golang_build') open_file(file_path, VIEW_SETTINGS, _run_build) time.sleep(0.5) self.assertTrue( confirm_user( 'Were you prompted that go could not be found in the PATH?' )) self.assertTrue( confirm_user( 'When you pressed "Open Documentation", was it opened in your browser?' ))
def run_os_command(cmd): shell = os.name == 'nt' try: options = { 'shell': shell, 'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT, 'universal_newlines': False, } if not shell: options['env'] = {} options['env'].update({'PATH': shellenv.get_env()[1]['PATH']}) proc = subprocess.Popen(cmd, **options) output = proc.communicate()[0].decode() debug('run_os_command: output', output) return output except Exception as e: debug('run_os_command: exception', str(e)) return "ERROR: run_os_command: {0}".format(e)
def check_and_install_dependencies(): """ The function is dosen't check whether npm/node is installed or not. """ # check if already installed if os.path.exists(PLUGIN_PACKAGE_LOCK): return # merge /usr/local/{bin,sbin} cmd = ['npm', 'install', '-s'] exec_options = { 'quiet': True, 'working_dir': PLUGIN_PATH } if os.name != 'nt': # update paths for searching executables exec_options['cmd'] = cmd exec_options['env'] = {} exec_options['env'].update({'PATH': shellenv.get_env()[1]['PATH']}) else: exec_options['shell_cmd'] = ' '.join(cmd) info('Running `npm install` to install plugin dependencies') sublime.active_window().run_command('exec', exec_options)
def get_env(self, shell): shell, env = shellenv.get_env(shell) self.assertEqual(str_cls, type(shell)) if sys.platform == 'win32': home_var = 'HOMEPATH' else: home_var = 'HOME' home_val = os.environ[home_var] if sys.version_info < (3, ): home_val = home_val.decode('mbcs' if sys.platform == 'win32' else 'utf-8') self.assertEqual(home_val, env[home_var]) if sys.platform == 'win32': user_var = 'USERNAME' else: user_var = 'USER' user_val = os.environ[user_var] if sys.version_info < (3, ): user_val = user_val.decode(locale.getpreferredencoding() if sys. platform == 'win32' else 'utf-8') self.assertEqual(user_val, env[user_var]) self.assertTrue(len(env) > 5) for key in env: self.assertEqual(str_cls, type(key)) self.assertEqual(str_cls, type(env[key]))
def test_build_no_gopath(self): ensure_not_ui_thread() shell, env = shellenv.get_env() if 'GOPATH' in env: del env['GOPATH'] with GolangBuildMock(shell=shell, env=env): file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go') def _run_build(view, result_queue): notify_user( 'Press the "Open Documentation" button when prompted about GOPATH not being set' ) view.window().run_command('golang_build') custom_view_settings = VIEW_SETTINGS.copy() del custom_view_settings['GOPATH'] open_file(file_path, custom_view_settings, _run_build) time.sleep(0.5) self.assertTrue( confirm_user('Were you prompted that GOPATH was not set?')) self.assertTrue( confirm_user( 'When you pressed "Open Documentation", was it opened in your browser?' ))
def get_env(self, shell): shell, env = shellenv.get_env(shell) self.assertEqual(str_cls, type(shell)) if sys.platform == 'win32': home_var = 'HOMEPATH' else: home_var = 'HOME' home_val = os.environ[home_var] if sys.version_info < (3,): home_val = home_val.decode('mbcs' if sys.platform == 'win32' else 'utf-8') self.assertEqual(home_val, env[home_var]) if sys.platform == 'win32': user_var = 'USERNAME' else: user_var = 'USER' user_val = os.environ[user_var] if sys.version_info < (3,): user_val = user_val.decode(locale.getpreferredencoding() if sys.platform == 'win32' else 'utf-8') self.assertEqual(user_val, env[user_var]) self.assertTrue(len(env) > 5) for key in env: self.assertEqual(str_cls, type(key)) self.assertEqual(str_cls, type(env[key]))
def run(self): """ Runs the "golang_build_terminal" command - invoked by Sublime Text via the command palette or sublime.Window.run_command() """ working_dir = _determine_working_dir(self.window) if working_dir is None: return relevant_sources = set([ 'project file', 'project file (os-specific)', 'golang.sublime-settings', 'golang.sublime-settings (os-specific)' ]) env_overrides = {} for var_name in GO_ENV_VARS: value, source = golangconfig.setting_value(var_name, window=self.window) # Only set overrides that are not coming from the user's shell if source in relevant_sources: env_overrides[var_name] = value # Get the PATH from the shell environment and then prepend any custom # value so the user's terminal searches all locations value, source = golangconfig.setting_value('PATH', window=self.window) if source in relevant_sources: shell, env = shellenv.get_env() env_overrides['PATH'] = value + os.pathsep + env.get('PATH', '') newterm.launch_terminal(working_dir, env=env_overrides)
def git_commit_info(package_dir): """ Get the git SHA1 hash, commit date and summary for the current git commit :param package_dir: A unicode string of the filesystem path to the folder containing the package :return: A tuple containing: [0] A unicode string of the short commit hash [1] A datetime.datetime object of the commit date [2] A unicode string of the commit message summary """ startupinfo = None if sys.platform == 'win32': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW _, env = shellenv.get_env(for_subprocess=True) proc = subprocess.Popen( ['git', 'log', '-n', '1', "--pretty=format:%h %at %s", 'HEAD'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=package_dir, startupinfo=startupinfo ) stdout, stderr = proc.communicate() if stderr: raise OSError(stderr.decode('utf-8').strip()) parts = stdout.decode('utf-8').strip().split(' ', 2) return (parts[0], datetime.utcfromtimestamp(int(parts[1])), parts[2])
def is_git_clean(package_dir): """ Detects if the git repository is currently all committed :param package_dir: A unicode string of the filesystem path to the folder containing the package :return: A boolean - if the repository is clean """ startupinfo = None if sys.platform == 'win32': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW _, env = shellenv.get_env(for_subprocess=True) proc = subprocess.Popen( ['git', 'status', '--porcelain'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, cwd=package_dir, startupinfo=startupinfo ) stdout, stderr = proc.communicate() if stderr: raise OSError(stderr.decode('utf-8').strip()) return len(stdout.decode('utf-8').strip()) == 0
def guru(self, end_offset, begin_offset=None, mode="describe", callback=None): """ Builds the guru shell command and calls it, returning it's output as a string. """ pos = "#" + str(end_offset) if begin_offset is not None: pos = "#%i,#%i" %(begin_offset, end_offset) file_path = self.view.file_name() # golang config or shellenv ? cmd_env = '' if use_golangconfig: try: toolpath, cmd_env = golangconfig.subprocess_info('guru', ['GOPATH', 'PATH'], view=self.view) toolpath = os.path.realpath(toolpath) except: error("golangconfig:", sys.exc_info()) return else: toolpath = 'guru' cmd_env = shellenv.get_env(for_subprocess=True)[1] cmd_env.update(get_setting("env", {})) debug("env", cmd_env) guru_scope = ",".join(get_setting("guru_scope", "")) # add local package to guru scope if get_setting("use_current_package", True) : current_file_path = os.path.realpath(os.path.dirname(file_path)) GOPATH = os.path.realpath(cmd_env["GOPATH"]) GOPATH = os.path.join(GOPATH,"src") local_package = os.path.relpath(current_file_path, GOPATH) if sublime.platform() == 'windows': local_package = local_package.replace('\\', '/') debug("GOPATH", GOPATH) debug("local_package", local_package) guru_scope = guru_scope+','+local_package guru_scope = guru_scope.strip() debug("guru_scope", guru_scope) if len(guru_scope) > 0: guru_scope = "-scope "+guru_scope guru_json = "" if get_setting("guru_json", False): guru_json = "-json" # Build guru cmd. cmd = "%(toolpath)s %(scope)s %(guru_json)s %(mode)s %(file_path)s:%(pos)s" % { "toolpath": toolpath, "file_path": file_path, "pos": pos, "guru_json": guru_json, "mode": mode, "scope": guru_scope} debug("cmd", cmd) sublime.set_timeout_async(lambda: self.runInThread(cmd, callback, cmd_env), 0)
def run_command(self, command, callback=None, show_status=True, filter_empty_args=True, **kwargs): shell = False if filter_empty_args: command = [arg for arg in command if arg] if 'working_dir' not in kwargs: kwargs['working_dir'] = self.get_working_dir() s = sublime.load_settings("Nodejs.sublime-settings") if s.get('save_first') and self.active_view() and self.active_view( ).is_dirty(): self.active_view().run_command('save') if command[0] == 'node': if s.get('node_command'): self.insert_command_with_args(s.get('node_command'), command) if s.get('node_path'): kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))} if command[0] == 'npm' and s.get('npm_command'): self.insert_command_with_args(s.get('npm_command'), command) debug("NodeCommand: run_command: command", command) # update paths for searching executables kwargs['env'] = {} kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']}) if not callback: callback = self.generic_done if os.name == 'nt': shell = True # doing exception for debugger commands to be able # get PID of node.exe on Windows not cmd.exe debug("NodeCommand: run_command: class name", self.__class__.__name__) if self.__class__.__name__.lower().find("drun") != -1: shell = False kwargs['shell'] = shell debug("NodeCommand: run_command: kwargs", kwargs) thread = CommandThread(command, callback, **kwargs) thread.start() if show_status: message = kwargs.get('status_message', False) or ' '.join(command) sublime.status_message(message)
def get_env_for_subprocess(self, shell): shell, env = shellenv.get_env(shell, for_subprocess=True) self.assertEqual(str, type(shell)) self.assertTrue(len(env) > 5) for key in env: self.assertEqual(str, type(key)) self.assertEqual(str, type(env[key]))
def run_command(self, command, callback=None, show_status=True, filter_empty_args=True, **kwargs): shell = False if filter_empty_args: command = [arg for arg in command if arg] if 'working_dir' not in kwargs: kwargs['working_dir'] = self.get_working_dir() s = sublime.load_settings("Nodejs.sublime-settings") if s.get('save_first') and self.active_view() and self.active_view().is_dirty(): self.active_view().run_command('save') if command[0] == 'node': if s.get('node_command'): command[0] = s.get('node_command') if s.get('node_path'): kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))} if command[0] == 'npm' and s.get('npm_command'): command[0] = s.get('npm_command') # update paths for searching executables kwargs['env'] = {} kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']}) if not callback: callback = self.generic_done if os.name == 'nt': shell = True # doing exception for debugger commands to be able # get PID of node.exe on Windows not cmd.exe debug("NodeCommand: run_command: class name", self.__class__.__name__) if self.__class__.__name__.lower().find("drun") != -1: shell = False kwargs['shell'] = shell debug("NodeCommand: run_command: kwargs", kwargs) thread = CommandThread(command, callback, **kwargs) thread.start() if show_status: message = kwargs.get('status_message', False) or ' '.join(command) sublime.status_message(message)
def guru(self, end_offset, begin_offset=None, mode="describe", callback=None): """ Builds the guru shell command and calls it, returning it's output as a string. """ pos = "#" + str(end_offset) if begin_offset is not None: pos = "#%i,#%i" % (begin_offset, end_offset) #Set GOOS based on os at the end of the file name. #TODO Check file header for builds. file_path = self.view.file_name() merged_env = shellenv.get_env(for_subprocess=True)[1] merged_env.update(get_setting("env", {})) debug("env", merged_env) guru_scope = ",".join(get_setting("guru_scope", "")) # assumed local package if get_setting("use_current_package", True): current_file_path = os.path.realpath(os.path.dirname(file_path)) GOPATH = os.path.realpath(merged_env["GOPATH"] + "/src") + "/" local_package = current_file_path.replace(GOPATH, "") debug("current_file_path", current_file_path) debug("GOPATH", GOPATH) debug("local_package", local_package) guru_scope = guru_scope + ',' + local_package guru_scope = guru_scope.strip() debug("guru_scope", guru_scope) if len(guru_scope) > 0: guru_scope = "-scope " + guru_scope # Build guru cmd. cmd = "guru %(scope)s -format=%(output_format)s %(mode)s %(file_path)s:%(pos)s" % { "file_path": file_path, "pos": pos, "output_format": get_setting("guru_format"), "mode": mode, "scope": guru_scope } debug("cmd", cmd) sublime.set_timeout_async( lambda: self.runInThread(cmd, callback, merged_env), 0)
def test_build_go_missing(self): ensure_not_ui_thread() shell, _ = shellenv.get_env() search_path = path.expanduser('~') with GolangBuildMock(shell=shell, env={'PATH': search_path}): file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go') def _run_build(view, result_queue): notify_user('Press the "Open Documentation" button when prompted about go not being found in the PATH') view.window().run_command('golang_build') open_file(file_path, VIEW_SETTINGS, _run_build) time.sleep(0.5) self.assertTrue(confirm_user('Were you prompted that go could not be found in the PATH?')) self.assertTrue(confirm_user('When you pressed "Open Documentation", was it opened in your browser?'))
def guru(self, end_offset, begin_offset=None, mode="describe", callback=None): """ Builds the guru shell command and calls it, returning it's output as a string. """ pos = "#" + str(end_offset) if begin_offset is not None: pos = "#%i,#%i" %(begin_offset, end_offset) #Set GOOS based on os at the end of the file name. #TODO Check file header for builds. file_path = self.view.file_name() merged_env = shellenv.get_env(for_subprocess=True)[1] merged_env.update(get_setting("env", {})) debug("env", merged_env) guru_scope = ",".join(get_setting("guru_scope", "")) # assumed local package if get_setting("use_current_package", True) : current_file_path = os.path.realpath(os.path.dirname(file_path)) GOPATH = os.path.realpath(merged_env["GOPATH"]+"/src")+"/" local_package = current_file_path.replace(GOPATH, "") debug("current_file_path", current_file_path) debug("GOPATH", GOPATH) debug("local_package", local_package) guru_scope = guru_scope+','+local_package guru_scope = guru_scope.strip() debug("guru_scope", guru_scope) if len(guru_scope) > 0: guru_scope = "-scope "+guru_scope # Build guru cmd. cmd = "guru %(scope)s -format=%(output_format)s %(mode)s %(file_path)s:%(pos)s" % { "file_path": file_path, "pos": pos, "output_format": get_setting("guru_format"), "mode": mode, "scope": guru_scope} debug("cmd", cmd) sublime.set_timeout_async(lambda: self.runInThread(cmd, callback, merged_env), 0)
class Nvm(object): """ The class for work with NVM if it is installed in system """ nvm_file = '.nvmrc' user_env = shellenv.get_env()[1] current_node_version = '' current_node_path = '' @staticmethod def is_installed(): if os.name == 'nt': return None if not Nvm.user_env.get('NVM_BIN', False): return False return True @staticmethod def node_version(): rx = r'v\d+\.\d+\.\d+' if not Nvm.is_installed(): return False if not Nvm.user_env.get('NVM_SYMLINK_CURRENT', False): debug('NVM_SYMLINK_CURRENT', False) Nvm.current_node_version = re.findall(rx, Nvm.user_env.get('NVM_BIN', False))[0] else: debug('NVM_SYMLINK_CURRENT', True) home_dir = os.path.expanduser("~/.nvm/current") realpath = os.path.realpath(home_dir) Nvm.current_node_version = re.findall(rx, realpath)[0] return Nvm.current_node_version @staticmethod def get_current_node_path(): if os.name == 'nt': return None Nvm.current_node_path = Nvm.user_env.get('NVM_BIN', False) return Nvm.current_node_path
def test_build_missing_gopath(self): ensure_not_ui_thread() shell, env = shellenv.get_env() env['GOPATH'] += '12345678' with GolangBuildMock(shell=shell, env=env): file_path = path.join(TEST_GOPATH, 'src', 'good', 'rune_len.go') def _run_build(view, result_queue): notify_user('Press the "Open Documentation" button when prompted about GOPATH not being found') view.window().run_command('golang_build') custom_view_settings = VIEW_SETTINGS.copy() del custom_view_settings['GOPATH'] open_file(file_path, custom_view_settings, _run_build) time.sleep(0.5) self.assertTrue(confirm_user('Were you prompted that GOPATH was not found?')) self.assertTrue(confirm_user('When you pressed "Open Documentation", was it opened in your browser?'))
def run_command(self, command, callback=None, show_status=True, filter_empty_args=True, **kwargs): if filter_empty_args: command = [arg for arg in command if arg] if 'working_dir' not in kwargs: kwargs['working_dir'] = self.get_working_dir() s = sublime.load_settings("Nodejs.sublime-settings") if s.get('save_first') and self.active_view() and self.active_view( ).is_dirty(): self.active_view().run_command('save') if command[0] == 'node': if s.get('node_command'): command[0] = s.get('node_command') if s.get('node_path'): kwargs['env'] = {"NODE_PATH": str(s.get('node_path'))} if command[0] == 'npm' and s.get('npm_command'): command[0] = s.get('npm_command') # update paths for searching executables kwargs['env'] = {} kwargs['env'].update({'PATH': shellenv.get_env()[1]['PATH']}) if not callback: callback = self.generic_done thread = CommandThread(command, callback, **kwargs) thread.start() if show_status: message = kwargs.get('status_message', False) or ' '.join(command) sublime.status_message(message)
def test_get_env_ensure_copy(self): shell, env = shellenv.get_env() env['FOOBAR'] = 'test' shell2, env2 = shellenv.get_env() self.assertEqual(None, env2.get('FOOBAR'))
def run(self, window, cmd, cwd, listener, env=None, decode_json=True, json_stop_pattern=None): """Run the process. :param window: Sublime window. :param cmd: The command to run (list of strings). :param cwd: The directory where to run the command. :param listener: `ProcListener` to receive the output. :param env: Dictionary of environment variables to add. :param decode_json: If True, will check for lines starting with `{` to decode as a JSON message. :param json_stop_pattern: Regular expression used to detect when it should stop looking for JSON messages. This is used by `cargo run` so that it does not capture output from the user's program that might start with an open curly brace. :raises ProcessTermiantedError: Process was terminated by another thread. """ self.cmd = cmd self.cwd = cwd self.listener = listener self.start_time = time.time() self.window = window self.decode_json = decode_json self.json_stop_pattern = json_stop_pattern from . import rust_thread try: t = rust_thread.THREADS[window.id()] except KeyError: pass else: if t.should_exit: raise ProcessTerminatedError() with PROCS_LOCK: PROCS[window.id()] = self listener.on_begin(self) # Configure the environment. self.env = os.environ.copy() if util.get_setting('rust_include_shell_env', True): global USER_SHELL_ENV if USER_SHELL_ENV is None: USER_SHELL_ENV = shellenv.get_env()[1] self.env.update(USER_SHELL_ENV) rust_env = util.get_setting('rust_env') if rust_env: for k, v in rust_env.items(): rust_env[k] = os.path.expandvars(v) self.env.update(rust_env) if env: self.env.update(env) # XXX: Debug config. util.debug('Rust running: %s', self.cmd) if sys.platform == 'win32': # Prevent a console window from popping up. startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW self.proc = subprocess.Popen( self.cmd, cwd=self.cwd, env=self.env, startupinfo=startupinfo, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) else: # Make the process the group leader so we can easily kill all its # children. self.proc = subprocess.Popen( self.cmd, cwd=self.cwd, preexec_fn=os.setpgrp, env=self.env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) self._stdout_thread = threading.Thread( target=self._read_stdout, name='%s: Stdout' % (threading.current_thread().name, )) self._stdout_thread.start()
def run(self, window, cmd, cwd, listener, env=None, decode_json=True, json_stop_pattern=None): """Run the process. :param window: Sublime window. :param cmd: The command to run (list of strings). :param cwd: The directory where to run the command. :param listener: `ProcListener` to receive the output. :param env: Dictionary of environment variables to add. :param decode_json: If True, will check for lines starting with `{` to decode as a JSON message. :param json_stop_pattern: Regular expression used to detect when it should stop looking for JSON messages. This is used by `cargo run` so that it does not capture output from the user's program that might start with an open curly brace. :raises ProcessTermiantedError: Process was terminated by another thread. :raises OSError: Failed to launch the child process. `FileNotFoundError` is a typical example if the executable is not found. """ self.cmd = cmd self.cwd = cwd self.listener = listener self.start_time = time.time() self.window = window self.decode_json = decode_json self.json_stop_pattern = json_stop_pattern from . import rust_thread try: t = rust_thread.THREADS[window.id()] except KeyError: pass else: if t.should_exit: raise ProcessTerminatedError() with PROCS_LOCK: PROCS[window.id()] = self listener.on_begin(self) # Configure the environment. self.env = os.environ.copy() if util.get_setting('rust_include_shell_env', True): global USER_SHELL_ENV if USER_SHELL_ENV is None: USER_SHELL_ENV = shellenv.get_env()[1] self.env.update(USER_SHELL_ENV) rust_env = util.get_setting('rust_env') if rust_env: for k, v in rust_env.items(): rust_env[k] = os.path.expandvars(v) self.env.update(rust_env) if env: self.env.update(env) log.log(window, 'Running: %s', ' '.join(self.cmd)) if sys.platform == 'win32': # Prevent a console window from popping up. startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW self.proc = subprocess.Popen( self.cmd, cwd=self.cwd, env=self.env, startupinfo=startupinfo, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) else: # Make the process the group leader so we can easily kill all its # children. self.proc = subprocess.Popen( self.cmd, cwd=self.cwd, preexec_fn=os.setpgrp, env=self.env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) self._stdout_thread = threading.Thread(target=self._read_stdout, name='%s: Stdout' % (threading.current_thread().name,)) self._stdout_thread.start()
def subprocess_info(executable_name, required_vars, optional_vars=None, view=None, window=None): """ Gathers and formats information necessary to use subprocess.Popen() to run one of the go executables, with details pulled from setting_value() and executable_path(). Ensures that the executable path and env dictionary are properly encoded for Sublime Text 2, where byte strings are necessary. :param executable_name: A unicode string of the executable to locate, e.g. "go" or "gofmt" :param required_vars: A list of unicode strings of the environment variables that are required, e.g. "GOPATH". Obtains values from setting_value(). :param optional_vars: A list of unicode strings of the environment variables that are optional, but should be pulled from setting_value() if available - e.g. "GOOS", "GOARCH". Obtains values from setting_value(). :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.ExecutableError When the executable requested could not be located. The .name attribute contains the name of the executable that could not be located. The .dirs attribute contains a list of unicode strings of the directories searched. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. :return: A two-element tuple. - [0] A unicode string (byte string for ST2) of the path to the executable - [1] A dict to pass to the env parameter of subprocess.Popen() """ path, _ = executable_path(executable_name, view=view, window=window) if path is None: name = executable_name if sys.platform == 'win32': name += '.exe' dirs = [] settings_path, _ = _get_most_specific_setting('PATH', view=view, window=window) if settings_path and settings_path != _NO_VALUE: dirs.extend(settings_path.split(os.pathsep)) _, shell_dirs = shellenv.get_path() for shell_dir in shell_dirs: if shell_dir not in dirs: dirs.append(shell_dir) exception = ExecutableError( 'The executable "%s" could not be located in any of the following locations: "%s"' % (name, '", "'.join(dirs))) exception.name = name exception.dirs = dirs raise exception path = shellenv.path_encode(path) _, env = shellenv.get_env(for_subprocess=True) var_groups = [required_vars] if optional_vars: var_groups.append(optional_vars) missing_vars = [] for var_names in var_groups: for var_name in var_names: value, _ = setting_value(var_name, view=view, window=window) var_key = var_name if value is not None: value = str_cls(value) value = shellenv.env_encode(value) var_key = shellenv.env_encode(var_key) if value is None: if var_key in env: del env[var_key] continue env[var_key] = value for required_var in required_vars: var_key = shellenv.env_encode(required_var) if var_key not in env: missing_vars.append(required_var) if missing_vars: missing_vars = sorted(missing_vars, key=lambda s: s.lower()) exception = EnvVarError( 'The following environment variable%s currently unset: %s' % ('s are' if len(missing_vars) > 1 else ' is', ', '.join(missing_vars))) exception.missing = missing_vars raise exception encoded_goroot = shellenv.env_encode('GOROOT') if encoded_goroot in env: unicode_sep = shellenv.path_decode(os.sep) name = executable_name if sys.platform == 'win32': name += '.exe' relative_executable_path = shellenv.path_encode('bin%s%s' % (unicode_sep, name)) goroot_executable_path = os.path.join(env[encoded_goroot], relative_executable_path) if goroot_executable_path != path: print( 'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"' % (executable_name, path, shellenv.path_decode(env[encoded_goroot]))) return (path, env)
def setting_value(setting_name, view=None, window=None): """ Returns the user's setting for a specific variable, such as GOPATH or GOROOT. Supports global and per-platform settings. Finds settings by looking in: 1. If a project is open, the project settings 2. The global golang.sublime-settings file 3. The user's environment variables, as defined by their login shell If the setting is a known name, e.g. GOPATH or GOROOT, the value will be checked to ensure the path exists. :param setting_name: A unicode string of the setting to retrieve :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type :return: A two-element tuple. If no setting was found, the return value will be: - [0] None - [1] None If a setting was found, the return value will be: - [0] The setting value - [1] The source of the setting, a unicode string: - "project file (os-specific)" - "golang.sublime-settings (os-specific)" - "project file" - "golang.sublime-settings" - A unicode string of the path to the user's login shell The second element of the tuple is intended to be used in the display of debugging information to end users. """ _require_unicode('setting_name', setting_name) _check_view_window(view, window) setting, source = _get_most_specific_setting(setting_name, view, window) if setting == _NO_VALUE: setting = None source = None shell, env = shellenv.get_env() if setting_name in env: source = shell setting = env[setting_name] if setting_name not in set(['GOPATH', 'GOROOT']): return (setting, source) # We add some extra processing here for known settings to improve the # user experience, especially around debugging is_str = isinstance(setting, str_cls) if is_str: if os.path.exists(setting): return (setting, source) if debug_enabled(): print( 'golangconfig: the value for %s from %s - "%s" - does not exist on the filesystem' % (setting_name, source, setting)) elif debug_enabled(): _debug_unicode_string(setting_name, setting, source) return (None, None)
def subprocess_info(executable_name, required_vars, optional_vars=None, view=None, window=None): """ Gathers and formats information necessary to use subprocess.Popen() to run one of the go executables, with details pulled from setting_value() and executable_path(). Ensures that the executable path and env dictionary are properly encoded for Sublime Text 2, where byte strings are necessary. :param executable_name: A unicode string of the executable to locate, e.g. "go" or "gofmt" :param required_vars: A list of unicode strings of the environment variables that are required, e.g. "GOPATH". Obtains values from setting_value(). :param optional_vars: A list of unicode strings of the environment variables that are optional, but should be pulled from setting_value() if available - e.g. "GOOS", "GOARCH". Obtains values from setting_value(). :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.ExecutableError When the executable requested could not be located. The .name attribute contains the name of the executable that could not be located. The .dirs attribute contains a list of unicode strings of the directories searched. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. golangconfig.GoPathNotFoundError When one or more directories specified by the GOPATH environment variable could not be found on disk. The .directories attribute will be a list of the directories that could not be found. golangconfig.GoRootNotFoundError When the directory specified by GOROOT environment variable could not be found on disk. The .directory attribute will be the path to the directory that could not be found. golangconfig.EnvVarError When one or more required_vars are not available. The .missing attribute will be a list of the names of missing environment variables. :return: A two-element tuple. - [0] A unicode string (byte string for ST2) of the path to the executable - [1] A dict to pass to the env parameter of subprocess.Popen() """ path, _ = executable_path(executable_name, view=view, window=window) if path is None: name = executable_name if sys.platform == 'win32': name += '.exe' dirs = [] settings_path, _ = _get_most_specific_setting('PATH', view=view, window=window) if settings_path and settings_path != _NO_VALUE: dirs.extend(settings_path.split(os.pathsep)) _, shell_dirs = shellenv.get_path() for shell_dir in shell_dirs: if shell_dir not in dirs: dirs.append(shell_dir) exception = ExecutableError( 'The executable "%s" could not be located in any of the following locations: "%s"' % ( name, '", "'.join(dirs) ) ) exception.name = name exception.dirs = dirs raise exception path = shellenv.path_encode(path) _, env = shellenv.get_env(for_subprocess=True) var_groups = [required_vars] if optional_vars: var_groups.append(optional_vars) missing_vars = [] for var_names in var_groups: for var_name in var_names: value, _ = setting_value(var_name, view=view, window=window) var_key = var_name if value is not None: value = str_cls(value) value = shellenv.env_encode(value) var_key = shellenv.env_encode(var_key) if value is None: if var_key in env: del env[var_key] continue env[var_key] = value for required_var in required_vars: var_key = shellenv.env_encode(required_var) if var_key not in env: missing_vars.append(required_var) if missing_vars: missing_vars = sorted(missing_vars, key=lambda s: s.lower()) exception = EnvVarError( 'The following environment variable%s currently unset: %s' % ( 's are' if len(missing_vars) > 1 else ' is', ', '.join(missing_vars) ) ) exception.missing = missing_vars raise exception encoded_goroot = shellenv.env_encode('GOROOT') if encoded_goroot in env: unicode_sep = shellenv.path_decode(os.sep) name = executable_name if sys.platform == 'win32': name += '.exe' relative_executable_path = shellenv.path_encode('bin%s%s' % (unicode_sep, name)) goroot_executable_path = os.path.join(env[encoded_goroot], relative_executable_path) if goroot_executable_path != path: print( 'golangconfig: warning - binary %s was found at "%s", which is not inside of the GOROOT "%s"' % ( executable_name, path, shellenv.path_decode(env[encoded_goroot]) ) ) return (path, env)
def setting_value(setting_name, view=None, window=None): """ Returns the user's setting for a specific variable, such as GOPATH or GOROOT. Supports global and per-platform settings. Finds settings by looking in: 1. If a project is open, the project settings 2. The global golang.sublime-settings file 3. The user's environment variables, as defined by their login shell If the setting is a known name, e.g. GOPATH or GOROOT, the value will be checked to ensure the path exists. :param setting_name: A unicode string of the setting to retrieve :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.GoPathNotFoundError When one or more directories specified by the GOPATH environment variable could not be found on disk. The .directories attribute will be a list of the directories that could not be found. golangconfig.GoRootNotFoundError When the directory specified by GOROOT environment variable could not be found on disk. The .directory attribute will be the path to the directory that could not be found. :return: A two-element tuple. If no setting was found, the return value will be: - [0] None - [1] None If a setting was found, the return value will be: - [0] The setting value - [1] The source of the setting, a unicode string: - "project file (os-specific)" - "golang.sublime-settings (os-specific)" - "project file" - "golang.sublime-settings" - A unicode string of the path to the user's login shell The second element of the tuple is intended to be used in the display of debugging information to end users. """ _require_unicode('setting_name', setting_name) _check_view_window(view, window) setting, source = _get_most_specific_setting(setting_name, view, window) if setting == _NO_VALUE: setting = None source = None shell, env = shellenv.get_env() if setting_name in env: source = shell setting = env[setting_name] if setting_name not in set(['GOPATH', 'GOROOT']): return (setting, source) if setting is None and source is None: return (setting, source) # We add some extra processing here for known settings to improve the # user experience, especially around debugging _debug_unicode_string(setting_name, setting, source) if not isinstance(setting, str_cls): setting = str_cls(setting) if setting_name == 'GOROOT': if os.path.exists(setting): return (setting, source) has_multiple = False if setting_name == 'GOPATH': values = setting.split(os.pathsep) has_multiple = len(values) > 1 missing = [] for value in values: if not os.path.exists(value): missing.append(value) if not missing: return (setting, source) if setting_name == 'GOROOT': message = 'The GOROOT environment variable value "%s" does not exist on the filesystem' e = GoRootNotFoundError(message % setting) e.directory = setting raise e if not has_multiple: suffix = 'value "%s" does not exist on the filesystem' % missing[0] elif len(missing) == 1: suffix = 'contains the directory "%s" that does not exist on the filesystem' % missing[0] else: paths = ', '.join('"' + path + '"' for path in missing) suffix = 'contains %s directories that do not exist on the filesystem: %s' % (len(missing), paths) message = 'The GOPATH environment variable ' + suffix e = GoPathNotFoundError(message) e.directories = missing raise e
def get_env(): _, env = shellenv.get_env() return env
def setting_value(setting_name, view=None, window=None): """ Returns the user's setting for a specific variable, such as GOPATH or GOROOT. Supports global and per-platform settings. Finds settings by looking in: 1. If a project is open, the project settings 2. The global golang.sublime-settings file 3. The user's environment variables, as defined by their login shell If the setting is a known name, e.g. GOPATH or GOROOT, the value will be checked to ensure the path exists. :param setting_name: A unicode string of the setting to retrieve :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type golangconfig.GoPathNotFoundError When one or more directories specified by the GOPATH environment variable could not be found on disk. The .directories attribute will be a list of the directories that could not be found. golangconfig.GoRootNotFoundError When the directory specified by GOROOT environment variable could not be found on disk. The .directory attribute will be the path to the directory that could not be found. :return: A two-element tuple. If no setting was found, the return value will be: - [0] None - [1] None If a setting was found, the return value will be: - [0] The setting value - [1] The source of the setting, a unicode string: - "project file (os-specific)" - "golang.sublime-settings (os-specific)" - "project file" - "golang.sublime-settings" - A unicode string of the path to the user's login shell The second element of the tuple is intended to be used in the display of debugging information to end users. """ _require_unicode('setting_name', setting_name) _check_view_window(view, window) setting, source = _get_most_specific_setting(setting_name, view, window) if setting == _NO_VALUE: setting = None source = None shell, env = shellenv.get_env() if setting_name in env: source = shell setting = env[setting_name] if setting_name not in set(['GOPATH', 'GOROOT']): return (setting, source) if setting is None and source is None: return (setting, source) # We add some extra processing here for known settings to improve the # user experience, especially around debugging _debug_unicode_string(setting_name, setting, source) if not isinstance(setting, str_cls): setting = str_cls(setting) if setting_name == 'GOROOT': if os.path.exists(setting): return (setting, source) has_multiple = False if setting_name == 'GOPATH': values = setting.split(os.pathsep) has_multiple = len(values) > 1 missing = [] for value in values: if not os.path.exists(value): missing.append(value) if not missing: return (setting, source) if setting_name == 'GOROOT': message = 'The GOROOT environment variable value "%s" does not exist on the filesystem' e = GoRootNotFoundError(message % setting) e.directory = setting raise e if not has_multiple: suffix = 'value "%s" does not exist on the filesystem' % missing[0] elif len(missing) == 1: suffix = 'contains the directory "%s" that does not exist on the filesystem' % missing[ 0] else: paths = ', '.join('"' + path + '"' for path in missing) suffix = 'contains %s directories that do not exist on the filesystem: %s' % ( len(missing), paths) message = 'The GOPATH environment variable ' + suffix e = GoPathNotFoundError(message) e.directories = missing raise e
# import lib's modules from .lib.nodejs_debug import debug, info from .lib.nodejs_constants import * from .lib.nodejs_paths import * from .lib.nodejs_commands import * from .lib.nodejs_nvm import * debug('PLUGIN_PATH', PLUGIN_PATH) debug('PLUGIN_LIB_DIR', PLUGIN_LIB_DIR) debug('PLUGIN_DEBUG_FILE', PLUGIN_DEBUG_FILE) debug('UGLIFY_PATH', UGLIFY_PATH) debug('BUILDER_PATH', BUILDER_PATH) debug('SHELLENV', shellenv.get_env()) def generate_completions(): info('Running `node_builddocs` to generate Node.js completions') sublime.active_window().run_command('node_builddocs') def check_and_install_dependencies(): """ The function is dosen't check whether npm/node is installed or not. """ # check if already installed if os.path.exists(PLUGIN_PACKAGE_LOCK): return
def setting_value(setting_name, view=None, window=None): """ Returns the user's setting for a specific variable, such as GOPATH or GOROOT. Supports global and per-platform settings. Finds settings by looking in: 1. If a project is open, the project settings 2. The global golang.sublime-settings file 3. The user's environment variables, as defined by their login shell If the setting is a known name, e.g. GOPATH or GOROOT, the value will be checked to ensure the path exists. :param setting_name: A unicode string of the setting to retrieve :param view: A sublime.View object to use in finding project-specific settings. This should be passed whenever available. :param window: A sublime.Window object to use in finding project-specific settings. This should be passed whenever available. :raises: RuntimeError When the function is called from any thread but the UI thread TypeError When any of the parameters are of the wrong type :return: A two-element tuple. If no setting was found, the return value will be: - [0] None - [1] None If a setting was found, the return value will be: - [0] The setting value - [1] The source of the setting, a unicode string: - "project file (os-specific)" - "golang.sublime-settings (os-specific)" - "project file" - "golang.sublime-settings" - A unicode string of the path to the user's login shell The second element of the tuple is intended to be used in the display of debugging information to end users. """ _require_unicode('setting_name', setting_name) _check_view_window(view, window) setting, source = _get_most_specific_setting(setting_name, view, window) if setting == _NO_VALUE: setting = None source = None shell, env = shellenv.get_env() if setting_name in env: source = shell setting = env[setting_name] if setting_name not in set(['GOPATH', 'GOROOT']): return (setting, source) # We add some extra processing here for known settings to improve the # user experience, especially around debugging is_str = isinstance(setting, str_cls) if is_str: if os.path.exists(setting): return (setting, source) if debug_enabled(): print( 'golangconfig: the value for %s from %s - "%s" - does not exist on the filesystem' % ( setting_name, source, setting ) ) elif debug_enabled(): _debug_unicode_string(setting_name, setting, source) return (None, None)