From c3f799808ce584937b5b0122bb54cdef01fe3725 Mon Sep 17 00:00:00 2001 From: Daniel Stockman Date: Fri, 19 Jul 2019 13:34:28 -0700 Subject: [PATCH] fix(create-symlink): Generate shims for missing bin scripts for Windows --- .../__tests__/create-symlink.test.js | 30 +++++++++++++++++++ utils/create-symlink/create-symlink.js | 21 ++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/utils/create-symlink/__tests__/create-symlink.test.js b/utils/create-symlink/__tests__/create-symlink.test.js index 928d278521..6c9ec04126 100644 --- a/utils/create-symlink/__tests__/create-symlink.test.js +++ b/utils/create-symlink/__tests__/create-symlink.test.js @@ -15,6 +15,8 @@ describe("create-symlink", () => { fs.unlink.mockResolvedValue(); fs.symlink.mockResolvedValue(); fs.pathExists.mockResolvedValue(true); + fs.outputFile.mockResolvedValue(); + fs.remove.mockResolvedValue(); cmdShim.mockResolvedValue(); if (process.platform !== "win32") { @@ -86,5 +88,33 @@ describe("create-symlink", () => { expect(fs.unlink).toHaveBeenLastCalledWith(dst); expect(fs.symlink).toHaveBeenLastCalledWith(src, dst, type); }); + + it("creates stub symlink to executable that doesn't exist yet", async () => { + const src = path.resolve("./packages/package-3/cli.js"); + const dst = path.resolve("./packages/package-1/node_modules/.bin/package-3"); + const type = "exec"; + + fs.pathExists.mockResolvedValueOnce(false); + + await createSymlink(src, dst, type); + + expect(fs.outputFile).toHaveBeenLastCalledWith(src, ""); + expect(cmdShim).toHaveBeenLastCalledWith(src, dst); + expect(fs.remove).toHaveBeenLastCalledWith(src); + }); + + it("does not swallow cmd-shim errors when executable doesn't exist yet", async () => { + cmdShim.mockImplementationOnce(() => Promise.reject(new Error("oh no"))); + fs.pathExists.mockResolvedValueOnce(false); + + try { + await createSymlink("src", "dst", "exec"); + } catch (err) { + expect(err.message).toBe("oh no"); + expect(fs.remove).toHaveBeenLastCalledWith("src"); + } + + expect.hasAssertions(); + }); } }); diff --git a/utils/create-symlink/create-symlink.js b/utils/create-symlink/create-symlink.js index 3615373dd1..dce3bf5c31 100644 --- a/utils/create-symlink/create-symlink.js +++ b/utils/create-symlink/create-symlink.js @@ -50,7 +50,26 @@ function createPosixSymlink(src, dest, _type) { function createWindowsSymlink(src, dest, type) { if (type === "exec") { - return cmdShim(src, dest); + // If the src exists, shim directly. + // If the src doesn't exist yet, create a temp src so cmd-shim doesn't explode. + return fs.pathExists(src).then(exists => { + if (exists) { + return cmdShim(src, dest); + } + + return fs + .outputFile(src, "") + .then(() => cmdShim(src, dest)) + .then( + // fs.remove() never rejects + () => fs.remove(src), + err => + fs.remove(src).then(() => { + // clean up, but don't swallow error + throw err; + }) + ); + }); } return createSymbolicLink(src, dest, type);