-
-
Notifications
You must be signed in to change notification settings - Fork 197
remove npm2 dependency #2209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
remove npm2 dependency #2209
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ef2fcbc
remove npm2 dependency + fixes after reviews
Plamen5kov f2b53a4
always save to dependencies on platform add
Plamen5kov 8d0fb1e
comment out tests, so CI runs
Plamen5kov 3832925
fixed broken test
Plamen5kov 5763a53
updated submodule
Plamen5kov fd15624
fix ios-debug after merge
Plamen5kov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
import Future = require("fibers/future"); | ||
import * as npm from "npm"; | ||
import * as path from "path"; | ||
|
||
interface INpmOpts { | ||
config?: any; | ||
|
@@ -8,35 +7,13 @@ interface INpmOpts { | |
} | ||
|
||
export class NodePackageManager implements INodePackageManager { | ||
constructor(private $childProcess: IChildProcess, | ||
constructor(private $fs: IFileSystem, | ||
private $hostInfo: IHostInfo, | ||
private $errors: IErrors, | ||
private $childProcess: IChildProcess, | ||
private $logger: ILogger, | ||
private $options: IOptions) { } | ||
|
||
public getCache(): string { | ||
return npm.cache; | ||
} | ||
|
||
public load(config?: any): IFuture<void> { | ||
if (npm.config.loaded) { | ||
let data = npm.config.sources.cli.data; | ||
Object.keys(data).forEach(k => delete data[k]); | ||
if (config) { | ||
_.assign(data, config); | ||
} | ||
return Future.fromResult(); | ||
} else { | ||
let future = new Future<void>(); | ||
npm.load(config, (err: Error) => { | ||
if (err) { | ||
future.throw(err); | ||
} else { | ||
future.return(); | ||
} | ||
}); | ||
return future; | ||
} | ||
} | ||
|
||
public install(packageName: string, pathToSave: string, config?: any): IFuture<any> { | ||
return (() => { | ||
if (this.$options.disableNpmInstall) { | ||
|
@@ -47,100 +24,105 @@ export class NodePackageManager implements INodePackageManager { | |
config["ignore-scripts"] = true; | ||
} | ||
|
||
let jsonContentBefore = this.$fs.readJson(path.join(pathToSave, "package.json")).wait(); | ||
// let dependenciesBefore: Array<string> = []; | ||
let dependenciesBefore = _.keys(jsonContentBefore.dependencies).concat(_.keys(jsonContentBefore.devDependencies)); | ||
|
||
let flags = this.getFlagsString(config, true); | ||
let params = ["install"]; | ||
if(packageName !== pathToSave) { | ||
params.push(packageName); //because npm install ${pwd} on mac tries to install itself as a dependency (windows and linux have no such issues) | ||
} | ||
params = params.concat(flags); | ||
try { | ||
return this.loadAndExecute("install", [pathToSave, packageName], { config: config }).wait(); | ||
this.$childProcess.spawnFromEvent(this.getNpmExecutableName(), params, "close", { cwd: pathToSave }).wait(); | ||
} catch (err) { | ||
if (err.code === "EPEERINVALID") { | ||
if (err.message && err.message.indexOf("EPEERINVALID") !== -1) { | ||
// Not installed peer dependencies are treated by npm 2 as errors, but npm 3 treats them as warnings. | ||
// We'll show them as warnings and let the user install them in case they are needed. | ||
// The strucutre of the error object in such case is: | ||
// { [Error: The package @angular/[email protected] does not satisfy its siblings' peerDependencies requirements!] | ||
// code: 'EPEERINVALID', | ||
// packageName: '@angular/core', | ||
// packageVersion: '2.1.0-beta.0', | ||
// peersDepending: | ||
// { '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@angular/[email protected]': '2.1.0-beta.0', | ||
// '@ngrx/[email protected]': '^2.0.0', | ||
// '@ngrx/[email protected]': '^2.0.0', | ||
// '[email protected]': '~2.0.0' } } | ||
this.$logger.warn(err.message); | ||
this.$logger.trace("Required peerDependencies are: ", err.peersDepending); | ||
} else { | ||
// All other errors should be handled by the caller code. | ||
throw err; | ||
} | ||
} | ||
|
||
let jsonContentAfter = this.$fs.readJson(path.join(pathToSave, "package.json")).wait(); | ||
let dependenciesAfter = _.keys(jsonContentAfter.dependencies).concat(_.keys(jsonContentAfter.devDependencies)); | ||
|
||
/** This diff is done in case the installed pakcage is a URL address, a path to local directory or a .tgz file | ||
* in these cases we don't have the package name and we can't rely on "npm install --json"" option | ||
* to get the project name because we have to parse the output from the stdout and we have no controll over it (so other messages may be mangled in stdout) | ||
* The solution is to compare package.json project dependencies before and after install and get the name of the installed package, | ||
* even if it's installed through local path or URL. If command installes more than one package, only the package originally installed is returned. | ||
*/ | ||
let dependencyDiff = _(jsonContentAfter.dependencies) | ||
.omitBy((val: string, key: string) => jsonContentBefore && jsonContentBefore.dependencies && jsonContentBefore.dependencies[key] && jsonContentBefore.dependencies[key] === val) | ||
.keys() | ||
.value(); | ||
|
||
let devDependencyDiff = _(jsonContentAfter.devDependencies) | ||
.omitBy((val: string, key: string) => jsonContentBefore && jsonContentBefore.devDependencies && jsonContentBefore.devDependencies[key] && jsonContentBefore.devDependencies[key] === val) | ||
.keys() | ||
.value(); | ||
|
||
let diff = dependencyDiff.concat(devDependencyDiff); | ||
|
||
if(diff.length <= 0 && dependenciesBefore.length === dependenciesAfter.length && packageName !== pathToSave) { | ||
this.$errors.failWithoutHelp(`The plugin ${packageName} is already installed`); | ||
} | ||
if(diff.length <= 0 && dependenciesBefore.length !== dependenciesAfter.length) { | ||
this.$errors.failWithoutHelp(`Couldn't install package correctly`); | ||
} | ||
|
||
return diff; | ||
}).future<any>()(); | ||
} | ||
|
||
public uninstall(packageName: string, config?: any, path?: string): IFuture<any> { | ||
return this.loadAndExecute("uninstall", [[packageName]], { config, path }); | ||
let flags = this.getFlagsString(config, false); | ||
return this.$childProcess.exec(`npm uninstall ${packageName} ${flags}`, { cwd: path }); | ||
} | ||
|
||
public search(filter: string[], silent: boolean): IFuture<any> { | ||
let args = (<any[]>([filter] || [])).concat(silent); | ||
return this.loadAndExecute("search", args); | ||
public search(filter: string[], config: any): IFuture<any> { | ||
let args = (<any[]>([filter] || [])).concat(config.silent); | ||
return this.$childProcess.exec(`npm search ${args.join(" ")}`); | ||
} | ||
|
||
public cache(packageName: string, version: string, config?: any): IFuture<IDependencyData> { | ||
// function cache (pkg, ver, where, scrub, cb) | ||
return this.loadAndExecute("cache", [packageName, version, undefined, false], { subCommandName: "add", config: config }); | ||
} | ||
|
||
public cacheUnpack(packageName: string, version: string, unpackTarget?: string): IFuture<void> { | ||
// function unpack (pkg, ver, unpackTarget, dMode, fMode, uid, gid, cb) | ||
return this.loadAndExecute("cache", [packageName, version, unpackTarget, null, null, null, null], { subCommandName: "unpack" }); | ||
public view(packageName: string, config: any): IFuture<any> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method should return future, you should wrap the code in: return (() => {
}).future<any>()(); |
||
return (() => { | ||
let flags = this.getFlagsString(config, false); | ||
let viewResult = this.$childProcess.exec(`npm view ${packageName} ${flags}`).wait(); | ||
return JSON.parse(viewResult); | ||
}).future<any>()(); | ||
} | ||
|
||
public view(packageName: string, propertyName: string): IFuture<any> { | ||
return this.loadAndExecute("view", [[packageName, propertyName], [false]]); | ||
} | ||
private getNpmExecutableName(): string { | ||
let npmExecutableName = "npm"; | ||
|
||
public executeNpmCommand(npmCommandName: string, currentWorkingDirectory: string): IFuture<any> { | ||
return this.$childProcess.exec(npmCommandName, { cwd: currentWorkingDirectory }); | ||
} | ||
if (this.$hostInfo.isWindows) { | ||
npmExecutableName += ".cmd"; | ||
} | ||
|
||
private loadAndExecute(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> { | ||
return (() => { | ||
opts = opts || {}; | ||
this.load(opts.config).wait(); | ||
return this.executeCore(commandName, args, opts).wait(); | ||
}).future<any>()(); | ||
return npmExecutableName; | ||
} | ||
|
||
private executeCore(commandName: string, args: any[], opts?: INpmOpts): IFuture<any> { | ||
let future = new Future<any>(); | ||
let oldNpmPath: string = undefined; | ||
let callback = (err: Error, data: any) => { | ||
if (oldNpmPath) { | ||
(<any>npm).prefix = oldNpmPath; | ||
} | ||
|
||
if (err) { | ||
future.throw(err); | ||
} else { | ||
future.return(data); | ||
private getFlagsString(config: any, asArray: boolean) : any{ | ||
let array:Array<string> = []; | ||
for(let flag in config) { | ||
if(config[flag]) { | ||
if(flag==="dist-tags" || flag==="versions") { | ||
array.push(` ${flag}`); | ||
continue; | ||
} | ||
array.push(`--${flag}`); | ||
} | ||
}; | ||
args.push(callback); | ||
|
||
if (opts && opts.path) { | ||
oldNpmPath = npm.prefix; | ||
(<any>npm).prefix = opts.path; | ||
} | ||
if(asArray) { | ||
return array; | ||
} | ||
|
||
let subCommandName: string = opts.subCommandName; | ||
let command = subCommandName ? npm.commands[commandName][subCommandName] : npm.commands[commandName]; | ||
command.apply(this, args); | ||
|
||
return future; | ||
return array.join(" "); | ||
} | ||
} | ||
$injector.register("npm", NodePackageManager); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case
npm install
fails with EPEERINVALID error, the method will show it as warning and will skip all of the checks regarding jsonContentBefore and jsonContentAfter. Also the method will not return anything. Is this expected?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not, I'll fix it