Cannot add plugin to a Cordova project in a subdirectory of the plugin
Bug Report
Problem
What is expected to happen?
Some plugins may include an example app project (demonstrating the plugin functionality) in a subdirectory of their repository. It should be possible to add the plugin to such an example app project using a local path.
|--- myPlugin/
| |--- exampleApp/ (uses myPlugin)
$ cd exampleApp
$ cordova plugin add ..
What does actually happen?
When adding a plugin to a Cordova project located in a subdirectory of the plugin to be installed, Cordova CLI exits with an error.
Information
This issue might be related to the fact that npm install creates symlinks when installing a local package. Cordova may attempt to copy the symlink to the plugin to a subdirectory of the plugin (using ShellJS), resulting in endless recursion.
Command or Code
$ plugman create --name myPlugin --plugin_id my.plugin.id --plugin_version 0.1.0
$ cd myPlugin
$ plugman createpackagejson .
# ... confirm interactive prompt ...
$ mkdir exampleApp
$ cd exampleApp
$ cordova create .
$ cordova plugin add ..
shell.js: internal error
Error: ENAMETOOLONG: name too long, lstat '/private/tmp/myPlugin/exampleApp/node_modules/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp'
at Object.fs.lstatSync (fs.js:965:11)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:69:26)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
at cpdirSyncRecursive (/Users/cpetrov/.nvm/versions/node/v9.7.1/lib/node_modules/cordova/node_modules/cordova-lib/node_modules/shelljs/src/cp.js:73:7)
Version information
macOS 10.14 Cordova CLI 8.1.2 ([email protected]) npm 6.4.1 Node.js v9.7.1 Plugman 2.0.0
Checklist
- [x] I searched for existing GitHub issues
- [x] I updated all Cordova tooling to most recent version
- [x] I included all the necessary information above
/private/tmp/myPlugin/exampleApp/node_modules/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp/plugins/my.plugin.id/exampleApp
Well, that doesn't look to good. Thanks for reporting!
Basically the same with Cordova 9 after the switch to fs-extra:
Error: ELOOP: too many symbolic links encountered, stat '/tmp/tmp.PFZp1QUusU/myPlugin/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id/exampleApp/node_modules/my.plugin.id'
After giving this some thought, I have to say this scenario is a very special case and quite tricky at that. It would certainly be nice if it would just work, but I would not make it a priority either.
If you are interested in contributing something that either fixes this or detects the situation and throws an error with a meaningful message that the operation is not supported, then you are very welcome to do so. Here's the line that throws the error.
There are workarounds for the initial creation:
- Create example app somewhere else, then copy to plugin dir
- Use
cordova plugin add .. --link
The problem is, that commands like cordova prepare will still fail with the resulting project.
The bug might have been caused by this PR: https://github.com/apache/cordova-lib/pull/705. If I remove the dereference option from the call to fs.copySync, the installation finishes normally, since the symlink is simply copied, not dereferenced.