All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] devtool / recipetool fixes for node.js modules
@ 2017-04-12 10:41 Paul Eggleton
  2017-04-12 10:41 ` [PATCH 1/4] recipetool: create: fix for regression in npm license handling Paul Eggleton
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Paul Eggleton @ 2017-04-12 10:41 UTC (permalink / raw)
  To: openembedded-core

This fixes a few regressions in master in handling devtool add on
node.js modules relative to morty.


The following changes since commit 210c518ba8f8d6ec6e9d34e0df8b963a3b2e0593:

  ptest-runner: Upgrade to minor version 2.0.2 (2017-04-11 18:09:21 +0100)

are available in the git repository at:

  git://git.openembedded.org/openembedded-core-contrib paule/npm-fixes3
  http://cgit.openembedded.org/openembedded-core-contrib/log/?h=paule/npm-fixes3

Paul Eggleton (4):
  recipetool: create: fix for regression in npm license handling
  devtool: add: fix node.js/npm handling with recipe specific sysroots
  devtool: add: prevent repeatedly running recipetool
  recipetool: create: hide missing npm error when called from devtool

 scripts/lib/devtool/__init__.py      | 25 ++++++++++++++-----------
 scripts/lib/devtool/standard.py      |  6 +++++-
 scripts/lib/recipetool/create.py     | 32 ++++++++++++++++++++++++++------
 scripts/lib/recipetool/create_npm.py | 23 +++++++++++++----------
 4 files changed, 58 insertions(+), 28 deletions(-)

-- 
2.9.3



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] recipetool: create: fix for regression in npm license handling
  2017-04-12 10:41 [PATCH 0/4] devtool / recipetool fixes for node.js modules Paul Eggleton
@ 2017-04-12 10:41 ` Paul Eggleton
  2017-04-12 10:41 ` [PATCH 2/4] devtool: add: fix node.js/npm handling with recipe specific sysroots Paul Eggleton
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Eggleton @ 2017-04-12 10:41 UTC (permalink / raw)
  To: openembedded-core

OE-Core commit c0cfd9b1d54b05ad048f444d6fe248aa0500159e added handling
for AND / OR in license strings coming from npm, but made the assumption
that an & would always be present in the license value. Check if it's
there first so we don't fail if it isn't.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
 scripts/lib/recipetool/create_npm.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index a215026..eb19555 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -240,7 +240,8 @@ class NpmRecipeHandler(RecipeHandler):
                     packages['${PN}'] = ''
                     pkglicenses = split_pkg_licenses(licvalues, packages, lines_after, licenses)
                     all_licenses = list(set([item.replace('_', ' ') for pkglicense in pkglicenses.values() for item in pkglicense]))
-                    all_licenses.remove('&')
+                    if '&' in all_licenses:
+                        all_licenses.remove('&')
                     # Go back and update the LICENSE value since we have a bit more
                     # information than when that was written out (and we know all apply
                     # vs. there being a choice, so we can join them with &)
-- 
2.9.3



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] devtool: add: fix node.js/npm handling with recipe specific sysroots
  2017-04-12 10:41 [PATCH 0/4] devtool / recipetool fixes for node.js modules Paul Eggleton
  2017-04-12 10:41 ` [PATCH 1/4] recipetool: create: fix for regression in npm license handling Paul Eggleton
@ 2017-04-12 10:41 ` Paul Eggleton
  2017-04-12 10:41 ` [PATCH 3/4] devtool: add: prevent repeatedly running recipetool Paul Eggleton
  2017-04-12 10:41 ` [PATCH 4/4] recipetool: create: hide missing npm error when called from devtool Paul Eggleton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Eggleton @ 2017-04-12 10:41 UTC (permalink / raw)
  To: openembedded-core

The change over to recipe specific sysroots means that we can no longer
get a known location simply from configuration for the npm binary - we
need to get the recipe sysroot for nodejs-native, look there for npm if
we need to check it's present, and add that to PATH when calling out to
npm. Unfortunately this means anywhere we need to get that path we have
to have parsed all recipes, otherwise we have no reliable way of
resolving nodejs-native. Thus we have to change recipetool create to
always parse all recipes (the structure of the code does not allow us to
do this conditionally).

In the worst case, if npm hasn't already been added to its own sysroot
and we are fetching from a source repository rather than an npm
registry, this gets a bit ugly because we end up parsing recipes three
times:
1) recipetool startup, which then fetches the code and determines it's
   a node.js module, finds that npm isn't available and then exits with
   a specific error to tell devtool it needs to build npm
2) when we invoke bitbake -c addto_recipe_sysroot nodejs-native
3) when we re-invoke recipetool

This code is badly in need of refactoring, but now is unfortunately not
the time to do that, so we're going to have to live with this ugliness
for now.

Fixes [YOCTO #10992].

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
 scripts/lib/devtool/__init__.py      | 25 ++++++++++++++-----------
 scripts/lib/devtool/standard.py      |  2 +-
 scripts/lib/recipetool/create.py     | 28 ++++++++++++++++++++++------
 scripts/lib/recipetool/create_npm.py | 20 +++++++++++---------
 4 files changed, 48 insertions(+), 27 deletions(-)

diff --git a/scripts/lib/devtool/__init__.py b/scripts/lib/devtool/__init__.py
index 8c385be..d646b0c 100644
--- a/scripts/lib/devtool/__init__.py
+++ b/scripts/lib/devtool/__init__.py
@@ -261,23 +261,28 @@ def get_bbclassextend_targets(recipefile, pn):
                 targets.append('%s-%s' % (pn, variant))
     return targets
 
-def ensure_npm(config, basepath, fixed_setup=False):
+def ensure_npm(config, basepath, fixed_setup=False, check_exists=True):
     """
     Ensure that npm is available and either build it or show a
     reasonable error message
     """
-    tinfoil = setup_tinfoil(config_only=True, basepath=basepath)
-    try:
-        nativepath = tinfoil.config_data.getVar('STAGING_BINDIR_NATIVE')
-    finally:
-        tinfoil.shutdown()
+    if check_exists:
+        tinfoil = setup_tinfoil(config_only=False, basepath=basepath)
+        try:
+            rd = tinfoil.parse_recipe('nodejs-native')
+            nativepath = rd.getVar('STAGING_BINDIR_NATIVE')
+        finally:
+            tinfoil.shutdown()
+        npmpath = os.path.join(nativepath, 'npm')
+        build_npm = not os.path.exists(npmpath)
+    else:
+        build_npm = True
 
-    npmpath = os.path.join(nativepath, 'npm')
-    if not os.path.exists(npmpath):
+    if build_npm:
         logger.info('Building nodejs-native')
         try:
             exec_build_env_command(config.init_path, basepath,
-                                'bitbake -q nodejs-native', watch=True)
+                                'bitbake -q nodejs-native -c addto_recipe_sysroot', watch=True)
         except bb.process.ExecutionError as e:
             if "Nothing PROVIDES 'nodejs-native'" in e.stdout:
                 if fixed_setup:
@@ -287,5 +292,3 @@ def ensure_npm(config, basepath, fixed_setup=False):
                 raise DevtoolError(msg)
             else:
                 raise
-        if not os.path.exists(npmpath):
-            raise DevtoolError('Built nodejs-native but npm binary still could not be found at %s' % npmpath)
diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index ffca2c9..73e629c 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -165,7 +165,7 @@ def add(args, config, basepath, workspace):
                     # inside recipetool since recipetool keeps tinfoil active
                     # with references to it throughout the code, so we have
                     # to exit out and come back here to do it.
-                    ensure_npm(config, basepath, args.fixed_setup)
+                    ensure_npm(config, basepath, args.fixed_setup, check_exists=False)
                     logger.info('Re-running recipe creation process after building nodejs')
                     continue
                 elif e.exitcode == 15:
diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 648f2d6..439dca0 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -416,12 +416,14 @@ def create_recipe(args):
             srcuri = rev_re.sub('', srcuri)
         tempsrc = tempfile.mkdtemp(prefix='recipetool-')
         srctree = tempsrc
+        d = bb.data.createCopy(tinfoil.config_data)
         if fetchuri.startswith('npm://'):
             # Check if npm is available
-            check_npm(tinfoil.config_data, args.devtool)
+            npm_bindir = check_npm(tinfoil, args.devtool)
+            d.prependVar('PATH', '%s:' % npm_bindir)
         logger.info('Fetching %s...' % srcuri)
         try:
-            checksums = scriptutils.fetch_uri(tinfoil.config_data, fetchuri, srctree, srcrev)
+            checksums = scriptutils.fetch_uri(d, fetchuri, srctree, srcrev)
         except bb.fetch2.BBFetchException as e:
             logger.error(str(e).rstrip())
             sys.exit(1)
@@ -1119,10 +1121,21 @@ def convert_rpm_xml(xmlfile):
     return values
 
 
-def check_npm(d, debugonly=False):
-    if not os.path.exists(os.path.join(d.getVar('STAGING_BINDIR_NATIVE'), 'npm')):
-        log_error_cond('npm required to process specified source, but npm is not available - you need to build nodejs-native first', debugonly)
+def check_npm(tinfoil, debugonly=False):
+    try:
+        rd = tinfoil.parse_recipe('nodejs-native')
+    except bb.providers.NoProvider:
+        # We still conditionally show the message and exit with the special
+        # return code, otherwise we can't show the proper message for eSDK
+        # users
+        log_error_cond('nodejs-native is required for npm but is not available - you will likely need to add a layer that provides nodejs', debugonly)
+        sys.exit(14)
+    bindir = rd.getVar('STAGING_BINDIR_NATIVE')
+    npmpath = os.path.join(bindir, 'npm')
+    if not os.path.exists(npmpath):
+        log_error_cond('npm required to process specified source, but npm is not available - you need to run bitbake -c addto_recipe_sysroot nodejs-native first', debugonly)
         sys.exit(14)
+    return bindir
 
 def register_commands(subparsers):
     parser_create = subparsers.add_parser('create',
@@ -1141,5 +1154,8 @@ def register_commands(subparsers):
     parser_create.add_argument('--keep-temp', action="store_true", help='Keep temporary directory (for debugging)')
     parser_create.add_argument('--fetch-dev', action="store_true", help='For npm, also fetch devDependencies')
     parser_create.add_argument('--devtool', action="store_true", help=argparse.SUPPRESS)
-    parser_create.set_defaults(func=create_recipe)
+    # FIXME I really hate having to set parserecipes for this, but given we may need
+    # to call into npm (and we don't know in advance if we will or not) and in order
+    # to do so we need to know npm's recipe sysroot path, there's not much alternative
+    parser_create.set_defaults(func=create_recipe, parserecipes=True)
 
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index eb19555..a79a9afb 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -65,9 +65,9 @@ class NpmRecipeHandler(RecipeHandler):
                                           'SEE-LICENSE-IN-EULA')
         return license
 
-    def _shrinkwrap(self, srctree, localfilesdir, extravalues, lines_before):
+    def _shrinkwrap(self, srctree, localfilesdir, extravalues, lines_before, d):
         try:
-            runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH'))
+            runenv = dict(os.environ, PATH=d.getVar('PATH'))
             bb.process.run('npm shrinkwrap', cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True)
         except bb.process.ExecutionError as e:
             logger.warn('npm shrinkwrap failed:\n%s' % e.stdout)
@@ -79,8 +79,8 @@ class NpmRecipeHandler(RecipeHandler):
         extravalues['extrafiles']['npm-shrinkwrap.json'] = tmpfile
         lines_before.append('NPM_SHRINKWRAP := "${THISDIR}/${PN}/npm-shrinkwrap.json"')
 
-    def _lockdown(self, srctree, localfilesdir, extravalues, lines_before):
-        runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH'))
+    def _lockdown(self, srctree, localfilesdir, extravalues, lines_before, d):
+        runenv = dict(os.environ, PATH=d.getVar('PATH'))
         if not NpmRecipeHandler.lockdownpath:
             NpmRecipeHandler.lockdownpath = tempfile.mkdtemp('recipetool-npm-lockdown')
             bb.process.run('npm install lockdown --prefix %s' % NpmRecipeHandler.lockdownpath,
@@ -188,7 +188,9 @@ class NpmRecipeHandler(RecipeHandler):
 
         files = RecipeHandler.checkfiles(srctree, ['package.json'])
         if files:
-            check_npm(tinfoil.config_data)
+            d = bb.data.createCopy(tinfoil.config_data)
+            npm_bindir = check_npm(tinfoil)
+            d.prependVar('PATH', '%s:' % npm_bindir)
 
             data = read_package_json(files[0])
             if 'name' in data and 'version' in data:
@@ -203,17 +205,17 @@ class NpmRecipeHandler(RecipeHandler):
 
                 fetchdev = extravalues['fetchdev'] or None
                 deps, optdeps, devdeps = self.get_npm_package_dependencies(data, fetchdev)
-                updated = self._handle_dependencies(tinfoil.config_data, deps, optdeps, devdeps, lines_before, srctree)
+                updated = self._handle_dependencies(d, deps, optdeps, devdeps, lines_before, srctree)
                 if updated:
                     # We need to redo the license stuff
-                    self._replace_license_vars(srctree, lines_before, handled, extravalues, tinfoil.config_data)
+                    self._replace_license_vars(srctree, lines_before, handled, extravalues, d)
 
                 # Shrinkwrap
                 localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm')
-                self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before)
+                self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before, d)
 
                 # Lockdown
-                self._lockdown(srctree, localfilesdir, extravalues, lines_before)
+                self._lockdown(srctree, localfilesdir, extravalues, lines_before, d)
 
                 # Split each npm module out to is own package
                 npmpackages = oe.package.npm_split_package_dirs(srctree)
-- 
2.9.3



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] devtool: add: prevent repeatedly running recipetool
  2017-04-12 10:41 [PATCH 0/4] devtool / recipetool fixes for node.js modules Paul Eggleton
  2017-04-12 10:41 ` [PATCH 1/4] recipetool: create: fix for regression in npm license handling Paul Eggleton
  2017-04-12 10:41 ` [PATCH 2/4] devtool: add: fix node.js/npm handling with recipe specific sysroots Paul Eggleton
@ 2017-04-12 10:41 ` Paul Eggleton
  2017-04-12 10:41 ` [PATCH 4/4] recipetool: create: hide missing npm error when called from devtool Paul Eggleton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Eggleton @ 2017-04-12 10:41 UTC (permalink / raw)
  To: openembedded-core

If recipetool returns with exit code 14 this means devtool needs to
build nodejs-native and then call it again. If recipetool returns exit
code 14 again then clearly something has gone wrong and we should just
quit with an error.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
 scripts/lib/devtool/standard.py | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/scripts/lib/devtool/standard.py b/scripts/lib/devtool/standard.py
index 73e629c..1e84ae4 100644
--- a/scripts/lib/devtool/standard.py
+++ b/scripts/lib/devtool/standard.py
@@ -155,11 +155,14 @@ def add(args, config, basepath, workspace):
 
     tempdir = tempfile.mkdtemp(prefix='devtool')
     try:
+        builtnpm = False
         while True:
             try:
                 stdout, _ = exec_build_env_command(config.init_path, basepath, 'recipetool --color=%s create --devtool -o %s \'%s\' %s' % (color, tempdir, source, extracmdopts), watch=True)
             except bb.process.ExecutionError as e:
                 if e.exitcode == 14:
+                    if builtnpm:
+                        raise DevtoolError('Re-running recipetool still failed to find npm')
                     # FIXME this is a horrible hack that is unfortunately
                     # necessary due to the fact that we can't run bitbake from
                     # inside recipetool since recipetool keeps tinfoil active
@@ -167,6 +170,7 @@ def add(args, config, basepath, workspace):
                     # to exit out and come back here to do it.
                     ensure_npm(config, basepath, args.fixed_setup, check_exists=False)
                     logger.info('Re-running recipe creation process after building nodejs')
+                    builtnpm = True
                     continue
                 elif e.exitcode == 15:
                     raise DevtoolError('Could not auto-determine recipe name, please specify it on the command line')
-- 
2.9.3



^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] recipetool: create: hide missing npm error when called from devtool
  2017-04-12 10:41 [PATCH 0/4] devtool / recipetool fixes for node.js modules Paul Eggleton
                   ` (2 preceding siblings ...)
  2017-04-12 10:41 ` [PATCH 3/4] devtool: add: prevent repeatedly running recipetool Paul Eggleton
@ 2017-04-12 10:41 ` Paul Eggleton
  3 siblings, 0 replies; 5+ messages in thread
From: Paul Eggleton @ 2017-04-12 10:41 UTC (permalink / raw)
  To: openembedded-core

If devtool is called with a URL to a source repository containing a
node.js module, we don't know that until recipetool has fetched it, and
due to the structure of the code we have to exit with a special code in
order to let devtool know it needs to build nodejs-native. We also want
to suppress the error message that recipetool would normally print under
these circumstances; there is already a mechanism for this but it wasn't
operative in the case where we're pointed to a source repository rather
than an npm:// URL, so create some plumbing so that we know to hide the
message.

Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
---
 scripts/lib/recipetool/create.py     | 4 ++++
 scripts/lib/recipetool/create_npm.py | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/scripts/lib/recipetool/create.py b/scripts/lib/recipetool/create.py
index 439dca0..5af58a1 100644
--- a/scripts/lib/recipetool/create.py
+++ b/scripts/lib/recipetool/create.py
@@ -59,6 +59,9 @@ class RecipeHandler(object):
     recipecmakefilemap = {}
     recipebinmap = {}
 
+    def __init__(self):
+        self._devtool = False
+
     @staticmethod
     def load_libmap(d):
         '''Load library->recipe mapping'''
@@ -622,6 +625,7 @@ def create_recipe(args):
     handlers.sort(key=lambda item: (item[1], -item[2]), reverse=True)
     for handler, priority, _ in handlers:
         logger.debug('Handler: %s (priority %d)' % (handler.__class__.__name__, priority))
+        setattr(handler, '_devtool', args.devtool)
     handlers = [item[0] for item in handlers]
 
     # Apply the handlers
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py
index a79a9afb..cb8f338 100644
--- a/scripts/lib/recipetool/create_npm.py
+++ b/scripts/lib/recipetool/create_npm.py
@@ -189,7 +189,7 @@ class NpmRecipeHandler(RecipeHandler):
         files = RecipeHandler.checkfiles(srctree, ['package.json'])
         if files:
             d = bb.data.createCopy(tinfoil.config_data)
-            npm_bindir = check_npm(tinfoil)
+            npm_bindir = check_npm(tinfoil, self._devtool)
             d.prependVar('PATH', '%s:' % npm_bindir)
 
             data = read_package_json(files[0])
-- 
2.9.3



^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-04-12 10:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-12 10:41 [PATCH 0/4] devtool / recipetool fixes for node.js modules Paul Eggleton
2017-04-12 10:41 ` [PATCH 1/4] recipetool: create: fix for regression in npm license handling Paul Eggleton
2017-04-12 10:41 ` [PATCH 2/4] devtool: add: fix node.js/npm handling with recipe specific sysroots Paul Eggleton
2017-04-12 10:41 ` [PATCH 3/4] devtool: add: prevent repeatedly running recipetool Paul Eggleton
2017-04-12 10:41 ` [PATCH 4/4] recipetool: create: hide missing npm error when called from devtool Paul Eggleton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.