def det_full_ec_version(ec): """ Determine exact install version, based on supplied easyconfig. e.g. 1.2.3-goalf-1.1.0-no-OFED or 1.2.3 (for system toolchains) """ ecver = None toolchain = ec.get('toolchain', {'name': SYSTEM_TOOLCHAIN_NAME}) # determine main install version based on toolchain if is_system_toolchain(toolchain['name']): ecver = ec['version'] else: ecver = "%s-%s-%s" % (ec['version'], toolchain['name'], toolchain['version']) # prepend/append version prefix/suffix ecver = ''.join([ x for x in [ec.get('versionprefix', ''), ecver, ec.get('versionsuffix', '')] if x ]) return ecver
def list_software(output_format=FORMAT_TXT, detailed=False, only_installed=False): """ Show list of supported software :param output_format: output format to use :param detailed: whether or not to return detailed information (incl. version, versionsuffix, toolchain info) :param only_installed: only retain software for which a corresponding module is available :return: multi-line string presenting requested info """ silent = build_option('silent') ec_paths = find_matching_easyconfigs('*', '*', build_option('robot_path') or []) ecs = [] cnt = len(ec_paths) for idx, ec_path in enumerate(ec_paths): # full EasyConfig instance is only required when module name is needed # this is significantly slower (5-10x) than a 'shallow' parse via EasyConfigParser if only_installed: ec = process_easyconfig(ec_path, validate=False, parse_only=True)[0]['ec'] else: ec = EasyConfigParser(filename=ec_path).get_config_dict() ecs.append(ec) print_msg('\r', prefix=False, newline=False, silent=silent) print_msg("Processed %d/%d easyconfigs..." % (idx + 1, cnt), newline=False, silent=silent) print_msg('', prefix=False, silent=silent) software = {} for ec in ecs: software.setdefault(ec['name'], []) if is_system_toolchain(ec['toolchain']['name']): toolchain = SYSTEM_TOOLCHAIN_NAME else: toolchain = '%s/%s' % (ec['toolchain']['name'], ec['toolchain']['version']) keys = ['description', 'homepage', 'version', 'versionsuffix'] info = {'toolchain': toolchain} for key in keys: info[key] = ec.get(key, '') # make sure values like homepage & versionsuffix get properly templated if isinstance(ec, dict): template_values = template_constant_dict(ec) for key in keys: if '%(' in info[key]: try: info[key] = info[key] % template_values except (KeyError, TypeError, ValueError) as err: _log.debug("Ignoring failure to resolve templates: %s", err) software[ec['name']].append(info) if only_installed: software[ec['name']][-1].update({'mod_name': ec.full_mod_name}) print_msg("Found %d different software packages" % len(software), silent=silent) if only_installed: avail_mod_names = modules_tool().available() # rebuild software, only retain entries with a corresponding available module software, all_software = {}, software for key in all_software: for entry in all_software[key]: if entry['mod_name'] in avail_mod_names: software.setdefault(key, []).append(entry) print_msg("Retained %d installed software packages" % len(software), silent=silent) return generate_doc('list_software_%s' % output_format, [software, detailed])
def find_related_easyconfigs(path, ec): """ Find related easyconfigs for provided parsed easyconfig in specified path. A list of easyconfigs for the same software (name) is returned, matching the 1st criterion that yields a non-empty list. The following criteria are considered (in this order) next to common software version criterion, i.e. exact version match, a major/minor version match, a major version match, or no version match (in that order). (i) matching versionsuffix and toolchain name/version (ii) matching versionsuffix and toolchain name (any toolchain version) (iii) matching versionsuffix (any toolchain name/version) (iv) matching toolchain name/version (any versionsuffix) (v) matching toolchain name (any versionsuffix, toolchain version) (vi) no extra requirements (any versionsuffix, toolchain name/version) If no related easyconfigs with a matching software name are found, an empty list is returned. """ name = ec.name version = ec.version versionsuffix = ec['versionsuffix'] toolchain_name = ec['toolchain']['name'] toolchain_name_pattern = r'-%s-\S+' % toolchain_name toolchain_pattern = '-%s-%s' % (toolchain_name, ec['toolchain']['version']) if is_system_toolchain(toolchain_name): toolchain_name_pattern = '' toolchain_pattern = '' potential_paths = [ glob.glob(ec_path) for ec_path in create_paths(path, name, '*') ] potential_paths = sum(potential_paths, []) # flatten _log.debug("found these potential paths: %s" % potential_paths) parsed_version = LooseVersion(version).version version_patterns = [version] # exact version match if len(parsed_version) >= 2: version_patterns.append( r'%s\.%s\.\w+' % tuple(parsed_version[:2])) # major/minor version match if parsed_version != parsed_version[0]: version_patterns.append(r'%s\.[\d-]+\.\w+' % parsed_version[0]) # major version match version_patterns.append(r'[\w.]+') # any version regexes = [] for version_pattern in version_patterns: common_pattern = r'^\S+/%s-%s%%s\.eb$' % (re.escape(name), version_pattern) regexes.extend([ common_pattern % (toolchain_pattern + versionsuffix), common_pattern % (toolchain_name_pattern + versionsuffix), common_pattern % (r'\S*%s' % versionsuffix), common_pattern % toolchain_pattern, common_pattern % toolchain_name_pattern, common_pattern % r'\S*', ]) for regex in regexes: res = [p for p in potential_paths if re.match(regex, p)] if res: _log.debug("Related easyconfigs found using '%s': %s" % (regex, res)) break else: _log.debug("No related easyconfigs in potential paths using '%s'" % regex) return sorted(res)