This repository has been archived by the owner on Jun 26, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bdl
462 lines (414 loc) · 16.9 KB
/
bdl
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
454
455
456
457
458
459
460
461
462
#!/bin/sh
# NOT POSIX, AT ALL. TODO: Make this not suck. Create a bash fork that does not have any of the BASH exclusive "features" and is 100% POSIX and ISO C.
# UPDATE: POSIX syntax. Still relies on undefined behaviour/BASHisms/features the GNU might have accidentally implemented in their attempt to rework Thompson Shell.
# If you install "Gum" (https://github.com/charmbracelet/gum) you will get some TUI fanciness.
# UPDATE: Dismiss the TODO; Try: "https://github.com/xplshn/bigdl", which you can statically link, and no longer depend on anything but a Linux system.
INAME="$0"
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Directories, files, etc. NOTE: Not consistent. TODO: Enhance readability, simplify variables.
INSTALL_DIR="${HOME}/.local/bin" # You may change this to whatever dir you want, make sure to add it to your PATH.
TEMP_DIR="${TMPDIR:-/tmp}/bdl_cached"
BOOTSTRAP_DIR="$HOME/.cache/bdl_bootstraped"
CACHE_FILE="${TMPDIR:-${TEMP_DIR}}/bdl_install-less_bins_cached"
METADATA_URL="https://raw.githubusercontent.com/metis-os/hysp-pkgs/main/data/metadata.json"
SYSTEM_ARCH="$(uname -m)"
if [ -z "$BASH_VERSION" ]; then
xPATH="$PATH"
PATH="$PATH:$BOOTSTRAP_DIR"
if command -v bash >/dev/null 2>&1; then
exec bash "$0" "$@"
else
echo "Running under SH, some features might not work(run), unless bash is installed or bootstrapped, there will be undefined behaviour. If the command you want to run fails try one more time. It might be related to this."
fi
PATH="$xPATH"
fi
spinner() {
if [ -z "$COOLSPINNER" ]; then
COOLSPINNER='|/-\\'
fi
if [ -z "$COOLSPINNER_COLOR" ]; then
COOLSPINNER_COLOR='\033[0m'
fi
if [ -z "$COOLSPINNER_DELAY" ]; then
COOLSPINNER_DELAY=0.1
fi
len=$(printf "%s" "$COOLSPINNER" | wc -c | awk '{print $1}')
trap 'printf "\033[?25h"; exit' INT
while true; do
i=1
while [ "$i" -le "$len" ]; do
char=$(printf "%s" "$COOLSPINNER" | cut -c "$i")
if [ -n "$COOLSPINNER_COLOR" ]; then
printf "%b%s%b" "$COOLSPINNER_COLOR" "$char" "\033[0m"
else
printf "%s" "$char"
fi
sleep "$COOLSPINNER_DELAY"
printf "\r"
i=$((i + 1))
done
done
}
# Function to display colored output
print_color() {
printf "%b%s%b\\n" "$1" "$2" "$NC"
}
# Define a helper function to determine which fetcher tool (curl or wget) should be used for bootstrapping
determine_fetcher() {
if command -v wget >/dev/null 2>&1; then
FETCHER="wget"
elif command -v curl >/dev/null 2>&1; then
FETCHER="curl"
else
printf "Neither curl nor wget found. Cannot proceed with bootstrapping.\n"
return 1
fi
}
fetch_binary() {
PACKAGE_NAME="$1"
nINSTALL_DIR="$2"
DESTINATION="${3:-$nINSTALL_DIR/$PACKAGE_NAME}"
mkdir -p "$nINSTALL_DIR"
determine_fetcher
SOURCE_URL=$(find_url "$PACKAGE_NAME")
if [ -z "$SOURCE_URL" ]; then
print_color "$YELLOW" "Source URL not found for '$PACKAGE_NAME'."
return 1
fi
COOLSPINNER_COLOR='\033[92m'
spinner & spinner_pid=$!
if [ "$FETCHER" = "curl" ]; then
if ! "$FETCHER" -o "$DESTINATION" "$SOURCE_URL" >/dev/null 2>&1; then
kill "$spinner_pid" >/dev/null 2>&1 # Stop the spinner
printf "\033[2K\r" # Clear the spinner character
print_color "$YELLOW" "Failed to fetch $PACKAGE_NAME."
return 1
fi
chmod +x "$DESTINATION" &&
kill "$spinner_pid" >/dev/null 2>&1 # Stop the spinner
printf "\033[2K\r" # Clear the spinner character
print_color "$GREEN" "Fetched binary successfully."
else
if ! "$FETCHER" -O "$DESTINATION" "$SOURCE_URL" >/dev/null 2>&1; then
kill "$spinner_pid" >/dev/null 2>&1 # Stop the spinner
printf "\033[2K\r" # Clear the spinner character
print_color "$YELLOW" "Failed to fetch $PACKAGE_NAME."
return 1
fi
chmod +x "$DESTINATION" &&
kill "$spinner_pid" >/dev/null 2>&1 # Stop the spinner
printf "\033[2K\r" # Clear the spinner character
print_color "$GREEN" "Fetched binary successfully."
fi
}
# Function to retrieve cached file location
return_cached_file() {
PACKAGE_NAME="$1"
if [ -f "$CACHE_FILE" ] && grep -q "^$PACKAGE_NAME " "$CACHE_FILE"; then
CACHED_LOCATION=$(grep -E "^$PACKAGE_NAME " "$CACHE_FILE" | awk '{ print $2 }')
if [ -n "$CACHED_LOCATION" ]; then
printf "%s\n" "$CACHED_LOCATION"
return 0
fi
fi
return 1
}
# Function to clean the cache (limit 40 programs)
clean_cache() {
if [ -f "$CACHE_FILE" ]; then
# Remove duplicate entries in the cache
awk '!seen[$0]++' "$CACHE_FILE" > temp.txt
mv temp.txt "$CACHE_FILE"
# Remove non-existent files from the cache
while read -r line; do
cached_package=$(echo "$line" | awk '{print $1}')
cached_file=$(echo "$line" | awk '{print $2}')
if [ ! -f "$TEMP_DIR/$cached_file" ] || [ "$cached_package" != "$(echo "$cached_file" | cut -d'-' -f 1 | cut -d'_' -f 2-)" ]; then
sed -i "/$cached_file/d" "$CACHE_FILE"
fi
done < "$CACHE_FILE"
fi
}
# Function to run from cache or fetch if not found
run_from_cache() {
PACKAGE_NAME="$1"
CACHED_LOCATION=$(return_cached_file "$PACKAGE_NAME")
if [ -n "$CACHED_LOCATION" ] && [ -x "$TEMP_DIR/$CACHED_LOCATION" ]; then
printf "%bRunning '%s' from cache...%b\n" "$GREEN" "$PACKAGE_NAME" "$NC"
clean_cache
"$TEMP_DIR/$CACHED_LOCATION" "${@:2}" # Pass additional parameters as flags
return 0
else
NEW_CACHED_LOCATION="bdl_$PACKAGE_NAME-$(date +'%s')"
if fetch_binary "$PACKAGE_NAME" "$TEMP_DIR" "$TEMP_DIR/$NEW_CACHED_LOCATION"; then
echo "$PACKAGE_NAME $NEW_CACHED_LOCATION" >> "$CACHE_FILE" # Update cache with the fetched binary
clean_cache # Clean the cache
"$TEMP_DIR/$NEW_CACHED_LOCATION" "${@:2}" # Execute the fetched binary
return 0
else
return 1
fi
fi
}
install_binary() {
PACKAGE_NAME="$1"
# Check if the package name is empty
if [ -z "$PACKAGE_NAME" ]; then
print_color "$YELLOW" "No package name provided."
return
fi
# Check if the binary is already installed in the INSTALL_DIR
if [ -f "$INSTALL_DIR/$PACKAGE_NAME" ]; then
print_color "$YELLOW" "The requested binary is already at: $INSTALL_DIR/$PACKAGE_NAME."
if command -v gum >/dev/null 2>&1; then
gum confirm "Do you want to continue?" || return
else
return
fi
fi
# Get the cached location of the package
CACHED_LOCATION=$(return_cached_file "$PACKAGE_NAME")
if [ -n "$CACHED_LOCATION" ] && [ -x "$TEMP_DIR/$CACHED_LOCATION" ]; then
print_color "$GREEN" "Installing '$PACKAGE_NAME' from cache..."
mv "$TEMP_DIR/$CACHED_LOCATION" "$INSTALL_DIR/$PACKAGE_NAME"
clean_cache # Remove duplicates and non-existent files from the cache
return 1
else
# Fetch the binary if it's not found in the installation directory or cache
fetch_binary "$PACKAGE_NAME" "$INSTALL_DIR" && print_color "$GREEN" "OK: $INSTALL_DIR/$PACKAGE_NAME"
clean_cache # Remove duplicates and non-existent files from the cache
fi
}
# Function to remove an installed package
remove_package() {
PACKAGE_NAME="$1"
PACKAGE_LOCATION="$INSTALL_DIR/$PACKAGE_NAME"
if [ -f "$PACKAGE_LOCATION" ]; then
rm "$PACKAGE_LOCATION" && print_color "$GREEN" "Package '$PACKAGE_NAME' removed."
else
print_color "$YELLOW" "Package '$PACKAGE_NAME' is not installed."
fi
}
# Function to retrieve package source URL
find_url() {
PACKAGE_NAME="$1"
if [ -n "$NO_METADATA" ]; then
if [ -n "$BASE" ]; then
echo "https://bin.ajam.dev/$SYSTEM_ARCH/Baseutils/$PACKAGE_NAME"
else
echo "https://bin.ajam.dev/$SYSTEM_ARCH/$PACKAGE_NAME"
fi
return
fi
SOURCE_URL=$(curl -s "$METADATA_URL" | jq -r --arg pname "$PACKAGE_NAME" --arg sysarch "$SYSTEM_ARCH" \
'.packages[] | select(.name == $pname and .architecture == $sysarch) | .source')
# Check if source URL is empty -> Find the URL manually if so. #NOTE:If the firt SOURCE_URL check works, it saves time, that's why we preffer extracting from metadata first and turning to "curl --fail" IFs/checks as a last resort
if [ -z "$SOURCE_URL" ]; then
SOURCE_URL="https://bin.ajam.dev/$SYSTEM_ARCH/$PACKAGE_NAME"
if ! curl --location --output /dev/null --silent --fail "$SOURCE_URL"; then
SOURCE_URL="https://bin.ajam.dev/$SYSTEM_ARCH/Baseutils/$PACKAGE_NAME"
if ! curl --location --output /dev/null --silent --fail "$SOURCE_URL"; then
SOURCE_URL="https://raw.githubusercontent.com/xplshn/Handyscripts/master/$PACKAGE_NAME"
if ! curl --location --output /dev/null --silent --fail "$SOURCE_URL"; then
print_color "$YELLOW" "Source URL not found for '$PACKAGE_NAME'."
return 1
fi
fi
fi
fi
printf '%s\n' "$SOURCE_URL"
}
# Function to show detailed package information with color
show_package_info() {
PACKAGE_NAME="$1"
# Start spinner in the background & capture its PID.
spinner & spinner_pid=$!
PACKAGE_INFO=$(curl -s "$METADATA_URL" | jq --arg pname "$PACKAGE_NAME" --arg sysarch "$SYSTEM_ARCH" \
'.packages[] | select(.name == $pname and .architecture == $sysarch) | {description, name, version, updated, size, sha, source}')
if [ -z "$PACKAGE_INFO" ]; then
# Kill the spinner if download fails
kill "$spinner_pid" >/dev/null 2>&1
# Clear the line
printf "\033[2K\r"
# Print error.
print_color "$YELLOW" "Info for package '$PACKAGE_NAME' not found in the metadata.json file. Please contribute to $METADATA_URL."
else
# Kill the spinner if download succeeds
kill "$spinner_pid" >/dev/null 2>&1
# Clear the line
printf "\033[2K\r"
# SUCCESS: Print info in JSON.
print_color "$GREEN" "$PACKAGE_INFO"
fi
}
fSearch() {
SEARCH_TERM="$1"
# Fetch metadata
METADATA=$(curl -s "$METADATA_URL")
# Check if metadata retrieval failed
if [ -z "$METADATA" ]; then
printf "Failed to fetch package information.\n"
return 1
fi
# Filter packages based on the search term
SEARCH_RESULTS=$(printf '%s\n' "$METADATA" | jq -r --arg sterm "$SEARCH_TERM" \
'.packages[] | select(.name + .description | test($sterm; "i")) | "\(.name) - \(.description)"' | sort -u)
# Check if no matching packages found
if [ -z "$SEARCH_RESULTS" ]; then
printf "No matching packages found for '%s'.\n" "$SEARCH_TERM"
return 1
elif [ "$(echo "$SEARCH_RESULTS" | wc -l)" -gt 10 ]; then # Maximum results length
printf "Too many matching packages found for '%s'.\n" "$SEARCH_TERM"
return 1
elif ! echo "$SEARCH_RESULTS" | grep -w "$SEARCH_TERM" > /dev/null; then
printf "No matching packages found for '%s'.\n" "$SEARCH_TERM"
return 1
fi
# Determine the truncation length
TRUNC_LENGTH=$(( $(tput cols 2>/dev/null || echo "80") - 3 ))
# Check if the package binary exists in the INSTALL_DIR and print results with installation state indicators
printf '%s\n' "$SEARCH_RESULTS" | while IFS= read -r line; do # Take out the "grep -w" line if you want ACTUAL fuzzy search
NAME=$(echo "$line" | awk -F ' - ' '{print $1}')
DESCRIPTION=$(echo "$line" | awk -F ' - ' '{$1=""; print substr($0,2)}')
CACHED_LOCATION=$(return_cached_file "$NAME")
if [ -f "$INSTALL_DIR/$NAME" ]; then
PREFIX="[i]"
elif [ -n "$CACHED_LOCATION" ] && [ -x "$TEMP_DIR/$CACHED_LOCATION" ]; then
PREFIX="[c]"
else
PREFIX="[-]"
fi
# Calculate available space for description
AVAILABLE_SPACE=$((TRUNC_LENGTH - ${#PREFIX} - ${#NAME} - 4)) # 4 accounts for space around ' - '
# Truncate the description if it exceeds the available space
if [ ${#DESCRIPTION} -gt "$AVAILABLE_SPACE" ]; then
DESCRIPTION=$(printf '%s' "$DESCRIPTION" | cut -c 1-"$AVAILABLE_SPACE" | sed 's/[ ,]*$//;s/,$//') # Shrink to the maximum line size + Remove trailing spaces & commas.
DESCRIPTION="${DESCRIPTION}..."
fi
printf "%s %s - %s\n" "$PREFIX" "$NAME" "$DESCRIPTION"
done
}
# Function to list all possible packages
list_packages() {
spinner & spinner_pid=$!
packages=$(
{
curl -qfsSL "https://bin.ajam.dev/$SYSTEM_ARCH/METADATA.json" && \
curl -qfsSL "https://bin.ajam.dev/$SYSTEM_ARCH/Baseutils/METADATA.json" && \
curl -qfsSL "https://api.github.com/repos/xplshn/Handyscripts/contents"
} | jq -r '.[] | (.Name // .name)' | grep -v "\.7z$\|\.bz2$\|\.json$\|\.gz$\|\.md$\|\.txt$\|\.tar$\|\.zip$\|_dir$" | sort -u)
kill "$spinner_pid" >/dev/null 2>&1
printf "\033[2K\r%s\n" "$packages"
}
bootstrap() {
mkdir -p "$BOOTSTRAP_DIR"
PATH="$PATH:$BOOTSTRAP_DIR"
if [ -n "$FETCHER" ]; then
export NO_METADATA=1
if ! command -v bash >/dev/null 2>&1; then
print_color "${YELLOW}" "bash is not available. Bootstrapping..."
BASE="true" fetch_binary "bash" "$BOOTSTRAP_DIR"
fi
if ! command -v curl >/dev/null 2>&1; then
print_color "${YELLOW}" "curl is not installed. Bootstrapping..."
fetch_binary curl "$BOOTSTRAP_DIR"
fi
if ! command -v jq >/dev/null 2>&1; then
print_color "${YELLOW}" "jq is not installed. Bootstrapping..."
fetch_binary "jq" "$BOOTSTRAP_DIR"
fi
if ! command -v awk >/dev/null 2>&1; then
print_color "${YELLOW}" "awk is not installed. Bootstrapping..."
BASE="true" fetch_binary "awk" "$BOOTSTRAP_DIR"
fi
if ! command -v tput >/dev/null 2>&1; then
print_color "${YELLOW}" "tput is not available (from the netcurses package). Bootstrapping..."
BASE="true" fetch_binary "tput" "$BOOTSTRAP_DIR"
fi
unset NO_METADATA
fi
}
stubdl() {
DEST="/tmp/._bdlstub_bigdl.bin"
ARCH="$(uname -m)"
if [ "$ARCH" = "x86_64" ]; then
ARCH_SUFFIX="amd64"
elif [ "$ARCH" = "aarch64" ]; then
ARCH_SUFFIX="arm64"
else
echo "Unsupported architecture: $ARCH"
exit 1
fi
BIGDL="https://github.com/xplshn/bigdl/releases/latest/download/bigdl_fast_${ARCH_SUFFIX}"
if [ "$1" = "--install" ]; then
DEST="$2"
fi
if [ -e "$DEST" ] && [ ! "$1" = "--install" ]; then
"$DEST" "$@"
else
mkdir -p "$(dirname "$DEST")"
if command -v wget >/dev/null 2>&1; then
wget -q "$BIGDL" -O "$DEST"
elif command -v curl >/dev/null 2>&1; then
curl -qfsSL "$BIGDL" -o "$DEST"
else
echo "Neither wget nor curl is available."
exit 1
fi
[ -e "$DEST" ] && [ "$1" = "--install" ] && echo "BIGDL IS NOW AVAILABLE. ($DEST)"
chmod +x "$DEST"
[ ! "$1" = "--install" ] && "$DEST" "$@"
fi
}
determine_fetcher && bootstrap && \
case $1 in
run)
run_from_cache "$2" "${@:3}"
;;
install)
install_binary "$2"
;;
remove)
remove_package "$2"
;;
search)
fSearch "$2"
;;
info)
show_package_info "$2"
;;
list)
list_packages
;;
find_url)
find_url "$2"
;;
tldr)
run_from_cache tlrc "${@:2}" # Official TL;DR pages client written in Rust.
;;
bigdl)
shift
stubdl "${@}" # Run bigdl (A total rewrite of bdl, which corrects all of its downfalls and implements a new `update` feature. bigdl is designed to be pretty. bigdl releases weight no more than 2 megs)
;;
*)
if [ "$1" = "what" ] && [ "$2" = "is" ] && [ "$3" = "bigdl?" -o "$3" = "bigdl" ]; then
run_from_cache glow "https://raw.githubusercontent.com/xplshn/bigdl/master/README.md"
exit
fi
if [ "$1" = "put" ] && [ "$2" = "bigdl" ] && [ "$3" = "at" ] && [ -n "$4" ]; then
stubdl --install "$4"
exit
fi
printf 'Usage: %s [list|install|remove|run|info|search|tldr|bigdl] [args...]\n' "$INAME"
printf 'Usage: %s bdl is deprecated, please read about its rewrite/replacement in Go using the following command: ' "$INAME"
print_color "$YELLOW" "$INAME what is bigdl?"
printf 'Usage: %s You may also simply try it using the following command: ' "$INAME"
print_color "$YELLOW" "$INAME bigdl"
printf 'Usage: %s If you wish to install bigdl, use the following command: ' "$INAME"
print_color "$YELLOW" "$INAME put bigdl at $HOME/.local/bin/bigdl"
exit 1
;;
esac
exit 0