Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a597a81
chore: Add new top level comps/ dir, containing files used to generat…
ddstreet Mar 26, 2026
4515194
fix: remove ELN targets from comps/
ddstreet Mar 26, 2026
398d648
fix: remove all content in po/ and remove po target from Makefile
ddstreet Apr 7, 2026
6782eb0
fix: define SHELL in comps/Makefile
ddstreet Mar 26, 2026
700607f
feat: copy comps-f43.xml.in to comps-azl4.xml.in
ddstreet Apr 3, 2026
c4e6e56
feat: remove comps-azl4.xml.in langpacks except man-pages
ddstreet Apr 6, 2026
b70b21e
feat: remove comps-azl4.xml.in all categories
ddstreet Apr 3, 2026
b0c131c
feat: remove comps-azl4.xml.in unneeded environments
ddstreet Apr 3, 2026
8dc6ebf
feat: remove comps-azl4.xml.in unneeded groups
ddstreet Apr 3, 2026
ba541b9
feat: remove comps-azl4.xml.in 'critical-path' groups
ddstreet Apr 6, 2026
219437e
feat: remove comps-azl4.xml.in font groups
ddstreet Apr 6, 2026
df1413a
feat: remove comps-azl4.xml.in development groups
ddstreet Apr 6, 2026
c4ed203
feat: remove comps-azl4.xml.in cloud-infrastructure and cloud-managem…
ddstreet Apr 6, 2026
eb5aa93
feat: remove comps-azl4.xml.in container-management-tools group
ddstreet Apr 7, 2026
a1ba91c
feat: remove comps-azl4.xml.in ppc support
ddstreet Apr 6, 2026
f894fc7
feat: remove comps-azl4.xml.in s390x support
ddstreet Apr 6, 2026
3c6dac0
feat: remove comps-azl4.xml.in ia32 (32-bit x86) support
ddstreet Apr 6, 2026
e3c9b51
feat: remove comps-azl4.xml.in packages not provided in our repo
ddstreet Apr 6, 2026
333c31d
feat: remove comps-azl4.xml.in anaconda-tools group
ddstreet Apr 7, 2026
55c7e41
feat: remove comps-azl4.xml.in hardware-support group
ddstreet Apr 7, 2026
59809dd
feat: change comps-azl4.xml.in packages from mandatory or default to …
ddstreet Apr 7, 2026
0691b3b
feat: replace 'fedora' with 'azurelinux' in comps-azl4.xml.in
ddstreet Apr 6, 2026
58666aa
feat: add comps/.gitignore to ignore generated comps-*.xml file(s)
ddstreet Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions comps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
comps-*.xml
52 changes: 52 additions & 0 deletions comps/Fedora-README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Fedora Comps #

comps files are XML files used by various Fedora tools to perform grouping of packages into functional groups.

## How comps is used ##

### Installation ###

comps is used by the installer during package selection. On the Software Selection screen, environment groups (as defined by the `environment` keyword in `comps.xml`) are listed down the left-hand side. All optional groups (defined by the `group` keyword) for that environment (listed in the environment's `optionlist`) are shown at the top of the right-hand pane. Other groups which have `uservisible` set are displayed lower in the right-hand pane.

At install time, the installer will usually install the `mandatory`, `default` and appropriate `conditional` packages from all groups listed in the selected environment group's `grouplist`, plus those from any optional groups the user selected on the right-hand side. See below for more details on these 'levels'.

### Running System ###

In dnf, groups and environment groups are used by the `dnf group install` and `dnf group remove` commands, and can be queried with the `dnf group list` command. There are many others besides these: see the [dnf documentation](https://dnf.readthedocs.io/en/latest/index.html) for more on this.

### Tree, Release, and Image Composition ###

The kickstart files in [fedora-kickstarts](https://pagure.io/fedora-kickstarts.git) use the group and environment group definitions from comps. Multiple tools use these kickstarts to compose different types of images, and the release trees. The manifests for rpm-ostree-based Fedora variants in [workstation-ostree-config](https://pagure.io/workstation-ostree-config) (the name is a misnomer these days) are synced against comps using the `comps-sync.py` script, and used to define the package sets included in those variants.

### Package levels ###

In any group, there are four levels of packages: `optional`, `default`, `mandatory`, and `conditional`.

* `mandatory` - these packages must be installed for the group to be considered installed
* `default` - these packages are installed by default, but can be removed while the group is still considered installed
* `optional` - these packages are not installed by default, but can be pulled in by kickstart or dnf options
* `conditional` - these packages are brought in if their `requires` package is installed

When using the interactive installer, you cannot include `optional` packages. However, if using a kickstart, you can add the `--optional` option for a group to specify that its optional packages should be included. Similarly, when installing a group with `dnf`, you can pass `--with-optional` to include the optional packages.

### Categories ###

Categories are barely used any more. They used to be something like environment groups for an older form of the Fedora installer. Some older graphical package management tools can still display these categories.

### Developing comps ###

For Fedora packagers:

git clone ssh://git@pagure.io/fedora-comps.git

For others:

git clone https://pagure.io/fedora-comps.git

When changing the packages, make sure the file is sorted. This helps to make it more maintainable. Use `make sort` command to fix the sorting. Also run `make validate` to check for XML syntax errors. You can submit pull requests using the common Github-style workflow - fork the repository from [the web UI](https://pagure.io/fedora-comps), push your changes to your fork, and submit a pull request for it. If you are not familiar with this workflow, see the [Pagure documentation](https://docs.pagure.org/pagure/usage/pull_requests.html).

## For more info ##

For more information, including rules on how and when to edit comps, see the [Fedora project wiki](https://fedoraproject.org/wiki/How_to_use_and_edit_comps.xml_for_package_groups).

Bugs against comps can be filed as Pagure [issues](https://pagure.io/fedora-comps/issues).
40 changes: 40 additions & 0 deletions comps/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
SHELL = /bin/bash
XMLINFILES=$(wildcard *.xml.in)
XMLFILES = $(patsubst %.xml.in,%.xml,$(XMLINFILES))

all: $(XMLFILES) sort

clean:
@rm -fv *~ *.xml

validate: $(XMLFILES) comps.rng
# Run xmllint on each file and exit with non-zero if any validation fails
RES=0; for f in $(XMLFILES); do \
xmllint --noout --relaxng comps.rng $$f; \
RES=$$(($$RES + $$?)); \
done; exit $$RES

sort:
@# Run xsltproc on each xml.in file and exit with non-zero if any sorting fails
@# The comps-eln.xml.in is not sorted alphabetically but manually
@# based on the need needs of Fedora ELN SIG.
@RES=0; for f in $(XMLINFILES); do \
if [[ "$$f" == 'comps-eln.xml.in' ]]; then \
continue; \
fi; \
xsltproc --novalid -o $$f comps-cleanup.xsl $$f; \
RES=$$(($$RES + $$?)); \
done; exit $$RES

.PHONY: comps-eln.xml.in
comps-eln.xml.in: comps-eln.xml.in.in
./update-eln-extras-comps comps-eln.xml.in.in comps-eln.xml.in

%.xml: %.xml.in
@xmllint --noout $<
@if test ".$(CLEANUP)" == .yes; then xsltproc --novalid -o $< comps-cleanup.xsl $<; fi
./update-comps $@

# Add an easy alias to generate a rawhide comps file
comps-rawhide.xml comps-rawhide: comps-f45.xml
@mv comps-f45.xml comps-rawhide.xml
8 changes: 8 additions & 0 deletions comps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# comps

The files here are taken from https://pagure.io/fedora-comps and
reduced/modified for AzureLinux. Use "make" to generate the
comps-*.xml file(s) from the comps-*.xml.in file(s). The resulting
comps-*.xml file must be included in the corresponding repo created
using "createrepo -g comps-DISTRO.xml", for example for AzureLinux 4:
"createrepo -g comps-azl4.xml".
157 changes: 157 additions & 0 deletions comps/check-missing
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/bin/python3

# This script looks for the comps-fXX.xml.in file for the release version
# specified, grabs lists of all packages that exist in that release of
# Fedora, and looks through the comps `pkgreq` lines for ones that specify
# packages that do not currently exist . It is arch-aware. It expects to
# be run on a Fedora system with network access, as it will try to query
# the dnf repos to get lists of currently-existing packages. It relies on
# the non-Rawhide repo definitions actually working for Rawhide if passed
# the Rawhide-matching release number, which is a kinda undocumented
# feature but we rely on it in other places too. You will need
# fedora-repos and python3-lxml packages installed.

import glob
import argparse
import subprocess
import sys
import lxml.etree as ET
from collections import defaultdict

ARCHES = ('aarch64', 'ppc64le', 's390x', 'x86_64')

parser = argparse.ArgumentParser(description='Check Fedora comps files for missing packages and packages missing on architectures')
parser.add_argument('relver', help='Release version to check')
parser.add_argument('--update', dest='update', action='store_true', default=False,
help='Update the comps file with the changes')
args = parser.parse_args()

# gather package lists. this eats lots of RAM. I don't care.
# FIXME: for this script to work for EPEL and ELN someone would have
# to figure out the right tweaks to this command line.
pkgs = {}
for arch in ARCHES:
pkgtext = subprocess.run(('dnf', f'--forcearch={arch}', f'--releasever={args.relver}', '--disablerepo=*', '--enablerepo=fedora', '--enablerepo=updates', '--enablerepo=fedora-cisco-openh264', 'repoquery', '--qf=%{NAME}\n'), capture_output=True, text=True).stdout
pkgs[arch] = pkgtext.splitlines()

compsfile = f'comps-f{args.relver}.xml.in'

# find package reqs in comps
tree = ET.parse(compsfile) #, ET.XMLParser(target=CommentedTreeBuilder()))
root = tree.getroot()
pkgreqs = root.findall('.//packagereq')

# Check if each package is in the repository for each architecture
removedpkgs = defaultdict(list)
archpkgs = defaultdict(list)
for pkgreq in pkgreqs:
reqtype = pkgreq.get('type', '')
# list of arches the package is missing on
missing = []
present = []

# arches the package is listed for (if no 'arch' key, it's listed for all)
reqarches = pkgreq.get('arch', '')
if reqarches:
reqarches = reqarches.split(',')
else:
reqarches = ARCHES

# do the actual check, append arch to 'missing' if it's not there
for arch in reqarches:
if arch in pkgs and pkgreq.text not in pkgs[arch]:
missing.append(arch)
else:
present.append(arch)

grpid = pkgreq.find('./../../id').text
pkgname = pkgreq.text

# print the result
if missing and not present:
if pkgreq.getparent() is not None:
removedpkgs[pkgname].append(grpid)
pkgreq.getparent().remove(pkgreq)
elif missing and reqtype != 'optional':
archpkgs[pkgname] = ','.join(present)

# Find empty groups after packages not in repositories have been removed
pkglists = root.findall('.//packagelist')
removedgrps = {}
for pkglist in pkglists:
if not len(pkglist):
group = pkglist.getparent()
grpid = group.find('./id').text
removedgrps[grpid] = []
group.getparent().remove(group)


# Remove any empty groups from the environment lists
envlists = root.findall('.//environment//groupid')
for envgrp in envlists:
grpid = envgrp.text
if grpid in removedgrps:
# The groups are inside a grouplist inside the environment
par = envgrp.getparent()
envid = par.getparent().find('./id').text
removedgrps[grpid].append(envid)
par.remove(envgrp)


# Remove any empty groups from the category lists
catlists = root.findall('.//category//groupid')
for catgrp in catlists:
grpid = catgrp.text
if grpid in removedgrps:
# The groups are inside a grouplist inside the category
par = catgrp.getparent()
catid = par.getparent().find('./id').text
removedgrps[grpid].append(catid)
par.remove(catgrp)


# Remove any language packs for packages that don't exist anymore
langpacks = root.find('.//langpacks')
removedlang = []
for lang in langpacks.getchildren():
pkg = lang.get('name')
if pkg in list(removedpkgs):
removedlang.append(pkg)
lang.getparent().remove(lang)

# Print out a summary
if archpkgs:
print('Packages with incorrect architecture tags:')
for pkg in sorted(archpkgs):
print(' {} only available on {}'.format(pkg, archpkgs[pkg]))
print()

if removedpkgs:
print('Removing packages:')
for pkg in sorted(removedpkgs):
print(' {} in group {}'.format(pkg, ', '.join(removedpkgs[pkg])))
print()

if removedgrps:
print('Removing empty groups:')
for group in sorted(removedgrps):
print(' {} in {}'.format(group, ', '.join(removedgrps[group])))
print()

if removedlang:
print('Removing language packs for:')
for lang in removedlang:
print(' {}'.format(lang))
print()

if not archpkgs and not removedpkgs and not removedgrps and not removedlang:
print("No problems found!")

# Write out the updated XML file if desired
if args.update:
tree.write(compsfile, encoding="UTF-8", xml_declaration=True)
sys.exit(0)

if archpkgs or removedpkgs or removedgrps or removedlang:
sys.exit(1)
sys.exit(0)
Loading
Loading