@jetbrains/junie-cli 562.3.0 → 624.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 +94 -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": "624.1.0",
|
|
4
|
+
"junieVersion": "624.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,29 @@ 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
|
+
|
|
10
|
+
// Check for Windows early and exit gracefully
|
|
11
|
+
if (os.platform() === 'win32') {
|
|
12
|
+
console.log('')
|
|
13
|
+
console.log('╭──────────────────────────────────────────────────────╮')
|
|
14
|
+
console.log('│ │')
|
|
15
|
+
console.log('│ Junie CLI does not support Windows yet. │')
|
|
16
|
+
console.log('│ Supported platforms: macOS, Linux │')
|
|
17
|
+
console.log('│ │')
|
|
18
|
+
console.log('│ Stay tuned for Windows support in future releases! │')
|
|
19
|
+
console.log('│ │')
|
|
20
|
+
console.log('╰──────────────────────────────────────────────────────╯')
|
|
21
|
+
console.log('')
|
|
22
|
+
process.exit(0)
|
|
23
|
+
}
|
|
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')
|
|
9
31
|
|
|
10
32
|
const ARCH_MAP = {
|
|
11
33
|
x64: 'amd64',
|
|
@@ -71,15 +93,68 @@ function chmodRecursive(dirPath) {
|
|
|
71
93
|
}
|
|
72
94
|
}
|
|
73
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
|
+
|
|
74
129
|
async function downloadAndInstall() {
|
|
75
130
|
const {arch, osName} = resolveTarget()
|
|
76
131
|
const url = buildUrl({arch, osName})
|
|
77
|
-
const
|
|
78
|
-
const
|
|
132
|
+
const version = require("./package.json").junieVersion
|
|
133
|
+
const targetDir = path.join(VERSIONS_DIR, version)
|
|
134
|
+
|
|
135
|
+
// Create directories
|
|
136
|
+
fs.mkdirSync(JUNIE_BIN, {recursive: true})
|
|
137
|
+
fs.mkdirSync(targetDir, {recursive: true})
|
|
138
|
+
fs.mkdirSync(UPDATES_DIR, {recursive: true})
|
|
79
139
|
|
|
80
|
-
|
|
140
|
+
// Install shim
|
|
141
|
+
installShim()
|
|
81
142
|
|
|
82
|
-
|
|
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')
|
|
83
158
|
console.log(`[Junie] Downloading from ${url}`)
|
|
84
159
|
|
|
85
160
|
const res = await fetch(url)
|
|
@@ -87,31 +162,34 @@ async function downloadAndInstall() {
|
|
|
87
162
|
|
|
88
163
|
await pipeline(res.body, fs.createWriteStream(zipPath))
|
|
89
164
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
chmodRecursive(workDir)
|
|
93
|
-
stripQuarantine(workDir)
|
|
165
|
+
console.log('[Junie] Extracting...')
|
|
166
|
+
await fs.createReadStream(zipPath).pipe(unzipper.Extract({ path: targetDir })).promise()
|
|
94
167
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
try { fs.chmodSync(binaryPath, 0o755); } catch {}
|
|
168
|
+
chmodRecursive(targetDir)
|
|
169
|
+
stripQuarantine(targetDir)
|
|
98
170
|
|
|
99
171
|
fs.rmSync(zipPath)
|
|
100
172
|
|
|
101
|
-
|
|
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)
|
|
102
178
|
|
|
103
|
-
console.log(
|
|
179
|
+
console.log(`[Junie] Installed version ${version}`)
|
|
180
|
+
printPathInstructions()
|
|
104
181
|
|
|
105
|
-
return
|
|
182
|
+
return path.join(targetDir, 'junie')
|
|
106
183
|
}
|
|
107
184
|
|
|
108
185
|
async function main() {
|
|
109
186
|
try {
|
|
110
187
|
await downloadAndInstall()
|
|
188
|
+
console.log('[Junie] Installation complete.')
|
|
111
189
|
} catch (error) {
|
|
112
190
|
console.error('[Junie] Post-install error:', error)
|
|
113
191
|
process.exit(1)
|
|
114
192
|
}
|
|
115
193
|
}
|
|
116
194
|
|
|
117
|
-
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 "$@"
|