summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aptsources/aptsources.py407
-rw-r--r--aptsources/distinfo.py (renamed from aptsources/DistInfo.py)99
-rw-r--r--aptsources/distro.py422
3 files changed, 477 insertions, 451 deletions
diff --git a/aptsources/aptsources.py b/aptsources/aptsources.py
index 457e13f2..0928a0e8 100644
--- a/aptsources/aptsources.py
+++ b/aptsources/aptsources.py
@@ -1,12 +1,12 @@
-# aptsource.py.in - parse sources.list
+# aptsource.py - Provide an abstraction of the sources.list
#
-# Copyright (c) 2004-2006 Canonical
+# Copyright (c) 2004-2007 Canonical Ltd.
# 2004 Michiel Sikkes
-# 2006 Sebastian Heinlein
+# 2006-2007 Sebastian Heinlein
#
# Author: Michiel Sikkes <michiel@eyesopened.nl>
# Michael Vogt <mvo@debian.org>
-# Sebastian Heinlein
+# 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
@@ -407,405 +407,6 @@ class SourceEntryMatcher:
break
return found
-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)
# some simple tests
if __name__ == "__main__":
diff --git a/aptsources/DistInfo.py b/aptsources/distinfo.py
index 69bc3410..7568b558 100644
--- a/aptsources/DistInfo.py
+++ b/aptsources/distinfo.py
@@ -1,8 +1,10 @@
#!/usr/bin/env python
-# DistInfo.py - simple parser for a xml-based metainfo file
#
+# 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>
#
@@ -30,7 +32,8 @@ import string
from gettext import gettext as _
import re
-class Suite:
+
+class Template:
def __init__(self):
self.name = None
self.child = False
@@ -116,7 +119,7 @@ class DistInfo:
dist = None,
base_dir = "/usr/share/python-aptsources/templates"):
self.metarelease_uri = ''
- self.suites = []
+ self.templates = []
location = None
match_loc = re.compile(r"^#LOC:(.+)$")
@@ -138,7 +141,7 @@ class DistInfo:
dist_file = open (dist_fname)
if not dist_file:
return
- suite = None
+ template = None
component = None
for line in dist_file:
tokens = line.split (':', 1)
@@ -151,38 +154,38 @@ class DistInfo:
elif field == 'MetaReleaseURI':
self.metarelease_uri = value
elif field == 'Suite':
- if suite:
- if component and not suite.has_component(component.name):
- suite.components.append(component)
+ if template:
+ if component and not template.has_component(component.name):
+ template.components.append(component)
component = None
- self.suites.append (suite)
- suite = Suite ()
- suite.name = value
- suite.distribution = dist
- suite.match_name = "^%s$" % value
+ self.templates.append(template)
+ template = Template()
+ template.name = value
+ template.distribution = dist
+ template.match_name = "^%s$" % value
elif field == 'MatchName':
- suite.match_name = value
+ template.match_name = value
elif field == 'ParentSuite':
- suite.child = True
- for nanny in self.suites:
+ template.child = True
+ for nanny in self.templates:
if nanny.name == value:
- nanny.children.append(suite)
- # reuse some properties of the parent suite
- if suite.match_uri == None:
- suite.match_uri = nanny.match_uri
- if suite.mirror_set == {}:
- suite.mirror_set = nanny.mirror_set
- if suite.base_uri == None:
- suite.base_uri = nanny.base_uri
+ 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':
- suite.available = value
+ template.available = value
elif field == 'RepositoryType':
- suite.type = value
+ template.type = value
elif field == 'BaseURI':
- suite.base_uri = value
- suite.match_uri = value
+ template.base_uri = value
+ template.match_uri = value
elif field == 'MatchURI':
- suite.match_uri = value
+ template.match_uri = value
elif field == 'MirrorsFile':
if not map_mirror_sets.has_key(value):
mirror_set = {}
@@ -202,37 +205,37 @@ class DistInfo:
else:
mirror_set[hostname] = Mirror(proto, hostname, dir, location)
map_mirror_sets[value] = mirror_set
- suite.mirror_set = map_mirror_sets[value]
+ template.mirror_set = map_mirror_sets[value]
elif field == 'Description':
- suite.description = _(value)
+ template.description = _(value)
elif field == 'Component':
- if component and not suite.has_component(component.name):
- suite.components.append(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 suite:
+ if template:
if component:
- suite.components.append(component)
+ template.components.append(component)
component = None
- self.suites.append (suite)
- suite = None
+ self.templates.append(template)
+ template = None
if __name__ == "__main__":
- d = DistInfo ("Ubuntu", "/usr/share/python-aptsources/templates")
+ d = DistInfo ("Ubuntu", "/usr/share/python-apt/templates")
print d.changelogs_uri
- for suite in d.suites:
- print "\nSuite: %s" % suite.name
- print "Desc: %s" % suite.description
- print "BaseURI: %s" % suite.base_uri
- print "MatchURI: %s" % suite.match_uri
- if suite.mirror_set != {}:
- print "Mirrors: %s" % suite.mirror_set.keys()
- for comp in suite.components:
+ 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.short_description)
- for child in suite.children:
+ 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..18a8ca46
--- /dev/null
+++ b/aptsources/distro.py
@@ -0,0 +1,422 @@
+# 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
+
+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)