From 4af3706de3421097742e7e61ee8c47a06cd3f4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eray=20=C3=96zkural?= Date: Sat, 19 Nov 2005 19:41:49 +0000 Subject: [PATCH] * xmlfilecdom: typo * improve build code path: - move more build stuff into build.py, especially SourceFetcher class which has too much affinity with Builder class to keep it in a separate, also move low-level build iface build and build_until into build and import from pisi.api - eliminate much redundancy - by these improvements bug 838 has been isolated, don't use svn I'm going to fix this bug * files.File -> files.FileInfo avoid potential name clash --- pisi/api.py | 84 +------------- pisi/build.py | 244 ++++++++++++++++++++++++++++++--------- pisi/file.py | 4 +- pisi/files.py | 4 +- pisi/pxml/xmlfilecdom.py | 2 +- pisi/sourcearchive.py | 12 +- pisi/sourcefetcher.py | 67 ----------- 7 files changed, 204 insertions(+), 213 deletions(-) diff --git a/pisi/api.py b/pisi/api.py index acc5da7a..dfe71f9e 100644 --- a/pisi/api.py +++ b/pisi/api.py @@ -42,6 +42,7 @@ import pisi.component as component from pisi.index import Index import pisi.cli from pisi.operations import install, remove, upgrade +from pisi.build import build, build_until from pisi.atomicoperations import resurrect_package from pisi.metadata import MetaData from pisi.files import Files @@ -258,89 +259,6 @@ def update_repo(repo): index.update_db(repo) ctx.ui.info(_('\n* Package database updated.')) - -# build functions... -def prepare_for_build(pspecfile, authInfo=None): - - url = URI(pspecfile) - if url.is_remote_file(): - from sourcefetcher import SourceFetcher - fs = SourceFetcher(url, authInfo) - url.uri = fs.fetch_all() - - import pisi.build - pb = pisi.build.Builder(url.uri) - - return pb - -def build(pspecfile, authInfo=None): - pb = prepare_for_build(pspecfile, authInfo) - pb.build() - -order = {"none": 0, - "unpack": 1, - "setupaction": 2, - "buildaction": 3, - "installaction": 4, - "buildpackages": 5} - -def __buildState_unpack(pb): - # unpack is the first state to run. - pb.fetch_source_archive() - pb.unpack_source_archive() - pb.apply_patches() - -def __buildState_setupaction(pb, last): - - if order[last] < order["unpack"]: - __buildState_unpack(pb) - pb.run_setup_action() - -def __buildState_buildaction(pb, last): - - if order[last] < order["setupaction"]: - __buildState_setupaction(pb, last) - pb.run_build_action() - -def __buildState_installaction(pb, last): - - if order[last] < order["buildaction"]: - __buildState_buildaction(pb, last) - pb.run_install_action() - -def __buildState_buildpackages(pb, last): - - if order[last] < order["installaction"]: - __buildState_installaction(pb, last) - pb.build_packages() - -def build_until(pspecfile, state, authInfo=None): - pb = prepare_for_build(pspecfile, authInfo) - pb.compile_action_script() - - last = pb.get_state() - ctx.ui.info("Last state was %s"%last) - - if not last: last = "none" - - if state == "unpack": - __buildState_unpack(pb) - return - - if state == "setupaction": - __buildState_setupaction(pb, last) - return - - if state == "buildaction": - __buildState_buildaction(pb, last) - return - - if state == "installaction": - __buildState_installaction(pb, last) - return - - __buildState_buildpackages(pb, last) - def delete_cache(): util.clean_dir(ctx.config.packages_dir()) util.clean_dir(ctx.config.archives_dir()) diff --git a/pisi/build.py b/pisi/build.py index 3c1a4c10..dfe4d0c0 100644 --- a/pisi/build.py +++ b/pisi/build.py @@ -17,18 +17,21 @@ import os import sys import glob +from os.path import basename, dirname import gettext __trans = gettext.translation('pisi', fallback=True) _ = __trans.ugettext import pisi +from pisi.specfile import SpecFile import pisi.util as util +from pisi.util import join_path as join import pisi.context as ctx import pisi.dependency as dependency import pisi.operations as operations from pisi.sourcearchive import SourceArchive -from pisi.files import Files, File as FileInfo +from pisi.files import Files, FileInfo from pisi.fetcher import fetch_url from pisi.uri import URI from pisi.metadata import MetaData @@ -39,6 +42,74 @@ import pisi.component as component class Error(pisi.Error): pass +class SourceFetcher(object): + def __init__(self, url, authInfo=None): + self.url = url + if authInfo: + self.url.set_auth_info(authInfo) + self.location = dirname(self.url.uri) + + pkgname = basename(dirname(self.url.path())) + self.dest = join(ctx.config.tmp_dir(), pkgname) + + def fetch_all(self): + # fetch pspec file + self.fetch() + pspec = join(self.dest, self.url.filename()) + self.spec = SpecFile() + self.spec.read(pspec) + + self.fetch_actionsfile() + self.fetch_patches() + self.fetch_comarfiles() + self.fetch_additionalFiles() + + return URI(pspec) + + def fetch_actionsfile(self): + actionsuri = join(self.location, ctx.const.actions_file) + self.url.uri = actionsuri + self.fetch() + + def fetch_patches(self): + spec = self.spec + for patch in spec.source.patches: + file_name = basename(patch.filename) + dir_name = dirname(patch.filename) + patchuri = join(self.location, + ctx.const.files_dir, dir_name, file_name) + self.url.uri = patchuri + target_dir = join(ctx.const.files_dir, dir_name) + self.fetch(target_dir) + + def fetch_comarfiles(self): + spec = self.spec + for package in spec.packages: + for pcomar in package.providesComar: + comaruri = join(self.location, + ctx.const.comar_dir, pcomar.script) + self.url.uri = comaruri + self.fetch(ctx.const.comar_dir) + + def fetch_additionalFiles(self): + spec = self.spec + for pkg in spec.packages: + for afile in pkg.additionalFiles: + file_name = basename(afile.filename) + dir_name = dirname(afile.filename) + afileuri = join(self.location, + ctx.const.files_dir, dir_name, file_name) + self.url.uri = afileuri + target_dir = join(ctx.const.files_dir, dir_name) + self.fetch(target_dir) + + def fetch(self, appendDest=""): + from fetcher import fetch_url + + ctx.ui.info(_("Fetching %s") % self.url.uri) + dest = join(self.dest, appendDest) + fetch_url(self.url, dest) + # Helper Functions def get_file_type(path, pinfoList): @@ -81,21 +152,34 @@ def check_path_collision(package, pkgList): path.path) return collisions -# a dynamic build context -from pisi.specfile import SpecFile +class Builder: + """Provides the package build and creation routines""" + #FIXME: this class and every other class must use URLs as paths! -class BuildContext(object): - """Build Context""" + def __init__(self, pspecuri, authinfo = None): - def __init__(self, pspecfile): - super(BuildContext, self).__init__() - self.set_spec_file(pspecfile) + if not isinstance(pspecuri, URI): + pspecuri = URI(pspecuri) - def set_spec_file(self, pspecfile): - self.pspecfile = pspecfile + if pspecuri.is_remote_file(): + fs = SourceFetcher(pspecuri, authinfo) + #make local here and fuck up + pspecuri = fs.fetch_all() + + self.set_spec_file(pspecuri) + self.specdir = os.path.dirname(os.path.realpath(pspecuri.get_uri())) + self.sourceArchive = SourceArchive(self.spec, self.pkg_work_dir()) + + self.set_environment_vars() + + self.actionLocals = None + self.actionGlobals = None + self.srcDir = None + + def set_spec_file(self, pspecuri): spec = SpecFile() - spec.read(pspecfile) + spec.read(pspecuri, ctx.config.tmp_dir()) self.spec = spec # directory accessor functions @@ -115,28 +199,12 @@ class BuildContext(object): def pkg_install_dir(self): return self.pkg_dir() + ctx.const.install_dir_suffix - -class Builder: - """Provides the package build and creation routines""" - #FIXME: this class and every other class must use URLs as paths! - def __init__(self, pspec): - self.bctx = BuildContext(pspec) - self.pspecdir = os.path.dirname(os.path.realpath(self.bctx.pspecfile)) - self.spec = self.bctx.spec - self.sourceArchive = SourceArchive(self.bctx) - - self.set_environment_vars() - - self.actionLocals = None - self.actionGlobals = None - self.srcDir = None - def set_state(self, state): - stateFile = util.join_path(self.bctx.pkg_work_dir(), "pisiBuildState") + stateFile = util.join_path(self.pkg_work_dir(), "pisiBuildState") open(stateFile, "w").write(state) def get_state(self): - stateFile = util.join_path(self.bctx.pkg_work_dir(), "pisiBuildState") + stateFile = util.join_path(self.pkg_work_dir(), "pisiBuildState") if not os.path.exists(stateFile): # no state return None return open(stateFile, "r").read() @@ -172,9 +240,9 @@ class Builder: def set_environment_vars(self): """Sets the environment variables for actions API to use""" evn = { - "PKG_DIR": self.bctx.pkg_dir(), - "WORK_DIR": self.bctx.pkg_work_dir(), - "INSTALL_DIR": self.bctx.pkg_install_dir(), + "PKG_DIR": self.pkg_dir(), + "WORK_DIR": self.pkg_work_dir(), + "INSTALL_DIR": self.pkg_install_dir(), "SRC_NAME": self.spec.source.name, "SRC_VERSION": self.spec.source.version, "SRC_RELEASE": self.spec.source.release @@ -195,12 +263,12 @@ class Builder: def get_component(self): if not self.spec.source.partOf: ctx.ui.warning(_('PartOf tag not defined, looking for component')) - parentdir = os.path.realpath(self.pspecdir + '/../') + parentdir = os.path.realpath(self.specdir + '/../') url = util.join_path(parentdir, 'component.xml') progress = ctx.ui.Progress if URI(url).is_remote_file(): - fetch_url(url, self.bctx.pkg_work_dir(), progress) - path = util.join_path(self.bctx.pkg_work_dir(), 'component.xml') + fetch_url(url, self.pkg_work_dir(), progress) + path = util.join_path(self.pkg_work_dir(), 'component.xml') else: if not os.path.exists(url): raise Exception(_('Cannot find component.xml in upper directory')) @@ -220,7 +288,7 @@ class Builder: def unpack_source_archive(self): ctx.ui.info(_("Unpacking archive...")) self.sourceArchive.unpack() - ctx.ui.info(_(" unpacked (%s)") % self.bctx.pkg_work_dir()) + ctx.ui.info(_(" unpacked (%s)") % self.pkg_work_dir()) self.set_state("unpack") def run_setup_action(self): @@ -238,8 +306,8 @@ class Builder: ctx.ui.action(_("Installing...")) # Before install make sure install_dir is clean - if os.path.exists(self.bctx.pkg_install_dir()): - util.clean_dir(self.bctx.pkg_install_dir()) + if os.path.exists(self.pkg_install_dir()): + util.clean_dir(self.pkg_install_dir()) # install function is mandatory! self.run_action_function(ctx.const.install_func, True) @@ -247,8 +315,7 @@ class Builder: def compile_action_script(self): """Compiles actions.py and sets the actionLocals and actionGlobals""" - specdir = os.path.dirname(self.bctx.pspecfile) - scriptfile = util.join_path(specdir, ctx.const.actions_file) + scriptfile = util.join_path(self.specdir, ctx.const.actions_file) try: localSymbols = globalSymbols = {} buf = open(scriptfile).read() @@ -269,7 +336,7 @@ class Builder: except KeyError: workdir = self.spec.source.name + "-" + self.spec.source.version - return util.join_path(self.bctx.pkg_work_dir(), workdir) + return util.join_path(self.pkg_work_dir(), workdir) def run_action_function(self, func, mandatory=False): """Calls the corresponding function in actions.py. @@ -330,7 +397,7 @@ class Builder: def patch_exists(self): """check existence of patch files declared in PSPEC""" - files_dir = os.path.abspath(util.join_path(self.pspecdir, + files_dir = os.path.abspath(util.join_path(self.specdir, ctx.const.files_dir)) for patch in self.spec.source.patches: patchFile = util.join_path(files_dir, patch.filename) @@ -338,7 +405,7 @@ class Builder: raise Error(_("Patch file is missing: %s\n") % patch.filename) def apply_patches(self): - files_dir = os.path.abspath(util.join_path(self.pspecdir, + files_dir = os.path.abspath(util.join_path(self.specdir, ctx.const.files_dir)) for patch in self.spec.source.patches: @@ -354,7 +421,7 @@ class Builder: def strip_install_dir(self): """strip install directory""" ctx.ui.action(_("Stripping files..")) - install_dir = self.bctx.pkg_install_dir() + install_dir = self.pkg_install_dir() try: nostrip = self.actionGlobals['NoStrip'] util.strip_directory(install_dir, nostrip) @@ -373,7 +440,7 @@ class Builder: metadata.package.distributionRelease = ctx.config.values.general.distribution_release metadata.package.architecture = "Any" - size, d = 0, self.bctx.pkg_install_dir() + size, d = 0, self.pkg_install_dir() for path in package.files: size += util.dir_size(util.join_path(d, path.path)) @@ -387,7 +454,7 @@ class Builder: else: metadata.package.build = self.calc_build_no(metadata.package.name) - metadata_xml_path = util.join_path(self.bctx.pkg_dir(), ctx.const.metadata_xml) + metadata_xml_path = util.join_path(self.pkg_dir(), ctx.const.metadata_xml) metadata.write(metadata_xml_path) self.metadata = metadata @@ -395,7 +462,7 @@ class Builder: """Generates files.xml using the path definitions in specfile and the files produced by the build system.""" files = Files() - install_dir = self.bctx.pkg_install_dir() + install_dir = self.pkg_install_dir() # FIXME: We need to expand globs before trying to calculate hashes # Not on the fly like now. @@ -427,7 +494,7 @@ class Builder: for (p, fileinfo) in d.iteritems(): files.append(fileinfo) - files_xml_path = util.join_path(self.bctx.pkg_dir(), ctx.const.files_xml) + files_xml_path = util.join_path(self.pkg_dir(), ctx.const.files_xml) files.write(files_xml_path) self.files = files @@ -521,8 +588,8 @@ class Builder: for package in self.spec.packages: # store additional files c = os.getcwd() - os.chdir(self.pspecdir) - install_dir = self.bctx.pkg_dir() + ctx.const.install_dir_suffix + os.chdir(self.specdir) + install_dir = self.pkg_dir() + ctx.const.install_dir_suffix tmp_aF = [] for afile in package.additionalFiles: destdir = util.join_path(install_dir, os.path.dirname(afile.target)) @@ -561,14 +628,14 @@ class Builder: package_names.append(name) # add comar files to package - os.chdir(self.pspecdir) + os.chdir(self.specdir) for pcomar in package.providesComar: fname = util.join_path(ctx.const.comar_dir, pcomar.script) pkg.add_to_package(fname) # add xmls and files - os.chdir(self.bctx.pkg_dir()) + os.chdir(self.pkg_dir()) pkg.add_to_package(ctx.const.metadata_xml) pkg.add_to_package(ctx.const.files_xml) @@ -588,8 +655,79 @@ class Builder: if ctx.config.values.general.autoclean is True: ctx.ui.info(_("Cleaning Build Directory...")) - util.clean_dir(self.bctx.pkg_dir()) + util.clean_dir(self.pkg_dir()) else: ctx.ui.info(_("Keeping Build Directory")) return package_names + + +# build functions... + +def build(pspecfile, authinfo=None): + pb = pisi.build.Builder(pspecfile, authinfo) + pb.build() + +order = {"none": 0, + "unpack": 1, + "setupaction": 2, + "buildaction": 3, + "installaction": 4, + "buildpackages": 5} + +def __buildState_unpack(pb): + # unpack is the first state to run. + pb.fetch_source_archive() + pb.unpack_source_archive() + pb.apply_patches() + +def __buildState_setupaction(pb, last): + + if order[last] < order["unpack"]: + __buildState_unpack(pb) + pb.run_setup_action() + +def __buildState_buildaction(pb, last): + + if order[last] < order["setupaction"]: + __buildState_setupaction(pb, last) + pb.run_build_action() + +def __buildState_installaction(pb, last): + + if order[last] < order["buildaction"]: + __buildState_buildaction(pb, last) + pb.run_install_action() + +def __buildState_buildpackages(pb, last): + + if order[last] < order["installaction"]: + __buildState_installaction(pb, last) + pb.build_packages() + +def build_until(pspecfile, state, authInfo=None): + pb = pisi.build.Builder(pspecfile, authinfo) + pb.compile_action_script() + + last = pb.get_state() + ctx.ui.info("Last state was %s"%last) + + if not last: last = "none" + + if state == "unpack": + __buildState_unpack(pb) + return + + if state == "setupaction": + __buildState_setupaction(pb, last) + return + + if state == "buildaction": + __buildState_buildaction(pb, last) + return + + if state == "installaction": + __buildState_installaction(pb, last) + return + + __buildState_buildpackages(pb, last) diff --git a/pisi/file.py b/pisi/file.py index 6445ff72..eb621e2a 100644 --- a/pisi/file.py +++ b/pisi/file.py @@ -47,13 +47,15 @@ class File: return uri @staticmethod - def download(self, uri, transfer_dir = "/tmp"): + def download(uri, transfer_dir = "/tmp"): + assert type(uri == URI) if uri.is_remote_file(): ctx.ui.info(_("Fetching %s") % uri.get_uri()) localfile = join(transfer_dir, uri.filename()) fetch_url(uri, transfer_dir) # FIXME: localfile would look better for fetch iface? else: localfile = uri.get_uri() #TODO: use a special function here? + return localfile def __init__(self, uri, mode, transfer_dir = "/tmp"): "it is pointless to open a file without a URI and a mode" diff --git a/pisi/files.py b/pisi/files.py index d4cc3104..f186c734 100644 --- a/pisi/files.py +++ b/pisi/files.py @@ -19,7 +19,7 @@ import pisi.pxml.autoxml as autoxml from pisi.util import Checks import pisi.lockeddbshelve as shelve -class File: +class FileInfo: """File holds the information for a File node/tag in files.xml""" __metaclass__ = autoxml.autoxml @@ -40,7 +40,7 @@ class Files(autoxml.XmlFile): tag = "Files" - t_List = [ [File], autoxml.optional, "File"] + t_List = [ [FileInfo], autoxml.optional, "File"] def append(self, fileinfo): self.list.append(fileinfo) diff --git a/pisi/pxml/xmlfilecdom.py b/pisi/pxml/xmlfilecdom.py index 41c28a97..464ee3d6 100644 --- a/pisi/pxml/xmlfilecdom.py +++ b/pisi/pxml/xmlfilecdom.py @@ -80,7 +80,7 @@ class XmlFile(object): raise Error(_("File '%s' not found") % path ) def writexml(self, uri, tmpDir = '/tmp'): - f = file(path, 'w') + f = file(uri, 'w') PrettyPrint(self.rootNode(), stream = f) f.close() diff --git a/pisi/sourcearchive.py b/pisi/sourcearchive.py index bf6479a9..599bfe22 100644 --- a/pisi/sourcearchive.py +++ b/pisi/sourcearchive.py @@ -35,11 +35,11 @@ class Error(pisi.Error): class SourceArchive: """source archive. this is a class responsible for fetching and unpacking a source archive""" - def __init__(self, bctx): - self.url = URI(bctx.spec.source.archive.uri) + def __init__(self, spec, pkg_work_dir): + self.url = URI(spec.source.archive.uri) + self.pkg_work_dir = pkg_work_dir self.archiveFile = join(ctx.config.archives_dir(), self.url.filename()) - self.archive = bctx.spec.source.archive - self.bctx = bctx + self.archive = spec.source.archive def fetch(self, interactive=True): if not self.is_cached(interactive): @@ -48,7 +48,7 @@ class SourceArchive: else: progress = None fetch_url(self.url, ctx.config.archives_dir(), progress) - + def is_cached(self, interactive=True): if not access(self.archiveFile, R_OK): return False @@ -68,4 +68,4 @@ class SourceArchive: raise Error, _("unpack: check_file_hash failed") archive = Archive(self.archiveFile, self.archive.type) - archive.unpack(self.bctx.pkg_work_dir(), clean_dir) + archive.unpack(self.pkg_work_dir, clean_dir) diff --git a/pisi/sourcefetcher.py b/pisi/sourcefetcher.py index e5ab333f..6bf25e03 100644 --- a/pisi/sourcefetcher.py +++ b/pisi/sourcefetcher.py @@ -20,71 +20,4 @@ import pisi.context as ctx from pisi.uri import URI from pisi.specfile import SpecFile -class SourceFetcher(object): - def __init__(self, url, authInfo=None): - self.url = url - if authInfo: - self.url.set_auth_info(authInfo) - self.location = dirname(self.url.uri) - - pkgname = basename(dirname(self.url.path())) - self.dest = join(ctx.config.tmp_dir(), pkgname) - - def fetch_all(self): - # fetch pspec file - self.fetch() - pspec = join(self.dest, self.url.filename()) - self.spec = SpecFile() - self.spec.read(pspec) - - self.fetch_actionsfile() - self.fetch_patches() - self.fetch_comarfiles() - self.fetch_additionalFiles() - - return pspec - - def fetch_actionsfile(self): - actionsuri = join(self.location, ctx.const.actions_file) - self.url.uri = actionsuri - self.fetch() - - def fetch_patches(self): - spec = self.spec - for patch in spec.source.patches: - file_name = basename(patch.filename) - dir_name = dirname(patch.filename) - patchuri = join(self.location, - ctx.const.files_dir, dir_name, file_name) - self.url.uri = patchuri - target_dir = join(ctx.const.files_dir, dir_name) - self.fetch(target_dir) - - def fetch_comarfiles(self): - spec = self.spec - for package in spec.packages: - for pcomar in package.providesComar: - comaruri = join(self.location, - ctx.const.comar_dir, pcomar.script) - self.url.uri = comaruri - self.fetch(ctx.const.comar_dir) - - def fetch_additionalFiles(self): - spec = self.spec - for pkg in spec.packages: - for afile in pkg.additionalFiles: - file_name = basename(afile.filename) - dir_name = dirname(afile.filename) - afileuri = join(self.location, - ctx.const.files_dir, dir_name, file_name) - self.url.uri = afileuri - target_dir = join(ctx.const.files_dir, dir_name) - self.fetch(target_dir) - - def fetch(self, appendDest=""): - from fetcher import fetch_url - - ctx.ui.info(_("Fetching %s") % self.url.uri) - dest = join(self.dest, appendDest) - fetch_url(self.url, dest)