blob: 81818ed03c18384460c1baab771a6821952c68b9 [file] [log] [blame]
# Copyright (c) 2014 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from webports.error import Error
from webports import configuration, pkg_info, util
EXTRA_KEYS = ['BUILD_CONFIG', 'BUILD_ARCH', 'BUILD_TOOLCHAIN',
'BUILD_SDK_VERSION', 'BUILD_NACLPORTS_REVISION']
class Package(object):
extra_keys = []
list_props = (
'DEPENDS',
'CONFLICTS',
'DISABLED_ARCH',
'DISABLED_LIBC',
'DISABLED_TOOLCHAIN'
)
def __init__(self, info_file=None):
self.info = info_file
if self.info:
with open(self.info) as f:
self.parse_info(f.read())
def parse_info(self, info_string):
valid_keys = pkg_info.VALID_KEYS + self.extra_keys
required_keys = pkg_info.REQUIRED_KEYS + self.extra_keys
for key in valid_keys:
if key in self.list_props:
setattr(self, key, [])
else:
setattr(self, key, None)
# Parse pkg_info file
info = pkg_info.parse_pkg_info(info_string, self.info, valid_keys,
required_keys)
# Set attributres based on pkg_info setttings.
for key, value in info.items():
setattr(self, key, value)
self.validate()
def validate(self):
for libc in self.DISABLED_LIBC:
if libc not in configuration.VALID_LIBC:
raise Error('%s: invalid libc: %s' % (self.info, libc))
for toolchain in self.DISABLED_TOOLCHAIN:
if '/' in toolchain:
toolchain, arch = toolchain.split('/')
if arch not in util.arch_to_pkgarch:
raise Error('%s: invalid architecture: %s' % (self.info, arch))
if toolchain not in configuration.VALID_TOOLCHAINS:
raise Error('%s: invalid toolchain: %s' % (self.info, toolchain))
for arch in self.DISABLED_ARCH:
if arch not in util.arch_to_pkgarch:
raise Error('%s: invalid architecture: %s' % (self.info, arch))
if '_' in self.NAME:
raise Error('%s: package NAME cannot contain underscores' % self.info)
if self.NAME != self.NAME.lower():
raise Error('%s: package NAME cannot contain uppercase characters' %
self.info)
if '_' in self.VERSION:
raise Error('%s: package VERSION cannot contain underscores' % self.info)
if self.DISABLED_ARCH and self.ARCH is not None:
raise Error('%s: contains both ARCH and DISABLED_ARCH' % self.info)
def __cmp__(self, other):
return cmp((self.NAME, self.VERSION, self.config),
(other.NAME, other.VERSION, other.config))
def __hash__(self):
return hash((self.NAME, self.VERSION, self.config))
def __str__(self):
return '<Package %s %s %s>' % (self.NAME, self.VERSION, self.config)
def info_string(self):
return "'%s' [%s]" % ((util.colorize(self.NAME, 'yellow'),
util.colorize(self.config, 'blue')))
def log_status(self, message, suffix=''):
util.log_heading(message, " " + self.info_string())
def check_deps(self, valid_packages):
for package in self.DEPENDS:
if package not in valid_packages:
util.log('%s: Invalid dependency: %s' % (self.info, package))
return False
for package in self.CONFLICTS:
if package not in valid_packages:
util.log('%s: Invalid conflict: %s' % (self.info, package))
return False
return True
def is_any_version_installed(self):
return util.is_installed(self.NAME, self.config)
def get_install_stamp(self):
"""Returns the name of install stamp for this package."""
return util.get_install_stamp(self.NAME, self.config)
def get_list_file(self):
"""Returns the name of the installed file list for this package."""
return util.get_list_file(self.NAME, self.config)