karnel-termux 4.17.7 → 4.17.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/docs/CHANGELOG.md +10 -0
- package/docs/_config.yml +3 -0
- package/docs/assets/css/{style.css → style.scss} +41 -9
- package/docs/index.md +9 -6
- package/karnel/RELEASE_COMMIT +1 -1
- package/karnel/tools/ai/antigravity-cli/install.sh +6 -3
- package/karnel/tools/deploy/railway/install.sh +10 -7
- package/karnel/tools/deploy/supabase/install.sh +3 -1
- package/karnel/tools/lang/bun/install.sh +23 -13
- package/karnel/tools/utils/zork/install.sh +5 -1
- package/karnel/utils/agent_actions.sh +3 -1
- package/karnel/utils/agent_llm.sh +14 -1
- package/karnel/utils/install.sh +17 -7
- package/karnel/utils/log.sh +3 -1
- package/karnel/utils/version.sh +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://github.com/israelmarques1024-dotcom/karnel-termux">
|
|
11
|
-
<img src="https://img.shields.io/badge/version-4.17.
|
|
11
|
+
<img src="https://img.shields.io/badge/version-4.17.8-0078D4?style=for-the-badge" alt="Version">
|
|
12
12
|
</a>
|
|
13
13
|
<a href="https://www.npmjs.com/package/karnel-termux">
|
|
14
14
|
<img src="https://img.shields.io/npm/v/karnel-termux?style=for-the-badge&logo=npm&color=cb3837" alt="npm">
|
|
@@ -61,7 +61,7 @@ Core agent contributions by **devcorex**.
|
|
|
61
61
|
### Via checksummed GitHub release (recommended)
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
version=4.17.
|
|
64
|
+
version=4.17.8
|
|
65
65
|
tmpdir=$(mktemp -d) && trap 'rm -rf "$tmpdir"' EXIT
|
|
66
66
|
base="https://github.com/israelmarques1024-dotcom/karnel-termux/releases/download/v$version"
|
|
67
67
|
curl -fsSL "$base/karnel-termux-install.sh" -o "$tmpdir/karnel-termux-install.sh"
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Documentation Changelog
|
|
2
2
|
|
|
3
|
+
## 4.17.7
|
|
4
|
+
|
|
5
|
+
- Documentation site overhauled: valid `_config.yml`, cayman-compatible custom
|
|
6
|
+
stylesheet that imports the full theme, a workflow that builds Jekyll before
|
|
7
|
+
deploying to GitHub Pages, and tool counts reconciled with the actual
|
|
8
|
+
`karnel/tools/*` and `karnel/tools/ai/*` directories (45 AI tools, 3 editors,
|
|
9
|
+
8 languages, 5 databases, 22 dev tools, 11 npm packages, 10 shell plugins,
|
|
10
|
+
4 UI components, 4 deploy CLIs, 6 games, 2 network tools, 12 utility tools,
|
|
11
|
+
30 security tools, 1 automation tool).
|
|
12
|
+
|
|
3
13
|
## 4.16.1 - 2026-08-22
|
|
4
14
|
|
|
5
15
|
- `karnel agent ask/run`: when the model endpoint is unreachable and Cactus is
|
package/docs/_config.yml
CHANGED
|
@@ -2,11 +2,14 @@ title: Karnel Termux
|
|
|
2
2
|
description: >-
|
|
3
3
|
Modular Dev Environment for Termux — install languages, databases, AI agents,
|
|
4
4
|
editors, and more with one command.
|
|
5
|
+
author: Israel Marques
|
|
6
|
+
lang: en-US
|
|
5
7
|
theme: jekyll-theme-cayman
|
|
6
8
|
markdown: kramdown
|
|
7
9
|
logo: /assets/images/karnel-logo.png
|
|
8
10
|
custom_css: /assets/css/style.css
|
|
9
11
|
baseurl: /karnel-termux
|
|
12
|
+
show_downloads: false
|
|
10
13
|
exclude:
|
|
11
14
|
- vendor
|
|
12
15
|
- Gemfile
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
---
|
|
3
|
+
|
|
4
|
+
@import "jekyll-theme-cayman";
|
|
5
|
+
|
|
1
6
|
/* Karnel Termux — custom styling layered on top of jekyll-theme-cayman */
|
|
2
7
|
|
|
3
8
|
:root {
|
|
@@ -21,6 +26,16 @@ body {
|
|
|
21
26
|
color: #24292f;
|
|
22
27
|
}
|
|
23
28
|
|
|
29
|
+
/* Logo (added in page content; cayman's default.html does not render site.logo) */
|
|
30
|
+
.karnel-logo {
|
|
31
|
+
display: block;
|
|
32
|
+
margin: 0 auto 1.25rem;
|
|
33
|
+
max-width: 220px;
|
|
34
|
+
height: auto;
|
|
35
|
+
border-radius: 14px;
|
|
36
|
+
box-shadow: 0 6px 22px rgba(0, 0, 0, 0.18);
|
|
37
|
+
}
|
|
38
|
+
|
|
24
39
|
@media (prefers-color-scheme: dark) {
|
|
25
40
|
body {
|
|
26
41
|
background: var(--karnel-bg);
|
|
@@ -53,15 +68,6 @@ body {
|
|
|
53
68
|
font-size: 1.1rem;
|
|
54
69
|
}
|
|
55
70
|
|
|
56
|
-
/* Logo */
|
|
57
|
-
.karnel-logo {
|
|
58
|
-
display: block;
|
|
59
|
-
margin: 0 auto 1.25rem;
|
|
60
|
-
max-width: 220px;
|
|
61
|
-
height: auto;
|
|
62
|
-
filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.35));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
71
|
/* Landing navigation */
|
|
66
72
|
.karnel-nav {
|
|
67
73
|
display: flex;
|
|
@@ -149,6 +155,15 @@ body {
|
|
|
149
155
|
font-size: 0.88em;
|
|
150
156
|
}
|
|
151
157
|
|
|
158
|
+
/* Inline code should not be wrapped in its own block styling */
|
|
159
|
+
.main-content p code,
|
|
160
|
+
.main-content li code,
|
|
161
|
+
.main-content td code {
|
|
162
|
+
background: rgba(120, 120, 120, 0.12);
|
|
163
|
+
padding: 0.12em 0.4em;
|
|
164
|
+
border-radius: 4px;
|
|
165
|
+
}
|
|
166
|
+
|
|
152
167
|
/* Blockquotes */
|
|
153
168
|
.main-content blockquote {
|
|
154
169
|
border-left: 4px solid var(--karnel-accent-2, #0078d4);
|
|
@@ -158,6 +173,16 @@ body {
|
|
|
158
173
|
border-radius: 0 6px 6px 0;
|
|
159
174
|
}
|
|
160
175
|
|
|
176
|
+
/* Admonition callouts */
|
|
177
|
+
.karnel-note {
|
|
178
|
+
border: 1px solid var(--karnel-accent-2, #0078d4);
|
|
179
|
+
border-left-width: 4px;
|
|
180
|
+
border-radius: 8px;
|
|
181
|
+
padding: 0.75rem 1rem;
|
|
182
|
+
margin: 1.25rem 0;
|
|
183
|
+
background: rgba(0, 120, 212, 0.06);
|
|
184
|
+
}
|
|
185
|
+
|
|
161
186
|
/* Section spacing */
|
|
162
187
|
.main-content h2 {
|
|
163
188
|
margin-top: 2.5rem;
|
|
@@ -203,3 +228,10 @@ body {
|
|
|
203
228
|
color: #e6edf3;
|
|
204
229
|
}
|
|
205
230
|
}
|
|
231
|
+
|
|
232
|
+
/* Footer credit spacing */
|
|
233
|
+
.site-footer {
|
|
234
|
+
margin-top: 2.5rem;
|
|
235
|
+
border-top: 1px solid #e1e4e8;
|
|
236
|
+
padding-top: 1rem;
|
|
237
|
+
}
|
package/docs/index.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Karnel Termux Documentation
|
|
2
2
|
|
|
3
|
+
<img class="karnel-logo" src="{{ '/assets/images/karnel-logo.png' | relative_url }}" alt="Karnel Termux">
|
|
4
|
+
|
|
3
5
|
> Modular Dev Environment for Termux — install languages, databases, AI agents, editors, and more with one command
|
|
4
6
|
|
|
5
7
|
Navigate the docs:
|
|
@@ -16,12 +18,13 @@ Navigate the docs:
|
|
|
16
18
|
## What is Karnel?
|
|
17
19
|
|
|
18
20
|
Karnel Termux transforms your Android device into a complete development workstation.
|
|
19
|
-
With a single CLI (`karnel`), you can install and manage 45 AI tools,
|
|
20
|
-
5 databases, 22 dev tools, 11 npm packages, 10 shell plugins,
|
|
21
|
-
4 deploy CLIs, 6 games, 2 network tools, 12 utility tools,
|
|
22
|
-
|
|
23
|
-
from modules: `ai`, `auto`, `db`,
|
|
24
|
-
`
|
|
21
|
+
With a single CLI (`karnel`), you can install and manage 45 AI tools, 3 editors,
|
|
22
|
+
8 languages, 5 databases, 22 dev tools, 11 npm packages, 10 shell plugins,
|
|
23
|
+
4 UI components, 4 deploy CLIs, 6 games, 2 network tools, 12 utility tools,
|
|
24
|
+
30 security tools, 1 automation tool, responsible OSINT, a second brain,
|
|
25
|
+
voice commands, and reviewed plugins — all from modules: `ai`, `auto`, `db`,
|
|
26
|
+
`deploy`, `dev`, `editor`, `games`, `lang`, `network`, `npm`, `osint`,
|
|
27
|
+
`security`, `shell`, `ui`, `utils`, `voice`, `plugin`.
|
|
25
28
|
|
|
26
29
|
## Sections
|
|
27
30
|
|
package/karnel/RELEASE_COMMIT
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ad787cd9d5efa67b498b0b1dc5e00203553b32e7
|
|
@@ -88,13 +88,16 @@ _antigravity_download_binary_impl() {
|
|
|
88
88
|
fi
|
|
89
89
|
|
|
90
90
|
if [[ "$manifest_sha256" =~ ^[0-9a-f]{64}$ ]]; then
|
|
91
|
-
verify_sha256 "$tarball" "$manifest_sha256" || return 1
|
|
91
|
+
verify_sha256 "$tarball" "$manifest_sha256" || { rm -f "$tarball"; return 1; }
|
|
92
92
|
else
|
|
93
|
-
|
|
93
|
+
log_error "Antigravity CLI manifest does not publish a SHA-256; refusing install"
|
|
94
|
+
rm -f "$tarball"
|
|
95
|
+
return 1
|
|
94
96
|
fi
|
|
95
97
|
|
|
96
|
-
if !
|
|
98
|
+
if ! safe_extract_tar "$tarball" "$AGY_DATA_DIR"; then
|
|
97
99
|
log_error "Failed to extract Antigravity CLI binary"
|
|
100
|
+
rm -f "$tarball"
|
|
98
101
|
return 1
|
|
99
102
|
fi
|
|
100
103
|
|
|
@@ -4,7 +4,7 @@ import "@/utils/log"
|
|
|
4
4
|
import "@/utils/install"
|
|
5
5
|
import "@/utils/version"
|
|
6
6
|
|
|
7
|
-
LOG_FILE="$KARNEL_CACHE/install_deploy.log"
|
|
7
|
+
LOG_FILE="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}/install_deploy.log"
|
|
8
8
|
RAILWAY_DATA_DIR="${KARNEL_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data}/deploy/railway"
|
|
9
9
|
_RAILWAY_MARKER="$PREFIX/share/karnel-installers/railway"
|
|
10
10
|
_RAILWAY_DATA_MARKER="$RAILWAY_DATA_DIR/.karnel-managed"
|
|
@@ -113,14 +113,17 @@ _install_railway_manual_impl() {
|
|
|
113
113
|
|
|
114
114
|
local expected
|
|
115
115
|
expected=$(github_release_asset_sha256 railwayapp/cli "$latest_version" "railway-${version}-aarch64-linux.tar.gz") || expected=""
|
|
116
|
-
if [[ "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
116
|
+
if [[ ! "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
117
|
+
log_error "No published SHA-256 for Railway CLI; refusing install"
|
|
118
|
+
rm -f "$RAILWAY_DATA_DIR/railway.tar.gz"
|
|
119
|
+
return 1
|
|
121
120
|
fi
|
|
121
|
+
verify_sha256 "$RAILWAY_DATA_DIR/railway.tar.gz" "$expected" || {
|
|
122
|
+
rm -f "$RAILWAY_DATA_DIR/railway.tar.gz"
|
|
123
|
+
return 1
|
|
124
|
+
}
|
|
122
125
|
|
|
123
|
-
|
|
126
|
+
safe_extract_tar "$RAILWAY_DATA_DIR/railway.tar.gz" "$RAILWAY_DATA_DIR" || {
|
|
124
127
|
rm -f "$RAILWAY_DATA_DIR/railway.tar.gz"
|
|
125
128
|
return 1
|
|
126
129
|
}
|
|
@@ -43,7 +43,9 @@ install_supabase() (
|
|
|
43
43
|
local url="${_SUPABASE_RELEASE_URL}/${filename}"
|
|
44
44
|
local checksum_url="${_SUPABASE_RELEASE_URL}/supabase_${_SUPABASE_VERSION}_checksums.txt"
|
|
45
45
|
local tmp_dir staged_bin marker_staging="" old_bin="" old_marker=""
|
|
46
|
-
|
|
46
|
+
local _kdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
47
|
+
mkdir -p "$_kdir" 2>/dev/null || _kdir="${TMPDIR:-/tmp}"
|
|
48
|
+
tmp_dir=$(mktemp -d "$_kdir/supabase.XXXXXX") || return 1
|
|
47
49
|
staged_bin=""
|
|
48
50
|
trap 'rm -rf "$tmp_dir"; [[ -z "$staged_bin" ]] || rm -f "$staged_bin"; [[ -z "$marker_staging" ]] || rm -f "$marker_staging"' EXIT
|
|
49
51
|
|
|
@@ -143,16 +143,24 @@ _download_bun_binary_native_impl() {
|
|
|
143
143
|
}
|
|
144
144
|
if declare -F github_release_asset_sha256 >/dev/null; then
|
|
145
145
|
expected=$(github_release_asset_sha256 "$BUN_REPO" "bun-v$version" "$zip_name") || expected=""
|
|
146
|
-
if [[ "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
if [[ ! "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
147
|
+
rm -rf "$staging_dir"
|
|
148
|
+
log_error "No published SHA-256 for Bun native; refusing install"
|
|
149
|
+
return 1
|
|
150
|
+
fi
|
|
151
|
+
verify_sha256 "$staging_dir/$zip_name" "$expected" || { rm -rf "$staging_dir"; return 1; }
|
|
152
|
+
if ! safe_extract_zip "$staging_dir/$zip_name" "$staging_dir"; then
|
|
153
|
+
rm -rf "$staging_dir"
|
|
154
|
+
log_error "Failed to extract Bun binary"
|
|
155
|
+
return 1
|
|
156
|
+
fi
|
|
157
|
+
else
|
|
158
|
+
command -v log_warn >/dev/null 2>&1 && log_warn "Integrity helpers unavailable; skipping Bun integrity verification"
|
|
159
|
+
if ! unzip -o "$staging_dir/$zip_name" -d "$staging_dir" &>>"$LOG_FILE"; then
|
|
160
|
+
rm -rf "$staging_dir"
|
|
161
|
+
log_error "Failed to extract Bun binary"
|
|
162
|
+
return 1
|
|
150
163
|
fi
|
|
151
|
-
fi
|
|
152
|
-
if ! unzip -o "$staging_dir/$zip_name" -d "$staging_dir" &>>"$LOG_FILE"; then
|
|
153
|
-
rm -rf "$staging_dir"
|
|
154
|
-
log_error "Failed to extract Bun binary"
|
|
155
|
-
return 1
|
|
156
164
|
fi
|
|
157
165
|
rm -f "$staging_dir/$zip_name"
|
|
158
166
|
extracted="$staging_dir/bun-linux-aarch64/bun"
|
|
@@ -280,13 +288,14 @@ _install_bun_proot_impl() {
|
|
|
280
288
|
local expected
|
|
281
289
|
expected=$(github_release_asset_sha256 "$BUN_REPO" "bun-v$version" "bun-linux-aarch64.zip") || expected=""
|
|
282
290
|
if [[ ! "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
283
|
-
|
|
291
|
+
log_error "No published SHA-256 for Bun; refusing install"
|
|
292
|
+
return 1
|
|
284
293
|
fi
|
|
285
294
|
_bun_proot_ubuntu /bin/bash -c '
|
|
286
295
|
export HOME=/root TMPDIR=/tmp
|
|
287
296
|
cd /tmp &&
|
|
288
297
|
curl -fsSL "$1" -o bun.zip &&
|
|
289
|
-
|
|
298
|
+
[ "$(sha256sum bun.zip | awk "{print \$1}")" = "$2" ] &&
|
|
290
299
|
unzip -o bun.zip >/dev/null 2>&1 &&
|
|
291
300
|
mkdir -p /usr/local/bin &&
|
|
292
301
|
mv bun-linux-aarch64/bun /usr/local/bin/bun &&
|
|
@@ -392,13 +401,14 @@ _update_bun_proot() {
|
|
|
392
401
|
local expected
|
|
393
402
|
expected=$(github_release_asset_sha256 "$BUN_REPO" "bun-v$version" "bun-linux-aarch64.zip") || expected=""
|
|
394
403
|
if [[ ! "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
395
|
-
|
|
404
|
+
log_error "No published SHA-256 for Bun; refusing update"
|
|
405
|
+
return 1
|
|
396
406
|
fi
|
|
397
407
|
_bun_proot_ubuntu /bin/bash -c '
|
|
398
408
|
export HOME=/root TMPDIR=/tmp
|
|
399
409
|
cd /tmp &&
|
|
400
410
|
curl -fsSL "$1" -o bun.zip &&
|
|
401
|
-
|
|
411
|
+
[ "$(sha256sum bun.zip | awk "{print \$1}")" = "$2" ] &&
|
|
402
412
|
unzip -o bun.zip >/dev/null 2>&1 &&
|
|
403
413
|
mkdir -p /usr/local/bin &&
|
|
404
414
|
mv bun-linux-aarch64/bun /usr/local/bin/bun &&
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import "@/utils/log"
|
|
4
4
|
import "@/utils/version"
|
|
5
|
+
import "@/utils/install"
|
|
5
6
|
|
|
6
7
|
LOG_FILE="$KARNEL_CACHE/install_zork.log"
|
|
7
8
|
ZORK_DATA_DIR="${KARNEL_DATA:-${XDG_DATA_HOME:-$HOME/.local/share}/karnel-data}/zork"
|
|
@@ -62,7 +63,10 @@ _download_zork_data_impl() {
|
|
|
62
63
|
return 1
|
|
63
64
|
fi
|
|
64
65
|
|
|
65
|
-
if
|
|
66
|
+
if declare -F safe_extract_zip >/dev/null; then
|
|
67
|
+
safe_extract_zip "$zip_file" "$staging_dir" 2>>"$LOG_FILE" || {
|
|
68
|
+
rm -rf "$staging_dir"; log_error "Failed to extract Zork ${num}"; return 1; }
|
|
69
|
+
elif ! unzip -o "$zip_file" -d "$staging_dir" 2>>"$LOG_FILE"; then
|
|
66
70
|
rm -rf "$staging_dir"
|
|
67
71
|
log_error "Failed to extract Zork ${num}"
|
|
68
72
|
return 1
|
|
@@ -889,7 +889,9 @@ agent_exec_loading() {
|
|
|
889
889
|
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
890
890
|
local delay=0.08
|
|
891
891
|
local tmpfile
|
|
892
|
-
|
|
892
|
+
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
893
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-/tmp}"
|
|
894
|
+
tmpfile="$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null)" || tmpfile="$(mktemp 2>/dev/null)"
|
|
893
895
|
|
|
894
896
|
local stty_saved=""
|
|
895
897
|
if [[ -t 0 ]]; then
|
|
@@ -244,7 +244,20 @@ agent_chat_completion() {
|
|
|
244
244
|
# characters. Real UTF-8 text passes through untouched.
|
|
245
245
|
# ------------------------------------------------------------
|
|
246
246
|
_agent_unescape_unicode() {
|
|
247
|
-
|
|
247
|
+
if command -v perl >/dev/null 2>&1; then
|
|
248
|
+
perl -CS -pe 's/\\u([0-9a-fA-F]{4})/chr(hex($1))/ge'
|
|
249
|
+
elif command -v python3 >/dev/null 2>&1; then
|
|
250
|
+
python3 -c 'import sys,re;sys.stdout.write(re.sub(r"\\u([0-9a-fA-F]{4})",lambda m:chr(int(m.group(1),16)),sys.stdin.read()))'
|
|
251
|
+
else
|
|
252
|
+
awk '{
|
|
253
|
+
while (match($0, /\\u[0-9a-fA-F]{4}/)) {
|
|
254
|
+
h = substr($0, RSTART + 2, 4)
|
|
255
|
+
c = sprintf("%c", strtonum("0x" h))
|
|
256
|
+
$0 = substr($0, 1, RSTART - 1) c substr($0, RSTART + 6)
|
|
257
|
+
}
|
|
258
|
+
print
|
|
259
|
+
}'
|
|
260
|
+
fi
|
|
248
261
|
}
|
|
249
262
|
|
|
250
263
|
# ------------------------------------------------------------
|
package/karnel/utils/install.sh
CHANGED
|
@@ -211,9 +211,11 @@ github_release_asset_sha256() {
|
|
|
211
211
|
return 0
|
|
212
212
|
fi
|
|
213
213
|
# Fallback: a checksums.txt / SHA256SUMS asset listing every released file.
|
|
214
|
+
# Match the filename field exactly (it is the LAST field) so a substring or
|
|
215
|
+
# regex-metacharacter in $asset cannot select the wrong line's digest.
|
|
214
216
|
digest=$(curl -fsSL --connect-timeout 10 --max-time 30 \
|
|
215
217
|
"https://github.com/$repo/releases/download/$version/checksums.txt" 2>/dev/null \
|
|
216
|
-
| awk -v a="$asset" '
|
|
218
|
+
| awk -v a="$asset" '{ f=$NF; if (f == a) { sub(/^\*/, "", $1); print $1; exit } }' | tr -d '\r')
|
|
217
219
|
if [[ "$digest" =~ ^[0-9a-f]{64}$ ]]; then
|
|
218
220
|
echo "$digest"
|
|
219
221
|
return 0
|
|
@@ -248,20 +250,26 @@ extract_tarball() {
|
|
|
248
250
|
|
|
249
251
|
replace_managed_directory() {
|
|
250
252
|
local staging="$1" destination="$2" marker="$3"
|
|
251
|
-
local
|
|
253
|
+
local backup_dir backup_target=""
|
|
252
254
|
if [[ -e "$destination" && ! -f "$destination/$marker" ]]; then
|
|
253
255
|
log_error "Refusing to replace unowned installation: $destination"
|
|
254
256
|
return 1
|
|
255
257
|
fi
|
|
256
258
|
printf '%s\n' 'karnel-managed-v1' >"$staging/$marker" || return 1
|
|
257
|
-
|
|
258
|
-
|
|
259
|
+
backup_dir="$(mktemp -d "$(dirname "$destination")/.karnel-managed.XXXXXX")" || return 1
|
|
260
|
+
if [[ -e "$destination" ]]; then
|
|
261
|
+
backup_target="$backup_dir/$(basename "$destination")"
|
|
262
|
+
if ! mv "$destination" "$backup_target"; then
|
|
263
|
+
rm -rf "$backup_dir"
|
|
264
|
+
return 1
|
|
265
|
+
fi
|
|
259
266
|
fi
|
|
260
267
|
if ! mv "$staging" "$destination"; then
|
|
261
|
-
[[
|
|
268
|
+
[[ -n "$backup_target" ]] && mv "$backup_target" "$destination" 2>/dev/null
|
|
269
|
+
rm -rf "$backup_dir"
|
|
262
270
|
return 1
|
|
263
271
|
fi
|
|
264
|
-
rm -rf "$
|
|
272
|
+
rm -rf "$backup_dir"
|
|
265
273
|
}
|
|
266
274
|
|
|
267
275
|
record_managed_file() {
|
|
@@ -283,7 +291,9 @@ github_download_and_extract() {
|
|
|
283
291
|
if [[ "$expected" =~ ^[0-9a-f]{64}$ ]]; then
|
|
284
292
|
verify_sha256 "$tarball" "$expected" || return 1
|
|
285
293
|
else
|
|
286
|
-
|
|
294
|
+
log_error "No verifiable SHA-256 digest published for $repo/$asset; refusing install"
|
|
295
|
+
rm -f "$tarball"
|
|
296
|
+
return 1
|
|
287
297
|
fi
|
|
288
298
|
extract_tarball "$tarball" "$outdir" || return 1
|
|
289
299
|
return 0
|
package/karnel/utils/log.sh
CHANGED
|
@@ -429,7 +429,9 @@ loading() {
|
|
|
429
429
|
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
430
430
|
local delay=0.08
|
|
431
431
|
local tmpfile
|
|
432
|
-
|
|
432
|
+
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
433
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-/tmp}"
|
|
434
|
+
tmpfile="$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null)" || tmpfile="$(mktemp 2>/dev/null)"
|
|
433
435
|
local cmd_pid=""
|
|
434
436
|
|
|
435
437
|
trap 'kill "$cmd_pid" 2>/dev/null; rm -f "$tmpfile"; return 1' INT TERM
|
package/karnel/utils/version.sh
CHANGED
|
@@ -51,7 +51,9 @@ _spin_capture() {
|
|
|
51
51
|
shift
|
|
52
52
|
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
|
|
53
53
|
local tmp
|
|
54
|
-
|
|
54
|
+
local _ktmpdir="${KARNEL_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/karnel}"
|
|
55
|
+
mkdir -p "$_ktmpdir" 2>/dev/null || _ktmpdir="${TMPDIR:-/tmp}"
|
|
56
|
+
tmp=$(mktemp "$_ktmpdir/karnel.XXXXXX" 2>/dev/null) || tmp=$(mktemp 2>/dev/null)
|
|
55
57
|
local spinner_fd
|
|
56
58
|
if [ -c /dev/tty ] 2>/dev/null; then
|
|
57
59
|
spinner_fd=/dev/tty
|
package/package.json
CHANGED