-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
Β·393 lines (328 loc) Β· 13.9 KB
/
install.sh
File metadata and controls
executable file
Β·393 lines (328 loc) Β· 13.9 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
#!/bin/bash
# Luca Installation Script
# This script downloads and installs the Luca executable and sets up shell hooks
# for directory-specific PATH management.
# =============================================================================
# CONFIGURATION VARIABLES
# =============================================================================
TOOL_NAME="Luca"
BIN_NAME="luca"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
TOOL_FOLDER=".luca"
VERSION_FILE="${PWD}/.luca-version"
ORGANIZATION="LucaTools"
REPOSITORY_URL="https://github.com/LucaTools/Luca"
TOOL_DIR="$HOME/$TOOL_FOLDER"
SHELL_HOOK_SCRIPT_PATH="$TOOL_DIR/shell_hook.sh"
SHELL_HOOK_SCRIPT_URL="https://raw.githubusercontent.com/LucaTools/LucaScripts/HEAD/shell_hook.sh"
POST_CHECKOUT_HOOK_PATH="$TOOL_DIR/post-checkout"
POST_CHECKOUT_HOOK_URL="https://raw.githubusercontent.com/LucaTools/LucaScripts/HEAD/post-checkout"
# =============================================================================
# GITHUB API AUTHENTICATION
# =============================================================================
trap 'printf "\nβ Installation interrupted.\n"; exit 130' INT
# Build curl options for GitHub API requests.
# If GITHUB_TOKEN is set, include it as a Bearer token to avoid rate limiting
# (5000 req/hr authenticated vs. 60 req/hr unauthenticated).
CURL_GITHUB_API_OPTS=()
if [ -n "${GITHUB_TOKEN:-}" ]; then
CURL_GITHUB_API_OPTS=(-H "Authorization: Bearer $GITHUB_TOKEN")
echo "Using GITHUB_TOKEN for authenticated GitHub API requests"
fi
# =============================================================================
# TOOL VERSION DETECTION
# =============================================================================
# Check existence of version file
if [ ! -f "$VERSION_FILE" ]; then
echo "Missing $VERSION_FILE. Fetching the latest version"
# Fetch latest release version from GitHub API
REQUIRED_EXECUTABLE_VERSION=$(curl -LSsf "${CURL_GITHUB_API_OPTS[@]}" "https://api.github.com/repos/$ORGANIZATION/$TOOL_NAME/releases/latest" | grep '"tag_name":' | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')
if [ -z "$REQUIRED_EXECUTABLE_VERSION" ]; then
echo "ERROR: Could not fetch latest version from $REPOSITORY_URL"
echo "Please check your internet connectivity."
exit 1
fi
echo "Using latest version: $REQUIRED_EXECUTABLE_VERSION"
else
echo "Using version from $VERSION_FILE"
REQUIRED_EXECUTABLE_VERSION=$(cat "$VERSION_FILE")
fi
# Function to validate SemVer format
validate_semver() {
local version="$1"
if [ -z "$version" ]; then
return 1
fi
# Basic SemVer validation: should match pattern like 1.2.3, 1.2.3-alpha, v1.2.3
if ! echo "$version" | grep -qE '^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?$'; then
echo "ERROR: Invalid version format '$version'. Expected SemVer format (e.g., 1.2.3 or v1.2.3)"
return 1
fi
return 0
}
if [ -n "$REQUIRED_EXECUTABLE_VERSION" ]; then
if ! validate_semver "$REQUIRED_EXECUTABLE_VERSION"; then
exit 1
fi
fi
# Ensure we have a valid version to install
if [ -z "$REQUIRED_EXECUTABLE_VERSION" ]; then
echo "ERROR: $TOOL_NAME version not found in $VERSION_FILE file nor a valid release exists at $REPOSITORY_URL"
exit 1
fi
echo "Target version: $REQUIRED_EXECUTABLE_VERSION"
# =============================================================================
# OPERATING SYSTEM DETECTION
# =============================================================================
# Temporary filename for the downloaded zip (set based on OS detection)
TEMP_EXECUTABLE_ZIP_FILENAME=""
# Detect the operating system and set appropriate download filename
if [ "$(uname -s)" = "Darwin" ]; then
OS="macos"
TEMP_EXECUTABLE_ZIP_FILENAME="Luca-macOS.zip"
echo "Detected macOS system"
elif [ -f "/etc/os-release" ]; then
OS="linux"
TEMP_EXECUTABLE_ZIP_FILENAME="Luca-Linux.zip"
echo "Detected Linux system"
else
OS="unknown"
echo "ERROR: Unsupported operating system."
echo "This script supports macOS and Linux only."
exit 1
fi
# =============================================================================
# VERSION CHECK - SKIP IF ALREADY UP TO DATE
# =============================================================================
EXECUTABLE_FILE="$INSTALL_DIR/$BIN_NAME"
# Check if Luca is already installed and up-to-date
if [ -f "$EXECUTABLE_FILE" ]; then
echo "Found existing $TOOL_NAME installation at $EXECUTABLE_FILE"
# Get the currently installed version
EXISTING_EXECUTABLE_VERSION=$($EXECUTABLE_FILE --version 2>/dev/null)
# Compare versions to avoid unnecessary reinstallation
if [ "$EXISTING_EXECUTABLE_VERSION" = "$REQUIRED_EXECUTABLE_VERSION" ]; then
echo "β
$TOOL_NAME version $REQUIRED_EXECUTABLE_VERSION is already up to date."
SKIP_INSTALLATION=true
else
echo "Current version: $EXISTING_EXECUTABLE_VERSION"
echo "Updating to version: $REQUIRED_EXECUTABLE_VERSION"
SKIP_INSTALLATION=false
fi
else
echo "No existing installation found. Proceeding with fresh installation..."
SKIP_INSTALLATION=false
fi
# =============================================================================
# DEPENDENCY CHECK AND INSTALLATION
# =============================================================================
# Ensure curl is available for downloading (Linux systems may not have it by default)
if [ "$OS" = "linux" ]; then
if ! command -v curl >/dev/null 2>&1; then
echo "Installing curl dependency..."
if command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y curl
elif command -v yum >/dev/null 2>&1; then
yum install -y curl
else
echo "ERROR: Cannot install curl automatically. Please install curl manually and retry."
exit 1
fi
else
echo "β
curl is already available"
fi
fi
# Skip the download and installation if version is already current
if [ "$SKIP_INSTALLATION" = "true" ]; then
echo "Skipping $TOOL_NAME download and installation..."
exit 0
fi
# =============================================================================
# LUCA DOWNLOAD AND INSTALLATION
# =============================================================================
echo "π₯ Downloading $TOOL_NAME ($REQUIRED_EXECUTABLE_VERSION)..."
# Download the appropriate version for the detected OS
curl -LSsf --output "./$TEMP_EXECUTABLE_ZIP_FILENAME" \
"$REPOSITORY_URL/releases/download/$REQUIRED_EXECUTABLE_VERSION/$TEMP_EXECUTABLE_ZIP_FILENAME"
DOWNLOAD_SUCCESS=$?
if [ $DOWNLOAD_SUCCESS -ne 0 ]; then
echo "β ERROR: Could not download $TOOL_NAME ($REQUIRED_EXECUTABLE_VERSION)."
echo "Please check your internet connection and verify the version exists."
exit 1
fi
echo "β
Download completed successfully"
# =============================================================================
# EXTRACTION AND INSTALLATION
# =============================================================================
echo "π¦ Extracting $TEMP_EXECUTABLE_ZIP_FILENAME..."
# Extract the downloaded zip file quietly
if ! unzip -o -qq "./$TEMP_EXECUTABLE_ZIP_FILENAME" -d ./; then
echo "β ERROR: Failed to extract $TEMP_EXECUTABLE_ZIP_FILENAME"
rm -f "./$TEMP_EXECUTABLE_ZIP_FILENAME"
exit 1
fi
echo "β
Extraction completed"
# Clean up the downloaded zip file
rm "./$TEMP_EXECUTABLE_ZIP_FILENAME"
echo "π§Ή Cleaned up temporary files"
# =============================================================================
# SYSTEM INSTALLATION WITH PRIVILEGE HANDLING
# =============================================================================
# Helper function to run commands with sudo only if needed
# This checks if the install directory is writable before using sudo
sudo_if_install_dir_not_writeable() {
local command="$1"
local exit_code
if [ -w "$INSTALL_DIR" ]; then
# Directory is writable, run without sudo
sh -c "$command"
else
# Directory requires elevated privileges
echo "π Administrator privileges required for installation to $INSTALL_DIR"
sudo sh -c "$command"
fi
exit_code=$?
if [ "$exit_code" -ne 0 ]; then
echo "β ERROR: Command failed or was interrupted (exit code: $exit_code)"
exit "$exit_code"
fi
}
# Create install directory if it doesn't exist
if [ ! -d "$INSTALL_DIR" ]; then
echo "π Creating install directory: $INSTALL_DIR"
sudo_if_install_dir_not_writeable "mkdir -p $INSTALL_DIR"
fi
# Move the executable to the install directory and make it executable
# The zip may contain either 'Luca' (uppercase) or 'luca' (lowercase) depending on the release
echo "π Installing $TOOL_NAME to $INSTALL_DIR..."
if [ -f "$TOOL_NAME" ]; then
EXTRACTED_BIN="$TOOL_NAME"
elif [ -f "$BIN_NAME" ]; then
EXTRACTED_BIN="$BIN_NAME"
else
echo "β ERROR: Could not find extracted binary (expected '$TOOL_NAME' or '$BIN_NAME')"
exit 1
fi
sudo_if_install_dir_not_writeable "mv $EXTRACTED_BIN $EXECUTABLE_FILE"
sudo_if_install_dir_not_writeable "chmod +x $EXECUTABLE_FILE"
echo "β
$TOOL_NAME ($REQUIRED_EXECUTABLE_VERSION) successfully installed to $INSTALL_DIR"
# =============================================================================
# SHELL HOOK SETUP
# =============================================================================
echo "π§ Setting up shell hook for directory-specific PATH management..."
# Create the tool directory
echo "π Creating tool directory: $TOOL_DIR"
mkdir -p "$TOOL_DIR"
# Download the shell hook script
echo "π₯ Downloading shell hook script..."
curl -LSsf --output "$SHELL_HOOK_SCRIPT_PATH" "$SHELL_HOOK_SCRIPT_URL"
HOOK_DOWNLOAD_SUCCESS=$?
if [ $HOOK_DOWNLOAD_SUCCESS -ne 0 ]; then
echo "β WARNING: Could not download shell hook script from $SHELL_HOOK_SCRIPT_URL"
echo "You can manually download it later or the tool may still work without hooks"
echo "Continuing with installation..."
else
echo "β
Shell hook script downloaded successfully to $SHELL_HOOK_SCRIPT_PATH"
# Make the shell hook script executable
chmod +x "$SHELL_HOOK_SCRIPT_PATH"
# Source the shell_hook.sh script to install the shell hook into current shell
echo "π Installing shell hook into your shell configuration..."
if [ -f "$SHELL_HOOK_SCRIPT_PATH" ]; then
# shellcheck source=/dev/null
. "$SHELL_HOOK_SCRIPT_PATH"
fi
fi
# Download the post-checkout hook script to ~/.luca/ for later use
echo "π₯ Downloading post-checkout hook script..."
curl -LSsf --output "$POST_CHECKOUT_HOOK_PATH" "$POST_CHECKOUT_HOOK_URL"
POST_CHECKOUT_DOWNLOAD_SUCCESS=$?
if [ $POST_CHECKOUT_DOWNLOAD_SUCCESS -ne 0 ]; then
echo "β οΈ WARNING: Could not download post-checkout hook from $POST_CHECKOUT_HOOK_URL"
else
echo "β
Post-checkout hook downloaded to $POST_CHECKOUT_HOOK_PATH"
chmod +x "$POST_CHECKOUT_HOOK_PATH"
fi
# =============================================================================
# GIT POST-CHECKOUT HOOK SETUP (OPTIONAL)
# =============================================================================
# Track whether git hook was installed (used in summary)
GIT_HOOK_INSTALLED=false
GIT_HOOK_PATH=""
# Install git hook if we're in a git repository
install_git_hook() {
local git_root
git_root=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$git_root" ]; then
# Not in a git repository, skip
return 0
fi
local hooks_dir="$git_root/.git/hooks"
local hook_file="$hooks_dir/post-checkout"
# Check if hooks directory exists
if [ ! -d "$hooks_dir" ]; then
echo "β οΈ Git hooks directory not found, skipping git hook installation"
return 0
fi
# Check if hook already exists
if [ -f "$hook_file" ]; then
# Check if it's our hook by looking for the Luca identifier
if grep -q "LUCA POST-CHECKOUT GIT HOOK" "$hook_file" 2>/dev/null; then
echo "βΉοΈ Luca post-checkout hook already installed"
GIT_HOOK_INSTALLED=true
GIT_HOOK_PATH="$hook_file"
return 0
else
echo "β οΈ A post-checkout hook already exists at $hook_file"
echo " To install Luca's hook, please manually merge or replace it."
echo " The hook script can be found at: $POST_CHECKOUT_HOOK_PATH"
return 0
fi
fi
# Copy from local ~/.luca/post-checkout (already downloaded earlier)
echo "π₯ Installing git post-checkout hook..."
if [ -f "$POST_CHECKOUT_HOOK_PATH" ]; then
cp "$POST_CHECKOUT_HOOK_PATH" "$hook_file"
chmod +x "$hook_file"
echo "β
Git post-checkout hook installed at $hook_file"
GIT_HOOK_INSTALLED=true
GIT_HOOK_PATH="$hook_file"
else
echo "β οΈ Could not install post-checkout hook (source not found)"
fi
}
# Try to install the git hook (optional, won't fail installation if it fails)
install_git_hook
# =============================================================================
# INSTALLATION COMPLETE
# =============================================================================
echo ""
echo "π Luca installation completed successfully!"
echo ""
echo "π Installation Summary:"
echo " β’ Executable: $EXECUTABLE_FILE"
echo " β’ Version: $REQUIRED_EXECUTABLE_VERSION"
echo " β’ Shell Hook: $SHELL_HOOK_SCRIPT_PATH"
if [ "$GIT_HOOK_INSTALLED" = "true" ]; then
echo " β’ Post-checkout Hook: $POST_CHECKOUT_HOOK_PATH"
fi
echo ""
echo "π‘ To start using Luca:"
# Detect the current shell and set the appropriate RC file
SHELL_PROFILE=""
case "$SHELL" in
*/bash)
SHELL_PROFILE="$HOME/.bashrc"
;;
*/zsh)
SHELL_PROFILE="$HOME/.zshrc"
;;
*)
echo "WARNING: Unsupported shell: $SHELL"
echo "Manual setup may be required. Supported shells: bash, zsh"
exit 1
;;
esac
echo " 1. Restart your terminal or run: source $SHELL_PROFILE"
echo " 2. Run: $BIN_NAME --help"
echo ""