fix(dlx): pnpm dlx should work with git-hosted pkgs (#4717)

close #4714
This commit is contained in:
Zoltan Kochan
2022-05-11 13:04:11 +03:00
committed by GitHub
parent 0bdf6bab57
commit 53f653340e
4 changed files with 41 additions and 15 deletions

View File

@@ -0,0 +1,6 @@
---
"@pnpm/plugin-commands-script-runners": patch
"pnpm": patch
---
`pnpm dlx` should work with git-hosted packages. For example: `pnpm dlx gengjiawen/envinfo` [#4714](https://github.com/pnpm/pnpm/issues/4714).

View File

@@ -77,13 +77,18 @@ export async function handler (
}, pkgs)
const binName = opts.package
? command
: await getBinName(modulesDir, versionless(command))
: await getBinName(modulesDir, await getPkgName(prefix))
await execa(binName, args, {
env,
stdio: 'inherit',
})
}
async function getPkgName (pkgDir: string) {
const manifest = await readPkgFromDir(pkgDir)
return Object.keys(manifest.dependencies ?? {})[0]
}
async function getBinName (modulesDir: string, pkgName: string): Promise<string> {
const pkgDir = path.join(modulesDir, pkgName)
const manifest = await readPkgFromDir(pkgDir)
@@ -112,12 +117,6 @@ function scopeless (pkgName: string) {
return pkgName
}
function versionless (pkgName: string) {
const index = pkgName.indexOf('@', 1)
if (index === -1) return pkgName
return pkgName.substring(0, index)
}
async function getDlxDir (
opts: {
dir: string

View File

@@ -1,4 +1,5 @@
import fs from 'fs'
import path from 'path'
import { dlx } from '@pnpm/plugin-commands-script-runners'
import { prepareEmpty } from '@pnpm/prepare'
import { DLX_DEFAULT_OPTS as DEFAULT_OPTS } from './utils'
@@ -8,18 +9,31 @@ test('dlx', async () => {
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['shx', 'touch', 'foo'])
expect(fs.existsSync('foo')).toBeTruthy()
})
test('dlx install from git', async () => {
prepareEmpty()
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
}, ['shelljs/shx#61aca968cd7afc712ca61a4fc4ec3201e3770dc7', 'touch', 'foo'])
expect(fs.existsSync('foo')).toBeTruthy()
})
test('dlx should work when the package name differs from the bin name', async () => {
prepareEmpty()
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['touch-file-one-bin'])
expect(fs.existsSync('touch.txt')).toBeTruthy()
@@ -31,7 +45,8 @@ test('dlx should fail when the installed package has many commands and none equa
await expect(
dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['touch-file-many-bins'])
).rejects.toThrow('Could not determine executable to run. touch-file-many-bins has multiple binaries: t, tt')
})
@@ -41,7 +56,8 @@ test('dlx should not fail when the installed package has many commands and one e
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['touch-file-good-bin-name'])
expect(fs.existsSync('touch.txt')).toBeTruthy()
@@ -52,7 +68,8 @@ test('dlx --package <pkg1> [--package <pkg2>]', async () => {
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
package: [
'zkochan/for-testing-pnpm-dlx',
'is-positive',
@@ -68,7 +85,8 @@ test('dlx should fail when the package has no bins', async () => {
await expect(
dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['is-positive'])
).rejects.toThrow(/No binaries found in is-positive/)
})

View File

@@ -1,3 +1,4 @@
import path from 'path'
import execa from 'execa'
import { dlx } from '@pnpm/plugin-commands-script-runners'
import { prepareEmpty } from '@pnpm/prepare'
@@ -13,7 +14,8 @@ test('dlx should work with scoped packages', async () => {
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
userAgent,
}, ['@foo/touch-file-one-bin'])
@@ -29,7 +31,8 @@ test('dlx should work with versioned packages', async () => {
await dlx.handler({
...DEFAULT_OPTS,
dir: process.cwd(),
dir: path.resolve('project'),
storeDir: path.resolve('store'),
}, ['@foo/touch-file-one-bin@latest'])
expect(execa).toBeCalledWith('touch-file-one-bin', [], expect.anything())