mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-18 22:02:53 -04:00
6
.changeset/moody-cows-invite.md
Normal file
6
.changeset/moody-cows-invite.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/link-bins": patch
|
||||||
|
"pnpm": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Deduplicate bin names to prevent race condition and corrupted bin scripts [#7833](https://github.com/pnpm/pnpm/issues/7833).
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"p-settle": "^4.1.1",
|
"p-settle": "^4.1.1",
|
||||||
"ramda": "npm:@pnpm/ramda@0.28.1",
|
"ramda": "npm:@pnpm/ramda@0.28.1",
|
||||||
|
"semver": "^7.6.0",
|
||||||
"symlink-dir": "^6.0.0"
|
"symlink-dir": "^6.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
"@types/node": "^18.19.32",
|
"@types/node": "^18.19.32",
|
||||||
"@types/normalize-path": "^3.0.2",
|
"@types/normalize-path": "^3.0.2",
|
||||||
"@types/ramda": "0.29.12",
|
"@types/ramda": "0.29.12",
|
||||||
|
"@types/semver": "7.5.3",
|
||||||
"cmd-extension": "^1.0.2",
|
"cmd-extension": "^1.0.2",
|
||||||
"path-exists": "^4.0.0",
|
"path-exists": "^4.0.0",
|
||||||
"tempy": "^1.0.1"
|
"tempy": "^1.0.1"
|
||||||
|
|||||||
@@ -15,10 +15,11 @@ import isSubdir from 'is-subdir'
|
|||||||
import isWindows from 'is-windows'
|
import isWindows from 'is-windows'
|
||||||
import normalizePath from 'normalize-path'
|
import normalizePath from 'normalize-path'
|
||||||
import pSettle from 'p-settle'
|
import pSettle from 'p-settle'
|
||||||
import { type KeyValuePair } from 'ramda'
|
|
||||||
import isEmpty from 'ramda/src/isEmpty'
|
import isEmpty from 'ramda/src/isEmpty'
|
||||||
import unnest from 'ramda/src/unnest'
|
import unnest from 'ramda/src/unnest'
|
||||||
|
import groupBy from 'ramda/src/groupBy'
|
||||||
import partition from 'ramda/src/partition'
|
import partition from 'ramda/src/partition'
|
||||||
|
import semver from 'semver'
|
||||||
import symlinkDir from 'symlink-dir'
|
import symlinkDir from 'symlink-dir'
|
||||||
import fixBin from 'bin-links/lib/fix-bin'
|
import fixBin from 'bin-links/lib/fix-bin'
|
||||||
|
|
||||||
@@ -124,6 +125,7 @@ export async function linkBinsOfPackages (
|
|||||||
interface CommandInfo extends Command {
|
interface CommandInfo extends Command {
|
||||||
ownName: boolean
|
ownName: boolean
|
||||||
pkgName: string
|
pkgName: string
|
||||||
|
pkgVersion: string
|
||||||
makePowerShellShim: boolean
|
makePowerShellShim: boolean
|
||||||
nodeExecPath?: string
|
nodeExecPath?: string
|
||||||
}
|
}
|
||||||
@@ -135,29 +137,15 @@ async function _linkBins (
|
|||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
if (allCmds.length === 0) return [] as string[]
|
if (allCmds.length === 0) return [] as string[]
|
||||||
|
|
||||||
|
// deduplicate bin names to prevent race conditions (multiple writers for the same file)
|
||||||
|
allCmds = deduplicateCommands(allCmds, binsDir)
|
||||||
|
|
||||||
await fs.mkdir(binsDir, { recursive: true })
|
await fs.mkdir(binsDir, { recursive: true })
|
||||||
|
|
||||||
const [cmdsWithOwnName, cmdsWithOtherNames] = partition(({ ownName }) => ownName, allCmds)
|
const results = await pSettle(allCmds.map(async cmd => linkBin(cmd, binsDir, opts)))
|
||||||
|
|
||||||
const results1 = await pSettle(cmdsWithOwnName.map(async (cmd) => linkBin(cmd, binsDir, opts)))
|
|
||||||
|
|
||||||
const usedNames = Object.fromEntries(cmdsWithOwnName.map((cmd) => [cmd.name, cmd.name] as KeyValuePair<string, string>))
|
|
||||||
const results2 = await pSettle(cmdsWithOtherNames.map(async (cmd) => {
|
|
||||||
if (usedNames[cmd.name]) {
|
|
||||||
binsConflictLogger.debug({
|
|
||||||
binaryName: cmd.name,
|
|
||||||
binsDir,
|
|
||||||
linkedPkgName: usedNames[cmd.name],
|
|
||||||
skippedPkgName: cmd.pkgName,
|
|
||||||
})
|
|
||||||
return Promise.resolve(undefined)
|
|
||||||
}
|
|
||||||
usedNames[cmd.name] = cmd.pkgName
|
|
||||||
return linkBin(cmd, binsDir, opts)
|
|
||||||
}))
|
|
||||||
|
|
||||||
// We want to create all commands that we can create before throwing an exception
|
// We want to create all commands that we can create before throwing an exception
|
||||||
for (const result of [...results1, ...results2]) {
|
for (const result of results) {
|
||||||
if (result.isRejected) {
|
if (result.isRejected) {
|
||||||
throw result.reason
|
throw result.reason
|
||||||
}
|
}
|
||||||
@@ -166,6 +154,39 @@ async function _linkBins (
|
|||||||
return allCmds.map(cmd => cmd.pkgName)
|
return allCmds.map(cmd => cmd.pkgName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deduplicateCommands (commands: CommandInfo[], binsDir: string): CommandInfo[] {
|
||||||
|
const cmdGroups = groupBy(cmd => cmd.name, commands)
|
||||||
|
return Object.values(cmdGroups)
|
||||||
|
.filter((group): group is CommandInfo[] => group !== undefined && group.length !== 0)
|
||||||
|
.map(group => resolveCommandConflicts(group, binsDir))
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveCommandConflicts (group: CommandInfo[], binsDir: string): CommandInfo {
|
||||||
|
return group.reduce((a, b) => {
|
||||||
|
const [chosen, skipped] = compareCommandsInConflict(a, b) >= 0 ? [a, b] : [b, a]
|
||||||
|
logCommandConflict(chosen, skipped, binsDir)
|
||||||
|
return chosen
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function compareCommandsInConflict (a: CommandInfo, b: CommandInfo): number {
|
||||||
|
if (a.ownName && !b.ownName) return 1
|
||||||
|
if (!a.ownName && b.ownName) return -1
|
||||||
|
if (a.pkgName !== b.pkgName) return a.pkgName.localeCompare(b.pkgName) // it's pointless to compare versions of 2 different package
|
||||||
|
return semver.compare(a.pkgVersion, b.pkgVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
function logCommandConflict (chosen: CommandInfo, skipped: CommandInfo, binsDir: string): void {
|
||||||
|
binsConflictLogger.debug({
|
||||||
|
binaryName: skipped.name,
|
||||||
|
binsDir,
|
||||||
|
linkedPkgName: chosen.pkgName,
|
||||||
|
linkedPkgVersion: chosen.pkgVersion,
|
||||||
|
skippedPkgName: skipped.pkgName,
|
||||||
|
skippedPkgVersion: skipped.pkgVersion,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
async function isFromModules (filename: string): Promise<boolean> {
|
async function isFromModules (filename: string): Promise<boolean> {
|
||||||
const real = await fs.realpath(filename)
|
const real = await fs.realpath(filename)
|
||||||
return normalizePath(real).includes('/node_modules/')
|
return normalizePath(real).includes('/node_modules/')
|
||||||
@@ -206,6 +227,7 @@ async function getPackageBinsFromManifest (manifest: DependencyManifest, pkgDir:
|
|||||||
...cmd,
|
...cmd,
|
||||||
ownName: cmd.name === manifest.name,
|
ownName: cmd.name === manifest.name,
|
||||||
pkgName: manifest.name,
|
pkgName: manifest.name,
|
||||||
|
pkgVersion: manifest.version,
|
||||||
makePowerShellShim: POWER_SHELL_IS_SUPPORTED && manifest.name !== 'pnpm',
|
makePowerShellShim: POWER_SHELL_IS_SUPPORTED && manifest.name !== 'pnpm',
|
||||||
nodeExecPath,
|
nodeExecPath,
|
||||||
}))
|
}))
|
||||||
|
|||||||
2
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/.gitignore
vendored
Normal file
2
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
!**/node_modules/**/*
|
||||||
|
!/node_modules/
|
||||||
1
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/bar/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/bar/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/bar/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/bar/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "bar",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/foo/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/foo/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/foo/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/bin-name-conflicts-no-own-name/node_modules/foo/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "foo",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
pkg-manager/link-bins/test/fixtures/different-versions/.gitignore
vendored
Normal file
3
pkg-manager/link-bins/test/fixtures/different-versions/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
!**/node_modules/**/*
|
||||||
|
!/node_modules/
|
||||||
|
|
||||||
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-greater/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-greater/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-greater/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-greater/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "my-command",
|
||||||
|
"version": "1.2.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-lesser/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-lesser/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-lesser/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-lesser/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "my-command",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-middle/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-middle/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-middle/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/different-versions/node_modules/my-command-middle/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "my-command",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/.gitignore
vendored
Normal file
3
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
!**/node_modules/**/*
|
||||||
|
!/node_modules/
|
||||||
|
|
||||||
1
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/my-command/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/my-command/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
7
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/my-command/package.json
generated
vendored
Normal file
7
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/my-command/package.json
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "aliased-to-my-command",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/original-my-command/index.js
generated
vendored
Normal file
1
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/original-my-command/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
8
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/original-my-command/package.json
generated
vendored
Normal file
8
pkg-manager/link-bins/test/fixtures/matching-alias-vs-matching-name/node_modules/original-my-command/package.json
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "my-command",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bin": {
|
||||||
|
"my-command": "index.js",
|
||||||
|
"unaltered": "index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -208,7 +208,9 @@ test('linkBins() resolves conflicts. Prefer packages that use their name as bin
|
|||||||
binaryName: 'bar',
|
binaryName: 'bar',
|
||||||
binsDir: binTarget,
|
binsDir: binTarget,
|
||||||
linkedPkgName: 'bar',
|
linkedPkgName: 'bar',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
skippedPkgName: 'foo',
|
skippedPkgName: 'foo',
|
||||||
|
skippedPkgVersion: expect.any(String),
|
||||||
})
|
})
|
||||||
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['bar', 'foofoo']))
|
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['bar', 'foofoo']))
|
||||||
|
|
||||||
@@ -227,6 +229,64 @@ test('linkBins() resolves conflicts. Prefer packages that use their name as bin
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('linkBins() resolves conflicts. Prefer packages whose name is greater in localeCompare', async () => {
|
||||||
|
const binTarget = tempy.directory()
|
||||||
|
const binNameConflictsFixture = f.prepare('bin-name-conflicts-no-own-name')
|
||||||
|
const warn = jest.fn()
|
||||||
|
|
||||||
|
await linkBins(path.join(binNameConflictsFixture, 'node_modules'), binTarget, { warn })
|
||||||
|
|
||||||
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
|
binaryName: 'my-command',
|
||||||
|
binsDir: binTarget,
|
||||||
|
linkedPkgName: 'foo',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgName: 'bar',
|
||||||
|
skippedPkgVersion: expect.any(String),
|
||||||
|
})
|
||||||
|
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['my-command']))
|
||||||
|
|
||||||
|
{
|
||||||
|
const binLocation = path.join(binTarget, 'my-command')
|
||||||
|
expect(fs.existsSync(binLocation)).toBe(true)
|
||||||
|
const content = fs.readFileSync(binLocation, 'utf8')
|
||||||
|
expect(content).toMatch('node_modules/foo/index.js')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
test('linkBins() resolves conflicts. Prefer the latest version of the same package', async () => {
|
||||||
|
const binTarget = tempy.directory()
|
||||||
|
const binNameConflictsFixture = f.prepare('different-versions')
|
||||||
|
const warn = jest.fn()
|
||||||
|
|
||||||
|
await linkBins(path.join(binNameConflictsFixture, 'node_modules'), binTarget, { warn })
|
||||||
|
|
||||||
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
|
binaryName: 'my-command',
|
||||||
|
binsDir: binTarget,
|
||||||
|
linkedPkgName: 'my-command',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgName: 'my-command',
|
||||||
|
skippedPkgVersion: '1.0.0',
|
||||||
|
})
|
||||||
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
|
binaryName: 'my-command',
|
||||||
|
binsDir: binTarget,
|
||||||
|
linkedPkgName: 'my-command',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgName: 'my-command',
|
||||||
|
skippedPkgVersion: '1.1.0',
|
||||||
|
})
|
||||||
|
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['my-command']))
|
||||||
|
|
||||||
|
{
|
||||||
|
const binLocation = path.join(binTarget, 'my-command')
|
||||||
|
expect(fs.existsSync(binLocation)).toBe(true)
|
||||||
|
const content = fs.readFileSync(binLocation, 'utf8')
|
||||||
|
expect(content).toMatch('node_modules/my-command-greater/index.js')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their name as bin name', async () => {
|
test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their name as bin name', async () => {
|
||||||
const binTarget = tempy.directory()
|
const binTarget = tempy.directory()
|
||||||
const binNameConflictsFixture = f.prepare('bin-name-conflicts')
|
const binNameConflictsFixture = f.prepare('bin-name-conflicts')
|
||||||
@@ -250,8 +310,12 @@ test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their na
|
|||||||
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
binaryName: 'bar',
|
binaryName: 'bar',
|
||||||
binsDir: binTarget,
|
binsDir: binTarget,
|
||||||
|
linkedPkgAlias: undefined,
|
||||||
linkedPkgName: 'bar',
|
linkedPkgName: 'bar',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgAlias: undefined,
|
||||||
skippedPkgName: 'foo',
|
skippedPkgName: 'foo',
|
||||||
|
skippedPkgVersion: expect.any(String),
|
||||||
})
|
})
|
||||||
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['bar', 'foofoo']))
|
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['bar', 'foofoo']))
|
||||||
|
|
||||||
@@ -270,6 +334,60 @@ test('linkBinsOfPackages() resolves conflicts. Prefer packages that use their na
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('linkBinsOfPackages() resolves conflicts. Prefer the latest version', async () => {
|
||||||
|
const binTarget = tempy.directory()
|
||||||
|
const binNameConflictsFixture = f.prepare('different-versions')
|
||||||
|
|
||||||
|
const modulesPath = path.join(binNameConflictsFixture, 'node_modules')
|
||||||
|
|
||||||
|
await linkBinsOfPackages(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
location: path.join(modulesPath, 'my-command-lesser'),
|
||||||
|
manifest: (await import(path.join(modulesPath, 'my-command-lesser', 'package.json'))).default,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
location: path.join(modulesPath, 'my-command-middle'),
|
||||||
|
manifest: (await import(path.join(modulesPath, 'my-command-middle', 'package.json'))).default,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
location: path.join(modulesPath, 'my-command-greater'),
|
||||||
|
manifest: (await import(path.join(modulesPath, 'my-command-greater', 'package.json'))).default,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
binTarget
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
|
binaryName: 'my-command',
|
||||||
|
binsDir: binTarget,
|
||||||
|
linkedPkgAlias: undefined,
|
||||||
|
linkedPkgName: 'my-command',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgAlias: undefined,
|
||||||
|
skippedPkgName: 'my-command',
|
||||||
|
skippedPkgVersion: '1.0.0',
|
||||||
|
})
|
||||||
|
expect(binsConflictLogger.debug).toHaveBeenCalledWith({
|
||||||
|
binaryName: 'my-command',
|
||||||
|
binsDir: binTarget,
|
||||||
|
linkedPkgAlias: undefined,
|
||||||
|
linkedPkgName: 'my-command',
|
||||||
|
linkedPkgVersion: expect.any(String),
|
||||||
|
skippedPkgAlias: undefined,
|
||||||
|
skippedPkgName: 'my-command',
|
||||||
|
skippedPkgVersion: '1.1.0',
|
||||||
|
})
|
||||||
|
expect(fs.readdirSync(binTarget)).toEqual(getExpectedBins(['my-command']))
|
||||||
|
|
||||||
|
{
|
||||||
|
const binLocation = path.join(binTarget, 'my-command')
|
||||||
|
expect(fs.existsSync(binLocation)).toBe(true)
|
||||||
|
const content = fs.readFileSync(binLocation, 'utf8')
|
||||||
|
expect(content).toMatch('node_modules/my-command-greater/index.js')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('linkBins() resolves conflicts. Prefer packages are direct dependencies', async () => {
|
test('linkBins() resolves conflicts. Prefer packages are direct dependencies', async () => {
|
||||||
const binTarget = tempy.directory()
|
const binTarget = tempy.directory()
|
||||||
const binNameConflictsFixture = f.prepare('bin-name-conflicts')
|
const binNameConflictsFixture = f.prepare('bin-name-conflicts')
|
||||||
|
|||||||
6
pnpm-lock.yaml
generated
6
pnpm-lock.yaml
generated
@@ -3698,6 +3698,9 @@ importers:
|
|||||||
ramda:
|
ramda:
|
||||||
specifier: npm:@pnpm/ramda@0.28.1
|
specifier: npm:@pnpm/ramda@0.28.1
|
||||||
version: '@pnpm/ramda@0.28.1'
|
version: '@pnpm/ramda@0.28.1'
|
||||||
|
semver:
|
||||||
|
specifier: ^7.6.0
|
||||||
|
version: 7.6.2
|
||||||
symlink-dir:
|
symlink-dir:
|
||||||
specifier: ^6.0.0
|
specifier: ^6.0.0
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
@@ -3720,6 +3723,9 @@ importers:
|
|||||||
'@types/ramda':
|
'@types/ramda':
|
||||||
specifier: 0.29.12
|
specifier: 0.29.12
|
||||||
version: 0.29.12
|
version: 0.29.12
|
||||||
|
'@types/semver':
|
||||||
|
specifier: 7.5.3
|
||||||
|
version: 7.5.3
|
||||||
cmd-extension:
|
cmd-extension:
|
||||||
specifier: ^1.0.2
|
specifier: ^1.0.2
|
||||||
version: 1.0.2
|
version: 1.0.2
|
||||||
|
|||||||
Reference in New Issue
Block a user