def _ext_specs(project): # Get a list of WestExtCommandSpec objects for the given # west.manifest.Project. spec_file = os.path.join(project.abspath, project.west_commands) # Verify project.west_commands isn't trying a directory traversal # outside of the project. if escapes_directory(spec_file, project.abspath): raise ExtensionCommandError( 'west-commands file {} escapes project path {}'.format( project.west_commands, project.path)) # Project may not be cloned yet. if not os.path.exists(spec_file): return [] # Load the spec file and check the schema. with open(spec_file, 'r') as f: try: commands_spec = yaml.safe_load(f.read()) except yaml.YAMLError as e: raise ExtensionCommandError from e try: pykwalify.core.Core(source_data=commands_spec, schema_files=[_EXT_SCHEMA_PATH]).validate() except pykwalify.errors.SchemaError as e: raise ExtensionCommandError from e ret = [] for commands_desc in commands_spec['west-commands']: ret.extend(_ext_specs_from_desc(project, commands_desc)) return ret
def _resolve_build_dir(fmt, cwd, **kwargs): # Remove any None values, we do not want 'None' as a string kwargs = {k: v for k, v in kwargs.items() if v is not None} # Check if source_dir is below cwd first source_dir = kwargs.get('source_dir') if source_dir: if escapes_directory(cwd, source_dir): kwargs['source_dir'] = os.path.relpath(source_dir, cwd) else: # no meaningful relative path possible kwargs['source_dir'] = '' return fmt.format(**kwargs)
def _ext_specs(project): # Get a list of WestExtCommandSpec objects for the given # west.manifest.Project. ret = [] # As an internal implementation detail, we allow the internal # representation of a project to have sequences as their # west_commands attribute value. This is required for manifest # imports, where e.g. the final ManifestProject.west_commands # might contain the results of importing multiple repositories. if isinstance(project.west_commands, str): commands = [project.west_commands] else: commands = list(project.west_commands) for cmd in commands: spec_file = os.path.join(project.abspath, cmd) # Verify project.west_commands isn't trying a directory traversal # outside of the project. if escapes_directory(spec_file, project.abspath): raise ExtensionCommandError( f'west-commands file {project.west_commands} ' f'escapes project path {project.path}') # The project may not be cloned yet, or this might be coming # from a manifest that was copy/pasted into a self import # location. if not os.path.exists(spec_file): continue # Load the spec file and check the schema. with open(spec_file, 'r') as f: try: commands_spec = yaml.safe_load(f.read()) except yaml.YAMLError as e: raise ExtensionCommandError from e try: pykwalify.core.Core( source_data=commands_spec, schema_files=[_EXT_SCHEMA_PATH]).validate() except pykwalify.errors.SchemaError as e: raise ExtensionCommandError from e for commands_desc in commands_spec['west-commands']: ret.extend(_ext_specs_from_desc(project, commands_desc)) return ret
def _resolve_build_dir(fmt, guess, cwd, **kwargs): # Remove any None values, we do not want 'None' as a string kwargs = {k: v for k, v in kwargs.items() if v is not None} # Check if source_dir is below cwd first source_dir = kwargs.get('source_dir') if source_dir: if escapes_directory(cwd, source_dir): kwargs['source_dir'] = os.path.relpath(source_dir, cwd) else: # no meaningful relative path possible kwargs['source_dir'] = '' try: return fmt.format(**kwargs) except KeyError: if not guess: return None # Guess the build folder by iterating through all sub-folders from the # root of the format string and trying to resolve. If resolving fails, # proceed to iterate over subfolders only if there is a single folder # present on each iteration. parts = Path(fmt).parts b = Path('.') for p in parts: # default to cwd in the first iteration curr = b b = b.joinpath(p) try: # if fmt is an absolute path, the first iteration will always # resolve '/' b = Path(str(b).format(**kwargs)) except KeyError: # Missing key, check sub-folders and match if a single one exists while True: if not curr.exists(): return None dirs = [f for f in curr.iterdir() if f.is_dir()] if len(dirs) != 1: return None curr = dirs[0] if is_zephyr_build(str(curr)): return str(curr) return str(b)
def _ext_specs_from_desc(project, commands_desc): py_file = os.path.join(project.abspath, commands_desc['file']) # Verify the YAML's python file doesn't escape the project directory. if escapes_directory(py_file, project.abspath): raise ExtensionCommandError( 'extension command python file "{}" escapes project path {}'. format(commands_desc['file'], project.path)) # Create the command thunks. thunks = [] for command_desc in commands_desc['commands']: name = command_desc['name'] attr = command_desc.get('class', name) help = command_desc.get( 'help', '(no help provided; try "west {} -h")'.format(name)) factory = _ExtFactory(py_file, name, attr) thunks.append(WestExtCommandSpec(name, project, help, factory)) # Return the thunks for this project. return thunks
def _ext_specs(project): # Get a list of WestExtCommandSpec objects for the given # west.manifest.Project. ret = [] for cmd in project.west_commands: spec_file = os.path.join(project.abspath, cmd) # Verify project.west_commands isn't trying a directory traversal # outside of the project. if escapes_directory(spec_file, project.abspath): raise ExtensionCommandError(f'west-commands file {cmd} ' f'escapes project path {project.path}') # The project may not be cloned yet, or this might be coming # from a manifest that was copy/pasted into a self import # location. if not os.path.exists(spec_file): continue # Load the spec file and check the schema. with open(spec_file, 'r') as f: try: commands_spec = yaml.safe_load(f.read()) except yaml.YAMLError as e: raise ExtensionCommandError from e try: pykwalify.core.Core(source_data=commands_spec, schema_files=[_EXT_SCHEMA_PATH]).validate() except pykwalify.errors.SchemaError as e: raise ExtensionCommandError from e for commands_desc in commands_spec['west-commands']: ret.extend(_ext_specs_from_desc(project, commands_desc)) return ret