<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 16, 2015 at 8:21 AM, Paul Eggleton <span dir="ltr"><<a href="mailto:paul.eggleton@linux.intel.com" target="_blank">paul.eggleton@linux.intel.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div id=":2yp" class="a3s" style="overflow:hidden">Hi Chris,<br>
<div><div class="h5"><br>
On Tuesday 15 September 2015 20:57:46 Christopher Larson wrote:<br>
> This sub-command creates a bbappend for the specified target and prints the<br>
> path to the bbappend. The -w argument, as with some of the other recipetool<br>
> commands, will make a version-independent bbappend.<br>
><br>
> Example usage: recipetool newappend meta-mylayer virtual/kernel<br>
><br>
> [YOCTO #7964]<br>
><br>
> Signed-off-by: Christopher Larson <<a href="mailto:kergoth@gmail.com">kergoth@gmail.com</a>><br>
> ---<br>
> scripts/lib/recipetool/newappend.py | 126<br>
> ++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+)<br>
> create mode 100644 scripts/lib/recipetool/newappend.py<br>
><br>
> diff --git a/scripts/lib/recipetool/newappend.py<br>
> b/scripts/lib/recipetool/newappend.py new file mode 100644<br>
> index 0000000..be9077c<br>
> --- /dev/null<br>
> +++ b/scripts/lib/recipetool/newappend.py<br>
> @@ -0,0 +1,126 @@<br>
> +# Recipe creation tool - newappend plugin<br>
> +#<br>
> +# This sub-command creates a bbappend for the specified target and prints<br>
> the +# path to the bbappend.<br>
> +#<br>
> +# Example: recipetool newappend meta-mylayer busybox<br>
> +#<br>
> +# Copyright (C) 2015 Christopher Larson <<a href="mailto:kergoth@gmail.com">kergoth@gmail.com</a>><br>
> +#<br>
> +# This program is free software; you can redistribute it and/or modify<br>
> +# it under the terms of the GNU General Public License version 2 as<br>
> +# published by the Free Software Foundation.<br>
> +#<br>
> +# This program is distributed in the hope that it will be useful,<br>
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
> +# GNU General Public License for more details.<br>
> +#<br>
> +# You should have received a copy of the GNU General Public License along<br>
> +# with this program; if not, write to the Free Software Foundation, Inc.,<br>
> +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.<br>
> +<br>
> +import argparse<br>
> +import errno<br>
> +import logging<br>
> +import os<br>
> +import re<br>
> +<br>
> +<br>
> +logger = logging.getLogger('recipetool')<br>
> +tinfoil = None<br>
> +<br>
> +<br>
> +def plugin_init(pluginlist):<br>
> + # Don't need to do anything here right now, but plugins must have this<br>
> function defined + pass<br>
> +<br>
> +<br>
> +def tinfoil_init(instance):<br>
> + global tinfoil<br>
> + tinfoil = instance<br>
> +<br>
> +<br>
> +def _provide_to_pn(cooker, provide):<br>
> + """Get the name of the preferred recipe for the specified provide."""<br>
> + import bb.providers<br>
> + filenames = cooker.recipecache.providers[provide]<br>
> + eligible, foundUnique = bb.providers.filterProviders(filenames,<br>
> provide, cooker.expanded_data, cooker.recipecache) + filename =<br>
> eligible[0]<br>
> + pn = cooker.recipecache.pkg_fn[filename]<br>
> + return pn<br>
> +<br>
> +<br>
> +def _get_recipe_file(cooker, pn):<br>
> + import oe.recipeutils<br>
> + recipefile = oe.recipeutils.pn_to_recipe(cooker, pn)<br>
> + if not recipefile:<br>
> + skipreasons = oe.recipeutils.get_unavailable_reasons(cooker, pn)<br>
> + if skipreasons:<br>
> + logger.error('\n'.join(skipreasons))<br>
> + else:<br>
> + logger.error("Unable to find any recipe file matching %s" % pn)<br>
> + return recipefile<br>
> +<br>
> +<br>
> +def layer(layerpath):<br>
> + if not os.path.exists(os.path.join(layerpath, 'conf', 'layer.conf')):<br>
> + raise argparse.ArgumentTypeError('{0!r} must be a path to a valid<br>
> layer'.format(layerpath)) + return layerpath<br>
> +<br>
> +<br>
> +def newappend(args):<br>
> + pn = _provide_to_pn(tinfoil.cooker, args.target)<br>
> + recipe_path = _get_recipe_file(tinfoil.cooker, pn)<br>
> +<br>
> + # Map recipe path to the layer it's in<br>
> + for layerpath in tinfoil.config_data.getVar('BBLAYERS', True).split():<br>
> + layerconf = os.path.join(layerpath, 'conf', 'layer.conf')<br>
> + l = bb.data.init()<br>
> + l.setVar('LAYERDIR', layerpath)<br>
> + l = bb.parse.handle(layerconf, l)<br>
> + l.expandVarref('LAYERDIR')<br>
> +<br>
> + for layername in l.getVar('BBFILE_COLLECTIONS', True).split():<br>
> + pattern = l.getVar('BBFILE_PATTERN_' + layername, True)<br>
> + if pattern and re.match(pattern, recipe_path):<br>
> + recipe_layer_path = layerpath<br>
> + break<br>
> + else:<br>
> + continue<br>
> + break<br>
> + else:<br>
> + recipe_layer_path =<br>
> os.path.dirname(os.path.dirname(os.path.dirname(recipe_path))) +<br>
> + recipe_relpath = os.path.relpath(recipe_path, recipe_layer_path)<br>
> + append_relpath = recipe_relpath + 'append'<br>
> + append_path = os.path.join(args.destlayer, append_relpath)<br>
> +<br>
> + if args.wildcard_version and '_' in os.path.basename(append_path):<br>
> + base, _ = os.path.splitext(append_path)<br>
> + base, _ = base.rsplit('_', 1)<br>
> + append_path = base + '_%.bbappend'<br>
> +<br>
> + if not os.path.exists(append_path):<br>
> + try:<br>
> + os.makedirs(os.path.dirname(append_path))<br>
> + except OSError as exc:<br>
> + if exc.errno != errno.EEXIST:<br>
> + raise<br>
> +<br>
> + try:<br>
> + open(append_path, 'a')<br>
> + except (OSError, IOError) as exc:<br>
> + logger.critical(str(exc))<br>
> + return 1<br>
> +<br>
> + print(append_path)<br>
> +<br>
> +<br>
> +def register_command(subparsers):<br>
> + parser = subparsers.add_parser('newappend',<br>
> + help='Create a bbappend for the<br>
> specified target in the specified layer') + parser.add_argument('-w',<br>
> '--wildcard-version', help='Use wildcard to make the bbappend apply to any<br>
> recipe version', action='store_true') + parser.add_argument('destlayer',<br>
> help='Base directory of the destination layer to write the bbappend to',<br>
> type=layer) + parser.add_argument('target', help='Target recipe/provide<br>
> to append') + parser.set_defaults(func=newappend, parserecipes=True)<br>
<br>
</div></div>So the first thing that springs to mind here is that there's a bunch of code to<br>
do the major part of this in recipeutils (e.g. finding the correct name and<br>
location for a bbappend file is done by get_bbappend_path()) - shouldn't we be<br>
using that here?</div></blockquote></div><br>Probably, I had no idea that function existed :) Thanks, will take a look.<br>-- <br><div class="gmail_signature"><div dir="ltr">Christopher Larson<br>kergoth at gmail dot com<br>Founder - BitBake, OpenEmbedded, OpenZaurus<br>Maintainer - Tslib<br>Senior Software Engineer, Mentor Graphics</div></div>
</div></div>