diff options
| -rw-r--r-- | AUTHORS | 3 | ||||
| -rw-r--r-- | TODO | 5 | ||||
| -rw-r--r-- | aptsources/__init__.py | 1 | ||||
| -rw-r--r-- | aptsources/distinfo.py | 241 | ||||
| -rw-r--r-- | aptsources/distro.py | 430 | ||||
| -rw-r--r-- | aptsources/sourceslist.py | 428 | ||||
| -rw-r--r-- | data/templates/Debian.info.in | 98 | ||||
| -rw-r--r-- | data/templates/Debian.mirrors | 797 | ||||
| -rw-r--r-- | data/templates/README.templates | 46 | ||||
| -rw-r--r-- | data/templates/Ubuntu.info.in | 279 | ||||
| -rw-r--r-- | data/templates/Ubuntu.mirrors | 267 | ||||
| -rw-r--r-- | debian/control | 9 | ||||
| -rw-r--r-- | debian/python-apt.docs | 1 | ||||
| -rwxr-xr-x | debian/rules | 78 | ||||
| -rw-r--r-- | po/POTFILES.in | 3 | ||||
| -rw-r--r-- | po/python-apt.pot | 269 | ||||
| -rw-r--r-- | setup.cfg | 8 | ||||
| -rwxr-xr-x[-rw-r--r--] | setup.py | 27 | ||||
| -rw-r--r-- | tests/data/sources.list | 6 | ||||
| -rw-r--r-- | tests/data/sources.list.testDistribution | 11 | ||||
| -rw-r--r-- | tests/test_aptsources.py | 127 | ||||
| -rwxr-xr-x | utils/get_debian_mirrors.py | 71 | ||||
| -rwxr-xr-x | utils/get_ubuntu_mirrors.py | 61 | ||||
| -rwxr-xr-x | utils/get_ubuntu_mirrors_from_lp.py | 85 | ||||
| -rwxr-xr-x | utils/mirrortest | 100 |
25 files changed, 3371 insertions, 80 deletions
@@ -1,3 +1,6 @@ jgg Jason Gunthorpe <jgg@debian.org> mdz Matt Zimmerman <mdz@debian.org> mvo Michael Vogt <mvo@debian.org> +Michiel Sikkes <michiel@eyesopened.nl> +Sebastian Heinlein <glatzor@ubuntu.com> +Sean Wheller <sean@inwords.co.za> @@ -2,3 +2,8 @@ - change all candidateInstalledSize() to installSize(useCandidate=True) same for candidateOrigin() (see downloadable for a example). - might be better to have "Package.candidate.{downloadable,size,etc} + +* aptsources: + - make the distro detection in sources.list more clever by using the + origin informaton to avoid adding full uris to (unofficial/internal) + mirrors diff --git a/aptsources/__init__.py b/aptsources/__init__.py new file mode 100644 index 00000000..8d1c8b69 --- /dev/null +++ b/aptsources/__init__.py @@ -0,0 +1 @@ + diff --git a/aptsources/distinfo.py b/aptsources/distinfo.py new file mode 100644 index 00000000..d7289b4b --- /dev/null +++ b/aptsources/distinfo.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# +# distinfo.py - provide meta information for distro repositories +# +# Copyright (c) 2005 Gustavo Noronha Silva +# 2006-2007 Sebastian Heinlein +# +# Author: Gustavo Noronha Silva <kov@debian.org> +# Sebastian Heinlein <glatzor@ubuntu.com> +# +# 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-1307 +# USA + +import os +import gettext +from os import getenv +import ConfigParser +import string + +from gettext import gettext as _ + +import re + +class Template: + def __init__(self): + self.name = None + self.child = False + self.match_name = None + self.description = None + self.base_uri = None + self.type = None + self.components = [] + self.children = [] + self.match_uri = None + self.mirror_set = {} + self.distribution = None + self.available = True + + def has_component(self, comp): + ''' Check if the distribution provides the given component ''' + return comp in map(lambda c: c.name, self.components) + + def is_mirror(self, url): + ''' Check if a given url of a repository is a valid mirror ''' + proto, hostname, dir = split_url(url) + if self.mirror_set.has_key(hostname): + return self.mirror_set[hostname].has_repository(proto, dir) + else: + return False + +class Component: + def __init__(self, name, desc=None, long_desc=None): + self.name = name + self.description = desc + self.description_long = long_desc + def get_description(self): + if self.description_long != None: + return self.description_long + elif self.description != None: + return self.description + else: + return None + def set_description(self, desc): + self.description = desc + def set_description_long(self, desc): + self.description_long = desc + def get_description_long(self): + return self.description_long + +class Mirror: + ''' Storage for mirror related information ''' + def __init__(self, proto, hostname, dir, location=None): + self.hostname = hostname + self.repositories = [] + self.add_repository(proto, dir) + self.location = location + def add_repository(self, proto, dir): + self.repositories.append(Repository(proto, dir)) + def get_repositories_for_proto(self, proto): + return filter(lambda r: r.proto == proto, self.repositories) + def has_repository(self, proto, dir): + return len(filter(lambda r: (r.proto == proto) and dir in r.dir, + self.repositories)) > 0 + def get_repo_urls(self): + return map(lambda r: r.get_url(self.hostname), self.repositories) + def get_location(self): + return self.location + def set_location(self, location): + self.location = location + +class Repository: + def __init__(self, proto, dir): + self.proto = proto + self.dir = dir + def get_info(self): + return self.proto, self.dir + def get_url(self, hostname): + return "%s://%s/%s" % (self.proto, hostname, self.dir) + +def split_url(url): + ''' split a given URL into the protocoll, the hostname and the dir part ''' + return map(lambda a,b: a, re.split(":*\/+", url, maxsplit=2), + [None, None, None]) + +class DistInfo: + def __init__(self, + dist = None, + base_dir = "/usr/share/python-apt/templates"): + self.metarelease_uri = '' + self.templates = [] + + location = None + match_loc = re.compile(r"^#LOC:(.+)$") + match_mirror_line = re.compile(r"^(#LOC:.+)|(((http)|(ftp)|(rsync)|(file)|(https))://[A-Za-z/\.:\-_]+)$") + #match_mirror_line = re.compile(r".+") + + if not dist: + pipe = os.popen("lsb_release -i -s") + dist = pipe.read().strip() + pipe.close() + del pipe + + self.dist = dist + + + map_mirror_sets = {} + + dist_fname = "%s/%s.info" % (base_dir, dist) + dist_file = open (dist_fname) + if not dist_file: + return + template = None + component = None + for line in dist_file: + tokens = line.split (':', 1) + if len (tokens) < 2: + continue + field = tokens[0].strip () + value = tokens[1].strip () + if field == 'ChangelogURI': + self.changelogs_uri = _(value) + elif field == 'MetaReleaseURI': + self.metarelease_uri = value + elif field == 'Suite': + if template: + if component and not template.has_component(component.name): + template.components.append(component) + component = None + self.templates.append(template) + template = Template() + template.name = value + template.distribution = dist + template.match_name = "^%s$" % value + elif field == 'MatchName': + template.match_name = value + elif field == 'ParentSuite': + template.child = True + for nanny in self.templates: + if nanny.name == value: + nanny.children.append(template) + # reuse some properties of the parent template + if template.match_uri == None: + template.match_uri = nanny.match_uri + if template.mirror_set == {}: + template.mirror_set = nanny.mirror_set + if template.base_uri == None: + template.base_uri = nanny.base_uri + elif field == 'Available': + template.available = value + elif field == 'RepositoryType': + template.type = value + elif field == 'BaseURI': + template.base_uri = value + template.match_uri = value + elif field == 'MatchURI': + template.match_uri = value + elif field == 'MirrorsFile': + if not map_mirror_sets.has_key(value): + mirror_set = {} + try: + mirror_data = filter(match_mirror_line.match, + map(string.strip, open(value))) + except: + print "ERROR: Failed to read mirror file" + mirrors = [] + for line in mirror_data: + if line.startswith("#LOC:"): + location = match_loc.sub(r"\1", line) + continue + (proto, hostname, dir) = split_url(line) + if mirror_set.has_key(hostname): + mirror_set[hostname].add_repository(proto, dir) + else: + mirror_set[hostname] = Mirror(proto, hostname, dir, location) + map_mirror_sets[value] = mirror_set + template.mirror_set = map_mirror_sets[value] + elif field == 'Description': + template.description = _(value) + elif field == 'Component': + if component and not template.has_component(component.name): + template.components.append(component) + component = Component(value) + elif field == 'CompDescription': + component.set_description(_(value)) + elif field == 'CompDescriptionLong': + component.set_description_long(_(value)) + if template: + if component: + template.components.append(component) + component = None + self.templates.append(template) + template = None + +if __name__ == "__main__": + d = DistInfo ("Ubuntu", "/usr/share/python-apt/templates") + print d.changelogs_uri + for template in d.templates: + print "\nSuite: %s" % template.name + print "Desc: %s" % template.description + print "BaseURI: %s" % template.base_uri + print "MatchURI: %s" % template.match_uri + if template.mirror_set != {}: + print "Mirrors: %s" % template.mirror_set.keys() + for comp in template.components: + print " %s -%s -%s" % (comp.name, + comp.description, + comp.description_long) + for child in template.children: + print " %s" % child.description diff --git a/aptsources/distro.py b/aptsources/distro.py new file mode 100644 index 00000000..5b4c6522 --- /dev/null +++ b/aptsources/distro.py @@ -0,0 +1,430 @@ +# distro.py - Provide a distro abstraction of the sources.list +# +# Copyright (c) 2004-2007 Canonical Ltd. +# 2006-2007 Sebastian Heinlein +# +# Authors: Sebastian Heinlein <glatzor@ubuntu.com> +# Michael Vogt <mvo@debian.org> +# +# 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-1307 +# USA + +import string +import gettext +import re +import os +import sys +from gettext import gettext as _ + + +class Distribution: + def __init__(self, id, codename, description, release): + """ Container for distribution specific informations """ + # LSB information + self.id = id + self.codename = codename + self.description = description + self.release = release + + self.binary_type = "deb" + self.source_type = "deb-src" + + def get_sources(self, sourceslist): + """ + Find the corresponding template, main and child sources + for the distribution + """ + + self.sourceslist = sourceslist + # corresponding sources + self.source_template = None + self.child_sources = [] + self.main_sources = [] + self.disabled_sources = [] + self.cdrom_sources = [] + self.download_comps = [] + self.enabled_comps = [] + self.cdrom_comps = [] + self.used_media = [] + self.get_source_code = False + self.source_code_sources = [] + + # location of the sources + self.default_server = "" + self.main_server = "" + self.nearest_server = "" + self.used_servers = [] + + # find the distro template + for template in self.sourceslist.matcher.templates: + if self.is_codename(template.name) and\ + template.distribution == self.id: + #print "yeah! found a template for %s" % self.description + #print template.description, template.base_uri, template.components + self.source_template = template + break + if self.source_template == None: + print "Error: could not find a distribution template" + # FIXME: will go away - only for debugging issues + sys.exit(1) + + # find main and child sources + media = [] + comps = [] + cdrom_comps = [] + enabled_comps = [] + source_code = [] + for source in self.sourceslist.list: + if source.invalid == False and\ + self.is_codename(source.dist) and\ + source.template and\ + self.is_codename(source.template.name): + #print "yeah! found a distro repo: %s" % source.line + # cdroms need do be handled differently + if source.uri.startswith("cdrom:") and \ + source.disabled == False: + self.cdrom_sources.append(source) + cdrom_comps.extend(source.comps) + elif source.uri.startswith("cdrom:") and \ + source.disabled == True: + self.cdrom_sources.append(source) + elif source.type == self.binary_type and \ + source.disabled == False: + self.main_sources.append(source) + comps.extend(source.comps) + media.append(source.uri) + elif source.type == self.binary_type and \ + source.disabled == True: + self.disabled_sources.append(source) + elif source.type == self.source_type and source.disabled == False: + self.source_code_sources.append(source) + elif source.type == self.source_type and source.disabled == True: + self.disabled_sources.append(source) + if source.invalid == False and\ + source.template in self.source_template.children: + if source.disabled == False and source.type == self.binary_type: + self.child_sources.append(source) + elif source.disabled == False and source.type == self.source_type: + self.source_code_sources.append(source) + else: + self.disabled_sources.append(source) + self.download_comps = set(comps) + self.cdrom_comps = set(cdrom_comps) + enabled_comps.extend(comps) + enabled_comps.extend(cdrom_comps) + self.enabled_comps = set(enabled_comps) + self.used_media = set(media) + + self.get_mirrors() + + def get_mirrors(self): + """ + Provide a set of mirrors where you can get the distribution from + """ + # the main server is stored in the template + self.main_server = self.source_template.base_uri + + # other used servers + for medium in self.used_media: + if not medium.startswith("cdrom:"): + # seems to be a network source + self.used_servers.append(medium) + + if len(self.main_sources) == 0: + self.default_server = self.main_server + else: + self.default_server = self.main_sources[0].uri + + def add_source(self, type=None, + uri=None, dist=None, comps=None, comment=""): + """ + Add distribution specific sources + """ + if uri == None: + # FIXME: Add support for the server selector + uri = self.default_server + if dist == None: + dist = self.codename + if comps == None: + comps = list(self.enabled_comps) + if type == None: + type = self.binary_type + new_source = self.sourceslist.add(type, uri, dist, comps, comment) + # if source code is enabled add a deb-src line after the new + # source + if self.get_source_code == True and tpye == self.binary_type: + self.sourceslist.add(self.source_type, uri, dist, comps, comment, + file=new_source.file, + pos=self.sourceslist.list.index(new_source)+1) + + def enable_component(self, comp): + """ + Enable a component in all main, child and source code sources + (excluding cdrom based sources) + + sourceslist: an aptsource.sources_list + comp: the component that should be enabled + """ + def add_component_only_once(source, comps_per_dist): + """ + Check if we already added the component to the repository, since + a repository could be splitted into different apt lines. If not + add the component + """ + # if we don't that distro, just reutnr (can happen for e.g. + # dapper-update only in deb-src + if not comps_per_dist.has_key(source.dist): + return + # if we have seen this component already for this distro, + # return (nothing to do + if comp in comps_per_dist[source.dist]: + return + # add it + source.comps.append(comp) + comps_per_dist[source.dist].add(comp) + + sources = [] + sources.extend(self.main_sources) + sources.extend(self.child_sources) + # store what comps are enabled already per distro (where distro is + # e.g. "dapper", "dapper-updates") + comps_per_dist = {} + comps_per_sdist = {} + for s in sources: + if s.type == self.binary_type: + if not comps_per_dist.has_key(s.dist): + comps_per_dist[s.dist] = set() + map(comps_per_dist[s.dist].add, s.comps) + for s in self.source_code_sources: + if s.type == self.source_type: + if not comps_per_sdist.has_key(s.dist): + comps_per_sdist[s.dist] = set() + map(comps_per_sdist[s.dist].add, s.comps) + + # check if there is a main source at all + if len(self.main_sources) < 1: + # create a new main source + self.add_source(comps=["%s"%comp]) + else: + # add the comp to all main, child and source code sources + for source in sources: + add_component_only_once(source, comps_per_dist) + + # check if there is a main source code source at all + if self.get_source_code == True: + if len(self.source_code_sources) < 1: + # create a new main source + self.add_source(type=self.source_type, comps=["%s"%comp]) + else: + # add the comp to all main, child and source code sources + for source in self.source_code_sources: + add_component_only_once(source, comps_per_sdist) + + def disable_component(self, comp): + """ + Disable a component in all main, child and source code sources + (excluding cdrom based sources) + """ + sources = [] + sources.extend(self.main_sources) + sources.extend(self.child_sources) + sources.extend(self.source_code_sources) + if comp in self.cdrom_comps: + sources = [] + sources.extend(self.main_sources) + + for source in sources: + if comp in source.comps: + source.comps.remove(comp) + if len(source.comps) < 1: + self.sourceslist.remove(source) + + def change_server(self, uri): + ''' Change the server of all distro specific sources to + a given host ''' + sources = [] + seen = [] + self.default_server = uri + sources.extend(self.main_sources) + sources.extend(self.child_sources) + sources.extend(self.source_code_sources) + for source in sources: + # Avoid creating duplicate entries + source.uri = uri + for comp in source.comps: + if [source.uri, source.dist, comp] in seen: + source.comps.remove(comp) + else: + seen.append([source.uri, source.dist, comp]) + if len(source.comps) < 1: + self.sourceslist.remove(source) + + def is_codename(self, name): + ''' Compare a given name with the release codename. ''' + if name == self.codename: + return True + else: + return False + + def get_server_list(self): + ''' Return a list of used and suggested servers ''' + # Store all available servers: + # Name, URI, active + mirrors = [] + + mirrors.append([_("Main server"), self.main_server, + len(self.used_servers) == 1 and + self.used_servers[0] == self.main_server]) + + if len(self.used_servers) == 1 and not re.match(self.used_servers[0], + self.main_server): + # Only one server is used + server = self.used_servers[0] + mirrors.append([server, server, True]) + elif len(self.used_servers) > 1: + # More than one server is used. Since we don't handle this case + # in the user interface we set "custom servers" to true and + # append a list of all used servers + mirrors.append([_("Custom servers"), None, True]) + for server in self.used_servers: + if not [server, server, False] in mirrors: + mirrors.append([server, server, False]) + + return mirrors + + if len(self.used_servers) == 1 and not is_single_server(self.main_server): + mirrors.append(["%s" % self.used_servers[0], + self.used_servers[0], True]) + elif len(self.used_servers) > 1 or not is_single_server(self.main_server): + mirrors.append([_("Custom servers"), None, True]) + + return mirrors + + +class DebianDistribution(Distribution): + ''' Class to support specific Debian features ''' + + def is_codename(self, name): + ''' Compare a given name with the release codename and check if + if it can be used as a synonym for a development releases ''' + if name == self.codename or self.release in ("testing", "unstable"): + return True + else: + return False + +class UbuntuDistribution(Distribution): + ''' Class to support specific Ubuntu features ''' + def get_mirrors(self): + Distribution.get_mirrors(self) + # get a list of country codes and real names + self.countries = {} + try: + f = open("/usr/share/iso-codes/iso_3166.tab", "r") + lines = f.readlines() + for line in lines: + parts = line.split("\t") + self.countries[parts[0].lower()] = parts[1].strip() + except: + print "could not open file '%s'" % file + else: + f.close() + + # try to guess the nearest mirror from the locale + self.country = None + self.country_code = None + locale = os.getenv("LANG", default="en.UK") + a = locale.find("_") + z = locale.find(".") + if z == -1: + z = len(locale) + country_code = locale[a+1:z].lower() + self.nearest_server = "http://%s.archive.ubuntu.com/ubuntu/" % \ + country_code + if self.countries.has_key(country_code): + self.country = self.countries[country_code] + self.country_code = country_code + + def get_server_list(self): + ''' Return a list of used and suggested servers ''' + + def get_mirror_name(server): + ''' Try to get a human readable name for the main mirror of a country''' + country = None + i = server.find("://") + l = server.find(".archive.ubuntu.com") + if i != -1 and l != -1: + country = server[i+len("://"):l] + if self.countries.has_key(country): + # TRANSLATORS: %s is a country + return _("Server for %s") % \ + gettext.dgettext("iso-3166", + self.countries[country].rstrip()).rstrip() + else: + return("%s" % server) + + # Store all available servers: + # Name, URI, active + mirrors = [] + if len(self.used_servers) < 1 or \ + (len(self.used_servers) == 1 and \ + self.used_servers[0] == self.main_server): + mirrors.append([_("Main server"), self.main_server, True]) + mirrors.append([get_mirror_name(self.nearest_server), + self.nearest_server, False]) + elif len(self.used_servers) == 1 and not re.match(self.used_servers[0], + self.main_server): + mirrors.append([_("Main server"), self.main_server, False]) + # Only one server is used + server = self.used_servers[0] + + # Append the nearest server if it's not already used + if not re.match(server, self.nearest_server): + mirrors.append([get_mirror_name(self.nearest_server), + self.nearest_server, False]) + mirrors.append([get_mirror_name(server), server, True]) + + elif len(self.used_servers) > 1: + # More than one server is used. Since we don't handle this case + # in the user interface we set "custom servers" to true and + # append a list of all used servers + mirrors.append([_("Main server"), self.main_server, False]) + mirrors.append([get_mirror_name(self.nearest_server), + self.nearest_server, False]) + mirrors.append([_("Custom servers"), None, True]) + for server in self.used_servers: + if re.match(server, self.nearest_server): + continue + elif not [get_mirror_name(server), server, False] in mirrors: + mirrors.append([get_mirror_name(server), server, False]) + + return mirrors + +def get_distro(): + ''' Check the currently used distribution and return the corresponding + distriubtion class that supports distro specific features. ''' + lsb_info = [] + for lsb_option in ["-i", "-c", "-d", "-r"]: + pipe = os.popen("lsb_release %s -s" % lsb_option) + lsb_info.append(pipe.read().strip()) + del pipe + (id, codename, description, release) = lsb_info + if id == "Ubuntu": + return UbuntuDistribution(id, codename, description, + release) + elif id == "Debian": + return DebianDistribution(id, codename, description, + release) + else: + return Distribution(id, codename, description, relase) diff --git a/aptsources/sourceslist.py b/aptsources/sourceslist.py new file mode 100644 index 00000000..14c2a0ea --- /dev/null +++ b/aptsources/sourceslist.py @@ -0,0 +1,428 @@ +# aptsource.py - Provide an abstraction of the sources.list +# +# Copyright (c) 2004-2007 Canonical Ltd. +# 2004 Michiel Sikkes +# 2006-2007 Sebastian Heinlein +# +# Author: Michiel Sikkes <michiel@eyesopened.nl> +# Michael Vogt <mvo@debian.org> +# Sebastian Heinlein <glatzor@ubuntu.com> +# +# 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-1307 +# USA + +import string +import gettext +import re +import apt_pkg +import glob +import shutil +import time +import os.path +import sys +from gettext import gettext as _ +#import pdb + +#from UpdateManager.Common.DistInfo import DistInfo +from distinfo import DistInfo + +# some global helpers +def is_mirror(master_uri, compare_uri): + """check if the given add_url is idential or a mirror of orig_uri + e.g. master_uri = archive.ubuntu.com + compare_uri = de.archive.ubuntu.com + -> True + """ + # remove traling spaces and "/" + compare_uri = compare_uri.rstrip("/ ") + master_uri = master_uri.rstrip("/ ") + # uri is identical + if compare_uri == master_uri: + #print "Identical" + return True + # add uri is a master site and orig_uri has the from "XX.mastersite" + # (e.g. de.archive.ubuntu.com) + try: + compare_srv = compare_uri.split("//")[1] + master_srv = master_uri.split("//")[1] + #print "%s == %s " % (add_srv, orig_srv) + except IndexError: # ok, somethings wrong here + #print "IndexError" + return False + # remove the leading "<country>." (if any) and see if that helps + if "." in compare_srv and \ + compare_srv[compare_srv.index(".")+1:] == master_srv: + #print "Mirror" + return True + return False + +def uniq(s): + """ simple and efficient way to return uniq list """ + return list(set(s)) + +class SourceEntry: + """ single sources.list entry """ + def __init__(self, line,file=None): + self.invalid = False # is the source entry valid + self.disabled = False # is it disabled ('#' in front) + self.type = "" # what type (deb, deb-src) + self.uri = "" # base-uri + self.dist = "" # distribution (dapper, edgy, etc) + self.comps = [] # list of available componetns (may empty) + self.comment = "" # (optional) comment + self.line = line # the original sources.list line + if file == None: + file = apt_pkg.Config.FindDir("Dir::Etc")+apt_pkg.Config.Find("Dir::Etc::sourcelist") + self.file = file # the file that the entry is located in + self.parse(line) + self.template = None # type DistInfo.Suite + self.children = [] + + def __eq__(self, other): + """ equal operator for two sources.list entries """ + return (self.disabled == other.disabled and + self.type == other.type and + self.uri == other.uri and + self.dist == other.dist and + self.comps == other.comps) + + + def mysplit(self, line): + """ a split() implementation that understands the sources.list + format better and takes [] into account (for e.g. cdroms) """ + line = string.strip(line) + pieces = [] + tmp = "" + # we are inside a [..] block + p_found = False + space_found = False + for i in range(len(line)): + if line[i] == "[": + p_found=True + tmp += line[i] + elif line[i] == "]": + p_found=False + tmp += line[i] + elif space_found and not line[i].isspace(): # we skip one or more space + space_found = False + pieces.append(tmp) + tmp = line[i] + elif line[i].isspace() and not p_found: # found a whitespace + space_found = True + else: + tmp += line[i] + # append last piece + if len(tmp) > 0: + pieces.append(tmp) + return pieces + + def parse(self,line): + """ parse a given sources.list (textual) line and break it up + into the field we have """ + line = string.strip(self.line) + #print line + # check if the source is enabled/disabled + if line == "" or line == "#": # empty line + self.invalid = True + return + if line[0] == "#": + self.disabled = True + pieces = string.split(line[1:]) + # if it looks not like a disabled deb line return + if not pieces[0] in ("rpm", "rpm-src", "deb", "deb-src"): + self.invalid = True + return + else: + line = line[1:] + # check for another "#" in the line (this is treated as a comment) + i = line.find("#") + if i > 0: + self.comment = line[i+1:] + line = line[:i] + # source is ok, split it and see what we have + pieces = self.mysplit(line) + # Sanity check + if len(pieces) < 3: + self.invalid = True + return + # Type, deb or deb-src + self.type = string.strip(pieces[0]) + # Sanity check + if self.type not in ("deb", "deb-src", "rpm", "rpm-src"): + self.invalid = True + return + # URI + self.uri = string.strip(pieces[1]) + if len(self.uri) < 1: + self.invalid = True + # distro and components (optional) + # Directory or distro + self.dist = string.strip(pieces[2]) + if len(pieces) > 3: + # List of components + self.comps = pieces[3:] + else: + self.comps = [] + + def set_enabled(self, new_value): + """ set a line to enabled or disabled """ + self.disabled = not new_value + # enable, remove all "#" from the start of the line + if new_value == True: + i=0 + self.line = string.lstrip(self.line) + while self.line[i] == "#": + i += 1 + self.line = self.line[i:] + else: + # disabled, add a "#" + if string.strip(self.line)[0] != "#": + self.line = "#" + self.line + + def __str__(self): + """ debug helper """ + return self.str().strip() + + def str(self): + """ return the current line as string """ + if self.invalid: + return self.line + line = "" + if self.disabled: + line = "# " + line += "%s %s %s" % (self.type, self.uri, self.dist) + if len(self.comps) > 0: + line += " " + " ".join(self.comps) + if self.comment != "": + line += " #"+self.comment + line += "\n" + return line + +class NullMatcher(object): + """ a Matcher that does nothing """ + def match(self, s): + return True + +class SourcesList: + """ represents the full sources.list + sources.list.d file """ + def __init__(self, + withMatcher=True, + matcherPath="/usr/share/python-aptsources/templates/"): + self.list = [] # the actual SourceEntries Type + if withMatcher: + self.matcher = SourceEntryMatcher(matcherPath) + else: + self.matcher = NullMatcher() + self.refresh() + + def refresh(self): + """ update the list of known entries """ + self.list = [] + # read sources.list + dir = apt_pkg.Config.FindDir("Dir::Etc") + file = apt_pkg.Config.Find("Dir::Etc::sourcelist") + self.load(dir+file) + # read sources.list.d + partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") + for file in glob.glob("%s/*.list" % partsdir): + self.load(file) + # check if the source item fits a predefined template + for source in self.list: + if source.invalid == False: + self.matcher.match(source) + + def __iter__(self): + """ simple iterator to go over self.list, returns SourceEntry + types """ + for entry in self.list: + yield entry + raise StopIteration + + def add(self, type, uri, dist, comps, comment="", pos=-1, file=None): + """ + Add a new source to the sources.list. + The method will search for existing matching repos and will try to + reuse them as far as possible + """ + # check if we have this source already in the sources.list + for source in self.list: + if source.disabled == False and source.invalid == False and \ + source.type == type and uri == source.uri and \ + source.dist == dist: + for new_comp in comps: + if new_comp in source.comps: + # we have this component already, delete it from the new_comps + # list + del comps[comps.index(new_comp)] + if len(comps) == 0: + return source + for source in self.list: + # if there is a repo with the same (type, uri, dist) just add the + # components + if source.disabled == False and source.invalid == False and \ + source.type == type and uri == source.uri and \ + source.dist == dist: + comps = uniq(source.comps + comps) + source.comps = comps + return source + # if there is a corresponding repo which is disabled, enable it + elif source.disabled == True and source.invalid == False and \ + source.type == type and uri == source.uri and \ + source.dist == dist and \ + len(set(source.comps) & set(comps)) == len(comps): + source.disabled = False + return source + # there isn't any matching source, so create a new line and parse it + line = "%s %s %s" % (type,uri,dist) + for c in comps: + line = line + " " + c; + if comment != "": + line = "%s #%s\n" %(line,comment) + line = line + "\n" + new_entry = SourceEntry(line) + if file != None: + new_entry.file = file + self.matcher.match(new_entry) + self.list.insert(pos, new_entry) + return new_entry + + def remove(self, source_entry): + """ remove the specified entry from the sources.list """ + self.list.remove(source_entry) + + def restoreBackup(self, backup_ext): + " restore sources.list files based on the backup extension " + dir = apt_pkg.Config.FindDir("Dir::Etc") + file = apt_pkg.Config.Find("Dir::Etc::sourcelist") + if os.path.exists(dir+file+backup_ext) and \ + os.path.exists(dir+file): + shutil.copy(dir+file+backup_ext,dir+file) + # now sources.list.d + partsdir = apt_pkg.Config.FindDir("Dir::Etc::sourceparts") + for file in glob.glob("%s/*.list" % partsdir): + if os.path.exists(file+backup_ext): + shutil.copy(file+backup_ext,file) + + def backup(self, backup_ext=None): + """ make a backup of the current source files, if no backup extension + is given, the current date/time is used (and returned) """ + already_backuped = set() + if backup_ext == None: + backup_ext = time.strftime("%y%m%d.%H%M") + for source in self.list: + if not source.file in already_backuped and os.path.exists(source.file): + shutil.copy(source.file,"%s%s" % (source.file,backup_ext)) + return backup_ext + + def load(self,file): + """ (re)load the current sources """ + try: + f = open(file, "r") + lines = f.readlines() + for line in lines: + source = SourceEntry(line,file) + self.list.append(source) + except: + print "could not open file '%s'" % file + else: + f.close() + + def save(self): + """ save the current sources """ + files = {} + for source in self.list: + if not files.has_key(source.file): + files[source.file]=open(source.file,"w") + files[source.file].write(source.str()) + for f in files: + files[f].close() + + def check_for_relations(self, sources_list): + """get all parent and child channels in the sources list""" + parents = [] + used_child_templates = {} + for source in sources_list: + # try to avoid checking uninterressting sources + if source.template == None: + continue + # set up a dict with all used child templates and corresponding + # source entries + if source.template.child == True: + key = source.template + if not used_child_templates.has_key(key): + used_child_templates[key] = [] + temp = used_child_templates[key] + temp.append(source) + else: + # store each source with children aka. a parent :) + if len(source.template.children) > 0: + parents.append(source) + #print self.used_child_templates + #print self.parents + return (parents, used_child_templates) + +# matcher class to make a source entry look nice +# lots of predefined matchers to make it i18n/gettext friendly +class SourceEntryMatcher: + def __init__(self, matcherPath): + self.templates = [] + # Get the human readable channel and comp names from the channel .infos + spec_files = glob.glob("%s/*.info" % matcherPath) + for f in spec_files: + f = os.path.basename(f) + i = f.find(".info") + f = f[0:i] + dist = DistInfo(f,base_dir=matcherPath) + for template in dist.templates: + if template.match_uri != None: + self.templates.append(template) + return + + def match(self, source): + """Add a matching template to the source""" + _ = gettext.gettext + found = False + for template in self.templates: + if (re.search(template.match_uri, source.uri) and + re.match(template.match_name, source.dist)): + found = True + source.template = template + break + elif (template.is_mirror(source.uri) and + re.match(template.match_name, source.dist)): + found = True + source.template = template + break + return found + + +# some simple tests +if __name__ == "__main__": + apt_pkg.InitConfig() + sources = SourcesList() + + for entry in sources: + print entry.str() + #print entry.uri + + mirror = is_mirror("http://archive.ubuntu.com/ubuntu/", + "http://de.archive.ubuntu.com/ubuntu/") + print "is_mirror(): %s" % mirror + + print is_mirror("http://archive.ubuntu.com/ubuntu", + "http://de.archive.ubuntu.com/ubuntu/") + print is_mirror("http://archive.ubuntu.com/ubuntu/", + "http://de.archive.ubuntu.com/ubuntu") + diff --git a/data/templates/Debian.info.in b/data/templates/Debian.info.in new file mode 100644 index 00000000..8a2eead3 --- /dev/null +++ b/data/templates/Debian.info.in @@ -0,0 +1,98 @@ +_ChangelogURI: http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog + +Suite: etch +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MatchUri: ftp[0-9]*\.[a-z]\.debian\.org +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian 4.0 'Etch' +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software + +Suite: etch-proposed-updates +RepositoryType: deb +ParentSuite: etch +_Description: Proposed updates + +Suite: etch/updates +RepositoryType: deb +ParentSuite: etch +_Description: Security updates + +Suite: sarge +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MatchUri: ftp[0-9]*\.[a-z]\.debian\.org +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian 3.1 'Sarge' +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software + +Suite: sarge-proposed-updates +RepositoryType: deb +ParentSuite: sarge +_Description: Proposed updates + +Suite: sarge/updates +RepositoryType: deb +ParentSuite: sarge +_Description: Security updates + +Suite: stable +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MatchUri: ftp[0-9]*\.[a-z]\.debian\.org +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian current stable release +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software + +Suite: testing +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MatchUri: ftp[0-9]*\.[a-z]\.debian\.org +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian testing +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software + +Suite: sid +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MatchUri: ftp[0-9]*\.[a-z]\.debian\.org +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian 'Sid' (unstable) +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software + +Suite: unstable +RepositoryType: deb +BaseURI: http://http.us.debian.org/debian/ +MirrorsFile: /usr/share/python-aptsources/templates/Debian.mirrors +_Description: Debian 'Sid' (unstable) +Component: main +_CompDescription: Officially supported +Component: contrib +_CompDescription: DFSG-compatible Software with Non-Free Dependencies +Component: non-free +_CompDescription: Non-DFSG-compatible Software diff --git a/data/templates/Debian.mirrors b/data/templates/Debian.mirrors new file mode 100644 index 00000000..3e92cdc8 --- /dev/null +++ b/data/templates/Debian.mirrors @@ -0,0 +1,797 @@ +#LOC:AR +http://debian.logiclinux.com/debian/ +ftp://ftp.ccc.uba.ar/pub/linux/debian/debian/ +http://ftp.ccc.uba.ar/pub/linux/debian/debian/ +#LOC:AT +ftp://ftp.at.debian.org/debian/ +ftp://debian.sil.at/debian/ +ftp://ftp.debian.at/debian/ +http://ftp.at.debian.org/debian/ +http://debian.sil.at/debian/ +http://ftp.debian.at/debian/ +ftp://gd.tuwien.ac.at/opsys/linux/debian/ +ftp://ftp.tuwien.ac.at/opsys/linux/debian/ +http://gd.tuwien.ac.at/opsys/linux/debian/ +http://ftp.tuwien.ac.at/opsys/linux/debian/ +ftp://debian.mur.at/debian/ +ftp://algo.mur.at/debian/ +ftp://spider.mur.at/debian/ +http://debian.mur.at/debian/ +http://algo.mur.at/debian/ +http://spider.mur.at/debian/ +ftp://ftp.tu-graz.ac.at/mirror/debian/ +ftp://ftp.tugraz.at/mirror/debian/ +http://ftp.tu-graz.ac.at/mirror/debian/ +http://ftp.tugraz.at/mirror/debian/ +ftp://ftp.univie.ac.at/systems/linux/debian/debian/ +http://ftp.univie.ac.at/systems/linux/debian/debian/ +ftp://debian.inode.at/debian/ +http://debian.inode.at/debian/ +#LOC:AU +ftp://ftp.wa.au.debian.org/debian/ +ftp://ftp.it.net.au/debian/ +ftp://poledra.it.net.au/debian/ +http://ftp.wa.au.debian.org/debian/ +http://ftp.it.net.au/debian/ +http://poledra.it.net.au/debian/ +ftp://ftp.au.debian.org/debian/ +ftp://planetmirror.com/debian/ +http://ftp.au.debian.org/debian/ +http://planetmirror.com/debian/ +ftp://mirror.aarnet.edu.au/debian/ +http://mirror.aarnet.edu.au/debian/ +ftp://ftp.monash.edu.au/pub/linux/debian/ +http://ftp.monash.edu.au/pub/linux/debian/ +ftp://ftp.uwa.edu.au/debian/ +http://ftp.uwa.edu.au/debian/ +ftp://mirror.eftel.com/debian/ +ftp://mirror.q-net.net.au/debian/ +http://mirror.eftel.com/debian/ +http://mirror.q-net.net.au/debian/ +ftp://mirror.pacific.net.au/debian/ +http://mirror.pacific.net.au/debian/ +ftp://ftp.iinet.net.au/debian/debian/ +http://ftp.iinet.net.au/debian/debian/ +ftp://mirror.datafast.net.au/debian/ +http://mirror.datafast.net.au/debian/ +http://mirror.optus.net/debian/ +http://mirror.optusnet.com.au/debian/ +#LOC:BE +ftp://ftp.kulnet.kuleuven.ac.be/debian/ +http://ftp.kulnet.kuleuven.ac.be/debian/ +ftp://ftp.easynet.be/debian/ +http://ftp.easynet.be/ftp/debian/ +ftp://ftp.belnet.be/debian/ +ftp://dalet.belnet.be/debian/ +http://ftp.belnet.be/debian/ +http://dalet.belnet.be/debian/ +ftp://ftp.debian.skynet.be/debian/ +http://ftp.debian.skynet.be/ftp/debian/ +ftp://ftp.scarlet.be/pub/debian/ +http://ftp.scarlet.be/pub/debian/ +#LOC:BG +ftp://ftp.bg.debian.org/debian/ +ftp://debian.spnet.net/debian/ +http://ftp.bg.debian.org/debian/ +http://debian.spnet.net/debian/ +ftp://debian.ludost.net/debian/ +ftp://marla.ludost.net/debian/ +http://debian.ludost.net/debian/ +http://marla.ludost.net/debian/ +ftp://ftp.uni-sofia.bg/debian/ +http://ftp.uni-sofia.bg/debian/ +ftp://debian.telecoms.bg/debian/ +http://debian.telecoms.bg/debian/ +#LOC:BR +ftp://ftp.br.debian.org/debian/ +ftp://ftp.inf.ufpr.br/debian/ +ftp://www.inf.ufpr.br/debian/ +http://ftp.br.debian.org/debian/ +http://ftp.inf.ufpr.br/debian/ +http://www.inf.ufpr.br/debian/ +http://sft.if.usp.br/debian/ +http://fma.if.usp.br/debian/ +ftp://linorg.usp.br/debian/ +http://linorg.usp.br/debian/ +http://linux.iq.usp.br/debian/ +http://torio.iq.usp.br/debian/ +ftp://ftp.pucpr.br/debian/ +http://ftp.pucpr.br/debian/ +ftp://www.las.ic.unicamp.br/pub/debian/ +ftp://seraph.las.ic.unicamp.br/pub/debian/ +ftp://ftp.las.ic.unicamp.br/pub/debian/ +http://www.las.ic.unicamp.br/pub/debian/ +http://seraph.las.ic.unicamp.br/pub/debian/ +http://ftp.las.ic.unicamp.br/pub/debian/ +http://debian.pop-sc.rnp.br/debian/ +http://mirror.pop-sc.rnp.br/debian/ +#LOC:BY +ftp://linux.org.by/debian/ +http://linux.org.by/debian/ +ftp://ftp.mgts.by/debian/ +http://ftp.mgts.by/debian/ +#LOC:CA +http://debian.yorku.ca/debian/ +ftp://ftp3.nrc.ca/debian/ +http://ftp3.nrc.ca/debian/ +ftp://gulus.usherbrooke.ca/debian/ +http://gulus.usherbrooke.ca/debian/ +ftp://mirror.cpsc.ucalgary.ca/debian/ +http://mirror.cpsc.ucalgary.ca/debian/ +http://mirror.peer1.net/debian/ +ftp://debian.mirror.rafal.ca/debian/ +http://debian.mirror.rafal.ca/debian/ +ftp://debian.savoirfairelinux.net/debian/ +ftp://gpl.savoirfairelinux.net/debian/ +http://debian.savoirfairelinux.net/debian/ +http://gpl.savoirfairelinux.net/debian/ +ftp://debian.mirror.iweb.ca/debian/ +http://debian.mirror.iweb.ca/debian/ +#LOC:CH +ftp://ftp.ch.debian.org/debian/ +ftp://debian.ethz.ch/debian/ +ftp://kaerpf.ethz.ch/debian/ +http://ftp.ch.debian.org/debian/ +http://debian.ethz.ch/debian/ +http://kaerpf.ethz.ch/debian/ +ftp://mirror.switch.ch/mirror/debian/ +http://mirror.switch.ch/ftp/mirror/debian/ +#LOC:CL +http://debian.ubiobio.cl/debian/ +#LOC:CN +ftp://ftp.linuxforum.net/debian/ +ftp://www2.linuxforum.net/debian/ +ftp://mirrors.geekbone.org/debian/ +http://mirrors.geekbone.org/debian/ +ftp://debian.cn99.com/debian/ +ftp://mirrors.cn99.com/debian/ +http://debian.cn99.com/debian/ +http://mirrors.cn99.com/debian/ +#LOC:CO +http://fatboy.umng.edu.co/debian/ +#LOC:CZ +ftp://ftp.cz.debian.org/debian/ +ftp://ftp.debian.cz/debian/ +ftp://www.debian.cz/debian/ +http://ftp.cz.debian.org/debian/ +http://ftp.debian.cz/debian/ +http://www.debian.cz/debian/ +ftp://debian.sh.cvut.cz/debian/ +ftp://ftp.sh.cvut.cz/debian/ +http://debian.sh.cvut.cz/debian/ +http://ftp.sh.cvut.cz/debian/ +ftp://ftp.zcu.cz/mirrors/debian/ +http://ftp.zcu.cz/mirrors/debian/ +#LOC:DE +ftp://ftp.de.debian.org/debian/ +ftp://ftp1.de.debian.org/debian/ +ftp://debian.inf.tu-dresden.de/debian/ +http://ftp.de.debian.org/debian/ +http://ftp1.de.debian.org/debian/ +http://debian.inf.tu-dresden.de/debian/ +ftp://ftp2.de.debian.org/debian/ +ftp://ftp.rfc822.org/debian/ +ftp://source.rfc822.org/debian/ +http://ftp2.de.debian.org/debian/ +http://ftp.rfc822.org/debian/ +http://source.rfc822.org/debian/ +ftp://ftp.tu-clausthal.de/pub/linux/debian/ +ftp://pegasus.rz.tu-clausthal.de/pub/linux/debian/ +ftp://debian.uni-essen.de/debian/ +ftp://debian.physik.uni-essen.de/debian/ +http://debian.uni-essen.de/debian/ +http://debian.physik.uni-essen.de/debian/ +ftp://ftp.freenet.de/pub/ftp.debian.org/debian/ +http://ftp.freenet.de/debian/ +ftp://ftp.uni-erlangen.de/pub/Linux/debian/ +http://ftp.uni-erlangen.de/pub/Linux/debian/ +ftp://sunsite.informatik.rwth-aachen.de/pub/Linux/debian/ +http://sunsite.informatik.rwth-aachen.de/ftp/pub/Linux/debian/ +ftp://ftp-stud.fht-esslingen.de/debian/ +http://ftp-stud.fht-esslingen.de/debian/ +ftp://ftp.stw-bonn.de/debian/ +http://ftp.stw-bonn.de/debian/ +ftp://ftp.fu-berlin.de/pub/unix/linux/mirrors/debian/ +ftp://Hefe.ZEDAT.FU-Berlin.DE/pub/unix/linux/mirrors/debian/ +ftp://debian.tu-bs.de/debian/ +http://debian.tu-bs.de/debian/ +ftp://ftp.uni-koeln.de/debian/ +http://ftp.uni-koeln.de/debian/ +ftp://debian.pffa.de/pub/mirrors/debian/ +ftp://debian.ipv6.fhtw-berlin.de/pub/mirrors/debian/ +http://debian.pffa.de/mirrors/debian/ +http://debian.ipv6.fhtw-berlin.de/mirrors/debian/ +ftp://ftp.mpi-sb.mpg.de/pub/linux/distributions/debian/debian/ +ftp://ftp.tiscali.de/pub/debian/debian/ +ftp://pandemonium.tiscali.de/pub/debian/debian/ +http://ftp.tiscali.de/pub/debian/debian/ +http://pandemonium.tiscali.de/pub/debian/debian/ +ftp://ftp.tu-chemnitz.de/pub/linux/debian/debian/ +http://ftp.tu-chemnitz.de/pub/linux/debian/debian/ +ftp://ftp.uni-kl.de/debian/ +http://ftp.uni-kl.de/debian/ +ftp://ftp.uni-bayreuth.de/pub/linux/Debian/debian/ +ftp://rsync.uni-bayreuth.de/pub/linux/Debian/debian/ +ftp://btr0x2.rz.uni-bayreuth.de/pub/linux/Debian/debian/ +ftp://btr0qx.rz.uni-bayreuth.de/pub/linux/Debian/debian/ +http://ftp.uni-bayreuth.de/linux/Debian/debian/ +http://rsync.uni-bayreuth.de/linux/Debian/debian/ +http://btr0x2.rz.uni-bayreuth.de/linux/Debian/debian/ +http://btr0qx.rz.uni-bayreuth.de/linux/Debian/debian/ +ftp://ftp.informatik.hu-berlin.de/pub/Mirrors/ftp.de.debian.org/debian/ +ftp://ftp.gwdg.de/pub/linux/debian/debian/ +http://ftp.gwdg.de/pub/linux/debian/debian/ +ftp://ftp.hosteurope.de/pub/linux/debian/ +http://ftp.hosteurope.de/pub/linux/debian/ +ftp://ftp.informatik.uni-frankfurt.de/pub/linux/Mirror/ftp.debian.org/debian/ +ftp://ftp.cs.uni-frankfurt.de/pub/linux/Mirror/ftp.debian.org/debian/ +http://ftp.informatik.uni-frankfurt.de/debian/ +http://ftp.cs.uni-frankfurt.de/debian/ +ftp://debian.netcologne.de/debian/ +http://debian.netcologne.de/debian/ +ftp://artfiles.org/debian/ +http://artfiles.org/debian/ +http://debian.intergenia.de/debian/ +http://debian.server4you.de/debian/ +http://debian.vserver.de/debian/ +http://debian.plusserver.de/debian/ +ftp://debian.swordcoast.net/debian/ +http://debian.swordcoast.net/debian/ +#LOC:DK +ftp://ftp.dk.debian.org/debian/ +ftp://mirrors.dotsrc.org/debian/ +http://ftp.dk.debian.org/debian/ +http://mirrors.dotsrc.org/debian/ +ftp://ftp.dkuug.dk/pub/debian/ +http://ftp.dkuug.dk/debian/ +http://mirror.here.dk/debian/ +http://debian.uni-c.dk/debian/ +http://ymer.uni-c.dk/debian/ +ftp://mirrors.telianet.dk/debian/ +ftp://mirrors.dk.telia.net/debian/ +http://mirrors.telianet.dk/debian/ +http://mirrors.dk.telia.net/debian/ +#LOC:EE +ftp://ftp.ee.debian.org/debian/ +ftp://ftp.linux.ee/debian/ +ftp://linux.ee/debian/ +http://ftp.ee.debian.org/debian/ +http://ftp.linux.ee/debian/ +http://linux.ee/debian/ +#LOC:ES +ftp://ftp.es.debian.org/debian/ +ftp://ulises.adi.uam.es/debian/ +http://ftp.es.debian.org/debian/ +http://ulises.adi.uam.es/debian/ +ftp://ftp.rediris.es/debian/ +http://ftp.rediris.es/debian/ +ftp://ftp.caliu.info/debian/ +http://ftp.caliu.info/debian/ +ftp://ftp.gva.es/pub/mirror/debian/ +ftp://frigga.gva.es/pub/mirror/debian/ +http://ftp.gva.es/mirror/debian/ +http://frigga.gva.es/mirror/debian/ +ftp://ftp.gul.uc3m.es/debian/ +ftp://ftp.gul.es/debian/ +http://ftp.gul.uc3m.es/debian/ +http://ftp.gul.es/debian/ +#LOC:FI +ftp://ftp.fi.debian.org/debian/ +ftp://trumpetti.atm.tut.fi/debian/ +http://ftp.fi.debian.org/debian/ +http://trumpetti.atm.tut.fi/debian/ +ftp://ftp.funet.fi/pub/linux/mirrors/debian/ +http://ftp.funet.fi/pub/linux/mirrors/debian/ +ftp://ftp.jyu.fi/debian/ +ftp://lennon.cc.jyu.fi/debian/ +http://ftp.jyu.fi/debian/ +http://lennon.cc.jyu.fi/debian/ +#LOC:FR +ftp://ftp.fr.debian.org/debian/ +ftp://debian.proxad.net/debian/ +ftp://ftpmirror.proxad.net/debian/ +http://ftp.fr.debian.org/debian/ +http://debian.proxad.net/debian/ +http://ftpmirror.proxad.net/debian/ +ftp://ftp2.fr.debian.org/debian/ +ftp://ftp.oleane.net/debian/ +http://ftp2.fr.debian.org/debian/ +http://ftp.oleane.net/debian/ +ftp://ftp.iut-bm.univ-fcomte.fr/debian/ +http://ftp.iut-bm.univ-fcomte.fr/debian/ +ftp://ftp.proxad.net/mirrors/ftp.debian.org/ +ftp://ftp.free.fr/mirrors/ftp.debian.org/ +ftp://ftp.online.fr/mirrors/ftp.debian.org/ +ftp://ftp.proxad.fr/mirrors/ftp.debian.org/ +ftp://ftp.lip6.fr/pub/linux/distributions/debian/ +http://ftp.lip6.fr/pub/linux/distributions/debian/ +ftp://debian.ens-cachan.fr/debian/ +ftp://ftp.ens-cachan.fr/debian/ +http://debian.ens-cachan.fr/ftp/debian/ +http://ftp.ens-cachan.fr/ftp/debian/ +ftp://ftp.u-picardie.fr/mirror/debian/ +http://ftp.u-picardie.fr/mirror/debian/ +ftp://debian.mirrors.easynet.fr/debian/ +ftp://tengu.easynet.fr/debian/ +http://debian.mirrors.easynet.fr/ +http://tengu.easynet.fr/ +ftp://ftp.u-strasbg.fr/debian/ +http://ftp.u-strasbg.fr/debian/ +ftp://debian.ibisc.univ-evry.fr/debian/ +http://debian.ibisc.univ-evry.fr/debian/ +ftp://mir1.ovh.net/debian/ +http://mir1.ovh.net/debian/ +http://mir2.ovh.net/debian/ +http://mirror.ovh.net/debian/ +ftp://ftp.nerim.net/debian/ +http://ftp.nerim.net/debian/ +ftp://ftp.crihan.fr/debian/ +http://ftp.crihan.fr/debian/ +ftp://debian.mines.inpl-nancy.fr/debian/ +ftp://ftp.mines.inpl-nancy.fr/debian/ +http://debian.mines.inpl-nancy.fr/debian/ +http://ftp.mines.inpl-nancy.fr/debian/ +ftp://ftp.debian.ikoula.com/debian/ +ftp://webb.ens-cachan.fr/debian/ +ftp://debian.ens-cachan.fr/debian/ +http://webb.ens-cachan.fr/debian/ +http://debian.ens-cachan.fr/debian/ +ftp://mirrors.ircam.fr/pub/debian/ +http://mirrors.ircam.fr/pub/debian/ +#LOC:GB +ftp://ftp.uk.debian.org/debian/ +ftp://debian.hands.com/debian/ +http://ftp.uk.debian.org/debian/ +http://debian.hands.com/debian/ +ftp://debian.hands.com/debian/ +ftp://open.hands.com/debian/ +http://debian.hands.com/debian/ +http://open.hands.com/debian/ +ftp://ftp.demon.co.uk/pub/mirrors/linux/debian/ +ftp://ftp.demon.net/pub/mirrors/linux/debian/ +ftp://ftp.mcc.ac.uk/pub/linux/distributions/Debian/ +ftp://www.mirrorservice.org/sites/ftp.debian.org/debian/ +ftp://ftp.mirrorservice.org/sites/ftp.debian.org/debian/ +http://www.mirrorservice.org/sites/ftp.debian.org/debian/ +http://ftp.mirrorservice.org/sites/ftp.debian.org/debian/ +ftp://download.mirror.ac.uk/sites/ftp.debian.org/debian/ +ftp://ftp.mirror.ac.uk/sites/ftp.debian.org/debian/ +http://download.mirror.ac.uk/sites/ftp.debian.org/debian/ +http://ftp.mirror.ac.uk/sites/ftp.debian.org/debian/ +ftp://ftp.ticklers.org/debian/ +ftp://rib.ticklers.org/debian/ +http://ftp.ticklers.org/debian/ +http://rib.ticklers.org/debian/ +ftp://debian.blueyonder.co.uk/pub/debian/ +ftp://mirror2.blueyonder.co.uk/pub/debian/ +http://debian.blueyonder.co.uk/ +http://mirror2.blueyonder.co.uk/ +ftp://mirror.positive-internet.com/debian/ +http://mirror.positive-internet.com/debian/ +ftp://the.earth.li/debian/ +http://the.earth.li/debian/ +ftp://mirror.ox.ac.uk/debian/ +http://mirror.ox.ac.uk/debian/ +#LOC:GR +ftp://debian.otenet.gr/pub/linux/debian/ +http://debian.otenet.gr/debian/ +ftp://ftp.ntua.gr/pub/linux/debian/ +http://ftp.ntua.gr/pub/linux/debian/ +ftp://ftp.duth.gr/debian/ +http://ftp.duth.gr/debian/ +ftp://ftp.softnet.tuc.gr/pub/linux/debian/ +ftp://antirix.softnet.tuc.gr/pub/linux/debian/ +http://ftp.softnet.tuc.gr/ftp/linux/debian/ +http://antirix.softnet.tuc.gr/ftp/linux/debian/ +ftp://debian.internet.gr/debian/ +http://debian.internet.gr/debian/ +#LOC:HK +ftp://ftp.hk.debian.org/debian/ +ftp://ftp.debian.org.hk/debian/ +http://ftp.hk.debian.org/debian/ +http://ftp.debian.org.hk/debian/ +http://www.zentek-international.com/mirrors/debian/ +#LOC:HR +ftp://ftp.hr.debian.org/debian/ +ftp://debian.carnet.hr/debian/ +http://ftp.hr.debian.org/debian/ +http://debian.carnet.hr/debian/ +ftp://ftp.irb.hr/debian/ +http://ftp.irb.hr/debian/ +ftp://ftp.carnet.hr/debian/ +http://ftp.carnet.hr/debian/ +ftp://debian.iskon.hr/debian/ +http://debian.iskon.hr/debian/ +#LOC:HU +ftp://ftp.hu.debian.org/debian/ +ftp://ftp.fsn.hu/debian/ +http://ftp.hu.debian.org/debian/ +http://ftp.fsn.hu/debian/ +ftp://debian.inf.elte.hu/debian/ +http://debian.inf.elte.hu/debian/ +ftp://ftp.bme.hu/OS/Linux/dist/debian/ +http://ftp.bme.hu/OS/Linux/dist/debian/ +#LOC:ID +ftp://kebo.vlsm.org/debian/ +ftp://surabaya.vlsm.org/debian/ +ftp://katmai.its.ac.id/debian/ +http://kebo.vlsm.org/debian/ +http://surabaya.vlsm.org/debian/ +http://katmai.its.ac.id/debian/ +http://debian.indika.net.id/debian/ +#LOC:IE +ftp://ftp.ie.debian.org/debian/ +ftp://debian.heanet.ie/debian/ +ftp://debian.ipv6.heanet.ie/debian/ +ftp://canyonero.heanet.ie/debian/ +http://ftp.ie.debian.org/debian/ +http://debian.heanet.ie/debian/ +http://debian.ipv6.heanet.ie/debian/ +http://canyonero.heanet.ie/debian/ +ftp://ftp.esat.net/pub/linux/debian/ +http://ftp.esat.net/pub/linux/debian/ +#LOC:IL +http://mirror.hamakor.org.il/pub/mirrors/debian/ +#LOC:IN +ftp://ftp.iitm.ac.in/debian/ +http://ftp.iitm.ac.in/debian/ +#LOC:IS +ftp://ftp.is.debian.org/debian/ +ftp://ftp.rhnet.is/debian/ +http://ftp.is.debian.org/debian/ +http://ftp.rhnet.is/debian/ +#LOC:IT +ftp://ftp.it.debian.org/debian/ +ftp://ftp.bofh.it/debian/ +ftp://vlad-tepes.bofh.it/debian/ +http://ftp.it.debian.org/debian/ +http://ftp.bofh.it/debian/ +http://vlad-tepes.bofh.it/debian/ +ftp://ftp.bononia.it/debian/ +http://ftp.bononia.it/debian/ +ftp://freedom.dicea.unifi.it/pub/linux/debian/ +http://freedom.dicea.unifi.it/ftp/pub/linux/debian/ +ftp://ftp.eutelia.it/pub/Debian_Mirror/ +ftp://mi.mirror.garr.it/mirrors/debian/ +http://mi.mirror.garr.it/mirrors/debian/ +ftp://debian.fastweb.it/debian/ +http://debian.fastweb.it/debian/ +ftp://ftp.unina.it/pub/linux/distributions/debian/ +http://ftp.unina.it/pub/linux/distributions/debian/ +ftp://debian.fastbull.org/debian/ +ftp://bull02.fastbull.org/debian/ +http://debian.fastbull.org/debian/ +http://bull02.fastbull.org/debian/ +#LOC:JP +ftp://ftp.jp.debian.org/debian/ +ftp://ftp.nara.wide.ad.jp/debian/ +ftp://ftp.aist-nara.ac.jp/debian/ +http://ftp.jp.debian.org/debian/ +http://ftp.nara.wide.ad.jp/debian/ +http://ftp.aist-nara.ac.jp/debian/ +ftp://ftp2.jp.debian.org/debian/ +ftp://ftp.debian.or.jp/debian/ +ftp://http.debian.or.jp/debian/ +http://ftp2.jp.debian.org/debian/ +http://ftp.debian.or.jp/debian/ +http://http.debian.or.jp/debian/ +ftp://ring.asahi-net.or.jp/pub/linux/debian/debian/ +http://ring.asahi-net.or.jp/archives/linux/debian/debian/ +ftp://ftp.dti.ad.jp/pub/Linux/debian/ +http://ftp.dti.ad.jp/pub/Linux/debian/ +ftp://dennou-k.gfd-dennou.org/library/Linux/debian/ +ftp://dennou-k.gaia.h.kyoto-u.ac.jp/library/Linux/debian/ +http://dennou-k.gfd-dennou.org/library/Linux/debian/ +http://dennou-k.gaia.h.kyoto-u.ac.jp/library/Linux/debian/ +ftp://dennou-q.gfd-dennou.org/library/Linux/debian/ +ftp://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian/ +http://dennou-q.gfd-dennou.org/library/Linux/debian/ +http://dennou-q.geo.kyushu-u.ac.jp/library/Linux/debian/ +ftp://ftp.yz.yamagata-u.ac.jp/debian/ +ftp://linux.yz.yamagata-u.ac.jp/debian/ +http://ftp.yz.yamagata-u.ac.jp/debian/ +http://linux.yz.yamagata-u.ac.jp/debian/ +ftp://sb.itc.u-tokyo.ac.jp/DEBIAN/debian/ +ftp://ftp.ecc.u-tokyo.ac.jp/DEBIAN/debian/ +ftp://ftp.riken.go.jp/pub/Linux/debian/debian/ +http://ftp.riken.go.jp/pub/Linux/debian/debian/ +http://debian.shimpinomori.net/debian/ +ftp://www.ring.gr.jp/pub/linux/debian/debian/ +ftp://ftp.ring.gr.jp/pub/linux/debian/debian/ +http://www.ring.gr.jp/archives/linux/debian/debian/ +http://ftp.ring.gr.jp/archives/linux/debian/debian/ +ftp://ftp.jaist.ac.jp/pub/Linux/Debian/ +http://ftp.jaist.ac.jp/pub/Linux/Debian/ +#LOC:KR +ftp://ftp.kr.debian.org/debian/ +ftp://ftp.kaist.ac.kr/debian/ +http://ftp.kr.debian.org/debian/ +http://ftp.kaist.ac.kr/debian/ +#LOC:LT +ftp://ameba.sc-uni.ktu.lt/debian/ +http://ameba.sc-uni.ktu.lt/debian/ +ftp://debian.balt.net/debian/ +http://debian.balt.net/debian/ +#LOC:LV +ftp://ftp.latnet.lv/linux/debian/ +ftp://milzis.latnet.lv/linux/debian/ +http://ftp.latnet.lv/linux/debian/ +http://milzis.latnet.lv/linux/debian/ +#LOC:MX +ftp://nisamox.fciencias.unam.mx/debian/ +http://nisamox.fciencias.unam.mx/debian/ +#LOC:NI +http://debian.uni.edu.ni/debian/ +#LOC:NL +ftp://ftp.nl.debian.org/debian/ +ftp://slagroom.snt.utwente.nl/debian/ +http://ftp.nl.debian.org/debian/ +http://slagroom.snt.utwente.nl/debian/ +ftp://ftp.nluug.nl/pub/os/Linux/distr/debian/ +http://ftp.nluug.nl/pub/os/Linux/distr/debian/ +ftp://ftp.surfnet.nl/pub/os/Linux/distr/debian/ +http://ftp.surfnet.nl/os/Linux/distr/debian/ +ftp://download.xs4all.nl/pub/mirror/debian/ +ftp://dl.xs4all.nl/pub/mirror/debian/ +ftp://ftp.debian.nl/debian/ +ftp://morpheus.hoho.nl/debian/ +http://ftp.debian.nl/debian/ +http://morpheus.hoho.nl/debian/ +ftp://ftp.tiscali.nl/pub/mirrors/debian/ +http://ftp.tiscali.nl/debian/ +ftp://debian.essentkabel.com/debian/ +http://debian.essentkabel.com/debian/ +#LOC:NO +ftp://ftp.no.debian.org/debian/ +ftp://ftp.uninett.no/debian/ +http://ftp.no.debian.org/debian/ +http://ftp.uninett.no/debian/ +#LOC:NZ +ftp://ftp.nz.debian.org/debian/ +ftp://ftp.citylink.co.nz/debian/ +http://ftp.nz.debian.org/debian/ +http://ftp.citylink.co.nz/debian/ +ftp://debian.ihug.co.nz/debian/ +http://debian.ihug.co.nz/debian/ +#LOC:PL +ftp://ftp.pl.debian.org/debian/ +ftp://ftp.task.gda.pl/debian/ +http://ftp.pl.debian.org/debian/ +http://ftp.task.gda.pl/debian/ +ftp://ftp.icm.edu.pl/pub/Linux/debian/ +ftp://sunsite.icm.edu.pl/pub/Linux/debian/ +http://ftp.icm.edu.pl/pub/Linux/debian/ +http://sunsite.icm.edu.pl/pub/Linux/debian/ +ftp://ftp.man.szczecin.pl/pub/Linux/debian/ +ftp://rubycon.man.szczecin.pl/pub/Linux/debian/ +#LOC:PT +ftp://ftp.uevora.pt/debian/ +ftp://khaverna.sc.uevora.pt/debian/ +http://ftp.uevora.pt/debian/ +http://khaverna.sc.uevora.pt/debian/ +ftp://ftp.eq.uc.pt/pub/software/Linux/debian/ +http://ftp.eq.uc.pt/software/Linux/debian/ +ftp://debian.ua.pt/debian/ +ftp://ftp.ua.pt/debian/ +http://debian.ua.pt/debian/ +http://ftp.ua.pt/debian/ +ftp://ftp.linux.pt/pub/mirrors/debian/ +http://ftp.linux.pt/pub/mirrors/debian/ +#LOC:RO +ftp://ftp.ro.debian.org/debian/ +ftp://ftp.iasi.roedu.net/debian/ +http://ftp.ro.debian.org/debian/ +http://ftp.iasi.roedu.net/debian/ +ftp://ftp.lug.ro/debian/ +http://ftp.lug.ro/debian/ +#LOC:RU +ftp://ftp.ru.debian.org/debian/ +ftp://ftp.chg.ru/debian/ +http://ftp.ru.debian.org/debian/ +http://ftp.chg.ru/debian/ +ftp://debian.nsu.ru/debian/ +http://debian.nsu.ru/debian/ +ftp://debian.udsu.ru/debian/ +ftp://ftp.udsu.ru/debian/ +http://debian.udsu.ru/debian/ +http://ftp.udsu.ru/debian/ +ftp://ftp.psn.ru/debian/ +ftp://server.psn.ru/debian/ +http://ftp.psn.ru/debian/ +http://server.psn.ru/debian/ +ftp://ftp.corbina.ru/pub/Linux/debian/ +ftp://earth.corbina.net/pub/Linux/debian/ +ftp://ftp.mipt.ru/debian/ +ftp://petrel.telecom.mipt.ru/debian/ +#LOC:SE +ftp://ftp.se.debian.org/debian/ +ftp://ftp.acc.umu.se/debian/ +http://ftp.se.debian.org/debian/ +http://ftp.acc.umu.se/debian/ +ftp://ftp.sunet.se/pub/os/Linux/distributions/debian/ +http://ftp.sunet.se/pub/os/Linux/distributions/debian/ +ftp://ftp.du.se/debian/ +http://ftp.du.se/debian/ +ftp://ftp.port80.se/debian/ +http://ftp.port80.se/debian/ +ftp://ftp.ds.hj.se/pub/os/linux/debian/ +http://ftp.ds.hj.se/pub/os/linux/debian/ +#LOC:SG +ftp://mirror.nus.edu.sg/pub/Debian/ +ftp://mirror.comp.nus.edu.sg/pub/Debian/ +http://mirror.nus.edu.sg/Debian/ +http://mirror.comp.nus.edu.sg/Debian/ +ftp://debian.wow-vision.com.sg/debian/ +http://debian.wow-vision.com.sg/debian/ +#LOC:SI +ftp://ftp.si.debian.org/debian/ +ftp://ftp.camtp.uni-mb.si/debian/ +ftp://debian.camtp.uni-mb.si/debian/ +http://ftp.si.debian.org/debian/ +http://ftp.camtp.uni-mb.si/debian/ +http://debian.camtp.uni-mb.si/debian/ +ftp://ftp.arnes.si/packages/debian/ +#LOC:SK +ftp://ftp.sk.debian.org/debian/ +ftp://ftp.tuke.sk/debian/ +ftp://ccfrog.ke.sanet.sk/debian/ +http://ftp.sk.debian.org/debian/ +http://ftp.tuke.sk/debian/ +http://ccfrog.ke.sanet.sk/debian/ +#LOC:TH +ftp://ftp.nectec.or.th/pub/linux-distributions/Debian/ +ftp://download.nectec.or.th/pub/linux-distributions/Debian/ +ftp://ftp.coe.psu.ac.th/debian/ +ftp://debian.coe.psu.ac.th/debian/ +http://ftp.coe.psu.ac.th/debian/ +http://debian.coe.psu.ac.th/debian/ +#LOC:TR +ftp://ftp.tr.debian.org/debian/ +ftp://debian.ankara.edu.tr/debian/ +ftp://ftp.ankara.edu.tr/debian/ +http://ftp.tr.debian.org/debian/ +http://debian.ankara.edu.tr/debian/ +http://ftp.ankara.edu.tr/debian/ +ftp://ftp.linux.org.tr/pub/mirrors/debian/ +#LOC:TW +ftp://ftp.tw.debian.org/debian/ +ftp://debian.linux.org.tw/debian/ +http://ftp.tw.debian.org/debian/ +http://debian.linux.org.tw/debian/ +ftp://debian.csie.ntu.edu.tw/pub/debian/ +http://debian.csie.ntu.edu.tw/debian/ +ftp://linux.cdpa.nsysu.edu.tw/debian/ +http://linux.cdpa.nsysu.edu.tw/debian/ +ftp://opensource.nchc.org.tw/debian/ +ftp://os.nchc.org.tw/debian/ +http://opensource.nchc.org.tw/debian/ +http://os.nchc.org.tw/debian/ +http://debian.nctu.edu.tw/debian/ +http://debian.ntcu.net/debian/ +ftp://mirror.nttu.edu.tw/debian/ +http://mirror.nttu.edu.tw/debian/ +#LOC:UA +ftp://debian.osdn.org.ua/pub/Debian/debian/ +http://debian.osdn.org.ua/debian/ +ftp://debian.org.ua/debian/ +ftp://mirror.3logic.net/debian/ +ftp://mirror.debian.org.ua/debian/ +http://debian.org.ua/debian/ +http://mirror.3logic.net/debian/ +http://mirror.debian.org.ua/debian/ +ftp://ftp.3logic.net/debian/ +#LOC:US +ftp://ftp.us.debian.org/debian/ +ftp://http.us.debian.org/debian/ +http://ftp.us.debian.org/debian/ +http://http.us.debian.org/debian/ +ftp://ftp.debian.org/debian/ +http://ftp.debian.org/debian/ +ftp://ftp.gtlib.gatech.edu/pub/debian/ +http://ftp.gtlib.gatech.edu/debian/ +ftp://ftp.egr.msu.edu/debian/ +ftp://ike.egr.msu.edu/debian/ +http://ftp.egr.msu.edu/debian/ +http://ike.egr.msu.edu/debian/ +ftp://distro.ibiblio.org/pub/linux/distributions/debian/ +http://distro.ibiblio.org/pub/linux/distributions/debian/ +ftp://ftp-mirror.internap.com/pub/debian/ +http://ftp-mirror.internap.com/pub/debian/ +ftp://ftp.cerias.purdue.edu/pub/os/debian/ +ftp://ftp9.freebsd.org/pub/os/debian/ +ftp://ftp8.usa.openbsd.org/pub/os/debian/ +ftp://omelas.cerias.purdue.edu/pub/os/debian/ +http://ftp.cerias.purdue.edu/pub/os/debian/ +http://ftp9.freebsd.org/pub/os/debian/ +http://ftp8.usa.openbsd.org/pub/os/debian/ +http://omelas.cerias.purdue.edu/pub/os/debian/ +ftp://ftp.cs.unm.edu/mirrors/debian/ +ftp://thelma.cs.unm.edu/mirrors/debian/ +ftp://mirrors.cs.unm.edu/mirrors/debian/ +ftp://mirror.cs.wisc.edu/pub/mirrors/linux/debian/ +http://mirror.cs.wisc.edu/pub/mirrors/linux/debian/ +ftp://ftp.uwsg.indiana.edu/linux/debian/ +ftp://uwsg.iu.edu/linux/debian/ +http://ftp.uwsg.indiana.edu/linux/debian/ +http://uwsg.iu.edu/linux/debian/ +ftp://ftp.ndlug.nd.edu/debian/ +http://ftp.ndlug.nd.edu/mirrors/debian/ +ftp://debian.uchicago.edu/debian/ +ftp://linux.uchicago.edu/debian/ +http://debian.uchicago.edu/debian/ +http://linux.uchicago.edu/debian/ +ftp://carroll.aset.psu.edu/pub/linux/distributions/debian/ +ftp://carroll.cac.psu.edu/pub/linux/distributions/debian/ +http://carroll.aset.psu.edu/pub/linux/distributions/debian/ +http://carroll.cac.psu.edu/pub/linux/distributions/debian/ +ftp://debian.fifi.org/pub/debian/ +ftp://ftp.fifi.org/pub/debian/ +http://debian.fifi.org/debian/ +http://ftp.fifi.org/debian/ +ftp://gladiator.real-time.com/linux/debian/ +ftp://mirrors.kernel.org/debian/ +ftp://rsync.kernel.org/debian/ +ftp://zeus1.kernel.org/debian/ +ftp://zeus2.kernel.org/debian/ +http://mirrors.kernel.org/debian/ +http://rsync.kernel.org/debian/ +http://zeus1.kernel.org/debian/ +http://zeus2.kernel.org/debian/ +ftp://ftp.keystealth.org/debian/ +http://ftp.keystealth.org/debian/ +ftp://debian.lcs.mit.edu/debian/ +ftp://debian.ipv6.lcs.mit.edu/debian/ +http://debian.lcs.mit.edu/debian/ +http://debian.ipv6.lcs.mit.edu/debian/ +ftp://linux.csua.berkeley.edu/debian/ +ftp://screwdriver.csua.berkeley.edu/debian/ +http://linux.csua.berkeley.edu/debian/ +http://screwdriver.csua.berkeley.edu/debian/ +ftp://debian.secsup.org/pub/linux/debian/ +http://debian.secsup.org/ +ftp://techweb.rfa.org/debian/ +ftp://chameleon.techweb.rfa.org/debian/ +http://techweb.rfa.org/debian/ +http://chameleon.techweb.rfa.org/debian/ +ftp://debian.osuosl.org/debian/ +ftp://debian.oregonstate.edu/debian/ +ftp://ftp.oregonstate.edu/debian/ +ftp://ftp.osuosl.org/debian/ +http://debian.osuosl.org/debian/ +http://debian.oregonstate.edu/debian/ +http://ftp.oregonstate.edu/debian/ +http://ftp.osuosl.org/debian/ +ftp://mirror.anl.gov/pub/debian/ +http://mirror.anl.gov/debian/ +ftp://sluglug.ucsc.edu/debian/ +http://sluglug.ucsc.edu/debian/ +ftp://mirrors.geeks.org/debian/ +http://mirrors.geeks.org/debian/ +http://debian.midco.net/debian/ +ftp://mirrors.usc.edu/pub/linux/distributions/debian/ +http://mirrors.usc.edu/pub/linux/distributions/debian/ +ftp://debian.mirrors.pair.com/ +http://debian.mirrors.pair.com/ +ftp://lug.mtu.edu/debian/ +http://lug.mtu.edu/debian/ +ftp://debian.mirrors.tds.net/debian/ +http://debian.mirrors.tds.net/debian/ +ftp://debian.cites.uiuc.edu/pub/debian/ +ftp://bazaar.cites.uiuc.edu/pub/debian/ +ftp://cosmos.cites.uiuc.edu/pub/debian/ +http://debian.cites.uiuc.edu/pub/debian/ +http://bazaar.cites.uiuc.edu/pub/debian/ +http://cosmos.cites.uiuc.edu/pub/debian/ +ftp://mirrors.tummy.com/pub/ftp.debian.org/ +http://mirrors.tummy.com/debian/ +ftp://debian.mirror.frontiernet.net/debian/ +http://debian.mirror.frontiernet.net/debian/ +ftp://cudlug.cudenver.edu/debian/ +http://cudlug.cudenver.edu/debian/ +#LOC:VE +http://debian.unesr.edu.ve/debian/ +#LOC:ZA +ftp://ftp.sun.ac.za/debian/ +ftp://archive.sun.ac.za/debian/ +http://ftp.sun.ac.za/ftp/debian/ +http://archive.sun.ac.za/ftp/debian/ diff --git a/data/templates/README.templates b/data/templates/README.templates new file mode 100644 index 00000000..414148ed --- /dev/null +++ b/data/templates/README.templates @@ -0,0 +1,46 @@ +Channel Definition +------------------ + +The .info files allow to specify a set of default channels that is available +in the dialog "add channel". The .info file whose name corresponds to the +LSB release name is used, e.g. 'Ubuntu.info' on a Ubuntu system. + +Furthermore all .info files are used to render the channels presented in the +sources list more user friendly. + + +Tags +---- + +Suite: the name of the dist used in the repository + +MatchSuite: mainly used for cdroms. defaults to Suite + +ParentSuite: the channel only appears as a component of the parent suite in + the add dialog + the components/sections of the suite correspond to the ones of + the parent suite. specified components of the suite itself + are ignored + +Available: determs the availabilty of the suite in the add dialog. + defaults to False + +RepositoryType: does the repository contain binary or source packages + +BaseURI: the base URI of the repository + +MatchURI: used for identifing mirrors + +Description: description of the suite. the translation is done through + gettext at runtime + +Component: a component/section of the suite (ignored if ParentSuite is + set) + +CompDescription: humand readable description of the component/section + (ignored if ParentSuite is set). the translation is done + through gettext at runtime + +ValidMirros: A file that contains a list of mirrors + + diff --git a/data/templates/Ubuntu.info.in b/data/templates/Ubuntu.info.in new file mode 100644 index 00000000..fa76879f --- /dev/null +++ b/data/templates/Ubuntu.info.in @@ -0,0 +1,279 @@ +_ChangelogURI: http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog + +Suite: feisty +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +MirrorsFile: /usr/share/python-aptsources/templates/Ubuntu.mirrors +_Description: Ubuntu 7.04 'Feisty Fawn' +Component: main +_CompDescription: Officially supported +_CompDescriptionLong: Canonical-supported Open Source software +Component: universe +_CompDescription: Community-maintained +_CompDescriptionLong: Community-maintained Open Source software +Component: restricted +_CompDescription: Non-free drivers +_CompDescriptionLong: Proprietary drivers for devices +Component: multiverse +_CompDescription: Restricted software +_CompDescriptionLong: Software restricted by copyright or legal issues + +Suite: feisty +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*7.04 +_Description: Cdrom with Ubuntu 7.04 'Feisty Fawn' +Available: False +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: feisty-security +ParentSuite: feisty +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Important security updates + +Suite: feisty-updates +ParentSuite: feisty +RepositoryType: deb +_Description: Recommended updates + +Suite: feisty-proposed +ParentSuite: feisty +RepositoryType: deb +_Description: Proposed updates + +Suite: feisty-backports +ParentSuite: feisty +RepositoryType: deb +_Description: Backported updates + +Suite: edgy +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +MirrorsFile: /usr/share/python-aptsources/templates/Ubuntu.mirrors +_Description: Ubuntu 6.10 'Edgy Eft' +Component: main +_CompDescription: Officially supported +_CompDescriptionLong: Canonical-supported Open Source software +Component: universe +_CompDescription: Community-maintained +_CompDescriptionLong: Community-maintained Open Source software +Component: restricted +_CompDescription: Non-free drivers +_CompDescriptionLong: Proprietary drivers for devices +Component: multiverse +_CompDescription: Restricted software +_CompDescriptionLong: Software restricted by copyright or legal issues + +Suite: edgy +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*6.10 +_Description: Cdrom with Ubuntu 6.10 'Edgy Eft' +Available: False +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: edgy-security +ParentSuite: edgy +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Important security updates + +Suite: edgy-updates +ParentSuite: edgy +RepositoryType: deb +_Description: Recommended updates + +Suite: edgy-proposed +ParentSuite: edgy +RepositoryType: deb +_Description: Proposed updates + +Suite: edgy-backports +ParentSuite: edgy +RepositoryType: deb +_Description: Backported updates + +Suite: dapper +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +MirrorsFile: /usr/share/python-aptsources/templates/Ubuntu.mirrors +_Description: Ubuntu 6.06 LTS 'Dapper Drake' +Component: main +_CompDescription: Officially supported +_CompDescriptionLong: Canonical-supported Open Source software +Component: universe +_CompDescription: Community-maintained (universe) +_CompDescriptionLong: Community-maintained Open Source software +Component: restricted +_CompDescription: Non-free drivers +_CompDescriptionLong: Proprietary drivers for devices +Component: multiverse +_CompDescription: Restricted software (Multiverse) +_CompDescriptionLong: Software restricted by copyright or legal issues + +Suite: dapper +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*6.06 +_Description: Cdrom with Ubuntu 6.06 LTS 'Dapper Drake' +Available: False +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: dapper-security +ParentSuite: dapper +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Important security updates + +Suite: dapper-updates +ParentSuite: dapper +RepositoryType: deb +_Description: Recommended updates + +Suite: dapper-proposed +ParentSuite: dapper +RepositoryType: deb +_Description: Proposed updates + +Suite: dapper-backports +ParentSuite: dapper +RepositoryType: deb +_Description: Backported updates + +Suite: breezy +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +MirrorsFile: /usr/share/python-aptsources/templates/Ubuntu.mirrors +_Description: Ubuntu 5.10 'Breezy Badger' +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright +Component: universe +_CompDescription: Community-maintained (Universe) +Component: multiverse +_CompDescription: Non-free (Multiverse) + +Suite: breezy +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*5.10 +_Description: Cdrom with Ubuntu 5.10 'Breezy Badger' +Available: False +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: breezy-security +ParentSuite: breezy +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Ubuntu 5.10 Security Updates + +Suite: breezy-updates +ParentSuite: breezy +RepositoryType: deb +_Description: Ubuntu 5.10 Updates + +Suite: breezy-backports +ParentSuite: breezy +RepositoryType: deb +_Description: Ubuntu 5.10 Backports + +Suite: hoary +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +MirrorsFile: /usr/share/python-aptsources/templates/Ubuntu.mirrors +_Description: Ubuntu 5.04 'Hoary Hedgehog' +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright +Component: universe +_CompDescription: Community-maintained (Universe) +Component: multiverse +_CompDescription: Non-free (Multiverse) + +Suite: hoary +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*5.04 +_Description: Cdrom with Ubuntu 5.04 'Hoary Hedgehog' +Available: False +Component: main +_CompDescription: Officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: hoary-security +ParentSuite: hoary +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Ubuntu 5.04 Security Updates + +Suite: hoary-updates +ParentSuite: hoary +RepositoryType: deb +_Description: Ubuntu 5.04 Updates + +Suite: hoary-backports +ParentSuite: hoary +RepositoryType: deb +_Description: Ubuntu 5.04 Backports + +Suite: warty +RepositoryType: deb +BaseURI: http://archive.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu +_Description: Ubuntu 4.10 'Warty Warthog' +Component: main +_CompDescription: No longer officially supported +Component: restricted +_CompDescription: Restricted copyright +Component: universe +_CompDescription: Community-maintained (Universe) +Component: multiverse +_CompDescription: Non-free (Multiverse) + +Suite: warty +MatchName: .* +BaseURI: cdrom:\[Ubuntu.*4.10 +_Description: Cdrom with Ubuntu 4.10 'Warty Warthog' +Available: False +Component: main +_CompDescription: No longer officially supported +Component: restricted +_CompDescription: Restricted copyright + +Suite: warty-security +ParentSuite: warty +RepositoryType: deb +BaseURI: http://security.ubuntu.com/ubuntu/ +MatchURI: archive.ubuntu.com/ubuntu|security.ubuntu.com +_Description: Ubuntu 4.10 Security Updates + +Suite: warty-updates +ParentSuite: warty +RepositoryType: deb +_Description: Ubuntu 4.10 Updates + +Suite: warty-backports +ParentSuite: warty +RepositoryType: deb +_Description: Ubuntu 4.10 Backports diff --git a/data/templates/Ubuntu.mirrors b/data/templates/Ubuntu.mirrors new file mode 100644 index 00000000..72b2b434 --- /dev/null +++ b/data/templates/Ubuntu.mirrors @@ -0,0 +1,267 @@ +#LOC:AU +http://mirror.optus.net/ubuntu/ +http://mirror.pacific.net.au/linux/ubuntu +#LOC:AT +http://ubuntu.inode.at/ubuntu/ +ftp://ubuntu.inode.at/ubuntu/ +rsync://ubuntu.inode.at/ubuntu/ubuntu/ +http://gd.tuwien.ac.at/opsys/linux/ubuntu/archive/ +#LOC:BE +http://ftp.belnet.be/linux/ubuntu/ubuntu/ +http://ubuntu.mirrors.skynet.be/pub/ubuntu.com/ubuntu/ +#LOC:BR +http://br.archive.ubuntu.com/ubuntu/ +ftp://br.archive.ubuntu.com/ubuntu/ +rsync://br.archive.ubuntu.com/ubuntu/ +http://espelhos.edugraf.ufsc.br/ubuntu/ +http://ubuntu.c3sl.ufpr.br/ubuntu/ +#LOC:BG +http://ubuntu.linux-bg.org/ubuntu/ +ftp://ubuntu.linux-bg.org/ubuntu/ +rsync://ubuntu.linux-bg.org::ubuntu +http://ubuntu.ipacct.com/ubuntu/ +ftp://ubuntu.ipacct.com/ubuntu/ +#LOC:CA +http://gulus.USherbrooke.ca/ubuntu/ +ftp://gulus.USherbrooke.ca/ubuntu/ +http://mirror.cpsc.ucalgary.ca/mirror/ubuntu.com/ +ftp://mirror.cpsc.ucalgary.ca/mirror/ubuntu.com/ +rsync://mirror.cpsc.ucalgary.ca/mirror/ubuntu.com/ +ftp://ftp.cs.mun.ca/pub/mirror/ubuntu/ +ftp://ftp.cs.mun.ca/pub/mirror/ubuntu/ +http://gulus.usherbrooke.ca/pub/distro/ubuntu/ +http://mirror.arcticnetwork.ca/pub/ubuntu/packages +http://ubuntu.mirror.rafal.ca/ubuntu/ +#LOC:CL +http://cl.archive.ubuntu.com/ubuntu/ +ftp://cl.archive.ubuntu.com/ubuntu/ +rsync://cl.archive.ubuntu.com/ubuntu/ +#LOC:CN +http://ubuntu.cn99.com/ubuntu/ +http://mirror.lupaworld.com/ubuntu/archive/ +#LOC:CR +http://ftp.ucr.ac.cr/ubuntu/ +#LOC:HR +http://hr.archive.ubuntu.com/ubuntu +ftp://hr.archive.ubuntu.com/ubuntu +rsync://hr.archive.ubuntu.com/ubuntu +#LOC:CZ +http://ubuntu.supp.name/ubuntu/ +http://ubuntu.sh.cvut.cz/ +http://ubuntu.supp.name/ubuntu +#LOC:DK +http://dk.archive.ubuntu.com/ubuntu/ +http://klid.dk/ftp/ubuntu/ +ftp://klid.dk/ubuntu +http://mirror.uni-c.dk/ubuntu/ +http://mirrors.dotsrc.org/ubuntu +#LOC:EE +http://ftp.estpak.ee/ubuntu/ +ftp://ftp.estpak.ee/ubuntu/ +rsync://ftp.estpak.ee/ubuntu/ +http://ftp.estpak.ee/pub/ubuntu/ +#LOC:FI +http://www.nic.funet.fi/pub/mirrors/archive.ubuntu.com/ +ftp://ftp.funet.fi/pub/mirrors/archive.ubuntu.com/ +rsync://rsync.nic.funet.fi/ftp/pub/mirrors/archive.ubuntu.com/ +http://mirrors.nic.funet.fi/ubuntu/ +#LOC:FR +ftp://ftp.free.fr/mirrors/ftp.ubuntu.com/ubuntu/ +ftp://ftp.free.fr/mirrors/ftp.ubuntu.com/ubuntu/ +http://ftp.crihan.fr/ubuntu +ftp://ftp.crihan.fr/ubuntu/ +rsync://ftp.crihan.fr/ubuntu/ +http://ftp.oleane.net/ubuntu +ftp://ftp.oleane.net/ubuntu +http://ftp.u-picardie.fr/mirror/ubuntu/ubuntu/ +ftp://ftp.u-picardie.fr/mirror/ubuntu/ubuntu/ +ftp://ubuntu.univ-nantes.fr/ubuntu +ftp://ubuntu.univ-nantes.fr/ubuntu +http://ftp.crihan.fr/mirrors/archive.ubuntu.com/ +ftp://ftp.free.fr/mirrors/ftp.ubuntu.com/ubuntu +ftp://ftp.free.fr/mirrors/ftp.ubuntu.com/ubuntu +#LOC:GE +http://ubuntu.eriders.ge/ubuntu +#LOC:DE +http://ubuntu.intergenia.de/ubuntu/ +rsync://ubuntu.intergenia.de/ubuntu-linux/ubuntu/ +ftp://ftp.fu-berlin.de/linux/ubuntu/ +ftp://ftp.fu-berlin.de/linux/ubuntu/ +http://ftp.halifax.rwth-aachen.de/ubuntu/ +ftp://ftp.halifax.rwth-aachen.de/ubuntu/ +http://ftp.stw-bonn.de/ubuntu/ +ftp://ftp.stw-bonn.de/ubuntu/ +rsync://ftp.stw-bonn.de/ubuntu/ +http://debian.charite.de/ubuntu/ +http://de.archive.ubuntu.com/ubuntu/ +ftp://ftp.cw.net/pub/linux/ftp.ubuntu.com/ubuntu/ +ftp://ftp.cw.net/pub/linux/ftp.ubuntu.com/ubuntu/ +http://ftp-stud.fht-esslingen.de/Mirrors/ubuntu +http://ftp.stw-bonn.de/ubuntu +http://ftp.tu-chemnitz.de/pub/linux/ubuntu/ +http://ftp.uni-muenster.de/pub/mirrors/ftp.ubuntu.com/ubuntu/ +http://snert.mi.hs-heilbronn.de/pub/ubuntu/ubuntu/ +#LOC:GR +http://ftp.duth.gr/pub/ubuntu/ +ftp://ftp.duth.gr/pub/ubuntu/ +rsync://ftp.duth.gr/ubuntu/ +http://ftp.ntua.gr/pub/linux/ubuntu/ +ftp://ftp.ntua.gr/pub/linux/ubuntu/ +http://gr.archive.ubuntu.com/ubuntu/ +ftp://gr.archive.ubuntu.com/ubuntu/ +#LOC:HU +ftp://ftp.fsn.hu/pub/linux/distributions/ubuntu +ftp://ftp.fsn.hu/pub/linux/distributions/ubuntu +#LOC:IS +http://ubuntu.lhi.is/ubuntu +#LOC:IE +http://ie.archive.ubuntu.com/ubuntu/ +ftp://ie.archive.ubuntu.com/ubuntu/ +rsync://ie.archive.ubuntu.com/ubuntu/ +http://ftp.esat.net/mirrors/archive.ubuntu.com/ +http://ftp.heanet.ie/pub/ubuntu/ +#LOC:IT +http://na.mirror.garr.it/mirrors/ubuntu-archive/ +ftp://na.mirror.garr.it/mirrors/ubuntu-archive/ +rsync://na.mirror.garr.it::ubuntu-archive/ +http://ubuntu.fastbull.org/ubuntu/ +ftp://ubuntu.fastbull.org/ubuntu/ +http://na.mirror.garr.it/mirrors/ubuntu-archive +#LOC:JP +http://ftp.ecc.u-tokyo.ac.jp/ubuntu/ +#LOC:KR +http://kr.archive.ubuntu.com/ubuntu/ +ftp://kr.archive.ubuntu.com/ubuntu/ +rsync://kr.archive.ubuntu.com/ubuntu +http://ftp.kaist.ac.kr/pub/ubuntu +http://mirror.letsopen.com/os/ubuntu +#LOC:LV +http://ftp.linux.edu.lv/ubuntu/ +#LOC:LT +http://ftp.litnet.lt/pub/ubuntu +#LOC:MN +http://archive.mnosi.org/ubuntu/ +ftp://archive.mnosi.org/ubuntu/ +#LOC:NL +http://nl.archive.ubuntu.com/ubuntu/ +ftp://nl.archive.ubuntu.com/ubuntu/ +rsync://nl.archive.ubuntu.com/ubuntu/ +http://ftp.tiscali.nl/ubuntu/ +ftp://ftp.tiscali.nl/pub/mirror/ubuntu +ftp://ftp.tudelft.nl/pub/Linux/archive.ubuntu.com/ +ftp://ftp.tudelft.nl/pub/Linux/archive.ubuntu.com/ +ftp://ftpserv.tudelft.nl/pub/Linux/archive.ubuntu.com/ +ftp://ftpserv.tudelft.nl/pub/Linux/archive.ubuntu.com/ +http://ubuntu.bit.nl/ubuntu/ +#LOC:NZ +http://ftp.citylink.co.nz/ubuntu/ +#LOC:NO +http://ftp.uninett.no/ubuntu/ +ftp://ftp.uninett.no/ubuntu/ +rsync://ftp.uninett.no/ubuntu/ +http://no.archive.ubuntu.com/ubuntu/ +ftp://no.archive.ubuntu.com/ubuntu/ +http://no.archive.ubuntu.com/ubuntu +ftp://no.archive.ubuntu.com/ubuntu +ftp://ftp.uninett.no/linux/ubuntu +ftp://ftp.uninett.no/linux/ubuntu +http://mirror.trivini.no/ubuntu/ +#LOC:PL +http://ftp.vectranet.pl/ubuntu +ftp://ftp.vectranet.pl/ubuntu +rsync://ftp.vectranet.pl/ubuntu +ftp://ftp.man.szczecin.pl/pub/Linux/ubuntu/ +ftp://ftp.man.szczecin.pl/pub/Linux/ubuntu/ +http://ubuntu.task.gda.pl/ubuntu/ +#LOC:PT +http://ftp.dei.uc.pt/pub/linux/ubuntu/archive/ +ftp://ftp.dei.uc.pt/pub/linux/ubuntu/archive/ +http://ubuntu.dcc.fc.up.pt/ +http://ftp.gil.di.uminho.pt/ubuntu/ +ftp://ftp.gil.di.uminho.pt/ubuntu/ +rsync://ftp.gil.di.uminho.pt/ubuntu/ +http://ubuntu.dcc.fc.up.pt +#LOC:RO +http://ftp.lug.ro/ubuntu/ +#LOC:RU +http://ftp.chg.ru/pub/Linux/ubuntu/archive/ +#LOC:CS +http://yu.archive.ubuntu.com/ubuntu +ftp://yu.archive.ubuntu.com/ubuntu +rsync://yu.archive.ubuntu.com/ubuntu +http://mirror.etf.bg.ac.yu/distributions/ubuntu/ubuntu-archive/ +http://mirror2.etf.bg.ac.yu/distributions/ubuntu/ubuntu-archive/ +#LOC:SK +http://ubuntu.ynet.sk/ubuntu/ +#LOC:ZA +http://ubuntu.mirror.ac.za/ +ftp://ubuntu.mirror.ac.za +rsync://ubuntu.mirror.ac.za/Ubuntu +http://ftp.leg.uct.ac.za/pub/linux/ubuntu/ +ftp://ftp.leg.uct.ac.za/pub/linux/ubuntu/ +rsync://ftp.leg.uct.ac.za/pub/linux/ubuntu/ +#LOC:ES +http://ftp.gui.uva.es/sites/ubuntu.com/ubuntu/ +ftp://ftp.um.es/mirror/ubuntu/ +ftp://ftp.um.es/mirror/ubuntu/ +#LOC:SE +http://se.archive.ubuntu.com/ubuntu/ +ftp://se.archive.ubuntu.com/ubuntu/ +rsync://se.archive.ubuntu.com/ubuntu/ +http://ftp.ds.karen.hj.se/pub/os/linux/ubuntu/ +ftp://ftp.ds.karen.hj.se/pub/os/linux/ubuntu/ +http://ftp.port80.se/ubuntu/ +#LOC:CH +http://mirror.switch.ch/ftp/mirror/ubuntu/ +ftp://mirror.switch.ch/mirror/ubuntu/ +#LOC:TW +http://ftp.cse.yzu.edu.tw/pub/Linux/Ubuntu/ubuntu/ +ftp://ftp.cse.yzu.edu.tw/pub/Linux/Ubuntu/ubuntu/ +http://ftp.twaren.net/Linux/Ubuntu/ubuntu/ +ftp://ftp.twaren.net/Linux/Ubuntu/ubuntu/ +http://mirror.nttu.edu.tw/ubuntu/ +ftp://mirror.nttu.edu.tw/ubuntu/ +http://tw.archive.ubuntu.com/ubuntu +ftp://tw.archive.ubuntu.com/ubuntu +rsync://tw.archive.ubuntu.com/ubuntu +http://debian.linux.org.tw/ubuntu +http://ftp.cse.yzu.edu.tw/ubuntu/ +#LOC:GB +http://www.mirrorservice.org/sites/archive.ubuntu.com/ubuntu/ +ftp://ftp.mirrorservice.org/sites/archive.ubuntu.com/ubuntu/ +rsync://rsync.mirrorservice.org/archive.ubuntu.com/ubuntu/ +http://archive.ubuntu.com/ubuntu/ +ftp://archive.ubuntu.com/ubuntu/ +rsync://archive.ubuntu.com/ubuntu +http://ftp.ticklers.org/archive.ubuntu.org/ubuntu/ +ftp://ftp.ticklers.org/archive.ubuntu.org/ubuntu/ +rsync://ftp0.ticklers.org/archive.ubuntu.org/ubuntu/ +#LOC:US +http://mirror.anl.gov/pub/ubuntu/ +ftp://mirror.anl.gov/pub/ubuntu/ +rsync://mirror.anl.gov/ubuntu/ +http://mirrors.cat.pdx.edu/ubuntu/ +ftp://mirrors.cat.pdx.edu/ubuntu/ +rsync://mirrors.cat.pdx.edu/ubuntu/ +http://www.gtlib.gatech.edu/pub/ubuntu +ftp://ftp.gtlib.gatech.edu/pub/ubuntu +rsync://rsync.gtlib.gatech.edu/ubuntu +http://mirror.cc.columbia.edu/pub/linux/ubuntu/archive/ +ftp://mirror.cc.columbia.edu/pub/linux/ubuntu/archive/ +http://mirror.cs.umn.edu/ubuntu/ +rsync://mirror.cs.umn.edu/ubuntu/ +http://carroll.cac.psu.edu/pub/linux/distributions/ubuntu/ +http://ftp.unina.it/pub/linux/distributions/ubuntu +http://ftp.ussg.iu.edu/linux/ubuntu/ +http://lug.mtu.edu/ubuntu/ +ftp://lug.mtu.edu/ubuntu/ +rsync://lug.mtu.edu/ubuntu/ +http://mirror.mcs.anl.gov/pub/ubuntu/ +http://mirrors.cs.wmich.edu/ubuntu/ +http://tamago.cs.ucr.edu/ubuntu/ubuntu/ +http://ubuntu.cs.utah.edu/ubuntu +http://ubuntu.secs.oakland.edu/ +#LOC:UZ +http://ubuntu.uz/ubuntu/ +http://ubuntu.snet.uz/ubuntu/ +ftp://ubuntu.snet.uz/ubuntu/ diff --git a/debian/control b/debian/control index 765c3914..4ea3a31c 100644 --- a/debian/control +++ b/debian/control @@ -5,18 +5,18 @@ Maintainer: APT Development Team <deity@lists.debian.org> Uploaders: Matt Zimmerman <mdz@debian.org>, Michael Vogt <mvo@debian.org> Standards-Version: 3.7.2 XS-Python-Version: all -Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.6.45ubuntu3), apt-utils, python-all-dev, python-central +Build-Depends: debhelper (>= 5.0.37.1), libapt-pkg-dev (>= 0.6.45), apt-utils, python-all-dev, python-central, python-distutils-extra, cdbs Package: python-apt Architecture: any -Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends} +Depends: ${python:Depends}, ${shlibs:Depends}, ${misc:Depends}, lsb-release Priority: optional Replaces: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18) Conflicts: python2.3-apt (<< 0.6.18), python2.4-apt (<< 0.6.18) Provides: ${python:Provides} XB-Python-Version: ${python:Versions} Description: Python interface to libapt-pkg - The apt-pkg Python interface will provide full access to the internal + The apt_pkg Python interface will provide full access to the internal libapt-pkg structures allowing Python programs to easily perform a variety of functions, such as: . @@ -24,3 +24,6 @@ Description: Python interface to libapt-pkg - Access to the APT package information database - Parsing of Debian package control files, and other files with a similar structure + . + The included 'aptsources' Python interface provides an abstraction of + the sources.list configuration on the repository and the distro level. diff --git a/debian/python-apt.docs b/debian/python-apt.docs index f7756d28..208050c5 100644 --- a/debian/python-apt.docs +++ b/debian/python-apt.docs @@ -1,2 +1,3 @@ README apt/README.apt +data/templates/README.templates diff --git a/debian/rules b/debian/rules index 7299f554..6367c02f 100755 --- a/debian/rules +++ b/debian/rules @@ -1,76 +1,8 @@ #!/usr/bin/make -f -# Made with the aid of dh_make, by Craig Small -# Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. -# Some lines taken from debmake, by Cristoph Lameter. -# This has to be exported to make some magic below work. -export DH_OPTIONS +DEB_AUTO_CLEANUP_RCS := yes +DEB_PYTHON_SYSTEM=pycentral -DEBVER=$(shell dpkg-parsechangelog |sed -n -e '/^Version:/s/^Version: //p') -DEB_BUILD_PROG:=debuild --preserve-envvar PATH --preserve-envvar CCACHE_DIR -us -uc $(DEB_BUILD_PROG_OPTS) - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -PYTHON=$(shell pyversions -r debian/control) - -build: build-stamp -build-stamp: - dh_testdir - - for PY in $(PYTHON); do \ - /usr/bin/$$PY setup.py build; \ - done - - touch build-stamp - -clean: - dh_testdir - dh_testroot - rm -f build-stamp - - for PY in $(PYTHON); do \ - /usr/bin/$$PY setup.py clean --all; \ - done - - dh_clean - -# Build architecture-independent files here. -binary-indep: DH_OPTIONS=-i -binary-indep: build - -# Build architecture-dependent files here. -binary-arch: DH_OPTIONS=-a -binary-arch: build - dh_testdir - dh_testroot - dh_clean -k - - for PY in $(PYTHON); do \ - /usr/bin/$$PY setup.py install --prefix=`pwd`/debian/python-apt/usr; \ - done - - dh_installdocs - dh_installchangelogs - dh_installexamples - dh_pycentral - dh_strip - dh_compress - dh_fixperms - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -source diff: - @echo >&2 'source and diff are obsolete - use dpkg-source -b'; false - -arch-build: - rm -rf debian/arch-build - mkdir -p debian/arch-build/python-apt-$(DEBVER) - tar -c --exclude=arch-build --no-recursion -f - `bzr inventory` | (cd debian/arch-build/python-apt-$(DEBVER);tar xf -) - (cd debian/arch-build/python-apt-$(DEBVER); $(DEB_BUILD_PROG)) - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary +# Add here any variable or target overrides you need +include /usr/share/cdbs/1/rules/debhelper.mk +include /usr/share/cdbs/1/class/python-distutils.mk diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 00000000..d5a84db2 --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1,3 @@ +[encoding: UTF-8] +[type: gettext/rfc822deb] data/templates/Ubuntu.info.in +[type: gettext/rfc822deb] data/templates/Debian.info.in diff --git a/po/python-apt.pot b/po/python-apt.pot new file mode 100644 index 00000000..ba144165 --- /dev/null +++ b/po/python-apt.pot @@ -0,0 +1,269 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2007-01-26 14:17+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#. ChangelogURI +#: ../data/templates/Ubuntu.info.in.h:4 +#, no-c-format +msgid "http://changelogs.ubuntu.com/changelogs/pool/%s/%s/%s/%s_%s/changelog" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:8 +msgid "Ubuntu 7.04 'Feisty Fawn'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:25 +msgid "Cdrom with Ubuntu 7.04 'Feisty Fawn'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:59 +msgid "Ubuntu 6.10 'Edgy Eft'" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:64 +msgid "Community-maintained" +msgstr "" + +#. CompDescriptionLong +#: ../data/templates/Ubuntu.info.in:68 +msgid "Proprietary drivers for devices" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:70 +msgid "Restricted software" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:76 +msgid "Cdrom with Ubuntu 6.10 'Edgy Eft'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:110 +msgid "Ubuntu 6.06 LTS 'Dapper Drake'" +msgstr "" + +#. CompDescriptionLong +#: ../data/templates/Ubuntu.info.in:113 +msgid "Canonical-supported Open Source software" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:115 +msgid "Community-maintained (universe)" +msgstr "" + +#. CompDescriptionLong +#: ../data/templates/Ubuntu.info.in:116 +msgid "Community-maintained Open Source software" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:118 +msgid "Non-free drivers" +msgstr "" + +#. CompDescriptionLong +#: ../data/templates/Ubuntu.info.in:119 +msgid "Proprietary drivers for devices " +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:121 +msgid "Restricted software (Multiverse)" +msgstr "" + +#. CompDescriptionLong +#: ../data/templates/Ubuntu.info.in:122 +msgid "Software restricted by copyright or legal issues" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:127 +msgid "Cdrom with Ubuntu 6.06 LTS 'Dapper Drake'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:139 +msgid "Important security updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:144 +msgid "Recommended updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:149 ../data/templates/Debian.info.in:42 +msgid "Proposed updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:154 +msgid "Backported updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:161 +msgid "Ubuntu 5.10 'Breezy Badger'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:174 +msgid "Cdrom with Ubuntu 5.10 'Breezy Badger'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:186 +msgid "Ubuntu 5.10 Security Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:191 +msgid "Ubuntu 5.10 Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:196 +msgid "Ubuntu 5.10 Backports" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:203 +msgid "Ubuntu 5.04 'Hoary Hedgehog'" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:216 +msgid "Cdrom with Ubuntu 5.04 'Hoary Hedgehog'" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:219 ../data/templates/Debian.info.in:94 +msgid "Officially supported" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:228 +msgid "Ubuntu 5.04 Security Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:233 +msgid "Ubuntu 5.04 Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:238 +msgid "Ubuntu 5.04 Backports" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:244 +msgid "Ubuntu 4.10 'Warty Warthog'" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:250 +msgid "Community-maintained (Universe)" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:252 +msgid "Non-free (Multiverse)" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:257 +msgid "Cdrom with Ubuntu 4.10 'Warty Warthog'" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:260 +msgid "No longer officially supported" +msgstr "" + +#. CompDescription +#: ../data/templates/Ubuntu.info.in:262 +msgid "Restricted copyright" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:269 +msgid "Ubuntu 4.10 Security Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:274 +msgid "Ubuntu 4.10 Updates" +msgstr "" + +#. Description +#: ../data/templates/Ubuntu.info.in:279 +msgid "Ubuntu 4.10 Backports" +msgstr "" + +#. ChangelogURI +#: ../data/templates/Debian.info.in.h:4 +#, no-c-format +msgid "http://packages.debian.org/changelogs/pool/%s/%s/%s/%s_%s/changelog" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:8 +msgid "Debian 4.0 'Etch' " +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:31 +msgid "Debian 3.1 'Sarge'" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:47 +msgid "Security updates" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:54 +msgid "Debian current stable release" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:67 +msgid "Debian testing" +msgstr "" + +#. Description +#: ../data/templates/Debian.info.in:92 +msgid "Debian 'Sid' (unstable)" +msgstr "" + +#. CompDescription +#: ../data/templates/Debian.info.in:96 +msgid "DFSG-compatible Software with Non-Free Dependencies" +msgstr "" + +#. CompDescription +#: ../data/templates/Debian.info.in:98 +msgid "Non-DFSG-compatible Software" +msgstr "" diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..718b6e23 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,8 @@ +[build] +l10n=True + +[build_l10n] +domain=python-apt + +[sdist] +formats = bztar @@ -3,8 +3,8 @@ from distutils.core import setup, Extension from distutils.sysconfig import parse_makefile -import string, glob - +from DistUtilsExtra.distutils_extra import build_extra, build_l10n +import glob, os, string # The apt_pkg module files = map(lambda source: "python/"+source, @@ -16,6 +16,18 @@ files = map(lambda source: "python/"+source, string.split(parse_makefile("python/makefile")["APT_INST_SRC"])) apt_inst = Extension("apt_inst", files, libraries=["apt-pkg","apt-inst"]); +# Replace the leading _ that is used in the templates for translation +templates = [] +if not os.path.exists("build/data/templates/"): + os.makedirs("build/data/templates") +for template in glob.glob('data/templates/*.info.in'): + source = open(template, "r") + build = open(os.path.join("build", template[:-3]), "w") + lines = source.readlines() + for line in lines: + build.write(line.lstrip("_")) + source.close() + build.close() setup(name="python-apt", version="0.6.17", @@ -23,6 +35,13 @@ setup(name="python-apt", author="APT Development Team", author_email="deity@lists.debian.org", ext_modules=[apt_pkg,apt_inst], - packages=['apt'] + packages=['apt', 'aptsources'], + data_files = [('share/python-apt/templates', + glob.glob('build/data/templates/*.info')), + ('share/python-apt/templates', + glob.glob('data/templates/*.mirrors'))], + cmdclass = { "build" : build_extra, + "build_l10n" : build_l10n }, + license = 'GNU GPL', + platforms = 'posix' ) - diff --git a/tests/data/sources.list b/tests/data/sources.list new file mode 100644 index 00000000..5481d4f0 --- /dev/null +++ b/tests/data/sources.list @@ -0,0 +1,6 @@ +# comment 1 +deb http://de.archive.ubuntu.com/ubuntu/ edgy main +# comment 2 +deb http://de.archive.ubuntu.com/ubuntu/ edgy restricted +# comment 3 +deb http://de.archive.ubuntu.com/ubuntu/ edgy universe
\ No newline at end of file diff --git a/tests/data/sources.list.testDistribution b/tests/data/sources.list.testDistribution new file mode 100644 index 00000000..1687c504 --- /dev/null +++ b/tests/data/sources.list.testDistribution @@ -0,0 +1,11 @@ +deb http://de.archive.ubuntu.com/ubuntu/ edgy main +deb http://de.archive.ubuntu.com/ubuntu/ edgy restricted +deb http://de.archive.ubuntu.com/ubuntu/ edgy universe +deb http://de.archive.ubuntu.com/ubuntu/ edgy-updates universe multiverse +deb http://de.archive.ubuntu.com/ubuntu/ edgy-updates restricted +deb http://de.archive.ubuntu.com/ubuntu/ edgy-security main +deb http://de.archive.ubuntu.com/ubuntu/ edgy-security multiverse +deb http://ftp.debian.org/debian sid main +deb ftp://ubuntu.cs.utah.edu/pub/ubuntu/ubuntu/ breezy main +deb ftp://ubuntu.cs.utah.edu/pub/ubuntu/ubuntu/ breezy-backports main +deb http://archive.ubuntu.com/ubuntu/ hoary main diff --git a/tests/test_aptsources.py b/tests/test_aptsources.py new file mode 100644 index 00000000..3ee106be --- /dev/null +++ b/tests/test_aptsources.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +import UpdateManager.Common.aptsources as aptsources +import unittest +import apt_pkg +import os +import copy + +class TestAptSources(unittest.TestCase): + def __init__(self, methodName): + unittest.TestCase.__init__(self, methodName) + apt_pkg.init() + apt_pkg.Config.Set("Dir::Etc", os.getcwd()) + apt_pkg.Config.Set("Dir::Etc::sourceparts",".") + + def testIsMirror(self): + self.assertTrue(aptsources.is_mirror("http://archive.ubuntu.com", + "http://de.archive.ubuntu.com")) + self.assertFalse(aptsources.is_mirror("http://archive.ubuntu.com", + "http://ftp.debian.org")) + + def testSourcesListReading(self): + apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list") + sources = aptsources.SourcesList() + self.assertEqual(len(sources.list), 6) + # test load + sources.list = [] + sources.load("data/sources.list") + self.assertEqual(len(sources.list), 6) + + def testSourcesListAdding(self): + apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list") + sources = aptsources.SourcesList() + # test to add something that is already there (main) + before = copy.deepcopy(sources) + sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["main"]) + self.assertTrue(sources.list == before.list) + # test to add something that is already there (restricted) + before = copy.deepcopy(sources) + sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["restricted"]) + self.assertTrue(sources.list == before.list) + # test to add something new: multiverse + sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["multiverse"]) + found = False + for entry in sources: + if (entry.type == "deb" and + entry.uri == "http://de.archive.ubuntu.com/ubuntu/" and + entry.dist == "edgy" and + "multiverse" in entry.comps): + found = True + self.assertTrue(found) + # test to add something new: multiverse *and* + # something that is already there + before = copy.deepcopy(sources) + sources.add("deb","http://de.archive.ubuntu.com/ubuntu/", + "edgy", + ["universe", "something"]) + found_universe = 0 + found_something = 0 + for entry in sources: + if (entry.type == "deb" and + entry.uri == "http://de.archive.ubuntu.com/ubuntu/" and + entry.dist == "edgy"): + for c in entry.comps: + if c == "universe": + found_universe += 1 + if c == "something": + found_something += 1 + #print "\n".join([s.str() for s in sources]) + self.assertEqual(found_something, 1) + self.assertEqual(found_universe, 1) + + def testDistribution(self): + apt_pkg.Config.Set("Dir::Etc::sourcelist","data/sources.list.testDistribution") + sources = aptsources.SourcesList() + distro = aptsources.Distribution() + distro.get_sources(sources) + # test if all suits of the current distro were detected correctly + dist_templates = set() + for s in sources: + if s.template: + dist_templates.add(s.template.name) + #print dist_templates + for d in ["edgy","edgy-security","edgy-updates","hoary","breezy", "breezy-backports"]: + self.assertTrue(d in dist_templates) + # test enable + comp = "restricted" + distro.enable_component(sources, comp) + found = {} + for entry in sources: + if (entry.type == "deb" and + entry.uri == "http://de.archive.ubuntu.com/ubuntu/" and + "edgy" in entry.dist): + for c in entry.comps: + if c == comp: + if not found.has_key(entry.dist): + found[entry.dist] = 0 + found[entry.dist] += 1 + #print "".join([s.str() for s in sources]) + for key in found: + self.assertEqual(found[key], 1) + + # add a not-already available component + comp = "multiverse" + distro.enable_component(sources, comp) + found = {} + for entry in sources: + if (entry.type == "deb" and + entry.template and + entry.template.name == "edgy"): + for c in entry.comps: + if c == comp: + if not found.has_key(entry.dist): + found[entry.dist] = 0 + found[entry.dist] += 1 + #print "".join([s.str() for s in sources]) + for key in found: + self.assertEqual(found[key], 1) + +if __name__ == "__main__": + unittest.main() diff --git a/utils/get_debian_mirrors.py b/utils/get_debian_mirrors.py new file mode 100755 index 00000000..ccddf8ed --- /dev/null +++ b/utils/get_debian_mirrors.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# get_debian_mirrors.py +# +# Download the latest list with available mirrors from the Debian +# website and extract the hosts from the raw page +# +# Copyright (c) 2006 Free Software Foundation Europe +# +# Author: Sebastian Heinlein <glatzor@ubuntu.com> +# +# 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-1307 +# USA + +import urllib2 +import re +import os +import commands +import sys + +# the list of official Ubuntu servers +mirrors = [] +# path to the local mirror list +list_path = "../data/templates/Debian.mirrors" + +req = urllib2.Request("http://www.debian.org/mirror/mirrors_full") +match = re.compile("^.*>([A-Za-z0-9-.\/_]+)<\/a>.*\n$") +match_location = re.compile('^<strong><a name="([A-Z]+)">.*') + +def add_sites(line, proto, sites, mirror_type): + path = match.sub(r"\1", line) + for site in sites: + mirror_type.append("%s://%s%s\n" % (proto, site.lstrip(), path)) + +try: + print "Downloading mirrors list from the Debian website..." + uri=urllib2.urlopen(req) + for line in uri.readlines(): + if line.startswith('<strong><a name="'): + location = match_location.sub(r"\1", line) + if location: + mirrors.append("#LOC:%s" % location) + if line.startswith("Site:"): + sites = line[6:-1].split(",") + elif line.startswith('Packages over HTTP'): + add_sites(line, "http", sites, mirrors) + elif line.startswith('Packages over FTP'): + add_sites(line, "ftp", sites, mirrors) + uri.close() +except: + print "Failed to download or to extract the mirrors list!" + sys.exit(1) + +print "Writing local mirrors list: %s" % list_path +list = open(list_path, "w") +for mirror in mirrors: + list.write("%s" % mirror) +list.close() +print "Done." diff --git a/utils/get_ubuntu_mirrors.py b/utils/get_ubuntu_mirrors.py new file mode 100755 index 00000000..62b18ba6 --- /dev/null +++ b/utils/get_ubuntu_mirrors.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# +# get_ubuntu_mirrors.py +# +# Download the latest list with available mirrors from the Ubuntu +# wiki and extract the hosts from the raw page +# +# Copyright (c) 2006 Free Software Foundation Europe +# +# Author: Sebastian Heinlein <glatzor@ubuntu.com> +# +# 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-1307 +# USA + +import urllib2 +import re +import os +import commands +import sys + +# the list of official Ubuntu servers +mirrors = [] +# path to the local mirror list +list_path = "../data/templates/Ubuntu.mirrors" + +req = urllib2.Request("https://wiki.ubuntu.com/Archive?action=raw") + +try: + print "Downloading mirrors list from the Ubuntu wiki..." + uri=urllib2.urlopen(req) + p = re.compile('^.*((http|ftp):\/\/[A-Za-z0-9-.:\/_]+).*\n*$') + for line in uri.readlines(): + if r"[[Anchor(dvd-images)]]" in line: + break + if "http://" in line or "ftp://" in line: + mirrors.append(p.sub(r"\1", line)) + uri.close() +except: + print "Failed to download or extract the mirrors list!" + sys.exit(1) + +print "Writing local mirrors list: %s" % list_path +list = open(list_path, "w") +for mirror in mirrors: + list.write("%s\n" % mirror) +list.close() +print "Done." + + diff --git a/utils/get_ubuntu_mirrors_from_lp.py b/utils/get_ubuntu_mirrors_from_lp.py new file mode 100755 index 00000000..fad495b5 --- /dev/null +++ b/utils/get_ubuntu_mirrors_from_lp.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# get_ubuntu_lp_mirrors.py +# +# Download the latest list with available Ubuntu mirrors from Launchpad.net +# and extract the hosts from the raw page +# +# Copyright (c) 2006 Free Software Foundation Europe +# +# Author: Sebastian Heinlein <glatzor@ubuntu.com> +# +# 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-1307 +# USA + +import urllib2 +import re +import sys + +# the list of official Ubuntu servers +mirrors = [] +# path to the local mirror list +list_path = "../data/templates/Ubuntu.mirrors" + + +try: + f = open("/usr/share/iso-codes/iso_3166.tab", "r") + lines = f.readlines() + f.close() +except: + print "Could not read country information" + sys.exit(1) + +countries = {} +for line in lines: + parts = line.split("\t") + countries[parts[1].strip()] = parts[0].lower() + +req = urllib2.Request("https://launchpad.net/ubuntu/+archivemirrors") +print "Downloading mirrors list from the Ubuntu wiki..." +try: + uri=urllib2.urlopen(req) + content = uri.read() + uri.close() +except: + print "Failed to download or extract the mirrors list!" + sys.exit(1) + +content = content.replace("\n", "") + +content_splits = re.split(r'<tr class="highlighted"', + re.findall(r'<table class="listing">.+?</table>', + content)[0]) +lines=[] +def find(split): + country = re.search(r"<strong>(.+?)</strong>", split) + if not country: + return + urls = re.findall(r'<a href="(?![a-zA-Z:/_\-]+launchpad.+?">)(.+?)">', + split) + if countries.has_key(country.group(1)): + lines.append("#LOC:%s" % countries[country.group(1)].upper()) + else: + lines.append("#LOC:%s" % country.group(1)) + map(lines.append, urls) + +map(find, content_splits) + +print "Writing local mirrors list: %s" % list_path +list = open(list_path, "w") +for line in lines: + list.write("%s\n" % line) +list.close() +print "Done." diff --git a/utils/mirrortest b/utils/mirrortest new file mode 100755 index 00000000..75ef917b --- /dev/null +++ b/utils/mirrortest @@ -0,0 +1,100 @@ +#!/usr/bin/env python +import threading, Queue, time, re, os, tempfile +import aptsources.sourceslist +import aptsources.distro +from timeit import Timer +import urllib +import socket +import random +socket.setdefaulttimeout(2) + +class MirrorTest: + class PingWorker(threading.Thread): + def __init__(self, jobs, results, id): + self.id = id + self.jobs = jobs + self.results = results + self.match_result = re.compile(r"^rtt .* = [\.\d]+/([\.\d]+)/.*") + threading.Thread.__init__(self) + def run(self): + result = None + while MirrorTest.completed_pings < MirrorTest.todo: + try: + mirror = self.jobs.get(True, 1) + host = mirror.hostname + except: + continue + print "Pinging (Worker %s) %s (%s) ..." % (self.id, + host, + MirrorTest.completed_pings) + commando = os.popen("ping -q -c 4 -W 2 -i 0.3 %s" % host, + "r") + while True: + line = commando.readline() + if not line: + break + result = re.findall(self.match_result, line) + MirrorTest.completed_pings_lock.acquire() + MirrorTest.completed_pings += 1 + if result: + self.results.append([float(result[0]), host, mirror]) + MirrorTest.completed_pings_lock.release() + + def speed_test(self, mirror): + url = "%s/%s" % (mirror.get_repo_urls()[0], + self.test_file) + print "Downloading %s ..." % url + start = time.time() + try: + data = urllib.urlopen(url).read(51200) + return 50 / (time.time() - start) + except: + return 0 + + def __init__(self, hosts, test_file): + self.test_file = test_file + jobs = Queue.Queue() + results = [] + for h in hosts: + jobs.put(h) + self.threads = [] + MirrorTest.completed_pings = 0 + MirrorTest.completed_pings_lock = threading.Lock() + MirrorTest.todo = len(hosts) + + for i in range(10): + t = MirrorTest.PingWorker(jobs, results, i) + self.threads.append(t) + t.start() + + for t in self.threads: + t.join() + + results.sort() + print "\n\nTop ten RTTs:" + for r in results[0:10]: + print "%s: %s" % (r[1], r[0]) + print "\n\n" + + results.insert(0, [0, "rand", hosts[random.randint(1, len(hosts))]]) + results.insert(0, [0, "rand", hosts[random.randint(1, len(hosts))]]) + + final = map(lambda r: (self.speed_test(r[2]), r[2]), + results[0:12]) + final.sort() + final.reverse() + print "\n\nBest mirrors:" + for f in final: + print "%s: %s KByte/s" % (f[1].hostname, int(f[0])) + +if __name__ == "__main__": + distro = aptsources.distro.get_distro() + distro.get_sources(aptsources.sourceslist.SourcesList()) + pipe = os.popen("dpkg --print-architecture") + arch = pipe.read().strip() + test_file = "dists/%s/%s/binary-%s/Packages.gz" % \ + (distro.source_template.name, + distro.source_template.components[0].name, + arch) + app = MirrorTest(distro.source_template.mirror_set.values(), + test_file) |
