NativeScript / nativescript-cli

Command-line interface for building NativeScript apps
https://www.npmjs.com/package/nativescript
Apache License 2.0
1.04k stars 195 forks source link

[npm5] Local dependency brakes build #3028

Closed dtopuzov closed 5 years ago

dtopuzov commented 7 years ago

From @surdu on August 1, 2017 7:57

After upgrading nativescript to 3.1.3 I have the following error in my project when I try to build:

Unable to apply changes on device: <device-id>. Error is: cp: cannot create directory 
'/Users/<user>/work/<project>/platforms/android/src/main/assets/app/tns_modules': No such 
file or directory.

Did a little investigation and realized the problem is a local dependency in my package JSON:

nativescript-local-notifications": "file:../nativescript-local-notifications"

Taking this out make the app build again.

The weird part is that's not the only local dependency in my project, I have another that doesn't brakes the build.

I can confirm the problem is only in 3.1.3 because I reverted back to 3.1.2 (twice) and the problem is not reproducible using that version.

For context, here is the full dependencies entry:

  "dependencies": {
    "moment": "^2.18.1",
    "nativescript-activity-detection": "file:../nativescript-activity-detection",
    "nativescript-android-utils": "^1.0.2",
    "nativescript-geolocation": "^3.0.0",
    "nativescript-local-notifications": "file:../nativescript-local-notifications",
    "nativescript-theme-core": "~1.0.2",
    "nativescript-webview-interface": "^1.4.1",
    "tns-core-modules": "^3.1.0"
  }

Copied from original issue: NativeScript/NativeScript#4634

dtopuzov commented 7 years ago

From @tsonevn on August 1, 2017 10:54

Hi @surdu, I tested your case on my side while using latest NativeScript CLI and local tgz file for the plugin, however, I was unable to reproduce this scenario. I am attaching my sample project together with the plugin. Could you provide some info about the Android device, which you are using for testing? Also, could you check if in the main app folder of the project there is tns_modules folder? If so this could be the reason for this problem and you should delete it. Then you will be able to build the project successfully. Archive.zip

dtopuzov commented 7 years ago

Hi @surdu,

Can you please specify version of node and npm on your machine? npm5 handle dependencies to folder is a bit different way, so I can suggest you flowing:

surdu commented 7 years ago

@dtopuzov Sorry for the late response.

Yes, that was the problem: I had npm v5.

Downgraded to npm 4, removed node_modules and platform, rebuild and now it works.

I'll leave at your latitude to decide if this is a bug worth tracking. Please close the issue if you see fit.

dtopuzov commented 7 years ago

The problem is that we call npm install on the project and npm install fails in this case. Using local packages from tgz files should be ok with npm5.

We will leave it open for now and see if we can do something, but if there is no good way to workaround this npm5 behavior we will close the issue.

rosen-vladimirov commented 7 years ago

Hey @surdu , may I ask you for more details on your case. I've tried to reproduce the issue, but without success. Can you send us the following information:

In case you can send us a sample project, reproducing the issue, it will be a great help for us.

surdu commented 7 years ago

@rosen-vladimirov

node: v7.7.2 npm: 5.3.0

TestDep.zip

Hope it helps!

rosen-vladimirov commented 7 years ago

Hey @surdu , Many thanks for the sample project. I've investigated the issue and it turns out to be a problem in shelljs module that we are using. The problem arise when you have a symlink to a read-only file. When npm 5 is used, it automatically creates a symlink in node_modules. In your plugin directory, there is .git dir and the files inside it are read-only (there are only read permissions). In this case, when CLI tries to copy files from node_modules of the project to the platforms/<platform>/... directory, it finds out the symlink for the local plugin and tries to follow it and copy the resources. When it gets to the .git dir, the code of shelljs fails, but it hides the real error, which is Error: cp: copyFileSync: could not write to dest file (code=EACCES):/Users/vladimirov/Work/nativescript-cli/scratch/TestDep/TestDep/platforms/ios/TestDep/app/tns_modules/nativescript-local-notifications/.git/objects/0d/945103b4c28575e55e510792d3b3877b97e019

Here's the issue in shelljs https://github.com/shelljs/shelljs/issues/98

Another way to reproduce it is to execute the following:

$ tns create myApp
$ cd myApp/app
$ touch a.js
$ chmod 0444 a.js
$ ln -s a.js b.js
$ tns run ios
stop the process with ctrl + c
make a change in js file
$ tns run ios

And you'll see error: cp: copyFileSync: could not write to dest file (code=EACCES):/Users/vladimirov/Library/Developer/CoreSimulator/Devices/6DE793B1-13CF-4D0C-BB6E-C7D6CDECCAFD/data/Containers/Bundle/Application/D39CAAF7-5814-4177-91DE-DED45CE3B1FA/app54.app/app/a.js.

For the moment, I would suggest you to use the local plugin from .tgz or remove the .git repository from the plugin when building your project.

Once again, thank you for the sample project.

surdu commented 7 years ago

No problem ;)

Make sense why it's working with npm 4: it copies the contents of the plugin in node_modules on npm link, and it either not copies the .git folder or it copies it with different permissions.

As I actively work on a number of plugins, for now I prefer do downgrade to npm 4 instead of the .tgz idea. Hopefully, this will be fixed soon.

manijak commented 7 years ago

I have the same issue with my local plugins. Will have to downgrade to npm4 since both plugins are being worked on with the app itself.

drice commented 7 years ago

Thanks @rosen-vladimirov, I was struggling with this issue as well. I chmod-ed the .git folder and was able to build successfully 👍

usernameisMan commented 6 years ago

yes , I delete node_module ,npm version 5 => 4 。 then npm install 。 build success

paulpv commented 6 years ago

Any 5.x solution for this?

BeMor81 commented 6 years ago

Hi, any solution for this on 5 yet?

Use npm pack command within your module's folder to create your compressed package file. Hope this helps someone new to the platform like myself.

NathanaelA commented 6 years ago

For those interested; the best solution to this issue is to move to the new plugin structure that I detail in the video that Nathan Walker, Brad Martin and myself did back for the NS Dev Days; https://youtu.be/n9nXy7Q9RbI?t=4179 -- This should link you right to where I discuss the plugin layouts in the video.

I detail out why we need to change to a new structure. Interestingly enough, I found out a couple days ago the newer version of the plugin seed also use the same structure I proposed. And Paul (thanks!) has updated the plugin documentation already https://github.com/NativeScript/docs/pull/1065 outlining the new structure so it co-insides with the official seed and explains some of the reasons.

Using (& converting old plugins to ) the new layout totally solves this issue and the related npm 5 recursion issue, and gives you the benefit of faster plugin development.

speigg commented 6 years ago

^ Gosh, moving all of the plugin source into a src subdirectory worked. This solution was painfully difficult to find. It seems my issue was exactly as @rosen-vladimirov described ( a read-only .git folder making nativescript-cli go crazy ).

In this case, when CLI tries to copy files from node_modules of the project to the platforms//... directory, it finds out the symlink for the local plugin and tries to follow it and copy the resources.

How about a simple solution so no-one has to go through this headache again: can the CLI just change the read/write permissions on the files it copies into the platforms folder? Would that work?

Edit: Nevermind, it seems the issue in shelljs has been fixed recently. Updating that would be the proper solution I suppose.

NathanaelA commented 6 years ago

@speigg - Well, depending on your structure it might work; however it would slow down building as when it is copying the plugin, it would then have to check to see if their is a .git folder present after the copy (i.e. meaning another directory scan of the destination folders and all file names) and then chmod it.

However, if your structure of your plugin is like most plugins from NS 1 & 2 days, (i.e. source in root folder, rather than in a src folder) you will run into the risk of the recursion issue. Hence the subfolder "src" solves both issues at the same time and is fairly simple to do.

speigg commented 6 years ago

Yeah, I like how much easier the plugin development is now. It was just a pain figuring out why updating npm broke everything.