PkgInfo: tweaks to 'centos'

Make repository name optional, so they can be listed if only the release number is given. Fix --exact and add a --startswith filter option for packages.
This commit is contained in:
James Lu 2016-06-14 19:43:04 -07:00
parent 22a4fb457d
commit 413a9961d4

View File

@ -454,55 +454,84 @@ class PkgInfo(callbacks.Plugin):
friendly_url)
irc.reply(s)
@wrap(['positiveInt', 'somethingWithoutSpaces', 'somethingWithoutSpaces',
getopts({'arch': 'somethingWithoutSpaces'})])
@wrap(['positiveInt', additional('somethingWithoutSpaces'), additional('somethingWithoutSpaces'),
getopts({'arch': 'somethingWithoutSpaces', 'exact': '', 'startswith': ''})])
def centos(self, irc, msg, args, release, repo, query, opts):
"""<release> <repository> <package name> [--arch <arch>]
"""<release> [<repository> <package name>] [--arch <arch>] [--startswith|--exact]
Looks up <package> in CentOS's repositories. <release> is the release
version (6, 7, etc.), and <repository> is the repository name.
You can find a list of possible repository names here:
http://mirror.centos.org/centos/7/ (each folder is a repository).
Supported values for <arch> include x86_64 and i386 (prior to CentOS 7)"""
# CentOS doesn't have a package lookup interface, but only an autoindexed
# file server...
arch = dict(opts).get('arch') or 'x86_64'
query = query.lower()
# Different CentOS versions use different paths for their pool, ugh.
for folder in ('Packages', 'RPMS', 'openstack-juno', 'openstack-kilo',
'CentOS'):
url = 'http://mirror.centos.org/centos/%s/%s/%s/%s/' % \
(release, repo, arch, folder)
self.log.debug("PkgInfo: trying url %s for 'centos' command", url)
try:
fd = utils.web.getUrl(url).decode("utf-8")
except utils.web.Error:
continue
Supported values for <arch> include x86_64 and i386 (prior to CentOS 7),
and defaults to x86_64.
If <repository> is not given, a list of available ones will be shown instead.
If --startswith is given, results starting with the given query are shown. If --exact
is given, only exact matches are shown."""
# TL;DR CentOS doesn't have a package lookup interface, but only an autoindexed
# file server... We must find all repositories, package URLs, etc. that way.
opts = dict(opts)
exact = opts.get('exact')
startswith = opts.get('startswith')
arch = opts.get('arch') or 'x86_64'
url = 'http://mirror.centos.org/centos/%s' % release
if repo:
if query:
query = query.lower()
# Both repo and package name were given, so look in folders there.
# Note: different CentOS versions different paths for their pool, ugh.
for folder in ('Packages', 'RPMS', 'openstack-juno', 'openstack-kilo',
'CentOS'):
url = 'http://mirror.centos.org/centos/%s/%s/%s/%s/' % \
(release, repo, arch, folder)
self.log.debug("PkgInfo: trying url %s for 'centos' command", url)
try:
fd = utils.web.getUrl(url).decode("utf-8")
except utils.web.Error:
continue
else:
break
else:
irc.error('Unknown repository %r.' % repo, Raise=True)
else:
break
else:
irc.error('Unknown repository %r.' % repo, Raise=True)
# Giving a repository but no package name is useless. Usually there
# are too many results to display without filtering anyways.
irc.error("Missing package query.", Raise=True)
else: # No repository given; list the ones available.
fd = utils.web.getUrl(url).decode("utf-8")
soup = BeautifulSoup(fd)
# The first two tables are for the navigation bar; the third is the actual autoindex
# content.
res = []
packagetable = soup.find_all('table')[2]
exact = 'exact' in dict(opts)
for tr in packagetable.find_all('tr'):
for tr in packagetable.find_all('tr')[3:]:
try:
package = tr.find_all('td')[1].a.text
entry = tr.find_all('td')[1].a.text
except IndexError:
continue
if not package.endswith('.rpm'):
# Prevent things like "Parent Directory" from appearing in results
entry = entry.lower()
if not query: # No query filter given; show everything.
res.append(entry)
elif exact:
if query == entry: # Exact match
res.append(entry)
continue
elif startswith:
if entry.startswith(query): # startswith() match
res.append(entry)
continue
elif query in entry: # Default substring search
res.append(entry)
continue
package = ircutils.bold(package)
if exact:
if query == package.lower():
res.append(package)
else:
if query in package.lower():
res.append(package)
if res:
irc.reply(format('Found %n: %L; View more at: %u', (len(res), 'result'), res, url))
else: