@jetbrains/junie-cli 576.1.0 → 704.1.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/bin/index.js +6 -7
- package/getExecutable.js +10 -23
- package/package.json +3 -2
- package/postinstall.js +79 -16
- package/shim/junie +295 -0
package/bin/index.js
CHANGED
|
@@ -3,14 +3,13 @@ const {spawnSync} = require('child_process')
|
|
|
3
3
|
const {getExecutable} = require('../getExecutable')
|
|
4
4
|
|
|
5
5
|
function main() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const result = spawnSync(exe, process.argv.slice(2), {stdio: 'inherit'})
|
|
9
|
-
process.exit(result.status ?? 0)
|
|
10
|
-
} catch (error) {
|
|
11
|
-
console.error('[Junie] Error:', error.message)
|
|
6
|
+
const exe = getExecutable()
|
|
7
|
+
if (!exe) {
|
|
12
8
|
process.exit(1)
|
|
13
9
|
}
|
|
10
|
+
|
|
11
|
+
const result = spawnSync(exe, process.argv.slice(2), {stdio: 'inherit'})
|
|
12
|
+
process.exit(result.status ?? 0)
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
main()
|
|
15
|
+
main()
|
package/getExecutable.js
CHANGED
|
@@ -1,34 +1,21 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
2
|
const path = require('path')
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
function getExpectedBinaryPath() {
|
|
6
|
-
const workDir = path.resolve(__dirname, 'bin', 'junie')
|
|
7
|
-
|
|
8
|
-
return platform() === 'darwin'
|
|
9
|
-
? path.join(workDir, 'Applications', 'junie.app', 'Contents', 'MacOS', 'junie')
|
|
10
|
-
: path.join(workDir, 'junie', 'bin', 'junie')
|
|
11
|
-
}
|
|
3
|
+
const os = require('os')
|
|
12
4
|
|
|
5
|
+
const JUNIE_BIN = path.join(os.homedir(), '.local', 'bin')
|
|
13
6
|
|
|
14
7
|
function getExecutable() {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
if (fs.existsSync(markerFile)) {
|
|
18
|
-
const binaryPath = getExpectedBinaryPath()
|
|
8
|
+
const shimPath = path.join(JUNIE_BIN, 'junie')
|
|
19
9
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} else {
|
|
23
|
-
console.error('Junie binary not found. Please re-install the package')
|
|
24
|
-
}
|
|
25
|
-
} else {
|
|
26
|
-
console.error('Junie download is corrupted. Please re-install the package')
|
|
10
|
+
if (fs.existsSync(shimPath)) {
|
|
11
|
+
return shimPath
|
|
27
12
|
}
|
|
28
|
-
}
|
|
29
13
|
|
|
14
|
+
console.error('[Junie] Shim not found at', shimPath)
|
|
15
|
+
console.error('[Junie] Please reinstall: npm install @jetbrains/junie-cli')
|
|
16
|
+
return null
|
|
17
|
+
}
|
|
30
18
|
|
|
31
19
|
module.exports = {
|
|
32
|
-
getExpectedBinaryPath,
|
|
33
20
|
getExecutable,
|
|
34
|
-
}
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/junie-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"junieVersion": "
|
|
3
|
+
"version": "704.1.0",
|
|
4
|
+
"junieVersion": "704.1",
|
|
5
5
|
"description": "Junie command‑line client",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
7
7
|
"repository": "https://github.com/jetbrains-junie/junie",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"bin/",
|
|
24
|
+
"shim/",
|
|
24
25
|
"postinstall.js",
|
|
25
26
|
"getExecutable.js"
|
|
26
27
|
],
|
package/postinstall.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require("fs")
|
|
|
5
5
|
const { pipeline } = require("stream/promises")
|
|
6
6
|
const unzipper = require('unzipper')
|
|
7
7
|
const os = require("os")
|
|
8
|
-
const {
|
|
8
|
+
const { execSync } = require("child_process")
|
|
9
9
|
|
|
10
10
|
// Check for Windows early and exit gracefully
|
|
11
11
|
if (os.platform() === 'win32') {
|
|
@@ -22,6 +22,13 @@ if (os.platform() === 'win32') {
|
|
|
22
22
|
process.exit(0)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// === Configuration ===
|
|
26
|
+
const JUNIE_BIN = path.join(os.homedir(), '.local', 'bin')
|
|
27
|
+
const JUNIE_DATA = path.join(os.homedir(), '.local', 'share', 'junie')
|
|
28
|
+
const VERSIONS_DIR = path.join(JUNIE_DATA, 'versions')
|
|
29
|
+
const UPDATES_DIR = path.join(JUNIE_DATA, 'updates')
|
|
30
|
+
const CURRENT_LINK = path.join(JUNIE_DATA, 'current')
|
|
31
|
+
|
|
25
32
|
const ARCH_MAP = {
|
|
26
33
|
x64: 'amd64',
|
|
27
34
|
amd64: 'amd64',
|
|
@@ -86,15 +93,68 @@ function chmodRecursive(dirPath) {
|
|
|
86
93
|
}
|
|
87
94
|
}
|
|
88
95
|
|
|
96
|
+
function installShim() {
|
|
97
|
+
const shimPath = path.join(JUNIE_BIN, 'junie')
|
|
98
|
+
const shimSource = path.join(__dirname, 'shim', 'junie')
|
|
99
|
+
|
|
100
|
+
// Check if shim already exists
|
|
101
|
+
if (fs.existsSync(shimPath)) {
|
|
102
|
+
console.log('[Junie] Updating shim at', shimPath)
|
|
103
|
+
} else {
|
|
104
|
+
console.log('[Junie] Installing shim to', shimPath)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Copy shim.sh to ~/.local/bin/junie
|
|
108
|
+
const shimContent = fs.readFileSync(shimSource, 'utf8')
|
|
109
|
+
fs.writeFileSync(shimPath, shimContent, { mode: 0o755 })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function printPathInstructions() {
|
|
113
|
+
const currentPath = process.env.PATH || ''
|
|
114
|
+
if (!currentPath.includes(JUNIE_BIN)) {
|
|
115
|
+
console.log('')
|
|
116
|
+
console.log('╭──────────────────────────────────────────────────────╮')
|
|
117
|
+
console.log('│ │')
|
|
118
|
+
console.log('│ Add ~/.local/bin to your PATH to use junie directly │')
|
|
119
|
+
console.log('│ │')
|
|
120
|
+
console.log('│ Run: export PATH="$HOME/.local/bin:$PATH" │')
|
|
121
|
+
console.log('│ │')
|
|
122
|
+
console.log('│ Or add to your shell profile (~/.bashrc, ~/.zshrc) │')
|
|
123
|
+
console.log('│ │')
|
|
124
|
+
console.log('╰──────────────────────────────────────────────────────╯')
|
|
125
|
+
console.log('')
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
89
129
|
async function downloadAndInstall() {
|
|
90
130
|
const {arch, osName} = resolveTarget()
|
|
91
131
|
const url = buildUrl({arch, osName})
|
|
92
|
-
const
|
|
93
|
-
const
|
|
132
|
+
const version = require("./package.json").junieVersion
|
|
133
|
+
const targetDir = path.join(VERSIONS_DIR, version)
|
|
94
134
|
|
|
95
|
-
|
|
135
|
+
// Create directories
|
|
136
|
+
fs.mkdirSync(JUNIE_BIN, {recursive: true})
|
|
137
|
+
fs.mkdirSync(targetDir, {recursive: true})
|
|
138
|
+
fs.mkdirSync(UPDATES_DIR, {recursive: true})
|
|
96
139
|
|
|
97
|
-
|
|
140
|
+
// Install shim
|
|
141
|
+
installShim()
|
|
142
|
+
|
|
143
|
+
// Check if version already installed
|
|
144
|
+
if (fs.existsSync(CURRENT_LINK)) {
|
|
145
|
+
try {
|
|
146
|
+
const currentVersion = path.basename(fs.readlinkSync(CURRENT_LINK))
|
|
147
|
+
if (currentVersion === version && fs.readdirSync(targetDir).length > 0) {
|
|
148
|
+
console.log(`[Junie] Version ${version} already installed`)
|
|
149
|
+
printPathInstructions()
|
|
150
|
+
return path.join(targetDir, 'junie')
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
// Continue with installation
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const zipPath = path.join(targetDir, 'junie.zip')
|
|
98
158
|
console.log(`[Junie] Downloading from ${url}`)
|
|
99
159
|
|
|
100
160
|
const res = await fetch(url)
|
|
@@ -102,31 +162,34 @@ async function downloadAndInstall() {
|
|
|
102
162
|
|
|
103
163
|
await pipeline(res.body, fs.createWriteStream(zipPath))
|
|
104
164
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
chmodRecursive(workDir)
|
|
108
|
-
stripQuarantine(workDir)
|
|
165
|
+
console.log('[Junie] Extracting...')
|
|
166
|
+
await fs.createReadStream(zipPath).pipe(unzipper.Extract({ path: targetDir })).promise()
|
|
109
167
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
try { fs.chmodSync(binaryPath, 0o755); } catch {}
|
|
168
|
+
chmodRecursive(targetDir)
|
|
169
|
+
stripQuarantine(targetDir)
|
|
113
170
|
|
|
114
171
|
fs.rmSync(zipPath)
|
|
115
172
|
|
|
116
|
-
|
|
173
|
+
// Update current symlink atomically
|
|
174
|
+
const tempLink = path.join(JUNIE_DATA, 'current.tmp')
|
|
175
|
+
try { fs.unlinkSync(tempLink) } catch {}
|
|
176
|
+
fs.symlinkSync(targetDir, tempLink)
|
|
177
|
+
fs.renameSync(tempLink, CURRENT_LINK)
|
|
117
178
|
|
|
118
|
-
console.log(
|
|
179
|
+
console.log(`[Junie] Installed version ${version}`)
|
|
180
|
+
printPathInstructions()
|
|
119
181
|
|
|
120
|
-
return
|
|
182
|
+
return path.join(targetDir, 'junie')
|
|
121
183
|
}
|
|
122
184
|
|
|
123
185
|
async function main() {
|
|
124
186
|
try {
|
|
125
187
|
await downloadAndInstall()
|
|
188
|
+
console.log('[Junie] Installation complete.')
|
|
126
189
|
} catch (error) {
|
|
127
190
|
console.error('[Junie] Post-install error:', error)
|
|
128
191
|
process.exit(1)
|
|
129
192
|
}
|
|
130
193
|
}
|
|
131
194
|
|
|
132
|
-
main()
|
|
195
|
+
main()
|
package/shim/junie
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Junie CLI Shim
|
|
4
|
+
#
|
|
5
|
+
# This script is the entry point for Junie CLI. It handles:
|
|
6
|
+
# 1. Applying pending updates before launching
|
|
7
|
+
# 2. Version selection via JUNIE_VERSION env or --use-version flag
|
|
8
|
+
# 3. Executing the appropriate version binary
|
|
9
|
+
#
|
|
10
|
+
# Installation locations:
|
|
11
|
+
# Shim: ~/.local/bin/junie
|
|
12
|
+
# Data: ~/.local/share/junie/
|
|
13
|
+
# Versions: ~/.local/share/junie/versions/<version>/junie
|
|
14
|
+
# Updates: ~/.local/share/junie/updates/
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
# === Configuration ===
|
|
19
|
+
JUNIE_DATA="${JUNIE_DATA:-$HOME/.local/share/junie}"
|
|
20
|
+
VERSIONS_DIR="$JUNIE_DATA/versions"
|
|
21
|
+
UPDATES_DIR="$JUNIE_DATA/updates"
|
|
22
|
+
CURRENT_LINK="$JUNIE_DATA/current"
|
|
23
|
+
PENDING_UPDATE="$UPDATES_DIR/pending-update.json"
|
|
24
|
+
|
|
25
|
+
# === Utility Functions ===
|
|
26
|
+
|
|
27
|
+
# Log message to stderr
|
|
28
|
+
log() {
|
|
29
|
+
echo "[Junie] $*" >&2
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
# Check if a command exists
|
|
33
|
+
has_command() {
|
|
34
|
+
command -v "$1" > /dev/null 2>&1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# Parse JSON field (basic, works without jq)
|
|
38
|
+
# Usage: parse_json "field" < file.json
|
|
39
|
+
parse_json_field() {
|
|
40
|
+
local field="$1"
|
|
41
|
+
# Extract value for "field": "value" or "field": number
|
|
42
|
+
grep -o "\"$field\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" | head -1 | sed 's/.*:[[:space:]]*"\([^"]*\)"/\1/' || true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Parse JSON field with jq if available, fallback to grep
|
|
46
|
+
get_json_field() {
|
|
47
|
+
local file="$1"
|
|
48
|
+
local field="$2"
|
|
49
|
+
|
|
50
|
+
if has_command jq; then
|
|
51
|
+
jq -r ".$field // empty" "$file" 2>/dev/null || true
|
|
52
|
+
else
|
|
53
|
+
parse_json_field "$field" < "$file"
|
|
54
|
+
fi
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
# Calculate SHA-256 checksum
|
|
58
|
+
sha256sum_file() {
|
|
59
|
+
local file="$1"
|
|
60
|
+
if has_command shasum; then
|
|
61
|
+
shasum -a 256 "$file" | cut -d' ' -f1
|
|
62
|
+
elif has_command sha256sum; then
|
|
63
|
+
sha256sum "$file" | cut -d' ' -f1
|
|
64
|
+
else
|
|
65
|
+
log "Warning: No SHA-256 tool available, skipping checksum verification"
|
|
66
|
+
echo ""
|
|
67
|
+
fi
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Get binary path for a given version
|
|
71
|
+
# Handles different package structures (macOS app bundle, Linux, direct binary)
|
|
72
|
+
get_binary_path() {
|
|
73
|
+
local version="$1"
|
|
74
|
+
local version_dir="$VERSIONS_DIR/$version"
|
|
75
|
+
|
|
76
|
+
# macOS: look for .app bundle
|
|
77
|
+
if [[ -d "$version_dir/Applications/junie.app" ]]; then
|
|
78
|
+
echo "$version_dir/Applications/junie.app/Contents/MacOS/junie"
|
|
79
|
+
# Linux: look for junie/bin/junie
|
|
80
|
+
elif [[ -f "$version_dir/junie/bin/junie" ]]; then
|
|
81
|
+
echo "$version_dir/junie/bin/junie"
|
|
82
|
+
# Fallback: direct junie binary
|
|
83
|
+
elif [[ -f "$version_dir/junie" ]]; then
|
|
84
|
+
echo "$version_dir/junie"
|
|
85
|
+
else
|
|
86
|
+
echo ""
|
|
87
|
+
fi
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# === Apply Pending Update ===
|
|
91
|
+
apply_pending_update() {
|
|
92
|
+
if [[ ! -f "$PENDING_UPDATE" ]]; then
|
|
93
|
+
return 0
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
log "Applying pending update..."
|
|
97
|
+
|
|
98
|
+
# Parse manifest
|
|
99
|
+
local version zip_path sha256
|
|
100
|
+
version=$(get_json_field "$PENDING_UPDATE" "version")
|
|
101
|
+
zip_path=$(get_json_field "$PENDING_UPDATE" "zipPath")
|
|
102
|
+
sha256=$(get_json_field "$PENDING_UPDATE" "sha256")
|
|
103
|
+
|
|
104
|
+
if [[ -z "$version" || -z "$zip_path" ]]; then
|
|
105
|
+
log "Invalid pending update manifest, skipping"
|
|
106
|
+
rm -f "$PENDING_UPDATE"
|
|
107
|
+
return 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
if [[ ! -f "$zip_path" ]]; then
|
|
111
|
+
log "Update file not found: $zip_path"
|
|
112
|
+
rm -f "$PENDING_UPDATE"
|
|
113
|
+
return 1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
# Verify checksum if available
|
|
117
|
+
if [[ -n "$sha256" ]]; then
|
|
118
|
+
local actual_sha256
|
|
119
|
+
actual_sha256=$(sha256sum_file "$zip_path")
|
|
120
|
+
|
|
121
|
+
# Case-insensitive comparison (compatible with bash 3.x on macOS)
|
|
122
|
+
if [[ -n "$actual_sha256" ]] && ! echo "$actual_sha256" | grep -qi "^${sha256}$"; then
|
|
123
|
+
log "Checksum mismatch, skipping update"
|
|
124
|
+
log "Expected: $sha256"
|
|
125
|
+
log "Got: $actual_sha256"
|
|
126
|
+
rm -f "$PENDING_UPDATE" "$zip_path"
|
|
127
|
+
return 1
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# Extract to versions directory
|
|
132
|
+
local target_dir="$VERSIONS_DIR/$version"
|
|
133
|
+
mkdir -p "$target_dir"
|
|
134
|
+
|
|
135
|
+
log "Extracting to $target_dir..."
|
|
136
|
+
|
|
137
|
+
if has_command unzip; then
|
|
138
|
+
unzip -q -o "$zip_path" -d "$target_dir"
|
|
139
|
+
elif has_command tar; then
|
|
140
|
+
# Fallback for .tar.gz files
|
|
141
|
+
tar -xzf "$zip_path" -C "$target_dir"
|
|
142
|
+
else
|
|
143
|
+
log "Error: No extraction tool available (unzip or tar)"
|
|
144
|
+
return 1
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
# Make binary executable
|
|
148
|
+
chmod +x "$target_dir/junie" 2>/dev/null || true
|
|
149
|
+
|
|
150
|
+
# Remove quarantine on macOS
|
|
151
|
+
xattr -dr com.apple.quarantine "$target_dir" 2>/dev/null || true
|
|
152
|
+
|
|
153
|
+
# Update current symlink atomically
|
|
154
|
+
ln -sfn "$target_dir" "$CURRENT_LINK"
|
|
155
|
+
|
|
156
|
+
# Cleanup
|
|
157
|
+
rm -f "$zip_path" "$PENDING_UPDATE"
|
|
158
|
+
|
|
159
|
+
log "Updated to version $version"
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# === Resolve Version ===
|
|
163
|
+
resolve_version() {
|
|
164
|
+
local version=""
|
|
165
|
+
|
|
166
|
+
# Priority 1: --use-version flag
|
|
167
|
+
for arg in "$@"; do
|
|
168
|
+
case "$arg" in
|
|
169
|
+
--use-version=*)
|
|
170
|
+
version="${arg#--use-version=}"
|
|
171
|
+
break
|
|
172
|
+
;;
|
|
173
|
+
esac
|
|
174
|
+
done
|
|
175
|
+
|
|
176
|
+
# Priority 2: JUNIE_VERSION environment variable
|
|
177
|
+
if [[ -z "$version" && -n "${JUNIE_VERSION:-}" ]]; then
|
|
178
|
+
version="$JUNIE_VERSION"
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
# Priority 3: current symlink
|
|
182
|
+
if [[ -z "$version" ]]; then
|
|
183
|
+
if [[ -L "$CURRENT_LINK" ]]; then
|
|
184
|
+
version=$(basename "$(readlink "$CURRENT_LINK")")
|
|
185
|
+
elif [[ -d "$CURRENT_LINK" ]]; then
|
|
186
|
+
# current might be a directory in some setups
|
|
187
|
+
version=$(basename "$CURRENT_LINK")
|
|
188
|
+
fi
|
|
189
|
+
fi
|
|
190
|
+
|
|
191
|
+
if [[ -z "$version" ]]; then
|
|
192
|
+
log "Error: No version found. Please reinstall Junie."
|
|
193
|
+
log "Run: curl -fsSL https://junie.jetbrains.com/install.sh | bash"
|
|
194
|
+
exit 1
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
# Verify version exists
|
|
198
|
+
if [[ ! -d "$VERSIONS_DIR/$version" ]]; then
|
|
199
|
+
log "Error: Version $version not found in $VERSIONS_DIR"
|
|
200
|
+
log "Available versions:"
|
|
201
|
+
ls -1 "$VERSIONS_DIR" 2>/dev/null || log " (none)"
|
|
202
|
+
exit 1
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
echo "$version"
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
# === Filter Shim-Specific Arguments ===
|
|
209
|
+
# Global array to store filtered args (needed because bash can't return arrays)
|
|
210
|
+
FILTERED_ARGS=()
|
|
211
|
+
|
|
212
|
+
filter_args() {
|
|
213
|
+
FILTERED_ARGS=()
|
|
214
|
+
for arg in "$@"; do
|
|
215
|
+
case "$arg" in
|
|
216
|
+
--use-version=*) ;; # Skip shim-specific flag
|
|
217
|
+
*) FILTERED_ARGS+=("$arg") ;;
|
|
218
|
+
esac
|
|
219
|
+
done
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# === Handle Shim Commands ===
|
|
223
|
+
handle_shim_commands() {
|
|
224
|
+
case "${1:-}" in
|
|
225
|
+
--shim-version)
|
|
226
|
+
echo "junie-shim 1.0.0"
|
|
227
|
+
exit 0
|
|
228
|
+
;;
|
|
229
|
+
--list-versions)
|
|
230
|
+
echo "Installed versions:"
|
|
231
|
+
if [[ -d "$VERSIONS_DIR" ]]; then
|
|
232
|
+
local current_version=""
|
|
233
|
+
if [[ -L "$CURRENT_LINK" ]]; then
|
|
234
|
+
current_version=$(basename "$(readlink "$CURRENT_LINK")")
|
|
235
|
+
fi
|
|
236
|
+
for v in "$VERSIONS_DIR"/*/; do
|
|
237
|
+
local vname=$(basename "$v")
|
|
238
|
+
if [[ "$vname" == "$current_version" ]]; then
|
|
239
|
+
echo " $vname (current)"
|
|
240
|
+
else
|
|
241
|
+
echo " $vname"
|
|
242
|
+
fi
|
|
243
|
+
done
|
|
244
|
+
else
|
|
245
|
+
echo " (none)"
|
|
246
|
+
fi
|
|
247
|
+
exit 0
|
|
248
|
+
;;
|
|
249
|
+
--switch-version=*)
|
|
250
|
+
local new_version="${1#--switch-version=}"
|
|
251
|
+
if [[ ! -d "$VERSIONS_DIR/$new_version" ]]; then
|
|
252
|
+
log "Error: Version $new_version not found"
|
|
253
|
+
exit 1
|
|
254
|
+
fi
|
|
255
|
+
ln -sfn "$VERSIONS_DIR/$new_version" "$CURRENT_LINK"
|
|
256
|
+
log "Switched to version $new_version"
|
|
257
|
+
exit 0
|
|
258
|
+
;;
|
|
259
|
+
esac
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
# === Main ===
|
|
263
|
+
main() {
|
|
264
|
+
# Handle shim-specific commands
|
|
265
|
+
handle_shim_commands "$@"
|
|
266
|
+
|
|
267
|
+
# Apply pending update if exists
|
|
268
|
+
apply_pending_update || true
|
|
269
|
+
|
|
270
|
+
# Resolve which version to run
|
|
271
|
+
local version
|
|
272
|
+
version=$(resolve_version "$@")
|
|
273
|
+
|
|
274
|
+
# Get binary path (handles macOS app bundle, Linux, direct binary)
|
|
275
|
+
local binary
|
|
276
|
+
binary=$(get_binary_path "$version")
|
|
277
|
+
|
|
278
|
+
if [[ -z "$binary" || ! -x "$binary" ]]; then
|
|
279
|
+
log "Error: Binary not found or not executable for version $version"
|
|
280
|
+
log "Looked in: $VERSIONS_DIR/$version"
|
|
281
|
+
exit 1
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
# Set required environment variable for Junie
|
|
285
|
+
export EJ_RUNNER_PWD="${EJ_RUNNER_PWD:-$(pwd)}"
|
|
286
|
+
|
|
287
|
+
# Set JUNIE_DATA for the app to know where data is stored
|
|
288
|
+
export JUNIE_DATA="$JUNIE_DATA"
|
|
289
|
+
|
|
290
|
+
# Filter out shim-specific args and execute
|
|
291
|
+
filter_args "$@"
|
|
292
|
+
exec "$binary" ${FILTERED_ARGS[@]+"${FILTERED_ARGS[@]}"}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
main "$@"
|