Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 97 additions & 46 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -530,72 +530,81 @@ function get_app_name($path) {
return ''
}

function get_app_name_from_ps1_shim($shim_ps1) {
if (!(Test-Path($shim_ps1))) {
function get_app_name_from_shim($shim) {
if (!(Test-Path($shim))) {
return ''
}
$content = (Get-Content $shim_ps1 -Encoding utf8) -join ' '
$content = (Get-Content $shim -Encoding UTF8) -join ' '
return get_app_name $content
}

function warn_on_overwrite($shim_ps1, $path) {
if (!(Test-Path($shim_ps1))) {
function warn_on_overwrite($shim, $path) {
if (!(Test-Path($shim))) {
return
}
$shim_app = get_app_name_from_ps1_shim $shim_ps1
$shim_app = get_app_name_from_shim $shim
$path_app = get_app_name $path
if ($shim_app -eq $path_app) {
return
}
$filename = [System.IO.Path]::GetFileName($path)
warn "Overwriting shim to $filename installed from $shim_app"
$shimname = (fname $shim) -replace '\.shim$', '.exe'
$filename = (fname $path) -replace '\.shim$', '.exe'
warn "Overwriting shim ('$shimname' -> '$filename') installed from $shim_app"
}

function shim($path, $global, $name, $arg) {
if(!(test-path $path)) { abort "Can't shim '$(fname $path)': couldn't find '$path'." }
if (!(Test-Path $path)) { abort "Can't shim '$(fname $path)': couldn't find '$path'." }
$abs_shimdir = ensure (shimdir $global)
if(!$name) { $name = strip_ext (fname $path) }
if (!$name) { $name = strip_ext (fname $path) }

$shim = "$abs_shimdir\$($name.tolower())"

warn_on_overwrite "$shim.ps1" $path

# convert to relative path
Push-Location $abs_shimdir
$relative_path = resolve-path -relative $path
$relative_path = Resolve-Path -Relative $path
Pop-Location
$resolved_path = resolve-path $path

# if $path points to another drive resolve-path prepends .\ which could break shims
if($relative_path -match "^(.\\[\w]:).*$") {
write-output "`$path = `"$path`"" | out-file "$shim.ps1" -encoding utf8
} else {
# Setting PSScriptRoot in Shim if it is not defined, so the shim doesn't break in PowerShell 2.0
Write-Output "if (!(Test-Path Variable:PSScriptRoot)) { `$PSScriptRoot = Split-Path `$MyInvocation.MyCommand.Path -Parent }" | Out-File "$shim.ps1" -Encoding utf8
write-output "`$path = join-path `"`$psscriptroot`" `"$relative_path`"" | out-file "$shim.ps1" -Encoding utf8 -Append
}
$resolved_path = Resolve-Path $path

if($path -match '\.jar$') {
"if(`$myinvocation.expectingInput) { `$input | & java -jar `$path $arg @args } else { & java -jar `$path $arg @args }" | out-file "$shim.ps1" -encoding utf8 -append
} else {
"if(`$myinvocation.expectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }" | out-file "$shim.ps1" -encoding utf8 -append
}

if($path -match '\.(exe|com)$') {
if ($path -match '\.(exe|com)$') {
# for programs with no awareness of any shell
Copy-Item (get_shim_path) "$shim.exe" -force
write-output "path = $resolved_path" | out-file "$shim.shim" -encoding utf8
if($arg) {
write-output "args = $arg" | out-file "$shim.shim" -encoding utf8 -append
warn_on_overwrite "$shim.shim" $path
Copy-Item (get_shim_path) "$shim.exe" -Force
Write-Output "path = $resolved_path" | Out-File "$shim.shim" -Encoding UTF8
if ($arg) {
Write-Output "args = $arg" | Out-File "$shim.shim" -Encoding UTF8 -Append
}
} elseif($path -match '\.(bat|cmd)$') {
} elseif ($path -match '\.(bat|cmd)$') {
# shim .bat, .cmd so they can be used by programs with no awareness of PSH
"@`"$resolved_path`" $arg %*" | out-file "$shim.cmd" -encoding ascii
warn_on_overwrite "$shim.cmd" $path
"@rem $resolved_path
@`"$resolved_path`" $arg %*" | Out-File "$shim.cmd" -Encoding ASCII

warn_on_overwrite $shim $path
"#!/bin/sh
# $resolved_path
MSYS2_ARG_CONV_EXCL=/C cmd.exe /C `"$resolved_path`" $arg `"$@`"" | Out-File $shim -Encoding ASCII
} elseif ($path -match '\.ps1$') {
# if $path points to another drive resolve-path prepends .\ which could break shims
warn_on_overwrite "$shim.ps1" $path
$ps1text = if ($relative_path -match '^(.\\[\w]:).*$') {
"# $resolved_path
`$path = `"$path`"
if(`$myinvocation.expectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }
exit `$lastexitcode"
} else {
# Setting PSScriptRoot in Shim if it is not defined, so the shim doesn't break in PowerShell 2.0
"# $resolved_path
if (!(Test-Path Variable:PSScriptRoot)) { `$PSScriptRoot = Split-Path `$MyInvocation.MyCommand.Path -Parent }
`$path = join-path `"`$psscriptroot`" `"$relative_path`"
if(`$myinvocation.expectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }
exit `$lastexitcode"
}
$ps1text | Out-File "$shim.ps1" -Encoding UTF8

"#!/bin/sh`nMSYS2_ARG_CONV_EXCL=/C cmd.exe /C `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
} elseif($path -match '\.ps1$') {
# make ps1 accessible from cmd.exe
"@echo off
warn_on_overwrite "$shim.cmd" $path
"@rem $resolved_path
@echo off
setlocal enabledelayedexpansion
set args=%*
:: replace problem characters in arguments
Expand All @@ -604,22 +613,64 @@ set args=%args:(=``(%
set args=%args:)=``)%
set invalid=`"='
if !args! == !invalid! ( set args= )
powershell -noprofile -ex unrestricted `"& '$resolved_path' $arg %args%;exit `$lastexitcode`"" | out-file "$shim.cmd" -encoding ascii
where /q pwsh.exe
if %errorlevel% equ 0 (
pwsh -noprofile -ex unrestricted `"& '$resolved_path' $arg %args%;exit `$lastexitcode`"
) else (
powershell -noprofile -ex unrestricted `"& '$resolved_path' $arg %args%;exit `$lastexitcode`"
)" | Out-File "$shim.cmd" -Encoding ASCII

warn_on_overwrite $shim $path
"#!/bin/sh
# $resolved_path
if command -v pwsh.exe &> /dev/null; then
pwsh.exe -noprofile -ex unrestricted `"$resolved_path`" $arg `"$@`"
else
powershell.exe -noprofile -ex unrestricted `"$resolved_path`" $arg `"$@`"
fi" | Out-File $shim -Encoding ASCII
} elseif ($path -match '\.jar$') {
warn_on_overwrite "$shim.cmd" $path
"@rem $resolved_path
@java -jar `"$resolved_path`" $arg %*" | Out-File "$shim.cmd" -Encoding ASCII

warn_on_overwrite $shim $path
"#!/bin/sh
# $resolved_path
java -jar `"$resolved_path`" $arg `"$@`"" | Out-File $shim -Encoding ASCII
} elseif ($path -match '\.py$') {
warn_on_overwrite "$shim.cmd" $path
"@rem $resolved_path
@python `"$resolved_path`" $arg %*" | Out-File "$shim.cmd" -Encoding ASCII

warn_on_overwrite $shim $path
"#!/bin/sh
# $resolved_path
python `"$resolved_path`" $arg `"$@`"" | Out-File $shim -Encoding ASCII
} else {
warn_on_overwrite "$shim.cmd" $path
# find path to Git's bash so that batch scripts can run bash scripts
$gitdir = (Get-Item (Get-Command git -ErrorAction:Stop).Source -ErrorAction:Stop).Directory.Parent
if ($gitdir.FullName -imatch 'mingw') {
$gitdir = $gitdir.Parent
}
"@rem $resolved_path
@`"$(Join-Path (Join-Path $gitdir.FullName 'bin') 'bash.exe')`" `"$resolved_path`" $arg %*" | Out-File "$shim.cmd" -Encoding ASCII

"#!/bin/sh`npowershell.exe -noprofile -ex unrestricted `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
} elseif($path -match '\.jar$') {
"@java -jar `"$resolved_path`" $arg %*" | out-file "$shim.cmd" -encoding ascii
"#!/bin/sh`njava -jar `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
warn_on_overwrite $shim $path
"#!/bin/sh
# $resolved_path
`"$resolved_path`" $arg `"$@`"" | Out-File $shim -Encoding ASCII
}
}

function get_shim_path() {
$shim_path = "$(versiondir 'scoop' 'current')\supporting\shimexe\bin\shim.exe"
$shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\kiennq\shim.exe"
$shim_version = get_config 'shim' 'default'
switch ($shim_version) {
'71' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\71\shim.exe"; Break }
'kiennq' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\kiennq\shim.exe"; Break }
Comment thread
rashil2000 marked this conversation as resolved.
'scoopcs' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shimexe\bin\shim.exe"; Break }
'rshim' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\rshim\shim.exe"; Break }
'kiennq' { Break } # for backward compatibility
Comment thread
rashil2000 marked this conversation as resolved.
'default' { Break }
default { warn "Unknown shim version: '$shim_version'" }
}
Expand Down
13 changes: 2 additions & 11 deletions lib/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -870,18 +870,9 @@ function create_shims($manifest, $dir, $global, $arch) {
}

function rm_shim($name, $shimdir) {
$shim = "$shimdir\$name.ps1"

if(!(test-path $shim)) { # handle no shim from failed install
warn "Shim for '$name' is missing. Skipping."
} else {
write-output "Removing shim for '$name'."
Remove-Item $shim
}

# other shim types might be present
'', '.exe', '.shim', '.cmd' | ForEach-Object {
'', '.exe', '.shim', '.cmd', '.ps1' | ForEach-Object {
if(test-path -Path "$shimdir\$name$_" -PathType leaf) {
Write-Output "Removing shim '$name$_'."
Remove-Item "$shimdir\$name$_"
}
}
Expand Down
13 changes: 9 additions & 4 deletions libexec/scoop-which.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ $path = "$($gcm.path)"
$usershims = "$(resolve-path $(shimdir $false))"
$globalshims = fullpath (shimdir $true) # don't resolve: may not exist

if($path.endswith(".ps1") -and ($path -like "$usershims*" -or $path -like "$globalshims*")) {
$shimtext = Get-Content $path

$exepath = ($shimtext | Where-Object { $_.startswith('$path') }).split(' ') | Select-Object -Last 1 | Invoke-Expression
if($path -like "$usershims*" -or $path -like "$globalshims*") {
$exepath = if ($path.endswith(".exe") -or $path.endswith(".shim")) {
(Get-Content ($path -replace '\.exe$', '.shim') | Select-Object -First 1).replace('path = ', '')
} else {
((Select-String -Path $path -Pattern '^(?:@rem|#)\s*(.*)$').Matches.Groups | Select-Object -Index 1).Value
Comment thread
niheaven marked this conversation as resolved.
}
if (!$exepath) {
$exepath = ((Select-String -Path $path -Pattern '[''"]([^@&]*?)[''"]' -AllMatches).Matches.Groups | Select-Object -Last 1).Value
}

if(![system.io.path]::ispathrooted($exepath)) {
# Expand relative path
Expand Down
12 changes: 6 additions & 6 deletions test/Scoop-Core.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -221,28 +221,28 @@ describe "rm_shim" -Tag 'Scoop' {
}
}

Describe "get_app_name_from_ps1_shim" -Tag 'Scoop' {
Describe "get_app_name_from_shim" -Tag 'Scoop' {
BeforeAll {
$working_dir = setup_working "shim"
$shimdir = shimdir
$(ensure_in_path $shimdir) | Out-Null
}

It "returns empty string if file does not exist" -skip:$isUnix {
get_app_name_from_ps1_shim "non-existent-file" | should -be ""
get_app_name_from_shim "non-existent-file" | should -be ""
}

It "returns app name if file exists and is a shim to an app" -skip:$isUnix {
mkdir -p "$working_dir/mockapp/current/"
Write-Output "" | Out-File "$working_dir/mockapp/current/mockapp.ps1"
shim "$working_dir/mockapp/current/mockapp.ps1" $false "shim-test"
$shim_path = (get-command "shim-test.ps1").Path
get_app_name_from_ps1_shim "$shim_path" | should -be "mockapp"
get_app_name_from_shim "$shim_path" | should -be "mockapp"
}

It "returns empty string if file exists and is not a shim" -skip:$isUnix {
Write-Output "lorem ipsum" | Out-File -Encoding ascii "$working_dir/mock-shim.ps1"
get_app_name_from_ps1_shim "$working_dir/mock-shim.ps1" | should -be ""
get_app_name_from_shim "$working_dir/mock-shim.ps1" | should -be ""
}

AfterEach {
Expand All @@ -269,7 +269,7 @@ describe "ensure_robocopy_in_path" -Tag 'Scoop' {

ensure_robocopy_in_path

"$shimdir/robocopy.ps1" | should -exist
# "$shimdir/robocopy.ps1" | should -exist
"$shimdir/robocopy.exe" | should -exist

# clean up
Expand All @@ -284,7 +284,7 @@ describe "ensure_robocopy_in_path" -Tag 'Scoop' {

ensure_robocopy_in_path

"$shimdir/robocopy.ps1" | should -not -exist
# "$shimdir/robocopy.ps1" | should -not -exist
"$shimdir/robocopy.exe" | should -not -exist
}
}
Expand Down