#!/usr/bin/python3 -t # newrepo: create new repositories # newrepo distro.archbits import os import re import sys from collections import defaultdict from functools import cmp_to_key from optparse import OptionParser from shutil import rmtree from subprocess import call # Hardcode the repo path and URL for now # Note that this script creates the archive area directories, unlike debugrepo repo_path = "/home/paul/cfo-repo" repo_url = "http://www.city-fan.org/ftp/contrib/" repo_name = "city-fan.org repository" archive_dir = "ARCHIVE" # List of regexes of directories we don't want to look in for packages to populate the repositories dirpaths_to_exclude = [ 'buildsys', 'drivers/pptp/(OLD|pre-built)', 'drivers/Samsung-ML4500', 'yum-repo/.*' ] # Package exclusion regex list # # Each entry is a tuple of regexes for name, version, release, dist, repo-arch # Packages matching ALL entries in a tuple are excluded from the repos for dist # Note: to match i386/i486/i586/i686 repo-arch, use ix86 # ANY = '.' packages_to_exclude = [ # build system hacks (ANY, ANY, 'buildsys_hack', ANY, ANY), ('^kernel-dummy$', ANY, ANY, ANY, ANY), # dovecot 1.x ('^dovecot', '^1[.]', ANY, ANY, ANY), # Java SRPMs; don't want them prior to EL-5/F-7 ('^java-', ANY, ANY, '^(fc[4-6])$', ANY), # Kernel modules ('^kernel-advansys$', ANY, ANY, ANY, ANY), ('^kernel-mppe$', ANY, ANY, ANY, ANY), ('^kernel_ppp_mppe$', ANY, ANY, ANY, ANY), # pptpconfig builds for Mandriva or SuSE ('^pptpconfig$', ANY, '(mdk|suse)', ANY, ANY), # dkms is generally up to date and with dist tag from Fedora 6, EPEL-4 # Using upstream dkms package from FC-6 onwards and RHEL too ('^dkms$', ANY, ANY, '^(fc([6-9]|[1-9][0-9])|rhel[0-9]*)$', ANY), # hot-babe would have broken dependencies from F-19, and it's not an enterprise package ('^hot-babe', ANY, ANY, '^(rhel[0-9][0-9]*|fc19|fc[2-9][0-9][0-9]*)$', ANY), # Exclude all compat autotools packages ('^autoconf260$', ANY, ANY, ANY, ANY), ('^automake19$', ANY, ANY, ANY, ANY), ('^automake110$', ANY, ANY, ANY, ANY), # We have bittorrent 5.x on all supported repos, so exclude bittorrent 4.x ('^bittorrent', '^4[.]', ANY, ANY, ANY), # Dropping all bittorrent support from F-19 ('^(bittorrent|compat-wx)', ANY, ANY, '^(fc19|fc[2-9][0-9]|rhel[7-9])$', ANY), ('^(pyserial|python-fpconst|python-pyasn1|python-twisted|python-zope-interface)', ANY, ANY, '^(fc19|fc[2-9][0-9]|rhel[7-9])$', ANY), ('^(python-crypto|python3-crypto|gtorrentviewer|torrentsniff)', ANY, ANY, '^(fc19|fc[2-9][0-9]|rhel[7-9])$', ANY), # Only need SOAPpy for RHEL-5 ('^SOAPpy$', ANY, ANY, '^(fc[0-9]*|rhel[6-9])$', ANY), # plusnet-fttc starts at F-17 ('^plusnet-fttc$', ANY, ANY, '^(fc[4-9]|fc1[0-6]|rhel[3-6])$', ANY), # Don't want python-setuptools* in F-13 onwards ('^python-setuptools$', ANY, ANY, '^(fc([2-9][0-9]|1[3-9])|rhel[7-9])$', ANY), # Drop old, unsupported sendmail-milter-spf and perl-Mail-SPF-Query ('^(sendmail-milter-spf|perl-Mail-SPF-Query)$', ANY, ANY, ANY, ANY), # DSBL is long dead, drop from Fedora 32 repos onwards ('^(dsbl-testers|ecncheck|firedns|firedns-devel|firedns-progs|firestring|firestring-devel|lckdo|proxycheck)$', ANY, ANY, '^(rhel[89]|fc3[2-9]|fc[4-9][0-9])$', ANY), # fetchyahoo is broken and unmaintained ('^fetchyahoo$', ANY, ANY, ANY, ANY), # Don't want proftpd release candidates in the repo ('^proftpd', ANY, '[.]rc[0-9][0-9]*', '^(fc[0-9]*|rhel[0-9]*)$', ANY), # pptpconfig dependencies not buildable on EL-8 as ORBit needs glibc-static # Dropping support for it and (most of) the Gnome 1 stack from Fedora 32 onwards ('^pptpconfig$', ANY, ANY, '^(rhel[89]|fc3[2-9]|fc[4-9][0-9])$', ANY), # yum-arch needs python2-rpm (rpm-python), which does not exist from Fedora 32 ('^yum-arch', ANY, ANY, '^fc3[2-9]$', ANY), # Drop spfmilter and compat-libspf2 from Fedora 32, RHEL-8 onwards (should have happened years ago) ('^(compat-libspf2|spfmilter)', ANY, ANY, '^(rhel[89]|fc3[2-9]|fc[4-9][0-9])$', ANY), # Don't let noarch epel7 packages for i386 support reach the x86_64 repo ('^(python2-six|python36-(nose|ply|py|pycparser|pytest|six)|epel-rpm-macros|libspf2-apidoc|lua-srpm-macros)', ANY, ANY, '^rhel7$', '^x86_64$'), # epel-rpm-macros and lua-srpm-macros don't have dist tags ('^(epel-rpm|lua-srpm)-macros', ANY, ANY, '^(fc[0-9]*|rhel[^7])$', ANY), # Java support dropped for libidn on ix86 from F-37 ('^libidn-java', ANY, ANY, '^fc(3[7-9]|[4-9][0-9])$', '^ix86$'), # ix86 build of dovecot dropped from F-41 (and maybe F-40) ('^dovecot', ANY, ANY, '^fc(4[1-9]|[5-9][0-9])$', '^ix86$'), # ix86 build of php dropped from F-41 ('^(contagged|php-)', ANY, ANY, '^fc(4[1-9]|[5-9][0-9])$', '^ix86$'), # Legacy tool package rpm-utils uses getopts.pl, which recent perls don't provide ('^rpm-utils', ANY, ANY, '^(fc([2-9][0-9])|rhel[7-9])$', ANY) ] # Other globals dry_run = False no_old_pkgs = False skip_generic_pkg_check = False rawhide = 'Fedora Development' # How to use newrepo usage_string = "newrepo: usage: newrepo [-n] [-o] [-f fromdist] [-t todist] [-x dist_regex] [distro[.bits]]" # This might not be needed in view of parseArgs below def usage(stream = sys.stdout): print(usage_string, file = stream) # Process optional args def parseArgs(): parser = OptionParser(usage = usage_string) parser.add_option('-n', '--dry-run', default = False, dest = 'dry_run', action = 'store_true', help = "dry-run mode: show what would be done but don't actually do it") parser.add_option('-f', '--from', default = 'fc19', dest = 'from_rel', help = "set starting release for repository (default: fc19)") parser.add_option('-o', '--no-old-packages', default = False, dest = 'no_old_pkgs', action = 'store_true', help = "exclude packages from older releases for development repos") parser.add_option('-t', '--to', default = 'development', dest = 'to_rel', help="set ending release for repository (default: development)") parser.add_option('-x', '--regex', default = None, dest = 'rel_regex', help="specify releases for repository by regex") (opts, args) = parser.parse_args() return (opts, args) # Supported distributions and their configuration # Some of this data is inherited from "mb", won't be used and will be removed # the multilib stuff needs tidying too # At EOL, set 'archive', and 'status' to 'eol-migrate' for a week or so to allow # mirrors to sync packages hardlinked to archive area, then set 'status' to 'eol' # to remove EOL packages from main tree distros = { 'fc4': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 13, 'rel': 20050613, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-4', 'status': 'eol', 'name': 'Fedora Core 4', 'multilib': set([ 'c-ares', 'curl', 'libcares140', 'libcurl', 'libcurl7112', 'libcurl7155', 'libidn', 'libssh2' ]) }, 'fc5': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 14, 'rel': 20060320, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-5', 'status': 'eol', 'name': 'Fedora Core 5', 'multilib': set([ 'c-ares', 'curl', 'libcares140', 'libcurl', 'libcurl7112', 'libcurl7155', 'libidn', 'libmetalink', 'libssh2', 'xz-libs' ]) }, 'fc6': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 15, 'rel': 20061024, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-6', 'status': 'eol', 'name': 'Fedora Core 6', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcares140', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc7': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 16, 'rel': 20070531, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-7', 'status': 'eol', 'name': 'Fedora 7', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcares140', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc8': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 17, 'rel': 20071108, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-8', 'status': 'eol', 'name': 'Fedora 8', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcares140', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc9': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 18, 'rel': 20080513, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'FC-9', 'status': 'eol', 'name': 'Fedora 9', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc10': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 19, 'rel': 20081125, 'compress': 'bz2', 'archive': 'FC-10', 'status': 'eol', 'name': 'Fedora 10', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc11': { 'archlist': [ { 'id': '32', 'arch': 'i586', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 20, 'rel': 20090619, 'compress': 'bz2', 'archive': 'FC-11', 'status': 'eol', 'name': 'Fedora 11', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc12': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 21, 'rel': 20091117, 'compress': 'bz2', 'archive': 'FC-12', 'status': 'eol', 'name': 'Fedora 12', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc13': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 22, 'rel': 20100525, 'compress': 'bz2', 'archive': 'FC-13', 'status': 'eol', 'name': 'Fedora 13', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc14': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 23, 'rel': 20101102, 'compress': 'bz2', 'archive': 'FC-14', 'status': 'eol', 'name': 'Fedora 14', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc15': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 24, 'rel': 20110524, 'compress': 'bz2', 'archive': 'FC-15', 'status': 'eol', 'name': 'Fedora 15', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc16': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 25, 'rel': 20111108, 'compress': 'gz', 'archive': 'FC-16', 'status': 'eol', 'name': 'Fedora 16', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc17': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 26, 'rel': 20120529, 'compress': 'gz', 'archive': 'FC-17', 'status': 'eol', 'name': 'Fedora 17', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc18': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 27, 'rel': 20130115, 'compress': 'gz', 'archive': 'FC-18', 'status': 'eol', 'name': 'Fedora 18', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc19': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 28, 'rel': 20130702, 'compress': 'gz', 'archive': 'FC-19', 'status': 'eol', 'name': 'Fedora 19', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc20': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 29, 'rel': 20131217, 'compress': 'gz', 'archive': 'FC-20', 'status': 'eol', 'name': 'Fedora 20', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc21': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 30, 'rel': 20141209, 'compress': 'gz', 'archive': 'FC-21', 'status': 'eol', 'name': 'Fedora 21', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc22': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 31, 'rel': 20150526, 'compress': 'gz', 'archive': 'FC-22', 'status': 'eol', 'name': 'Fedora 22', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc23': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 32, 'rel': 20151103, 'compress': 'gz', 'archive': 'FC-23', 'status': 'eol', 'name': 'Fedora 23', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'fc24': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 33, 'rel': 20160621, 'compress': 'gz', 'archive': 'FC-24', 'status': 'eol', 'name': 'Fedora 24', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc25': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 34, 'rel': 20161122, 'compress': 'gz', 'archive': 'FC-25', 'status': 'eol', 'name': 'Fedora 25', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc26': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 35, 'rel': 20170711, 'compress': 'gz', 'archive': 'FC-26', 'status': 'eol', 'name': 'Fedora 26', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcurl', 'libcurl-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc27': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 36, 'rel': 20171114, 'compress': 'gz', 'archive': 'FC-27', 'status': 'eol', 'name': 'Fedora 27', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc28': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 37, 'rel': 20180501, 'compress': 'gz', 'name': 'Fedora 28', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc29': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 38, 'rel': 20181030, 'compress': 'gz', 'name': 'Fedora 29', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc30': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 39, 'rel': 20190430, 'compress': 'gz', 'name': 'Fedora 30', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc31': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 40, 'rel': 20191029, 'compress': 'gz', 'name': 'Fedora 31', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc32': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 41, 'rel': 20200428, 'compress': 'gz', 'name': 'Fedora 32', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc33': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 42, 'rel': 20201027, 'compress': 'gz', 'name': 'Fedora 33', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc34': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 43, 'rel': 20210424, 'compress': 'gz', 'name': 'Fedora 34', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc35': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 44, 'rel': 20211102, 'compress': 'gz', 'name': 'Fedora 35', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc36': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 45, 'rel': 20220510, 'compress': 'gz', 'name': 'Fedora 36', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc37': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 46, 'rel': 20221115, 'compress': 'xz', 'name': 'Fedora 37', 'multilib': set([ 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc38': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 47, 'rel': 20230418, 'compress': 'xz', 'name': 'Fedora 38', 'multilib': set([ 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel', 'xz-devel', 'xz-libs', 'xz-static' ]) }, 'fc39': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 48, 'rel': 20231107, 'name': 'Fedora 39', 'multilib': set([ 'curl', 'curl-minimal', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel' ]) }, 'fc40': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 49, 'rel': 20240423, 'name': 'Fedora 40', 'multilib': set([ 'curl', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel' ]) }, 'fc41': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 50, 'rel': 20241029, 'name': 'Fedora 41', 'multilib': set([ 'curl', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel' ]) }, 'fc42': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 51, 'rel': 20250422, 'name': 'Fedora 42', 'also-accept': [ 'fc41' ], 'multilib': set([ 'curl', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel' ]) }, # Note: also-accept entries should be in descending order of preference 'development': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 100, 'rel': 99999999, 'name': 'Fedora Rawhide', 'also-accept': [ 'fc42', 'fc41' ], 'multilib': set([ 'curl', 'libcurl', 'libcurl-devel', 'libcurl-minimal', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'sendmail-milter-devel' ]) }, 'rhel5': { 'archlist': [ { 'id': '32', 'arch': 'i386', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 500, 'rel': 20070314, 'checksum': 'sha', 'compress': 'bz2', 'archive': 'RHEL-5', 'status': 'eol', 'name': 'Red Hat Enterprise Linux 5', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcares140', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'rhel6': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 600, 'rel': 20101110, 'compress': 'bz2', 'archive': 'RHEL-6', 'status': 'eol', 'name': 'Red Hat Enterprise Linux 6', 'multilib': set([ 'c-ares', 'c-ares-devel', 'curl', 'libcares140', 'libcurl', 'libcurl-devel', 'libcurl7112', 'libcurl7155', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn', 'libidn-devel', 'libmetalink', 'libmetalink-devel', 'libpng10', 'libpng10-devel', 'libssh2', 'libssh2-devel', 'libxml2', 'libxml2-devel', 'libxslt', 'libxslt-devel', 'sendmail-devel', 'sendmail-milter', 'xz-libs' ]) }, 'rhel7': { 'archlist': [ { 'id': '32', 'arch': 'i686', 'basearch': 'i386' }, { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 700, 'rel': 20140610, 'compress': 'gz', 'archive': 'RHEL-7', 'status': 'eol', 'name': 'Red Hat Enterprise Linux 7', 'multilib': set([ 'c-ares', 'c-ares-devel', 'check', 'check-devel', 'check-static', 'dovecot', 'GeoIP', 'GeoIP-devel', 'libcurl', 'libcurl-devel', 'libgcrypt', 'libgcrypt-devel', 'libgpg-error', 'libgpg-error-devel', 'libidn2', 'libidn2-devel', 'libmetalink', 'libmetalink-devel', 'libnet', 'libnet-devel', 'libnghttp2', 'libnghttp2-devel', 'libpsl', 'libpsl-devel', 'libssh2', 'libssh2-devel', 'libsodium', 'libsodium-devel', 'libsodium-static', 'libxml2', 'libxml2-devel', 'libxml2-static', 'libxslt', 'libxslt-devel', 'ppp-devel', 'sendmail-devel', 'sendmail-milter', 'xz-compat-libs', 'xz-devel', 'xz-libs' ]) }, 'rhel8': { 'archlist': [ { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 800, 'rel': 20191116, 'compress': 'gz', 'name': 'Red Hat Enterprise Linux 8' }, 'rhel9': { 'archlist': [ { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 900, 'rel': 20220201, 'compress': 'gz', 'name': 'Red Hat Enterprise Linux 9' }, 'rhel10': { 'archlist': [ { 'id': '64', 'arch': 'x86_64', 'basearch': 'x86_64' } ], 'buildseq': 1000, 'rel': 20240816, 'name': 'Red Hat Enterprise Linux 10' } } distro_alias = { 'el5': 'rhel5', 'el6': 'rhel6', 'el7': 'rhel7', 'el7_9': 'rhel7', 'el8': 'rhel8', 'el9': 'rhel9', 'el10': 'rhel10', 'branched': 'fc42', 'fc43': 'development', 'rawhide': 'development' } # Initialise our package dict pkgdict = {} # Initialise lists of generic packages generic_pkg_archived = defaultdict(dict) generic_pkg_required = {} # Initialise our symlink lists symlinks_needed = defaultdict(dict) # Declare hardlinks dicts hardlinks_needed = {} # Determine oldest and newest distros: if we're not building all repos, # skip the generic package in use check distro_list = sorted(distros, key=lambda dist: distros[dist]['rel']) oldest_distro = distro_list[0] newest_distro = distro_list[-1] # Sort comparison function where devel directories always compare last # Similarly, prefer "libraries" over "drivers" # And... anything preferred to ARCHIVE, so we don't pick up packages from the archive # that are still needed by non-EOL distributions def dirsort(a, b): a_archive = archive_dir in a b_archive = archive_dir in b if a_archive and not b_archive: return 1 if b_archive and not a_archive: return -1 a_devel = 'devel' in a b_devel = 'devel' in b if a_devel and not b_devel: return 1 if b_devel and not a_devel: return -1 a_drivers = 'drivers' in a b_drivers = 'drivers' in b if a_drivers and not b_drivers: return 1 if b_drivers and not a_drivers: return -1 return (a > b) - (a < b) def main(): global dry_run global no_old_pkgs global rawhide global skip_generic_pkg_check (opts, args) = parseArgs() dry_run = opts.dry_run no_old_pkgs = opts.no_old_pkgs bits = None # If there is more than one argument remaining, the user needs help if len(args) > 1: usage(sys.stderr) sys.exit(1) # If there is an argument remaining, it should be a distro[.bits] specifer if len(args) == 1: requested_distro = args[0] # First check for distro.bits match = re.search("^([^.]+)[.]([^.]+)$", requested_distro) if match: reqdist = match.group(1) reqbits = match.group(2) if reqdist in distro_alias: reqdist = distro_alias[reqdist] if not reqdist in distros: print("newrepo: unrecognized distro specification: %s" % (requested_distro), file = sys.stderr) sys.exit(1) for tryarch in distros[reqdist]['archlist']: trybits = tryarch['id'] if reqbits == trybits: opts.from_rel = reqdist opts.to_rel = reqdist bits = reqbits break else: print("newrepo: unrecognized distro specification: %s" % (requested_distro), file = sys.stderr) sys.exit(1) # Alternatively, check for a plain distro specifier else: reqdist = requested_distro if reqdist in distro_alias: reqdist = distro_alias[reqdist] if not reqdist in distros: print("newrepo: unrecognized distro specification: %s" % (requested_distro), file = sys.stderr) sys.exit(1) opts.from_rel = reqdist opts.to_rel = reqdist # Determine which distro is Rawhide/development targeting for dist in distro_alias: if distro_alias[dist] == 'development': rawhide = dist break # Compile a list of repos to build if opts.from_rel in distro_alias: opts.from_rel = distro_alias[opts.from_rel] if opts.to_rel in distro_alias: opts.to_rel = distro_alias[opts.to_rel] if opts.from_rel != oldest_distro or opts.to_rel != newest_distro: print("Skipping generic package utilization check") skip_generic_pkg_check = True baserel = distros[opts.from_rel]['rel'] endrel = distros[opts.to_rel]['rel'] buildlist = [] for dist, distdata in distros.items(): if distdata['rel'] < baserel: continue if distdata['rel'] > endrel: continue for tryarch in distdata['archlist']: if bits is not None and tryarch['id'] != bits: continue if opts.rel_regex is not None: dist_id = dist + '.' + tryarch['id'] matched_dist = re.search(opts.rel_regex, dist_id) for try_alias in distro_alias: if matched_dist is not None or dist != distro_alias[try_alias]: continue dist_id = try_alias + '.' + tryarch['id'] matched_dist = re.search(opts.rel_regex, dist_id) if matched_dist is None: continue buildlist.append({ 'dist': dist, 'buildseq': distdata['buildseq'], 'basearch': tryarch['basearch'] }) source_repo = { 'dist': dist, 'buildseq': distdata['buildseq'], 'basearch': 'src' } if not source_repo in buildlist: buildlist.append(source_repo) # Now sort the buildlist by build sequence number buildlist.sort(key=lambda dist: dist['buildseq']) #print("Building new repositories for the following distributions:") import pprint #pprint.pprint(buildlist) # Fix up SELinux file contexts so we can serve the repo over http print("Fixing up SELinux file contexts") from selinux import restorecon if not dry_run: restorecon(repo_path, recursive = True) # Find all of the packages print("Looking for packages...") os.chdir(repo_path) for root, dirs, files in os.walk('.'): # Make sure we always visit directories in the same order dirs.sort(key = cmp_to_key(dirsort)) # Prune some directories we want to exclude for this_dir in dirs[:]: thispath = os.path.normpath(os.path.join(root, this_dir)) for exclusion in dirpaths_to_exclude: if re.match(exclusion, thispath) is not None: dirs.remove(this_dir) # Process one directory at a time, and strip off the leading "." or "./" rpmdir = root if (rpmdir == '.'): rpmdir = '' else: rpmdir = rpmdir[2:] # Process all of the files in that directory for rpm in files: # Not interested in any file that's not an RPM if rpm[-4:] != '.rpm': continue # Grok the package arch arch = rpm[:-4] arch = arch[arch.rindex('.')+1:] # Treat nosrc as src if arch == 'nosrc': arch = 'src' # Munge ix86 arches rawarch = arch if re.match('i[3456]86', arch) is not None: arch = 'ix86' # Grok the package dist dist = rpm[:-4] dist = dist[:dist.rindex('.')] try: dist = dist[dist.rindex('.')+1:] except ValueError: dist = "generic" dist.lower() # el is equivalent to rhel if re.match('el[0-9]+', dist) is not None: dist = 'rh' + dist # devel is... if dist == 'devel': dist = rawhide # Skip anything that looks like it's for SuSE, Mandriva or an ancient Red Hat / Fedora Linux if re.match('.*mdk[0-9.]*[.](noarch|i[35]86|src)[.]rpm$', rpm) is not None: dist = 'mdk' if re.match('.*suse[0-9.]*[.](noarch|i[35]86|src)[.]rpm$', rpm) is not None: dist = 'suse' if re.match('.*[.]rhl[3-8][.][0-9][.](noarch|i[35]86|src)[.]rpm$', rpm) is not None: dist = 'rhl8.0' if re.match('(mdk|suse|rhl8|rhl8.0|rhl7|rhl7.[0123]|fc[1-3]|rhel[34])$', dist) is not None: continue # Fedora/RHEL packages may have numbered suffixes after the dist tag rpm_filename = rpm match = re.search("[.](el[0-9]+)[_.]", rpm_filename) if match is not None: rpm_filename = rpm_filename[:match.start(1)] + "rh" + match.group(1) + rpm_filename[match.end(1):] match = re.search("((?:fc|rhel)[0-9]+)[_.][0-9]+[.](?:i[3456]86|x86_64|noarch|src|nosrc)[.]rpm$", rpm_filename) if match is not None: dist = match.group(1) # Anything not distribution-specific is generic to all distributions if re.match('^(fc[4-9]|fc[1-9][0-9]|rhel[1-9][0-9]*)$', dist) is None: dist = 'generic' # Grok the base RPM name (including %{VERSION} and %{RELEASE}) rpmname = rpm[:-4] rpmname = rpmname[:rpmname.rindex('.')] # If there's a dist tag, strip it off if dist != 'generic': rpmname = rpmname[:rpmname.rindex('.')] # Grok the package name, version and release (less dist tag) #print("Processing %s" % rpm_filename) rpmpkg = rpmname rpmpkg = rpmpkg[:rpmpkg.rindex('-')] rpmpkg = rpmpkg[:rpmpkg.rindex('-')] rpmver = rpmname rpmver = rpmver[:rpmver.rindex('-')] rpmver = rpmver[rpmver.rindex('-')+1:] rpmrel = rpmname rpmrel = rpmrel[rpmrel.rindex('-')+1:] # Is this rpm multilib for this dist? distro_key = dist in distro_alias and distro_alias[dist] or dist multilib = distro_key != 'generic' and 'multilib' in distros[distro_key] and rpmpkg in distros[distro_key]['multilib'] # Store the RPM data in the package dict # If we already have an entry for this package, don't add it again if rpmpkg in pkgdict: for pver, prel, pdist, parch, pdir, prpm, pmultilib in pkgdict[rpmpkg]: if pver == rpmver and prel == rpmrel and pdist == dist and parch == arch and prpm == rpm: break else: # Append this rpm to the pkglist pkgdict[rpmpkg].append((rpmver, rpmrel, dist, arch, rpmdir, rpm, multilib)) else: # Create a pkgdict entry for this rpm pkgdict[rpmpkg] = [ (rpmver, rpmrel, dist, arch, rpmdir, rpm, multilib) ] # For generic packages, we don't want to update them in EOL-ed distributions # so we note which ones are in the archive area; for ones not in the archive # area, we tag them so we can detect generic packages that are no longer # required for any non-EOL distribution if distro_key == 'generic': if rpmdir.startswith(archive_dir + '/'): nvr = rpmpkg + '-' + rpmver + '-' + rpmrel # Determine which distro's archive dir we're in for eol_dist in distros: try: dist_archive_dir = distros[eol_dist]['archive'] if rpmdir.startswith(archive_dir + '/' + dist_archive_dir + '/'): # Mark the package as archived for this distro generic_pkg_archived[eol_dist][nvr] = True except KeyError: pass else: # Don't worry about excluded packages for r_name, r_ver, r_rel, r_dist, r_arch in packages_to_exclude: if re.search(r_name, rpmpkg) is not None and \ re.search(r_ver, rpmver) is not None and \ re.search(r_rel, rpmrel) is not None and \ re.search(r_dist, dist) is not None and \ re.search(r_arch, arch) is not None: break else: #print("Found generic package %s/%s-%s-%s" % (rpmdir, rpmpkg, rpmver, rpmrel)) generic_pkg_required[rpmpkg + '-' + rpmver + '-' + rpmrel] = False #pprint.pprint(pkgdict) for repo in buildlist: package_list(repo['dist'], repo['basearch']) # Check to see if any generic packages are no longer required by non-EOL distributions if not skip_generic_pkg_check: for pkg in generic_pkg_required: if not generic_pkg_required[pkg]: print("Generic package %s no longer required for non-EOL releases" % pkg) def check_rpm(dist, realdist, rpmpkg, arch): global hardlinks_needed #print("Looking for %s for distribution %s (really %s) (%s)" % (rpmpkg, dist, realdist, arch)) target_arch = arch if re.match("i[356]86", arch) is not None: arch = "ix86" # If the realdist is an alias, map it to a repo directory dist_dir = realdist in distro_alias and distro_alias[realdist] or realdist # Have per-dist GPG keys from Fedora 36 (2022) so we don't want generic packages from that point block_generic_pkgs = (distros[dist_dir].get('rel') > 20220000) # Note whether or not this is an EOL dist distro_status = distros[dist_dir].get('status', 'non-eol') if arch != 'src': repo_dir = 'yum-repo/' + dist_dir + '/' + target_arch else: repo_dir = 'yum-repo/' + dist_dir + '/source' # see if the requested package variant exists foundone = False for pver, prel, pdist, parch, pdir, prpm, pmultilib in pkgdict[rpmpkg]: # Process exclusions for r_name, r_ver, r_rel, r_dist, r_arch in packages_to_exclude: if re.search(r_name, rpmpkg) is not None and \ re.search(r_ver, pver) is not None and \ re.search(r_rel, prel) is not None and \ re.search(r_dist, realdist) is not None and \ re.search(r_arch, arch) is not None: # Handle migration of excluded non-generic packages to the archive area if (pdist == realdist and ( (parch == arch) or (parch == 'noarch' and arch != 'src') or (pmultilib and arch == 'x86_64' and parch == 'ix86') ) ): if (distro_status == 'eol' or distro_status == 'eol-migrate') and not pdir.startswith(archive_dir + '/'): #print("Found excluded EOL package in main area: %s" % prpm) if arch != 'src': archive_archdir = target_arch else: archive_archdir = 'SRPMS' archive_location = \ archive_dir + '/' + \ distros[dist_dir]['archive'] + '/' + \ archive_archdir + '/' + \ prpm hardlinks_needed[pdir + '/' + prpm] = { 'target': archive_location, 'generic': False } break else: if (pdist == dist and ( (parch == arch) or (parch == 'noarch' and arch != 'src') or (pmultilib and arch == 'x86_64' and parch == 'ix86') ) ): # We don't want to symlink in new generic packages for EOL distributions, # or old generic packages for non-EOL distributions, hence we only take # generic packages from the archive for EOL distributions, and outside # the archive for non-EOL distributions nvr = rpmpkg + '-' + pver + '-' + prel if dist != 'generic' or \ (distro_status != 'eol' and not pdir.startswith(archive_dir + '/') and not block_generic_pkgs) or \ (distro_status == 'eol' and nvr in generic_pkg_archived[dist_dir]): symlinks_needed[repo_dir][prpm] = '../../../' + pdir + '/' + prpm #print("Found %s" % prpm) foundone = True # Handle migration of packages for EOL distributions to the archive area # Record use of generic package for non-EOL distribution if dist == 'generic' and \ distro_status != 'eol' and \ not block_generic_pkgs and \ not pdir.startswith(archive_dir + '/'): generic_pkg_required[rpmpkg + '-' + pver + '-' + prel] = True # Decide where in the archive tree a package should be linked to if distro_status == 'eol' or distro_status == 'eol-migrate': if arch != 'src': archive_archdir = target_arch else: archive_archdir = 'SRPMS' archive_location = \ archive_dir + '/' + \ distros[dist_dir]['archive'] + '/' + \ archive_archdir + '/' + \ prpm # Packages only found in the archive area don't need further hardlinking if not pdir.startswith(archive_dir + '/'): hardlinks_needed[pdir + '/' + prpm] = { 'target': archive_location, 'generic': (dist == 'generic') } # Symlinks for EOL distributions should point to that distro's archive area symlinks_needed[repo_dir][prpm] = '../../../' + archive_location if not foundone: #print("Didn't find it") pass return foundone def mkdir_p(newdir): """works the way a good mkdir should :) - already exists, silently complete - regular file in the way, raise an exception - parent directory(ies) does not exist, make them as well """ if os.path.isdir(newdir): pass elif os.path.isfile(newdir): raise OSError("a file with the same name as the desired " \ "dir, '%s', already exists." % newdir) else: head, tail = os.path.split(newdir) if head and not os.path.isdir(head): mkdir_p(head) if tail: print("MKDIR " + newdir) if not dry_run: os.mkdir(newdir) def package_list(dist, arch): import pprint if arch == 'src': print("Building repository for %s (source)" % (dist)) repodir = 'yum-repo/' + dist + '/source' else: print("Building repository for %s (%s)" % (dist, arch)) repodir = 'yum-repo/' + dist + '/' + arch # Make sure the repo directory exists mkdir_p(repodir) symlinks_existing = {} repo_touched = False global hardlinks_needed hardlinks_needed = {} # For EOL distros, make sure the archive area exists distro_status = distros[dist].get('status', 'non-eol') if distro_status != 'non-eol': if arch == 'src': archive_pkg_dir = archive_dir + '/' + distros[dist]['archive'] + '/SRPMS' else: archive_pkg_dir = archive_dir + '/' + distros[dist]['archive'] + '/' + arch mkdir_p(archive_pkg_dir) # Collate existing symlinks in this repo if os.path.isdir(repodir): for entry in os.listdir(repodir): # Skip repodata directories if entry == "repodata": continue # Read any existing symlinks entrypath = os.path.join(repodir, entry) if os.path.islink(entrypath): symlinks_existing[entry] = os.readlink(entrypath) else: print("UNEXPECTED NON-SYMLINK: %s" % entrypath) else: print("DIRECTORY DOES NOT YET EXIST: %s" % repodir) #pprint.pprint(symlinks_existing) # Decide which symlinks we actually need target_dist = dist == 'development' and rawhide or dist for rpmpkg in list(pkgdict.keys()): #print("Checking for %s for %s (%s)" % (rpmname, dist, arch)) distro_accept = [ target_dist ] if 'also-accept' in distros[dist] and not no_old_pkgs: distro_accept = distro_accept + distros[dist]['also-accept'] distro_accept = distro_accept + [ 'generic' ] for trydist in distro_accept: if check_rpm(trydist, target_dist, rpmpkg, arch): break #pprint.pprint(symlinks_needed[repodir]) # Look for existing symlinks that we no longer need for symlink, whereto in symlinks_existing.items(): if symlink not in symlinks_needed[repodir]: print("REMOVE SYMLINK: %s -> %s" % (symlink, whereto)) if not dry_run: os.remove(os.path.join(repodir, symlink)) repo_touched = True continue target_rpm = symlinks_needed[repodir][symlink] if target_rpm != whereto: print("CHANGE SYMLINK: %s -> %s rather than %s" % (symlink, target_rpm, whereto)) if not dry_run: os.remove(os.path.join(repodir, symlink)) os.symlink(target_rpm, os.path.join(repodir, symlink)) repo_touched = True # else: # print("RETAIN SYMLINK: %s -> %s" % (symlink, whereto)) # Look for new symlinks we need to add for symlink, whereto in symlinks_needed[repodir].items(): if symlink not in symlinks_existing: print("ADD SYMLINK: %s -> %s" % (symlink, whereto)) if not dry_run: os.symlink(whereto, os.path.join(repodir, symlink)) repo_touched = True # See which hardlinks we should have for EOL distro migration for hardlink, details in hardlinks_needed.items(): whereto = details['target'] generic = details['generic'] try: statinfo = os.stat(whereto) archive_inode = statinfo.st_ino try: statinfo = os.stat(hardlink) # See if the hardlink is already made if (statinfo.st_ino != archive_inode): # Hardlink target exists but is not the desired file print("ERROR: hardlink target %s is not linked to %s" % (whereto, hardlink)) else: if distro_status == "eol" and not generic: # We should now be removing the file from its original location, # unless it's a generic package that may be in use for other distributions # This doesn't affect the repo really, so no need to set repo_touched # Note: it'll take multiple passes to remove all non-archive RPMs if they're # hardlinked in multiple places in the repo, such as perl SRPMs print("REMOVE ARCHIVED EOL PACKAGE: %s" % hardlink) if not dry_run: os.remove(hardlink) else: #print("RETAIN HARDLINK: %s" % hardlink) pass except OSError: # For 2nd or subsequent arch for a newly-EOL distro, we'd expect noarch packages # to have already been deleted for the first arch, so don't moan about it if distro_status != "eol" or not hardlink.endswith(".noarch.rpm"): print("ERROR: %s has disappeared!" % hardlink) except OSError: # Link target not found, make new hardlink print("ADD HARDLINK: %s -> %s" % (hardlink, whereto)) if not dry_run: # This doesn't affect the repo really, so no need to set repo_touched os.link(hardlink, whereto) # Skip everything else if nothing changed if not (repo_touched or dry_run): print("Repo not changed, skipping metadata build") return # Build repository repodata needed for current dnf/yum and mock print("Creating repodata for %s" % repodir) createrepo_cmd = [ 'createrepo_c', '--update' ] if 'checksum' in distros[dist]: createrepo_cmd.append('--checksum') createrepo_cmd.append(distros[dist]['checksum']) # Use traditional compression on old distros for compatibility if 'compress' in distros[dist]: createrepo_cmd.append('--general-compress-type') createrepo_cmd.append(distros[dist]['compress']) createrepo_cmd.append(repodir) print("%s" % ' '.join(map(str, createrepo_cmd))) if not dry_run: call(createrepo_cmd) # All done! if arch == 'src': print("Built repository for %s (source)" % (dist)) else: print("Built repository for %s (%s)" % (dist, arch)) # TODO: optionally run repoclosure checks if __name__ == "__main__": main()