2013-12-29 16:09:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
class SourceLists(object):
|
2016-06-04 11:35:59 +02:00
|
|
|
"""Represents a list of sources lists for apt
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, manifest_vars):
|
|
|
|
"""
|
|
|
|
:param dict manifest_vars: The manifest variables
|
|
|
|
"""
|
|
|
|
# A dictionary with the name of the file in sources.list.d as the key
|
|
|
|
# That values are lists of Source objects
|
|
|
|
self.sources = {}
|
|
|
|
# Save the manifest variables, we need the later on
|
|
|
|
self.manifest_vars = manifest_vars
|
|
|
|
|
|
|
|
def add(self, name, line):
|
|
|
|
"""Adds a source to the apt sources list
|
|
|
|
|
|
|
|
:param str name: Name of the file in sources.list.d, may contain manifest vars references
|
|
|
|
:param str line: The line for the source file, may contain manifest vars references
|
|
|
|
"""
|
|
|
|
name = name.format(**self.manifest_vars)
|
|
|
|
line = line.format(**self.manifest_vars)
|
|
|
|
if name not in self.sources:
|
|
|
|
self.sources[name] = []
|
|
|
|
self.sources[name].append(Source(line))
|
|
|
|
|
|
|
|
def target_exists(self, target):
|
|
|
|
"""Checks whether the target exists in the sources list
|
|
|
|
|
|
|
|
:param str target: Name of the target to check for, may contain manifest vars references
|
|
|
|
|
|
|
|
:return: Whether the target exists
|
|
|
|
:rtype: bool
|
|
|
|
"""
|
|
|
|
target = target.format(**self.manifest_vars)
|
|
|
|
# Run through all the sources and return True if the target exists
|
|
|
|
for lines in self.sources.itervalues():
|
|
|
|
if target in (source.distribution for source in lines):
|
|
|
|
return True
|
|
|
|
return False
|
2013-12-29 16:09:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
class Source(object):
|
2016-06-04 11:35:59 +02:00
|
|
|
"""Represents a single source line
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, line):
|
|
|
|
"""
|
|
|
|
:param str line: A apt source line
|
|
|
|
|
|
|
|
:raises SourceError: When the source line cannot be parsed
|
|
|
|
"""
|
|
|
|
# Parse the source line and populate the class attributes with it
|
|
|
|
# The format is taken from `man sources.list`
|
|
|
|
# or: http://manpages.debian.org/cgi-bin/man.cgi?sektion=5&query=sources.list&apropos=0&manpath=sid&locale=en
|
|
|
|
import re
|
|
|
|
regexp = re.compile('^(?P<type>deb|deb-src)\s+'
|
|
|
|
'(\[\s*(?P<options>.+\S)?\s*\]\s+)?'
|
|
|
|
'(?P<uri>\S+)\s+'
|
|
|
|
'(?P<distribution>\S+)'
|
|
|
|
'(\s+(?P<components>.+\S))?\s*$')
|
|
|
|
match = regexp.match(line).groupdict()
|
|
|
|
if match is None:
|
|
|
|
from exceptions import SourceError
|
|
|
|
raise SourceError('Unable to parse source line: ' + line)
|
|
|
|
self.type = match['type']
|
|
|
|
self.options = []
|
|
|
|
if match['options'] is not None:
|
|
|
|
self.options = re.sub(' +', ' ', match['options']).split(' ')
|
|
|
|
self.uri = match['uri']
|
|
|
|
self.distribution = match['distribution']
|
|
|
|
self.components = []
|
|
|
|
if match['components'] is not None:
|
|
|
|
self.components = re.sub(' +', ' ', match['components']).split(' ')
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
"""Convert the object into a source line
|
|
|
|
This is pretty much the reverse of what we're doing in the initialization function.
|
|
|
|
|
|
|
|
:rtype: str
|
|
|
|
"""
|
|
|
|
options = ''
|
|
|
|
if len(self.options) > 0:
|
|
|
|
options = ' [{options}]'.format(options=' '.join(self.options))
|
|
|
|
|
|
|
|
components = ''
|
|
|
|
if len(self.components) > 0:
|
|
|
|
components = ' {components}'.format(components=' '.join(self.components))
|
|
|
|
|
|
|
|
return ('{type}{options} {uri} {distribution}{components}'
|
|
|
|
.format(type=self.type, options=options,
|
|
|
|
uri=self.uri, distribution=self.distribution,
|
|
|
|
components=components))
|