mirror of
https://github.com/ScoopInstaller/Scoop.git
synced 2025-11-18 23:46:35 +00:00
Compare commits
240 Commits
2019-10-18
...
v0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aaa726c09f | ||
|
|
b93d0b4157 | ||
|
|
0b6de90c03 | ||
|
|
b96abcfda9 | ||
|
|
cb7cd99e7a | ||
|
|
22365c2169 | ||
|
|
e6d03715fa | ||
|
|
6296822f1f | ||
|
|
7ee74a0638 | ||
|
|
f947b620d5 | ||
|
|
47c0f46d58 | ||
|
|
f6679c2170 | ||
|
|
22c7d58e33 | ||
|
|
55b26da657 | ||
|
|
f441968983 | ||
|
|
72fd0c5f83 | ||
|
|
d29e336417 | ||
|
|
32de4c5714 | ||
|
|
ced36b285d | ||
|
|
ad3fc4f8fb | ||
|
|
45db5fb325 | ||
|
|
5e4e6e9e5d | ||
|
|
53cdf68e26 | ||
|
|
4d36cbd90d | ||
|
|
635ae1715a | ||
|
|
5a795caca5 | ||
|
|
5025661fa2 | ||
|
|
476b507bb6 | ||
|
|
a66a086fb0 | ||
|
|
60d308f7d6 | ||
|
|
af26d86d02 | ||
|
|
7d5a47cc77 | ||
|
|
04b30de9dd | ||
|
|
750ea54d49 | ||
|
|
43d5e99705 | ||
|
|
63b858c41f | ||
|
|
59328fc83c | ||
|
|
6bb5e932fe | ||
|
|
3af0cdbc21 | ||
|
|
765d3aad7e | ||
|
|
b740e98c36 | ||
|
|
a8e36d35c7 | ||
|
|
9024ee450c | ||
|
|
e4580dd705 | ||
|
|
a67937f77d | ||
|
|
aa61f1994a | ||
|
|
0cb6152e1a | ||
|
|
4047d6962c | ||
|
|
40b2d951e8 | ||
|
|
b95ccbe14a | ||
|
|
e1f569b01b | ||
|
|
d1f828c942 | ||
|
|
26517644df | ||
|
|
f83fa145de | ||
|
|
21c5c6e775 | ||
|
|
c41cb84404 | ||
|
|
f24159c8f1 | ||
|
|
14854c3548 | ||
|
|
3345a5ed10 | ||
|
|
53f56e350f | ||
|
|
ef2bfeb3f2 | ||
|
|
b2a27f420d | ||
|
|
c01960f283 | ||
|
|
285ffd0322 | ||
|
|
b69bdbd6d2 | ||
|
|
ba970d5c42 | ||
|
|
e450843827 | ||
|
|
f559c813df | ||
|
|
7967905980 | ||
|
|
0e4721a408 | ||
|
|
e0a5313132 | ||
|
|
8c02776c6c | ||
|
|
c6b10c8f89 | ||
|
|
5b0bdaf893 | ||
|
|
ba28a4f4f1 | ||
|
|
3f4c191faa | ||
|
|
4a9efaa2d9 | ||
|
|
98ea7a5e82 | ||
|
|
2644a5f7b1 | ||
|
|
158c0fd4d0 | ||
|
|
e09127f7be | ||
|
|
37f5024194 | ||
|
|
5f407ca434 | ||
|
|
d023e6cf0d | ||
|
|
81b7aaf8d7 | ||
|
|
4e64db7f93 | ||
|
|
6f8bf04ce5 | ||
|
|
c9df8f4017 | ||
|
|
d9f55a3a0a | ||
|
|
d7fb97f517 | ||
|
|
d71fe82f9d | ||
|
|
5b87c99aa8 | ||
|
|
3ca1b1f2e3 | ||
|
|
30f57aee6a | ||
|
|
bc35a563b5 | ||
|
|
25b170895f | ||
|
|
92c89f86ed | ||
|
|
cabaf59f62 | ||
|
|
9142703bce | ||
|
|
00adc0d828 | ||
|
|
399274e242 | ||
|
|
4f5ecd029e | ||
|
|
c864f68c0b | ||
|
|
3c5f5ff20a | ||
|
|
fba658c020 | ||
|
|
00f7859b3f | ||
|
|
5d8aeb54bb | ||
|
|
d5cb86078b | ||
|
|
271d41b949 | ||
|
|
36ae35c606 | ||
|
|
0d1ad20869 | ||
|
|
5602083868 | ||
|
|
2a0187458d | ||
|
|
1dbab1fee8 | ||
|
|
5e11c94a54 | ||
|
|
fb496c482b | ||
|
|
dec2598052 | ||
|
|
af2056a8fd | ||
|
|
f343bd9f5e | ||
|
|
cdba268b47 | ||
|
|
cbe29eddb3 | ||
|
|
cd6d31dae8 | ||
|
|
6f60059035 | ||
|
|
f3cdfffcfe | ||
|
|
b966ca8c63 | ||
|
|
2f7ff1bab5 | ||
|
|
6c6a2ca410 | ||
|
|
02da753fa7 | ||
|
|
b488cb9ab3 | ||
|
|
48b035d7f9 | ||
|
|
386d3be20e | ||
|
|
992e99358a | ||
|
|
c1d48e4853 | ||
|
|
4d5fee36e1 | ||
|
|
2ec00d576c | ||
|
|
37a886947d | ||
|
|
6387b7d1cd | ||
|
|
3c90d1a070 | ||
|
|
ef4349bee4 | ||
|
|
c31ccea971 | ||
|
|
d021438b20 | ||
|
|
ab8be955b4 | ||
|
|
5a1cdcb93d | ||
|
|
4ec9eccdb4 | ||
|
|
07ecd01159 | ||
|
|
3bb7036ee1 | ||
|
|
1d5e81d2dc | ||
|
|
29477d992a | ||
|
|
ac71fccbec | ||
|
|
0f5097be4f | ||
|
|
f34be82516 | ||
|
|
59088a9f00 | ||
|
|
cf3f57caa3 | ||
|
|
3c344682fe | ||
|
|
90fa473262 | ||
|
|
bbad8aef6c | ||
|
|
2bc2e652e3 | ||
|
|
abcb04878c | ||
|
|
e663027299 | ||
|
|
ae89213842 | ||
|
|
6c2b34d29b | ||
|
|
6161f0bf9f | ||
|
|
baa20aef55 | ||
|
|
77d00d1771 | ||
|
|
ef3bf14547 | ||
|
|
5ad8c76dd7 | ||
|
|
47ebc6f176 | ||
|
|
84590f89f4 | ||
|
|
e35ff313a5 | ||
|
|
af7a6f6d0e | ||
|
|
948daa0c63 | ||
|
|
1490869e6f | ||
|
|
dcce404529 | ||
|
|
8bb7390a75 | ||
|
|
2047f8a929 | ||
|
|
458ec9003f | ||
|
|
bae0be9581 | ||
|
|
1e90310838 | ||
|
|
30e7967a04 | ||
|
|
6c340cb7e3 | ||
|
|
35b2a42ede | ||
|
|
818162fe82 | ||
|
|
b174775b71 | ||
|
|
5226f26f18 | ||
|
|
4f5acd7210 | ||
|
|
f1a46e1095 | ||
|
|
3e9a4d4ea0 | ||
|
|
2cf025a80b | ||
|
|
0920050464 | ||
|
|
3d67b7d37c | ||
|
|
63a26584cd | ||
|
|
dc7df618c1 | ||
|
|
8ecdb7cc14 | ||
|
|
227de6cfb8 | ||
|
|
ad061d2a6a | ||
|
|
0948824ec7 | ||
|
|
b0557b647b | ||
|
|
7db0fe9382 | ||
|
|
643cfb0da8 | ||
|
|
c8453767b4 | ||
|
|
5e81d49984 | ||
|
|
9b29bbb711 | ||
|
|
22a59866c7 | ||
|
|
6df80c1aee | ||
|
|
6659c55959 | ||
|
|
91ea657923 | ||
|
|
3188115369 | ||
|
|
22fd6986bf | ||
|
|
078b29bc80 | ||
|
|
33a357241d | ||
|
|
573e0933cf | ||
|
|
96de9c14bb | ||
|
|
7995f99dc1 | ||
|
|
f91968cb16 | ||
|
|
0d721abc2f | ||
|
|
48f121e466 | ||
|
|
eada459be9 | ||
|
|
398ccea2ae | ||
|
|
50df0c52c4 | ||
|
|
e6b355eae0 | ||
|
|
5851eaf762 | ||
|
|
2a91ddb101 | ||
|
|
3279bbfb71 | ||
|
|
efcd3bfa38 | ||
|
|
9c9cc807ba | ||
|
|
4eba120897 | ||
|
|
fe01ed52d5 | ||
|
|
ad9f7c6ff1 | ||
|
|
062e6d7973 | ||
|
|
48bb96a3d8 | ||
|
|
e0c5ac2396 | ||
|
|
7e32139322 | ||
|
|
a9fa775d59 | ||
|
|
5afad4e3d1 | ||
|
|
8ac23f8fbc | ||
|
|
6eb90c9c11 | ||
|
|
eb3d42de8f | ||
|
|
e997017f1a | ||
|
|
8ee45a57dc | ||
|
|
ce3464f2f4 |
@@ -18,3 +18,8 @@ end_of_line = crlf
|
|||||||
|
|
||||||
[*.{yml, yaml}]
|
[*.{yml, yaml}]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
# Makefiles require tab indentation
|
||||||
|
[{{M,m,GNU}akefile{,.*},*.mak,*.mk}]
|
||||||
|
indent_style = tab
|
||||||
|
end_of_line = lf
|
||||||
|
|||||||
47
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
47
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
name: "Bug Report"
|
||||||
|
about: "I am facing some problems."
|
||||||
|
title: '[Bug] '
|
||||||
|
labels: "bug"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
IMPORTANT:
|
||||||
|
If your problem is related to a specific package, open the issue in the relevant bucket,
|
||||||
|
not here.
|
||||||
|
By opening this issue you confirm that you have searched for similar issues/PRs here already.
|
||||||
|
Failing to do so will most likely result in closing of this issue without any explanation.
|
||||||
|
Incomplete form details below might also result in closing of the issue.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Bug Report
|
||||||
|
|
||||||
|
#### Current Behavior
|
||||||
|
<!-- A clear and concise description of the behavior. -->
|
||||||
|
|
||||||
|
#### Expected Behavior
|
||||||
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
|
#### Additional context/output
|
||||||
|
<!-- Add any other context about the problem here. If applicable, paste terminal output here to help explain. -->
|
||||||
|
|
||||||
|
#### Possible Solution
|
||||||
|
<!--- Only if you have suggestions on a fix for the bug -->
|
||||||
|
|
||||||
|
### System details
|
||||||
|
|
||||||
|
**Windows version:** [e.g. 7, 8, 10]
|
||||||
|
|
||||||
|
**OS architecture:** [e.g. 32bit, 64bit]
|
||||||
|
|
||||||
|
**PowerShell version:** [output of `"$($PSVersionTable.PSVersion)"`]
|
||||||
|
|
||||||
|
**Additional software:** [(optional) e.g. ConEmu, Git]
|
||||||
|
|
||||||
|
#### Scoop Configuration
|
||||||
|
<!-- Can be found in ~/.config/scoop/config.json -->
|
||||||
|
|
||||||
|
```json
|
||||||
|
//# Your configuration here
|
||||||
|
```
|
||||||
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: "Feature Request"
|
||||||
|
about: "I have a suggestion (and may want to implement it)!"
|
||||||
|
title: '[Feature] '
|
||||||
|
labels: "enhancement"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
IMPORTANT:
|
||||||
|
If your request is related to a specific package, open the issue in the relevant bucket,
|
||||||
|
not here.
|
||||||
|
By opening this issue you confirm that you have searched for similar issues/PRs here already.
|
||||||
|
Failing to do so will most likely result in closing of this issue without any explanation.
|
||||||
|
Incomplete form details below might also result in closing of the issue.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Feature Request
|
||||||
|
|
||||||
|
#### Is your feature request related to a problem? Please describe.
|
||||||
|
<!-- A clear and concise description of what the problem is. Ex. I have an issue when [...] -->
|
||||||
|
|
||||||
|
#### Describe the solution you'd like
|
||||||
|
<!-- A clear and concise description of what you want to happen. Add any considered drawbacks. -->
|
||||||
|
|
||||||
|
#### Describe alternatives you've considered
|
||||||
|
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
2
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
|
||||||
35
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
35
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<!-- Provide a general summary of your changes in the Title above -->
|
||||||
|
<!-- To help with semantic versioning the PR title should start with one of the conventional commit types. -->
|
||||||
|
<!-- The conventional commit types for Semantic PR are: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
By opening this PR you confirm that you have searched for similar issues/PRs here already.
|
||||||
|
Failing to do so will most likely result in closing of this PR without any explanation.
|
||||||
|
It is also mandatory to open a relevant issue for discussion with the maintainers,
|
||||||
|
before creating any new PR.
|
||||||
|
Read the contributing guide first to save both your and our time.
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
<!-- Describe your changes in detail -->
|
||||||
|
|
||||||
|
#### Motivation and Context
|
||||||
|
<!-- Why is this change required? What problem does it solve? -->
|
||||||
|
<!-- If it fixes an open issue, please link to the issue here. -->
|
||||||
|
Closes #XXXX
|
||||||
|
<!-- or -->
|
||||||
|
Relates to #XXXX
|
||||||
|
|
||||||
|
#### How Has This Been Tested?
|
||||||
|
<!-- Please describe in detail how you tested your changes. -->
|
||||||
|
<!-- Include details of your testing environment, tests ran to see how -->
|
||||||
|
<!-- your change affects other areas of the code, etc. -->
|
||||||
|
|
||||||
|
#### Checklist:
|
||||||
|
<!-- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||||
|
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||||
|
- [ ] I have read the [Contributing Guide](https://github.com/ScoopInstaller/.github/blob/main/.github/CONTRIBUTING.md).
|
||||||
|
- [ ] I have ensured that I am targeting the `develop` branch.
|
||||||
|
- [ ] I have updated the documentation accordingly.
|
||||||
|
- [ ] I have updated the tests accordingly.
|
||||||
|
- [ ] I have added an entry in the CHANGELOG.
|
||||||
39
.github/workflows/ci.yml
vendored
Normal file
39
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: Scoop Core CI Tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test_powershell:
|
||||||
|
name: WindowsPowerShell
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
- name: Init Test Suite
|
||||||
|
uses: potatoqualitee/psmodulecache@v4
|
||||||
|
with:
|
||||||
|
modules-to-cache: PSScriptAnalyzer, BuildHelpers, Pester:4.10.1
|
||||||
|
shell: powershell
|
||||||
|
- name: Test Scoop Core
|
||||||
|
shell: powershell
|
||||||
|
run: ./test/bin/test.ps1
|
||||||
|
test_pwsh:
|
||||||
|
name: PowerShell
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 2
|
||||||
|
- name: Init Test Suite
|
||||||
|
uses: potatoqualitee/psmodulecache@v4
|
||||||
|
with:
|
||||||
|
modules-to-cache: PSScriptAnalyzer, BuildHelpers, Pester:4.10.1
|
||||||
|
shell: pwsh
|
||||||
|
- name: Test Scoop Core
|
||||||
|
shell: pwsh
|
||||||
|
run: ./test/bin/test.ps1
|
||||||
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
@@ -1,9 +1,5 @@
|
|||||||
// Configure PSScriptAnalyzer settings
|
// Configure PSScriptAnalyzer settings
|
||||||
{
|
{
|
||||||
"[powershell]": {
|
|
||||||
// Disable formating until: https://github.com/PowerShell/vscode-powershell/issues/1019 is fixed
|
|
||||||
"editor.formatOnSave": false
|
|
||||||
},
|
|
||||||
"powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
|
"powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
|
||||||
"powershell.codeFormatting.preset": "OTBS",
|
"powershell.codeFormatting.preset": "OTBS",
|
||||||
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
"powershell.codeFormatting.alignPropertyValuePairs": true,
|
||||||
|
|||||||
565
CHANGELOG.md
Normal file
565
CHANGELOG.md
Normal file
@@ -0,0 +1,565 @@
|
|||||||
|
## [v0.2.0](https://github.com/ScoopInstaller/Scoop/compare/v0.1.0...v0.2.0) - 2022-05-10
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **relicense:** Relicense to dual-license (Unlicense or MIT) ([#4903](https://github.com/ScoopInstaller/Scoop/issues/4903), [#4870](https://github.com/ScoopInstaller/Scoop/issues/4870))
|
||||||
|
- **install:** Allow downloading from private repositories ([#4254](https://github.com/ScoopInstaller/Scoop/issues/4254))
|
||||||
|
- **scoop-cleanup:** Add `-a/--all` switch to cleanup all apps ([#4906](https://github.com/ScoopInstaller/Scoop/issues/4906))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **bucket:** Return empty list correctly in `Get-LocalBucket` ([#4885](https://github.com/ScoopInstaller/Scoop/issues/4885))
|
||||||
|
- **install:** Fix issue with installation inside containers ([#4837](https://github.com/ScoopInstaller/Scoop/issues/4837))
|
||||||
|
- **installed:** If no `$global`, check both local and global installed ([#4798](https://github.com/ScoopInstaller/Scoop/issues/4798))
|
||||||
|
- **shim:** Manipulating shims with UTF8 encoding ([#4791](https://github.com/ScoopInstaller/Scoop/issues/4791), [#4813](https://github.com/ScoopInstaller/Scoop/issues/4813))
|
||||||
|
- **shim:** Correctly quote $@ in sh->ps1 shims ([#4809](https://github.com/ScoopInstaller/Scoop/issues/4809))
|
||||||
|
- **update:** Skip logs starting with `(chore)` ([#4800](https://github.com/ScoopInstaller/Scoop/issues/4800))
|
||||||
|
- **scoop-download:** Add failure check ([#4822](https://github.com/ScoopInstaller/Scoop/issues/4822))
|
||||||
|
- **scoop-list:** Fix date in 'Updated' column showing the months in the place of minutes ([#4880](https://github.com/ScoopInstaller/Scoop/issues/4880))
|
||||||
|
- **scoop-prefix:** Fix typo that breaks global installed apps ([#4795](https://github.com/ScoopInstaller/Scoop/issues/4795))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
- **scoop:** Load libs only once ([#4839](https://github.com/ScoopInstaller/Scoop/issues/4839), [#4884](https://github.com/ScoopInstaller/Scoop/issues/4884))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **bucket:** Move 'Find-Manifest' and 'list_buckets' to 'buckets' ([#4814](https://github.com/ScoopInstaller/Scoop/issues/4814))
|
||||||
|
- **relpath:** Use `$PSScriptRoot` instead of `relpath` ([#4793](https://github.com/ScoopInstaller/Scoop/issues/4793))
|
||||||
|
- **reset_aliases:** Move core function of `reset_aliases` to `scoop` ([#4794](https://github.com/ScoopInstaller/Scoop/issues/4794))
|
||||||
|
- **config:** Rename checkver_token to gh_token and SCOOP_CHECKVER_TOKEN to SCOOP_GH_TOKEN ([#4832](https://github.com/ScoopInstaller/Scoop/issues/4832), [#4842](https://github.com/ScoopInstaller/Scoop/issues/4842))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **checkver:** Add option to throw error as exception ([#4867](https://github.com/ScoopInstaller/Scoop/issues/4867))
|
||||||
|
- **schema:** Remove 'description' from required fields ([#4853](https://github.com/ScoopInstaller/Scoop/issues/4853), [#4874](https://github.com/ScoopInstaller/Scoop/issues/4874))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **changelog:** Rearrange CHANGELOG ([#4897](https://github.com/ScoopInstaller/Scoop/issues/4897))
|
||||||
|
- **readme:** Update installation instruction ([#4825](https://github.com/ScoopInstaller/Scoop/issues/4825))
|
||||||
|
- **readme:** Fix badges for Gitter and CI Tests ([#4830](https://github.com/ScoopInstaller/Scoop/issues/4830))
|
||||||
|
- **scoop-shim:** Fix typo ([#4836](https://github.com/ScoopInstaller/Scoop/issues/4836))
|
||||||
|
|
||||||
|
## [v0.1.0](https://github.com/ScoopInstaller/Scoop/compare/2021-12-26...v0.1.0) - 2022-03-01
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **scoop-bucket:** List more detailed information for buckets ([#4704](https://github.com/ScoopInstaller/Scoop/issues/4704), [#4756](https://github.com/ScoopInstaller/Scoop/issues/4756), [#4759](https://github.com/ScoopInstaller/Scoop/issues/4759))
|
||||||
|
- **scoop-cache:** Handle multiple apps and show detailed information ([#4738](https://github.com/ScoopInstaller/Scoop/issues/4738))
|
||||||
|
- **scoop-cat:** Use `bat` to pretty-print JSON ([#4742](https://github.com/ScoopInstaller/Scoop/issues/4742))
|
||||||
|
- **scoop-config:** Allow Scoop to ignore running processes during reset/uninstall/update ([#4713](https://github.com/ScoopInstaller/Scoop/issues/4713), [#4731](https://github.com/ScoopInstaller/Scoop/issues/4731))
|
||||||
|
- **scoop-config:** Show all settings ([#4765](https://github.com/ScoopInstaller/Scoop/issues/4765))
|
||||||
|
- **scoop-download:** Add `scoop download` command ([#4621](https://github.com/ScoopInstaller/Scoop/issues/4621))
|
||||||
|
- **scoop-(install|virustotal):** Allow skipping update check ([#4634](https://github.com/ScoopInstaller/Scoop/issues/4634))
|
||||||
|
- **scoop-list:** Allow list manipulation ([#4718](https://github.com/ScoopInstaller/Scoop/issues/4718))
|
||||||
|
- **scoop-list:** Show last-updated time ([#4723](https://github.com/ScoopInstaller/Scoop/issues/4723))
|
||||||
|
- **scoop-info:** Revamp details and show more information ([#4747](https://github.com/ScoopInstaller/Scoop/issues/4747))
|
||||||
|
- **scoop-shim:** Add `scoop shim` to manipulate shims ([#4727](https://github.com/ScoopInstaller/Scoop/issues/4727), [#4736](https://github.com/ScoopInstaller/Scoop/issues/4736))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **autoupdate:** Allow checksum file that contains whitespaces ([#4619](https://github.com/ScoopInstaller/Scoop/issues/4619))
|
||||||
|
- **autoupdate:** Rename $response to $res ([#4706](https://github.com/ScoopInstaller/Scoop/issues/4706))
|
||||||
|
- **config:** Ensure manipulating config with UTF8 encoding ([#4644](https://github.com/ScoopInstaller/Scoop/issues/4644))
|
||||||
|
- **config:** Allow scoop config use Unicode characters ([#4631](https://github.com/ScoopInstaller/Scoop/issues/4631))
|
||||||
|
- **config:** Fix `set_config` bugs ([#3681](https://github.com/ScoopInstaller/Scoop/issues/3681))
|
||||||
|
- **current:** Remove 'current' while it's not a junction ([#4687](https://github.com/ScoopInstaller/Scoop/issues/4687))
|
||||||
|
- **depends:** Prevent error on no URL ([#4595](https://github.com/ScoopInstaller/Scoop/issues/4595))
|
||||||
|
- **depends:** Check if extractor is available ([#4042](https://github.com/ScoopInstaller/Scoop/issues/4042))
|
||||||
|
- **decompress:** Fix nested Zstd archive extraction ([#4608](https://github.com/ScoopInstaller/Scoop/issues/4608), [#4639](https://github.com/ScoopInstaller/Scoop/issues/4639))
|
||||||
|
- **installed:** Fix 'core/installed' that mark failed app as 'installed' ([#4650](https://github.com/ScoopInstaller/Scoop/issues/4650), [#4676](https://github.com/ScoopInstaller/Scoop/issues/4676), [#4689](https://github.com/ScoopInstaller/Scoop/issues/4689), [#4785](https://github.com/ScoopInstaller/Scoop/issues/4785))
|
||||||
|
- **no-junctions:** Fix error when `NO_JUNCTIONS` is been set ([#4722](https://github.com/ScoopInstaller/Scoop/issues/4722), [#4726](https://github.com/ScoopInstaller/Scoop/issues/4726))
|
||||||
|
- **shim:** Fix PS1 shim error when in different drive in PS7 ([#4614](https://github.com/ScoopInstaller/Scoop/issues/4614))
|
||||||
|
- **shim:** Fix `sh` shim error in WSL ([#4637](https://github.com/ScoopInstaller/Scoop/issues/4637))
|
||||||
|
- **shim:** Use `-file` instead of `-command` in ps1 script shims ([#4721](https://github.com/ScoopInstaller/Scoop/issues/4721))
|
||||||
|
- **shim:** Fix exe shim when app path has white spaces ([#4734](https://github.com/ScoopInstaller/Scoop/issues/4734), [#4780](https://github.com/ScoopInstaller/Scoop/issues/4780))
|
||||||
|
- **versions:** Fix wrong version number when only one version dir ([#4679](https://github.com/ScoopInstaller/Scoop/issues/4679))
|
||||||
|
- **versions:** Get current version from failed installation if possible ([#4720](https://github.com/ScoopInstaller/Scoop/issues/4720), [#4725](https://github.com/ScoopInstaller/Scoop/issues/4725))
|
||||||
|
- **scoop-alias:** Fix alias initialization ([#4737](https://github.com/ScoopInstaller/Scoop/issues/4737))
|
||||||
|
- **scoop-checkup:** Skip 'check_windows_defender' when have not admin privileges ([#4699](https://github.com/ScoopInstaller/Scoop/issues/4699))
|
||||||
|
- **scoop-cleanup:** Remove apps other than current version ([#4665](https://github.com/ScoopInstaller/Scoop/issues/4665))
|
||||||
|
- **scoop-search:** Remove redundant 'bucket/' in search result ([#4773](https://github.com/ScoopInstaller/Scoop/issues/4773))
|
||||||
|
- **scoop-update:** Skip updating non git buckets ([#4670](https://github.com/ScoopInstaller/Scoop/issues/4670), [#4672](https://github.com/ScoopInstaller/Scoop/issues/4672))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
- **uninstall:** Avoid checking all files for unlinking persisted data ([#4681](https://github.com/ScoopInstaller/Scoop/issues/4681), [#4763](https://github.com/ScoopInstaller/Scoop/issues/4763))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **depends:** Rewrite 'depends.ps1' ([#4638](https://github.com/ScoopInstaller/Scoop/issues/4638), [#4673](https://github.com/ScoopInstaller/Scoop/issues/4673))
|
||||||
|
- **mklink:** Use 'New-Item' instead of 'mklink' ([#4690](https://github.com/ScoopInstaller/Scoop/issues/4690))
|
||||||
|
- **rmdir:** Use 'Remove-Item' instead of 'rmdir' ([#4691](https://github.com/ScoopInstaller/Scoop/issues/4691))
|
||||||
|
- **COMSPEC:** Deprecate use of subshell cmd.exe ([#4692](https://github.com/ScoopInstaller/Scoop/issues/4692))
|
||||||
|
- **git:** Use 'git -C' to specify the work directory instead of 'Push-Location'/'Pop-Location' ([#4697](https://github.com/ScoopInstaller/Scoop/issues/4697))
|
||||||
|
- **scoop-info:** Use List View for output ([#4741](https://github.com/ScoopInstaller/Scoop/issues/4741))
|
||||||
|
- **scoop-config:** Use underscores everywhere ([#4745](https://github.com/ScoopInstaller/Scoop/issues/4745))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **checkver:** Fix output with '-Version' ([#3774](https://github.com/ScoopInstaller/Scoop/issues/3774))
|
||||||
|
- **schema:** Add '$schema' property ([#4623](https://github.com/ScoopInstaller/Scoop/issues/4623))
|
||||||
|
- **schema:** Add explicit escape to opening bracket matcher in jp/jsonpath regex ([#3719](https://github.com/ScoopInstaller/Scoop/issues/3719))
|
||||||
|
- **schema:** Fix typo ('note' -> 'notes') ([#4678](https://github.com/ScoopInstaller/Scoop/issues/4678))
|
||||||
|
- **tests:** Support both AppVeyor and GitHub Actions ([#4655](https://github.com/ScoopInstaller/Scoop/issues/4655))
|
||||||
|
- **tests:** Run GitHub Actions CI on each commit ([#4664](https://github.com/ScoopInstaller/Scoop/issues/4664))
|
||||||
|
- **tests:** Use cache in GitHub Actions ([#4671](https://github.com/ScoopInstaller/Scoop/issues/4671))
|
||||||
|
- **tests:** Disable CI test on 'push' ([#4677](https://github.com/ScoopInstaller/Scoop/issues/4677))
|
||||||
|
- **vscode-settings:** Remove 'formatOnSave' trigger ([#4635](https://github.com/ScoopInstaller/Scoop/issues/4635))
|
||||||
|
|
||||||
|
### Styles
|
||||||
|
|
||||||
|
- **test:** Format scripts by VSCode's PowerShell extension ([#4609](https://github.com/ScoopInstaller/Scoop/issues/4609))
|
||||||
|
- **style:** Use correct casing for `$PSScriptRoot` ([#4775](https://github.com/ScoopInstaller/Scoop/issues/4775))
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- **test-bin:** Only write output file in CI and fix trailing whitespaces ([#4613](https://github.com/ScoopInstaller/Scoop/issues/4613))
|
||||||
|
- **manifest:** Fix manifests validation ([#4620](https://github.com/ScoopInstaller/Scoop/issues/4620))
|
||||||
|
- **zstd:** Fix 'zstd' extraction error in test ([#4651](https://github.com/ScoopInstaller/Scoop/issues/4651))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **changelog:** Add 'CHANGLOG.md' ([#4600](https://github.com/ScoopInstaller/Scoop/issues/4600))
|
||||||
|
- **changelog:** Rearrange CHANGELOG ([#4729](https://github.com/ScoopInstaller/Scoop/issues/4729))
|
||||||
|
- **changelog:** Link CHANGELOG headers to 'releases/tag' ([#4730](https://github.com/ScoopInstaller/Scoop/issues/4730))
|
||||||
|
|
||||||
|
## [2021-12-26](https://github.com/ScoopInstaller/Scoop/compare/2021-11-22...2021-12-26)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **core:** Redirect 'StandardError' in `Invoke-ExternalCommand()` ([#4570](https://github.com/ScoopInstaller/Scoop/issues/4570), [#4582](https://github.com/ScoopInstaller/Scoop/issues/4582))
|
||||||
|
- **install:** Add portableapps.com to strip_filename skips ([#3244](https://github.com/ScoopInstaller/Scoop/issues/3244))
|
||||||
|
- **install:** Show manifest on installation ([#4155](https://github.com/ScoopInstaller/Scoop/issues/4155), [fb496c48](https://github.com/ScoopInstaller/Scoop/commit/fb496c482bec4063e01b328f943224ab703dbbd8), [#4581](https://github.com/ScoopInstaller/Scoop/issues/4581))
|
||||||
|
- **template:** Add issue/PR templates ([#4572](https://github.com/ScoopInstaller/Scoop/issues/4572))
|
||||||
|
- **scoop-cat:** Add `scoop cat` command ([#4532](https://github.com/ScoopInstaller/Scoop/issues/4532))
|
||||||
|
- **scoop-config:** Document all configuration options ([#4579](https://github.com/ScoopInstaller/Scoop/issues/4579))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **bucket:** Remove JetBrains bucket ([dec25980](https://github.com/ScoopInstaller/Scoop/commit/dec25980525a81c176b3fd5f238e964db00f3be3))
|
||||||
|
- **bucket:** Remove nightlies bucket ([48b035d7](https://github.com/ScoopInstaller/Scoop/commit/48b035d7f99baa2e81d87ead4ff03a9594e49c3d))
|
||||||
|
- **core:** Escape '.' in 'parse_app()'. ([#4578](https://github.com/ScoopInstaller/Scoop/issues/4578))
|
||||||
|
- **core:** Use '-Encoding ASCII' in 'Out-File' ([#4571](https://github.com/ScoopInstaller/Scoop/issues/4571))
|
||||||
|
- **depends:** Specify function scope ([4d5fee36](https://github.com/ScoopInstaller/Scoop/commit/4d5fee36e1ed13fc850fd22a5414186aec030c6e))
|
||||||
|
- **install:** Use `Select-CurrentVersion` ([#4535](https://github.com/ScoopInstaller/Scoop/issues/4535))
|
||||||
|
- **install:** 'env_add_path' doesn't append '.' ([#4550](https://github.com/ScoopInstaller/Scoop/issues/4550))
|
||||||
|
- **repo:** Update repo links ([cbe29edd](https://github.com/ScoopInstaller/Scoop/commit/cbe29eddb3475e34740300eb1c2c52715446e3be))
|
||||||
|
- **scoop-update:** Update apps with '--all' ([ac71fccb](https://github.com/ScoopInstaller/Scoop/commit/ac71fccbecb3d4158f249db9c1b9bb043cb8e966))
|
||||||
|
- **scoop-update:** Fix scoop update -a requiring arguments ([#4531](https://github.com/ScoopInstaller/Scoop/issues/4531))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **shim:** Rework shimming logic ([#4543](https://github.com/ScoopInstaller/Scoop/issues/4543), [#4555](https://github.com/ScoopInstaller/Scoop/issues/4555), [3c90d1a0](https://github.com/ScoopInstaller/Scoop/commit/3c90d1a0701b0b64730dbf9ebc8d31f9b9c238f1), [2ec00d57](https://github.com/ScoopInstaller/Scoop/commit/2ec00d576c7e594dc5c0f1eac4536c5310ce6f17))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **auto-pr:** Remove hardcoded 'master' branch ([#4567](https://github.com/ScoopInstaller/Scoop/issues/4567))
|
||||||
|
- **checkver:** Improve JSONPath extraction support ([#4522](https://github.com/ScoopInstaller/Scoop/issues/4522))
|
||||||
|
- **checkver:** Use GitHub token from environment ([#4557](https://github.com/ScoopInstaller/Scoop/issues/4557))
|
||||||
|
- **schema:** Enable autoupdate for 'license' ([#4528](https://github.com/ScoopInstaller/Scoop/issues/4528), [#4596](https://github.com/ScoopInstaller/Scoop/issues/4596))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **readme:** Add link to Contributing Guide ([5e11c94a](https://github.com/ScoopInstaller/Scoop/commit/5e11c94a544ff2adbdbec5072c32a94d3e5acb9c))
|
||||||
|
- **readme:** Fix links ([3bb7036e](https://github.com/ScoopInstaller/Scoop/commit/3bb7036ee111bfe58e82ba3d0fd39189b058776a))
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
- **shim:** Revert [#4229](https://github.com/ScoopInstaller/Scoop/issues/4229) ([#4553](https://github.com/ScoopInstaller/Scoop/issues/4553))
|
||||||
|
|
||||||
|
## [2021-11-22](https://github.com/ScoopInstaller/Scoop/compare/2020-11-26...2021-11-22)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **bucket:** Move extras bucket to [@ScoopInstaller](https://github.com/ScoopInstaller) ([3e9a4d4e](https://github.com/ScoopInstaller/Scoop/commit/3e9a4d4ea0e7e4d6489099c46a763f58db07e633))
|
||||||
|
- **decompress:** Support Zstandard archive ([#4372](https://github.com/ScoopInstaller/Scoop/issues/4372), [e35ff313](https://github.com/ScoopInstaller/Scoop/commit/e35ff313a5d35cab1049024938c3423a5f6bf060), [47ebc6f1](https://github.com/ScoopInstaller/Scoop/commit/47ebc6f176b0db0afeb51b4ee237a20b2d8649e9))
|
||||||
|
- **install:** Handle arch-specific env_add_path ([#4013](https://github.com/ScoopInstaller/Scoop/issues/4013))
|
||||||
|
- **install:** s/lukesamson/ScoopInstaller in install.ps1 ([5226f26f](https://github.com/ScoopInstaller/Scoop/commit/5226f26f18157ed78f1529144404ec682374452e))
|
||||||
|
- **message:** Add config to disable aria2 warning message ([#4422](https://github.com/ScoopInstaller/Scoop/issues/4422))
|
||||||
|
- **shim:** Add another alternative shim written in rust ([#4229](https://github.com/ScoopInstaller/Scoop/issues/4229))
|
||||||
|
- **scoop-prefix:** Remove unused imports and functions ([#4494](https://github.com/ScoopInstaller/Scoop/issues/4494))
|
||||||
|
- **scoop-install:** Auto uninstall previous failed installation ([#3281](https://github.com/ScoopInstaller/Scoop/issues/3281))
|
||||||
|
- **scoop-update:** Add flags `--all` as an alternative to '*' to update all ([#3871](https://github.com/ScoopInstaller/Scoop/issues/3871))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **core:** Change url() scope to avoid conflict with global aliases ([#4342](https://github.com/ScoopInstaller/Scoop/issues/4342), [#4492](https://github.com/ScoopInstaller/Scoop/issues/4492))
|
||||||
|
- **install:** Fix `aria2`'s resume download feature ([#3292](https://github.com/ScoopInstaller/Scoop/issues/3292))
|
||||||
|
- **shim:** Fixed trailing whitespace issue ([#4307](https://github.com/ScoopInstaller/Scoop/issues/4307))
|
||||||
|
- **scoop-reset:** Skip when app instance is running ([#4359](https://github.com/ScoopInstaller/Scoop/issues/4359))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **versions:** Refactor 'versions.ps1' ([#3721](https://github.com/ScoopInstaller/Scoop/issues/3721), [e6630272](https://github.com/ScoopInstaller/Scoop/commit/e663027299d03ca768a252fa4bcbc51d124d4cae), [ae892138](https://github.com/ScoopInstaller/Scoop/commit/ae892138423bb9bbf54c8f0bed8331b93199f6b8))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **autoupdate:** Add multiple URL/hash/extract_dir... support ([#3518](https://github.com/ScoopInstaller/Scoop/issues/3518), [#4502](https://github.com/ScoopInstaller/Scoop/issues/4502))
|
||||||
|
- **schema:** Fix Schema to support `+` in version ([#4504](https://github.com/ScoopInstaller/Scoop/issues/4504))
|
||||||
|
- **supporting:** Update Json to 12.0.3, Json.Schema to 3.0.14 ([#3352](https://github.com/ScoopInstaller/Scoop/issues/3352))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **readme:** Capitalize to prevent redirect ([#4483](https://github.com/ScoopInstaller/Scoop/issues/4483))
|
||||||
|
- **readme:** s/lukesampson/ScoopInstaller in readme ([4f5acd72](https://github.com/ScoopInstaller/Scoop/commit/4f5acd72109a98a148d1bfa269c23a2d43644d23))
|
||||||
|
- **readme:** Update extras bucket url in readme ([f1a46e10](https://github.com/ScoopInstaller/Scoop/commit/f1a46e109596c55c7e83c77fc1fc9daedbe71636))
|
||||||
|
- **readme:** Update Java bucket text ([#4514](https://github.com/ScoopInstaller/Scoop/issues/4514))
|
||||||
|
- **readme:** Update notes about the NirSoft bucket ([#4524](https://github.com/ScoopInstaller/Scoop/issues/4524))
|
||||||
|
|
||||||
|
## [2020-11-26](https://github.com/ScoopInstaller/Scoop/compare/2020-10-22...2020-11-26)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **shim:** Fix Makefile typo ([0948824e](https://github.com/ScoopInstaller/Scoop/commit/0948824ec7269c979882d09342d9a269193cd674)) ([227de6cf](https://github.com/ScoopInstaller/Scoop/commit/227de6cfb8433a86ac0f0a279e691327ae04554c))
|
||||||
|
|
||||||
|
## [2020-10-22](https://github.com/ScoopInstaller/Scoop/compare/2019-10-23...2020-10-22)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **aria2:** Inline progress ([#3987](https://github.com/ScoopInstaller/Scoop/issues/3987))
|
||||||
|
- **autoupdate:** Add $urlNoExt and $basenameNoExt substitutions ([#3742](https://github.com/ScoopInstaller/Scoop/issues/3742))
|
||||||
|
- **config:** Add configuration option for default architecture ([#3778](https://github.com/ScoopInstaller/Scoop/issues/3778))
|
||||||
|
- **install:** Follow HTTP redirections when downloading a file ([#3902](https://github.com/ScoopInstaller/Scoop/issues/3902))
|
||||||
|
- **install:** Let pathes in 'env_add_path' be added ascendantly ([#3788](https://github.com/ScoopInstaller/Scoop/issues/3788), [#3976](https://github.com/ScoopInstaller/Scoop/issues/3976))
|
||||||
|
- **list:** Display main bucket name ([#3759](https://github.com/ScoopInstaller/Scoop/issues/3759))
|
||||||
|
- **shim:** Add alt-shim support ([#3998](https://github.com/ScoopInstaller/Scoop/issues/3998))
|
||||||
|
- **scoop-checkup:** Add check_envs_requirements ([#3860](https://github.com/ScoopInstaller/Scoop/issues/3860))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **bucket:** Update scoop-nonportable URL ([#3776](https://github.com/ScoopInstaller/Scoop/issues/3776))
|
||||||
|
- **download:** Fosshub download ([#4051](https://github.com/ScoopInstaller/Scoop/issues/4051))
|
||||||
|
- **download:** Progress bar on small files ([96de9c14](https://github.com/ScoopInstaller/Scoop/commit/96de9c14bb483f9278e4b0a9e22b1923ee752901))
|
||||||
|
- **hold:** Replace "locked" terminology with "held" for consistency ([#3917](https://github.com/ScoopInstaller/Scoop/issues/3917))
|
||||||
|
- **git:** Don't execute autostart programs when executing git commands ([#3993](https://github.com/ScoopInstaller/Scoop/issues/3993))
|
||||||
|
- **git:** Enforce pull without rebase ([#3765](https://github.com/ScoopInstaller/Scoop/issues/3765))
|
||||||
|
- **install:** Aria2 inline progress negative values ([#4053](https://github.com/ScoopInstaller/Scoop/issues/4053))
|
||||||
|
- **install:** Fix wrong output of 'install/failed' ([#3784](https://github.com/ScoopInstaller/Scoop/issues/3784), [#3867](https://github.com/ScoopInstaller/Scoop/issues/3867))
|
||||||
|
- **install:** Re-add "Don't send referer to portableapps.com" ([#3961](https://github.com/ScoopInstaller/Scoop/issues/3961))
|
||||||
|
- **scoop:** Remove temporary code from the scoop executable ([#3898](https://github.com/ScoopInstaller/Scoop/issues/3898))
|
||||||
|
- **update:** Update outdated PowerShell 5 warning ([#3986](https://github.com/ScoopInstaller/Scoop/issues/3986))
|
||||||
|
- **scoop-info:** Check bucket of installed app ([#3740](https://github.com/ScoopInstaller/Scoop/issues/3740))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **checkver:** Present script property ([#3900](https://github.com/ScoopInstaller/Scoop/issues/3900))
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- **init:** Force pester v4 ([#4040](https://github.com/ScoopInstaller/Scoop/issues/4040))
|
||||||
|
|
||||||
|
## [2019-10-23](https://github.com/ScoopInstaller/Scoop/compare/2019-10-18...2019-10-23)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **update:** Support $persist_dir in uninstaller.script ([#3692](https://github.com/ScoopInstaller/Scoop/issues/3692))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **core:** Use [Environment]::Is64BitOperatingSystem instead of [intptr]::size ([#3690](https://github.com/ScoopInstaller/Scoop/issues/3690))
|
||||||
|
- **git:** Remove unnecessary git_proxy_cmd() calls for local commands ([8ee45a57](https://github.com/ScoopInstaller/Scoop/commit/8ee45a57dc01a525dcf8776bf9bb45263992c81f))
|
||||||
|
- **install:** Check execution policy ([#3619](https://github.com/ScoopInstaller/Scoop/issues/3619))
|
||||||
|
- **update:** Fix scoop update changelog output ([e997017f](https://github.com/ScoopInstaller/Scoop/commit/e997017f1a03e2eefef2157acdfefe2e4fced896))
|
||||||
|
|
||||||
|
## [2019-10-18](https://github.com/ScoopInstaller/Scoop/compare/2019-06-24...2019-10-18)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **core:** Tweak Invoke-ExternalCommand parameters ([#3547](https://github.com/ScoopInstaller/Scoop/issues/3547))
|
||||||
|
- **install:** Use 7zip when available for faster zip file extraction ([#3460](https://github.com/ScoopInstaller/Scoop/issues/3460))
|
||||||
|
- **install:** Add arch support to `env_add_path` and `env_set` ([#3503](https://github.com/ScoopInstaller/Scoop/issues/3503))
|
||||||
|
- **install:** Allow $version to be used in uninstaller scripts ([#3592](https://github.com/ScoopInstaller/Scoop/issues/3592))
|
||||||
|
- **install:** Allow installing specific version if latest is installed ([11c42d78](https://github.com/ScoopInstaller/Scoop/commit/11c42d782f8adb29fbe0d94daa5f121cdda935ab))
|
||||||
|
- **update:** Allow updating apps from local manifest or URL ([#3685](https://github.com/ScoopInstaller/Scoop/issues/3685))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **autoupdate:** Decode basename when extract hash ([#3615](https://github.com/ScoopInstaller/Scoop/issues/3615))
|
||||||
|
- **autoupdate:** Remove any whitespace from hash ([#3579](https://github.com/ScoopInstaller/Scoop/issues/3579))
|
||||||
|
- **bucket:** Only lookup directories in buckets folder ([#3631](https://github.com/ScoopInstaller/Scoop/issues/3631))
|
||||||
|
- **comspec:** Escape variables when calling COMSPEC commands ([#3538](https://github.com/ScoopInstaller/Scoop/issues/3538))
|
||||||
|
- **decompress:** Fix bugs on extract_dir ([#3540](https://github.com/ScoopInstaller/Scoop/issues/3540))
|
||||||
|
- **editorconfig:** Add missing } to bat/cmd regex ([#3529](https://github.com/ScoopInstaller/Scoop/issues/3529))
|
||||||
|
- **help:** Rename help() to scoop_help() ([#3564](https://github.com/ScoopInstaller/Scoop/issues/3564))
|
||||||
|
- **install:** Use Join-Path instead of string gluing. ([#3566](https://github.com/ScoopInstaller/Scoop/issues/3566))
|
||||||
|
- **scoop-info:** Fix output for single binaries with alias ([#3651](https://github.com/ScoopInstaller/Scoop/issues/3651))
|
||||||
|
- **scoop-info:** Remove a whitespace ([#3652](https://github.com/ScoopInstaller/Scoop/issues/3652))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **auto-pr:** Fix git status detection ([7decfd4c](https://github.com/ScoopInstaller/Scoop/commit/7decfd4c107b8d8a59d7eedfe8a56e1801120c2f))
|
||||||
|
- **auto-pr:** Hard reset bucket after running ([79f8538b](https://github.com/ScoopInstaller/Scoop/commit/79f8538b57b9021db71a279879b9032fefd1ae52))
|
||||||
|
- **checkurls:** Trim renaming suffix in url ([#3677](https://github.com/ScoopInstaller/Scoop/issues/3677))
|
||||||
|
|
||||||
|
### Continuous Integration
|
||||||
|
|
||||||
|
- **appveyor:** use VS2019 image to fix PS6 issues ([#3646](https://github.com/ScoopInstaller/Scoop/issues/3646))
|
||||||
|
- **tests:** Do not force maintainers to have SCOOP_HELPERS ([#3604](https://github.com/ScoopInstaller/Scoop/issues/3604))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **readme:** Improve installation instructions ([#3600](https://github.com/ScoopInstaller/Scoop/issues/3600))
|
||||||
|
|
||||||
|
## [2019-06-24](https://github.com/ScoopInstaller/Scoop/compare/2019-05-15...2019-06-24)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **decompress:** Add 'ExtractDir' to 'Expand-...' functions ([#3466](https://github.com/ScoopInstaller/Scoop/issues/3466), [#3470](https://github.com/ScoopInstaller/Scoop/issues/3470), [#3472](https://github.com/ScoopInstaller/Scoop/issues/3472))
|
||||||
|
- **decompress:** Allow 'Expand-InnoArchive -ExtractDir' to accept '{xxx}' ([#3487](https://github.com/ScoopInstaller/Scoop/issues/3487))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **config:** Show correct output when removing a config value ([#3462](https://github.com/ScoopInstaller/Scoop/issues/3462))
|
||||||
|
- **decompress:** Change dark.exe parameter order ([6141e46d](https://github.com/ScoopInstaller/Scoop/commit/6141e46d6ae74b3ccf65e02a1c3fc92e1b4d3e7a))
|
||||||
|
- **proxy:** Rename parameters for Net.NetworkCredential ([#3483](https://github.com/ScoopInstaller/Scoop/issues/3483))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **core:** `run()` -> 'Invoke-ExternalCommand()' ([#3432](https://github.com/ScoopInstaller/Scoop/issues/3432))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **checkhashes:** Checkhashes downloading twice when architecture properties does hot have url property ([#3479](https://github.com/ScoopInstaller/Scoop/issues/3479))
|
||||||
|
- **checkhashes:** Do not call scoop directly ([#3527](https://github.com/ScoopInstaller/Scoop/issues/3527))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **readme:** Add known buckets to end of readme ([2849e0f9](https://github.com/ScoopInstaller/Scoop/commit/2849e0f96099004f761d7d8c715377e0d2c105f2))
|
||||||
|
- **readme:** Adjust URL of `runat.json` ([#3484](https://github.com/ScoopInstaller/Scoop/issues/3484))
|
||||||
|
- **readme:** Fix a small typo ([#3512](https://github.com/ScoopInstaller/Scoop/issues/3512))
|
||||||
|
- **readme:** Fix typo in readme ([03bb07c8](https://github.com/ScoopInstaller/Scoop/commit/03bb07c8231563fa3a2092b9b52d4dde372f2a8e))
|
||||||
|
- **readme:** Update readme with correct count of nirsoft apps ([e8d0be66](https://github.com/ScoopInstaller/Scoop/commit/e8d0be663b3bab25d9ee55c597b90bf922f4ec5d))
|
||||||
|
|
||||||
|
## [2019-05-15](https://github.com/ScoopInstaller/Scoop/compare/2019-05-12...2019-05-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **manifest:** XPath support in checkver and autoupdate ([#3458](https://github.com/ScoopInstaller/Scoop/issues/3458))
|
||||||
|
- **update:** Support changing scoop tracking repository ([#3459](https://github.com/ScoopInstaller/Scoop/issues/3459))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **autoupdate:** Handle xml namespace in xpath mode ([#3465](https://github.com/ScoopInstaller/Scoop/issues/3465))
|
||||||
|
|
||||||
|
## [2019-05-12](https://github.com/ScoopInstaller/Scoop/releases/tag/2019-05-12)
|
||||||
|
|
||||||
|
### BREAKING CHANGE
|
||||||
|
|
||||||
|
- **core:** Finalize bucket extraction ([#3399](https://github.com/ScoopInstaller/Scoop/issues/3399))
|
||||||
|
- **core:** Bucket extraction and refactoring ([#3449](https://github.com/ScoopInstaller/Scoop/issues/3449))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **autoupdate:** Add 'regex' alias for 'find' ([3453487e](https://github.com/ScoopInstaller/Scoop/commit/3453487ed65378cc9ba2efc658ed6bc1431ef463))
|
||||||
|
- **autoupdate:** Allow simple metalink and meta4 hash extraction ([ecf627c3](https://github.com/ScoopInstaller/Scoop/commit/ecf627c3b8493b3ccf7ddb882b0c946533774d76))
|
||||||
|
- **autoupdate:** Add version variables to autoupdate.hash.regex ([#2966](https://github.com/ScoopInstaller/Scoop/issues/2996))
|
||||||
|
- **autoupdate:** Autoupdate improvements ([#1371](https://github.com/ScoopInstaller/Scoop/issues/1371))
|
||||||
|
- **autoupdate:** Convert base64 encoded hash values ([04c9ddeb](https://github.com/ScoopInstaller/Scoop/commit/04c9ddeb6d3b99496c39543ad468d34f4f1adeff))
|
||||||
|
- **autoupdate:** Improve base64 hash detection ([310096e2](https://github.com/ScoopInstaller/Scoop/commit/310096e2386ff3bf9082d547b140a98b92b87a83))
|
||||||
|
- **core:** Add basic WSL support by appending .exe to powershell ([#2323](https://github.com/ScoopInstaller/Scoop/issues/2323))
|
||||||
|
- **core:** Add Expand-DarkArchive and some other dependency features ([#3450](https://github.com/ScoopInstaller/Scoop/issues/3450))
|
||||||
|
- **core:** Enable TLS 1.2 in core.ps1 ([#2074](https://github.com/ScoopInstaller/Scoop/issues/2074))
|
||||||
|
- **core:** Prepare extraction of main bucket ([#3060](https://github.com/ScoopInstaller/Scoop/issues/3060))
|
||||||
|
- **core:** Support loading basedirs from config ([#3121](https://github.com/ScoopInstaller/Scoop/issues/3121))
|
||||||
|
- **core:** Update requirement to version 5 or greater ([#3330](https://github.com/ScoopInstaller/Scoop/issues/3330))
|
||||||
|
- **core:** Use consistent User-Agent Header on all webrequests ([12962acf](https://github.com/ScoopInstaller/Scoop/commit/12962acfa853593e371d09186e51660aece331e5))
|
||||||
|
- **core:** Warn on shim overwrite ([#2033](https://github.com/ScoopInstaller/Scoop/issues/2033))
|
||||||
|
- **debug:** Add option to indent debug output ([bf54a978](https://github.com/ScoopInstaller/Scoop/commit/bf54a978a1bc2efcde52513a60ec5bcb7bb1a44e))
|
||||||
|
- **decompress:** Allow other args to be passthrough ([#3411](https://github.com/ScoopInstaller/Scoop/issues/3411))
|
||||||
|
- **download:** Add support for multi-connection downloads via aria2c ([#2312](https://github.com/ScoopInstaller/Scoop/issues/2312))
|
||||||
|
- **download:** Convert sourceforge urls to use downloads mirror ([#3340](https://github.com/ScoopInstaller/Scoop/issues/3340))
|
||||||
|
- **install:** Add .NET 4.5 check to scoop install script ([e52c24c9](https://github.com/ScoopInstaller/Scoop/commit/e52c24c94ec805a327440cc07aec699afc7cc308))
|
||||||
|
- **install:** Set file write permission to global persist dir ([#2524](https://github.com/ScoopInstaller/Scoop/issues/2524))
|
||||||
|
- **json:** Normalize multi-line strings to string arrays on format ([#2444](https://github.com/ScoopInstaller/Scoop/issues/2444))
|
||||||
|
- **persist:** Support persisting files without a file extension ([#2408](https://github.com/ScoopInstaller/Scoop/issues/2408))
|
||||||
|
- **shim:** Add '.com'-type shim ([#3366](https://github.com/ScoopInstaller/Scoop/issues/3366))
|
||||||
|
- **shim:** Enabled applications which require elevated privileges ([#2053](https://github.com/ScoopInstaller/Scoop/issues/2053))
|
||||||
|
- **shim:** Enabled shimming of external applications ([#2072](https://github.com/ScoopInstaller/Scoop/issues/2072))
|
||||||
|
- **shim:** Enabled wide characters forwarding in shims ([#2106](https://github.com/ScoopInstaller/Scoop/issues/2106))
|
||||||
|
- **shim:** Make shim support PowerShell 2.0 ([#2562](https://github.com/ScoopInstaller/Scoop/issues/2562))
|
||||||
|
- **shim:** Create sh shim ([#1951](https://github.com/ScoopInstaller/Scoop/issues/1951))
|
||||||
|
- **shortcuts:** Add subdirectories/arguments for shortcuts ([#1945](https://github.com/ScoopInstaller/Scoop/issues/1945))
|
||||||
|
- **shortcuts:** Allow $dir, $original_dir and $persist_dir substitutions for shortcuts ([f3ddf0c0](https://github.com/ScoopInstaller/Scoop/commit/f3ddf0c0f81ee2a11466edf5d9f6e38a0fc2b9d4))
|
||||||
|
- **shortcuts:** Get start menu folder location from environment rather than predefined user profile path ([c245a7fe](https://github.com/ScoopInstaller/Scoop/commit/c245a7fe96ffa0b0fba23bd47f31480ea93cc183))
|
||||||
|
- **uninstall:** Print purge step to console ([#3123](https://github.com/ScoopInstaller/Scoop/issues/3123))
|
||||||
|
- **uninstall:** Add support for soft/purge uninstalling of scoop itself ([#2781](https://github.com/ScoopInstaller/Scoop/issues/2781))
|
||||||
|
- **update:** Add hold/unhold command ([#3444](https://github.com/ScoopInstaller/Scoop/issues/3444))
|
||||||
|
- **scoop-checkup:** Add NTFS check to checkup command ([#1944](https://github.com/ScoopInstaller/Scoop/issues/1944))
|
||||||
|
- **scoop-checkup:** Check for LongPaths setting ([#3387](https://github.com/ScoopInstaller/Scoop/issues/3387))
|
||||||
|
- **scoop-info:** Add scoop-info command ([#2165](https://github.com/ScoopInstaller/Scoop/issues/2165))
|
||||||
|
- **scoop-info:** Support url manifest ([#2538](https://github.com/ScoopInstaller/Scoop/issues/2538))
|
||||||
|
- **scoop-prefix:** Add scoop prefix command ([#2117](https://github.com/ScoopInstaller/Scoop/issues/2117))
|
||||||
|
- **scoop-update:** Add notification for new main bucket ([#3392](https://github.com/ScoopInstaller/Scoop/issues/3392))
|
||||||
|
- **scoop-update:** Show changelog after updating scoop and buckets ([56c35f8f](https://github.com/ScoopInstaller/Scoop/commit/56c35f8f05ed387997ef1a80ec0362adec6e51a5))
|
||||||
|
- **scoop-which:** Also show other applications in PATH with 'scoop which' ([79bf99c3](https://github.com/ScoopInstaller/Scoop/commit/79bf99c3c110494d799e147263db7b6f2f921d4e))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- **autoupdate:** Fix base64 hash extraction ([98afb999](https://github.com/ScoopInstaller/Scoop/commit/98afb99990561c4f98f1e1334f348e52b4bee4e7))
|
||||||
|
- **autoupdate:** Fix base64 hash extraction length ([#2852](https://github.com/ScoopInstaller/Scoop/issues/2852))
|
||||||
|
- **autoupdate:** Fix metalink hash extraction ([2ad54747](https://github.com/ScoopInstaller/Scoop/commit/2ad547477b1432e7a269c90b393d62d88dce9803))
|
||||||
|
- **autoupdate:** Fix single line hash extraction ([#3015](https://github.com/ScoopInstaller/Scoop/issues/3015))
|
||||||
|
- **autoupdate:** Improve auto-update hash extraction regex ([21bf0dea](https://github.com/ScoopInstaller/Scoop/commit/21bf0dea561db021aa59bcd9363792436ac7c162))
|
||||||
|
- **autoupdate:** Linter fix ([c9539b65](https://github.com/ScoopInstaller/Scoop/commit/c9539b6575e8842a8f895d82b4119c3aef01d7c2))
|
||||||
|
- **autoupdate:** Use normal variable instead of magic $matches variable name ([d74e0a85](https://github.com/ScoopInstaller/Scoop/commit/d74e0a85b4081745bd1ab107a45794f02299737d))
|
||||||
|
- **bucket:** Change wording of new_issue_msg() ([e82587df](https://github.com/ScoopInstaller/Scoop/commit/e82587dfc41618474e03347df333e847dfaffc70))
|
||||||
|
- **bucket:** Fix new_issue_msg ([#3375](https://github.com/ScoopInstaller/Scoop/issues/3375))
|
||||||
|
- **bucket:** Use $_.Name on gci result ([1eb2609d](https://github.com/ScoopInstaller/Scoop/commit/1eb2609db51587772a4b5d1b6f58114f52639568))
|
||||||
|
- **config:** Enable writing to hidden .scoop file ([#1982](https://github.com/ScoopInstaller/Scoop/issues/1982))
|
||||||
|
- **config:** Save and load true/false values as booleans in scoops config ([16aec1a4](https://github.com/ScoopInstaller/Scoop/commit/16aec1a40b45ba241ef2ac45ccf89de7206891be))
|
||||||
|
- **core:** Allowed underscores in package names ([#2930](https://github.com/ScoopInstaller/Scoop/issues/2930))
|
||||||
|
- **core:** Clean up some error messages ([#2032](https://github.com/ScoopInstaller/Scoop/issues/2032))
|
||||||
|
- **core:** Change sf regex not to break some manifests ([#2476](https://github.com/ScoopInstaller/Scoop/issues/2476))
|
||||||
|
- **core:** Check if 7zip installed via Scoop instead of using 7z.exe from PATH ([55ce0c0b](https://github.com/ScoopInstaller/Scoop/commit/55ce0c0b0c481ec3807655cb7aeac6dfcf9ef271))
|
||||||
|
- **core:** Filter null or empty string from Scoops directory settings ([5d5c7fa9](https://github.com/ScoopInstaller/Scoop/commit/5d5c7fa91c03f05b705d3420618ec96d8e870174))
|
||||||
|
- **core:** Fix "enable-encryptionscheme" for OSes before Windows 10 ([#2084](https://github.com/ScoopInstaller/Scoop/issues/2084))
|
||||||
|
- **core:** Fix bug with Start-Process -Wait, exclusive to PowerShell Core on Windows 7 ([#3415](https://github.com/ScoopInstaller/Scoop/issues/3415))
|
||||||
|
- **core:** Fix for relative paths ([ff9c0c3d](https://github.com/ScoopInstaller/Scoop/commit/ff9c0c3dafb3567ee958379b83205da84a925ecf))
|
||||||
|
- **core:** Fix robocopy not releasing a directory after moving it ([e2792f2e](https://github.com/ScoopInstaller/Scoop/commit/e2792f2e02adee5947ebb95022a62282fb61024f))
|
||||||
|
- **core:** Fix substitute() for arrays ([#2048](https://github.com/ScoopInstaller/Scoop/issues/2048))
|
||||||
|
- **core:** Format hashes to lowercase ([5d56f8ff](https://github.com/ScoopInstaller/Scoop/commit/5d56f8ff5760ddedaf44eaf9652000e833b0944e))
|
||||||
|
- **core:** Invoke powershell with -noprofile flag from bash shims ([#3165](https://github.com/ScoopInstaller/Scoop/issues/3165))
|
||||||
|
- **core:** Removed the bucket from the app name when checking directories ([#2435](https://github.com/ScoopInstaller/Scoop/issues/2435))
|
||||||
|
- **core:** Return true for checking if a directory is 'in' itself ([ac8a1567](https://github.com/ScoopInstaller/Scoop/commit/ac8a156796cb6d3d9cba24a2839271d924ab8fea))
|
||||||
|
- **core:** Store last update time as String ([e8af15cc](https://github.com/ScoopInstaller/Scoop/commit/e8af15cc0615b707aee79be95f9c00e3ae0bfd9b))
|
||||||
|
- **decompress:** Add .bz2 files to decompression ([#2085](https://github.com/ScoopInstaller/Scoop/issues/2085))
|
||||||
|
- **decompress:** Added retry when unzip fail because of AV ([#1822](https://github.com/ScoopInstaller/Scoop/issues/1822))
|
||||||
|
- **decompress:** Catch unzip failures from bad file names ([#2472](https://github.com/ScoopInstaller/Scoop/issues/2472))
|
||||||
|
- **decompress:** Compatible Expand-ZipArchive() with Pscx ([#3425](https://github.com/ScoopInstaller/Scoop/issues/3425))
|
||||||
|
- **decompress:** Correct deprecation function name ([#3406](https://github.com/ScoopInstaller/Scoop/issues/3406))
|
||||||
|
- **decompress:** Fix dark parameter order ([87a1e784](https://github.com/ScoopInstaller/Scoop/commit/87a1e784d7463fea36fa41fcb7cb5537cbcfdc52))
|
||||||
|
- **depends:** Don't force adding dark dependency ([#3453](https://github.com/ScoopInstaller/Scoop/issues/3453))
|
||||||
|
- **depends:** Don't include the requested app in the list of dependencies ([1bc6a479](https://github.com/ScoopInstaller/Scoop/commit/1bc6a479ee969e44e2b0d83ed6ff19efd86c6ae9))
|
||||||
|
- **depends:** Fix empty bucket name ([#2827](https://github.com/ScoopInstaller/Scoop/issues/2827))
|
||||||
|
- **depends:** Fix null reference error when no buckets are configured ([88040972](https://github.com/ScoopInstaller/Scoop/commit/88040972a30b459a3859c7c2f883e47e19da9f84))
|
||||||
|
- **depends:** Show message about missing bucket when installing dependencies ([7a6218c5](https://github.com/ScoopInstaller/Scoop/commit/7a6218c58677170fe32cf1c2bfcfe7488e4c3655))
|
||||||
|
- **download:** Don't send referer to portableapps.com ([0c2b3da3](https://github.com/ScoopInstaller/Scoop/commit/0c2b3da3ff639722ad3ddf587219bb3155e97c7f))
|
||||||
|
- **download:** Fix fosshub downloads with aria2c ([803525a8](https://github.com/ScoopInstaller/Scoop/commit/803525a8661ffaa39fc4ad6f0dc776cccad4c45e))
|
||||||
|
- **download:** Interrupt download causes partial cache file to be used for next install ([5be02865](https://github.com/ScoopInstaller/Scoop/commit/5be0286561398debfee2c0610e51f006ef2dc2fb))
|
||||||
|
- **download:** Overwrite any existing files when extracting ([58cca68f](https://github.com/ScoopInstaller/Scoop/commit/58cca68f7565bd5e8f63e08ad052c0029b98a23d))
|
||||||
|
- **download:** Show warning about SourceForge.net hash validation fails ([8504338b](https://github.com/ScoopInstaller/Scoop/commit/8504338bc5faab3235cef2e1c2f41abd7ae496eb))
|
||||||
|
- **getopt:** Don't try to parse int arguments ([23fe5a53](https://github.com/ScoopInstaller/Scoop/commit/23fe5a5319d4ede84c532df04f576c3854fd5826))
|
||||||
|
- **getopt:** Don't try to parse array arguments ([9b6e7b5e](https://github.com/ScoopInstaller/Scoop/commit/9b6e7b5e0f7f6ddecdb139f932ad7d582fe639a4))
|
||||||
|
- **getopt:** Return remaining args, use getopt for scoop install ([b7cfd6fd](https://github.com/ScoopInstaller/Scoop/commit/b7cfd6fdb0e18a623ceacfa6fc824241dabc6d01))
|
||||||
|
- **getopt:** Skip if arg is $null ([f2d9f0d7](https://github.com/ScoopInstaller/Scoop/commit/f2d9f0d79fdf4a63879c1b87a6c0f5317a40a1d9))
|
||||||
|
- **getopt:** Skip arg if it's decimal ([5f0c8cfb](https://github.com/ScoopInstaller/Scoop/commit/5f0c8cfb0a34078bb8118a21191cf046ddad18ac))
|
||||||
|
- **git:** Disable git pager when running git log ([cac99759](https://github.com/ScoopInstaller/Scoop/commit/cac9975924691fe6e608789218b06be56bb8c658))
|
||||||
|
- **git:** Fix update log output ([0daa25c6](https://github.com/ScoopInstaller/Scoop/commit/0daa25c6300cd2ab605d63b71037d741c9c904c6))
|
||||||
|
- **json:** Catch JsonReaderException ([fb58e92c](https://github.com/ScoopInstaller/Scoop/commit/fb58e92c13552199f19f5df112801fc41321eee2))
|
||||||
|
- **install:** Add filename to warning for files without hash in the manifest ([4c9beee8](https://github.com/ScoopInstaller/Scoop/commit/4c9beee8f2df891b2ec314e1efffb2ee9d5cca20))
|
||||||
|
- **install:** Add multi-line support to pre/post_install ([#1980](https://github.com/ScoopInstaller/Scoop/issues/1980))
|
||||||
|
- **install:** Added exclusion for sourceforge. [#METR-21516] ([#2109](https://github.com/ScoopInstaller/Scoop/issues/2109))
|
||||||
|
- **install:** Ignore url fragment for PowerShell Core 6.1.0 ([#2602](https://github.com/ScoopInstaller/Scoop/issues/2602))
|
||||||
|
- **install:** Fix fail when installing from non-default bucket ([#2247](https://github.com/ScoopInstaller/Scoop/issues/2247))
|
||||||
|
- **install:** Fix PowerShell core crash ([#2554](https://github.com/ScoopInstaller/Scoop/issues/2554))
|
||||||
|
- **install:** Option to skip hash validation and error message improvements ([#2260](https://github.com/ScoopInstaller/Scoop/issues/2260))
|
||||||
|
- **install:** Remove env_ensure_home ([#1967](https://github.com/ScoopInstaller/Scoop/issues/1967))
|
||||||
|
- **install:** Show first 8 bytes of file in the hash check error message ([e4cbb42e](https://github.com/ScoopInstaller/Scoop/commit/e4cbb42e64843e53b5b24de92f43062bca98c474))
|
||||||
|
- **persist:** Fix condition for persist_permission() ([eb7b7cbf](https://github.com/ScoopInstaller/Scoop/commit/eb7b7cbf4f30e4122762856723155f3c1e980d1b)) ([1a2598bc](https://github.com/ScoopInstaller/Scoop/commit/1a2598bc3082a2e3fffac1a6bea0b42032e388f0))
|
||||||
|
- **persist:** Fixed persisting bug when force update app with same version ([#2774](https://github.com/ScoopInstaller/Scoop/issues/2774))
|
||||||
|
- **persist:** Fix the target didn't be created ([#3008](https://github.com/ScoopInstaller/Scoop/issues/3008))
|
||||||
|
- **persist:** Prevent directory creation from being output ([#1999](https://github.com/ScoopInstaller/Scoop/issues/1999))
|
||||||
|
- **scoop:** Force to add new main bucket ([#3419](https://github.com/ScoopInstaller/Scoop/issues/3419))
|
||||||
|
- **shim:** Fix .ps1 shim parsing logic ([#2564](https://github.com/ScoopInstaller/Scoop/issues/2564))
|
||||||
|
- **shim:** Fixed ps1/jar->ps1 shims args handling ([#2120](https://github.com/ScoopInstaller/Scoop/issues/2120))
|
||||||
|
- **shortcuts:** Improve Shortcut creation ([83b82386](https://github.com/ScoopInstaller/Scoop/commit/83b823868f5ef5256d3dcfbecff278bb355fefc8))
|
||||||
|
- **uninstall:** Better error handling during uninstallation ([#2079](https://github.com/ScoopInstaller/Scoop/issues/2079))
|
||||||
|
- **uninstall:** Uninstall fails to remove architecture-specific shims ([8b1871b2](https://github.com/ScoopInstaller/Scoop/commit/8b1871b20df4dbf1b603d4066937ba213c03bb32))
|
||||||
|
- **update:** Rewording PowerShell update notice ([d006fb93](https://github.com/ScoopInstaller/Scoop/commit/d006fb9315b55a9d8e6a36218cf5dbdde51433ec))
|
||||||
|
- **versions:** Improvements for the reset command to deal with empty current alias dir correctly ([#2896](https://github.com/ScoopInstaller/Scoop/issues/2896))
|
||||||
|
- **scoop-alias:** Improve "scoop alias list" output ([#2163](https://github.com/ScoopInstaller/Scoop/issues/2163))
|
||||||
|
- **scoop-cache:** Display help on incorrect cache command ([#3431](https://github.com/ScoopInstaller/Scoop/issues/3431))
|
||||||
|
- **scoop-cache:** scoop cache command not using $SCOOP_CACHE ([#1990](https://github.com/ScoopInstaller/Scoop/issues/1990))
|
||||||
|
- **scoop-info:** Improve scoop-info license attributes output ([#2397](https://github.com/ScoopInstaller/Scoop/issues/2397))
|
||||||
|
- **scoop-install:** Prevent installing programs from JSON multiple times ([936cf9cb](https://github.com/ScoopInstaller/Scoop/commit/936cf9cbb0c4dd3a594fbaf5c696ce519e586d8c))
|
||||||
|
- **scoop-reset:** Persist data on reset ([#2773](https://github.com/ScoopInstaller/Scoop/issues/2773))
|
||||||
|
- **scoop-reset:** Re-create shortcuts ([6e5b7e57](https://github.com/ScoopInstaller/Scoop/commit/6e5b7e57bb0628f072872d9a5b8c8a0fa58389e1))
|
||||||
|
- **scoop-search:** Better handling for invalid query ([bf024705](https://github.com/ScoopInstaller/Scoop/commit/bf024705a8cc38592571aa3026dca2471f19ac5a))
|
||||||
|
- **scoop-uninstall:** Checked if uninstaller removed its directory ([#2078](https://github.com/ScoopInstaller/Scoop/issues/2078))
|
||||||
|
- **scoop-update:** Add config option "show_update_log" ([d68cb3ce](https://github.com/ScoopInstaller/Scoop/commit/d68cb3ce52acaa9983f278822febd506f54ebe02))
|
||||||
|
- **scoop-update:** First scoop update fails because scoop deletes itself too early ([376630fd](https://github.com/ScoopInstaller/Scoop/commit/376630fd80a3f9012fd6e673460b9e28e375e951))
|
||||||
|
- **scoop-update:** Fix branch switching ([#3372](https://github.com/ScoopInstaller/Scoop/issues/3372))
|
||||||
|
- **scoop-update:** Fix update with cookies ([#3261](https://github.com/ScoopInstaller/Scoop/issues/3261))
|
||||||
|
- **scoop-update:** Improve is_scoop_outdated() and add last_scoop_update() ([f3f559c4](https://github.com/ScoopInstaller/Scoop/commit/f3f559c460406689dab2375310fb1026e2be58bd))
|
||||||
|
- **scoop-update:** Resolve linting, fix appveyor tests error ([#2148](https://github.com/ScoopInstaller/Scoop/issues/2148))
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
- **bucket:** Move function into lib from lib-exec ([#3062](https://github.com/ScoopInstaller/Scoop/issues/3062))
|
||||||
|
- **bucket:** Optimize buckets function ([#3341](https://github.com/ScoopInstaller/Scoop/issues/3341))
|
||||||
|
- **config:** Move configuration handling to core.ps1 ([#3242](https://github.com/ScoopInstaller/Scoop/issues/3242))
|
||||||
|
- **core:** aria2_path() -> file_path() ([0f464016](https://github.com/ScoopInstaller/Scoop/commit/0f4640168da8d68a52eb2b80af2f3ffa01c9b658))
|
||||||
|
- **core:** cmd_available() -> Test-CommandAvailable() ([#3314](https://github.com/ScoopInstaller/Scoop/issues/3314))
|
||||||
|
- **core:** ensure_all_installed() -> Confirm-InstallationStatus() ([#3293](https://github.com/ScoopInstaller/Scoop/issues/3293))
|
||||||
|
- **core:** Move default_aliases into the scoped function ([#3233](https://github.com/ScoopInstaller/Scoop/issues/3233))
|
||||||
|
- **core:** Refactor function names and fix installing 7zip locally if already globally available ([#3416](https://github.com/ScoopInstaller/Scoop/issues/3416))
|
||||||
|
- **core:** Simplified last_scoop_update() ([#2931](https://github.com/ScoopInstaller/Scoop/issues/2931))
|
||||||
|
- **core:** Tweak SecurityProtocol usage ([#3065](https://github.com/ScoopInstaller/Scoop/issues/3065))
|
||||||
|
- **decompress:** Refactored (w/ install.ps1, core.ps1) ([#3169](https://github.com/ScoopInstaller/Scoop/issues/3169))
|
||||||
|
- **decompress:** Refactor extraction handling functions ([#3204](https://github.com/ScoopInstaller/Scoop/issues/3204))
|
||||||
|
- **download:** Download functionality refactor ([#1329](https://github.com/ScoopInstaller/Scoop/issues/1329))
|
||||||
|
- **install:** Rename locate() to Find-Manifest() ([9eed3d89](https://github.com/ScoopInstaller/Scoop/commit/9eed3d8914c7a0fa294110eb0761776a01adf034))
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
- **auto-pr:** Add -App parameter ([#3157](https://github.com/ScoopInstaller/Scoop/issues/3157))
|
||||||
|
- **auto-pr:** Add SkipUpdated parameter ([#3168](https://github.com/ScoopInstaller/Scoop/issues/3168))
|
||||||
|
- **checkhashes:** Add bin\checkhashes.ps1 ([#2766](https://github.com/ScoopInstaller/Scoop/issues/2766))
|
||||||
|
- **checkurls:** Add SkipValid Parameter ([#2845](https://github.com/ScoopInstaller/Scoop/issues/2845))
|
||||||
|
- **checkurls:** Import config.ps1 in checkurls.ps1 ([126e9c97](https://github.com/ScoopInstaller/Scoop/commit/126e9c97d2ef7db537a5137167089a97f343e98e))
|
||||||
|
- **checkver:** Add 'useragent' property ([8feb3867](https://github.com/ScoopInstaller/Scoop/commit/8feb3867a74ea0340585e3e695934d96cf483a05))
|
||||||
|
- **checkver:** Add 'jsonpath' alias for 'jp' ([76fdb6b7](https://github.com/ScoopInstaller/Scoop/commit/76fdb6b74c1772bf607d2dad5f6c50269369ff88))
|
||||||
|
- **checkver:** Add 're' alias 'regex' ([468649c8](https://github.com/ScoopInstaller/Scoop/commit/468649c88dea9c1ff9614f2cdf29a521d572664e))
|
||||||
|
- **checkver:** Allow using the current version in checkver URL ([607ac9ca](https://github.com/ScoopInstaller/Scoop/commit/607ac9ca7c185da61e2c746ea87d28c2abe62adc))
|
||||||
|
- **checkver:** Fix example parameters ([#3413](https://github.com/ScoopInstaller/Scoop/issues/3413))
|
||||||
|
- **checkver:** GitHub checkver case-insensitive version check ([2e2633e9](https://github.com/ScoopInstaller/Scoop/commit/2e2633e9640f6cab5c2f895b680345cd6ca))
|
||||||
|
- **checkver:** Remove old commented code ([72754036](https://github.com/ScoopInstaller/Scoop/commit/72754036a251fffd2f2eb0e242edfd9895543e3c))
|
||||||
|
- **checkver:** Resolve issue on Powershell >6.1.0 ([#2592](https://github.com/ScoopInstaller/Scoop/issues/2592))
|
||||||
|
- **checkver:** Support skipping up to date manifests ([#2624](https://github.com/ScoopInstaller/Scoop/issues/2624))
|
||||||
|
- **schema:** Add shortcutsArray definition to schema.json ([0c7e6002](https://github.com/ScoopInstaller/Scoop/commit/0c7e60024a06e122331b17a204a158e4c5800a3d))
|
||||||
|
- **schema:** extract_to property is on active duty (not deprecated) ([59e994c5](https://github.com/ScoopInstaller/Scoop/commit/59e994c5fdeb8dffe6037ca6767d56ad13bf04da))
|
||||||
|
- **schema:** Improve comments in schema.json ([b5ed0761](https://github.com/ScoopInstaller/Scoop/commit/b5ed0761aef4f3e864533dc0460d110115850ba7))
|
||||||
|
- **supporting:** Update validator.exe and shim.exe ([#2024](https://github.com/ScoopInstaller/Scoop/issues/2024), [#2034](https://github.com/ScoopInstaller/Scoop/issues/2034))
|
||||||
|
- **supporting:** Update Newtonsoft.Json to 11.0.2, Newtonsoft.Json.Schema to 3.0.10 ([#3043](https://github.com/ScoopInstaller/Scoop/issues/3043))
|
||||||
|
- **validator:** Improve error reporting, add support for multiple files ([#3134](https://github.com/ScoopInstaller/Scoop/issues/3134))
|
||||||
|
|
||||||
|
### Continuous Integration
|
||||||
|
|
||||||
|
- **appveyor:** Rebuild cache ([7311b41b](https://github.com/ScoopInstaller/Scoop/commit/7311b41b8d1e2e010175fb7d079662bbcba5bac8))
|
||||||
|
- **appveyor:** Run tests for PowerShell 5 and 6 ([#2603](https://github.com/ScoopInstaller/Scoop/issues/2603))
|
||||||
|
- **test:** Improve installation of lessmsi and innounp ([#3409](https://github.com/ScoopInstaller/Scoop/issues/3409))
|
||||||
|
|
||||||
|
### Styles
|
||||||
|
|
||||||
|
- **lint:** PSAvoidUsingCmdletAliases ([#2075](https://github.com/ScoopInstaller/Scoop/issues/2075))
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
- **bucket:** Add importable tests for Buckets ([478f52c4](https://github.com/ScoopInstaller/Scoop/commit/478f52c421ca35ea35b5fd0b2df2631cf7d82487))
|
||||||
|
- **bucket:** Fix manifest tests for buckets ([589303fa](https://github.com/ScoopInstaller/Scoop/commit/589303facc5284f6f95c1305191e0558c0169691))
|
||||||
|
- **bucket:** Handle JSON.NET schema validation limit exceeded. ([139813a8](https://github.com/ScoopInstaller/Scoop/commit/139813a8f50ace85e2752d9b6c9f82fc64ff3e48))
|
||||||
|
- **file:** Move style constraints tests to separate test file ([7b7113fc](https://github.com/ScoopInstaller/Scoop/commit/7b7113fc3bf962aaeba625f58341c30a80f0fe6a))
|
||||||
|
- **linux:** Fix some tests on linux ([#2153](https://github.com/ScoopInstaller/Scoop/issues/2153))
|
||||||
|
- **manifest:** Expose bucketdir variable in manifest test script ([#2182](https://github.com/ScoopInstaller/Scoop/issues/2182))
|
||||||
|
- **test:** Add -TestPath param to test.ps1 ([f857dce9](https://github.com/ScoopInstaller/Scoop/commit/f857dce9f59a490f6dd07085c3abaa51e9577fda))
|
||||||
|
- **test:** Force install PSScriptAnalyzer and BuildHelpers ([7a1b5a18](https://github.com/ScoopInstaller/Scoop/commit/7a1b5a1840e30321951fa0f5333c34d10f57fa94))
|
||||||
|
- **test:** Require BuildHelpers version 2.0.0 ([ac3ee766](https://github.com/ScoopInstaller/Scoop/commit/ac3ee766722e99c1f15dc60a1f1dfb0a48428c55))
|
||||||
|
- **test:** Update BuildHelpers to version 2.0.1 ([dde4d0f9](https://github.com/ScoopInstaller/Scoop/commit/dde4d0f93f260191af5524c0ecab927f3e252361))
|
||||||
|
- **core:** Use Pester 4.0 syntax in core tests ([#2712](https://github.com/ScoopInstaller/Scoop/issues/2712))
|
||||||
|
- **install:** Use Pester 4.0 syntax to the install tests ([#2713](https://github.com/ScoopInstaller/Scoop/issues/2713))
|
||||||
|
- **test:** Use Pester 4.0 syntax to multiple files ([#2714](https://github.com/ScoopInstaller/Scoop/issues/2714))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **readme:** Add discord chat badge ([#3241](https://github.com/ScoopInstaller/Scoop/issues/3241))
|
||||||
|
- **readme:** Add more details about scoops installation ([#2273](https://github.com/ScoopInstaller/Scoop/issues/2273))
|
||||||
|
- **readme:** Corrected enable powershell executionpolicy ([#2020](https://github.com/ScoopInstaller/Scoop/issues/2020))
|
||||||
|
- **readme:** Update Discord invite link ([5f269249](https://github.com/ScoopInstaller/Scoop/commit/5f269249609b43f5c4fa9aba4def999e7ee05fe1))
|
||||||
|
- **readme:** Update requirements note ([#2509](https://github.com/ScoopInstaller/Scoop/issues/2509))
|
||||||
|
- **readme:** Fix typo (you -> your), (it's -> its) ([#2698](https://github.com/ScoopInstaller/Scoop/issues/2698))
|
||||||
|
- **readme:** Remove trailing whitespaces ([d25186bf](https://github.com/ScoopInstaller/Scoop/commit/d25186bf1f833e30d8c5b530b7c260fe399b75ed))
|
||||||
|
- **readme:** Remove "tail" from example (is coreutils) ([#2158](https://github.com/ScoopInstaller/Scoop/issues/2158))
|
||||||
|
|
||||||
|
## *Commits before 2018 are trimmed*
|
||||||
49
LICENSE
49
LICENSE
@@ -1,3 +1,27 @@
|
|||||||
|
SPDX-License-Identifier: UNLICENSE or MIT
|
||||||
|
|
||||||
|
INFORMATION ABOUT THIS PROJECT'S LICENSE (SHORT)
|
||||||
|
============================================================================================
|
||||||
|
This project is licensed under the Unlicense or the MIT license,
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
INFORMATION ABOUT THIS PROJECT'S LICENSE (LONG)
|
||||||
|
============================================================================================
|
||||||
|
This project ("Scoop") is free software, licensed under the Unlicense or the
|
||||||
|
MIT license, at your option. Scoop was previously licensed under only the Unlicense,
|
||||||
|
but was dual-licensed from version 0.2.0.
|
||||||
|
|
||||||
|
Scoop comes with ABSOLUTELY NO WARRANTY. Use it at your own risk. Scoop is provided
|
||||||
|
on an AS-IS BASIS and its contributors disclaim all warranties.
|
||||||
|
|
||||||
|
You may use, modify, distribute, sell, copy, compile, or merge Scoop by any means.
|
||||||
|
|
||||||
|
Copies of both licenses can be found below.
|
||||||
|
|
||||||
|
THE LICENSE OF SCOOP
|
||||||
|
============================================================================================
|
||||||
|
Unlicense
|
||||||
|
---------
|
||||||
This is free and unencumbered software released into the public domain.
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
@@ -22,3 +46,28 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
For more information, please refer to <http://unlicense.org/>
|
For more information, please refer to <http://unlicense.org/>
|
||||||
|
|
||||||
|
MIT license
|
||||||
|
-----------
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2013-2017 Luke Sampson (https://github.com/lukesampson)
|
||||||
|
Copyright (c) 2013-present Scoop contributors (https://github.com/ScoopInstaller/Scoop/graphs/contributors)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
# Only diagnostic records of the specified severity will be generated.
|
# Only diagnostic records of the specified severity will be generated.
|
||||||
# Uncomment the following line if you only want Errors and Warnings but
|
# Uncomment the following line if you only want Errors and Warnings but
|
||||||
# not Information diagnostic records.
|
# not Information diagnostic records.
|
||||||
Severity = @('Error','Warning')
|
Severity = @('Error')
|
||||||
|
|
||||||
# Analyze **only** the following rules. Use IncludeRules when you want
|
# Analyze **only** the following rules. Use IncludeRules when you want
|
||||||
# to invoke only a small subset of the defualt rules.
|
# to invoke only a small subset of the defualt rules.
|
||||||
|
|||||||
91
README.md
91
README.md
@@ -3,23 +3,23 @@
|
|||||||
<h1 align="center">Scoop</h1>
|
<h1 align="center">Scoop</h1>
|
||||||
</p>
|
</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<b><a href="https://github.com/lukesampson/scoop#what-does-scoop-do">Features</a></b>
|
<b><a href="https://github.com/ScoopInstaller/Scoop#what-does-scoop-do">Features</a></b>
|
||||||
|
|
|
|
||||||
<b><a href="https://github.com/lukesampson/scoop#installation">Installation</a></b>
|
<b><a href="https://github.com/ScoopInstaller/Scoop#installation">Installation</a></b>
|
||||||
|
|
|
|
||||||
<b><a href="https://github.com/lukesampson/scoop/wiki">Documentation</a></b>
|
<b><a href="https://github.com/ScoopInstaller/Scoop/wiki">Documentation</a></b>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
- - -
|
- - -
|
||||||
<p align="center" >
|
<p align="center" >
|
||||||
<a href="https://github.com/lukesampson/scoop">
|
<a href="https://github.com/ScoopInstaller/Scoop">
|
||||||
<img src="https://img.shields.io/github/languages/code-size/lukesampson/scoop.svg" alt="Code Size" />
|
<img src="https://img.shields.io/github/languages/code-size/ScoopInstaller/Scoop.svg" alt="Code Size" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/lukesampson/scoop">
|
<a href="https://github.com/ScoopInstaller/Scoop">
|
||||||
<img src="https://img.shields.io/github/repo-size/lukesampson/scoop.svg" alt="Repository size" />
|
<img src="https://img.shields.io/github/repo-size/ScoopInstaller/Scoop.svg" alt="Repository size" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ci.appveyor.com/project/lukesampson/scoop">
|
<a href="https://github.com/ScoopInstaller/Scoop/actions/workflows/ci.yml">
|
||||||
<img src="https://ci.appveyor.com/api/projects/status/05foxatmrqo0l788?svg=true" alt="Build Status" />
|
<img src="https://github.com/ScoopInstaller/Scoop/actions/workflows/ci.yml/badge.svg" alt="Scoop Core CI Tests" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/s9yRQHt">
|
<a href="https://discord.gg/s9yRQHt">
|
||||||
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
|
<img src="https://img.shields.io/badge/chat-on%20discord-7289DA.svg" alt="Discord Chat" />
|
||||||
@@ -27,8 +27,8 @@
|
|||||||
<a href="https://gitter.im/lukesampson/scoop">
|
<a href="https://gitter.im/lukesampson/scoop">
|
||||||
<img src="https://badges.gitter.im/lukesampson/scoop.png" alt="Gitter Chat" />
|
<img src="https://badges.gitter.im/lukesampson/scoop.png" alt="Gitter Chat" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/lukesampson/scoop/blob/master/LICENSE">
|
<a href="https://github.com/ScoopInstaller/Scoop/blob/master/LICENSE">
|
||||||
<img src="https://img.shields.io/github/license/lukesampson/scoop.svg" alt="License" />
|
<img src="https://img.shields.io/github/license/ScoopInstaller/Scoop.svg" alt="License" />
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -36,14 +36,14 @@ Scoop is a command-line installer for Windows.
|
|||||||
|
|
||||||
## What does Scoop do?
|
## What does Scoop do?
|
||||||
|
|
||||||
Scoop installs programs from the command line with a minimal amount of friction. It tries to eliminate things like:
|
Scoop installs programs from the command line with a minimal amount of friction. It:
|
||||||
|
|
||||||
- Permission popup windows
|
- Eliminates permission popup windows
|
||||||
- GUI wizard-style installers
|
- Hides GUI wizard-style installers
|
||||||
- Path pollution from installing lots of programs
|
- Prevents PATH pollution from installing lots of programs
|
||||||
- Unexpected side-effects from installing and uninstalling programs
|
- Avoids unexpected side-effects from installing and uninstalling programs
|
||||||
- The need to find and install dependencies
|
- Finds and installs dependencies automatically
|
||||||
- The need to perform extra setup steps to get a working program
|
- Performs all the extra setup steps itself to get a working program
|
||||||
|
|
||||||
Scoop is very scriptable, so you can run repeatable setups to get your environment just the way you like, e.g.:
|
Scoop is very scriptable, so you can run repeatable setups to get your environment just the way you like, e.g.:
|
||||||
|
|
||||||
@@ -56,46 +56,17 @@ scoop install python ruby go perl
|
|||||||
|
|
||||||
If you've built software that you'd like others to use, Scoop is an alternative to building an installer (e.g. MSI or InnoSetup) — you just need to zip your program and provide a JSON manifest that describes how to install it.
|
If you've built software that you'd like others to use, Scoop is an alternative to building an installer (e.g. MSI or InnoSetup) — you just need to zip your program and provide a JSON manifest that describes how to install it.
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- Windows 7 SP1+ / Windows Server 2008+
|
|
||||||
- [PowerShell 5](https://aka.ms/wmf5download) (or later, include [PowerShell Core](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-windows?view=powershell-6)) and [.NET Framework 4.5](https://www.microsoft.com/net/download) (or later)
|
|
||||||
- PowerShell must be enabled for your user account e.g. `Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser`
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Run the following command from your PowerShell to install scoop to its default location (`C:\Users\<user>\scoop`)
|
Run the following command from a **non-admin** PowerShell to install scoop to its default location `C:\Users\<YOUR USERNAME>\scoop`.
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
|
|
||||||
|
|
||||||
# or shorter
|
|
||||||
iwr -useb get.scoop.sh | iex
|
iwr -useb get.scoop.sh | iex
|
||||||
```
|
```
|
||||||
|
|
||||||
Once installed, run `scoop help` for instructions.
|
Advanced installation instruction and full documentation of the installer are available in [ScoopInstaller/Install](https://github.com/ScoopInstaller/Install). Please create new issues there if you have questions about the installation.
|
||||||
|
|
||||||
The default setup is configured so all user installed programs and Scoop itself live in `C:\Users\<user>\scoop`.
|
## [Documentation](https://github.com/ScoopInstaller/Scoop/wiki)
|
||||||
Globally installed programs (`--global`) live in `C:\ProgramData\scoop`.
|
|
||||||
These settings can be changed through environment variables.
|
|
||||||
|
|
||||||
### Install Scoop to a Custom Directory by changing `SCOOP`
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
$env:SCOOP='D:\Applications\Scoop'
|
|
||||||
[Environment]::SetEnvironmentVariable('SCOOP', $env:SCOOP, 'User')
|
|
||||||
# run the installer
|
|
||||||
```
|
|
||||||
|
|
||||||
### Configure Scoop to install global programs to a Custom Directory by changing `SCOOP_GLOBAL`
|
|
||||||
|
|
||||||
```powershell
|
|
||||||
$env:SCOOP_GLOBAL='F:\GlobalScoopApps'
|
|
||||||
[Environment]::SetEnvironmentVariable('SCOOP_GLOBAL', $env:SCOOP_GLOBAL, 'Machine')
|
|
||||||
# run the installer
|
|
||||||
```
|
|
||||||
|
|
||||||
## [Documentation](https://github.com/lukesampson/scoop/wiki)
|
|
||||||
|
|
||||||
## Multi-connection downloads with `aria2`
|
## Multi-connection downloads with `aria2`
|
||||||
|
|
||||||
@@ -105,13 +76,17 @@ Scoop can utilize [`aria2`](https://github.com/aria2/aria2) to use multi-connect
|
|||||||
scoop install aria2
|
scoop install aria2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
By default, `scoop` displays a warning when running `scoop install` or `scoop update` while `aria2` is enabled. This warning can be suppressed by running `scoop config aria2-warning-enabled false`.
|
||||||
|
|
||||||
You can tweak the following `aria2` settings with the `scoop config` command:
|
You can tweak the following `aria2` settings with the `scoop config` command:
|
||||||
|
|
||||||
- aria2-enabled (default: true)
|
- aria2-enabled (default: true)
|
||||||
|
- aria2-warning-enabled (default: true)
|
||||||
- [aria2-retry-wait](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-retry-wait) (default: 2)
|
- [aria2-retry-wait](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-retry-wait) (default: 2)
|
||||||
- [aria2-split](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-s) (default: 5)
|
- [aria2-split](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-s) (default: 5)
|
||||||
- [aria2-max-connection-per-server](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-x) (default: 5)
|
- [aria2-max-connection-per-server](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-x) (default: 5)
|
||||||
- [aria2-min-split-size](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-k) (default: 5M)
|
- [aria2-min-split-size](https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-k) (default: 5M)
|
||||||
|
- [aria2-options](https://aria2.github.io/manual/en/html/aria2c.html#options) (default: )
|
||||||
|
|
||||||
## Inspiration
|
## Inspiration
|
||||||
|
|
||||||
@@ -126,6 +101,10 @@ Since installers are common, Scoop supports them too (and their uninstallers).
|
|||||||
|
|
||||||
Scoop is also great at handling single-file programs and Powershell scripts. These don't even need to be compressed. See the [runat](https://github.com/ScoopInstaller/Main/blob/master/bucket/runat.json) package for an example: it's really just a GitHub gist.
|
Scoop is also great at handling single-file programs and Powershell scripts. These don't even need to be compressed. See the [runat](https://github.com/ScoopInstaller/Main/blob/master/bucket/runat.json) package for an example: it's really just a GitHub gist.
|
||||||
|
|
||||||
|
### Contribute to this project
|
||||||
|
|
||||||
|
If you'd like to improve Scoop by adding features or fixing bugs, please read our [Contributing Guide](https://github.com/ScoopInstaller/.github/blob/main/.github/CONTRIBUTING.md).
|
||||||
|
|
||||||
### Support this project
|
### Support this project
|
||||||
|
|
||||||
If you find Scoop useful and would like to support ongoing development and maintenance, here's how:
|
If you find Scoop useful and would like to support ongoing development and maintenance, here's how:
|
||||||
@@ -137,14 +116,12 @@ If you find Scoop useful and would like to support ongoing development and maint
|
|||||||
The following buckets are known to scoop:
|
The following buckets are known to scoop:
|
||||||
|
|
||||||
- [main](https://github.com/ScoopInstaller/Main) - Default bucket for the most common (mostly CLI) apps
|
- [main](https://github.com/ScoopInstaller/Main) - Default bucket for the most common (mostly CLI) apps
|
||||||
- [extras](https://github.com/lukesampson/scoop-extras) - Apps that don't fit the main bucket's [criteria](https://github.com/lukesampson/scoop/wiki/Criteria-for-including-apps-in-the-main-bucket)
|
- [extras](https://github.com/ScoopInstaller/Extras) - Apps that don't fit the main bucket's [criteria](https://github.com/ScoopInstaller/Scoop/wiki/Criteria-for-including-apps-in-the-main-bucket)
|
||||||
- [games](https://github.com/Calinou/scoop-games) - Open source/freeware games and game-related tools
|
- [games](https://github.com/Calinou/scoop-games) - Open source/freeware games and game-related tools
|
||||||
- [nerd-fonts](https://github.com/matthewjberger/scoop-nerd-fonts) - Nerd Fonts
|
- [nerd-fonts](https://github.com/matthewjberger/scoop-nerd-fonts) - Nerd Fonts
|
||||||
- [nirsoft](https://github.com/kodybrown/scoop-nirsoft) - A subset of the [250](https://github.com/rasa/scoop-directory/blob/master/by-score.md#MCOfficer_scoop-nirsoft) [Nirsoft](https://nirsoft.net) apps
|
- [nirsoft](https://github.com/kodybrown/scoop-nirsoft) - Almost all of the [250+](https://rasa.github.io/scoop-directory/by-apps#kodybrown_scoop-nirsoft) apps from [Nirsoft](https://nirsoft.net)
|
||||||
- [java](https://github.com/ScoopInstaller/Java) - Installers for Oracle Java, OpenJDK, Zulu, ojdkbuild, AdoptOpenJDK, Amazon Corretto, BellSoft Liberica & SapMachine
|
- [java](https://github.com/ScoopInstaller/Java) - A collection of Java development kits (JDKs), Java runtime engines (JREs), Java's virtual machine debugging tools and Java based runtime engines.
|
||||||
- [jetbrains](https://github.com/Ash258/Scoop-JetBrains) - Installers for all JetBrains utilities and IDEs
|
- [nonportable](https://github.com/TheRandomLabs/scoop-nonportable) - Non-portable apps (may require UAC)
|
||||||
<!-- * [nightlies](https://github.com/ScoopInstaller/Nightlies) - No longer used -->
|
|
||||||
- [nonportable](https://github.com/oltolm/scoop-nonportable) - Non-portable apps (may require UAC)
|
|
||||||
- [php](https://github.com/ScoopInstaller/PHP) - Installers for most versions of PHP
|
- [php](https://github.com/ScoopInstaller/PHP) - Installers for most versions of PHP
|
||||||
- [versions](https://github.com/ScoopInstaller/Versions) - Alternative versions of apps found in other buckets
|
- [versions](https://github.com/ScoopInstaller/Versions) - Alternative versions of apps found in other buckets
|
||||||
|
|
||||||
@@ -159,4 +136,4 @@ scoop bucket add extras
|
|||||||
|
|
||||||
## Other application buckets
|
## Other application buckets
|
||||||
|
|
||||||
Many other application buckets hosted on Github can be found in the [Scoop Directory](https://github.com/rasa/scoop-directory).
|
Many other application buckets hosted on Github can be found in the [Scoop Directory](https://rasa.github.io/scoop-directory/) or via [other search engines](https://rasa.github.io/scoop-directory/#other-search-engines).
|
||||||
|
|||||||
34
appveyor.yml
34
appveyor.yml
@@ -2,36 +2,34 @@ version: "{build}-{branch}"
|
|||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
- gh-pages
|
- gh-pages
|
||||||
build: off
|
build: false
|
||||||
deploy: off
|
deploy: false
|
||||||
clone_depth: 49
|
clone_depth: 2
|
||||||
image: Visual Studio 2019
|
image: Visual Studio 2022
|
||||||
environment:
|
environment:
|
||||||
scoop: C:\projects\scoop
|
|
||||||
scoop_home: C:\projects\scoop
|
|
||||||
scoop_helpers: C:\projects\helpers
|
|
||||||
lessmsi: '%scoop_helpers%\lessmsi\lessmsi.exe'
|
|
||||||
innounp: '%scoop_helpers%\innounp\innounp.exe'
|
|
||||||
matrix:
|
matrix:
|
||||||
- PowerShell: 5
|
- PowerShell: 5
|
||||||
- PowerShell: 6
|
- PowerShell: 7
|
||||||
cache:
|
|
||||||
- '%USERPROFILE%\Documents\WindowsPowerShell\Modules -> appveyor.yml, test\bin\*.ps1'
|
|
||||||
- C:\projects\helpers -> appveyor.yml, test\bin\*.ps1
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
for:
|
for:
|
||||||
- matrix:
|
- matrix:
|
||||||
only:
|
only:
|
||||||
- PowerShell: 5
|
- PowerShell: 5
|
||||||
|
cache:
|
||||||
|
- '%USERPROFILE%\Documents\WindowsPowerShell\Modules -> appveyor.yml, test\bin\*.ps1'
|
||||||
|
- C:\projects\helpers -> appveyor.yml, test\bin\*.ps1
|
||||||
install:
|
install:
|
||||||
- ps: . "$env:SCOOP_HOME\test\bin\init.ps1"
|
- ps: .\test\bin\init.ps1
|
||||||
test_script:
|
test_script:
|
||||||
- ps: . "$env:SCOOP_HOME\test\bin\test.ps1" -TestPath "$env:APPVEYOR_BUILD_FOLDER"
|
- ps: .\test\bin\test.ps1
|
||||||
- matrix:
|
- matrix:
|
||||||
only:
|
only:
|
||||||
- PowerShell: 6
|
- PowerShell: 7
|
||||||
|
cache:
|
||||||
|
- '%USERPROFILE%\Documents\PowerShell\Modules -> appveyor.yml, test\bin\*.ps1'
|
||||||
|
- C:\projects\helpers -> appveyor.yml, test\bin\*.ps1
|
||||||
install:
|
install:
|
||||||
- pwsh: . "$env:SCOOP_HOME\test\bin\init.ps1"
|
- pwsh: .\test\bin\init.ps1
|
||||||
test_script:
|
test_script:
|
||||||
- pwsh: . "$env:SCOOP_HOME\test\bin\test.ps1" -TestPath "$env:APPVEYOR_BUILD_FOLDER"
|
- pwsh: .\test\bin\test.ps1
|
||||||
|
|||||||
@@ -2,25 +2,29 @@
|
|||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Updates manifests and pushes them or creates pull-requests.
|
Updates manifests and pushes them or creates pull-requests.
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Updates manifests and pushes them directly to the master branch or creates pull-requests for upstream.
|
Updates manifests and pushes them directly to the origin branch or creates pull-requests for upstream.
|
||||||
.PARAMETER Upstream
|
.PARAMETER Upstream
|
||||||
Upstream repository with the target branch.
|
Upstream repository with the target branch.
|
||||||
Must be in format '<user>/<repo>:<branch>'
|
Must be in format '<user>/<repo>:<branch>'
|
||||||
|
.PARAMETER OriginBranch
|
||||||
|
Origin (local) branch name.
|
||||||
.PARAMETER App
|
.PARAMETER App
|
||||||
Manifest name to search.
|
Manifest name to search.
|
||||||
Placeholders are supported.
|
Placeholders are supported.
|
||||||
.PARAMETER Dir
|
.PARAMETER Dir
|
||||||
The directory where to search for manifests.
|
The directory where to search for manifests.
|
||||||
.PARAMETER Push
|
.PARAMETER Push
|
||||||
Push updates directly to 'origin master'.
|
Push updates directly to 'origin branch'.
|
||||||
.PARAMETER Request
|
.PARAMETER Request
|
||||||
Create pull-requests on 'upstream master' for each update.
|
Create pull-requests on 'upstream branch' for each update.
|
||||||
.PARAMETER Help
|
.PARAMETER Help
|
||||||
Print help to console.
|
Print help to console.
|
||||||
.PARAMETER SpecialSnowflakes
|
.PARAMETER SpecialSnowflakes
|
||||||
An array of manifests, which should be updated all the time. (-ForceUpdate parameter to checkver)
|
An array of manifests, which should be updated all the time. (-ForceUpdate parameter to checkver)
|
||||||
.PARAMETER SkipUpdated
|
.PARAMETER SkipUpdated
|
||||||
Updated manifests will not be shown.
|
Updated manifests will not be shown.
|
||||||
|
.PARAMETER ThrowError
|
||||||
|
Throw error as exception instead of just printing it.
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS BUCKETROOT > .\bin\auto-pr.ps1 'someUsername/repository:branch' -Request
|
PS BUCKETROOT > .\bin\auto-pr.ps1 'someUsername/repository:branch' -Request
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
@@ -37,6 +41,7 @@ param(
|
|||||||
$true
|
$true
|
||||||
})]
|
})]
|
||||||
[String] $Upstream,
|
[String] $Upstream,
|
||||||
|
[String] $OriginBranch = 'master',
|
||||||
[String] $App = '*',
|
[String] $App = '*',
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[ValidateScript( {
|
[ValidateScript( {
|
||||||
@@ -51,7 +56,8 @@ param(
|
|||||||
[Switch] $Request,
|
[Switch] $Request,
|
||||||
[Switch] $Help,
|
[Switch] $Help,
|
||||||
[string[]] $SpecialSnowflakes,
|
[string[]] $SpecialSnowflakes,
|
||||||
[Switch] $SkipUpdated
|
[Switch] $SkipUpdated,
|
||||||
|
[Switch] $ThrowError
|
||||||
)
|
)
|
||||||
|
|
||||||
. "$PSScriptRoot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
@@ -65,12 +71,12 @@ if ((!$Push -and !$Request) -or $Help) {
|
|||||||
Usage: auto-pr.ps1 [OPTION]
|
Usage: auto-pr.ps1 [OPTION]
|
||||||
|
|
||||||
Mandatory options:
|
Mandatory options:
|
||||||
-p, -push push updates directly to 'origin master'
|
-p, -push push updates directly to 'origin branch'
|
||||||
-r, -request create pull-requests on 'upstream master' for each update
|
-r, -request create pull-requests on 'upstream branch' for each update
|
||||||
|
|
||||||
Optional options:
|
Optional options:
|
||||||
-u, -upstream upstream repository with target branch
|
-u, -upstream upstream repository with target branch
|
||||||
only used if -r is set (default: lukesampson/scoop:master)
|
-o, -originbranch origin (local) branch name
|
||||||
-h, -help
|
-h, -help
|
||||||
'@
|
'@
|
||||||
exit 0
|
exit 0
|
||||||
@@ -104,7 +110,7 @@ function pull_requests($json, [String] $app, [String] $upstream, [String] $manif
|
|||||||
$homepage = $json.homepage
|
$homepage = $json.homepage
|
||||||
$branch = "manifest/$app-$version"
|
$branch = "manifest/$app-$version"
|
||||||
|
|
||||||
execute 'hub checkout master'
|
execute "hub checkout $OriginBranch"
|
||||||
Write-Host "hub rev-parse --verify $branch" -ForegroundColor Green
|
Write-Host "hub rev-parse --verify $branch" -ForegroundColor Green
|
||||||
hub rev-parse --verify $branch
|
hub rev-parse --verify $branch
|
||||||
|
|
||||||
@@ -141,7 +147,7 @@ a new version of [$app]($homepage) is available.
|
|||||||
| New version | $version |
|
| New version | $version |
|
||||||
"@
|
"@
|
||||||
|
|
||||||
hub pull-request -m "$msg" -b '$upstream' -h '$branch'
|
hub pull-request -m "$msg" -b "$upstream" -h "$branch"
|
||||||
if ($LASTEXITCODE -gt 0) {
|
if ($LASTEXITCODE -gt 0) {
|
||||||
execute 'hub reset'
|
execute 'hub reset'
|
||||||
abort "Pull Request failed! (hub pull-request -m '${app}: Update to version $version' -b '$upstream' -h '$branch')"
|
abort "Pull Request failed! (hub pull-request -m '${app}: Update to version $version' -b '$upstream' -h '$branch')"
|
||||||
@@ -150,18 +156,18 @@ a new version of [$app]($homepage) is available.
|
|||||||
|
|
||||||
Write-Host 'Updating ...' -ForegroundColor DarkCyan
|
Write-Host 'Updating ...' -ForegroundColor DarkCyan
|
||||||
if ($Push) {
|
if ($Push) {
|
||||||
execute 'hub pull origin master'
|
execute "hub pull origin $OriginBranch"
|
||||||
execute 'hub checkout master'
|
execute "hub checkout $OriginBranch"
|
||||||
} else {
|
} else {
|
||||||
execute 'hub pull upstream master'
|
execute "hub pull upstream $OriginBranch"
|
||||||
execute 'hub push origin master'
|
execute "hub push origin $OriginBranch"
|
||||||
}
|
}
|
||||||
|
|
||||||
. "$PSScriptRoot\checkver.ps1" -App $App -Dir $Dir -Update -SkipUpdated:$SkipUpdated
|
. "$PSScriptRoot\checkver.ps1" -App $App -Dir $Dir -Update -SkipUpdated:$SkipUpdated -ThrowError:$ThrowError
|
||||||
if ($SpecialSnowflakes) {
|
if ($SpecialSnowflakes) {
|
||||||
Write-Host "Forcing update on our special snowflakes: $($SpecialSnowflakes -join ',')" -ForegroundColor DarkCyan
|
Write-Host "Forcing update on our special snowflakes: $($SpecialSnowflakes -join ',')" -ForegroundColor DarkCyan
|
||||||
$SpecialSnowflakes -split ',' | ForEach-Object {
|
$SpecialSnowflakes -split ',' | ForEach-Object {
|
||||||
. "$PSScriptRoot\checkver.ps1" $_ -Dir $Dir -ForceUpdate
|
. "$PSScriptRoot\checkver.ps1" $_ -Dir $Dir -ForceUpdate -ThrowError:$ThrowError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,10 +204,10 @@ hub diff --name-only | ForEach-Object {
|
|||||||
|
|
||||||
if ($Push) {
|
if ($Push) {
|
||||||
Write-Host 'Pushing updates ...' -ForegroundColor DarkCyan
|
Write-Host 'Pushing updates ...' -ForegroundColor DarkCyan
|
||||||
execute 'hub push origin master'
|
execute "hub push origin $OriginBranch"
|
||||||
} else {
|
} else {
|
||||||
Write-Host 'Returning to master branch and removing unstaged files ...' -ForegroundColor DarkCyan
|
Write-Host "Returning to $OriginBranch branch and removing unstaged files ..." -ForegroundColor DarkCyan
|
||||||
execute 'hub checkout -f master'
|
execute "hub checkout -f $OriginBranch"
|
||||||
}
|
}
|
||||||
|
|
||||||
execute 'hub reset --hard'
|
execute 'hub reset --hard'
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
Manifests without mismatch will not be shown.
|
Manifests without mismatch will not be shown.
|
||||||
.PARAMETER UseCache
|
.PARAMETER UseCache
|
||||||
Downloaded files will not be deleted after script finish.
|
Downloaded files will not be deleted after script finish.
|
||||||
Should not be used, because check should be used for downloading actual version of file (as normal user, not finding in some document from vendors, which could be damaged / wrong (Example: Slack@3.3.1 lukesampson/scoop-extras#1192)), not some previously downloaded.
|
Should not be used, because check should be used for downloading actual version of file (as normal user, not finding in some document from vendors, which could be damaged / wrong (Example: Slack@3.3.1 ScoopInstaller/Extras#1192)), not some previously downloaded.
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS BUCKETROOT> .\bin\checkhashes.ps1
|
PS BUCKETROOT> .\bin\checkhashes.ps1
|
||||||
Check all manifests for hash mismatch.
|
Check all manifests for hash mismatch.
|
||||||
@@ -75,9 +75,9 @@ foreach ($single in Get-ChildItem $Dir "$App.json") {
|
|||||||
$manifest.hash | ForEach-Object { $hashes += $_ }
|
$manifest.hash | ForEach-Object { $hashes += $_ }
|
||||||
} elseif ($manifest.architecture) {
|
} elseif ($manifest.architecture) {
|
||||||
# First handle 64bit
|
# First handle 64bit
|
||||||
url $manifest '64bit' | ForEach-Object { $urls += $_ }
|
script:url $manifest '64bit' | ForEach-Object { $urls += $_ }
|
||||||
hash $manifest '64bit' | ForEach-Object { $hashes += $_ }
|
hash $manifest '64bit' | ForEach-Object { $hashes += $_ }
|
||||||
url $manifest '32bit' | ForEach-Object { $urls += $_ }
|
script:url $manifest '32bit' | ForEach-Object { $urls += $_ }
|
||||||
hash $manifest '32bit' | ForEach-Object { $hashes += $_ }
|
hash $manifest '32bit' | ForEach-Object { $hashes += $_ }
|
||||||
} else {
|
} else {
|
||||||
err $name 'Manifest does not contain URL property.'
|
err $name 'Manifest does not contain URL property.'
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ foreach ($man in $Queue) {
|
|||||||
if ($manifest.url) {
|
if ($manifest.url) {
|
||||||
$manifest.url | ForEach-Object { $urls += $_ }
|
$manifest.url | ForEach-Object { $urls += $_ }
|
||||||
} else {
|
} else {
|
||||||
url $manifest '64bit' | ForEach-Object { $urls += $_ }
|
script:url $manifest '64bit' | ForEach-Object { $urls += $_ }
|
||||||
url $manifest '32bit' | ForEach-Object { $urls += $_ }
|
script:url $manifest '32bit' | ForEach-Object { $urls += $_ }
|
||||||
}
|
}
|
||||||
|
|
||||||
$urls | ForEach-Object {
|
$urls | ForEach-Object {
|
||||||
|
|||||||
225
bin/checkver.ps1
225
bin/checkver.ps1
@@ -15,6 +15,10 @@
|
|||||||
Useful for hash updates.
|
Useful for hash updates.
|
||||||
.PARAMETER SkipUpdated
|
.PARAMETER SkipUpdated
|
||||||
Updated manifests will not be shown.
|
Updated manifests will not be shown.
|
||||||
|
.PARAMETER Version
|
||||||
|
Update manifest to specific version.
|
||||||
|
.PARAMETER ThrowError
|
||||||
|
Throw error as exception instead of just printing it.
|
||||||
.EXAMPLE
|
.EXAMPLE
|
||||||
PS BUCKETROOT > .\bin\checkver.ps1
|
PS BUCKETROOT > .\bin\checkver.ps1
|
||||||
Check all manifest inside default directory.
|
Check all manifest inside default directory.
|
||||||
@@ -60,20 +64,27 @@ param(
|
|||||||
[Switch] $Update,
|
[Switch] $Update,
|
||||||
[Switch] $ForceUpdate,
|
[Switch] $ForceUpdate,
|
||||||
[Switch] $SkipUpdated,
|
[Switch] $SkipUpdated,
|
||||||
[String] $Version = ''
|
[String] $Version = '',
|
||||||
|
[Switch] $ThrowError
|
||||||
)
|
)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\autoupdate.ps1"
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
. "$psscriptroot\..\lib\autoupdate.ps1"
|
. "$PSScriptRoot\..\lib\buckets.ps1"
|
||||||
. "$psscriptroot\..\lib\json.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1"
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1"
|
||||||
. "$psscriptroot\..\lib\install.ps1" # needed for hash generation
|
. "$PSScriptRoot\..\lib\install.ps1" # needed for hash generation
|
||||||
. "$psscriptroot\..\lib\unix.ps1"
|
. "$PSScriptRoot\..\lib\unix.ps1"
|
||||||
|
|
||||||
$Dir = Resolve-Path $Dir
|
$Dir = Resolve-Path $Dir
|
||||||
$Search = $App
|
$Search = $App
|
||||||
|
$GitHubToken = Get-GitHubToken
|
||||||
|
|
||||||
|
# don't use $Version with $App = '*'
|
||||||
|
if ($App -eq '*' -and $Version -ne '') {
|
||||||
|
throw "Don't use '-Version' with '-App *'!"
|
||||||
|
}
|
||||||
|
|
||||||
# get apps to check
|
# get apps to check
|
||||||
$Queue = @()
|
$Queue = @()
|
||||||
@@ -94,7 +105,7 @@ Get-Event | ForEach-Object {
|
|||||||
$Queue | ForEach-Object {
|
$Queue | ForEach-Object {
|
||||||
$name, $json = $_
|
$name, $json = $_
|
||||||
|
|
||||||
$substitutions = get_version_substitutions $json.version
|
$substitutions = Get-VersionSubstitution $json.version # 'autoupdate.ps1'
|
||||||
|
|
||||||
$wc = New-Object Net.Webclient
|
$wc = New-Object Net.Webclient
|
||||||
if ($json.checkver.useragent) {
|
if ($json.checkver.useragent) {
|
||||||
@@ -114,18 +125,21 @@ $Queue | ForEach-Object {
|
|||||||
$jsonpath = ''
|
$jsonpath = ''
|
||||||
$xpath = ''
|
$xpath = ''
|
||||||
$replace = ''
|
$replace = ''
|
||||||
|
$useGithubAPI = $false
|
||||||
|
|
||||||
if ($json.checkver -eq 'github') {
|
if ($json.checkver -eq 'github') {
|
||||||
if (!$json.homepage.StartsWith('https://github.com/')) {
|
if (!$json.homepage.StartsWith('https://github.com/')) {
|
||||||
error "$name checkver expects the homepage to be a github repository"
|
error "$name checkver expects the homepage to be a github repository"
|
||||||
}
|
}
|
||||||
$url = $json.homepage + '/releases/latest'
|
$url = $json.homepage.TrimEnd('/') + '/releases/latest'
|
||||||
$regex = $githubRegex
|
$regex = $githubRegex
|
||||||
|
$useGithubAPI = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($json.checkver.github) {
|
if ($json.checkver.github) {
|
||||||
$url = $json.checkver.github + '/releases/latest'
|
$url = $json.checkver.github.TrimEnd('/') + '/releases/latest'
|
||||||
$regex = $githubRegex
|
$regex = $githubRegex
|
||||||
|
if ($json.checkver.PSObject.Properties.Count -eq 1) { $useGithubAPI = $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($json.checkver.re) {
|
if ($json.checkver.re) {
|
||||||
@@ -155,6 +169,13 @@ $Queue | ForEach-Object {
|
|||||||
|
|
||||||
$reverse = $json.checkver.reverse -and $json.checkver.reverse -eq 'true'
|
$reverse = $json.checkver.reverse -and $json.checkver.reverse -eq 'true'
|
||||||
|
|
||||||
|
if ($url -like '*api.github.com/*') { $useGithubAPI = $true }
|
||||||
|
|
||||||
|
if ($useGithubAPI -and ($null -ne $GitHubToken)) {
|
||||||
|
$url = $url -replace '//(www\.)?github.com/', '//api.github.com/repos/'
|
||||||
|
$wc.Headers.Add('Authorization', "token $GitHubToken")
|
||||||
|
}
|
||||||
|
|
||||||
$url = substitute $url $substitutions
|
$url = substitute $url $substitutions
|
||||||
|
|
||||||
$state = New-Object psobject @{
|
$state = New-Object psobject @{
|
||||||
@@ -194,86 +215,97 @@ while ($in_progress -gt 0) {
|
|||||||
$reverse = $state.reverse
|
$reverse = $state.reverse
|
||||||
$replace = $state.replace
|
$replace = $state.replace
|
||||||
$expected_ver = $json.version
|
$expected_ver = $json.version
|
||||||
$ver = ''
|
$ver = $Version
|
||||||
|
|
||||||
$err = $ev.SourceEventArgs.Error
|
|
||||||
$page = $ev.SourceEventArgs.Result
|
|
||||||
|
|
||||||
if ($err) {
|
|
||||||
next "$($err.message)`r`nURL $url is not valid"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$regex -and $replace) {
|
|
||||||
next "'replace' requires 're' or 'regex'"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($jsonpath) {
|
|
||||||
$ver = json_path $page $jsonpath
|
|
||||||
if (!$ver) {
|
|
||||||
$ver = json_path_legacy $page $jsonpath
|
|
||||||
}
|
|
||||||
if (!$ver) {
|
|
||||||
next "couldn't find '$jsonpath' in $url"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($xpath) {
|
|
||||||
$xml = [xml]$page
|
|
||||||
# Find all `significant namespace declarations` from the XML file
|
|
||||||
$nsList = $xml.SelectNodes("//namespace::*[not(. = ../../namespace::*)]")
|
|
||||||
# Then add them into the NamespaceManager
|
|
||||||
$nsmgr = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
|
|
||||||
$nsList | ForEach-Object {
|
|
||||||
$nsmgr.AddNamespace($_.LocalName, $_.Value)
|
|
||||||
}
|
|
||||||
# Getting version from XML, using XPath
|
|
||||||
$ver = $xml.SelectSingleNode($xpath, $nsmgr).'#text'
|
|
||||||
if (!$ver) {
|
|
||||||
next "couldn't find '$xpath' in $url"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($jsonpath -and $regexp) {
|
|
||||||
$page = $ver
|
|
||||||
$ver = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($xpath -and $regexp) {
|
|
||||||
$page = $ver
|
|
||||||
$ver = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($regexp) {
|
|
||||||
$regex = New-Object System.Text.RegularExpressions.Regex($regexp)
|
|
||||||
if ($reverse) {
|
|
||||||
$match = $regex.Matches($page) | Select-Object -Last 1
|
|
||||||
} else {
|
|
||||||
$match = $regex.Matches($page) | Select-Object -First 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($match -and $match.Success) {
|
|
||||||
$matchesHashtable = @{}
|
|
||||||
$regex.GetGroupNames() | ForEach-Object { $matchesHashtable.Add($_, $match.Groups[$_].Value) }
|
|
||||||
$ver = $matchesHashtable['1']
|
|
||||||
if ($replace) {
|
|
||||||
$ver = $regex.Replace($match.Value, $replace)
|
|
||||||
}
|
|
||||||
if (!$ver) {
|
|
||||||
$ver = $matchesHashtable['version']
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
next "couldn't match '$regexp' in $url"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$ver) {
|
if (!$ver) {
|
||||||
next "couldn't find new version in $url"
|
$page = $ev.SourceEventArgs.Result
|
||||||
continue
|
$err = $ev.SourceEventArgs.Error
|
||||||
|
if ($json.checkver.script) {
|
||||||
|
$page = $json.checkver.script -join "`r`n" | Invoke-Expression
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($err) {
|
||||||
|
next "$($err.message)`r`nURL $url is not valid"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$regex -and $replace) {
|
||||||
|
next "'replace' requires 're' or 'regex'"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($jsonpath) {
|
||||||
|
# Return only a single value if regex is absent
|
||||||
|
$noregex = [String]::IsNullOrEmpty($regex)
|
||||||
|
# If reverse is ON and regex is ON,
|
||||||
|
# Then reverse would have no effect because regex handles reverse
|
||||||
|
# on its own
|
||||||
|
# So in this case we have to disable reverse
|
||||||
|
$ver = json_path $page $jsonpath $null ($reverse -and $noregex) $noregex
|
||||||
|
if (!$ver) {
|
||||||
|
$ver = json_path_legacy $page $jsonpath
|
||||||
|
}
|
||||||
|
if (!$ver) {
|
||||||
|
next "couldn't find '$jsonpath' in $url"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($xpath) {
|
||||||
|
$xml = [xml]$page
|
||||||
|
# Find all `significant namespace declarations` from the XML file
|
||||||
|
$nsList = $xml.SelectNodes("//namespace::*[not(. = ../../namespace::*)]")
|
||||||
|
# Then add them into the NamespaceManager
|
||||||
|
$nsmgr = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
|
||||||
|
$nsList | ForEach-Object {
|
||||||
|
$nsmgr.AddNamespace($_.LocalName, $_.Value)
|
||||||
|
}
|
||||||
|
# Getting version from XML, using XPath
|
||||||
|
$ver = $xml.SelectSingleNode($xpath, $nsmgr).'#text'
|
||||||
|
if (!$ver) {
|
||||||
|
next "couldn't find '$xpath' in $url"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($jsonpath -and $regexp) {
|
||||||
|
$page = $ver
|
||||||
|
$ver = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($xpath -and $regexp) {
|
||||||
|
$page = $ver
|
||||||
|
$ver = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($regexp) {
|
||||||
|
$regex = New-Object System.Text.RegularExpressions.Regex($regexp)
|
||||||
|
if ($reverse) {
|
||||||
|
$match = $regex.Matches($page) | Select-Object -Last 1
|
||||||
|
} else {
|
||||||
|
$match = $regex.Matches($page) | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($match -and $match.Success) {
|
||||||
|
$matchesHashtable = @{}
|
||||||
|
$regex.GetGroupNames() | ForEach-Object { $matchesHashtable.Add($_, $match.Groups[$_].Value) }
|
||||||
|
$ver = $matchesHashtable['1']
|
||||||
|
if ($replace) {
|
||||||
|
$ver = $regex.Replace($match.Value, $replace)
|
||||||
|
}
|
||||||
|
if (!$ver) {
|
||||||
|
$ver = $matchesHashtable['version']
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next "couldn't match '$regexp' in $url"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$ver) {
|
||||||
|
next "couldn't find new version in $url"
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Skip actual only if versions are same and there is no -f
|
# Skip actual only if versions are same and there is no -f
|
||||||
@@ -289,7 +321,7 @@ while ($in_progress -gt 0) {
|
|||||||
|
|
||||||
Write-Host $ver -ForegroundColor DarkRed -NoNewline
|
Write-Host $ver -ForegroundColor DarkRed -NoNewline
|
||||||
Write-Host " (scoop version is $expected_ver)" -NoNewline
|
Write-Host " (scoop version is $expected_ver)" -NoNewline
|
||||||
$update_available = (compare_versions $expected_ver $ver) -eq -1
|
$update_available = (Compare-Version -ReferenceVersion $ver -DifferenceVersion $expected_ver) -ne 0
|
||||||
|
|
||||||
if ($json.autoupdate -and $update_available) {
|
if ($json.autoupdate -and $update_available) {
|
||||||
Write-Host ' autoupdate available' -ForegroundColor Cyan
|
Write-Host ' autoupdate available' -ForegroundColor Cyan
|
||||||
@@ -305,12 +337,13 @@ while ($in_progress -gt 0) {
|
|||||||
Write-Host 'Forcing autoupdate!' -ForegroundColor DarkMagenta
|
Write-Host 'Forcing autoupdate!' -ForegroundColor DarkMagenta
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if ($Version -ne "") {
|
Invoke-AutoUpdate $App $Dir $json $ver $matchesHashtable # 'autoupdate.ps1'
|
||||||
$ver = $Version
|
|
||||||
}
|
|
||||||
autoupdate $App $Dir $json $ver $matchesHashtable
|
|
||||||
} catch {
|
} catch {
|
||||||
error $_.Exception.Message
|
if ($ThrowError) {
|
||||||
|
throw $_
|
||||||
|
} else {
|
||||||
|
error $_.Exception.Message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,21 +5,22 @@
|
|||||||
$old_erroractionpreference = $erroractionpreference
|
$old_erroractionpreference = $erroractionpreference
|
||||||
$erroractionpreference = 'stop' # quit if anything goes wrong
|
$erroractionpreference = 'stop' # quit if anything goes wrong
|
||||||
|
|
||||||
if(($PSVersionTable.PSVersion.Major) -lt 5) {
|
if (($PSVersionTable.PSVersion.Major) -lt 5) {
|
||||||
Write-Output "PowerShell 5 or later is required to run Scoop."
|
Write-Output "PowerShell 5 or later is required to run Scoop."
|
||||||
Write-Output "Upgrade PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell"
|
Write-Output "Upgrade PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
# show notification to change execution policy:
|
# show notification to change execution policy:
|
||||||
if((Get-ExecutionPolicy) -gt 'RemoteSigned' -or (Get-ExecutionPolicy) -eq 'ByPass') {
|
$allowedExecutionPolicy = @('Unrestricted', 'RemoteSigned', 'ByPass')
|
||||||
Write-Output "PowerShell requires an execution policy of 'RemoteSigned' to run Scoop."
|
if ((Get-ExecutionPolicy).ToString() -notin $allowedExecutionPolicy) {
|
||||||
Write-Output "To make this change please run:"
|
Write-Output "PowerShell requires an execution policy in [$($allowedExecutionPolicy -join ", ")] to run Scoop."
|
||||||
|
Write-Output "For example, to set the execution policy to 'RemoteSigned' please run :"
|
||||||
Write-Output "'Set-ExecutionPolicy RemoteSigned -scope CurrentUser'"
|
Write-Output "'Set-ExecutionPolicy RemoteSigned -scope CurrentUser'"
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') {
|
if ([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls12') {
|
||||||
Write-Output "Scoop requires at least .NET Framework 4.5"
|
Write-Output "Scoop requires at least .NET Framework 4.5"
|
||||||
Write-Output "Please download and install it first:"
|
Write-Output "Please download and install it first:"
|
||||||
Write-Output "https://www.microsoft.com/net/download"
|
Write-Output "https://www.microsoft.com/net/download"
|
||||||
@@ -27,27 +28,27 @@ if([System.Enum]::GetNames([System.Net.SecurityProtocolType]) -notcontains 'Tls1
|
|||||||
}
|
}
|
||||||
|
|
||||||
# get core functions
|
# get core functions
|
||||||
$core_url = 'https://raw.githubusercontent.com/lukesampson/scoop/master/lib/core.ps1'
|
$core_url = 'https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/lib/core.ps1'
|
||||||
Write-Output 'Initializing...'
|
Write-Output 'Initializing...'
|
||||||
Invoke-Expression (new-object net.webclient).downloadstring($core_url)
|
Invoke-Expression (new-object net.webclient).downloadstring($core_url)
|
||||||
|
|
||||||
# prep
|
# prep
|
||||||
if(installed 'scoop') {
|
if (Get-Command -Name 'scoop' -ErrorAction SilentlyContinue) {
|
||||||
write-host "Scoop is already installed. Run 'scoop update' to get the latest version." -f red
|
write-host "Scoop is already installed. Run 'scoop update' to get the latest version." -f red
|
||||||
# don't abort if invoked with iex that would close the PS session
|
# don't abort if invoked with iex that would close the PS session
|
||||||
if($myinvocation.mycommand.commandtype -eq 'Script') { return } else { exit 1 }
|
if ($myinvocation.mycommand.commandtype -eq 'Script') { return } else { exit 1 }
|
||||||
}
|
}
|
||||||
$dir = ensure (versiondir 'scoop' 'current')
|
$dir = ensure (versiondir 'scoop' 'current')
|
||||||
|
|
||||||
# download scoop zip
|
# download scoop zip
|
||||||
$zipurl = 'https://github.com/lukesampson/scoop/archive/master.zip'
|
$zipurl = 'https://github.com/ScoopInstaller/Scoop/archive/master.zip'
|
||||||
$zipfile = "$dir\scoop.zip"
|
$zipfile = "$dir\scoop.zip"
|
||||||
Write-Output 'Downloading scoop...'
|
Write-Output 'Downloading scoop...'
|
||||||
dl $zipurl $zipfile
|
dl $zipurl $zipfile
|
||||||
|
|
||||||
Write-Output 'Extracting...'
|
Write-Output 'Extracting...'
|
||||||
Add-Type -Assembly "System.IO.Compression.FileSystem"
|
Add-Type -Assembly "System.IO.Compression.FileSystem"
|
||||||
[IO.Compression.ZipFile]::ExtractToDirectory($zipfile,"$dir\_tmp")
|
[IO.Compression.ZipFile]::ExtractToDirectory($zipfile, "$dir\_tmp")
|
||||||
Copy-Item "$dir\_tmp\*master\*" $dir -Recurse -Force
|
Copy-Item "$dir\_tmp\*master\*" $dir -Recurse -Force
|
||||||
Remove-Item "$dir\_tmp", $zipfile -Recurse -Force
|
Remove-Item "$dir\_tmp", $zipfile -Recurse -Force
|
||||||
|
|
||||||
@@ -68,7 +69,6 @@ Copy-Item "$dir\_tmp\*-master\*" $dir -Recurse -Force
|
|||||||
Remove-Item "$dir\_tmp", $zipfile -Recurse -Force
|
Remove-Item "$dir\_tmp", $zipfile -Recurse -Force
|
||||||
|
|
||||||
ensure_robocopy_in_path
|
ensure_robocopy_in_path
|
||||||
ensure_scoop_in_path
|
|
||||||
|
|
||||||
scoop config lastupdate ([System.DateTime]::Now.ToString('o'))
|
scoop config lastupdate ([System.DateTime]::Now.ToString('o'))
|
||||||
success 'Scoop was installed successfully!'
|
success 'Scoop was installed successfully!'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# for development, update the installed scripts to match local source
|
# for development, update the installed scripts to match local source
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
|
|
||||||
$src = relpath ".."
|
$src = "$PSScriptRoot\.."
|
||||||
$dest = ensure (versiondir 'scoop' 'current')
|
$dest = ensure (versiondir 'scoop' 'current')
|
||||||
|
|
||||||
# make sure not running from the installed directory
|
# make sure not running from the installed directory
|
||||||
@@ -15,5 +15,4 @@ $output | Where-Object { $_ -ne "" }
|
|||||||
Write-Output 'creating shim...'
|
Write-Output 'creating shim...'
|
||||||
shim "$dest\bin\scoop.ps1" $false
|
shim "$dest\bin\scoop.ps1" $false
|
||||||
|
|
||||||
ensure_scoop_in_path
|
|
||||||
success 'scoop was refreshed!'
|
success 'scoop was refreshed!'
|
||||||
|
|||||||
@@ -1,41 +1,56 @@
|
|||||||
#requires -v 3
|
#Requires -Version 5
|
||||||
param($cmd)
|
param($SubCommand)
|
||||||
|
|
||||||
set-strictmode -off
|
Set-StrictMode -Off
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
. "$psscriptroot\..\lib\git.ps1"
|
. "$PSScriptRoot\..\lib\buckets.ps1"
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\commands.ps1"
|
||||||
. (relpath '..\lib\commands')
|
. "$PSScriptRoot\..\lib\help.ps1"
|
||||||
|
|
||||||
reset_aliases
|
# for aliases where there's a local function, re-alias so the function takes precedence
|
||||||
|
$aliases = Get-Alias | Where-Object { $_.Options -notmatch 'ReadOnly|AllScope' } | ForEach-Object { $_.Name }
|
||||||
# TODO: remove this in a few weeks
|
Get-ChildItem Function: | Where-Object -Property Name -In -Value $aliases | ForEach-Object {
|
||||||
if ((Get-LocalBucket) -notcontains 'main') {
|
Set-Alias -Name $_.Name -Value Local:$($_.Name) -Scope Script
|
||||||
warn "The main bucket of Scoop has been separated to 'https://github.com/ScoopInstaller/Main'"
|
|
||||||
warn "You don't have the main bucket added, adding main bucket for you..."
|
|
||||||
add_bucket 'main'
|
|
||||||
exit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$commands = commands
|
switch ($SubCommand) {
|
||||||
if ('--version' -contains $cmd -or (!$cmd -and '-v' -contains $args)) {
|
({ $SubCommand -in @($null, '--help', '/?') }) {
|
||||||
Push-Location $(versiondir 'scoop' 'current')
|
if (!$SubCommand -and $Args -eq '-v') {
|
||||||
write-host "Current Scoop version:"
|
$SubCommand = '--version'
|
||||||
git_log --oneline HEAD -n 1
|
} else {
|
||||||
write-host ""
|
exec 'help'
|
||||||
Pop-Location
|
|
||||||
|
|
||||||
Get-LocalBucket | ForEach-Object {
|
|
||||||
Push-Location (Find-BucketDirectory $_ -Root)
|
|
||||||
if(test-path '.git') {
|
|
||||||
write-host "'$_' bucket:"
|
|
||||||
git_log --oneline HEAD -n 1
|
|
||||||
write-host ""
|
|
||||||
}
|
}
|
||||||
Pop-Location
|
}
|
||||||
|
({ $SubCommand -eq '--version' }) {
|
||||||
|
Write-Host 'Current Scoop version:'
|
||||||
|
if ((Test-CommandAvailable git) -and (Test-Path "$PSScriptRoot\..\.git") -and (get_config SCOOP_BRANCH 'master') -ne 'master') {
|
||||||
|
Invoke-Expression "git -C '$PSScriptRoot\..' --no-pager log --oneline HEAD -n 1"
|
||||||
|
} else {
|
||||||
|
$version = Select-String -Pattern '^## \[(v[\d.]+)\].*?([\d-]+)$' -Path "$PSScriptRoot\..\CHANGELOG.md"
|
||||||
|
Write-Host $version.Matches.Groups[1].Value -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host " - Released at $($version.Matches.Groups[2].Value)"
|
||||||
|
}
|
||||||
|
Write-Host ''
|
||||||
|
|
||||||
|
Get-LocalBucket | ForEach-Object {
|
||||||
|
$bucketLoc = Find-BucketDirectory $_ -Root
|
||||||
|
if ((Test-Path (Join-Path $bucketLoc '.git')) -and (Test-CommandAvailable git)) {
|
||||||
|
Write-Host "'$_' bucket:"
|
||||||
|
Invoke-Expression "git -C '$bucketLoc' --no-pager log --oneline HEAD -n 1"
|
||||||
|
Write-Host ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
({ $SubCommand -in (commands) }) {
|
||||||
|
if ($Args -in @('-h', '--help', '/?')) {
|
||||||
|
exec 'help' @($SubCommand)
|
||||||
|
} else {
|
||||||
|
exec $SubCommand $Args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
"scoop: '$SubCommand' isn't a scoop command. See 'scoop help'."
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elseif (@($null, '--help', '/?') -contains $cmd -or $args[0] -contains '-h') { exec 'help' $args }
|
|
||||||
elseif ($commands -contains $cmd) { exec $cmd $args }
|
|
||||||
else { "scoop: '$cmd' isn't a scoop command. See 'scoop help'."; exit 1 }
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
invoke-pester "$psscriptroot\..\test"
|
. "$PSScriptRoot\..\test\bin\test.ps1"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ $errors = $false
|
|||||||
|
|
||||||
# Uninstall given app
|
# Uninstall given app
|
||||||
function do_uninstall($app, $global) {
|
function do_uninstall($app, $global) {
|
||||||
$version = current_version $app $global
|
$version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
$dir = versiondir $app $version $global
|
$dir = versiondir $app $version $global
|
||||||
$manifest = installed_manifest $app $version $global
|
$manifest = installed_manifest $app $version $global
|
||||||
$install = install_info $app $version $global
|
$install = install_info $app $version $global
|
||||||
@@ -42,15 +42,15 @@ function do_uninstall($app, $global) {
|
|||||||
|
|
||||||
Write-Output "Uninstalling '$app'"
|
Write-Output "Uninstalling '$app'"
|
||||||
run_uninstaller $manifest $architecture $dir
|
run_uninstaller $manifest $architecture $dir
|
||||||
rm_shims $manifest $global $architecture
|
rm_shims $app $manifest $global $architecture
|
||||||
|
|
||||||
# If a junction was used during install, that will have been used
|
# If a junction was used during install, that will have been used
|
||||||
# as the reference directory. Othewise it will just be the version
|
# as the reference directory. Othewise it will just be the version
|
||||||
# directory.
|
# directory.
|
||||||
$refdir = unlink_current (appdir $app $global)
|
$refdir = unlink_current (appdir $app $global)
|
||||||
|
|
||||||
env_rm_path $manifest $refdir $global
|
env_rm_path $manifest $refdir $global $architecture
|
||||||
env_rm $manifest $global
|
env_rm $manifest $global $architecture
|
||||||
|
|
||||||
$appdir = appdir $app $global
|
$appdir = appdir $app $global
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
{
|
{
|
||||||
"main": "https://github.com/ScoopInstaller/Main",
|
"main": "https://github.com/ScoopInstaller/Main",
|
||||||
"extras": "https://github.com/lukesampson/scoop-extras",
|
"extras": "https://github.com/ScoopInstaller/Extras",
|
||||||
"versions": "https://github.com/ScoopInstaller/Versions",
|
"versions": "https://github.com/ScoopInstaller/Versions",
|
||||||
"nightlies": "https://github.com/ScoopInstaller/Nightlies",
|
|
||||||
"nirsoft": "https://github.com/kodybrown/scoop-nirsoft",
|
"nirsoft": "https://github.com/kodybrown/scoop-nirsoft",
|
||||||
"php": "https://github.com/ScoopInstaller/PHP",
|
"php": "https://github.com/ScoopInstaller/PHP",
|
||||||
"nerd-fonts": "https://github.com/matthewjberger/scoop-nerd-fonts",
|
"nerd-fonts": "https://github.com/matthewjberger/scoop-nerd-fonts",
|
||||||
"nonportable": "https://github.com/oltolm/scoop-nonportable",
|
"nonportable": "https://github.com/TheRandomLabs/scoop-nonportable",
|
||||||
"java": "https://github.com/ScoopInstaller/Java",
|
"java": "https://github.com/ScoopInstaller/Java",
|
||||||
"games": "https://github.com/Calinou/scoop-games",
|
"games": "https://github.com/Calinou/scoop-games"
|
||||||
"jetbrains": "https://github.com/Ash258/Scoop-JetBrains"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
<#
|
# Must included with 'json.ps1'
|
||||||
TODO
|
|
||||||
- clean up
|
|
||||||
#>
|
|
||||||
. "$psscriptroot\..\lib\json.ps1"
|
|
||||||
|
|
||||||
. "$psscriptroot/core.ps1"
|
|
||||||
. "$psscriptroot/json.ps1"
|
|
||||||
|
|
||||||
function find_hash_in_rdf([String] $url, [String] $basename) {
|
function find_hash_in_rdf([String] $url, [String] $basename) {
|
||||||
$data = $null
|
$data = $null
|
||||||
try {
|
try {
|
||||||
@@ -51,7 +43,7 @@ function find_hash_in_textfile([String] $url, [Hashtable] $substitutions, [Strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($regex.Length -eq 0) {
|
if ($regex.Length -eq 0) {
|
||||||
$regex = '^([a-fA-F0-9]+)$'
|
$regex = '^\s*([a-fA-F0-9]+)\s*$'
|
||||||
}
|
}
|
||||||
|
|
||||||
$regex = substitute $regex $templates $false
|
$regex = substitute $regex $templates $false
|
||||||
@@ -152,7 +144,7 @@ function find_hash_in_headers([String] $url) {
|
|||||||
$req.Timeout = 2000
|
$req.Timeout = 2000
|
||||||
$req.Method = 'HEAD'
|
$req.Method = 'HEAD'
|
||||||
$res = $req.GetResponse()
|
$res = $req.GetResponse()
|
||||||
if(([int]$response.StatusCode -ge 300) -and ([int]$response.StatusCode -lt 400)) {
|
if(([int]$res.StatusCode -ge 300) -and ([int]$res.StatusCode -lt 400)) {
|
||||||
if($res.Headers['Digest'] -match 'SHA-256=([^,]+)' -or $res.Headers['Digest'] -match 'SHA=([^,]+)' -or $res.Headers['Digest'] -match 'MD5=([^,]+)') {
|
if($res.Headers['Digest'] -match 'SHA-256=([^,]+)' -or $res.Headers['Digest'] -match 'SHA=([^,]+)' -or $res.Headers['Digest'] -match 'MD5=([^,]+)') {
|
||||||
$hash = ([System.Convert]::FromBase64String($matches[1]) | ForEach-Object { $_.ToString('x2') }) -join ''
|
$hash = ([System.Convert]::FromBase64String($matches[1]) | ForEach-Object { $_.ToString('x2') }) -join ''
|
||||||
debug $hash
|
debug $hash
|
||||||
@@ -178,6 +170,9 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u
|
|||||||
$substitutions.Add('$url', (strip_fragment $url))
|
$substitutions.Add('$url', (strip_fragment $url))
|
||||||
$substitutions.Add('$baseurl', (strip_filename (strip_fragment $url)).TrimEnd('/'))
|
$substitutions.Add('$baseurl', (strip_filename (strip_fragment $url)).TrimEnd('/'))
|
||||||
$substitutions.Add('$basename', $basename)
|
$substitutions.Add('$basename', $basename)
|
||||||
|
$substitutions.Add('$urlNoExt', (strip_ext (strip_fragment $url)))
|
||||||
|
$substitutions.Add('$basenameNoExt', (strip_ext $basename))
|
||||||
|
|
||||||
debug $substitutions
|
debug $substitutions
|
||||||
|
|
||||||
$hashfile_url = substitute $config.url $substitutions
|
$hashfile_url = substitute $config.url $substitutions
|
||||||
@@ -281,66 +276,131 @@ function get_hash_for_app([String] $app, $config, [String] $version, [String] $u
|
|||||||
return $hash
|
return $hash
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_manifest_with_new_version($json, [String] $version, [String] $url, [String] $hash, $architecture = $null) {
|
function Update-ManifestProperty {
|
||||||
$json.version = $version
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
if ($null -eq $architecture) {
|
Update propert(y|ies) in manifest
|
||||||
if ($json.url -is [System.Array]) {
|
.DESCRIPTION
|
||||||
$json.url[0] = $url
|
Update selected propert(y|ies) to given version in manifest.
|
||||||
$json.hash[0] = $hash
|
.PARAMETER Manifest
|
||||||
} else {
|
Manifest to be updated
|
||||||
$json.url = $url
|
.PARAMETER Property
|
||||||
$json.hash = $hash
|
Selected propert(y|ies) to be updated
|
||||||
}
|
.PARAMETER AppName
|
||||||
} else {
|
Software name
|
||||||
# If there are multiple urls we replace the first one
|
.PARAMETER Version
|
||||||
if ($json.architecture.$architecture.url -is [System.Array]) {
|
Given software version
|
||||||
$json.architecture.$architecture.url[0] = $url
|
.PARAMETER Substitutions
|
||||||
$json.architecture.$architecture.hash[0] = $hash
|
Hashtable of internal substitutable variables
|
||||||
} else {
|
.OUTPUTS
|
||||||
$json.architecture.$architecture.url = $url
|
System.Boolean
|
||||||
$json.architecture.$architecture.hash = $hash
|
Flag that indicate if there are any changed properties
|
||||||
}
|
#>
|
||||||
|
[CmdletBinding(SupportsShouldProcess = $true)]
|
||||||
|
[OutputType([Boolean])]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 1)]
|
||||||
|
[PSCustomObject]
|
||||||
|
$Manifest,
|
||||||
|
[Parameter(ValueFromPipeline = $true, Position = 2)]
|
||||||
|
[String[]]
|
||||||
|
$Property,
|
||||||
|
[String]
|
||||||
|
$AppName,
|
||||||
|
[String]
|
||||||
|
$Version,
|
||||||
|
[Alias('Matches')]
|
||||||
|
[HashTable]
|
||||||
|
$Substitutions
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
$hasManifestChanged = $false
|
||||||
}
|
}
|
||||||
}
|
process {
|
||||||
|
foreach ($currentProperty in $Property) {
|
||||||
function update_manifest_prop([String] $prop, $json, [Hashtable] $substitutions) {
|
if ($currentProperty -eq 'hash') {
|
||||||
# first try the global property
|
# Update hash
|
||||||
if ($json.$prop -and $json.autoupdate.$prop) {
|
if ($Manifest.hash) {
|
||||||
$json.$prop = substitute $json.autoupdate.$prop $substitutions
|
# Global
|
||||||
}
|
$newURL = substitute $Manifest.autoupdate.url $Substitutions
|
||||||
|
$newHash = HashHelper -AppName $AppName -Version $Version -HashExtraction $Manifest.autoupdate.hash -URL $newURL -Substitutions $Substitutions
|
||||||
# check if there are architecture specific variants
|
$Manifest.hash, $hasPropertyChanged = PropertyHelper -Property $Manifest.hash -Value $newHash
|
||||||
if ($json.architecture -and $json.autoupdate.architecture) {
|
$hasManifestChanged = $hasManifestChanged -or $hasPropertyChanged
|
||||||
$json.architecture | Get-Member -MemberType NoteProperty | ForEach-Object {
|
} else {
|
||||||
$architecture = $_.Name
|
# Arch-spec
|
||||||
if ($json.architecture.$architecture.$prop -and $json.autoupdate.architecture.$architecture.$prop) {
|
$Manifest.architecture | Get-Member -MemberType NoteProperty | ForEach-Object {
|
||||||
$json.architecture.$architecture.$prop = substitute (arch_specific $prop $json.autoupdate $architecture) $substitutions
|
$arch = $_.Name
|
||||||
|
$newURL = substitute (arch_specific 'url' $Manifest.autoupdate $arch) $Substitutions
|
||||||
|
$newHash = HashHelper -AppName $AppName -Version $Version -HashExtraction (arch_specific 'hash' $Manifest.autoupdate $arch) -URL $newURL -Substitutions $Substitutions
|
||||||
|
$Manifest.architecture.$arch.hash, $hasPropertyChanged = PropertyHelper -Property $Manifest.architecture.$arch.hash -Value $newHash
|
||||||
|
$hasManifestChanged = $hasManifestChanged -or $hasPropertyChanged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($Manifest.$currentProperty -and $Manifest.autoupdate.$currentProperty) {
|
||||||
|
# Update other property (global)
|
||||||
|
$autoupdateProperty = $Manifest.autoupdate.$currentProperty
|
||||||
|
$newValue = substitute $autoupdateProperty $Substitutions
|
||||||
|
if (($autoupdateProperty.GetType().Name -eq 'Object[]') -and ($autoupdateProperty.Length -eq 1)) {
|
||||||
|
# Make sure it's an array
|
||||||
|
$newValue = ,$newValue
|
||||||
|
}
|
||||||
|
$Manifest.$currentProperty, $hasPropertyChanged = PropertyHelper -Property $Manifest.$currentProperty -Value $newValue
|
||||||
|
$hasManifestChanged = $hasManifestChanged -or $hasPropertyChanged
|
||||||
|
} elseif ($Manifest.architecture) {
|
||||||
|
# Update other property (arch-spec)
|
||||||
|
$Manifest.architecture | Get-Member -MemberType NoteProperty | ForEach-Object {
|
||||||
|
$arch = $_.Name
|
||||||
|
if ($Manifest.architecture.$arch.$currentProperty -and ($Manifest.autoupdate.architecture.$arch.$currentProperty -or $Manifest.autoupdate.$currentProperty)) {
|
||||||
|
$autoupdateProperty = @(arch_specific $currentProperty $Manifest.autoupdate $arch)
|
||||||
|
$newValue = substitute $autoupdateProperty $Substitutions
|
||||||
|
if (($autoupdateProperty.GetType().Name -eq 'Object[]') -and ($autoupdateProperty.Length -eq 1)) {
|
||||||
|
# Make sure it's an array
|
||||||
|
$newValue = ,$newValue
|
||||||
|
}
|
||||||
|
$Manifest.architecture.$arch.$currentProperty, $hasPropertyChanged = PropertyHelper -Property $Manifest.architecture.$arch.$currentProperty -Value $newValue
|
||||||
|
$hasManifestChanged = $hasManifestChanged -or $hasPropertyChanged
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
end {
|
||||||
|
if ($Version -ne '' -and $Manifest.version -ne $Version) {
|
||||||
|
$Manifest.version = $Version
|
||||||
|
$hasManifestChanged = $true
|
||||||
|
}
|
||||||
|
return $hasManifestChanged
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_version_substitutions([String] $version, [Hashtable] $customMatches) {
|
function Get-VersionSubstitution {
|
||||||
$firstPart = $version.Split('-') | Select-Object -first 1
|
param (
|
||||||
$lastPart = $version.Split('-') | Select-Object -last 1
|
[String]
|
||||||
|
$Version,
|
||||||
|
[Hashtable]
|
||||||
|
$CustomMatches
|
||||||
|
)
|
||||||
|
|
||||||
|
$firstPart = $Version.Split('-') | Select-Object -First 1
|
||||||
|
$lastPart = $Version.Split('-') | Select-Object -Last 1
|
||||||
$versionVariables = @{
|
$versionVariables = @{
|
||||||
'$version' = $version;
|
'$version' = $Version;
|
||||||
'$underscoreVersion' = ($version -replace "\.", "_");
|
'$dotVersion' = ($Version -replace '[._-]', '.');
|
||||||
'$dashVersion' = ($version -replace "\.", "-");
|
'$underscoreVersion' = ($Version -replace '[._-]', '_');
|
||||||
'$cleanVersion' = ($version -replace "\.", "");
|
'$dashVersion' = ($Version -replace '[._-]', '-');
|
||||||
'$majorVersion' = $firstPart.Split('.') | Select-Object -first 1;
|
'$cleanVersion' = ($Version -replace '[._-]', '');
|
||||||
'$minorVersion' = $firstPart.Split('.') | Select-Object -skip 1 -first 1;
|
'$majorVersion' = $firstPart.Split('.') | Select-Object -First 1;
|
||||||
'$patchVersion' = $firstPart.Split('.') | Select-Object -skip 2 -first 1;
|
'$minorVersion' = $firstPart.Split('.') | Select-Object -Skip 1 -First 1;
|
||||||
'$buildVersion' = $firstPart.Split('.') | Select-Object -skip 3 -first 1;
|
'$patchVersion' = $firstPart.Split('.') | Select-Object -Skip 2 -First 1;
|
||||||
|
'$buildVersion' = $firstPart.Split('.') | Select-Object -Skip 3 -First 1;
|
||||||
'$preReleaseVersion' = $lastPart;
|
'$preReleaseVersion' = $lastPart;
|
||||||
}
|
}
|
||||||
if($version -match "(?<head>\d+\.\d+(?:\.\d+)?)(?<tail>.*)") {
|
if($Version -match "(?<head>\d+\.\d+(?:\.\d+)?)(?<tail>.*)") {
|
||||||
$versionVariables.Set_Item('$matchHead', $matches['head'])
|
$versionVariables.Set_Item('$matchHead', $Matches['head'])
|
||||||
$versionVariables.Set_Item('$matchTail', $matches['tail'])
|
$versionVariables.Set_Item('$matchTail', $Matches['tail'])
|
||||||
}
|
}
|
||||||
if($customMatches) {
|
if($CustomMatches) {
|
||||||
$customMatches.GetEnumerator() | ForEach-Object {
|
$CustomMatches.GetEnumerator() | ForEach-Object {
|
||||||
if($_.Name -ne "0") {
|
if($_.Name -ne "0") {
|
||||||
$versionVariables.Set_Item('$match' + (Get-Culture).TextInfo.ToTitleCase($_.Name), $_.Value)
|
$versionVariables.Set_Item('$match' + (Get-Culture).TextInfo.ToTitleCase($_.Name), $_.Value)
|
||||||
}
|
}
|
||||||
@@ -349,85 +409,168 @@ function get_version_substitutions([String] $version, [Hashtable] $customMatches
|
|||||||
return $versionVariables
|
return $versionVariables
|
||||||
}
|
}
|
||||||
|
|
||||||
function autoupdate([String] $app, $dir, $json, [String] $version, [Hashtable] $matches) {
|
function Invoke-AutoUpdate {
|
||||||
Write-Host -f DarkCyan "Autoupdating $app"
|
param (
|
||||||
$has_changes = $false
|
[String]
|
||||||
$has_errors = $false
|
$AppName,
|
||||||
[Bool]$valid = $true
|
[String]
|
||||||
$substitutions = get_version_substitutions $version $matches
|
$Path,
|
||||||
|
[PSObject]
|
||||||
|
$Manifest,
|
||||||
|
[String]
|
||||||
|
$Version,
|
||||||
|
[Hashtable]
|
||||||
|
$CustomMatches
|
||||||
|
)
|
||||||
|
|
||||||
if ($json.url) {
|
Write-Host "Autoupdating $AppName" -ForegroundColor DarkCyan
|
||||||
# create new url
|
$substitutions = Get-VersionSubstitution $Version $CustomMatches
|
||||||
$url = substitute $json.autoupdate.url $substitutions
|
|
||||||
$valid = $true
|
|
||||||
|
|
||||||
if($valid) {
|
|
||||||
# create hash
|
|
||||||
$hash = get_hash_for_app $app $json.autoupdate.hash $version $url $substitutions
|
|
||||||
if ($null -eq $hash) {
|
|
||||||
$valid = $false
|
|
||||||
Write-Host -f DarkRed "Could not find hash!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# write changes to the json object
|
|
||||||
if ($valid) {
|
|
||||||
$has_changes = $true
|
|
||||||
update_manifest_with_new_version $json $version $url $hash
|
|
||||||
} else {
|
|
||||||
$has_errors = $true
|
|
||||||
throw "Could not update $app"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$json.architecture | Get-Member -MemberType NoteProperty | ForEach-Object {
|
|
||||||
$valid = $true
|
|
||||||
$architecture = $_.Name
|
|
||||||
|
|
||||||
# create new url
|
|
||||||
$url = substitute (arch_specific "url" $json.autoupdate $architecture) $substitutions
|
|
||||||
$valid = $true
|
|
||||||
|
|
||||||
if($valid) {
|
|
||||||
# create hash
|
|
||||||
$hash = get_hash_for_app $app (arch_specific "hash" $json.autoupdate $architecture) $version $url $substitutions
|
|
||||||
if ($null -eq $hash) {
|
|
||||||
$valid = $false
|
|
||||||
Write-Host -f DarkRed "Could not find hash!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# write changes to the json object
|
|
||||||
if ($valid) {
|
|
||||||
$has_changes = $true
|
|
||||||
update_manifest_with_new_version $json $version $url $hash $architecture
|
|
||||||
} else {
|
|
||||||
$has_errors = $true
|
|
||||||
throw "Could not update $app $architecture"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# update properties
|
# update properties
|
||||||
update_manifest_prop "extract_dir" $json $substitutions
|
$updatedProperties = @(@($Manifest.autoupdate.PSObject.Properties.Name) -ne 'architecture')
|
||||||
|
if ($Manifest.autoupdate.architecture) {
|
||||||
|
$updatedProperties += $Manifest.autoupdate.architecture.PSObject.Properties | ForEach-Object { $_.Value.PSObject.Properties.Name }
|
||||||
|
}
|
||||||
|
if ($updatedProperties -contains 'url') {
|
||||||
|
$updatedProperties += 'hash'
|
||||||
|
}
|
||||||
|
$updatedProperties = $updatedProperties | Select-Object -Unique
|
||||||
|
debug [$updatedProperties]
|
||||||
|
$hasChanged = Update-ManifestProperty -Manifest $Manifest -Property $updatedProperties -AppName $AppName -Version $Version -Substitutions $substitutions
|
||||||
|
|
||||||
# update license
|
if ($hasChanged) {
|
||||||
update_manifest_prop "license" $json $substitutions
|
|
||||||
|
|
||||||
if ($has_changes -and !$has_errors) {
|
|
||||||
# write file
|
# write file
|
||||||
Write-Host -f DarkGreen "Writing updated $app manifest"
|
Write-Host "Writing updated $AppName manifest" -ForegroundColor DarkGreen
|
||||||
|
# Accept unusual Unicode characters
|
||||||
$path = join-path $dir "$app.json"
|
# 'Set-Content -Encoding ASCII' don't works in PowerShell 5
|
||||||
|
# Wait for 'UTF8NoBOM' Encoding in PowerShell 7
|
||||||
$file_content = $json | ConvertToPrettyJson
|
# $Manifest | ConvertToPrettyJson | Set-Content -Path (Join-Path $Path "$AppName.json") -Encoding UTF8NoBOM
|
||||||
[System.IO.File]::WriteAllLines($path, $file_content)
|
[System.IO.File]::WriteAllLines((Join-Path $Path "$AppName.json"), (ConvertToPrettyJson $Manifest))
|
||||||
|
|
||||||
# notes
|
# notes
|
||||||
if ($json.autoupdate.note) {
|
$note = "`nUpdating note:"
|
||||||
Write-Host ""
|
if ($Manifest.autoupdate.note) {
|
||||||
Write-Host -f DarkYellow $json.autoupdate.note
|
$note += "`nno-arch: $($Manifest.autoupdate.note)"
|
||||||
|
$hasNote = $true
|
||||||
|
}
|
||||||
|
if ($Manifest.autoupdate.architecture) {
|
||||||
|
'64bit', '32bit' | ForEach-Object {
|
||||||
|
if ($Manifest.autoupdate.architecture.$_.note) {
|
||||||
|
$note += "`n$_-arch: $($Manifest.autoupdate.architecture.$_.note)"
|
||||||
|
$hasNote = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($hasNote) {
|
||||||
|
Write-Host $note -ForegroundColor DarkYellow
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Write-Host -f DarkGray "No updates for $app"
|
# This if-else branch may not be in use.
|
||||||
|
Write-Host "No updates for $AppName" -ForegroundColor DarkGray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## Helper Functions
|
||||||
|
|
||||||
|
function PropertyHelper {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Helper of updating property
|
||||||
|
.DESCRIPTION
|
||||||
|
Update manifest property (String, Array or PSCustomObject).
|
||||||
|
.PARAMETER Property
|
||||||
|
Property to be updated
|
||||||
|
.PARAMETER Value
|
||||||
|
New property values
|
||||||
|
Update line by line
|
||||||
|
.OUTPUTS
|
||||||
|
System.Object[]
|
||||||
|
The first element is new property, the second element is change flag
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[Object]$Property,
|
||||||
|
[Object]$Value
|
||||||
|
)
|
||||||
|
$hasChanged = $false
|
||||||
|
if (@($Property).Length -lt @($Value).Length) {
|
||||||
|
$Property = $Value
|
||||||
|
$hasChanged = $true
|
||||||
|
} else {
|
||||||
|
switch ($Property.GetType().Name) {
|
||||||
|
'String' {
|
||||||
|
$Value = $Value -as [String]
|
||||||
|
if ($null -ne $Value) {
|
||||||
|
$Property = $Value
|
||||||
|
$hasChanged = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'Object[]' {
|
||||||
|
$Value = @($Value)
|
||||||
|
for ($i = 0; $i -lt $Value.Length; $i++) {
|
||||||
|
$Property[$i], $hasItemChanged = PropertyHelper -Property $Property[$i] -Value $Value[$i]
|
||||||
|
$hasChanged = $hasChanged -or $hasItemChanged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'PSCustomObject' {
|
||||||
|
if ($Value -is [PSObject]) {
|
||||||
|
foreach ($name in $Property.PSObject.Properties.Name) {
|
||||||
|
if ($Value.$name) {
|
||||||
|
$Property.$name, $hasItemChanged = PropertyHelper -Property $Property.$name -Value $Value.$name
|
||||||
|
$hasChanged = $hasChanged -or $hasItemChanged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $Property, $hasChanged
|
||||||
|
}
|
||||||
|
|
||||||
|
function HashHelper {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Helper of getting file hash(es)
|
||||||
|
.DESCRIPTION
|
||||||
|
Extract or calculate file hash(es).
|
||||||
|
If hash extraction templates are less then URLs, the last template will be reused for the rest URLs.
|
||||||
|
.PARAMETER AppName
|
||||||
|
Software name
|
||||||
|
.PARAMETER Version
|
||||||
|
Given software version
|
||||||
|
.PARAMETER HashExtraction
|
||||||
|
Hash extraction template(s)
|
||||||
|
.PARAMETER URL
|
||||||
|
New download URL(s), used to calculate hash locally (fallback)
|
||||||
|
.PARAMETER Substitutions
|
||||||
|
Hashtable of internal substitutable variables
|
||||||
|
.OUTPUTS
|
||||||
|
System.String
|
||||||
|
Hash value (single URL)
|
||||||
|
System.String[]
|
||||||
|
Hash values (multi URLs)
|
||||||
|
#>
|
||||||
|
param (
|
||||||
|
[String]
|
||||||
|
$AppName,
|
||||||
|
[String]
|
||||||
|
$Version,
|
||||||
|
[PSObject[]]
|
||||||
|
$HashExtraction,
|
||||||
|
[String[]]
|
||||||
|
$URL,
|
||||||
|
[HashTable]
|
||||||
|
$Substitutions
|
||||||
|
)
|
||||||
|
$hash = @()
|
||||||
|
for ($i = 0; $i -lt $URL.Length; $i++) {
|
||||||
|
if ($null -eq $HashExtraction) {
|
||||||
|
$currentHashExtraction = $null
|
||||||
|
} else {
|
||||||
|
$currentHashExtraction = $HashExtraction[$i], $HashExtraction[-1] | Select-Object -First 1
|
||||||
|
}
|
||||||
|
$hash += get_hash_for_app $AppName $currentHashExtraction $Version $URL[$i] $Substitutions
|
||||||
|
if ($null -eq $hash[$i]) {
|
||||||
|
throw "Could not update $AppName, hash for $(url_remote_filename $URL[$i]) failed!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $hash
|
||||||
|
}
|
||||||
|
|||||||
155
lib/buckets.ps1
155
lib/buckets.ps1
@@ -1,5 +1,3 @@
|
|||||||
. "$PSScriptRoot\core.ps1"
|
|
||||||
|
|
||||||
$bucketsdir = "$scoopdir\buckets"
|
$bucketsdir = "$scoopdir\buckets"
|
||||||
|
|
||||||
function Find-BucketDirectory {
|
function Find-BucketDirectory {
|
||||||
@@ -18,7 +16,9 @@ function Find-BucketDirectory {
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Handle info passing empty string as bucket ($install.bucket)
|
# Handle info passing empty string as bucket ($install.bucket)
|
||||||
if(($null -eq $Name) -or ($Name -eq '')) { $Name = 'main' }
|
if (($null -eq $Name) -or ($Name -eq '')) {
|
||||||
|
$Name = 'main'
|
||||||
|
}
|
||||||
$bucket = "$bucketsdir\$Name"
|
$bucket = "$bucketsdir\$Name"
|
||||||
|
|
||||||
if ((Test-Path "$bucket\bucket") -and !$Root) {
|
if ((Test-Path "$bucket\bucket") -and !$Root) {
|
||||||
@@ -37,7 +37,7 @@ function bucketdir($name) {
|
|||||||
function known_bucket_repos {
|
function known_bucket_repos {
|
||||||
$json = "$PSScriptRoot\..\buckets.json"
|
$json = "$PSScriptRoot\..\buckets.json"
|
||||||
|
|
||||||
return Get-Content $json -raw | convertfrom-json -ea stop
|
return Get-Content $json -Raw | ConvertFrom-Json -ErrorAction stop
|
||||||
}
|
}
|
||||||
|
|
||||||
function known_bucket_repo($name) {
|
function known_bucket_repo($name) {
|
||||||
@@ -46,11 +46,11 @@ function known_bucket_repo($name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function known_buckets {
|
function known_buckets {
|
||||||
known_bucket_repos | ForEach-Object { $_.psobject.properties | Select-Object -expand 'name' }
|
known_bucket_repos | ForEach-Object { $_.PSObject.Properties | Select-Object -Expand 'name' }
|
||||||
}
|
}
|
||||||
|
|
||||||
function apps_in_bucket($dir) {
|
function apps_in_bucket($dir) {
|
||||||
return Get-ChildItem $dir | Where-Object { $_.Name.endswith('.json') } | ForEach-Object { $_.Name -replace '.json$', '' }
|
return Get-ChildItem $dir | Where-Object { $_.Name.EndsWith('.json') } | ForEach-Object { $_.Name -replace '.json$', '' }
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-LocalBucket {
|
function Get-LocalBucket {
|
||||||
@@ -58,8 +58,12 @@ function Get-LocalBucket {
|
|||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
List all local buckets.
|
List all local buckets.
|
||||||
#>
|
#>
|
||||||
|
$bucketNames = (Get-ChildItem -Path $bucketsdir -Directory).Name
|
||||||
return (Get-ChildItem -Directory $bucketsdir).Name
|
if ($null -eq $bucketNames) {
|
||||||
|
return @() # Return a zero-length list instead of $null.
|
||||||
|
} else {
|
||||||
|
return $bucketNames
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buckets {
|
function buckets {
|
||||||
@@ -68,57 +72,126 @@ function buckets {
|
|||||||
return Get-LocalBucket
|
return Get-LocalBucket
|
||||||
}
|
}
|
||||||
|
|
||||||
function find_manifest($app, $bucket) {
|
function Find-Manifest($app, $bucket) {
|
||||||
if ($bucket) {
|
$manifest, $url = $null, $null
|
||||||
$manifest = manifest $app $bucket
|
|
||||||
if ($manifest) { return $manifest, $bucket }
|
# check if app is a URL or UNC path
|
||||||
return $null
|
if ($app -match '^(ht|f)tps?://|\\\\') {
|
||||||
|
$url = $app
|
||||||
|
$app = appname_from_url $url
|
||||||
|
$manifest = url_manifest $url
|
||||||
|
} else {
|
||||||
|
if ($bucket) {
|
||||||
|
$manifest = manifest $app $bucket
|
||||||
|
} else {
|
||||||
|
foreach ($bucket in Get-LocalBucket) {
|
||||||
|
$manifest = manifest $app $bucket
|
||||||
|
if ($manifest) { break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$manifest) {
|
||||||
|
# couldn't find app in buckets: check if it's a local path
|
||||||
|
$path = $app
|
||||||
|
if (!$path.endswith('.json')) { $path += '.json' }
|
||||||
|
if (Test-Path $path) {
|
||||||
|
$url = "$(Resolve-Path $path)"
|
||||||
|
$app = appname_from_url $url
|
||||||
|
$manifest, $bucket = url_manifest $url
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($bucket in Get-LocalBucket) {
|
return $app, $manifest, $bucket, $url
|
||||||
$manifest = manifest $app $bucket
|
}
|
||||||
if($manifest) { return $manifest, $bucket }
|
|
||||||
|
function Convert-RepositoryUri {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[String] $Uri
|
||||||
|
)
|
||||||
|
|
||||||
|
process {
|
||||||
|
# https://git-scm.com/docs/git-clone#_git_urls
|
||||||
|
# https://regex101.com/r/xGmwRr/1
|
||||||
|
if ($Uri -match '(?:@|/{1,3})(?:www\.|.*@)?(?<provider>[^/]+?)(?::\d+)?[:/](?<user>.+)/(?<repo>.+?)(?:\.git)?/?$') {
|
||||||
|
$Matches.provider, $Matches.user, $Matches.repo -join '/'
|
||||||
|
} else {
|
||||||
|
error "$Uri is not a valid Git URL!"
|
||||||
|
error "Please see https://git-scm.com/docs/git-clone#_git_urls for valid ones."
|
||||||
|
return $null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function list_buckets {
|
||||||
|
$buckets = @()
|
||||||
|
Get-LocalBucket | ForEach-Object {
|
||||||
|
$bucket = [Ordered]@{ Name = $_ }
|
||||||
|
$path = Find-BucketDirectory $_ -Root
|
||||||
|
if ((Test-Path (Join-Path $path '.git')) -and (Get-Command git -ErrorAction SilentlyContinue)) {
|
||||||
|
$bucket.Source = git -C $path config remote.origin.url
|
||||||
|
$bucket.Updated = git -C $path log --format='%aD' -n 1 | Get-Date
|
||||||
|
} else {
|
||||||
|
$bucket.Source = friendly_path $path
|
||||||
|
$bucket.Updated = (Get-Item "$path\bucket").LastWriteTime
|
||||||
|
}
|
||||||
|
$bucket.Manifests = Get-ChildItem "$path\bucket" -Force -Recurse -ErrorAction SilentlyContinue |
|
||||||
|
Measure-Object | Select-Object -ExpandProperty Count
|
||||||
|
$buckets += [PSCustomObject]$bucket
|
||||||
|
}
|
||||||
|
$buckets
|
||||||
|
}
|
||||||
|
|
||||||
function add_bucket($name, $repo) {
|
function add_bucket($name, $repo) {
|
||||||
if (!$name) { "<name> missing"; $usage_add; exit 1 }
|
|
||||||
if (!$repo) {
|
|
||||||
$repo = known_bucket_repo $name
|
|
||||||
if (!$repo) { "Unknown bucket '$name'. Try specifying <repo>."; $usage_add; exit 1 }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Test-CommandAvailable git)) {
|
if (!(Test-CommandAvailable git)) {
|
||||||
abort "Git is required for buckets. Run 'scoop install git' and try again."
|
error "Git is required for buckets. Run 'scoop install git' and try again."
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = Find-BucketDirectory $name -Root
|
$dir = Find-BucketDirectory $name -Root
|
||||||
if (test-path $dir) {
|
if (Test-Path $dir) {
|
||||||
warn "The '$name' bucket already exists. Use 'scoop bucket rm $name' to remove it."
|
warn "The '$name' bucket already exists. Use 'scoop bucket rm $name' to remove it."
|
||||||
exit 0
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
write-host 'Checking repo... ' -nonewline
|
$uni_repo = Convert-RepositoryUri -Uri $repo
|
||||||
$out = git_ls_remote $repo 2>&1
|
if ($null -eq $uni_repo) {
|
||||||
if ($lastexitcode -ne 0) {
|
return 1
|
||||||
abort "'$repo' doesn't look like a valid git repository`n`nError given:`n$out"
|
}
|
||||||
|
foreach ($bucket in Get-LocalBucket) {
|
||||||
|
$remote = git -C "$bucketsdir\$bucket" config --get remote.origin.url
|
||||||
|
if ((Convert-RepositoryUri -Uri $remote) -eq $uni_repo) {
|
||||||
|
warn "Bucket $bucket already exists for $repo"
|
||||||
|
return 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
write-host 'ok'
|
|
||||||
|
|
||||||
ensure $bucketsdir > $null
|
Write-Host 'Checking repo... ' -NoNewline
|
||||||
|
$out = git_cmd ls-remote $repo 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
error "'$repo' doesn't look like a valid git repository`n`nError given:`n$out"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
Write-Host 'OK'
|
||||||
|
|
||||||
|
ensure $bucketsdir | Out-Null
|
||||||
$dir = ensure $dir
|
$dir = ensure $dir
|
||||||
git_clone "$repo" "`"$dir`"" -q
|
git_cmd clone "$repo" "`"$dir`"" -q
|
||||||
success "The $name bucket was added successfully."
|
success "The $name bucket was added successfully."
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function rm_bucket($name) {
|
function rm_bucket($name) {
|
||||||
if (!$name) { "<name> missing"; $usage_rm; exit 1 }
|
|
||||||
$dir = Find-BucketDirectory $name -Root
|
$dir = Find-BucketDirectory $name -Root
|
||||||
if (!(test-path $dir)) {
|
if (!(Test-Path $dir)) {
|
||||||
abort "'$name' bucket not found."
|
error "'$name' bucket not found."
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
Remove-Item $dir -r -force -ea stop
|
Remove-Item $dir -Recurse -Force -ErrorAction Stop
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function new_issue_msg($app, $bucket, $title, $body) {
|
function new_issue_msg($app, $bucket, $title, $body) {
|
||||||
@@ -126,18 +199,16 @@ function new_issue_msg($app, $bucket, $title, $body) {
|
|||||||
$url = known_bucket_repo $bucket
|
$url = known_bucket_repo $bucket
|
||||||
$bucket_path = "$bucketsdir\$bucket"
|
$bucket_path = "$bucketsdir\$bucket"
|
||||||
|
|
||||||
if (Test-path $bucket_path) {
|
if (Test-Path $bucket_path) {
|
||||||
Push-Location $bucket_path
|
$remote = Invoke-Expression "git -C '$bucket_path' config --get remote.origin.url"
|
||||||
$remote = git_config --get remote.origin.url
|
|
||||||
# Support ssh and http syntax
|
# Support ssh and http syntax
|
||||||
# git@PROVIDER:USER/REPO.git
|
# git@PROVIDER:USER/REPO.git
|
||||||
# https://PROVIDER/USER/REPO.git
|
# https://PROVIDER/USER/REPO.git
|
||||||
$remote -match '(@|:\/\/)(?<provider>.+)[:/](?<user>.*)\/(?<repo>.*)(\.git)?$' | Out-Null
|
$remote -match '(@|:\/\/)(?<provider>.+)[:/](?<user>.*)\/(?<repo>.*)(\.git)?$' | Out-Null
|
||||||
$url = "https://$($Matches.Provider)/$($Matches.User)/$($Matches.Repo)"
|
$url = "https://$($Matches.Provider)/$($Matches.User)/$($Matches.Repo)"
|
||||||
Pop-Location
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$url) { return 'Please contact the bucket maintainer!' }
|
if (!$url) { return 'Please contact the bucket maintainer!' }
|
||||||
|
|
||||||
# Print only github repositories
|
# Print only github repositories
|
||||||
if ($url -like '*github*') {
|
if ($url -like '*github*') {
|
||||||
@@ -145,7 +216,7 @@ function new_issue_msg($app, $bucket, $title, $body) {
|
|||||||
$body = [System.Web.HttpUtility]::UrlEncode($body)
|
$body = [System.Web.HttpUtility]::UrlEncode($body)
|
||||||
$url = $url -replace '\.git$', ''
|
$url = $url -replace '\.git$', ''
|
||||||
$url = "$url/issues/new?title=$title"
|
$url = "$url/issues/new?title=$title"
|
||||||
if($body) {
|
if ($body) {
|
||||||
$url += "&body=$body"
|
$url += "&body=$body"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
function command_files {
|
function command_files {
|
||||||
(Get-ChildItem (relpath '..\libexec')) `
|
(Get-ChildItem "$PSScriptRoot\..\libexec") + (Get-ChildItem "$scoopdir\shims") |
|
||||||
+ (Get-ChildItem "$scoopdir\shims") `
|
Where-Object 'scoop-.*?\.ps1$' -Property Name -Match
|
||||||
| Where-Object { $_.name -match 'scoop-.*?\.ps1$' }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function commands {
|
function commands {
|
||||||
@@ -13,7 +12,7 @@ function command_name($filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function command_path($cmd) {
|
function command_path($cmd) {
|
||||||
$cmd_path = relpath "..\libexec\scoop-$cmd.ps1"
|
$cmd_path = "$PSScriptRoot\..\libexec\scoop-$cmd.ps1"
|
||||||
|
|
||||||
# built in commands
|
# built in commands
|
||||||
if (!(Test-Path $cmd_path)) {
|
if (!(Test-Path $cmd_path)) {
|
||||||
|
|||||||
545
lib/core.ps1
545
lib/core.ps1
@@ -41,7 +41,10 @@ function load_cfg($file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return (Get-Content $file -Raw | ConvertFrom-Json -ErrorAction Stop)
|
# ReadAllLines will detect the encoding of the file automatically
|
||||||
|
# Ref: https://docs.microsoft.com/en-us/dotnet/api/system.io.file.readalllines?view=netframework-4.5
|
||||||
|
$content = [System.IO.File]::ReadAllLines($file)
|
||||||
|
return ($content | ConvertFrom-Json -ErrorAction Stop)
|
||||||
} catch {
|
} catch {
|
||||||
Write-Host "ERROR loading $file`: $($_.exception.message)"
|
Write-Host "ERROR loading $file`: $($_.exception.message)"
|
||||||
}
|
}
|
||||||
@@ -54,27 +57,34 @@ function get_config($name, $default) {
|
|||||||
return $scoopConfig.$name
|
return $scoopConfig.$name
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_config($name, $value) {
|
function set_config {
|
||||||
if($null -eq $scoopConfig -or $scoopConfig.Count -eq 0) {
|
Param (
|
||||||
|
[ValidateNotNullOrEmpty()]
|
||||||
|
$name,
|
||||||
|
$value
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($null -eq $scoopConfig -or $scoopConfig.Count -eq 0) {
|
||||||
ensure (Split-Path -Path $configFile) | Out-Null
|
ensure (Split-Path -Path $configFile) | Out-Null
|
||||||
$scoopConfig = New-Object PSObject
|
$scoopConfig = New-Object -TypeName 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($null -eq $scoopConfig.$name) {
|
|
||||||
$scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value
|
|
||||||
} else {
|
|
||||||
$scoopConfig.$name = $value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($null -eq $value) {
|
if ($value -eq [bool]::TrueString -or $value -eq [bool]::FalseString) {
|
||||||
|
$value = [System.Convert]::ToBoolean($value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -eq $scoopConfig.$name) {
|
||||||
|
$scoopConfig | Add-Member -MemberType NoteProperty -Name $name -Value $value
|
||||||
|
} else {
|
||||||
|
$scoopConfig.$name = $value
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -eq $value) {
|
||||||
$scoopConfig.PSObject.Properties.Remove($name)
|
$scoopConfig.PSObject.Properties.Remove($name)
|
||||||
}
|
}
|
||||||
|
|
||||||
ConvertTo-Json $scoopConfig | Set-Content $configFile -Encoding ASCII
|
# Save config with UTF8NoBOM encoding
|
||||||
|
ConvertTo-Json $scoopConfig | Out-UTF8File -FilePath $configFile
|
||||||
return $scoopConfig
|
return $scoopConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +117,15 @@ function setup_proxy() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function git_cmd {
|
||||||
|
$proxy = get_config 'proxy'
|
||||||
|
$cmd = "git $($args | ForEach-Object { "$_ " })"
|
||||||
|
if ($proxy -and $proxy -ne 'none') {
|
||||||
|
$cmd = "SET HTTPS_PROXY=$proxy&&SET HTTP_PROXY=$proxy&&$cmd"
|
||||||
|
}
|
||||||
|
cmd.exe /d /c $cmd
|
||||||
|
}
|
||||||
|
|
||||||
# helper functions
|
# helper functions
|
||||||
function coalesce($a, $b) { if($a) { return $a } $b }
|
function coalesce($a, $b) { if($a) { return $a } $b }
|
||||||
|
|
||||||
@@ -168,6 +187,9 @@ function filesize($length) {
|
|||||||
} elseif($length -gt $kb) {
|
} elseif($length -gt $kb) {
|
||||||
"{0:n1} KB" -f ($length / $kb)
|
"{0:n1} KB" -f ($length / $kb)
|
||||||
} else {
|
} else {
|
||||||
|
if ($null -eq $length) {
|
||||||
|
$length = 0
|
||||||
|
}
|
||||||
"$($length) B"
|
"$($length) B"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,6 +200,16 @@ function appsdir($global) { "$(basedir $global)\apps" }
|
|||||||
function shimdir($global) { "$(basedir $global)\shims" }
|
function shimdir($global) { "$(basedir $global)\shims" }
|
||||||
function appdir($app, $global) { "$(appsdir $global)\$app" }
|
function appdir($app, $global) { "$(appsdir $global)\$app" }
|
||||||
function versiondir($app, $version, $global) { "$(appdir $app $global)\$version" }
|
function versiondir($app, $version, $global) { "$(appdir $app $global)\$version" }
|
||||||
|
|
||||||
|
function currentdir($app, $global) {
|
||||||
|
if (get_config NO_JUNCTIONS) {
|
||||||
|
$version = Select-CurrentVersion -App $app -Global:$global
|
||||||
|
} else {
|
||||||
|
$version = 'current'
|
||||||
|
}
|
||||||
|
"$(appdir $app $global)\$version"
|
||||||
|
}
|
||||||
|
|
||||||
function persistdir($app, $global) { "$(basedir $global)\persist\$app" }
|
function persistdir($app, $global) { "$(basedir $global)\persist\$app" }
|
||||||
function usermanifestsdir { "$(basedir)\workspace" }
|
function usermanifestsdir { "$(basedir)\workspace" }
|
||||||
function usermanifest($app) { "$(usermanifestsdir)\$app.json" }
|
function usermanifest($app) { "$(usermanifestsdir)\$app.json" }
|
||||||
@@ -185,21 +217,31 @@ function cache_path($app, $version, $url) { "$cachedir\$app#$version#$($url -rep
|
|||||||
|
|
||||||
# apps
|
# apps
|
||||||
function sanitary_path($path) { return [regex]::replace($path, "[/\\?:*<>|]", "") }
|
function sanitary_path($path) { return [regex]::replace($path, "[/\\?:*<>|]", "") }
|
||||||
function installed($app, $global=$null) {
|
function installed($app, $global) {
|
||||||
if($null -eq $global) { return (installed $app $true) -or (installed $app $false) }
|
if (-not $PSBoundParameters.ContainsKey('global')) {
|
||||||
|
return (installed $app $false) -or (installed $app $true)
|
||||||
|
}
|
||||||
# Dependencies of the format "bucket/dependency" install in a directory of form
|
# Dependencies of the format "bucket/dependency" install in a directory of form
|
||||||
# "dependency". So we need to extract the bucket from the name and only give the app
|
# "dependency". So we need to extract the bucket from the name and only give the app
|
||||||
# name to is_directory
|
# name to is_directory
|
||||||
$app = $app.split("/")[-1]
|
$app = ($app -split '/|\\')[-1]
|
||||||
return is_directory (appdir $app $global)
|
return $null -ne (Select-CurrentVersion -AppName $app -Global:$global)
|
||||||
}
|
}
|
||||||
function installed_apps($global) {
|
function installed_apps($global) {
|
||||||
$dir = appsdir $global
|
$dir = appsdir $global
|
||||||
if(test-path $dir) {
|
if (Test-Path $dir) {
|
||||||
Get-ChildItem $dir | Where-Object { $_.psiscontainer -and $_.name -ne 'scoop' } | ForEach-Object { $_.name }
|
Get-ChildItem $dir | Where-Object { $_.psiscontainer -and $_.name -ne 'scoop' } | ForEach-Object { $_.name }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check whether the app failed to install
|
||||||
|
function failed($app, $global) {
|
||||||
|
$app = ($app -split '/|\\')[-1]
|
||||||
|
$appPath = appdir $app $global
|
||||||
|
$hasCurrent = (get_config NO_JUNCTIONS) -or (Test-Path "$appPath\current")
|
||||||
|
return (Test-Path $appPath) -and !($hasCurrent -and (installed $app $global))
|
||||||
|
}
|
||||||
|
|
||||||
function file_path($app, $file) {
|
function file_path($app, $file) {
|
||||||
Show-DeprecatedWarning $MyInvocation 'Get-AppFilePath'
|
Show-DeprecatedWarning $MyInvocation 'Get-AppFilePath'
|
||||||
Get-AppFilePath -App $app -File $file
|
Get-AppFilePath -App $app -File $file
|
||||||
@@ -207,6 +249,7 @@ function file_path($app, $file) {
|
|||||||
|
|
||||||
function Get-AppFilePath {
|
function Get-AppFilePath {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
|
[OutputType([String])]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true, Position = 0)]
|
[Parameter(Mandatory = $true, Position = 0)]
|
||||||
[String]
|
[String]
|
||||||
@@ -217,14 +260,14 @@ function Get-AppFilePath {
|
|||||||
)
|
)
|
||||||
|
|
||||||
# normal path to file
|
# normal path to file
|
||||||
$Path = "$(versiondir $App 'current' $false)\$File"
|
$Path = "$(currentdir $App $false)\$File"
|
||||||
if(Test-Path $Path) {
|
if (Test-Path $Path) {
|
||||||
return $Path
|
return $Path
|
||||||
}
|
}
|
||||||
|
|
||||||
# global path to file
|
# global path to file
|
||||||
$Path = "$(versiondir $App 'current' $true)\$File"
|
$Path = "$(currentdir $App $true)\$File"
|
||||||
if(Test-Path $Path) {
|
if (Test-Path $Path) {
|
||||||
return $Path
|
return $Path
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,40 +284,45 @@ Function Test-CommandAvailable {
|
|||||||
|
|
||||||
function Get-HelperPath {
|
function Get-HelperPath {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
|
[OutputType([String])]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
[ValidateSet('7zip', 'Lessmsi', 'Innounp', 'Dark', 'Aria2')]
|
[ValidateSet('7zip', 'Lessmsi', 'Innounp', 'Dark', 'Aria2', 'Zstd')]
|
||||||
[String]
|
[String]
|
||||||
$Helper
|
$Helper
|
||||||
)
|
)
|
||||||
|
begin {
|
||||||
$HelperPath = $null
|
$HelperPath = $null
|
||||||
switch ($Helper) {
|
|
||||||
'7zip' {
|
|
||||||
$HelperPath = Get-AppFilePath '7zip' '7z.exe'
|
|
||||||
if([String]::IsNullOrEmpty($HelperPath)) {
|
|
||||||
$HelperPath = Get-AppFilePath '7zip-zstd' '7z.exe'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'Lessmsi' { $HelperPath = Get-AppFilePath 'lessmsi' 'lessmsi.exe' }
|
|
||||||
'Innounp' { $HelperPath = Get-AppFilePath 'innounp' 'innounp.exe' }
|
|
||||||
'Dark' {
|
|
||||||
$HelperPath = Get-AppFilePath 'dark' 'dark.exe'
|
|
||||||
if([String]::IsNullOrEmpty($HelperPath)) {
|
|
||||||
$HelperPath = Get-AppFilePath 'wixtoolset' 'dark.exe'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
'Aria2' { $HelperPath = Get-AppFilePath 'aria2' 'aria2c.exe' }
|
|
||||||
}
|
}
|
||||||
|
process {
|
||||||
|
switch ($Helper) {
|
||||||
|
'7zip' {
|
||||||
|
$HelperPath = Get-AppFilePath '7zip' '7z.exe'
|
||||||
|
if ([String]::IsNullOrEmpty($HelperPath)) {
|
||||||
|
$HelperPath = Get-AppFilePath '7zip-zstd' '7z.exe'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'Lessmsi' { $HelperPath = Get-AppFilePath 'lessmsi' 'lessmsi.exe' }
|
||||||
|
'Innounp' { $HelperPath = Get-AppFilePath 'innounp' 'innounp.exe' }
|
||||||
|
'Dark' {
|
||||||
|
$HelperPath = Get-AppFilePath 'dark' 'dark.exe'
|
||||||
|
if ([String]::IsNullOrEmpty($HelperPath)) {
|
||||||
|
$HelperPath = Get-AppFilePath 'wixtoolset' 'dark.exe'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'Aria2' { $HelperPath = Get-AppFilePath 'aria2' 'aria2c.exe' }
|
||||||
|
'Zstd' { $HelperPath = Get-AppFilePath 'zstd' 'zstd.exe' }
|
||||||
|
}
|
||||||
|
|
||||||
return $HelperPath
|
return $HelperPath
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Test-HelperInstalled {
|
function Test-HelperInstalled {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
[ValidateSet('7zip', 'Lessmsi', 'Innounp', 'Dark', 'Aria2')]
|
[ValidateSet('7zip', 'Lessmsi', 'Innounp', 'Dark', 'Aria2', 'Zstd')]
|
||||||
[String]
|
[String]
|
||||||
$Helper
|
$Helper
|
||||||
)
|
)
|
||||||
@@ -288,33 +336,41 @@ function Test-Aria2Enabled {
|
|||||||
|
|
||||||
function app_status($app, $global) {
|
function app_status($app, $global) {
|
||||||
$status = @{}
|
$status = @{}
|
||||||
$status.installed = (installed $app $global)
|
$status.installed = installed $app $global
|
||||||
$status.version = current_version $app $global
|
$status.version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
$status.latest_version = $status.version
|
$status.latest_version = $status.version
|
||||||
|
|
||||||
$install_info = install_info $app $status.version $global
|
$install_info = install_info $app $status.version $global
|
||||||
|
|
||||||
$status.failed = (!$install_info -or !$status.version)
|
$status.failed = failed $app $global
|
||||||
$status.hold = ($install_info.hold -eq $true)
|
$status.hold = ($install_info.hold -eq $true)
|
||||||
|
|
||||||
$manifest = manifest $app $install_info.bucket $install_info.url
|
$manifest = manifest $app $install_info.bucket $install_info.url
|
||||||
$status.removed = (!$manifest)
|
$status.removed = (!$manifest)
|
||||||
if($manifest.version) {
|
if ($manifest.version) {
|
||||||
$status.latest_version = $manifest.version
|
$status.latest_version = $manifest.version
|
||||||
}
|
}
|
||||||
|
|
||||||
$status.outdated = $false
|
$status.outdated = $false
|
||||||
if($status.version -and $status.latest_version) {
|
if ($status.version -and $status.latest_version) {
|
||||||
$status.outdated = ((compare_versions $status.latest_version $status.version) -gt 0)
|
if (get_config 'force_update' $false) {
|
||||||
|
$status.outdated = ((Compare-Version -ReferenceVersion $status.version -DifferenceVersion $status.latest_version) -ne 0)
|
||||||
|
} else {
|
||||||
|
$status.outdated = ((Compare-Version -ReferenceVersion $status.version -DifferenceVersion $status.latest_version) -gt 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$status.missing_deps = @()
|
$status.missing_deps = @()
|
||||||
$deps = @(runtime_deps $manifest) | Where-Object {
|
$deps = @($manifest.depends) | Where-Object {
|
||||||
$app, $bucket, $null = parse_app $_
|
if ($null -eq $_) {
|
||||||
return !(installed $app)
|
return $null
|
||||||
|
} else {
|
||||||
|
$app, $bucket, $null = parse_app $_
|
||||||
|
return !(installed $app)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if($deps) {
|
if ($deps) {
|
||||||
$status.missing_deps += ,$deps
|
$status.missing_deps += , $deps
|
||||||
}
|
}
|
||||||
|
|
||||||
return $status
|
return $status
|
||||||
@@ -351,11 +407,16 @@ function url_remote_filename($url) {
|
|||||||
return $basename
|
return $basename
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensure($dir) { if(!(test-path $dir)) { mkdir $dir > $null }; resolve-path $dir }
|
function ensure($dir) {
|
||||||
function fullpath($path) { # should be ~ rooted
|
if (!(Test-Path -Path $dir)) {
|
||||||
$executionContext.sessionState.path.getUnresolvedProviderPathFromPSPath($path)
|
New-Item -Path $dir -ItemType Directory | Out-Null
|
||||||
|
}
|
||||||
|
Convert-Path -Path $dir
|
||||||
|
}
|
||||||
|
function fullpath($path) {
|
||||||
|
# should be ~ rooted
|
||||||
|
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($path)
|
||||||
}
|
}
|
||||||
function relpath($path) { "$($myinvocation.psscriptroot)\$path" } # relative to calling script
|
|
||||||
function friendly_path($path) {
|
function friendly_path($path) {
|
||||||
$h = (Get-PsProvider 'FileSystem').home; if(!$h.endswith('\')) { $h += '\' }
|
$h = (Get-PsProvider 'FileSystem').home; if(!$h.endswith('\')) { $h += '\' }
|
||||||
if($h -eq '\') { return $path }
|
if($h -eq '\') { return $path }
|
||||||
@@ -429,7 +490,8 @@ function Invoke-ExternalCommand {
|
|||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
if ($LogPath -and ($FilePath -notmatch '(^|\W)msiexec($|\W)')) {
|
if ($LogPath -and ($FilePath -notmatch '(^|\W)msiexec($|\W)')) {
|
||||||
Out-File -FilePath $LogPath -Encoding ASCII -Append -InputObject $Process.StandardOutput.ReadToEnd()
|
Out-UTF8File -FilePath $LogPath -Append -InputObject $Process.StandardOutput.ReadToEnd()
|
||||||
|
Out-UTF8File -FilePath $LogPath -Append -InputObject $Process.StandardError.ReadToEnd()
|
||||||
}
|
}
|
||||||
$Process.WaitForExit()
|
$Process.WaitForExit()
|
||||||
if ($Process.ExitCode -ne 0) {
|
if ($Process.ExitCode -ne 0) {
|
||||||
@@ -519,95 +581,190 @@ function movedir($from, $to) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_app_name($path) {
|
function get_app_name($path) {
|
||||||
if ($path -match '([^/\\]+)[/\\]current[/\\]') {
|
if ((Test-Path (appsdir $false)) -and ($path -match "$([Regex]::Escape($(Convert-Path (appsdir $false))))[/\\]([^/\\]+)")) {
|
||||||
return $matches[1].tolower()
|
$appName = $Matches[1].ToLower()
|
||||||
|
} elseif ((Test-Path (appsdir $true)) -and ($path -match "$([Regex]::Escape($(Convert-Path (appsdir $true))))[/\\]([^/\\]+)")) {
|
||||||
|
$appName = $Matches[1].ToLower()
|
||||||
|
} else {
|
||||||
|
$appName = ''
|
||||||
}
|
}
|
||||||
return ''
|
return $appName
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_app_name_from_ps1_shim($shim_ps1) {
|
function get_app_name_from_shim($shim) {
|
||||||
if (!(Test-Path($shim_ps1))) {
|
if (!(Test-Path($shim))) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
$content = (Get-Content $shim_ps1 -Encoding utf8) -join ' '
|
$content = (Get-Content $shim -Encoding UTF8) -join ' '
|
||||||
return get_app_name $content
|
return get_app_name $content
|
||||||
}
|
}
|
||||||
|
|
||||||
function warn_on_overwrite($shim_ps1, $path) {
|
function warn_on_overwrite($shim, $path) {
|
||||||
if (!(Test-Path($shim_ps1))) {
|
if (!(Test-Path $shim)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
$shim_app = get_app_name_from_ps1_shim $shim_ps1
|
$shim_app = get_app_name_from_shim $shim
|
||||||
$path_app = get_app_name $path
|
$path_app = get_app_name $path
|
||||||
if ($shim_app -eq $path_app) {
|
if ($shim_app -eq $path_app) {
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
if (Test-Path -Path "$shim.$path_app" -PathType Leaf) {
|
||||||
|
Remove-Item -Path "$shim.$path_app" -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
Rename-Item -Path $shim -NewName "$shim.$shim_app" -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
$filename = [System.IO.Path]::GetFileName($path)
|
$shimname = (fname $shim) -replace '\.shim$', '.exe'
|
||||||
warn "Overwriting shim to $filename installed from $shim_app"
|
$filename = (fname $path) -replace '\.shim$', '.exe'
|
||||||
|
warn "Overwriting shim ('$shimname' -> '$filename')$(if ($shim_app) { ' installed from ' + $shim_app })"
|
||||||
}
|
}
|
||||||
|
|
||||||
function shim($path, $global, $name, $arg) {
|
function shim($path, $global, $name, $arg) {
|
||||||
if(!(test-path $path)) { abort "Can't shim '$(fname $path)': couldn't find '$path'." }
|
if (!(Test-Path $path)) { abort "Can't shim '$(fname $path)': couldn't find '$path'." }
|
||||||
$abs_shimdir = ensure (shimdir $global)
|
$abs_shimdir = ensure (shimdir $global)
|
||||||
if(!$name) { $name = strip_ext (fname $path) }
|
ensure_in_path $abs_shimdir $global
|
||||||
|
if (!$name) { $name = strip_ext (fname $path) }
|
||||||
|
|
||||||
$shim = "$abs_shimdir\$($name.tolower())"
|
$shim = "$abs_shimdir\$($name.tolower())"
|
||||||
|
|
||||||
warn_on_overwrite "$shim.ps1" $path
|
|
||||||
|
|
||||||
# convert to relative path
|
# convert to relative path
|
||||||
Push-Location $abs_shimdir
|
Push-Location $abs_shimdir
|
||||||
$relative_path = resolve-path -relative $path
|
$relative_path = Resolve-Path -Relative $path
|
||||||
Pop-Location
|
Pop-Location
|
||||||
$resolved_path = resolve-path $path
|
$resolved_path = Resolve-Path $path
|
||||||
|
|
||||||
# if $path points to another drive resolve-path prepends .\ which could break shims
|
if ($path -match '\.(exe|com)$') {
|
||||||
if($relative_path -match "^(.\\[\w]:).*$") {
|
|
||||||
write-output "`$path = `"$path`"" | out-file "$shim.ps1" -encoding utf8
|
|
||||||
} else {
|
|
||||||
# Setting PSScriptRoot in Shim if it is not defined, so the shim doesn't break in PowerShell 2.0
|
|
||||||
Write-Output "if (!(Test-Path Variable:PSScriptRoot)) { `$PSScriptRoot = Split-Path `$MyInvocation.MyCommand.Path -Parent }" | Out-File "$shim.ps1" -Encoding utf8
|
|
||||||
write-output "`$path = join-path `"`$psscriptroot`" `"$relative_path`"" | out-file "$shim.ps1" -Encoding utf8 -Append
|
|
||||||
}
|
|
||||||
|
|
||||||
if($path -match '\.jar$') {
|
|
||||||
"if(`$myinvocation.expectingInput) { `$input | & java -jar `$path $arg @args } else { & java -jar `$path $arg @args }" | out-file "$shim.ps1" -encoding utf8 -append
|
|
||||||
} else {
|
|
||||||
"if(`$myinvocation.expectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }" | out-file "$shim.ps1" -encoding utf8 -append
|
|
||||||
}
|
|
||||||
|
|
||||||
if($path -match '\.(exe|com)$') {
|
|
||||||
# for programs with no awareness of any shell
|
# for programs with no awareness of any shell
|
||||||
Copy-Item "$(versiondir 'scoop' 'current')\supporting\shimexe\bin\shim.exe" "$shim.exe" -force
|
warn_on_overwrite "$shim.shim" $path
|
||||||
write-output "path = $resolved_path" | out-file "$shim.shim" -encoding utf8
|
Copy-Item (get_shim_path) "$shim.exe" -Force
|
||||||
if($arg) {
|
Write-Output "path = `"$resolved_path`"" | Out-UTF8File "$shim.shim"
|
||||||
write-output "args = $arg" | out-file "$shim.shim" -encoding utf8 -append
|
if ($arg) {
|
||||||
|
Write-Output "args = $arg" | Out-UTF8File "$shim.shim" -Append
|
||||||
}
|
}
|
||||||
} elseif($path -match '\.(bat|cmd)$') {
|
} elseif ($path -match '\.(bat|cmd)$') {
|
||||||
# shim .bat, .cmd so they can be used by programs with no awareness of PSH
|
# shim .bat, .cmd so they can be used by programs with no awareness of PSH
|
||||||
"@`"$resolved_path`" $arg %*" | out-file "$shim.cmd" -encoding ascii
|
warn_on_overwrite "$shim.cmd" $path
|
||||||
|
@(
|
||||||
|
"@rem $resolved_path",
|
||||||
|
"@`"$resolved_path`" $arg %*"
|
||||||
|
) -join "`r`n" | Out-UTF8File "$shim.cmd"
|
||||||
|
|
||||||
|
warn_on_overwrite $shim $path
|
||||||
|
@(
|
||||||
|
"#!/bin/sh",
|
||||||
|
"# $resolved_path",
|
||||||
|
"MSYS2_ARG_CONV_EXCL=/C cmd.exe /C `"$resolved_path`" $arg `"$@`""
|
||||||
|
) -join "`n" | Out-UTF8File $shim -NoNewLine
|
||||||
|
} elseif ($path -match '\.ps1$') {
|
||||||
|
# if $path points to another drive resolve-path prepends .\ which could break shims
|
||||||
|
warn_on_overwrite "$shim.ps1" $path
|
||||||
|
$ps1text = if ($relative_path -match '^(\.\\)?\w:.*$') {
|
||||||
|
@(
|
||||||
|
"# $resolved_path",
|
||||||
|
"`$path = `"$path`"",
|
||||||
|
"if (`$MyInvocation.ExpectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }",
|
||||||
|
"exit `$LASTEXITCODE"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
@(
|
||||||
|
"# $resolved_path",
|
||||||
|
"`$path = Join-Path `$PSScriptRoot `"$relative_path`"",
|
||||||
|
"if (`$MyInvocation.ExpectingInput) { `$input | & `$path $arg @args } else { & `$path $arg @args }",
|
||||||
|
"exit `$LASTEXITCODE"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
$ps1text -join "`r`n" | Out-UTF8File "$shim.ps1"
|
||||||
|
|
||||||
"#!/bin/sh`nMSYS2_ARG_CONV_EXCL=/C cmd.exe /C `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
|
|
||||||
} elseif($path -match '\.ps1$') {
|
|
||||||
# make ps1 accessible from cmd.exe
|
# make ps1 accessible from cmd.exe
|
||||||
"@echo off
|
warn_on_overwrite "$shim.cmd" $path
|
||||||
setlocal enabledelayedexpansion
|
@(
|
||||||
set args=%*
|
"@rem $resolved_path",
|
||||||
:: replace problem characters in arguments
|
"@echo off",
|
||||||
set args=%args:`"='%
|
"setlocal enabledelayedexpansion",
|
||||||
set args=%args:(=``(%
|
"set args=%*",
|
||||||
set args=%args:)=``)%
|
":: replace problem characters in arguments",
|
||||||
set invalid=`"='
|
"set args=%args:`"='%",
|
||||||
if !args! == !invalid! ( set args= )
|
"set args=%args:(=``(%",
|
||||||
powershell -noprofile -ex unrestricted `"& '$resolved_path' $arg %args%;exit `$lastexitcode`"" | out-file "$shim.cmd" -encoding ascii
|
"set args=%args:)=``)%",
|
||||||
|
"set invalid=`"='",
|
||||||
|
"if !args! == !invalid! ( set args= )",
|
||||||
|
"where /q pwsh.exe",
|
||||||
|
"if %errorlevel% equ 0 (",
|
||||||
|
" pwsh -noprofile -ex unrestricted -file `"$resolved_path`" $arg %args%",
|
||||||
|
") else (",
|
||||||
|
" powershell -noprofile -ex unrestricted -file `"$resolved_path`" $arg %args%",
|
||||||
|
")"
|
||||||
|
) -join "`r`n" | Out-UTF8File "$shim.cmd"
|
||||||
|
|
||||||
"#!/bin/sh`npowershell.exe -noprofile -ex unrestricted `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
|
warn_on_overwrite $shim $path
|
||||||
} elseif($path -match '\.jar$') {
|
@(
|
||||||
"@java -jar `"$resolved_path`" $arg %*" | out-file "$shim.cmd" -encoding ascii
|
"#!/bin/sh",
|
||||||
"#!/bin/sh`njava -jar `"$resolved_path`" $arg `"$@`"" | out-file $shim -encoding ascii
|
"# $resolved_path",
|
||||||
|
"if command -v pwsh.exe > /dev/null 2>&1; then",
|
||||||
|
" pwsh.exe -noprofile -ex unrestricted -file `"$resolved_path`" $arg `"$@`"",
|
||||||
|
"else",
|
||||||
|
" powershell.exe -noprofile -ex unrestricted -file `"$resolved_path`" $arg `"$@`"",
|
||||||
|
"fi"
|
||||||
|
) -join "`n" | Out-UTF8File $shim -NoNewLine
|
||||||
|
} elseif ($path -match '\.jar$') {
|
||||||
|
warn_on_overwrite "$shim.cmd" $path
|
||||||
|
@(
|
||||||
|
"@rem $resolved_path",
|
||||||
|
"@java -jar `"$resolved_path`" $arg %*"
|
||||||
|
) -join "`r`n" | Out-UTF8File "$shim.cmd"
|
||||||
|
|
||||||
|
warn_on_overwrite $shim $path
|
||||||
|
@(
|
||||||
|
"#!/bin/sh",
|
||||||
|
"# $resolved_path",
|
||||||
|
"java.exe -jar `"$resolved_path`" $arg `"$@`""
|
||||||
|
) -join "`n" | Out-UTF8File $shim -NoNewLine
|
||||||
|
} elseif ($path -match '\.py$') {
|
||||||
|
warn_on_overwrite "$shim.cmd" $path
|
||||||
|
@(
|
||||||
|
"@rem $resolved_path",
|
||||||
|
"@python `"$resolved_path`" $arg %*"
|
||||||
|
) -join "`r`n" | Out-UTF8File "$shim.cmd"
|
||||||
|
|
||||||
|
warn_on_overwrite $shim $path
|
||||||
|
@(
|
||||||
|
"#!/bin/sh",
|
||||||
|
"# $resolved_path",
|
||||||
|
"python.exe `"$resolved_path`" $arg `"$@`""
|
||||||
|
) -join "`n" | Out-UTF8File $shim -NoNewLine
|
||||||
|
} else {
|
||||||
|
warn_on_overwrite "$shim.cmd" $path
|
||||||
|
# find path to Git's bash so that batch scripts can run bash scripts
|
||||||
|
$gitdir = (Get-Item (Get-Command git -CommandType:Application -ErrorAction:Stop).Source -ErrorAction:Stop).Directory.Parent
|
||||||
|
if ($gitdir.FullName -imatch 'mingw') {
|
||||||
|
$gitdir = $gitdir.Parent
|
||||||
|
}
|
||||||
|
@(
|
||||||
|
"@rem $resolved_path",
|
||||||
|
"@`"$(Join-Path (Join-Path $gitdir.FullName 'bin') 'bash.exe')`" `"$resolved_path`" $arg %*"
|
||||||
|
) -join "`r`n" | Out-UTF8File "$shim.cmd"
|
||||||
|
|
||||||
|
warn_on_overwrite $shim $path
|
||||||
|
@(
|
||||||
|
"#!/bin/sh",
|
||||||
|
"# $resolved_path",
|
||||||
|
"`"$resolved_path`" $arg `"$@`""
|
||||||
|
) -join "`n" | Out-UTF8File $shim -NoNewLine
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_shim_path() {
|
||||||
|
$shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\kiennq\shim.exe"
|
||||||
|
$shim_version = get_config 'shim' 'default'
|
||||||
|
switch ($shim_version) {
|
||||||
|
'71' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shims\71\shim.exe"; Break }
|
||||||
|
'scoopcs' { $shim_path = "$(versiondir 'scoop' 'current')\supporting\shimexe\bin\shim.exe"; Break }
|
||||||
|
'kiennq' { Break } # for backward compatibility
|
||||||
|
'default' { Break }
|
||||||
|
default { warn "Unknown shim version: '$shim_version'" }
|
||||||
|
}
|
||||||
|
return $shim_path
|
||||||
|
}
|
||||||
|
|
||||||
function search_in_path($target) {
|
function search_in_path($target) {
|
||||||
$path = (env 'PATH' $false) + ";" + (env 'PATH' $true)
|
$path = (env 'PATH' $false) + ";" + (env 'PATH' $true)
|
||||||
foreach($dir in $path.split(';')) {
|
foreach($dir in $path.split(';')) {
|
||||||
@@ -642,6 +799,7 @@ function ensure_architecture($architecture_opt) {
|
|||||||
|
|
||||||
function Confirm-InstallationStatus {
|
function Confirm-InstallationStatus {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
|
[OutputType([Object[]])]
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[String[]]
|
[String[]]
|
||||||
@@ -653,26 +811,29 @@ function Confirm-InstallationStatus {
|
|||||||
$Apps | Select-Object -Unique | Where-Object { $_.Name -ne 'scoop' } | ForEach-Object {
|
$Apps | Select-Object -Unique | Where-Object { $_.Name -ne 'scoop' } | ForEach-Object {
|
||||||
$App, $null, $null = parse_app $_
|
$App, $null, $null = parse_app $_
|
||||||
if ($Global) {
|
if ($Global) {
|
||||||
if (installed $App $true) {
|
if (Test-Path (appdir $App $true)) {
|
||||||
$Installed += ,@($App, $true)
|
$Installed += , @($App, $true)
|
||||||
} elseif (installed $App $false) {
|
} elseif (Test-Path (appdir $App $false)) {
|
||||||
error "'$App' isn't installed globally, but it is installed for your account."
|
error "'$App' isn't installed globally, but it may be installed locally."
|
||||||
warn "Try again without the --global (or -g) flag instead."
|
warn "Try again without the --global (or -g) flag instead."
|
||||||
} else {
|
} else {
|
||||||
error "'$App' isn't installed."
|
error "'$App' isn't installed."
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(installed $App $false) {
|
if (Test-Path (appdir $App $false)) {
|
||||||
$Installed += ,@($App, $false)
|
$Installed += , @($App, $false)
|
||||||
} elseif (installed $App $true) {
|
} elseif (Test-Path (appdir $App $true)) {
|
||||||
error "'$App' isn't installed for your account, but it is installed globally."
|
error "'$App' isn't installed locally, but it may be installed globally."
|
||||||
warn "Try again with the --global (or -g) flag instead."
|
warn "Try again with the --global (or -g) flag instead."
|
||||||
} else {
|
} else {
|
||||||
error "'$App' isn't installed."
|
error "'$App' isn't installed."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (failed $App $Global) {
|
||||||
|
error "'$App' isn't installed correctly."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ,$Installed
|
return , $Installed
|
||||||
}
|
}
|
||||||
|
|
||||||
function strip_path($orig_path, $dir) {
|
function strip_path($orig_path, $dir) {
|
||||||
@@ -708,12 +869,6 @@ function remove_from_path($dir, $global) {
|
|||||||
if($was_in_path) { $env:PATH = $newpath }
|
if($was_in_path) { $env:PATH = $newpath }
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensure_scoop_in_path($global) {
|
|
||||||
$abs_shimdir = ensure (shimdir $global)
|
|
||||||
# be aggressive (b-e-aggressive) and install scoop first in the path
|
|
||||||
ensure_in_path $abs_shimdir $global
|
|
||||||
}
|
|
||||||
|
|
||||||
function ensure_robocopy_in_path {
|
function ensure_robocopy_in_path {
|
||||||
if(!(Test-CommandAvailable robocopy)) {
|
if(!(Test-CommandAvailable robocopy)) {
|
||||||
shim "C:\Windows\System32\Robocopy.exe" $false
|
shim "C:\Windows\System32\Robocopy.exe" $false
|
||||||
@@ -741,55 +896,6 @@ function pluralize($count, $singular, $plural) {
|
|||||||
if($count -eq 1) { $singular } else { $plural }
|
if($count -eq 1) { $singular } else { $plural }
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset_alias($name, $value) {
|
|
||||||
if($existing = get-alias $name -ea ignore | Where-Object { $_.options -match 'readonly' }) {
|
|
||||||
if($existing.definition -ne $value) {
|
|
||||||
write-host "Alias $name is read-only; can't reset it." -f darkyellow
|
|
||||||
}
|
|
||||||
return # already set
|
|
||||||
}
|
|
||||||
if($value -is [scriptblock]) {
|
|
||||||
if(!(test-path -path "function:script:$name")) {
|
|
||||||
new-item -path function: -name "script:$name" -value $value | out-null
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
set-alias $name $value -scope script -option allscope
|
|
||||||
}
|
|
||||||
|
|
||||||
function reset_aliases() {
|
|
||||||
# for aliases where there's a local function, re-alias so the function takes precedence
|
|
||||||
$aliases = get-alias | Where-Object { $_.options -notmatch 'readonly|allscope' } | ForEach-Object { $_.name }
|
|
||||||
get-childitem function: | ForEach-Object {
|
|
||||||
$fn = $_.name
|
|
||||||
if($aliases -contains $fn) {
|
|
||||||
set-alias $fn local:$fn -scope script
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# for dealing with user aliases
|
|
||||||
$default_aliases = @{
|
|
||||||
'cp' = 'copy-item'
|
|
||||||
'echo' = 'write-output'
|
|
||||||
'gc' = 'get-content'
|
|
||||||
'gci' = 'get-childitem'
|
|
||||||
'gcm' = 'get-command'
|
|
||||||
'gm' = 'get-member'
|
|
||||||
'iex' = 'invoke-expression'
|
|
||||||
'ls' = 'get-childitem'
|
|
||||||
'mkdir' = { new-item -type directory @args }
|
|
||||||
'mv' = 'move-item'
|
|
||||||
'rm' = 'remove-item'
|
|
||||||
'sc' = 'set-content'
|
|
||||||
'select' = 'select-object'
|
|
||||||
'sls' = 'select-string'
|
|
||||||
}
|
|
||||||
|
|
||||||
# set default aliases
|
|
||||||
$default_aliases.keys | ForEach-Object { reset_alias $_ $default_aliases[$_] }
|
|
||||||
}
|
|
||||||
|
|
||||||
# convert list of apps to list of ($app, $global) tuples
|
# convert list of apps to list of ($app, $global) tuples
|
||||||
function applist($apps, $global) {
|
function applist($apps, $global) {
|
||||||
if(!$apps) { return @() }
|
if(!$apps) { return @() }
|
||||||
@@ -797,7 +903,7 @@ function applist($apps, $global) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parse_app([string] $app) {
|
function parse_app([string] $app) {
|
||||||
if($app -match '(?:(?<bucket>[a-zA-Z0-9-]+)\/)?(?<app>.*.json$|[a-zA-Z0-9-_.]+)(?:@(?<version>.*))?') {
|
if($app -match '(?:(?<bucket>[a-zA-Z0-9-]+)\/)?(?<app>.*\.json$|[a-zA-Z0-9-_.]+)(?:@(?<version>.*))?') {
|
||||||
return $matches['app'], $matches['bucket'], $matches['version']
|
return $matches['app'], $matches['bucket'], $matches['version']
|
||||||
}
|
}
|
||||||
return $app, $null, $null
|
return $app, $null, $null
|
||||||
@@ -815,7 +921,7 @@ function show_app($app, $bucket, $version) {
|
|||||||
|
|
||||||
function last_scoop_update() {
|
function last_scoop_update() {
|
||||||
# PowerShell 6 returns an DateTime Object
|
# PowerShell 6 returns an DateTime Object
|
||||||
$last_update = (scoop config lastupdate)
|
$last_update = (get_config lastupdate)
|
||||||
|
|
||||||
if ($null -ne $last_update -and $last_update.GetType() -eq [System.String]) {
|
if ($null -ne $last_update -and $last_update.GetType() -eq [System.String]) {
|
||||||
try {
|
try {
|
||||||
@@ -831,7 +937,7 @@ function is_scoop_outdated() {
|
|||||||
$last_update = $(last_scoop_update)
|
$last_update = $(last_scoop_update)
|
||||||
$now = [System.DateTime]::Now
|
$now = [System.DateTime]::Now
|
||||||
if($null -eq $last_update) {
|
if($null -eq $last_update) {
|
||||||
scoop config lastupdate $now.ToString('o')
|
set_config lastupdate $now.ToString('o')
|
||||||
# enforce an update for the first time
|
# enforce an update for the first time
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
@@ -839,18 +945,27 @@ function is_scoop_outdated() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function substitute($entity, [Hashtable] $params, [Bool]$regexEscape = $false) {
|
function substitute($entity, [Hashtable] $params, [Bool]$regexEscape = $false) {
|
||||||
if ($entity -is [Array]) {
|
$newentity = $entity
|
||||||
return $entity | ForEach-Object { substitute $_ $params $regexEscape}
|
if ($null -ne $newentity) {
|
||||||
} elseif ($entity -is [String]) {
|
switch ($entity.GetType().Name) {
|
||||||
$params.GetEnumerator() | ForEach-Object {
|
'String' {
|
||||||
if($regexEscape -eq $false -or $null -eq $_.Value) {
|
$params.GetEnumerator() | ForEach-Object {
|
||||||
$entity = $entity.Replace($_.Name, $_.Value)
|
if ($regexEscape -eq $false -or $null -eq $_.Value) {
|
||||||
} else {
|
$newentity = $newentity.Replace($_.Name, $_.Value)
|
||||||
$entity = $entity.Replace($_.Name, [Regex]::Escape($_.Value))
|
} else {
|
||||||
|
$newentity = $newentity.Replace($_.Name, [Regex]::Escape($_.Value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'Object[]' {
|
||||||
|
$newentity = $entity | ForEach-Object { ,(substitute $_ $params $regexEscape) }
|
||||||
|
}
|
||||||
|
'PSCustomObject' {
|
||||||
|
$newentity.PSObject.Properties | ForEach-Object { $_.Value = substitute $_.Value $params $regexEscape }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $entity
|
|
||||||
}
|
}
|
||||||
|
return $newentity
|
||||||
}
|
}
|
||||||
|
|
||||||
function format_hash([String] $hash) {
|
function format_hash([String] $hash) {
|
||||||
@@ -893,6 +1008,10 @@ function get_hash([String] $multihash) {
|
|||||||
return $type, $hash.ToLower()
|
return $type, $hash.ToLower()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-GitHubToken {
|
||||||
|
return $env:SCOOP_GH_TOKEN, (get_config 'gh_token') | Where-Object -Property Length -Value 0 -GT | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
function handle_special_urls($url)
|
function handle_special_urls($url)
|
||||||
{
|
{
|
||||||
# FossHub.com
|
# FossHub.com
|
||||||
@@ -900,6 +1019,7 @@ function handle_special_urls($url)
|
|||||||
$Body = @{
|
$Body = @{
|
||||||
projectUri = $Matches.name;
|
projectUri = $Matches.name;
|
||||||
fileName = $Matches.filename;
|
fileName = $Matches.filename;
|
||||||
|
source = 'CF';
|
||||||
isLatestVersion = $true
|
isLatestVersion = $true
|
||||||
}
|
}
|
||||||
if ((Invoke-RestMethod -Uri $url) -match '"p":"(?<pid>[a-f0-9]{24}).*?"r":"(?<rid>[a-f0-9]{24})') {
|
if ((Invoke-RestMethod -Uri $url) -match '"p":"(?<pid>[a-f0-9]{24}).*?"r":"(?<rid>[a-f0-9]{24})') {
|
||||||
@@ -917,6 +1037,18 @@ function handle_special_urls($url)
|
|||||||
# Reshapes the URL to avoid redirections
|
# Reshapes the URL to avoid redirections
|
||||||
$url = "https://downloads.sourceforge.net/project/$($matches['project'])/$($matches['file'])"
|
$url = "https://downloads.sourceforge.net/project/$($matches['project'])/$($matches['file'])"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Github.com
|
||||||
|
if ($url -match 'github.com/(?<owner>[^/]+)/(?<repo>[^/]+)/releases/download/(?<tag>[^/]+)/(?<file>[^/#]+)(?<filename>.*)' -and ($token = Get-GitHubToken)) {
|
||||||
|
$headers = @{ "Authorization" = "token $token" }
|
||||||
|
$privateUrl = "https://api.github.com/repos/$($Matches.owner)/$($Matches.repo)"
|
||||||
|
$assetUrl = "https://api.github.com/repos/$($Matches.owner)/$($Matches.repo)/releases/tags/$($Matches.tag)"
|
||||||
|
|
||||||
|
if ((Invoke-RestMethod -Uri $privateUrl -Headers $headers).Private) {
|
||||||
|
$url = ((Invoke-RestMethod -Uri $assetUrl -Headers $headers).Assets | Where-Object -Property Name -EQ -Value $Matches.file).Url, $Matches.filename -join ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $url
|
return $url
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,6 +1074,33 @@ function get_magic_bytes_pretty($file, $glue = ' ') {
|
|||||||
return (get_magic_bytes $file | ForEach-Object { $_.ToString('x2') }) -join $glue
|
return (get_magic_bytes $file | ForEach-Object { $_.ToString('x2') }) -join $glue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Out-UTF8File {
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $True, Position = 0)]
|
||||||
|
[Alias("Path")]
|
||||||
|
[String] $FilePath,
|
||||||
|
[Switch] $Append,
|
||||||
|
[Switch] $NoNewLine,
|
||||||
|
[Parameter(ValueFromPipeline = $True)]
|
||||||
|
[PSObject] $InputObject
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
if ($Append) {
|
||||||
|
[System.IO.File]::AppendAllText($FilePath, $InputObject)
|
||||||
|
} else {
|
||||||
|
if (!$NoNewLine) {
|
||||||
|
# Ref: https://stackoverflow.com/questions/5596982
|
||||||
|
# Performance Note: `WriteAllLines` throttles memory usage while
|
||||||
|
# `WriteAllText` needs to keep the complete string in memory.
|
||||||
|
[System.IO.File]::WriteAllLines($FilePath, $InputObject)
|
||||||
|
} else {
|
||||||
|
# However `WriteAllText` does not add ending newline.
|
||||||
|
[System.IO.File]::WriteAllText($FilePath, $InputObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Core Bootstrap #
|
# Core Bootstrap #
|
||||||
##################
|
##################
|
||||||
|
|||||||
@@ -1,40 +1,3 @@
|
|||||||
function Test-7zipRequirement {
|
|
||||||
[CmdletBinding(DefaultParameterSetName = "URL")]
|
|
||||||
[OutputType([Boolean])]
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "URL")]
|
|
||||||
[String[]]
|
|
||||||
$URL,
|
|
||||||
[Parameter(Mandatory = $true, ParameterSetName = "File")]
|
|
||||||
[String]
|
|
||||||
$File
|
|
||||||
)
|
|
||||||
if ($URL) {
|
|
||||||
if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) {
|
|
||||||
return $false
|
|
||||||
} 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))$'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Test-LessmsiRequirement {
|
|
||||||
[CmdletBinding()]
|
|
||||||
[OutputType([Boolean])]
|
|
||||||
param (
|
|
||||||
[Parameter(Mandatory = $true)]
|
|
||||||
[String[]]
|
|
||||||
$URL
|
|
||||||
)
|
|
||||||
if ((get_config MSIEXTRACT_USE_LESSMSI)) {
|
|
||||||
return ($URL | Where-Object { $_ -match '\.msi$' }).Count -gt 0
|
|
||||||
} else {
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Expand-7zipArchive {
|
function Expand-7zipArchive {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
@@ -49,7 +12,7 @@ function Expand-7zipArchive {
|
|||||||
[Parameter(ValueFromRemainingArguments = $true)]
|
[Parameter(ValueFromRemainingArguments = $true)]
|
||||||
[String]
|
[String]
|
||||||
$Switches,
|
$Switches,
|
||||||
[ValidateSet("All", "Skip", "Rename")]
|
[ValidateSet('All', 'Skip', 'Rename')]
|
||||||
[String]
|
[String]
|
||||||
$Overwrite,
|
$Overwrite,
|
||||||
[Switch]
|
[Switch]
|
||||||
@@ -57,9 +20,9 @@ function Expand-7zipArchive {
|
|||||||
)
|
)
|
||||||
if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) {
|
if ((get_config 7ZIPEXTRACT_USE_EXTERNAL)) {
|
||||||
try {
|
try {
|
||||||
$7zPath = (Get-Command '7z' -CommandType Application | Select-Object -First 1).Source
|
$7zPath = (Get-Command '7z' -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source
|
||||||
} catch [System.Management.Automation.CommandNotFoundException] {
|
} 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 "`nCannot 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 {
|
} else {
|
||||||
$7zPath = Get-HelperPath -Helper 7zip
|
$7zPath = Get-HelperPath -Helper 7zip
|
||||||
@@ -74,9 +37,9 @@ function Expand-7zipArchive {
|
|||||||
$ArgList += (-split $Switches)
|
$ArgList += (-split $Switches)
|
||||||
}
|
}
|
||||||
switch ($Overwrite) {
|
switch ($Overwrite) {
|
||||||
"All" { $ArgList += "-aoa" }
|
'All' { $ArgList += '-aoa' }
|
||||||
"Skip" { $ArgList += "-aos" }
|
'Skip' { $ArgList += '-aos' }
|
||||||
"Rename" { $ArgList += "-aou" }
|
'Rename' { $ArgList += '-aou' }
|
||||||
}
|
}
|
||||||
$Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath
|
$Status = Invoke-ExternalCommand $7zPath $ArgList -LogPath $LogPath
|
||||||
if (!$Status) {
|
if (!$Status) {
|
||||||
@@ -92,7 +55,8 @@ function Expand-7zipArchive {
|
|||||||
# Check for tar
|
# Check for tar
|
||||||
$Status = Invoke-ExternalCommand $7zPath @('l', "`"$Path`"") -LogPath $LogPath
|
$Status = Invoke-ExternalCommand $7zPath @('l', "`"$Path`"") -LogPath $LogPath
|
||||||
if ($Status) {
|
if ($Status) {
|
||||||
$TarFile = (Get-Content -Path $LogPath)[-4] -replace '.{53}(.*)', '$1' # get inner tar file name
|
# get inner tar file name
|
||||||
|
$TarFile = (Select-String -Path $LogPath -Pattern '[^ ]*tar$').Matches.Value
|
||||||
Expand-7zipArchive -Path "$DestinationPath\$TarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal
|
Expand-7zipArchive -Path "$DestinationPath\$TarFile" -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal
|
||||||
} else {
|
} else {
|
||||||
abort "Failed to list files in $Path.`nNot a 7-Zip supported archive file."
|
abort "Failed to list files in $Path.`nNot a 7-Zip supported archive file."
|
||||||
@@ -104,6 +68,54 @@ function Expand-7zipArchive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Expand-ZstdArchive {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[String]
|
||||||
|
$Path,
|
||||||
|
[Parameter(Position = 1)]
|
||||||
|
[String]
|
||||||
|
$DestinationPath = (Split-Path $Path),
|
||||||
|
[String]
|
||||||
|
$ExtractDir,
|
||||||
|
[Parameter(ValueFromRemainingArguments = $true)]
|
||||||
|
[String]
|
||||||
|
$Switches,
|
||||||
|
[Switch]
|
||||||
|
$Removal
|
||||||
|
)
|
||||||
|
$ZstdPath = Get-HelperPath -Helper Zstd
|
||||||
|
$LogPath = Join-Path (Split-Path $Path) 'zstd.log'
|
||||||
|
$DestinationPath = $DestinationPath.TrimEnd('\')
|
||||||
|
ensure $DestinationPath | Out-Null
|
||||||
|
$ArgList = @('-d', "`"$Path`"", '--output-dir-flat', "`"$DestinationPath`"", '-f', '-v')
|
||||||
|
|
||||||
|
if ($Switches) {
|
||||||
|
$ArgList += (-split $Switches)
|
||||||
|
}
|
||||||
|
if ($Removal) {
|
||||||
|
# Remove original archive file
|
||||||
|
$ArgList += '--rm'
|
||||||
|
}
|
||||||
|
$Status = Invoke-ExternalCommand $ZstdPath $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')"
|
||||||
|
}
|
||||||
|
$IsTar = (strip_ext $Path) -match '\.tar$'
|
||||||
|
if (!$IsTar -and $ExtractDir) {
|
||||||
|
movedir (Join-Path $DestinationPath $ExtractDir) $DestinationPath | Out-Null
|
||||||
|
}
|
||||||
|
if (Test-Path $LogPath) {
|
||||||
|
Remove-Item $LogPath -Force
|
||||||
|
}
|
||||||
|
if ($IsTar) {
|
||||||
|
# Check for tar
|
||||||
|
$TarFile = Join-Path $DestinationPath (strip_ext (fname $Path))
|
||||||
|
Expand-7zipArchive -Path $TarFile -DestinationPath $DestinationPath -ExtractDir $ExtractDir -Removal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Expand-MsiArchive {
|
function Expand-MsiArchive {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param (
|
param (
|
||||||
@@ -121,7 +133,7 @@ function Expand-MsiArchive {
|
|||||||
[Switch]
|
[Switch]
|
||||||
$Removal
|
$Removal
|
||||||
)
|
)
|
||||||
$DestinationPath = $DestinationPath.TrimEnd("\")
|
$DestinationPath = $DestinationPath.TrimEnd('\')
|
||||||
if ($ExtractDir) {
|
if ($ExtractDir) {
|
||||||
$OriDestinationPath = $DestinationPath
|
$OriDestinationPath = $DestinationPath
|
||||||
$DestinationPath = "$DestinationPath\_tmp"
|
$DestinationPath = "$DestinationPath\_tmp"
|
||||||
@@ -182,9 +194,9 @@ function Expand-InnoArchive {
|
|||||||
$LogPath = "$(Split-Path $Path)\innounp.log"
|
$LogPath = "$(Split-Path $Path)\innounp.log"
|
||||||
$ArgList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y')
|
$ArgList = @('-x', "-d`"$DestinationPath`"", "`"$Path`"", '-y')
|
||||||
switch -Regex ($ExtractDir) {
|
switch -Regex ($ExtractDir) {
|
||||||
"^[^{].*" { $ArgList += "-c{app}\$ExtractDir" }
|
'^[^{].*' { $ArgList += "-c{app}\$ExtractDir" }
|
||||||
"^{.*" { $ArgList += "-c$ExtractDir" }
|
'^{.*' { $ArgList += "-c$ExtractDir" }
|
||||||
Default { $ArgList += "-c{app}" }
|
Default { $ArgList += '-c{app}' }
|
||||||
}
|
}
|
||||||
if ($Switches) {
|
if ($Switches) {
|
||||||
$ArgList += (-split $Switches)
|
$ArgList += (-split $Switches)
|
||||||
@@ -220,34 +232,7 @@ function Expand-ZipArchive {
|
|||||||
$OriDestinationPath = $DestinationPath
|
$OriDestinationPath = $DestinationPath
|
||||||
$DestinationPath = "$DestinationPath\_tmp"
|
$DestinationPath = "$DestinationPath\_tmp"
|
||||||
}
|
}
|
||||||
# All methods to unzip the file require .NET4.5+
|
Expand-Archive -Path $Path -DestinationPath $DestinationPath -Force
|
||||||
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
|
|
||||||
}
|
|
||||||
if ($ExtractDir) {
|
if ($ExtractDir) {
|
||||||
movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null
|
movedir "$DestinationPath\$ExtractDir" $OriDestinationPath | Out-Null
|
||||||
Remove-Item $DestinationPath -Recurse -Force
|
Remove-Item $DestinationPath -Recurse -Force
|
||||||
@@ -290,23 +275,3 @@ function Expand-DarkArchive {
|
|||||||
Remove-Item $Path -Force
|
Remove-Item $Path -Force
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function extract_7zip($path, $to, $removal) {
|
|
||||||
Show-DeprecatedWarning $MyInvocation 'Expand-7zipArchive'
|
|
||||||
Expand-7zipArchive -Path $path -DestinationPath $to -Removal:$removal @args
|
|
||||||
}
|
|
||||||
|
|
||||||
function extract_msi($path, $to, $removal) {
|
|
||||||
Show-DeprecatedWarning $MyInvocation 'Expand-MsiArchive'
|
|
||||||
Expand-MsiArchive -Path $path -DestinationPath $to -Removal:$removal
|
|
||||||
}
|
|
||||||
|
|
||||||
function unpack_inno($path, $to, $removal) {
|
|
||||||
Show-DeprecatedWarning $MyInvocation 'Expand-InnoArchive'
|
|
||||||
Expand-InnoArchive -Path $path -DestinationPath $to -Removal:$removal @args
|
|
||||||
}
|
|
||||||
|
|
||||||
function extract_zip($path, $to, $removal) {
|
|
||||||
Show-DeprecatedWarning $MyInvocation 'Expand-ZipArchive'
|
|
||||||
Expand-ZipArchive -Path $path -DestinationPath $to -Removal:$removal
|
|
||||||
}
|
|
||||||
|
|||||||
246
lib/depends.ps1
246
lib/depends.ps1
@@ -1,98 +1,170 @@
|
|||||||
# resolve dependencies for the supplied apps, and sort into the correct order
|
function Get-Dependency {
|
||||||
function install_order($apps, $arch) {
|
<#
|
||||||
$res = @()
|
.SYNOPSIS
|
||||||
foreach ($app in $apps) {
|
Get app's dependencies (with apps attached at the end).
|
||||||
foreach ($dep in deps $app $arch) {
|
.PARAMETER AppName
|
||||||
if ($res -notcontains $dep) { $res += $dep}
|
App's name
|
||||||
}
|
.PARAMETER Architecture
|
||||||
if ($res -notcontains $app) { $res += $app }
|
App's architecture
|
||||||
}
|
.PARAMETER Resolved
|
||||||
return $res
|
List of resolved dependencies (internal use)
|
||||||
}
|
.PARAMETER Unresolved
|
||||||
|
List of unresolved dependencies (internal use)
|
||||||
|
.OUTPUTS
|
||||||
|
[Object[]]
|
||||||
|
List of app's dependencies
|
||||||
|
.NOTES
|
||||||
|
When pipeline input is used, the output will have duplicate items, and should be filtered by 'Select-Object -Unique'.
|
||||||
|
ALgorithm: http://www.electricmonk.nl/docs/dependency_resolving_algorithm/dependency_resolving_algorithm.html
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Object[]])]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[PSObject]
|
||||||
|
$AppName,
|
||||||
|
[Parameter(Mandatory = $true, Position = 1)]
|
||||||
|
[String]
|
||||||
|
$Architecture,
|
||||||
|
[String[]]
|
||||||
|
$Resolved = @(),
|
||||||
|
[String[]]
|
||||||
|
$Unresolved = @()
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$AppName, $bucket, $null = parse_app $AppName
|
||||||
|
$Unresolved += $AppName
|
||||||
|
$null, $manifest, $null, $null = Find-Manifest $AppName $bucket
|
||||||
|
|
||||||
# http://www.electricmonk.nl/docs/dependency_resolving_algorithm/dependency_resolving_algorithm.html
|
if (!$manifest) {
|
||||||
function deps($app, $arch) {
|
if (((Get-LocalBucket) -notcontains $bucket) -and $bucket) {
|
||||||
$resolved = new-object collections.arraylist
|
warn "Bucket '$bucket' not installed. Add it with 'scoop bucket add $bucket' or 'scoop bucket add $bucket <repo>'."
|
||||||
dep_resolve $app $arch $resolved @()
|
|
||||||
|
|
||||||
if ($resolved.count -eq 1) { return @() } # no dependencies
|
|
||||||
return $resolved[0..($resolved.count - 2)]
|
|
||||||
}
|
|
||||||
|
|
||||||
function dep_resolve($app, $arch, $resolved, $unresolved) {
|
|
||||||
$app, $bucket, $null = parse_app $app
|
|
||||||
$unresolved += $app
|
|
||||||
$null, $manifest, $null, $null = Find-Manifest $app $bucket
|
|
||||||
|
|
||||||
if(!$manifest) {
|
|
||||||
if(((Get-LocalBucket) -notcontains $bucket) -and $bucket) {
|
|
||||||
warn "Bucket '$bucket' not installed. Add it with 'scoop bucket add $bucket' or 'scoop bucket add $bucket <repo>'."
|
|
||||||
}
|
|
||||||
abort "Couldn't find manifest for '$app'$(if(!$bucket) { '.' } else { " from '$bucket' bucket." })"
|
|
||||||
}
|
|
||||||
|
|
||||||
$deps = @(install_deps $manifest $arch) + @(runtime_deps $manifest) | Select-Object -Unique
|
|
||||||
|
|
||||||
foreach ($dep in $deps) {
|
|
||||||
if ($resolved -notcontains $dep) {
|
|
||||||
if ($unresolved -contains $dep) {
|
|
||||||
abort "Circular dependency detected: '$app' -> '$dep'."
|
|
||||||
}
|
}
|
||||||
dep_resolve $dep $arch $resolved $unresolved
|
abort "Couldn't find manifest for '$AppName'$(if(!$bucket) { '.' } else { " from '$bucket' bucket." })"
|
||||||
|
}
|
||||||
|
|
||||||
|
$deps = @(Get-InstallationHelper $manifest $Architecture) + @($manifest.depends) | Select-Object -Unique
|
||||||
|
|
||||||
|
foreach ($dep in $deps) {
|
||||||
|
if ($Resolved -notcontains $dep) {
|
||||||
|
if ($Unresolved -contains $dep) {
|
||||||
|
abort "Circular dependency detected: '$AppName' -> '$dep'."
|
||||||
|
}
|
||||||
|
$Resolved, $Unresolved = Get-Dependency $dep $Architecture -Resolved $Resolved -Unresolved $Unresolved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Unresolved = $Unresolved -ne $AppName
|
||||||
|
if ($bucket) {
|
||||||
|
$Resolved += "$bucket/$AppName"
|
||||||
|
} else {
|
||||||
|
$Resolved += $AppName
|
||||||
|
}
|
||||||
|
if ($Unresolved.Length -eq 0) {
|
||||||
|
return $Resolved
|
||||||
|
} else {
|
||||||
|
return $Resolved, $Unresolved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$resolved.add($app) | Out-Null
|
|
||||||
$unresolved = $unresolved -ne $app # remove from unresolved
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runtime_deps($manifest) {
|
function Get-InstallationHelper {
|
||||||
if ($manifest.depends) { return $manifest.depends }
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Get helpers that used in installation
|
||||||
|
.PARAMETER Manifest
|
||||||
|
App's manifest
|
||||||
|
.PARAMETER Architecture
|
||||||
|
Architecture of the app
|
||||||
|
.PARAMETER All
|
||||||
|
If true, return all helpers, otherwise return only helpers that are not already installed
|
||||||
|
.OUTPUTS
|
||||||
|
[Object[]]
|
||||||
|
List of helpers
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
[OutputType([Object[]])]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[PSObject]
|
||||||
|
$Manifest,
|
||||||
|
[Parameter(Mandatory = $true, Position = 1)]
|
||||||
|
[String]
|
||||||
|
$Architecture,
|
||||||
|
[Switch]
|
||||||
|
$All
|
||||||
|
)
|
||||||
|
begin {
|
||||||
|
$helper = @()
|
||||||
|
}
|
||||||
|
process {
|
||||||
|
$url = arch_specific 'url' $Manifest $Architecture
|
||||||
|
$pre_install = arch_specific 'pre_install' $Manifest $Architecture
|
||||||
|
$installer = arch_specific 'installer' $Manifest $Architecture
|
||||||
|
$post_install = arch_specific 'post_install' $Manifest $Architecture
|
||||||
|
$script = $pre_install + $installer.script + $post_install
|
||||||
|
if (((Test-7zipRequirement -Uri $url) -or ($script -like '*Expand-7zipArchive *')) -and !(get_config 7ZIPEXTRACT_USE_EXTERNAL)) {
|
||||||
|
$helper += '7zip'
|
||||||
|
}
|
||||||
|
if (((Test-LessmsiRequirement -Uri $url) -or ($script -like '*Expand-MsiArchive *')) -and (get_config MSIEXTRACT_USE_LESSMSI)) {
|
||||||
|
$helper += 'lessmsi'
|
||||||
|
}
|
||||||
|
if ($Manifest.innosetup -or ($script -like '*Expand-InnoArchive *')) {
|
||||||
|
$helper += 'innounp'
|
||||||
|
}
|
||||||
|
if ($script -like '*Expand-DarkArchive *') {
|
||||||
|
$helper += 'dark'
|
||||||
|
}
|
||||||
|
if ((Test-ZstdRequirement -Uri $url) -or ($script -like '*Expand-ZstdArchive *')) {
|
||||||
|
$helper += 'zstd'
|
||||||
|
}
|
||||||
|
if (!$All) {
|
||||||
|
'7zip', 'lessmsi', 'innounp', 'dark', 'zstd' | ForEach-Object {
|
||||||
|
if (Test-HelperInstalled -Helper $_) {
|
||||||
|
$helper = $helper -ne $_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end {
|
||||||
|
return $helper
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function script_deps($script) {
|
function Test-7zipRequirement {
|
||||||
$deps = @()
|
[CmdletBinding()]
|
||||||
if($script -is [Array]) {
|
[OutputType([Boolean])]
|
||||||
$script = $script -join "`n"
|
param (
|
||||||
}
|
[Parameter(Mandatory = $true)]
|
||||||
if([String]::IsNullOrEmpty($script)) {
|
[AllowNull()]
|
||||||
return $deps
|
[String[]]
|
||||||
}
|
$Uri
|
||||||
|
)
|
||||||
if($script -like '*Expand-7zipArchive *' -or $script -like '*extract_7zip *') {
|
return ($Uri | Where-Object {
|
||||||
$deps += '7zip'
|
$_ -match '\.((gz)|(tar)|(t[abgpx]z2?)|(lzma)|(bz2?)|(7z)|(rar)|(iso)|(xz)|(lzh)|(nupkg))(\.[^.]+)?$'
|
||||||
}
|
}).Count -gt 0
|
||||||
if($script -like '*Expand-MsiArchive *' -or $script -like '*extract_msi *') {
|
|
||||||
$deps += 'lessmsi'
|
|
||||||
}
|
|
||||||
if($script -like '*Expand-InnoArchive *' -or $script -like '*unpack_inno *') {
|
|
||||||
$deps += 'innounp'
|
|
||||||
}
|
|
||||||
if($script -like '*Expand-DarkArchive *') {
|
|
||||||
$deps += 'dark'
|
|
||||||
}
|
|
||||||
|
|
||||||
return $deps
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_deps($manifest, $arch) {
|
function Test-ZstdRequirement {
|
||||||
$deps = @()
|
[CmdletBinding()]
|
||||||
|
[OutputType([Boolean])]
|
||||||
if (!(Test-HelperInstalled -Helper 7zip) -and (Test-7zipRequirement -URL (url $manifest $arch))) {
|
param (
|
||||||
$deps += '7zip'
|
[Parameter(Mandatory = $true)]
|
||||||
}
|
[AllowNull()]
|
||||||
if (!(Test-HelperInstalled -Helper Lessmsi) -and (Test-LessmsiRequirement -URL (url $manifest $arch))) {
|
[String[]]
|
||||||
$deps += 'lessmsi'
|
$Uri
|
||||||
}
|
)
|
||||||
if (!(Test-HelperInstalled -Helper Innounp) -and $manifest.innosetup) {
|
return ($Uri | Where-Object { $_ -match '\.zst$' }).Count -gt 0
|
||||||
$deps += 'innounp'
|
}
|
||||||
}
|
|
||||||
|
function Test-LessmsiRequirement {
|
||||||
$pre_install = arch_specific 'pre_install' $manifest $arch
|
[CmdletBinding()]
|
||||||
$installer = arch_specific 'installer' $manifest $arch
|
[OutputType([Boolean])]
|
||||||
$post_install = arch_specific 'post_install' $manifest $arch
|
param (
|
||||||
$deps += script_deps $pre_install
|
[Parameter(Mandatory = $true)]
|
||||||
$deps += script_deps $installer.script
|
[AllowNull()]
|
||||||
$deps += script_deps $post_install
|
[String[]]
|
||||||
|
$Uri
|
||||||
return $deps | Select-Object -Unique
|
)
|
||||||
|
return ($Uri | Where-Object { $_ -match '\.msi$' }).Count -gt 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,22 +3,21 @@ Diagnostic tests.
|
|||||||
Return $true if the test passed, otherwise $false.
|
Return $true if the test passed, otherwise $false.
|
||||||
Use 'warn' to highlight the issue, and follow up with the recommended actions to rectify.
|
Use 'warn' to highlight the issue, and follow up with the recommended actions to rectify.
|
||||||
#>
|
#>
|
||||||
. "$PSScriptRoot\buckets.ps1"
|
|
||||||
|
|
||||||
function check_windows_defender($global) {
|
function check_windows_defender($global) {
|
||||||
$defender = get-service -name WinDefend -errorAction SilentlyContinue
|
$defender = Get-Service -Name WinDefend -ErrorAction SilentlyContinue
|
||||||
if($defender -and $defender.status) {
|
if (Test-CommandAvailable Get-MpPreference) {
|
||||||
if($defender.status -eq [system.serviceprocess.servicecontrollerstatus]::running) {
|
if ((Get-MpPreference).DisableRealtimeMonitoring) { return $true }
|
||||||
if (Test-CommandAvailable Get-MpPreference) {
|
if ($defender -and $defender.Status) {
|
||||||
|
if ($defender.Status -eq [System.ServiceProcess.ServiceControllerStatus]::Running) {
|
||||||
$installPath = $scoopdir;
|
$installPath = $scoopdir;
|
||||||
if($global) { $installPath = $globaldir; }
|
if ($global) { $installPath = $globaldir; }
|
||||||
|
|
||||||
$exclusionPath = (Get-MpPreference).exclusionPath
|
$exclusionPath = (Get-MpPreference).ExclusionPath
|
||||||
if(!($exclusionPath -contains $installPath)) {
|
if (!($exclusionPath -contains $installPath)) {
|
||||||
warn "Windows Defender may slow down or disrupt installs with realtime scanning."
|
info "Windows Defender may slow down or disrupt installs with realtime scanning."
|
||||||
write-host " Consider running:"
|
Write-Host " Consider running:"
|
||||||
write-host " sudo Add-MpPreference -ExclusionPath '$installPath'"
|
Write-Host " sudo Add-MpPreference -ExclusionPath '$installPath'"
|
||||||
write-host " (Requires 'sudo' command. Run 'scoop install sudo' if you don't have it.)"
|
Write-Host " (Requires 'sudo' command. Run 'scoop install sudo' if you don't have it.)"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +27,7 @@ function check_windows_defender($global) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function check_main_bucket {
|
function check_main_bucket {
|
||||||
if ((Get-LocalBucket) -notcontains 'main'){
|
if ((Get-LocalBucket) -notcontains 'main') {
|
||||||
warn 'Main bucket is not added.'
|
warn 'Main bucket is not added.'
|
||||||
Write-Host " run 'scoop bucket add main'"
|
Write-Host " run 'scoop bucket add main'"
|
||||||
|
|
||||||
@@ -39,12 +38,16 @@ function check_main_bucket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function check_long_paths {
|
function check_long_paths {
|
||||||
|
if ([System.Environment]::OSVersion.Version.Major -lt 10 -or [System.Environment]::OSVersion.Version.Build -lt 1607) {
|
||||||
|
warn 'This version of Windows does not support configuration of LongPaths.'
|
||||||
|
return $false
|
||||||
|
}
|
||||||
$key = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -ErrorAction SilentlyContinue -Name 'LongPathsEnabled'
|
$key = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -ErrorAction SilentlyContinue -Name 'LongPathsEnabled'
|
||||||
if (!$key -or ($key.LongPathsEnabled -eq 0)) {
|
if (!$key -or ($key.LongPathsEnabled -eq 0)) {
|
||||||
warn 'LongPaths support is not enabled.'
|
warn 'LongPaths support is not enabled.'
|
||||||
Write-Host "You can enable it with running:"
|
Write-Host " You can enable it by running:"
|
||||||
Write-Host " Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1"
|
Write-Host " sudo Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1"
|
||||||
|
Write-Host " (Requires 'sudo' command. Run 'scoop install sudo' if you don't have it.)"
|
||||||
return $false
|
return $false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
lib/git.ps1
52
lib/git.ps1
@@ -1,52 +0,0 @@
|
|||||||
function git_proxy_cmd {
|
|
||||||
$proxy = get_config 'proxy'
|
|
||||||
$cmd = "git $($args | ForEach-Object { "$_ " })"
|
|
||||||
if($proxy -and $proxy -ne 'none') {
|
|
||||||
$cmd = "SET HTTPS_PROXY=$proxy&&SET HTTP_PROXY=$proxy&&$cmd"
|
|
||||||
}
|
|
||||||
& "$env:COMSPEC" /c $cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_clone {
|
|
||||||
git_proxy_cmd clone $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_ls_remote {
|
|
||||||
git_proxy_cmd ls-remote $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_checkout {
|
|
||||||
git_proxy_cmd checkout $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_branch {
|
|
||||||
git_proxy_cmd branch $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_pull {
|
|
||||||
git_proxy_cmd pull $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_fetch {
|
|
||||||
git_proxy_cmd fetch $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_log {
|
|
||||||
git_proxy_cmd --no-pager log $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_checkout {
|
|
||||||
git_proxy_cmd checkout $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_branch {
|
|
||||||
git_proxy_cmd branch $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_config {
|
|
||||||
git_proxy_cmd config $args
|
|
||||||
}
|
|
||||||
|
|
||||||
function git_reset {
|
|
||||||
git_proxy_cmd reset $args
|
|
||||||
}
|
|
||||||
431
lib/install.ps1
431
lib/install.ps1
@@ -1,6 +1,3 @@
|
|||||||
. "$psscriptroot/autoupdate.ps1"
|
|
||||||
. "$psscriptroot/buckets.ps1"
|
|
||||||
|
|
||||||
function nightly_version($date, $quiet = $false) {
|
function nightly_version($date, $quiet = $false) {
|
||||||
$date_str = $date.tostring("yyyyMMdd")
|
$date_str = $date.tostring("yyyyMMdd")
|
||||||
if (!$quiet) {
|
if (!$quiet) {
|
||||||
@@ -34,6 +31,19 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((get_config 'manifest_review' $false) -and ($MyInvocation.ScriptName -notlike '*scoop-update*')) {
|
||||||
|
Write-Host "Manifest: $app.json"
|
||||||
|
$style = get_config cat_style
|
||||||
|
if ($style) {
|
||||||
|
$manifest | ConvertToPrettyJson | bat --no-paging --style $style --language json
|
||||||
|
} else {
|
||||||
|
$manifest | ConvertToPrettyJson
|
||||||
|
}
|
||||||
|
$answer = Read-Host -Prompt "Continue installation? [Y/n]"
|
||||||
|
if (($answer -eq 'n') -or ($answer -eq 'N')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
write-output "Installing '$app' ($version) [$architecture]"
|
write-output "Installing '$app' ($version) [$architecture]"
|
||||||
|
|
||||||
$dir = ensure (versiondir $app $version $global)
|
$dir = ensure (versiondir $app $version $global)
|
||||||
@@ -48,7 +58,6 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru
|
|||||||
create_shims $manifest $dir $global $architecture
|
create_shims $manifest $dir $global $architecture
|
||||||
create_startmenu_shortcuts $manifest $dir $global $architecture
|
create_startmenu_shortcuts $manifest $dir $global $architecture
|
||||||
install_psmodule $manifest $dir $global
|
install_psmodule $manifest $dir $global
|
||||||
if($global) { ensure_scoop_in_path $global } # can assume local scoop is in path
|
|
||||||
env_add_path $manifest $dir $global $architecture
|
env_add_path $manifest $dir $global $architecture
|
||||||
env_set $manifest $dir $global $architecture
|
env_set $manifest $dir $global $architecture
|
||||||
|
|
||||||
@@ -71,38 +80,6 @@ function install_app($app, $architecture, $global, $suggested, $use_cache = $tru
|
|||||||
show_notes $manifest $dir $original_dir $persist_dir
|
show_notes $manifest $dir $original_dir $persist_dir
|
||||||
}
|
}
|
||||||
|
|
||||||
function locate($app, $bucket) {
|
|
||||||
Show-DeprecatedWarning $MyInvocation 'Find-Manifest'
|
|
||||||
return Find-Manifest $app $bucket
|
|
||||||
}
|
|
||||||
|
|
||||||
function Find-Manifest($app, $bucket) {
|
|
||||||
$manifest, $url = $null, $null
|
|
||||||
|
|
||||||
# check if app is a URL or UNC path
|
|
||||||
if($app -match '^(ht|f)tps?://|\\\\') {
|
|
||||||
$url = $app
|
|
||||||
$app = appname_from_url $url
|
|
||||||
$manifest = url_manifest $url
|
|
||||||
} else {
|
|
||||||
# check buckets
|
|
||||||
$manifest, $bucket = find_manifest $app $bucket
|
|
||||||
|
|
||||||
if(!$manifest) {
|
|
||||||
# couldn't find app in buckets: check if it's a local path
|
|
||||||
$path = $app
|
|
||||||
if(!$path.endswith('.json')) { $path += '.json' }
|
|
||||||
if(test-path $path) {
|
|
||||||
$url = "$(resolve-path $path)"
|
|
||||||
$app = appname_from_url $url
|
|
||||||
$manifest, $bucket = url_manifest $url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $app, $manifest, $bucket, $url
|
|
||||||
}
|
|
||||||
|
|
||||||
function dl_with_cache($app, $version, $url, $to, $cookies = $null, $use_cache = $true) {
|
function dl_with_cache($app, $version, $url, $to, $cookies = $null, $use_cache = $true) {
|
||||||
$cached = fullpath (cache_path $app $version $url)
|
$cached = fullpath (cache_path $app $version $url)
|
||||||
|
|
||||||
@@ -200,12 +177,12 @@ function get_filename_from_metalink($file) {
|
|||||||
|
|
||||||
function dl_with_cache_aria2($app, $version, $manifest, $architecture, $dir, $cookies = $null, $use_cache = $true, $check_hash = $true) {
|
function dl_with_cache_aria2($app, $version, $manifest, $architecture, $dir, $cookies = $null, $use_cache = $true, $check_hash = $true) {
|
||||||
$data = @{}
|
$data = @{}
|
||||||
$urls = @(url $manifest $architecture)
|
$urls = @(script:url $manifest $architecture)
|
||||||
|
|
||||||
# aria2 input file
|
# aria2 input file
|
||||||
$urlstxt = Join-Path $cachedir "$app.txt"
|
$urlstxt = Join-Path $cachedir "$app.txt"
|
||||||
$urlstxt_content = ''
|
$urlstxt_content = ''
|
||||||
$has_downloads = $false
|
$download_finished = $true
|
||||||
|
|
||||||
# aria2 options
|
# aria2 options
|
||||||
$options = @(
|
$options = @(
|
||||||
@@ -225,127 +202,149 @@ function dl_with_cache_aria2($app, $version, $manifest, $architecture, $dir, $co
|
|||||||
"--min-tls-version=TLSv1.2"
|
"--min-tls-version=TLSv1.2"
|
||||||
"--stop-with-process=$PID"
|
"--stop-with-process=$PID"
|
||||||
"--continue"
|
"--continue"
|
||||||
|
"--summary-interval=0"
|
||||||
|
"--auto-save-interval=1"
|
||||||
)
|
)
|
||||||
|
|
||||||
if($cookies) {
|
if ($cookies) {
|
||||||
$options += "--header='Cookie: $(cookie_header $cookies)'"
|
$options += "--header='Cookie: $(cookie_header $cookies)'"
|
||||||
}
|
}
|
||||||
|
|
||||||
$proxy = get_config 'proxy'
|
$proxy = get_config 'proxy'
|
||||||
if($proxy -ne 'none') {
|
if ($proxy -ne 'none') {
|
||||||
if([Net.Webrequest]::DefaultWebProxy.Address) {
|
if ([Net.Webrequest]::DefaultWebProxy.Address) {
|
||||||
$options += "--all-proxy='$([Net.Webrequest]::DefaultWebProxy.Address.Authority)'"
|
$options += "--all-proxy='$([Net.Webrequest]::DefaultWebProxy.Address.Authority)'"
|
||||||
}
|
}
|
||||||
if([Net.Webrequest]::DefaultWebProxy.Credentials.UserName) {
|
if ([Net.Webrequest]::DefaultWebProxy.Credentials.UserName) {
|
||||||
$options += "--all-proxy-user='$([Net.Webrequest]::DefaultWebProxy.Credentials.UserName)'"
|
$options += "--all-proxy-user='$([Net.Webrequest]::DefaultWebProxy.Credentials.UserName)'"
|
||||||
}
|
}
|
||||||
if([Net.Webrequest]::DefaultWebProxy.Credentials.Password) {
|
if ([Net.Webrequest]::DefaultWebProxy.Credentials.Password) {
|
||||||
$options += "--all-proxy-passwd='$([Net.Webrequest]::DefaultWebProxy.Credentials.Password)'"
|
$options += "--all-proxy-passwd='$([Net.Webrequest]::DefaultWebProxy.Credentials.Password)'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$more_options = get_config 'aria2-options'
|
$more_options = get_config 'aria2-options'
|
||||||
if($more_options) {
|
if ($more_options) {
|
||||||
$options += $more_options
|
$options += $more_options
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($url in $urls) {
|
foreach ($url in $urls) {
|
||||||
$data.$url = @{
|
$data.$url = @{
|
||||||
'filename' = url_filename $url
|
'target' = "$dir\$(url_filename $url)"
|
||||||
'target' = "$dir\$(url_filename $url)"
|
|
||||||
'cachename' = fname (cache_path $app $version $url)
|
'cachename' = fname (cache_path $app $version $url)
|
||||||
'source' = fullpath (cache_path $app $version $url)
|
'source' = fullpath (cache_path $app $version $url)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!(test-path $data.$url.source)) {
|
if ((Test-Path $data.$url.source) -and -not((Test-Path "$($data.$url.source).aria2") -or (Test-Path $urlstxt)) -and $use_cache) {
|
||||||
$has_downloads = $true
|
Write-Host 'Loading ' -NoNewline
|
||||||
|
Write-Host $(url_remote_filename $url) -f Cyan -NoNewline
|
||||||
|
Write-Host ' from cache.'
|
||||||
|
} else {
|
||||||
|
$download_finished = $false
|
||||||
# create aria2 input file content
|
# create aria2 input file content
|
||||||
$urlstxt_content += "$(handle_special_urls $url)`n"
|
$urlstxt_content += "$(handle_special_urls $url)`n"
|
||||||
if(!$url.Contains('sourceforge.net')) {
|
if (!$url.Contains('sourceforge.net')) {
|
||||||
$urlstxt_content += " referer=$(strip_filename $url)`n"
|
$urlstxt_content += " referer=$(strip_filename $url)`n"
|
||||||
}
|
}
|
||||||
$urlstxt_content += " dir=$cachedir`n"
|
$urlstxt_content += " dir=$cachedir`n"
|
||||||
$urlstxt_content += " out=$($data.$url.cachename)`n"
|
$urlstxt_content += " out=$($data.$url.cachename)`n"
|
||||||
} else {
|
|
||||||
Write-Host "Loading " -NoNewline
|
|
||||||
Write-Host $(url_remote_filename $url) -f Cyan -NoNewline
|
|
||||||
Write-Host " from cache."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($has_downloads) {
|
if (-not($download_finished)) {
|
||||||
# write aria2 input file
|
# write aria2 input file
|
||||||
Set-Content -Path $urlstxt $urlstxt_content
|
if ($urlstxt_content -ne '') {
|
||||||
|
ensure $cachedir | Out-Null
|
||||||
|
# Write aria2 input-file with UTF8NoBOM encoding
|
||||||
|
$urlstxt_content | Out-UTF8File -FilePath $urlstxt
|
||||||
|
}
|
||||||
|
|
||||||
# build aria2 command
|
# build aria2 command
|
||||||
$aria2 = "& '$(Get-HelperPath -Helper Aria2)' $($options -join ' ')"
|
$aria2 = "& '$(Get-HelperPath -Helper Aria2)' $($options -join ' ')"
|
||||||
|
|
||||||
# handle aria2 console output
|
# handle aria2 console output
|
||||||
Write-Host "Starting download with aria2 ..."
|
Write-Host 'Starting download with aria2 ...'
|
||||||
$prefix = "Download: "
|
|
||||||
|
# Set console output encoding to UTF8 for non-ASCII characters printing
|
||||||
|
$oriConsoleEncoding = [Console]::OutputEncoding
|
||||||
|
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
|
||||||
|
|
||||||
Invoke-Expression $aria2 | ForEach-Object {
|
Invoke-Expression $aria2 | ForEach-Object {
|
||||||
if([String]::IsNullOrWhiteSpace($_)) {
|
# Skip blank lines
|
||||||
# skip blank lines
|
if ([String]::IsNullOrWhiteSpace($_)) { return }
|
||||||
return
|
|
||||||
}
|
# Prevent potential overlaping of text when one line is shorter
|
||||||
Write-Host $prefix -NoNewline
|
$len = $Host.UI.RawUI.WindowSize.Width - $_.Length - 20
|
||||||
if($_.StartsWith('(OK):')) {
|
$blank = if ($len -gt 0) { ' ' * $len } else { '' }
|
||||||
Write-Host $_ -f Green
|
$color = 'Gray'
|
||||||
} elseif($_.StartsWith('[') -and $_.EndsWith(']')) {
|
|
||||||
Write-Host $_ -f Cyan
|
if ($_.StartsWith('(OK):')) {
|
||||||
} else {
|
$noNewLine = $true
|
||||||
Write-Host $_ -f Gray
|
$color = 'Green'
|
||||||
|
} elseif ($_.StartsWith('[') -and $_.EndsWith(']')) {
|
||||||
|
$noNewLine = $true
|
||||||
|
$color = 'Cyan'
|
||||||
|
} elseif ($_.StartsWith('Download Results:')) {
|
||||||
|
$noNewLine = $false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Write-Host "`rDownload: $_$blank" -ForegroundColor $color -NoNewline:$noNewLine
|
||||||
}
|
}
|
||||||
|
Write-Host ''
|
||||||
|
|
||||||
if($lastexitcode -gt 0) {
|
if($lastexitcode -gt 0) {
|
||||||
error "Download failed! (Error $lastexitcode) $(aria_exit_code $lastexitcode)"
|
error "Download failed! (Error $lastexitcode) $(aria_exit_code $lastexitcode)"
|
||||||
error $urlstxt_content
|
error $urlstxt_content
|
||||||
error $aria2
|
error $aria2
|
||||||
abort $(new_issue_msg $app $bucket "download via aria2 failed")
|
abort $(new_issue_msg $app $bucket 'download via aria2 failed')
|
||||||
}
|
}
|
||||||
|
|
||||||
# remove aria2 input file when done
|
# remove aria2 input file when done
|
||||||
if(test-path($urlstxt)) {
|
if (Test-Path $urlstxt, "$($data.$url.source).aria2*") {
|
||||||
Remove-Item $urlstxt
|
Remove-Item $urlstxt -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item "$($data.$url.source).aria2*" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Revert console encoding
|
||||||
|
[Console]::OutputEncoding = $oriConsoleEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach($url in $urls) {
|
foreach ($url in $urls) {
|
||||||
|
|
||||||
$metalink_filename = get_filename_from_metalink $data.$url.source
|
$metalink_filename = get_filename_from_metalink $data.$url.source
|
||||||
if($metalink_filename) {
|
if ($metalink_filename) {
|
||||||
Remove-Item $data.$url.source -Force
|
Remove-Item $data.$url.source -Force
|
||||||
Rename-Item -Force (Join-Path -Path $cachedir -ChildPath $metalink_filename) $data.$url.source
|
Rename-Item -Force (Join-Path -Path $cachedir -ChildPath $metalink_filename) $data.$url.source
|
||||||
}
|
}
|
||||||
|
|
||||||
# run hash checks
|
# run hash checks
|
||||||
if($check_hash) {
|
if ($check_hash) {
|
||||||
$manifest_hash = hash_for_url $manifest $url $architecture
|
$manifest_hash = hash_for_url $manifest $url $architecture
|
||||||
$ok, $err = check_hash $data.$url.source $manifest_hash $(show_app $app $bucket)
|
$ok, $err = check_hash $data.$url.source $manifest_hash $(show_app $app $bucket)
|
||||||
if(!$ok) {
|
if (!$ok) {
|
||||||
error $err
|
error $err
|
||||||
if(test-path $data.$url.source) {
|
if (Test-Path $data.$url.source) {
|
||||||
# rm cached file
|
# rm cached file
|
||||||
Remove-Item -force $data.$url.source
|
Remove-Item $data.$url.source -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item "$($data.$url.source).aria2*" -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
if($url.Contains('sourceforge.net')) {
|
if ($url.Contains('sourceforge.net')) {
|
||||||
Write-Host -f yellow 'SourceForge.net is known for causing hash validation fails. Please try again before opening a ticket.'
|
Write-Host -f yellow 'SourceForge.net is known for causing hash validation fails. Please try again before opening a ticket.'
|
||||||
}
|
}
|
||||||
abort $(new_issue_msg $app $bucket "hash check failed")
|
abort $(new_issue_msg $app $bucket 'hash check failed')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# copy or move file to target location
|
# copy or move file to target location
|
||||||
if(!(test-path $data.$url.source) ) {
|
if (!(Test-Path $data.$url.source) ) {
|
||||||
abort $(new_issue_msg $app $bucket "cached file not found")
|
abort $(new_issue_msg $app $bucket 'cached file not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!($dir -eq $cachedir)) {
|
if (!($dir -eq $cachedir)) {
|
||||||
if($use_cache) {
|
if ($use_cache) {
|
||||||
Copy-Item $data.$url.source $data.$url.target
|
Copy-Item $data.$url.source $data.$url.target
|
||||||
} else {
|
} else {
|
||||||
Move-Item $data.$url.source $data.$url.target -force
|
Move-Item $data.$url.source $data.$url.target -Force
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,19 +352,63 @@ function dl_with_cache_aria2($app, $version, $manifest, $architecture, $dir, $co
|
|||||||
|
|
||||||
# download with filesize and progress indicator
|
# download with filesize and progress indicator
|
||||||
function dl($url, $to, $cookies, $progress) {
|
function dl($url, $to, $cookies, $progress) {
|
||||||
$reqUrl = ($url -split "#")[0]
|
$reqUrl = ($url -split '#')[0]
|
||||||
$wreq = [net.webrequest]::create($reqUrl)
|
$wreq = [Net.WebRequest]::Create($reqUrl)
|
||||||
if($wreq -is [net.httpwebrequest]) {
|
if ($wreq -is [Net.HttpWebRequest]) {
|
||||||
$wreq.useragent = Get-UserAgent
|
$wreq.UserAgent = Get-UserAgent
|
||||||
if (-not ($url -imatch "sourceforge\.net")) {
|
if (-not ($url -match 'sourceforge\.net' -or $url -match 'portableapps\.com')) {
|
||||||
$wreq.referer = strip_filename $url
|
$wreq.Referer = strip_filename $url
|
||||||
}
|
}
|
||||||
if($cookies) {
|
if ($url -match 'api\.github\.com/repos') {
|
||||||
$wreq.headers.add('Cookie', (cookie_header $cookies))
|
$wreq.Accept = 'application/octet-stream'
|
||||||
|
$wreq.Headers['Authorization'] = "token $(Get-GitHubToken)"
|
||||||
|
}
|
||||||
|
if ($cookies) {
|
||||||
|
$wreq.Headers.Add('Cookie', (cookie_header $cookies))
|
||||||
|
}
|
||||||
|
|
||||||
|
get_config 'private_hosts' | Where-Object { $_ -ne $null -and $url -match $_.match } | ForEach-Object {
|
||||||
|
(ConvertFrom-StringData -StringData $_.Headers).GetEnumerator() | ForEach-Object {
|
||||||
|
$wreq.Headers[$_.Key] = $_.Value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$wres = $wreq.getresponse()
|
try {
|
||||||
|
$wres = $wreq.GetResponse()
|
||||||
|
} catch [System.Net.WebException] {
|
||||||
|
$exc = $_.Exception
|
||||||
|
$handledCodes = @(
|
||||||
|
[System.Net.HttpStatusCode]::MovedPermanently, # HTTP 301
|
||||||
|
[System.Net.HttpStatusCode]::Found, # HTTP 302
|
||||||
|
[System.Net.HttpStatusCode]::SeeOther, # HTTP 303
|
||||||
|
[System.Net.HttpStatusCode]::TemporaryRedirect # HTTP 307
|
||||||
|
)
|
||||||
|
|
||||||
|
# Only handle redirection codes
|
||||||
|
$redirectRes = $exc.Response
|
||||||
|
if ($handledCodes -notcontains $redirectRes.StatusCode) {
|
||||||
|
throw $exc
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the new location of the file
|
||||||
|
if ((-not $redirectRes.Headers) -or ($redirectRes.Headers -notcontains 'Location')) {
|
||||||
|
throw $exc
|
||||||
|
}
|
||||||
|
|
||||||
|
$newUrl = $redirectRes.Headers['Location']
|
||||||
|
info "Following redirect to $newUrl..."
|
||||||
|
|
||||||
|
# Handle manual file rename
|
||||||
|
if ($url -like '*#/*') {
|
||||||
|
$null, $postfix = $url -split '#/'
|
||||||
|
$newUrl = "$newUrl#/$postfix"
|
||||||
|
}
|
||||||
|
|
||||||
|
dl $newUrl $to $cookies $progress
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
$total = $wres.ContentLength
|
$total = $wres.ContentLength
|
||||||
if($total -eq -1 -and $wreq -is [net.ftpwebrequest]) {
|
if($total -eq -1 -and $wreq -is [net.ftpwebrequest]) {
|
||||||
$total = ftp_file_size($url)
|
$total = ftp_file_size($url)
|
||||||
@@ -469,6 +512,7 @@ function dl_progress($read, $total, $url) {
|
|||||||
write-host
|
write-host
|
||||||
$left = 0
|
$left = 0
|
||||||
$top = $top + 1
|
$top = $top + 1
|
||||||
|
if($top -gt $console.CursorPosition.Y) { $top = $console.CursorPosition.Y }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +526,7 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c
|
|||||||
|
|
||||||
# can be multiple urls: if there are, then msi or installer should go last,
|
# can be multiple urls: if there are, then msi or installer should go last,
|
||||||
# so that $fname is set properly
|
# so that $fname is set properly
|
||||||
$urls = @(url $manifest $architecture)
|
$urls = @(script:url $manifest $architecture)
|
||||||
|
|
||||||
# can be multiple cookies: they will be used for all HTTP requests.
|
# can be multiple cookies: they will be used for all HTTP requests.
|
||||||
$cookies = $manifest.cookie
|
$cookies = $manifest.cookie
|
||||||
@@ -552,7 +596,9 @@ function dl_urls($app, $version, $manifest, $bucket, $architecture, $dir, $use_c
|
|||||||
} else {
|
} else {
|
||||||
$extract_fn = 'Expand-MsiArchive'
|
$extract_fn = 'Expand-MsiArchive'
|
||||||
}
|
}
|
||||||
} elseif(Test-7zipRequirement -File $fname) { # 7zip
|
} elseif(Test-ZstdRequirement -Uri $fname) { # Zstd first
|
||||||
|
$extract_fn = 'Expand-ZstdArchive'
|
||||||
|
} elseif(Test-7zipRequirement -Uri $fname) { # 7zip
|
||||||
$extract_fn = 'Expand-7zipArchive'
|
$extract_fn = 'Expand-7zipArchive'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -597,7 +643,7 @@ function hash_for_url($manifest, $url, $arch) {
|
|||||||
|
|
||||||
if($hashes.length -eq 0) { return $null }
|
if($hashes.length -eq 0) { return $null }
|
||||||
|
|
||||||
$urls = @(url $manifest $arch)
|
$urls = @(script:url $manifest $arch)
|
||||||
|
|
||||||
$index = [array]::indexof($urls, $url)
|
$index = [array]::indexof($urls, $url)
|
||||||
if($index -eq -1) { abort "Couldn't find hash in manifest for '$url'." }
|
if($index -eq -1) { abort "Couldn't find hash in manifest for '$url'." }
|
||||||
@@ -819,66 +865,63 @@ function create_shims($manifest, $dir, $global, $arch) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rm_shim($name, $shimdir) {
|
function rm_shim($name, $shimdir, $app) {
|
||||||
$shim = "$shimdir\$name.ps1"
|
'', '.shim', '.cmd', '.ps1' | ForEach-Object {
|
||||||
|
$shimPath = "$shimdir\$name$_"
|
||||||
if(!(test-path $shim)) { # handle no shim from failed install
|
$altShimPath = "$shimPath.$app"
|
||||||
warn "Shim for '$name' is missing. Skipping."
|
if ($app -and (Test-Path -Path $altShimPath -PathType Leaf)) {
|
||||||
} else {
|
Write-Output "Removing shim '$name$_.$app'."
|
||||||
write-output "Removing shim for '$name'."
|
Remove-Item $altShimPath
|
||||||
Remove-Item $shim
|
} elseif (Test-Path -Path $shimPath -PathType Leaf) {
|
||||||
}
|
Write-Output "Removing shim '$name$_'."
|
||||||
|
Remove-Item $shimPath
|
||||||
# other shim types might be present
|
$oldShims = Get-Item -Path "$shimPath.*" -Exclude '*.shim', '*.cmd', '*.ps1'
|
||||||
'', '.exe', '.shim', '.cmd' | ForEach-Object {
|
if ($null -eq $oldShims) {
|
||||||
if(test-path -Path "$shimdir\$name$_" -PathType leaf) {
|
if ($_ -eq '.shim') {
|
||||||
Remove-Item "$shimdir\$name$_"
|
Write-Output "Removing shim '$name.exe'."
|
||||||
|
Remove-Item -Path "$shimdir\$name.exe"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(@($oldShims) | Sort-Object -Property LastWriteTimeUtc)[-1] | Rename-Item -NewName { $_.Name -replace '\.[^.]*$', '' }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function rm_shims($manifest, $global, $arch) {
|
function rm_shims($app, $manifest, $global, $arch) {
|
||||||
$shims = @(arch_specific 'bin' $manifest $arch)
|
$shims = @(arch_specific 'bin' $manifest $arch)
|
||||||
|
|
||||||
$shims | Where-Object { $_ -ne $null } | ForEach-Object {
|
$shims | Where-Object { $_ -ne $null } | ForEach-Object {
|
||||||
$target, $name, $null = shim_def $_
|
$target, $name, $null = shim_def $_
|
||||||
$shimdir = shimdir $global
|
$shimdir = shimdir $global
|
||||||
|
|
||||||
rm_shim $name $shimdir
|
rm_shim $name $shimdir $app
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Gets the path for the 'current' directory junction for
|
|
||||||
# the specified version directory.
|
|
||||||
function current_dir($versiondir) {
|
|
||||||
$parent = split-path $versiondir
|
|
||||||
return "$parent\current"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Creates or updates the directory junction for [app]/current,
|
# Creates or updates the directory junction for [app]/current,
|
||||||
# pointing to the specified version directory for the app.
|
# pointing to the specified version directory for the app.
|
||||||
#
|
#
|
||||||
# Returns the 'current' junction directory if in use, otherwise
|
# Returns the 'current' junction directory if in use, otherwise
|
||||||
# the version directory.
|
# the version directory.
|
||||||
function link_current($versiondir) {
|
function link_current($versiondir) {
|
||||||
if(get_config NO_JUNCTIONS) { return $versiondir }
|
if (get_config NO_JUNCTIONS) { return $versiondir.ToString() }
|
||||||
|
|
||||||
$currentdir = current_dir $versiondir
|
$currentdir = "$(Split-Path $versiondir)\current"
|
||||||
|
|
||||||
write-host "Linking $(friendly_path $currentdir) => $(friendly_path $versiondir)"
|
Write-Host "Linking $(friendly_path $currentdir) => $(friendly_path $versiondir)"
|
||||||
|
|
||||||
if($currentdir -eq $versiondir) {
|
if ($currentdir -eq $versiondir) {
|
||||||
abort "Error: Version 'current' is not allowed!"
|
abort "Error: Version 'current' is not allowed!"
|
||||||
}
|
}
|
||||||
|
|
||||||
if(test-path $currentdir) {
|
if (Test-Path $currentdir) {
|
||||||
# remove the junction
|
# remove the junction
|
||||||
attrib -R /L $currentdir
|
attrib -R /L $currentdir
|
||||||
& "$env:COMSPEC" /c rmdir $currentdir
|
Remove-Item $currentdir -Recurse -Force -ErrorAction Stop
|
||||||
}
|
}
|
||||||
|
|
||||||
& "$env:COMSPEC" /c mklink /j $currentdir $versiondir | out-null
|
New-DirectoryJunction $currentdir $versiondir | Out-Null
|
||||||
attrib $currentdir +R /L
|
attrib $currentdir +R /L
|
||||||
return $currentdir
|
return $currentdir
|
||||||
}
|
}
|
||||||
@@ -889,17 +932,17 @@ function link_current($versiondir) {
|
|||||||
# Returns the 'current' junction directory (if it exists),
|
# Returns the 'current' junction directory (if it exists),
|
||||||
# otherwise the normal version directory.
|
# otherwise the normal version directory.
|
||||||
function unlink_current($versiondir) {
|
function unlink_current($versiondir) {
|
||||||
if(get_config NO_JUNCTIONS) { return $versiondir }
|
if (get_config NO_JUNCTIONS) { return $versiondir.ToString() }
|
||||||
$currentdir = current_dir $versiondir
|
$currentdir = "$(Split-Path $versiondir)\current"
|
||||||
|
|
||||||
if(test-path $currentdir) {
|
if (Test-Path $currentdir) {
|
||||||
write-host "Unlinking $(friendly_path $currentdir)"
|
Write-Host "Unlinking $(friendly_path $currentdir)"
|
||||||
|
|
||||||
# remove read-only attribute on link
|
# remove read-only attribute on link
|
||||||
attrib $currentdir -R /L
|
attrib $currentdir -R /L
|
||||||
|
|
||||||
# remove the junction
|
# remove the junction
|
||||||
& "$env:COMSPEC" /c "rmdir `"$currentdir`""
|
Remove-Item $currentdir -Recurse -Force -ErrorAction Stop
|
||||||
return $currentdir
|
return $currentdir
|
||||||
}
|
}
|
||||||
return $versiondir
|
return $versiondir
|
||||||
@@ -938,13 +981,22 @@ function find_dir_or_subdir($path, $dir) {
|
|||||||
|
|
||||||
function env_add_path($manifest, $dir, $global, $arch) {
|
function env_add_path($manifest, $dir, $global, $arch) {
|
||||||
$env_add_path = arch_specific 'env_add_path' $manifest $arch
|
$env_add_path = arch_specific 'env_add_path' $manifest $arch
|
||||||
$env_add_path | Where-Object { $_ } | ForEach-Object {
|
$dir = $dir.TrimEnd('\')
|
||||||
$path_dir = Join-Path $dir $_
|
if ($env_add_path) {
|
||||||
|
# GH-3785: Add path in ascending order.
|
||||||
|
[Array]::Reverse($env_add_path)
|
||||||
|
$env_add_path | Where-Object { $_ } | ForEach-Object {
|
||||||
|
if ($_ -eq '.') {
|
||||||
|
$path_dir = $dir
|
||||||
|
} else {
|
||||||
|
$path_dir = Join-Path $dir $_
|
||||||
|
}
|
||||||
|
|
||||||
if (!(is_in_dir $dir $path_dir)) {
|
if (!(is_in_dir $dir $path_dir)) {
|
||||||
abort "Error in manifest: env_add_path '$_' is outside the app directory."
|
abort "Error in manifest: env_add_path '$_' is outside the app directory."
|
||||||
|
}
|
||||||
|
add_first_in_path $path_dir $global
|
||||||
}
|
}
|
||||||
add_first_in_path $path_dir $global
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,19 +1071,19 @@ function prune_installed($apps, $global) {
|
|||||||
return @($uninstalled), @($installed)
|
return @($uninstalled), @($installed)
|
||||||
}
|
}
|
||||||
|
|
||||||
# check whether the app failed to install
|
function ensure_none_failed($apps) {
|
||||||
function failed($app, $global) {
|
foreach ($app in $apps) {
|
||||||
$ver = current_version $app $global
|
$app = ($app -split '/|\\')[-1] -replace '\.json$', ''
|
||||||
if(!$ver) { return $false }
|
foreach ($global in $true, $false) {
|
||||||
$info = install_info $app $ver $global
|
if (failed $app $global) {
|
||||||
if(!$info) { return $true }
|
if (installed $app $global) {
|
||||||
return $false
|
info "Repair previous failed installation of $app."
|
||||||
}
|
& "$PSScriptRoot\..\libexec\scoop-reset.ps1" $app$(if ($global) { ' --global' })
|
||||||
|
} else {
|
||||||
function ensure_none_failed($apps, $global) {
|
warn "Purging previous failed installation of $app."
|
||||||
foreach($app in $apps) {
|
& "$PSScriptRoot\..\libexec\scoop-uninstall.ps1" $app$(if ($global) { ' --global' })
|
||||||
if(failed $app $global) {
|
}
|
||||||
abort "'$app' install failed previously. Please uninstall it and try again."
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1103,15 +1155,15 @@ function persist_data($manifest, $original_dir, $persist_dir) {
|
|||||||
if (Test-Path $source) {
|
if (Test-Path $source) {
|
||||||
Move-Item -Force $source "$source.original"
|
Move-Item -Force $source "$source.original"
|
||||||
}
|
}
|
||||||
# we don't have persist data in the store, move the source to target, then create link
|
# we don't have persist data in the store, move the source to target, then create link
|
||||||
} elseif (Test-Path $source) {
|
} elseif (Test-Path $source) {
|
||||||
# ensure target parent folder exist
|
# ensure target parent folder exist
|
||||||
ensure (Split-Path -Path $target) | Out-Null
|
ensure (Split-Path -Path $target) | Out-Null
|
||||||
Move-Item $source $target
|
Move-Item $source $target
|
||||||
# we don't have neither source nor target data! we need to crate an empty target,
|
# we don't have neither source nor target data! we need to create an empty target,
|
||||||
# but we can't make a judgement that the data should be a file or directory...
|
# but we can't make a judgement that the data should be a file or directory...
|
||||||
# so we create a directory by default. to avoid this, use pre_install
|
# so we create a directory by default. to avoid this, use pre_install
|
||||||
# to create the source file before persisting (DON'T use post_install)
|
# to create the source file before persisting (DON'T use post_install)
|
||||||
} else {
|
} else {
|
||||||
$target = New-Object System.IO.DirectoryInfo($target)
|
$target = New-Object System.IO.DirectoryInfo($target)
|
||||||
ensure $target | Out-Null
|
ensure $target | Out-Null
|
||||||
@@ -1120,31 +1172,35 @@ function persist_data($manifest, $original_dir, $persist_dir) {
|
|||||||
# create link
|
# create link
|
||||||
if (is_directory $target) {
|
if (is_directory $target) {
|
||||||
# target is a directory, create junction
|
# target is a directory, create junction
|
||||||
& "$env:COMSPEC" /c "mklink /j `"$source`" `"$target`"" | out-null
|
New-DirectoryJunction $source $target | Out-Null
|
||||||
attrib $source +R /L
|
attrib $source +R /L
|
||||||
} else {
|
} else {
|
||||||
# target is a file, create hard link
|
# target is a file, create hard link
|
||||||
& "$env:COMSPEC" /c "mklink /h `"$source`" `"$target`"" | out-null
|
New-Item -Path $source -ItemType HardLink -Value $target | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlink_persist_data($dir) {
|
function unlink_persist_data($manifest, $dir) {
|
||||||
|
$persist = $manifest.persist
|
||||||
# unlink all junction / hard link in the directory
|
# unlink all junction / hard link in the directory
|
||||||
Get-ChildItem -Recurse $dir | ForEach-Object {
|
if ($persist) {
|
||||||
$file = $_
|
@($persist) | ForEach-Object {
|
||||||
if ($null -ne $file.LinkType) {
|
$source, $null = persist_def $_
|
||||||
$filepath = $file.FullName
|
$source = Get-Item "$dir\$source"
|
||||||
# directory (junction)
|
if ($source.LinkType) {
|
||||||
if ($file -is [System.IO.DirectoryInfo]) {
|
$source_path = $source.FullName
|
||||||
# remove read-only attribute on the link
|
# directory (junction)
|
||||||
attrib -R /L $filepath
|
if ($source -is [System.IO.DirectoryInfo]) {
|
||||||
# remove the junction
|
# remove read-only attribute on the link
|
||||||
& "$env:COMSPEC" /c "rmdir /s /q `"$filepath`""
|
attrib -R /L $source_path
|
||||||
} else {
|
# remove the junction
|
||||||
# remove the hard link
|
Remove-Item -Path $source_path -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
& "$env:COMSPEC" /c "del `"$filepath`""
|
} else {
|
||||||
|
# remove the hard link
|
||||||
|
Remove-Item -Path $source_path -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1161,3 +1217,32 @@ function persist_permission($manifest, $global) {
|
|||||||
$acl | Set-Acl -Path $path
|
$acl | Set-Acl -Path $path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# test if there are running processes
|
||||||
|
function test_running_process($app, $global) {
|
||||||
|
$processdir = appdir $app $global | Convert-Path
|
||||||
|
$running_processes = Get-Process | Where-Object { $_.Path -like "$processdir\*" }
|
||||||
|
|
||||||
|
if ($running_processes) {
|
||||||
|
if (get_config 'ignore_running_processes') {
|
||||||
|
warn "Application `"$app`" is still running. Scoop is configured to ignore this condition."
|
||||||
|
return $false
|
||||||
|
} else {
|
||||||
|
error "Application `"$app`" is still running. Close all instances and try again."
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# wrapper function to create junction links
|
||||||
|
# Required to handle docker/for-win#12240
|
||||||
|
function New-DirectoryJunction($source, $target) {
|
||||||
|
# test if this script is being executed inside a docker container
|
||||||
|
if (Get-Service -Name cexecsvc -ErrorAction SilentlyContinue) {
|
||||||
|
cmd.exe /d /c "mklink /j `"$source`" `"$target`""
|
||||||
|
} else {
|
||||||
|
New-Item -Path $source -ItemType Junction -Value $target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
42
lib/json.ps1
42
lib/json.ps1
@@ -92,32 +92,34 @@ function ConvertToPrettyJson {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function json_path([String] $json, [String] $jsonpath, [Hashtable] $substitutions) {
|
function json_path([String] $json, [String] $jsonpath, [Hashtable] $substitutions, [Boolean] $reverse, [Boolean] $single) {
|
||||||
Add-Type -Path "$psscriptroot\..\supporting\validator\bin\Newtonsoft.Json.dll"
|
Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Newtonsoft.Json.dll"
|
||||||
if ($null -ne $substitutions) {
|
if ($null -ne $substitutions) {
|
||||||
$jsonpath = substitute $jsonpath $substitutions ($jsonpath -like "*=~*")
|
$jsonpath = substitute $jsonpath $substitutions ($jsonpath -like "*=~*")
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
$obj = [Newtonsoft.Json.Linq.JObject]::Parse($json)
|
$obj = [Newtonsoft.Json.Linq.JValue]::Parse($json)
|
||||||
} catch [Newtonsoft.Json.JsonReaderException] {
|
} catch [Newtonsoft.Json.JsonReaderException] {
|
||||||
try {
|
|
||||||
$obj = [Newtonsoft.Json.Linq.JArray]::Parse($json)
|
|
||||||
} catch [Newtonsoft.Json.JsonReaderException] {
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
$result = $obj.SelectToken($jsonpath, $true)
|
|
||||||
} catch [Newtonsoft.Json.JsonException] {
|
|
||||||
return $null
|
|
||||||
}
|
|
||||||
return $result.ToString()
|
|
||||||
} catch [System.Management.Automation.MethodInvocationException] {
|
|
||||||
write-host -f DarkRed $_
|
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
$result = $obj.SelectTokens($jsonpath, $true)
|
||||||
|
if ($reverse) {
|
||||||
|
# Return versions in reverse order
|
||||||
|
$result = [System.Linq.Enumerable]::Reverse($result)
|
||||||
|
}
|
||||||
|
if ($single) {
|
||||||
|
# Extract First value
|
||||||
|
$result = [System.Linq.Enumerable]::First($result)
|
||||||
|
# Convert first value to string
|
||||||
|
$result = $result.ToString()
|
||||||
|
} else {
|
||||||
|
$result = "$([String]::Join('\n', $result))"
|
||||||
|
}
|
||||||
|
return $result
|
||||||
|
} catch [Exception] {
|
||||||
|
Write-Host $_ -ForegroundColor DarkRed
|
||||||
|
}
|
||||||
|
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
@@ -160,7 +162,7 @@ function normalize_values([psobject] $json) {
|
|||||||
# Recursively edit psobjects
|
# Recursively edit psobjects
|
||||||
# If the values is psobjects, its not normalized
|
# If the values is psobjects, its not normalized
|
||||||
# For example if manifest have architecture and it's architecture have array with single value it's not formatted.
|
# For example if manifest have architecture and it's architecture have array with single value it's not formatted.
|
||||||
# @see https://github.com/lukesampson/scoop/pull/2642#issue-220506263
|
# @see https://github.com/ScoopInstaller/Scoop/pull/2642#issue-220506263
|
||||||
if ($_.Value -is [System.Management.Automation.PSCustomObject]) {
|
if ($_.Value -is [System.Management.Automation.PSCustomObject]) {
|
||||||
$_.Value = normalize_values $_.Value
|
$_.Value = normalize_values $_.Value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
. "$psscriptroot/core.ps1"
|
|
||||||
. "$psscriptroot/autoupdate.ps1"
|
|
||||||
|
|
||||||
function manifest_path($app, $bucket) {
|
function manifest_path($app, $bucket) {
|
||||||
fullpath "$(Find-BucketDirectory $bucket)\$(sanitary_path $app).json"
|
fullpath "$(Find-BucketDirectory $bucket)\$(sanitary_path $app).json"
|
||||||
}
|
}
|
||||||
@@ -48,7 +45,7 @@ function save_install_info($info, $dir) {
|
|||||||
$nulls = $info.keys | Where-Object { $null -eq $info[$_] }
|
$nulls = $info.keys | Where-Object { $null -eq $info[$_] }
|
||||||
$nulls | ForEach-Object { $info.remove($_) } # strip null-valued
|
$nulls | ForEach-Object { $info.remove($_) } # strip null-valued
|
||||||
|
|
||||||
$file_content = $info | ConvertToPrettyJson
|
$file_content = $info | ConvertToPrettyJson # in 'json.ps1'
|
||||||
[System.IO.File]::WriteAllLines("$dir\install.json", $file_content)
|
[System.IO.File]::WriteAllLines("$dir\install.json", $file_content)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,8 +56,20 @@ function install_info($app, $version, $global) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function default_architecture {
|
function default_architecture {
|
||||||
if([intptr]::size -eq 8) { return "64bit" }
|
$arch = get_config 'default_architecture'
|
||||||
"32bit"
|
$system = if ([Environment]::Is64BitOperatingSystem) { '64bit' } else { '32bit' }
|
||||||
|
if ($null -eq $arch) {
|
||||||
|
$arch = $system
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$arch = ensure_architecture $arch
|
||||||
|
} catch {
|
||||||
|
warn 'Invalid default architecture configured. Determining default system architecture'
|
||||||
|
$arch = $system
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $arch
|
||||||
}
|
}
|
||||||
|
|
||||||
function arch_specific($prop, $manifest, $architecture) {
|
function arch_specific($prop, $manifest, $architecture) {
|
||||||
@@ -76,7 +85,7 @@ function supports_architecture($manifest, $architecture) {
|
|||||||
return -not [String]::IsNullOrEmpty((arch_specific 'url' $manifest $architecture))
|
return -not [String]::IsNullOrEmpty((arch_specific 'url' $manifest $architecture))
|
||||||
}
|
}
|
||||||
|
|
||||||
function generate_user_manifest($app, $bucket, $version) {
|
function generate_user_manifest($app, $bucket, $version) { # 'autoupdate.ps1' 'buckets.ps1' 'manifest.ps1'
|
||||||
$null, $manifest, $bucket, $null = Find-Manifest $app $bucket
|
$null, $manifest, $bucket, $null = Find-Manifest $app $bucket
|
||||||
if ("$($manifest.version)" -eq "$version") {
|
if ("$($manifest.version)" -eq "$version") {
|
||||||
return manifest_path $app $bucket
|
return manifest_path $app $bucket
|
||||||
@@ -90,7 +99,7 @@ function generate_user_manifest($app, $bucket, $version) {
|
|||||||
|
|
||||||
ensure $(usermanifestsdir) | out-null
|
ensure $(usermanifestsdir) | out-null
|
||||||
try {
|
try {
|
||||||
autoupdate $app "$(resolve-path $(usermanifestsdir))" $manifest $version $(@{})
|
Invoke-AutoUpdate $app "$(resolve-path $(usermanifestsdir))" $manifest $version $(@{ })
|
||||||
return "$(resolve-path $(usermanifest $app))"
|
return "$(resolve-path $(usermanifest $app))"
|
||||||
} catch {
|
} catch {
|
||||||
write-host -f darkred "Could not install $app@$version"
|
write-host -f darkred "Could not install $app@$version"
|
||||||
|
|||||||
@@ -2,56 +2,56 @@ $modulesdir = "$scoopdir\modules"
|
|||||||
|
|
||||||
function install_psmodule($manifest, $dir, $global) {
|
function install_psmodule($manifest, $dir, $global) {
|
||||||
$psmodule = $manifest.psmodule
|
$psmodule = $manifest.psmodule
|
||||||
if(!$psmodule) { return }
|
if (!$psmodule) { return }
|
||||||
|
|
||||||
if($global) {
|
if ($global) {
|
||||||
abort "Installing PowerShell modules globally is not implemented!"
|
abort 'Installing PowerShell modules globally is not implemented!'
|
||||||
}
|
}
|
||||||
|
|
||||||
$modulesdir = ensure $modulesdir
|
$modulesdir = ensure $modulesdir
|
||||||
ensure_in_psmodulepath $modulesdir $global
|
ensure_in_psmodulepath $modulesdir $global
|
||||||
|
|
||||||
$module_name = $psmodule.name
|
$module_name = $psmodule.name
|
||||||
if(!$module_name) {
|
if (!$module_name) {
|
||||||
abort "Invalid manifest: The 'name' property is missing from 'psmodule'."
|
abort "Invalid manifest: The 'name' property is missing from 'psmodule'."
|
||||||
}
|
}
|
||||||
|
|
||||||
$linkfrom = "$modulesdir\$module_name"
|
$linkfrom = "$modulesdir\$module_name"
|
||||||
write-host "Installing PowerShell module '$module_name'"
|
Write-Host "Installing PowerShell module '$module_name'"
|
||||||
|
|
||||||
write-host "Linking $(friendly_path $linkfrom) => $(friendly_path $dir)"
|
Write-Host "Linking $(friendly_path $linkfrom) => $(friendly_path $dir)"
|
||||||
|
|
||||||
if(test-path $linkfrom) {
|
if (Test-Path $linkfrom) {
|
||||||
warn "$(friendly_path $linkfrom) already exists. It will be replaced."
|
warn "$(friendly_path $linkfrom) already exists. It will be replaced."
|
||||||
& "$env:COMSPEC" /c "rmdir `"$linkfrom`""
|
Remove-Item -Path $linkfrom -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
& "$env:COMSPEC" /c "mklink /j `"$linkfrom`" `"$dir`"" | out-null
|
New-DirectoryJunction $linkfrom $dir | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
function uninstall_psmodule($manifest, $dir, $global) {
|
function uninstall_psmodule($manifest, $dir, $global) {
|
||||||
$psmodule = $manifest.psmodule
|
$psmodule = $manifest.psmodule
|
||||||
if(!$psmodule) { return }
|
if (!$psmodule) { return }
|
||||||
|
|
||||||
$module_name = $psmodule.name
|
$module_name = $psmodule.name
|
||||||
write-host "Uninstalling PowerShell module '$module_name'."
|
Write-Host "Uninstalling PowerShell module '$module_name'."
|
||||||
|
|
||||||
$linkfrom = "$modulesdir\$module_name"
|
$linkfrom = "$modulesdir\$module_name"
|
||||||
if(test-path $linkfrom) {
|
if (Test-Path $linkfrom) {
|
||||||
write-host "Removing $(friendly_path $linkfrom)"
|
Write-Host "Removing $(friendly_path $linkfrom)"
|
||||||
$linkfrom = resolve-path $linkfrom
|
$linkfrom = Resolve-Path $linkfrom
|
||||||
& "$env:COMSPEC" /c "rmdir `"$linkfrom`""
|
Remove-Item -Path $linkfrom -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensure_in_psmodulepath($dir, $global) {
|
function ensure_in_psmodulepath($dir, $global) {
|
||||||
$path = env 'psmodulepath' $global
|
$path = env 'psmodulepath' $global
|
||||||
if(!$global -and $null -eq $path) {
|
if (!$global -and $null -eq $path) {
|
||||||
$path = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
|
$path = "$env:USERPROFILE\Documents\WindowsPowerShell\Modules"
|
||||||
}
|
}
|
||||||
$dir = fullpath $dir
|
$dir = fullpath $dir
|
||||||
if($path -notmatch [regex]::escape($dir)) {
|
if ($path -notmatch [Regex]::Escape($dir)) {
|
||||||
write-output "Adding $(friendly_path $dir) to $(if($global){'global'}else{'your'}) PowerShell module path."
|
Write-Output "Adding $(friendly_path $dir) to $(if($global){'global'}else{'your'}) PowerShell module path."
|
||||||
|
|
||||||
env 'psmodulepath' $global "$dir;$path" # for future sessions...
|
env 'psmodulepath' $global "$dir;$path" # for future sessions...
|
||||||
$env:psmodulepath = "$dir;$env:psmodulepath" # for this session
|
$env:psmodulepath = "$dir;$env:psmodulepath" # for this session
|
||||||
|
|||||||
304
lib/versions.ps1
304
lib/versions.ps1
@@ -1,53 +1,285 @@
|
|||||||
# versions
|
function Get-LatestVersion {
|
||||||
function latest_version($app, $bucket, $url) {
|
<#
|
||||||
(manifest $app $bucket $url).version
|
.SYNOPSIS
|
||||||
}
|
Get latest version of app from manifest
|
||||||
function current_version($app, $global) {
|
.PARAMETER AppName
|
||||||
@(versions $app $global)[-1]
|
App's name
|
||||||
}
|
.PARAMETER Bucket
|
||||||
function versions($app, $global) {
|
Bucket which the app belongs to
|
||||||
$appdir = appdir $app $global
|
.PARAMETER Uri
|
||||||
if(!(test-path $appdir)) { return @() }
|
Remote app manifest's URI
|
||||||
|
#>
|
||||||
sort_versions (Get-ChildItem $appdir -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.fullname) } | ForEach-Object { $_.name })
|
[OutputType([String])]
|
||||||
}
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
function version($ver) {
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
$ver -split '[\.-]' | ForEach-Object {
|
[Alias('App')]
|
||||||
$num = $_ -as [int]
|
[String]
|
||||||
if($num) { $num } else { $_ }
|
$AppName,
|
||||||
|
[Parameter(Position = 1)]
|
||||||
|
[String]
|
||||||
|
$Bucket,
|
||||||
|
[Parameter(Position = 2)]
|
||||||
|
[String]
|
||||||
|
$Uri
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
return (manifest $AppName $Bucket $Uri).version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function compare_versions($a, $b) {
|
|
||||||
$ver_a = @(version $a)
|
|
||||||
$ver_b = @(version $b)
|
|
||||||
|
|
||||||
for($i=0;$i -lt $ver_a.length;$i++) {
|
function Select-CurrentVersion { # 'manifest.ps1'
|
||||||
if($i -gt $ver_b.length) { return 1; }
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Select current version of installed app, from 'current\manifest.json' or modified time of version directory
|
||||||
|
.PARAMETER AppName
|
||||||
|
App's name
|
||||||
|
.PARAMETER Global
|
||||||
|
Globally installed application
|
||||||
|
#>
|
||||||
|
[OutputType([String])]
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[Alias('App')]
|
||||||
|
[String]
|
||||||
|
$AppName,
|
||||||
|
[Parameter(Position = 1)]
|
||||||
|
[Switch]
|
||||||
|
$Global
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$currentPath = "$(appdir $AppName $Global)\current"
|
||||||
|
if (!(get_config NO_JUNCTIONS)) {
|
||||||
|
$currentVersion = (parse_json "$currentPath\manifest.json").version
|
||||||
|
if ($currentVersion -eq 'nightly') {
|
||||||
|
$currentVersion = (Get-Item $currentPath).Target | Split-Path -Leaf
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($null -eq $currentVersion) {
|
||||||
|
$installedVersion = Get-InstalledVersion -AppName $AppName -Global:$Global
|
||||||
|
if ($installedVersion) {
|
||||||
|
$currentVersion = @($installedVersion)[-1]
|
||||||
|
} else {
|
||||||
|
$currentVersion = $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $currentVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# don't try to compare int to string
|
function Get-InstalledVersion {
|
||||||
if($ver_b[$i] -is [string] -and $ver_a[$i] -isnot [string]) {
|
<#
|
||||||
$ver_a[$i] = "$($ver_a[$i])"
|
.SYNOPSIS
|
||||||
|
Get all installed version of app, by checking version directories' 'install.json'
|
||||||
|
.PARAMETER AppName
|
||||||
|
App's name
|
||||||
|
.PARAMETER Global
|
||||||
|
Globally installed application
|
||||||
|
.NOTES
|
||||||
|
Versions are sorted from oldest to newest, i.e., latest installed version is the last one in the output array.
|
||||||
|
If no installed version found, empty array will be returned.
|
||||||
|
#>
|
||||||
|
[OutputType([Object[]])]
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[Alias('App')]
|
||||||
|
[String]
|
||||||
|
$AppName,
|
||||||
|
[Parameter(Position = 1)]
|
||||||
|
[Switch]
|
||||||
|
$Global
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$appPath = appdir $AppName $Global
|
||||||
|
if (Test-Path $appPath) {
|
||||||
|
$versions = @((Get-ChildItem "$appPath\*\install.json" | Sort-Object -Property LastWriteTimeUtc).Directory.Name)
|
||||||
|
return $versions | Where-Object { ($_ -ne 'current') -and ($_ -notlike '_*.old*') }
|
||||||
|
} else {
|
||||||
|
return @()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Deprecated
|
||||||
|
# sort_versions (Get-ChildItem $appPath -dir -attr !reparsePoint | Where-Object { $null -ne $(Get-ChildItem $_.FullName) } | ForEach-Object { $_.Name })
|
||||||
|
}
|
||||||
|
|
||||||
|
function Compare-Version {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Compare versions, mainly according to SemVer's rules
|
||||||
|
.PARAMETER ReferenceVersion
|
||||||
|
Specifies a version used as a reference for comparison
|
||||||
|
.PARAMETER DifferenceVersion
|
||||||
|
Specifies the version that are compared to the reference version
|
||||||
|
.PARAMETER Delimiter
|
||||||
|
Specifies the delimiter of versions
|
||||||
|
.OUTPUTS
|
||||||
|
System.Int32
|
||||||
|
'0' if DifferenceVersion is equal to ReferenceVersion,
|
||||||
|
'1' if DifferenceVersion is greater then ReferenceVersion,
|
||||||
|
'-1' if DifferenceVersion is less then ReferenceVersion
|
||||||
|
#>
|
||||||
|
[OutputType([Int32])]
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0)]
|
||||||
|
[AllowEmptyString()]
|
||||||
|
[String]
|
||||||
|
$ReferenceVersion,
|
||||||
|
[Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)]
|
||||||
|
[AllowEmptyString()]
|
||||||
|
[String]
|
||||||
|
$DifferenceVersion,
|
||||||
|
[String]
|
||||||
|
$Delimiter = '-'
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
# Use '+' sign as post-release, see https://github.com/ScoopInstaller/Scoop/pull/3721#issuecomment-553718093
|
||||||
|
$ReferenceVersion, $DifferenceVersion = @($ReferenceVersion, $DifferenceVersion) -replace '\+', '-'
|
||||||
|
|
||||||
|
# Return 0 if versions are equal
|
||||||
|
if ($DifferenceVersion -eq $ReferenceVersion) {
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if($ver_a[$i] -gt $ver_b[$i]) { return 1; }
|
# Preprocess versions (split, convert and separate)
|
||||||
if($ver_a[$i] -lt $ver_b[$i]) { return -1; }
|
$splitReferenceVersion = @(SplitVersion -Version $ReferenceVersion -Delimiter $Delimiter)
|
||||||
|
$splitDifferenceVersion = @(SplitVersion -Version $DifferenceVersion -Delimiter $Delimiter)
|
||||||
|
|
||||||
|
# Nightly versions are always equal
|
||||||
|
if ($splitReferenceVersion[0] -eq 'nightly' -and $splitDifferenceVersion[0] -eq 'nightly') {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0; $i -lt [Math]::Max($splitReferenceVersion.Length, $splitDifferenceVersion.Length); $i++) {
|
||||||
|
# '1.1-alpha' is less then '1.1'
|
||||||
|
if ($i -ge $splitReferenceVersion.Length) {
|
||||||
|
if ($splitDifferenceVersion[$i] -match 'alpha|beta|rc|pre') {
|
||||||
|
return -1
|
||||||
|
} else {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# '1.1' is greater then '1.1-beta'
|
||||||
|
if ($i -ge $splitDifferenceVersion.Length) {
|
||||||
|
if ($splitReferenceVersion[$i] -match 'alpha|beta|rc|pre') {
|
||||||
|
return 1
|
||||||
|
} else {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If some parts of versions have '.', compare them with delimiter '.'
|
||||||
|
if (($splitReferenceVersion[$i] -match '\.') -or ($splitDifferenceVersion[$i] -match '\.')) {
|
||||||
|
$Result = Compare-Version -ReferenceVersion $splitReferenceVersion[$i] -DifferenceVersion $splitDifferenceVersion[$i] -Delimiter '.'
|
||||||
|
# If the parts are equal, continue to next part, otherwise return
|
||||||
|
if ($Result -ne 0) {
|
||||||
|
return $Result
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# If some parts of versions have '_', compare them with delimiter '_'
|
||||||
|
if (($splitReferenceVersion[$i] -match '_') -or ($splitDifferenceVersion[$i] -match '_')) {
|
||||||
|
$Result = Compare-Version -ReferenceVersion $splitReferenceVersion[$i] -DifferenceVersion $splitDifferenceVersion[$i] -Delimiter '_'
|
||||||
|
# If the parts are equal, continue to next part, otherwise return
|
||||||
|
if ($Result -ne 0) {
|
||||||
|
return $Result
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Don't try to compare [Long] to [String]
|
||||||
|
if ($null -ne $splitReferenceVersion[$i] -and $null -ne $splitDifferenceVersion[$i]) {
|
||||||
|
if ($splitReferenceVersion[$i] -is [String] -and $splitDifferenceVersion[$i] -isnot [String]) {
|
||||||
|
$splitDifferenceVersion[$i] = "$($splitDifferenceVersion[$i])"
|
||||||
|
}
|
||||||
|
if ($splitDifferenceVersion[$i] -is [String] -and $splitReferenceVersion[$i] -isnot [String]) {
|
||||||
|
$splitReferenceVersion[$i] = "$($splitReferenceVersion[$i])"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Compare [String] or [Long]
|
||||||
|
if ($splitDifferenceVersion[$i] -gt $splitReferenceVersion[$i]) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if ($splitDifferenceVersion[$i] -lt $splitReferenceVersion[$i]) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if($ver_b.length -gt $ver_a.length) { return -1 }
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Helper function
|
||||||
|
function SplitVersion {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Split version by Delimiter, convert number string to number, and separate letters from numbers
|
||||||
|
.PARAMETER Version
|
||||||
|
Specifies a version
|
||||||
|
.PARAMETER Delimiter
|
||||||
|
Specifies the delimiter of version (Literal)
|
||||||
|
#>
|
||||||
|
[OutputType([Object[]])]
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
|
||||||
|
[AllowEmptyString()]
|
||||||
|
[String]
|
||||||
|
$Version,
|
||||||
|
[String]
|
||||||
|
$Delimiter = '-'
|
||||||
|
)
|
||||||
|
process {
|
||||||
|
$Version = $Version -replace '[a-zA-Z]+', "$Delimiter$&$Delimiter"
|
||||||
|
return ($Version -split [Regex]::Escape($Delimiter) -ne '' | ForEach-Object { if ($_ -match '^\d+$') { [Long]$_ } else { $_ } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deprecated
|
||||||
|
# Not used anymore in scoop core
|
||||||
function qsort($ary, $fn) {
|
function qsort($ary, $fn) {
|
||||||
if($null -eq $ary) { return @() }
|
warn '"qsort" is deprecated. Please avoid using it anymore.'
|
||||||
if(!($ary -is [array])) { return @($ary) }
|
if ($null -eq $ary) { return @() }
|
||||||
|
if (!($ary -is [array])) { return @($ary) }
|
||||||
|
|
||||||
$pivot = $ary[0]
|
$pivot = $ary[0]
|
||||||
$rem = $ary[1..($ary.length-1)]
|
$rem = $ary[1..($ary.length - 1)]
|
||||||
|
|
||||||
$lesser = qsort ($rem | Where-Object { (& $fn $_ $pivot) -lt 0 }) $fn
|
$lesser = qsort ($rem | Where-Object { (& $fn $pivot $_) -lt 0 }) $fn
|
||||||
|
|
||||||
$greater = qsort ($rem | Where-Object { (& $fn $_ $pivot) -ge 0 }) $fn
|
$greater = qsort ($rem | Where-Object { (& $fn $pivot $_) -ge 0 }) $fn
|
||||||
|
|
||||||
return @() + $lesser + @($pivot) + $greater
|
return @() + $lesser + @($pivot) + $greater
|
||||||
}
|
}
|
||||||
function sort_versions($versions) { qsort $versions compare_versions }
|
|
||||||
|
# Deprecated
|
||||||
|
# Not used anymore in scoop core
|
||||||
|
function sort_versions($versions) {
|
||||||
|
warn '"sort_versions" is deprecated. Please avoid using it anymore.'
|
||||||
|
qsort $versions Compare-Version
|
||||||
|
}
|
||||||
|
|
||||||
|
function compare_versions($a, $b) {
|
||||||
|
Show-DeprecatedWarning $MyInvocation 'Compare-Version'
|
||||||
|
# Please note the parameters' sequence
|
||||||
|
return Compare-Version -ReferenceVersion $b -DifferenceVersion $a
|
||||||
|
}
|
||||||
|
|
||||||
|
function latest_version($app, $bucket, $url) {
|
||||||
|
Show-DeprecatedWarning $MyInvocation 'Get-LatestVersion'
|
||||||
|
return Get-LatestVersion -AppName $app -Bucket $bucket -Uri $url
|
||||||
|
}
|
||||||
|
|
||||||
|
function current_version($app, $global) {
|
||||||
|
Show-DeprecatedWarning $MyInvocation 'Select-CurrentVersion'
|
||||||
|
return Select-CurrentVersion -AppName $app -Global:$global
|
||||||
|
}
|
||||||
|
|
||||||
|
function versions($app, $global) {
|
||||||
|
Show-DeprecatedWarning $MyInvocation 'Get-InstalledVersion'
|
||||||
|
return Get-InstalledVersion -AppName $app -Global:$global
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,36 +16,34 @@
|
|||||||
# -v, --verbose Show alias description and table headers (works only for 'list')
|
# -v, --verbose Show alias description and table headers (works only for 'list')
|
||||||
|
|
||||||
param(
|
param(
|
||||||
[String]$opt,
|
[String]$opt,
|
||||||
[String]$name,
|
[String]$name,
|
||||||
[String]$command,
|
[String]$command,
|
||||||
[String]$description,
|
[String]$description,
|
||||||
[Switch]$verbose = $false
|
[Switch]$verbose = $false
|
||||||
)
|
)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1" # shim related
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
|
||||||
|
|
||||||
$script:config_alias = "alias"
|
$script:config_alias = 'alias'
|
||||||
|
|
||||||
function init_alias_config {
|
function init_alias_config {
|
||||||
$aliases = get_config $script:config_alias
|
$aliases = get_config $script:config_alias
|
||||||
if(!$aliases) {
|
if ($aliases) {
|
||||||
$aliases = @{}
|
$aliases
|
||||||
|
} else {
|
||||||
|
New-Object -TypeName PSObject
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aliases
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_alias($name, $command) {
|
function add_alias($name, $command) {
|
||||||
if(!$command) {
|
if (!$command) {
|
||||||
abort "Can't create an empty alias."
|
abort "Can't create an empty alias."
|
||||||
}
|
}
|
||||||
|
|
||||||
# get current aliases from config
|
# get current aliases from config
|
||||||
$aliases = init_alias_config
|
$aliases = init_alias_config
|
||||||
if($aliases.$name) {
|
if ($aliases.$name) {
|
||||||
abort "Alias $name already exists."
|
abort "Alias $name already exists."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +52,11 @@ function add_alias($name, $command) {
|
|||||||
# generate script
|
# generate script
|
||||||
$shimdir = shimdir $false
|
$shimdir = shimdir $false
|
||||||
$script =
|
$script =
|
||||||
@"
|
@"
|
||||||
# Summary: $description
|
# Summary: $description
|
||||||
$command
|
$command
|
||||||
"@
|
"@
|
||||||
$script | out-file "$shimdir\$alias_file.ps1" -encoding utf8
|
$script | Out-UTF8File "$shimdir\$alias_file.ps1"
|
||||||
|
|
||||||
# add alias to config
|
# add alias to config
|
||||||
$aliases | Add-Member -MemberType NoteProperty -Name $name -Value $alias_file
|
$aliases | Add-Member -MemberType NoteProperty -Name $name -Value $alias_file
|
||||||
@@ -68,11 +66,11 @@ $command
|
|||||||
|
|
||||||
function rm_alias($name) {
|
function rm_alias($name) {
|
||||||
$aliases = init_alias_config
|
$aliases = init_alias_config
|
||||||
if(!$name) {
|
if (!$name) {
|
||||||
abort "Which alias should be removed?"
|
abort 'Which alias should be removed?'
|
||||||
}
|
}
|
||||||
|
|
||||||
if($aliases.$name) {
|
if ($aliases.$name) {
|
||||||
"Removing alias $name..."
|
"Removing alias $name..."
|
||||||
|
|
||||||
rm_shim $aliases.$name (shimdir $false)
|
rm_shim $aliases.$name (shimdir $false)
|
||||||
@@ -92,24 +90,24 @@ function list_aliases {
|
|||||||
$command = ($content | Select-Object -Skip 1).Trim()
|
$command = ($content | Select-Object -Skip 1).Trim()
|
||||||
$summary = (summary $content).Trim()
|
$summary = (summary $content).Trim()
|
||||||
|
|
||||||
$aliases += New-Object psobject -Property @{Name=$_.name; Summary=$summary; Command=$command}
|
$aliases += New-Object psobject -Property @{Name = $_.name; Summary = $summary; Command = $command }
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$aliases.count) {
|
if (!$aliases.count) {
|
||||||
warn "No aliases founds."
|
info "No alias found."
|
||||||
}
|
}
|
||||||
$aliases = $aliases.GetEnumerator() | Sort-Object Name
|
$aliases = $aliases.GetEnumerator() | Sort-Object Name
|
||||||
if($verbose) {
|
if ($verbose) {
|
||||||
return $aliases | Select-Object Name, Command, Summary | Format-Table -autosize -wrap
|
return $aliases | Select-Object Name, Command, Summary
|
||||||
} else {
|
} else {
|
||||||
return $aliases | Select-Object Name, Command | Format-Table -autosize -hidetablehead -wrap
|
return $aliases | Select-Object Name, Command
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($opt) {
|
switch ($opt) {
|
||||||
"add" { add_alias $name $command }
|
'add' { add_alias $name $command }
|
||||||
"rm" { rm_alias $name }
|
'rm' { rm_alias $name }
|
||||||
"list" { list_aliases }
|
'list' { list_aliases }
|
||||||
default { my_usage; exit 1 }
|
default { my_usage; exit 1 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# scoop bucket add <name> [<repo>]
|
# scoop bucket add <name> [<repo>]
|
||||||
#
|
#
|
||||||
# e.g.:
|
# e.g.:
|
||||||
# scoop bucket add extras https://github.com/lukesampson/scoop-extras.git
|
# scoop bucket add extras https://github.com/ScoopInstaller/Extras.git
|
||||||
#
|
#
|
||||||
# Since the 'extras' bucket is known to Scoop, this can be shortened to:
|
# Since the 'extras' bucket is known to Scoop, this can be shortened to:
|
||||||
# scoop bucket add extras
|
# scoop bucket add extras
|
||||||
@@ -19,22 +19,53 @@
|
|||||||
# scoop bucket known
|
# scoop bucket known
|
||||||
param($cmd, $name, $repo)
|
param($cmd, $name, $repo)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
$usage_add = 'usage: scoop bucket add <name> [<repo>]'
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
$usage_rm = 'usage: scoop bucket rm <name>'
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\git.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
switch ($cmd) {
|
||||||
|
'add' {
|
||||||
$usage_add = "usage: scoop bucket add <name> [<repo>]"
|
if (!$name) {
|
||||||
$usage_rm = "usage: scoop bucket rm <name>"
|
'<name> missing'
|
||||||
|
$usage_add
|
||||||
switch($cmd) {
|
exit 1
|
||||||
'add' { add_bucket $name $repo }
|
}
|
||||||
'rm' { rm_bucket $name }
|
if (!$repo) {
|
||||||
'list' { Get-LocalBucket }
|
$repo = known_bucket_repo $name
|
||||||
'known' { known_buckets }
|
if (!$repo) {
|
||||||
default { "scoop bucket: cmd '$cmd' not supported"; my_usage; exit 1 }
|
"Unknown bucket '$name'. Try specifying <repo>."
|
||||||
|
$usage_add
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$status = add_bucket $name $repo
|
||||||
|
exit $status
|
||||||
|
}
|
||||||
|
'rm' {
|
||||||
|
if (!$name) {
|
||||||
|
'<name> missing'
|
||||||
|
$usage_rm
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$status = rm_bucket $name
|
||||||
|
exit $status
|
||||||
|
}
|
||||||
|
'list' {
|
||||||
|
$buckets = list_buckets
|
||||||
|
if (!$buckets.Length) {
|
||||||
|
warn "No bucket found. Please run 'scoop bucket add main' to add the default 'main' bucket."
|
||||||
|
exit 2
|
||||||
|
} else {
|
||||||
|
$buckets
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'known' {
|
||||||
|
known_buckets
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
"scoop bucket: cmd '$cmd' not supported"
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Usage: scoop cache show|rm [app]
|
# Usage: scoop cache show|rm [app(s)]
|
||||||
# Summary: Show or clear the download cache
|
# Summary: Show or clear the download cache
|
||||||
# Help: Scoop caches downloads so you don't need to download the same files
|
# Help: Scoop caches downloads so you don't need to download the same files
|
||||||
# when you uninstall and re-install the same version of an app.
|
# when you uninstall and re-install the same version of an app.
|
||||||
@@ -10,48 +10,61 @@
|
|||||||
#
|
#
|
||||||
# To clear everything in your cache, use:
|
# To clear everything in your cache, use:
|
||||||
# scoop cache rm *
|
# scoop cache rm *
|
||||||
param($cmd, $app)
|
param($cmd)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
|
|
||||||
function cacheinfo($file) {
|
function cacheinfo($file) {
|
||||||
$app, $version, $url = $file.name -split '#'
|
$app, $version, $url = $file.Name -split '#'
|
||||||
$size = filesize $file.length
|
New-Object PSObject -Property @{ Name = $app; Version = $version; Length = $file.Length; URL = $url }
|
||||||
return new-object psobject -prop @{ app=$app; version=$version; url=$url; size=$size }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function show($app) {
|
function cacheshow($app) {
|
||||||
$files = @(Get-ChildItem "$cachedir" | Where-Object { $_.name -match "^$app" })
|
if (!$app -or $app -eq '*') {
|
||||||
$total_length = ($files | Measure-Object length -sum).sum -as [double]
|
$app = '.*?'
|
||||||
|
} else {
|
||||||
|
$app = '(' + ($app -join '|') + ')'
|
||||||
|
}
|
||||||
|
$files = @(Get-ChildItem $cachedir | Where-Object -Property Name -Value "^$app#" -Match)
|
||||||
|
$totalLength = ($files | Measure-Object -Property Length -Sum).Sum
|
||||||
|
|
||||||
$f_app = @{ expression={"$($_.app) ($($_.version))" }}
|
$files | ForEach-Object { cacheinfo $_ } | Select-Object Name, Version, Length, URL
|
||||||
$f_url = @{ expression={$_.url};alignment='right'}
|
|
||||||
$f_size = @{ expression={$_.size}; alignment='right'}
|
|
||||||
|
|
||||||
|
Write-Host "Total: $($files.Length) $(pluralize $files.Length 'file' 'files'), $(filesize $totalLength)" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
$files | ForEach-Object { cacheinfo $_ } | Format-Table $f_size, $f_app, $f_url -auto -hide
|
function cacheremove($app) {
|
||||||
|
if (!$app) {
|
||||||
|
'ERROR: <app(s)> missing'
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
} elseif ($app -eq '*') {
|
||||||
|
$files = @(Get-ChildItem $cachedir)
|
||||||
|
} else {
|
||||||
|
$app = '(' + ($app -join '|') + ')'
|
||||||
|
$files = @(Get-ChildItem $cachedir | Where-Object -Property Name -Value "^$app#" -Match)
|
||||||
|
}
|
||||||
|
$totalLength = ($files | Measure-Object -Property Length -Sum).Sum
|
||||||
|
|
||||||
"Total: $($files.length) $(pluralize $files.length 'file' 'files'), $(filesize $total_length)"
|
$files | ForEach-Object {
|
||||||
|
$curr = cacheinfo $_
|
||||||
|
Write-Host "Removing $($curr.URL)..."
|
||||||
|
Remove-Item $_.FullName
|
||||||
|
if(Test-Path "$cachedir\$($curr.Name).txt") {
|
||||||
|
Remove-Item "$cachedir\$($curr.Name).txt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Deleted: $($files.Length) $(pluralize $files.Length 'file' 'files'), $(filesize $totalLength)" -ForegroundColor Yellow
|
||||||
}
|
}
|
||||||
|
|
||||||
switch($cmd) {
|
switch($cmd) {
|
||||||
'rm' {
|
'rm' {
|
||||||
if(!$app) { 'ERROR: <app> missing'; my_usage; exit 1 }
|
cacheremove $Args
|
||||||
Remove-Item "$cachedir\$app#*"
|
|
||||||
if(test-path("$cachedir\$app.txt")) {
|
|
||||||
Remove-Item "$cachedir\$app.txt"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
'show' {
|
'show' {
|
||||||
show $app
|
cacheshow $Args
|
||||||
}
|
|
||||||
'' {
|
|
||||||
show
|
|
||||||
}
|
}
|
||||||
default {
|
default {
|
||||||
my_usage
|
cacheshow (@($cmd) + $Args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
libexec/scoop-cat.ps1
Normal file
25
libexec/scoop-cat.ps1
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# Usage: scoop cat <app>
|
||||||
|
# Summary: Show content of specified manifest. If available, `bat` will be used to pretty-print the JSON.
|
||||||
|
|
||||||
|
param($app)
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\lib\json.ps1" # 'ConvertToPrettyJson'
|
||||||
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly)
|
||||||
|
|
||||||
|
if (!$app) { error '<app> missing'; my_usage; exit 1 }
|
||||||
|
|
||||||
|
$app, $bucket, $null = parse_app $app
|
||||||
|
$app, $manifest, $bucket, $url = Find-Manifest $app $bucket
|
||||||
|
|
||||||
|
if ($manifest) {
|
||||||
|
$style = get_config cat_style
|
||||||
|
if ($style) {
|
||||||
|
$manifest | ConvertToPrettyJson | bat --no-paging --style $style --language json
|
||||||
|
} else {
|
||||||
|
$manifest | ConvertToPrettyJson
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
abort "Couldn't find manifest for '$app'$(if($url) { " at the URL $url" })."
|
||||||
|
}
|
||||||
|
|
||||||
|
exit $exitCode
|
||||||
@@ -3,13 +3,18 @@
|
|||||||
# Help: Performs a series of diagnostic tests to try to identify things that may
|
# Help: Performs a series of diagnostic tests to try to identify things that may
|
||||||
# cause problems with Scoop.
|
# cause problems with Scoop.
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\diagnostic.ps1"
|
||||||
. "$psscriptroot\..\lib\diagnostic.ps1"
|
|
||||||
|
|
||||||
$issues = 0
|
$issues = 0
|
||||||
|
$defenderIssues = 0
|
||||||
|
|
||||||
|
$adminPrivileges = ([System.Security.Principal.WindowsPrincipal] [System.Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
|
||||||
|
|
||||||
|
if ($adminPrivileges) {
|
||||||
|
$defenderIssues += !(check_windows_defender $false)
|
||||||
|
$defenderIssues += !(check_windows_defender $true)
|
||||||
|
}
|
||||||
|
|
||||||
$issues += !(check_windows_defender $false)
|
|
||||||
$issues += !(check_windows_defender $true)
|
|
||||||
$issues += !(check_main_bucket)
|
$issues += !(check_main_bucket)
|
||||||
$issues += !(check_long_paths)
|
$issues += !(check_long_paths)
|
||||||
|
|
||||||
@@ -29,19 +34,22 @@ if (!(Test-HelperInstalled -Helper Dark)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$globaldir = New-Object System.IO.DriveInfo($globaldir)
|
$globaldir = New-Object System.IO.DriveInfo($globaldir)
|
||||||
if($globaldir.DriveFormat -ne 'NTFS') {
|
if ($globaldir.DriveFormat -ne 'NTFS') {
|
||||||
error "Scoop requires an NTFS volume to work! Please point `$env:SCOOP_GLOBAL or 'globalPath' variable in '~/.config/scoop/config.json' to another Drive."
|
error "Scoop requires an NTFS volume to work! Please point `$env:SCOOP_GLOBAL or 'globalPath' variable in '~/.config/scoop/config.json' to another Drive."
|
||||||
$issues++
|
$issues++
|
||||||
}
|
}
|
||||||
|
|
||||||
$scoopdir = New-Object System.IO.DriveInfo($scoopdir)
|
$scoopdir = New-Object System.IO.DriveInfo($scoopdir)
|
||||||
if($scoopdir.DriveFormat -ne 'NTFS') {
|
if ($scoopdir.DriveFormat -ne 'NTFS') {
|
||||||
error "Scoop requires an NTFS volume to work! Please point `$env:SCOOP or 'rootPath' variable in '~/.config/scoop/config.json' to another Drive."
|
error "Scoop requires an NTFS volume to work! Please point `$env:SCOOP or 'rootPath' variable in '~/.config/scoop/config.json' to another Drive."
|
||||||
$issues++
|
$issues++
|
||||||
}
|
}
|
||||||
|
|
||||||
if($issues) {
|
if ($issues) {
|
||||||
warn "Found $issues potential $(pluralize $issues problem problems)."
|
warn "Found $issues potential $(pluralize $issues problem problems)."
|
||||||
|
} elseif ($defenderIssues) {
|
||||||
|
info "Found $defenderIssues performance $(pluralize $defenderIssues problem problems)."
|
||||||
|
warn "Security is more important than performance, in most cases."
|
||||||
} else {
|
} else {
|
||||||
success "No problems identified!"
|
success "No problems identified!"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,70 +3,78 @@
|
|||||||
# Help: 'scoop cleanup' cleans Scoop apps by removing old versions.
|
# Help: 'scoop cleanup' cleans Scoop apps by removing old versions.
|
||||||
# 'scoop cleanup <app>' cleans up the old versions of that app if said versions exist.
|
# 'scoop cleanup <app>' cleans up the old versions of that app if said versions exist.
|
||||||
#
|
#
|
||||||
# You can use '*' in place of <app> to cleanup all apps.
|
# You can use '*' in place of <app> or `-a`/`--all` switch to cleanup all apps.
|
||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
|
# -a, --all Cleanup all apps (alternative to '*')
|
||||||
# -g, --global Cleanup a globally installed app
|
# -g, --global Cleanup a globally installed app
|
||||||
# -k, --cache Remove outdated download cache
|
# -k, --cache Remove outdated download cache
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Select-CurrentVersion' (indirectly)
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1" # persist related
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
$opt, $apps, $err = getopt $args 'agk' 'all', 'global', 'cache'
|
||||||
|
|
||||||
$opt, $apps, $err = getopt $args 'gk' 'global', 'cache'
|
|
||||||
if ($err) { "scoop cleanup: $err"; exit 1 }
|
if ($err) { "scoop cleanup: $err"; exit 1 }
|
||||||
$global = $opt.g -or $opt.global
|
$global = $opt.g -or $opt.global
|
||||||
$cache = $opt.k -or $opt.cache
|
$cache = $opt.k -or $opt.cache
|
||||||
|
$all = $opt.a -or $opt.all
|
||||||
|
|
||||||
if (!$apps) { 'ERROR: <app> missing'; my_usage; exit 1 }
|
if (!$apps -and !$all) { 'ERROR: <app> missing'; my_usage; exit 1 }
|
||||||
|
|
||||||
if ($global -and !(is_admin)) {
|
if ($global -and !(is_admin)) {
|
||||||
'ERROR: you need admin rights to cleanup global apps'; exit 1
|
'ERROR: you need admin rights to cleanup global apps'; exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup($app, $global, $verbose, $cache) {
|
function cleanup($app, $global, $verbose, $cache) {
|
||||||
$current_version = current_version $app $global
|
$current_version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
if ($cache) {
|
if ($cache) {
|
||||||
Remove-Item "$cachedir\$app#*" -Exclude "$app#$current_version#*"
|
Remove-Item "$cachedir\$app#*" -Exclude "$app#$current_version#*"
|
||||||
}
|
}
|
||||||
$versions = versions $app $global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
|
$appDir = appdir $app $global
|
||||||
|
$versions = Get-ChildItem $appDir -Name
|
||||||
|
$versions = $versions | Where-Object { $current_version -ne $_ -and $_ -ne 'current' }
|
||||||
if (!$versions) {
|
if (!$versions) {
|
||||||
if ($verbose) { success "$app is already clean" }
|
if ($verbose) { success "$app is already clean" }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
write-host -f yellow "Removing $app`:" -nonewline
|
Write-Host -f yellow "Removing $app`:" -NoNewline
|
||||||
$versions | ForEach-Object {
|
$versions | ForEach-Object {
|
||||||
$version = $_
|
$version = $_
|
||||||
write-host " $version" -nonewline
|
Write-Host " $version" -NoNewline
|
||||||
$dir = versiondir $app $version $global
|
$dir = versiondir $app $version $global
|
||||||
# unlink all potential old link before doing recursive Remove-Item
|
# unlink all potential old link before doing recursive Remove-Item
|
||||||
unlink_persist_data $dir
|
unlink_persist_data (installed_manifest $app $version $global) $dir
|
||||||
Remove-Item $dir -ErrorAction Stop -Recurse -Force
|
Remove-Item $dir -ErrorAction Stop -Recurse -Force
|
||||||
}
|
}
|
||||||
write-host ''
|
$leftVersions = Get-ChildItem $appDir
|
||||||
|
if ($leftVersions.Length -eq 1 -and $leftVersions.Name -eq 'current' -and $leftVersions.LinkType) {
|
||||||
|
attrib $leftVersions.FullName -R /L
|
||||||
|
Remove-Item $leftVersions.FullName -ErrorAction Stop -Force
|
||||||
|
$leftVersions = $null
|
||||||
|
}
|
||||||
|
if (!$leftVersions) {
|
||||||
|
Remove-Item $appDir -ErrorAction Stop -Force
|
||||||
|
}
|
||||||
|
Write-Host ''
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($apps) {
|
if ($apps -or $all) {
|
||||||
$verbose = $true
|
if ($apps -eq '*' -or $all) {
|
||||||
if ($apps -eq '*') {
|
|
||||||
$verbose = $false
|
$verbose = $false
|
||||||
$apps = applist (installed_apps $false) $false
|
$apps = applist (installed_apps $false) $false
|
||||||
if ($global) {
|
if ($global) {
|
||||||
$apps += applist (installed_apps $true) $true
|
$apps += applist (installed_apps $true) $true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
$verbose = $true
|
||||||
$apps = Confirm-InstallationStatus $apps -Global:$global
|
$apps = Confirm-InstallationStatus $apps -Global:$global
|
||||||
}
|
}
|
||||||
|
|
||||||
# $apps is now a list of ($app, $global) tuples
|
# $apps is now a list of ($app, $global) tuples
|
||||||
$apps | ForEach-Object { cleanup @_ $verbose $cache}
|
$apps | ForEach-Object { cleanup @_ $verbose $cache }
|
||||||
|
|
||||||
if ($cache) {
|
if ($cache) {
|
||||||
Remove-Item "$cachedir\*.download" -ErrorAction Ignore
|
Remove-Item "$cachedir\*.download" -ErrorAction Ignore
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
# Summary: Get or set configuration values
|
# Summary: Get or set configuration values
|
||||||
# Help: The scoop configuration file is saved at ~/.config/scoop/config.json.
|
# Help: The scoop configuration file is saved at ~/.config/scoop/config.json.
|
||||||
#
|
#
|
||||||
|
# To get all configuration settings:
|
||||||
|
#
|
||||||
|
# scoop config
|
||||||
|
#
|
||||||
# To get a configuration setting:
|
# To get a configuration setting:
|
||||||
#
|
#
|
||||||
# scoop config <name>
|
# scoop config <name>
|
||||||
@@ -17,36 +21,133 @@
|
|||||||
# Settings
|
# Settings
|
||||||
# --------
|
# --------
|
||||||
#
|
#
|
||||||
|
# 7ZIPEXTRACT_USE_EXTERNAL: $true|$false
|
||||||
|
# External 7zip (from path) will be used for archives extraction.
|
||||||
|
#
|
||||||
|
# MSIEXTRACT_USE_LESSMSI: $true|$false
|
||||||
|
# Prefer lessmsi utility over native msiexec.
|
||||||
|
#
|
||||||
|
# NO_JUNCTIONS: $true|$false
|
||||||
|
# The 'current' version alias will not be used. Shims and shortcuts will point to specific version instead.
|
||||||
|
#
|
||||||
|
# SCOOP_REPO: http://github.com/ScoopInstaller/Scoop
|
||||||
|
# Git repository containining scoop source code.
|
||||||
|
# This configuration is useful for custom forks.
|
||||||
|
#
|
||||||
|
# SCOOP_BRANCH: master|develop
|
||||||
|
# Allow to use different branch than master.
|
||||||
|
# Could be used for testing specific functionalities before released into all users.
|
||||||
|
# If you want to receive updates earlier to test new functionalities use develop (see: 'https://github.com/ScoopInstaller/Scoop/issues/2939')
|
||||||
|
#
|
||||||
# proxy: [username:password@]host:port
|
# proxy: [username:password@]host:port
|
||||||
|
# By default, Scoop will use the proxy settings from Internet Options, but with anonymous authentication.
|
||||||
#
|
#
|
||||||
# By default, Scoop will use the proxy settings from Internet Options, but with anonymous authentication.
|
# * To use the credentials for the current logged-in user, use 'currentuser' in place of username:password
|
||||||
|
# * To use the system proxy settings configured in Internet Options, use 'default' in place of host:port
|
||||||
|
# * An empty or unset value for proxy is equivalent to 'default' (with no username or password)
|
||||||
|
# * To bypass the system proxy and connect directly, use 'none' (with no username or password)
|
||||||
#
|
#
|
||||||
# * To use the credentials for the current logged-in user, use 'currentuser' in place of username:password
|
# default_architecture: 64bit|32bit
|
||||||
# * To use the system proxy settings configured in Internet Options, use 'default' in place of host:port
|
# Allow to configure preferred architecture for application installation.
|
||||||
# * An empty or unset value for proxy is equivalent to 'default' (with no username or password)
|
# If not specified, architecture is determined be system.
|
||||||
# * To bypass the system proxy and connect directly, use 'none' (with no username or password)
|
#
|
||||||
|
# debug: $true|$false
|
||||||
|
# Additional and detailed output will be shown.
|
||||||
|
#
|
||||||
|
# force_update: $true|$false
|
||||||
|
# Force apps updating to bucket's version.
|
||||||
|
#
|
||||||
|
# show_update_log: $true|$false
|
||||||
|
# Do not show changed commits on 'scoop update'
|
||||||
|
#
|
||||||
|
# manifest_review: $true|$false
|
||||||
|
# Displays the manifest of every app that's about to
|
||||||
|
# be installed, then asks user if they wish to proceed.
|
||||||
|
#
|
||||||
|
# shim: kiennq|scoopcs|71
|
||||||
|
# Choose scoop shim build.
|
||||||
|
#
|
||||||
|
# rootPath: $Env:UserProfile\scoop
|
||||||
|
# Path to Scoop root directory.
|
||||||
|
#
|
||||||
|
# globalPath: $Env:ProgramData\scoop
|
||||||
|
# Path to Scoop root directory for global apps.
|
||||||
|
#
|
||||||
|
# cachePath:
|
||||||
|
# For downloads, defaults to 'cache' folder under Scoop root directory.
|
||||||
|
#
|
||||||
|
# gh_token:
|
||||||
|
# GitHub API token used to make authenticated requests.
|
||||||
|
# This is essential for checkver and similar functions to run without
|
||||||
|
# incurring rate limits and download from private repositories.
|
||||||
|
#
|
||||||
|
# virustotal_api_key:
|
||||||
|
# API key used for uploading/scanning files using virustotal.
|
||||||
|
# See: 'https://support.virustotal.com/hc/en-us/articles/115002088769-Please-give-me-an-API-key'
|
||||||
|
#
|
||||||
|
# cat_style:
|
||||||
|
# When set to a non-empty string, Scoop will use 'bat' to display the manifest for
|
||||||
|
# the `scoop cat` command and while doing manifest review. This requires 'bat' to be
|
||||||
|
# installed (run `scoop install bat` to install it), otherwise errors will be thrown.
|
||||||
|
# The accepted values are the same as ones passed to the --style flag of 'bat'.
|
||||||
|
#
|
||||||
|
# ignore_running_processes: $true|$false
|
||||||
|
# When set to $false (default), Scoop would stop its procedure immediately if it detects
|
||||||
|
# any target app process is running. Procedure here refers to reset/uninstall/update.
|
||||||
|
# When set to $true, Scoop only displays a warning message and continues procedure.
|
||||||
|
#
|
||||||
|
# private_hosts:
|
||||||
|
# Array of private hosts that need additional authentication.
|
||||||
|
# For example, if you want to access a private GitHub repository,
|
||||||
|
# you need to add the host to this list with 'match' and 'headers' strings.
|
||||||
|
#
|
||||||
|
# ARIA2 configuration
|
||||||
|
# -------------------
|
||||||
|
#
|
||||||
|
# aria2-enabled: $true|$false
|
||||||
|
# Aria2c will be used for downloading of artifacts.
|
||||||
|
#
|
||||||
|
# aria2-warning-enabled: $true|$false
|
||||||
|
# Disable Aria2c warning which is shown while downloading.
|
||||||
|
#
|
||||||
|
# aria2-retry-wait: 2
|
||||||
|
# Number of seconds to wait between retries.
|
||||||
|
# See: 'https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-retry-wait'
|
||||||
|
#
|
||||||
|
# aria2-split: 5
|
||||||
|
# Number of connections used for downlaod.
|
||||||
|
# See: 'https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-s'
|
||||||
|
#
|
||||||
|
# aria2-max-connection-per-server: 5
|
||||||
|
# The maximum number of connections to one server for each download.
|
||||||
|
# See: 'https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-x'
|
||||||
|
#
|
||||||
|
# aria2-min-split-size: 5M
|
||||||
|
# Downloaded files will be splitted by this configured size and downloaded using multiple connections.
|
||||||
|
# See: 'https://aria2.github.io/manual/en/html/aria2c.html#cmdoption-k'
|
||||||
|
#
|
||||||
|
# aria2-options:
|
||||||
|
# Array of additional aria2 options.
|
||||||
|
# See: 'https://aria2.github.io/manual/en/html/aria2c.html#options'
|
||||||
|
|
||||||
param($name, $value)
|
param($name, $value)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
if (!$name) {
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
$scoopConfig
|
||||||
|
} elseif ($name -like '--help') {
|
||||||
reset_aliases
|
my_usage
|
||||||
|
} elseif ($name -like 'rm') {
|
||||||
if(!$name) { my_usage; exit 1 }
|
|
||||||
|
|
||||||
if($name -like 'rm') {
|
|
||||||
set_config $value $null | Out-Null
|
set_config $value $null | Out-Null
|
||||||
Write-Output "'$value' has been removed"
|
Write-Host "'$value' has been removed"
|
||||||
} elseif($null -ne $value) {
|
} elseif ($null -ne $value) {
|
||||||
set_config $name $value | Out-Null
|
set_config $name $value | Out-Null
|
||||||
Write-Output "'$name' has been set to '$value'"
|
Write-Host "'$name' has been set to '$value'"
|
||||||
} else {
|
} else {
|
||||||
$value = get_config $name
|
$value = get_config $name
|
||||||
if($null -eq $value) {
|
if($null -eq $value) {
|
||||||
Write-Output "'$name' is not set"
|
Write-Host "'$name' is not set"
|
||||||
} else {
|
} else {
|
||||||
Write-Output $value
|
$value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,29 +11,28 @@ function create_manifest($url) {
|
|||||||
$url_parts = $null
|
$url_parts = $null
|
||||||
try {
|
try {
|
||||||
$url_parts = parse_url $url
|
$url_parts = parse_url $url
|
||||||
}
|
} catch {
|
||||||
catch {
|
|
||||||
abort "Error: $url is not a valid URL"
|
abort "Error: $url is not a valid URL"
|
||||||
}
|
}
|
||||||
|
|
||||||
$name = choose_item $url_parts "App name"
|
$name = choose_item $url_parts 'App name'
|
||||||
$name = if ($name.Length -gt 0) {
|
$name = if ($name.Length -gt 0) {
|
||||||
$name
|
$name
|
||||||
}
|
} else {
|
||||||
else {
|
file_name ($url_parts | Select-Object -Last 1)
|
||||||
file_name ($url_parts | select-object -last 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$manifest.version = choose_item $url_parts "Version"
|
$manifest.version = choose_item $url_parts 'Version'
|
||||||
|
|
||||||
$manifest | convertto-json | out-file -filepath "$name.json" -encoding utf8
|
$manifest | ConvertTo-Json | Out-File -FilePath "$name.json" -Encoding ASCII
|
||||||
$manifest_path = join-path $pwd "$name.json"
|
$manifest_path = Join-Path $pwd "$name.json"
|
||||||
write-host "Created '$manifest_path'."
|
Write-Host "Created '$manifest_path'."
|
||||||
}
|
}
|
||||||
|
|
||||||
function new_manifest() {
|
function new_manifest() {
|
||||||
@{ "homepage" = ""; "license" = ""; "version" = ""; "url" = "";
|
@{ 'homepage' = ''; 'license' = ''; 'version' = ''; 'url' = '';
|
||||||
"hash" = ""; "extract_dir" = ""; "bin" = ""; "depends" = "" }
|
'hash' = ''; 'extract_dir' = ''; 'bin' = ''; 'depends' = ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function file_name($segment) {
|
function file_name($segment) {
|
||||||
@@ -41,19 +40,19 @@ function file_name($segment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parse_url($url) {
|
function parse_url($url) {
|
||||||
$uri = new-object Uri $url
|
$uri = New-Object Uri $url
|
||||||
$uri.pathandquery.substring(1).split("/")
|
$uri.pathandquery.substring(1).split('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
function choose_item($list, $query) {
|
function choose_item($list, $query) {
|
||||||
for ($i = 0; $i -lt $list.count; $i++) {
|
for ($i = 0; $i -lt $list.count; $i++) {
|
||||||
$item = $list[$i]
|
$item = $list[$i]
|
||||||
write-host "$($i + 1)) $item"
|
Write-Host "$($i + 1)) $item"
|
||||||
}
|
}
|
||||||
$sel = read-host $query
|
$sel = Read-Host $query
|
||||||
|
|
||||||
if ($sel.trim() -match '^[0-9+]$') {
|
if ($sel.trim() -match '^[0-9+]$') {
|
||||||
return $list[$sel-1]
|
return $list[$sel - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
$sel
|
$sel
|
||||||
@@ -61,8 +60,7 @@ function choose_item($list, $query) {
|
|||||||
|
|
||||||
if (!$url) {
|
if (!$url) {
|
||||||
scoop help create
|
scoop help create
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
create_manifest $url
|
create_manifest $url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
# Usage: scoop depends <app>
|
# Usage: scoop depends <app>
|
||||||
# Summary: List dependencies for an app
|
# Summary: List dependencies for an app
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\depends.ps1" # 'Get-Dependency'
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture'
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
|
||||||
. "$psscriptroot\..\lib\decompress.ps1"
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
|
|
||||||
$opt, $apps, $err = getopt $args 'a:' 'arch='
|
$opt, $apps, $err = getopt $args 'a:' 'arch='
|
||||||
$app = $apps[0]
|
$app = $apps[0]
|
||||||
@@ -23,7 +17,7 @@ try {
|
|||||||
abort "ERROR: $_"
|
abort "ERROR: $_"
|
||||||
}
|
}
|
||||||
|
|
||||||
$deps = @(deps $app $architecture)
|
$deps = @(Get-Dependency $app $architecture) -ne $app
|
||||||
if($deps) {
|
if($deps) {
|
||||||
$deps[($deps.length - 1)..0]
|
$deps[($deps.length - 1)..0]
|
||||||
}
|
}
|
||||||
|
|||||||
134
libexec/scoop-download.ps1
Normal file
134
libexec/scoop-download.ps1
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
# Usage: scoop download <app> [options]
|
||||||
|
# Summary: Download apps in the cache folder and verify hashes
|
||||||
|
# Help: e.g. The usual way to download an app, without installing it (uses your local 'buckets'):
|
||||||
|
# scoop download git
|
||||||
|
#
|
||||||
|
# To download an app from a manifest at a URL:
|
||||||
|
# scoop download https://raw.githubusercontent.com/ScoopInstaller/Main/master/bucket/runat.json
|
||||||
|
#
|
||||||
|
# To download an app from a manifest on your computer
|
||||||
|
# scoop download path\to\app.json
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -f, --force Force download (overwrite cache)
|
||||||
|
# -h, --no-hash-check Skip hash verification (use with caution!)
|
||||||
|
# -u, --no-update-scoop Don't update Scoop before downloading if it's outdated
|
||||||
|
# -a, --arch <32bit|64bit> Use the specified architecture, if the app supports it
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\json.ps1" # 'autoupdate.ps1' (indirectly)
|
||||||
|
. "$PSScriptRoot\..\lib\autoupdate.ps1" # 'generate_user_manifest' (indirectly)
|
||||||
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Find-Manifest' (indirectly)
|
||||||
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
|
|
||||||
|
$opt, $apps, $err = getopt $args 'fhua:' 'force', 'no-hash-check', 'no-update-scoop', 'arch='
|
||||||
|
if ($err) { error "scoop download: $err"; exit 1 }
|
||||||
|
|
||||||
|
$check_hash = !($opt.h -or $opt.'no-hash-check')
|
||||||
|
$use_cache = !($opt.f -or $opt.force)
|
||||||
|
$architecture = default_architecture
|
||||||
|
try {
|
||||||
|
$architecture = ensure_architecture ($opt.a + $opt.arch)
|
||||||
|
} catch {
|
||||||
|
abort "ERROR: $_"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$apps) { error '<app> missing'; my_usage; exit 1 }
|
||||||
|
|
||||||
|
if (is_scoop_outdated) {
|
||||||
|
if ($opt.u -or $opt.'no-update-scoop') {
|
||||||
|
warn "Scoop is out of date."
|
||||||
|
} else {
|
||||||
|
scoop update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# we only want to show this warning once
|
||||||
|
if(!$use_cache) { warn "Cache is being ignored." }
|
||||||
|
|
||||||
|
foreach ($curr_app in $apps) {
|
||||||
|
# Prevent leaking variables from previous iteration
|
||||||
|
$bucket = $version = $app = $manifest = $url = $null
|
||||||
|
|
||||||
|
$app, $bucket, $version = parse_app $curr_app
|
||||||
|
$app, $manifest, $bucket, $url = Find-Manifest $app $bucket
|
||||||
|
|
||||||
|
info "Starting download for $app..."
|
||||||
|
|
||||||
|
# Generate manifest if there is different version in manifest
|
||||||
|
if (($null -ne $version) -and ($manifest.version -ne $version)) {
|
||||||
|
$generated = generate_user_manifest $app $bucket $version
|
||||||
|
if ($null -eq $generated) {
|
||||||
|
error 'Manifest cannot be generated with provided version'
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$manifest = parse_json($generated)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$manifest) {
|
||||||
|
error "Couldn't find manifest for '$app'$(if($url) { " at the URL $url" })."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$version = $manifest.version
|
||||||
|
if(!$version) {
|
||||||
|
error "Manifest doesn't specify a version."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if($version -match '[^\w\.\-\+_]') {
|
||||||
|
error "Manifest version has unsupported character '$($matches[0])'."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$curr_check_hash = $check_hash
|
||||||
|
if ($version -eq 'nightly') {
|
||||||
|
$version = nightly_version $(get-date)
|
||||||
|
$curr_check_hash = $false
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(supports_architecture $manifest $architecture)) {
|
||||||
|
error "'$app' doesn't support $architecture architecture!"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Test-Aria2Enabled) {
|
||||||
|
dl_with_cache_aria2 $app $version $manifest $architecture $cachedir $manifest.cookie $use_cache $curr_check_hash
|
||||||
|
} else {
|
||||||
|
foreach($url in script:url $manifest $architecture) {
|
||||||
|
try {
|
||||||
|
dl_with_cache $app $version $url $null $manifest.cookie $use_cache
|
||||||
|
} catch {
|
||||||
|
write-host -f darkred $_
|
||||||
|
error "URL $url is not valid"
|
||||||
|
$dl_failure = $true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if($curr_check_hash) {
|
||||||
|
$manifest_hash = hash_for_url $manifest $url $architecture
|
||||||
|
$cached = cache_path $app $version $url
|
||||||
|
$ok, $err = check_hash $cached $manifest_hash (show_app $app $bucket)
|
||||||
|
|
||||||
|
if(!$ok) {
|
||||||
|
error $err
|
||||||
|
if(test-path $cached) {
|
||||||
|
# rm cached file
|
||||||
|
Remove-Item -force $cached
|
||||||
|
}
|
||||||
|
if ($url -like '*sourceforge.net*') {
|
||||||
|
warn 'SourceForge.net is known for causing hash validation fails. Please try again before opening a ticket.'
|
||||||
|
}
|
||||||
|
error (new_issue_msg $app $bucket "hash check failed")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info "Skipping hash verification."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$dl_failure) {
|
||||||
|
success "'$app' ($version) was downloaded successfully!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -2,12 +2,9 @@
|
|||||||
# Summary: Exports (an importable) list of installed apps
|
# Summary: Exports (an importable) list of installed apps
|
||||||
# Help: Lists all installed apps.
|
# Help: Lists all installed apps.
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'Select-CurrentVersion' (indirectly)
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
$def_arch = default_architecture
|
$def_arch = default_architecture
|
||||||
|
|
||||||
$local = installed_apps $false | ForEach-Object { @{ name = $_; global = $false } }
|
$local = installed_apps $false | ForEach-Object { @{ name = $_; global = $false } }
|
||||||
@@ -23,7 +20,7 @@ if($apps) {
|
|||||||
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
|
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
|
||||||
$app = $_.name
|
$app = $_.name
|
||||||
$global = $_.global
|
$global = $_.global
|
||||||
$ver = current_version $app $global
|
$ver = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
$global_display = $null; if($global) { $global_display = ' *global*'}
|
$global_display = $null; if($global) { $global_display = ' *global*'}
|
||||||
|
|
||||||
$install_info = install_info $app $ver $global
|
$install_info = install_info $app $ver $global
|
||||||
|
|||||||
@@ -2,12 +2,6 @@
|
|||||||
# Summary: Show help for a command
|
# Summary: Show help for a command
|
||||||
param($cmd)
|
param($cmd)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
|
||||||
. "$psscriptroot\..\lib\commands.ps1"
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
|
|
||||||
function print_help($cmd) {
|
function print_help($cmd) {
|
||||||
$file = Get-Content (command_path $cmd) -raw
|
$file = Get-Content (command_path $cmd) -raw
|
||||||
|
|
||||||
@@ -47,4 +41,3 @@ Some useful commands are:"
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Usage: scoop hold <apps>
|
# Usage: scoop hold <apps>
|
||||||
# Summary: Hold an app to disable updates
|
# Summary: Hold an app to disable updates
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1" # 'save_install_info' (indirectly)
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'install_info' 'Select-CurrentVersion' (indirectly)
|
||||||
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
$apps = $args
|
$apps = $args
|
||||||
|
|
||||||
if(!$apps) {
|
if(!$apps) {
|
||||||
@@ -21,13 +21,18 @@ $apps | ForEach-Object {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = versiondir $app 'current' $global
|
if (get_config NO_JUNCTIONS) {
|
||||||
$json = install_info $app 'current' $global
|
$version = Select-CurrentVersion -App $app -Global:$global
|
||||||
|
} else {
|
||||||
|
$version = 'current'
|
||||||
|
}
|
||||||
|
$dir = versiondir $app $version $global
|
||||||
|
$json = install_info $app $version $global
|
||||||
$install = @{}
|
$install = @{}
|
||||||
$json | Get-Member -MemberType Properties | ForEach-Object { $install.Add($_.Name, $json.($_.Name))}
|
$json | Get-Member -MemberType Properties | ForEach-Object { $install.Add($_.Name, $json.($_.Name))}
|
||||||
$install.hold = $true
|
$install.hold = $true
|
||||||
save_install_info $install $dir
|
save_install_info $install $dir
|
||||||
success "$app is now locked and can not be updated anymore."
|
success "$app is now held and can not be updated anymore."
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitcode
|
exit $exitcode
|
||||||
|
|||||||
@@ -2,24 +2,22 @@
|
|||||||
# Summary: Opens the app homepage
|
# Summary: Opens the app homepage
|
||||||
param($app)
|
param($app)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly)
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
if ($app) {
|
||||||
|
$null, $manifest, $bucket, $null = Find-Manifest $app
|
||||||
if($app) {
|
if ($manifest) {
|
||||||
$manifest, $bucket = find_manifest $app
|
if ($manifest.homepage) {
|
||||||
if($manifest) {
|
Start-Process $manifest.homepage
|
||||||
if([string]::isnullorempty($manifest.homepage)) {
|
} else {
|
||||||
abort "Could not find homepage in manifest for '$app'."
|
abort "Could not find homepage in manifest for '$app'."
|
||||||
}
|
}
|
||||||
Start-Process $manifest.homepage
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
abort "Could not find manifest for '$app'."
|
abort "Could not find manifest for '$app'."
|
||||||
}
|
}
|
||||||
} else { my_usage }
|
} else {
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
# Usage: scoop info <app>
|
# Usage: scoop info <app> [--verbose]
|
||||||
# Summary: Display information about an app
|
# Summary: Display information about an app
|
||||||
param($app)
|
# Options:
|
||||||
|
# -v, --verbose Show full paths and URLs
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly)
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Get-InstalledVersion'
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
$opt, $app, $err = getopt $args 'v' 'verbose'
|
||||||
|
if ($err) { error "scoop info: $err"; exit 1 }
|
||||||
|
$verbose = $opt.v -or $opt.verbose
|
||||||
|
|
||||||
if(!$app) { my_usage; exit 1 }
|
if (!$app) { my_usage; exit 1 }
|
||||||
|
|
||||||
if ($app -match '^(ht|f)tps?://|\\\\') {
|
if ($app -match '^(ht|f)tps?://|\\\\') {
|
||||||
# check if $app is a URL or UNC path
|
# check if $app is a URL or UNC path
|
||||||
@@ -27,7 +26,7 @@ if ($app -match '^(ht|f)tps?://|\\\\') {
|
|||||||
$global = installed $app $true
|
$global = installed $app $true
|
||||||
$app, $bucket, $null = parse_app $app
|
$app, $bucket, $null = parse_app $app
|
||||||
$status = app_status $app $global
|
$status = app_status $app $global
|
||||||
$manifest, $bucket = find_manifest $app $bucket
|
$app, $manifest, $bucket, $url = Find-Manifest $app $bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$manifest) {
|
if (!$manifest) {
|
||||||
@@ -35,105 +34,143 @@ if (!$manifest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$install = install_info $app $status.version $global
|
$install = install_info $app $status.version $global
|
||||||
|
$status.installed = $bucket -and $install.bucket -eq $bucket
|
||||||
$version_output = $manifest.version
|
$version_output = $manifest.version
|
||||||
if (!$manifest_file) {
|
if (!$manifest_file) {
|
||||||
$manifest_file = manifest_path $app $bucket
|
$manifest_file = if ($bucket) { manifest_path $app $bucket } else { $url }
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = versiondir $app 'current' $global
|
if ($verbose) {
|
||||||
$original_dir = versiondir $app $manifest.version $global
|
$dir = currentdir $app $global
|
||||||
$persist_dir = persistdir $app $global
|
$original_dir = versiondir $app $manifest.version $global
|
||||||
|
$persist_dir = persistdir $app $global
|
||||||
|
} else {
|
||||||
|
$dir, $original_dir, $persist_dir = "<root>", "<root>", "<root>"
|
||||||
|
}
|
||||||
|
|
||||||
if($status.installed) {
|
if ($status.installed) {
|
||||||
$manifest_file = manifest_path $app $install.bucket
|
$manifest_file = manifest_path $app $install.bucket
|
||||||
if ($install.url) {
|
if ($install.url) {
|
||||||
$manifest_file = $install.url
|
$manifest_file = $install.url
|
||||||
}
|
}
|
||||||
if($status.version -eq $manifest.version) {
|
if ($status.version -eq $manifest.version) {
|
||||||
$version_output = $status.version
|
$version_output = $status.version
|
||||||
} else {
|
} else {
|
||||||
$version_output = "$($status.version) (Update to $($manifest.version) available)"
|
$version_output = "$($status.version) (Update to $($manifest.version) available)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Output "Name: $app"
|
$item = [ordered]@{ Name = $app }
|
||||||
if ($manifest.description) {
|
if ($manifest.description) {
|
||||||
Write-Output "Description: $($manifest.description)"
|
$item.Description = $manifest.description
|
||||||
|
}
|
||||||
|
$item.Version = $version_output
|
||||||
|
if ($bucket) {
|
||||||
|
$item.Bucket = $bucket
|
||||||
|
}
|
||||||
|
if ($manifest.homepage) {
|
||||||
|
$item.Website = $manifest.homepage.TrimEnd('/')
|
||||||
}
|
}
|
||||||
Write-Output "Version: $version_output"
|
|
||||||
Write-Output "Website: $($manifest.homepage)"
|
|
||||||
# Show license
|
# Show license
|
||||||
if ($manifest.license) {
|
if ($manifest.license) {
|
||||||
$license = $manifest.license
|
$item.License = if ($manifest.license.identifier -and $manifest.license.url) {
|
||||||
if ($manifest.license.identifier -and $manifest.license.url) {
|
if ($verbose) { "$($manifest.license.identifier) ($($manifest.license.url))" } else { $manifest.license.identifier }
|
||||||
$license = "$($manifest.license.identifier) ($($manifest.license.url))"
|
|
||||||
} elseif ($manifest.license -match '^((ht)|f)tps?://') {
|
} elseif ($manifest.license -match '^((ht)|f)tps?://') {
|
||||||
$license = "$($manifest.license)"
|
$manifest.license
|
||||||
} elseif ($manifest.license -match '[|,]') {
|
} elseif ($manifest.license -match '[|,]') {
|
||||||
$licurl = $manifest.license.Split("|,") | ForEach-Object {"https://spdx.org/licenses/$_.html"}
|
if ($verbose) {
|
||||||
$license = "$($manifest.license) ($($licurl -join ', '))"
|
"$($manifest.license) ($(($manifest.license -Split "\||," | ForEach-Object { "https://spdx.org/licenses/$_.html" }) -join ', '))"
|
||||||
|
} else {
|
||||||
|
$manifest.license
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$license = "$($manifest.license) (https://spdx.org/licenses/$($manifest.license).html)"
|
if ($verbose) { "$($manifest.license) (https://spdx.org/licenses/$($manifest.license).html)" } else { $manifest.license }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($manifest.depends) {
|
||||||
|
$item.Dependencies = $manifest.depends -join ' | '
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $manifest_file) {
|
||||||
|
if (Get-Command git -ErrorAction Ignore) {
|
||||||
|
$gitinfo = (git -C (Split-Path $manifest_file) log -1 -s --format='%aD#%an' $manifest_file 2> $null) -Split '#'
|
||||||
|
}
|
||||||
|
if ($gitinfo) {
|
||||||
|
$item.'Updated at' = $gitinfo[0] | Get-Date
|
||||||
|
$item.'Updated by' = $gitinfo[1]
|
||||||
|
} else {
|
||||||
|
$item.'Updated at' = (Get-Item $manifest_file).LastWriteTime
|
||||||
|
$item.'Updated by' = (Get-Acl $manifest_file).Owner.Split('\')[-1]
|
||||||
}
|
}
|
||||||
Write-Output "License: $license"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Manifest file
|
# Manifest file
|
||||||
Write-Output "Manifest:`n $manifest_file"
|
if ($verbose) { $item.Manifest = $manifest_file }
|
||||||
|
|
||||||
if($status.installed) {
|
if ($status.installed) {
|
||||||
# Show installed versions
|
# Show installed versions
|
||||||
Write-Output "Installed:"
|
$installed_output = @()
|
||||||
$versions = versions $app $global
|
Get-InstalledVersion -AppName $app -Global:$global | ForEach-Object {
|
||||||
$versions | ForEach-Object {
|
$installed_output += if ($verbose) { versiondir $app $_ $global } else { "$_$(if ($global) { " *global*" })" }
|
||||||
$dir = versiondir $app $_ $global
|
|
||||||
if($global) { $dir += " *global*" }
|
|
||||||
Write-Output " $dir"
|
|
||||||
}
|
}
|
||||||
} else {
|
$item.Installed = $installed_output -join "`n"
|
||||||
Write-Output "Installed: No"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$binaries = @(arch_specific 'bin' $manifest $install.architecture)
|
$binaries = @(arch_specific 'bin' $manifest $install.architecture)
|
||||||
if($binaries) {
|
if ($binaries) {
|
||||||
$binary_output = "Binaries:`n "
|
$binary_output = @()
|
||||||
$binaries | ForEach-Object {
|
$binaries | ForEach-Object {
|
||||||
if($_ -is [System.Array]) {
|
if ($_ -is [System.Array]) {
|
||||||
$binary_output += " $($_[1]).exe"
|
$binary_output += "$($_[1]).$($_[0].Split('.')[-1])"
|
||||||
} else {
|
} else {
|
||||||
$binary_output += " $_"
|
$binary_output += $_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Write-Output $binary_output
|
$item.Binaries = $binary_output -join " | "
|
||||||
|
}
|
||||||
|
$shortcuts = @(arch_specific 'shortcuts' $manifest $install.architecture)
|
||||||
|
if ($shortcuts) {
|
||||||
|
$shortcut_output = @()
|
||||||
|
$shortcuts | ForEach-Object {
|
||||||
|
$shortcut_output += $_[1]
|
||||||
|
}
|
||||||
|
$item.Shortcuts = $shortcut_output -join " | "
|
||||||
|
}
|
||||||
|
$env_set = arch_specific 'env_set' $manifest $install.architecture
|
||||||
|
if ($env_set) {
|
||||||
|
$env_vars = @()
|
||||||
|
$env_set | Get-Member -member noteproperty | ForEach-Object {
|
||||||
|
$env_vars += "$($_.name) = $(format $env_set.$($_.name) @{ "dir" = $dir })"
|
||||||
|
}
|
||||||
|
$item.Environment = $env_vars -join "`n"
|
||||||
|
}
|
||||||
|
$env_add_path = arch_specific 'env_add_path' $manifest $install.architecture
|
||||||
|
if ($env_add_path) {
|
||||||
|
$env_path = @()
|
||||||
|
$env_add_path | Where-Object { $_ } | ForEach-Object {
|
||||||
|
$env_path += if ($_ -eq '.') {
|
||||||
|
$dir
|
||||||
|
} else {
|
||||||
|
"$dir\$_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$item.'Path Added' = $env_path -join "`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
if($manifest.env_set -or $manifest.env_add_path) {
|
if ($manifest.suggest) {
|
||||||
if($status.installed) {
|
$suggest_output = @()
|
||||||
Write-Output "Environment:"
|
$manifest.suggest.PSObject.Properties | ForEach-Object {
|
||||||
} else {
|
$suggest_output += $_.Value -join ' | '
|
||||||
Write-Output "Environment: (simulated)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($manifest.env_set) {
|
|
||||||
$manifest.env_set | Get-Member -member noteproperty | ForEach-Object {
|
|
||||||
$value = env $_.name $global
|
|
||||||
if(!$value) {
|
|
||||||
$value = format $manifest.env_set.$($_.name) @{ "dir" = $dir }
|
|
||||||
}
|
|
||||||
Write-Output " $($_.name)=$value"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($manifest.env_add_path) {
|
|
||||||
$manifest.env_add_path | Where-Object { $_ } | ForEach-Object {
|
|
||||||
if($_ -eq '.') {
|
|
||||||
Write-Output " PATH=%PATH%;$dir"
|
|
||||||
} else {
|
|
||||||
Write-Output " PATH=%PATH%;$dir\$_"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
$item.Suggestions = $suggest_output -join ' | '
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show notes
|
if ($manifest.notes) {
|
||||||
show_notes $manifest $dir $original_dir $persist_dir
|
# Show notes
|
||||||
|
$item.Notes = (substitute $manifest.notes @{ '$dir' = $dir; '$original_dir' = $original_dir; '$persist_dir' = $persist_dir }) -join "`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
[PSCustomObject]$item
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -13,41 +13,22 @@
|
|||||||
# -g, --global Install the app globally
|
# -g, --global Install the app globally
|
||||||
# -i, --independent Don't install dependencies automatically
|
# -i, --independent Don't install dependencies automatically
|
||||||
# -k, --no-cache Don't use the download cache
|
# -k, --no-cache Don't use the download cache
|
||||||
|
# -u, --no-update-scoop Don't update Scoop before installing if it's outdated
|
||||||
# -s, --skip Skip hash validation (use with caution!)
|
# -s, --skip Skip hash validation (use with caution!)
|
||||||
# -a, --arch <32bit|64bit> Use the specified architecture, if the app supports it
|
# -a, --arch <32bit|64bit> Use the specified architecture, if the app supports it
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1" # 'autoupdate.ps1' 'manifest.ps1' (indirectly)
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\autoupdate.ps1" # 'generate_user_manifest' (indirectly)
|
||||||
. "$psscriptroot\..\lib\decompress.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'default_architecture' 'generate_user_manifest' 'Select-CurrentVersion' (indirectly)
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$psscriptroot\..\lib\shortcuts.ps1"
|
. "$PSScriptRoot\..\lib\decompress.ps1"
|
||||||
. "$psscriptroot\..\lib\psmodules.ps1"
|
. "$PSScriptRoot\..\lib\shortcuts.ps1"
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\psmodules.ps1"
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1"
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
. "$PSScriptRoot\..\lib\depends.ps1"
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
$opt, $apps, $err = getopt $args 'gikusa:' 'global', 'independent', 'no-cache', 'no-update-scoop', 'skip', 'arch='
|
||||||
|
|
||||||
function is_installed($app, $global) {
|
|
||||||
if ($app.EndsWith('.json')) {
|
|
||||||
$app = [System.IO.Path]::GetFileNameWithoutExtension($app)
|
|
||||||
}
|
|
||||||
if (installed $app $global) {
|
|
||||||
function gf($g) { if ($g) { ' --global' } }
|
|
||||||
|
|
||||||
$version = @(versions $app $global)[-1]
|
|
||||||
if (!(install_info $app $version $global)) {
|
|
||||||
error "It looks like a previous installation of $app failed.`nRun 'scoop uninstall $app$(gf $global)' before retrying the install."
|
|
||||||
}
|
|
||||||
warn "'$app' ($version) is already installed.`nUse 'scoop update $app$(gf $global)' to install a new version."
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
|
|
||||||
$opt, $apps, $err = getopt $args 'gfiksa:' 'global', 'force', 'independent', 'no-cache', 'skip', 'arch='
|
|
||||||
if ($err) { "scoop install: $err"; exit 1 }
|
if ($err) { "scoop install: $err"; exit 1 }
|
||||||
|
|
||||||
$global = $opt.g -or $opt.global
|
$global = $opt.g -or $opt.global
|
||||||
@@ -68,13 +49,24 @@ if ($global -and !(is_admin)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_scoop_outdated) {
|
if (is_scoop_outdated) {
|
||||||
scoop update
|
if ($opt.u -or $opt.'no-update-scoop') {
|
||||||
|
warn "Scoop is out of date."
|
||||||
|
} else {
|
||||||
|
scoop update
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ensure_none_failed $apps
|
||||||
|
|
||||||
if ($apps.length -eq 1) {
|
if ($apps.length -eq 1) {
|
||||||
$app, $null, $version = parse_app $apps
|
$app, $null, $version = parse_app $apps
|
||||||
if ($null -eq $version -and (is_installed $app $global)) {
|
if ($app.EndsWith('.json')) {
|
||||||
return
|
$app = [System.IO.Path]::GetFileNameWithoutExtension($app)
|
||||||
|
}
|
||||||
|
$curVersion = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
|
if ($null -eq $version -and $curVersion) {
|
||||||
|
warn "'$app' ($curVersion) is already installed.`nUse 'scoop update $app$(if ($global) { ' --global' })' to install a new version."
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +86,8 @@ if ($specific_versions.length -gt 0) {
|
|||||||
$specific_versions_paths = $specific_versions | ForEach-Object {
|
$specific_versions_paths = $specific_versions | ForEach-Object {
|
||||||
$app, $bucket, $version = parse_app $_
|
$app, $bucket, $version = parse_app $_
|
||||||
if (installed_manifest $app $version) {
|
if (installed_manifest $app $version) {
|
||||||
abort "'$app' ($version) is already installed.`nUse 'scoop update $app$global_flag' to install a new version."
|
warn "'$app' ($version) is already installed.`nUse 'scoop update $app$(if ($global) { " --global" })' to install a new version."
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_user_manifest $app $bucket $version
|
generate_user_manifest $app $bucket $version
|
||||||
@@ -106,22 +99,23 @@ $apps = @(($specific_versions_paths + $difference) | Where-Object { $_ } | Sort-
|
|||||||
$explicit_apps = $apps
|
$explicit_apps = $apps
|
||||||
|
|
||||||
if (!$independent) {
|
if (!$independent) {
|
||||||
$apps = install_order $apps $architecture # adds dependencies
|
$apps = $apps | Get-Dependency -Architecture $architecture | Select-Object -Unique # adds dependencies
|
||||||
}
|
}
|
||||||
ensure_none_failed $apps $global
|
ensure_none_failed $apps
|
||||||
|
|
||||||
$apps, $skip = prune_installed $apps $global
|
$apps, $skip = prune_installed $apps $global
|
||||||
|
|
||||||
$skip | Where-Object { $explicit_apps -contains $_ } | ForEach-Object {
|
$skip | Where-Object { $explicit_apps -contains $_ } | ForEach-Object {
|
||||||
$app, $null, $null = parse_app $_
|
$app, $null, $null = parse_app $_
|
||||||
$version = @(versions $app $global)[-1]
|
$version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
warn "'$app' ($version) is already installed. Skipping."
|
warn "'$app' ($version) is already installed. Skipping."
|
||||||
}
|
}
|
||||||
|
|
||||||
$suggested = @{ };
|
$suggested = @{ };
|
||||||
if (Test-Aria2Enabled) {
|
if ((Test-Aria2Enabled) -and (get_config 'aria2-warning-enabled' $true)) {
|
||||||
warn "Scoop uses 'aria2c' for multi-connection downloads."
|
warn "Scoop uses 'aria2c' for multi-connection downloads."
|
||||||
warn "Should it cause issues, run 'scoop config aria2-enabled false' to disable it."
|
warn "Should it cause issues, run 'scoop config aria2-enabled false' to disable it."
|
||||||
|
warn "To disable this warning, run 'scoop config aria2-warning-enabled false'."
|
||||||
}
|
}
|
||||||
$apps | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash }
|
$apps | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash }
|
||||||
|
|
||||||
|
|||||||
@@ -3,49 +3,60 @@
|
|||||||
# Help: Lists all installed apps, or the apps matching the supplied query.
|
# Help: Lists all installed apps, or the apps matching the supplied query.
|
||||||
param($query)
|
param($query)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'parse_json' 'Select-CurrentVersion' (indirectly)
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
$def_arch = default_architecture
|
$def_arch = default_architecture
|
||||||
|
if (-not (Get-FormatData ScoopApps)) {
|
||||||
|
Update-FormatData "$PSScriptRoot\..\supporting\formats\ScoopTypes.Format.ps1xml"
|
||||||
|
}
|
||||||
|
|
||||||
$local = installed_apps $false | ForEach-Object { @{ name = $_ } }
|
$local = installed_apps $false | ForEach-Object { @{ name = $_ } }
|
||||||
$global = installed_apps $true | ForEach-Object { @{ name = $_; global = $true } }
|
$global = installed_apps $true | ForEach-Object { @{ name = $_; global = $true } }
|
||||||
|
|
||||||
$apps = @($local) + @($global)
|
$apps = @($local) + @($global)
|
||||||
|
if (-not $apps) {
|
||||||
if($apps) {
|
Write-Host "There aren't any apps installed."
|
||||||
write-host "Installed apps$(if($query) { `" matching '$query'`"}): `n"
|
|
||||||
$apps | Sort-Object { $_.name } | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
|
|
||||||
$app = $_.name
|
|
||||||
$global = $_.global
|
|
||||||
$ver = current_version $app $global
|
|
||||||
|
|
||||||
$install_info = install_info $app $ver $global
|
|
||||||
write-host " $app " -NoNewline
|
|
||||||
write-host -f DarkCyan $ver -NoNewline
|
|
||||||
|
|
||||||
if($global) { write-host -f DarkGreen ' *global*' -NoNewline }
|
|
||||||
|
|
||||||
if (!$install_info) { Write-Host ' *failed*' -ForegroundColor DarkRed -NoNewline }
|
|
||||||
if ($install_info.hold) { Write-Host ' *hold*' -ForegroundColor DarkMagenta -NoNewline }
|
|
||||||
|
|
||||||
if ($install_info.bucket -and ($install_info.bucket -ne 'main')) {
|
|
||||||
write-host -f Yellow " [$($install_info.bucket)]" -NoNewline
|
|
||||||
} elseif ($install_info.url) {
|
|
||||||
write-host -f Yellow " [$($install_info.url)]" -NoNewline
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($install_info.architecture -and $def_arch -ne $install_info.architecture) {
|
|
||||||
write-host -f DarkRed " {$($install_info.architecture)}" -NoNewline
|
|
||||||
}
|
|
||||||
write-host ''
|
|
||||||
}
|
|
||||||
write-host ''
|
|
||||||
exit 0
|
|
||||||
} else {
|
|
||||||
write-host "There aren't any apps installed."
|
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$list = @()
|
||||||
|
Write-Host "Installed apps$(if($query) { `" matching '$query'`"}):"
|
||||||
|
$apps | Where-Object { !$query -or ($_.name -match $query) } | ForEach-Object {
|
||||||
|
$app = $_.name
|
||||||
|
$global = $_.global
|
||||||
|
$item = @{}
|
||||||
|
$ver = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
|
$item.Name = $app
|
||||||
|
$item.Version = $ver
|
||||||
|
|
||||||
|
$install_info_path = "$(versiondir $app $ver $global)\install.json"
|
||||||
|
$updated = (Get-Item (appdir $app $global)).LastWriteTime
|
||||||
|
$install_info = $null
|
||||||
|
if (Test-Path $install_info_path) {
|
||||||
|
$install_info = parse_json $install_info_path
|
||||||
|
$updated = (Get-Item $install_info_path).LastWriteTime
|
||||||
|
}
|
||||||
|
|
||||||
|
$item.Source = if ($install_info.bucket) {
|
||||||
|
$install_info.bucket
|
||||||
|
} elseif ($install_info.url) {
|
||||||
|
if ($install_info.url -eq (usermanifest $app)) { '<auto-generated>' }
|
||||||
|
else { $install_info.url }
|
||||||
|
}
|
||||||
|
$item.Updated = $updated
|
||||||
|
|
||||||
|
$info = @()
|
||||||
|
if ($global) { $info += 'Global install' }
|
||||||
|
if (failed $app $global) { $info += 'Install failed' }
|
||||||
|
if ($install_info.hold) { $info += 'Held package' }
|
||||||
|
if ($install_info.architecture -and $def_arch -ne $install_info.architecture) {
|
||||||
|
$info += $install_info.architecture
|
||||||
|
}
|
||||||
|
$item.Info = $info -join ', '
|
||||||
|
|
||||||
|
$list += [PSCustomObject]$item
|
||||||
|
}
|
||||||
|
|
||||||
|
$list | Add-Member -TypeName 'ScoopApps' -PassThru
|
||||||
|
exit 0
|
||||||
|
|||||||
@@ -2,21 +2,19 @@
|
|||||||
# Summary: Returns the path to the specified app
|
# Summary: Returns the path to the specified app
|
||||||
param($app)
|
param($app)
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'currentdir' (indirectly)
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
if (!$app) {
|
||||||
|
my_usage
|
||||||
if(!$app) { my_usage; exit 1 }
|
exit 1
|
||||||
|
|
||||||
$app_path = versiondir $app 'current' $false
|
|
||||||
if(!(Test-Path $app_path)) {
|
|
||||||
$app_path = versiondir $app 'current' $true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Test-Path $app_path) {
|
$app_path = currentdir $app $false
|
||||||
|
if (!(Test-Path $app_path)) {
|
||||||
|
$app_path = currentdir $app $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-Path $app_path) {
|
||||||
Write-Output $app_path
|
Write-Output $app_path
|
||||||
} else {
|
} else {
|
||||||
abort "Could not find app path for '$app'."
|
abort "Could not find app path for '$app'."
|
||||||
|
|||||||
@@ -4,15 +4,12 @@
|
|||||||
# if you've installed 'python' and 'python27', you can use 'scoop reset' to switch between
|
# if you've installed 'python' and 'python27', you can use 'scoop reset' to switch between
|
||||||
# using one or the other.
|
# using one or the other.
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Select-CurrentVersion' (indirectly)
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\shortcuts.ps1"
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
|
||||||
. "$psscriptroot\..\lib\shortcuts.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
$opt, $apps, $err = getopt $args
|
$opt, $apps, $err = getopt $args
|
||||||
if($err) { "scoop reset: $err"; exit 1 }
|
if($err) { "scoop reset: $err"; exit 1 }
|
||||||
|
|
||||||
@@ -45,7 +42,7 @@ $apps | ForEach-Object {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($null -eq $version) {
|
if ($null -eq $version) {
|
||||||
$version = current_version $app $global
|
$version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
}
|
}
|
||||||
|
|
||||||
$manifest = installed_manifest $app $version $global
|
$manifest = installed_manifest $app $version $global
|
||||||
@@ -67,16 +64,22 @@ $apps | ForEach-Object {
|
|||||||
$original_dir = $dir
|
$original_dir = $dir
|
||||||
$persist_dir = persistdir $app $global
|
$persist_dir = persistdir $app $global
|
||||||
|
|
||||||
|
#region Workaround for #2952
|
||||||
|
if (test_running_process $app $global) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
#endregion Workaround for #2952
|
||||||
|
|
||||||
$install = install_info $app $version $global
|
$install = install_info $app $version $global
|
||||||
$architecture = $install.architecture
|
$architecture = $install.architecture
|
||||||
|
|
||||||
$dir = link_current $dir
|
$dir = link_current $dir
|
||||||
create_shims $manifest $dir $global $architecture
|
create_shims $manifest $dir $global $architecture
|
||||||
create_startmenu_shortcuts $manifest $dir $global $architecture
|
create_startmenu_shortcuts $manifest $dir $global $architecture
|
||||||
env_add_path $manifest $dir
|
env_add_path $manifest $dir $global $architecture
|
||||||
env_set $manifest $dir $global
|
env_set $manifest $dir $global $architecture
|
||||||
# unlink all potential old link before re-persisting
|
# unlink all potential old link before re-persisting
|
||||||
unlink_persist_data $original_dir
|
unlink_persist_data $manifest $original_dir
|
||||||
persist_data $manifest $original_dir $persist_dir
|
persist_data $manifest $original_dir $persist_dir
|
||||||
persist_permission $manifest $global
|
persist_permission $manifest $global
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,9 @@
|
|||||||
# If used with [query], shows app names that match the query.
|
# If used with [query], shows app names that match the query.
|
||||||
# Without [query], shows all the available apps.
|
# Without [query], shows all the available apps.
|
||||||
param($query)
|
param($query)
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'manifest'
|
||||||
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Get-LatestVersion'
|
||||||
|
|
||||||
function bin_match($manifest, $query) {
|
function bin_match($manifest, $query) {
|
||||||
if(!$manifest.bin) { return $false }
|
if(!$manifest.bin) { return $false }
|
||||||
@@ -44,32 +41,30 @@ function search_bucket($bucket, $query) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$apps | ForEach-Object { $_.version = (latest_version $_.name $bucket); $_ }
|
$apps | ForEach-Object { $_.version = (Get-LatestVersion -AppName $_.name -Bucket $bucket); $_ }
|
||||||
}
|
}
|
||||||
|
|
||||||
function download_json($url) {
|
function download_json($url) {
|
||||||
$progressPreference = 'silentlycontinue'
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
$result = invoke-webrequest $url -UseBasicParsing | Select-Object -exp content | convertfrom-json
|
$result = Invoke-WebRequest $url -UseBasicParsing | Select-Object -ExpandProperty content | ConvertFrom-Json
|
||||||
$progressPreference = 'continue'
|
$ProgressPreference = 'Continue'
|
||||||
$result
|
$result
|
||||||
}
|
}
|
||||||
|
|
||||||
function github_ratelimit_reached {
|
function github_ratelimit_reached {
|
||||||
$api_link = "https://api.github.com/rate_limit"
|
$api_link = 'https://api.github.com/rate_limit'
|
||||||
(download_json $api_link).rate.remaining -eq 0
|
(download_json $api_link).rate.remaining -eq 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function search_remote($bucket, $query) {
|
function search_remote($bucket, $query) {
|
||||||
$repo = known_bucket_repo $bucket
|
$uri = [System.Uri](known_bucket_repo $bucket)
|
||||||
|
if ($uri.AbsolutePath -match '/([a-zA-Z0-9]*)/([a-zA-Z0-9-]*)(?:.git|/)?') {
|
||||||
$uri = [system.uri]($repo)
|
$user = $Matches[1]
|
||||||
if ($uri.absolutepath -match '/([a-zA-Z0-9]*)/([a-zA-Z0-9-]*)(.git|/)?') {
|
$repo_name = $Matches[2]
|
||||||
$user = $matches[1]
|
|
||||||
$repo_name = $matches[2]
|
|
||||||
$api_link = "https://api.github.com/repos/$user/$repo_name/git/trees/HEAD?recursive=1"
|
$api_link = "https://api.github.com/repos/$user/$repo_name/git/trees/HEAD?recursive=1"
|
||||||
$result = download_json $api_link | Select-Object -exp tree | Where-Object {
|
$result = download_json $api_link | Select-Object -ExpandProperty tree |
|
||||||
$_.path -match "(^(.*$query.*).json$)"
|
Where-Object -Value "^(?:bucket/)?(.*$query.*)\.json$" -Property Path -Match |
|
||||||
} | ForEach-Object { $matches[2] }
|
ForEach-Object { $Matches[1] }
|
||||||
}
|
}
|
||||||
|
|
||||||
$result
|
$result
|
||||||
@@ -90,7 +85,7 @@ function search_remotes($query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$results | ForEach-Object {
|
$results | ForEach-Object {
|
||||||
"'$($_.bucket)' bucket:"
|
"'$($_.bucket)' bucket (install using 'scoop install $($_.bucket)/<app>'):"
|
||||||
$_.results | ForEach-Object { " $_" }
|
$_.results | ForEach-Object { " $_" }
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|||||||
240
libexec/scoop-shim.ps1
Normal file
240
libexec/scoop-shim.ps1
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
# Usage: scoop shim <subcommand> [<shim_names>] [<command_path> [<args>...]] [-g(lobal)]
|
||||||
|
# Summary: Manipulate Scoop shims
|
||||||
|
# Help: Manipulate Scoop shims: add, rm, list, info, alter, etc.
|
||||||
|
#
|
||||||
|
# To add a custom shim, use the 'add' subcommand:
|
||||||
|
#
|
||||||
|
# scoop shim add <shim_name> <command_path> [<args>...]
|
||||||
|
#
|
||||||
|
# To remove a shim, use the 'rm' subcommand (CAUTION: this could remove shims added by an app manifest):
|
||||||
|
#
|
||||||
|
# scoop shim rm <shim_names>
|
||||||
|
#
|
||||||
|
# To list all shims or matching shims, use the 'list' subcommand:
|
||||||
|
#
|
||||||
|
# scoop shim list [<shim_names>]
|
||||||
|
#
|
||||||
|
# To show a shim's information, use the 'info' subcommand:
|
||||||
|
#
|
||||||
|
# scoop shim info <shim_name>
|
||||||
|
#
|
||||||
|
# To alternate a shim's target source, use the 'alter' subcommand:
|
||||||
|
#
|
||||||
|
# scoop shim alter <shim_name>
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -g(lobal) Add/Remove/Info/Alter global shim(s)
|
||||||
|
# (NOTICE: USING SINGLE DASH)
|
||||||
|
# (HINT: To pass arguments like '-g' or '-global' to the shim, use quotes)
|
||||||
|
|
||||||
|
param($SubCommand, $ShimName, [Switch]$global)
|
||||||
|
|
||||||
|
. "$PSScriptRoot\..\lib\install.ps1" # for rm_shim
|
||||||
|
|
||||||
|
if ($SubCommand -notin @('add', 'rm', 'list', 'info', 'alter')) {
|
||||||
|
'ERROR: <subcommand> must be one of: add, rm, list, info, alter'
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($SubCommand -ne 'list' -and !$ShimName) {
|
||||||
|
"ERROR: <shim_name> must be specified for subcommand '$SubCommand'"
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Args) {
|
||||||
|
switch ($SubCommand) {
|
||||||
|
'add' {
|
||||||
|
if ($Args[0] -like '-*') {
|
||||||
|
"ERROR: <command_path> must be specified for subcommand 'add'"
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
} else {
|
||||||
|
if (($Args -join ' ') -match "^'(.*?)'\s*(.*?)$") {
|
||||||
|
$commandPath = $Matches[1]
|
||||||
|
$commandArgs = $Matches[2]
|
||||||
|
} else {
|
||||||
|
$commandPath = $Args[0]
|
||||||
|
if ($Args.Length -gt 1) {
|
||||||
|
$commandArgs = $Args[1..($Args.Length - 1)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'rm' {
|
||||||
|
$ShimName = @($ShimName) + $Args
|
||||||
|
}
|
||||||
|
'list' {
|
||||||
|
$ShimName = (@($ShimName) + $Args) -join '|'
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
# For 'info' and 'alter'
|
||||||
|
"ERROR: Option $Args not recognized."
|
||||||
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Get-FormatData ScoopShims)) {
|
||||||
|
Update-FormatData "$PSScriptRoot\..\supporting\formats\ScoopTypes.Format.ps1xml"
|
||||||
|
}
|
||||||
|
|
||||||
|
$localShimDir = shimdir $false
|
||||||
|
$globalShimDir = shimdir $true
|
||||||
|
|
||||||
|
function Get-ShimInfo($ShimPath) {
|
||||||
|
$info = [Ordered]@{}
|
||||||
|
$info.Name = strip_ext (fname $ShimPath)
|
||||||
|
$info.Path = $ShimPath -replace 'shim$', 'exe'
|
||||||
|
$info.Source = (get_app_name_from_shim $ShimPath) -replace '^$', 'External'
|
||||||
|
$info.Type = if ($ShimPath.EndsWith('.ps1')) { 'ExternalScript' } else { 'Application' }
|
||||||
|
$altShims = Get-Item -Path "$ShimPath.*" -Exclude '*.shim', '*.cmd', '*.ps1'
|
||||||
|
if ($altShims) {
|
||||||
|
$info.Alternatives = (@($info.Source) + ($altShims | ForEach-Object { $_.Extension.Remove(0, 1) } | Select-Object -Unique)) -join ' '
|
||||||
|
}
|
||||||
|
$info.IsGlobal = $ShimPath.StartsWith("$globalShimDir")
|
||||||
|
$info.IsHidden = !((Get-Command -Name $info.Name).Path -eq $info.Path)
|
||||||
|
[PSCustomObject]$info
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ShimPath($ShimName, $Global) {
|
||||||
|
'.shim', '.ps1' | ForEach-Object {
|
||||||
|
$shimPath = Join-Path (shimdir $Global) "$ShimName$_"
|
||||||
|
if (Test-Path $shimPath) {
|
||||||
|
return $shimPath
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-ShimTarget($ShimPath) {
|
||||||
|
if ($ShimPath) {
|
||||||
|
$shimTarget = if ($ShimPath.EndsWith('.shim')) {
|
||||||
|
(Get-Content -Path $ShimPath | Select-Object -First 1).Replace('path = ', '').Replace('"', '')
|
||||||
|
} else {
|
||||||
|
((Select-String -Path $ShimPath -Pattern '^(?:@rem|#)\s*(.*)$').Matches.Groups | Select-Object -Index 1).Value
|
||||||
|
}
|
||||||
|
if (!$shimTarget) {
|
||||||
|
$shimTarget = ((Select-String -Path $ShimPath -Pattern '[''"]([^@&]*?)[''"]' -AllMatches).Matches.Groups | Select-Object -Last 1).Value
|
||||||
|
}
|
||||||
|
$shimTarget | Convert-Path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($SubCommand) {
|
||||||
|
'add' {
|
||||||
|
if ($commandPath -notmatch '[\\/]') {
|
||||||
|
$shortPath = $commandPath
|
||||||
|
$commandPath = Get-ShimTarget (Get-ShimPath $shortPath $global)
|
||||||
|
if (!$commandPath) {
|
||||||
|
$exCommand = Get-Command $shortPath -ErrorAction SilentlyContinue
|
||||||
|
if ($exCommand -and $exCommand.CommandType -eq 'Application') {
|
||||||
|
$commandPath = $exCommand.Path
|
||||||
|
} # TODO - add support for more command types: Alias, Cmdlet, ExternalScript, Filter, Function, Script, and Workflow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($commandPath -and (Test-Path $commandPath)) {
|
||||||
|
Write-Host "Adding $(if ($global) { 'global' } else { 'local' }) shim " -NoNewline
|
||||||
|
Write-Host $shimName -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host '...'
|
||||||
|
shim $commandPath $global $shimName $commandArgs
|
||||||
|
} else {
|
||||||
|
abort "ERROR: '$($Args[0])' does not exist" 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'rm' {
|
||||||
|
$failed = @()
|
||||||
|
$ShimName | ForEach-Object {
|
||||||
|
if (Get-ShimPath $_ $global) {
|
||||||
|
rm_shim $_ (shimdir $global)
|
||||||
|
} else {
|
||||||
|
$failed += $_
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($failed) {
|
||||||
|
Write-Host 'Shims not found: ' -NoNewline
|
||||||
|
Write-Host $failed -ForegroundColor Cyan
|
||||||
|
exit 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'list' {
|
||||||
|
$shims = Get-ChildItem -Path $localShimDir -Recurse -Include '*.shim', '*.ps1' |
|
||||||
|
Where-Object { !$ShimName -or ($_.BaseName -match $ShimName) } |
|
||||||
|
Select-Object -ExpandProperty FullName
|
||||||
|
if (Test-Path $globalShimDir) {
|
||||||
|
$shims += Get-ChildItem -Path $globalShimDir -Recurse -Include '*.shim', '*.ps1' |
|
||||||
|
Where-Object { !$ShimName -or ($_.BaseName -match $ShimName) } |
|
||||||
|
Select-Object -ExpandProperty FullName
|
||||||
|
}
|
||||||
|
$shims.ForEach({ Get-ShimInfo $_ }) | Add-Member -TypeName 'ScoopShims' -PassThru
|
||||||
|
}
|
||||||
|
'info' {
|
||||||
|
$shimPath = Get-ShimPath $ShimName $global
|
||||||
|
if ($shimPath) {
|
||||||
|
Get-ShimInfo $shimPath
|
||||||
|
} else {
|
||||||
|
Write-Host "$(if ($global) { 'Global' } else { 'Local' }) shim not found: " -NoNewline
|
||||||
|
Write-Host $ShimName -ForegroundColor Cyan
|
||||||
|
if (Get-ShimPath $ShimName (!$global)) {
|
||||||
|
Write-Host "But a $(if ($global) { 'local' } else {'global' }) shim exists, " -NoNewline
|
||||||
|
Write-Host "run 'scoop shim info $ShimName$(if (!$global) { ' -global' })' to show its info"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
exit 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'alter' {
|
||||||
|
$shimPath = Get-ShimPath $ShimName $global
|
||||||
|
if ($shimPath) {
|
||||||
|
$shimInfo = Get-ShimInfo $shimPath
|
||||||
|
if ($null -eq $shimInfo.Alternatives) {
|
||||||
|
Write-Host 'No alternatives of ' -NoNewline
|
||||||
|
Write-Host $ShimName -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host ' found.'
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
$shimInfo.Alternatives = $shimInfo.Alternatives.Split(' ')
|
||||||
|
[System.Management.Automation.Host.ChoiceDescription[]]$altApps = 1..$shimInfo.Alternatives.Length | ForEach-Object {
|
||||||
|
New-Object System.Management.Automation.Host.ChoiceDescription "&$($_)`b$($shimInfo.Alternatives[$_ - 1])", "Sets '$ShimName' shim from $($shimInfo.Alternatives[$_ - 1])."
|
||||||
|
}
|
||||||
|
$selected = $Host.UI.PromptForChoice("Alternatives of '$ShimName' command", "Please choose one that provides '$ShimName' as default:", $altApps, 0)
|
||||||
|
if ($selected -eq 0) {
|
||||||
|
Write-Host $ShimName -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host ' is already from ' -NoNewline
|
||||||
|
Write-Host $shimInfo.Source -ForegroundColor DarkYellow -NoNewline
|
||||||
|
Write-Host ', nothing changed.'
|
||||||
|
} else {
|
||||||
|
$newApp = $shimInfo.Alternatives[$selected]
|
||||||
|
Write-Host 'Use ' -NoNewline
|
||||||
|
Write-Host $ShimName -ForegroundColor Cyan -NoNewline
|
||||||
|
Write-Host ' from ' -NoNewline
|
||||||
|
Write-Host $newApp -ForegroundColor DarkYellow -NoNewline
|
||||||
|
Write-Host ' as default...' -NoNewline
|
||||||
|
$pathNoExt = strip_ext $shimPath
|
||||||
|
'', '.shim', '.cmd', '.ps1' | ForEach-Object {
|
||||||
|
$oldShimPath = "$pathNoExt$_"
|
||||||
|
$newShimPath = "$oldShimPath.$newApp"
|
||||||
|
if (Test-Path -Path $oldShimPath -PathType Leaf) {
|
||||||
|
Rename-Item -Path $oldShimPath -NewName "$oldShimPath.$($shimInfo.Source)" -Force
|
||||||
|
if (Test-Path -Path $newShimPath -PathType Leaf) {
|
||||||
|
Rename-Item -Path $newShimPath -NewName $oldShimPath -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Write-Host 'done.'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "$(if ($global) { 'Global' } else { 'Local' }) shim not found: " -NoNewline
|
||||||
|
Write-Host $ShimName -ForegroundColor Cyan
|
||||||
|
if (Get-ShimPath $ShimName (!$global)) {
|
||||||
|
Write-Host "But a $(if ($global) { 'local' } else {'global' }) shim exists, " -NoNewline
|
||||||
|
Write-Host "run 'scoop shim alter $ShimName$(if (!$global) { ' -global' })' to alternate its source"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
exit 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,34 +1,24 @@
|
|||||||
# Usage: scoop status
|
# Usage: scoop status
|
||||||
# Summary: Show status and check for new app versions
|
# Summary: Show status and check for new app versions
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'manifest' 'parse_json' "install_info"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
|
||||||
. "$psscriptroot\..\lib\git.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
|
|
||||||
# check if scoop needs updating
|
# check if scoop needs updating
|
||||||
$currentdir = fullpath $(versiondir 'scoop' 'current')
|
$currentdir = fullpath $(versiondir 'scoop' 'current')
|
||||||
$needs_update = $false
|
$needs_update = $false
|
||||||
|
|
||||||
if(test-path "$currentdir\.git") {
|
if (Test-Path "$currentdir\.git") {
|
||||||
Push-Location $currentdir
|
git_cmd -C "`"$currentdir`"" fetch -q origin
|
||||||
git_fetch -q origin
|
$commits = $(git -C $currentdir log "HEAD..origin/$(get_config SCOOP_BRANCH)" --oneline)
|
||||||
$commits = $(git log "HEAD..origin/$(scoop config SCOOP_BRANCH)" --oneline)
|
if ($commits) { $needs_update = $true }
|
||||||
if($commits) { $needs_update = $true }
|
} else {
|
||||||
Pop-Location
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$needs_update = $true
|
$needs_update = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
if($needs_update) {
|
if ($needs_update) {
|
||||||
warn "Scoop is out of date. Run 'scoop update' to get the latest changes."
|
warn "Scoop is out of date. Run 'scoop update' to get the latest changes."
|
||||||
}
|
} else { success 'Scoop is up to date.' }
|
||||||
else { success "Scoop is up to date."}
|
|
||||||
|
|
||||||
$failed = @()
|
$failed = @()
|
||||||
$outdated = @()
|
$outdated = @()
|
||||||
@@ -39,69 +29,69 @@ $onhold = @()
|
|||||||
$true, $false | ForEach-Object { # local and global apps
|
$true, $false | ForEach-Object { # local and global apps
|
||||||
$global = $_
|
$global = $_
|
||||||
$dir = appsdir $global
|
$dir = appsdir $global
|
||||||
if(!(test-path $dir)) { return }
|
if (!(Test-Path $dir)) { return }
|
||||||
|
|
||||||
Get-ChildItem $dir | Where-Object name -ne 'scoop' | ForEach-Object {
|
Get-ChildItem $dir | Where-Object name -NE 'scoop' | ForEach-Object {
|
||||||
$app = $_.name
|
$app = $_.name
|
||||||
$status = app_status $app $global
|
$status = app_status $app $global
|
||||||
if($status.failed) {
|
if ($status.failed) {
|
||||||
$failed += @{ $app = $status.version }
|
$failed += @{ $app = $status.version }
|
||||||
}
|
}
|
||||||
if($status.removed) {
|
if ($status.removed) {
|
||||||
$removed += @{ $app = $status.version }
|
$removed += @{ $app = $status.version }
|
||||||
}
|
}
|
||||||
if($status.outdated) {
|
if ($status.outdated) {
|
||||||
$outdated += @{ $app = @($status.version, $status.latest_version) }
|
$outdated += @{ $app = @($status.version, $status.latest_version) }
|
||||||
if($status.hold) {
|
if ($status.hold) {
|
||||||
$onhold += @{ $app = @($status.version, $status.latest_version) }
|
$onhold += @{ $app = @($status.version, $status.latest_version) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($status.missing_deps) {
|
if ($status.missing_deps) {
|
||||||
$missing_deps += ,(@($app) + @($status.missing_deps))
|
$missing_deps += , (@($app) + @($status.missing_deps))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($outdated) {
|
if ($outdated) {
|
||||||
write-host -f DarkCyan 'Updates are available for:'
|
Write-Host -f DarkCyan 'Updates are available for:'
|
||||||
$outdated.keys | ForEach-Object {
|
$outdated.keys | ForEach-Object {
|
||||||
$versions = $outdated.$_
|
$versions = $outdated.$_
|
||||||
" $_`: $($versions[0]) -> $($versions[1])"
|
" $_`: $($versions[0]) -> $($versions[1])"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($onhold) {
|
if ($onhold) {
|
||||||
write-host -f DarkCyan 'These apps are outdated and on hold:'
|
Write-Host -f DarkCyan 'These apps are outdated and on hold:'
|
||||||
$onhold.keys | ForEach-Object {
|
$onhold.keys | ForEach-Object {
|
||||||
$versions = $onhold.$_
|
$versions = $onhold.$_
|
||||||
" $_`: $($versions[0]) -> $($versions[1])"
|
" $_`: $($versions[0]) -> $($versions[1])"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($removed) {
|
if ($removed) {
|
||||||
write-host -f DarkCyan 'These app manifests have been removed:'
|
Write-Host -f DarkCyan 'These app manifests have been removed:'
|
||||||
$removed.keys | ForEach-Object {
|
$removed.keys | ForEach-Object {
|
||||||
" $_"
|
" $_"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($failed) {
|
if ($failed) {
|
||||||
write-host -f DarkCyan 'These apps failed to install:'
|
Write-Host -f DarkCyan 'These apps failed to install:'
|
||||||
$failed.keys | ForEach-Object {
|
$failed.keys | ForEach-Object {
|
||||||
" $_"
|
" $_"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($missing_deps) {
|
if ($missing_deps) {
|
||||||
write-host -f DarkCyan 'Missing runtime dependencies:'
|
Write-Host -f DarkCyan 'Missing runtime dependencies:'
|
||||||
$missing_deps | ForEach-Object {
|
$missing_deps | ForEach-Object {
|
||||||
$app, $deps = $_
|
$app, $deps = $_
|
||||||
" '$app' requires '$([string]::join("', '", $deps))'"
|
" '$app' requires '$([string]::join("', '", $deps))'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$old -and !$removed -and !$failed -and !$missing_deps -and !$needs_update) {
|
if (!$old -and !$removed -and !$failed -and !$missing_deps -and !$needs_update) {
|
||||||
success "Everything is ok!"
|
success 'Everything is ok!'
|
||||||
}
|
}
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
# Usage: scoop unhold <app>
|
# Usage: scoop unhold <app>
|
||||||
# Summary: Unhold an app to enable updates
|
# Summary: Unhold an app to enable updates
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1" # 'save_install_info' (indirectly)
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'install_info' 'Select-CurrentVersion' (indirectly)
|
||||||
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
$apps = $args
|
$apps = $args
|
||||||
|
|
||||||
if(!$apps) {
|
if(!$apps) {
|
||||||
@@ -21,13 +21,18 @@ $apps | ForEach-Object {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = versiondir $app 'current' $global
|
if (get_config NO_JUNCTIONS) {
|
||||||
$json = install_info $app 'current' $global
|
$version = Select-CurrentVersion -App $app -Global:$global
|
||||||
|
} else {
|
||||||
|
$version = 'current'
|
||||||
|
}
|
||||||
|
$dir = versiondir $app $version $global
|
||||||
|
$json = install_info $app $version $global
|
||||||
$install = @{}
|
$install = @{}
|
||||||
$json | Get-Member -MemberType Properties | ForEach-Object { $install.Add($_.Name, $json.($_.Name))}
|
$json | Get-Member -MemberType Properties | ForEach-Object { $install.Add($_.Name, $json.($_.Name))}
|
||||||
$install.hold = $null
|
$install.hold = $null
|
||||||
save_install_info $install $dir
|
save_install_info $install $dir
|
||||||
success "$app is now unlocked and can be updated again."
|
success "$app is no longer held and can be updated again."
|
||||||
}
|
}
|
||||||
|
|
||||||
exit $exitcode
|
exit $exitcode
|
||||||
|
|||||||
@@ -6,16 +6,12 @@
|
|||||||
# -g, --global Uninstall a globally installed app
|
# -g, --global Uninstall a globally installed app
|
||||||
# -p, --purge Remove all persistent data
|
# -p, --purge Remove all persistent data
|
||||||
|
|
||||||
. "$PSScriptRoot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$PSScriptRoot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Select-CurrentVersion' (indirectly)
|
||||||
. "$PSScriptRoot\..\lib\help.ps1"
|
|
||||||
. "$PSScriptRoot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$PSScriptRoot\..\lib\shortcuts.ps1"
|
. "$PSScriptRoot\..\lib\shortcuts.ps1"
|
||||||
. "$PSScriptRoot\..\lib\psmodules.ps1"
|
. "$PSScriptRoot\..\lib\psmodules.ps1"
|
||||||
. "$PSScriptRoot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1" # 'Select-CurrentVersion'
|
||||||
. "$PSScriptRoot\..\lib\getopt.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
|
||||||
|
|
||||||
# options
|
# options
|
||||||
$opt, $apps, $err = getopt $args 'gp' 'global', 'purge'
|
$opt, $apps, $err = getopt $args 'gp' 'global', 'purge'
|
||||||
@@ -50,73 +46,75 @@ if (!$apps) { exit 0 }
|
|||||||
:app_loop foreach ($_ in $apps) {
|
:app_loop foreach ($_ in $apps) {
|
||||||
($app, $global) = $_
|
($app, $global) = $_
|
||||||
|
|
||||||
$version = current_version $app $global
|
$version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
Write-Host "Uninstalling '$app' ($version)."
|
$appDir = appdir $app $global
|
||||||
|
if ($version) {
|
||||||
|
Write-Host "Uninstalling '$app' ($version)."
|
||||||
|
|
||||||
$dir = versiondir $app $version $global
|
$dir = versiondir $app $version $global
|
||||||
$persist_dir = persistdir $app $global
|
$persist_dir = persistdir $app $global
|
||||||
|
|
||||||
#region Workaround for #2952
|
#region Workaround for #2952
|
||||||
$processdir = appdir $app $global | Resolve-Path | Select-Object -ExpandProperty Path
|
if (test_running_process $app $global) {
|
||||||
if (Get-Process | Where-Object { $_.Path -like "$processdir\*" }) {
|
|
||||||
error "Application is still running. Close all instances and try again."
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
#endregion Workaround for #2952
|
|
||||||
|
|
||||||
try {
|
|
||||||
Test-Path $dir -ErrorAction Stop | Out-Null
|
|
||||||
} catch [UnauthorizedAccessException] {
|
|
||||||
error "Access denied: $dir. You might need to restart."
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
$manifest = installed_manifest $app $version $global
|
|
||||||
$install = install_info $app $version $global
|
|
||||||
$architecture = $install.architecture
|
|
||||||
|
|
||||||
run_uninstaller $manifest $architecture $dir
|
|
||||||
rm_shims $manifest $global $architecture
|
|
||||||
rm_startmenu_shortcuts $manifest $global $architecture
|
|
||||||
|
|
||||||
# If a junction was used during install, that will have been used
|
|
||||||
# as the reference directory. Otherwise it will just be the version
|
|
||||||
# directory.
|
|
||||||
$refdir = unlink_current $dir
|
|
||||||
|
|
||||||
uninstall_psmodule $manifest $refdir $global
|
|
||||||
|
|
||||||
env_rm_path $manifest $refdir $global
|
|
||||||
env_rm $manifest $global
|
|
||||||
|
|
||||||
try {
|
|
||||||
# unlink all potential old link before doing recursive Remove-Item
|
|
||||||
unlink_persist_data $dir
|
|
||||||
Remove-Item $dir -Recurse -Force -ErrorAction Stop
|
|
||||||
} catch {
|
|
||||||
if (Test-Path $dir) {
|
|
||||||
error "Couldn't remove '$(friendly_path $dir)'; it may be in use."
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
#endregion Workaround for #2952
|
||||||
|
|
||||||
|
try {
|
||||||
|
Test-Path $dir -ErrorAction Stop | Out-Null
|
||||||
|
} catch [UnauthorizedAccessException] {
|
||||||
|
error "Access denied: $dir. You might need to restart."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$manifest = installed_manifest $app $version $global
|
||||||
|
$install = install_info $app $version $global
|
||||||
|
$architecture = $install.architecture
|
||||||
|
|
||||||
|
run_uninstaller $manifest $architecture $dir
|
||||||
|
rm_shims $app $manifest $global $architecture
|
||||||
|
rm_startmenu_shortcuts $manifest $global $architecture
|
||||||
|
|
||||||
|
# If a junction was used during install, that will have been used
|
||||||
|
# as the reference directory. Otherwise it will just be the version
|
||||||
|
# directory.
|
||||||
|
$refdir = unlink_current $dir
|
||||||
|
|
||||||
|
uninstall_psmodule $manifest $refdir $global
|
||||||
|
|
||||||
|
env_rm_path $manifest $refdir $global $architecture
|
||||||
|
env_rm $manifest $global $architecture
|
||||||
|
|
||||||
# remove older versions
|
|
||||||
$old = @(versions $app $global)
|
|
||||||
foreach ($oldver in $old) {
|
|
||||||
Write-Host "Removing older version ($oldver)."
|
|
||||||
$dir = versiondir $app $oldver $global
|
|
||||||
try {
|
try {
|
||||||
# unlink all potential old link before doing recursive Remove-Item
|
# unlink all potential old link before doing recursive Remove-Item
|
||||||
unlink_persist_data $dir
|
unlink_persist_data $manifest $dir
|
||||||
|
Remove-Item $dir -Recurse -Force -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
if (Test-Path $dir) {
|
||||||
|
error "Couldn't remove '$(friendly_path $dir)'; it may be in use."
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# remove older versions
|
||||||
|
$oldVersions = @(Get-ChildItem $appDir -Name -Exclude 'current')
|
||||||
|
foreach ($version in $oldVersions) {
|
||||||
|
Write-Host "Removing older version ($version)."
|
||||||
|
$dir = versiondir $app $version $global
|
||||||
|
try {
|
||||||
|
# unlink all potential old link before doing recursive Remove-Item
|
||||||
|
unlink_persist_data $manifest $dir
|
||||||
Remove-Item $dir -Recurse -Force -ErrorAction Stop
|
Remove-Item $dir -Recurse -Force -ErrorAction Stop
|
||||||
} catch {
|
} catch {
|
||||||
error "Couldn't remove '$(friendly_path $dir)'; it may be in use."
|
error "Couldn't remove '$(friendly_path $dir)'; it may be in use."
|
||||||
continue app_loop
|
continue app_loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Test-Path ($currentDir = Join-Path $appDir 'current')) {
|
||||||
if (@(versions $app $global).length -eq 0) {
|
attrib $currentDir -R /L
|
||||||
$appdir = appdir $app $global
|
Remove-Item $currentDir -ErrorAction Stop -Force
|
||||||
|
}
|
||||||
|
if (!(Get-ChildItem $appDir)) {
|
||||||
try {
|
try {
|
||||||
# if last install failed, the directory seems to be locked and this
|
# if last install failed, the directory seems to be locked and this
|
||||||
# will throw an error about the directory not existing
|
# will throw an error about the directory not existing
|
||||||
|
|||||||
@@ -12,22 +12,19 @@
|
|||||||
# -k, --no-cache Don't use the download cache
|
# -k, --no-cache Don't use the download cache
|
||||||
# -s, --skip Skip hash validation (use with caution!)
|
# -s, --skip Skip hash validation (use with caution!)
|
||||||
# -q, --quiet Hide extraneous messages
|
# -q, --quiet Hide extraneous messages
|
||||||
|
# -a, --all Update all apps (alternative to '*')
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\shortcuts.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1" # 'save_install_info' in 'manifest.ps1' (indirectly)
|
||||||
. "$psscriptroot\..\lib\psmodules.ps1"
|
. "$PSScriptRoot\..\lib\shortcuts.ps1"
|
||||||
. "$psscriptroot\..\lib\decompress.ps1"
|
. "$PSScriptRoot\..\lib\psmodules.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\decompress.ps1"
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
. "$psscriptroot\..\lib\versions.ps1"
|
. "$PSScriptRoot\..\lib\versions.ps1"
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
. "$PSScriptRoot\..\lib\depends.ps1"
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$psscriptroot\..\lib\git.ps1"
|
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
$opt, $apps, $err = getopt $args 'gfiksqa' 'global', 'force', 'independent', 'no-cache', 'skip', 'quiet', 'all'
|
||||||
|
|
||||||
$opt, $apps, $err = getopt $args 'gfiksq:' 'global', 'force', 'independent', 'no-cache', 'skip', 'quiet'
|
|
||||||
if ($err) { "scoop update: $err"; exit 1 }
|
if ($err) { "scoop update: $err"; exit 1 }
|
||||||
$global = $opt.g -or $opt.global
|
$global = $opt.g -or $opt.global
|
||||||
$force = $opt.f -or $opt.force
|
$force = $opt.f -or $opt.force
|
||||||
@@ -35,11 +32,12 @@ $check_hash = !($opt.s -or $opt.skip)
|
|||||||
$use_cache = !($opt.k -or $opt.'no-cache')
|
$use_cache = !($opt.k -or $opt.'no-cache')
|
||||||
$quiet = $opt.q -or $opt.quiet
|
$quiet = $opt.q -or $opt.quiet
|
||||||
$independent = $opt.i -or $opt.independent
|
$independent = $opt.i -or $opt.independent
|
||||||
|
$all = $opt.a -or $opt.all
|
||||||
|
|
||||||
# load config
|
# load config
|
||||||
$configRepo = get_config SCOOP_REPO
|
$configRepo = get_config SCOOP_REPO
|
||||||
if (!$configRepo) {
|
if (!$configRepo) {
|
||||||
$configRepo = "https://github.com/lukesampson/scoop"
|
$configRepo = "https://github.com/ScoopInstaller/Scoop"
|
||||||
set_config SCOOP_REPO $configRepo | Out-Null
|
set_config SCOOP_REPO $configRepo | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,36 +50,29 @@ if (!$configBranch) {
|
|||||||
|
|
||||||
if(($PSVersionTable.PSVersion.Major) -lt 5) {
|
if(($PSVersionTable.PSVersion.Major) -lt 5) {
|
||||||
# check powershell version
|
# check powershell version
|
||||||
# should be deleted after Oct 1, 2019
|
Write-Output "PowerShell 5 or later is required to run Scoop."
|
||||||
If ((Get-Date).ToUniversalTime() -ge "2019-10-01") {
|
Write-Output "Upgrade PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-windows"
|
||||||
Write-Output "PowerShell 5 or later is required to run Scoop."
|
break
|
||||||
Write-Output "Upgrade PowerShell: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell"
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
Write-Output "Scoop is going to stop supporting old version of PowerShell."
|
|
||||||
Write-Output "Please upgrade to PowerShell 5 or later version before Oct 1, 2019 UTC."
|
|
||||||
Write-Output "Guideline: https://docs.microsoft.com/en-us/powershell/scripting/setup/installing-windows-powershell"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function update_scoop() {
|
function update_scoop() {
|
||||||
# check for git
|
# check for git
|
||||||
if(!(Test-CommandAvailable git)) { abort "Scoop uses Git to update itself. Run 'scoop install git' and try again." }
|
if(!(Test-CommandAvailable git)) { abort "Scoop uses Git to update itself. Run 'scoop install git' and try again." }
|
||||||
|
|
||||||
write-host "Updating Scoop..."
|
Write-Host "Updating Scoop..."
|
||||||
$last_update = $(last_scoop_update)
|
$last_update = $(last_scoop_update)
|
||||||
if ($null -eq $last_update) {$last_update = [System.DateTime]::Now}
|
if ($null -eq $last_update) {$last_update = [System.DateTime]::Now}
|
||||||
$last_update = $last_update.ToString('s')
|
$last_update = $last_update.ToString('s')
|
||||||
$show_update_log = get_config 'show_update_log' $true
|
$show_update_log = get_config 'show_update_log' $true
|
||||||
$currentdir = fullpath $(versiondir 'scoop' 'current')
|
$currentdir = fullpath $(versiondir 'scoop' 'current')
|
||||||
if (!(test-path "$currentdir\.git")) {
|
if (!(Test-Path "$currentdir\.git")) {
|
||||||
$newdir = fullpath $(versiondir 'scoop' 'new')
|
$newdir = fullpath $(versiondir 'scoop' 'new')
|
||||||
|
|
||||||
# get git scoop
|
# get git scoop
|
||||||
git_clone -q $configRepo --branch $configBranch --single-branch "`"$newdir`""
|
git_cmd clone -q $configRepo --branch $configBranch --single-branch "`"$newdir`""
|
||||||
|
|
||||||
# check if scoop was successful downloaded
|
# check if scoop was successful downloaded
|
||||||
if (!(test-path "$newdir")) {
|
if (!(Test-Path "$newdir")) {
|
||||||
abort 'Scoop update failed.'
|
abort 'Scoop update failed.'
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,69 +80,73 @@ function update_scoop() {
|
|||||||
Remove-Item -r -force $currentdir -ea stop
|
Remove-Item -r -force $currentdir -ea stop
|
||||||
Move-Item $newdir $currentdir
|
Move-Item $newdir $currentdir
|
||||||
} else {
|
} else {
|
||||||
Push-Location $currentdir
|
$previousCommit = Invoke-Expression "git -C '$currentdir' rev-parse HEAD"
|
||||||
|
$currentRepo = Invoke-Expression "git -C '$currentdir' config remote.origin.url"
|
||||||
$currentRepo = git_config remote.origin.url
|
$currentBranch = Invoke-Expression "git -C '$currentdir' branch"
|
||||||
$currentBranch = git_branch
|
|
||||||
|
|
||||||
$isRepoChanged = !($currentRepo -match $configRepo)
|
$isRepoChanged = !($currentRepo -match $configRepo)
|
||||||
$isBranchChanged = !($currentBranch -match "\*\s+$configBranch")
|
$isBranchChanged = !($currentBranch -match "\*\s+$configBranch")
|
||||||
|
|
||||||
# Change remote url if the repo is changed
|
# Change remote url if the repo is changed
|
||||||
if ($isRepoChanged) {
|
if ($isRepoChanged) {
|
||||||
git_config remote.origin.url "$configRepo"
|
Invoke-Expression "git -C '$currentdir' config remote.origin.url '$configRepo'"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Fetch and reset local repo if the repo or the branch is changed
|
# Fetch and reset local repo if the repo or the branch is changed
|
||||||
if ($isRepoChanged -or $isBranchChanged) {
|
if ($isRepoChanged -or $isBranchChanged) {
|
||||||
# Reset git fetch refs, so that it can fetch all branches (GH-3368)
|
# Reset git fetch refs, so that it can fetch all branches (GH-3368)
|
||||||
git_config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
Invoke-Expression "git -C '$currentdir' config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'"
|
||||||
# fetch remote branch
|
# fetch remote branch
|
||||||
git_fetch --force origin "refs/heads/`"$configBranch`":refs/remotes/origin/$configBranch" -q
|
git_cmd -C "`"$currentdir`"" fetch --force origin "refs/heads/`"$configBranch`":refs/remotes/origin/$configBranch" -q
|
||||||
# checkout and track the branch
|
# checkout and track the branch
|
||||||
git_checkout -B $configBranch -t origin/$configBranch -q
|
git_cmd -C "`"$currentdir`"" checkout -B $configBranch -t origin/$configBranch -q
|
||||||
# reset branch HEAD
|
# reset branch HEAD
|
||||||
git_reset --hard origin/$configBranch -q
|
Invoke-Expression "git -C '$currentdir' reset --hard origin/$configBranch -q"
|
||||||
} else {
|
} else {
|
||||||
git_pull -q
|
git_cmd -C "`"$currentdir`"" pull -q
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $lastexitcode
|
$res = $lastexitcode
|
||||||
if ($show_update_log) {
|
if ($show_update_log) {
|
||||||
git_log --no-decorate --date=local --since="`"$last_update`"" --format="`"tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset`"" HEAD
|
Invoke-Expression "git -C '$currentdir' --no-pager log --no-decorate --grep='^(chore)' --invert-grep --format='tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset' '$previousCommit..HEAD'"
|
||||||
}
|
}
|
||||||
|
|
||||||
Pop-Location
|
|
||||||
if ($res -ne 0) {
|
if ($res -ne 0) {
|
||||||
abort 'Update failed.'
|
abort 'Update failed.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Get-LocalBucket) -notcontains 'main') {
|
# This should have been deprecated after 2019-05-12
|
||||||
info "The main bucket of Scoop has been separated to 'https://github.com/ScoopInstaller/Main'"
|
# if ((Get-LocalBucket) -notcontains 'main') {
|
||||||
info "Adding main bucket..."
|
# info "The main bucket of Scoop has been separated to 'https://github.com/ScoopInstaller/Main'"
|
||||||
add_bucket 'main'
|
# info "Adding main bucket..."
|
||||||
}
|
# add_bucket 'main'
|
||||||
|
# }
|
||||||
|
|
||||||
ensure_scoop_in_path
|
|
||||||
shim "$currentdir\bin\scoop.ps1" $false
|
shim "$currentdir\bin\scoop.ps1" $false
|
||||||
|
|
||||||
Get-LocalBucket | ForEach-Object {
|
foreach ($bucket in Get-LocalBucket) {
|
||||||
write-host "Updating '$_' bucket..."
|
Write-Host "Updating '$bucket' bucket..."
|
||||||
|
|
||||||
$loc = Find-BucketDirectory $_ -Root
|
$bucketLoc = Find-BucketDirectory $bucket -Root
|
||||||
# Make sure main bucket, which was downloaded as zip, will be properly "converted" into git
|
|
||||||
if (($_ -eq 'main') -and !(Test-Path "$loc\.git")) {
|
if (!(Test-Path (Join-Path $bucketLoc '.git'))) {
|
||||||
rm_bucket 'main'
|
if ($bucket -eq 'main') {
|
||||||
add_bucket 'main'
|
# Make sure main bucket, which was downloaded as zip, will be properly "converted" into git
|
||||||
|
Write-Host " Converting 'main' bucket to git..."
|
||||||
|
rm_bucket 'main'
|
||||||
|
add_bucket 'main'
|
||||||
|
} else {
|
||||||
|
Write-Host "'$bucket' is not a git repository. Skipped."
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
Push-Location $loc
|
$previousCommit = (Invoke-Expression "git -C '$bucketLoc' rev-parse HEAD")
|
||||||
git_pull -q
|
git_cmd -C "`"$bucketLoc`"" pull -q
|
||||||
if ($show_update_log) {
|
if ($show_update_log) {
|
||||||
git_log --no-decorate --date=local --since="`"$last_update`"" --format="`"tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset`"" HEAD
|
Invoke-Expression "git -C '$bucketLoc' --no-pager log --no-decorate --grep='^(chore)' --invert-grep --format='tformat: * %C(yellow)%h%Creset %<|(72,trunc)%s %C(cyan)%cr%Creset' '$previousCommit..HEAD'"
|
||||||
}
|
}
|
||||||
Pop-Location
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_config lastupdate ([System.DateTime]::Now.ToString('o')) | Out-Null
|
set_config lastupdate ([System.DateTime]::Now.ToString('o')) | Out-Null
|
||||||
@@ -159,7 +154,7 @@ function update_scoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update($app, $global, $quiet = $false, $independent, $suggested, $use_cache = $true, $check_hash = $true) {
|
function update($app, $global, $quiet = $false, $independent, $suggested, $use_cache = $true, $check_hash = $true) {
|
||||||
$old_version = current_version $app $global
|
$old_version = Select-CurrentVersion -AppName $app -Global:$global
|
||||||
$old_manifest = installed_manifest $app $old_version $global
|
$old_manifest = installed_manifest $app $old_version $global
|
||||||
$install = install_info $app $old_version $global
|
$install = install_info $app $old_version $global
|
||||||
|
|
||||||
@@ -171,14 +166,8 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
|
|||||||
}
|
}
|
||||||
$url = $install.url
|
$url = $install.url
|
||||||
|
|
||||||
if (!$independent) {
|
$manifest = manifest $app $bucket $url
|
||||||
# check dependencies
|
$version = $manifest.version
|
||||||
$man = if ($url) { $url } else { $app }
|
|
||||||
$deps = @(deps $man $architecture) | Where-Object { !(installed $_) }
|
|
||||||
$deps | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash }
|
|
||||||
}
|
|
||||||
|
|
||||||
$version = latest_version $app $bucket $url
|
|
||||||
$is_nightly = $version -eq 'nightly'
|
$is_nightly = $version -eq 'nightly'
|
||||||
if ($is_nightly) {
|
if ($is_nightly) {
|
||||||
$version = nightly_version $(get-date) $quiet
|
$version = nightly_version $(get-date) $quiet
|
||||||
@@ -197,18 +186,16 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$manifest = manifest $app $bucket $url
|
Write-Host "Updating '$app' ($old_version -> $version)"
|
||||||
|
|
||||||
write-host "Updating '$app' ($old_version -> $version)"
|
|
||||||
|
|
||||||
# region Workaround
|
# region Workaround
|
||||||
# Workaround for https://github.com/lukesampson/scoop/issues/2220 until install is refactored
|
# Workaround for https://github.com/ScoopInstaller/Scoop/issues/2220 until install is refactored
|
||||||
# Remove and replace whole region after proper fix
|
# Remove and replace whole region after proper fix
|
||||||
Write-Host "Downloading new version"
|
Write-Host "Downloading new version"
|
||||||
if (Test-Aria2Enabled) {
|
if (Test-Aria2Enabled) {
|
||||||
dl_with_cache_aria2 $app $version $manifest $architecture $cachedir $manifest.cookie $true $check_hash
|
dl_with_cache_aria2 $app $version $manifest $architecture $cachedir $manifest.cookie $true $check_hash
|
||||||
} else {
|
} else {
|
||||||
$urls = url $manifest $architecture
|
$urls = script:url $manifest $architecture
|
||||||
|
|
||||||
foreach ($url in $urls) {
|
foreach ($url in $urls) {
|
||||||
dl_with_cache $app $version $url $null $manifest.cookie $true
|
dl_with_cache $app $version $url $null $manifest.cookie $true
|
||||||
@@ -220,7 +207,7 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
|
|||||||
|
|
||||||
if (!$ok) {
|
if (!$ok) {
|
||||||
error $err
|
error $err
|
||||||
if (test-path $source) {
|
if (Test-Path $source) {
|
||||||
# rm cached file
|
# rm cached file
|
||||||
Remove-Item -force $source
|
Remove-Item -force $source
|
||||||
}
|
}
|
||||||
@@ -237,20 +224,19 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
|
|||||||
# endregion Workaround
|
# endregion Workaround
|
||||||
|
|
||||||
$dir = versiondir $app $old_version $global
|
$dir = versiondir $app $old_version $global
|
||||||
|
$persist_dir = persistdir $app $global
|
||||||
|
|
||||||
#region Workaround for #2952
|
#region Workaround for #2952
|
||||||
$processdir = appdir $app $global | Resolve-Path | Select-Object -ExpandProperty Path
|
if (test_running_process $app $global) {
|
||||||
if (Get-Process | Where-Object { $_.Path -like "$processdir\*" }) {
|
|
||||||
error "Application is still running. Close all instances and try again."
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
#endregion Workaround for #2952
|
#endregion Workaround for #2952
|
||||||
|
|
||||||
write-host "Uninstalling '$app' ($old_version)"
|
Write-Host "Uninstalling '$app' ($old_version)"
|
||||||
run_uninstaller $old_manifest $architecture $dir
|
run_uninstaller $old_manifest $architecture $dir
|
||||||
rm_shims $old_manifest $global $architecture
|
rm_shims $app $old_manifest $global $architecture
|
||||||
env_rm_path $old_manifest $dir $global
|
env_rm_path $old_manifest $dir $global $architecture
|
||||||
env_rm $old_manifest $global
|
env_rm $old_manifest $global $architecture
|
||||||
|
|
||||||
# If a junction was used during install, that will have been used
|
# If a junction was used during install, that will have been used
|
||||||
# as the reference directory. Otherwise it will just be the version
|
# as the reference directory. Otherwise it will just be the version
|
||||||
@@ -277,15 +263,25 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
|
|||||||
# use the url of the install json if the application was installed through url
|
# use the url of the install json if the application was installed through url
|
||||||
$app = $install.url
|
$app = $install.url
|
||||||
}
|
}
|
||||||
install_app $app $architecture $global $suggested $use_cache $check_hash
|
|
||||||
|
if ($independent) {
|
||||||
|
install_app $app $architecture $global $suggested $use_cache $check_hash
|
||||||
|
} else {
|
||||||
|
# Also add missing dependencies
|
||||||
|
$apps = @(Get-Dependency $app $architecture) -ne $app
|
||||||
|
ensure_none_failed $apps
|
||||||
|
$apps.Where({ !(installed $_) }) + $app | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$apps) {
|
if (-not ($apps -or $all)) {
|
||||||
if ($global) {
|
if ($global) {
|
||||||
"scoop update: --global is invalid when <app> is not specified."; exit 1
|
error 'scoop update: --global is invalid when <app> is not specified.'
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
if (!$use_cache) {
|
if (!$use_cache) {
|
||||||
"scoop update: --no-cache is invalid when <app> is not specified."; exit 1
|
error 'scoop update: --no-cache is invalid when <app> is not specified.'
|
||||||
|
exit 1
|
||||||
}
|
}
|
||||||
update_scoop
|
update_scoop
|
||||||
} else {
|
} else {
|
||||||
@@ -299,7 +295,7 @@ if (!$apps) {
|
|||||||
$outdated = @()
|
$outdated = @()
|
||||||
$apps_param = $apps
|
$apps_param = $apps
|
||||||
|
|
||||||
if ($apps_param -eq '*') {
|
if ($apps_param -eq '*' -or $all) {
|
||||||
$apps = applist (installed_apps $false) $false
|
$apps = applist (installed_apps $false) $false
|
||||||
if ($global) {
|
if ($global) {
|
||||||
$apps += applist (installed_apps $true) $true
|
$apps += applist (installed_apps $true) $true
|
||||||
@@ -311,28 +307,34 @@ if (!$apps) {
|
|||||||
$apps | ForEach-Object {
|
$apps | ForEach-Object {
|
||||||
($app, $global) = $_
|
($app, $global) = $_
|
||||||
$status = app_status $app $global
|
$status = app_status $app $global
|
||||||
if ($force -or $status.outdated) {
|
if ($status.installed -and ($force -or $status.outdated)) {
|
||||||
if(!$status.hold) {
|
if (!$status.hold) {
|
||||||
$outdated += applist $app $global
|
$outdated += applist $app $global
|
||||||
write-host -f yellow ("$app`: $($status.version) -> $($status.latest_version){0}" -f ('',' (global)')[$global])
|
Write-Host -f yellow ("$app`: $($status.version) -> $($status.latest_version){0}" -f ('', ' (global)')[$global])
|
||||||
} else {
|
} else {
|
||||||
warn "'$app' is locked to version $($status.version)"
|
warn "'$app' is held to version $($status.version)"
|
||||||
}
|
}
|
||||||
} elseif ($apps_param -ne '*') {
|
} elseif ($apps_param -ne '*') {
|
||||||
write-host -f green "$app`: $($status.version) (latest version)"
|
if ($status.installed) {
|
||||||
|
ensure_none_failed $app
|
||||||
|
Write-Host "$app`: $($status.version) (latest version)" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
info 'Please reinstall it or fix the manifest.'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($outdated -and (Test-Aria2Enabled)) {
|
if ($outdated -and ((Test-Aria2Enabled) -and (get_config 'aria2-warning-enabled' $true))) {
|
||||||
warn "Scoop uses 'aria2c' for multi-connection downloads."
|
warn "Scoop uses 'aria2c' for multi-connection downloads."
|
||||||
warn "Should it cause issues, run 'scoop config aria2-enabled false' to disable it."
|
warn "Should it cause issues, run 'scoop config aria2-enabled false' to disable it."
|
||||||
|
warn "To disable this warning, run 'scoop config aria2-warning-enabled false'."
|
||||||
}
|
}
|
||||||
if ($outdated.Length -gt 1) {
|
if ($outdated.Length -gt 1) {
|
||||||
write-host -f DarkCyan "Updating $($outdated.Length) outdated apps:"
|
Write-Host -f DarkCyan "Updating $($outdated.Length) outdated apps:"
|
||||||
} elseif ($outdated.Length -eq 0) {
|
} elseif ($outdated.Length -eq 0) {
|
||||||
write-host -f Green "Latest versions for all apps are installed! For more information try 'scoop status'"
|
Write-Host -f Green "Latest versions for all apps are installed! For more information try 'scoop status'"
|
||||||
} else {
|
} else {
|
||||||
write-host -f DarkCyan "Updating one outdated app:"
|
Write-Host -f DarkCyan "Updating one outdated app:"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,40 +28,40 @@
|
|||||||
#
|
#
|
||||||
# Options:
|
# Options:
|
||||||
# -a, --arch <32bit|64bit> Use the specified architecture, if the app supports it
|
# -a, --arch <32bit|64bit> Use the specified architecture, if the app supports it
|
||||||
# -s, --scan For packages where VirusTotal has no information, send download URL
|
# -s, --scan For packages where VirusTotal has no information, send download URL
|
||||||
# for analysis (and future retrieval). This requires you to configure
|
# for analysis (and future retrieval). This requires you to configure
|
||||||
# your virustotal_api_key.
|
# your virustotal_api_key.
|
||||||
# -n, --no-depends By default, all dependencies are checked, too. This flag allows
|
# -n, --no-depends By default, all dependencies are checked too. This flag avoids it.
|
||||||
# to avoid it.
|
# -u, --no-update-scoop Don't update Scoop before checking if it's outdated
|
||||||
|
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\getopt.ps1"
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1" # 'Find-Manifest' (indirectly)
|
||||||
. "$psscriptroot\..\lib\getopt.ps1"
|
. "$PSScriptRoot\..\lib\json.ps1" # 'json_path'
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1" # 'hash_for_url'
|
||||||
. "$psscriptroot\..\lib\buckets.ps1"
|
. "$PSScriptRoot\..\lib\depends.ps1" # 'Get-Dependency'
|
||||||
. "$psscriptroot\..\lib\json.ps1"
|
|
||||||
. "$psscriptroot\..\lib\decompress.ps1"
|
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
|
||||||
. "$psscriptroot\..\lib\depends.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
$opt, $apps, $err = getopt $args 'a:snu' @('arch=', 'scan', 'no-depends', 'no-update-scoop')
|
||||||
|
if ($err) { "scoop virustotal: $err"; exit 1 }
|
||||||
$opt, $apps, $err = getopt $args 'a:sn' @('arch=', 'scan', 'no-depends')
|
if (!$apps) { my_usage; exit 1 }
|
||||||
if($err) { "scoop virustotal: $err"; exit 1 }
|
|
||||||
if(!$apps) { my_usage; exit 1 }
|
|
||||||
$architecture = ensure_architecture ($opt.a + $opt.arch)
|
$architecture = ensure_architecture ($opt.a + $opt.arch)
|
||||||
|
|
||||||
if(is_scoop_outdated) { scoop update }
|
if (is_scoop_outdated) {
|
||||||
|
if ($opt.u -or $opt.'no-update-scoop') {
|
||||||
|
warn 'Scoop is out of date.'
|
||||||
|
} else {
|
||||||
|
scoop update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$apps_param = $apps
|
$apps_param = $apps
|
||||||
|
|
||||||
if($apps_param -eq '*') {
|
if ($apps_param -eq '*') {
|
||||||
$apps = installed_apps $false
|
$apps = installed_apps $false
|
||||||
$apps += installed_apps $true
|
$apps += installed_apps $true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$opt.n -and !$opt."no-depends") {
|
if (!$opt.n -and !$opt.'no-depends') {
|
||||||
$apps = install_order $apps $architecture
|
$apps = $apps | Get-Dependency -Architecture $architecture | Select-Object -Unique
|
||||||
}
|
}
|
||||||
|
|
||||||
$_ERR_UNSAFE = 2
|
$_ERR_UNSAFE = 2
|
||||||
@@ -93,13 +93,13 @@ Function Get-VirusTotalResult($hash, $app) {
|
|||||||
$unsafe = [int]$malicious + [int]$suspicious
|
$unsafe = [int]$malicious + [int]$suspicious
|
||||||
$see_url = "see https://www.virustotal.com/#/file/$hash/detection"
|
$see_url = "see https://www.virustotal.com/#/file/$hash/detection"
|
||||||
switch ($unsafe) {
|
switch ($unsafe) {
|
||||||
0 { if ($undetected -eq 0) { $fg = "Yellow" } else { $fg = "DarkGreen" } }
|
0 { if ($undetected -eq 0) { $fg = 'Yellow' } else { $fg = 'DarkGreen' } }
|
||||||
1 { $fg = "DarkYellow" }
|
1 { $fg = 'DarkYellow' }
|
||||||
2 { $fg = "Yellow" }
|
2 { $fg = 'Yellow' }
|
||||||
default { $fg = "Red" }
|
default { $fg = 'Red' }
|
||||||
}
|
}
|
||||||
write-host -f $fg "$app`: $unsafe/$undetected, $see_url"
|
Write-Host -f $fg "$app`: $unsafe/$undetected, $see_url"
|
||||||
if($unsafe -gt 0) {
|
if ($unsafe -gt 0) {
|
||||||
return $_ERR_UNSAFE
|
return $_ERR_UNSAFE
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
@@ -126,16 +126,15 @@ Function Submit-RedirectedUrl {
|
|||||||
# Adapted according to Roy's response (January 23, 2014 at 11:59 am)
|
# Adapted according to Roy's response (January 23, 2014 at 11:59 am)
|
||||||
# Adapted to always return an URL
|
# Adapted to always return an URL
|
||||||
Param (
|
Param (
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[String]$URL
|
[String]$URL
|
||||||
)
|
)
|
||||||
$request = [System.Net.WebRequest]::Create($url)
|
$request = [System.Net.WebRequest]::Create($url)
|
||||||
$request.AllowAutoRedirect=$false
|
$request.AllowAutoRedirect = $false
|
||||||
$response=$request.GetResponse()
|
$response = $request.GetResponse()
|
||||||
if (([int]$response.StatusCode -ge 300) -and ([int]$response.StatusCode -lt 400)) {
|
if (([int]$response.StatusCode -ge 300) -and ([int]$response.StatusCode -lt 400)) {
|
||||||
$redir = $response.GetResponseHeader("Location")
|
$redir = $response.GetResponseHeader('Location')
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
$redir = $URL
|
$redir = $URL
|
||||||
}
|
}
|
||||||
$response.Close()
|
$response.Close()
|
||||||
@@ -152,8 +151,8 @@ Function Submit-RedirectedUrl {
|
|||||||
# submitting the file after a delay if the rate limit is
|
# submitting the file after a delay if the rate limit is
|
||||||
# exceeded, without risking an infinite loop (as stack
|
# exceeded, without risking an infinite loop (as stack
|
||||||
# overflow) if the submission keeps failing.
|
# overflow) if the submission keeps failing.
|
||||||
Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying=$False) {
|
Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying = $False) {
|
||||||
$api_key = get_config("virustotal_api_key")
|
$api_key = get_config virustotal_api_key
|
||||||
if ($do_scan -and !$api_key -and !$warned_no_api_key) {
|
if ($do_scan -and !$api_key -and !$warned_no_api_key) {
|
||||||
$warned_no_api_key = $true
|
$warned_no_api_key = $true
|
||||||
info "Submitting unknown apps needs a VirusTotal API key. " +
|
info "Submitting unknown apps needs a VirusTotal API key. " +
|
||||||
@@ -203,14 +202,14 @@ Function Submit-ToVirusTotal ($url, $app, $do_scan, $retrying=$False) {
|
|||||||
$apps | ForEach-Object {
|
$apps | ForEach-Object {
|
||||||
$app = $_
|
$app = $_
|
||||||
# write-host $app
|
# write-host $app
|
||||||
$manifest, $bucket = find_manifest $app
|
$null, $manifest, $bucket, $null = Find-Manifest $app
|
||||||
if(!$manifest) {
|
if(!$manifest) {
|
||||||
$exit_code = $exit_code -bor $_ERR_NO_INFO
|
$exit_code = $exit_code -bor $_ERR_NO_INFO
|
||||||
warn "$app`: manifest not found"
|
warn "$app`: manifest not found"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$urls = url $manifest $architecture
|
$urls = script:url $manifest $architecture
|
||||||
$urls | ForEach-Object {
|
$urls | ForEach-Object {
|
||||||
$url = $_
|
$url = $_
|
||||||
$hash = hash_for_url $manifest $url $architecture
|
$hash = hash_for_url $manifest $url $architecture
|
||||||
|
|||||||
@@ -2,40 +2,45 @@
|
|||||||
# Summary: Locate a shim/executable (similar to 'which' on Linux)
|
# Summary: Locate a shim/executable (similar to 'which' on Linux)
|
||||||
# Help: Locate the path to a shim/executable that was installed with Scoop (similar to 'which' on Linux)
|
# Help: Locate the path to a shim/executable that was installed with Scoop (similar to 'which' on Linux)
|
||||||
param($command)
|
param($command)
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
|
||||||
. "$psscriptroot\..\lib\help.ps1"
|
|
||||||
|
|
||||||
reset_aliases
|
if (!$command) {
|
||||||
|
'ERROR: <command> missing'
|
||||||
if(!$command) { 'ERROR: <command> missing'; my_usage; exit 1 }
|
my_usage
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$gcm = Get-Command "$command" -ea stop
|
$gcm = Get-Command "$command" -ErrorAction Stop
|
||||||
} catch {
|
} catch {
|
||||||
abort "'$command' not found" 3
|
abort "'$command' not found" 3
|
||||||
}
|
}
|
||||||
|
|
||||||
$path = "$($gcm.path)"
|
$path = $gcm.Path
|
||||||
$usershims = "$(resolve-path $(shimdir $false))"
|
$usershims = Convert-Path (shimdir $false)
|
||||||
$globalshims = fullpath (shimdir $true) # don't resolve: may not exist
|
$globalshims = fullpath (shimdir $true) # don't resolve: may not exist
|
||||||
|
|
||||||
if($path.endswith(".ps1") -and ($path -like "$usershims*" -or $path -like "$globalshims*")) {
|
if ($path -like "$usershims*" -or $path -like "$globalshims*") {
|
||||||
$shimtext = Get-Content $path
|
$exepath = if ($path.EndsWith('.exe') -or $path.EndsWith('.shim')) {
|
||||||
|
(Get-Content ($path -replace '\.exe$', '.shim') | Select-Object -First 1).Replace('path = ', '').Replace('"', '')
|
||||||
|
} else {
|
||||||
|
((Select-String -Path $path -Pattern '^(?:@rem|#)\s*(.*)$').Matches.Groups | Select-Object -Index 1).Value
|
||||||
|
}
|
||||||
|
if (!$exepath) {
|
||||||
|
$exepath = ((Select-String -Path $path -Pattern '[''"]([^@&]*?)[''"]' -AllMatches).Matches.Groups | Select-Object -Last 1).Value
|
||||||
|
}
|
||||||
|
|
||||||
$exepath = ($shimtext | Where-Object { $_.startswith('$path') }).split(' ') | Select-Object -Last 1 | Invoke-Expression
|
if (![System.IO.Path]::IsPathRooted($exepath)) {
|
||||||
|
|
||||||
if(![system.io.path]::ispathrooted($exepath)) {
|
|
||||||
# Expand relative path
|
# Expand relative path
|
||||||
$exepath = resolve-path (join-path (split-path $path) $exepath)
|
$exepath = Convert-Path $exepath
|
||||||
}
|
}
|
||||||
|
|
||||||
friendly_path $exepath
|
friendly_path $exepath
|
||||||
} elseif($gcm.commandtype -eq 'Application') {
|
} elseif ($gcm.CommandType -eq 'Application') {
|
||||||
$gcm.Source
|
$gcm.Source
|
||||||
} elseif($gcm.commandtype -eq 'Alias') {
|
} elseif ($gcm.CommandType -eq 'Alias') {
|
||||||
scoop which $gcm.resolvedcommandname
|
scoop which $gcm.ResolvedCommandName
|
||||||
} else {
|
} else {
|
||||||
[console]::error.writeline("Not a scoop shim.")
|
Write-Host 'Not a scoop shim.'
|
||||||
$path
|
$path
|
||||||
exit 2
|
exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
225
schema.json
225
schema.json
@@ -7,6 +7,10 @@
|
|||||||
"pattern": "^([a-fA-F0-9]{64}|(sha1|sha256|sha512|md5):([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{128}))$",
|
"pattern": "^([a-fA-F0-9]{64}|(sha1|sha256|sha512|md5):([a-fA-F0-9]{32}|[a-fA-F0-9]{40}|[a-fA-F0-9]{64}|[a-fA-F0-9]{128}))$",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"jsonPathPattern": {
|
||||||
|
"pattern": "^\\$[.\\[].*$",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"hash": {
|
"hash": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -35,13 +39,11 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"jp": {
|
"jp": {
|
||||||
"pattern": "^\\$[.[].*$",
|
"$ref": "#/definitions/jsonPathPattern",
|
||||||
"type": "string",
|
|
||||||
"description": "Same as 'jsonpath'"
|
"description": "Same as 'jsonpath'"
|
||||||
},
|
},
|
||||||
"jsonpath": {
|
"jsonpath": {
|
||||||
"pattern": "^\\$[.[].*$",
|
"$ref": "#/definitions/jsonPathPattern"
|
||||||
"type": "string"
|
|
||||||
},
|
},
|
||||||
"xpath": {
|
"xpath": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -86,6 +88,21 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"hashExtractionOrArrayOfHashExtractions": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/hashExtraction"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/hashExtraction"
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"architecture": {
|
"architecture": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
@@ -155,63 +172,93 @@
|
|||||||
"minItems": 1,
|
"minItems": 1,
|
||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"autoupdate": {
|
"autoupdateArch": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"architecture": {
|
"url": {
|
||||||
|
"$ref": "#/definitions/autoupdateUriOrArrayOfAutoupdateUris"
|
||||||
|
},
|
||||||
|
"hash": {
|
||||||
|
"$ref": "#/definitions/hashExtractionOrArrayOfHashExtractions"
|
||||||
|
},
|
||||||
|
"extract_dir": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
|
},
|
||||||
|
"extract_to": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
|
},
|
||||||
|
"env_add_path": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
|
},
|
||||||
|
"env_set": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
|
||||||
|
},
|
||||||
|
"shortcuts": {
|
||||||
|
"$ref": "#/definitions/shortcutsArray"
|
||||||
|
},
|
||||||
|
"installer": {
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"properties": {
|
"properties": {
|
||||||
"32bit": {
|
"file": {
|
||||||
"additionalProperties": false,
|
"type": "string"
|
||||||
"properties": {
|
|
||||||
"extract_dir": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"format": "uri",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"hash": {
|
|
||||||
"$ref": "#/definitions/hashExtraction"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"64bit": {
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"extract_dir": {
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"url": {
|
|
||||||
"format": "uri",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"hash": {
|
|
||||||
"$ref": "#/definitions/hashExtraction"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"extract_dir": {
|
"post_install": {
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"hash": {
|
|
||||||
"$ref": "#/definitions/hashExtraction"
|
|
||||||
},
|
|
||||||
"note": {
|
|
||||||
"$ref": "#/definitions/stringOrArrayOfStrings"
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
},
|
},
|
||||||
"url": {
|
"psmodule": {
|
||||||
"format": "uri",
|
"additionalProperties": false,
|
||||||
"type": "string"
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"persist": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStringsOrAnArrayOfArrayOfStrings"
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"$ref": "#/definitions/license"
|
||||||
|
},
|
||||||
|
"notes": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"autoupdate": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/autoupdateArch"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"properties": {
|
||||||
|
"notes": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
|
},
|
||||||
|
"architecture": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"32bit": {
|
||||||
|
"$ref": "#/definitions/autoupdateArch"
|
||||||
|
},
|
||||||
|
"64bit": {
|
||||||
|
"$ref": "#/definitions/autoupdateArch"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"checkver": {
|
"checkver": {
|
||||||
"anyOf": [
|
"anyOf": [
|
||||||
{
|
{
|
||||||
@@ -239,13 +286,11 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"jp": {
|
"jp": {
|
||||||
"pattern": "^\\$[.[].*$",
|
"$ref": "#/definitions/jsonPathPattern",
|
||||||
"type": "string",
|
|
||||||
"description": "Same as 'jsonpath'"
|
"description": "Same as 'jsonpath'"
|
||||||
},
|
},
|
||||||
"jsonpath": {
|
"jsonpath": {
|
||||||
"pattern": "^\\$[.[].*$",
|
"$ref": "#/definitions/jsonPathPattern"
|
||||||
"type": "string"
|
|
||||||
},
|
},
|
||||||
"xpath": {
|
"xpath": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -260,6 +305,10 @@
|
|||||||
},
|
},
|
||||||
"useragent": {
|
"useragent": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"script": {
|
||||||
|
"$ref": "#/definitions/stringOrArrayOfStrings",
|
||||||
|
"description": "Custom PowerShell script to retrieve application version using more complex approach."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@@ -365,6 +414,23 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"autoupdateUriOrArrayOfAutoupdateUris": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"format": "uri",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"items": {
|
||||||
|
"format": "uri",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"type": "array",
|
||||||
|
"uniqueItems": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"licenseIdentifiers": {
|
"licenseIdentifiers": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "License identifier based on SPDX License List https://spdx.org/licenses/",
|
"description": "License identifier based on SPDX License List https://spdx.org/licenses/",
|
||||||
@@ -390,9 +456,36 @@
|
|||||||
"Shareware",
|
"Shareware",
|
||||||
"Unlicense"
|
"Unlicense"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/licenseIdentifiers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"format": "uri",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"identifier": {
|
||||||
|
"$ref": "#/definitions/licenseIdentifiers"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"identifier"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"$schema": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri"
|
||||||
|
},
|
||||||
"_comment": {
|
"_comment": {
|
||||||
"description": "Deprecated. Use ## instead.",
|
"description": "Deprecated. Use ## instead.",
|
||||||
"$ref": "#/definitions/stringOrArrayOfStrings"
|
"$ref": "#/definitions/stringOrArrayOfStrings"
|
||||||
@@ -455,34 +548,14 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"innosetup": {
|
"innosetup": {
|
||||||
"description": "True if the installer InnoSetup based. Found in https://github.com/lukesampson/scoop/search?l=JSON&q=innosetup",
|
"description": "True if the installer InnoSetup based. Found in https://github.com/ScoopInstaller/Main/search?l=JSON&q=innosetup",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"installer": {
|
"installer": {
|
||||||
"$ref": "#/definitions/installer"
|
"$ref": "#/definitions/installer"
|
||||||
},
|
},
|
||||||
"license": {
|
"license": {
|
||||||
"anyOf": [
|
"$ref": "#/definitions/license"
|
||||||
{
|
|
||||||
"$ref": "#/definitions/licenseIdentifiers"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"additionalProperties": false,
|
|
||||||
"properties": {
|
|
||||||
"url": {
|
|
||||||
"format": "uri",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"identifier": {
|
|
||||||
"$ref": "#/definitions/licenseIdentifiers"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"identifier"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"msi": {
|
"msi": {
|
||||||
"$ref": "#/definitions/stringOrArrayOfStrings",
|
"$ref": "#/definitions/stringOrArrayOfStrings",
|
||||||
@@ -525,12 +598,14 @@
|
|||||||
"$ref": "#/definitions/uriOrArrayOfUris"
|
"$ref": "#/definitions/uriOrArrayOfUris"
|
||||||
},
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"pattern": "^[\\w\\.\\-_]+$",
|
"pattern": "^[\\w\\.\\-+_]+$",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
"version"
|
"version",
|
||||||
|
"homepage",
|
||||||
|
"license"
|
||||||
],
|
],
|
||||||
"title": "scoop app manifest schema",
|
"title": "scoop app manifest schema",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
|||||||
64
supporting/formats/ScoopTypes.Format.ps1xml
Normal file
64
supporting/formats/ScoopTypes.Format.ps1xml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Configuration>
|
||||||
|
<ViewDefinitions>
|
||||||
|
<View>
|
||||||
|
<Name>ScoopAppsType</Name>
|
||||||
|
<ViewSelectedBy>
|
||||||
|
<TypeName>ScoopApps</TypeName>
|
||||||
|
</ViewSelectedBy>
|
||||||
|
<TableControl>
|
||||||
|
<TableRowEntries>
|
||||||
|
<TableRowEntry>
|
||||||
|
<TableColumnItems>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Name</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Version</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Source</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Updated</PropertyName>
|
||||||
|
<FormatString>yyyy-MM-dd HH:mm:ss</FormatString>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Info</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
</TableColumnItems>
|
||||||
|
</TableRowEntry>
|
||||||
|
</TableRowEntries>
|
||||||
|
</TableControl>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Name>ScoopShimsType</Name>
|
||||||
|
<ViewSelectedBy>
|
||||||
|
<TypeName>ScoopShims</TypeName>
|
||||||
|
</ViewSelectedBy>
|
||||||
|
<TableControl>
|
||||||
|
<TableRowEntries>
|
||||||
|
<TableRowEntry>
|
||||||
|
<TableColumnItems>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Name</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Source</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>Alternatives</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>IsGlobal</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
<TableColumnItem>
|
||||||
|
<PropertyName>IsHidden</PropertyName>
|
||||||
|
</TableColumnItem>
|
||||||
|
</TableColumnItems>
|
||||||
|
</TableRowEntry>
|
||||||
|
</TableRowEntries>
|
||||||
|
</TableControl>
|
||||||
|
</View>
|
||||||
|
</ViewDefinitions>
|
||||||
|
</Configuration>
|
||||||
@@ -1 +1 @@
|
|||||||
cb440b8a08a2095a59666a859b35aa5a1524b140b909ecc760f38f3baccf80e6 *shim.exe
|
9726c3a429009a5b22bd92cb8ab96724c670e164e7240e83f27b7c8b7bd1ca39 *shim.exe
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
710aeef5381f96ea0360a27ce6b792f67e018abb91d6dc67fc5c18c15baf611f36268a3f9e70a339b1a1b0e5dbfdaee10d74288352e609764d5b81303409a332 *shim.exe
|
18a737674afde4d5e7e1647d8d1e98471bb260513c57739651f92fdf1647d76c92f0cd0a9bb458daf4eae4bdab9d31404162acf6d74a041e6415752b75d722e0 *shim.exe
|
||||||
|
|||||||
Binary file not shown.
@@ -1,21 +1,21 @@
|
|||||||
Param([Switch]$Fast)
|
Param([Switch]$Fast)
|
||||||
Push-Location $psscriptroot
|
Push-Location $PSScriptRoot
|
||||||
. "$psscriptroot\..\..\lib\install.ps1"
|
. "$PSScriptRoot\..\..\lib\install.ps1"
|
||||||
|
|
||||||
if(!$Fast) {
|
if (!$Fast) {
|
||||||
Write-Host "Install dependencies ..."
|
Write-Host "Install dependencies ..."
|
||||||
Invoke-Expression "$psscriptroot\install.ps1"
|
Invoke-Expression "$PSScriptRoot\install.ps1"
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = "$psscriptroot\bin"
|
$output = "$PSScriptRoot\bin"
|
||||||
Write-Output 'Compiling shim.cs ...'
|
Write-Output 'Compiling shim.cs ...'
|
||||||
& "$psscriptroot\packages\Microsoft.Net.Compilers\tools\csc.exe" /deterministic /platform:anycpu /nologo /optimize /target:exe /out:"$output\shim.exe" shim.cs
|
& "$PSScriptRoot\packages\Microsoft.Net.Compilers.Toolset\tasks\net472\csc.exe" -deterministic -platform:anycpu -nologo -optimize -target:exe -out:"$output\shim.exe" shim.cs
|
||||||
|
|
||||||
Write-Output 'Computing checksums ...'
|
Write-Output 'Computing checksums ...'
|
||||||
Remove-Item "$psscriptroot\bin\checksum.sha256" -ErrorAction Ignore
|
Remove-Item "$PSScriptRoot\bin\checksum.sha256" -ErrorAction Ignore
|
||||||
Remove-Item "$psscriptroot\bin\checksum.sha512" -ErrorAction Ignore
|
Remove-Item "$PSScriptRoot\bin\checksum.sha512" -ErrorAction Ignore
|
||||||
Get-ChildItem "$psscriptroot\bin\*" -Include *.exe,*.dll | ForEach-Object {
|
Get-ChildItem "$PSScriptRoot\bin\*" -Include *.exe, *.dll | ForEach-Object {
|
||||||
"$(compute_hash $_ 'sha256') *$($_.Name)" | Out-File "$psscriptroot\bin\checksum.sha256" -Append -Encoding oem
|
"$(compute_hash $_ 'sha256') *$($_.Name)" | Out-File "$PSScriptRoot\bin\checksum.sha256" -Append -Encoding oem
|
||||||
"$(compute_hash $_ 'sha512') *$($_.Name)" | Out-File "$psscriptroot\bin\checksum.sha512" -Append -Encoding oem
|
"$(compute_hash $_ 'sha512') *$($_.Name)" | Out-File "$PSScriptRoot\bin\checksum.sha512" -Append -Encoding oem
|
||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# https://github.com/edymtt/nugetstandalone
|
# https://github.com/edymtt/nugetstandalone
|
||||||
$destinationFolder = "$psscriptroot\packages"
|
$destinationFolder = "$PSScriptRoot\packages"
|
||||||
if ((Test-Path -path $destinationFolder)) {
|
if ((Test-Path -Path $destinationFolder)) {
|
||||||
Remove-Item -Path $destinationFolder -Recurse | Out-Null
|
Remove-Item -Path $destinationFolder -Recurse | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Microsoft.Net.Compilers" version="2.10.0" targetFramework="net45" developmentDependency="true" />
|
<package id="Microsoft.Net.Compilers.Toolset" version="4.0.1" targetFramework="net45" developmentDependency="true" />
|
||||||
</packages>
|
</packages>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props" Condition="Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" />
|
<Import Project="packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props" Condition="Exists('packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props')" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -31,6 +31,6 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props'))" />
|
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# https://github.com/edymtt/nugetstandalone
|
# https://github.com/edymtt/nugetstandalone
|
||||||
$destinationFolder = "$psscriptroot\packages"
|
$destinationFolder = "$PSScriptRoot\packages"
|
||||||
if (!(Test-Path -path $destinationFolder)) {
|
if (!(Test-Path -Path $destinationFolder)) {
|
||||||
Write-Host -f Red "Run .\install.ps1 first!"
|
Write-Host -f Red "Run .\install.ps1 first!"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
1
supporting/shims/71/checksum.sha256
Normal file
1
supporting/shims/71/checksum.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
70d4690b8ac3b3f715f537cdea6e07a39fda4bc0347bf6b958e4f3ff2f0e04d4 shim.exe
|
||||||
1
supporting/shims/71/checksum.sha512
Normal file
1
supporting/shims/71/checksum.sha512
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ecde07b32192846c4885cf4d2208eedc170765ea115ae49b81509fed0ce474e21064100bb2f3d815ee79f1c12463d32ef013d4182647eae71855cd18e4196176 shim.exe
|
||||||
BIN
supporting/shims/71/shim.exe
Normal file
BIN
supporting/shims/71/shim.exe
Normal file
Binary file not shown.
2
supporting/shims/kiennq/.gitignore
vendored
Normal file
2
supporting/shims/kiennq/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.zip
|
||||||
|
*.bak
|
||||||
52
supporting/shims/kiennq/Makefile
Normal file
52
supporting/shims/kiennq/Makefile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
VER?=2.2.1
|
||||||
|
ZIP=shimexe.zip
|
||||||
|
URL?=https://github.com/kiennq/scoop-better-shimexe/releases/download/$(VER)/$(ZIP)
|
||||||
|
LATEST_URL?=https://github.com/kiennq/scoop-better-shimexe/releases/latest
|
||||||
|
NEWVER=$(shell cat version.txt)
|
||||||
|
|
||||||
|
all: verify ## make download unzip verify
|
||||||
|
|
||||||
|
version.txt:
|
||||||
|
@curl --max-redirs 0 -s -D - -o /dev/null $(LATEST_URL) | grep -i ^location | sed -E -e "s|.*/([^/]+)$$|\1|" >version.txt
|
||||||
|
@printf "%s " "Latest version is:"
|
||||||
|
@cat version.txt
|
||||||
|
|
||||||
|
check: version.txt ## Check the version number in version.txt and update if needed
|
||||||
|
|
||||||
|
bump: check ## Bump version number in Makefile
|
||||||
|
@rm -f Makefile.bak
|
||||||
|
@sed -i.bak -e 's|=$(VER)|=$(NEWVER)|' Makefile
|
||||||
|
@cmp --quiet Makefile{,.bak} || echo "Makefile bumped from $(VER) to $(NEWVER)"
|
||||||
|
|
||||||
|
$(ZIP): version.txt
|
||||||
|
curl -L -s -o $(ZIP) $(URL)
|
||||||
|
@touch $@
|
||||||
|
|
||||||
|
download: $(ZIP) ## Download shim from https://github.com/kiennq/scoop-better-shimexe
|
||||||
|
|
||||||
|
shim.exe: $(ZIP)
|
||||||
|
unzip -z -j -o $(ZIP)
|
||||||
|
@touch $@
|
||||||
|
|
||||||
|
unzip: shim.exe ## Unzip download
|
||||||
|
|
||||||
|
verify: shim.exe ## Verify SHA256 checksum for shim.exe
|
||||||
|
sed -e "s|bin/||" checksum.sha256 | sha256sum -c
|
||||||
|
|
||||||
|
clean: ## Clean .zip files
|
||||||
|
rm -f *.zip
|
||||||
|
|
||||||
|
help: ## Display help text
|
||||||
|
@printf "%-8s %s\n" Target Description
|
||||||
|
@printf "%-8s %s\n" '--------' '------------------------------------------'
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-8s %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
.PHONY: bump
|
||||||
|
.PHONY: check
|
||||||
|
.PHONY: clean
|
||||||
|
.PHONY: download
|
||||||
|
.PHONY: help
|
||||||
|
.PHONY: unzip
|
||||||
|
.PHONY: verify
|
||||||
1
supporting/shims/kiennq/checksum.sha256
Normal file
1
supporting/shims/kiennq/checksum.sha256
Normal file
@@ -0,0 +1 @@
|
|||||||
|
aa685053f4a5c0e7145f2a27514c8a56ceae25b0824062326f04037937caa558 bin/shim.exe
|
||||||
1
supporting/shims/kiennq/checksum.sha512
Normal file
1
supporting/shims/kiennq/checksum.sha512
Normal file
@@ -0,0 +1 @@
|
|||||||
|
67c605c8163869d8ef8153c64eb09b82645cbae8228928c0fef944d0259a7b2d3791ecf4b4b01e23566916a878ee7977bfc1a59846bccf3c63bd6a1cf4f521b5 bin/shim.exe
|
||||||
BIN
supporting/shims/kiennq/shim.exe
Normal file
BIN
supporting/shims/kiennq/shim.exe
Normal file
Binary file not shown.
1
supporting/shims/kiennq/version.txt
Normal file
1
supporting/shims/kiennq/version.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
2.2.1
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
f58c374ffcaae4e36d740d90fbf7fe70d0abb7328cd9af3a0a7b70803e994ba4 *Newtonsoft.Json.dll
|
7f912b28a07c226e0be3acfb2f57f050538aba0100fa1f0bf2c39f1a1f1da814 *Newtonsoft.Json.dll
|
||||||
4ca0681df3755205cfd178aaa38f7fd6818c183c4d14c77cd77f8d777282a650 *Newtonsoft.Json.Schema.dll
|
cff8fc4ce358d7daff84ab47129a776797a4ec819c1586a15bd5e63144f5b73f *Newtonsoft.Json.Schema.dll
|
||||||
55f1292b42fa2e8a7a4b3eb360fcfffe97be0fe043b4709979fcd37b8a400456 *Scoop.Validator.dll
|
0d6b228378cbabff23a30456d22f1a31337c466f90cf8b7997cc48bd171155f3 *Scoop.Validator.dll
|
||||||
6dfbe59d9f1c17d362bdd4509975ab40d96e09585aa8d0a1f5527dafbc1c3727 *validator.exe
|
40a70bee96d108701f8f2e81392f9b79fd003f1cb4e1653ad2429753153fd7ee *validator.exe
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
7cbbbef742f56af80f1012d7da86fe5375ac05813045756fb45d0691c36ef13c069361457500ba4200157d5ee7922fd118bf4c0635e5192e3f8c6183fd580944 *Newtonsoft.Json.dll
|
3398094ce429ab5dcdecf2ad04803230669bb4accaef7083992e9b87afac55841ba8def2a5168358bd17e60799e55d076b0e5ca44c86b9e6c91150d3dc37c721 *Newtonsoft.Json.dll
|
||||||
2d9c630948c21b325af7b7ad3de9219a3fdcc23fa65270a0cdb78ea9609038434f6b741a968e9758f93782a3bab57efc3072429bdf84f8ad25a94bf5a8c4bc48 *Newtonsoft.Json.Schema.dll
|
298d3d0b656acbb1fe5ed0c3abb49a640c47889184ab7bd4b594e51a7d7f829d5c8685edbd10a286fd56bfd8d601b9f187da463a5a9c8509365eddaea280642f *Newtonsoft.Json.Schema.dll
|
||||||
6d89196ce01823093f5c3da98d34d41bc1733316d04e181d6f24982a373cc28487b8e4e74b54f5a665a550ad4a7fa6d7208d99de947b82b20e524747bdb41bdd *Scoop.Validator.dll
|
afabe1df6ab837395a5da5ec8dd12bf3f36a8512b76e6f751c14045544246980e9d4061d437792836db792864b7db2761e84f1bf65bac688657a862b68fc7b45 *Scoop.Validator.dll
|
||||||
e9b2162b3e109291c61005a9088d9ebf30fb0307fa285ccf5c54aef05fb3c02944d9513f2557e75d670682b0f3ba67a4f8df3561c715eaa5daa077b591fb4d54 *validator.exe
|
d497c27b48f44f4cff270d3c8801b0cecc74108f8786a4a7c40e57541308ae33a69f5456cfc43ae1ce4214038d20da9fbeac1bcf76cc58d972863b58dab18401 *validator.exe
|
||||||
|
|||||||
Binary file not shown.
@@ -1,26 +1,26 @@
|
|||||||
Param([Switch]$Fast)
|
Param([Switch]$Fast)
|
||||||
Push-Location $psscriptroot
|
Push-Location $PSScriptRoot
|
||||||
. "$psscriptroot\..\..\lib\install.ps1"
|
. "$PSScriptRoot\..\..\lib\install.ps1"
|
||||||
|
|
||||||
if(!$Fast) {
|
if (!$Fast) {
|
||||||
Write-Host "Install dependencies ..."
|
Write-Host "Install dependencies ..."
|
||||||
Invoke-Expression "$psscriptroot\install.ps1"
|
Invoke-Expression "$PSScriptRoot\install.ps1"
|
||||||
}
|
}
|
||||||
|
|
||||||
$output = "$psscriptroot\bin"
|
$output = "$PSScriptRoot\bin"
|
||||||
if(!$Fast) {
|
if (!$Fast) {
|
||||||
Get-ChildItem "$psscriptroot\packages\Newtonsoft.*\lib\net45\*.dll" -File | ForEach-Object { Copy-Item $_ $output }
|
Get-ChildItem "$PSScriptRoot\packages\Newtonsoft.*\lib\net45\*.dll" -File | ForEach-Object { Copy-Item $_ $output }
|
||||||
}
|
}
|
||||||
Write-Output 'Compiling Scoop.Validator.cs ...'
|
Write-Output 'Compiling Scoop.Validator.cs ...'
|
||||||
& "$psscriptroot\packages\Microsoft.Net.Compilers\tools\csc.exe" /deterministic /platform:anycpu /nologo /optimize /target:library /reference:"$output\Newtonsoft.Json.dll","$output\Newtonsoft.Json.Schema.dll" /out:"$output\Scoop.Validator.dll" Scoop.Validator.cs
|
& "$PSScriptRoot\packages\Microsoft.Net.Compilers.Toolset\tasks\net472\csc.exe" -deterministic -platform:anycpu -nologo -optimize -target:library -reference:"$output\Newtonsoft.Json.dll" -reference:"$output\Newtonsoft.Json.Schema.dll" -out:"$output\Scoop.Validator.dll" Scoop.Validator.cs
|
||||||
Write-Output 'Compiling validator.cs ...'
|
Write-Output 'Compiling validator.cs ...'
|
||||||
& "$psscriptroot\packages\Microsoft.Net.Compilers\tools\csc.exe" /deterministic /platform:anycpu /nologo /optimize /target:exe /reference:"$output\Scoop.Validator.dll","$output\Newtonsoft.Json.dll","$output\Newtonsoft.Json.Schema.dll" /out:"$output\validator.exe" validator.cs
|
& "$PSScriptRoot\packages\Microsoft.Net.Compilers.Toolset\tasks\net472\csc.exe" -deterministic -platform:anycpu -nologo -optimize -target:exe -reference:"$output\Scoop.Validator.dll" -reference:"$output\Newtonsoft.Json.dll" -reference:"$output\Newtonsoft.Json.Schema.dll" -out:"$output\validator.exe" validator.cs
|
||||||
|
|
||||||
Write-Output 'Computing checksums ...'
|
Write-Output 'Computing checksums ...'
|
||||||
Remove-Item "$psscriptroot\bin\checksum.sha256" -ErrorAction Ignore
|
Remove-Item "$PSScriptRoot\bin\checksum.sha256" -ErrorAction Ignore
|
||||||
Remove-Item "$psscriptroot\bin\checksum.sha512" -ErrorAction Ignore
|
Remove-Item "$PSScriptRoot\bin\checksum.sha512" -ErrorAction Ignore
|
||||||
Get-ChildItem "$psscriptroot\bin\*" -Include *.exe,*.dll | ForEach-Object {
|
Get-ChildItem "$PSScriptRoot\bin\*" -Include *.exe, *.dll | ForEach-Object {
|
||||||
"$(compute_hash $_ 'sha256') *$($_.Name)" | Out-File "$psscriptroot\bin\checksum.sha256" -Append -Encoding oem
|
"$(compute_hash $_ 'sha256') *$($_.Name)" | Out-File "$PSScriptRoot\bin\checksum.sha256" -Append -Encoding oem
|
||||||
"$(compute_hash $_ 'sha512') *$($_.Name)" | Out-File "$psscriptroot\bin\checksum.sha512" -Append -Encoding oem
|
"$(compute_hash $_ 'sha512') *$($_.Name)" | Out-File "$PSScriptRoot\bin\checksum.sha512" -Append -Encoding oem
|
||||||
}
|
}
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# https://github.com/edymtt/nugetstandalone
|
# https://github.com/edymtt/nugetstandalone
|
||||||
$destinationFolder = "$psscriptroot\packages"
|
$destinationFolder = "$PSScriptRoot\packages"
|
||||||
if ((Test-Path -path $destinationFolder)) {
|
if ((Test-Path -Path $destinationFolder)) {
|
||||||
Remove-Item -Path $destinationFolder -Recurse | Out-Null
|
Remove-Item -Path $destinationFolder -Recurse | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net45" />
|
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net45" />
|
||||||
<package id="Newtonsoft.Json.Schema" version="3.0.10" targetFramework="net45" />
|
<package id="Newtonsoft.Json.Schema" version="3.0.14" targetFramework="net45" />
|
||||||
<package id="Microsoft.Net.Compilers" version="2.10.0" targetFramework="net45" developmentDependency="true" />
|
<package id="Microsoft.Net.Compilers.Toolset" version="4.0.1" targetFramework="net45" developmentDependency="true" />
|
||||||
</packages>
|
</packages>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# https://github.com/edymtt/nugetstandalone
|
# https://github.com/edymtt/nugetstandalone
|
||||||
$destinationFolder = "$psscriptroot\packages"
|
$destinationFolder = "$PSScriptRoot\packages"
|
||||||
if (!(Test-Path -path $destinationFolder)) {
|
if (!(Test-Path -Path $destinationFolder)) {
|
||||||
Write-Host -f Red "Run .\install.ps1 first!"
|
Write-Host -f Red "Run .\install.ps1 first!"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props" Condition="Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" />
|
<Import Project="packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props" Condition="Exists('packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props')" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -14,12 +14,12 @@
|
|||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<HintPath>packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json.Schema, Version=3.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
<Reference Include="Newtonsoft.Json.Schema, Version=3.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed">
|
||||||
<HintPath>packages\Newtonsoft.Json.Schema.3.0.10\lib\net45\Newtonsoft.Json.Schema.dll</HintPath>
|
<HintPath>packages\Newtonsoft.Json.Schema.3.0.14\lib\net45\Newtonsoft.Json.Schema.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
@@ -43,6 +43,6 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.2.10.0\build\Microsoft.Net.Compilers.props'))" />
|
<Error Condition="!Exists('packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Net.Compilers.Toolset.4.0.1\build\Microsoft.Net.Compilers.Toolset.props'))" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,29 +1,28 @@
|
|||||||
$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).Directory.Parent.FullName
|
$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).Directory.Parent.FullName
|
||||||
|
|
||||||
$repo_files = @( Get-ChildItem $repo_dir -file -recurse -force )
|
$repo_files = @( Get-ChildItem $repo_dir -File -Recurse -Force )
|
||||||
|
|
||||||
$project_file_exclusions = @(
|
$project_file_exclusions = @(
|
||||||
$([regex]::Escape($repo_dir)+'(\\|/).git(\\|/).*$'),
|
'[\\/]\.git[\\/]',
|
||||||
'.sublime-workspace$',
|
'\.sublime-workspace$',
|
||||||
'.DS_Store$',
|
'\.DS_Store$',
|
||||||
'supporting(\\|/)validator(\\|/)packages(\\|/)*',
|
'supporting(\\|/)validator(\\|/)packages(\\|/)*',
|
||||||
'supporting(\\|/)shimexe(\\|/)packages(\\|/)*'
|
'supporting(\\|/)shimexe(\\|/)packages(\\|/)*'
|
||||||
)
|
)
|
||||||
|
|
||||||
describe 'Project code' {
|
Describe 'Project code' {
|
||||||
|
|
||||||
$files = @(
|
$files = @(
|
||||||
$repo_files |
|
$repo_files |
|
||||||
where-object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } |
|
Where-Object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } |
|
||||||
where-object { $_.fullname -imatch '.(ps1|psm1)$' }
|
Where-Object { $_.fullname -imatch '.(ps1|psm1)$' }
|
||||||
)
|
)
|
||||||
|
|
||||||
$files_exist = ($files.Count -gt 0)
|
$files_exist = ($files.Count -gt 0)
|
||||||
|
|
||||||
it $('PowerShell code files exist ({0} found)' -f $files.Count) -skip:$(-not $files_exist) {
|
It $('PowerShell code files exist ({0} found)' -f $files.Count) -Skip:$(-not $files_exist) {
|
||||||
if (-not ($files.Count -gt 0))
|
if (-not ($files.Count -gt 0)) {
|
||||||
{
|
throw 'No PowerShell code files were found'
|
||||||
throw "No PowerShell code files were found"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,30 +48,27 @@ describe 'Project code' {
|
|||||||
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
|
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
|
||||||
|
|
||||||
New-Object psobject -Property @{
|
New-Object psobject -Property @{
|
||||||
Path = $scriptPath
|
Path = $scriptPath
|
||||||
SyntaxErrorsFound = ($errors.Count -gt 0)
|
SyntaxErrorsFound = ($errors.Count -gt 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'PowerShell code files do not contain syntax errors' -skip:$(-not $files_exist) {
|
It 'PowerShell code files do not contain syntax errors' -Skip:$(-not $files_exist) {
|
||||||
$badFiles = @(
|
$badFiles = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
if ( (Test-PowerShellSyntax $file.FullName).SyntaxErrorsFound ) {
|
||||||
if ( (Test-PowerShellSyntax $file.FullName).SyntaxErrorsFound )
|
|
||||||
{
|
|
||||||
$file.FullName
|
$file.FullName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badFiles.Count -gt 0)
|
if ($badFiles.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following files have syntax errors: `r`n`r`n$($badFiles -join "`r`n")"
|
throw "The following files have syntax errors: `r`n`r`n$($badFiles -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
. "$psscriptroot\Import-File-Tests.ps1"
|
. "$PSScriptRoot\Import-File-Tests.ps1"
|
||||||
|
|||||||
@@ -1,28 +1,127 @@
|
|||||||
if([String]::IsNullOrEmpty($MyInvocation.PSScriptRoot)) {
|
#Requires -Version 5.0
|
||||||
Write-Error 'This script should not be called directly! It has to be imported from a buckets test file!'
|
#Requires -Modules @{ ModuleName = 'Pester'; RequiredVersion = '4.10.1' }
|
||||||
exit 1
|
param(
|
||||||
}
|
[ValidateNotNullOrEmpty()]
|
||||||
|
[String]
|
||||||
. "$psscriptroot\Scoop-TestLib.ps1"
|
$repo_dir = (Split-Path -Path $MyInvocation.PSCommandPath -Parent)
|
||||||
. "$psscriptroot\..\lib\core.ps1"
|
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
|
||||||
. "$psscriptroot\..\lib\unix.ps1"
|
|
||||||
|
|
||||||
$repo_dir = (Get-Item $MyInvocation.PSScriptRoot).FullName
|
|
||||||
|
|
||||||
$repo_files = @(Get-ChildItem $repo_dir -file -recurse)
|
|
||||||
|
|
||||||
$project_file_exclusions = @(
|
|
||||||
$([regex]::Escape($repo_dir)+'(\\|/).git(\\|/).*$'),
|
|
||||||
'.sublime-workspace$',
|
|
||||||
'.DS_Store$',
|
|
||||||
'supporting(\\|/)validator(\\|/)packages(\\|/)*'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\unix.ps1"
|
||||||
|
|
||||||
$bucketdir = $repo_dir
|
$bucketdir = $repo_dir
|
||||||
if(Test-Path("$repo_dir\bucket")) {
|
if (Test-Path("$repo_dir\..\bucket")) {
|
||||||
|
$bucketdir = "$repo_dir\..\bucket"
|
||||||
|
} elseif (Test-Path("$repo_dir\bucket")) {
|
||||||
$bucketdir = "$repo_dir\bucket"
|
$bucketdir = "$repo_dir\bucket"
|
||||||
}
|
}
|
||||||
|
|
||||||
. "$psscriptroot\Import-File-Tests.ps1"
|
# Tests for non manifest files
|
||||||
. "$psscriptroot\Scoop-Manifest.Tests.ps1" -bucketdir $bucketdir
|
$repo_files = @(Get-ChildItem -Path $repo_dir -File -Recurse)
|
||||||
|
$project_file_exclusions = @(
|
||||||
|
'[\\/]\.git[\\/]',
|
||||||
|
'.sublime-workspace$',
|
||||||
|
'.DS_Store$'
|
||||||
|
)
|
||||||
|
. "$PSScriptRoot\Import-File-Tests.ps1"
|
||||||
|
|
||||||
|
# Tests for manifest files
|
||||||
|
Describe 'Manifest Validator' -Tag 'Validator' {
|
||||||
|
BeforeAll {
|
||||||
|
$schema = "$PSScriptRoot\..\schema.json"
|
||||||
|
$working_dir = setup_working 'manifest'
|
||||||
|
Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Newtonsoft.Json.dll"
|
||||||
|
Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Newtonsoft.Json.Schema.dll"
|
||||||
|
Add-Type -Path "$PSScriptRoot\..\supporting\validator\bin\Scoop.Validator.dll"
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'Scoop.Validator is available' {
|
||||||
|
([System.Management.Automation.PSTypeName]'Scoop.Validator').Type | Should -Be 'Scoop.Validator'
|
||||||
|
}
|
||||||
|
|
||||||
|
Context 'parse_json function' {
|
||||||
|
It 'fails with invalid json' {
|
||||||
|
{ parse_json "$working_dir\broken_wget.json" } | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context 'schema validation' {
|
||||||
|
It 'fails with broken schema' {
|
||||||
|
$validator = New-Object Scoop.Validator("$working_dir\broken_schema.json", $true)
|
||||||
|
$validator.Validate("$working_dir\wget.json") | Should -BeFalse
|
||||||
|
$validator.Errors.Count | Should -Be 1
|
||||||
|
$validator.Errors | Select-Object -First 1 | Should -Match 'broken_schema.*(line 6).*(position 4)'
|
||||||
|
}
|
||||||
|
It 'fails with broken manifest' {
|
||||||
|
$validator = New-Object Scoop.Validator($schema, $true)
|
||||||
|
$validator.Validate("$working_dir\broken_wget.json") | Should -BeFalse
|
||||||
|
$validator.Errors.Count | Should -Be 1
|
||||||
|
$validator.Errors | Select-Object -First 1 | Should -Match 'broken_wget.*(line 5).*(position 4)'
|
||||||
|
}
|
||||||
|
It 'fails with invalid manifest' {
|
||||||
|
$validator = New-Object Scoop.Validator($schema, $true)
|
||||||
|
$validator.Validate("$working_dir\invalid_wget.json") | Should -BeFalse
|
||||||
|
$validator.Errors.Count | Should -Be 16
|
||||||
|
$validator.Errors | Select-Object -First 1 | Should -Match "Property 'randomproperty' has not been defined and the schema does not allow additional properties\."
|
||||||
|
$validator.Errors | Select-Object -Last 1 | Should -Match 'Required properties are missing from object: version\.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Describe 'manifest validates against the schema' -Tag 'Manifests' {
|
||||||
|
BeforeAll {
|
||||||
|
$schema = "$PSScriptRoot\..\schema.json"
|
||||||
|
$changed_manifests = @()
|
||||||
|
if ($env:CI -eq $true) {
|
||||||
|
# AppVeyor
|
||||||
|
$commit = if ($env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT) { $env:APPVEYOR_PULL_REQUEST_HEAD_COMMIT } else { $env:APPVEYOR_REPO_COMMIT }
|
||||||
|
|
||||||
|
# GitHub Actions
|
||||||
|
if ($env:GITHUB_SHA) {
|
||||||
|
$commit = $env:GITHUB_SHA
|
||||||
|
}
|
||||||
|
$changed_manifests = (Get-GitChangedFile -Path $repo_dir -Include '*.json' -Commit $commit)
|
||||||
|
}
|
||||||
|
$manifest_files = Get-ChildItem $bucketdir *.json
|
||||||
|
$validator = New-Object Scoop.Validator($schema, $true)
|
||||||
|
}
|
||||||
|
|
||||||
|
$quota_exceeded = $false
|
||||||
|
|
||||||
|
$manifest_files | ForEach-Object {
|
||||||
|
$skip_manifest = ($changed_manifests -inotcontains $_.FullName)
|
||||||
|
if ($env:CI -ne $true -or $changed_manifests -imatch 'schema.json') {
|
||||||
|
$skip_manifest = $false
|
||||||
|
}
|
||||||
|
It "$_" -Skip:$skip_manifest {
|
||||||
|
$file = $_ # exception handling may overwrite $_
|
||||||
|
|
||||||
|
if (!($quota_exceeded)) {
|
||||||
|
try {
|
||||||
|
$validator.Validate($file.fullname)
|
||||||
|
|
||||||
|
if ($validator.Errors.Count -gt 0) {
|
||||||
|
Write-Host -f red " [-] $_ has $($validator.Errors.Count) Error$(If($validator.Errors.Count -gt 1) { 's' })!"
|
||||||
|
Write-Host -f yellow $validator.ErrorsAsString
|
||||||
|
}
|
||||||
|
$validator.Errors.Count | Should -Be 0
|
||||||
|
} catch {
|
||||||
|
if ($_.exception.message -like '*The free-quota limit of 1000 schema validations per hour has been reached.*') {
|
||||||
|
$quota_exceeded = $true
|
||||||
|
Write-Host -f darkyellow 'Schema validation limit exceeded. Will skip further validations.'
|
||||||
|
} else {
|
||||||
|
throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$manifest = parse_json $file.fullname
|
||||||
|
$url = arch_specific 'url' $manifest '32bit'
|
||||||
|
$url64 = arch_specific 'url' $manifest '64bit'
|
||||||
|
if (!$url) {
|
||||||
|
$url = $url64
|
||||||
|
}
|
||||||
|
$url | Should -Not -BeNullOrEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,35 +1,33 @@
|
|||||||
if([String]::IsNullOrEmpty($MyInvocation.PSScriptRoot)) {
|
if ([String]::IsNullOrEmpty($MyInvocation.PSScriptRoot)) {
|
||||||
Write-Error 'This script should not be called directly! It has to be imported from a buckets test file!'
|
Write-Error 'This script should not be called directly! It has to be imported from a buckets test file!'
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
describe 'Style constraints for non-binary project files' {
|
Describe 'Style constraints for non-binary project files' {
|
||||||
|
|
||||||
$files = @(
|
$files = @(
|
||||||
# gather all files except '*.exe', '*.zip', or any .git repository files
|
# gather all files except '*.exe', '*.zip', or any .git repository files
|
||||||
$repo_files |
|
$repo_files |
|
||||||
where-object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } |
|
Where-Object { $_.fullname -inotmatch $($project_file_exclusions -join '|') } |
|
||||||
where-object { $_.fullname -inotmatch '(.exe|.zip|.dll)$' } |
|
Where-Object { $_.fullname -inotmatch '(.exe|.zip|.dll)$' } |
|
||||||
where-object { $_.fullname -inotmatch '(unformated)' }
|
Where-Object { $_.fullname -inotmatch '(unformated)' }
|
||||||
)
|
)
|
||||||
|
|
||||||
$files_exist = ($files.Count -gt 0)
|
$files_exist = ($files.Count -gt 0)
|
||||||
|
|
||||||
it $('non-binary project files exist ({0} found)' -f $files.Count) -skip:$(-not $files_exist) {
|
It $('non-binary project files exist ({0} found)' -f $files.Count) -Skip:$(-not $files_exist) {
|
||||||
if (-not ($files.Count -gt 0))
|
if (-not ($files.Count -gt 0)) {
|
||||||
{
|
throw 'No non-binary project were found'
|
||||||
throw "No non-binary project were found"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'files do not contain leading UTF-8 BOM' -skip:$(-not $files_exist) {
|
It 'files do not contain leading UTF-8 BOM' -Skip:$(-not $files_exist) {
|
||||||
# UTF-8 BOM == 0xEF 0xBB 0xBF
|
# UTF-8 BOM == 0xEF 0xBB 0xBF
|
||||||
# see http://www.powershellmagazine.com/2012/12/17/pscxtip-how-to-determine-the-byte-order-mark-of-a-text-file @@ https://archive.is/RgT42
|
# see http://www.powershellmagazine.com/2012/12/17/pscxtip-how-to-determine-the-byte-order-mark-of-a-text-file @@ https://archive.is/RgT42
|
||||||
# ref: http://poshcode.org/2153 @@ https://archive.is/sGnnu
|
# ref: http://poshcode.org/2153 @@ https://archive.is/sGnnu
|
||||||
$badFiles = @(
|
$badFiles = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
if ((Get-Command Get-Content).parameters.ContainsKey('AsByteStream')) {
|
||||||
if((Get-Command Get-Content).parameters.ContainsKey('AsByteStream')) {
|
|
||||||
# PowerShell Core (6.0+) '-Encoding byte' is replaced by '-AsByteStream'
|
# PowerShell Core (6.0+) '-Encoding byte' is replaced by '-AsByteStream'
|
||||||
$content = ([char[]](Get-Content $file.FullName -AsByteStream -TotalCount 3) -join '')
|
$content = ([char[]](Get-Content $file.FullName -AsByteStream -TotalCount 3) -join '')
|
||||||
} else {
|
} else {
|
||||||
@@ -41,49 +39,42 @@ describe 'Style constraints for non-binary project files' {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badFiles.Count -gt 0)
|
if ($badFiles.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following files have utf-8 BOM: `r`n`r`n$($badFiles -join "`r`n")"
|
throw "The following files have utf-8 BOM: `r`n`r`n$($badFiles -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'files end with a newline' -skip:$(-not $files_exist) {
|
It 'files end with a newline' -Skip:$(-not $files_exist) {
|
||||||
$badFiles = @(
|
$badFiles = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
|
||||||
# Ignore previous TestResults.xml
|
# Ignore previous TestResults.xml
|
||||||
if ($file -match "TestResults.xml") {
|
if ($file -match 'TestResults.xml') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$string = [System.IO.File]::ReadAllText($file.FullName)
|
$string = [System.IO.File]::ReadAllText($file.FullName)
|
||||||
if ($string.Length -gt 0 -and $string[-1] -ne "`n")
|
if ($string.Length -gt 0 -and $string[-1] -ne "`n") {
|
||||||
{
|
|
||||||
$file.FullName
|
$file.FullName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badFiles.Count -gt 0)
|
if ($badFiles.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")"
|
throw "The following files do not end with a newline: `r`n`r`n$($badFiles -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'file newlines are CRLF' -skip:$(-not $files_exist) {
|
It 'file newlines are CRLF' -Skip:$(-not $files_exist) {
|
||||||
$badFiles = @(
|
$badFiles = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
$content = Get-Content -Raw $file.FullName
|
||||||
$content = Get-Content -raw $file.FullName
|
if (!$content) {
|
||||||
if(!$content) {
|
|
||||||
throw "File contents are null: $($file.FullName)"
|
throw "File contents are null: $($file.FullName)"
|
||||||
}
|
}
|
||||||
$lines = [regex]::split($content, '\r\n')
|
$lines = [regex]::split($content, '\r\n')
|
||||||
$lineCount = $lines.Count
|
$lineCount = $lines.Count
|
||||||
|
|
||||||
for ($i = 0; $i -lt $lineCount; $i++)
|
for ($i = 0; $i -lt $lineCount; $i++) {
|
||||||
{
|
if ( [regex]::match($lines[$i], '\r|\n').success ) {
|
||||||
if ( [regex]::match($lines[$i], '\r|\n').success )
|
|
||||||
{
|
|
||||||
$file.FullName
|
$file.FullName
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -91,52 +82,43 @@ describe 'Style constraints for non-binary project files' {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badFiles.Count -gt 0)
|
if ($badFiles.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following files have non-CRLF line endings: `r`n`r`n$($badFiles -join "`r`n")"
|
throw "The following files have non-CRLF line endings: `r`n`r`n$($badFiles -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'files have no lines containing trailing whitespace' -skip:$(-not $files_exist) {
|
It 'files have no lines containing trailing whitespace' -Skip:$(-not $files_exist) {
|
||||||
$badLines = @(
|
$badLines = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
|
||||||
# Ignore previous TestResults.xml
|
# Ignore previous TestResults.xml
|
||||||
if ($file -match "TestResults.xml") {
|
if ($file -match 'TestResults.xml') {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
$lines = [System.IO.File]::ReadAllLines($file.FullName)
|
$lines = [System.IO.File]::ReadAllLines($file.FullName)
|
||||||
$lineCount = $lines.Count
|
$lineCount = $lines.Count
|
||||||
|
|
||||||
for ($i = 0; $i -lt $lineCount; $i++)
|
for ($i = 0; $i -lt $lineCount; $i++) {
|
||||||
{
|
if ($lines[$i] -match '\s+$') {
|
||||||
if ($lines[$i] -match '\s+$')
|
|
||||||
{
|
|
||||||
'File: {0}, Line: {1}' -f $file.FullName, ($i + 1)
|
'File: {0}, Line: {1}' -f $file.FullName, ($i + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badLines.Count -gt 0)
|
if ($badLines.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")"
|
throw "The following $($badLines.Count) lines contain trailing whitespace: `r`n`r`n$($badLines -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
it 'any leading whitespace consists only of spaces (excepting makefiles)' -skip:$(-not $files_exist) {
|
It 'any leading whitespace consists only of spaces (excepting makefiles)' -Skip:$(-not $files_exist) {
|
||||||
$badLines = @(
|
$badLines = @(
|
||||||
foreach ($file in $files)
|
foreach ($file in $files) {
|
||||||
{
|
if ($file.fullname -inotmatch '(^|.)makefile$') {
|
||||||
if ($file.fullname -inotmatch '(^|.)makefile$')
|
|
||||||
{
|
|
||||||
$lines = [System.IO.File]::ReadAllLines($file.FullName)
|
$lines = [System.IO.File]::ReadAllLines($file.FullName)
|
||||||
$lineCount = $lines.Count
|
$lineCount = $lines.Count
|
||||||
|
|
||||||
for ($i = 0; $i -lt $lineCount; $i++)
|
for ($i = 0; $i -lt $lineCount; $i++) {
|
||||||
{
|
if ($lines[$i] -notmatch '^[ ]*(\S|$)') {
|
||||||
if ($lines[$i] -notmatch '^[ ]*(\S|$)')
|
|
||||||
{
|
|
||||||
'File: {0}, Line: {1}' -f $file.FullName, ($i + 1)
|
'File: {0}, Line: {1}' -f $file.FullName, ($i + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -144,8 +126,7 @@ describe 'Style constraints for non-binary project files' {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($badLines.Count -gt 0)
|
if ($badLines.Count -gt 0) {
|
||||||
{
|
|
||||||
throw "The following $($badLines.Count) lines contain TABs within leading whitespace: `r`n`r`n$($badLines -join "`r`n")"
|
throw "The following $($badLines.Count) lines contain TABs within leading whitespace: `r`n`r`n$($badLines -join "`r`n")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,56 @@
|
|||||||
. "$psscriptroot\..\libexec\scoop-alias.ps1" | out-null
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\help.ps1"
|
||||||
|
. "$PSScriptRoot\..\libexec\scoop-alias.ps1" | Out-Null
|
||||||
|
|
||||||
reset_aliases
|
Describe 'add_alias' -Tag 'Scoop' {
|
||||||
|
Mock shimdir { "$env:TEMP\shims" }
|
||||||
|
Mock set_config { }
|
||||||
|
Mock get_config { @{} }
|
||||||
|
|
||||||
describe "add_alias" -Tag 'Scoop' {
|
$shimdir = shimdir
|
||||||
mock shimdir { "TestDrive:\shim" }
|
ensure $shimdir
|
||||||
mock set_config { }
|
|
||||||
mock get_config { @{} }
|
|
||||||
|
|
||||||
$shimdir = shimdir
|
Context "alias doesn't exist" {
|
||||||
mkdir $shimdir
|
It 'creates a new alias' {
|
||||||
|
$alias_file = "$shimdir\scoop-rm.ps1"
|
||||||
|
$alias_file | Should -Not -Exist
|
||||||
|
|
||||||
context "alias doesn't exist" {
|
add_alias 'rm' '"hello, world!"'
|
||||||
it "creates a new alias" {
|
Invoke-Expression $alias_file | Should -Be 'hello, world!'
|
||||||
$alias_file = "$shimdir\scoop-rm.ps1"
|
}
|
||||||
$alias_file | should -not -exist
|
|
||||||
|
|
||||||
add_alias "rm" '"hello, world!"'
|
|
||||||
Invoke-Expression $alias_file | should -be "hello, world!"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
context "alias exists" {
|
Context 'alias exists' {
|
||||||
it "does not change existing alias" {
|
It 'does not change existing alias' {
|
||||||
$alias_file = "$shimdir\scoop-rm.ps1"
|
$alias_file = "$shimdir\scoop-rm.ps1"
|
||||||
new-item $alias_file -type file
|
New-Item $alias_file -Type File -Force
|
||||||
$alias_file | should -exist
|
$alias_file | Should -Exist
|
||||||
|
|
||||||
add_alias "rm" "test"
|
add_alias 'rm' 'test'
|
||||||
$alias_file | should -FileContentMatch ""
|
$alias_file | Should -FileContentMatch ''
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "rm_alias" {
|
Describe 'rm_alias' -Tag 'Scoop' {
|
||||||
mock shimdir { "TestDrive:\shim" }
|
Mock shimdir { "$env:TEMP\shims" }
|
||||||
mock set_config { }
|
Mock set_config { }
|
||||||
mock get_config { @{} }
|
Mock get_config { @{} }
|
||||||
|
|
||||||
$shimdir = shimdir
|
$shimdir = shimdir
|
||||||
mkdir $shimdir
|
ensure $shimdir
|
||||||
|
|
||||||
context "alias exists" {
|
Context 'alias exists' {
|
||||||
it "removes an existing alias" {
|
It 'removes an existing alias' {
|
||||||
$alias_file = "$shimdir\scoop-rm.ps1"
|
$alias_file = "$shimdir\scoop-rm.ps1"
|
||||||
add_alias "rm" '"hello, world!"'
|
add_alias 'rm' '"hello, world!"'
|
||||||
|
|
||||||
$alias_file | should -exist
|
$alias_file | Should -Exist
|
||||||
mock get_config { @(@{"rm" = "scoop-rm"}) }
|
Mock get_config { @(@{'rm' = 'scoop-rm' }) }
|
||||||
|
|
||||||
rm_alias "rm"
|
rm_alias 'rm'
|
||||||
$alias_file | should -not -exist
|
$alias_file | Should -Not -Exist
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +1,79 @@
|
|||||||
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
. "$PSScriptRoot\..\lib\core.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
|
|
||||||
Describe "config" -Tag 'Scoop' {
|
Describe 'config' -Tag 'Scoop' {
|
||||||
BeforeAll {
|
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" }'
|
$configFile = "$env:TEMP\ScoopTestFixtures\config.json"
|
||||||
}
|
if (Test-Path $configFile) {
|
||||||
|
Remove-Item -Path $configFile -Force
|
||||||
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 -BeTrue
|
|
||||||
$obj.six | Should -BeFalse
|
|
||||||
$obj.seven | Should -BeOfType [System.DateTime]
|
|
||||||
if($PSVersionTable.PSVersion.Major -lt 6) {
|
|
||||||
$obj.eight | Should -BeOfType [System.String]
|
|
||||||
} else {
|
|
||||||
$obj.eight | Should -BeOfType [System.DateTime]
|
|
||||||
}
|
}
|
||||||
|
$unicode = [Regex]::Unescape('\u4f60\u597d\u3053\u3093\u306b\u3061\u306f') # 你好こんにちは
|
||||||
}
|
}
|
||||||
|
|
||||||
It "load_config should return PSObject" {
|
BeforeEach {
|
||||||
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
|
|
||||||
get_config 'seven' | Should -BeOfType [System.DateTime]
|
|
||||||
if($PSVersionTable.PSVersion.Major -lt 6) {
|
|
||||||
get_config 'eight' | Should -BeOfType [System.String]
|
|
||||||
} else {
|
|
||||||
get_config 'eight' | Should -BeOfType [System.DateTime]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
It "set_config should create a new PSObject and ensure existing directory" {
|
|
||||||
$scoopConfig = $null
|
$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" {
|
It 'load_cfg should return null if config file does not exist' {
|
||||||
$scoopConfig = New-Object PSObject
|
load_cfg $configFile | Should -Be $null
|
||||||
$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 }
|
It 'set_config should be able to save typed values correctly' {
|
||||||
Mock ConvertTo-Json { '' } -Verifiable -ParameterFilter { $InputObject -is [System.Management.Automation.PSObject] }
|
# number
|
||||||
|
$scoopConfig = set_config 'one' 1
|
||||||
|
$scoopConfig.one | Should -BeExactly 1
|
||||||
|
|
||||||
$scoopConfig = set_config 'should_be_removed' $null
|
# boolean
|
||||||
$scoopConfig.should_be_removed | Should -BeNullOrEmpty
|
$scoopConfig = set_config 'two' $true
|
||||||
$scoopConfig.should_stay | Should -Be 'another_value'
|
$scoopConfig.two | Should -BeTrue
|
||||||
|
$scoopConfig = set_config 'three' $false
|
||||||
|
$scoopConfig.three | Should -BeFalse
|
||||||
|
|
||||||
Assert-VerifiableMock
|
# underline key
|
||||||
|
$scoopConfig = set_config 'under_line' 'four'
|
||||||
|
$scoopConfig.under_line | Should -BeExactly 'four'
|
||||||
|
|
||||||
|
# string
|
||||||
|
$scoopConfig = set_config 'five' 'not null'
|
||||||
|
|
||||||
|
# datetime
|
||||||
|
$scoopConfig = set_config 'time' ([System.DateTime]::Parse('2019-03-18T15:22:09.3930000+00:00', $null, [System.Globalization.DateTimeStyles]::AdjustToUniversal))
|
||||||
|
$scoopConfig.time | Should -BeOfType [System.DateTime]
|
||||||
|
|
||||||
|
# non-ASCII
|
||||||
|
$scoopConfig = set_config 'unicode' $unicode
|
||||||
|
$scoopConfig.unicode | Should -Be $unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'load_cfg should return PSObject if config file exist' {
|
||||||
|
$scoopConfig = load_cfg $configFile
|
||||||
|
$scoopConfig | Should -Not -BeNullOrEmpty
|
||||||
|
$scoopConfig | Should -BeOfType [System.Management.Automation.PSObject]
|
||||||
|
$scoopConfig.one | Should -BeExactly 1
|
||||||
|
$scoopConfig.two | Should -BeTrue
|
||||||
|
$scoopConfig.three | Should -BeFalse
|
||||||
|
$scoopConfig.under_line | Should -BeExactly 'four'
|
||||||
|
$scoopConfig.five | Should -Be 'not null'
|
||||||
|
$scoopConfig.time | Should -BeOfType [System.DateTime]
|
||||||
|
$scoopConfig.time | Should -Be ([System.DateTime]::Parse('2019-03-18T15:22:09.3930000+00:00', $null, [System.Globalization.DateTimeStyles]::AdjustToUniversal))
|
||||||
|
$scoopConfig.unicode | Should -Be $unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'get_config should return exactly the same values' {
|
||||||
|
$scoopConfig = load_cfg $configFile
|
||||||
|
(get_config 'one') | Should -BeExactly 1
|
||||||
|
(get_config 'two') | Should -BeTrue
|
||||||
|
(get_config 'three') | Should -BeFalse
|
||||||
|
(get_config 'under_line') | Should -BeExactly 'four'
|
||||||
|
(get_config 'five') | Should -Be 'not null'
|
||||||
|
(get_config 'time') | Should -BeOfType [System.DateTime]
|
||||||
|
(get_config 'time') | Should -Be ([System.DateTime]::Parse('2019-03-18T15:22:09.3930000+00:00', $null, [System.Globalization.DateTimeStyles]::AdjustToUniversal))
|
||||||
|
(get_config 'unicode') | Should -Be $unicode
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'set_config should remove a value if being set to $null' {
|
||||||
|
$scoopConfig = load_cfg $configFile
|
||||||
|
$scoopConfig = set_config 'five' $null
|
||||||
|
$scoopConfig.five | Should -BeNullOrEmpty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,87 +1,87 @@
|
|||||||
. "$psscriptroot\..\lib\core.ps1"
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
. "$psscriptroot\..\lib\unix.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$psscriptroot\Scoop-TestLib.ps1"
|
. "$PSScriptRoot\..\lib\unix.ps1"
|
||||||
|
|
||||||
$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).directory.parent.FullName
|
$repo_dir = (Get-Item $MyInvocation.MyCommand.Path).directory.parent.FullName
|
||||||
$isUnix = is_unix
|
$isUnix = is_unix
|
||||||
|
|
||||||
describe "Get-AppFilePath" -Tag 'Scoop' {
|
Describe 'Get-AppFilePath' -Tag 'Scoop' {
|
||||||
beforeall {
|
BeforeAll {
|
||||||
$working_dir = setup_working "is_directory"
|
$working_dir = setup_working 'is_directory'
|
||||||
Mock versiondir { 'local' } -Verifiable -ParameterFilter { $global -eq $false }
|
Mock currentdir { 'local' } -Verifiable -ParameterFilter { $global -eq $false }
|
||||||
Mock versiondir { 'global' } -Verifiable -ParameterFilter { $global -eq $true }
|
Mock currentdir { 'global' } -Verifiable -ParameterFilter { $global -eq $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return locally installed program" {
|
It 'should return locally installed program' {
|
||||||
Mock Test-Path { $true } -Verifiable -ParameterFilter { $Path -eq 'local\i_am_a_file.txt' }
|
Mock Test-Path { $true } -Verifiable -ParameterFilter { $Path -eq 'local\i_am_a_file.txt' }
|
||||||
Mock Test-Path { $false } -Verifiable -ParameterFilter { $Path -eq 'global\i_am_a_file.txt' }
|
Mock Test-Path { $false } -Verifiable -ParameterFilter { $Path -eq 'global\i_am_a_file.txt' }
|
||||||
Get-AppFilePath -App 'is_directory' -File 'i_am_a_file.txt' | Should -Be 'local\i_am_a_file.txt'
|
Get-AppFilePath -App 'is_directory' -File 'i_am_a_file.txt' | Should -Be 'local\i_am_a_file.txt'
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return globally installed program" {
|
It 'should return globally installed program' {
|
||||||
Mock Test-Path { $false } -Verifiable -ParameterFilter { $Path -eq 'local\i_am_a_file.txt' }
|
Mock Test-Path { $false } -Verifiable -ParameterFilter { $Path -eq 'local\i_am_a_file.txt' }
|
||||||
Mock Test-Path { $true } -Verifiable -ParameterFilter { $Path -eq 'global\i_am_a_file.txt' }
|
Mock Test-Path { $true } -Verifiable -ParameterFilter { $Path -eq 'global\i_am_a_file.txt' }
|
||||||
Get-AppFilePath -App 'is_directory' -File 'i_am_a_file.txt' | Should -Be 'global\i_am_a_file.txt'
|
Get-AppFilePath -App 'is_directory' -File 'i_am_a_file.txt' | Should -Be 'global\i_am_a_file.txt'
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return null if program is not installed" {
|
It 'should return null if program is not installed' {
|
||||||
Get-AppFilePath -App 'is_directory' -File 'i_do_not_exist' | Should -BeNullOrEmpty
|
Get-AppFilePath -App 'is_directory' -File 'i_do_not_exist' | Should -BeNullOrEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should throw if parameter is wrong or missing" {
|
It 'should throw if parameter is wrong or missing' {
|
||||||
{ Get-AppFilePath -App 'is_directory' -File } | Should -Throw
|
{ Get-AppFilePath -App 'is_directory' -File } | Should -Throw
|
||||||
{ Get-AppFilePath -App -File 'i_am_a_file.txt' } | Should -Throw
|
{ Get-AppFilePath -App -File 'i_am_a_file.txt' } | Should -Throw
|
||||||
{ Get-AppFilePath -App -File } | Should -Throw
|
{ Get-AppFilePath -App -File } | Should -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "Get-HelperPath" -Tag 'Scoop' {
|
Describe 'Get-HelperPath' -Tag 'Scoop' {
|
||||||
beforeall {
|
BeforeAll {
|
||||||
$working_dir = setup_working "is_directory"
|
$working_dir = setup_working 'is_directory'
|
||||||
}
|
}
|
||||||
it "should return path if program is installed" {
|
It 'should return path if program is installed' {
|
||||||
Mock Get-AppFilePath { '7zip\current\7z.exe' }
|
Mock Get-AppFilePath { '7zip\current\7z.exe' }
|
||||||
Get-HelperPath -Helper 7zip | Should -Be '7zip\current\7z.exe'
|
Get-HelperPath -Helper 7zip | Should -Be '7zip\current\7z.exe'
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return null if program is not installed" {
|
It 'should return null if program is not installed' {
|
||||||
Mock Get-AppFilePath { $null }
|
Mock Get-AppFilePath { $null }
|
||||||
Get-HelperPath -Helper 7zip | Should -BeNullOrEmpty
|
Get-HelperPath -Helper 7zip | Should -BeNullOrEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should throw if parameter is wrong or missing" {
|
It 'should throw if parameter is wrong or missing' {
|
||||||
{ Get-HelperPath -Helper } | Should -Throw
|
{ Get-HelperPath -Helper } | Should -Throw
|
||||||
{ Get-HelperPath -Helper Wrong } | Should -Throw
|
{ Get-HelperPath -Helper Wrong } | Should -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe "Test-HelperInstalled" -Tag 'Scoop' {
|
Describe 'Test-HelperInstalled' -Tag 'Scoop' {
|
||||||
it "should return true if program is installed" {
|
It 'should return true if program is installed' {
|
||||||
Mock Get-HelperPath { '7z.exe' }
|
Mock Get-HelperPath { '7z.exe' }
|
||||||
Test-HelperInstalled -Helper 7zip | Should -BeTrue
|
Test-HelperInstalled -Helper 7zip | Should -BeTrue
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return false if program is not installed" {
|
It 'should return false if program is not installed' {
|
||||||
Mock Get-HelperPath { $null }
|
Mock Get-HelperPath { $null }
|
||||||
Test-HelperInstalled -Helper 7zip | Should -BeFalse
|
Test-HelperInstalled -Helper 7zip | Should -BeFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should throw if parameter is wrong or missing" {
|
It 'should throw if parameter is wrong or missing' {
|
||||||
{ Test-HelperInstalled -Helper } | Should -Throw
|
{ Test-HelperInstalled -Helper } | Should -Throw
|
||||||
{ Test-HelperInstalled -Helper Wrong } | Should -Throw
|
{ Test-HelperInstalled -Helper Wrong } | Should -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "Test-Aria2Enabled" -Tag 'Scoop' {
|
Describe 'Test-Aria2Enabled' -Tag 'Scoop' {
|
||||||
it "should return true if aria2 is installed" {
|
It 'should return true if aria2 is installed' {
|
||||||
Mock Test-HelperInstalled { $true }
|
Mock Test-HelperInstalled { $true }
|
||||||
Mock get_config { $true }
|
Mock get_config { $true }
|
||||||
Test-Aria2Enabled | Should -BeTrue
|
Test-Aria2Enabled | Should -BeTrue
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return false if aria2 is not installed" {
|
It 'should return false if aria2 is not installed' {
|
||||||
Mock Test-HelperInstalled { $false }
|
Mock Test-HelperInstalled { $false }
|
||||||
Mock get_config { $false }
|
Mock get_config { $false }
|
||||||
Test-Aria2Enabled | Should -BeFalse
|
Test-Aria2Enabled | Should -BeFalse
|
||||||
@@ -96,299 +96,304 @@ describe "Test-Aria2Enabled" -Tag 'Scoop' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "Test-CommandAvailable" -Tag 'Scoop' {
|
Describe 'Test-CommandAvailable' -Tag 'Scoop' {
|
||||||
it "should return true if command exists" {
|
It 'should return true if command exists' {
|
||||||
Test-CommandAvailable 'Write-Host' | Should -BeTrue
|
Test-CommandAvailable 'Write-Host' | Should -BeTrue
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should return false if command doesn't exist" {
|
It "should return false if command doesn't exist" {
|
||||||
Test-CommandAvailable 'Write-ThisWillProbablyNotExist' | Should -BeFalse
|
Test-CommandAvailable 'Write-ThisWillProbablyNotExist' | Should -BeFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
it "should throw if parameter is wrong or missing" {
|
It 'should throw if parameter is wrong or missing' {
|
||||||
{ Test-CommandAvailable } | Should -Throw
|
{ Test-CommandAvailable } | Should -Throw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe "is_directory" -Tag 'Scoop' {
|
Describe 'is_directory' -Tag 'Scoop' {
|
||||||
beforeall {
|
BeforeAll {
|
||||||
$working_dir = setup_working "is_directory"
|
$working_dir = setup_working 'is_directory'
|
||||||
}
|
}
|
||||||
|
|
||||||
it "is_directory recognize directories" {
|
It 'is_directory recognize directories' {
|
||||||
is_directory "$working_dir\i_am_a_directory" | should -be $true
|
is_directory "$working_dir\i_am_a_directory" | Should -Be $true
|
||||||
}
|
}
|
||||||
it "is_directory recognize files" {
|
It 'is_directory recognize files' {
|
||||||
is_directory "$working_dir\i_am_a_file.txt" | should -be $false
|
is_directory "$working_dir\i_am_a_file.txt" | Should -Be $false
|
||||||
}
|
}
|
||||||
|
|
||||||
it "is_directory is falsey on unknown path" {
|
It 'is_directory is falsey on unknown path' {
|
||||||
is_directory "$working_dir\i_do_not_exist" | should -be $false
|
is_directory "$working_dir\i_do_not_exist" | Should -Be $false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "movedir" -Tag 'Scoop' {
|
Describe 'movedir' -Tag 'Scoop' {
|
||||||
$extract_dir = "subdir"
|
$extract_dir = 'subdir'
|
||||||
$extract_to = $null
|
$extract_to = $null
|
||||||
|
|
||||||
beforeall {
|
BeforeAll {
|
||||||
$working_dir = setup_working "movedir"
|
$working_dir = setup_working 'movedir'
|
||||||
}
|
}
|
||||||
|
|
||||||
it "moves directories with no spaces in path" -skip:$isUnix {
|
It 'moves directories with no spaces in path' -Skip:$isUnix {
|
||||||
$dir = "$working_dir\user"
|
$dir = "$working_dir\user"
|
||||||
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
||||||
|
|
||||||
"$dir\test.txt" | should -FileContentMatch "this is the one"
|
"$dir\test.txt" | Should -FileContentMatch 'this is the one'
|
||||||
"$dir\_tmp\$extract_dir" | should -not -exist
|
"$dir\_tmp\$extract_dir" | Should -Not -Exist
|
||||||
}
|
}
|
||||||
|
|
||||||
it "moves directories with spaces in path" -skip:$isUnix {
|
It 'moves directories with spaces in path' -Skip:$isUnix {
|
||||||
$dir = "$working_dir\user with space"
|
$dir = "$working_dir\user with space"
|
||||||
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
||||||
|
|
||||||
"$dir\test.txt" | should -FileContentMatch "this is the one"
|
"$dir\test.txt" | Should -FileContentMatch 'this is the one'
|
||||||
"$dir\_tmp\$extract_dir" | should -not -exist
|
"$dir\_tmp\$extract_dir" | Should -Not -Exist
|
||||||
|
|
||||||
# test trailing \ in from dir
|
# test trailing \ in from dir
|
||||||
movedir "$dir\_tmp\$null" "$dir\another"
|
movedir "$dir\_tmp\$null" "$dir\another"
|
||||||
"$dir\another\test.txt" | should -FileContentMatch "testing"
|
"$dir\another\test.txt" | Should -FileContentMatch 'testing'
|
||||||
"$dir\_tmp" | should -not -exist
|
"$dir\_tmp" | Should -Not -Exist
|
||||||
}
|
}
|
||||||
|
|
||||||
it "moves directories with quotes in path" -skip:$isUnix {
|
It 'moves directories with quotes in path' -Skip:$isUnix {
|
||||||
$dir = "$working_dir\user with 'quote"
|
$dir = "$working_dir\user with 'quote"
|
||||||
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
movedir "$dir\_tmp\$extract_dir" "$dir\$extract_to"
|
||||||
|
|
||||||
"$dir\test.txt" | should -FileContentMatch "this is the one"
|
"$dir\test.txt" | Should -FileContentMatch 'this is the one'
|
||||||
"$dir\_tmp\$extract_dir" | should -not -exist
|
"$dir\_tmp\$extract_dir" | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "shim" -Tag 'Scoop' {
|
Describe 'shim' -Tag 'Scoop' {
|
||||||
beforeall {
|
|
||||||
$working_dir = setup_working "shim"
|
|
||||||
$shimdir = shimdir
|
|
||||||
$(ensure_in_path $shimdir) | out-null
|
|
||||||
}
|
|
||||||
|
|
||||||
it "links a file onto the user's path" -skip:$isUnix {
|
|
||||||
{ get-command "shim-test" -ea stop } | should -throw
|
|
||||||
{ get-command "shim-test.ps1" -ea stop } | should -throw
|
|
||||||
{ get-command "shim-test.cmd" -ea stop } | should -throw
|
|
||||||
{ shim-test } | should -throw
|
|
||||||
|
|
||||||
shim "$working_dir\shim-test.ps1" $false "shim-test"
|
|
||||||
{ get-command "shim-test" -ea stop } | should -not -throw
|
|
||||||
{ get-command "shim-test.ps1" -ea stop } | should -not -throw
|
|
||||||
{ get-command "shim-test.cmd" -ea stop } | should -not -throw
|
|
||||||
shim-test | should -be "Hello, world!"
|
|
||||||
}
|
|
||||||
|
|
||||||
context "user with quote" {
|
|
||||||
it "shims a file with quote in path" -skip:$isUnix {
|
|
||||||
{ get-command "shim-test" -ea stop } | should -throw
|
|
||||||
{ shim-test } | should -throw
|
|
||||||
|
|
||||||
shim "$working_dir\user with 'quote\shim-test.ps1" $false "shim-test"
|
|
||||||
{ get-command "shim-test" -ea stop } | should -not -throw
|
|
||||||
shim-test | should -be "Hello, world!"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aftereach {
|
|
||||||
rm_shim "shim-test" $shimdir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe "rm_shim" -Tag 'Scoop' {
|
|
||||||
beforeall {
|
|
||||||
$working_dir = setup_working "shim"
|
|
||||||
$shimdir = shimdir
|
|
||||||
$(ensure_in_path $shimdir) | out-null
|
|
||||||
}
|
|
||||||
|
|
||||||
it "removes shim from path" -skip:$isUnix {
|
|
||||||
shim "$working_dir\shim-test.ps1" $false "shim-test"
|
|
||||||
|
|
||||||
rm_shim "shim-test" $shimdir
|
|
||||||
|
|
||||||
{ get-command "shim-test" -ea stop } | should -throw
|
|
||||||
{ get-command "shim-test.ps1" -ea stop } | should -throw
|
|
||||||
{ get-command "shim-test.cmd" -ea stop } | should -throw
|
|
||||||
{ shim-test } | should -throw
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Describe "get_app_name_from_ps1_shim" -Tag 'Scoop' {
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$working_dir = setup_working "shim"
|
$working_dir = setup_working 'shim'
|
||||||
$shimdir = shimdir
|
$shimdir = shimdir
|
||||||
$(ensure_in_path $shimdir) | Out-Null
|
$(ensure_in_path $shimdir) | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
It "returns empty string if file does not exist" -skip:$isUnix {
|
It "links a file onto the user's path" -Skip:$isUnix {
|
||||||
get_app_name_from_ps1_shim "non-existent-file" | should -be ""
|
{ Get-Command 'shim-test' -ea stop } | Should -Throw
|
||||||
|
{ Get-Command 'shim-test.ps1' -ea stop } | Should -Throw
|
||||||
|
{ Get-Command 'shim-test.cmd' -ea stop } | Should -Throw
|
||||||
|
{ shim-test } | Should -Throw
|
||||||
|
|
||||||
|
shim "$working_dir\shim-test.ps1" $false 'shim-test'
|
||||||
|
{ Get-Command 'shim-test' -ea stop } | Should -Not -Throw
|
||||||
|
{ Get-Command 'shim-test.ps1' -ea stop } | Should -Not -Throw
|
||||||
|
{ Get-Command 'shim-test.cmd' -ea stop } | Should -Not -Throw
|
||||||
|
shim-test | Should -Be 'Hello, world!'
|
||||||
}
|
}
|
||||||
|
|
||||||
It "returns app name if file exists and is a shim to an app" -skip:$isUnix {
|
Context 'user with quote' {
|
||||||
mkdir -p "$working_dir/mockapp/current/"
|
It 'shims a file with quote in path' -Skip:$isUnix {
|
||||||
Write-Output "" | Out-File "$working_dir/mockapp/current/mockapp.ps1"
|
{ Get-Command 'shim-test' -ea stop } | Should -Throw
|
||||||
shim "$working_dir/mockapp/current/mockapp.ps1" $false "shim-test"
|
{ shim-test } | Should -Throw
|
||||||
$shim_path = (get-command "shim-test.ps1").Path
|
|
||||||
get_app_name_from_ps1_shim "$shim_path" | should -be "mockapp"
|
|
||||||
}
|
|
||||||
|
|
||||||
It "returns empty string if file exists and is not a shim" -skip:$isUnix {
|
shim "$working_dir\user with 'quote\shim-test.ps1" $false 'shim-test'
|
||||||
Write-Output "lorem ipsum" | Out-File -Encoding ascii "$working_dir/mock-shim.ps1"
|
{ Get-Command 'shim-test' -ea stop } | Should -Not -Throw
|
||||||
get_app_name_from_ps1_shim "$working_dir/mock-shim.ps1" | should -be ""
|
shim-test | Should -Be 'Hello, world!'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AfterEach {
|
AfterEach {
|
||||||
if (Get-Command "shim-test" -ErrorAction SilentlyContinue) {
|
rm_shim 'shim-test' $shimdir
|
||||||
rm_shim "shim-test" $shimdir -ErrorAction SilentlyContinue
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Describe 'rm_shim' -Tag 'Scoop' {
|
||||||
|
BeforeAll {
|
||||||
|
$working_dir = setup_working 'shim'
|
||||||
|
$shimdir = shimdir
|
||||||
|
$(ensure_in_path $shimdir) | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'removes shim from path' -Skip:$isUnix {
|
||||||
|
shim "$working_dir\shim-test.ps1" $false 'shim-test'
|
||||||
|
|
||||||
|
rm_shim 'shim-test' $shimdir
|
||||||
|
|
||||||
|
{ Get-Command 'shim-test' -ea stop } | Should -Throw
|
||||||
|
{ Get-Command 'shim-test.ps1' -ea stop } | Should -Throw
|
||||||
|
{ Get-Command 'shim-test.cmd' -ea stop } | Should -Throw
|
||||||
|
{ shim-test } | Should -Throw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Describe 'get_app_name_from_shim' -Tag 'Scoop' {
|
||||||
|
BeforeAll {
|
||||||
|
$working_dir = setup_working 'shim'
|
||||||
|
$shimdir = shimdir
|
||||||
|
$(ensure_in_path $shimdir) | Out-Null
|
||||||
|
Mock appsdir { $working_dir }
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns empty string if file does not exist' -Skip:$isUnix {
|
||||||
|
get_app_name_from_shim 'non-existent-file' | Should -Be ''
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns app name if file exists and is a shim to an app' -Skip:$isUnix {
|
||||||
|
ensure "$working_dir/mockapp/current/"
|
||||||
|
Write-Output '' | Out-File "$working_dir/mockapp/current/mockapp1.ps1"
|
||||||
|
shim "$working_dir/mockapp/current/mockapp1.ps1" $false 'shim-test1'
|
||||||
|
$shim_path1 = (Get-Command 'shim-test1.ps1').Path
|
||||||
|
get_app_name_from_shim "$shim_path1" | Should -Be 'mockapp'
|
||||||
|
ensure "$working_dir/mockapp/1.0.0/"
|
||||||
|
Write-Output '' | Out-File "$working_dir/mockapp/1.0.0/mockapp2.ps1"
|
||||||
|
shim "$working_dir/mockapp/1.0.0/mockapp2.ps1" $false 'shim-test2'
|
||||||
|
$shim_path2 = (Get-Command 'shim-test2.ps1').Path
|
||||||
|
get_app_name_from_shim "$shim_path2" | Should -Be 'mockapp'
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'returns empty string if file exists and is not a shim' -Skip:$isUnix {
|
||||||
|
Write-Output 'lorem ipsum' | Out-File -Encoding ascii "$working_dir/mock-shim.ps1"
|
||||||
|
get_app_name_from_shim "$working_dir/mock-shim.ps1" | Should -Be ''
|
||||||
|
}
|
||||||
|
|
||||||
|
AfterAll {
|
||||||
|
if (Get-Command 'shim-test1' -ErrorAction SilentlyContinue) {
|
||||||
|
rm_shim 'shim-test1' $shimdir -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
if (Get-Command 'shim-test2' -ErrorAction SilentlyContinue) {
|
||||||
|
rm_shim 'shim-test2' $shimdir -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "$working_dir/mockapp"
|
Remove-Item -Force -Recurse -ErrorAction SilentlyContinue "$working_dir/mockapp"
|
||||||
Remove-Item -Force -ErrorAction SilentlyContinue "$working_dir/moch-shim.ps1"
|
Remove-Item -Force -ErrorAction SilentlyContinue "$working_dir/moch-shim.ps1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe "ensure_robocopy_in_path" -Tag 'Scoop' {
|
Describe 'ensure_robocopy_in_path' -Tag 'Scoop' {
|
||||||
$shimdir = shimdir $false
|
$shimdir = shimdir $false
|
||||||
mock versiondir { $repo_dir }
|
Mock versiondir { $repo_dir }
|
||||||
|
|
||||||
beforeall {
|
Context 'robocopy is not in path' {
|
||||||
reset_aliases
|
It 'shims robocopy when not on path' -Skip:$isUnix {
|
||||||
}
|
Mock Test-CommandAvailable { $false }
|
||||||
|
Test-CommandAvailable robocopy | Should -Be $false
|
||||||
context "robocopy is not in path" {
|
|
||||||
it "shims robocopy when not on path" -skip:$isUnix {
|
|
||||||
mock Test-CommandAvailable { $false }
|
|
||||||
Test-CommandAvailable robocopy | should -be $false
|
|
||||||
|
|
||||||
ensure_robocopy_in_path
|
ensure_robocopy_in_path
|
||||||
|
|
||||||
"$shimdir/robocopy.ps1" | should -exist
|
# "$shimdir/robocopy.ps1" | should -exist
|
||||||
"$shimdir/robocopy.exe" | should -exist
|
"$shimdir/robocopy.exe" | Should -Exist
|
||||||
|
|
||||||
# clean up
|
# clean up
|
||||||
rm_shim robocopy $(shimdir $false) | out-null
|
rm_shim robocopy $(shimdir $false) | Out-Null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context "robocopy is in path" {
|
Context 'robocopy is in path' {
|
||||||
it "does not shim robocopy when it is in path" -skip:$isUnix {
|
It 'does not shim robocopy when it is in path' -Skip:$isUnix {
|
||||||
mock Test-CommandAvailable { $true }
|
Mock Test-CommandAvailable { $true }
|
||||||
Test-CommandAvailable robocopy | should -be $true
|
Test-CommandAvailable robocopy | Should -Be $true
|
||||||
|
|
||||||
ensure_robocopy_in_path
|
ensure_robocopy_in_path
|
||||||
|
|
||||||
"$shimdir/robocopy.ps1" | should -not -exist
|
# "$shimdir/robocopy.ps1" | should -not -exist
|
||||||
"$shimdir/robocopy.exe" | should -not -exist
|
"$shimdir/robocopy.exe" | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe 'sanitary_path' -Tag 'Scoop' {
|
Describe 'sanitary_path' -Tag 'Scoop' {
|
||||||
it 'removes invalid path characters from a string' {
|
It 'removes invalid path characters from a string' {
|
||||||
$path = 'test?.json'
|
$path = 'test?.json'
|
||||||
$valid_path = sanitary_path $path
|
$valid_path = sanitary_path $path
|
||||||
|
|
||||||
$valid_path | should -be "test.json"
|
$valid_path | Should -Be 'test.json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe 'app' -Tag 'Scoop' {
|
Describe 'app' -Tag 'Scoop' {
|
||||||
it 'parses the bucket name from an app query' {
|
It 'parses the bucket name from an app query' {
|
||||||
$query = "C:\test.json"
|
$query = 'C:\test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "C:\test.json"
|
$app | Should -Be 'C:\test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test.json"
|
$query = 'test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test.json"
|
$app | Should -Be 'test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = ".\test.json"
|
$query = '.\test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be ".\test.json"
|
$app | Should -Be '.\test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "..\test.json"
|
$query = '..\test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "..\test.json"
|
$app | Should -Be '..\test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "\\share\test.json"
|
$query = '\\share\test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "\\share\test.json"
|
$app | Should -Be '\\share\test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "https://example.com/test.json"
|
$query = 'https://example.com/test.json'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "https://example.com/test.json"
|
$app | Should -Be 'https://example.com/test.json'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test"
|
$query = 'test'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test"
|
$app | Should -Be 'test'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "extras/enso"
|
$query = 'extras/enso'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "enso"
|
$app | Should -Be 'enso'
|
||||||
$bucket | should -be "extras"
|
$bucket | Should -Be 'extras'
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test-app"
|
$query = 'test-app'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test-app"
|
$app | Should -Be 'test-app'
|
||||||
$bucket | should -benullorempty
|
$bucket | Should -BeNullOrEmpty
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test-bucket/test-app"
|
$query = 'test-bucket/test-app'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test-app"
|
$app | Should -Be 'test-app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test-bucket/test-app@1.8.0"
|
$query = 'test-bucket/test-app@1.8.0'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test-app"
|
$app | Should -Be 'test-app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -be "1.8.0"
|
$version | Should -Be '1.8.0'
|
||||||
|
|
||||||
$query = "test-bucket/test-app@1.8.0-rc2"
|
$query = 'test-bucket/test-app@1.8.0-rc2'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test-app"
|
$app | Should -Be 'test-app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -be "1.8.0-rc2"
|
$version | Should -Be '1.8.0-rc2'
|
||||||
|
|
||||||
$query = "test-bucket/test_app"
|
$query = 'test-bucket/test_app'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test_app"
|
$app | Should -Be 'test_app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -benullorempty
|
$version | Should -BeNullOrEmpty
|
||||||
|
|
||||||
$query = "test-bucket/test_app@1.8.0"
|
$query = 'test-bucket/test_app@1.8.0'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test_app"
|
$app | Should -Be 'test_app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -be "1.8.0"
|
$version | Should -Be '1.8.0'
|
||||||
|
|
||||||
$query = "test-bucket/test_app@1.8.0-rc2"
|
$query = 'test-bucket/test_app@1.8.0-rc2'
|
||||||
$app, $bucket, $version = parse_app $query
|
$app, $bucket, $version = parse_app $query
|
||||||
$app | should -be "test_app"
|
$app | Should -Be 'test_app'
|
||||||
$bucket | should -be "test-bucket"
|
$bucket | Should -Be 'test-bucket'
|
||||||
$version | should -be "1.8.0-rc2"
|
$version | Should -Be '1.8.0-rc2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,40 @@
|
|||||||
. "$psscriptroot\Scoop-TestLib.ps1"
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
. "$psscriptroot\..\lib\decompress.ps1"
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
. "$psscriptroot\..\lib\unix.ps1"
|
. "$PSScriptRoot\..\lib\decompress.ps1"
|
||||||
. "$psscriptroot\..\lib\install.ps1"
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
. "$psscriptroot\..\lib\manifest.ps1"
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\versions.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\unix.ps1"
|
||||||
|
|
||||||
$isUnix = is_unix
|
$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 'Decompression function' -Tag 'Scoop', 'Decompress' {
|
Describe 'Decompression function' -Tag 'Scoop', 'Decompress' {
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$working_dir = setup_working 'decompress'
|
$working_dir = setup_working 'decompress'
|
||||||
|
|
||||||
It "Decompression test cases should exist" {
|
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 = "$working_dir\TestCases.zip"
|
||||||
$testcases | Should -Exist
|
$testcases | Should -Exist
|
||||||
compute_hash $testcases 'sha256' | Should -Be '695bb18cafda52644a19afd184b2545e9c48f1a191f7ff1efc26cb034587079c'
|
compute_hash $testcases 'sha256' | Should -Be '3a442e85b466833eeafbd08c57d8f51bf7ff041867ee0bdb7db1f12480b3624a'
|
||||||
if (!$isUnix) {
|
if (!$isUnix) {
|
||||||
Microsoft.Powershell.Archive\Expand-Archive $testcases $working_dir
|
Microsoft.PowerShell.Archive\Expand-Archive $testcases $working_dir
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "7zip extraction" {
|
Context '7zip extraction' {
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($env:CI) {
|
if ($env:CI) {
|
||||||
mock Get-AppFilePath { (Get-Command 7z.exe).Path }
|
Mock Get-AppFilePath { (Get-Command 7z.exe).Path }
|
||||||
} elseif(!(installed 7zip)) {
|
} elseif (!(installed 7zip)) {
|
||||||
scoop install 7zip
|
scoop install 7zip
|
||||||
}
|
}
|
||||||
$test1 = "$working_dir\7ZipTest1.7z"
|
$test1 = "$working_dir\7ZipTest1.7z"
|
||||||
@@ -40,116 +43,151 @@ Describe 'Decompression function' -Tag 'Scoop', 'Decompress' {
|
|||||||
$test4 = "$working_dir\7ZipTest4.tar.gz"
|
$test4 = "$working_dir\7ZipTest4.tar.gz"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract normal compressed file" -Skip:$isUnix {
|
It 'extract normal compressed file' -Skip:$isUnix {
|
||||||
$to = test_extract "Expand-7zipArchive" $test1
|
$to = test_extract 'Expand-7zipArchive' $test1
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(Get-ChildItem $to).Count | Should -Be 1
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract nested compressed file" -Skip:$isUnix {
|
It 'extract nested compressed file' -Skip:$isUnix {
|
||||||
# file ext: tgz
|
# file ext: tgz
|
||||||
$to = test_extract "Expand-7zipArchive" $test2
|
$to = test_extract 'Expand-7zipArchive' $test2
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(Get-ChildItem $to).Count | Should -Be 1
|
||||||
|
|
||||||
# file ext: tar.bz2
|
# file ext: tar.bz2
|
||||||
$to = test_extract "Expand-7zipArchive" $test3
|
$to = test_extract 'Expand-7zipArchive' $test3
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(Get-ChildItem $to).Count | Should -Be 1
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract nested compressed file with different inner name" -Skip:$isUnix {
|
It 'extract nested compressed file with different inner name' -Skip:$isUnix {
|
||||||
$to = test_extract "Expand-7zipArchive" $test4
|
$to = test_extract 'Expand-7zipArchive' $test4
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(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
|
$test1 | Should -Exist
|
||||||
test_extract "Expand-7zipArchive" $test1 $true
|
test_extract 'Expand-7zipArchive' $test1 $true
|
||||||
$test1 | Should -Not -Exist
|
$test1 | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "msi extraction" {
|
Context 'zstd extraction' {
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($env:CI) {
|
if ($env:CI) {
|
||||||
mock Get-AppFilePath { $env:lessmsi }
|
Mock Get-AppFilePath { $env:SCOOP_ZSTD_PATH } -ParameterFilter { $Helper -eq 'zstd' }
|
||||||
} elseif(!(installed lessmsi)) {
|
Mock Get-AppFilePath { '7z.exe' } -ParameterFilter { $Helper -eq '7zip' }
|
||||||
|
} elseif (!(installed zstd)) {
|
||||||
|
scoop install zstd
|
||||||
|
}
|
||||||
|
|
||||||
|
$test1 = "$working_dir\ZstdTest.zst"
|
||||||
|
$test2 = "$working_dir\ZstdTest.tar.zst"
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'extract normal compressed file' -Skip:$isUnix {
|
||||||
|
$to = test_extract 'Expand-ZstdArchive' $test1
|
||||||
|
$to | Should -Exist
|
||||||
|
"$to\ZstdTest" | Should -Exist
|
||||||
|
(Get-ChildItem $to).Count | Should -Be 1
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'extract nested compressed file' -Skip:$isUnix {
|
||||||
|
$to = test_extract 'Expand-ZstdArchive' $test2
|
||||||
|
$to | Should -Exist
|
||||||
|
"$to\ZstdTest" | Should -Exist
|
||||||
|
(Get-ChildItem $to).Count | Should -Be 1
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'works with "-Removal" switch ($removal param)' -Skip:$isUnix {
|
||||||
|
$test1 | Should -Exist
|
||||||
|
test_extract 'Expand-ZstdArchive' $test1 $true
|
||||||
|
$test1 | Should -Not -Exist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context 'msi extraction' {
|
||||||
|
|
||||||
|
BeforeAll {
|
||||||
|
if ($env:CI) {
|
||||||
|
Mock Get-AppFilePath { $env:SCOOP_LESSMSI_PATH }
|
||||||
|
} elseif (!(installed lessmsi)) {
|
||||||
scoop install lessmsi
|
scoop install lessmsi
|
||||||
}
|
}
|
||||||
$test1 = "$working_dir\MSITest.msi"
|
$test1 = "$working_dir\MSITest.msi"
|
||||||
$test2 = "$working_dir\MSITestNull.msi"
|
$test2 = "$working_dir\MSITestNull.msi"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract normal MSI file" -Skip:$isUnix {
|
It 'extract normal MSI file' -Skip:$isUnix {
|
||||||
mock get_config { $false }
|
Mock get_config { $false }
|
||||||
$to = test_extract "Expand-MsiArchive" $test1
|
$to = test_extract 'Expand-MsiArchive' $test1
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\MSITest\empty" | Should -Exist
|
"$to\MSITest\empty" | Should -Exist
|
||||||
(Get-ChildItem "$to\MSITest").Count | Should -Be 1
|
(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 }
|
Mock get_config { $true }
|
||||||
$to = test_extract "Expand-MsiArchive" $test2
|
$to = test_extract 'Expand-MsiArchive' $test2
|
||||||
$to | Should -Exist
|
$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 }
|
Mock get_config { $false }
|
||||||
$test1 | Should -Exist
|
$test1 | Should -Exist
|
||||||
test_extract "Expand-MsiArchive" $test1 $true
|
test_extract 'Expand-MsiArchive' $test1 $true
|
||||||
$test1 | Should -Not -Exist
|
$test1 | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "inno extraction" {
|
Context 'inno extraction' {
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
if($env:CI) {
|
if ($env:CI) {
|
||||||
mock Get-AppFilePath { $env:innounp }
|
Mock Get-AppFilePath { $env:SCOOP_INNOUNP_PATH }
|
||||||
} elseif(!(installed innounp)) {
|
} elseif (!(installed innounp)) {
|
||||||
scoop install innounp
|
scoop install innounp
|
||||||
}
|
}
|
||||||
$test = "$working_dir\InnoTest.exe"
|
$test = "$working_dir\InnoTest.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract Inno Setup file" -Skip:$isUnix {
|
It 'extract Inno Setup file' -Skip:$isUnix {
|
||||||
$to = test_extract "Expand-InnoArchive" $test
|
$to = test_extract 'Expand-InnoArchive' $test
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(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 | Should -Exist
|
||||||
test_extract "Expand-InnoArchive" $test $true
|
test_extract 'Expand-InnoArchive' $test $true
|
||||||
$test | Should -Not -Exist
|
$test | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context "zip extraction" {
|
Context 'zip extraction' {
|
||||||
|
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$test = "$working_dir\ZipTest.zip"
|
$test = "$working_dir\ZipTest.zip"
|
||||||
}
|
}
|
||||||
|
|
||||||
It "extract compressed file" -Skip:$isUnix {
|
It 'extract compressed file' -Skip:$isUnix {
|
||||||
$to = test_extract "Expand-ZipArchive" $test
|
$to = test_extract 'Expand-ZipArchive' $test
|
||||||
$to | Should -Exist
|
$to | Should -Exist
|
||||||
"$to\empty" | Should -Exist
|
"$to\empty" | Should -Exist
|
||||||
(Get-ChildItem $to).Count | Should -Be 1
|
(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 | Should -Exist
|
||||||
test_extract "Expand-ZipArchive" $test $true
|
test_extract 'Expand-ZipArchive' $test $true
|
||||||
$test | Should -Not -Exist
|
$test | Should -Not -Exist
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
98
test/Scoop-Depends.Tests.ps1
Normal file
98
test/Scoop-Depends.Tests.ps1
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
. "$PSScriptRoot\Scoop-TestLib.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\core.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\depends.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\buckets.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\install.ps1"
|
||||||
|
. "$PSScriptRoot\..\lib\manifest.ps1"
|
||||||
|
|
||||||
|
Describe 'Package Dependencies' -Tag 'Scoop' {
|
||||||
|
Context 'Requirement function' {
|
||||||
|
It 'Test 7zip requirement' {
|
||||||
|
Test-7zipRequirement -Uri 'test.xz' | Should -BeTrue
|
||||||
|
Test-7zipRequirement -Uri 'test.bin' | Should -BeFalse
|
||||||
|
Test-7zipRequirement -Uri @('test.xz', 'test.bin') | Should -BeTrue
|
||||||
|
}
|
||||||
|
It 'Test Zstd requirement' {
|
||||||
|
Test-ZstdRequirement -Uri 'test.zst' | Should -BeTrue
|
||||||
|
Test-ZstdRequirement -Uri 'test.bin' | Should -BeFalse
|
||||||
|
Test-ZstdRequirement -Uri @('test.zst', 'test.bin') | Should -BeTrue
|
||||||
|
}
|
||||||
|
It 'Test lessmsi requirement' {
|
||||||
|
Mock get_config { $true }
|
||||||
|
Test-LessmsiRequirement -Uri 'test.msi' | Should -BeTrue
|
||||||
|
Test-LessmsiRequirement -Uri 'test.bin' | Should -BeFalse
|
||||||
|
Test-LessmsiRequirement -Uri @('test.msi', 'test.bin') | Should -BeTrue
|
||||||
|
}
|
||||||
|
It 'Allow $Uri be $null' {
|
||||||
|
Test-7zipRequirement -Uri $null | Should -BeFalse
|
||||||
|
Test-ZstdRequirement -Uri $null | Should -BeFalse
|
||||||
|
Test-LessmsiRequirement -Uri $null | Should -BeFalse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context 'InstallationHelper function' {
|
||||||
|
BeforeAll {
|
||||||
|
$working_dir = setup_working 'format/formated'
|
||||||
|
$manifest1 = parse_json (Join-Path $working_dir '3-array-with-single-and-multi.json')
|
||||||
|
$manifest2 = parse_json (Join-Path $working_dir '4-script-block.json')
|
||||||
|
Mock Test-HelperInstalled { $false }
|
||||||
|
}
|
||||||
|
It 'Get helpers from URL' {
|
||||||
|
Mock get_config { $true }
|
||||||
|
Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -Be @('lessmsi')
|
||||||
|
}
|
||||||
|
It 'Get helpers from script' {
|
||||||
|
Mock get_config { $false }
|
||||||
|
Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -Be @('7zip')
|
||||||
|
}
|
||||||
|
It 'Helpers reflect config changes' {
|
||||||
|
Mock get_config { $false } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' }
|
||||||
|
Mock get_config { $true } -ParameterFilter { $name -eq '7ZIPEXTRACT_USE_EXTERNAL' }
|
||||||
|
Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -BeNullOrEmpty
|
||||||
|
Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -BeNullOrEmpty
|
||||||
|
}
|
||||||
|
It 'Not return installed helpers' {
|
||||||
|
Mock get_config { $true } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' }
|
||||||
|
Mock get_config { $false } -ParameterFilter { $name -eq '7ZIPEXTRACT_USE_EXTERNAL' }
|
||||||
|
Mock Test-HelperInstalled { $true }-ParameterFilter { $Helper -eq '7zip' }
|
||||||
|
Mock Test-HelperInstalled { $false }-ParameterFilter { $Helper -eq 'Lessmsi' }
|
||||||
|
Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -Be @('lessmsi')
|
||||||
|
Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -BeNullOrEmpty
|
||||||
|
Mock Test-HelperInstalled { $false }-ParameterFilter { $Helper -eq '7zip' }
|
||||||
|
Mock Test-HelperInstalled { $true }-ParameterFilter { $Helper -eq 'Lessmsi' }
|
||||||
|
Get-InstallationHelper -Manifest $manifest1 -Architecture '32bit' | Should -BeNullOrEmpty
|
||||||
|
Get-InstallationHelper -Manifest $manifest2 -Architecture '32bit' | Should -Be @('7zip')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context 'Dependencies resolution' {
|
||||||
|
BeforeAll {
|
||||||
|
Mock Test-HelperInstalled { $false }
|
||||||
|
Mock get_config { $true } -ParameterFilter { $name -eq 'MSIEXTRACT_USE_LESSMSI' }
|
||||||
|
Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'lessmsi' }
|
||||||
|
Mock Find-Manifest { $null, @{ url = 'test.msi' }, $null, $null } -ParameterFilter { $AppName -eq '7zip' }
|
||||||
|
Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'innounp' }
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'Resolve install dependencies' {
|
||||||
|
Mock Find-Manifest { $null, @{ url = 'test.7z' }, $null, $null }
|
||||||
|
Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('lessmsi', '7zip', 'test')
|
||||||
|
Mock Find-Manifest { $null, @{ innosetup = $true }, $null, $null }
|
||||||
|
Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('innounp', 'test')
|
||||||
|
}
|
||||||
|
It 'Resolve script dependencies' {
|
||||||
|
Mock Find-Manifest { $null, @{ pre_install = 'Expand-7zipArchive ' }, $null, $null }
|
||||||
|
Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('lessmsi', '7zip', 'test')
|
||||||
|
}
|
||||||
|
It 'Resolve runtime dependencies' {
|
||||||
|
Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'depends' }
|
||||||
|
Mock Find-Manifest { $null, @{ depends = 'depends' }, $null, $null }
|
||||||
|
Get-Dependency -AppName 'test' -Architecture '32bit' | Should -Be @('depends', 'test')
|
||||||
|
}
|
||||||
|
It 'Keep bucket name of app' {
|
||||||
|
Mock Find-Manifest { $null, @{}, $null, $null } -ParameterFilter { $AppName -eq 'bucket/depends' }
|
||||||
|
Mock Find-Manifest { $null, @{ depends = 'bucket/depends' }, $null, $null }
|
||||||
|
Get-Dependency -AppName 'anotherbucket/test' -Architecture '32bit' | Should -Be @('bucket/depends', 'anotherbucket/test')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user