From c99e8dfb3caf497e4518e9cfc9a273e56e3b8aee Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Mon, 10 Jun 2019 13:50:31 +0800 Subject: [PATCH 01/15] chore(install): Use actural file name in output --- lib/install.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index 35db21b2e5..625e41291a 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -553,7 +553,7 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c if($extract_fn) { Write-Host "Extracting " -NoNewline - Write-Host $fname -f Cyan -NoNewline + Write-Host $(url_remote_filename $url) -f Cyan -NoNewline Write-Host " ... " -NoNewline & $extract_fn -Path "$dir\$fname" -DestinationPath "$dir\$extract_to" -ExtractDir $extract_dir -Removal Write-Host "done." -f Green From a7cc1a617378ce8827718454a7aa02a71fb36c44 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 14 May 2019 16:17:02 +0800 Subject: [PATCH 02/15] fix(msi): Remove deprecated 'msi' --- lib/install.ps1 | 93 +++++++----------------------------------------- lib/manifest.ps1 | 1 - schema.json | 8 ----- 3 files changed, 13 insertions(+), 89 deletions(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index 625e41291a..05775cfc39 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -480,7 +480,7 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c # we only want to show this warning once if(!$use_cache) { warn "Cache is being ignored." } - # can be multiple urls: if there are, then msi or installer should go last, + # can be multiple urls: if there are, then installer should go last, # so that $fname is set properly $urls = @(url $manifest $architecture) @@ -541,12 +541,7 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c } elseif($fname -match '\.zip$') { $extract_fn = 'Expand-ZipArchive' } elseif($fname -match '\.msi$') { - # check manifest doesn't use deprecated install method - if(msi $manifest $architecture) { - warn "MSI install is deprecated. If you maintain this manifest, please refer to the manifest reference docs." - } else { - $extract_fn = 'Expand-MsiArchive' - } + $extract_fn = 'Expand-MsiArchive' } elseif(Test-7zipRequirement -File $fname) { # 7zip $extract_fn = 'Expand-7zipArchive' } @@ -662,8 +657,6 @@ function args($config, $dir, $global) { } function run_installer($fname, $manifest, $architecture, $dir, $global) { - # MSI or other installer - $msi = msi $manifest $architecture $installer = installer $manifest $architecture if($installer.script) { write-output "Running installer script..." @@ -671,54 +664,11 @@ function run_installer($fname, $manifest, $architecture, $dir, $global) { return } - if($msi) { - install_msi $fname $dir $msi - } elseif($installer) { + if ($installer) { install_prog $fname $dir $installer $global } } -# deprecated (see also msi_installed) -function install_msi($fname, $dir, $msi) { - $msifile = "$dir\$(coalesce $msi.file "$fname")" - if(!(is_in_dir $dir $msifile)) { - abort "Error in manifest: MSI file $msifile is outside the app directory." - } - if(!($msi.code)) { abort "Error in manifest: Couldn't find MSI code."} - if(msi_installed $msi.code) { abort "The MSI package is already installed on this system." } - - $logfile = "$dir\install.log" - - $arg = @("/i `"$msifile`"", '/norestart', "/lvp `"$logfile`"", "TARGETDIR=`"$dir`"", - "INSTALLDIR=`"$dir`"") + @(args $msi.args $dir) - - if($msi.silent) { $arg += '/qn', 'ALLUSERS=2', 'MSIINSTALLPERUSER=1' } - else { $arg += '/qb-!' } - - $continue_exit_codes = @{ 3010 = "a restart is required to complete installation" } - - $installed = Invoke-ExternalCommand 'msiexec' $arg -Activity "Running installer..." -ContinueExitCodes $continue_exit_codes - if(!$installed) { - abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again." - } - Remove-Item $logfile - Remove-Item $msifile -} - -# deprecated -# get-wmiobject win32_product is slow and checks integrity of each installed program, -# so this uses the [wmi] type accelerator instead -# http://blogs.technet.com/b/heyscriptingguy/archive/2011/12/14/use-powershell-to-find-and-uninstall-software.aspx -function msi_installed($code) { - $path = "hklm:\software\microsoft\windows\currentversion\uninstall\$code" - if(!(test-path $path)) { return $false } - $key = Get-Item $path - $name = $key.getvalue('displayname') - $version = $key.getvalue('displayversion') - $classkey = "IdentifyingNumber=`"$code`",Name=`"$name`",Version=`"$version`"" - try { $wmi = [wmi]"Win32_Product.$classkey"; $true } catch { $false } -} - function install_prog($fname, $dir, $installer, $global) { $prog = "$dir\$(coalesce $installer.file "$fname")" if(!(is_in_dir $dir $prog)) { @@ -735,14 +685,13 @@ function install_prog($fname, $dir, $installer, $global) { } # Don't remove installer if "keep" flag is set to true - if(!($installer.keep -eq "true")) { + if($installer.keep -ne "true") { Remove-Item $prog } } } function run_uninstaller($manifest, $architecture, $dir) { - $msi = msi $manifest $architecture $uninstaller = uninstaller $manifest $architecture if($uninstaller.script) { write-output "Running uninstaller script..." @@ -750,31 +699,15 @@ function run_uninstaller($manifest, $architecture, $dir) { return } - if($msi -or $uninstaller) { - $exe = $null; $arg = $null; $continue_exit_codes = @{} - - if($msi) { - $code = $msi.code - $exe = "msiexec"; - $arg = @("/norestart", "/x $code") - if($msi.silent) { - $arg += '/qn', 'ALLUSERS=2', 'MSIINSTALLPERUSER=1' - } else { - $arg += '/qb-!' - } - - $continue_exit_codes.1605 = 'not installed, skipping' - $continue_exit_codes.3010 = 'restart required' - } elseif($uninstaller) { - $exe = "$dir\$($uninstaller.file)" - $arg = args $uninstaller.args - if(!(is_in_dir $dir $exe)) { - warn "Error in manifest: Installer $exe is outside the app directory, skipping." - $exe = $null; - } elseif(!(test-path $exe)) { - warn "Uninstaller $exe is missing, skipping." - $exe = $null; - } + if($uninstaller) { + $exe = "$dir\$($uninstaller.file)" + $arg = args $uninstaller.args + if(!(is_in_dir $dir $exe)) { + warn "Error in manifest: Installer $exe is outside the app directory, skipping." + $exe = $null; + } elseif(!(test-path $exe)) { + warn "Uninstaller $exe is missing, skipping." + $exe = $null; } if($exe) { diff --git a/lib/manifest.ps1 b/lib/manifest.ps1 index 4e68b4a799..84645c3284 100644 --- a/lib/manifest.ps1 +++ b/lib/manifest.ps1 @@ -102,7 +102,6 @@ function generate_user_manifest($app, $bucket, $version) { function url($manifest, $arch) { arch_specific 'url' $manifest $arch } function installer($manifest, $arch) { arch_specific 'installer' $manifest $arch } function uninstaller($manifest, $arch) { arch_specific 'uninstaller' $manifest $arch } -function msi($manifest, $arch) { arch_specific 'msi' $manifest $arch } function hash($manifest, $arch) { arch_specific 'hash' $manifest $arch } function extract_dir($manifest, $arch) { arch_specific 'extract_dir' $manifest $arch} function extract_to($manifest, $arch) { arch_specific 'extract_to' $manifest $arch} diff --git a/schema.json b/schema.json index c245b5f8ac..61b064a45c 100644 --- a/schema.json +++ b/schema.json @@ -104,10 +104,6 @@ "installer": { "$ref": "#/definitions/installer" }, - "msi": { - "$ref": "#/definitions/stringOrArrayOfStrings", - "description": "Deprecated" - }, "post_install": { "$ref": "#/definitions/stringOrArrayOfStrings" }, @@ -478,10 +474,6 @@ } ] }, - "msi": { - "$ref": "#/definitions/stringOrArrayOfStrings", - "description": "Deprecated" - }, "notes": { "$ref": "#/definitions/stringOrArrayOfStrings" }, From b22251273e6fa6bdb194f26d94cb5aab1ecb4aef Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 9 Jul 2019 18:54:56 +0800 Subject: [PATCH 03/15] feat(schema): Add 'Installer.type' --- schema.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/schema.json b/schema.json index 61b064a45c..64bd2d6071 100644 --- a/schema.json +++ b/schema.json @@ -274,6 +274,19 @@ }, "keep": { "type": "boolean" + }, + "type": { + "enum": [ + "inno", + "nsis", + "wix" + ] + }, + "include": { + "$ref": "#/definitions/stringOrArrayOfStrings" + }, + "exclude": { + "$ref": "#/definitions/stringOrArrayOfStrings" } }, "type": "object" @@ -445,7 +458,7 @@ "type": "string" }, "innosetup": { - "description": "True if the installer InnoSetup based. Found in https://github.com/lukesampson/scoop/search?l=JSON&q=innosetup", + "description": "Deprecated. Use 'installer.type.inno' instead.", "type": "boolean" }, "installer": { From 639baa6cb33d9d07fe2ad73cec19b9974109c3b3 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Wed, 15 May 2019 11:11:25 +0800 Subject: [PATCH 04/15] feat(decompress): Add and fix 'Test-xxxRequirement' functions --- lib/decompress.ps1 | 69 +++++++++++++++++++++++++++++++++++++++------- lib/depends.ps1 | 10 ++++--- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 4606ce4c18..e4def2702c 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -1,22 +1,29 @@ function Test-7zipRequirement { - [CmdletBinding(DefaultParameterSetName = "URL")] + [CmdletBinding(DefaultParameterSetName = "Manifest")] [OutputType([Boolean])] param ( - [Parameter(Mandatory = $true, ParameterSetName = "URL")] - [String[]] - $URL, + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = "Manifest")] + [PSObject] + $Manifest, + [Parameter(Mandatory = $true, Position = 1, ParameterSetName = "Manifest")] + [String] + $Architecture, [Parameter(Mandatory = $true, ParameterSetName = "File")] [String] $File ) - if ($URL) { + if ($File) { + return $File -match '\.((gz)|(tar)|(tgz)|(lzma)|(bz)|(bz2)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))$' + } else { + $URL = url $Manifest $Architecture + $Installer = installer $Manifest $Architecture if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) { return $false + } elseif (($Installer.type -eq "nsis")) { + return $true } else { return ($URL | Where-Object { Test-7zipRequirement -File $_ }).Count -gt 0 } - } else { - return $File -match '\.((gz)|(tar)|(tgz)|(lzma)|(bz)|(bz2)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))$' } } @@ -24,10 +31,14 @@ function Test-LessmsiRequirement { [CmdletBinding()] [OutputType([Boolean])] param ( - [Parameter(Mandatory = $true)] - [String[]] - $URL + [Parameter(Mandatory = $true, Position = 0)] + [PSObject] + $Manifest, + [Parameter(Mandatory = $true, Position = 1)] + [String] + $Architecture ) + $URL = url $Manifest $Architecture if ((get_config MSIEXTRACT_USE_LESSMSI)) { return ($URL | Where-Object { $_ -match '\.msi$' }).Count -gt 0 } else { @@ -35,6 +46,44 @@ function Test-LessmsiRequirement { } } +function Test-InnounpRequirement { + [CmdletBinding()] + [OutputType([Boolean])] + param ( + [Parameter(Mandatory = $true, Position = 0)] + [PSObject] + $Manifest, + [Parameter(Mandatory = $true, Position = 1)] + [String] + $Architecture + ) + $Installer = installer $Manifest $Architecture + if (($Installer.type -eq "inno") -or $Manifest.innosetup) { + return $true + } else { + return $false + } +} + +function Test-DarkRequirement { + [CmdletBinding()] + [OutputType([Boolean])] + param ( + [Parameter(Mandatory = $true, Position = 0)] + [PSObject] + $Manifest, + [Parameter(Mandatory = $true, Position = 1)] + [String] + $Architecture + ) + $Installer = installer $Manifest $Architecture + if (($Installer.type -eq "wix")) { + return $true + } else { + return $false + } +} + function Expand-7zipArchive { [CmdletBinding()] param ( diff --git a/lib/depends.ps1 b/lib/depends.ps1 index 1486e59762..2928b21115 100644 --- a/lib/depends.ps1 +++ b/lib/depends.ps1 @@ -77,16 +77,18 @@ function script_deps($script) { function install_deps($manifest, $arch) { $deps = @() - if (!(Test-HelperInstalled -Helper 7zip) -and (Test-7zipRequirement -URL (url $manifest $arch))) { + if (!(Test-HelperInstalled -Helper 7zip) -and (Test-7zipRequirement -Manifest $manifest -Architecture $arch)) { $deps += '7zip' } - if (!(Test-HelperInstalled -Helper Lessmsi) -and (Test-LessmsiRequirement -URL (url $manifest $arch))) { + if (!(Test-HelperInstalled -Helper Lessmsi) -and (Test-LessmsiRequirement -Manifest $manifest -Architecture $arch)) { $deps += 'lessmsi' } - if (!(Test-HelperInstalled -Helper Innounp) -and $manifest.innosetup) { + if (!(Test-HelperInstalled -Helper Innounp) -and (Test-InnounpRequirement -Manifest $manifest -Architecture $arch)) { $deps += 'innounp' } - + if (!(Test-HelperInstalled -Helper Dark) -and (Test-DarkRequirement -Manifest $manifest -Architecture $arch)) { + $deps += 'dark' + } $pre_install = arch_specific 'pre_install' $manifest $arch $installer = arch_specific 'installer' $manifest $arch $post_install = arch_specific 'post_install' $manifest $arch From 7bea4063379657f9dfc1346ebfbc930ad03d2641 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 11 Jun 2019 00:16:07 +0800 Subject: [PATCH 05/15] feat(test): Add Test cases for 'Test-xxxRequirement' function --- test/Scoop-Decompress.Tests.ps1 | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index 7f452c2603..f7e9d7a34d 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -6,16 +6,42 @@ $isUnix = is_unix -function test_extract($extract_fn, $from, $removal) { - $to = (strip_ext $from) -replace '\.tar$', '' - & $extract_fn ($from -replace '/', '\') ($to -replace '/', '\') -Removal:$removal - return $to +Describe 'Requirement function' -Tag 'Scoop' { + It 'Test 7zip requirement' { + Mock get_config { $true } + Test-7zipRequirement @{ url = "test.7z" } '64bit' | Should -BeFalse + Mock get_config { $false } + Test-7zipRequirement @{ url = "test.7z" } '64bit' | Should -BeTrue + Test-7zipRequirement @{ installer = @{ type = "nsis" } } '64bit' | Should -BeTrue + Test-7zipRequirement @{ url = "test.exe" } '64bit' | Should -BeFalse + Test-7zipRequirement -File 'test.xz' | Should -BeTrue + Test-7zipRequirement -File 'test.bin' | Should -BeFalse + } + It 'Test lessmsi requirement' { + Mock get_config { $true } + Test-LessmsiRequirement @{ url = "test.msi"} '64bit' | Should -BeTrue + Test-LessmsiRequirement @{ url = "test.exe"} '64bit' | Should -BeFalse + } + It 'Test innounp requirement' { + Test-InnounpRequirement @{ installer = @{ type = "inno" } } '64bit' | Should -BeTrue + Test-InnounpRequirement @{ } '64bit' | Should -BeFalse + } + It 'Test dark requirement' { + Test-DarkRequirement @{ installer = @{ type = "wix" } } '64bit' | Should -BeTrue + Test-DarkRequirement @{ } '64bit' | Should -BeFalse + } } Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { BeforeAll { $working_dir = setup_working 'decompress' + function test_extract($extract_fn, $from, $removal) { + $to = (strip_ext $from) -replace '\.tar$', '' + & $extract_fn ($from -replace '/', '\') ($to -replace '/', '\') -Removal:$removal + return $to + } + It "Decompression test cases should exist" { $testcases = "$working_dir\TestCases.zip" $testcases | Should -Exist From 4de03050af17536fec8719a9aa363840045b2697 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Wed, 10 Jul 2019 16:28:28 +0800 Subject: [PATCH 06/15] feat(core): Add 'Remove-Directory' --- lib/core.ps1 | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/core.ps1 b/lib/core.ps1 index 29b237c238..e9478ed79c 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -514,6 +514,45 @@ function movedir($from, $to) { } } +function Confirm-IsEmptyDirectory { + param ( + [String] + $Path + ) + return @(Get-ChildItem -Path $Path -File -Recurse -Force -ErrorAction SilentlyContinue).Length -eq 0 +} + +function Remove-Directory { + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [String] + $Path, + [Switch] + $OnlyEmpty + ) + if (Test-Path $Path) { + if ($OnlyEmpty) { + (Get-ChildItem $Path -Directory -Recurse -Force -ErrorAction SilentlyContinue).FullName | ForEach-Object { + if (Confirm-IsEmptyDirectory -Path $_) { + Remove-Directory -Path $_ + } + } + if (Confirm-IsEmptyDirectory -Path $Path) { + Remove-Directory -Path $Path + } + } else { + try { + Remove-Item $Path -Recurse -Force -ErrorAction Stop + } catch [System.IO.PathTooLongException] { + & "$env:COMSPEC" /c "rmdir /s /q $Path" + } catch [System.UnauthorizedAccessException] { + warn "Couldn't remove '$Path': unauthorized access." + } + } + } +} + function get_app_name($path) { if ($path -match '([^/\\]+)[/\\]current[/\\]') { return $matches[1].tolower() From 206c4cb42d0327f7eda36fcedabbec60345e5fa0 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Mon, 15 Jul 2019 00:13:55 +0800 Subject: [PATCH 07/15] feat(decompress): Add installer unpacker --- lib/decompress.ps1 | 176 ++++++++++++++++++++++++++++++++++++++++----- lib/install.ps1 | 110 ++++++++++++++++++---------- 2 files changed, 230 insertions(+), 56 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index e4def2702c..b6c0c93c6c 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -57,12 +57,7 @@ function Test-InnounpRequirement { [String] $Architecture ) - $Installer = installer $Manifest $Architecture - if (($Installer.type -eq "inno") -or $Manifest.innosetup) { - return $true - } else { - return $false - } + return (installer $Manifest $Architecture).type -eq 'inno' } function Test-DarkRequirement { @@ -76,12 +71,7 @@ function Test-DarkRequirement { [String] $Architecture ) - $Installer = installer $Manifest $Architecture - if (($Installer.type -eq "wix")) { - return $true - } else { - return $false - } + return (installer $Manifest $Architecture).type -eq 'wix' } function Expand-7zipArchive { @@ -192,10 +182,10 @@ function Expand-MsiArchive { } if ($ExtractDir -and (Test-Path "$DestinationPath\SourceDir")) { movedir "$DestinationPath\SourceDir\$ExtractDir" $OriDestinationPath | Out-Null - Remove-Item $DestinationPath -Recurse -Force + Remove-Directory -Path $DestinationPath } elseif ($ExtractDir) { movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null - Remove-Item $DestinationPath -Recurse -Force + Remove-Directory -Path $DestinationPath } elseif (Test-Path "$DestinationPath\SourceDir") { movedir "$DestinationPath\SourceDir" $DestinationPath | Out-Null } @@ -231,9 +221,10 @@ function Expand-InnoArchive { $LogPath = "$(Split-Path $Path)\innounp.log" $ArgList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y') switch -Regex ($ExtractDir) { - "^[^{].*" { $ArgList += "-c{app}\$ExtractDir" } - "^{.*" { $ArgList += "-c$ExtractDir" } - Default { $ArgList += "-c{app}" } + "^\.$" { break } # Suppress '-cDIR' param + "^[^{].*" { $ArgList += "-c`"{app}\$ExtractDir`""; break } + "^{.*" { $ArgList += "-c`"$ExtractDir`""; break } + Default { $ArgList += "-c`"{app}`"" } } if ($Switches) { $ArgList += (-split $Switches) @@ -299,7 +290,7 @@ function Expand-ZipArchive { } if ($ExtractDir) { movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null - Remove-Item $DestinationPath -Recurse -Force + Remove-Directory -Path $DestinationPath } if ($Removal) { # Remove original archive file @@ -347,7 +338,7 @@ function extract_7zip($path, $to, $removal) { function extract_msi($path, $to, $removal) { Show-DeprecatedWarning $MyInvocation 'Expand-MsiArchive' - Expand-MsiArchive -Path $path -DestinationPath $to -Removal:$removal + Expand-MsiArchive -Path $path -DestinationPath $to -Removal:$removal @args } function unpack_inno($path, $to, $removal) { @@ -359,3 +350,150 @@ function extract_zip($path, $to, $removal) { Show-DeprecatedWarning $MyInvocation 'Expand-ZipArchive' Expand-ZipArchive -Path $path -DestinationPath $to -Removal:$removal } + +function Expand-NsisInstaller { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [String] + $Path, + [Parameter(Position = 1)] + [String] + $DestinationPath = (Split-Path $Path), + [String] + $Architecture, + [Switch] + $Removal + ) + Expand-7ZipArchive -Path $Path -DestinationPath $DestinationPath -Removal:$Removal + if (Test-Path "$DestinationPath\`$PLUGINSDIR\app-64.7z") { + if ($Architecture -eq "64bit") { + Expand-7ZipArchive -Path "$DestinationPath\`$PLUGINSDIR\app-64.7z" -DestinationPath $DestinationPath + } else { + abort "Software doesn't support $Architecture architecture!" + } + } elseif (Test-Path "$DestinationPath\`$PLUGINSDIR\app-32.7z") { + Expand-7ZipArchive -Path "$DestinationPath\`$PLUGINSDIR\app-32.7z" -DestinationPath $DestinationPath + } + @("*uninst*", "`$*") | ForEach-Object { Get-Item "$DestinationPath\$_" | Remove-Item -Recurse -Force } +} + +function Expand-WixInstaller { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [String] + $Path, + [Parameter(Position = 1)] + [String] + $DestinationPath = (Split-Path $Path), + [String[]] + $Exclude, + [Switch] + $Removal + ) + Expand-DarkArchive -Path $Path -DestinationPath (ensure "$DestinationPath\_tmp") -Removal:$Removal + if ($Exclude) { + Remove-Item "$DestinationPath\_tmp\AttachedContainer\*.msi" -Include $Exclude -Force + } + Get-ChildItem "$DestinationPath\_tmp\AttachedContainer\*.msi" | ForEach-Object { Expand-MsiArchive $_ $DestinationPath } + Remove-Directory -Path "$DestinationPath\_tmp" +} + +function ConvertFrom-Inno { + [CmdletBinding()] + [OutputType([Hashtable])] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [System.Array] + $InputObject, + [String[]] + $Include, + [String[]] + $Exclude + ) + + $FileList = New-Object System.Collections.Generic.List[System.Object] + $Files = $InputObject -match '^Source:' + foreach ($File in $Files) { + if ($File -match 'Source: "(?(?[^\\]*).*?)"; DestDir: "(?.*?)"; (?:DestName: "(?.*?)"; )?(?:Components: (?.*?);)?') { + $FileList.Add([PSCustomObject]@{source = $Matches.source; srcdir = $Matches.srcdir; destdir = $Matches.destdir; destname = $Matches.destname; components = $Matches.components }) + } + } + if ($FileList.components) { + $Comps = $FileList.components | Select-Object -Unique + $IncludeComps = @() + $ExcludeComps = @() + if ($Include) { + $Include = $Include -split '\\' | Select-Object -Unique + foreach ($IncFile in $Include) { + $IncFile = '\b' + [Regex]::Escape($IncFile) + '\b' + $IncludeComps += $Comps | Where-Object { + ($_ -match "$IncFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$IncFile") + } + $ExcludeComps += $Comps | Where-Object { $_ -match "not[^(]*?\(?[^(]*?$IncFile" } + } + } + if ($Exclude) { + foreach ($ExcFile in $Exclude) { + $ExcFile = '\b' + [Regex]::Escape($ExcFile) + '\b' + $ExcludeComps += $Comps | Where-Object { ($_ -match "$ExcFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$ExcFile") -and ($_ -notmatch "or[^(]*?$ExcFile") -and ($_ -notmatch "$ExcFile[^(]*?or") } + } + $IncludeComps = $IncludeComps | Where-Object { $_ -notin $ExcludeComps } + } + $Included = $FileList | Where-Object { $_.components -in $IncludeComps } + $Excluded = $FileList | Where-Object { $_.components -in $ExcludeComps } + } + + return @{ + FileList = $FileList; + Excluded = $Excluded; + Included = $Included; + Extracted = ($FileList.srcdir | Select-Object -Unique) -ne '{tmp}' + } +} + +function Expand-InnoInstaller { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] + [String] + $Path, + [Parameter(Position = 1)] + [String] + $DestinationPath = (Split-Path $Path), + [String] + $ExtractDir, + [String[]] + $Include, + [String[]] + $Exclude, + [Switch] + $Removal + ) + if ($ExtractDir) { + Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal:$Removal + } else { + Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir '.' -Switches 'install_script.iss' # Just extract install script + $InstallScript = Get-Content -Path "$DestinationPath\install_script.iss" + $InnoFiles = ConvertFrom-Inno -InputObject $InstallScript -Include $Include -Exclude ($Exclude -notlike '{*}') + $InnoFiles.Extracted | Where-Object { $_ -notin ($Exclude -like '{*}') } | ForEach-Object { + Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $_ -Switches '-a' + } + if ($InnoFiles.Excluded) { + ($InnoFiles.Excluded.source -replace "{.*?}", "$DestinationPath") | Remove-Item -Force -ErrorAction Ignore + } + if ($InnoFiles.Included) { + $InnoFiles.Included | Where-Object { $_.source -match ',' } | Rename-Item -Path { $_.source -replace "{.*?}", "$DestinationPath" } -NewName { $_.destname } -Force -ErrorAction Ignore + } + Get-ChildItem -Path $DestinationPath -Filter '*,*' -Recurse | Rename-Item -NewName { $_.name -Replace ',\d', '' } -Force -ErrorAction Ignore + Get-ChildItem -Path $DestinationPath -Filter '*,*' -Recurse | Remove-Item -Force -ErrorAction Ignore + Remove-Directory -Path $DestinationPath -OnlyEmpty + Remove-Item -Path "$DestinationPath\install_script.iss" -Force + + if ($Removal) { + # Remove original archive file + Remove-Item -Path $Path -Force + } + } +} diff --git a/lib/install.ps1 b/lib/install.ps1 index 05775cfc39..b062639286 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -34,6 +34,17 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru return } + # Change 'innosetup' to 'installer.type:inno' + if ($manifest.innosetup) { + if ($manifest.$architecture.installer) { + $manifest.$architecture.installer | Add-Member -MemberType NoteProperty -Name type -Value 'inno' + } elseif ($manifest.installer) { + $manifest.installer | Add-Member -MemberType NoteProperty -Name type -Value 'inno' + } else { + $manifest | Add-Member -MemberType NoteProperty -Name installer -Value @{ type = 'inno' } + } + } + write-output "Installing '$app' ($version) [$architecture]" $dir = ensure (versiondir $app $version $global) @@ -42,7 +53,7 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru $fname = dl_urls $app $version $manifest $bucket $architecture $dir $use_cache $check_hash pre_install $manifest $architecture - run_installer $fname $manifest $architecture $dir $global + Invoke-InstallerScript -Name $fname -Manifest $manifest -Architecture $architecture -DestinationPath $dir -Global:$global ensure_install_dir_not_in_path $dir $global $dir = link_current $dir create_shims $manifest $dir $global $architecture @@ -533,24 +544,34 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c $extract_dir = $extract_dirs[$extracted] $extract_to = $extract_tos[$extracted] - + $Installer = installer $manifest $architecture + $Args = @{ + Path = "$dir\$fname" + DestinationPath = "$dir\$extract_to" + } # work out extraction method, if applicable $extract_fn = $null - if ($manifest.innosetup) { - $extract_fn = 'Expand-InnoArchive' - } elseif($fname -match '\.zip$') { - $extract_fn = 'Expand-ZipArchive' - } elseif($fname -match '\.msi$') { - $extract_fn = 'Expand-MsiArchive' - } elseif(Test-7zipRequirement -File $fname) { # 7zip - $extract_fn = 'Expand-7zipArchive' + if ($Installer.type) { + switch ($Installer.type) { + 'inno' { $ExtractFn = 'Expand-InnoInstaller'; $Args.ExtractDir = $ExtractDirs[$i]; $Args.Include = $Installer.include; $Args.Exclude = $Installer.exclude } + 'nsis' { $ExtractFn = 'Expand-NsisInstaller'; $Args.Architecture = $Architecture } + 'wix' { $ExtractFn = 'Expand-WixInstaller'; $Args.Exclude = $Installer.exclude } + Default { abort "Error in manifest: installer type $_ is not supported." } + } + } else { + switch -Regex ($fname) { + ".*\.zip$" { $extract_fn = 'Expand-ZipArchive' } + ".*\.msi$" { $extract_fn = 'Expand-MsiArchive' } + { Test-7zipRequirement -File $_ } { $extract_fn = 'Expand-7zipArchive' } + } + $Args.ExtractDir = $extract_dir } - - if($extract_fn) { + debug $Args + if ($extract_fn) { Write-Host "Extracting " -NoNewline Write-Host $(url_remote_filename $url) -f Cyan -NoNewline Write-Host " ... " -NoNewline - & $extract_fn -Path "$dir\$fname" -DestinationPath "$dir\$extract_to" -ExtractDir $extract_dir -Removal + & $extract_fn @Args -Removal Write-Host "done." -f Green $extracted++ } @@ -656,37 +677,52 @@ function args($config, $dir, $global) { @() } -function run_installer($fname, $manifest, $architecture, $dir, $global) { - $installer = installer $manifest $architecture - if($installer.script) { - write-output "Running installer script..." - Invoke-Expression (@($installer.script) -join "`r`n") - return - } +function Invoke-InstallerScript { + [CmdletBinding()] + param ( + [String] + $Name, + [PSObject] + $Manifest, + [String] + $Architecture, + [String] + $DestinationPath, + [Switch] + $Global + ) + $Installer = installer $Manifest $Architecture - if ($installer) { - install_prog $fname $dir $installer $global + if ($Installer.script) { + Write-Host "Running installer script..." -NoNewline + Invoke-Expression (@($Installer.script) -join "`r`n") + Write-Host "done." -f Green + return } -} -function install_prog($fname, $dir, $installer, $global) { - $prog = "$dir\$(coalesce $installer.file "$fname")" - if(!(is_in_dir $dir $prog)) { - abort "Error in manifest: Installer $prog is outside the app directory." + if ($Installer.type) { + return } - $arg = @(args $installer.args $dir $global) - if($prog.endswith('.ps1')) { - & $prog @arg - } else { - $installed = Invoke-ExternalCommand $prog $arg -Activity "Running installer..." - if(!$installed) { - abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again." + if ($Installer) { + $prog = "$DestinationPath\$(coalesce $Installer.file "$Name")" + if(!(is_in_dir $DestinationPath $prog)) { + abort "Error in manifest: Installer $prog is outside the app directory." } + $arg = @(args $Installer.args $DestinationPath $global) - # Don't remove installer if "keep" flag is set to true - if($installer.keep -ne "true") { - Remove-Item $prog + if($prog.endswith('.ps1')) { + & $prog @arg + } else { + $installed = Invoke-ExternalCommand $prog $arg -Activity "Running installer..." + if(!$installed) { + abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again." + } + + # Don't remove installer if "keep" flag is set to true + if($Installer.keep -ne "true") { + Remove-Item $prog + } } } } From 0c4a419758a955e9d237e75fa6cf64192f3c7c86 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Thu, 13 Jun 2019 15:32:27 +0800 Subject: [PATCH 08/15] opt(install): Separate 'Invoke-Extraction' from 'dl_urls' --- lib/install.ps1 | 92 ++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index b062639286..0994fe4008 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -36,6 +36,8 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru # Change 'innosetup' to 'installer.type:inno' if ($manifest.innosetup) { + warn "'innosetup' is deprecated, please use 'installer.type:inno' instead." + warn "If you maintain this manifest, please refer to the manifest reference docs." if ($manifest.$architecture.installer) { $manifest.$architecture.installer | Add-Member -MemberType NoteProperty -Name type -Value 'inno' } elseif ($manifest.installer) { @@ -52,8 +54,9 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru $persist_dir = persistdir $app $global $fname = dl_urls $app $version $manifest $bucket $architecture $dir $use_cache $check_hash + Invoke-Extraction -FileName $fname -Manifest $manifest -Architecture $architecture -DestinationPath $dir pre_install $manifest $architecture - Invoke-InstallerScript -Name $fname -Manifest $manifest -Architecture $architecture -DestinationPath $dir -Global:$global + Invoke-InstallerScript -AppName $app -FileName $fname -Manifest $manifest -Architecture $architecture -DestinationPath $dir -Global:$global ensure_install_dir_not_in_path $dir $global $dir = link_current $dir create_shims $manifest $dir $global $architecture @@ -498,14 +501,6 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c # can be multiple cookies: they will be used for all HTTP requests. $cookies = $manifest.cookie - $fname = $null - - # extract_dir and extract_to in manifest are like queues: for each url that - # needs to be extracted, will get the next dir from the queue - $extract_dirs = @(extract_dir $manifest $architecture) - $extract_tos = @(extract_to $manifest $architecture) - $extracted = 0; - # download first if(Test-Aria2Enabled) { dl_with_cache_aria2 $app $version $manifest $architecture $dir $cookies $use_cache $check_hash @@ -539,19 +534,36 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c } } - foreach($url in $urls) { - $fname = url_filename $url + return $urls | ForEach-Object { url_filename $_ } +} - $extract_dir = $extract_dirs[$extracted] - $extract_to = $extract_tos[$extracted] - $Installer = installer $manifest $architecture +function Invoke-Extraction { + [CmdletBinding()] + param ( + [String[]] + $FileName, + [PSObject] + $Manifest, + [String] + $Architecture, + [String] + $DestinationPath + ) + + # 'url', 'extract_dir' and 'extract_to' are paired + $Urls = @(url $Manifest $Architecture) + $ExtractDirs = @(extract_dir $Manifest $Architecture) + $ExtractTos = @(extract_to $Manifest $Architecture) + $Installer = installer $Manifest $Architecture + + for ($i = 0; $i -lt $Urls.Length; $i++) { $Args = @{ - Path = "$dir\$fname" - DestinationPath = "$dir\$extract_to" + Path = "$DestinationPath\$($FileName[$i])" + DestinationPath = "$DestinationPath\$($ExtractTos[$i])" } # work out extraction method, if applicable - $extract_fn = $null - if ($Installer.type) { + $ExtractFn = $null + if ($i -eq 0 -and $Installer.type) { switch ($Installer.type) { 'inno' { $ExtractFn = 'Expand-InnoInstaller'; $Args.ExtractDir = $ExtractDirs[$i]; $Args.Include = $Installer.include; $Args.Exclude = $Installer.exclude } 'nsis' { $ExtractFn = 'Expand-NsisInstaller'; $Args.Architecture = $Architecture } @@ -559,25 +571,22 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c Default { abort "Error in manifest: installer type $_ is not supported." } } } else { - switch -Regex ($fname) { - ".*\.zip$" { $extract_fn = 'Expand-ZipArchive' } - ".*\.msi$" { $extract_fn = 'Expand-MsiArchive' } - { Test-7zipRequirement -File $_ } { $extract_fn = 'Expand-7zipArchive' } + switch -Regex ($Args.Path) { + ".*\.zip$" { $ExtractFn = 'Expand-ZipArchive' } + ".*\.msi$" { $ExtractFn = 'Expand-MsiArchive' } + { Test-7zipRequirement -File $_ } { $ExtractFn = 'Expand-7zipArchive' } } - $Args.ExtractDir = $extract_dir + $Args.ExtractDir = $ExtractDirs[$i] } debug $Args - if ($extract_fn) { + if ($ExtractFn) { Write-Host "Extracting " -NoNewline - Write-Host $(url_remote_filename $url) -f Cyan -NoNewline + Write-Host $(url_remote_filename $Urls[$i]) -f Cyan -NoNewline Write-Host " ... " -NoNewline - & $extract_fn @Args -Removal + & $ExtractFn @Args -Removal Write-Host "done." -f Green - $extracted++ } } - - $fname # returns the last downloaded file } function cookie_header($cookies) { @@ -681,7 +690,9 @@ function Invoke-InstallerScript { [CmdletBinding()] param ( [String] - $Name, + $AppName, + [String[]] + $FileName, [PSObject] $Manifest, [String] @@ -705,23 +716,24 @@ function Invoke-InstallerScript { } if ($Installer) { - $prog = "$DestinationPath\$(coalesce $Installer.file "$Name")" - if(!(is_in_dir $DestinationPath $prog)) { - abort "Error in manifest: Installer $prog is outside the app directory." + # Installer filename is either explicit defined ('installer.file') or file name in the first URL + $ProgName = "$DestinationPath\$(coalesce $Installer.file $FileName[1])" + if(!(is_in_dir $DestinationPath $ProgName)) { + abort "Error in manifest: Installer $ProgName is outside the app directory." } - $arg = @(args $Installer.args $DestinationPath $global) + $Args = @(args $Installer.args $DestinationPath $Global) - if($prog.endswith('.ps1')) { - & $prog @arg + if($ProgName.EndsWith('.ps1')) { + & $ProgName @Args } else { - $installed = Invoke-ExternalCommand $prog $arg -Activity "Running installer..." - if(!$installed) { - abort "Installation aborted. You might need to run 'scoop uninstall $app' before trying again." + $IsInstalled = Invoke-ExternalCommand $ProgName $Args -Activity "Running installer..." + if(!$IsInstalled) { + abort "Installation aborted. You might need to run 'scoop uninstall $AppName' before trying again." } # Don't remove installer if "keep" flag is set to true if($Installer.keep -ne "true") { - Remove-Item $prog + Remove-Item $ProgName } } } From 9d8993ff9a3ac947c54ee42f022e1941df057346 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Fri, 6 Sep 2019 19:09:48 +0800 Subject: [PATCH 09/15] Allow 'installer:xxx' and fix an error --- lib/decompress.ps1 | 2 +- lib/install.ps1 | 5 ++++ schema.json | 63 +++++++++++++++++++++++++++------------------- 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 53178a7c26..9a3921cfc3 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -449,7 +449,7 @@ function ConvertFrom-Inno { FileList = $FileList; Excluded = $Excluded; Included = $Included; - Extracted = ($FileList.srcdir | Select-Object -Unique) -ne '{tmp}' + Extracted = @($FileList.srcdir | Select-Object -Unique) -ne '{tmp}' } } diff --git a/lib/install.ps1 b/lib/install.ps1 index 75309ee43a..12be5fd834 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -47,6 +47,11 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru } } + # Change 'installer:xxx' to 'installer.type:xxx' + if ($manifest.installer -is [String]) { + $manifest.installer = @{ type = $manifest.installer } + } + write-output "Installing '$app' ($version) [$architecture]" $dir = ensure (versiondir $app $version $global) diff --git a/schema.json b/schema.json index 62e4391b87..e8e242754e 100644 --- a/schema.json +++ b/schema.json @@ -263,39 +263,50 @@ ] }, "installer": { - "additionalProperties": false, - "properties": { - "_comment": { - "description": "Undocumented: only used in scoop-extras/oraclejdk* and scoop-extras/appengine-go", - "type": "string" - }, - "args": { - "$ref": "#/definitions/stringOrArrayOfStrings" - }, - "file": { - "type": "string" - }, - "script": { - "$ref": "#/definitions/stringOrArrayOfStrings" - }, - "keep": { - "type": "boolean" - }, - "type": { + "anyOf": [ + { "enum": [ "inno", "nsis", "wix" ] }, - "include": { - "$ref": "#/definitions/stringOrArrayOfStrings" - }, - "exclude": { - "$ref": "#/definitions/stringOrArrayOfStrings" + { + "additionalProperties": false, + "properties": { + "_comment": { + "description": "Undocumented: only used in scoop-extras/oraclejdk* and scoop-extras/appengine-go", + "type": "string" + }, + "args": { + "$ref": "#/definitions/stringOrArrayOfStrings" + }, + "file": { + "type": "string" + }, + "script": { + "$ref": "#/definitions/stringOrArrayOfStrings" + }, + "keep": { + "type": "boolean" + }, + "type": { + "enum": [ + "inno", + "nsis", + "wix" + ] + }, + "include": { + "$ref": "#/definitions/stringOrArrayOfStrings" + }, + "exclude": { + "$ref": "#/definitions/stringOrArrayOfStrings" + } + }, + "type": "object" } - }, - "type": "object" + ] }, "stringOrArrayOfStrings": { "anyOf": [ From 25c49ed720e16ca41880659c4aeea086693425b0 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 24 Sep 2019 18:37:14 +0800 Subject: [PATCH 10/15] Fix 'Invoke-InstallerScript' --- lib/install.ps1 | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index 12be5fd834..cffde6a175 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -715,18 +715,7 @@ function Invoke-InstallerScript { ) $Installer = installer $Manifest $Architecture - if ($Installer.script) { - Write-Host "Running installer script..." -NoNewline - Invoke-Expression (@($Installer.script) -join "`r`n") - Write-Host "done." -f Green - return - } - - if ($Installer.type) { - return - } - - if ($Installer) { + if ($Installer.file -or $Installer.args) { # Installer filename is either explicit defined ('installer.file') or file name in the first URL $ProgName = "$DestinationPath\$(coalesce $Installer.file $FileName[1])" if(!(is_in_dir $DestinationPath $ProgName)) { @@ -748,6 +737,15 @@ function Invoke-InstallerScript { } } } + + if ($Installer.script) { + Write-Host "Running installer script..." -NoNewline + Invoke-Expression (@($Installer.script) -join "`r`n") + Write-Host "done." -f Green + } + + return + } function run_uninstaller($manifest, $architecture, $dir) { From 52d83c3735ce35ee8d27beeb5a56debedda43648 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 24 Sep 2019 23:47:45 +0800 Subject: [PATCH 11/15] Minor fix Co-Authored-By: linsui <36977733+linsui@users.noreply.github.com> --- lib/install.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index cffde6a175..9ec507f932 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -499,7 +499,7 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c # we only want to show this warning once if(!$use_cache) { warn "Cache is being ignored." } - # can be multiple urls: if there are, then installer should go last, + # can be multiple urls: if there are, then installer should go first, # so that $fname is set properly $urls = @(url $manifest $architecture) @@ -717,7 +717,7 @@ function Invoke-InstallerScript { if ($Installer.file -or $Installer.args) { # Installer filename is either explicit defined ('installer.file') or file name in the first URL - $ProgName = "$DestinationPath\$(coalesce $Installer.file $FileName[1])" + $ProgName = "$DestinationPath\$(coalesce $Installer.file $FileName[0])" if(!(is_in_dir $DestinationPath $ProgName)) { abort "Error in manifest: Installer $ProgName is outside the app directory." } From ab1d057df9cad1a2df7da2c48912b60e38df24f0 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 22 Oct 2019 18:24:18 +0800 Subject: [PATCH 12/15] Fix #3700 --- lib/decompress.ps1 | 4 +--- lib/depends.ps1 | 6 +++++- test/Scoop-Decompress.Tests.ps1 | 3 --- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 9a3921cfc3..747d127238 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -17,9 +17,7 @@ function Test-7zipRequirement { } else { $URL = url $Manifest $Architecture $Installer = installer $Manifest $Architecture - if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) { - return $false - } elseif (($Installer.type -eq "nsis")) { + if (($Installer.type -eq "nsis")) { return $true } else { return ($URL | Where-Object { Test-7zipRequirement -File $_ }).Count -gt 0 diff --git a/lib/depends.ps1 b/lib/depends.ps1 index 2928b21115..597338aa8f 100644 --- a/lib/depends.ps1 +++ b/lib/depends.ps1 @@ -96,5 +96,9 @@ function install_deps($manifest, $arch) { $deps += script_deps $installer.script $deps += script_deps $post_install - return $deps | Select-Object -Unique + if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) { + $deps = @($deps | Select-Object -Unique) -ne '7zip' + } + + return $deps } diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index f7e9d7a34d..7d3f399fc9 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -8,9 +8,6 @@ $isUnix = is_unix Describe 'Requirement function' -Tag 'Scoop' { It 'Test 7zip requirement' { - Mock get_config { $true } - Test-7zipRequirement @{ url = "test.7z" } '64bit' | Should -BeFalse - Mock get_config { $false } Test-7zipRequirement @{ url = "test.7z" } '64bit' | Should -BeTrue Test-7zipRequirement @{ installer = @{ type = "nsis" } } '64bit' | Should -BeTrue Test-7zipRequirement @{ url = "test.exe" } '64bit' | Should -BeFalse From 80ecb05bd881254d91827a6b98a5741dd112515d Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 26 Nov 2019 15:05:45 +0800 Subject: [PATCH 13/15] Change variable names --- lib/decompress.ps1 | 227 ++++++++++++++------------------ lib/install.ps1 | 90 ++++++------- test/Scoop-Decompress.Tests.ps1 | 70 +++++----- 3 files changed, 180 insertions(+), 207 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index 747d127238..fe482f05eb 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -15,12 +15,12 @@ function Test-7zipRequirement { if ($File) { return $File -match '\.((gz)|(tar)|(tgz)|(lzma)|(bz)|(bz2)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))$' } else { - $URL = url $Manifest $Architecture - $Installer = installer $Manifest $Architecture - if (($Installer.type -eq "nsis")) { + $uri = url $Manifest $Architecture + $installer = installer $Manifest $Architecture + if (($installer.type -eq 'nsis')) { return $true } else { - return ($URL | Where-Object { Test-7zipRequirement -File $_ }).Count -gt 0 + return ($uri | Where-Object { Test-7zipRequirement -File $_ }).Count -gt 0 } } } @@ -36,9 +36,9 @@ function Test-LessmsiRequirement { [String] $Architecture ) - $URL = url $Manifest $Architecture + $uri = url $Manifest $Architecture if ((get_config MSIEXTRACT_USE_LESSMSI)) { - return ($URL | Where-Object { $_ -match '\.msi$' }).Count -gt 0 + return ($uri | Where-Object { $_ -match '\.msi$' }).Count -gt 0 } else { return $false } @@ -86,7 +86,7 @@ function Expand-7zipArchive { [Parameter(ValueFromRemainingArguments = $true)] [String] $Switches, - [ValidateSet("All", "Skip", "Rename")] + [ValidateSet('All', 'Skip', 'Rename')] [String] $Overwrite, [Switch] @@ -96,41 +96,41 @@ function Expand-7zipArchive { try { $7zPath = (Get-Command '7z' -CommandType Application | Select-Object -First 1).Source } catch [System.Management.Automation.CommandNotFoundException] { - abort "Cannot find external 7-Zip (7z.exe) while '7ZIPEXTRACT_USE_EXTERNAL' is 'true'!`nRun 'scoop config 7ZIPEXTRACT_USE_EXTERNAL false' or install 7-Zip manually and try again." + abort 'Cannot find external 7-Zip (7z.exe) while "7ZIPEXTRACT_USE_EXTERNAL" is "true"!`nRun "scoop config 7ZIPEXTRACT_USE_EXTERNAL false" or install 7-Zip manually and try again.' } } else { $7zPath = Get-HelperPath -Helper 7zip } - $LogPath = "$(Split-Path $Path)\7zip.log" - $ArgList = @('x', "`"$Path`"", "-o`"$DestinationPath`"", '-y') - $IsTar = ((strip_ext $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') - if (!$IsTar -and $ExtractDir) { - $ArgList += "-ir!`"$ExtractDir\*`"" + $logPath = "$(Split-Path $Path)\7zip.log" + $argList = @('x', "`"$Path`"", "-o`"$DestinationPath`"", '-y') + $isTar = ((strip_ext $Path) -match '\.tar$') -or ($Path -match '\.t[abgpx]z2?$') + if (!$isTar -and $ExtractDir) { + $argList += "-ir!`"$ExtractDir\*`"" } if ($Switches) { - $ArgList += (-split $Switches) + $argList += (-split $Switches) } switch ($Overwrite) { - "All" { $ArgList += "-aoa" } - "Skip" { $ArgList += "-aos" } - "Rename" { $ArgList += "-aou" } + 'All' { $argList += '-aoa' } + 'Skip' { $argList += '-aos' } + 'Rename' { $argList += '-aou' } } - $Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath - if (!$Status) { - abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" + $status = Invoke-ExternalCommand $7zPath $argList -LogPath $logPath + if (!$status) { + abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $logPath)`n$(new_issue_msg $app $bucket 'decompress error')" } - if (!$IsTar -and $ExtractDir) { + if (!$isTar -and $ExtractDir) { movedir "$DestinationPath\$ExtractDir" $DestinationPath | Out-Null } - if (Test-Path $LogPath) { - Remove-Item $LogPath -Force + if (Test-Path $logPath) { + Remove-Item $logPath -Force } - if ($IsTar) { + if ($isTar) { # Check for tar - $Status = Invoke-ExternalCommand $7zPath @('l', "`"$Path`"") -LogPath $LogPath - if ($Status) { - $TarFile = (Get-Content -Path $LogPath)[-4] -replace '.{53}(.*)', '$1' # get inner tar file name - Expand-7zipArchive -Path "$DestinationPath\$TarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal + $status = Invoke-ExternalCommand $7zPath @('l', "`"$Path`"") -LogPath $logPath + if ($status) { + $tarFile = (Get-Content -Path $logPath)[-4] -replace '.{53}(.*)', '$1' # get inner tar file name + Expand-7zipArchive -Path "$DestinationPath\$tarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal } else { abort "Failed to list files in $Path.`nNot a 7-Zip supported archive file." } @@ -158,31 +158,31 @@ function Expand-MsiArchive { [Switch] $Removal ) - $DestinationPath = $DestinationPath.TrimEnd("\") + $DestinationPath = $DestinationPath.TrimEnd('\') if ($ExtractDir) { - $OriDestinationPath = $DestinationPath + $oriDestinationPath = $DestinationPath $DestinationPath = "$DestinationPath\_tmp" } if ((get_config MSIEXTRACT_USE_LESSMSI)) { - $MsiPath = Get-HelperPath -Helper Lessmsi - $ArgList = @('x', "`"$Path`"", "`"$DestinationPath\\`"") + $msiPath = Get-HelperPath -Helper Lessmsi + $argList = @('x', "`"$Path`"", "`"$DestinationPath\\`"") } else { - $MsiPath = 'msiexec.exe' - $ArgList = @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath\\SourceDir`"") + $msiPath = 'msiexec.exe' + $argList = @('/a', "`"$Path`"", '/qn', "TARGETDIR=`"$DestinationPath\\SourceDir`"") } - $LogPath = "$(Split-Path $Path)\msi.log" + $logPath = "$(Split-Path $Path)\msi.log" if ($Switches) { - $ArgList += (-split $Switches) + $argList += (-split $Switches) } - $Status = Invoke-ExternalCommand $MsiPath $ArgList -LogPath $LogPath - if (!$Status) { - abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" + $status = Invoke-ExternalCommand $msiPath $argList -LogPath $logPath + if (!$status) { + abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $logPath)`n$(new_issue_msg $app $bucket 'decompress error')" } if ($ExtractDir -and (Test-Path "$DestinationPath\SourceDir")) { - movedir "$DestinationPath\SourceDir\$ExtractDir" $OriDestinationPath | Out-Null + movedir "$DestinationPath\SourceDir\$ExtractDir" $oriDestinationPath | Out-Null Remove-Directory -Path $DestinationPath } elseif ($ExtractDir) { - movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null + movedir "$DestinationPath\$ExtractDir" $oriDestinationPath | Out-Null Remove-Directory -Path $DestinationPath } elseif (Test-Path "$DestinationPath\SourceDir") { movedir "$DestinationPath\SourceDir" $DestinationPath | Out-Null @@ -190,8 +190,8 @@ function Expand-MsiArchive { if (($DestinationPath -ne (Split-Path $Path)) -and (Test-Path "$DestinationPath\$(fname $Path)")) { Remove-Item "$DestinationPath\$(fname $Path)" -Force } - if (Test-Path $LogPath) { - Remove-Item $LogPath -Force + if (Test-Path $logPath) { + Remove-Item $logPath -Force } if ($Removal) { # Remove original archive file @@ -216,23 +216,23 @@ function Expand-InnoArchive { [Switch] $Removal ) - $LogPath = "$(Split-Path $Path)\innounp.log" - $ArgList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y') + $logPath = "$(Split-Path $Path)\innounp.log" + $argList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y') switch -Regex ($ExtractDir) { - "^\.$" { break } # Suppress '-cDIR' param - "^[^{].*" { $ArgList += "-c`"{app}\$ExtractDir`""; break } - "^{.*" { $ArgList += "-c`"$ExtractDir`""; break } - Default { $ArgList += "-c`"{app}`"" } + '^\.$' { break } # Suppress '-cDIR' param + '^[^{].*' { $argList += "-c`"{app}\$ExtractDir`""; break } + '^{.*' { $argList += "-c`"$ExtractDir`""; break } + Default { $argList += '-c"{app}"' } } if ($Switches) { - $ArgList += (-split $Switches) + $argList += (-split $Switches) } - $Status = Invoke-ExternalCommand (Get-HelperPath -Helper Innounp) $ArgList -LogPath $LogPath - if (!$Status) { - abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" + $status = Invoke-ExternalCommand (Get-HelperPath -Helper Innounp) $argList -LogPath $logPath + if (!$status) { + abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $logPath)`n$(new_issue_msg $app $bucket 'decompress error')" } - if (Test-Path $LogPath) { - Remove-Item $LogPath -Force + if (Test-Path $logPath) { + Remove-Item $logPath -Force } if ($Removal) { # Remove original archive file @@ -255,39 +255,13 @@ function Expand-ZipArchive { $Removal ) if ($ExtractDir) { - $OriDestinationPath = $DestinationPath + $oriDestinationPath = $DestinationPath $DestinationPath = "$DestinationPath\_tmp" } - # All methods to unzip the file require .NET4.5+ - if ($PSVersionTable.PSVersion.Major -lt 5) { - Add-Type -AssemblyName System.IO.Compression.FileSystem - try { - [System.IO.Compression.ZipFile]::ExtractToDirectory($Path, $DestinationPath) - } catch [System.IO.PathTooLongException] { - # try to fall back to 7zip if path is too long - if (Test-HelperInstalled -Helper 7zip) { - Expand-7zipArchive $Path $DestinationPath -Removal - return - } else { - abort "Unzip failed: Windows can't handle the long paths in this zip file.`nRun 'scoop install 7zip' and try again." - } - } catch [System.IO.IOException] { - if (Test-HelperInstalled -Helper 7zip) { - Expand-7zipArchive $Path $DestinationPath -Removal - return - } else { - abort "Unzip failed: Windows can't handle the file names in this zip file.`nRun 'scoop install 7zip' and try again." - } - } catch { - abort "Unzip failed: $_" - } - } else { - # Use Expand-Archive to unzip in PowerShell 5+ - # Compatible with Pscx (https://github.com/Pscx/Pscx) - Microsoft.PowerShell.Archive\Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force - } + # Compatible with Pscx (https://github.com/Pscx/Pscx) + Microsoft.PowerShell.Archive\Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force if ($ExtractDir) { - movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null + movedir "$DestinationPath\$ExtractDir" $oriDestinationPath | Out-Null Remove-Directory -Path $DestinationPath } if ($Removal) { @@ -311,17 +285,17 @@ function Expand-DarkArchive { [Switch] $Removal ) - $LogPath = "$(Split-Path $Path)\dark.log" - $ArgList = @('-nologo', "-x `"$DestinationPath`"", "`"$Path`"") + $logPath = "$(Split-Path $Path)\dark.log" + $argList = @('-nologo', "-x `"$DestinationPath`"", "`"$Path`"") if ($Switches) { - $ArgList += (-split $Switches) + $argList += (-split $Switches) } - $Status = Invoke-ExternalCommand (Get-HelperPath -Helper Dark) $ArgList -LogPath $LogPath - if (!$Status) { - abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $LogPath)`n$(new_issue_msg $app $bucket 'decompress error')" + $status = Invoke-ExternalCommand (Get-HelperPath -Helper Dark) $argList -LogPath $logPath + if (!$status) { + abort "Failed to extract files from $Path.`nLog file:`n $(friendly_path $logPath)`n$(new_issue_msg $app $bucket 'decompress error')" } - if (Test-Path $LogPath) { - Remove-Item $LogPath -Force + if (Test-Path $logPath) { + Remove-Item $logPath -Force } if ($Removal) { # Remove original archive file @@ -365,7 +339,7 @@ function Expand-NsisInstaller { ) Expand-7ZipArchive -Path $Path -DestinationPath $DestinationPath -Removal:$Removal if (Test-Path "$DestinationPath\`$PLUGINSDIR\app-64.7z") { - if ($Architecture -eq "64bit") { + if ($Architecture -eq '64bit') { Expand-7ZipArchive -Path "$DestinationPath\`$PLUGINSDIR\app-64.7z" -DestinationPath $DestinationPath } else { abort "Software doesn't support $Architecture architecture!" @@ -373,7 +347,7 @@ function Expand-NsisInstaller { } elseif (Test-Path "$DestinationPath\`$PLUGINSDIR\app-32.7z") { Expand-7ZipArchive -Path "$DestinationPath\`$PLUGINSDIR\app-32.7z" -DestinationPath $DestinationPath } - @("*uninst*", "`$*") | ForEach-Object { Get-Item "$DestinationPath\$_" | Remove-Item -Recurse -Force } + @('*uninst*', '$*') | ForEach-Object { Get-Item "$DestinationPath\$_" | Remove-Item -Recurse -Force } } function Expand-WixInstaller { @@ -403,7 +377,7 @@ function ConvertFrom-Inno { [OutputType([Hashtable])] param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)] - [System.Array] + [Object[]] $InputObject, [String[]] $Include, @@ -411,43 +385,42 @@ function ConvertFrom-Inno { $Exclude ) - $FileList = New-Object System.Collections.Generic.List[System.Object] - $Files = $InputObject -match '^Source:' - foreach ($File in $Files) { - if ($File -match 'Source: "(?(?[^\\]*).*?)"; DestDir: "(?.*?)"; (?:DestName: "(?.*?)"; )?(?:Components: (?.*?);)?') { - $FileList.Add([PSCustomObject]@{source = $Matches.source; srcdir = $Matches.srcdir; destdir = $Matches.destdir; destname = $Matches.destname; components = $Matches.components }) + $fileList = New-Object System.Collections.Generic.List[System.Object] + foreach ($file in ($InputObject -match '^Source:')) { + if ($file -match 'Source: "(?(?[^\\]*).*?)"; DestDir: "(?.*?)"; (?:DestName: "(?.*?)"; )?(?:Components: (?.*?);)?') { + $fileList.Add([PSCustomObject]@{source = $Matches.source; srcdir = $Matches.srcdir; destdir = $Matches.destdir; destname = $Matches.destname; components = $Matches.components }) } } - if ($FileList.components) { - $Comps = $FileList.components | Select-Object -Unique - $IncludeComps = @() - $ExcludeComps = @() + if ($fileList.components) { + $comps = $fileList.components | Select-Object -Unique + $includeComps = @() + $excludeComps = @() if ($Include) { $Include = $Include -split '\\' | Select-Object -Unique - foreach ($IncFile in $Include) { - $IncFile = '\b' + [Regex]::Escape($IncFile) + '\b' - $IncludeComps += $Comps | Where-Object { - ($_ -match "$IncFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$IncFile") + foreach ($incFile in $Include) { + $incFile = '\b' + [Regex]::Escape($incFile) + '\b' + $includeComps += $comps | Where-Object { + ($_ -match "$incFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$incFile") } - $ExcludeComps += $Comps | Where-Object { $_ -match "not[^(]*?\(?[^(]*?$IncFile" } + $excludeComps += $comps | Where-Object { $_ -match "not[^(]*?\(?[^(]*?$incFile" } } } if ($Exclude) { - foreach ($ExcFile in $Exclude) { - $ExcFile = '\b' + [Regex]::Escape($ExcFile) + '\b' - $ExcludeComps += $Comps | Where-Object { ($_ -match "$ExcFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$ExcFile") -and ($_ -notmatch "or[^(]*?$ExcFile") -and ($_ -notmatch "$ExcFile[^(]*?or") } + foreach ($excFile in $Exclude) { + $excFile = '\b' + [Regex]::Escape($excFile) + '\b' + $excludeComps += $comps | Where-Object { ($_ -match "$excFile") -and ($_ -notmatch "not[^(]*?\(?[^(]*?$excFile") -and ($_ -notmatch "or[^(]*?$excFile") -and ($_ -notmatch "$excFile[^(]*?or") } } - $IncludeComps = $IncludeComps | Where-Object { $_ -notin $ExcludeComps } + $includeComps = $includeComps | Where-Object { $_ -notin $excludeComps } } - $Included = $FileList | Where-Object { $_.components -in $IncludeComps } - $Excluded = $FileList | Where-Object { $_.components -in $ExcludeComps } + $included = $fileList | Where-Object { $_.components -in $includeComps } + $excluded = $fileList | Where-Object { $_.components -in $excludeComps } } return @{ - FileList = $FileList; - Excluded = $Excluded; - Included = $Included; - Extracted = @($FileList.srcdir | Select-Object -Unique) -ne '{tmp}' + FileList = $fileList; + Excluded = $excluded; + Included = $included; + Extracted = @($fileList.srcdir | Select-Object -Unique) -ne '{tmp}' } } @@ -473,16 +446,16 @@ function Expand-InnoInstaller { Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal:$Removal } else { Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir '.' -Switches 'install_script.iss' # Just extract install script - $InstallScript = Get-Content -Path "$DestinationPath\install_script.iss" - $InnoFiles = ConvertFrom-Inno -InputObject $InstallScript -Include $Include -Exclude ($Exclude -notlike '{*}') - $InnoFiles.Extracted | Where-Object { $_ -notin ($Exclude -like '{*}') } | ForEach-Object { + $installScript = Get-Content -Path "$DestinationPath\install_script.iss" + $innoFiles = ConvertFrom-Inno -InputObject $installScript -Include $Include -Exclude ($Exclude -notlike '{*}') + $innoFiles.Extracted | Where-Object { $_ -notin ($Exclude -like '{*}') } | ForEach-Object { Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $_ -Switches '-a' } - if ($InnoFiles.Excluded) { - ($InnoFiles.Excluded.source -replace "{.*?}", "$DestinationPath") | Remove-Item -Force -ErrorAction Ignore + if ($innoFiles.Excluded) { + ($innoFiles.Excluded.source -replace '{.*?}', "$DestinationPath") | Remove-Item -Force -ErrorAction Ignore } - if ($InnoFiles.Included) { - $InnoFiles.Included | Where-Object { $_.source -match ',' } | Rename-Item -Path { $_.source -replace "{.*?}", "$DestinationPath" } -NewName { $_.destname } -Force -ErrorAction Ignore + if ($innoFiles.Included) { + $innoFiles.Included | Where-Object { $_.source -match ',' } | Rename-Item -Path { $_.source -replace '{.*?}', "$DestinationPath" } -NewName { $_.destname } -Force -ErrorAction Ignore } Get-ChildItem -Path $DestinationPath -Filter '*,*' -Recurse | Rename-Item -NewName { $_.name -Replace ',\d', '' } -Force -ErrorAction Ignore Get-ChildItem -Path $DestinationPath -Filter '*,*' -Recurse | Remove-Item -Force -ErrorAction Ignore diff --git a/lib/install.ps1 b/lib/install.ps1 index 18e413f536..2dae8e2afe 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -36,8 +36,8 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru # Change 'innosetup' to 'installer.type:inno' if ($manifest.innosetup) { - warn "'innosetup' is deprecated, please use 'installer.type:inno' instead." - warn "If you maintain this manifest, please refer to the manifest reference docs." + warn '"innosetup" is deprecated, please use "installer.type:inno" instead.' + warn 'If you maintain this manifest, please refer to the manifest reference docs.' if ($manifest.$architecture.installer) { $manifest.$architecture.installer | Add-Member -MemberType NoteProperty -Name type -Value 'inno' } elseif ($manifest.installer) { @@ -556,46 +556,46 @@ function Invoke-Extraction { ) # 'url', 'extract_dir' and 'extract_to' are paired - $Urls = @(url $Manifest $Architecture) - $ExtractDirs = @(extract_dir $Manifest $Architecture) - $ExtractTos = @(extract_to $Manifest $Architecture) - $Installer = installer $Manifest $Architecture - - for ($i = 0; $i -lt $Urls.Length; $i++) { - $Args = @{ - Path = "$DestinationPath\$($FileName[$i])" - DestinationPath = "$DestinationPath\$($ExtractTos[$i])" + $uris = @(url $Manifest $Architecture) + $extractDirs = @(extract_dir $Manifest $Architecture) + $extractTos = @(extract_to $Manifest $Architecture) + $installer = installer $Manifest $Architecture + + for ($i = 0; $i -lt $uris.Length; $i++) { + $args = @{ + Path = "$DestinationPath\$($FileName[$i])" + DestinationPath = "$DestinationPath\$($extractTos[$i])" } # work out extraction method, if applicable - $ExtractFn = $null - if ($i -eq 0 -and $Installer.type) { - switch ($Installer.type) { - 'inno' { $ExtractFn = 'Expand-InnoInstaller'; $Args.ExtractDir = $ExtractDirs[$i]; $Args.Include = $Installer.include; $Args.Exclude = $Installer.exclude } - 'nsis' { $ExtractFn = 'Expand-NsisInstaller'; $Args.Architecture = $Architecture } - 'wix' { $ExtractFn = 'Expand-WixInstaller'; $Args.Exclude = $Installer.exclude } + $extractFn = $null + if ($i -eq 0 -and $installer.type) { + switch ($installer.type) { + 'inno' { $extractFn = 'Expand-InnoInstaller'; $args.ExtractDir = $extractDirs[$i]; $args.Include = $installer.include; $args.Exclude = $installer.exclude } + 'nsis' { $extractFn = 'Expand-NsisInstaller'; $args.Architecture = $Architecture } + 'wix' { $extractFn = 'Expand-WixInstaller'; $args.Exclude = $installer.exclude } Default { abort "Error in manifest: installer type $_ is not supported." } } } else { - switch -Regex ($Args.Path) { - ".*\.zip$" { + switch -Regex ($args.Path) { + '.*\.zip$' { if (((get_config 7ZIPEXTRACT_USE_EXTERNAL) -and (Test-CommandAvailable 7z)) -or (Test-HelperInstalled -Helper 7zip)) { - $ExtractFn = 'Expand-7zipArchive' + $extractFn = 'Expand-7zipArchive' } else { - $ExtractFn = 'Expand-ZipArchive' + $extractFn = 'Expand-ZipArchive' } } - ".*\.msi$" { $ExtractFn = 'Expand-MsiArchive' } - { Test-7zipRequirement -File $_ } { $ExtractFn = 'Expand-7zipArchive' } + '.*\.msi$' { $extractFn = 'Expand-MsiArchive' } + { Test-7zipRequirement -File $_ } { $extractFn = 'Expand-7zipArchive' } } - $Args.ExtractDir = $ExtractDirs[$i] + $args.ExtractDir = $extractDirs[$i] } - debug $Args - if ($ExtractFn) { + debug $args + if ($extractFn) { Write-Host "Extracting " -NoNewline - Write-Host $(url_remote_filename $Urls[$i]) -f Cyan -NoNewline + Write-Host $(url_remote_filename $uris[$i]) -ForegroundColor Cyan -NoNewline Write-Host " ... " -NoNewline - & $ExtractFn @Args -Removal - Write-Host "done." -f Green + & $extractFn @Args -Removal + Write-Host "done." -ForegroundColor Green } } } @@ -713,35 +713,35 @@ function Invoke-InstallerScript { [Switch] $Global ) - $Installer = installer $Manifest $Architecture + $installer = installer $Manifest $Architecture - if ($Installer.file -or $Installer.args) { + if ($installer.file -or $installer.args) { # Installer filename is either explicit defined ('installer.file') or file name in the first URL - $ProgName = "$DestinationPath\$(coalesce $Installer.file $FileName[0])" - if(!(is_in_dir $DestinationPath $ProgName)) { - abort "Error in manifest: Installer $ProgName is outside the app directory." + $progName = "$DestinationPath\$(coalesce $installer.file $FileName[0])" + if(!(is_in_dir $DestinationPath $progName)) { + abort "Error in manifest: Installer $progName is outside the app directory." } - $Args = @(args $Installer.args $DestinationPath $Global) + $args = @(args $installer.args $DestinationPath $Global) - if($ProgName.EndsWith('.ps1')) { - & $ProgName @Args + if($progName.EndsWith('.ps1')) { + & $progName @Args } else { - $IsInstalled = Invoke-ExternalCommand $ProgName $Args -Activity "Running installer..." - if(!$IsInstalled) { + $isInstalled = Invoke-ExternalCommand $progName $args -Activity "Running installer..." + if(!$isInstalled) { abort "Installation aborted. You might need to run 'scoop uninstall $AppName' before trying again." } # Don't remove installer if "keep" flag is set to true - if($Installer.keep -ne "true") { - Remove-Item $ProgName + if($installer.keep -ne 'true') { + Remove-Item $progName } } } - if ($Installer.script) { - Write-Host "Running installer script..." -NoNewline - Invoke-Expression (@($Installer.script) -join "`r`n") - Write-Host "done." -f Green + if ($installer.script) { + Write-Host 'Running installer script...' -NoNewline + Invoke-Expression (@($installer.script) -join "`r`n") + Write-Host 'done.' -ForegroundColor Green } return diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index 7d3f399fc9..e6ef0ad5a2 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -8,23 +8,23 @@ $isUnix = is_unix Describe 'Requirement function' -Tag 'Scoop' { It 'Test 7zip requirement' { - Test-7zipRequirement @{ url = "test.7z" } '64bit' | Should -BeTrue - Test-7zipRequirement @{ installer = @{ type = "nsis" } } '64bit' | Should -BeTrue - Test-7zipRequirement @{ url = "test.exe" } '64bit' | Should -BeFalse + Test-7zipRequirement @{ url = 'test.7z' } '64bit' | Should -BeTrue + Test-7zipRequirement @{ installer = @{ type = 'nsis' } } '64bit' | Should -BeTrue + Test-7zipRequirement @{ url = 'test.exe' } '64bit' | Should -BeFalse Test-7zipRequirement -File 'test.xz' | Should -BeTrue Test-7zipRequirement -File 'test.bin' | Should -BeFalse } It 'Test lessmsi requirement' { Mock get_config { $true } - Test-LessmsiRequirement @{ url = "test.msi"} '64bit' | Should -BeTrue - Test-LessmsiRequirement @{ url = "test.exe"} '64bit' | Should -BeFalse + Test-LessmsiRequirement @{ url = 'test.msi'} '64bit' | Should -BeTrue + Test-LessmsiRequirement @{ url = 'test.exe'} '64bit' | Should -BeFalse } It 'Test innounp requirement' { - Test-InnounpRequirement @{ installer = @{ type = "inno" } } '64bit' | Should -BeTrue + Test-InnounpRequirement @{ installer = @{ type = 'inno' } } '64bit' | Should -BeTrue Test-InnounpRequirement @{ } '64bit' | Should -BeFalse } It 'Test dark requirement' { - Test-DarkRequirement @{ installer = @{ type = "wix" } } '64bit' | Should -BeTrue + Test-DarkRequirement @{ installer = @{ type = 'wix' } } '64bit' | Should -BeTrue Test-DarkRequirement @{ } '64bit' | Should -BeFalse } } @@ -39,7 +39,7 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { return $to } - It "Decompression test cases should exist" { + It 'Decompression test cases should exist' { $testcases = "$working_dir\TestCases.zip" $testcases | Should -Exist compute_hash $testcases 'sha256' | Should -Be '695bb18cafda52644a19afd184b2545e9c48f1a191f7ff1efc26cb034587079c' @@ -49,7 +49,7 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { } } - Context "7zip extraction" { + Context '7zip extraction' { BeforeAll { if($env:CI) { @@ -63,42 +63,42 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test4 = "$working_dir\7ZipTest4.tar.gz" } - It "extract normal compressed file" -Skip:$isUnix { - $to = test_extract "Expand-7zipArchive" $test1 + It 'extract normal compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-7zipArchive' $test1 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "extract nested compressed file" -Skip:$isUnix { + It 'extract nested compressed file' -Skip:$isUnix { # file ext: tgz - $to = test_extract "Expand-7zipArchive" $test2 + $to = test_extract 'Expand-7zipArchive' $test2 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 # file ext: tar.bz2 - $to = test_extract "Expand-7zipArchive" $test3 + $to = test_extract 'Expand-7zipArchive' $test3 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "extract nested compressed file with different inner name" -Skip:$isUnix { - $to = test_extract "Expand-7zipArchive" $test4 + It 'extract nested compressed file with different inner name' -Skip:$isUnix { + $to = test_extract 'Expand-7zipArchive' $test4 $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test1 | Should -Exist - test_extract "Expand-7zipArchive" $test1 $true + test_extract 'Expand-7zipArchive' $test1 $true $test1 | Should -Not -Exist } } - Context "msi extraction" { + Context 'msi extraction' { BeforeAll { if($env:CI) { @@ -110,29 +110,29 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test2 = "$working_dir\MSITestNull.msi" } - It "extract normal MSI file" -Skip:$isUnix { + It 'extract normal MSI file' -Skip:$isUnix { mock get_config { $false } - $to = test_extract "Expand-MsiArchive" $test1 + $to = test_extract 'Expand-MsiArchive' $test1 $to | Should -Exist "$to\MSITest\empty" | Should -Exist (Get-ChildItem "$to\MSITest").Count | Should -Be 1 } - It "extract empty MSI file using lessmsi" -Skip:$isUnix { + It 'extract empty MSI file using lessmsi' -Skip:$isUnix { mock get_config { $true } - $to = test_extract "Expand-MsiArchive" $test2 + $to = test_extract 'Expand-MsiArchive' $test2 $to | Should -Exist } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { mock get_config { $false } $test1 | Should -Exist - test_extract "Expand-MsiArchive" $test1 $true + test_extract 'Expand-MsiArchive' $test1 $true $test1 | Should -Not -Exist } } - Context "inno extraction" { + Context 'inno extraction' { BeforeAll { if($env:CI) { @@ -143,36 +143,36 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' { $test = "$working_dir\InnoTest.exe" } - It "extract Inno Setup file" -Skip:$isUnix { - $to = test_extract "Expand-InnoArchive" $test + It 'extract Inno Setup file' -Skip:$isUnix { + $to = test_extract 'Expand-InnoArchive' $test $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test | Should -Exist - test_extract "Expand-InnoArchive" $test $true + test_extract 'Expand-InnoArchive' $test $true $test | Should -Not -Exist } } - Context "zip extraction" { + Context 'zip extraction' { BeforeAll { $test = "$working_dir\ZipTest.zip" } - It "extract compressed file" -Skip:$isUnix { - $to = test_extract "Expand-ZipArchive" $test + It 'extract compressed file' -Skip:$isUnix { + $to = test_extract 'Expand-ZipArchive' $test $to | Should -Exist "$to\empty" | Should -Exist (Get-ChildItem $to).Count | Should -Be 1 } - It "works with '-Removal' switch (`$removal param)" -Skip:$isUnix { + It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix { $test | Should -Exist - test_extract "Expand-ZipArchive" $test $true + test_extract 'Expand-ZipArchive' $test $true $test | Should -Not -Exist } } From 3003667442cb95466b8eed34c2109fafcf8f21e2 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Tue, 26 Nov 2019 17:11:29 +0800 Subject: [PATCH 14/15] Add backward compatible of 'Expand-InnoInstaller' --- lib/decompress.ps1 | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/decompress.ps1 b/lib/decompress.ps1 index fe482f05eb..021b31048e 100644 --- a/lib/decompress.ps1 +++ b/lib/decompress.ps1 @@ -444,12 +444,12 @@ function Expand-InnoInstaller { ) if ($ExtractDir) { Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal:$Removal - } else { + } elseif ($Include -or $Exclude) { Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir '.' -Switches 'install_script.iss' # Just extract install script $installScript = Get-Content -Path "$DestinationPath\install_script.iss" $innoFiles = ConvertFrom-Inno -InputObject $installScript -Include $Include -Exclude ($Exclude -notlike '{*}') $innoFiles.Extracted | Where-Object { $_ -notin ($Exclude -like '{*}') } | ForEach-Object { - Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $_ -Switches '-a' + Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -ExtractDir $_ -Switches '-a' -Removal:$Removal } if ($innoFiles.Excluded) { ($innoFiles.Excluded.source -replace '{.*?}', "$DestinationPath") | Remove-Item -Force -ErrorAction Ignore @@ -461,10 +461,7 @@ function Expand-InnoInstaller { Get-ChildItem -Path $DestinationPath -Filter '*,*' -Recurse | Remove-Item -Force -ErrorAction Ignore Remove-Directory -Path $DestinationPath -OnlyEmpty Remove-Item -Path "$DestinationPath\install_script.iss" -Force - - if ($Removal) { - # Remove original archive file - Remove-Item -Path $Path -Force - } + } else { + Expand-InnoArchive -Path $Path -DestinationPath $DestinationPath -Removal:$Removal } } From 2c146d1b45067c10a796cea471bf4c68d7e91b4a Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Sat, 8 Jan 2022 01:42:31 +0800 Subject: [PATCH 15/15] style(install): Do some styling --- lib/install.ps1 | 55 ++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/lib/install.ps1 b/lib/install.ps1 index 4e4cc328da..e5877cf3f0 100644 --- a/lib/install.ps1 +++ b/lib/install.ps1 @@ -618,21 +618,34 @@ function Invoke-Extraction { $installer = installer $Manifest $Architecture for ($i = 0; $i -lt $uris.Length; $i++) { - $args = @{ - Path = "$DestinationPath\$($FileName[$i])" + $fnArgs = @{ + Path = "$DestinationPath\$($FileName[$i])" DestinationPath = "$DestinationPath\$($extractTos[$i])" } # work out extraction method, if applicable $extractFn = $null if ($i -eq 0 -and $installer.type) { switch ($installer.type) { - 'inno' { $extractFn = 'Expand-InnoInstaller'; $args.ExtractDir = $extractDirs[$i]; $args.Include = $installer.include; $args.Exclude = $installer.exclude } - 'nsis' { $extractFn = 'Expand-NsisInstaller'; $args.Architecture = $Architecture } - 'wix' { $extractFn = 'Expand-WixInstaller'; $args.Exclude = $installer.exclude } - Default { abort "Error in manifest: installer type $_ is not supported." } + 'inno' { + $extractFn = 'Expand-InnoInstaller' + $fnArgs.ExtractDir = $extractDirs[$i] + $fnArgs.Include = $installer.include + $fnArgs.Exclude = $installer.exclude + } + 'nsis' { + $extractFn = 'Expand-NsisInstaller' + $fnArgs.Architecture = $Architecture + } + 'wix' { + $extractFn = 'Expand-WixInstaller' + $fnArgs.Exclude = $installer.exclude + } + Default { + abort "Error in manifest: installer type $_ is not supported." + } } } else { - switch -Regex ($args.Path) { + switch -Regex ($fnArgs.Path) { '.*\.zip$' { if (((get_config 7ZIPEXTRACT_USE_EXTERNAL) -and (Test-CommandAvailable 7z)) -or (Test-HelperInstalled -Helper 7zip)) { $extractFn = 'Expand-7zipArchive' @@ -656,15 +669,15 @@ function Invoke-Extraction { continue } } - $args.ExtractDir = $extractDirs[$i] + $fnArgs.ExtractDir = $extractDirs[$i] } - debug $args + debug $fnArgs if ($extractFn) { - Write-Host "Extracting " -NoNewline + Write-Host 'Extracting ' -NoNewline Write-Host $(url_remote_filename $uris[$i]) -ForegroundColor Cyan -NoNewline - Write-Host " ... " -NoNewline - & $extractFn @Args -Removal - Write-Host "done." -ForegroundColor Green + Write-Host ' ... ' -NoNewline + & $extractFn @fnArgs -Removal + Write-Host 'done.' -ForegroundColor Green } } } @@ -786,22 +799,22 @@ function Invoke-InstallerScript { if ($installer.file -or $installer.args) { # Installer filename is either explicit defined ('installer.file') or file name in the first URL - $progName = "$DestinationPath\$(coalesce $installer.file $FileName[0])" - if(!(is_in_dir $DestinationPath $progName)) { + $progName = "$DestinationPath\$(coalesce $installer.file $FileName[0])" + if (!(is_in_dir $DestinationPath $progName)) { abort "Error in manifest: Installer $progName is outside the app directory." } - $args = @(args $installer.args $DestinationPath $Global) + $fnArgs = @(args $installer.args $DestinationPath $Global) - if($progName.EndsWith('.ps1')) { - & $progName @Args + if ($progName.EndsWith('.ps1')) { + & $progName @fnArgs } else { - $isInstalled = Invoke-ExternalCommand $progName $args -Activity "Running installer..." - if(!$isInstalled) { + $isInstalled = Invoke-ExternalCommand $progName $fnArgs -Activity 'Running installer...' + if (!$isInstalled) { abort "Installation aborted. You might need to run 'scoop uninstall $AppName' before trying again." } # Don't remove installer if "keep" flag is set to true - if($installer.keep -ne 'true') { + if ($installer.keep -ne 'true') { Remove-Item $progName } }