PackageInfo: General overhaul.
* Add full support for Debian releases. * Unify and simplify piping and redirection. * Various general and minor improvements. * Switch architecture for infos to amd64. * Update default configuration. * Improve APT update scripts.
This commit is contained in:
@ -20,10 +20,10 @@ deb-src http://archive.ubuntu.com/ubuntu lucid main restricted universe multiver
|
||||
|
||||
supybot.plugins.PackageInfo.defaultRelease:
|
||||
Set this to the default release to use when none is specified. (Channel)
|
||||
Default: 'lucid'
|
||||
Default: 'zesty'
|
||||
|
||||
Whenever you create a new .list file, it is important to run the update_apt
|
||||
and update_apt_file scripts that comes with this plugin. Before you run these,
|
||||
and update_apt_file scripts that come with this plugin. Before you run these,
|
||||
you have to edit them to point to your apt dir. It's also useful to run them
|
||||
periodically from cron (say, once per week for update_apt and once per moth for
|
||||
update_apt_file). You also need to reload the plugin to make it pick up the new
|
||||
@ -39,11 +39,14 @@ Default: !
|
||||
|
||||
--Usage--
|
||||
find <package/filename> [<release>]
|
||||
Search for <package> or, of that fails, find <filename>'s package(s).
|
||||
Optionally in <release>
|
||||
Search for <package> or, if that fails, <filename> in packages,
|
||||
optionally in <release>
|
||||
|
||||
info <package> [<release>]
|
||||
Lookup information for <package>, optionally in <release>
|
||||
Look up information for <package>, optionally in <release>
|
||||
|
||||
if supybot.plugins.PackageInfo.enabled is True the bot will also reply to
|
||||
depends <package> [<release>]
|
||||
Look up dependencies for <package>, optionally in <release>
|
||||
|
||||
If supybot.plugins.PackageInfo.enabled is True the bot will also reply to
|
||||
the commands if prefixed with supybot.plugins.PackageInfo.prefixchar.
|
||||
|
@ -22,7 +22,7 @@ import supybot
|
||||
import supybot.world as world
|
||||
from imp import reload
|
||||
|
||||
__version__ = "1.1.0"
|
||||
__version__ = "1.2.0"
|
||||
__author__ = supybot.Author("Krytarik Raido", "krytarik", "krytarik@tuxgarage.com")
|
||||
__contributors__ = {
|
||||
supybot.Author("Dennis Kaarsemaker", "Seveas", "dennis@kaarsemaker.net"): ['Original Concept'],
|
||||
|
@ -18,15 +18,24 @@ import supybot.conf as conf
|
||||
import supybot.registry as registry
|
||||
|
||||
def configure(advanced):
|
||||
# This will be called by supybot to configure this module. advanced is
|
||||
# This will be called by Supybot to configure this module. advanced is
|
||||
# a bool that specifies whether the user identified himself as an advanced
|
||||
# user or not. You should effect your configuration by manipulating the
|
||||
# user or not. You should affect your configuration by manipulating the
|
||||
# registry as appropriate.
|
||||
def makeSource(release):
|
||||
def makeSourceUbuntu(release):
|
||||
return """deb http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
""" % (release, release)
|
||||
#"""
|
||||
|
||||
def makeSourceDebian(release):
|
||||
return """deb http://deb.debian.org/debian/ %s main contrib non-free
|
||||
deb-src deb http://deb.debian.org/debian/ %s main contrib non-free
|
||||
""" % (release, release)
|
||||
|
||||
def makeSourceDebianSec(release):
|
||||
return """deb http://security.debian.org/ %s/updates main contrib non-free
|
||||
deb-src deb http://security.debian.org/ %s/updates main contrib non-free
|
||||
""" % (release, release)
|
||||
|
||||
from supybot.questions import output, expect, something, yn
|
||||
import subprocess
|
||||
@ -42,13 +51,13 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
enabled = yn("Enable this plugin in all channels?", default=True)
|
||||
|
||||
if enabled and advanced:
|
||||
prefixchar = something("Which prefix character should be bot respond to?", default=PackageInfo.prefixchar._default)
|
||||
defaultRelease = something("What should be the default distrobution when not specified?", default=PackageInfo.defaultRelease._default)
|
||||
prefixchar = something("Which prefix character should the bot respond to?", default=PackageInfo.prefixchar._default)
|
||||
defaultRelease = something("What should be the default release when none is specified?", default=PackageInfo.defaultRelease._default)
|
||||
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
||||
|
||||
# People tend to thing this should be /var/cache/apt
|
||||
# People tend to think this should be /var/cache/apt
|
||||
while aptdir.startswith('/var'): #NOTE: This is not a good hack. Maybe just blacklist /var/cache/apt (or use apt to report back the cache dir)
|
||||
output("NO! Do not use your systems apt directory")
|
||||
output("NO! Do not use your system's apt directory")
|
||||
aptdir = something("Which directory should be used for the apt cache when looking up packages?", default=PackageInfo.aptdir._default)
|
||||
|
||||
else:
|
||||
@ -62,7 +71,8 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
PackageInfo.prefixchar.setValue(prefixchar)
|
||||
PackageInfo.defaultRelease.setValue(defaultRelease)
|
||||
|
||||
default_dists = set(['dapper', 'hardy', 'lucid', 'maveric', 'natty', 'oneiric'])
|
||||
default_dists = set(['precise', 'trusty', 'xenial', 'yakkety', 'zesty', 'artful',
|
||||
'oldstable', 'stable', 'unstable', 'testing', 'experimental'])
|
||||
pluginDir = os.path.abspath(os.path.dirname(__file__))
|
||||
update_apt = os.path.join(pluginDir, 'update_apt')
|
||||
update_apt_file = os.path.join(pluginDir, 'update_apt_file')
|
||||
@ -72,7 +82,7 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
## Create the aptdir
|
||||
try:
|
||||
os.makedirs(aptdir)
|
||||
except OSError: # The error number would be OS dependant (17 on Linux 2.6, ?? on others). So just pass on this
|
||||
except OSError: # The error number would be OS dependent (17 on Linux 2.6, ?? on others). So just pass on this
|
||||
pass
|
||||
|
||||
for release in default_dists:
|
||||
@ -80,19 +90,31 @@ deb-src http://archive.ubuntu.com/ubuntu/ %s main restricted universe multiverse
|
||||
try:
|
||||
output("Creating %s" % filename)
|
||||
fd = open(filename, 'wb')
|
||||
fd.write("# Apt sources list for Ubuntu %s\n" % release)
|
||||
fd.write(makeSource(release))
|
||||
fd.write(makeSource(release + '-security'))
|
||||
fd.write(makeSource(release + '-updates'))
|
||||
fd.write("# Apt sources list for %s\n" % release)
|
||||
if release in ('oldstable', 'stable', 'unstable', 'testing', 'experimental'):
|
||||
fd.write(makeSourceDebian(release))
|
||||
if release in ('oldstable', 'stable', 'testing'):
|
||||
fd.write(makeSourceDebian(release + '-updates'))
|
||||
fd.write(makeSourceDebianSec(release))
|
||||
else:
|
||||
fd.write(makeSourceUbuntu(release))
|
||||
fd.write(makeSourceUbuntu(release + '-updates'))
|
||||
fd.write(makeSourceUbuntu(release + '-security'))
|
||||
fd.close()
|
||||
|
||||
if release in ('unstable', 'experimental'):
|
||||
continue
|
||||
|
||||
for sub in ('backports', 'proposed'):
|
||||
sub_release = "%s-%s" % (release, sub)
|
||||
filename = os.path.join(aptdir, "%s.list" % sub_release)
|
||||
output("Creating %s" % filename)
|
||||
fd = open(filename, 'wb')
|
||||
fd.write("# Apt sources list for Ubuntu %s\n" % release)
|
||||
fd.write(makeSource(sub_release))
|
||||
fd.write("# Apt sources list for %s\n" % sub_release)
|
||||
if release in ('oldstable', 'stable', 'testing'):
|
||||
fd.write(makeSourceDebian(sub_release.replace('proposed', 'proposed-updates')))
|
||||
else:
|
||||
fd.write(makeSourceUbuntu(sub_release))
|
||||
fd.close()
|
||||
except Exception as e:
|
||||
output("Error writing to %r: %r (%s)" % (filename, str(e), type(e)))
|
||||
@ -116,7 +138,7 @@ conf.registerChannelValue(PackageInfo, 'enabled',
|
||||
conf.registerChannelValue(PackageInfo, 'prefixchar',
|
||||
conf.ValidPrefixChars('!', "Character the bot will respond to"))
|
||||
conf.registerChannelValue(PackageInfo, 'defaultRelease',
|
||||
registry.String('natty', "Default release to use when none is specified"))
|
||||
registry.String('zesty', "Default release to use when none is specified"))
|
||||
conf.registerGlobalValue(PackageInfo, 'aptdir',
|
||||
conf.Directory(conf.supybot.directories.data.dirize('aptdir'), "Path to the apt directory", private=True))
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- Encoding: utf-8 -*-
|
||||
###
|
||||
# Copyright (c) 2006-2007 Dennis Kaarsemaker
|
||||
@ -18,38 +17,39 @@
|
||||
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning)
|
||||
import subprocess, os, apt
|
||||
import subprocess, os, apt, re
|
||||
import supybot.utils as utils
|
||||
from email.parser import FeedParser
|
||||
|
||||
def component(arg):
|
||||
if '/' in arg: return arg[:arg.find('/')]
|
||||
if '/' in arg:
|
||||
return arg[:arg.find('/')]
|
||||
return 'main'
|
||||
|
||||
def description(pkg):
|
||||
if not pkg:
|
||||
return None
|
||||
if 'Description-en' in pkg:
|
||||
return pkg['Description-en'].split('\n')[0]
|
||||
elif 'Description' in pkg:
|
||||
return pkg['Description'].split('\n')[0]
|
||||
return None
|
||||
return "Description not available"
|
||||
|
||||
def apt_cache(aptdir, distro, extra):
|
||||
def apt_cache(aptdir, distro, cmd, pkg):
|
||||
return subprocess.check_output(['apt-cache',
|
||||
'-oAPT::Architecture=amd64',
|
||||
'-oAPT::Architectures::=i386',
|
||||
'-oAPT::Architectures::=amd64',
|
||||
'-oDir::State::Lists=%s/%s' % (aptdir, distro),
|
||||
'-oDir::State::Status=%s/%s.status' % (aptdir, distro),
|
||||
'-oDir::Etc::SourceList=%s/%s.list' % (aptdir, distro),
|
||||
'-oDir::Etc::SourceParts=""',
|
||||
'-oDir::Cache=%s/cache' % aptdir,
|
||||
'-oAPT::Architecture=i386'] +
|
||||
extra).decode('utf8')
|
||||
'-oDir::Cache=%s/cache' % aptdir] +
|
||||
cmd + [pkg.lower()]).decode('utf8')
|
||||
|
||||
def apt_file(aptdir, distro, pkg):
|
||||
return subprocess.check_output(['apt-file',
|
||||
'-s', '%s/%s.list' % (aptdir, distro),
|
||||
'-c', '%s/apt-file/%s' % (aptdir, distro),
|
||||
'-l', '-a', 'i386',
|
||||
'-l', '-i', '-a', 'amd64',
|
||||
'search', pkg]).decode('utf8')
|
||||
|
||||
class Apt:
|
||||
@ -62,19 +62,22 @@ class Apt:
|
||||
if self.aptdir:
|
||||
self.distros = sorted([x[:-5] for x in os.listdir(self.aptdir) if x.endswith('.list')])
|
||||
|
||||
def find(self, pkg, chkdistro, filelookup=True):
|
||||
_pkg = ''.join([x for x in pkg.strip().split(None,1)[0] if x.isalnum() or x in '.-_+/'])
|
||||
distro = ''
|
||||
if len(pkg.strip().split()) > 1:
|
||||
distro = ''.join([x for x in pkg.strip().split(None,2)[1] if x.isalnum() or x in '.-_+'])
|
||||
if not distro:
|
||||
distro = chkdistro
|
||||
def _parse(self, pkg):
|
||||
parser = FeedParser()
|
||||
parser.feed(pkg)
|
||||
return parser.close()
|
||||
|
||||
def find(self, pkg, distro, filelookup=True):
|
||||
if distro not in self.distros:
|
||||
return "%s is not a valid distribution: %s" % (distro, ", ".join(self.distros))
|
||||
pkg = _pkg
|
||||
return "%r is not a valid release: %s" % (distro, ", ".join(self.distros))
|
||||
|
||||
if distro.split('-')[0] in ('oldstable', 'stable', 'unstable', 'testing', 'experimental'):
|
||||
pkgTracURL = "https://packages.debian.org"
|
||||
else:
|
||||
pkgTracURL = "https://packages.ubuntu.com"
|
||||
|
||||
try:
|
||||
data = apt_cache(self.aptdir, distro, ['search', '-n', pkg])
|
||||
data = apt_cache(self.aptdir, distro, ['search', '-n'], pkg)
|
||||
except subprocess.CalledProcessError as e:
|
||||
data = e.output
|
||||
if not data:
|
||||
@ -85,111 +88,81 @@ class Apt:
|
||||
data = e.output
|
||||
if data:
|
||||
if data[0] == 'sh:': # apt-file isn't installed
|
||||
self.log.error("PackageInfo/packages: apt-file is not installed")
|
||||
return "Please use http://packages.ubuntu.com/ to search for files"
|
||||
self.log.error("PackageInfo/packages: apt-file is not installed")
|
||||
return "Please use %s/ to search for files" % pkgTracURL
|
||||
if data[0] == 'E:': # No files in the cache dir
|
||||
self.log.error("PackageInfo/packages: Please run the 'update_apt_file' script")
|
||||
return "Cache out of date, please contact the administrator"
|
||||
self.log.error("PackageInfo/packages: Please run the 'update_apt_file' script")
|
||||
return "Cache out of date, please contact the administrator"
|
||||
if data[0] == "Use" and data[1] == "of":
|
||||
url = "http://packages.ubuntu.com/search?searchon=contents&keywords=%s&mode=&suite=%s&arch=any" % (utils.web.urlquote(pkg), distro)
|
||||
return url
|
||||
return "%s/search?searchon=contents&keywords=%s&mode=exactfilename&suite=%s&arch=any" % (pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||
if len(data) > 10:
|
||||
return "File %s found in %s (and %d others) http://packages.ubuntu.com/search?searchon=contents&keywords=%s&mode=&suite=%s&arch=any" % (pkg, ', '.join(data[:10]), len(data)-10, utils.web.urlquote(pkg), distro)
|
||||
return "File %s found in %s and %d others <%s/search?searchon=contents&keywords=%s&mode=exactfilename&suite=%s&arch=any>" % (pkg, ', '.join(data[:10]), len(data)-10, pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||
return "File %s found in %s" % (pkg, ', '.join(data))
|
||||
return 'Package/file %s does not exist in %s' % (pkg, distro)
|
||||
return "No packages matching '%s' could be found" % pkg
|
||||
pkgs = [x.split()[0] for x in data.split('\n') if x]
|
||||
if len(pkgs) > 10:
|
||||
return "Found: %s (and %d others) http://packages.ubuntu.com/search?keywords=%s&searchon=names&suite=%s§ion=all" % (', '.join(pkgs[:10]), len(pkgs)-10, utils.web.urlquote(pkg), distro)
|
||||
return "Found: %s and %d others <%s/search?keywords=%s&searchon=names&suite=%s§ion=all>" % (', '.join(pkgs[:10]), len(pkgs)-10, pkgTracURL, utils.web.urlquote(pkg), distro)
|
||||
else:
|
||||
return "Found: %s" % ', '.join(pkgs[:5])
|
||||
|
||||
def raw_info(self, pkg, chkdistro):
|
||||
if not pkg.strip():
|
||||
return ''
|
||||
_pkg = ''.join([x for x in pkg.strip().split(None,1)[0] if x.isalnum() or x in '.-_+'])
|
||||
distro = chkdistro
|
||||
if len(pkg.strip().split()) > 1:
|
||||
distro = ''.join([x for x in pkg.strip().split(None,2)[1] if x.isalnum() or x in '-._+'])
|
||||
def raw_info(self, pkg, distro, archlookup=True):
|
||||
if distro not in self.distros:
|
||||
return "%r is not a valid distribution: %s" % (distro, ", ".join(self.distros))
|
||||
|
||||
pkg = _pkg
|
||||
return "%r is not a valid release: %s" % (distro, ", ".join(self.distros))
|
||||
|
||||
try:
|
||||
data = apt_cache(self.aptdir, distro, ['show', pkg])
|
||||
data = apt_cache(self.aptdir, distro, ['show'], pkg)
|
||||
except subprocess.CalledProcessError as e:
|
||||
data = e.output
|
||||
try:
|
||||
data2 = apt_cache(self.aptdir, distro, ['showsrc', pkg])
|
||||
except subprocess.CalledProcessError as e:
|
||||
data2 = e.output
|
||||
if not data or 'E: No packages found' in data:
|
||||
return 'Package %s does not exist in %s' % (pkg, distro)
|
||||
|
||||
maxp = {'Version': '0~'}
|
||||
packages = [x.strip() for x in data.split('\n\n')]
|
||||
packages = list(map(self._parse, [x for x in data.split('\n\n') if x]))
|
||||
for p in packages:
|
||||
if not p.strip():
|
||||
continue
|
||||
parser = FeedParser()
|
||||
parser.feed(p)
|
||||
p = parser.close()
|
||||
if type(p) == type(""):
|
||||
self.log.error("PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s.list?" % distro)
|
||||
return "Package lookup faild"
|
||||
if not p.get("Version", None):
|
||||
continue
|
||||
if apt.apt_pkg.version_compare(maxp['Version'], p['Version']) <= 0:
|
||||
maxp = p
|
||||
del parser
|
||||
|
||||
if not archlookup:
|
||||
return maxp
|
||||
|
||||
try:
|
||||
data2 = apt_cache(self.aptdir, distro, ['showsrc'], pkg)
|
||||
except subprocess.CalledProcessError:
|
||||
return maxp
|
||||
|
||||
maxp2 = {'Version': '0~'}
|
||||
packages2 = [x.strip() for x in data2.split('\n\n')]
|
||||
packages2 = list(map(self._parse, [x for x in data2.split('\n\n') if x]))
|
||||
for p in packages2:
|
||||
if not p.strip():
|
||||
continue
|
||||
parser = FeedParser()
|
||||
parser.feed(p)
|
||||
p = parser.close()
|
||||
if type(p) == type(""):
|
||||
self.log.error("PackageInfo/packages: apt returned an error, do you have the deb-src URLs in %s.list?" % distro)
|
||||
return "Package lookup faild"
|
||||
if not p['Version']:
|
||||
continue
|
||||
if apt.apt_pkg.version_compare(maxp2['Version'], p['Version']) <= 0:
|
||||
maxp2 = p
|
||||
del parser
|
||||
archs = ''
|
||||
if 'Architecture' in maxp2:
|
||||
archs = [_.strip() for _ in maxp2['Architecture'].split() if _.strip()]
|
||||
for arch in archs:
|
||||
if arch not in ('any', 'all'):
|
||||
continue
|
||||
else:
|
||||
archs = ''
|
||||
break
|
||||
|
||||
if archs:
|
||||
archs = ' (Only available for %s)' % '; '.join(archs)
|
||||
archs = re.match(r'.*^ %s \S+ \S+ \S+ arch=(?P<arch>\S+)$' % re.escape(pkg), maxp2['Package-List'],
|
||||
re.I | re.M | re.DOTALL)
|
||||
if archs:
|
||||
archs = archs.group('arch').split(',')
|
||||
if not ('any' in archs or 'all' in archs):
|
||||
maxp['Architectures'] = ', '.join(archs)
|
||||
|
||||
maxp["Distribution"] = distro
|
||||
maxp["Architectures"] = archs
|
||||
return maxp
|
||||
|
||||
def info(self, pkg, chkdistro):
|
||||
maxp = self.raw_info(pkg, chkdistro)
|
||||
def info(self, pkg, distro):
|
||||
maxp = self.raw_info(pkg, distro)
|
||||
if isinstance(maxp, str):
|
||||
return maxp
|
||||
return("%s (source: %s): %s. In component %s, is %s. Version %s (%s), package size %s kB, installed size %s kB%s" %
|
||||
(maxp['Package'], maxp['Source'] or maxp['Package'], description(maxp), component(maxp['Section']),
|
||||
maxp['Priority'], maxp['Version'], maxp["Distribution"], int(maxp['Size'])/1024, maxp['Installed-Size'], maxp["Architectures"]))
|
||||
(maxp['Package'], maxp.get('Source', None) or maxp['Package'], description(maxp), component(maxp['Section']),
|
||||
maxp['Priority'], maxp['Version'], distro, int(maxp['Size'])/1024, maxp['Installed-Size'],
|
||||
". (Only available for %s)" % maxp['Architectures'] if maxp.get('Architectures', None) else ""))
|
||||
|
||||
def depends(self, pkg, chkdistro):
|
||||
maxp = self.raw_info(pkg, chkdistro)
|
||||
def depends(self, pkg, distro):
|
||||
maxp = self.raw_info(pkg, distro, archlookup=False)
|
||||
if isinstance(maxp, str):
|
||||
return maxp
|
||||
return("%s (version %s in %s) depends on: %s" %
|
||||
(maxp['Package'], maxp["Version"], maxp["Distribution"], maxp["Depends"]))
|
||||
|
||||
return("%s (version: %s, %s): Depends on %s%s" %
|
||||
(maxp['Package'], maxp['Version'], distro, maxp.get('Depends', None) or "nothing",
|
||||
". Recommends %s" % maxp['Recommends'] if maxp.get('Recommends', None) else ""))
|
||||
|
||||
# Simple test
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
@ -210,21 +183,14 @@ if __name__ == "__main__":
|
||||
def registryValue(self, *args, **kwargs):
|
||||
return "/home/bot/aptdir"
|
||||
|
||||
command = argv[1].split(None, 1)[0]
|
||||
try:
|
||||
lookup = argv[1].split(None, 1)[1]
|
||||
(command, lookup) = argv[1].split(None, 1)
|
||||
except:
|
||||
print("Need something to lookup")
|
||||
print("Need something to look up")
|
||||
sys.exit(1)
|
||||
dists = "hardy"
|
||||
dist = "zesty"
|
||||
if argc == 3:
|
||||
dists = argv[2]
|
||||
dist = argv[2]
|
||||
plugin = FakePlugin()
|
||||
aptlookup = Apt(plugin)
|
||||
if command == "find":
|
||||
print(aptlookup.find(lookup, dists))
|
||||
elif command == "depends":
|
||||
print(aptlookup.depends(lookup, dists))
|
||||
else:
|
||||
print(aptlookup.info(lookup, dists))
|
||||
|
||||
print(getattr(aptlookup, command)(lookup, dist))
|
||||
|
@ -14,69 +14,79 @@
|
||||
#
|
||||
###
|
||||
|
||||
import supybot.utils as utils
|
||||
from supybot.commands import *
|
||||
import supybot.plugins as plugins
|
||||
import supybot.utils as utils
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.ircmsgs as ircmsgs
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.ircutils as ircutils
|
||||
import supybot.ircdb as ircdb
|
||||
import supybot.callbacks as callbacks
|
||||
import supybot.conf as conf
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import re, time
|
||||
from . import packages
|
||||
|
||||
def get_user(msg):
|
||||
try:
|
||||
user = ircdb.users.getUser(msg.prefix)
|
||||
except:
|
||||
return False
|
||||
return user
|
||||
|
||||
_stripNickChars = """!"#$%&'()*+,./:;<=>?@~"""
|
||||
def stripNick(nick):
|
||||
while nick and nick[-1] in _stripNickChars:
|
||||
nick = nick[:-1]
|
||||
return nick
|
||||
|
||||
def defaultIgnored(hostmask, recipient):
|
||||
if not conf.supybot.defaultIgnore():
|
||||
return False
|
||||
if conf.version <= '0.83.4.1' \
|
||||
and ircutils.isChannel(recipient):
|
||||
return False
|
||||
try:
|
||||
user = ircdb.users.getUser(hostmask)
|
||||
except KeyError:
|
||||
return True
|
||||
return False
|
||||
|
||||
def checkIgnored(hostmask, recipient):
|
||||
try:
|
||||
user = ircdb.users.getUser(hostmask)
|
||||
if user._checkCapability('owner'):
|
||||
return False
|
||||
elif user.ignore:
|
||||
return True
|
||||
except KeyError:
|
||||
pass
|
||||
if ircdb.ignores.checkIgnored(hostmask):
|
||||
return True
|
||||
if ircutils.isChannel(recipient):
|
||||
c = ircdb.channels.getChannel(recipient)
|
||||
if c.checkIgnored(hostmask):
|
||||
return True
|
||||
return False
|
||||
|
||||
## Taken from Encyclopedia ##
|
||||
# Repeat filtering message queue
|
||||
msgcache = {}
|
||||
def queue(irc, to, msg):
|
||||
def queue(irc, target, msg):
|
||||
now = time.time()
|
||||
for m in list(msgcache.keys()):
|
||||
if msgcache[m] < now - 30:
|
||||
msgcache.pop(m)
|
||||
for m in msgcache:
|
||||
if m[0] == irc and m[1] == to:
|
||||
if m[0] == irc and m[1] == target:
|
||||
oldmsg = m[2]
|
||||
if msg == oldmsg or oldmsg.endswith(msg):
|
||||
if oldmsg.endswith(msg):
|
||||
break
|
||||
if msg.endswith(oldmsg):
|
||||
msg = msg[:-len(oldmsg)] + 'please see above'
|
||||
if msg.endswith(oldmsg) and msg[:-len(oldmsg)].endswith(': '):
|
||||
msg = msg[:-len(oldmsg)] + 'Please see above'
|
||||
else:
|
||||
msgcache[(irc, to, msg)] = now
|
||||
irc.queueMsg(ircmsgs.privmsg(to, msg))
|
||||
msgcache[(irc, target, msg)] = now
|
||||
irc.reply(msg, to=target)
|
||||
|
||||
class PackageInfo(callbacks.Plugin):
|
||||
"""Lookup package information via apt-cache/apt-file"""
|
||||
"""Look up package information via apt-cache/apt-file"""
|
||||
threaded = True
|
||||
space_re = re.compile(r' *')
|
||||
|
||||
def __init__(self, irc):
|
||||
self.__parent = super(PackageInfo, self)
|
||||
self.__parent.__init__(irc)
|
||||
self.Apt = packages.Apt(self)
|
||||
|
||||
def callPrecedence(self, irc):
|
||||
before = []
|
||||
for cb in irc.callbacks:
|
||||
if cb.name() == 'IRCLogin':
|
||||
before.append(cb)
|
||||
return (before, [])
|
||||
|
||||
def __getRelease(self, irc, release, channel, doError=True):
|
||||
if release:
|
||||
release = release.strip()
|
||||
@ -87,253 +97,124 @@ class PackageInfo(callbacks.Plugin):
|
||||
return (None, None)
|
||||
if not release:
|
||||
return (defaultRelease, None)
|
||||
(release, rest) = (release.split(' ', 1) + [None])[:2]
|
||||
if release[0] in ('|', '>'):
|
||||
(release, rest) = (release.split(None, 1) + [None])[:2]
|
||||
if release[0] in '|>':
|
||||
return (defaultRelease, "%s %s" % (release, rest))
|
||||
return (release, rest)
|
||||
|
||||
def __getChannel(self, channel):
|
||||
return ircutils.isChannel(channel) and channel or None
|
||||
def __handleRest(self, msg, target, reply, rest):
|
||||
targeto = target
|
||||
prefix = ''
|
||||
if rest[0] == '|':
|
||||
rest = rest.lstrip('|').strip()
|
||||
if rest:
|
||||
if rest.lower() == "me":
|
||||
rest = msg.nick
|
||||
prefix = "%s: " % rest
|
||||
elif rest[0] == '>':
|
||||
rest = rest.lstrip('>').strip()
|
||||
if rest:
|
||||
# Take the first "nick" and strip off bad chars
|
||||
target = stripNick(rest.split()[0])
|
||||
if target.lower() == "me":
|
||||
target = msg.nick
|
||||
prefix = "<%s> wants you to know: " % msg.nick
|
||||
|
||||
def __getReplyChars(self, channel):
|
||||
prefix_chars = list(self.registryValue("prefixchar", channel))
|
||||
address_chars = list(str( conf.supybot.reply.whenAddressedBy.chars() ))
|
||||
if channel:
|
||||
address_chars = list(str( conf.supybot.reply.whenAddressedBy.chars.get(channel) ))
|
||||
return tuple(set(prefix_chars + address_chars))
|
||||
if target.lower() != targeto.lower() and ircutils.isChannel(target):
|
||||
target = targeto
|
||||
prefix = "(Forwarding to channels is not permitted) "
|
||||
elif msg.nick.lower() in (target.lower(), prefix[:-2].lower()) \
|
||||
and msg.nick.lower() != targeto.lower():
|
||||
target = msg.nick
|
||||
prefix = "(In the future, please use a private message to investigate) "
|
||||
|
||||
def __getCommand(self, text, channel):
|
||||
reply_chars = self.__getReplyChars(channel)
|
||||
my_commands = self.listCommands()
|
||||
if text[0] in reply_chars:
|
||||
text = text[1:]
|
||||
return text.strip().lower().split(' ', 1)[0]
|
||||
return (target, prefix + reply)
|
||||
|
||||
def real_info(self, irc, msg, args, package, release):
|
||||
def real_info(self, irc, msg, args, package, release=None):
|
||||
"""<package> [<release>]
|
||||
|
||||
Lookup information for <package>, optionally in <release>
|
||||
Look up information for <package>, optionally in <release>
|
||||
"""
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
reply_target = ircutils.replyTo(msg)
|
||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||
if not self.registryValue("enabled", channel):
|
||||
return
|
||||
(release, rest) = self.__getRelease(irc, release, channel)
|
||||
if not release:
|
||||
return
|
||||
target = ircutils.replyTo(msg)
|
||||
reply = self.Apt.info(package, release)
|
||||
if rest:
|
||||
if rest[0] == '|':
|
||||
try:
|
||||
target = rest
|
||||
while target[0] == '|':
|
||||
target = target[1:].strip()
|
||||
if target.lower() == "me":
|
||||
target = msg.nick
|
||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (info) Exception in pipe: %r" % e)
|
||||
pass
|
||||
elif rest[0] == '>':
|
||||
try:
|
||||
while rest[0] == '>':
|
||||
rest = rest[1:].strip()
|
||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
||||
if target.lower() == "me":
|
||||
target = msg.nick # redirect
|
||||
if not target: # Throw error
|
||||
raise Exception('No target')
|
||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (info) Exception in redirect: %r" % e)
|
||||
pass
|
||||
|
||||
queue(irc, reply_target, reply)
|
||||
|
||||
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||
queue(irc, target, reply)
|
||||
info = wrap(real_info, ['anything', optional('text')])
|
||||
|
||||
def real_depends(self, irc, msg, args, package, release):
|
||||
def real_depends(self, irc, msg, args, package, release=None):
|
||||
"""<package> [<release>]
|
||||
|
||||
Lookup dependencies for <package>, optionally in <release>
|
||||
Look up dependencies for <package>, optionally in <release>
|
||||
"""
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
reply_target = ircutils.replyTo(msg)
|
||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||
if not self.registryValue("enabled", channel):
|
||||
return
|
||||
(release, rest) = self.__getRelease(irc, release, channel)
|
||||
if not release:
|
||||
return
|
||||
target = ircutils.replyTo(msg)
|
||||
reply = self.Apt.depends(package, release)
|
||||
if rest:
|
||||
if rest[0] == '|':
|
||||
try:
|
||||
target = rest
|
||||
while target[0] == '|':
|
||||
target = target[1:].strip()
|
||||
if target.lower() == "me":
|
||||
target = msg.nick
|
||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (depends) Exception in pipe: %r" % e)
|
||||
pass
|
||||
elif rest[0] == '>':
|
||||
try:
|
||||
while rest[0] == '>':
|
||||
rest = rest[1:].strip()
|
||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
||||
if target.lower() == "me":
|
||||
target = msg.nick # redirect
|
||||
if not target: # Throw error
|
||||
raise Exception('No target')
|
||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (depends) Exception in redirect: %r" % e)
|
||||
pass
|
||||
|
||||
queue(irc, reply_target, reply)
|
||||
|
||||
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||
queue(irc, target, reply)
|
||||
depends = wrap(real_depends, ['anything', optional('text')])
|
||||
|
||||
def real_find(self, irc, msg, args, package, release):
|
||||
def real_find(self, irc, msg, args, package, release=None):
|
||||
"""<package/filename> [<release>]
|
||||
|
||||
Search for <package> or, of that fails, find <filename>'s package(s).
|
||||
Optionally in <release>
|
||||
Search for <package> or, if that fails, <filename> in packages,
|
||||
optionally in <release>
|
||||
"""
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
reply_target = ircutils.replyTo(msg)
|
||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||
if not self.registryValue("enabled", channel):
|
||||
return
|
||||
(release, rest) = self.__getRelease(irc, release, channel)
|
||||
if not release:
|
||||
return
|
||||
target = ircutils.replyTo(msg)
|
||||
reply = self.Apt.find(package, release)
|
||||
if rest:
|
||||
if rest[0] == '|':
|
||||
try:
|
||||
target = rest
|
||||
while target[0] == '|':
|
||||
target = target[1:].strip()
|
||||
if target.lower() == "me":
|
||||
target = msg.nick
|
||||
queue(irc, reply_target, "%s: %s" % (target, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (find) Exception in pipe: %r" % e)
|
||||
pass
|
||||
elif rest[0] == '>':
|
||||
try:
|
||||
while rest[0] == '>':
|
||||
rest = rest[1:].strip()
|
||||
targets = [_ for _ in rest.split() if _] # Split and discard empty parts
|
||||
target = stripNick(targets[0]) # Take the first "nick" and strip off bad chars
|
||||
if target.lower() == "me":
|
||||
target = msg.nick # redirect
|
||||
if not target: # Throw error
|
||||
raise Exception('No target')
|
||||
queue(irc, target, "<%s> wants you to know: %s" % (msg.nick, reply))
|
||||
return
|
||||
except Exception as e:
|
||||
self.log.info("PackageInfo: (find) Exception in redirect: %r" % e)
|
||||
pass
|
||||
|
||||
queue(irc, reply_target, reply)
|
||||
|
||||
(target, reply) = self.__handleRest(msg, target, reply, rest)
|
||||
queue(irc, target, reply)
|
||||
find = wrap(real_find, ['anything', optional('text')])
|
||||
|
||||
def privmsg(self, irc, msg, user):
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
text = self.space_re.subn(' ', msg.args[1].strip())[0]
|
||||
my_commands = self.listCommands()
|
||||
if text[0] == self.registryValue("prefixchar"):
|
||||
text = text[1:].strip()
|
||||
if user and text[0] in list(conf.supybot.reply.whenAddressedBy.chars()):
|
||||
return
|
||||
(cmd, rest) = (text.split(' ', 1) + [None])[:2]
|
||||
if cmd not in my_commands:
|
||||
return
|
||||
if not rest:
|
||||
return
|
||||
(term, rest) = (rest.split(' ', 1) + [None])[:2]
|
||||
if cmd == "find":
|
||||
self.real_find(irc, msg, [], term, rest)
|
||||
elif cmd == "depends":
|
||||
self.real_depends(irc, msg, [], term, rest)
|
||||
else:
|
||||
self.real_info(irc, msg, [], term, rest)
|
||||
|
||||
def chanmsg(self, irc, msg, user):
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
text = self.space_re.subn(' ', msg.args[1].strip())[0]
|
||||
my_commands = self.listCommands()
|
||||
if text[0] != self.registryValue("prefixchar", channel):
|
||||
return
|
||||
text = text[1:]
|
||||
(cmd, rest) = (text.split(' ', 1) + [None])[:2]
|
||||
if cmd not in my_commands:
|
||||
return
|
||||
if not rest:
|
||||
return
|
||||
(term, rest) = (rest.split(' ', 1) + [None])[:2]
|
||||
if cmd == "find":
|
||||
self.real_find(irc, msg, [], term, rest)
|
||||
elif cmd == "depends":
|
||||
self.real_depends(irc, msg, [], term, rest)
|
||||
else:
|
||||
self.real_info(irc, msg, [], term, rest)
|
||||
|
||||
def doPrivmsg(self, irc, msg):
|
||||
if chr(1) in msg.args[1]: # CTCP
|
||||
return
|
||||
if not msg.args[1]:
|
||||
text = msg.args[1].strip()
|
||||
if not text:
|
||||
return
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
if not self.registryValue("enabled", channel):
|
||||
channel = msg.args[0] if ircutils.isChannel(msg.args[0]) else None
|
||||
if text[0] == self.registryValue("prefixchar", channel):
|
||||
text = text[1:].strip()
|
||||
elif channel or text[0] in conf.supybot.reply.whenAddressedBy.chars():
|
||||
return
|
||||
user = get_user(msg)
|
||||
if channel:
|
||||
self.chanmsg(irc, msg, user)
|
||||
else:
|
||||
if user:
|
||||
return
|
||||
self.privmsg(irc, msg, user)
|
||||
if not text:
|
||||
return
|
||||
(cmd, rest) = (text.split(None, 1) + [None])[:2]
|
||||
if not cmd:
|
||||
return
|
||||
cmd = cmd.lower()
|
||||
if not (cmd in ("info", "depends", "find") and rest):
|
||||
return
|
||||
(package, release) = (rest.split(None, 1) + [None])[:2]
|
||||
irc = callbacks.NestedCommandsIrcProxy(irc, msg, [])
|
||||
getattr(self, "real_%s" % cmd)(irc, msg, [], package, release)
|
||||
|
||||
def inFilter(self, irc, msg):
|
||||
if msg.command != "PRIVMSG":
|
||||
if not defaultIgnored(msg.prefix, msg.args[0]):
|
||||
return msg
|
||||
if not conf.supybot.defaultIgnore():
|
||||
if checkIgnored(msg.prefix, msg.args[0]):
|
||||
return msg
|
||||
text = msg.args[1].strip()
|
||||
if len(text) < 6:
|
||||
return msg
|
||||
user = get_user(msg)
|
||||
channel = self.__getChannel(msg.args[0])
|
||||
reply_chars = self.__getReplyChars(channel)
|
||||
my_commands = self.listCommands()
|
||||
cmd = self.__getCommand(text, channel)
|
||||
|
||||
if cmd not in my_commands:
|
||||
return msg
|
||||
|
||||
if user:
|
||||
if not channel and text[0] == self.registryValue("prefixchar"):
|
||||
msg.args = (msg.args[0], text[1:])
|
||||
return msg
|
||||
|
||||
if channel:
|
||||
if text[0] not in reply_chars:
|
||||
return msg
|
||||
|
||||
# if not hasattr(irc, 'reply'):
|
||||
# irc = callbacks.ReplyIrcProxy(irc, msg)
|
||||
# self.doPrivmsg(irc, msg)
|
||||
else:
|
||||
if text[1] in reply_chars:
|
||||
msg.args = (msg.args[0], text[1:])
|
||||
irc = callbacks.ReplyIrcProxy(irc, msg)
|
||||
if msg.command == "PRIVMSG":
|
||||
self.doPrivmsg(irc, msg)
|
||||
|
||||
return msg
|
||||
|
||||
Class = PackageInfo
|
||||
|
@ -7,76 +7,65 @@ DIR=""
|
||||
# Be quiet by default.
|
||||
VERBOSE=0
|
||||
|
||||
|
||||
## Please don't change anything below this line, unless you really know what
|
||||
## you are doing and don't bother me with whatever errors it produces :)
|
||||
|
||||
# Print usage information.
|
||||
usage() {
|
||||
echo "Usage $0 [OPTION]..."
|
||||
echo "Updates the APT package cache for PackageInfo"
|
||||
echo ""
|
||||
echo "-h, --help Display this message and exit."
|
||||
echo "-v, --verbose Be more verbose than normal."
|
||||
echo "-V, --very-verbose Be even more verbose than normal."
|
||||
echo "-d, --dir[=DIR] Sets the directory to use when updating the APT package cache."
|
||||
echo ""
|
||||
echo "Note:"
|
||||
echo " Please separate each option with a space, eg:"
|
||||
echo " $0 -v -d /home/bot/aptdir"
|
||||
echo " Rather than:"
|
||||
echo " $0 -vd /home/bot/aptdir"
|
||||
echo ""
|
||||
echo "This script is intended to be ran automatically (eg: cron), so it shows no output by default."
|
||||
echo "You can make the script more verbose with either the -v/--verbose or -V/--very-verbose options."
|
||||
echo "The -d/--dir option sets the directory where this script looks for *.list files for apt-get."
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTION]...
|
||||
|
||||
Updates the APT package cache for PackageInfo.
|
||||
|
||||
-d, --dir <DIR> Specify directory for APT package cache.
|
||||
-v, --verbose Be more verbose than normal.
|
||||
-V, --very-verbose Be even more verbose than normal.
|
||||
-h, --help Display this message and exit.
|
||||
|
||||
Note:
|
||||
Please separate each option with a space, eg:
|
||||
$0 -v -d /home/bot/aptdir
|
||||
Rather than:
|
||||
$0 -vd /home/bot/aptdir
|
||||
|
||||
This script is intended to be run automatically (eg: cron), so it shows no output by default.
|
||||
You can make the script more verbose with the -v/--verbose or -V/--very-verbose options.
|
||||
The -d/--dir option sets the directory where this script looks for *.list files for apt-get.
|
||||
EOF
|
||||
}
|
||||
|
||||
# Prints an error message, usage (above), then exit with the specified exit value.
|
||||
# Prints an error message, usage (above), then exits with the specified exit value.
|
||||
error() {
|
||||
local exit_val=$1
|
||||
shift
|
||||
echo $@ >&2
|
||||
echo "$@" >&2
|
||||
usage >&2
|
||||
exit $exit_val
|
||||
}
|
||||
|
||||
# Runs apt-get update in the specified directory for the specified distribution.
|
||||
update_apt() {
|
||||
local apt_dir="$1"
|
||||
local dist="$2"
|
||||
local apt_args=""
|
||||
|
||||
if [ $VERBOSE -eq 0 ]; then
|
||||
apt_args="-qq"
|
||||
elif [ $VERBOSE -eq 1 ]; then
|
||||
apt_args="-q"
|
||||
fi
|
||||
|
||||
apt-get $apt_args -o="APT::Architecture=i386" \
|
||||
apt-get $apt_args \
|
||||
-o="APT::Architecture=amd64" \
|
||||
-o="APT::Architectures::=i386" \
|
||||
-o "APT::Architectures::=amd64" \
|
||||
-o="Dir::State::Lists=$apt_dir/$dist" \
|
||||
-o="Dir::State::Status=$apt_dir/$dist.status" \
|
||||
-o="Dir::Cache=$apt_dir/cache" \
|
||||
-o="Dir::Etc::SourceList=$apt_dir/$dist.list" \
|
||||
-o="Dir::Etc::SourceParts=\"\"" \
|
||||
-o="APT::Architectures::=amd64" \
|
||||
-o="Dir::State::Lists=$DIR/$DIST" \
|
||||
-o="Dir::State::Status=$DIR/$DIST.status" \
|
||||
-o="Dir::Etc::SourceList=$DIR/$DIST.list" \
|
||||
-o="Dir::Etc::SourceParts=''" \
|
||||
-o="Dir::Cache=$DIR/cache" \
|
||||
update
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
# main()
|
||||
|
||||
# Acepted arguments are:
|
||||
# -h,--help
|
||||
# -v,--verbose
|
||||
# -V,--very-verbose
|
||||
# -d,--dir[=DIR]
|
||||
|
||||
# Check command-line arguments
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
case $1 in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
@ -88,13 +77,13 @@ while [ $# -gt 0 ]; do
|
||||
VERBOSE=2
|
||||
;;
|
||||
-d|--dir)
|
||||
[ -z "$2" ] && error 1 "\"-d|--dir\" requires an argument."
|
||||
[ -z "$2" ] && error 1 '"-d/--dir" requires an argument.'
|
||||
shift
|
||||
DIR="$1"
|
||||
;;
|
||||
--dir=*)
|
||||
DIR="${1:6}"
|
||||
[ -z "$DIR" ] && error 1 "\"--dir\" requires an argument."
|
||||
[ -z "$DIR" ] && error 1 '"--dir" requires an argument.'
|
||||
;;
|
||||
-*)
|
||||
error 1 "Unknown option \"$1\"."
|
||||
@ -106,38 +95,33 @@ while [ $# -gt 0 ]; do
|
||||
shift
|
||||
done
|
||||
|
||||
apt_get=$(which apt-get 2>/dev/null)
|
||||
|
||||
# Check that apt-get exists and bail if it doesn't.
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: apt-get not found. Please install apt-get in your \$PATH." >&2
|
||||
# Check if apt-get is installed and bail if not.
|
||||
if ! which apt-get >/dev/null 2>&1; then
|
||||
echo "ERROR: apt-get not found. Please install apt-get in your PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#TODO: Remove this section and error out if DIR is not set,
|
||||
# This could hide errors where DIR/-d was not set, an error message.
|
||||
if [ -z "$DIR" ]; then
|
||||
DIR=/home/bot/aptdir
|
||||
echo "WARNING: No DIR set and no -d/--dir option given, defaulting to \"$DIR\"" >&2
|
||||
echo "WARNING: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option" >&2
|
||||
error 1 "ERROR: No DIR set in the script and no -d/--dir option given."
|
||||
fi
|
||||
|
||||
#[ -z "$DIR" ] && error 1 "ERROT: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option"
|
||||
items=("$DIR"/*.list)
|
||||
[ ! -e "${items[0]}" ] && error 1 "ERROR: Could not find any *.list files in \"$DIR\"."
|
||||
|
||||
DIR="$(echo $DIR | sed 's,/*$,,')" # Normalize $DIR
|
||||
|
||||
items=$(ls "${DIR}"/*.list 2>/dev/null)
|
||||
[ $? -ne 0 ] && error 1 "Could not find \"*.list\" files in \"$DIR\"."
|
||||
|
||||
for DIST in $items; do
|
||||
for DIST in "${items[@]}"; do
|
||||
[ -h "$DIST" ] && continue # Ignore symbolic links
|
||||
# Extract the distribution name from the .list file name.
|
||||
DIST="${DIST:${#DIR}}"
|
||||
DIST="${DIST/.list}"
|
||||
DIST="${DIST:1}"
|
||||
DIST=${DIST##*/}
|
||||
DIST=${DIST%.list}
|
||||
|
||||
touch "${DIR}/${DIST}.status" # Create APT status file
|
||||
mkdir -p "${DIR}/${DIST}/partial" # APT needs this to exist
|
||||
update_apt "$DIR" "$DIST" # Update the package list with apt-get
|
||||
[ $VERBOSE -gt 0 ] && echo "INFO: Processing $DIST"
|
||||
touch "$DIR/$DIST.status" # Create APT status file
|
||||
mkdir -p "$DIR/$DIST/partial" # APT needs this to exist
|
||||
update_apt # Update APT package cache
|
||||
if [ $? -ne 0 ]; then
|
||||
[ $VERBOSE -eq 0 ] && echo "Try passing -v or -V to get the error message." >&2
|
||||
echo "ERROR: apt-get update failed for $DIST." >&2
|
||||
exit_val=$?
|
||||
fi
|
||||
done
|
||||
|
||||
exit $exit_val
|
||||
|
@ -4,7 +4,7 @@
|
||||
# or use the --dir command-line option.
|
||||
DIR=""
|
||||
|
||||
# Be quiet by default
|
||||
# Be quiet by default.
|
||||
VERBOSE=0
|
||||
|
||||
## Please don't change anything below this line, unless you really know what
|
||||
@ -12,53 +12,48 @@ VERBOSE=0
|
||||
|
||||
# Print usage information.
|
||||
usage() {
|
||||
echo "Usage $0 [OPTION]..."
|
||||
echo "Updates the apt-file cache for PackageInfo"
|
||||
echo ""
|
||||
echo "-h, --help Display this message and exit."
|
||||
echo "-v, --verbose Be more verbose than normal."
|
||||
echo "-d, --dir[=DIR] Sets the directory to use when updating the apt-file cache."
|
||||
echo ""
|
||||
echo "Note:"
|
||||
echo " Please separate each option with a space, eg:"
|
||||
echo " $0 -v -d /home/bot/aptdir"
|
||||
echo " Rather than:"
|
||||
echo " $0 -vd /home/bot/aptdir"
|
||||
echo ""
|
||||
echo "This script is intended to be ran automatically (eg: cron), so it shows no output by default."
|
||||
echo "You can make the script more verbose with the -v/--verbose option."
|
||||
echo "The -d/--dir option sets the directory where this script looks for *.list files for apt-file."
|
||||
cat <<EOF
|
||||
Usage: $0 [OPTION]...
|
||||
|
||||
Updates the apt-file cache for PackageInfo.
|
||||
|
||||
-d, --dir <DIR> Specify directory for apt-file cache.
|
||||
-v, --verbose Be more verbose than normal.
|
||||
-h, --help Display this message and exit.
|
||||
|
||||
Note:
|
||||
Please separate each option with a space, eg:
|
||||
$0 -v -d /home/bot/aptdir
|
||||
Rather than:
|
||||
$0 -vd /home/bot/aptdir
|
||||
|
||||
This script is intended to be run automatically (eg: cron), so it shows no output by default.
|
||||
You can make the script more verbose with the -v/--verbose option.
|
||||
The -d/--dir option sets the directory where this script looks for *.list files for apt-file.
|
||||
EOF
|
||||
}
|
||||
|
||||
# Prints an error message, usage (above), then exit with the specified exit value.
|
||||
# Prints an error message, usage (above), then exits with the specified exit value.
|
||||
error() {
|
||||
local exit_val=$1
|
||||
shift
|
||||
echo $@ >&2
|
||||
echo "$@" >&2
|
||||
usage >&2
|
||||
exit $exit_val
|
||||
}
|
||||
|
||||
# Runs apt-file in the specified directory against the specified distribution.
|
||||
update_apt() {
|
||||
local DIST="$1"
|
||||
# Runs apt-file update in the specified directory for the specified distribution.
|
||||
update_apt_file() {
|
||||
if [ $VERBOSE -eq 0 ]; then
|
||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a i386 update >/dev/null 2>&1
|
||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a amd64 update >/dev/null 2>&1
|
||||
else
|
||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a i386 update
|
||||
apt-file -N -l -c "$DIR/apt-file/$DIST" -s "$DIR/$DIST.list" -a amd64 update
|
||||
fi
|
||||
}
|
||||
|
||||
# main()
|
||||
|
||||
# Acepted arguments are:
|
||||
# -h,--help
|
||||
# -v,--verbose
|
||||
# -d,--dir[=DIR]
|
||||
|
||||
# Check command-line arguments
|
||||
while [ $# -ne 0 ]; do
|
||||
case "$1" in
|
||||
while [ $# -gt 0 ]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
@ -67,61 +62,50 @@ while [ $# -ne 0 ]; do
|
||||
VERBOSE=1
|
||||
;;
|
||||
-d|--dir)
|
||||
[ -z "$2" ] && error 1 "\"-d|--dir\" requires an argument."
|
||||
[ -z "$2" ] && error 1 '"-d/--dir" requires an argument.'
|
||||
shift
|
||||
DIR="$1"
|
||||
;;
|
||||
--dir=*)
|
||||
DIR="${1:6}"
|
||||
[ -z "$DIR" ] && error 1 "\"--dir\" requires an argument."
|
||||
[ -z "$DIR" ] && error 1 '"--dir" requires an argument.'
|
||||
;;
|
||||
-*)
|
||||
error 1 "Unknown option \"$1\"."
|
||||
;;
|
||||
*)
|
||||
error 1 "This script takes no non-argument parameterss."
|
||||
error 1 "This script takes no non-argument parameters."
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
apt_file=$(which apt-file 2>/dev/null)
|
||||
|
||||
# Check if apt-file is installed and bail if it isn't.
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: apt-file not found. Please install apt-file in your \$PATH." >&2
|
||||
# Check if apt-file is installed and bail if not.
|
||||
if ! which apt-file >/dev/null 2>&1; then
|
||||
echo "ERROR: apt-file not found. Please install apt-file in your PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#TODO: Remove this and error out if DIR is not set,
|
||||
# This is legacy code and needs to disappear sometime.
|
||||
if [ -z "$DIR" ]; then
|
||||
DIR=/home/bot/aptdir
|
||||
echo "WARNING: No DIR set and no -d/--dir option given, defaulting to \"$DIR\"" >&2
|
||||
echo "WARNING: Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option" >&2
|
||||
error 1 "ERROR: No DIR set in the script and no -d/--dir option given."
|
||||
fi
|
||||
|
||||
#[ -z "$DIR" ] && error 1 "Please set DIR on line 5 of $(readlink -f $0) or use the -d/--dir option"
|
||||
items=("$DIR"/*.list)
|
||||
[ ! -e "${items[0]}" ] && error 1 "ERROR: Could not find any *.list files in \"$DIR\"."
|
||||
|
||||
DIR="$(echo $DIR | sed 's,/*$,,')" # Normalize $DIR
|
||||
for DIST in "${items[@]}"; do
|
||||
[ -h "$DIST" ] && continue # Ignore symbolic links
|
||||
# Extract the distribution name from the .list file name.
|
||||
DIST=${DIST##*/}
|
||||
DIST=${DIST%.list}
|
||||
|
||||
items=$(ls "${DIR}"/*.list 2>/dev/null)
|
||||
[ $? -ne 0 ] && error 1 "ERROR: Could not find \"*.list\" files in \"$DIR\"."
|
||||
|
||||
for DIST in $items; do
|
||||
[ -h $DIST ] && continue # Ignore symbolic links
|
||||
# Extract the distribution from the .list file name
|
||||
DIST="${DIST:${#DIR}}"
|
||||
DIST="${DIST/.list}"
|
||||
DIST="${DIST:1}"
|
||||
|
||||
mkdir -p "$DIR/apt-file/$DIST" # Create apt-file directory, if it doesn't exist
|
||||
|
||||
[ $VERBOSE -ne 0 ] && echo "INFO: Processing $DIST"
|
||||
update_apt "$DIST" # Update apt-file database
|
||||
[ $VERBOSE -gt 0 ] && echo "INFO: Processing $DIST"
|
||||
mkdir -p "$DIR/apt-file/$DIST" # Create apt-file directory if it doesn't exist
|
||||
update_apt_file # Update apt-file cache
|
||||
if [ $? -ne 0 ]; then
|
||||
[ $VERBOSE -eq 0 ] && echo "Try passing -v to get the error message." >&2
|
||||
error 1 "ERROR: apt-file failed for ${DIST}!."
|
||||
echo "ERROR: apt-file update failed for $DIST." >&2
|
||||
exit_val=$?
|
||||
fi
|
||||
done
|
||||
|
||||
exit $exit_val
|
||||
|
Reference in New Issue
Block a user