-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflutter-tool.sh
More file actions
executable file
·367 lines (321 loc) · 11 KB
/
flutter-tool.sh
File metadata and controls
executable file
·367 lines (321 loc) · 11 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
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# ================= CONFIG =================
DEFAULT_REPO="zhzhzhy/Flutter-SDK-ARM64"
FLUTTER_REPO="${FLUTTER_REPO_URL:-$DEFAULT_REPO}"
FLUTTER_VERSION="${FLUTTER_VERSION:-latest}"
CACHE_DIR="$HOME/.cache/flutter-tool"
INSTALL_DIR="$HOME/.flutter-tool"
BIN_DIR="$HOME/.local/bin"
FLUTTER_BIN="$INSTALL_DIR/flutter/bin/flutter"
VERSION_FILE="$CACHE_DIR/.version"
BASHRC="$HOME/.bashrc"
# ================= FLAGS =================
CMD="${1:-help}"; shift || true
AUTO_YES=0
NO_API=0
PURGE_CACHE=0
UPGRADE_FLAG=0
FIX_DART_FLAG=0
while [[ $# -gt 0 ]]; do
case "$1" in
--yes|-y) AUTO_YES=1 ;;
--no-api) NO_API=1 ;;
--purge-cache) PURGE_CACHE=1 ;;
--upgrade) UPGRADE_FLAG=1 ;;
--fix-dart) FIX_DART_FLAG=1 ;;
*) echo -e "\e[31mUnknown flag: $1\e[0m"; exit 1 ;;
esac
shift
done
# ================= COLORS =================
COLOR_INFO="\e[34m"
COLOR_SUCCESS="\e[32m"
COLOR_ERROR="\e[31m"
COLOR_WARN="\e[33m"
COLOR_RESET="\e[0m"
# ================= UTILS =================
die() { echo -e "${COLOR_ERROR}❌ $*${COLOR_RESET}"; exit 1; }
log() { echo -e "${COLOR_INFO}▶ $*${COLOR_RESET}"; }
success() { echo -e "${COLOR_SUCCESS}✅ $*${COLOR_RESET}"; }
warn() { echo -e "${COLOR_WARN}⚠ $*${COLOR_RESET}"; }
need() { command -v "$1" >/dev/null || die "Missing dependency: $1"; }
spinner() {
local pid=$1
local msg=$2
local delay=0.1
local spinstr='|/-\'
while kill -0 "$pid" 2>/dev/null; do
for i in $(seq 0 3); do
printf "\r${COLOR_INFO}⏳ ${spinstr:i:1} $msg...${COLOR_RESET}"
sleep $delay
done
done
printf "\r${COLOR_SUCCESS}✔ $msg${COLOR_RESET}\n"
}
basic_checks() { need wget; need unzip; need tar; }
is_installed() {
[[ -x "$FLUTTER_BIN" ]] && "$FLUTTER_BIN" --version >/dev/null 2>&1
}
# ================= DEPENDENCY CHECK =================
check_dependencies() {
local ext="$1"
case "$ext" in
zip) need unzip ;;
xz|tar.xz) need tar ;;
*) die "Unsupported archive extension: $ext" ;;
esac
}
# ================= FETCH ASSET =================
get_tag() {
local tag
if [[ "$FLUTTER_VERSION" == "latest" ]]; then
if [[ "$NO_API" -eq 0 ]]; then
if command -v jq >/dev/null; then
tag=$(wget -qO- \
--header="Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$FLUTTER_REPO/releases/latest" \
| jq -r '.tag_name // empty')
else
tag=$(wget -qO- \
--header="Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$FLUTTER_REPO/releases/latest" \
| grep -Po '"tag_name":.*?[^\\]",' \
| sed 's/.*"tag_name": "\(.*\)".*/\1/')
fi
else
tag=$(wget -q --server-response --max-redirect=0 \
"https://github.com/$FLUTTER_REPO/releases/latest" 2>&1 \
| grep -i location \
| sed 's#.*/tag/##' \
| tr -d '\r' \
| sed 's/ *$//')
fi
else
tag="$FLUTTER_VERSION"
fi
[[ -z "$tag" ]] && die "Failed to detect release tag for $FLUTTER_REPO"
echo "$tag"
}
get_asset_url() {
local tag="$1" assets asset_url
if [[ "$NO_API" -eq 0 ]]; then
if command -v jq >/dev/null; then
assets=$(wget -qO- \
--header="Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$FLUTTER_REPO/releases/tags/$tag" \
| jq -r '.assets[].browser_download_url // empty')
else
assets=$(wget -qO- \
--header="Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$FLUTTER_REPO/releases/tags/$tag" \
| grep -Po '"browser_download_url":.*?[^\\]",' \
| sed 's/.*"browser_download_url": "\(.*\)".*/\1/')
fi
if [[ "$FLUTTER_REPO" == "zhzhzhy/Flutter-SDK-ARM64" ]]; then
asset_url=$(echo "$assets" | grep -Ei 'Flutter-SDK.*\.(zip|tar\.xz)' | head -n1)
else
asset_url=$(echo "$assets" | grep -iE '(arm64|linux).*\.(zip|tar\.xz)' | head -n1)
fi
else
warn "Using fallback URL in --no-api mode"
if [[ "$FLUTTER_REPO" == "zhzhzhy/Flutter-SDK-ARM64" ]]; then
asset_url="https://github.com/$FLUTTER_REPO/releases/download/$tag/Flutter-SDK-$tag.zip"
else
asset_url="https://github.com/$FLUTTER_REPO/releases/download/$tag/flutter_linux_arm64_$tag.tar.xz"
fi
fi
[[ -z "$asset_url" ]] && die "Failed to detect Flutter asset"
echo "$asset_url"
}
get_flutter_asset() {
local tag asset_url ext
tag=$(get_tag)
asset_url=$(get_asset_url "$tag")
ext="${asset_url##*.}"
echo "$asset_url|$tag|$ext"
}
# ================= FLUTTER PREFLIGHT =================
flutter_preflight() {
log "🧪 Running Flutter preflight (initial setup & cache warmup)..."
(
"$FLUTTER_BIN" --version >/dev/null 2>&1
) &
local pid=$!
spinner "$pid" "Flutter initial configuration"
wait "$pid" || die "Flutter preflight failed"
success "Flutter preflight completed"
}
# ================= DART ARM64 FIX =================
fix_dart_sdk() {
local dart_url="https://storage.googleapis.com/dart-archive/channels/stable/release/latest/sdk/dartsdk-linux-arm64-release.zip"
local dart_zip="$CACHE_DIR/dart-sdk-arm64.zip"
log "🚀 Fixing Dart SDK..."
mkdir -p "$CACHE_DIR"
wget -q -O "$dart_zip" "$dart_url"
log "[WORKING] Removing incompatible Dart SDK..."
rm -rf "$INSTALL_DIR/flutter/bin/cache/dart-sdk"
success "[DONE] Dart SDK removed"
log "[WORKING] Injecting ARM64 Dart SDK..."
unzip -q "$dart_zip" -d "$INSTALL_DIR/flutter/bin/cache"
chmod +x "$INSTALL_DIR/flutter/bin/cache/dart-sdk/bin/dart"
rm -rf "$INSTALL_DIR/flutter/bin/cache/flutter_tools.snapshot"
success "[DONE] Dart SDK replaced"
}
# ================= SHELL INTEGRATION =================
setup_shell_integration() {
local start="# === FLUTTER-FLEXIBLE START ==="
local end="# === FLUTTER-FLEXIBLE END ==="
sed -i "/$start/,/$end/d" "$BASHRC" || true
cat >>"$BASHRC" <<EOF
$start
flutter-on() {
if [[ ":\$PATH:" != *":$INSTALL_DIR/flutter/bin:"* ]]; then
export PATH="$INSTALL_DIR/flutter/bin:\$PATH"
echo -e "${COLOR_SUCCESS}✅ Flutter bin added to PATH.${COLOR_RESET}"
else
echo -e "${COLOR_INFO}▶ Flutter bin already in PATH.${COLOR_RESET}"
fi
}
flutter-off() {
export PATH=\$(echo "\$PATH" | sed -E "s#$INSTALL_DIR/flutter/bin:##")
echo -e "${COLOR_WARN}⚠ Flutter bin removed from PATH.${COLOR_RESET}"
}
$end
EOF
success "Shell integration installed. Run 'source ~/.bashrc' and then 'flutter-on'."
}
remove_shell_integration() {
local start="# === FLUTTER-FLEXIBLE START ==="
local end="# === FLUTTER-FLEXIBLE END ==="
sed -i "/$start/,/$end/d" "$BASHRC" || true
success "Removed flutter shell functions from ~/.bashrc"
}
# ================= UNINSTALL =================
purge_all() {
local remove_cache=${1:-0}
if [[ -d "$INSTALL_DIR/flutter" ]]; then
log "[WORKING] Removing Flutter installation..."
rm -rf "$INSTALL_DIR/flutter"
success "[DONE] Flutter removed"
else
warn "Flutter installation not found"
fi
if [[ "$remove_cache" -eq 1 && -d "$CACHE_DIR" ]]; then
log "[WORKING] Removing cache directory..."
rm -rf "$CACHE_DIR"
success "[DONE] Cache removed"
fi
remove_shell_integration
success "Flutter completely uninstalled."
}
# ================= INSTALL =================
install_flutter() {
mkdir -p "$CACHE_DIR" "$INSTALL_DIR" "$BIN_DIR"
if is_installed; then
log "Flutter already installed"
[[ "$UPGRADE_FLAG" -eq 1 ]] && upgrade_flutter || check_update
return
fi
IFS='|' read -r ASSET_URL actual_tag ext <<< "$(get_flutter_asset)"
check_dependencies "$ext"
FLUTTER_FILE="$CACHE_DIR/flutter.${ext}"
log "Downloading Flutter ($ext) from $ASSET_URL"
wget -q -O "$FLUTTER_FILE" "$ASSET_URL"
log "[WORKING] Extracting Flutter..."
tmpdir=$(mktemp -d -p "$INSTALL_DIR" flutter_tmpXXXXXX)
mkdir -p "$tmpdir"
if [[ "$ext" == "zip" ]]; then
unzip -q "$FLUTTER_FILE" -d "$tmpdir"
else
tar -xf "$FLUTTER_FILE" -C "$tmpdir"
fi
success "[DONE] Extraction complete"
log "[WORKING] Moving files..."
rm -rf "$INSTALL_DIR/flutter"
mv "$tmpdir/flutter" "$INSTALL_DIR/flutter"
rm -rf "$tmpdir"
success "[DONE] Files moved"
echo "$actual_tag" > "$VERSION_FILE"
flutter_preflight
[[ "$FIX_DART_FLAG" -eq 1 ]] && fix_dart_sdk
log "🚀 Running initial Flutter doctor..."
"$FLUTTER_BIN" doctor
setup_shell_integration
echo -e "\n${COLOR_INFO}╔════════════════════════════════╗${COLOR_RESET}"
echo -e "${COLOR_INFO}║ Flutter Installation ║${COLOR_RESET}"
echo -e "${COLOR_INFO}╠════════════════════════════════╣${COLOR_RESET}"
printf "${COLOR_INFO}║ %-20s : %-14s ║\n${COLOR_RESET}" "Version" "$actual_tag"
printf "${COLOR_INFO}║ %-20s : %-14s ║\n${COLOR_RESET}" "Install Path" "$INSTALL_DIR/flutter"
echo -e "${COLOR_INFO}╚════════════════════════════════╝${COLOR_RESET}\n"
echo -e "${COLOR_INFO}▶ Run 'source ~/.bashrc' then 'flutter-on' to activate.${COLOR_RESET}"
}
# ================= UPGRADE =================
upgrade_flutter() {
if ! is_installed; then
die "Flutter is not installed, cannot upgrade."
fi
log "🚀 Upgrading Flutter..."
rm -rf "$INSTALL_DIR/flutter"
install_flutter
}
# ================= UPDATE CHECK =================
check_update() {
if ! is_installed; then
die "Flutter is not installed, cannot check updates."
fi
log "Checking for updates..."
local latest_tag
latest_tag=$(get_tag)
local current_tag
current_tag=$(<"$VERSION_FILE")
if [[ "$latest_tag" != "$current_tag" ]]; then
log "Update available: $latest_tag (current: $current_tag)"
[[ "$AUTO_YES" -eq 1 ]] && upgrade_flutter
else
success "Flutter is up to date (version $current_tag)"
fi
}
# ================= DOCTOR =================
doctor() {
if ! is_installed; then
die "Flutter is not installed."
fi
log "🚀 Running flutter doctor..."
"$FLUTTER_BIN" doctor
}
# ================= HELP =================
help() {
cat <<EOF
"Flutter ARM64 Installer v1.0.2 (Community-Distro)"
Commands:
install Install Flutter ARM64
upgrade Upgrade existing Flutter installation
update Check for updates
doctor Run Flutter doctor
purge Uninstall Flutter completely (--purge-cache to remove cache)
version|-v Show installer version
help|-h Show this help menu
Flags:
--yes, -y Automatic yes to prompts
--no-api Disable GitHub API usage
--purge-cache Remove cache during purge
--upgrade Upgrade Flutter if already installed
--fix-dart Replace Dart SDK with ARM64 binary
EOF
}
# ================= MAIN =================
basic_checks
case "$CMD" in
install)
[[ "$UPGRADE_FLAG" -eq 1 ]] && upgrade_flutter || install_flutter
;;
upgrade) upgrade_flutter ;;
update) check_update ;;
purge) purge_all "$PURGE_CACHE" ;;
doctor) doctor ;;
version|-v) echo "flutter-tool v1.0.2 (Community-Distro)" ;;
help|-h|"") help ;;
*) help; exit 1 ;;
esac