* fix: require build dependencies in Builder

* make ignore-dependency work with Build commands
* fix: all Build subcommands must derive from Build
* new option: ignore-action-errors, try it, you will love it!
* fix: proper error handling in actionsapi (see #460)
* rename: PisiBuild -> Builder
* cosmetic changes: 
  - eliminate unnecessary use of punctuation
  - when we have colors, do not print Error:,  Warning: prefixes
* fix some typos
This commit is contained in:
Eray Özkural
2005-10-12 10:19:11 +00:00
parent 1a6915dbe9
commit 2e9cad42c8
13 changed files with 104 additions and 77 deletions
+8
View File
@@ -20,3 +20,11 @@ class Error(pisi.Error):
class Exception(pisi.Exception):
pass
import pisi.context as ctx
def error(msg):
if ctx.config.get_option('ignore_action_errors'):
ctx.ui.error(msg)
else:
raise Error(msg)
+5 -5
View File
@@ -64,20 +64,20 @@ def configure(parameters = ''):
%s' % (get.kdeDIR(), get.HOST(), get.qtDIR(), get.qtLIBDIR(), parameters)
if system(args):
raise ConfigureError(_('!!! Configure failed...\n'))
raise ConfigureError(_('Configure failed.'))
else:
raise ConfigureError(_('!!! No configure script found...\n'))
raise ConfigureError(_('No configure script found.'))
def make(parameters = ''):
'''make source with given parameters = "all" || "doc" etc.'''
if system('make %s' % parameters):
raise MakeError(_('!!! Make failed...\n'))
raise MakeError(_('Make failed.'))
def install(parameters = 'install'):
if can_access_file('Makefile'):
args = 'make DESTDIR=%s destdir=%s %s' % (get.installDIR(), get.installDIR(), parameters)
if system(args):
raise InstallError(_('!!! Install failed...\n'))
raise InstallError(_('Install failed.'))
else:
raise InstallError(_('!!! No Makefile found...\n'))
raise InstallError(_('No Makefile found.'))
+2 -2
View File
@@ -35,7 +35,7 @@ def preplib(sourceDirectory = '/usr/lib'):
sourceDirectory = get.installDIR() + sourceDirectory
if can_access_directory(sourceDirectory):
if system('/sbin/ldconfig -n -N %s' % sourceDirectory):
raise RunTimeError(_('!!! Running ldconfig failed...'))
raise RunTimeError(_('Running ldconfig failed.'))
def gnuconfig_update():
''' copy newest config.* onto source\'s '''
@@ -47,7 +47,7 @@ def gnuconfig_update():
def libtoolize(parameters = ''):
if system('/usr/bin/libtoolize %s' % parameters):
raise RunTimeError(_('Running libtoolize failed...'))
raise RunTimeError(_('Running libtoolize failed.'))
def gen_usr_ldscript(dynamicLib):
+6 -6
View File
@@ -50,27 +50,27 @@ def configure(parameters = ''):
export('PERL_MM_USE_DEFAULT', '1')
if can_access_file('Build.PL'):
if system('perl Build.PL installdirs=vendor destdir=%s' % get.installDIR()):
raise CompileError, _('!!! Configure failed...\n')
raise CompileError, _('Configure failed.')
else:
if system('perl Makefile.PL %s PREFIX=/usr INSTALLDIRS=vendor DESTDIR=%s' % (parameters, get.installDIR())):
raise CompileError, _('!!! Configure failed...\n')
raise CompileError, _('Configure failed.')
def make(parameters = ''):
'''make source with given parameters.'''
if can_access_file('Makefile'):
if system('make %s' % parameters):
raise MakeError, _('!!! Make failed...\n')
raise MakeError, _('Make failed.')
else:
if system('perl Build build'):
raise MakeError, _('!!! Make failed...\n')
raise MakeError, _('perl build failed.')
def install(parameters = 'install'):
'''install source with given parameters.'''
if can_access_file('Makefile'):
if system('make %s' % parameters):
raise InstallError, _('!!! Install failed...\n')
raise InstallError, _('Make failed.')
else:
if system('perl Build install'):
raise MakeError, _('!!! Install failed...\n')
raise MakeError, _('perl install failed.')
# FIXME: fix_local_pod % update_pod
+9 -9
View File
@@ -30,6 +30,8 @@ import pisi.actionsapi.get as get
from pisi.actionsapi.pisitoolsfunctions import *
from pisi.actionsapi.shelltools import *
from pisi.actionsapi import error
def dobin(sourceFile, destinationDirectory = '/usr/bin'):
'''insert a executable file into /bin or /usr/bin'''
@@ -124,7 +126,7 @@ def doman(*sourceFiles):
pageName, pageDirectory = source[:source.rindex('.')], \
source[source.rindex('.')+1:]
except ValueError:
ctx.ui.warning(_('ActionsAPI [doman]: Wrong man page file: %s') % (source))
error(_('ActionsAPI [doman]: Wrong man page file: %s') % (source))
makedirs(manDIR + '/man%s' % pageDirectory)
system('install -m0644 %s %s' % (source, manDIR + '/man%s' % pageDirectory))
@@ -162,7 +164,7 @@ def rename(sourceFile, destinationFile):
try:
os.rename(get.installDIR() + sourceFile, get.installDIR() + baseDir + "/" + destinationFile)
except OSError:
ctx.ui.warning(_('ActionsAPI [rename]: No such file or directory: %s') % (sourceFile))
error(_('ActionsAPI [rename]: No such file or directory: %s') % (sourceFile))
def dosed(sourceFiles, findPattern, replacePattern = ''):
'''replaces patterns in sourceFiles'''
@@ -179,7 +181,7 @@ def dosed(sourceFiles, findPattern, replacePattern = ''):
line = re.sub(findPattern, replacePattern, line)
sys.stdout.write(line)
else:
raise FileError(_('File doesn\'t exists or permission denied: %s') % sourceFile)
raise FileError(_('File does not exist or permission denied: %s') % sourceFile)
def dosbin(sourceFile, destinationDirectory = '/usr/sbin'):
'''insert a executable file into /sbin or /usr/sbin'''
@@ -196,7 +198,7 @@ def dosym(sourceFile, destinationFile):
try:
os.symlink(sourceFile, get.installDIR() + destinationFile)
except OSError:
ctx.ui.warning(_('ActionsAPI [dosym]: File exists: %s') % (sourceFile))
error(_('ActionsAPI [dosym]: File exists: %s') % (sourceFile))
def insinto(destinationDirectory, sourceFile, destinationFile = ''):
'''insert a sourceFile into destinationDirectory as a destinationFile with same uid/guid/permissions'''
@@ -212,11 +214,9 @@ def insinto(destinationDirectory, sourceFile, destinationFile = ''):
def newdoc(sourceFile, destinationFile):
'''inserts a sourceFile into /usr/share/doc/PACKAGE/ directory as a destinationFile'''
destinationDirectory = '' #490
try:
destinationDirectory = destinationFile[:destinationFile.rindex('/')]
destinationFile = destinationFile[destinationFile.rindex('/') + 1:]
except:
pass
import os.path
destinationDirectory = os.path.dirname(destinationFile)
destinationFile = os.path.basename(destinationFile)
move(sourceFile, destinationFile)
readable_insinto(os.path.join(get.installDIR(), 'usr/share/doc', get.srcTAG(), destinationDirectory), destinationFile)
+3 -3
View File
@@ -43,7 +43,7 @@ def executable_insinto(destinationDirectory, *sourceFiles):
'''insert a executable file into destinationDirectory'''
if not sourceFiles or not destinationDirectory:
raise ArgumentError(_('Insufficient arguments...'))
raise ArgumentError(_('Insufficient arguments.'))
if not can_access_directory(destinationDirectory):
makedirs(destinationDirectory)
@@ -56,7 +56,7 @@ def readable_insinto(destinationDirectory, *sourceFiles):
'''inserts file list into destinationDirectory'''
if not sourceFiles or not destinationDirectory:
raise ArgumentError(_('Insufficient arguments...'))
raise ArgumentError(_('Insufficient arguments.'))
if not can_access_directory(destinationDirectory):
makedirs(destinationDirectory)
@@ -69,7 +69,7 @@ def lib_insinto(sourceFile, destinationDirectory, permission = 0644):
'''inserts a library fileinto destinationDirectory with given permission'''
if not sourceFile or not destinationDirectory:
raise ArgumentError(_(' Insufficient arguments...'))
raise ArgumentError(_(' Insufficient arguments.'))
if not can_access_directory(destinationDirectory):
makedirs(destinationDirectory)
+3 -3
View File
@@ -47,12 +47,12 @@ class RunTimeError(pisi.actionsapi.Error):
def compile(parameters = ''):
'''compile source with given parameters.'''
if system('python setup.py build %s' % (get.installDIR(), parameters)):
raise CompileError, _('!!! Make failed...\n')
raise CompileError, _('Make failed.')
def install(parameters = ''):
'''does python setup.py install'''
if system('python setup.py install --root=%s --no-compile %s' % (get.installDIR(), parameters)):
raise InstallError, _('!!! Install failed...\n')
raise InstallError, _('Install failed.')
DDOCS = 'CHANGELOG COPYRIGHT KNOWN_BUGS MAINTAINERS PKG-INFO \
CONTRIBUTORS LICENSE COPYING* Change* MANIFEST* README*'
@@ -64,4 +64,4 @@ def install(parameters = ''):
def run(parameters = ''):
'''executes parameters with python'''
if system('python %s' % (parameters)):
raise RunTimeError, _('!!! Running %s failed...\n') % parameters
raise RunTimeError, _('Running %s failed.') % parameters
+2 -2
View File
@@ -37,8 +37,8 @@ class InstallError(pisi.actionsapi.Error):
def make(parameters = ''):
if system("scons %s" % parameters):
raise MakeError(_('!!! Make failed...\n'))
raise MakeError(_('Make failed.'))
def install(parameters = 'install'):
if system("scons prefix=%s %s" % (get.installDIR(), parameters)):
raise InstallError(_('!!! Install failed...\n'))
raise InstallError(_('Install failed.'))
+13 -11
View File
@@ -27,6 +27,8 @@ import pisi.context as ctx
import pisi.actionsapi
import pisi.actionsapi.get
from pisi.actionsapi import error
def can_access_file(sourceFile):
'''test the existence of file'''
return os.access(sourceFile, os.F_OK)
@@ -40,7 +42,7 @@ def makedirs(destinationDirectory):
try:
os.makedirs(destinationDirectory)
except OSError:
pass
error(_('Cannot create directory %s' % destinationDirectory))
def echo(destionationFile, content):
try:
@@ -48,7 +50,7 @@ def echo(destionationFile, content):
f.write("%s\n" % content)
f.close()
except IOError:
ctx.ui.error(_(' ActionsAPI [echo]: Can\'t append to file %s...') % (destionationFile))
error(_('ActionsAPI [echo]: Can\'t append to file %s.') % (destionationFile))
def chmod(sourceFile, mode = 0755):
'''change the mode of sourceFile to the mode'''
@@ -98,11 +100,11 @@ def unlinkDir(sourceDirectory):
try:
shutil.rmtree(sourceDirectory)
except OSError:
ctx.ui.error(_(' ActionsAPI [unlinkDir]: Operation not permitted: %s') % (sourceDirectory))
error(_(' ActionsAPI [unlinkDir]: Operation not permitted: %s') % (sourceDirectory))
elif isFile(sourceDirectory):
pass
else:
ctx.ui.error(_(' ActionsAPI [unlinkDir]: Directory %s doesn\'t exists.') % (sourceDirectory))
error(_(' ActionsAPI [unlinkDir]: Directory %s doesn\'t exists.') % (sourceDirectory))
def move(sourceFile, destinationFile):
'''recursively move a sourceFile or directory to destinationFile'''
@@ -111,9 +113,9 @@ def move(sourceFile, destinationFile):
try:
shutil.move(file, destinationFile)
except OSError:
ctx.ui.error(_(' ActionsAPI [move]: Permission denied: %s to %s') % (file, destinationFile))
error(_(' ActionsAPI [move]: Permission denied: %s to %s') % (file, destinationFile))
else:
ctx.ui.error(_(' ActionsAPI [move]: File %s doesn\'t exists.') % (file))
error(_(' ActionsAPI [move]: File %s doesn\'t exists.') % (file))
def copy(sourceFile, destinationFile):
'''recursively copy a sourceFile or directory to destinationFile'''
@@ -122,11 +124,11 @@ def copy(sourceFile, destinationFile):
try:
shutil.copy(file, destinationFile)
except IOError:
ctx.ui.error(_('ActionsAPI [copy]: Permission denied: %s to %s') % (file, destinationFile))
error(_('ActionsAPI [copy]: Permission denied: %s to %s') % (file, destinationFile))
elif isDirectory(file):
copytree(file, destinationFile)
else:
ctx.ui.error(_('ActionsAPI [copy]: File %s does not exist.') % file)
error(_('ActionsAPI [copy]: File %s does not exist.') % file)
def copytree(source, destination, sym = False):
'''recursively copy an entire directory tree rooted at source'''
@@ -134,9 +136,9 @@ def copytree(source, destination, sym = False):
try:
shutil.copytree(source, destination, sym)
except OSError:
ctx.ui.error(_(' ActionsAPI [copytree]: Permission denied: %s to %s') % (source, destination))
error(_(' ActionsAPI [copytree]: Permission denied: %s to %s') % (source, destination))
else:
ctx.ui.error(_(' ActionsAPI [copytree]: Directory %s doesn\'t exists.') % (source))
error(_(' ActionsAPI [copytree]: Directory %s doesn\'t exists.') % (source))
def touch(sourceFile):
'''changes the access time of the 'sourceFile', or creates it if it is not exist'''
@@ -148,7 +150,7 @@ def touch(sourceFile):
f = open(sourceFile, 'w')
f.close()
except IOError:
ctx.ui.error(_(' ActionsAPI [touch]: Permission denied: %s') % (sourceFile))
error(_(' ActionsAPI [touch]: Permission denied: %s') % (sourceFile))
def cd(directoryName = ''):
'''change directory'''
+2 -20
View File
@@ -550,31 +550,14 @@ def update_repo(repo):
# build functions...
def prepare_for_build(pspecfile, authInfo=None):
# FIXME: there is a function named "build" in this module which
# makes it impossible to use build module directly.
from build import PisiBuild
url = URI(pspecfile)
if url.is_remote_file():
from sourcefetcher import SourceFetcher
fs = SourceFetcher(url, authInfo)
url.uri = fs.fetch_all()
pb = PisiBuild(url.uri)
# find out the build dependencies that are not satisfied...
dep_unsatis = []
for dep in pb.spec.source.buildDeps:
if not dependency.installed_satisfies_dep(dep):
dep_unsatis.append(dep)
# FIXME: take care of the required buildDeps...
# For now just report an error!
if dep_unsatis:
ctx.ui.error(_("Unsatisfied Build Dependencies:"))
for dep in dep_unsatis:
ctx.ui.warning(dep.package)
# FIXME: raise an exception if ignore-depends not given
import pisi.build
pb = pisi.build.Builder(url.uri)
return pb
@@ -582,7 +565,6 @@ def build(pspecfile, authInfo=None):
pb = prepare_for_build(pspecfile, authInfo)
pb.build()
order = {"none": 0,
"unpack": 1,
"setupaction": 2,
+22 -8
View File
@@ -24,6 +24,7 @@ _ = __trans.ugettext
import pisi
import pisi.util as util
import pisi.context as ctx
import pisi.dependency as dependency
from pisi.sourcearchive import SourceArchive
from pisi.files import Files, FileInfo
from pisi.metadata import MetaData
@@ -114,8 +115,8 @@ class BuildContext(object):
return self.pkg_dir() + ctx.const.install_dir_suffix
class PisiBuild:
"""PisiBuild class, provides the package build and creation routines"""
class Builder:
"""Provides the package build and creation routines"""
def __init__(self, pspec):
self.bctx = BuildContext(pspec)
self.pspecDir = os.path.dirname(os.path.realpath(self.bctx.pspecfile))
@@ -148,13 +149,12 @@ class PisiBuild:
# check if all patch files exists, if there are missing no need to unpack!
self.patch_exists()
self.check_build_dependencies()
self.fetch_source_archive()
self.unpack_source_archive()
self.solve_build_dependencies()
# apply the patches and prepare a source directory for build.
self.apply_patches()
@@ -256,10 +256,24 @@ class PisiBuild:
os.chdir(curDir)
def solve_build_dependencies(self):
def check_build_dependencies(self):
"""fail if dependencies not satisfied"""
#TODO: we'll have to do better than plugging a fxn here
pass
# find out the build dependencies that are not satisfied...
dep_unsatis = []
for dep in self.spec.source.buildDeps:
if not dependency.installed_satisfies_dep(dep):
dep_unsatis.append(dep)
# FIXME: take care of the required buildDeps...
# For now just report an error!
if dep_unsatis:
ctx.ui.error(_("Unsatisfied Build Dependencies:"))
for dep in dep_unsatis:
ctx.ui.warning(dep.package)
# FIXME: raise an exception if ignore-depends not given
if not ctx.config.get_option('ignore_dependency'):
raise Error(_('Cannot build package due to unsatisfied build dependencies'))
def patch_exists(self):
"""check existence of patch files declared in PSPEC"""
+8 -2
View File
@@ -72,10 +72,16 @@ class CLI(UI):
self.output(msg + msgend)
def warning(self,msg):
self.output(colorize(_('Warning: ') + msg + '\n', 'purple'), err=True)
if ctx.config.get_option('no_color'):
self.output(_('Warning: ') + msg + '\n', err=True)
else:
self.output(colorize(msg + '\n', 'purple'), err=True)
def error(self,msg):
self.output(colorize(_('Error: ') + msg + '\n', 'red'), err=True)
if ctx.config.get_option('no_color'):
self.output(_('Error: ') + msg + '\n', err=True)
else:
self.output(colorize(msg + '\n', 'red'), err=True)
def action(self,msg):
#TODO: this seems quite redundant?
+21 -6
View File
@@ -219,6 +219,7 @@ If run without parameters, it prints the general help."""
self.finalize()
class Clean(Command):
"""Clean stale locks."""
@@ -233,7 +234,8 @@ class Clean(Command):
self.init()
pisi.util.clean_locks()
self.finalize()
class DeleteCache(Command):
"""Delete cache files"""
@@ -248,6 +250,7 @@ class DeleteCache(Command):
self.init(database=False)
pisi.api.delete_cache()
class Graph(Command):
"""Graph package relations.
Usage: graph <package1> <package2> ...
@@ -270,12 +273,19 @@ conflicts relations starting from given packages.
g.write_graphviz(file('pgraph.dot', 'w'))
self.finalize()
# option mixins
def buildno_opts(self):
self.parser.add_option("", "--ignore-build-no", action="store_true",
default=False,
help=_("do not take build no into account."))
def ignoredep_opt(self):
p = self.parser
p.add_option("-E", "--ignore-dependency", action="store_true",
default=False,
help=_("do not take dependency information into account"))
class Build(Command):
"""Build a PISI package using a pspec.xml file
@@ -294,8 +304,13 @@ fetch all necessary files and build the package for you.
def options(self):
buildno_opts(self)
ignoredep_opt(self)
self.parser.add_option("-O", "--output-dir", action="store", default=".",
help=_("output directory for produced packages"))
self.parser.add_option("-A", "--ignore-action-errors",
action="store_true", default=False,
help=_("bypass errors from ActionsAPI"))
def run(self):
if not self.args:
@@ -320,9 +335,7 @@ class PackageOp(Command):
p = self.parser
p.add_option("-B", "--ignore-comar", action="store_true",
default=False, help=_("bypass comar configuration agent"))
p.add_option("", "--ignore-dependency", action="store_true",
default=False,
help=_("do not take dependency information into account"))
ignoredep_opt(self)
def init(self):
super(PackageOp, self).init(True)
@@ -331,6 +344,7 @@ class PackageOp(Command):
#self.finalize_db()
pass
class Install(PackageOp):
"""Install PISI packages
@@ -359,6 +373,7 @@ specified a package name, it should exist in a specified repository.
pisi.api.install(self.args)
self.finalize()
class Upgrade(PackageOp):
"""Upgrade PISI packages
@@ -864,9 +879,9 @@ Finds the installed package which contains the specified file.
self.finalize()
# Partial build commands
class BuildUntil(Build):
"""Run the build process partially
@@ -955,7 +970,7 @@ TODO: desc.
self.finalize()
class BuildBuild(Command):
class BuildBuild(Build):
"""Setup the source
Usage: build-build <pspec file>