| |
@@ -24,12 +24,16 @@
|
| |
gi.require_version('Modulemd', '1.0') # noqa: E402
|
| |
from gi.repository import Modulemd
|
| |
|
| |
+ import tempfile
|
| |
import smartcols
|
| |
+ from fnmatch import fnmatch
|
| |
+ from click import ClickException
|
| |
+ from collections import defaultdict
|
| |
|
| |
- from . import _repodata
|
| |
+ from . import _repodata, _fetchrepodata
|
| |
|
| |
|
| |
- def _print_summary(profiles, sdefaults, pdefaults, deps, restrict_to, as_tree):
|
| |
+ def _print_summary(profiles, sdefaults, pdefaults, deps, mfilter, as_tree):
|
| |
tb = smartcols.Table()
|
| |
cl = tb.new_column('Name')
|
| |
cl.tree = as_tree
|
| |
@@ -40,11 +44,11 @@
|
| |
cl_deps = tb.new_column('Dependencies')
|
| |
parent_ln = {}
|
| |
for nsvc, plist in sorted(profiles.items()):
|
| |
- modname, sname, version, context = nsvc.split(':')
|
| |
-
|
| |
- if restrict_to and modname not in restrict_to:
|
| |
+ if mfilter and not any((fnmatch(nsvc, p) for p in mfilter)):
|
| |
continue
|
| |
|
| |
+ modname, sname, version, context = nsvc.split(':')
|
| |
+
|
| |
def is_def_strm(s):
|
| |
return s == sdefaults.get(modname, '')
|
| |
|
| |
@@ -81,57 +85,74 @@
|
| |
print('\nHint: [d]efault')
|
| |
|
| |
|
| |
- def _add_module_metadata(yaml_files, profiles, dstreams, dprofiles, deps):
|
| |
- for yaml in yaml_files:
|
| |
- assert yaml.endswith('.yaml'), "Not a yaml file: {}".format(yaml)
|
| |
-
|
| |
- mmd_index, failures = Modulemd.index_from_file(yaml)
|
| |
- assert len(failures) == 0, failures
|
| |
-
|
| |
- for module_name, index in mmd_index.items():
|
| |
- for module in index.get_streams().values():
|
| |
- # local modulemd files might miss some info like context or
|
| |
- # version. So let's make sure nsvc is consistent
|
| |
- ctxt = module.get_context() or ''
|
| |
- nsvc = f'{module_name}:{module.get_stream()}:' \
|
| |
- f'{module.get_version()}:{ctxt}'
|
| |
- plist = list(module.get_profiles().keys())
|
| |
- profiles[nsvc] = sorted(set(profiles.get(nsvc, []) + plist))
|
| |
-
|
| |
- for dep in module.get_dependencies():
|
| |
- deplist = set(deps.get(nsvc, []))
|
| |
- for m, s in dep.peek_requires().items():
|
| |
- deplist.add(f"{m}:{','.join(s.get())}"
|
| |
- if len(s.get()) else m)
|
| |
- deps[nsvc] = sorted(deplist)
|
| |
-
|
| |
- defaults = index.get_defaults()
|
| |
- if not defaults:
|
| |
- continue
|
| |
+ def _parse_mmd(mmd_index, profiles, dstreams, dprofiles, deps):
|
| |
+ for index in mmd_index:
|
| |
+ module_name = index.get_name()
|
| |
+ for module in index.get_streams().values():
|
| |
+ # local modulemd files might miss some info like context or
|
| |
+ # version. So let's make sure nsvc is consistent
|
| |
+ ctxt = module.get_context() or ''
|
| |
+ nsvc = f'{module_name}:{module.get_stream()}:' \
|
| |
+ f'{module.get_version()}:{ctxt}'
|
| |
+ plist = list(module.get_profiles().keys())
|
| |
+ profiles[nsvc] = sorted(set(profiles.get(nsvc, []) + plist))
|
| |
+
|
| |
+ for dep in module.get_dependencies():
|
| |
+ deplist = set(deps.get(nsvc, []))
|
| |
+ for m, s in dep.peek_requires().items():
|
| |
+ deplist.add(f"{m}:{','.join(s.get())}"
|
| |
+ if len(s.get()) else m)
|
| |
+ deps[nsvc] = sorted(deplist)
|
| |
+
|
| |
+ defaults = index.get_defaults()
|
| |
+ if not defaults:
|
| |
+ continue
|
| |
|
| |
- # Local module metadata can overwrite metadata from repo
|
| |
- dstreams[module_name] = defaults.peek_default_stream()
|
| |
- for s, pset in defaults.peek_profile_defaults().items():
|
| |
- dprofiles[module_name][s] = pset.get()
|
| |
+ # Local module metadata can overwrite metadata from repo
|
| |
+ dstreams[module_name] = defaults.peek_default_stream()
|
| |
+ for s, pset in defaults.peek_profile_defaults().items():
|
| |
+ dprofiles[module_name][s] = pset.get()
|
| |
|
| |
|
| |
- def summarize_modules(restrict_list=None, yaml_files=None, as_tree=False):
|
| |
+ def summarize_modules(mfilter=None, yamls=None, urls=None, as_tree=False):
|
| |
"""
|
| |
- Load Modulemd objects from each repository in repo_list and print a summary
|
| |
- of the modules found with a summary of their streams and profiles.
|
| |
+ Load Modulemd objects from each yaml file in the `yamls` list or each url
|
| |
+ in `urls` list and print a summary of the modules found with streams,
|
| |
+ context, version, profiles and dependencies information.
|
| |
+ If no files and no ulrs are passed, local cached metadata is used instead.
|
| |
|
| |
- *restrict_list*: if present, restricts output to modules supplied
|
| |
+ *mfilter*: if present, restricts output to the nsvc supplied. Glob pattern
|
| |
+ can be used, e.g for filtering by stream: '*:master:*'
|
| |
|
| |
- *yaml_files*: additional yaml files to parse and include in the summary
|
| |
- """
|
| |
+ *yamls*: list of yaml files to parse. If any, locally cached metadata will
|
| |
+ be ignored
|
| |
|
| |
- profiles = _repodata.get_modules_profiles_lookup().copy()
|
| |
- dstreams = _repodata.get_modules_default_streams_lookup().copy()
|
| |
- dprofiles = _repodata.get_modules_default_profiles_lookup().copy()
|
| |
- deps = _repodata.get_modules_dependencies_lookup().copy()
|
| |
+ *urls*: list of repositories to read from. If any, locally cached metadata
|
| |
+ will be ignored.
|
| |
|
| |
- if yaml_files:
|
| |
- _add_module_metadata(yaml_files, profiles, dstreams, dprofiles, deps)
|
| |
+ *as_tree*: print the summary in tree format, grouping information.
|
| |
+ """
|
| |
|
| |
- restrict_list = restrict_list or []
|
| |
- _print_summary(profiles, dstreams, dprofiles, deps, restrict_list, as_tree)
|
| |
+ profiles, dstreams, dprofiles, deps = {}, {}, defaultdict(dict), {}
|
| |
+ if yamls:
|
| |
+ for yaml in yamls:
|
| |
+ index, failures = Modulemd.index_from_file(yaml)
|
| |
+ if len(failures) != 0:
|
| |
+ msgs = "\n".join((str(f.get_gerror()) for f in failures))
|
| |
+ raise ClickException(f"Could not read {yaml}: {msgs}")
|
| |
+ _parse_mmd(index.values(), profiles, dstreams, dprofiles, deps)
|
| |
+ elif urls:
|
| |
+ for url in urls:
|
| |
+ with tempfile.TemporaryDirectory() as local_path:
|
| |
+ rp = _fetchrepodata.RepoPaths(url, local_path)
|
| |
+ _fetchrepodata._download_metadata_files(rp)
|
| |
+ indexes = _fetchrepodata._read_modules(rp)
|
| |
+ _parse_mmd(indexes, profiles, dstreams, dprofiles, deps)
|
| |
+ else:
|
| |
+ profiles = _repodata.get_modules_profiles_lookup()
|
| |
+ dstreams = _repodata.get_modules_default_streams_lookup()
|
| |
+ dprofiles = _repodata.get_modules_default_profiles_lookup()
|
| |
+ deps = _repodata.get_modules_dependencies_lookup()
|
| |
+
|
| |
+ mfilter = mfilter or []
|
| |
+ _print_summary(profiles, dstreams, dprofiles, deps, mfilter, as_tree)
|
| |