Skip to content

Commit

Permalink
feat: add ps1 scripts (#6548)
Browse files Browse the repository at this point in the history
* add ps1 scripts

Resolves UNC path issues because powershell.exe
supports UNC, while cmd.exe doesn't.
(Which is why npm.cmd doesn't work within
UNC paths, even under powershell)

Resolves #6280

* fixup: add tests and prefix for ps1 scripts

---------

Co-authored-by: Luke Karrys <luke@lukekarrys.com>
  • Loading branch information
mribbons and lukekarrys committed Jun 26, 2023
1 parent 332dec3 commit 89b2741
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
35 changes: 35 additions & 0 deletions bin/npm.ps1
@@ -0,0 +1,35 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent

$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0

$nodeexe = "node$exe"
$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source
if ($nodebin -eq $null) {
Write-Host "$nodeexe not found."
exit 1
}
$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path

$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js"
$npmprefix=(& $nodeexe $npmclijs prefix -g)
if ($LASTEXITCODE -ne 0) {
Write-Host "Could not determine Node.js install directory"
exit 1
}
$npmprefixclijs="$npmprefix/node_modules/npm/bin/npm-cli.js"

# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & $nodeexe $npmprefixclijs $args
} else {
& $nodeexe $npmprefixclijs $args
}
$ret=$LASTEXITCODE
exit $ret
35 changes: 35 additions & 0 deletions bin/npx.ps1
@@ -0,0 +1,35 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent

$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0

$nodeexe = "node$exe"
$nodebin = $(Get-Command $nodeexe -ErrorAction SilentlyContinue -ErrorVariable F).Source
if ($nodebin -eq $null) {
Write-Host "$nodeexe not found."
exit 1
}
$nodedir = $(New-Object -ComObject Scripting.FileSystemObject).GetFile("$nodebin").ParentFolder.Path

$npmclijs="$nodedir/node_modules/npm/bin/npm-cli.js"
$npmprefix=(& $nodeexe $npmclijs prefix -g)
if ($LASTEXITCODE -ne 0) {
Write-Host "Could not determine Node.js install directory"
exit 1
}
$npmprefixclijs="$npmprefix/node_modules/npm/bin/npx-cli.js"

# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & $nodeexe $npmprefixclijs $args
} else {
& $nodeexe $npmprefixclijs $args
}
$ret=$LASTEXITCODE
exit $ret
21 changes: 20 additions & 1 deletion test/bin/windows-shims.js
@@ -1,6 +1,6 @@
const t = require('tap')
const { spawnSync } = require('child_process')
const { resolve, join, extname, basename } = require('path')
const { resolve, join, extname, basename, sep } = require('path')
const { readFileSync, chmodSync, readdirSync } = require('fs')
const Diff = require('diff')
const { sync: which } = require('which')
Expand All @@ -18,6 +18,12 @@ const SHIMS = readdirSync(BIN).reduce((acc, shim) => {

const SHIM_EXTS = [...new Set(Object.keys(SHIMS).map(p => extname(p)))]

// windows requires each segment of a command path to be quoted when using shell: true
const quotePath = (cmd) => cmd
.split(sep)
.map(p => p.includes(' ') ? `"${p}"` : p)
.join(sep)

t.test('shim contents', t => {
// these scripts should be kept in sync so this tests the contents of each
// and does a diff to ensure the only differences between them are necessary
Expand Down Expand Up @@ -49,6 +55,13 @@ t.test('shim contents', t => {
t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x')
t.end()
})

t.test('pwsh', t => {
const { diff, letters } = diffFiles(SHIMS['npm.ps1'], SHIMS['npx.ps1'])
t.equal(diff.length, 0)
t.strictSame([...letters], ['M', 'X'], 'all other changes are m->x')
t.end()
})
})

t.test('run shims', t => {
Expand Down Expand Up @@ -133,6 +146,7 @@ t.test('run shims', t => {

const shells = Object.entries({
cmd: 'cmd',
pwsh: 'pwsh',
git: join(ProgramFiles, 'Git', 'bin', 'bash.exe'),
'user git': join(ProgramFiles, 'Git', 'usr', 'bin', 'bash.exe'),
wsl: join(SystemRoot, 'System32', 'bash.exe'),
Expand Down Expand Up @@ -197,6 +211,11 @@ t.test('run shims', t => {
case 'bash.exe':
args.push(bin)
break
case 'pwsh.exe':
cmd = quotePath(cmd)
args.push(`${bin}.ps1`)
opts.shell = true
break
default:
throw new Error('unknown shell')
}
Expand Down

0 comments on commit 89b2741

Please sign in to comment.