Skip to content

Commit 9caeff1

Browse files
committed
Improve chroot guessing with availability hints
Copr can provide available chroots when a repository is not found. When a user hasn't provided the chroot, we can improve our guessing. The result is that it'll always prefer epel, but can also use the centos-stream or rhel buildroot when available. This makes it easier for projects that build without EPEL. This is an alternative take on 313470b.
1 parent 3a36885 commit 9caeff1

1 file changed

Lines changed: 38 additions & 7 deletions

File tree

plugins/copr.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ def linux_distribution():
7878
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
7979
from urllib2 import urlopen, HTTPError, URLError
8080

81+
82+
class RepoNotFoundError(dnf.exceptions.Error):
83+
def __init__(self, message, available_chroots=None):
84+
super(RepoNotFoundError, self).__init__(message)
85+
self.available_chroots = available_chroots
86+
87+
8188
@dnf.plugin.register_command
8289
class CoprCommand(dnf.cli.Command):
8390
""" Copr plugin for DNF """
@@ -454,7 +461,7 @@ def _need_root(cls):
454461
raise dnf.exceptions.Error(
455462
_('This command has to be run under the root user.'))
456463

457-
def _guess_chroot(self):
464+
def _guess_chroot(self, available_chroots=None):
458465
""" Guess which chroot is equivalent to this machine """
459466
# FIXME Copr should generate non-specific arch repo
460467
dist = self.chroot_config
@@ -490,7 +497,20 @@ def _guess_chroot(self):
490497
elif "Amazon Linux" in dist[0]:
491498
chroot = "amazonlinux-{}-{}".format(dist[1], distarch if distarch else "x86_64")
492499
else:
493-
chroot = ("epel-{}-{}".format(dist[1].split(".", 1)[0], distarch if distarch else "x86_64"))
500+
releasever = dist[1].split(".", 1)[0]
501+
arch = distarch if distarch else "x86_64"
502+
503+
if available_chroots:
504+
guesses = ['epel', 'rhel']
505+
if "CentOS Stream" in dist:
506+
guesses.insert(1, 'centos-stream')
507+
for guess in guesses:
508+
chroot = "{}-{}-{}".format(guess, releasever, arch)
509+
if chroot in available_chroots:
510+
return chroot
511+
return None
512+
else:
513+
chroot = "epel-{}-{}".format(releasever, arch)
494514
return chroot
495515

496516
def _download_repo_file(self, project_name, chroot):
@@ -509,17 +529,18 @@ def _download_repo_file(self, project_name, chroot):
509529
error_data_decoded = json.loads(error_data_decoded)
510530
error_msg += _("Repository '{0}' does not exist in project '{1}'.").format(
511531
chroot, project_name)
512-
if error_data_decoded.get("available chroots"):
532+
available_chroots = error_data_decoded.get("available chroots")
533+
if available_chroots:
513534
error_msg += _("\nAvailable repositories: ") + ', '.join(
514-
"'{}'".format(x) for x in error_data_decoded["available chroots"])
535+
"'{}'".format(x) for x in available_chroots)
515536
error_msg += _("\n\nIf you want to enable a non-default repository, use the following command:\n"
516537
" 'dnf copr enable {0} <repository>'\n"
517538
"But note that the installed repo file will likely need a manual "
518539
"modification.").format(project_name)
519-
raise dnf.exceptions.Error(error_msg)
540+
raise RepoNotFoundError(error_msg, available_chroots)
520541
else:
521542
error_msg += _("Project {0} does not exist.").format(project_name)
522-
raise dnf.exceptions.Error(error_msg)
543+
raise RepoNotFoundError(error_msg)
523544
except URLError as e:
524545
error_msg = _("Failed to connect to {0}: {1}").format(self.copr_url + api_path, e.reason.strerror)
525546
raise dnf.exceptions.Error(error_msg)
@@ -529,7 +550,17 @@ def _download_repo_file(self, project_name, chroot):
529550
def _download_repo(self, project_name, repo_filename, chroot=None):
530551
_chroot = chroot or self._guess_chroot()
531552

532-
response = self._download_repo_file(project_name, _chroot)
553+
try:
554+
response = self._download_repo_file(project_name, _chroot)
555+
except RepoNotFoundError as e:
556+
# If a chroot was given or none are available we shouldn't guess again
557+
if chroot or not e.available_chroots:
558+
raise
559+
560+
new_guess = self._guess_chroot(e.available_chroots)
561+
if not new_guess or new_guess == _chroot:
562+
raise
563+
response = self._download_repo_file(project_name, new_guess)
533564

534565
if os.path.exists(repo_filename):
535566
os.remove(repo_filename)

0 commit comments

Comments
 (0)