def exec_with_wrapper(exec_with, install_dir, cmd_list): '''Wrapper function for inserting the execution wrapper, e.g., 'cabal exec' or 'stack exec' :returns: Process object from ProcHelper. ''' proc_args = {} if exec_with is not None: if exec_with == 'cabal': cmd_list = ['cabal', 'exec'] + cmd_list cmd_list.insert(3, '--') elif exec_with == 'stack': cmd_list = ['stack', 'exec'] + cmd_list cmd_list.insert(3, '--') else: errmsg = 'HsDevBackend.exec_with_wrapper: Unknown execution prefix \'{0}\''.format( exec_with) raise RuntimeError(errmsg) if install_dir is not None: proc_args['cwd'] = Utils.normalize_path(install_dir) else: cmd = Which.which(cmd_list[0], ProcHelper.ProcHelper.get_extended_path()) if cmd is not None: cmd_list[0] = cmd Logging.log('HsDevBackend.exec_with_wrapper: {0}'.format(cmd_list), Logging.LOG_DEBUG) return ProcHelper.ProcHelper(cmd_list, **proc_args)
def cabal_new_clean(project_dir): '''Internal command that does the "cabal new-"-style 'clean' command (until it is actually implemented.) ''' def remove_subdir_recursively(subdir): subdir = Utils.normalize_path(os.path.join(project_dir, subdir)) if os.path.exists(subdir): if os.path.isdir(subdir): for dirpath, _dirnames, filenames in os.walk(subdir, topdown=False): try: for fname in filenames: os.remove(os.path.join(dirpath, fname)) os.rmdir(dirpath) except OSError as ex: diag_feedback.append(str(ex)) print(ex) else: os.remove(subdir) cabal_project_local = Utils.normalize_path(os.path.join(project_dir, 'cabal.project.local')) diag_feedback = [] for subd in ['dist-newstyle', 'dist']: remove_subdir_recursively(subd) if os.path.exists(cabal_project_local): os.remove(cabal_project_local) return (0 if not diag_feedback else 1, '\n'.join(diag_feedback))
def make_augmented_path(): ''' Generate the augmented PATH for subprocesses: adds the appropriate cabal/stack local install directory ($HOME/.local/bin for *nix, %APPDATA%/local/bin for Windows) and updates PATH with `add_to_PATH` extras. ''' std_places = [] if Settings.PLUGIN.add_standard_dirs: std_places.append("$HOME/.local/bin" if not Utils.is_windows() else "%APPDATA%/local/bin") if Utils.is_macosx(): std_places.append('$HOME/Library/Haskell/bin') std_places += CabalConfigRdr.cabal_config() std_places = [ dir for dir in [Utils.normalize_path(path) for path in std_places] if os.path.isdir(dir) ] add_to_path = list( filter(os.path.isdir, map(Utils.normalize_path, Settings.PLUGIN.add_to_path))) Logging.log("std_places = {0}".format(std_places), Logging.LOG_INFO) Logging.log("add_to_PATH = {0}".format(add_to_path), Logging.LOG_INFO) return os.pathsep.join(add_to_path + std_places)
def cabal_config(): cconfig = os.environ.get('CABAL_CONFIG') or \ ('~/.cabal' if not Utils.is_windows() else r'%APPDATA%/cabal') + \ "/config" # Various patterns to match... re_user_dirs = re.compile(r'^install-dirs\s+user') re_global_dirs = re.compile(r'^install-dirs\s+global') re_section = re.compile(r'^\w+') re_prefix = re.compile(r'prefix:\s+(.*)$') re_bindir = re.compile(r'bindir:\s+(.*)$') # Things to collect user_prefix = "$HOME/.cabal" if not Utils.is_windows() else r'%APPDATA%/cabal' # FIXME: Need to interrogate Shel32 for the Windows PROGRAMFILES known # folder path: global_prefix = "/usr/local" if not Utils.is_windows() else r'%PROGRAMFILES%/Haskell' user_bindir = "bin" global_bindir = "bin" p_state = 0 try: with open(Utils.normalize_path(cconfig), 'rU') as f_cconfig: # You would think that the Cabal maintainers would use a # well known file format... But now, they didn't. And they # had to go with an indentation-specific format. # # This is a "cheap and dirty" scanner to pick up for line in f_cconfig: line = line.rstrip() # One of the sections? if re_user_dirs.match(line): p_state = 1 elif re_global_dirs.match(line): p_state = 2 elif re.match(r'^\s+\w', line): # prefix attribute? m_prefix = re_prefix.search(line) if m_prefix: if p_state == 1: user_prefix = m_prefix.group(1) elif p_state == 2: global_prefix = m_prefix.group(1) # bindir attribute? m_bindir = re_bindir.search(line) if m_bindir: if p_state == 1: user_bindir = m_bindir.group(1) elif p_state == 2: global_bindir = m_bindir.group(1) elif re_section.match(line): p_state = 0 except IOError: # Silently fail. pass return [os.path.join(user_prefix, user_bindir) , os.path.join(global_prefix, global_bindir) ]
def __init__(self, backend_mgr, local=True, port=HSDEV_DEFAULT_PORT, host=HSDEV_DEFAULT_HOST, local_base_dir=None, remote_base_dir=None, **kwargs): super().__init__(backend_mgr) Logging.log( '{0}.__init__({1}, {2})'.format(type(self).__name__, host, port), Logging.LOG_INFO) # Sanity checking: exec_with = kwargs.get('exec-with') install_dir = kwargs.get('install-dir') if exec_with is not None and install_dir is None: sublime.error_message('\n'.join([ '\'exec_with\' requires an \'install_dir\'.', '', 'Please check your \'backends\' configuration and retry.' ])) raise RuntimeError('\'exec_with\' requires an \'install_dir\'.') elif exec_with is not None and exec_with not in ['stack', 'cabal']: sublime.error_message('\n'.join([ 'Invalid backend \'exec_with\': {0}'.format(exec_with), '', 'Valid values are "cabal" or "stack".', 'Please check your \'backends\' configuration and retry.' ])) raise RuntimeError( 'Invalid backend \'exec_with\': {0}'.format(exec_with)) # Local hsdev server process and params self.is_local_hsdev = local self.hsdev_process = None self.cache = os.path.join(Common.sublime_haskell_cache_path(), 'hsdev') self.log_file = os.path.join(Common.sublime_haskell_cache_path(), 'hsdev', 'hsdev.log') self.exec_with = exec_with self.install_dir = Utils.normalize_path( install_dir) if install_dir is not None else None # Keep track of the hsdev version early. Needed to patch command line arguments later. self.version = HsDevBackend.hsdev_version(self.exec_with, self.install_dir) self.drain_stdout = None self.drain_stderr = None # Connection params self.port = port self.hostname = host self.local_base_dir = local_base_dir self.remote_base_dir = remote_base_dir if self.is_local_hsdev: self.hostname = self.HSDEV_DEFAULT_HOST self.client = None
def remove_subdir_recursively(subdir): subdir = Utils.normalize_path(os.path.join(project_dir, subdir)) if os.path.exists(subdir): if os.path.isdir(subdir): for dirpath, _dirnames, filenames in os.walk(subdir, topdown=False): try: for fname in filenames: os.remove(os.path.join(dirpath, fname)) os.rmdir(dirpath) except OSError as ex: diag_feedback.append(str(ex)) print(ex) else: os.remove(subdir)
def __init__(self, backend_mgr, local=True, port=HSDEV_DEFAULT_PORT, host=HSDEV_DEFAULT_HOST, **kwargs): super().__init__(backend_mgr) Logging.log('{0}.__init__({1}, {2})'.format(type(self).__name__, host, port), Logging.LOG_INFO) # Sanity checking: exec_with = kwargs.get('exec-with') install_dir = kwargs.get('install-dir') if bool(exec_with) ^ bool(install_dir): if install_dir is None: sublime.error_message('\n'.join(['\'exec_with\' requires an \'install_dir\'.', '', 'Please check your \'backends\' configuration and retry.'])) raise RuntimeError('\'exec_with\' requires an \'install_dir\'.') else: sublime.error_message('\n'.join(['\'install_dir\' requires an \'exec_with\'.', '', 'Please check your \'backends\' configuration and retry.'])) raise RuntimeError('\'install_dir\' requires an \'exec_with\'.') elif exec_with and exec_with not in ['stack', 'cabal', 'cabal-new-build']: sublime.error_message('\n'.join(['Invalid backend \'exec_with\': {0}'.format(exec_with), '', 'Valid values are "cabal", "cabal-new-build" or "stack".', 'Please check your \'backends\' configuration and retry.'])) raise RuntimeError('Invalid backend \'exec_with\': {0}'.format(exec_with)) # Local hsdev server process and params self.is_local_hsdev = local self.hsdev_process = None self.cache = os.path.join(Common.sublime_haskell_cache_path(), 'hsdev') self.log_file = os.path.join(Common.sublime_haskell_cache_path(), 'hsdev', 'hsdev.log') self.exec_with = exec_with self.install_dir = Utils.normalize_path(install_dir) if install_dir is not None else None # Keep track of the hsdev version early. Needed to patch command line arguments later. self.version = HsDevBackend.hsdev_version(self.exec_with, self.install_dir) self.drain_stdout = None self.drain_stderr = None # Connection params self.port = port self.hostname = host if self.is_local_hsdev: self.hostname = self.HSDEV_DEFAULT_HOST self.client = None self.serial_lock = threading.RLock() self.request_serial = 1
def make_augmented_path(): ''' Generate the augmented PATH for subprocesses: adds the appropriate cabal/stack local install directory ($HOME/.local/bin for *nix, %APPDATA%/local/bin for Windows) and updates PATH with `add_to_PATH` extras. ''' std_places = [] if Settings.PLUGIN.add_standard_dirs: std_places.append("$HOME/.local/bin" if not Utils.is_windows() else "%APPDATA%/local/bin") if Utils.is_macosx(): std_places.append('$HOME/Library/Haskell/bin') std_places += CabalConfigRdr.cabal_config() std_places = [dir for dir in [Utils.normalize_path(path) for path in std_places] if os.path.isdir(dir)] add_to_path = list(filter(os.path.isdir, map(Utils.normalize_path, Settings.PLUGIN.add_to_path))) Logging.log("std_places = {0}".format(std_places), Logging.LOG_INFO) Logging.log("add_to_PATH = {0}".format(add_to_path), Logging.LOG_INFO) return os.pathsep.join(add_to_path + std_places)
def exec_with_wrapper(exec_with, install_dir, cmd_list): '''Wrapper function for inserting the execution wrapper, e.g., 'cabal exec' or 'stack exec' :returns: Process object from ProcHelper. ''' proc_args = {} if exec_with is not None: cmd_list = exec_wrapper_cmd(exec_with, cmd_list) if install_dir is not None: proc_args['cwd'] = Utils.normalize_path(install_dir) else: raise RuntimeError('ProcHelper.exec_with_wrapper: invalid install_dir (None)') else: cmd = Which.which(cmd_list[0], ProcHelper.get_extended_path()) if cmd is not None: cmd_list[0] = cmd Logging.log('ProcHelper.exec_with_wrapper: {0} in {1}'.format(cmd_list, proc_args.get('cwd')), Logging.LOG_DEBUG) return ProcHelper(cmd_list, **proc_args)
def exec_with_wrapper(exec_with, install_dir, cmd_list): '''Wrapper function for inserting the execution wrapper, e.g., 'cabal exec' or 'stack exec' :returns: Process object from ProcHelper. ''' proc_args = {} if exec_with is not None: cmd_list = exec_wrapper_cmd(exec_with, cmd_list) if install_dir is not None: proc_args['cwd'] = Utils.normalize_path(install_dir) else: cmd = Which.which(cmd_list[0], ProcHelper.get_extended_path()) if cmd is not None: cmd_list[0] = cmd Logging.log( 'ProcHelper.exec_with_wrapper: {0} in {1}'.format( cmd_list, proc_args.get('cwd')), Logging.LOG_DEBUG) return ProcHelper(cmd_list, **proc_args)
def childof(path, prefix): return Utils.normalize_path(path).startswith(Utils.normalize_path(prefix))
def cabal_config(): cconfig = os.environ.get('CABAL_CONFIG') or \ ('~/.cabal' if not Utils.is_windows() else r'%APPDATA%/cabal') + \ "/config" # Various patterns to match... re_user_dirs = re.compile(r'^install-dirs\s+user') re_global_dirs = re.compile(r'^install-dirs\s+global') re_section = re.compile(r'^\w+') re_prefix = re.compile(r'prefix:\s+(.*)$') re_bindir = re.compile(r'bindir:\s+(.*)$') # Things to collect user_prefix = "$HOME/.cabal" if not Utils.is_windows( ) else r'%APPDATA%/cabal' # FIXME: Need to interrogate Shel32 for the Windows PROGRAMFILES known # folder path: global_prefix = "/usr/local" if not Utils.is_windows( ) else r'%PROGRAMFILES%/Haskell' user_bindir = "bin" global_bindir = "bin" p_state = 0 try: with open(Utils.normalize_path(cconfig), 'rU') as f_cconfig: # You would think that the Cabal maintainers would use a # well known file format... But now, they didn't. And they # had to go with an indentation-specific format. # # This is a "cheap and dirty" scanner to pick up for line in f_cconfig: line = line.rstrip() # One of the sections? if re_user_dirs.match(line): p_state = 1 elif re_global_dirs.match(line): p_state = 2 elif re.match(r'^\s+\w', line): # prefix attribute? m_prefix = re_prefix.search(line) if m_prefix: if p_state == 1: user_prefix = m_prefix.group(1) elif p_state == 2: global_prefix = m_prefix.group(1) # bindir attribute? m_bindir = re_bindir.search(line) if m_bindir: if p_state == 1: user_bindir = m_bindir.group(1) elif p_state == 2: global_bindir = m_bindir.group(1) elif re_section.match(line): p_state = 0 except IOError: # Silently fail. pass return [ os.path.join(user_prefix, user_bindir), os.path.join(global_prefix, global_bindir) ]