@git.zone/cli 2.20.0 → 2.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/templates/asset_deno_binary_installer/install.sh +506 -0
- package/assets/templates/asset_deno_binary_postinstall/bin/wrapper.js +37 -0
- package/assets/templates/asset_deno_binary_postinstall/scripts/install-binary.js +123 -0
- package/assets/templates/asset_deno_binary_release_gitea/.gitea/workflows/release.yml +154 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/mod_config/index.js +91 -1
- package/dist_ts/mod_format/classes.baseformatter.d.ts +5 -2
- package/dist_ts/mod_format/classes.baseformatter.js +49 -7
- package/dist_ts/mod_format/formatters/assets.formatter.d.ts +14 -0
- package/dist_ts/mod_format/formatters/assets.formatter.js +384 -0
- package/dist_ts/mod_format/formatters/packagejson.formatter.js +40 -2
- package/dist_ts/mod_format/index.js +4 -1
- package/dist_ts/mod_format/interfaces.format.d.ts +3 -0
- package/dist_ts/mod_format/interfaces.format.js +2 -1
- package/package.json +2 -2
- package/readme.md +91 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/mod_config/index.ts +95 -0
- package/ts/mod_format/classes.baseformatter.ts +47 -6
- package/ts/mod_format/formatters/assets.formatter.ts +451 -0
- package/ts/mod_format/formatters/packagejson.formatter.ts +43 -1
- package/ts/mod_format/index.ts +3 -0
- package/ts/mod_format/interfaces.format.ts +4 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Managed by @git.zone/cli from assets/templates/asset_deno_binary_installer. Do not edit by hand.
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SHOW_HELP=0
|
|
7
|
+
SPECIFIED_VERSION=""
|
|
8
|
+
SPECIFIED_MAJOR=""
|
|
9
|
+
INSTALL_DIR="{{installer.installDir}}"
|
|
10
|
+
BIN_DIR="{{installer.binDir}}"
|
|
11
|
+
INSTALL_MODE="{{installer.defaultMode}}"
|
|
12
|
+
GITEA_BASE_URL="https://{{repository.host}}"
|
|
13
|
+
GITEA_REPO="{{repository.path}}"
|
|
14
|
+
REPO_URL="{{{repository.gitUrl}}}"
|
|
15
|
+
SERVICE_RESTART_NAME="{{installer.service.restartName}}"
|
|
16
|
+
PRIMARY_PRESERVE_PATH="{{installer.primaryPreservePath}}"
|
|
17
|
+
|
|
18
|
+
SERVICE_NAMES=(
|
|
19
|
+
{{#each installer.service.detectNames}}
|
|
20
|
+
"{{this}}"
|
|
21
|
+
{{/each}}
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
LEGACY_SERVICE_NAMES=(
|
|
25
|
+
{{#each installer.service.removeLegacyUnits}}
|
|
26
|
+
"{{this}}"
|
|
27
|
+
{{/each}}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
while [[ $# -gt 0 ]]; do
|
|
31
|
+
case "$1" in
|
|
32
|
+
-h|--help)
|
|
33
|
+
SHOW_HELP=1
|
|
34
|
+
shift
|
|
35
|
+
;;
|
|
36
|
+
--version)
|
|
37
|
+
if [[ $# -lt 2 ]]; then
|
|
38
|
+
echo "Error: --version requires a value"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
SPECIFIED_VERSION="$2"
|
|
42
|
+
shift 2
|
|
43
|
+
;;
|
|
44
|
+
{{#if installer.supportsMajor}}
|
|
45
|
+
--major)
|
|
46
|
+
if [[ $# -lt 2 ]]; then
|
|
47
|
+
echo "Error: --major requires a value"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
SPECIFIED_MAJOR="${2#v}"
|
|
51
|
+
shift 2
|
|
52
|
+
;;
|
|
53
|
+
{{/if}}
|
|
54
|
+
--install-dir)
|
|
55
|
+
if [[ $# -lt 2 ]]; then
|
|
56
|
+
echo "Error: --install-dir requires a value"
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
INSTALL_DIR="$2"
|
|
60
|
+
shift 2
|
|
61
|
+
;;
|
|
62
|
+
{{#if installer.source.enabled}}
|
|
63
|
+
--binary)
|
|
64
|
+
INSTALL_MODE="binary"
|
|
65
|
+
shift
|
|
66
|
+
;;
|
|
67
|
+
--source)
|
|
68
|
+
INSTALL_MODE="source"
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
71
|
+
{{/if}}
|
|
72
|
+
*)
|
|
73
|
+
echo "Unknown option: $1"
|
|
74
|
+
echo "Use -h or --help for usage information"
|
|
75
|
+
exit 1
|
|
76
|
+
;;
|
|
77
|
+
esac
|
|
78
|
+
done
|
|
79
|
+
|
|
80
|
+
if [[ $SHOW_HELP -eq 1 ]]; then
|
|
81
|
+
echo "{{displayName}} Installer Script"
|
|
82
|
+
echo "Downloads and installs pre-compiled {{displayName}} release binaries."
|
|
83
|
+
echo ""
|
|
84
|
+
echo "Usage: $0 [options]"
|
|
85
|
+
echo ""
|
|
86
|
+
echo "Options:"
|
|
87
|
+
echo " -h, --help Show this help message"
|
|
88
|
+
echo " --version VERSION Install a specific tag/version (e.g. vX.Y.Z)"
|
|
89
|
+
{{#if installer.supportsMajor}}
|
|
90
|
+
echo " --major MAJOR Install latest release for a major version (e.g. 1)"
|
|
91
|
+
{{/if}}
|
|
92
|
+
echo " --install-dir DIR Installation directory (default: {{installer.installDir}})"
|
|
93
|
+
{{#if installer.source.enabled}}
|
|
94
|
+
echo " --binary Install release binary (default)"
|
|
95
|
+
echo " --source Clone the tag and build from source locally"
|
|
96
|
+
{{/if}}
|
|
97
|
+
echo ""
|
|
98
|
+
echo "Examples:"
|
|
99
|
+
echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash"
|
|
100
|
+
echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --version vX.Y.Z"
|
|
101
|
+
{{#if installer.supportsMajor}}
|
|
102
|
+
echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --major 1"
|
|
103
|
+
{{/if}}
|
|
104
|
+
{{#if installer.source.enabled}}
|
|
105
|
+
echo " curl -sSL {{{installer.publicInstallUrl}}} | sudo bash -s -- --source"
|
|
106
|
+
{{/if}}
|
|
107
|
+
exit 0
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if [[ -n "$SPECIFIED_VERSION" && -n "$SPECIFIED_MAJOR" ]]; then
|
|
111
|
+
echo "Error: --version and --major are mutually exclusive"
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [[ -n "$SPECIFIED_MAJOR" && ! "$SPECIFIED_MAJOR" =~ ^[0-9]+$ ]]; then
|
|
116
|
+
echo "Error: --major must be a numeric major version, for example: --major 1"
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
if [[ "$EUID" -ne 0 ]]; then
|
|
121
|
+
echo "Please run as root (sudo bash install.sh or pipe to sudo bash)"
|
|
122
|
+
exit 1
|
|
123
|
+
fi
|
|
124
|
+
|
|
125
|
+
case "$INSTALL_DIR" in
|
|
126
|
+
""|"/")
|
|
127
|
+
echo "Error: unsafe install directory: $INSTALL_DIR"
|
|
128
|
+
exit 1
|
|
129
|
+
;;
|
|
130
|
+
esac
|
|
131
|
+
|
|
132
|
+
require_command() {
|
|
133
|
+
if ! command -v "$1" >/dev/null 2>&1; then
|
|
134
|
+
echo "Error: required command not found: $1"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ensure_pnpm() {
|
|
140
|
+
if command -v pnpm >/dev/null 2>&1; then
|
|
141
|
+
return
|
|
142
|
+
fi
|
|
143
|
+
if command -v corepack >/dev/null 2>&1; then
|
|
144
|
+
corepack enable
|
|
145
|
+
fi
|
|
146
|
+
if ! command -v pnpm >/dev/null 2>&1; then
|
|
147
|
+
echo "Error: pnpm is required for source installs. Install Node.js with corepack/pnpm first."
|
|
148
|
+
exit 1
|
|
149
|
+
fi
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get_latest_version() {
|
|
153
|
+
echo "Fetching latest release version from Gitea..." >&2
|
|
154
|
+
local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest"
|
|
155
|
+
local response
|
|
156
|
+
if ! response=$(curl -fsSL "$api_url" 2>/dev/null); then
|
|
157
|
+
echo "Error: Failed to fetch latest release information from Gitea API" >&2
|
|
158
|
+
echo "URL: $api_url" >&2
|
|
159
|
+
exit 1
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
local version
|
|
163
|
+
version=$(printf '%s' "$response" | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
|
|
164
|
+
if [[ -z "$version" ]]; then
|
|
165
|
+
echo "Error: Could not determine latest version from API response" >&2
|
|
166
|
+
exit 1
|
|
167
|
+
fi
|
|
168
|
+
echo "$version"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
{{#if installer.supportsMajor}}
|
|
172
|
+
get_latest_major_version() {
|
|
173
|
+
local major="$1"
|
|
174
|
+
echo "Fetching latest v${major}.x release version from Gitea..." >&2
|
|
175
|
+
local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases?limit=50"
|
|
176
|
+
local response
|
|
177
|
+
if ! response=$(curl -fsSL "$api_url" 2>/dev/null); then
|
|
178
|
+
echo "Error: Failed to fetch release list from Gitea API" >&2
|
|
179
|
+
echo "URL: $api_url" >&2
|
|
180
|
+
exit 1
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
local version
|
|
184
|
+
version=$(printf '%s' "$response" | grep -o '"tag_name":"v'"${major}"'\.[^"]*"' | cut -d'"' -f4 | head -n 1)
|
|
185
|
+
if [[ -z "$version" ]]; then
|
|
186
|
+
echo "Error: Could not determine latest v${major}.x version from API response" >&2
|
|
187
|
+
exit 1
|
|
188
|
+
fi
|
|
189
|
+
echo "$version"
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
{{/if}}
|
|
193
|
+
detect_binary_name() {
|
|
194
|
+
local os
|
|
195
|
+
local arch
|
|
196
|
+
local os_name
|
|
197
|
+
local arch_name
|
|
198
|
+
os=$(uname -s)
|
|
199
|
+
arch=$(uname -m)
|
|
200
|
+
|
|
201
|
+
case "$os" in
|
|
202
|
+
Linux) os_name="linux" ;;
|
|
203
|
+
Darwin) os_name="macos" ;;
|
|
204
|
+
MINGW*|MSYS*|CYGWIN*) os_name="windows" ;;
|
|
205
|
+
*)
|
|
206
|
+
echo "Error: Unsupported operating system: $os" >&2
|
|
207
|
+
echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
|
|
208
|
+
{{#if installer.source.enabled}}
|
|
209
|
+
echo "Use --source to build locally on this platform." >&2
|
|
210
|
+
{{/if}}
|
|
211
|
+
exit 1
|
|
212
|
+
;;
|
|
213
|
+
esac
|
|
214
|
+
|
|
215
|
+
case "$arch" in
|
|
216
|
+
x86_64|amd64) arch_name="x64" ;;
|
|
217
|
+
aarch64|arm64) arch_name="arm64" ;;
|
|
218
|
+
*)
|
|
219
|
+
echo "Error: Unsupported architecture: $arch" >&2
|
|
220
|
+
echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
|
|
221
|
+
{{#if installer.source.enabled}}
|
|
222
|
+
echo "Use --source to build locally on this architecture." >&2
|
|
223
|
+
{{/if}}
|
|
224
|
+
exit 1
|
|
225
|
+
;;
|
|
226
|
+
esac
|
|
227
|
+
|
|
228
|
+
case "${os_name}-${arch_name}" in
|
|
229
|
+
{{#each binary.targets}}
|
|
230
|
+
{{os}}-{{arch}}) echo "{{assetName}}" ;;
|
|
231
|
+
{{/each}}
|
|
232
|
+
*)
|
|
233
|
+
echo "Error: Unsupported platform: ${os_name}-${arch_name}" >&2
|
|
234
|
+
echo "Supported platforms: {{binary.supportedPlatformText}}" >&2
|
|
235
|
+
{{#if installer.source.enabled}}
|
|
236
|
+
echo "Use --source to build locally on this platform." >&2
|
|
237
|
+
{{/if}}
|
|
238
|
+
exit 1
|
|
239
|
+
;;
|
|
240
|
+
esac
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
echo "================================================"
|
|
244
|
+
echo " {{displayName}} Installation Script"
|
|
245
|
+
echo "================================================"
|
|
246
|
+
echo ""
|
|
247
|
+
|
|
248
|
+
require_command curl
|
|
249
|
+
require_command sed
|
|
250
|
+
|
|
251
|
+
if [[ -n "$SPECIFIED_VERSION" ]]; then
|
|
252
|
+
VERSION="$SPECIFIED_VERSION"
|
|
253
|
+
echo "Installing specified version: $VERSION"
|
|
254
|
+
{{#if installer.supportsMajor}}
|
|
255
|
+
elif [[ -n "$SPECIFIED_MAJOR" ]]; then
|
|
256
|
+
VERSION=$(get_latest_major_version "$SPECIFIED_MAJOR")
|
|
257
|
+
echo "Installing latest v${SPECIFIED_MAJOR}.x version: $VERSION"
|
|
258
|
+
{{/if}}
|
|
259
|
+
else
|
|
260
|
+
VERSION=$(get_latest_version)
|
|
261
|
+
echo "Installing latest version: $VERSION"
|
|
262
|
+
fi
|
|
263
|
+
echo "Install mode: $INSTALL_MODE"
|
|
264
|
+
echo ""
|
|
265
|
+
|
|
266
|
+
TEMP_DIR=$(mktemp -d)
|
|
267
|
+
SOURCE_DIR="$TEMP_DIR/source"
|
|
268
|
+
BACKUP_DIR=""
|
|
269
|
+
SERVICE_WAS_RUNNING=0
|
|
270
|
+
SERVICE_STOPPED=0
|
|
271
|
+
SYSTEMD_AVAILABLE=0
|
|
272
|
+
PRESERVE_PATH_EXISTS=0
|
|
273
|
+
|
|
274
|
+
cleanup_temp() {
|
|
275
|
+
rm -rf "$TEMP_DIR"
|
|
276
|
+
}
|
|
277
|
+
trap cleanup_temp EXIT
|
|
278
|
+
|
|
279
|
+
if command -v systemctl >/dev/null 2>&1; then
|
|
280
|
+
SYSTEMD_AVAILABLE=1
|
|
281
|
+
for service_name in "${SERVICE_NAMES[@]}"; do
|
|
282
|
+
if systemctl is-active --quiet "$service_name" 2>/dev/null; then
|
|
283
|
+
SERVICE_WAS_RUNNING=1
|
|
284
|
+
break
|
|
285
|
+
fi
|
|
286
|
+
done
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
if [[ -n "$PRIMARY_PRESERVE_PATH" && -e "$PRIMARY_PRESERVE_PATH" ]]; then
|
|
290
|
+
PRESERVE_PATH_EXISTS=1
|
|
291
|
+
fi
|
|
292
|
+
|
|
293
|
+
restore_previous_installation() {
|
|
294
|
+
if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
|
|
295
|
+
echo "Restoring previous installation from $BACKUP_DIR..."
|
|
296
|
+
rm -rf "$INSTALL_DIR" || true
|
|
297
|
+
mv "$BACKUP_DIR" "$INSTALL_DIR" || true
|
|
298
|
+
if [[ -f "$INSTALL_DIR/{{binary.installFileName}}" ]]; then
|
|
299
|
+
mkdir -p "$BIN_DIR" || true
|
|
300
|
+
ln -sf "$INSTALL_DIR/{{binary.installFileName}}" "$BIN_DIR/{{cliName}}" || true
|
|
301
|
+
{{#if installer.source.enabled}}
|
|
302
|
+
elif [[ -f "$INSTALL_DIR/{{installer.source.executable}}" ]]; then
|
|
303
|
+
mkdir -p "$BIN_DIR" || true
|
|
304
|
+
ln -sf "$INSTALL_DIR/{{installer.source.executable}}" "$BIN_DIR/{{cliName}}" || true
|
|
305
|
+
{{/if}}
|
|
306
|
+
fi
|
|
307
|
+
fi
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
restart_previous_service_on_error() {
|
|
311
|
+
if [[ $SERVICE_STOPPED -eq 1 && $SYSTEMD_AVAILABLE -eq 1 && -n "$SERVICE_RESTART_NAME" ]]; then
|
|
312
|
+
echo "Installation failed after stopping {{displayName}}; restarting previous service..."
|
|
313
|
+
systemctl start "$SERVICE_RESTART_NAME" || true
|
|
314
|
+
fi
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
handle_install_error() {
|
|
318
|
+
trap - ERR
|
|
319
|
+
restore_previous_installation
|
|
320
|
+
restart_previous_service_on_error
|
|
321
|
+
}
|
|
322
|
+
trap handle_install_error ERR
|
|
323
|
+
|
|
324
|
+
stop_service_if_running() {
|
|
325
|
+
if [[ $SYSTEMD_AVAILABLE -ne 1 ]]; then
|
|
326
|
+
return
|
|
327
|
+
fi
|
|
328
|
+
for service_name in "${SERVICE_NAMES[@]}"; do
|
|
329
|
+
if systemctl is-active --quiet "$service_name" 2>/dev/null; then
|
|
330
|
+
echo "Stopping service: $service_name"
|
|
331
|
+
systemctl stop "$service_name"
|
|
332
|
+
SERVICE_STOPPED=1
|
|
333
|
+
fi
|
|
334
|
+
done
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
remove_legacy_services() {
|
|
338
|
+
if [[ $SYSTEMD_AVAILABLE -ne 1 ]]; then
|
|
339
|
+
return
|
|
340
|
+
fi
|
|
341
|
+
local needs_reload=0
|
|
342
|
+
for service_name in "${LEGACY_SERVICE_NAMES[@]}"; do
|
|
343
|
+
if systemctl is-enabled --quiet "$service_name" 2>/dev/null \
|
|
344
|
+
|| systemctl is-active --quiet "$service_name" 2>/dev/null \
|
|
345
|
+
|| systemctl is-failed --quiet "$service_name" 2>/dev/null \
|
|
346
|
+
|| [[ -f "/etc/systemd/system/${service_name}.service" ]] \
|
|
347
|
+
|| [[ -f "/usr/lib/systemd/system/${service_name}.service" ]] \
|
|
348
|
+
|| [[ -f "/lib/systemd/system/${service_name}.service" ]]; then
|
|
349
|
+
echo "Removing legacy service: $service_name"
|
|
350
|
+
if systemctl is-active --quiet "$service_name" 2>/dev/null; then
|
|
351
|
+
systemctl stop "$service_name"
|
|
352
|
+
fi
|
|
353
|
+
systemctl disable "$service_name" 2>/dev/null || true
|
|
354
|
+
systemctl reset-failed "$service_name" 2>/dev/null || true
|
|
355
|
+
rm -f \
|
|
356
|
+
"/etc/systemd/system/${service_name}.service" \
|
|
357
|
+
"/usr/lib/systemd/system/${service_name}.service" \
|
|
358
|
+
"/lib/systemd/system/${service_name}.service"
|
|
359
|
+
needs_reload=1
|
|
360
|
+
fi
|
|
361
|
+
done
|
|
362
|
+
if [[ $needs_reload -eq 1 ]]; then
|
|
363
|
+
systemctl daemon-reload
|
|
364
|
+
fi
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
move_previous_installation() {
|
|
368
|
+
mkdir -p "$(dirname "$INSTALL_DIR")"
|
|
369
|
+
if [[ -d "$INSTALL_DIR" ]]; then
|
|
370
|
+
BACKUP_DIR="${INSTALL_DIR}.previous.$$"
|
|
371
|
+
echo "Moving previous installation to $BACKUP_DIR"
|
|
372
|
+
mv "$INSTALL_DIR" "$BACKUP_DIR"
|
|
373
|
+
fi
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
install_release_binary() {
|
|
377
|
+
local binary_name
|
|
378
|
+
local download_url
|
|
379
|
+
local temp_file
|
|
380
|
+
|
|
381
|
+
binary_name=$(detect_binary_name)
|
|
382
|
+
download_url="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${binary_name}"
|
|
383
|
+
temp_file="$TEMP_DIR/$binary_name"
|
|
384
|
+
|
|
385
|
+
echo "Downloading {{displayName}} binary: $download_url"
|
|
386
|
+
curl -fSL "$download_url" -o "$temp_file"
|
|
387
|
+
chmod 0755 "$temp_file"
|
|
388
|
+
|
|
389
|
+
echo "Validating downloaded binary..."
|
|
390
|
+
"$temp_file" --version >/dev/null
|
|
391
|
+
|
|
392
|
+
stop_service_if_running
|
|
393
|
+
move_previous_installation
|
|
394
|
+
|
|
395
|
+
echo "Installing binary to $INSTALL_DIR"
|
|
396
|
+
mkdir -p "$INSTALL_DIR"
|
|
397
|
+
install -m 0755 "$temp_file" "$INSTALL_DIR/{{binary.installFileName}}"
|
|
398
|
+
|
|
399
|
+
mkdir -p "$BIN_DIR"
|
|
400
|
+
ln -sf "$INSTALL_DIR/{{binary.installFileName}}" "$BIN_DIR/{{cliName}}"
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
{{#if installer.source.enabled}}
|
|
404
|
+
install_source_build() {
|
|
405
|
+
require_command git
|
|
406
|
+
require_command node
|
|
407
|
+
ensure_pnpm
|
|
408
|
+
|
|
409
|
+
echo "Cloning {{displayName}} source from $REPO_URL ($VERSION)..."
|
|
410
|
+
git clone --depth 1 --branch "$VERSION" "$REPO_URL" "$SOURCE_DIR"
|
|
411
|
+
|
|
412
|
+
echo "Building {{displayName}} from source..."
|
|
413
|
+
(
|
|
414
|
+
cd "$SOURCE_DIR"
|
|
415
|
+
{{#each installer.source.commands}}
|
|
416
|
+
{{{this}}}
|
|
417
|
+
{{/each}}
|
|
418
|
+
{{{installer.source.validateCommand}}}
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
stop_service_if_running
|
|
422
|
+
move_previous_installation
|
|
423
|
+
|
|
424
|
+
echo "Installing source build to $INSTALL_DIR"
|
|
425
|
+
mv "$SOURCE_DIR" "$INSTALL_DIR"
|
|
426
|
+
{{#each installer.source.executableFiles}}
|
|
427
|
+
chmod 0755 "$INSTALL_DIR/{{this}}"
|
|
428
|
+
{{/each}}
|
|
429
|
+
|
|
430
|
+
mkdir -p "$BIN_DIR"
|
|
431
|
+
ln -sf "$INSTALL_DIR/{{installer.source.executable}}" "$BIN_DIR/{{cliName}}"
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
{{/if}}
|
|
435
|
+
remove_legacy_services
|
|
436
|
+
|
|
437
|
+
if [[ "$INSTALL_MODE" == "source" ]]; then
|
|
438
|
+
{{#if installer.source.enabled}}
|
|
439
|
+
install_source_build
|
|
440
|
+
{{else}}
|
|
441
|
+
echo "Error: source install mode is not enabled for {{displayName}}"
|
|
442
|
+
exit 1
|
|
443
|
+
{{/if}}
|
|
444
|
+
else
|
|
445
|
+
install_release_binary
|
|
446
|
+
fi
|
|
447
|
+
|
|
448
|
+
echo "Symlink created: $BIN_DIR/{{cliName}}"
|
|
449
|
+
|
|
450
|
+
{{#each installer.ensureDirs}}
|
|
451
|
+
mkdir -p "{{this}}"
|
|
452
|
+
{{/each}}
|
|
453
|
+
|
|
454
|
+
if ! "$BIN_DIR/{{cliName}}" --version >/dev/null; then
|
|
455
|
+
echo "Error: Installed {{displayName}} CLI failed validation"
|
|
456
|
+
restore_previous_installation
|
|
457
|
+
restart_previous_service_on_error
|
|
458
|
+
exit 1
|
|
459
|
+
fi
|
|
460
|
+
|
|
461
|
+
if [[ -n "$BACKUP_DIR" && -d "$BACKUP_DIR" ]]; then
|
|
462
|
+
rm -rf "$BACKUP_DIR"
|
|
463
|
+
fi
|
|
464
|
+
|
|
465
|
+
if [[ $SERVICE_WAS_RUNNING -eq 1 && $SYSTEMD_AVAILABLE -eq 1 ]]; then
|
|
466
|
+
{{#if installer.service.hasRefreshCommand}}
|
|
467
|
+
echo "Refreshing systemd service..."
|
|
468
|
+
{{{installer.service.refreshCommand}}}
|
|
469
|
+
{{/if}}
|
|
470
|
+
if [[ -n "$SERVICE_RESTART_NAME" ]]; then
|
|
471
|
+
echo "Restarting service: $SERVICE_RESTART_NAME"
|
|
472
|
+
systemctl restart "$SERVICE_RESTART_NAME"
|
|
473
|
+
SERVICE_STOPPED=0
|
|
474
|
+
echo "Service restarted successfully."
|
|
475
|
+
echo ""
|
|
476
|
+
fi
|
|
477
|
+
fi
|
|
478
|
+
|
|
479
|
+
trap - ERR
|
|
480
|
+
|
|
481
|
+
echo "================================================"
|
|
482
|
+
echo " {{displayName}} Installation Complete!"
|
|
483
|
+
echo "================================================"
|
|
484
|
+
echo ""
|
|
485
|
+
echo "Installation details:"
|
|
486
|
+
echo " Install directory: $INSTALL_DIR"
|
|
487
|
+
echo " Symlink location: $BIN_DIR/{{cliName}}"
|
|
488
|
+
echo " Version: $VERSION"
|
|
489
|
+
echo " Mode: $INSTALL_MODE"
|
|
490
|
+
echo ""
|
|
491
|
+
|
|
492
|
+
if [[ $PRESERVE_PATH_EXISTS -eq 1 ]]; then
|
|
493
|
+
echo "Existing data/configuration preserved: $PRIMARY_PRESERVE_PATH"
|
|
494
|
+
echo ""
|
|
495
|
+
if [[ $SERVICE_WAS_RUNNING -eq 1 ]]; then
|
|
496
|
+
echo "The service has been restarted with your current settings."
|
|
497
|
+
else
|
|
498
|
+
echo "Start the service with: {{installer.service.startHint}}"
|
|
499
|
+
fi
|
|
500
|
+
else
|
|
501
|
+
echo "Get started:"
|
|
502
|
+
{{#each installer.successHints}}
|
|
503
|
+
echo " {{this}}"
|
|
504
|
+
{{/each}}
|
|
505
|
+
fi
|
|
506
|
+
echo ""
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Managed by @git.zone/cli from assets/templates/asset_deno_binary_postinstall. Do not edit by hand.
|
|
3
|
+
|
|
4
|
+
import { arch, platform } from 'node:os';
|
|
5
|
+
import { existsSync } from 'node:fs';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
9
|
+
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const BINARY_MAP = new Map([
|
|
13
|
+
{{#each binary.targets}}
|
|
14
|
+
['{{nodeKey}}', '{{assetName}}'],
|
|
15
|
+
{{/each}}
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const key = `${platform()}:${arch()}`;
|
|
19
|
+
const binaryName = BINARY_MAP.get(key);
|
|
20
|
+
if (!binaryName) {
|
|
21
|
+
console.error(`Unsupported platform/architecture: ${platform()}/${arch()}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const binaryPath = join(__dirname, '..', '{{{npmWrapper.binariesDir}}}', binaryName);
|
|
26
|
+
if (!existsSync(binaryPath)) {
|
|
27
|
+
console.error('{{displayName}} binary not found. Try reinstalling the package.');
|
|
28
|
+
console.error(`Missing binary: ${binaryPath}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const result = spawnSync(binaryPath, process.argv.slice(2), { stdio: 'inherit' });
|
|
33
|
+
if (result.error) {
|
|
34
|
+
console.error(result.error.message);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
process.exit(result.status ?? 0);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Managed by @git.zone/cli from assets/templates/asset_deno_binary_postinstall. Do not edit by hand.
|
|
3
|
+
|
|
4
|
+
import { arch, platform } from 'node:os';
|
|
5
|
+
import { chmodSync, existsSync, mkdirSync, unlinkSync } from 'node:fs';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import https from 'node:https';
|
|
9
|
+
import { pipeline } from 'node:stream';
|
|
10
|
+
import { createWriteStream } from 'node:fs';
|
|
11
|
+
import process from 'node:process';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = dirname(__filename);
|
|
15
|
+
|
|
16
|
+
const REPO_BASE = '{{{repository.baseUrl}}}';
|
|
17
|
+
const FALLBACK_BRANCH = '{{repository.branch}}';
|
|
18
|
+
const VERSION = process.env.npm_package_version || '{{versionFallback}}';
|
|
19
|
+
const BINARY_MAP = new Map([
|
|
20
|
+
{{#each binary.targets}}
|
|
21
|
+
['{{nodeKey}}', '{{assetName}}'],
|
|
22
|
+
{{/each}}
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
function getBinaryInfo() {
|
|
26
|
+
const key = `${platform()}:${arch()}`;
|
|
27
|
+
const binaryName = BINARY_MAP.get(key);
|
|
28
|
+
if (!binaryName) {
|
|
29
|
+
return { supported: false, key, platform: platform(), arch: arch() };
|
|
30
|
+
}
|
|
31
|
+
return { supported: true, key, binaryName, platform: platform(), arch: arch() };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function downloadFile(url, destination) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const download = (nextUrl, redirectCount = 0) => {
|
|
37
|
+
if (redirectCount > 5) {
|
|
38
|
+
reject(new Error('Too many redirects'));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log(`Downloading from: ${nextUrl}`);
|
|
43
|
+
https.get(nextUrl, (response) => {
|
|
44
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
45
|
+
download(response.headers.location, redirectCount + 1);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (response.statusCode !== 200) {
|
|
49
|
+
reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const file = createWriteStream(destination);
|
|
54
|
+
pipeline(response, file, (error) => {
|
|
55
|
+
if (error) {
|
|
56
|
+
reject(error);
|
|
57
|
+
} else {
|
|
58
|
+
resolve();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}).on('error', reject);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
download(url);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function main() {
|
|
69
|
+
console.log('===========================================');
|
|
70
|
+
console.log(' {{displayName}} - Binary Installation');
|
|
71
|
+
console.log('===========================================');
|
|
72
|
+
console.log('');
|
|
73
|
+
|
|
74
|
+
const binaryInfo = getBinaryInfo();
|
|
75
|
+
if (!binaryInfo.supported) {
|
|
76
|
+
console.error(`Error: Unsupported platform/architecture: ${binaryInfo.platform}/${binaryInfo.arch}`);
|
|
77
|
+
console.error('Supported platforms: {{binary.supportedPlatformText}}');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const binariesDir = join(__dirname, '..', '{{{npmWrapper.binariesDir}}}');
|
|
82
|
+
if (!existsSync(binariesDir)) {
|
|
83
|
+
mkdirSync(binariesDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const binaryPath = join(binariesDir, binaryInfo.binaryName);
|
|
87
|
+
if (existsSync(binaryPath)) {
|
|
88
|
+
console.log('Binary already exists, skipping download');
|
|
89
|
+
} else {
|
|
90
|
+
const releaseUrl = `${REPO_BASE}/releases/download/v${VERSION}/${binaryInfo.binaryName}`;
|
|
91
|
+
const fallbackUrl = `${REPO_BASE}/raw/branch/${FALLBACK_BRANCH}/{{{npmWrapper.binariesDir}}}/${binaryInfo.binaryName}`;
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
await downloadFile(releaseUrl, binaryPath);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.log(`Release download failed: ${error.message}`);
|
|
97
|
+
console.log('Trying fallback URL...');
|
|
98
|
+
try {
|
|
99
|
+
await downloadFile(fallbackUrl, binaryPath);
|
|
100
|
+
} catch (fallbackError) {
|
|
101
|
+
if (existsSync(binaryPath)) {
|
|
102
|
+
unlinkSync(binaryPath);
|
|
103
|
+
}
|
|
104
|
+
console.error('Error: Failed to download binary');
|
|
105
|
+
console.error(` Primary URL: ${releaseUrl}`);
|
|
106
|
+
console.error(` Fallback URL: ${fallbackUrl}`);
|
|
107
|
+
console.error(` Cause: ${fallbackError.message}`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (binaryInfo.platform !== 'win32') {
|
|
114
|
+
chmodSync(binaryPath, 0o755);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
console.log('{{displayName}} installation completed successfully.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
main().catch((error) => {
|
|
121
|
+
console.error(`Installation failed: ${error.message}`);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
});
|