Skip to content

Commit

Permalink
feat(bootstrap): Short-circuit when local file: specifiers are detect…
Browse files Browse the repository at this point in the history
…ed in the root
  • Loading branch information
evocateur committed Mar 28, 2018
1 parent fd8c391 commit d8a8f03
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
registry = https://registry.npmjs.org/
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"version": "1.0.0"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "relative-file-specs",
"description": "file: specifiers in dependencies should trigger root-only bootstrap",
"private": true,
"version": "0.0.0-lerna",
"dependencies": {
"package-2": "file:packages/package-2"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "package-1",
"version": "1.0.0",
"changed": false,
"dependencies": {
"tiny-tarball": "^1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "package-2",
"version": "1.0.0",
"dependencies": {
"package-1": "file:../package-1"
}
}
17 changes: 17 additions & 0 deletions commands/bootstrap/__tests__/bootstrap-command.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,23 @@ describe("BootstrapCommand", () => {
});
});

describe("with relative file: specifiers in root dependencies", () => {
it("only installs in the root", async () => {
const testDir = await initFixture("relative-file-specs");

await lernaBootstrap(testDir)();

expect(npmInstall.dependencies).not.toBeCalled();
expect(npmInstall).lastCalledWith(
expect.objectContaining({ name: "relative-file-specs" }),
expect.objectContaining({
npmClient: "npm",
stdio: "inherit",
})
);
});
});

describe("with duplicate package names", () => {
it("throws an error", async () => {
expect.assertions(1);
Expand Down
19 changes: 18 additions & 1 deletion commands/bootstrap/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const dedent = require("dedent");
const getPort = require("get-port");
const npa = require("npm-package-arg");
const path = require("path");
const pFinally = require("p-finally");
const pMap = require("p-map");
Expand Down Expand Up @@ -86,7 +87,7 @@ class BootstrapCommand extends Command {
}

execute() {
if (this.options.useWorkspaces) {
if (this.options.useWorkspaces || this.rootHasLocalFileDependencies()) {
return this.installRootPackageOnly();
}

Expand Down Expand Up @@ -124,6 +125,22 @@ class BootstrapCommand extends Command {
return npmInstall(this.project.package, this.npmConfig);
}

/**
* If the root manifest has local dependencies with `file:` specifiers,
* all the complicated bootstrap logic should be skipped in favor of
* npm5's package-locked auto-hoisting.
* @returns {Boolean}
*/
rootHasLocalFileDependencies() {
const rootDependencies = Object.assign({}, this.project.package.dependencies);

return Object.keys(rootDependencies).some(
name =>
this.packageGraph.has(name) &&
npa.resolve(name, rootDependencies[name], this.project.rootPath).type === "directory"
);
}

runLifecycleInPackages(stage) {
this.logger.verbose("lifecycle", stage);

Expand Down
1 change: 1 addition & 0 deletions commands/bootstrap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"dedent": "^0.7.0",
"get-port": "^3.2.0",
"multimatch": "^2.1.0",
"npm-package-arg": "^6.0.0",
"npmlog": "^4.1.2",
"p-finally": "^1.0.0",
"p-map": "^1.2.0",
Expand Down
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d8a8f03

Please sign in to comment.