Skip to content

Commit 9c570d1

Browse files
authored
Install extra packages by name via Package Control (#304)
A line in `extra-packages` without a `/` is now treated as a package name. It's added to `installed_packages` in Package Control's settings, so Package Control installs the latest compatible release on startup. The install helper waits for these packages before checking libraries and fails with the list of packages it could not install. Also fix a KeyError when reporting missing libraries.
1 parent 36eb591 commit 9c570d1

6 files changed

Lines changed: 126 additions & 7 deletions

File tree

‎.github/workflows/test.yaml‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,22 @@ jobs:
8080
SublimeText/UnitTesting
8181
- uses: "./UnitTesting/actions/run-tests"
8282
- uses: "./UnitTesting/actions/run-syntax-tests"
83+
84+
test-package-control-extra-packages:
85+
strategy:
86+
fail-fast: false
87+
matrix:
88+
st-version: [3, 4]
89+
os: ["ubuntu-latest", "macOS-latest", "windows-latest"]
90+
runs-on: ${{ matrix.os }}
91+
steps:
92+
- uses: actions/checkout@v6
93+
- uses: "./actions/setup"
94+
with:
95+
sublime-text-version: ${{ matrix.st-version }}
96+
extra-packages: |
97+
A File Icon
98+
- name: Check package installed by Package Control
99+
run: test -f "${SUBLIME_TEXT_PACKAGES%/}/../Installed Packages/A File Icon.sublime-package"
100+
shell: bash
101+
- uses: "./actions/run-tests"

‎README.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,14 @@ jobs:
336336
- uses: codecov/codecov-action@v4
337337
```
338338

339+
`extra-packages` takes one package per line, in one of these forms:
340+
341+
- `user/repo@ref` or `Package Name:user/repo@ref` clones the package from GitHub.
342+
`@ref` is a branch, a tag or a tag prefix (e.g. `st3-`). Without it, the latest `x.y.z` tag is used.
343+
- `Package Name` (no `/`) lets Package Control install the package,
344+
picking the latest release compatible with the Sublime Text build.
345+
Requires `install-package-control: true` (the default).
346+
339347
Check [this](https://github.com/randy3k/UnitTesting-example) for further examples.
340348

341349

‎actions/setup/action.yaml‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ inputs:
4848
or just `user/repo@ref` if the repo name is the same as the package name. `@ref` could
4949
be either a branch name, a tag name , or a prefix of tags e.g. `st3-` or simply left
5050
empty. If an exact match is not found, the latest tag is determined by semver x.y.z.
51+
A line with just a package name (no `/`), e.g. `A File Icon`, installs the package via
52+
Package Control, which picks the latest release compatible with the Sublime Text build.
53+
This requires `install-package-control` to be enabled.
5154
required: false
5255
display:
5356
description: internal and experimental only
@@ -214,6 +217,7 @@ runs:
214217
fi
215218
216219
# Install extra packages to to Packages/<Package>
220+
PC_PACKAGES=""
217221
while read -r x; do
218222
if [[ "$x" =~ ^(.*):(.*)/([^@]*)@?(.*)$ ]]; then
219223
PKG="${BASH_REMATCH[1]}"
@@ -225,12 +229,29 @@ runs:
225229
USER="${BASH_REMATCH[1]}"
226230
REPO="${BASH_REMATCH[2]}"
227231
SHA="${BASH_REMATCH[3]}"
232+
elif [ -n "$x" ]; then
233+
# Plain package name, installed by Package Control
234+
PC_PACKAGES+="$x"$'\n'
235+
continue
228236
else
229237
continue
230238
fi
231239
InstallPackage "$PKG" "https://github.com/$USER/$REPO" "$SHA"
232240
done <<< "${{ inputs.extra-packages }}"
233241
242+
# Pass packages to be installed by Package Control to the next step
243+
if [ -n "$PC_PACKAGES" ]; then
244+
if [ "${{ inputs.install-package-control }}" != "true" ]; then
245+
echo "::error::extra-packages lists packages to install via Package Control, but install-package-control is disabled."
246+
exit 1
247+
fi
248+
{
249+
echo "UNITTESTING_PC_PACKAGES<<UNITTESTING_PC_PACKAGES_EOF"
250+
printf '%s' "$PC_PACKAGES"
251+
echo "UNITTESTING_PC_PACKAGES_EOF"
252+
} >> "$GITHUB_ENV"
253+
fi
254+
234255
# Install UnitTesting to Packages/UnitTesting if not yet exists
235256
if [ ! -d "$SUBLIME_TEXT_PACKAGES/UnitTesting" ]; then
236257
echo "Copy action's 'UnitTesting' to $SUBLIME_TEXT_PACKAGES/UnitTesting"

‎actions/setup/install_package_control.ps1‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,22 @@ if (-not (Test-Path $PC_SETTINGS)) {
2626
"{`"auto_upgrade`": false, `"ignore_vcs_packages`": true, `"remove_orphaned`": false, `"submit_usage`": false }" | Out-File -filepath $PC_SETTINGS -encoding utf8
2727
}
2828

29+
# let Package Control install packages listed in `installed_packages` on startup
30+
if ($env:UNITTESTING_PC_PACKAGES) {
31+
Write-Verbose "Adding packages to be installed by Package Control:"
32+
$settings = Get-Content -Raw $PC_SETTINGS | ConvertFrom-Json
33+
$names = @($settings.installed_packages | Where-Object { $_ })
34+
foreach ($name in $env:UNITTESTING_PC_PACKAGES -split "`r?`n") {
35+
$name = $name.Trim()
36+
if ($name -and $names -notcontains $name) {
37+
Write-Verbose " $name"
38+
$names += $name
39+
}
40+
}
41+
$settings | Add-Member -NotePropertyName installed_packages -NotePropertyValue $names -Force
42+
$settings | ConvertTo-Json | Out-File -filepath $PC_SETTINGS -encoding utf8
43+
}
44+
2945
$PCH_PATH = "$STP\0_install_package_control_helper"
3046
New-Item -itemtype directory $PCH_PATH -force >$null
3147

‎actions/setup/install_package_control.sh‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,29 @@ if [ ! -f "$STP/User/Package Control.sublime-settings" ]; then
5555
echo '{"auto_upgrade": false, "ignore_vcs_packages": true, "remove_orphaned": false, "submit_usage": false }' > "$STP/User/Package Control.sublime-settings"
5656
fi
5757

58+
# let Package Control install packages listed in `installed_packages` on startup
59+
if [ -n "$UNITTESTING_PC_PACKAGES" ]; then
60+
echo Adding packages to be installed by Package Control:
61+
printf '%s' "$UNITTESTING_PC_PACKAGES" | sed 's/^/ /'
62+
python3 -B - "$STP/User/Package Control.sublime-settings" <<'EOF'
63+
import json
64+
import os
65+
import sys
66+
67+
path = sys.argv[1]
68+
with open(path, encoding="utf-8") as f:
69+
settings = json.load(f)
70+
names = settings.get("installed_packages", [])
71+
for name in os.environ["UNITTESTING_PC_PACKAGES"].splitlines():
72+
name = name.strip()
73+
if name and name not in names:
74+
names.append(name)
75+
settings["installed_packages"] = names
76+
with open(path, "w", encoding="utf-8") as f:
77+
json.dump(settings, f, indent=4)
78+
EOF
79+
fi
80+
5881
PCH_PATH="$STP/0_install_package_control_helper"
5982

6083
if [ ! -d "$PCH_PATH" ]; then

‎actions/setup/install_package_control_helper.py‎

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,48 @@ def check_package_control():
4444
Wait for Package Control to be loaded.
4545
"""
4646
if "Package Control" in sys.modules:
47-
sublime.set_timeout(check_libraries, 2000)
47+
sublime.set_timeout(check_packages, 2000)
4848
else:
4949
sublime.set_timeout(check_package_control, 2000)
5050

5151
num_retries = 0
5252

53+
def retry(callback):
54+
"""
55+
Schedule another check, return False if out of retries.
56+
"""
57+
nonlocal num_retries
58+
59+
if num_retries < 20:
60+
num_retries += 1
61+
sublime.set_timeout(callback, 2000)
62+
return True
63+
64+
return False
65+
66+
def check_packages():
67+
"""
68+
Wait for Package Control to install missing packages.
69+
70+
PC4 automatically installs packages listed in `installed_packages`
71+
at startup, before installing missing libraries.
72+
"""
73+
package_control = sys.modules["Package Control"].package_control
74+
manager = package_control.package_manager.PackageManager()
75+
settings = sublime.load_settings("Package Control.sublime-settings")
76+
missing_packages = set(settings.get("installed_packages", [])) - manager.list_packages()
77+
if not missing_packages:
78+
check_libraries()
79+
return
80+
81+
if retry(check_packages):
82+
return
83+
84+
log.write("missing packages:" + "\n")
85+
log.write("\n".join("- " + name for name in sorted(missing_packages)) + "\n")
86+
touch("failed")
87+
kill_subl(restart=False)
88+
5389
def check_libraries():
5490
"""
5591
Wait for Package Control to finish bootstrapping.
@@ -61,17 +97,13 @@ def check_libraries():
6197
manager = package_control.package_manager.PackageManager()
6298
missing_libraries = manager.find_missing_libraries()
6399
if missing_libraries:
64-
nonlocal num_retries
65-
66-
if num_retries < 10:
67-
num_retries += 1
68-
sublime.set_timeout(check_libraries, 2000)
100+
if retry(check_libraries):
69101
return
70102

71103
log.write("missing libraries:" + "\n")
72104
log.write(
73105
"\n".join(
74-
"- {lib.name} for Python {lib.python_version}".format(lib)
106+
"- {lib.name} for Python {lib.python_version}".format(lib=lib)
75107
for lib in sorted(missing_libraries)
76108
)
77109
+ "\n"

0 commit comments

Comments
 (0)