@@ -43,14 +43,71 @@ def __init__(self, verbose=False, base=None, repos=None):
4343 Args:
4444 verbose: Enable verbose output
4545 base: Optional DNF base object for testing (if None, creates real DNF base)
46- repos: List of repository IDs to enable (default: ['rawhide', 'rawhide-source'])
46+ repos: List of repository IDs to enable (default: ['rawhide', 'rawhide-source', 'koji', 'koji-source' ])
4747 """
4848 self .verbose = verbose
4949 self .base = base
50- self .repos = repos if repos is not None else ['rawhide' , 'rawhide-source' ]
50+ self .repos = repos if repos is not None else ['rawhide' , 'rawhide-source' , 'koji' , 'koji-source' ]
5151 if self .base is None :
5252 self ._init_dnf ()
5353
54+ def _get_known_repo_config (self , repo_id : str , releasever : str ):
55+ """Get known repository configuration for common Fedora repos.
56+
57+ Args:
58+ repo_id: Repository ID to configure
59+ releasever: Release version string
60+
61+ Returns:
62+ Dictionary with 'metalink' or 'baseurl' key, or None if repo is not known
63+ """
64+ import re
65+
66+ # Known repository configurations
67+ configs = {
68+ 'rawhide' : {
69+ 'metalink' : 'https://mirrors.fedoraproject.org/metalink?repo=rawhide&arch=$basearch'
70+ },
71+ 'rawhide-source' : {
72+ 'metalink' : 'https://mirrors.fedoraproject.org/metalink?repo=rawhide-source&arch=$basearch'
73+ },
74+ 'koji' : {
75+ 'baseurl' : 'https://kojipkgs.fedoraproject.org/repos/rawhide/latest/$basearch/'
76+ },
77+ 'koji-source' : {
78+ 'baseurl' : 'https://kojipkgs.fedoraproject.org/repos/rawhide/latest/src/'
79+ },
80+ 'fedora' : {
81+ 'metalink' : f'https://mirrors.fedoraproject.org/metalink?repo=fedora-{ releasever } &arch=$basearch'
82+ },
83+ 'fedora-source' : {
84+ 'metalink' : f'https://mirrors.fedoraproject.org/metalink?repo=fedora-source-{ releasever } &arch=$basearch'
85+ },
86+ }
87+
88+ # Check exact match first
89+ if repo_id in configs :
90+ return configs [repo_id ]
91+
92+ # Pattern-based repository configurations
93+ # Each tuple: (regex_pattern, metalink_repo_template)
94+ patterns = [
95+ (r'^f(\d+)$' , 'fedora-{version}' ),
96+ (r'^f(\d+)-source$' , 'fedora-source-{version}' ),
97+ (r'^fedora-(\d+)$' , 'fedora-{version}' ),
98+ (r'^fedora-(\d+)-source$' , 'fedora-source-{version}' ),
99+ ]
100+
101+ for pattern , repo_template in patterns :
102+ match = re .match (pattern , repo_id )
103+ if match :
104+ version = match .group (1 )
105+ return {
106+ 'metalink' : f'https://mirrors.fedoraproject.org/metalink?repo={ repo_template .format (version = version )} &arch=$basearch'
107+ }
108+
109+ return None
110+
54111 def _init_dnf (self ):
55112 """Initialize DNF 5 base and load repository metadata."""
56113 if self .verbose :
@@ -86,7 +143,11 @@ def _init_dnf(self):
86143 for repo in repo_query :
87144 repo .disable ()
88145
89- # Enable specified repositories
146+ # Track which repos were found in system config and which were created
147+ repos_from_config = set ()
148+ repos_created = []
149+
150+ # Enable specified repositories, create them if not found
90151 enabled_count = 0
91152
92153 for repo_id in self .repos :
@@ -99,16 +160,52 @@ def _init_dnf(self):
99160 repo .enable ()
100161 enabled_count += 1
101162 found = True
163+ repos_from_config .add (repo_id )
102164 if self .verbose :
103165 print (f" Enabled repo: { repo_id } " )
104166
105- if not found and self .verbose :
106- print (f" Warning: Repository '{ repo_id } ' not found in configuration" )
167+ # If not found in system config, try to create it if we know the configuration
168+ if not found :
169+ repo_config = self ._get_known_repo_config (repo_id , releasever )
170+ if repo_config :
171+ try :
172+ # Create the repository programmatically
173+ repo = repo_sack .create_repo (repo_id )
174+
175+ # Configure the repository
176+ config = repo .get_config ()
177+ if 'metalink' in repo_config :
178+ config .metalink ().set (libdnf5 .conf .Option .Priority_RUNTIME , repo_config ['metalink' ])
179+ elif 'baseurl' in repo_config :
180+ config .baseurl = repo_config ['baseurl' ]
181+
182+ # Disable GPG check for auto-created repos (following koji.repo pattern)
183+ config .pkg_gpgcheck = "0"
184+
185+ # Enable the repo
186+ repo .enable ()
187+ enabled_count += 1
188+ repos_created .append (repo_id )
189+
190+ if self .verbose :
191+ print (f" Created and enabled repo: { repo_id } (using default configuration)" )
192+ except Exception as e :
193+ if self .verbose :
194+ import traceback
195+ print (traceback .format_exc ())
196+ print (f" Warning: Failed to create repository '{ repo_id } ': { e } " )
197+ elif self .verbose :
198+ print (f" Warning: Repository '{ repo_id } ' not found in configuration and no default available" )
199+
200+ # Show warning if any repos were auto-created
201+ if repos_created :
202+ print (f"Warning: Using default configuration for repositories: { ', ' .join (repos_created )} " )
203+ print (" Consider installing the repository configuration in /etc/yum.repos.d/" )
107204
108205 if enabled_count == 0 :
109206 raise RuntimeError (
110207 f"Failed to enable any repositories from: { ', ' .join (self .repos )} . "
111- "Please ensure the repositories are configured in /etc/yum.repos.d/"
208+ "Please ensure the repositories are configured in /etc/yum.repos.d/ or use known repository IDs. "
112209 )
113210
114211 if self .verbose :
@@ -591,7 +688,8 @@ def main():
591688 help = 'Enable verbose output' )
592689 parser .add_argument ('-r' , '--repo' , action = 'append' , dest = 'repos' ,
593690 help = 'Repository ID to enable (can be specified multiple times). '
594- 'Default: rawhide and rawhide-source' )
691+ 'Default: rawhide, rawhide-source, koji, and koji-source. '
692+ 'Known repositories will be auto-configured if not in /etc/yum.repos.d/' )
595693
596694 args = parser .parse_args ()
597695
0 commit comments