Repository navigation
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·453 lines (390 loc) · 14.6 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·453 lines (390 loc) · 14.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
#!/usr/bin/env bash
# TRCC Linux — Auto-install / uninstall script
# Bootstraps pip, installs trcc-linux, delegates to `trcc setup` for deps.
# Usage:
# sudo ./install.sh # install
# sudo ./install.sh --uninstall # uninstall
# ./install.sh --help
# Re-exec under bash if invoked via 'sh install.sh' (dash doesn't support pipefail)
if [ -z "${BASH_VERSION:-}" ]; then
exec bash "$0" "$@"
fi
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TRCC_VERSION="$(grep '^__version__ =' "$SCRIPT_DIR/src/trcc/__version__.py" 2>/dev/null | sed 's/.*"\(.*\)"/\1/' || echo "unknown")"
# Paths
UDEV_RULES="/etc/udev/rules.d/99-trcc-lcd.rules"
RGB_UDEV_RULES="/etc/udev/rules.d/70-trcc-rgb.rules"
MODPROBE_CONF="/etc/modprobe.d/trcc-lcd.conf"
# Resolve real user when running under sudo
REAL_USER="${SUDO_USER:-$USER}"
REAL_HOME="$(getent passwd "$REAL_USER" | cut -d: -f6)"
DESKTOP_FILE="$REAL_HOME/.local/share/applications/trcc.desktop"
AUTOSTART_FILE="$REAL_HOME/.config/autostart/trcc.desktop"
CONFIG_DIR="$REAL_HOME/.trcc"
USER_CONTENT_DIR="$REAL_HOME/.trcc-user"
LEGACY_CONFIG_DIR="$REAL_HOME/.config/trcc"
VENV_DIR="$REAL_HOME/trcc-env"
USE_VENV=false
# ── Colors ───────────────────────────────────────────────────────────────────
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BOLD='\033[1m'
RESET='\033[0m'
else
RED='' GREEN='' YELLOW='' BOLD='' RESET=''
fi
info() { echo -e "${GREEN}[TRCC]${RESET} $*"; }
warn() { echo -e "${YELLOW}[WARN]${RESET} $*"; }
error() { echo -e "${RED}[ERROR]${RESET} $*" >&2; }
step() { echo -e "\n${BOLD}==> $1: $2${RESET}"; }
ask_yn() {
local prompt="$1" default="${2:-n}"
if [ "$default" = "y" ]; then
prompt="$prompt [Y/n] "
else
prompt="$prompt [y/N] "
fi
read -rp "$prompt" answer
answer="${answer:-$default}"
[[ "$answer" =~ ^[Yy] ]]
}
# ── Checks ───────────────────────────────────────────────────────────────────
check_bash_version() {
if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
error "Bash 4+ required (you have $BASH_VERSION)"
exit 1
fi
}
check_python() {
if ! command -v python3 &>/dev/null; then
error "Python 3 not found. Install it with your package manager first."
exit 1
fi
local py_ver
py_ver="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
local major minor
major="${py_ver%%.*}"
minor="${py_ver#*.}"
if [ "$major" -lt 3 ] || { [ "$major" -eq 3 ] && [ "$minor" -lt 9 ]; }; then
error "Python 3.9+ required (found $py_ver)"
exit 1
fi
info "Python $py_ver"
}
check_repo_root() {
if [ ! -f "$SCRIPT_DIR/pyproject.toml" ] || [ ! -d "$SCRIPT_DIR/src/trcc" ]; then
error "Run this script from the TRCC Linux repository root."
exit 1
fi
}
check_root() {
if [ "$(id -u)" -ne 0 ]; then
error "Root required for system setup."
echo " Run: sudo $0"
exit 1
fi
}
# ── Immutable Distro Detection ─────────────────────────────────────────────
# Only needed to decide pip vs venv. All dep install is handled by `trcc setup`.
detect_immutable() {
if [ ! -f /etc/os-release ]; then
return
fi
# shellcheck source=/dev/null
. /etc/os-release
local distro_id="${ID:-unknown}"
local variant="${VARIANT_ID:-}"
if [ "$distro_id" = "bazzite" ]; then
USE_VENV=true
return
fi
if [ "$distro_id" = "fedora" ] && command -v rpm-ostree &>/dev/null; then
case "$variant" in
silverblue|kinoite|sway-atomic|budgie-atomic|onyx)
USE_VENV=true
return
;;
esac
fi
if [ "$distro_id" = "steamos" ]; then
USE_VENV=true
return
fi
if [ "$distro_id" = "nixos" ]; then
warn "NixOS detected. This script cannot manage declarative packages."
warn "Follow the NixOS section in doc/GUIDE_INSTALL.md instead."
exit 0
fi
}
# ── Ensure pip ─────────────────────────────────────────────────────────────
ensure_pip() {
if python3 -m pip --version &>/dev/null; then
info "pip available"
return
fi
warn "pip not found — attempting to install..."
# Try ensurepip first (works on most distros)
if python3 -m ensurepip --default-pip 2>/dev/null; then
info "pip installed via ensurepip"
return
fi
# Fall back to package manager
if command -v dnf &>/dev/null; then
dnf install -y python3-pip
elif command -v apt &>/dev/null; then
apt update -y && apt install -y python3-pip python3-venv
elif command -v pacman &>/dev/null; then
pacman -S --noconfirm --needed python-pip
elif command -v zypper &>/dev/null; then
zypper install -y python3-pip
elif command -v xbps-install &>/dev/null; then
xbps-install -y python3-pip
elif command -v apk &>/dev/null; then
apk add py3-pip
elif command -v eopkg &>/dev/null; then
eopkg install -y python3-pip
else
error "Cannot install pip automatically. Install python3-pip manually."
exit 1
fi
if ! python3 -m pip --version &>/dev/null; then
error "pip still not available after install attempt."
exit 1
fi
info "pip installed"
}
# ── Python Install ──────────────────────────────────────────────────────────
install_trcc() {
if [ "$USE_VENV" = true ]; then
install_trcc_venv
return
fi
info "Installing TRCC via pip..."
if sudo -u "$REAL_USER" pip install --break-system-packages -e "$SCRIPT_DIR" 2>/dev/null; then
info "pip install succeeded."
else
warn "pip refused direct install — using virtual environment instead."
USE_VENV=true
install_trcc_venv
return
fi
check_trcc_on_path
}
install_trcc_venv() {
info "Setting up virtual environment at $VENV_DIR..."
if [ -d "$VENV_DIR" ]; then
if ask_yn "Virtual environment already exists at $VENV_DIR. Recreate it?"; then
rm -rf "$VENV_DIR"
fi
fi
if [ ! -d "$VENV_DIR" ]; then
sudo -u "$REAL_USER" python3 -m venv "$VENV_DIR"
fi
sudo -u "$REAL_USER" "$VENV_DIR/bin/pip" install -e "$SCRIPT_DIR"
info "Installed in venv: $VENV_DIR"
}
check_trcc_on_path() {
if command -v trcc &>/dev/null; then
info "trcc $(trcc --version 2>/dev/null || echo '') is ready."
return
fi
local pip_bin="$REAL_HOME/.local/bin"
if [ -f "$pip_bin/trcc" ]; then
warn "'trcc' installed to $pip_bin but it's not on your PATH."
warn "Add it with:"
warn " echo 'export PATH=\"\$PATH:\$HOME/.local/bin\"' >> ~/.bashrc"
warn " source ~/.bashrc"
fi
}
# ── Resolve trcc command ───────────────────────────────────────────────────
find_trcc_cmd() {
if command -v trcc &>/dev/null; then
echo "trcc"
elif [ -f "$VENV_DIR/bin/trcc" ]; then
echo "$VENV_DIR/bin/trcc"
elif [ -f "$REAL_HOME/.local/bin/trcc" ]; then
echo "$REAL_HOME/.local/bin/trcc"
else
echo "PYTHONPATH=$SCRIPT_DIR/src python3 -m trcc.cli"
fi
}
# ── Install Orchestrator ──────────────────────────────────────────────────
do_install() {
echo -e "${BOLD}TRCC Linux Installer v${TRCC_VERSION}${RESET}"
echo ""
check_bash_version
check_repo_root
check_root
step "1/3" "Checking Python & pip..."
check_python
detect_immutable
if [ "$USE_VENV" = true ]; then
info "Immutable distro — will use virtual environment."
fi
ensure_pip
step "2/3" "Installing TRCC Python package..."
install_trcc
step "3/3" "Running setup wizard (deps, udev, desktop entry)..."
local trcc_cmd
trcc_cmd="$(find_trcc_cmd)"
info "Running: $trcc_cmd system setup"
# `trcc system setup` writes /etc udev rules + modprobe quirks (needs root).
# The command is `system setup` — the old top-level `setup` was renamed in
# the cutover, so `setup --yes` failed with "No such command" and installs
# silently shipped WITHOUT udev rules.
#
# Run it AS ROOT (install.sh already is — check_root), NOT as the real user:
# setup re-execs its privileged udev step as root via `python -c`, and that
# root process can't import a user-local ~/.local trcc (ModuleNotFoundError
# → no rules written). Running as root from the start skips that re-exec;
# we put the user's site-packages on PYTHONPATH so root can import trcc.
local py_ver site_paths
py_ver="$(sudo -u "$REAL_USER" python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
site_paths="$REAL_HOME/.local/lib/python${py_ver}/site-packages"
if [ -d "$VENV_DIR/lib/python${py_ver}/site-packages" ]; then
site_paths="$VENV_DIR/lib/python${py_ver}/site-packages:$site_paths"
fi
if [[ "$trcc_cmd" == PYTHONPATH=* ]]; then
eval "$trcc_cmd system setup"
else
PYTHONPATH="$site_paths:$SCRIPT_DIR/src" "$trcc_cmd" system setup
fi
print_success
}
print_success() {
echo ""
echo -e "${GREEN}${BOLD}=== TRCC Linux v${TRCC_VERSION} installed ===${RESET}"
echo ""
echo "Next steps:"
echo " 1. Unplug and replug the USB cable (or reboot)"
if [ "$USE_VENV" = true ]; then
echo " 2. source $VENV_DIR/bin/activate"
echo " 3. trcc gui"
else
echo " 2. trcc gui"
fi
echo ""
echo "Troubleshooting:"
echo " trcc detect # check if the device is found"
echo " trcc display test <vid:pid> # color cycle test"
echo " trcc report -o trcc-report.txt # full diagnostic, attach to an issue"
echo ""
echo "Full guide: doc/GUIDE_INSTALL.md"
}
# ── Uninstall ──────────────────────────────────────────────────────────────
do_uninstall() {
echo -e "${BOLD}TRCC Linux Uninstaller${RESET}"
echo ""
check_bash_version
local removed=0
# 1. pip uninstall
info "Removing TRCC Python package..."
if pip uninstall -y trcc-linux 2>/dev/null; then
removed=1
fi
if sudo -u "$REAL_USER" pip uninstall -y trcc-linux 2>/dev/null; then
removed=1
fi
# Venv
if [ -f "$VENV_DIR/bin/pip" ]; then
"$VENV_DIR/bin/pip" uninstall -y trcc-linux 2>/dev/null || true
rm -rf "$VENV_DIR"
info "Removed venv: $VENV_DIR"
removed=1
fi
# 2. System files (need root)
if [ "$(id -u)" -eq 0 ]; then
for f in "$UDEV_RULES" "$RGB_UDEV_RULES" "$MODPROBE_CONF"; do
if [ -f "$f" ]; then
rm -f "$f"
info "Removed $f"
removed=1
fi
done
if command -v udevadm &>/dev/null; then
udevadm control --reload-rules 2>/dev/null || true
udevadm trigger 2>/dev/null || true
fi
else
for f in "$UDEV_RULES" "$RGB_UDEV_RULES" "$MODPROBE_CONF"; do
if [ -f "$f" ]; then
warn "Skipped $f (run with sudo to remove)"
fi
done
fi
# 3. User files. Config and cloud data are re-created/re-downloaded on the
# next install; themes the user authored are not. Ask before those.
for dir in "$CONFIG_DIR" "$LEGACY_CONFIG_DIR"; do
if [ -d "$dir" ]; then
rm -rf "$dir"
info "Removed $dir"
removed=1
fi
done
if [ -d "$USER_CONTENT_DIR" ]; then
echo ""
warn "$USER_CONTENT_DIR holds the themes and backgrounds you made."
warn "Nothing can download them back — deleting them is permanent."
if ask_yn "Delete your own themes and custom content too?" "n"; then
rm -rf "$USER_CONTENT_DIR"
info "Removed $USER_CONTENT_DIR"
removed=1
else
info "Kept your themes in $USER_CONTENT_DIR"
fi
fi
for f in "$AUTOSTART_FILE" "$DESKTOP_FILE"; do
if [ -f "$f" ]; then
rm -f "$f"
info "Removed $f"
removed=1
fi
done
echo ""
if [ "$removed" -eq 1 ]; then
echo -e "${GREEN}${BOLD}TRCC Linux has been uninstalled.${RESET}"
else
info "Nothing to remove — TRCC is already clean."
fi
}
# ── Help ─────────────────────────────────────────────────────────────────────
print_usage() {
cat << EOF
TRCC Linux Installer v${TRCC_VERSION}
Usage:
sudo ./install.sh Install TRCC Linux
sudo ./install.sh --uninstall Remove TRCC Linux
./install.sh --help Show this help
Uninstalling removes the app, its config, and downloaded cloud data. Themes
you made yourself (~/.trcc-user) are kept unless you confirm at the prompt.
The installer bootstraps pip, installs trcc-linux, then delegates to
'trcc setup' for system dependencies, udev rules, and desktop integration.
Supported distros:
Fedora, Ubuntu, Debian, Arch, Manjaro, openSUSE, Void, Gentoo,
Alpine, Nobara, Solus, Clear Linux, Bazzite, SteamOS, and more.
For NixOS or manual install, see doc/GUIDE_INSTALL.md
EOF
}
# ── Main ─────────────────────────────────────────────────────────────────────
main() {
case "${1:-}" in
--uninstall)
do_uninstall
;;
--help|-h)
print_usage
;;
"")
do_install
;;
*)
error "Unknown argument: $1"
print_usage
exit 1
;;
esac
}
main "$@"