@xaidenlabs/uso 1.1.68 ā 1.1.70
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/package.json +1 -1
- package/src/commands/init.js +218 -208
- package/src/platforms/wsl.js +89 -14
package/package.json
CHANGED
package/src/commands/init.js
CHANGED
|
@@ -1,240 +1,250 @@
|
|
|
1
|
-
const os = require(
|
|
2
|
-
const shell = require(
|
|
3
|
-
const { log, spinner } = require(
|
|
4
|
-
const { installWindows } = require(
|
|
5
|
-
const { installMacOS } = require(
|
|
6
|
-
const { installLinux } = require(
|
|
7
|
-
const { getCargoBinPath } = require(
|
|
8
|
-
const { checkRust, checkSolana, checkAnchor } = require(
|
|
9
|
-
const { ensureWalletInteractive } = require(
|
|
10
|
-
const path = require(
|
|
11
|
-
const fs = require(
|
|
12
|
-
|
|
13
|
-
const { installWsl, installWslFeature } = require(
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const shell = require("shelljs");
|
|
3
|
+
const { log, spinner } = require("../utils/logger");
|
|
4
|
+
const { installWindows } = require("../platforms/windows");
|
|
5
|
+
const { installMacOS } = require("../platforms/macos");
|
|
6
|
+
const { installLinux } = require("../platforms/linux");
|
|
7
|
+
const { getCargoBinPath } = require("../utils/paths");
|
|
8
|
+
const { checkRust, checkSolana, checkAnchor } = require("./doctor");
|
|
9
|
+
const { ensureWalletInteractive } = require("../utils/wallet");
|
|
10
|
+
const path = require("path");
|
|
11
|
+
const fs = require("fs");
|
|
12
|
+
|
|
13
|
+
const { installWsl, installWslFeature } = require("../platforms/wsl");
|
|
14
14
|
|
|
15
15
|
const init = async (component, options) => {
|
|
16
|
-
|
|
16
|
+
const platform = os.platform();
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
// --- On Windows, ALWAYS use the WSL path ---
|
|
19
|
+
if (platform === "win32") {
|
|
20
|
+
const hasWslBinary = !!shell.which("wsl");
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
if (!hasWslBinary) {
|
|
23
|
+
// WSL is not installed at all ā request admin elevation to enable the feature
|
|
24
|
+
log.header("š§ Windows Subsystem for Linux (WSL) not found.");
|
|
25
|
+
log.info("š”ļø Requesting administrator permission to install WSL...");
|
|
26
|
+
log.info(
|
|
27
|
+
"š Please click 'Yes' in the UAC popup that appears to allow this.",
|
|
28
|
+
);
|
|
29
|
+
console.log("");
|
|
28
30
|
|
|
29
|
-
|
|
31
|
+
const wslInstalled = await installWslFeature();
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// If we're here, WSL was instantly available (rare ā usually needs reboot)
|
|
37
|
-
// Fall through to installWsl() below
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// WSL binary is present ā run the full WSL toolchain install
|
|
41
|
-
await installWsl();
|
|
33
|
+
if (!wslInstalled && !shell.which("wsl")) {
|
|
34
|
+
// installWslFeature already printed the relevant error/reboot message
|
|
42
35
|
return;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (component) {
|
|
46
|
-
component = component.toLowerCase();
|
|
47
|
-
log.info(`šÆ Targeted installation: ${component}`);
|
|
48
|
-
|
|
49
|
-
if (component === 'rust') {
|
|
50
|
-
if (checkRust(true)) {
|
|
51
|
-
log.success("ā
Rust is already installed.");
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
log.info("š¦ Installing Rust...");
|
|
55
|
-
let success = false;
|
|
56
|
-
if (platform === 'win32') success = await installWindows(true, false);
|
|
57
|
-
else if (platform === 'darwin') success = await installMacOS(true, false);
|
|
58
|
-
else success = await installLinux(true, false);
|
|
59
|
-
|
|
60
|
-
if (success) log.success("ā
Rust installed successfully.");
|
|
61
|
-
else log.error("ā Rust installation failed.");
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (component === 'solana') {
|
|
66
|
-
if (checkSolana(true)) {
|
|
67
|
-
log.success("ā
Solana CLI is already installed.");
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
log.info("āļø Installing Solana CLI...");
|
|
71
|
-
let success = false;
|
|
72
|
-
if (platform === 'win32') success = await installWindows(false, true);
|
|
73
|
-
else if (platform === 'darwin') success = await installMacOS(false, true);
|
|
74
|
-
else success = await installLinux(false, true);
|
|
75
|
-
|
|
76
|
-
if (success) log.success("ā
Solana CLI installed successfully.");
|
|
77
|
-
else log.error("ā Solana CLI installation failed.");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
36
|
+
}
|
|
80
37
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Fall through to Anchor installation logic below, but skip others
|
|
87
|
-
} else if (component !== 'anchor') { // If it's not rust, solana, or anchor
|
|
88
|
-
log.error(`ā Unknown component: ${component}. Available: rust, solana, anchor`);
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
38
|
+
// If wsl.exe is now available, continue straight into the Ubuntu setup.
|
|
39
|
+
// On some machines this still needs a reboot, but we let the distro phase
|
|
40
|
+
// run immediately so setup can continue as far as the system allows.
|
|
91
41
|
}
|
|
92
42
|
|
|
93
|
-
//
|
|
43
|
+
// WSL binary is present ā run the full WSL toolchain install
|
|
44
|
+
await installWsl();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
94
47
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const hasAnchor = checkAnchor(true);
|
|
48
|
+
if (component) {
|
|
49
|
+
component = component.toLowerCase();
|
|
50
|
+
log.info(`šÆ Targeted installation: ${component}`);
|
|
99
51
|
|
|
100
|
-
if (component ===
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
52
|
+
if (component === "rust") {
|
|
53
|
+
if (checkRust(true)) {
|
|
54
|
+
log.success("ā
Rust is already installed.");
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
log.info("š¦ Installing Rust...");
|
|
58
|
+
let success = false;
|
|
59
|
+
if (platform === "win32") success = await installWindows(true, false);
|
|
60
|
+
else if (platform === "darwin") success = await installMacOS(true, false);
|
|
61
|
+
else success = await installLinux(true, false);
|
|
62
|
+
|
|
63
|
+
if (success) log.success("ā
Rust installed successfully.");
|
|
64
|
+
else log.error("ā Rust installation failed.");
|
|
65
|
+
return;
|
|
109
66
|
}
|
|
110
67
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
log.success("
|
|
114
|
-
await ensureWalletInteractive();
|
|
68
|
+
if (component === "solana") {
|
|
69
|
+
if (checkSolana(true)) {
|
|
70
|
+
log.success("ā
Solana CLI is already installed.");
|
|
115
71
|
return;
|
|
72
|
+
}
|
|
73
|
+
log.info("āļø Installing Solana CLI...");
|
|
74
|
+
let success = false;
|
|
75
|
+
if (platform === "win32") success = await installWindows(false, true);
|
|
76
|
+
else if (platform === "darwin") success = await installMacOS(false, true);
|
|
77
|
+
else success = await installLinux(false, true);
|
|
78
|
+
|
|
79
|
+
if (success) log.success("ā
Solana CLI installed successfully.");
|
|
80
|
+
else log.error("ā Solana CLI installation failed.");
|
|
81
|
+
return;
|
|
116
82
|
}
|
|
117
83
|
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
log.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (platform === 'win32') {
|
|
132
|
-
spin.stop();
|
|
133
|
-
success = await installWindows(installRust, installSolana);
|
|
134
|
-
} else if (platform === 'darwin') {
|
|
135
|
-
spin.stop();
|
|
136
|
-
success = await installMacOS(installRust, installSolana);
|
|
137
|
-
} else {
|
|
138
|
-
spin.stop();
|
|
139
|
-
success = await installLinux(installRust, installSolana);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
if (!success) {
|
|
143
|
-
log.error("ā Platform-specific installation failed.");
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
} catch (e) {
|
|
147
|
-
spin.stop();
|
|
148
|
-
log.error(e.message);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
84
|
+
if (component === "anchor") {
|
|
85
|
+
if (checkAnchor(true)) {
|
|
86
|
+
log.success("ā
Anchor is already installed.");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Fall through to Anchor installation logic below, but skip others
|
|
90
|
+
} else if (component !== "anchor") {
|
|
91
|
+
// If it's not rust, solana, or anchor
|
|
92
|
+
log.error(
|
|
93
|
+
`ā Unknown component: ${component}. Available: rust, solana, anchor`,
|
|
94
|
+
);
|
|
95
|
+
return;
|
|
151
96
|
}
|
|
97
|
+
}
|
|
152
98
|
|
|
153
|
-
|
|
154
|
-
if (!hasAnchor && (!component || component === 'anchor')) {
|
|
155
|
-
log.info("ā Installing Anchor Framework...");
|
|
99
|
+
// --- FULL INSTALLATION / ANCHOR ONLY FLOW ---
|
|
156
100
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
101
|
+
// If authenticating for just Anchor, we assume Rust/Solana are prerequisites or we skip them
|
|
102
|
+
let installRust = !checkRust(true);
|
|
103
|
+
let installSolana = !checkSolana(true);
|
|
104
|
+
const hasAnchor = checkAnchor(true);
|
|
160
105
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
106
|
+
if (component === "anchor") {
|
|
107
|
+
// ensuring prerequisites for anchor
|
|
108
|
+
if (installRust) {
|
|
109
|
+
log.warn("ā ļø Rust is required for Anchor but not installed.");
|
|
110
|
+
// asking or just failing? For granular, let's just fail or warn.
|
|
111
|
+
// But let's proceed to install Anchor logic which handles cargo check
|
|
112
|
+
}
|
|
113
|
+
installRust = false; // Don't run platform installers for these
|
|
114
|
+
installSolana = false;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Validating state for full install
|
|
118
|
+
if (!component && !installRust && !installSolana && hasAnchor) {
|
|
119
|
+
log.success("š Everything is already installed!");
|
|
120
|
+
await ensureWalletInteractive();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!component) {
|
|
125
|
+
log.header("š Checking current environment state...");
|
|
126
|
+
log.info(`\nš¦ Missing components:`);
|
|
127
|
+
if (installRust) log.error(" - Rust");
|
|
128
|
+
if (installSolana) log.error(" - Solana CLI");
|
|
129
|
+
if (!hasAnchor) log.error(" - Anchor");
|
|
130
|
+
console.log("");
|
|
131
|
+
|
|
132
|
+
const spin = spinner("Starting Installation...").start();
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
let success = false;
|
|
136
|
+
|
|
137
|
+
if (platform === "win32") {
|
|
138
|
+
spin.stop();
|
|
139
|
+
success = await installWindows(installRust, installSolana);
|
|
140
|
+
} else if (platform === "darwin") {
|
|
141
|
+
spin.stop();
|
|
142
|
+
success = await installMacOS(installRust, installSolana);
|
|
143
|
+
} else {
|
|
144
|
+
spin.stop();
|
|
145
|
+
success = await installLinux(installRust, installSolana);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!success) {
|
|
149
|
+
log.error("ā Platform-specific installation failed.");
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
} catch (e) {
|
|
153
|
+
spin.stop();
|
|
154
|
+
log.error(e.message);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Install Anchor (Universal) - Runs if component='anchor' OR full install
|
|
160
|
+
if (!hasAnchor && (!component || component === "anchor")) {
|
|
161
|
+
log.info("ā Installing Anchor Framework...");
|
|
162
|
+
|
|
163
|
+
const cargoBin = getCargoBinPath();
|
|
164
|
+
const cargoExe = platform === "win32" ? "cargo.exe" : "cargo";
|
|
165
|
+
const avmExe = platform === "win32" ? "avm.exe" : "avm";
|
|
166
|
+
|
|
167
|
+
// Resolve cargo command
|
|
168
|
+
let cargoCmd = cargoExe;
|
|
169
|
+
if (fs.existsSync(path.join(cargoBin, cargoExe))) {
|
|
170
|
+
cargoCmd = `"${path.join(cargoBin, cargoExe)}"`;
|
|
171
|
+
} else if (!installRust && checkRust(true)) {
|
|
172
|
+
cargoCmd = "cargo";
|
|
173
|
+
}
|
|
168
174
|
|
|
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
|
-
log.warn("ā ļø AVM installation failed. Trying fallback...");
|
|
204
|
-
fallbackDirectInstall(cargoCmd);
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
shell.exec(`${avmCmd} use latest`);
|
|
208
|
-
log.success("ā
Anchor installed.");
|
|
209
|
-
}
|
|
175
|
+
log.subHeader(`Using cargo: ${cargoCmd}`);
|
|
176
|
+
|
|
177
|
+
// Try installing AVM first (Preferred)
|
|
178
|
+
log.info(" Attempting AVM install...");
|
|
179
|
+
const avmInstall = shell.exec(
|
|
180
|
+
`${cargoCmd} install --git https://github.com/coral-xyz/anchor avm --locked --force`,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
if (avmInstall.code === 0) {
|
|
184
|
+
// Use AVM
|
|
185
|
+
let avmCmd = avmExe;
|
|
186
|
+
if (fs.existsSync(path.join(cargoBin, avmExe))) {
|
|
187
|
+
avmCmd = `"${path.join(cargoBin, avmExe)}"`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
log.subHeader(`Using avm: ${avmCmd}`);
|
|
191
|
+
const avmUse = shell.exec(`${avmCmd} install latest`);
|
|
192
|
+
|
|
193
|
+
// Detect Permission Error for AVM
|
|
194
|
+
if (avmUse.code !== 0) {
|
|
195
|
+
const output = avmUse.stderr + avmUse.stdout;
|
|
196
|
+
if (output.includes("os error 1314") && platform === "win32") {
|
|
197
|
+
log.warn("ā ļø AVM Permission denied (Symlink creation failed).");
|
|
198
|
+
log.info("š”ļø Triggering Run as Administrator (UAC) for Anchor...");
|
|
199
|
+
const absAvmPath = path.join(cargoBin, avmExe);
|
|
200
|
+
const elevateCmd = `powershell -Command "Start-Process -FilePath '${absAvmPath}' -ArgumentList 'install latest' -Verb RunAs -Wait; Start-Process -FilePath '${absAvmPath}' -ArgumentList 'use latest' -Verb RunAs -Wait"`;
|
|
201
|
+
const elevatedRun = shell.exec(elevateCmd);
|
|
202
|
+
|
|
203
|
+
if (elevatedRun.code === 0) {
|
|
204
|
+
log.success("ā
Anchor installed (Elevated).");
|
|
205
|
+
} else {
|
|
206
|
+
log.error("ā Elevated installation failed. Trying fallback...");
|
|
207
|
+
fallbackDirectInstall(cargoCmd);
|
|
208
|
+
}
|
|
210
209
|
} else {
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
log.warn("ā ļø AVM installation failed. Trying fallback...");
|
|
211
|
+
fallbackDirectInstall(cargoCmd);
|
|
213
212
|
}
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
} else {
|
|
214
|
+
shell.exec(`${avmCmd} use latest`);
|
|
215
|
+
log.success("ā
Anchor installed.");
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
log.error("ā Failed to install AVM via Cargo.");
|
|
219
|
+
return;
|
|
216
220
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
221
|
+
} else if (component === "anchor" && hasAnchor) {
|
|
222
|
+
log.success("ā
Anchor is already installed.");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (!component) {
|
|
226
|
+
log.header("\nā
Uso Setup Complete!");
|
|
227
|
+
await ensureWalletInteractive();
|
|
228
|
+
|
|
229
|
+
if (installRust || installSolana || !hasAnchor) {
|
|
230
|
+
log.warn(
|
|
231
|
+
"š Please RESTART your terminal/VS Code to ensure all PATH variables are updated.",
|
|
232
|
+
);
|
|
227
233
|
}
|
|
234
|
+
log.info("š Try running: uso verify");
|
|
235
|
+
}
|
|
228
236
|
};
|
|
229
237
|
|
|
230
238
|
const fallbackDirectInstall = (cargoCmd) => {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
log.info("š Falling back to direct 'anchor-cli' installation...");
|
|
240
|
+
const directInstall = shell.exec(
|
|
241
|
+
`${cargoCmd} install --git https://github.com/coral-xyz/anchor anchor-cli --locked --force`,
|
|
242
|
+
);
|
|
243
|
+
if (directInstall.code !== 0) {
|
|
244
|
+
log.error("ā Failed to install Anchor via fallback method.");
|
|
245
|
+
} else {
|
|
246
|
+
log.success("ā
Anchor installed (Direct Cargo).");
|
|
247
|
+
}
|
|
238
248
|
};
|
|
239
249
|
|
|
240
250
|
module.exports = { init };
|
package/src/platforms/wsl.js
CHANGED
|
@@ -8,6 +8,39 @@ const { spawnSync } = require("child_process");
|
|
|
8
8
|
const chalk = require("chalk");
|
|
9
9
|
const WSL_DISTRO = "Ubuntu";
|
|
10
10
|
|
|
11
|
+
const progressHelpers = `
|
|
12
|
+
print_progress() {
|
|
13
|
+
local label="$1"
|
|
14
|
+
local percent="$2"
|
|
15
|
+
printf "\r%s %d%%" "$label" "$percent"
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
run_with_progress() {
|
|
19
|
+
local label="$1"
|
|
20
|
+
local start="$2"
|
|
21
|
+
local end="$3"
|
|
22
|
+
shift 3
|
|
23
|
+
|
|
24
|
+
"$@" &
|
|
25
|
+
local pid=$!
|
|
26
|
+
local current="$start"
|
|
27
|
+
|
|
28
|
+
while kill -0 "$pid" 2>/dev/null; do
|
|
29
|
+
print_progress "$label" "$current"
|
|
30
|
+
if [ "$current" -lt "$((end - 1))" ]; then
|
|
31
|
+
current=$((current + 1))
|
|
32
|
+
fi
|
|
33
|
+
sleep 2
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
wait "$pid"
|
|
37
|
+
local status=$?
|
|
38
|
+
print_progress "$label" "$end"
|
|
39
|
+
printf "\n"
|
|
40
|
+
return "$status"
|
|
41
|
+
}
|
|
42
|
+
`.replace(/\r\n/g, "\n");
|
|
43
|
+
|
|
11
44
|
/**
|
|
12
45
|
* Installs the WSL Windows Feature via an elevated PowerShell UAC prompt.
|
|
13
46
|
* This is needed when `wsl.exe` is not present on the system at all.
|
|
@@ -126,9 +159,7 @@ const installWsl = async () => {
|
|
|
126
159
|
"\nš ACTION REQUIRED: Run this command manually in PowerShell as Administrator:",
|
|
127
160
|
);
|
|
128
161
|
console.log(
|
|
129
|
-
chalk.bold.yellow(
|
|
130
|
-
` wsl --install -d ${WSL_DISTRO} --web-download`,
|
|
131
|
-
),
|
|
162
|
+
chalk.bold.yellow(` wsl --install -d ${WSL_DISTRO} --web-download`),
|
|
132
163
|
);
|
|
133
164
|
log.warn(
|
|
134
165
|
"\nOnce that completes successfully, run 'uso setup --wsl' again.",
|
|
@@ -168,10 +199,10 @@ const installWsl = async () => {
|
|
|
168
199
|
set -e
|
|
169
200
|
export DEBIAN_FRONTEND=noninteractive
|
|
170
201
|
|
|
202
|
+
${progressHelpers}
|
|
203
|
+
|
|
171
204
|
if ! command -v cc &> /dev/null || ! command -v pkg-config &> /dev/null; then
|
|
172
|
-
|
|
173
|
-
apt-get update -y -qq
|
|
174
|
-
apt-get install -y -qq curl build-essential pkg-config libssl-dev libudev-dev
|
|
205
|
+
run_with_progress "š¦ Installing system build tools..." 0 100 bash -lc "apt-get update -y -qq && apt-get install -y -qq curl build-essential pkg-config libssl-dev libudev-dev"
|
|
175
206
|
echo "ā
Build tools installed."
|
|
176
207
|
else
|
|
177
208
|
echo "ā
Build tools already present."
|
|
@@ -201,6 +232,8 @@ fi
|
|
|
201
232
|
# NO set -e ā we handle errors per-step
|
|
202
233
|
FAILURES=""
|
|
203
234
|
|
|
235
|
+
${progressHelpers}
|
|
236
|
+
|
|
204
237
|
# Hush login
|
|
205
238
|
touch ~/.hushlogin
|
|
206
239
|
|
|
@@ -224,7 +257,7 @@ else
|
|
|
224
257
|
echo "ā
Rust repaired."
|
|
225
258
|
else
|
|
226
259
|
echo "š¦ Installing Rust..."
|
|
227
|
-
|
|
260
|
+
if run_with_progress "š¦ Installing Rust..." 10 35 bash -lc "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y"; then
|
|
228
261
|
source $HOME/.cargo/env 2>/dev/null || true
|
|
229
262
|
rustup toolchain install stable >/dev/null 2>&1 || true
|
|
230
263
|
rustup default stable >/dev/null 2>&1 || true
|
|
@@ -248,14 +281,54 @@ source $HOME/.cargo/env 2>/dev/null || true
|
|
|
248
281
|
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
|
|
249
282
|
if ! command -v solana &> /dev/null; then
|
|
250
283
|
echo "āļø Installing Solana CLI..."
|
|
251
|
-
|
|
284
|
+
|
|
285
|
+
# Helper to download with retries and proper SSL handling
|
|
286
|
+
install_solana_with_retry() {
|
|
287
|
+
local url="$1"
|
|
288
|
+
local description="$2"
|
|
289
|
+
local max_attempts=3
|
|
290
|
+
local attempt=1
|
|
291
|
+
|
|
292
|
+
while [ $attempt -le $max_attempts ]; do
|
|
293
|
+
if [ $attempt -gt 1 ]; then
|
|
294
|
+
echo " Retry attempt $attempt/$max_attempts..."
|
|
295
|
+
sleep 2
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
# Download installer script with SSL options and timeout
|
|
299
|
+
if curl --proto '=https' --tlsv1.2 -sSf --max-time 60 --connect-timeout 10 \
|
|
300
|
+
--cacert /etc/ssl/certs/ca-certificates.crt \
|
|
301
|
+
"$url" > /tmp/solana_install.sh 2>/dev/null; then
|
|
302
|
+
# Execute the downloaded script
|
|
303
|
+
if bash /tmp/solana_install.sh; then
|
|
304
|
+
rm -f /tmp/solana_install.sh
|
|
305
|
+
return 0
|
|
306
|
+
fi
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
attempt=$((attempt + 1))
|
|
310
|
+
done
|
|
311
|
+
|
|
312
|
+
rm -f /tmp/solana_install.sh
|
|
313
|
+
return 1
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
solana_installed=0
|
|
317
|
+
|
|
318
|
+
# Try official Solana release
|
|
319
|
+
if install_solana_with_retry "https://release.solana.com/stable/install" "Solana"; then
|
|
320
|
+
solana_installed=1
|
|
252
321
|
echo "ā
Solana installed."
|
|
253
|
-
|
|
322
|
+
# Fallback to Agave (community-maintained)
|
|
323
|
+
elif install_solana_with_retry "https://release.anza.xyz/stable/install" "Agave"; then
|
|
324
|
+
solana_installed=1
|
|
254
325
|
echo "ā
Solana installed (via Agave)."
|
|
255
326
|
else
|
|
256
327
|
FAILURES="$FAILURES solana"
|
|
257
|
-
echo "ā ļø Solana install
|
|
328
|
+
echo "ā ļø Solana install failed after retries. Network or certificate issue detected."
|
|
329
|
+
echo " Run 'uso init' again to retry."
|
|
258
330
|
fi
|
|
331
|
+
|
|
259
332
|
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
|
|
260
333
|
else
|
|
261
334
|
echo "ā
Solana already installed."
|
|
@@ -266,7 +339,7 @@ if ! command -v anchor &> /dev/null; then
|
|
|
266
339
|
# Install AVM if not present
|
|
267
340
|
if ! command -v avm &> /dev/null; then
|
|
268
341
|
echo "ā Installing AVM (compiling from source, ~5 min)..."
|
|
269
|
-
|
|
342
|
+
if run_with_progress "ā Installing AVM (compiling from source)..." 60 85 cargo install --git https://github.com/coral-xyz/anchor avm --locked --force; then
|
|
270
343
|
echo "ā
AVM compiled."
|
|
271
344
|
else
|
|
272
345
|
FAILURES="$FAILURES avm"
|
|
@@ -279,12 +352,12 @@ if ! command -v anchor &> /dev/null; then
|
|
|
279
352
|
# Install Anchor via AVM (try binary first, then compile from source)
|
|
280
353
|
if command -v avm &> /dev/null; then
|
|
281
354
|
echo "ā Installing Anchor CLI..."
|
|
282
|
-
|
|
355
|
+
if run_with_progress "ā Installing Anchor CLI..." 85 100 avm install latest; then
|
|
283
356
|
avm use latest
|
|
284
357
|
echo "ā
Anchor installed."
|
|
285
358
|
else
|
|
286
359
|
echo "ā ļø Binary download timed out. Building from source (this takes ~10 min)..."
|
|
287
|
-
|
|
360
|
+
if run_with_progress "ā Building Anchor CLI from source..." 85 100 avm install latest --force; then
|
|
288
361
|
avm use latest
|
|
289
362
|
echo "ā
Anchor built from source."
|
|
290
363
|
else
|
|
@@ -316,7 +389,9 @@ fi
|
|
|
316
389
|
const spin2 = spinner(
|
|
317
390
|
"Phase 2/2: Installing Rust, Solana, Anchor (this takes a while)...",
|
|
318
391
|
).start();
|
|
319
|
-
const userRes = shell.exec(
|
|
392
|
+
const userRes = shell.exec(
|
|
393
|
+
`wsl -d ${WSL_DISTRO} -e bash "${wslUserScriptPath}"`,
|
|
394
|
+
);
|
|
320
395
|
fs.unlinkSync(userScriptPath);
|
|
321
396
|
|
|
322
397
|
if (userRes.code === 0) {
|