@uofx/cli 1.0.0 → 1.0.2
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.
|
@@ -117,13 +117,23 @@ let WslUpdaterService = class WslUpdaterService {
|
|
|
117
117
|
return false;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* 檢查輸出是否指示需要重新啟動
|
|
122
|
+
* @param output - 命令輸出或錯誤訊息
|
|
123
|
+
* @returns 是否需要重新啟動
|
|
124
|
+
*/
|
|
125
|
+
checkNeedsRestart(output) {
|
|
126
|
+
return /restart|reboot|重新啟動|重启|再起動|rebooted/i.test(output);
|
|
127
|
+
}
|
|
120
128
|
/**
|
|
121
129
|
* 安裝或更新 WSL
|
|
122
|
-
*
|
|
130
|
+
* - install: 使用 wsl --install --no-distribution(首次安裝 WSL)
|
|
131
|
+
* - update: 使用 wsl --update(更新現有 WSL 安裝)
|
|
132
|
+
*
|
|
123
133
|
* 如果以管理員身分執行,則在當前控制台中執行
|
|
124
134
|
* 否則,提示用戶以管理員身份重新執行
|
|
125
135
|
*
|
|
126
|
-
* @param action 'install' 或 'update'
|
|
136
|
+
* @param action 'install' 或 'update'
|
|
127
137
|
* @param output - 輸出介面
|
|
128
138
|
* @returns 物件指示是否需要重新啟動
|
|
129
139
|
*/
|
|
@@ -134,22 +144,30 @@ let WslUpdaterService = class WslUpdaterService {
|
|
|
134
144
|
if (isAdmin) {
|
|
135
145
|
output?.info(`Running WSL ${actionDescription} in the current console...`).flush();
|
|
136
146
|
try {
|
|
137
|
-
//
|
|
138
|
-
|
|
139
|
-
|
|
147
|
+
// 根據 action 決定使用的命令
|
|
148
|
+
// install: 使用 wsl --install --no-distribution(首次安裝)
|
|
149
|
+
// update: 使用 wsl --update(更新現有安裝)
|
|
150
|
+
const builder = action === 'install'
|
|
151
|
+
? command_builder_1.CommandBuilder.create('wsl')
|
|
152
|
+
.arg('--install')
|
|
153
|
+
.arg('--no-distribution')
|
|
154
|
+
.inheritStdio()
|
|
155
|
+
: command_builder_1.CommandBuilder.create('wsl')
|
|
156
|
+
.wslCmd('--update')
|
|
157
|
+
.inheritStdio();
|
|
140
158
|
const result = await builder.exec(this.commandExecutor);
|
|
141
159
|
const cmdOutput = result.stdout + result.stderr;
|
|
142
160
|
if (result.exitCode !== 0) {
|
|
143
161
|
// 即使命令 "失敗",也可能已經成功但需要重新啟動
|
|
144
162
|
// Windows 經常在需要重新啟動時返回非零退出碼
|
|
145
|
-
if (
|
|
163
|
+
if (this.checkNeedsRestart(cmdOutput)) {
|
|
146
164
|
output?.success(`WSL ${actionDescription} completed (restart required).`).flush();
|
|
147
165
|
return { needsRestart: true };
|
|
148
166
|
}
|
|
149
167
|
throw new Error('Command failed');
|
|
150
168
|
}
|
|
151
169
|
// 根據輸出檢查是否需要重新啟動
|
|
152
|
-
const needsRestart =
|
|
170
|
+
const needsRestart = this.checkNeedsRestart(cmdOutput);
|
|
153
171
|
if (needsRestart) {
|
|
154
172
|
output?.success(`WSL ${actionDescription} completed.`).flush();
|
|
155
173
|
output?.warning('A system restart is required.').flush();
|
|
@@ -162,7 +180,7 @@ let WslUpdaterService = class WslUpdaterService {
|
|
|
162
180
|
catch (error) {
|
|
163
181
|
// 檢查錯誤訊息中是否包含重啟提示
|
|
164
182
|
const errorMessage = (0, error_formatter_util_1.formatErrorMessage)(error);
|
|
165
|
-
if (
|
|
183
|
+
if (this.checkNeedsRestart(errorMessage)) {
|
|
166
184
|
output?.success(`WSL ${actionDescription} completed (restart required).`).flush();
|
|
167
185
|
return { needsRestart: true };
|
|
168
186
|
}
|
|
@@ -173,7 +191,9 @@ let WslUpdaterService = class WslUpdaterService {
|
|
|
173
191
|
});
|
|
174
192
|
throw new errors_1.AppError(`Failed to execute WSL ${actionDescription}`, {
|
|
175
193
|
exitCode: errors_1.EXIT_CODES.SYSTEM_ERROR,
|
|
176
|
-
solution:
|
|
194
|
+
solution: action === 'install'
|
|
195
|
+
? 'Try running: wsl --install --no-distribution'
|
|
196
|
+
: 'Try running: wsl --update',
|
|
177
197
|
});
|
|
178
198
|
}
|
|
179
199
|
}
|
|
@@ -237,7 +257,13 @@ let WslUpdaterService = class WslUpdaterService {
|
|
|
237
257
|
lines.push('');
|
|
238
258
|
lines.push('To continue setup manually, please run:');
|
|
239
259
|
if (requirement.needsUpdate) {
|
|
240
|
-
|
|
260
|
+
// 根據是否有 currentVersion 判斷是安裝還是更新
|
|
261
|
+
if (!requirement.currentVersion) {
|
|
262
|
+
lines.push(' wsl --install --no-distribution');
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
lines.push(' wsl --update');
|
|
266
|
+
}
|
|
241
267
|
}
|
|
242
268
|
if (requirement.needsDefaultVersion) {
|
|
243
269
|
lines.push(' wsl --set-default-version 2');
|
|
@@ -24,9 +24,10 @@ const error_formatter_util_1 = require("../../infrastructure/utils/error-formatt
|
|
|
24
24
|
* 處理環境設定相關的 CLI 命令
|
|
25
25
|
*/
|
|
26
26
|
let SetupController = class SetupController {
|
|
27
|
-
constructor(setupUseCase, output, wslUpdater, runtimeEnvironment) {
|
|
27
|
+
constructor(setupUseCase, output, wslInfo, wslUpdater, runtimeEnvironment) {
|
|
28
28
|
this.setupUseCase = setupUseCase;
|
|
29
29
|
this.output = output;
|
|
30
|
+
this.wslInfo = wslInfo;
|
|
30
31
|
this.wslUpdater = wslUpdater;
|
|
31
32
|
this.runtimeEnvironment = runtimeEnvironment;
|
|
32
33
|
}
|
|
@@ -55,6 +56,40 @@ let SetupController = class SetupController {
|
|
|
55
56
|
.item('bullet', `Version: ${result.runtimeInfo.version}`);
|
|
56
57
|
if (result.runtimeInfo.isInstalled) {
|
|
57
58
|
this.output.success('Runtime installed');
|
|
59
|
+
// 檢查是否需要更新
|
|
60
|
+
const versionInfo = await this.wslInfo.getWslVersionInfo();
|
|
61
|
+
const updateReq = this.wslInfo.checkWslUpdateRequirement(versionInfo);
|
|
62
|
+
if (updateReq.needsUpdate || updateReq.needsDefaultVersion) {
|
|
63
|
+
this.output.newline().render();
|
|
64
|
+
// 詢問使用者是否要更新
|
|
65
|
+
const shouldSetup = await this.wslUpdater.promptWslSetup(updateReq, this.output);
|
|
66
|
+
if (shouldSetup) {
|
|
67
|
+
// 執行更新
|
|
68
|
+
if (updateReq.needsUpdate) {
|
|
69
|
+
const { needsRestart } = await this.wslUpdater.installWsl('update', this.output);
|
|
70
|
+
if (needsRestart) {
|
|
71
|
+
this.output
|
|
72
|
+
.newline()
|
|
73
|
+
.info('Please restart your computer and run "uofx env setup" again.')
|
|
74
|
+
.render();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// 設定預設版本
|
|
79
|
+
if (updateReq.needsDefaultVersion) {
|
|
80
|
+
await this.wslUpdater.setDefaultVersion(this.output);
|
|
81
|
+
}
|
|
82
|
+
this.output
|
|
83
|
+
.newline()
|
|
84
|
+
.success('WSL setup completed.')
|
|
85
|
+
.render();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// 使用者取消
|
|
90
|
+
this.wslUpdater.handleSetupCancelled(updateReq, this.output);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
58
93
|
}
|
|
59
94
|
else {
|
|
60
95
|
this.output.error('Runtime not installed').newline().render();
|
|
@@ -168,8 +203,9 @@ exports.SetupController = SetupController = __decorate([
|
|
|
168
203
|
(0, tsyringe_1.injectable)(),
|
|
169
204
|
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.SetupEnvironmentUseCase)),
|
|
170
205
|
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IOutputPort)),
|
|
171
|
-
__param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.
|
|
172
|
-
__param(3, (0, tsyringe_1.inject)(tokens_1.TOKENS.
|
|
173
|
-
|
|
206
|
+
__param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.WslInfoService)),
|
|
207
|
+
__param(3, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.WslUpdaterService)),
|
|
208
|
+
__param(4, (0, tsyringe_1.inject)(tokens_1.TOKENS.IRuntimeEnvironmentPort)),
|
|
209
|
+
__metadata("design:paramtypes", [setup_environment_use_case_1.SetupEnvironmentUseCase, Object, Object, Object, Object])
|
|
174
210
|
], SetupController);
|
|
175
211
|
//# sourceMappingURL=setup.controller.js.map
|