Пример #1
0
 def __init__(self, filename):
     self.id = os.path.splitext(os.path.basename(filename))[0]
     self.log = pb_logging.logger.getChild("Recipe[{}]".format(self.id))
     self.inherit = 'empty'
     self._static = False
     # Load original recipe:
     self.log.obnoxious("Loading recipe file: {}".format(filename))
     self._data = self._load_recipe_from_file(filename)
     # Recursively do the inheritance:
     while self._data.get('inherit', 'empty'):
         inherit_from = self._data.get('inherit', 'empty')
         try:
             filename = recipe_manager.recipe_manager.get_template_filename(inherit_from)
             self.log.obnoxious("Loading template file: {}".format(filename))
         except PBException as e:
             self.log.warn("Recipe attempting to inherit from unknown template {}".format(
                 inherit_from
             ))
             break
         self.log.obnoxious("Inheriting from file {}".format(filename))
         parent_data = self._load_recipe_from_file(filename)
         self._data['depends'] = self._data['depends'] + parent_data['depends']
         self._data = dict_merge(parent_data, self._data)
         self._data['inherit'] = parent_data.get('inherit')
     if self._data.get('target') == 'package':
         self._data = self.get_local_package_data()
     else:
         self._data = self._normalize_package_data(self._data)
     # Map all recipe info onto self:
     for k, v in iteritems(self._data):
         if not hasattr(self, k):
             setattr(self, k, v)
     self.log.obnoxious("Loaded recipe - {}".format(self.id))
Пример #2
0
    def update_cfg_file(self, new_data, cfg_file=None):
        """
        Write new data to a config file.

        If no config file is specified, the local config file
        is used (e.g., on Linux, the one in ~/.pybombs/).
        """
        if cfg_file is None:
            cfg_file = self.local_cfg
        if not os.path.isfile(cfg_file):
            self.log.info("Creating new config file {0}".format(cfg_file))
            cfg_data = new_data
            path = os.path.split(cfg_file)[0]
            if not os.path.isdir(path):
                os.path.mkdir(path)
        else:
            self.log.obnoxious(
                "Updating file {0} with new data: {1}".format(cfg_file, new_data)
            )
            try:
                old_cfg_data = yaml.safe_load(open(cfg_file).read()) or {}
            except IOError:
                self.log.debug("Error opening config file {0}.".format(cfg_file))
                old_cfg_data = {}
            cfg_data = dict_merge(old_cfg_data, new_data)
        open(cfg_file, 'wb').write(yaml.dump(cfg_data, default_flow_style=False))
Пример #3
0
    def update_cfg_file(self, new_data, cfg_file=None):
        """
        Write new data to a config file.

        If no config file is specified, the local config file
        is used (e.g., on Linux, the one in ~/.pybombs/).
        """
        if cfg_file is None:
            cfg_file = self.local_cfg
        if not os.path.isfile(cfg_file):
            self.log.info("Creating new config file {0}".format(cfg_file))
            cfg_data = new_data
            path = os.path.split(cfg_file)[0]
            if not os.path.isdir(path):
                os.path.mkdir(path)
        else:
            self.log.obnoxious("Updating file {0} with new data: {1}".format(
                cfg_file, new_data))
            try:
                old_cfg_data = yaml.safe_load(open(cfg_file).read()) or {}
            except IOError:
                self.log.debug(
                    "Error opening config file {0}.".format(cfg_file))
                old_cfg_data = {}
            cfg_data = dict_merge(old_cfg_data, new_data)
        open(cfg_file,
             'wb').write(yaml.dump(cfg_data, default_flow_style=False))
Пример #4
0
 def __init__(self, filename):
     self.id = os.path.splitext(os.path.basename(filename))[0]
     self.log = pb_logging.logger.getChild("Recipe[{0}]".format(self.id))
     self.inherit = 'empty'
     self._static = False
     # Load original recipe:
     self.log.trace("Loading recipe file: {0}".format(filename))
     self._data = self._load_recipe_from_file(filename)
     # Recursively do the inheritance:
     while self._data.get('inherit', 'empty'):
         inherit_from = self._data.get('inherit', 'empty')
         try:
             filename = recipe_manager.recipe_manager.get_template_filename(
                 inherit_from)
             self.log.trace("Loading template file: {0}".format(filename))
         except PBException as e:
             self.log.warn(
                 "Recipe attempting to inherit from unknown template {0}".
                 format(inherit_from))
             break
         self.log.trace("Inheriting from file {0}".format(filename))
         parent_data = self._load_recipe_from_file(filename)
         self._data[
             'depends'] = self._data['depends'] + parent_data['depends']
         self._data = dict_merge(parent_data, self._data)
         self._data['inherit'] = parent_data.get('inherit')
     if self._data.get('target') == 'package':
         self._data = self.get_local_package_data()
     else:
         self._data = self._normalize_package_data(self._data)
     # Map all recipe info onto self:
     for k, v in iteritems(self._data):
         if not hasattr(self, k):
             setattr(self, k, v)
     self.log.trace("Loaded recipe - {0}".format(self.id))
Пример #5
0
 def _install_sdk_to_prefix(self, sdkname):
     """
     Read recipe for sdkname, and install the SDK to the prefix.
     """
     from pybombs import recipe
     src_dir = self.prefix.src_dir
     cfg_file = self.prefix.cfg_file
     ### Get the recipe
     r = recipe.get_recipe(sdkname, target='sdk')
     try:
         self.log.trace("Switching CWD to {0}".format(src_dir))
         if not op.isdir(src_dir):
             os.mkdir(src_dir)
         os.chdir(src_dir)
     except:
         self.log.error("Source dir required to install SDK.")
         return False
     ### Install the actual SDK file
     self.log.debug("Fetching SDK `{sdk}'".format(sdk=sdkname))
     fetcher.Fetcher().fetch(r)
     self.log.info("Installing SDK `{sdk}'".format(sdk=sdkname))
     # Install command
     cmd = r.var_replace_all(r.get_command('install'))
     if subproc.monitor_process(cmd, shell=True, env=os.environ) == 0:
         self.log.debug("Installation successful")
     else:
         self.log.error("Error installing SDK. Aborting.")
         return False
     # Clean up
     files_to_delete = [op.normpath(op.join(src_dir, r.var_replace_all(x))) for x in r.clean]
     if len(files_to_delete):
         self.log.info("Cleaning up files...")
     for ftd in files_to_delete:
         if op.commonprefix((src_dir, ftd)) != src_dir:
             self.log.warn("Not removing {ftd} -- outside source dir!".format(ftd=ftd))
             continue
         self.log.debug("Removing {ftd}...".format(ftd=ftd))
         if op.isdir(ftd):
             shutil.rmtree(ftd)
         elif op.isfile(ftd):
             os.remove(ftd)
         else:
             self.log.error("Not sure what this is: {ftd}".format(ftd=ftd))
             return False
     ### Update the prefix-local config file
     self.log.debug("Updating config file with SDK recipe info.")
     try:
         old_cfg_data = PBConfigFile(cfg_file).get()
     except IOError:
         self.log.debug("There doesn't seem to be a config file yet for this prefix.")
         old_cfg_data = {}
     # Filter out keys we don't care about:
     sdk_recipe_keys_for_config = ('config', 'packages', 'categories', 'env')
     sdk_cfg_data = {k: v for k, v in iteritems(r.get_dict()) if k in sdk_recipe_keys_for_config}
     self.log.trace("New data: {new}".format(new=sdk_cfg_data))
     cfg_data = dict_merge(old_cfg_data, sdk_cfg_data)
     self.log.debug("Writing updated prefix config to `{0}'".format(cfg_file))
     PBConfigFile(cfg_file).save(cfg_data)
     return True
Пример #6
0
 def __init__(self, filename):
     self.id = os.path.splitext(os.path.basename(filename))[0]
     self.log = pb_logging.logger.getChild("Recipe[{}]".format(self.id))
     self.inherit = 'empty'
     self._static = False
     # Load original recipe:
     self.log.obnoxious("Loading recipe file: {}".format(filename))
     self._data = self._load_recipe_from_yaml(filename)
     # Recursively do the inheritance:
     while self._data.get('inherit', 'empty'):
         inherit_from = self._data.get('inherit', 'empty')
         try:
             filename = recipe_manager.recipe_manager.get_template_filename(
                 inherit_from)
             self.log.obnoxious(
                 "Loading template file: {}".format(filename))
         except PBException as e:
             self.log.warn(
                 "Recipe attempting to inherit from unknown template {}".
                 format(inherit_from))
             break
         self.log.obnoxious("Inheriting from file {}".format(filename))
         parent_data = self._load_recipe_from_yaml(filename)
         self._data[
             'depends'] = self._data['depends'] + parent_data['depends']
         self._data = dict_merge(parent_data, self._data)
         self._data['inherit'] = parent_data.get('inherit')
     # Post-process some fields:
     if self._data.has_key('source') and not isinstance(
             self._data['source'], list):
         self._data['source'] = [
             self._data['source'],
         ]
     # Package flags override vars:
     self._data['vars'] = dict_merge(
         self._data.get('vars', {}),
         config_manager.config_manager.get_package_flags(
             self.id, self._data.get('category')).get('vars', {}))
     # Map all recipe info onto self:
     for k, v in self._data.iteritems():
         if not hasattr(self, k):
             setattr(self, k, v)
Пример #7
0
 def _merge_config_info_from_file(self, cfg_file, cfg_data):
     """
     Load a config file, load its contents, and merge it into cfg_info.
     Return the result.
     """
     try:
         self.log.debug('Inspecting config file: {}'.format(cfg_file))
         cfg_data_new = yaml.safe_load(open(cfg_file, 'r').read()) or {}
     except Exception as e:
         self.log.debug('Well, looks like that failed.')
         return cfg_data
     return dict_merge(cfg_data, cfg_data_new)
Пример #8
0
 def _merge_config_info_from_file(self, cfg_file, cfg_data):
     """
     Load a config file, load its contents, and merge it into cfg_info.
     Return the result.
     """
     try:
         self.log.debug('Inspecting config file: {}'.format(cfg_file))
         cfg_data_new = yaml.safe_load(open(cfg_file, 'r').read()) or {}
     except Exception as e:
         self.log.debug('Well, looks like that failed.')
         return cfg_data
     return dict_merge(cfg_data, cfg_data_new)
Пример #9
0
 def _merge_config_info_from_file(self, cfg_file, cfg_data):
     """
     Load a config file, load its contents, and merge it into cfg_info.
     Return the result.
     """
     try:
         self.log.debug('Inspecting config file: {0}'.format(cfg_file))
         cfg_data_new = PBConfigFile(cfg_file).get()
     except Exception:
         self.log.debug('Well, looks like that failed.')
         return cfg_data
     return dict_merge(cfg_data, cfg_data_new)
Пример #10
0
 def _merge_config_info_from_file(self, cfg_file, cfg_data):
     """
     Load a config file, load its contents, and merge it into cfg_info.
     Return the result.
     """
     try:
         self.log.debug('Inspecting config file: {0}'.format(cfg_file))
         cfg_data_new = PBConfigFile(cfg_file).get()
     except Exception:
         self.log.debug('Well, looks like that failed.')
         return cfg_data
     return dict_merge(cfg_data, cfg_data_new)
Пример #11
0
    def get_local_package_data(self):
        """
        Merges the recipe data with local config settings. Local settings
        always supersede recipe settings.

        This allows users to override anything in a recipe with whatever's stored
        in the `package:` and `category:` sections of their local config files.
        """
        return dict_merge(
            self.get_dict(),
            config_manager.config_manager.get_package_flags(
                self.id,
                self.get_dict().get('category')))
Пример #12
0
 def __init__(self, filename):
     self.id = os.path.splitext(os.path.basename(filename))[0]
     self.log = pb_logging.logger.getChild("Recipe[{}]".format(self.id))
     self.inherit = 'empty'
     self._static = False
     # Load original recipe:
     self.log.obnoxious("Loading recipe file: {}".format(filename))
     self._data = self._load_recipe_from_yaml(filename)
     # Recursively do the inheritance:
     while self._data.get('inherit', 'empty'):
         inherit_from = self._data.get('inherit', 'empty')
         try:
             filename = recipe_manager.recipe_manager.get_template_filename(inherit_from)
             self.log.obnoxious("Loading template file: {}".format(filename))
         except PBException as e:
             self.log.warn("Recipe attempting to inherit from unknown template {}".format(
                 inherit_from
             ))
             break
         self.log.obnoxious("Inheriting from file {}".format(filename))
         parent_data = self._load_recipe_from_yaml(filename)
         self._data['depends'] = self._data['depends'] + parent_data['depends']
         self._data = dict_merge(parent_data, self._data)
         self._data['inherit'] = parent_data.get('inherit')
     # Post-process some fields:
     if self._data.has_key('source') and not isinstance(self._data['source'], list):
         self._data['source'] = [self._data['source'],]
     # Package flags override vars:
     self._data['vars'] = dict_merge(
         self._data.get('vars', {}),
         config_manager.config_manager.get_package_flags(
             self.id, self._data.get('category')
         ).get('vars', {})
     )
     # Map all recipe info onto self:
     for k, v in self._data.iteritems():
         if not hasattr(self, k):
             setattr(self, k, v)
     self.log.obnoxious("Loaded recipe - {}".format(self))
Пример #13
0
    def get_local_package_data(self):
        """
        Merges the recipe data with local config settings. Local settings
        always supersede recipe settings.

        This allows users to override anything in a recipe with whatever's stored
        in the `package:` and `category:` sections of their local config files.
        """
        return self._normalize_package_data(dict_merge(
            self.get_dict(),
            config_manager.config_manager.get_package_flags(
                self.id, self.get_dict().get('category')
            )
        ))
Пример #14
0
    def get_package_flags(self, pkgname, categoryname=None):
        """
        Return all the package flags of pkgname as a dictionary.
        If pkgname doesn't have any package flags, return an empty dict.

        Note: Only returns settings from the local settings files! If you
        want the full set of current package settings, prefer
        recipe.get_local_package_data().

        If categoryname is provided, it will load the category flags first
        and then merge the package flags on top of it.
        """
        return dict_merge(
            getattr(self._prefix_info, 'categories', {}).get(categoryname, {}),
            getattr(self._prefix_info, 'packages', {}).get(pkgname, {}))
Пример #15
0
    def get_package_flags(self, pkgname, categoryname=None):
        """
        Return all the package flags of pkgname as a dictionary.
        If pkgname doesn't have any package flags, return an empty dict.

        Note: Only returns settings from the local settings files! If you
        want the full set of current package settings, prefer
        recipe.get_local_package_data().

        If categoryname is provided, it will load the category flags first
        and then merge the package flags on top of it.
        """
        return dict_merge(
            getattr(self._prefix_info, 'categories', {}).get(categoryname, {}),
            getattr(self._prefix_info, 'packages', {}).get(pkgname, {})
        )
Пример #16
0
 def update(self, newdata):
     " Overwrite the data with newdata recursively. Updates the file. "
     self.data = dict_merge(self.data, newdata)
     self.save()
     return self.data
Пример #17
0
 def update(self, newdata):
     " Overwrite the data with newdata recursively. Updates the file. "
     self.data = dict_merge(self.data, newdata)
     self.save()
     return self.data
Пример #18
0
    def _run_init(self):
        """
        pybombs prefix init
        """
        def register_alias(alias):
            if alias is not None:
                if self.prefix is not None and \
                        self.prefix.prefix_aliases.get(alias) is not None \
                        and not confirm("Alias `{0}' already exists, overwrite?".format(alias)):
                    self.log.warn('Aborting.')
                    raise PBException("Could not create alias.")
                self.cfg.update_cfg_file({'prefix_aliases': {self.args.alias: path}})
        # Go, go, go!
        try:
            prefix_recipe = get_prefix_recipe(self.args.recipe)
        except PBException as ex:
            self.log.error(str(ex))
            return -1
        if prefix_recipe is None:
            self.log.error("Could not find recipe for `{0}'".format(self.args.recipe))
            return -1
        # Make sure the directory is writable
        path = op.abspath(op.normpath(self.args.path))
        if not sysutils.mkdir_writable(path, self.log):
            self.log.error("Cannot write to prefix path `{0}'.".format(path))
            return -1
        # Make sure that a pybombs directory doesn't already exist
        from pybombs import config_manager
        if op.exists(op.join(path, config_manager.PrefixInfo.prefix_conf_dir)):
            self.log.error("Ignoring. A prefix already exists in `{0}'".format(path))
            return -1
        # Add subdirs
        sysutils.require_subdirs(path, [k for k, v in prefix_recipe.dirs.items() if v])
        self.cfg.load(select_prefix=path)
        self.prefix = self.cfg.get_active_prefix()
        # Create files
        for fname, content in prefix_recipe.files.items():
            sysutils.write_file_in_subdir(path, fname, prefix_recipe.var_replace_all(content))
        # Register alias
        if self.args.alias is not None:
            register_alias(self.args.alias)
        # If there is no default prefix, make this the default
        if len(self.cfg.get('default_prefix')) == 0:
            if self.args.alias is not None:
                new_default_prefix = self.args.alias
            else:
                new_default_prefix = path
            self.cfg.update_cfg_file({'config': {'default_prefix': new_default_prefix}})
        # Create virtualenv if so desired
        if self.args.virtualenv:
            self.log.info("Creating Python virtualenv in prefix...")
            venv_args = ['virtualenv', '--no-site-packages']
            venv_args.append(path)
            subproc.monitor_process(args=venv_args)
        # Install SDK if so desired
        sdk = self.args.sdkname or prefix_recipe.sdk
        if sdk is not None:
            self.log.info("Installing SDK recipe {0}.".format(sdk))
            self.log.info("Reloading configuration...")
            self.cfg.load(select_prefix=path)
            self.prefix = self.cfg.get_active_prefix()
            self.inventory = self.prefix.inventory
            self._install_sdk_to_prefix(sdk)
        # Update config section
        if len(prefix_recipe.config):
            if self.args.virtualenv:
                prefix_recipe.config = dict_merge(
                    {'virtualenv': True}, prefix_recipe.config)
                self.cfg.update_cfg_file(prefix_recipe.config, self.prefix.cfg_file)
            else:
                prefix_recipe.config = dict_merge(
                    {'virtualenv': False}, prefix_recipe.config)
                self.cfg.update_cfg_file(prefix_recipe.config, self.prefix.cfg_file)

            self.cfg.load(select_prefix=path)
            self.prefix = self.cfg.get_active_prefix()
        # Install dependencies
        if len(prefix_recipe.depends):
            self.log.info("Installing default packages for prefix...")
            self.log.info("".join(["\n  - {0}".format(x) for x in prefix_recipe.depends]))
            from pybombs import install_manager
            install_manager.InstallManager().install(
                    prefix_recipe.depends,
                    'install', # install / update
                    fail_if_not_exists=False,
                    update_if_exists=False,
                    print_tree=True,
            )