def load_remote_configuration(self, pkg): """ attempt to load any remote configuration options for a package This call will scan select output locations of a package's content for any releng-tool-specific package configurations to late-load into a package definition. Args: pkg: the package Raises: RelengToolInvalidPackageConfiguration: when an error has been detected loading any of the package's extended options """ target_remote_configurations = [ os.path.join(pkg.build_dir, RELENG_CONF_EXTENDED_NAME) ] if pkg.build_subdir: target_remote_configurations.append( os.path.join(pkg.build_subdir, RELENG_CONF_EXTENDED_NAME)) # find the first available script to load from for target in target_remote_configurations: pkg_script, pkg_script_exists = opt_file(target) if pkg_script_exists: # attempt to finalize the package self.finalize_package(pkg, pkg_script) break
def install(opts): """ support installation project-defined scripts With provided installation options (``RelengInstallOptions``), the installation stage will be processed. Args: opts: installation options Returns: ``True`` if the installation stage is completed; ``False`` otherwise """ assert opts build_dir = opts.build_dir def_dir = opts.def_dir env = opts.env install_script_filename = '{}-{}'.format(opts.name, INSTALL_SCRIPT) install_script = os.path.join(def_dir, install_script_filename) install_script, install_script_exists = opt_file(install_script) if not install_script_exists: if (opts._skip_remote_scripts or 'releng.disable_remote_scripts' in opts._quirks): return True install_script_filename = '{}-{}'.format('releng', INSTALL_SCRIPT) install_script = os.path.join(build_dir, install_script_filename) install_script, install_script_exists = opt_file(install_script) if not install_script_exists: return True if not run_script(install_script, env, subject='install'): return False verbose('install script executed: ' + install_script) return True
def configure(opts): """ support configuration project-defined scripts With provided configuration options (``RelengConfigureOptions``), the configuration stage will be processed. Args: opts: configuration options Returns: ``True`` if the configuration stage is completed; ``False`` otherwise """ assert opts build_dir = opts.build_dir def_dir = opts.def_dir env = opts.env configure_script_filename = '{}-{}'.format(opts.name, CONFIGURE_SCRIPT) configure_script = os.path.join(def_dir, configure_script_filename) configure_script, configure_script_exists = opt_file(configure_script) if not configure_script_exists: if (opts._skip_remote_scripts or 'releng.disable_remote_scripts' in opts._quirks): return True configure_script_filename = '{}-{}'.format('releng', CONFIGURE_SCRIPT) configure_script = os.path.join(build_dir, configure_script_filename) configure_script, configure_script_exists = opt_file(configure_script) if not configure_script_exists: return True if not run_script(configure_script, env, subject='configure'): return False verbose('install script executed: ' + configure_script) return True
def build(opts): """ support building project-defined scripts With provided build options (``RelengBuildOptions``), the build stage will be processed. Args: opts: build options Returns: ``True`` if the building stage is completed; ``False`` otherwise """ assert opts build_dir = opts.build_dir def_dir = opts.def_dir env = opts.env build_script_filename = '{}-{}'.format(opts.name, BUILD_SCRIPT) build_script = os.path.join(def_dir, build_script_filename) build_script, build_script_exists = opt_file(build_script) if not build_script_exists: if (opts._skip_remote_scripts or 'releng.disable_remote_scripts' in opts._quirks): return True build_script_filename = '{}-{}'.format('releng', BUILD_SCRIPT) build_script = os.path.join(build_dir, build_script_filename) build_script, build_script_exists = opt_file(build_script) if not build_script_exists: return True if not run_script(build_script, env, subject='build'): return False verbose('install script executed: ' + build_script) return True
def test_utilio_optfile(self): with prepare_workdir() as work_dir: def _(*args): return os.path.join(work_dir, *args) # setup files = [ _('file1'), _('file2.py'), _('file3'), _('file3.py'), ] for file in files: with open(file, 'a') as f: f.write(file) # checks src = _('file1') target, existence = opt_file(src) self.assertTrue(existence) self.assertEqual(target, src) src = _('file2') opt = _('file2.py') target, existence = opt_file(src) self.assertTrue(existence) self.assertEqual(target, opt) src = _('file3') target, existence = opt_file(src) self.assertTrue(existence) self.assertEqual(target, src) src = _('file4') target, existence = opt_file(src) self.assertFalse(existence) self.assertEqual(target, src)
def stage(engine, pkg, script_env): """ handles the post-processing stage for a package With a provided engine and package instance, the post-processing stage will be processed. This stage is typically not advertised and is for advanced cases where a developer wishes to manipulate their build environment after package has completed each of its phases. Args: engine: the engine pkg: the package being built script_env: script environment information Returns: ``True`` if the post-processing stage is completed; ``False`` otherwise """ verbose('post-processing {}...', pkg.name) sys.stdout.flush() post_script_filename = '{}-{}'.format(pkg.name, POST_SCRIPT) post_script = os.path.join(pkg.def_dir, post_script_filename) post_script, post_script_exists = opt_file(post_script) if not post_script_exists: return True if pkg.build_subdir: build_dir = pkg.build_subdir else: build_dir = pkg.build_dir with interim_working_dir(build_dir): if not run_script(post_script, script_env, subject='post-processing'): return False verbose('post-processing script executed: ' + post_script) return True
def load(self, names): """ load one or more packages from the provided collection of names Attempts to load and return a series of ordered package instances using the collection of names provided. Each name will be used to find a package definition on the system. Package scripts are found, loaded and parsed. Packages with dependencies will have their dependent packages loaded as well (either from the explicitly from the ``names`` or implicitly from the package's configuration file). The returned package list will be an ordered package list based on configured dependencies outlined in the user's package definitions. When package dependencies do not play a role in the required order of the releng process, a first-configured first-returned approach is used. Args: names: the names of packages to load Returns: returns an ordered list of packages to use Raises: RelengToolInvalidPackageConfiguration: when an error has been detected loading the package """ pkgs = OrderedDict() final_deps = {} # cycle through all pending packages until the complete list is known names_left = list(names) while names_left: name = names_left.pop(0) # attempt to load the package from a user defined external directory pkg = None for pkg_dir in self.opts.extern_pkg_dirs: pkg_script = os.path.join(pkg_dir, name, name) pkg_script, pkg_script_exists = opt_file(pkg_script) if pkg_script_exists: pkg, env, deps = self.load_package(name, pkg_script) # if a package location has not been found, finally check the # default package directory if not pkg: pkg_script = os.path.join(self.opts.default_pkg_dir, name, name) pkg_script, _ = opt_file(pkg_script) pkg, env, deps = self.load_package(name, pkg_script) pkgs[pkg.name] = pkg for dep in deps: # if this is an unknown package and is not in out current list, # append it to the list of names to process if dep == name: raise RelengToolCyclicPackageDependency({ 'pkg_name': name, }) elif dep not in pkgs: if dep not in names_left: verbose('adding implicitly defined package: {}', dep) names_left.append(dep) if pkg not in final_deps: final_deps[pkg] = [] final_deps[pkg].append(dep) else: pkg.deps.append(pkgs[dep]) extend_script_env(self.script_env, env) # for packages which have a dependency but have not been bound yet, # bind the dependencies now for pkg, deps in final_deps.items(): for dep in deps: assert pkgs[dep] pkg.deps.append(pkgs[dep]) debug('sorting packages...') def fetch_deps(pkg): return pkg.deps sorter = TopologicalSorter(fetch_deps) sorted_pkgs = [] for pkg in pkgs.values(): sorted_pkgs = sorter.sort(pkg) if sorted_pkgs is None: raise RelengToolCyclicPackageDependency({ 'pkg_name': name, }) debug('sorted packages)') for pkg in sorted_pkgs: debug(' {}', pkg.name) return sorted_pkgs