mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-24 15:36:27 +00:00

Up until now I didn't see the point of using spaces for indentation. However, the previous commit (a18bec3) was quite eye opening. Given that python is an indentation aware language, the amount of mistakes that went unnoticed because tabs and spaces were used at the same time (tabs for indentation and spaces for alignment) were unacceptable. E101,W191 have been re-enable in the tox flake8 checker and the documentation has been modified accordingly. The following files have been left as-is: * bootstrapvz/common/assets/extlinux/extlinux.conf * bootstrapvz/common/assets/init.d/expand-root * bootstrapvz/common/assets/init.d/generate-ssh-hostkeys * bootstrapvz/common/assets/init.d/squeeze/generate-ssh-hostkeys * bootstrapvz/plugins/docker_daemon/assets/init.d/docker * bootstrapvz/providers/ec2/assets/bin/growpart * bootstrapvz/providers/ec2/assets/grub.d/40_custom * bootstrapvz/providers/ec2/assets/init.d/ec2-get-credentials * bootstrapvz/providers/ec2/assets/init.d/ec2-run-user-data * docs/_static/taskoverview.coffee * docs/_static/taskoverview.less * tests/unit/subprocess.sh
108 lines
4.7 KiB
Python
108 lines
4.7 KiB
Python
|
|
|
|
class PackageList(object):
|
|
"""Represents a list of packages
|
|
"""
|
|
|
|
class Remote(object):
|
|
"""A remote package with an optional target
|
|
"""
|
|
def __init__(self, name, target):
|
|
"""
|
|
:param str name: The name of the package
|
|
:param str target: The name of the target release
|
|
"""
|
|
self.name = name
|
|
self.target = target
|
|
|
|
def __str__(self):
|
|
"""Converts the package into somehting that apt-get install can parse
|
|
|
|
:rtype: str
|
|
"""
|
|
if self.target is None:
|
|
return self.name
|
|
else:
|
|
return self.name + '/' + self.target
|
|
|
|
class Local(object):
|
|
"""A local package
|
|
"""
|
|
def __init__(self, path):
|
|
"""
|
|
:param str path: The path to the local package
|
|
"""
|
|
self.path = path
|
|
|
|
def __str__(self):
|
|
"""
|
|
:return: The path to the local package
|
|
:rtype: string
|
|
"""
|
|
return self.path
|
|
|
|
def __init__(self, manifest_vars, source_lists):
|
|
"""
|
|
:param dict manifest_vars: The manifest variables
|
|
:param SourceLists source_lists: The sourcelists for apt
|
|
"""
|
|
self.manifest_vars = manifest_vars
|
|
self.source_lists = source_lists
|
|
# The default_target is the release we are bootstrapping
|
|
self.default_target = '{system.release}'.format(**self.manifest_vars)
|
|
# The list of packages that should be installed, this is not a set.
|
|
# We want to preserve the order in which the packages were added so that local
|
|
# packages may be installed in the correct order.
|
|
self.install = []
|
|
# A function that filters the install list and only returns remote packages
|
|
self.remote = lambda: filter(lambda x: isinstance(x, self.Remote), self.install)
|
|
|
|
def add(self, name, target=None):
|
|
"""Adds a package to the install list
|
|
|
|
:param str name: The name of the package to install, may contain manifest vars references
|
|
:param str target: The name of the target release for the package, may contain manifest vars references
|
|
|
|
:raises PackageError: When a package of the same name but with a different target has already been added.
|
|
:raises PackageError: When the specified target release could not be found.
|
|
"""
|
|
from exceptions import PackageError
|
|
name = name.format(**self.manifest_vars)
|
|
if target is not None:
|
|
target = target.format(**self.manifest_vars)
|
|
# Check if the package has already been added.
|
|
# If so, make sure it's the same target and raise a PackageError otherwise
|
|
package = next((pkg for pkg in self.remote() if pkg.name == name), None)
|
|
if package is not None:
|
|
# It's the same target if the target names match or one of the targets is None
|
|
# and the other is the default target.
|
|
same_target = package.target == target
|
|
same_target = same_target or package.target is None and target == self.default_target
|
|
same_target = same_target or package.target == self.default_target and target is None
|
|
if not same_target:
|
|
msg = ('The package {name} was already added to the package list, '
|
|
'but with target release `{target}\' instead of `{add_target}\''
|
|
.format(name=name, target=package.target, add_target=target))
|
|
raise PackageError(msg)
|
|
# The package has already been added, skip the checks below
|
|
return
|
|
|
|
# Check if the target exists (unless it's the default target) in the sources list
|
|
# raise a PackageError if does not
|
|
if target not in (None, self.default_target) and not self.source_lists.target_exists(target):
|
|
msg = ('The target release {target} was not found in the sources list').format(target=target)
|
|
raise PackageError(msg)
|
|
|
|
# Note that we maintain the target value even if it is none.
|
|
# This allows us to preserve the semantics of the default target when calling apt-get install
|
|
# Why? Try installing nfs-client/wheezy, you can't. It's a virtual package for which you cannot define
|
|
# a target release. Only `apt-get install nfs-client` works.
|
|
self.install.append(self.Remote(name, target))
|
|
|
|
def add_local(self, package_path):
|
|
"""Adds a local package to the installation list
|
|
|
|
:param str package_path: Path to the local package, may contain manifest vars references
|
|
"""
|
|
package_path = package_path.format(**self.manifest_vars)
|
|
self.install.append(self.Local(package_path))
|