Skip to content

Commit 66c8784

Browse files
committed
chore: added example application and renamed scripts
1 parent af4ee3b commit 66c8784

File tree

6 files changed

+897
-9
lines changed

6 files changed

+897
-9
lines changed

APPw renamed to APP

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,20 @@ if [ "$CURRENT_SCRIPT_PATH" != "$BIN_EXE_PATH" ]; then
194194
exec "$APP_EXE" "$@"
195195
fi
196196

197-
# If we are running from $BIN_DIR/$APP_NAME, the script continues below this line.
197+
##########################################
198+
# BELOW THIS POINT YOU PUT YOUR OWN CODE #
199+
##########################################
200+
198201
# This part is the "whatever might be there" section.
199202
LOG "Running inside the application's environment ($BIN_DIR)."
200-
# Example: start the application with special debugging flags, or run cleanup tasks.
203+
201204
# Your application's main logic or final execution step would go here if this script
202-
# *is* the final executable.
205+
# *is* the final executable. Otherwise you can call out to other scripts or binaries as needed.
206+
203207
# For simplicity, we just print a success message and exit.
204-
echo "--- Application $APP_NAME is running ---"
205-
echo "Arguments received: $@"
208+
echo "------------------------------------"
209+
echo "This is application: $APP_NAME"
210+
echo "Arguments received : $@"
206211
echo "------------------------------------"
207212

208213
exit 0

APPw.cmd renamed to APP.cmd

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,20 @@ if /I NOT "%SCRIPT_DIR_CLEAN%" EQU "%BIN_DIR%" (
204204
goto :eof
205205
)
206206

207-
rem If we are running from %BIN_DIR%, the script continues below this line.
207+
rem ##########################################
208+
rem # BELOW THIS POINT YOU PUT YOUR OWN CODE #
209+
rem ##########################################
210+
211+
rem This part is the "whatever might be there" section.
208212
call :LOG "Running inside the application's environment (%BIN_DIR%)."
209-
rem This is the "whatever might be there" section.
210-
echo --- Application %APP_NAME% is running ---
211-
echo Arguments received: %*
213+
214+
rem Your application's main logic or final execution step would go here if this script
215+
rem *is* the final executable. Otherwise you can call out to other scripts or binaries as needed.
216+
217+
rem For simplicity, we just print a success message and exit.
218+
echo ------------------------------------
219+
echo This is application: %APP_NAME%
220+
echo Arguments received : %*
212221
echo ------------------------------------
213222

214223
endlocal

dummy-app/dummyw

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
#!/bin/bash
2+
3+
# --- Configuration (Non-Overridable) ---
4+
APP_NAME="dummy"
5+
APP_DIR=".dummy-app"
6+
DOWNLOAD_URL="https://example.com/releases/.../foo-latest.tgz"
7+
# ---------------------------------------
8+
9+
# 1. Setup essential variables needed for config loading
10+
HOME_DIR="$HOME"
11+
APP_HOME="$HOME_DIR/$APP_DIR"
12+
13+
# 2. Define default overridable variables
14+
# The update period in days (e.g., 3 means check if the last_checked file is older than 3 days)
15+
UPDATE_PERIOD=3
16+
# Logging level (default empty/silent; set to anything, e.g., 'DEBUG', to enable logging)
17+
LOG_LEVEL=
18+
19+
# --- Configuration Loading ---
20+
# Function to load configuration variables from a file
21+
load_config() {
22+
local config_file="$1"
23+
if [ -f "$config_file" ]; then
24+
#LOG "Loading configuration from $config_file..."
25+
source "$config_file" 2>/dev/null
26+
fi
27+
}
28+
29+
# Load user-wide configuration (if exists)
30+
load_config "$APP_HOME/bootstrap.cfg"
31+
32+
# Load local configuration (if exists)
33+
load_config "./$APP_DIR/bootstrap.cfg"
34+
35+
# -----------------------------
36+
37+
# 3. Define the remaining path variables using the (potentially overridden) APP_NAME/UPDATE_PERIOD
38+
CACHE_DIR="$APP_HOME/_cache"
39+
BIN_DIR="$APP_HOME/bin"
40+
APP_EXE="$BIN_DIR/$APP_NAME"
41+
ARCHIVE_FILE="$CACHE_DIR/release.tgz"
42+
LAST_CHECKED_FILE="$CACHE_DIR/last_checked"
43+
44+
LOG() {
45+
# Only echo the log message if LOG_LEVEL is not empty
46+
if [ -n "$LOG_LEVEL" ]; then
47+
echo "[$APP_NAME Bootstrap] $1"
48+
fi
49+
}
50+
51+
# Function to get the last modification timestamp of a file
52+
get_file_mtime() {
53+
# Use stat command for reliable cross-platform (Linux/Mac) date retrieval
54+
# Linux: 'stat -c %Y' for seconds since epoch
55+
# macOS: 'stat -f %m' for seconds since epoch
56+
if command -v gstat &> /dev/null; then
57+
# Use GNU stat if available (e.g., via MacPorts/Homebrew)
58+
gstat -c %Y "$1" 2>/dev/null
59+
elif uname | grep -q "Darwin"; then
60+
# macOS
61+
stat -f %m "$1" 2>/dev/null
62+
else
63+
# Standard Linux
64+
stat -c %Y "$1" 2>/dev/null
65+
fi
66+
}
67+
68+
# --- Core Logic Functions ---
69+
70+
perform_full_install() {
71+
LOG "Application not found or update forced. Starting download and install..."
72+
73+
# 1. Setup directories
74+
mkdir -p "$CACHE_DIR" || { LOG "Error: Could not create cache directory $CACHE_DIR"; exit 1; }
75+
76+
# 2. Download the release archive
77+
LOG "Downloading $DOWNLOAD_URL..."
78+
# The --remote-time (-r) option ensures the local file date matches the remote server's date.
79+
if ! curl -fsSL --remote-time "$DOWNLOAD_URL" -o "$ARCHIVE_FILE"; then
80+
LOG "Error: Download failed for $DOWNLOAD_URL."
81+
exit 1
82+
fi
83+
84+
# 3. Unpack and clean up
85+
LOG "Unpacking application..."
86+
# Remove existing installation directory if it exists before unpacking
87+
rm -rf "$APP_HOME/temp_install"
88+
mkdir -p "$APP_HOME/temp_install"
89+
90+
if ! tar -xzf "$ARCHIVE_FILE" -C "$APP_HOME/temp_install"; then
91+
LOG "Error: Failed to unpack archive $ARCHIVE_FILE."
92+
rm -rf "$APP_HOME/temp_install"
93+
exit 1
94+
fi
95+
96+
# Find the top-level directory inside the archive (often matches the APP_NAME)
97+
# Move the contents of the single directory inside the archive to the app home
98+
# Assuming the archive unpacks to a single directory (e.g., 'foo-v1.0')
99+
UNPACKED_ROOT=$(find "$APP_HOME/temp_install" -mindepth 1 -maxdepth 1 -type d -print -quit)
100+
101+
if [ -d "$UNPACKED_ROOT" ]; then
102+
# Move contents of the single directory to APP_HOME
103+
LOG "Moving contents from $UNPACKED_ROOT to $APP_HOME"
104+
# Move all contents, excluding the original temp directory itself
105+
mv "$UNPACKED_ROOT"/* "$APP_HOME" 2>/dev/null
106+
mv "$UNPACKED_ROOT"/.* "$APP_HOME" 2>/dev/null # Move hidden files/dirs too
107+
else
108+
# If no single directory, move all contents of temp_install to APP_HOME
109+
LOG "Moving contents directly from $APP_HOME/temp_install to $APP_HOME"
110+
mv "$APP_HOME/temp_install"/* "$APP_HOME" 2>/dev/null
111+
mv "$APP_HOME/temp_install"/.* "$APP_HOME" 2>/dev/null # Move hidden files/dirs too
112+
fi
113+
114+
# Clean up the temporary directory
115+
rm -rf "$APP_HOME/temp_install"
116+
117+
# 4. Create/update the last_checked file
118+
touch "$LAST_CHECKED_FILE"
119+
LOG "Installation complete in $APP_HOME."
120+
}
121+
122+
123+
handle_update_check() {
124+
# 1. Check file age: older than $UPDATE_PERIOD days?
125+
# find command exits 0 and prints if a file matching criteria is found.
126+
# -mtime +N means modification time is older than N full 24-hour periods.
127+
if [ ! -f "$LAST_CHECKED_FILE" ] || find "$LAST_CHECKED_FILE" -mtime +$UPDATE_PERIOD -print -quit 2>/dev/null; then
128+
LOG "Checking for updates (last check older than $UPDATE_PERIOD days or file missing)..."
129+
130+
# Record the modification time of the current archive before potential download
131+
local OLD_MTIME=$(get_file_mtime "$ARCHIVE_FILE")
132+
133+
# 2. Conditional Download
134+
# -z "$ARCHIVE_FILE" tells curl to only download if the remote file is newer than the local one.
135+
# --remote-time (-r) ensures the new file uses the remote timestamp.
136+
LOG "Attempting conditional download..."
137+
138+
# Use -w "%{http_code}" to capture the status code
139+
HTTP_CODE=$(curl -w "%{http_code}" -sSL --remote-time -z "$ARCHIVE_FILE" "$DOWNLOAD_URL" -o "$ARCHIVE_FILE")
140+
141+
# 3. Check for successful download (HTTP 200) or successful conditional skip (HTTP 304 Not Modified)
142+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
143+
# Download successful (200 OK)
144+
LOG "New release downloaded."
145+
146+
# Record the new modification time of the archive
147+
local NEW_MTIME=$(get_file_mtime "$ARCHIVE_FILE")
148+
149+
# Check if the file timestamp actually changed (i.e., a newer file was downloaded)
150+
if [ "$NEW_MTIME" -ne "$OLD_MTIME" ]; then
151+
LOG "Archive file date changed (old=$OLD_MTIME, new=$NEW_MTIME). Unpacking update."
152+
# 4. Unpack the new release
153+
perform_full_install
154+
else
155+
LOG "Remote file was newer, but timestamp remained the same or file was skipped by curl -z. Skipping unpack."
156+
fi
157+
elif [ "$HTTP_CODE" -eq 304 ]; then
158+
# Conditional download skipped (304 Not Modified)
159+
LOG "No new release available (304 Not Modified)."
160+
else
161+
# Other error or redirection
162+
LOG "Conditional download failed or returned unexpected status code: $HTTP_CODE. Skipping update."
163+
fi
164+
165+
# 5. Update last_checked timestamp regardless of success/failure of the update attempt
166+
touch "$LAST_CHECKED_FILE"
167+
LOG "Update check complete. Timestamp updated."
168+
else
169+
LOG "Skipping update check (last check within $UPDATE_PERIOD days)."
170+
fi
171+
}
172+
173+
# --- Execution Flow ---
174+
175+
# 1. Installation/Update Check
176+
if [ ! -f "$APP_EXE" ]; then
177+
perform_full_install
178+
else
179+
# Ensure cache directory exists for the last_checked file
180+
mkdir -p "$CACHE_DIR" 2>/dev/null
181+
handle_update_check
182+
fi
183+
184+
# 2. Execution Handover (The final requirement)
185+
# Check if the currently executing script ($0) is NOT the application itself
186+
# Use realpath to resolve symbolic links and get the canonical path
187+
CURRENT_SCRIPT_PATH=$(realpath "$0")
188+
BIN_EXE_PATH=$(realpath "$APP_EXE")
189+
190+
# Check if the current script path is NOT the path of the actual application executable
191+
if [ "$CURRENT_SCRIPT_PATH" != "$BIN_EXE_PATH" ]; then
192+
LOG "Handing over execution to the installed application: $APP_EXE"
193+
# exec replaces the current script process with the application process
194+
exec "$APP_EXE" "$@"
195+
fi
196+
197+
##########################################
198+
# BELOW THIS POINT YOU PUT YOUR OWN CODE #
199+
##########################################
200+
201+
# This part is the "whatever might be there" section.
202+
LOG "Running inside the application's environment ($BIN_DIR)."
203+
204+
# Your application's main logic or final execution step would go here if this script
205+
# *is* the final executable. Otherwise you can call out to other scripts or binaries as needed.
206+
207+
# For simplicity, we just print a success message and exit.
208+
echo "------------------------------------"
209+
echo "This is application: $APP_NAME"
210+
echo "Arguments received : $@"
211+
echo "------------------------------------"
212+
213+
exit 0

0 commit comments

Comments
 (0)