@harmonyos-arkts/droid2hmos 0.0.9 → 0.0.10
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/LICENSE +21 -21
- package/README.md +249 -249
- package/config/preflight-checklist.json +65 -65
- package/dist/cli.js +190 -26
- package/dist/cli.js.map +1 -1
- package/package.json +36 -36
- package/templates/ohos/AppScope/app.json5 +10 -10
- package/templates/ohos/AppScope/resources/base/element/string.json +8 -8
- package/templates/ohos/AppScope/resources/base/media/layered_image.json +6 -6
- package/templates/ohos/build-profile.json5 +41 -41
- package/templates/ohos/code-linter.json5 +31 -31
- package/templates/ohos/entry/build-profile.json5 +32 -32
- package/templates/ohos/entry/hvigorfile.ts +5 -5
- package/templates/ohos/entry/obfuscation-rules.txt +22 -22
- package/templates/ohos/entry/oh-package.json5 +10 -10
- package/templates/ohos/entry/src/main/ets/entryability/EntryAbility.ets +47 -47
- package/templates/ohos/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +15 -15
- package/templates/ohos/entry/src/main/ets/pages/Index.ets +22 -22
- package/templates/ohos/entry/src/main/module.json5 +49 -49
- package/templates/ohos/entry/src/main/resources/base/element/color.json +7 -7
- package/templates/ohos/entry/src/main/resources/base/element/float.json +8 -8
- package/templates/ohos/entry/src/main/resources/base/element/string.json +15 -15
- package/templates/ohos/entry/src/main/resources/base/media/layered_image.json +6 -6
- package/templates/ohos/entry/src/main/resources/base/profile/backup_config.json +2 -2
- package/templates/ohos/entry/src/main/resources/base/profile/main_pages.json +5 -5
- package/templates/ohos/entry/src/main/resources/dark/element/color.json +7 -7
- package/templates/ohos/entry/src/mock/mock-config.json5 +1 -1
- package/templates/ohos/entry/src/ohosTest/ets/test/Ability.test.ets +34 -34
- package/templates/ohos/entry/src/ohosTest/ets/test/List.test.ets +4 -4
- package/templates/ohos/entry/src/ohosTest/ets/testability/TestAbility.ets +48 -48
- package/templates/ohos/entry/src/ohosTest/ets/testability/pages/Index.ets +14 -14
- package/templates/ohos/entry/src/ohosTest/ets/testrunner/OpenHarmonyTestRunner.ets +41 -41
- package/templates/ohos/entry/src/ohosTest/module.json5 +25 -25
- package/templates/ohos/entry/src/ohosTest/resources/base/element/color.json +7 -7
- package/templates/ohos/entry/src/ohosTest/resources/base/element/string.json +12 -12
- package/templates/ohos/entry/src/ohosTest/resources/base/profile/test_pages.json +5 -5
- package/templates/ohos/entry/src/test/List.test.ets +4 -4
- package/templates/ohos/entry/src/test/LocalUnit.test.ets +32 -32
- package/templates/ohos/hvigor/hvigor-config.json5 +23 -23
- package/templates/ohos/hvigorfile.ts +5 -5
- package/templates/ohos/oh-package-lock.json5 +27 -27
- package/templates/ohos/oh-package.json5 +10 -10
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"checks": {
|
|
4
|
-
"android-ui-stack": {
|
|
5
|
-
"name": "Android UI 技术栈",
|
|
6
|
-
"required": true,
|
|
7
|
-
"enabled": true
|
|
8
|
-
},
|
|
9
|
-
"git": {
|
|
10
|
-
"name": "Git 仓库和工作区",
|
|
11
|
-
"required": true,
|
|
12
|
-
"enabled": true
|
|
13
|
-
},
|
|
14
|
-
"toolchain": {
|
|
15
|
-
"name": "主机综合工具链",
|
|
16
|
-
"required": true,
|
|
17
|
-
"enabled": true
|
|
18
|
-
},
|
|
19
|
-
"devecocli-auth": {
|
|
20
|
-
"name": "DevEco CLI 登录状态",
|
|
21
|
-
"required": true,
|
|
22
|
-
"enabled": true
|
|
23
|
-
},
|
|
24
|
-
"appgraph": {
|
|
25
|
-
"name": "AppGraph 兼容性和健康状态",
|
|
26
|
-
"required": true,
|
|
27
|
-
"enabled": true
|
|
28
|
-
},
|
|
29
|
-
"config": {
|
|
30
|
-
"name": ".migration/config.json",
|
|
31
|
-
"required": true,
|
|
32
|
-
"enabled": true
|
|
33
|
-
},
|
|
34
|
-
"android-build": {
|
|
35
|
-
"name": "Android 基线构建",
|
|
36
|
-
"required": false,
|
|
37
|
-
"enabled": false
|
|
38
|
-
},
|
|
39
|
-
"android-emulator": {
|
|
40
|
-
"name": "Android 模拟器",
|
|
41
|
-
"required": false,
|
|
42
|
-
"enabled": true
|
|
43
|
-
},
|
|
44
|
-
"harmony-project": {
|
|
45
|
-
"name": "HarmonyOS 工程存在或初始化",
|
|
46
|
-
"required": true,
|
|
47
|
-
"enabled": true
|
|
48
|
-
},
|
|
49
|
-
"harmony-sdk": {
|
|
50
|
-
"name": "HarmonyOS SDK 声明根目录",
|
|
51
|
-
"required": false,
|
|
52
|
-
"enabled": true
|
|
53
|
-
},
|
|
54
|
-
"harmony-build": {
|
|
55
|
-
"name": "HarmonyOS 应用 HAP 构建",
|
|
56
|
-
"required": true,
|
|
57
|
-
"enabled": true
|
|
58
|
-
},
|
|
59
|
-
"harmony-device": {
|
|
60
|
-
"name": "HarmonyOS 设备和 Shell",
|
|
61
|
-
"required": true,
|
|
62
|
-
"enabled": true
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"checks": {
|
|
4
|
+
"android-ui-stack": {
|
|
5
|
+
"name": "Android UI 技术栈",
|
|
6
|
+
"required": true,
|
|
7
|
+
"enabled": true
|
|
8
|
+
},
|
|
9
|
+
"git": {
|
|
10
|
+
"name": "Git 仓库和工作区",
|
|
11
|
+
"required": true,
|
|
12
|
+
"enabled": true
|
|
13
|
+
},
|
|
14
|
+
"toolchain": {
|
|
15
|
+
"name": "主机综合工具链",
|
|
16
|
+
"required": true,
|
|
17
|
+
"enabled": true
|
|
18
|
+
},
|
|
19
|
+
"devecocli-auth": {
|
|
20
|
+
"name": "DevEco CLI 登录状态",
|
|
21
|
+
"required": true,
|
|
22
|
+
"enabled": true
|
|
23
|
+
},
|
|
24
|
+
"appgraph": {
|
|
25
|
+
"name": "AppGraph 兼容性和健康状态",
|
|
26
|
+
"required": true,
|
|
27
|
+
"enabled": true
|
|
28
|
+
},
|
|
29
|
+
"config": {
|
|
30
|
+
"name": ".migration/config.json",
|
|
31
|
+
"required": true,
|
|
32
|
+
"enabled": true
|
|
33
|
+
},
|
|
34
|
+
"android-build": {
|
|
35
|
+
"name": "Android 基线构建",
|
|
36
|
+
"required": false,
|
|
37
|
+
"enabled": false
|
|
38
|
+
},
|
|
39
|
+
"android-emulator": {
|
|
40
|
+
"name": "Android 模拟器",
|
|
41
|
+
"required": false,
|
|
42
|
+
"enabled": true
|
|
43
|
+
},
|
|
44
|
+
"harmony-project": {
|
|
45
|
+
"name": "HarmonyOS 工程存在或初始化",
|
|
46
|
+
"required": true,
|
|
47
|
+
"enabled": true
|
|
48
|
+
},
|
|
49
|
+
"harmony-sdk": {
|
|
50
|
+
"name": "HarmonyOS SDK 声明根目录",
|
|
51
|
+
"required": false,
|
|
52
|
+
"enabled": true
|
|
53
|
+
},
|
|
54
|
+
"harmony-build": {
|
|
55
|
+
"name": "HarmonyOS 应用 HAP 构建",
|
|
56
|
+
"required": true,
|
|
57
|
+
"enabled": true
|
|
58
|
+
},
|
|
59
|
+
"harmony-device": {
|
|
60
|
+
"name": "HarmonyOS 设备和 Shell",
|
|
61
|
+
"required": true,
|
|
62
|
+
"enabled": true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import path36 from "path";
|
|
5
|
-
import { existsSync as existsSync9, readFileSync as
|
|
5
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync, readdirSync as readdirSync5 } from "fs";
|
|
6
6
|
import { pathToFileURL } from "url";
|
|
7
7
|
|
|
8
8
|
// src/commands/lib/spawn-command.ts
|
|
@@ -3132,7 +3132,7 @@ function runHarmonyTest({ projectRoot, harmonyProject, timeoutMs, testClass = nu
|
|
|
3132
3132
|
}
|
|
3133
3133
|
|
|
3134
3134
|
// src/commands/python-hypium.ts
|
|
3135
|
-
import { existsSync as existsSync5, statSync as statSync3 } from "fs";
|
|
3135
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
|
|
3136
3136
|
import path16 from "path";
|
|
3137
3137
|
var safeTestName = /^[A-Za-z0-9_./-]+$/;
|
|
3138
3138
|
function executableWithArgs(executable, args) {
|
|
@@ -3222,8 +3222,51 @@ function runHarmonyPythonHypiumTest({
|
|
|
3222
3222
|
projectRoot,
|
|
3223
3223
|
timeoutMs
|
|
3224
3224
|
});
|
|
3225
|
+
if (execute.status !== "passed") {
|
|
3226
|
+
return {
|
|
3227
|
+
status: execute.status,
|
|
3228
|
+
key: "harmonyPythonTest",
|
|
3229
|
+
runner: "python",
|
|
3230
|
+
stage: "execute",
|
|
3231
|
+
target,
|
|
3232
|
+
appArtifact: appBuild.artifact,
|
|
3233
|
+
hypiumProject: testProjectRoot,
|
|
3234
|
+
testLists,
|
|
3235
|
+
reportPath: reports,
|
|
3236
|
+
signature,
|
|
3237
|
+
installApp,
|
|
3238
|
+
execute,
|
|
3239
|
+
summary: `Python Hypium \u6267\u884C\u5931\u8D25\uFF0C\u8BF7\u786E\u8BA4\u5DF2\u4E3A ${python} \u5B89\u88C5 hypium\uFF08python -m pip install hypium -U\uFF09`
|
|
3240
|
+
};
|
|
3241
|
+
}
|
|
3242
|
+
const stdoutText = (() => {
|
|
3243
|
+
try {
|
|
3244
|
+
return existsSync5(execute.stdout) ? readFileSync4(execute.stdout, "utf8") : "";
|
|
3245
|
+
} catch {
|
|
3246
|
+
return "";
|
|
3247
|
+
}
|
|
3248
|
+
})();
|
|
3249
|
+
const structuredHypiumResult = pythonHypiumResult({ stdoutText, reportsDir: reports });
|
|
3250
|
+
if (!structuredHypiumResult.valid) {
|
|
3251
|
+
return {
|
|
3252
|
+
status: "failed",
|
|
3253
|
+
key: "harmonyPythonTest",
|
|
3254
|
+
runner: "python",
|
|
3255
|
+
stage: "parse-summary",
|
|
3256
|
+
target,
|
|
3257
|
+
appArtifact: appBuild.artifact,
|
|
3258
|
+
hypiumProject: testProjectRoot,
|
|
3259
|
+
testLists,
|
|
3260
|
+
reportPath: reports,
|
|
3261
|
+
signature,
|
|
3262
|
+
installApp,
|
|
3263
|
+
execute,
|
|
3264
|
+
structuredHypiumResult,
|
|
3265
|
+
summary: `Hypium \u7ED3\u6784\u5316\u7ED3\u679C\u4E0D\u901A\u8FC7: ${structuredHypiumResult.summary}`
|
|
3266
|
+
};
|
|
3267
|
+
}
|
|
3225
3268
|
return {
|
|
3226
|
-
status:
|
|
3269
|
+
status: "passed",
|
|
3227
3270
|
key: "harmonyPythonTest",
|
|
3228
3271
|
runner: "python",
|
|
3229
3272
|
stage: "execute",
|
|
@@ -3235,9 +3278,123 @@ function runHarmonyPythonHypiumTest({
|
|
|
3235
3278
|
signature,
|
|
3236
3279
|
installApp,
|
|
3237
3280
|
execute,
|
|
3238
|
-
|
|
3281
|
+
structuredHypiumResult,
|
|
3282
|
+
tests: structuredHypiumResult,
|
|
3283
|
+
summary: `HarmonyOS \u5E94\u7528\u6784\u5EFA\u3001\u5B89\u88C5\u548C Python Hypium \u6D4B\u8BD5\u6267\u884C\u6210\u529F\uFF08${structuredHypiumResult.passed}/${structuredHypiumResult.total}\uFF09`
|
|
3239
3284
|
};
|
|
3240
3285
|
}
|
|
3286
|
+
function junitAttribute(tag, name) {
|
|
3287
|
+
const match = new RegExp(`\\b${name}="(-?\\d+)"`).exec(tag);
|
|
3288
|
+
return match ? Number(match[1]) : 0;
|
|
3289
|
+
}
|
|
3290
|
+
function aggregateJunitXmlResults(xmlTexts) {
|
|
3291
|
+
const suiteTags = [];
|
|
3292
|
+
let wrapperTag = "";
|
|
3293
|
+
const executedCases = [];
|
|
3294
|
+
for (const xml of xmlTexts) {
|
|
3295
|
+
const text = String(xml ?? "");
|
|
3296
|
+
wrapperTag = wrapperTag || (/<testsuites\b[^>]*>/.exec(text)?.[0] ?? "");
|
|
3297
|
+
for (const match of text.matchAll(/<testsuite\b[^>]*>/g)) suiteTags.push(match[0]);
|
|
3298
|
+
for (const match of text.matchAll(/<testcase\b[^>]*>/g)) {
|
|
3299
|
+
const classname = /\bclassname="([^"]*)"/.exec(match[0])?.[1];
|
|
3300
|
+
const name = /\bname="([^"]*)"/.exec(match[0])?.[1];
|
|
3301
|
+
if (name) executedCases.push(`${classname ?? "suite"}#${name}`);
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
if (!wrapperTag && !suiteTags.length) return null;
|
|
3305
|
+
const sources = wrapperTag ? [wrapperTag] : suiteTags;
|
|
3306
|
+
const sum = (attribute) => sources.reduce((total2, tag) => total2 + junitAttribute(tag, attribute), 0);
|
|
3307
|
+
const total = sum("tests");
|
|
3308
|
+
const failed = sum("failures");
|
|
3309
|
+
const errors = sum("errors");
|
|
3310
|
+
const ignored = sum("ignored") + sum("skipped");
|
|
3311
|
+
const disabled = sum("disabled");
|
|
3312
|
+
const unavailable = sum("unavailable");
|
|
3313
|
+
const passed = Math.max(total - failed - errors - ignored - disabled - unavailable, 0);
|
|
3314
|
+
const problems = [];
|
|
3315
|
+
if (total <= 0) problems.push("zero tests");
|
|
3316
|
+
if (failed) problems.push(`failed ${failed}`);
|
|
3317
|
+
if (errors) problems.push(`errors ${errors}`);
|
|
3318
|
+
if (ignored) problems.push(`ignored ${ignored}`);
|
|
3319
|
+
if (disabled) problems.push(`disabled ${disabled}`);
|
|
3320
|
+
if (unavailable) problems.push(`unavailable ${unavailable}`);
|
|
3321
|
+
return {
|
|
3322
|
+
valid: problems.length === 0,
|
|
3323
|
+
total,
|
|
3324
|
+
passed,
|
|
3325
|
+
failed,
|
|
3326
|
+
errors,
|
|
3327
|
+
ignored,
|
|
3328
|
+
disabled,
|
|
3329
|
+
summary: problems.length ? `Hypium rejected: ${problems.join(", ")}` : `Hypium ${passed}/${total} passed`,
|
|
3330
|
+
executedCases
|
|
3331
|
+
};
|
|
3332
|
+
}
|
|
3333
|
+
function pythonHypiumResult({ stdoutText, reportsDir }) {
|
|
3334
|
+
const empty2 = (summary) => ({
|
|
3335
|
+
valid: false,
|
|
3336
|
+
total: 0,
|
|
3337
|
+
passed: 0,
|
|
3338
|
+
failed: 0,
|
|
3339
|
+
errors: 0,
|
|
3340
|
+
ignored: 0,
|
|
3341
|
+
disabled: 0,
|
|
3342
|
+
executedCases: [],
|
|
3343
|
+
summary
|
|
3344
|
+
});
|
|
3345
|
+
const stdoutMatch = /Tests run:\s*(\d+)\s*,\s*Failure:\s*(\d+)\s*,\s*Error:\s*(\d+)\s*,\s*(?:Pass(?:ed)?:\s*(\d+)\s*,\s*)?Ignore:\s*(\d+)/.exec(String(stdoutText ?? ""));
|
|
3346
|
+
if (stdoutMatch) {
|
|
3347
|
+
const total = Number(stdoutMatch[1]);
|
|
3348
|
+
const failed = Number(stdoutMatch[2]);
|
|
3349
|
+
const errors = Number(stdoutMatch[3]);
|
|
3350
|
+
const reportedPass = stdoutMatch[4] !== void 0 ? Number(stdoutMatch[4]) : null;
|
|
3351
|
+
const ignored = Number(stdoutMatch[5]);
|
|
3352
|
+
const passed = reportedPass ?? Math.max(total - failed - errors - ignored, 0);
|
|
3353
|
+
const problems = [];
|
|
3354
|
+
if (total <= 0) problems.push("zero tests");
|
|
3355
|
+
if (failed) problems.push(`failed ${failed}`);
|
|
3356
|
+
if (errors) problems.push(`errors ${errors}`);
|
|
3357
|
+
if (ignored) problems.push(`ignored ${ignored}`);
|
|
3358
|
+
return {
|
|
3359
|
+
valid: problems.length === 0,
|
|
3360
|
+
total,
|
|
3361
|
+
passed,
|
|
3362
|
+
failed,
|
|
3363
|
+
errors,
|
|
3364
|
+
ignored,
|
|
3365
|
+
disabled: 0,
|
|
3366
|
+
executedCases: [],
|
|
3367
|
+
summary: problems.length ? `Hypium rejected: ${problems.join(", ")}` : `Hypium ${passed}/${total} passed`
|
|
3368
|
+
};
|
|
3369
|
+
}
|
|
3370
|
+
const xmlTexts = [];
|
|
3371
|
+
const aggregatePath = path16.join(reportsDir, "summary_report.xml");
|
|
3372
|
+
if (existsSync5(aggregatePath)) {
|
|
3373
|
+
try {
|
|
3374
|
+
xmlTexts.push(readFileSync4(aggregatePath, "utf8"));
|
|
3375
|
+
} catch {
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
if (existsSync5(reportsDir)) {
|
|
3379
|
+
try {
|
|
3380
|
+
const stamped = readdirSync3(reportsDir).filter((entry) => /^\d+$/.test(entry)).sort().reverse();
|
|
3381
|
+
for (const stamp of stamped) {
|
|
3382
|
+
const summaryPath = path16.join(reportsDir, stamp, "result", "summary.xml");
|
|
3383
|
+
if (existsSync5(summaryPath)) {
|
|
3384
|
+
try {
|
|
3385
|
+
xmlTexts.push(readFileSync4(summaryPath, "utf8"));
|
|
3386
|
+
} catch {
|
|
3387
|
+
}
|
|
3388
|
+
break;
|
|
3389
|
+
}
|
|
3390
|
+
}
|
|
3391
|
+
} catch {
|
|
3392
|
+
}
|
|
3393
|
+
}
|
|
3394
|
+
const aggregated = aggregateJunitXmlResults(xmlTexts);
|
|
3395
|
+
if (aggregated) return aggregated;
|
|
3396
|
+
return empty2(`Hypium did not produce a machine-readable test summary (stdout or ${reportsDir})`);
|
|
3397
|
+
}
|
|
3241
3398
|
|
|
3242
3399
|
// src/commands/detect-harmony-sdk.ts
|
|
3243
3400
|
import fs14 from "fs";
|
|
@@ -3356,12 +3513,12 @@ function parseProperties(text) {
|
|
|
3356
3513
|
}
|
|
3357
3514
|
|
|
3358
3515
|
// src/commands/upgrade.ts
|
|
3359
|
-
import { readFileSync as
|
|
3516
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
3360
3517
|
import path18 from "path";
|
|
3361
3518
|
function readPackageMetadata(packageRoot) {
|
|
3362
3519
|
if (!packageRoot) throw new Error("Cannot locate droid2hmos package metadata");
|
|
3363
3520
|
const packagePath = path18.join(packageRoot, "package.json");
|
|
3364
|
-
const metadata = JSON.parse(
|
|
3521
|
+
const metadata = JSON.parse(readFileSync5(packagePath, "utf8"));
|
|
3365
3522
|
if (!metadata.name || !metadata.version) throw new Error(`Invalid package metadata: ${packagePath}`);
|
|
3366
3523
|
return metadata;
|
|
3367
3524
|
}
|
|
@@ -4083,7 +4240,7 @@ async function runPreflight(options) {
|
|
|
4083
4240
|
|
|
4084
4241
|
// src/commands/deveco-auth-login.ts
|
|
4085
4242
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
4086
|
-
import { closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as
|
|
4243
|
+
import { closeSync as closeSync3, existsSync as existsSync6, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4087
4244
|
import path24 from "path";
|
|
4088
4245
|
import { setTimeout as delay2 } from "timers/promises";
|
|
4089
4246
|
var MANAGED_LOGIN_SERVICE_NAME = "devecocli-auth";
|
|
@@ -4115,7 +4272,7 @@ function isAlive2(pid) {
|
|
|
4115
4272
|
}
|
|
4116
4273
|
function readPidFile(pidFile) {
|
|
4117
4274
|
try {
|
|
4118
|
-
const pid = Number.parseInt(
|
|
4275
|
+
const pid = Number.parseInt(readFileSync6(pidFile, "utf8").trim(), 10);
|
|
4119
4276
|
return Number.isInteger(pid) ? pid : null;
|
|
4120
4277
|
} catch {
|
|
4121
4278
|
return null;
|
|
@@ -4123,7 +4280,7 @@ function readPidFile(pidFile) {
|
|
|
4123
4280
|
}
|
|
4124
4281
|
function tailFile(file, maxChars) {
|
|
4125
4282
|
try {
|
|
4126
|
-
const content =
|
|
4283
|
+
const content = readFileSync6(file, "utf8").trim();
|
|
4127
4284
|
return content.length > maxChars ? `\u2026${content.slice(-maxChars)}` : content;
|
|
4128
4285
|
} catch {
|
|
4129
4286
|
return "";
|
|
@@ -4214,7 +4371,7 @@ async function killOrphanDevEcoCliLogins(options) {
|
|
|
4214
4371
|
return { killedPids, managedPid: managedPid ?? null };
|
|
4215
4372
|
}
|
|
4216
4373
|
function runDetachedDevEcoAuthHost(requestPath) {
|
|
4217
|
-
const request = JSON.parse(
|
|
4374
|
+
const request = JSON.parse(readFileSync6(requestPath, "utf8"));
|
|
4218
4375
|
mkdirSync3(path24.dirname(request.stdout), { recursive: true });
|
|
4219
4376
|
mkdirSync3(path24.dirname(request.stderr), { recursive: true });
|
|
4220
4377
|
const stdout = openSync3(request.stdout, "a");
|
|
@@ -4272,7 +4429,7 @@ function runDetachedDevEcoAuthHost(requestPath) {
|
|
|
4272
4429
|
function findLoginUrl(state) {
|
|
4273
4430
|
for (const file of [state.stdoutLog, state.stderrLog]) {
|
|
4274
4431
|
try {
|
|
4275
|
-
const match =
|
|
4432
|
+
const match = readFileSync6(file, "utf8").match(LOGIN_URL_PATTERN);
|
|
4276
4433
|
if (match) return match[0];
|
|
4277
4434
|
} catch {
|
|
4278
4435
|
}
|
|
@@ -4359,10 +4516,10 @@ async function managedDevEcoCliLogin(options) {
|
|
|
4359
4516
|
};
|
|
4360
4517
|
}
|
|
4361
4518
|
if (pid2 === null && existsSync6(state.exitFile)) {
|
|
4362
|
-
return failure(`\u767B\u5F55\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08exit ${
|
|
4519
|
+
return failure(`\u767B\u5F55\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08exit ${readFileSync6(state.exitFile, "utf8").trim()}\uFF09: ${tailFile(state.stderrLog, 800) || tailFile(state.stdoutLog, 800) || "\u65E0\u8F93\u51FA"}`);
|
|
4363
4520
|
}
|
|
4364
4521
|
if (pid2 !== null && !isAlive2(pid2) && !existsSync6(state.pidFile)) {
|
|
4365
|
-
return failure(`\u767B\u5F55\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08exit ${existsSync6(state.exitFile) ?
|
|
4522
|
+
return failure(`\u767B\u5F55\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08exit ${existsSync6(state.exitFile) ? readFileSync6(state.exitFile, "utf8").trim() : "unknown"}\uFF09: ${tailFile(state.stderrLog, 800) || tailFile(state.stdoutLog, 800) || "\u65E0\u8F93\u51FA"}`);
|
|
4366
4523
|
}
|
|
4367
4524
|
const remainingSeconds = Math.round((deadline - Date.now()) / 1e3);
|
|
4368
4525
|
if (lastCountdownSeconds - remainingSeconds >= 30) {
|
|
@@ -4791,13 +4948,13 @@ Select a scenario with query parameter \`?scenario=empty\` or header \`x-droid2h
|
|
|
4791
4948
|
}
|
|
4792
4949
|
|
|
4793
4950
|
// src/commands/logs.ts
|
|
4794
|
-
import { existsSync as existsSync7, readFileSync as
|
|
4951
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as readdirSync4 } from "fs";
|
|
4795
4952
|
import path28 from "path";
|
|
4796
4953
|
function loadRecords(projectRoot) {
|
|
4797
4954
|
const directory = path28.join(migrationDirectory(projectRoot), "logs", "daily");
|
|
4798
4955
|
if (!existsSync7(directory)) return [];
|
|
4799
|
-
return
|
|
4800
|
-
(file) =>
|
|
4956
|
+
return readdirSync4(directory).filter((file) => file.endsWith(".jsonl")).sort().flatMap(
|
|
4957
|
+
(file) => readFileSync7(path28.join(directory, file), "utf8").split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line))
|
|
4801
4958
|
);
|
|
4802
4959
|
}
|
|
4803
4960
|
function queryCommandLogs(project, action, value) {
|
|
@@ -8311,7 +8468,7 @@ Usage:
|
|
|
8311
8468
|
droid2hmos config <init|validate> [project] [--harmony-project <path>]
|
|
8312
8469
|
droid2hmos build harmony [project] [--timeout-ms <ms>]
|
|
8313
8470
|
droid2hmos test harmony [project] [--runner arkts] (--class <class> [--case <case>] | --all) [--target <serial>] [--case-timeout-ms <ms>] [--ref <report-ref>...] [--timeout-ms <ms>]
|
|
8314
|
-
droid2hmos test harmony [project] --runner python --hypium-project <path> --test-list <name
|
|
8471
|
+
droid2hmos test harmony [project] --runner python --hypium-project <path> (--test-list <name>...|--all) [--target <serial>] [--python <path>] [--report-path <path>] [--ref <report-ref>...] [--timeout-ms <ms>]
|
|
8315
8472
|
droid2hmos report [project] [--require-complete]
|
|
8316
8473
|
droid2hmos report <init|validate|render> [project] [--require-complete]
|
|
8317
8474
|
droid2hmos report update [project] --ref <ref> [--status <status>] [--harmony-file <path>...] [--android-source <path>...] [--evidence <path>...] [--difference <text>|--clear-difference]
|
|
@@ -8494,7 +8651,7 @@ async function runCli(argv, runtime) {
|
|
|
8494
8651
|
const guardResult = guard("analyze:harmony", project);
|
|
8495
8652
|
const configPath = path36.join(migrationDirectory(projectRoot), "config.json");
|
|
8496
8653
|
if (!existsSync9(configPath)) throw new Error(`Migration config not found: ${configPath}`);
|
|
8497
|
-
const config = JSON.parse(
|
|
8654
|
+
const config = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
8498
8655
|
const configuredHarmony = config.harmonyProject ?? defaultHarmonyProjectPath(projectRoot);
|
|
8499
8656
|
const harmonyProject = path36.isAbsolute(configuredHarmony) ? configuredHarmony : path36.resolve(projectRoot, configuredHarmony);
|
|
8500
8657
|
const forwarded = ["build", harmonyProject, "--platform", "harmony"];
|
|
@@ -8655,7 +8812,7 @@ async function runCli(argv, runtime) {
|
|
|
8655
8812
|
const configPath = path36.join(migrationDirectory(projectRoot), "config.json");
|
|
8656
8813
|
if (!existsSync9(configPath)) throw new Error(`Migration config not found: ${configPath}`);
|
|
8657
8814
|
const guardResult = guard("build:harmony", projectRoot);
|
|
8658
|
-
const config = JSON.parse(
|
|
8815
|
+
const config = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
8659
8816
|
const configuredHarmony = config.harmonyProject ?? defaultHarmonyProjectPath(projectRoot);
|
|
8660
8817
|
const harmonyProject = path36.isAbsolute(configuredHarmony) ? configuredHarmony : path36.resolve(projectRoot, configuredHarmony);
|
|
8661
8818
|
let result;
|
|
@@ -8690,17 +8847,24 @@ async function runCli(argv, runtime) {
|
|
|
8690
8847
|
if (!Number.isFinite(caseTimeoutMs) || caseTimeoutMs <= 0) throw new CliError("--case-timeout-ms must be a positive number");
|
|
8691
8848
|
const configPath = path36.join(migrationDirectory(projectRoot), "config.json");
|
|
8692
8849
|
if (!existsSync9(configPath)) throw new Error(`Migration config not found: ${configPath}`);
|
|
8693
|
-
const config = JSON.parse(
|
|
8850
|
+
const config = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
8694
8851
|
const configuredHarmony = config.harmonyProject ?? defaultHarmonyProjectPath(projectRoot);
|
|
8695
8852
|
const harmonyProject = path36.isAbsolute(configuredHarmony) ? configuredHarmony : path36.resolve(projectRoot, configuredHarmony);
|
|
8696
8853
|
let result;
|
|
8697
8854
|
try {
|
|
8698
8855
|
if (runner === "python") {
|
|
8699
|
-
if (testClass || testCase
|
|
8856
|
+
if (testClass || testCase) throw new CliError("Python Hypium uses --test-list instead of --class or --case");
|
|
8700
8857
|
const hypiumProject = optionValue(args, "--hypium-project");
|
|
8701
|
-
const testLists = optionValues(args, "--test-list").flatMap((value) => value.split(";")).map((value) => value.trim()).filter(Boolean);
|
|
8702
8858
|
if (!hypiumProject) throw new CliError("Python Hypium requires --hypium-project");
|
|
8703
|
-
|
|
8859
|
+
let testLists = optionValues(args, "--test-list").flatMap((value) => value.split(";")).map((value) => value.trim()).filter(Boolean);
|
|
8860
|
+
if (fullRun) {
|
|
8861
|
+
const projectDir = path36.isAbsolute(hypiumProject) ? path36.resolve(hypiumProject) : path36.resolve(projectRoot, hypiumProject);
|
|
8862
|
+
const testcaseDir = path36.join(projectDir, "testcases");
|
|
8863
|
+
testLists = existsSync9(testcaseDir) ? readdirSync5(testcaseDir).filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/i, "")).sort() : [];
|
|
8864
|
+
if (!testLists.length) throw new CliError(`Python Hypium \u5168\u91CF\u56DE\u5F52\u672A\u53D1\u73B0\u7528\u4F8B\u914D\u7F6E\uFF08${testcaseDir}/*.json\uFF09`);
|
|
8865
|
+
} else if (!testLists.length) {
|
|
8866
|
+
throw new CliError("Python Hypium requires at least one --test-list");
|
|
8867
|
+
}
|
|
8704
8868
|
result = runHarmonyPythonHypiumTest({
|
|
8705
8869
|
projectRoot,
|
|
8706
8870
|
harmonyProject,
|
|
@@ -8805,7 +8969,7 @@ async function runCli(argv, runtime) {
|
|
|
8805
8969
|
const projectRoot = path36.resolve(project);
|
|
8806
8970
|
const configPath = path36.join(migrationDirectory(projectRoot), "config.json");
|
|
8807
8971
|
if (!existsSync9(configPath)) throw new Error(`Migration config not found: ${configPath}`);
|
|
8808
|
-
const config = JSON.parse(
|
|
8972
|
+
const config = JSON.parse(readFileSync8(configPath, "utf8"));
|
|
8809
8973
|
const configuredHarmony = config.harmonyProject ?? defaultHarmonyProjectPath(projectRoot);
|
|
8810
8974
|
const harmonyProject = path36.isAbsolute(configuredHarmony) ? configuredHarmony : path36.resolve(projectRoot, configuredHarmony);
|
|
8811
8975
|
const timeoutMs = Number(optionValue(args, "--timeout-ms") ?? 5 * 60 * 1e3);
|
|
@@ -8853,7 +9017,7 @@ async function runCli(argv, runtime) {
|
|
|
8853
9017
|
let execution;
|
|
8854
9018
|
if (before.status !== "passed") execution = { status: "failed", skipped: true, summary: "Baseline evidence capture failed; interaction was not executed" };
|
|
8855
9019
|
else {
|
|
8856
|
-
const config = JSON.parse(
|
|
9020
|
+
const config = JSON.parse(readFileSync8(path36.join(migrationDirectory(projectRoot), "config.json"), "utf8"));
|
|
8857
9021
|
const harmonyProject = path36.isAbsolute(config.harmonyProject) ? config.harmonyProject : path36.resolve(projectRoot, config.harmonyProject);
|
|
8858
9022
|
const testClass = optionValue(args, "--class") ?? null;
|
|
8859
9023
|
const testCase = optionValue(args, "--case") ?? null;
|
|
@@ -8992,7 +9156,7 @@ var invokedHref = (() => {
|
|
|
8992
9156
|
if (invokedHref && invokedHref === entryHref) {
|
|
8993
9157
|
const argv = process.argv.slice(2);
|
|
8994
9158
|
const runtime = resolveRuntimePaths(import.meta.url);
|
|
8995
|
-
const version = runtime.packageRoot && existsSync9(path36.join(runtime.packageRoot, "package.json")) ? JSON.parse(
|
|
9159
|
+
const version = runtime.packageRoot && existsSync9(path36.join(runtime.packageRoot, "package.json")) ? JSON.parse(readFileSync8(path36.join(runtime.packageRoot, "package.json"), "utf8")).version ?? "unknown" : "unknown";
|
|
8996
9160
|
const excluded = /* @__PURE__ */ new Set(["help", "-h", "--help", "status", "internal", "dev", "logs"]);
|
|
8997
9161
|
const readOnlyTaskQuery = argv[0] === "task" && ["status", "next", "show"].includes(argv[1] ?? "");
|
|
8998
9162
|
Promise.resolve(excluded.has(argv[0] ?? "help") || readOnlyTaskQuery || process.env.DROID2HMOS_DISABLE_LOGGING === "1" ? runCli(argv, runtime) : withCommandLog(argv, version, () => runCli(argv, runtime))).then((exitCode) => {
|