comps-wrapper: Port to libcomps
Instead of replacing yum.comps with an something from DNF, we can go directly to libcomps. DNF does not have the equivalent functionality (particularly it's impossible to load comps from file directly). We would have depended on libcomps anyway transitively, so this is not a big deal. Fixes: #587 Signed-off-by: Lubomír Sedlář <lsedlar@redhat.com>
This commit is contained in:
parent
39c3f42f77
commit
3861be3e08
@ -17,6 +17,7 @@ BuildRequires: python-jsonschema
|
|||||||
BuildRequires: python-enum34
|
BuildRequires: python-enum34
|
||||||
BuildRequires: python2-dnf
|
BuildRequires: python2-dnf
|
||||||
BuildRequires: python2-multilib
|
BuildRequires: python2-multilib
|
||||||
|
BuildRequires: python2-libcomps
|
||||||
|
|
||||||
Requires: createrepo >= 0.4.11
|
Requires: createrepo >= 0.4.11
|
||||||
Requires: yum => 3.4.3-28
|
Requires: yum => 3.4.3-28
|
||||||
@ -44,6 +45,7 @@ Requires: libguestfs-tools-c
|
|||||||
Requires: python-enum34
|
Requires: python-enum34
|
||||||
Requires: python2-dnf
|
Requires: python2-dnf
|
||||||
Requires: python2-multilib
|
Requires: python2-multilib
|
||||||
|
Requires: python2-libcomps
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
|
@ -14,10 +14,12 @@
|
|||||||
# along with this program; if not, see <https://gnu.org/licenses/>.
|
# along with this program; if not, see <https://gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import collections
|
||||||
|
from operator import attrgetter
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import libcomps
|
||||||
|
import sys
|
||||||
import xml.dom.minidom
|
import xml.dom.minidom
|
||||||
import yum.comps
|
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info[:2] < (2, 7):
|
if sys.version_info[:2] < (2, 7):
|
||||||
@ -36,17 +38,25 @@ if sys.version_info[:2] < (2, 7):
|
|||||||
xml.dom.minidom.Element = Element
|
xml.dom.minidom.Element = Element
|
||||||
|
|
||||||
|
|
||||||
|
TYPE_MAPPING = collections.OrderedDict([
|
||||||
|
(libcomps.PACKAGE_TYPE_MANDATORY, 'mandatory'),
|
||||||
|
(libcomps.PACKAGE_TYPE_DEFAULT, 'default'),
|
||||||
|
(libcomps.PACKAGE_TYPE_OPTIONAL, 'optional'),
|
||||||
|
(libcomps.PACKAGE_TYPE_CONDITIONAL, 'conditional'),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
class CompsWrapper(object):
|
class CompsWrapper(object):
|
||||||
"""Class for reading and retreiving information from comps XML files"""
|
"""Class for reading and retreiving information from comps XML files"""
|
||||||
|
|
||||||
def __init__(self, comps_file):
|
def __init__(self, comps_file):
|
||||||
self.comps = yum.comps.Comps()
|
self.comps = libcomps.Comps()
|
||||||
self.comps.add(comps_file)
|
self.comps.fromxml_f(comps_file)
|
||||||
self.comps_file = comps_file
|
self.comps_file = comps_file
|
||||||
|
|
||||||
def get_comps_groups(self):
|
def get_comps_groups(self):
|
||||||
"""Return a list of group IDs."""
|
"""Return a list of group IDs."""
|
||||||
return [group.groupid for group in self.comps.get_groups()]
|
return [group.id for group in self.comps.groups]
|
||||||
|
|
||||||
def write_comps(self, comps_obj=None, target_file=None):
|
def write_comps(self, comps_obj=None, target_file=None):
|
||||||
if not comps_obj:
|
if not comps_obj:
|
||||||
@ -63,31 +73,20 @@ class CompsWrapper(object):
|
|||||||
doc = impl.createDocument(None, "comps", doctype)
|
doc = impl.createDocument(None, "comps", doctype)
|
||||||
msg_elem = doc.documentElement
|
msg_elem = doc.documentElement
|
||||||
|
|
||||||
groups = {}
|
for group in sorted(self.comps.groups, key=attrgetter('id')):
|
||||||
for group_obj in self.comps.get_groups():
|
|
||||||
groupid = group_obj.groupid
|
|
||||||
groups[groupid] = {"group_obj": group_obj}
|
|
||||||
|
|
||||||
group_names = groups.keys()
|
|
||||||
group_names.sort()
|
|
||||||
for group_key in group_names:
|
|
||||||
group = groups[group_key]["group_obj"]
|
|
||||||
group_node = doc.createElement("group")
|
group_node = doc.createElement("group")
|
||||||
msg_elem.appendChild(group_node)
|
msg_elem.appendChild(group_node)
|
||||||
|
|
||||||
id_node = doc.createElement("id")
|
id_node = doc.createElement("id")
|
||||||
id_node.appendChild(doc.createTextNode(group.groupid))
|
id_node.appendChild(doc.createTextNode(group.id))
|
||||||
group_node.appendChild(id_node)
|
group_node.appendChild(id_node)
|
||||||
|
|
||||||
name_node = doc.createElement("name")
|
name_node = doc.createElement("name")
|
||||||
name_node.appendChild(doc.createTextNode(group.name))
|
name_node.appendChild(doc.createTextNode(group.name))
|
||||||
group_node.appendChild(name_node)
|
group_node.appendChild(name_node)
|
||||||
|
|
||||||
langs = group.translated_name.keys()
|
for lang in sorted(group.name_by_lang):
|
||||||
langs.sort()
|
text = group.name_by_lang[lang]
|
||||||
|
|
||||||
for lang in langs:
|
|
||||||
text = group.translated_name[lang].decode("UTF-8")
|
|
||||||
node = doc.createElement("name")
|
node = doc.createElement("name")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
@ -95,13 +94,11 @@ class CompsWrapper(object):
|
|||||||
|
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
group_node.appendChild(node)
|
group_node.appendChild(node)
|
||||||
if group.description and group.description != "":
|
if group.desc and group.desc != "":
|
||||||
node.appendChild(doc.createTextNode(group.description))
|
node.appendChild(doc.createTextNode(group.desc))
|
||||||
langs = group.translated_description.keys()
|
|
||||||
langs.sort()
|
|
||||||
|
|
||||||
for lang in langs:
|
for lang in sorted(group.desc_by_lang):
|
||||||
text = group.translated_description[lang].decode("UTF-8")
|
text = group.desc_by_lang[lang]
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
@ -112,64 +109,60 @@ class CompsWrapper(object):
|
|||||||
group_node.appendChild(node)
|
group_node.appendChild(node)
|
||||||
|
|
||||||
node = doc.createElement("uservisible")
|
node = doc.createElement("uservisible")
|
||||||
node.appendChild(doc.createTextNode("true" if group.user_visible else "false"))
|
node.appendChild(doc.createTextNode("true" if group.uservisible else "false"))
|
||||||
group_node.appendChild(node)
|
group_node.appendChild(node)
|
||||||
|
|
||||||
if group.langonly:
|
if group.lang_only:
|
||||||
node = doc.createElement("langonly")
|
node = doc.createElement("langonly")
|
||||||
node.appendChild(doc.createTextNode(group.langonly))
|
node.appendChild(doc.createTextNode(group.lang_only))
|
||||||
group_node.appendChild(node)
|
group_node.appendChild(node)
|
||||||
|
|
||||||
packagelist = doc.createElement("packagelist")
|
packagelist = doc.createElement("packagelist")
|
||||||
|
|
||||||
for package_type in ("mandatory", "default", "optional", "conditional"):
|
packages_by_type = collections.defaultdict(list)
|
||||||
packages = getattr(group, package_type + "_packages").keys()
|
for pkg in group.packages:
|
||||||
packages.sort()
|
packages_by_type[TYPE_MAPPING[pkg.type]].append(pkg)
|
||||||
for package in packages:
|
|
||||||
|
for type_name in TYPE_MAPPING.values():
|
||||||
|
for package in sorted(packages_by_type[type_name], key=attrgetter('name')):
|
||||||
node = doc.createElement("packagereq")
|
node = doc.createElement("packagereq")
|
||||||
node.appendChild(doc.createTextNode(package))
|
node.appendChild(doc.createTextNode(package.name))
|
||||||
node.setAttribute("type", package_type)
|
node.setAttribute("type", type_name)
|
||||||
packagelist.appendChild(node)
|
packagelist.appendChild(node)
|
||||||
if package_type == "conditional":
|
if type_name == "conditional":
|
||||||
node.setAttribute("requires", group.conditional_packages[package])
|
node.setAttribute("requires", pkg.requires)
|
||||||
|
|
||||||
group_node.appendChild(packagelist)
|
group_node.appendChild(packagelist)
|
||||||
|
|
||||||
categories = self.comps.get_categories()
|
for category in self.comps.categories:
|
||||||
for category in categories:
|
groups = set(x.name for x in category.group_ids) & set(self.get_comps_groups())
|
||||||
groups = set(category.groups) & set([i.groupid for i in self.comps.get_groups()])
|
|
||||||
if not groups:
|
if not groups:
|
||||||
continue
|
continue
|
||||||
cat_node = doc.createElement("category")
|
cat_node = doc.createElement("category")
|
||||||
msg_elem.appendChild(cat_node)
|
msg_elem.appendChild(cat_node)
|
||||||
|
|
||||||
id_node = doc.createElement("id")
|
id_node = doc.createElement("id")
|
||||||
id_node.appendChild(doc.createTextNode(category.categoryid))
|
id_node.appendChild(doc.createTextNode(category.id))
|
||||||
cat_node.appendChild(id_node)
|
cat_node.appendChild(id_node)
|
||||||
|
|
||||||
name_node = doc.createElement("name")
|
name_node = doc.createElement("name")
|
||||||
name_node.appendChild(doc.createTextNode(category.name))
|
name_node.appendChild(doc.createTextNode(category.name))
|
||||||
cat_node.appendChild(name_node)
|
cat_node.appendChild(name_node)
|
||||||
|
|
||||||
langs = category.translated_name.keys()
|
for lang in sorted(category.name_by_lang):
|
||||||
langs.sort()
|
text = category.name_by_lang[lang]
|
||||||
|
|
||||||
for lang in langs:
|
|
||||||
text = category.translated_name[lang].decode("UTF-8")
|
|
||||||
node = doc.createElement("name")
|
node = doc.createElement("name")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
cat_node.appendChild(node)
|
cat_node.appendChild(node)
|
||||||
|
|
||||||
if category.description and category.description != "":
|
if category.desc and category.desc != "":
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
node.appendChild(doc.createTextNode(category.description))
|
node.appendChild(doc.createTextNode(category.desc))
|
||||||
cat_node.appendChild(node)
|
cat_node.appendChild(node)
|
||||||
langs = category.translated_description.keys()
|
|
||||||
langs.sort()
|
|
||||||
|
|
||||||
for lang in langs:
|
for lang in sorted(category.desc_by_lang):
|
||||||
text = category.translated_description[lang].decode("UTF-8")
|
text = category.desc_by_lang[lang]
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
@ -190,44 +183,37 @@ class CompsWrapper(object):
|
|||||||
|
|
||||||
cat_node.appendChild(grouplist_node)
|
cat_node.appendChild(grouplist_node)
|
||||||
|
|
||||||
# XXX
|
environments = sorted(self.comps.environments, key=attrgetter('id'))
|
||||||
environments = self.comps.get_environments()
|
|
||||||
if environments:
|
if environments:
|
||||||
for environment in environments:
|
for environment in environments:
|
||||||
groups = set(environment.groups) & set([i.groupid for i in self.comps.get_groups()])
|
groups = set(x.name for x in environment.group_ids) & set(self.get_comps_groups())
|
||||||
if not groups:
|
if not groups:
|
||||||
continue
|
continue
|
||||||
env_node = doc.createElement("environment")
|
env_node = doc.createElement("environment")
|
||||||
msg_elem.appendChild(env_node)
|
msg_elem.appendChild(env_node)
|
||||||
|
|
||||||
id_node = doc.createElement("id")
|
id_node = doc.createElement("id")
|
||||||
id_node.appendChild(doc.createTextNode(environment.environmentid))
|
id_node.appendChild(doc.createTextNode(environment.id))
|
||||||
env_node.appendChild(id_node)
|
env_node.appendChild(id_node)
|
||||||
|
|
||||||
name_node = doc.createElement("name")
|
name_node = doc.createElement("name")
|
||||||
name_node.appendChild(doc.createTextNode(environment.name))
|
name_node.appendChild(doc.createTextNode(environment.name))
|
||||||
env_node.appendChild(name_node)
|
env_node.appendChild(name_node)
|
||||||
|
|
||||||
langs = environment.translated_name.keys()
|
for lang in sorted(environment.name_by_lang):
|
||||||
langs.sort()
|
text = environment.name_by_lang[lang]
|
||||||
|
|
||||||
for lang in langs:
|
|
||||||
text = environment.translated_name[lang].decode("UTF-8")
|
|
||||||
node = doc.createElement("name")
|
node = doc.createElement("name")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
env_node.appendChild(node)
|
env_node.appendChild(node)
|
||||||
|
|
||||||
if environment.description:
|
if environment.desc:
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
node.appendChild(doc.createTextNode(environment.description))
|
node.appendChild(doc.createTextNode(environment.desc))
|
||||||
env_node.appendChild(node)
|
env_node.appendChild(node)
|
||||||
|
|
||||||
langs = environment.translated_description.keys()
|
for lang in sorted(environment.desc_by_lang):
|
||||||
langs.sort()
|
text = environment.desc_by_lang[lang]
|
||||||
|
|
||||||
for lang in langs:
|
|
||||||
text = environment.translated_description[lang].decode("UTF-8")
|
|
||||||
node = doc.createElement("description")
|
node = doc.createElement("description")
|
||||||
node.setAttribute("xml:lang", lang)
|
node.setAttribute("xml:lang", lang)
|
||||||
node.appendChild(doc.createTextNode(text))
|
node.appendChild(doc.createTextNode(text))
|
||||||
@ -246,26 +232,23 @@ class CompsWrapper(object):
|
|||||||
grouplist_node.appendChild(node)
|
grouplist_node.appendChild(node)
|
||||||
env_node.appendChild(grouplist_node)
|
env_node.appendChild(grouplist_node)
|
||||||
|
|
||||||
optionids = sorted(environment.options)
|
if environment.option_ids:
|
||||||
if optionids:
|
|
||||||
optionlist_node = doc.createElement("optionlist")
|
optionlist_node = doc.createElement("optionlist")
|
||||||
for optionid in optionids:
|
for optionid in sorted(x.name for x in environment.option_ids):
|
||||||
node = doc.createElement("groupid")
|
node = doc.createElement("groupid")
|
||||||
node.appendChild(doc.createTextNode(optionid))
|
node.appendChild(doc.createTextNode(optionid))
|
||||||
optionlist_node.appendChild(node)
|
optionlist_node.appendChild(node)
|
||||||
env_node.appendChild(optionlist_node)
|
env_node.appendChild(optionlist_node)
|
||||||
|
|
||||||
# XXX
|
if self.comps.langpacks:
|
||||||
langpacks = self.comps.get_langpacks()
|
|
||||||
if langpacks:
|
|
||||||
lang_node = doc.createElement("langpacks")
|
lang_node = doc.createElement("langpacks")
|
||||||
msg_elem.appendChild(lang_node)
|
msg_elem.appendChild(lang_node)
|
||||||
|
|
||||||
for langpack in sorted(langpacks, key=lambda x: x['name']):
|
for name in sorted(self.comps.langpacks):
|
||||||
match_node = doc.createElement("match")
|
match_node = doc.createElement("match")
|
||||||
match_node.setAttribute("name", langpack["name"])
|
match_node.setAttribute("name", name)
|
||||||
match_node.setAttribute("install", langpack["install"])
|
match_node.setAttribute("install", self.comps.langpacks[name])
|
||||||
lang_node.appendChild(match_node)
|
lang_node.appendChild(match_node)
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
@ -273,7 +256,7 @@ class CompsWrapper(object):
|
|||||||
if group_dict["default"] is not None:
|
if group_dict["default"] is not None:
|
||||||
group_obj.default = group_dict["default"]
|
group_obj.default = group_dict["default"]
|
||||||
if group_dict["uservisible"] is not None:
|
if group_dict["uservisible"] is not None:
|
||||||
group_obj.user_visible = group_dict["uservisible"]
|
group_obj.uservisible = group_dict["uservisible"]
|
||||||
|
|
||||||
def _tweak_env(self, env_obj, env_dict):
|
def _tweak_env(self, env_obj, env_dict):
|
||||||
if env_dict["display_order"] is not None:
|
if env_dict["display_order"] is not None:
|
||||||
@ -282,7 +265,7 @@ class CompsWrapper(object):
|
|||||||
# write actual display order back to env_dict
|
# write actual display order back to env_dict
|
||||||
env_dict["display_order"] = env_obj.display_order
|
env_dict["display_order"] = env_obj.display_order
|
||||||
# write group list back to env_dict
|
# write group list back to env_dict
|
||||||
env_dict["groups"] = env_obj.groups[:]
|
env_dict["groups"] = [g.name for g in env_obj.group_ids]
|
||||||
|
|
||||||
def filter_groups(self, group_dicts):
|
def filter_groups(self, group_dicts):
|
||||||
"""Filter groups according to group definitions in group_dicts.
|
"""Filter groups according to group definitions in group_dicts.
|
||||||
@ -295,33 +278,27 @@ class CompsWrapper(object):
|
|||||||
"""
|
"""
|
||||||
to_remove = []
|
to_remove = []
|
||||||
for group_obj in self.comps.groups:
|
for group_obj in self.comps.groups:
|
||||||
found = False
|
|
||||||
for group_dict in group_dicts:
|
for group_dict in group_dicts:
|
||||||
if group_dict["glob"]:
|
if group_dict["glob"]:
|
||||||
if fnmatch.fnmatch(group_obj.groupid, group_dict["name"]):
|
if fnmatch.fnmatch(group_obj.id, group_dict["name"]):
|
||||||
found = True
|
|
||||||
self._tweak_group(group_obj, group_dict)
|
self._tweak_group(group_obj, group_dict)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if group_obj.groupid == group_dict["name"]:
|
if group_obj.id == group_dict["name"]:
|
||||||
self._tweak_group(group_obj, group_dict)
|
self._tweak_group(group_obj, group_dict)
|
||||||
found = True
|
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
to_remove.append(group_obj)
|
||||||
|
|
||||||
if not found:
|
for group in to_remove:
|
||||||
to_remove.append(group_obj.groupid)
|
self.comps.groups.remove(group)
|
||||||
|
|
||||||
if to_remove:
|
|
||||||
for key, value in self.comps._groups.items():
|
|
||||||
if key in to_remove:
|
|
||||||
del self.comps._groups[key]
|
|
||||||
|
|
||||||
# Sanity check to report warnings on unused group_dicts
|
# Sanity check to report warnings on unused group_dicts
|
||||||
unmatched = set()
|
unmatched = set()
|
||||||
for group_dict in group_dicts:
|
for group_dict in group_dicts:
|
||||||
matcher = fnmatch.fnmatch if group_dict["glob"] else lambda x, y: x == y
|
matcher = fnmatch.fnmatch if group_dict["glob"] else lambda x, y: x == y
|
||||||
for group_obj in self.comps.groups:
|
for group_obj in self.comps.groups:
|
||||||
if matcher(group_obj.groupid, group_dict["name"]):
|
if matcher(group_obj.id, group_dict["name"]):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
unmatched.add(group_dict["name"])
|
unmatched.add(group_dict["name"])
|
||||||
@ -336,17 +313,12 @@ class CompsWrapper(object):
|
|||||||
"""
|
"""
|
||||||
to_remove = []
|
to_remove = []
|
||||||
for env_obj in self.comps.environments:
|
for env_obj in self.comps.environments:
|
||||||
found = False
|
|
||||||
for env_dict in env_dicts:
|
for env_dict in env_dicts:
|
||||||
if env_obj.environmentid == env_dict["name"]:
|
if env_obj.id == env_dict["name"]:
|
||||||
self._tweak_env(env_obj, env_dict)
|
self._tweak_env(env_obj, env_dict)
|
||||||
found = True
|
|
||||||
break
|
break
|
||||||
|
else:
|
||||||
|
to_remove.append(env_obj)
|
||||||
|
|
||||||
if not found:
|
for env in to_remove:
|
||||||
to_remove.append(env_obj.environmentid)
|
self.comps.environments.remove(env)
|
||||||
|
|
||||||
if to_remove:
|
|
||||||
for key, value in self.comps._environments.items():
|
|
||||||
if key in to_remove:
|
|
||||||
del self.comps._environments[key]
|
|
||||||
|
Loading…
Reference in New Issue
Block a user