From 2f35e2a802175d22b9d0a52e1a82376bcb8ebff1 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 15:50:31 +0100 Subject: [PATCH 01/19] refactor(config): Move configuration handling to core.ps1 - Migrate ~\.scoop to ~\.config\scoop\config.json - Remove hashtable and hashtable_val functions because ConvertFrom-Json is enough - Add PowerShell 6 time conversion to tests --- lib/config.ps1 | 95 ------------------------------------- lib/core.ps1 | 78 ++++++++++++++++++++++++++++++ test/Scoop-Config.Tests.ps1 | 23 +++++---- 3 files changed, 89 insertions(+), 107 deletions(-) delete mode 100644 lib/config.ps1 diff --git a/lib/config.ps1 b/lib/config.ps1 deleted file mode 100644 index 10edc51da0..0000000000 --- a/lib/config.ps1 +++ /dev/null @@ -1,95 +0,0 @@ -$cfgpath = "~/.scoop" - -function hashtable($obj) { - $h = @{ } - $obj.psobject.properties | ForEach-Object { - $h[$_.name] = hashtable_val $_.value - } - return $h -} - -function hashtable_val($obj) { - if($null -eq $obj) { return $null } - if($obj -is [array]) { - $arr = @() - $obj | ForEach-Object { - $val = hashtable_val $_ - if($val -is [array]) { - $arr += ,@($val) - } else { - $arr += $val - } - } - return ,$arr - } - if($obj.gettype().name -eq 'pscustomobject') { # -is is unreliable - return hashtable $obj - } - if($obj -eq [bool]::TrueString -or $obj -eq [bool]::FalseString) { - $obj = [System.Convert]::ToBoolean($obj) - } - return $obj # assume primitive -} - -function load_cfg { - if(!(test-path $cfgpath)) { return $null } - - try { - hashtable (Get-Content $cfgpath -raw | convertfrom-json -ea stop) - } catch { - write-host "ERROR loading $cfgpath`: $($_.exception.message)" - } -} - -function get_config($name, $default) { - if($null -eq $cfg.$name -and $null -ne $default) { - return $default - } - return $cfg.$name -} - -function set_config($name, $val) { - if(!$cfg) { - $cfg = @{ $name = $val } - } else { - if($val -eq [bool]::TrueString -or $val -eq [bool]::FalseString) { - $val = [System.Convert]::ToBoolean($val) - } - $cfg.$name = $val - } - - if($null -eq $val) { - $cfg.remove($name) - } - - convertto-json $cfg | set-content $cfgpath -encoding utf8 -} - -$cfg = load_cfg - -# setup proxy -# note: '@' and ':' in password must be escaped, e.g. 'p@ssword' -> p\@ssword' -$p = get_config 'proxy' -if($p) { - try { - $cred, $address = $p -split '(? $($Invocation.PSCommandPath):$($Invocation.ScriptLineNumber):$($Invocation.OffsetInLine)" -ForegroundColor DarkGray } +function load_cfg($file) { + if(!(Test-Path $file)) { + return $null + } + + try { + return (Get-Content $file -Raw | ConvertFrom-Json -ErrorAction Stop) + } catch { + Write-Host "ERROR loading $file`: $($_.exception.message)" + } +} + +$scoopConfig = load_cfg $configFile + +function get_config($name, $default) { + if($null -eq $scoopConfig.$name -and $null -ne $default) { + return $default + } + return $scoopConfig.$name +} + +function set_config($name, $val) { + if(!$scoopConfig) { + $scoopConfig = @{ $name = $val } + } else { + if($val -eq [bool]::TrueString -or $val -eq [bool]::FalseString) { + $val = [System.Convert]::ToBoolean($val) + } + $scoopConfig.$name = $val + } + + if($null -eq $val) { + $scoopConfig.remove($name) + } + + ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding utf8 +} + +function setup_proxy() { + # note: '@' and ':' in password must be escaped, e.g. 'p@ssword' -> p\@ssword' + $proxy = get_config 'proxy' + if(!$proxy) { + return + } + try { + $credentials, $address = $proxy -split '(? Date: Mon, 18 Mar 2019 15:51:25 +0100 Subject: [PATCH 02/19] refactor(bin/libexec): remove config.ps1 imports --- bin/checkhashes.ps1 | 1 - bin/checkurls.ps1 | 1 - bin/checkver.ps1 | 1 - bin/scoop.ps1 | 1 - libexec/scoop-alias.ps1 | 1 - libexec/scoop-config.ps1 | 2 +- libexec/scoop-depends.ps1 | 1 - libexec/scoop-install.ps1 | 1 - libexec/scoop-reset.ps1 | 1 - libexec/scoop-search.ps1 | 1 - libexec/scoop-status.ps1 | 1 - libexec/scoop-update.ps1 | 1 - libexec/scoop-virustotal.ps1 | 1 - 13 files changed, 1 insertion(+), 13 deletions(-) diff --git a/bin/checkhashes.ps1 b/bin/checkhashes.ps1 index b84317f910..5233a96dd6 100644 --- a/bin/checkhashes.ps1 +++ b/bin/checkhashes.ps1 @@ -42,7 +42,6 @@ param( . "$PSScriptRoot\..\lib\core.ps1" . "$PSScriptRoot\..\lib\manifest.ps1" -. "$PSScriptRoot\..\lib\config.ps1" . "$PSScriptRoot\..\lib\buckets.ps1" . "$PSScriptRoot\..\lib\autoupdate.ps1" . "$PSScriptRoot\..\lib\json.ps1" diff --git a/bin/checkurls.ps1 b/bin/checkurls.ps1 index 48e6af13e5..6e08a86e84 100644 --- a/bin/checkurls.ps1 +++ b/bin/checkurls.ps1 @@ -28,7 +28,6 @@ param( . "$PSScriptRoot\..\lib\core.ps1" . "$PSScriptRoot\..\lib\manifest.ps1" -. "$PSScriptRoot\..\lib\config.ps1" . "$PSScriptRoot\..\lib\install.ps1" $Dir = Resolve-Path $Dir diff --git a/bin/checkver.ps1 b/bin/checkver.ps1 index a242037a00..831195c0b4 100644 --- a/bin/checkver.ps1 +++ b/bin/checkver.ps1 @@ -65,7 +65,6 @@ param( . "$psscriptroot\..\lib\core.ps1" . "$psscriptroot\..\lib\manifest.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\buckets.ps1" . "$psscriptroot\..\lib\autoupdate.ps1" . "$psscriptroot\..\lib\json.ps1" diff --git a/bin/scoop.ps1 b/bin/scoop.ps1 index 47532e6e7f..7ae7973034 100644 --- a/bin/scoop.ps1 +++ b/bin/scoop.ps1 @@ -3,7 +3,6 @@ param($cmd) set-strictmode -off -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\core.ps1" . "$psscriptroot\..\lib\git.ps1" . "$psscriptroot\..\lib\buckets.ps1" diff --git a/libexec/scoop-alias.ps1 b/libexec/scoop-alias.ps1 index d5cc66933d..5f1e785e73 100644 --- a/libexec/scoop-alias.ps1 +++ b/libexec/scoop-alias.ps1 @@ -25,7 +25,6 @@ param( . "$psscriptroot\..\lib\core.ps1" . "$psscriptroot\..\lib\help.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\install.ps1" $script:config_alias = "alias" diff --git a/libexec/scoop-config.ps1 b/libexec/scoop-config.ps1 index bea33c59ad..3b81c6ea9d 100644 --- a/libexec/scoop-config.ps1 +++ b/libexec/scoop-config.ps1 @@ -28,7 +28,7 @@ param($name, $value) -. "$psscriptroot\..\lib\config.ps1" +. "$psscriptroot\..\lib\core.ps1" . "$psscriptroot\..\lib\help.ps1" reset_aliases diff --git a/libexec/scoop-depends.ps1 b/libexec/scoop-depends.ps1 index 1a4e01388f..50193ccdfd 100644 --- a/libexec/scoop-depends.ps1 +++ b/libexec/scoop-depends.ps1 @@ -7,7 +7,6 @@ . "$psscriptroot\..\lib\buckets.ps1" . "$psscriptroot\..\lib\getopt.ps1" . "$psscriptroot\..\lib\decompress.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\help.ps1" reset_aliases diff --git a/libexec/scoop-install.ps1 b/libexec/scoop-install.ps1 index 8a05ca66e7..a4ab77362e 100644 --- a/libexec/scoop-install.ps1 +++ b/libexec/scoop-install.ps1 @@ -27,7 +27,6 @@ . "$psscriptroot\..\lib\help.ps1" . "$psscriptroot\..\lib\getopt.ps1" . "$psscriptroot\..\lib\depends.ps1" -. "$psscriptroot\..\lib\config.ps1" reset_aliases diff --git a/libexec/scoop-reset.ps1 b/libexec/scoop-reset.ps1 index f11dc20df1..4ce10098df 100644 --- a/libexec/scoop-reset.ps1 +++ b/libexec/scoop-reset.ps1 @@ -10,7 +10,6 @@ . "$psscriptroot\..\lib\getopt.ps1" . "$psscriptroot\..\lib\install.ps1" . "$psscriptroot\..\lib\versions.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\shortcuts.ps1" reset_aliases diff --git a/libexec/scoop-search.ps1 b/libexec/scoop-search.ps1 index 5ec6a8a014..7758fa53c8 100644 --- a/libexec/scoop-search.ps1 +++ b/libexec/scoop-search.ps1 @@ -9,7 +9,6 @@ param($query) . "$psscriptroot\..\lib\buckets.ps1" . "$psscriptroot\..\lib\manifest.ps1" . "$psscriptroot\..\lib\versions.ps1" -. "$psscriptroot\..\lib\config.ps1" reset_aliases diff --git a/libexec/scoop-status.ps1 b/libexec/scoop-status.ps1 index 685a547613..cd22f16472 100644 --- a/libexec/scoop-status.ps1 +++ b/libexec/scoop-status.ps1 @@ -6,7 +6,6 @@ . "$psscriptroot\..\lib\buckets.ps1" . "$psscriptroot\..\lib\versions.ps1" . "$psscriptroot\..\lib\depends.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\git.ps1" reset_aliases diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index 5556b52b98..03081130bc 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -22,7 +22,6 @@ . "$psscriptroot\..\lib\versions.ps1" . "$psscriptroot\..\lib\getopt.ps1" . "$psscriptroot\..\lib\depends.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\git.ps1" . "$psscriptroot\..\lib\install.ps1" diff --git a/libexec/scoop-virustotal.ps1 b/libexec/scoop-virustotal.ps1 index ef320270e5..f636d126a2 100644 --- a/libexec/scoop-virustotal.ps1 +++ b/libexec/scoop-virustotal.ps1 @@ -40,7 +40,6 @@ . "$psscriptroot\..\lib\manifest.ps1" . "$psscriptroot\..\lib\buckets.ps1" . "$psscriptroot\..\lib\json.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\decompress.ps1" . "$psscriptroot\..\lib\install.ps1" . "$psscriptroot\..\lib\depends.ps1" From e168bdbef862158662b678f3903169379193c5f4 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 15:59:02 +0100 Subject: [PATCH 03/19] refactor(config): Fix config value removing --- lib/core.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index a726ad3836..ac1120f171 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -98,7 +98,7 @@ function set_config($name, $val) { } if($null -eq $val) { - $scoopConfig.remove($name) + $scoopConfig.PSObject.Properties.Remove($name) } ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding utf8 From 391a5d4defa132c56f56a63cff1bc161476e3a9a Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 16:43:08 +0100 Subject: [PATCH 04/19] refactor(alias): Apply config changes to scoop-alias command --- libexec/scoop-alias.ps1 | 112 ++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/libexec/scoop-alias.ps1 b/libexec/scoop-alias.ps1 index 5f1e785e73..fb4d68da33 100644 --- a/libexec/scoop-alias.ps1 +++ b/libexec/scoop-alias.ps1 @@ -30,85 +30,87 @@ param( $script:config_alias = "alias" function init_alias_config { - $aliases = get_config $script:config_alias - if(!$aliases) { - $aliases = @{} - } + $aliases = get_config $script:config_alias + if(!$aliases) { + $aliases = @{} + } - $aliases + return $aliases } function add_alias($name, $command) { - if(!$command) { - abort "Can't create an empty alias." - } + if(!$command) { + abort "Can't create an empty alias." + } - # get current aliases from config - $aliases = init_alias_config - if($aliases.containskey($name)) { - abort "Alias $name already exists." - } + # get current aliases from config + $aliases = init_alias_config + if($aliases.$name) { + abort "Alias $name already exists." + } - $alias_file = "scoop-$name" + $alias_file = "scoop-$name" - # generate script - $shimdir = shimdir $false - $script = + # generate script + $shimdir = shimdir $false + $script = @" # Summary: $description $command "@ - $script | out-file "$shimdir\$alias_file.ps1" -encoding utf8 + $script | out-file "$shimdir\$alias_file.ps1" -encoding utf8 - # add alias to config - $aliases += @{ $name = $alias_file } - set_config $script:config_alias $aliases + # add alias to config + $aliases | Add-Member -MemberType NoteProperty -Name $name -Value $alias_file + + set_config $script:config_alias $aliases } function rm_alias($name) { - $aliases = init_alias_config - if(!$name) { - abort "Which alias should be removed?" - } + $aliases = init_alias_config + if(!$name) { + abort "Which alias should be removed?" + } - if($aliases.containskey($name)) { - "Removing alias $name..." + if($aliases.$name) { + "Removing alias $name..." - rm_shim $aliases.get_item($name) (shimdir $false) + rm_shim $aliases.$name (shimdir $false) - $aliases.remove($name) - set_config $script:config_alias $aliases - } - else { abort "Alias $name doesn't exist." } + $aliases.PSObject.Properties.Remove($name) + set_config $script:config_alias $aliases + } else { + abort "Alias $name doesn't exist." + } } function list_aliases { - $aliases = @() - - (init_alias_config).GetEnumerator() | ForEach-Object { - $content = Get-Content (command_path $_.name) - $command = ($content | Select-Object -Skip 1).Trim() - $summary = (summary $content).Trim() - - $aliases += New-Object psobject -Property @{Name=$_.name; Summary=$summary; Command=$command} - } - - if(!$aliases.count) { - warn "No aliases founds." - } - $aliases = $aliases.GetEnumerator() | Sort-Object Name - if($verbose) { - return $aliases | Select-Object Name, Command, Summary | Format-Table -autosize -wrap - } else { - return $aliases | Select-Object Name, Command | Format-Table -autosize -hidetablehead -wrap - } + $aliases = @() + + (init_alias_config).PSObject.Properties.GetEnumerator() | ForEach-Object { + $content = Get-Content (command_path $_.Name) + $command = ($content | Select-Object -Skip 1).Trim() + $summary = (summary $content).Trim() + + $aliases += New-Object psobject -Property @{Name=$_.name; Summary=$summary; Command=$command} + } + + if(!$aliases.count) { + warn "No aliases founds." + } + $aliases = $aliases.GetEnumerator() | Sort-Object Name + if($verbose) { + return $aliases | Select-Object Name, Command, Summary | Format-Table -autosize -wrap + } else { + return $aliases | Select-Object Name, Command | Format-Table -autosize -hidetablehead -wrap + } } switch($opt) { - "add" { add_alias $name $command } - "rm" { rm_alias $name } - "list" { list_aliases } - default { my_usage; exit 1 } + "add" { add_alias $name $command } + "rm" { rm_alias $name } + "list" { list_aliases } + default { my_usage; exit 1 } } exit 0 From 07b6165718a6f727a5c7c2c8702c525625df6449 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Mon, 18 Mar 2019 16:45:55 +0100 Subject: [PATCH 05/19] refactor(core): Prefer $XDG_CONFIG_HOME over ~\.config Co-Authored-By: r15ch13 --- lib/core.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index ac1120f171..e735b8a96c 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -18,7 +18,8 @@ $globaldir = $env:SCOOP_GLOBAL, "$env:ProgramData\scoop" | Select-Object -first # Use at your own risk. $cachedir = $env:SCOOP_CACHE, "$scoopdir\cache" | Select-Object -first 1 -$configFile = "$env:USERPROFILE\.config\scoop\config.json" +$configHome = $env:XDG_CONFIG_HOME, "$env:USERPROFILE\.config" | Select-Object -First 1 +$configFile = "$configHome\scoop\config.json" if ((Test-Path "$env:USERPROFILE\.scoop") -and !(Test-Path $configFile)) { New-Item -ItemType Directory "$env:USERPROFILE\.config\scoop" -ErrorAction Ignore | Out-Null Move-Item "$env:USERPROFILE\.scoop" $configFile From 3d97e5cd4b66808b6d121152d87c7c8252347342 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Mon, 18 Mar 2019 16:50:50 +0100 Subject: [PATCH 06/19] refactor(core): Use ASCII encoding because of PowerShell 5 Encode file in "ASCII", since "UTF8" in Powershell 5 will be "UTF8-with-BOM", while "ASCII" be "UTF8". Co-Authored-By: r15ch13 --- lib/core.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index e735b8a96c..6367c6ffe5 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -102,7 +102,7 @@ function set_config($name, $val) { $scoopConfig.PSObject.Properties.Remove($name) } - ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding utf8 + ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding ASCII } function setup_proxy() { From 9be8fb6d9a90d69d19de8abf79398512463607c4 Mon Sep 17 00:00:00 2001 From: Hsiao-nan Cheung Date: Mon, 18 Mar 2019 16:52:05 +0100 Subject: [PATCH 07/19] refactor(core): ensure config path exists Co-Authored-By: r15ch13 --- lib/core.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/core.ps1 b/lib/core.ps1 index 6367c6ffe5..165bc96466 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -90,6 +90,7 @@ function get_config($name, $default) { function set_config($name, $val) { if(!$scoopConfig) { + ensure (Split-Path -Path $configFile) | Out-Null $scoopConfig = @{ $name = $val } } else { if($val -eq [bool]::TrueString -or $val -eq [bool]::FalseString) { From eed3d6bf1890a749d46dd87b4183639d4d661cad Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 16:55:37 +0100 Subject: [PATCH 08/19] refactor(core): Remove hard-coded path --- lib/core.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index 165bc96466..01e8b4316c 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -21,7 +21,7 @@ $cachedir = $env:SCOOP_CACHE, "$scoopdir\cache" | Select-Object -first 1 $configHome = $env:XDG_CONFIG_HOME, "$env:USERPROFILE\.config" | Select-Object -First 1 $configFile = "$configHome\scoop\config.json" if ((Test-Path "$env:USERPROFILE\.scoop") -and !(Test-Path $configFile)) { - New-Item -ItemType Directory "$env:USERPROFILE\.config\scoop" -ErrorAction Ignore | Out-Null + New-Item -ItemType Directory (Split-Path -Path $configFile) -ErrorAction Ignore | Out-Null Move-Item "$env:USERPROFILE\.scoop" $configFile warn "Scoops configurations has been migrated from '~/.scoop'" warn "to '$configFile'" From 6caee6a287ffd3e7cf0edc548c890e0087c6636e Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 17:24:01 +0100 Subject: [PATCH 09/19] refactor(config): Fix set_config function --- lib/core.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index 01e8b4316c..8e7f2eaa86 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -88,18 +88,18 @@ function get_config($name, $default) { return $scoopConfig.$name } -function set_config($name, $val) { +function set_config($name, $value) { if(!$scoopConfig) { ensure (Split-Path -Path $configFile) | Out-Null - $scoopConfig = @{ $name = $val } + $scoopConfig = @{ $name = $value } } else { - if($val -eq [bool]::TrueString -or $val -eq [bool]::FalseString) { - $val = [System.Convert]::ToBoolean($val) + if($value -eq [bool]::TrueString -or $value -eq [bool]::FalseString) { + $value = [System.Convert]::ToBoolean($value) } - $scoopConfig.$name = $val + $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value } - if($null -eq $val) { + if($null -eq $value) { $scoopConfig.PSObject.Properties.Remove($name) } From 519af17a2196983a853d36ff8646d332c7397b55 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 17:24:18 +0100 Subject: [PATCH 10/19] refactor(config): Add more tests for load_config and get_config --- test/Scoop-Config.Tests.ps1 | 50 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/test/Scoop-Config.Tests.ps1 b/test/Scoop-Config.Tests.ps1 index 812a9efd4d..fd90b23036 100644 --- a/test/Scoop-Config.Tests.ps1 +++ b/test/Scoop-Config.Tests.ps1 @@ -1,19 +1,45 @@ . "$psscriptroot\..\lib\core.ps1" -describe "hashtable" -Tag 'Scoop' { - $json = '{ "one": 1, "two": [ { "a": "a" }, "b", 2 ], "three": { "four": 4 }, "five": true, "six": false, "seven": "\/Date(1529917395805)\/", "eight": "2019-03-18T15:22:09.3930000+01:00" }' +describe "config" -Tag 'Scoop' { + BeforeAll { + $json = '{ "one": 1, "two": [ { "a": "a" }, "b", 2 ], "three": { "four": 4 }, "five": true, "six": false, "seven": "\/Date(1529917395805)\/", "eight": "2019-03-18T15:22:09.3930000+01:00" }' + } - it "converts pscustomobject to hashtable" { + it "converts JSON to PSObject" { $obj = ConvertFrom-Json $json - $obj.one | should -beexactly 1 - $obj.two[0].a | should -be "a" - $obj.two[1] | should -be "b" - $obj.two[2] | should -beexactly 2 - $obj.three.four | should -beexactly 4 - $obj.five | should -beexactly $true - $obj.six | should -beexactly $false - [System.DateTime]::Equals($obj.seven, $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | should -betrue - [System.DateTime]::Equals([System.DateTime]::parse($obj.eight), $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | should -betrue + $obj.one | Should -BeExactly 1 + $obj.two[0].a | Should -Be "a" + $obj.two[1] | Should -Be "b" + $obj.two[2] | Should -BeExactly 2 + $obj.three.four | Should -BeExactly 4 + $obj.five | Should -BeTrue + $obj.six | Should -BeFalse + [System.DateTime]::Equals($obj.seven, $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue + [System.DateTime]::Equals([System.DateTime]::parse($obj.eight), $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue + } + + it "load_config should return PSObject" { + mock Get-Content { $json } + mock Test-Path { $true } + (load_cfg 'file') | Should -Not -BeNullOrEmpty + (load_cfg 'file') | Should -BeOfType System.Management.Automation.PSObject + (load_cfg 'file').one | Should -BeExactly 1 + + } + + it "get_config should return exactly the same values" { + $scoopConfig = ConvertFrom-Json $json + get_config 'does_not_exist' 'default' | Should -Be 'default' + + get_config 'one' | Should -BeExactly 1 + (get_config 'two')[0].a | Should -Be "a" + (get_config 'two')[1] | Should -Be "b" + (get_config 'two')[2] | Should -BeExactly 2 + (get_config 'three').four | Should -BeExactly 4 + get_config 'five' | Should -BeTrue + get_config 'six' | Should -BeFalse + [System.DateTime]::Equals((get_config 'seven'), $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue + [System.DateTime]::Equals([System.DateTime]::parse((get_config 'eight')), $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue } } From 049aaf92c8e5167a250f059000ea953915645fad Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 17:28:04 +0100 Subject: [PATCH 11/19] refactor(config): Fix set_config --- lib/core.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index 8e7f2eaa86..e0e42e4145 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -96,7 +96,11 @@ function set_config($name, $value) { if($value -eq [bool]::TrueString -or $value -eq [bool]::FalseString) { $value = [System.Convert]::ToBoolean($value) } - $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value + if($scoopConfig.$name) { + $scoopConfig.$name = $value + } else { + $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value + } } if($null -eq $value) { From c1ec8958b5d5545b4d6e6939b425b1f8c09b867b Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 18 Mar 2019 17:30:33 +0100 Subject: [PATCH 12/19] refactor(config): Fix warning message --- lib/core.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index e0e42e4145..ff102fd947 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -23,8 +23,8 @@ $configFile = "$configHome\scoop\config.json" if ((Test-Path "$env:USERPROFILE\.scoop") -and !(Test-Path $configFile)) { New-Item -ItemType Directory (Split-Path -Path $configFile) -ErrorAction Ignore | Out-Null Move-Item "$env:USERPROFILE\.scoop" $configFile - warn "Scoops configurations has been migrated from '~/.scoop'" - warn "to '$configFile'" + write-host "WARN Scoop configuration has been migrated from '~/.scoop'" -f darkyellow + write-host "WARN to '$configFile'" -f darkyellow } # Note: Github disabled TLS 1.0 support on 2018-02-23. Need to enable TLS 1.2 From d788f9a2060ad919930e6d2369cd535e597aa912 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 25 Mar 2019 16:15:15 +0100 Subject: [PATCH 13/19] fix(config): fix set_config check for existing property --- lib/core.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index ff102fd947..9dd598c0ac 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -96,7 +96,7 @@ function set_config($name, $value) { if($value -eq [bool]::TrueString -or $value -eq [bool]::FalseString) { $value = [System.Convert]::ToBoolean($value) } - if($scoopConfig.$name) { + if($scoopConfig.PSObject.Properties.Item($name)) { $scoopConfig.$name = $value } else { $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value From e8c4fd4f0fb0f18b13673a3fd6b1afc497f37991 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 25 Mar 2019 16:15:53 +0100 Subject: [PATCH 14/19] fix(config): fix datetime tests for PowerShell 6 --- test/Scoop-Config.Tests.ps1 | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/Scoop-Config.Tests.ps1 b/test/Scoop-Config.Tests.ps1 index fd90b23036..d7b63688f7 100644 --- a/test/Scoop-Config.Tests.ps1 +++ b/test/Scoop-Config.Tests.ps1 @@ -15,8 +15,15 @@ describe "config" -Tag 'Scoop' { $obj.three.four | Should -BeExactly 4 $obj.five | Should -BeTrue $obj.six | Should -BeFalse + if($PSVersionTable.PSVersion.Major -lt 6) { + $obj.eight = [System.DateTime]::parse($obj.eight) + } + write-host -f blue $obj.seven + write-host -f blue (New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805)) + write-host -f blue $obj.eight + write-host -f blue (New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393)) [System.DateTime]::Equals($obj.seven, $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue - [System.DateTime]::Equals([System.DateTime]::parse($obj.eight), $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue + [System.DateTime]::Equals($obj.eight, $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue } it "load_config should return PSObject" { @@ -40,6 +47,10 @@ describe "config" -Tag 'Scoop' { get_config 'five' | Should -BeTrue get_config 'six' | Should -BeFalse [System.DateTime]::Equals((get_config 'seven'), $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue - [System.DateTime]::Equals([System.DateTime]::parse((get_config 'eight')), $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue + $eight = get_config 'eight' + if($PSVersionTable.PSVersion.Major -lt 6) { + $eight = [System.DateTime]::parse($eight) + } + [System.DateTime]::Equals($eight, $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue } } From 35edae297d9d68b3ad1bdc951d4738c02ae5d9b5 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 25 Mar 2019 16:57:21 +0100 Subject: [PATCH 15/19] fix(config): Test for DateTime object instead for actual Time --- test/Scoop-Config.Tests.ps1 | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/test/Scoop-Config.Tests.ps1 b/test/Scoop-Config.Tests.ps1 index d7b63688f7..efe2998748 100644 --- a/test/Scoop-Config.Tests.ps1 +++ b/test/Scoop-Config.Tests.ps1 @@ -2,7 +2,7 @@ describe "config" -Tag 'Scoop' { BeforeAll { - $json = '{ "one": 1, "two": [ { "a": "a" }, "b", 2 ], "three": { "four": 4 }, "five": true, "six": false, "seven": "\/Date(1529917395805)\/", "eight": "2019-03-18T15:22:09.3930000+01:00" }' + $json = '{ "one": 1, "two": [ { "a": "a" }, "b", 2 ], "three": { "four": 4 }, "five": true, "six": false, "seven": "\/Date(1529917395805)\/", "eight": "2019-03-18T15:22:09.3930000+00:00" }' } it "converts JSON to PSObject" { @@ -15,22 +15,19 @@ describe "config" -Tag 'Scoop' { $obj.three.four | Should -BeExactly 4 $obj.five | Should -BeTrue $obj.six | Should -BeFalse + $obj.seven | Should -BeOfType [System.DateTime] if($PSVersionTable.PSVersion.Major -lt 6) { - $obj.eight = [System.DateTime]::parse($obj.eight) + $obj.eight | Should -BeOfType [System.String] + } else { + $obj.eight | Should -BeOfType [System.DateTime] } - write-host -f blue $obj.seven - write-host -f blue (New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805)) - write-host -f blue $obj.eight - write-host -f blue (New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393)) - [System.DateTime]::Equals($obj.seven, $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue - [System.DateTime]::Equals($obj.eight, $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue } it "load_config should return PSObject" { mock Get-Content { $json } mock Test-Path { $true } (load_cfg 'file') | Should -Not -BeNullOrEmpty - (load_cfg 'file') | Should -BeOfType System.Management.Automation.PSObject + (load_cfg 'file') | Should -BeOfType [System.Management.Automation.PSObject] (load_cfg 'file').one | Should -BeExactly 1 } @@ -46,11 +43,11 @@ describe "config" -Tag 'Scoop' { (get_config 'three').four | Should -BeExactly 4 get_config 'five' | Should -BeTrue get_config 'six' | Should -BeFalse - [System.DateTime]::Equals((get_config 'seven'), $(New-Object System.DateTime (2018, 06, 25, 09, 03, 15, 805))) | Should -BeTrue - $eight = get_config 'eight' + get_config 'seven' | Should -BeOfType [System.DateTime] if($PSVersionTable.PSVersion.Major -lt 6) { - $eight = [System.DateTime]::parse($eight) + get_config 'eight' | Should -BeOfType [System.String] + } else { + get_config 'eight' | Should -BeOfType [System.DateTime] } - [System.DateTime]::Equals($eight, $(New-Object System.DateTime (2019, 03, 18, 15, 22, 09, 393))) | Should -BeTrue } } From 5e93c883688f1914284a5bcd99ca6f7bd33c7b82 Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 25 Mar 2019 18:29:33 +0100 Subject: [PATCH 16/19] fix(config): More tests for set_config --- lib/core.ps1 | 12 +++++----- libexec/scoop-config.ps1 | 4 ++-- test/Scoop-Config.Tests.ps1 | 44 ++++++++++++++++++++++++++++++------- 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/lib/core.ps1 b/lib/core.ps1 index 9dd598c0ac..c69c894672 100644 --- a/lib/core.ps1 +++ b/lib/core.ps1 @@ -89,17 +89,18 @@ function get_config($name, $default) { } function set_config($name, $value) { - if(!$scoopConfig) { + if($null -eq $scoopConfig -or $scoopConfig.Count -eq 0) { ensure (Split-Path -Path $configFile) | Out-Null - $scoopConfig = @{ $name = $value } + $scoopConfig = New-Object PSObject + $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value } else { if($value -eq [bool]::TrueString -or $value -eq [bool]::FalseString) { $value = [System.Convert]::ToBoolean($value) } - if($scoopConfig.PSObject.Properties.Item($name)) { - $scoopConfig.$name = $value - } else { + if($null -eq $scoopConfig.$name) { $scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value + } else { + $scoopConfig.$name = $value } } @@ -108,6 +109,7 @@ function set_config($name, $value) { } ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding ASCII + return $scoopConfig } function setup_proxy() { diff --git a/libexec/scoop-config.ps1 b/libexec/scoop-config.ps1 index 3b81c6ea9d..f25638c05f 100644 --- a/libexec/scoop-config.ps1 +++ b/libexec/scoop-config.ps1 @@ -36,9 +36,9 @@ reset_aliases if(!$name) { my_usage; exit 1 } if($name -like 'rm') { - set_config $value $null + set_config $value $null | Out-Null } elseif($null -ne $value) { - set_config $name $value + set_config $name $value | Out-Null } else { get_config $name $value } diff --git a/test/Scoop-Config.Tests.ps1 b/test/Scoop-Config.Tests.ps1 index efe2998748..53f52c9d18 100644 --- a/test/Scoop-Config.Tests.ps1 +++ b/test/Scoop-Config.Tests.ps1 @@ -1,11 +1,11 @@ -. "$psscriptroot\..\lib\core.ps1" +. "$PSScriptRoot\..\lib\core.ps1" -describe "config" -Tag 'Scoop' { +Describe "config" -Tag 'Scoop' { BeforeAll { $json = '{ "one": 1, "two": [ { "a": "a" }, "b", 2 ], "three": { "four": 4 }, "five": true, "six": false, "seven": "\/Date(1529917395805)\/", "eight": "2019-03-18T15:22:09.3930000+00:00" }' } - it "converts JSON to PSObject" { + It "converts JSON to PSObject" { $obj = ConvertFrom-Json $json $obj.one | Should -BeExactly 1 @@ -23,16 +23,15 @@ describe "config" -Tag 'Scoop' { } } - it "load_config should return PSObject" { - mock Get-Content { $json } - mock Test-Path { $true } + It "load_config should return PSObject" { + Mock Get-Content { $json } + Mock Test-Path { $true } (load_cfg 'file') | Should -Not -BeNullOrEmpty (load_cfg 'file') | Should -BeOfType [System.Management.Automation.PSObject] (load_cfg 'file').one | Should -BeExactly 1 - } - it "get_config should return exactly the same values" { + It "get_config should return exactly the same values" { $scoopConfig = ConvertFrom-Json $json get_config 'does_not_exist' 'default' | Should -Be 'default' @@ -50,4 +49,33 @@ describe "config" -Tag 'Scoop' { get_config 'eight' | Should -BeOfType [System.DateTime] } } + + It "set_config should create a new PSObject and ensure existing directory" { + $scoopConfig = $null + $configFile = "$PSScriptRoot\.scoop" + + Mock ensure { $PSScriptRoot } -Verifiable -ParameterFilter { $dir -eq (Split-Path -Path $configFile) } + Mock Set-Content {} -Verifiable -ParameterFilter { $Path -eq $configFile } + Mock ConvertTo-Json { '' } -Verifiable -ParameterFilter { $InputObject -is [System.Management.Automation.PSObject] } + + set_config 'does_not_exist' 'default' + + Assert-VerifiableMock + } + + It "set_config should remove a value if set to `$null" { + $scoopConfig = New-Object PSObject + $scoopConfig | Add-Member -MemberType NoteProperty -Name 'should_be_removed' -Value 'a_value' + $scoopConfig | Add-Member -MemberType NoteProperty -Name 'should_stay' -Value 'another_value' + $configFile = "$PSScriptRoot\.scoop" + + Mock Set-Content {} -Verifiable -ParameterFilter { $Path -eq $configFile } + Mock ConvertTo-Json { '' } -Verifiable -ParameterFilter { $InputObject -is [System.Management.Automation.PSObject] } + + $scoopConfig = set_config 'should_be_removed' $null + $scoopConfig.should_be_removed | Should -BeNullOrEmpty + $scoopConfig.should_stay | Should -Be 'another_value' + + Assert-VerifiableMock + } } From d0de7944e5546bb50d7644651af921baef3d785c Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Mon, 25 Mar 2019 18:45:49 +0100 Subject: [PATCH 17/19] refactor(config): Better output for scoop config command --- libexec/scoop-config.ps1 | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libexec/scoop-config.ps1 b/libexec/scoop-config.ps1 index f25638c05f..26cd92f2ce 100644 --- a/libexec/scoop-config.ps1 +++ b/libexec/scoop-config.ps1 @@ -37,10 +37,17 @@ if(!$name) { my_usage; exit 1 } if($name -like 'rm') { set_config $value $null | Out-Null + Write-Output "'$name' has been removed" } elseif($null -ne $value) { set_config $name $value | Out-Null + Write-Output "'$name' has been set to '$value'" } else { - get_config $name $value + $value = get_config $name + if($null -eq $value) { + Write-Output "'$name' is not set" + } else { + Write-Output $value + } } exit 0 From ae9d802638f0cd95f8237ed2808ef4904d31807b Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Thu, 9 May 2019 20:16:54 +0200 Subject: [PATCH 18/19] refactor(config): Redirect set_config output to Out-Null --- libexec/scoop-alias.ps1 | 4 ++-- libexec/scoop-update.ps1 | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libexec/scoop-alias.ps1 b/libexec/scoop-alias.ps1 index fb4d68da33..8e67ab766e 100644 --- a/libexec/scoop-alias.ps1 +++ b/libexec/scoop-alias.ps1 @@ -63,7 +63,7 @@ $command # add alias to config $aliases | Add-Member -MemberType NoteProperty -Name $name -Value $alias_file - set_config $script:config_alias $aliases + set_config $script:config_alias $aliases | Out-Null } function rm_alias($name) { @@ -78,7 +78,7 @@ function rm_alias($name) { rm_shim $aliases.$name (shimdir $false) $aliases.PSObject.Properties.Remove($name) - set_config $script:config_alias $aliases + set_config $script:config_alias $aliases | Out-Null } else { abort "Alias $name doesn't exist." } diff --git a/libexec/scoop-update.ps1 b/libexec/scoop-update.ps1 index 03081130bc..1ca9b9b12f 100644 --- a/libexec/scoop-update.ps1 +++ b/libexec/scoop-update.ps1 @@ -40,14 +40,14 @@ $independent = $opt.i -or $opt.independent $repo = $(get_config SCOOP_REPO) if (!$repo) { $repo = "/~https://github.com/lukesampson/scoop" - set_config SCOOP_REPO "$repo" + set_config SCOOP_REPO "$repo" | Out-Null } # Find current update channel from config $branch = $(get_config SCOOP_BRANCH) if (!$branch) { $branch = "master" - set_config SCOOP_BRANCH "$branch" + set_config SCOOP_BRANCH "$branch" | Out-Null } if(($PSVersionTable.PSVersion.Major) -lt 5) { @@ -143,7 +143,7 @@ function update_scoop() { Pop-Location } - set_config lastupdate ([System.DateTime]::Now.ToString('o')) + set_config lastupdate ([System.DateTime]::Now.ToString('o')) | Out-Null success 'Scoop was updated successfully!' } From 4cc63c1fa589b27140e1fa6797a16fb095ad0d6f Mon Sep 17 00:00:00 2001 From: Richard Kuhnt Date: Thu, 9 May 2019 21:18:16 +0200 Subject: [PATCH 19/19] fix(config): Remove config.ps1 imports --- libexec/scoop-uninstall.ps1 | 1 - test/Scoop-Core.Tests.ps1 | 1 - test/Scoop-Decompress.Tests.ps1 | 1 - 3 files changed, 3 deletions(-) diff --git a/libexec/scoop-uninstall.ps1 b/libexec/scoop-uninstall.ps1 index 937603d2b5..736126bd67 100644 --- a/libexec/scoop-uninstall.ps1 +++ b/libexec/scoop-uninstall.ps1 @@ -14,7 +14,6 @@ . "$PSScriptRoot\..\lib\psmodules.ps1" . "$PSScriptRoot\..\lib\versions.ps1" . "$PSScriptRoot\..\lib\getopt.ps1" -. "$PSScriptRoot\..\lib\config.ps1" reset_aliases diff --git a/test/Scoop-Core.Tests.ps1 b/test/Scoop-Core.Tests.ps1 index 3e9a6baa5f..04bab9c478 100644 --- a/test/Scoop-Core.Tests.ps1 +++ b/test/Scoop-Core.Tests.ps1 @@ -1,5 +1,4 @@ . "$psscriptroot\..\lib\core.ps1" -. "$psscriptroot\..\lib\config.ps1" . "$psscriptroot\..\lib\install.ps1" . "$psscriptroot\..\lib\unix.ps1" . "$psscriptroot\Scoop-TestLib.ps1" diff --git a/test/Scoop-Decompress.Tests.ps1 b/test/Scoop-Decompress.Tests.ps1 index 258260c432..7f452c2603 100644 --- a/test/Scoop-Decompress.Tests.ps1 +++ b/test/Scoop-Decompress.Tests.ps1 @@ -3,7 +3,6 @@ . "$psscriptroot\..\lib\unix.ps1" . "$psscriptroot\..\lib\install.ps1" . "$psscriptroot\..\lib\manifest.ps1" -. "$psscriptroot\..\lib\config.ps1" $isUnix = is_unix