2018-02-17 16:46:23 +00:00
|
|
|
#!/usr/bin/python3
|
2019-02-19 08:05:55 +00:00
|
|
|
# Usage: ./comps-sync.py /path/to/comps-f31.xml.in
|
2018-02-17 22:08:14 +00:00
|
|
|
#
|
|
|
|
# Can both remove packages from the manifest
|
|
|
|
# which are not mentioned in comps, and add packages from
|
|
|
|
# comps.
|
2018-02-17 16:46:23 +00:00
|
|
|
|
2019-04-13 12:02:56 +00:00
|
|
|
import os, sys, subprocess, argparse, shlex, json, yaml, re
|
2018-02-17 16:46:23 +00:00
|
|
|
import libcomps
|
|
|
|
|
|
|
|
def fatal(msg):
|
|
|
|
print >>sys.stderr, msg
|
|
|
|
sys.exit(1)
|
|
|
|
|
2019-04-07 10:25:53 +00:00
|
|
|
def format_pkgtype(n):
|
|
|
|
if n == libcomps.PACKAGE_TYPE_DEFAULT:
|
|
|
|
return 'default'
|
|
|
|
elif n == libcomps.PACKAGE_TYPE_MANDATORY:
|
|
|
|
return 'mandatory'
|
|
|
|
else:
|
|
|
|
assert False
|
|
|
|
|
|
|
|
def write_manifest(fpath, pkgs, include=None):
|
|
|
|
with open(fpath, 'w') as f:
|
|
|
|
f.write("# DO NOT EDIT! This content is generated from comps-sync.py\n")
|
|
|
|
if include is not None:
|
|
|
|
f.write("include: {}\n".format(include))
|
|
|
|
f.write("packages:\n")
|
|
|
|
for pkg in sorted(pkgs):
|
|
|
|
f.write(" - {}\n".format(pkg))
|
|
|
|
print("Wrote {}".format(fpath))
|
|
|
|
|
2018-02-17 16:46:23 +00:00
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument("--save", help="Write changes", action='store_true')
|
|
|
|
parser.add_argument("src", help="Source path")
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
2019-04-07 10:29:21 +00:00
|
|
|
print("Syncing packages common to all desktops:")
|
2018-07-15 18:10:38 +00:00
|
|
|
|
2019-04-07 10:25:53 +00:00
|
|
|
base_pkgs_path = 'fedora-common-ostree-pkgs.yaml'
|
2018-02-17 16:46:23 +00:00
|
|
|
with open(base_pkgs_path) as f:
|
2019-04-07 10:25:53 +00:00
|
|
|
manifest = yaml.safe_load(f)
|
2019-04-07 10:30:37 +00:00
|
|
|
manifest_packages = set(manifest['packages'])
|
2018-02-17 16:46:23 +00:00
|
|
|
|
2018-02-17 22:08:14 +00:00
|
|
|
with open('comps-sync-blacklist.yml') as f:
|
2018-07-15 18:10:38 +00:00
|
|
|
doc = yaml.safe_load(f)
|
2018-02-17 22:08:14 +00:00
|
|
|
comps_blacklist = doc['blacklist']
|
2018-02-24 20:29:07 +00:00
|
|
|
comps_whitelist = doc['whitelist']
|
2018-02-17 22:08:14 +00:00
|
|
|
comps_blacklist_groups = doc['blacklist_groups']
|
2018-07-15 18:10:38 +00:00
|
|
|
comps_desktop_blacklist = doc['desktop_blacklist']
|
2019-04-13 12:02:56 +00:00
|
|
|
comps_blacklist_all = [re.compile(x) for x in doc['blacklist_all_regexp']]
|
|
|
|
|
|
|
|
def is_blacklisted(pkgname):
|
|
|
|
for br in comps_blacklist_all:
|
|
|
|
if br.match(pkgname):
|
|
|
|
return True
|
|
|
|
return False
|
2018-02-17 22:08:14 +00:00
|
|
|
|
2018-02-17 16:46:23 +00:00
|
|
|
# Parse comps, and build up a set of all packages so we
|
|
|
|
# can find packages not listed in comps *at all*, beyond
|
|
|
|
# just the workstation environment.
|
|
|
|
comps = libcomps.Comps()
|
|
|
|
comps.fromxml_f(args.src)
|
|
|
|
|
|
|
|
# Parse the workstation-product environment, gathering
|
|
|
|
# default or mandatory packages.
|
2018-02-24 20:29:07 +00:00
|
|
|
ws_env_name = 'workstation-product-environment'
|
|
|
|
ws_ostree_name = 'workstation-ostree-support'
|
|
|
|
ws_environ = comps.environments[ws_env_name]
|
2018-02-17 16:46:23 +00:00
|
|
|
ws_pkgs = {}
|
|
|
|
for gid in ws_environ.group_ids:
|
|
|
|
group = comps.groups_match(id=gid.name)[0]
|
2018-02-17 22:08:14 +00:00
|
|
|
if gid.name in comps_blacklist_groups:
|
|
|
|
continue
|
|
|
|
blacklist = comps_blacklist.get(gid.name, set())
|
2018-02-17 16:46:23 +00:00
|
|
|
for pkg in group.packages:
|
|
|
|
pkgname = pkg.name
|
|
|
|
if pkg.type not in (libcomps.PACKAGE_TYPE_DEFAULT,
|
|
|
|
libcomps.PACKAGE_TYPE_MANDATORY):
|
|
|
|
continue
|
2019-04-13 12:02:56 +00:00
|
|
|
if pkgname in blacklist or is_blacklisted(pkgname):
|
2018-02-17 22:08:14 +00:00
|
|
|
continue
|
2018-02-17 16:46:23 +00:00
|
|
|
pkgdata = ws_pkgs.get(pkgname)
|
|
|
|
if pkgdata is None:
|
|
|
|
ws_pkgs[pkgname] = pkgdata = (pkg.type, set([gid.name]))
|
|
|
|
if (pkgdata[0] == libcomps.PACKAGE_TYPE_DEFAULT and
|
|
|
|
pkg.type == libcomps.PACKAGE_TYPE_MANDATORY):
|
|
|
|
ws_pkgs[pkgname] = pkgdata = (pkg.type, pkgdata[1])
|
|
|
|
pkgdata[1].add(gid.name)
|
|
|
|
|
2018-02-24 20:29:07 +00:00
|
|
|
ws_ostree_pkgs = set()
|
|
|
|
for pkg in comps.groups_match(id=ws_ostree_name)[0].packages:
|
2019-04-13 12:02:56 +00:00
|
|
|
if not is_blacklisted(pkg.name):
|
|
|
|
ws_ostree_pkgs.add(pkg.name)
|
2018-02-24 20:29:07 +00:00
|
|
|
|
2019-04-07 10:30:37 +00:00
|
|
|
comps_unknown = set()
|
2018-02-24 20:29:07 +00:00
|
|
|
for pkg in manifest_packages:
|
|
|
|
if (pkg not in comps_whitelist and
|
|
|
|
pkg not in ws_pkgs and
|
|
|
|
pkg not in ws_ostree_pkgs):
|
|
|
|
comps_unknown.add(pkg)
|
|
|
|
|
2018-02-17 16:46:23 +00:00
|
|
|
# Look for packages in the manifest but not in comps at all
|
|
|
|
n_manifest_new = len(comps_unknown)
|
|
|
|
if n_manifest_new == 0:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - All manifest packages are already listed in comps.")
|
2018-02-17 16:46:23 +00:00
|
|
|
else:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - {} packages not in {}:".format(n_manifest_new, ws_env_name))
|
2018-02-17 16:46:23 +00:00
|
|
|
for pkg in sorted(comps_unknown):
|
2019-04-07 10:29:21 +00:00
|
|
|
print(' {}'.format(pkg))
|
2018-02-17 16:46:23 +00:00
|
|
|
manifest_packages.remove(pkg)
|
|
|
|
|
|
|
|
# Look for packages in workstation but not in the manifest
|
|
|
|
ws_added = {}
|
|
|
|
for (pkg,data) in ws_pkgs.items():
|
|
|
|
if pkg not in manifest_packages:
|
|
|
|
ws_added[pkg] = data
|
2018-02-17 22:08:14 +00:00
|
|
|
manifest_packages.add(pkg)
|
2018-02-17 16:46:23 +00:00
|
|
|
|
|
|
|
n_comps_new = len(ws_added)
|
|
|
|
if n_comps_new == 0:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - All comps packages are already listed in manifest.")
|
2018-02-17 16:46:23 +00:00
|
|
|
else:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - {} packages not in manifest:".format(n_comps_new))
|
2018-02-17 16:46:23 +00:00
|
|
|
for pkg in sorted(ws_added):
|
|
|
|
(req, groups) = ws_added[pkg]
|
2019-04-07 10:29:21 +00:00
|
|
|
print(' {} ({}, groups: {})'.format(pkg, format_pkgtype(req), ', '.join(groups)))
|
2018-02-17 16:46:23 +00:00
|
|
|
|
|
|
|
if (n_manifest_new > 0 or n_comps_new > 0) and args.save:
|
2019-04-07 10:25:53 +00:00
|
|
|
write_manifest(base_pkgs_path, manifest_packages)
|
2018-07-15 18:10:38 +00:00
|
|
|
|
|
|
|
# Generate treefiles for all desktops
|
2019-04-06 17:05:13 +00:00
|
|
|
for desktop in [ 'gnome-desktop', 'kde-desktop', 'xfce-desktop', 'lxqt-desktop', 'deepin-desktop', 'pantheon-desktop']:
|
2018-07-15 18:10:38 +00:00
|
|
|
print()
|
2019-04-07 10:29:21 +00:00
|
|
|
print("Syncing packages for {}:".format(desktop))
|
2018-07-15 18:10:38 +00:00
|
|
|
|
2019-04-07 10:25:53 +00:00
|
|
|
manifest_path = '{}-pkgs.yaml'.format(desktop)
|
|
|
|
with open(manifest_path) as f:
|
|
|
|
manifest = yaml.safe_load(f)
|
2018-07-15 18:10:38 +00:00
|
|
|
manifest_packages = set(manifest['packages'])
|
|
|
|
|
2019-04-07 10:30:37 +00:00
|
|
|
# Filter packages in the comps desktop group using the blacklist
|
|
|
|
comps_group_pkgs = set()
|
2018-07-15 18:10:38 +00:00
|
|
|
for pkg in comps.groups_match(id=desktop)[0].packages:
|
|
|
|
pkgname = pkg.name
|
2019-04-07 10:30:37 +00:00
|
|
|
blacklist = comps_desktop_blacklist.get(desktop, set())
|
2019-04-13 12:02:56 +00:00
|
|
|
if pkgname in blacklist or is_blacklisted(pkgname):
|
2018-07-15 18:10:38 +00:00
|
|
|
continue
|
2019-04-07 10:30:37 +00:00
|
|
|
comps_group_pkgs.add(pkg.name)
|
2018-07-15 18:10:38 +00:00
|
|
|
|
2019-04-07 10:30:37 +00:00
|
|
|
# Look for packages in the manifest but not in comps group
|
|
|
|
comps_unknown = set()
|
2018-07-15 18:10:38 +00:00
|
|
|
for pkg in manifest_packages:
|
2019-04-07 10:30:37 +00:00
|
|
|
if pkg not in comps_group_pkgs:
|
2018-07-15 18:10:38 +00:00
|
|
|
comps_unknown.add(pkg)
|
|
|
|
|
|
|
|
n_manifest_new = len(comps_unknown)
|
|
|
|
if n_manifest_new == 0:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - All manifest packages are already listed in comps.")
|
2018-07-15 18:10:38 +00:00
|
|
|
else:
|
2019-04-07 10:30:37 +00:00
|
|
|
print(" - {} packages not in {} comps group:".format(n_manifest_new, desktop))
|
2018-07-15 18:10:38 +00:00
|
|
|
for pkg in sorted(comps_unknown):
|
2019-04-07 10:29:21 +00:00
|
|
|
print(' {}'.format(pkg))
|
2018-07-15 18:10:38 +00:00
|
|
|
manifest_packages.remove(pkg)
|
|
|
|
|
2018-08-07 18:56:47 +00:00
|
|
|
# Look for packages in comps but not in the manifest
|
2019-04-07 10:30:37 +00:00
|
|
|
desktop_pkgs_added = set()
|
|
|
|
for pkg in comps_group_pkgs:
|
2018-07-15 18:10:38 +00:00
|
|
|
if pkg not in manifest_packages:
|
2019-04-07 10:30:37 +00:00
|
|
|
desktop_pkgs_added.add(pkg)
|
2018-07-15 18:10:38 +00:00
|
|
|
|
2019-04-07 10:30:37 +00:00
|
|
|
n_comps_new = len(desktop_pkgs_added)
|
2018-07-15 18:10:38 +00:00
|
|
|
if n_comps_new == 0:
|
2019-04-07 10:29:21 +00:00
|
|
|
print(" - All comps packages are already listed in manifest.")
|
2018-07-15 18:10:38 +00:00
|
|
|
else:
|
2019-04-07 10:30:37 +00:00
|
|
|
print(" - {} packages not in {} manifest:".format(n_comps_new, desktop))
|
|
|
|
for pkg in sorted(desktop_pkgs_added):
|
2019-04-07 10:29:21 +00:00
|
|
|
print(' {}'.format(pkg))
|
2019-04-07 10:30:37 +00:00
|
|
|
manifest_packages.add(pkg)
|
2018-07-15 18:10:38 +00:00
|
|
|
|
2019-04-07 10:30:37 +00:00
|
|
|
# Update manifest
|
2018-07-15 18:10:38 +00:00
|
|
|
if (n_manifest_new > 0 or n_comps_new > 0) and args.save:
|
2019-04-07 10:25:53 +00:00
|
|
|
write_manifest(manifest_path, manifest_packages, include="fedora-common-ostree.yaml")
|