'
__license__ = '''\
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
'''
__version__ = '0.20060716'
__all__ = []
# TODO
# - use rfc822 parser (to get the multiline description)
# - instead of configuring repository name, it could be taken from Release file
# - figure out a way to collect more metadata
# - make it look nice
# - get rid of apt_pkg or try to use it for downloading etc.
import apt_pkg
import urllib
import string
import gzip
import sys
import locale
from cStringIO import StringIO
class Repository:
def __init__(self, name, address, distribution='mistral', components=['user']):
self.name = name
self.address = address.rstrip('/')
self.distribution = distribution
self.components = components or []
def as_sources_list(self):
return '# %s\ndeb %s %s %s' % (self.name, self.address, self.distribution, ' '.join(self.components))
ARCHITECTURES = ('armel', 'all')
REPOSITORIES = [
Repository(name='Nokia Tableteer Certified',
address='http://catalogue.tableteer.nokia.com/certified'),
Repository(name='Nokia Tableteer Non-Certified',
address='http://catalogue.tableteer.nokia.com/non-certified'),
Repository(name='Maemo Garage',
address='http://repository.maemo.org/contrib/',
components=['free', 'non-free']),
Repository(name='Maemo repository',
address='http://repository.maemo.org/',
components=['free', 'non-free']),
Repository(name='FBReader',
address='http://only.mawhrin.net/fbreader/maemo/'),
Repository(name='Kernel Concepts',
address='http://downloads.kernelconcepts.de/maemo2',
components=['free']),
Repository(name='Maemo Hackers',
address='http://maemo-hackers.org/apt/',
components=['main']),
Repository(name='MUlliNER.ORG Repository',
address='http://www.mulliner.org/nokia770/repository/',
distribution='maemo2',
components=['free']),
Repository(name='Oak Court Repository',
address='http://www.oakcourt.dyndns.org/maemo/',
distribution='./',
components=None),
Repository(name='Sardine',
address='http://repository.maemo.org',
distribution='sardine',
components=['main', 'non-free']),
Repository(name='OpenedHand',
address='http://maemo.o-hand.com/packages',
distribution='mistral/',
components=None)
]
def load_packages_list(repo):
assert repo.address is not None
assert repo.distribution is not None
index_urls = []
if repo.components:
dists_url = repo.address + '/dists/' + repo.distribution
for arch in ARCHITECTURES:
for comp in repo.components:
url = dists_url + '/%s/binary-%s/Packages.gz' % (comp, arch)
index_urls.append(url)
else:
url = repo.address + '/' + repo.distribution + 'Packages.gz'
index_urls.append(url)
packages_by_name = {}
opener = urllib.URLopener()
for url in index_urls:
print >>sys.stderr, 'Fetching', url, '...',
try:
buf = opener.open(url).read()
fp = gzip.GzipFile(fileobj=StringIO(buf))
except IOError:
print >>sys.stderr, 'FAILED'
continue
package = None
for line in fp:
line = line.rstrip()
if not line:
if package:
packages_by_name[package['name']] = package
package = None
continue
if line[0] in string.letters and ':' in line:
hdr,val = line.split(':', 1)
hdr = hdr.lower()
val = val.lstrip()
if hdr == 'package':
assert package is None
package = {}
package['name'] = val
elif hdr == 'version':
if package is not None:
prev_package = packages_by_name.get(package['name'])
if prev_package:
prev_version = prev_package['version']
if apt_pkg.VersionCompare(prev_version, val) > 0:
package['version'] = val
else:
package = None
else:
package['version'] = val
elif hdr in ('section', 'description', 'architecture'):
if package is not None:
package[hdr] = val
print >>sys.stderr, 'OK'
return packages_by_name
def print_sections(sections, packages_by_section):
def package_cmp_name(a, b):
return locale.strcoll(a['name'].lower(), b['name'].lower())
def package_cmp_description(a, b):
return locale.strcoll(a['description'].lower(), b['description'].lower())
sections.sort()
for section in sections:
print '%s
' % section
packages = packages_by_section[section]
packages.sort(package_cmp_description)
for p in packages:
repo = p['repository']
print ''
print '
%(description)s
' % p
print '
%(name)s %(version)s
' % p
print '
%s
' % repo.name
print '
'
print
def main():
locale.setlocale(locale.LC_ALL, None)
apt_pkg.InitConfig()
apt_pkg.InitSystem()
packages_by_section = {}
for repo in REPOSITORIES:
packages = load_packages_list(repo)
if not packages:
continue
for package in packages.values():
package['repository'] = repo
sectionpkgs = packages_by_section.setdefault(package['section'], [])
sectionpkgs.append(package)
sections = packages_by_section.keys()
user_sections = filter(lambda s: s.startswith('user/'), sections)
other_sections = filter(lambda s: not s.startswith('user/'), sections)
print '''
'''
print 'User packages
'
print_sections(user_sections, packages_by_section)
print '
'
print 'Other packages
'
print_sections(other_sections, packages_by_section)
print '
'
print 'sources.list
'
print ''
for repo in REPOSITORIES:
print repo.as_sources_list()
print
print ''
print '''
'''
if __name__ == '__main__':
main()