mirror of
https://github.com/pnpm/pnpm.git
synced 2026-01-06 22:18:17 -05:00
fix(dlx): pnpm dlx should work with git-hosted pkgs (#4717)
close #4714
This commit is contained in:
6
.changeset/fifty-taxis-exist.md
Normal file
6
.changeset/fifty-taxis-exist.md
Normal 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).
|
||||
@@ -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
|
||||
|
||||
@@ -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/)
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user