@azrico/azcli 1.2.1 → 1.2.4
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/README.md +5 -0
- package/dist/cli/create-cli.js +2 -0
- package/dist/cli/create-cli.js.map +1 -1
- package/dist/features/verify-changes/command.js +3 -1
- package/dist/features/verify-changes/command.js.map +1 -1
- package/dist/features/verify-changes/config.js +34 -2
- package/dist/features/verify-changes/config.js.map +1 -1
- package/dist/features/worktree/command.js +55 -0
- package/dist/features/worktree/command.js.map +1 -0
- package/dist/features/worktree/config.js +115 -0
- package/dist/features/worktree/config.js.map +1 -0
- package/dist/features/worktree/git.js +62 -0
- package/dist/features/worktree/git.js.map +1 -0
- package/dist/features/worktree/start.js +156 -0
- package/dist/features/worktree/start.js.map +1 -0
- package/dist/features/worktree/status.js +50 -0
- package/dist/features/worktree/status.js.map +1 -0
- package/dist/features/worktree/sync.js +107 -0
- package/dist/features/worktree/sync.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -33,7 +33,12 @@ With Yarn available on PATH, the equivalent commands are `yarn install --immutab
|
|
|
33
33
|
| `transcripts <claude\|codex>` | Export sessions to Markdown with an `index.json`. |
|
|
34
34
|
| `optimize-transcripts <claude\|codex>` | Prepare a transcript snapshot and run the selected analysis agent. |
|
|
35
35
|
| `verify-changes` | Run the checks from `.azcli/verify.json` that match files changed since the base ref. Reports `passed`, `failed`, or `not-run`; exits 1 on failure (`--strict` also on not-run). `--profile`, `--base`, `--json`. |
|
|
36
|
+
| `worktree start <path>` | Install the worktree's locked dependencies, pick a free port above the configured default, run the dev server detached, and wait for it to answer or exit. Reports URL, pid, compile result, and log file (inside the git dir). Fails at once if the process exits; `--timeout` bounds the wait. `--page`, `--port`, `--skip-install`. |
|
|
37
|
+
| `worktree status <path>` | Branch tips and dirty files of the worktree and the target, ahead/behind counts, whether the branch is merged, and dependency manifests changed on each side. |
|
|
38
|
+
| `worktree sync <path> --direction in|out|both` | Merge the target into the worktree branch (`in`) and/or the branch into the target (`out`). Refuses dirty trees; on conflict stops with the merge in progress and writes base/ours/theirs copies under the git dir, flagging whitespace-only conflicts. Never resolves conflicts; exits 1 on conflict. |
|
|
36
39
|
|
|
40
|
+
Worktree commands read `.azcli/worktree.json` from the worktree, else from `--project`; run `azcli worktree start --help` for the format. All three accept `--target` and `--json`.
|
|
41
|
+
|
|
37
42
|
Project commands accept `--path` to select a working directory. Build, update, clean, and publish accept `--type`, direct flags such as `--python`, and exclusions such as `--nopython` or `--no-python`. Use `--quiet` to suppress progress. Errors go to stderr and cause a nonzero exit status.
|
|
38
43
|
|
|
39
44
|
External tools must already be available on PATH. Commands run with explicit argument arrays and working directories. On Windows, standard Node and Composer `.cmd`/`.bat` shims are resolved to their entry points without a command shell. Custom batch launchers are rejected with an explanatory error.
|
package/dist/cli/create-cli.js
CHANGED
|
@@ -13,6 +13,7 @@ const command_5 = __importDefault(require("../features/package/command"));
|
|
|
13
13
|
const command_6 = __importDefault(require("../features/transcripts/command"));
|
|
14
14
|
const command_7 = __importDefault(require("../features/optimize-transcripts/command"));
|
|
15
15
|
const command_8 = __importDefault(require("../features/verify-changes/command"));
|
|
16
|
+
const command_9 = __importDefault(require("../features/worktree/command"));
|
|
16
17
|
const commands_1 = require("../features/yarn/commands");
|
|
17
18
|
function createCli(args) {
|
|
18
19
|
return (0, yargs_1.default)(args)
|
|
@@ -27,6 +28,7 @@ function createCli(args) {
|
|
|
27
28
|
.command(command_6.default)
|
|
28
29
|
.command(command_7.default)
|
|
29
30
|
.command(command_8.default)
|
|
31
|
+
.command(command_9.default)
|
|
30
32
|
.command(commands_1.installCommand)
|
|
31
33
|
.command(commands_1.buildCommand)
|
|
32
34
|
.command(commands_1.testCommand)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-cli.js","sourceRoot":"","sources":["../../src/cli/create-cli.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAChC,wEAA8C;AAC9C,wEAA8C;AAC9C,yEAAgD;AAChD,0EAAkD;AAClD,0EAAmD;AACnD,8EAA0D;AAC1D,uFAAgE;AAChE,iFAA+D;AAC/D,wDAAsF;AAEtF,SAAgB,SAAS,CAAC,IAAc;IACvC,OAAO,IAAA,eAAK,EAAC,IAAI,CAAC;SAChB,UAAU,CAAC,OAAO,CAAC;SACnB,KAAK,CAAC,+BAA+B,CAAC;SACtC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,yCAAyC,EAAE,CAAC;SAC5G,OAAO,CAAC,iBAAK,CAAC;SACd,OAAO,CAAC,iBAAK,CAAC;SACd,OAAO,CAAC,iBAAM,CAAC;SACf,OAAO,CAAC,iBAAO,CAAC;SAChB,OAAO,CAAC,iBAAQ,CAAC;SACjB,OAAO,CAAC,iBAAW,CAAC;SACpB,OAAO,CAAC,iBAAQ,CAAC;SACjB,OAAO,CAAC,iBAAa,CAAC;SACtB,OAAO,CAAC,yBAAc,CAAC;SACvB,OAAO,CAAC,uBAAY,CAAC;SACrB,OAAO,CAAC,sBAAW,CAAC;SACpB,aAAa,CAAC,CAAC,CAAC;SAChB,MAAM,EAAE;SACR,IAAI,EAAE;SACN,WAAW,CAAC,KAAK,CAAC;SAClB,IAAI,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;
|
|
1
|
+
{"version":3,"file":"create-cli.js","sourceRoot":"","sources":["../../src/cli/create-cli.ts"],"names":[],"mappings":";;;;;;AAAA,wDAAgC;AAChC,wEAA8C;AAC9C,wEAA8C;AAC9C,yEAAgD;AAChD,0EAAkD;AAClD,0EAAmD;AACnD,8EAA0D;AAC1D,uFAAgE;AAChE,iFAA+D;AAC/D,2EAAoD;AACpD,wDAAsF;AAEtF,SAAgB,SAAS,CAAC,IAAc;IACvC,OAAO,IAAA,eAAK,EAAC,IAAI,CAAC;SAChB,UAAU,CAAC,OAAO,CAAC;SACnB,KAAK,CAAC,+BAA+B,CAAC;SACtC,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,yCAAyC,EAAE,CAAC;SAC5G,OAAO,CAAC,iBAAK,CAAC;SACd,OAAO,CAAC,iBAAK,CAAC;SACd,OAAO,CAAC,iBAAM,CAAC;SACf,OAAO,CAAC,iBAAO,CAAC;SAChB,OAAO,CAAC,iBAAQ,CAAC;SACjB,OAAO,CAAC,iBAAW,CAAC;SACpB,OAAO,CAAC,iBAAQ,CAAC;SACjB,OAAO,CAAC,iBAAa,CAAC;SACtB,OAAO,CAAC,iBAAQ,CAAC;SACjB,OAAO,CAAC,yBAAc,CAAC;SACvB,OAAO,CAAC,uBAAY,CAAC;SACrB,OAAO,CAAC,sBAAW,CAAC;SACpB,aAAa,CAAC,CAAC,CAAC;SAChB,MAAM,EAAE;SACR,IAAI,EAAE;SACN,WAAW,CAAC,KAAK,CAAC;SAClB,IAAI,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAtBD,8BAsBC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const logger_1 = require("../../core/logger");
|
|
4
|
+
const config_1 = require("./config");
|
|
4
5
|
const report_1 = require("./report");
|
|
5
6
|
const verify_1 = require("./verify");
|
|
6
7
|
const command = {
|
|
@@ -11,7 +12,8 @@ const command = {
|
|
|
11
12
|
.option('base', { type: 'string', describe: 'Compare against this ref (default: config base, else main/master)' })
|
|
12
13
|
.option('profile', { type: 'string', array: true, describe: 'Profiles from .azcli/verify.json (default: all)' })
|
|
13
14
|
.option('json', { type: 'boolean', describe: 'Print the full report as JSON' })
|
|
14
|
-
.option('strict', { type: 'boolean', describe: 'Treat checks that were not run as failures' })
|
|
15
|
+
.option('strict', { type: 'boolean', describe: 'Treat checks that were not run as failures' })
|
|
16
|
+
.epilog(config_1.configHelp),
|
|
15
17
|
handler: async (args) => {
|
|
16
18
|
const report = await (0, verify_1.verifyChanges)(args);
|
|
17
19
|
if (args.json)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/features/verify-changes/command.ts"],"names":[],"mappings":";;AACA,8CAAgD;AAChD,qCAAwD;AACxD,qCAAyC;AASzC,MAAM,OAAO,GAA4C;IACxD,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,wDAAwD;IAClE,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;SACnB,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;SACjE,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,mEAAmE,EAAE,CAAC;SACjH,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,iDAAiD,EAAE,CAAC;SAC/G,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,+BAA+B,EAAE,CAAC;SAC9E,MAAM,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,4CAA4C,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/features/verify-changes/command.ts"],"names":[],"mappings":";;AACA,8CAAgD;AAChD,qCAAsC;AACtC,qCAAwD;AACxD,qCAAyC;AASzC,MAAM,OAAO,GAA4C;IACxD,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,wDAAwD;IAClE,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;SACnB,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;SACjE,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,mEAAmE,EAAE,CAAC;SACjH,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,iDAAiD,EAAE,CAAC;SAC/G,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,+BAA+B,EAAE,CAAC;SAC9E,MAAM,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,4CAA4C,EAAE,CAAC;SAC7F,MAAM,CAAC,mBAAU,CAAC;IACpB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,MAAM,GAAG,MAAM,IAAA,sBAAa,EAAC,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;YACvD,IAAA,oBAAW,EAAC,IAAA,qBAAY,EAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACnE,OAAO,CAAC,QAAQ,GAAG,IAAA,uBAAc,EAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,CAAC;CACD,CAAC;AACF,kBAAe,OAAO,CAAC"}
|
|
@@ -3,11 +3,43 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.loadConfig = exports.parseConfig = exports.configFile = void 0;
|
|
6
|
+
exports.loadConfig = exports.parseConfig = exports.configHelp = exports.configFile = void 0;
|
|
7
7
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const json_1 = require("../../core/json");
|
|
10
10
|
exports.configFile = node_path_1.default.join('.azcli', 'verify.json');
|
|
11
|
+
exports.configHelp = `Config file: .azcli/verify.json in the project root (JSON). Example:
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
"base": "master",
|
|
15
|
+
"profiles": {
|
|
16
|
+
"web": [
|
|
17
|
+
{
|
|
18
|
+
"name": "typescript",
|
|
19
|
+
"command": "yarn",
|
|
20
|
+
"args": ["tsc", "--noEmit"],
|
|
21
|
+
"cwd": "web",
|
|
22
|
+
"paths": ["web/**/*.ts"]
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
Fields:
|
|
29
|
+
base optional. Ref to compare against. Default: first existing of
|
|
30
|
+
origin/main, origin/master, main, master, else HEAD.
|
|
31
|
+
profiles required. Profile name -> array of checks. Pick with --profile.
|
|
32
|
+
name required. Label shown in the report.
|
|
33
|
+
command required. Executable on PATH; run without a shell.
|
|
34
|
+
args optional. Array of strings, one entry per argument.
|
|
35
|
+
cwd optional. Directory relative to the project root, inside it.
|
|
36
|
+
paths optional. Globs relative to the project root: * stays within a
|
|
37
|
+
folder, ** spans folders, ? is one character. Omit to always run.
|
|
38
|
+
|
|
39
|
+
A check runs only if a file changed since the base (committed, staged,
|
|
40
|
+
unstaged, or untracked) matches its paths. Each check ends as passed, failed
|
|
41
|
+
(nonzero exit), or not-run (no matching changes, or the command could not
|
|
42
|
+
start). Exit code is 1 if any check failed; --strict also fails on not-run.`;
|
|
11
43
|
function stringArray(value, label) {
|
|
12
44
|
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string'))
|
|
13
45
|
throw new Error(`${label} must be an array of strings`);
|
|
@@ -45,7 +77,7 @@ exports.parseConfig = parseConfig;
|
|
|
45
77
|
function loadConfig(root) {
|
|
46
78
|
const file = node_path_1.default.join(root, exports.configFile);
|
|
47
79
|
if (!node_fs_1.default.existsSync(file))
|
|
48
|
-
throw new Error(`Missing ${exports.configFile} in ${root}
|
|
80
|
+
throw new Error(`Missing ${exports.configFile} in ${root}. Run "azcli verify-changes --help" to see the file format.`);
|
|
49
81
|
let parsed;
|
|
50
82
|
try {
|
|
51
83
|
parsed = JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/features/verify-changes/config.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAyB;AACzB,0DAA6B;AAC7B,0CAAqD;AAExC,QAAA,UAAU,GAAG,mBAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/features/verify-changes/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const logger_1 = require("../../core/logger");
|
|
4
|
+
const config_1 = require("./config");
|
|
5
|
+
const start_1 = require("./start");
|
|
6
|
+
const status_1 = require("./status");
|
|
7
|
+
const sync_1 = require("./sync");
|
|
8
|
+
function print(args, value, text) {
|
|
9
|
+
if (args.json)
|
|
10
|
+
console.log(JSON.stringify(value, null, 2));
|
|
11
|
+
else
|
|
12
|
+
(0, logger_1.showMessage)(text, 'text', false);
|
|
13
|
+
}
|
|
14
|
+
const command = {
|
|
15
|
+
command: 'worktree <action> <worktree>',
|
|
16
|
+
describe: 'Start a dev server in, inspect, or merge a git worktree',
|
|
17
|
+
builder: (cli) => cli
|
|
18
|
+
.positional('action', { choices: ['start', 'status', 'sync'], type: 'string', demandOption: true, describe: 'start: install, then run the dev server; status: branch and dependency overview; sync: merge in the requested direction' })
|
|
19
|
+
.positional('worktree', { type: 'string', demandOption: true, describe: 'Worktree directory' })
|
|
20
|
+
.option('project', { type: 'string', describe: 'Project directory used when the worktree has no .azcli/worktree.json' })
|
|
21
|
+
.option('target', { type: 'string', describe: 'Branch to compare with or merge (default: "target" in config)' })
|
|
22
|
+
.option('direction', { choices: ['in', 'out', 'both'], type: 'string', describe: 'sync only. in: merge target into the worktree branch; out: merge the worktree branch into the target' })
|
|
23
|
+
.option('port', { type: 'number', describe: 'start only. Port to use (default: first free port above the configured default)' })
|
|
24
|
+
.option('page', { type: 'string', describe: 'start only. Page name from the config, used for the reported URL' })
|
|
25
|
+
.option('timeout', { type: 'number', describe: 'start only. Seconds to wait for readiness' })
|
|
26
|
+
.option('skip-install', { type: 'boolean', describe: 'start only. Do not install dependencies first' })
|
|
27
|
+
.option('json', { type: 'boolean', describe: 'Print the full report as JSON' })
|
|
28
|
+
.check((args) => {
|
|
29
|
+
if (args.action === 'sync' && !args.direction)
|
|
30
|
+
throw new Error('sync needs --direction in|out|both');
|
|
31
|
+
return true;
|
|
32
|
+
})
|
|
33
|
+
.epilog(config_1.configHelp),
|
|
34
|
+
handler: async (args) => {
|
|
35
|
+
const base = { path: args.worktree, project: args.project };
|
|
36
|
+
if (args.action === 'status') {
|
|
37
|
+
const status = await (0, status_1.worktreeStatus)({ ...base, target: args.target });
|
|
38
|
+
print(args, status, (0, status_1.formatStatus)(status));
|
|
39
|
+
}
|
|
40
|
+
else if (args.action === 'sync') {
|
|
41
|
+
const report = await (0, sync_1.syncWorktree)({ ...base, target: args.target, direction: args.direction });
|
|
42
|
+
print(args, report, (0, sync_1.formatSync)(report));
|
|
43
|
+
if (report.steps.some((step) => step.result === 'conflict'))
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const report = await (0, start_1.startWorktree)({ ...base, port: args.port, page: args.page, timeout: args.timeout, skipInstall: args.skipInstall, quiet: args.quiet || args.json });
|
|
48
|
+
print(args, report, (0, start_1.formatStart)(report));
|
|
49
|
+
if (report.state !== 'running' || report.compile === 'failed')
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
exports.default = command;
|
|
55
|
+
//# sourceMappingURL=command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/features/worktree/command.ts"],"names":[],"mappings":";;AACA,8CAAgD;AAChD,qCAAsC;AACtC,mCAAqD;AACrD,qCAAwD;AACxD,iCAAiE;AAgBjE,SAAS,KAAK,CAAC,IAAqB,EAAE,KAAc,EAAE,IAAY;IACjE,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;;QACtD,IAAA,oBAAW,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,OAAO,GAAuC;IACnD,OAAO,EAAE,8BAA8B;IACvC,QAAQ,EAAE,yDAAyD;IACnE,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;SACnB,UAAU,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,yHAAyH,EAAE,CAAC;SAChP,UAAU,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,CAAC;SAC9F,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,sEAAsE,EAAE,CAAC;SACvH,MAAM,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,+DAA+D,EAAE,CAAC;SAC/G,MAAM,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,sGAAsG,EAAE,CAAC;SAClM,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,iFAAiF,EAAE,CAAC;SAC/H,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,kEAAkE,EAAE,CAAC;SAChH,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,2CAA2C,EAAE,CAAC;SAC5F,MAAM,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,+CAA+C,EAAE,CAAC;SACtG,MAAM,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,+BAA+B,EAAE,CAAC;SAC9E,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACf,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACrG,OAAO,IAAI,CAAC;IACb,CAAC,CAAC;SACD,MAAM,CAAC,mBAAU,CAAC;IACpB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACvB,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5D,IAAI,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAc,EAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YACtE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAA,qBAAY,EAAC,MAAM,CAAC,CAAC,CAAC;SAC1C;aAAM,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE;YAClC,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAY,EAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAA0B,EAAE,CAAC,CAAC;YAChH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAA,iBAAU,EAAC,MAAM,CAAC,CAAC,CAAC;YACxC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,KAAK,UAAU,CAAC;gBAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;SAClF;aAAM;YACN,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACxK,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,IAAA,mBAAW,EAAC,MAAM,CAAC,CAAC,CAAC;YACzC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ;gBAAE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;SACpF;IACF,CAAC;CACD,CAAC;AACF,kBAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadConfig = exports.parseConfig = exports.configHelp = exports.configFile = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const json_1 = require("../../core/json");
|
|
10
|
+
exports.configFile = node_path_1.default.join('.azcli', 'worktree.json');
|
|
11
|
+
exports.configHelp = `Config file: .azcli/worktree.json (JSON), read from the worktree, else the project. Example:
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
"target": "development",
|
|
15
|
+
"install": { "command": "yarn", "args": ["install", "--immutable"] },
|
|
16
|
+
"dev": {
|
|
17
|
+
"command": "react-app-rewired",
|
|
18
|
+
"args": ["start"],
|
|
19
|
+
"cwd": "packages_main/web",
|
|
20
|
+
"defaultPort": 3000,
|
|
21
|
+
"pages": { "order": "/order" },
|
|
22
|
+
"binDirs": ["node_modules/.bin"],
|
|
23
|
+
"timeoutSeconds": 120
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Fields:
|
|
28
|
+
target optional. Branch that status and sync compare against (--target overrides).
|
|
29
|
+
install optional. Default: yarn install --immutable at the worktree root.
|
|
30
|
+
dev required for "start". command and args run without a shell, in cwd.
|
|
31
|
+
portEnv optional. Environment variable receiving the port. Default PORT.
|
|
32
|
+
"{port}" inside args is replaced too.
|
|
33
|
+
defaultPort optional. Port used by the main checkout. Default 3000; start picks
|
|
34
|
+
the first free port above it.
|
|
35
|
+
readyPath optional. Path polled until the server answers. Default "/".
|
|
36
|
+
pages optional. Page name -> path, selected with --page.
|
|
37
|
+
timeoutSeconds optional. Maximum wait for readiness. Default 120.
|
|
38
|
+
binDirs optional. Directories searched for the command before PATH, relative to
|
|
39
|
+
the worktree root and to cwd. Default ["node_modules/.bin"].
|
|
40
|
+
compiledPattern, failedPattern
|
|
41
|
+
optional. Regexes matched against the dev log.`;
|
|
42
|
+
function stringArray(value, label) {
|
|
43
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string'))
|
|
44
|
+
throw new Error(`${label} must be an array of strings`);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
function commandConfig(value, label) {
|
|
48
|
+
if (!(0, json_1.isRecord)(value))
|
|
49
|
+
throw new Error(`${label} must be an object`);
|
|
50
|
+
const command = (0, json_1.asString)(value.command);
|
|
51
|
+
if (!command)
|
|
52
|
+
throw new Error(`${label} needs a "command"`);
|
|
53
|
+
return { command, args: value.args === undefined ? [] : stringArray(value.args, `${label} "args"`), cwd: (0, json_1.asString)(value.cwd) };
|
|
54
|
+
}
|
|
55
|
+
function positive(value, label, fallback) {
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
return fallback;
|
|
58
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0)
|
|
59
|
+
throw new Error(`${label} must be a positive integer`);
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
function parseConfig(value) {
|
|
63
|
+
if (!(0, json_1.isRecord)(value))
|
|
64
|
+
throw new Error(`${exports.configFile} must contain a JSON object`);
|
|
65
|
+
const config = {
|
|
66
|
+
target: (0, json_1.asString)(value.target),
|
|
67
|
+
install: value.install === undefined ? { command: 'yarn', args: ['install', '--immutable'] } : commandConfig(value.install, '"install"'),
|
|
68
|
+
};
|
|
69
|
+
if (value.dev !== undefined) {
|
|
70
|
+
const base = commandConfig(value.dev, '"dev"');
|
|
71
|
+
const dev = value.dev;
|
|
72
|
+
const pages = {};
|
|
73
|
+
if (dev.pages !== undefined) {
|
|
74
|
+
if (!(0, json_1.isRecord)(dev.pages))
|
|
75
|
+
throw new Error('"dev" "pages" must be an object');
|
|
76
|
+
for (const [name, page] of Object.entries(dev.pages)) {
|
|
77
|
+
if (typeof page !== 'string')
|
|
78
|
+
throw new Error(`"dev" page "${name}" must be a string`);
|
|
79
|
+
pages[name] = page;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
config.dev = {
|
|
83
|
+
...base,
|
|
84
|
+
portEnv: (0, json_1.asString)(dev.portEnv) ?? 'PORT',
|
|
85
|
+
defaultPort: positive(dev.defaultPort, '"dev" "defaultPort"', 3000),
|
|
86
|
+
readyPath: (0, json_1.asString)(dev.readyPath) ?? '/',
|
|
87
|
+
pages,
|
|
88
|
+
timeoutSeconds: positive(dev.timeoutSeconds, '"dev" "timeoutSeconds"', 120),
|
|
89
|
+
binDirs: dev.binDirs === undefined ? ['node_modules/.bin'] : stringArray(dev.binDirs, '"dev" "binDirs"'),
|
|
90
|
+
compiledPattern: (0, json_1.asString)(dev.compiledPattern) ?? 'Compiled (successfully|with warnings)',
|
|
91
|
+
failedPattern: (0, json_1.asString)(dev.failedPattern) ?? 'Failed to compile|Module not found|error TS\\d+',
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return config;
|
|
95
|
+
}
|
|
96
|
+
exports.parseConfig = parseConfig;
|
|
97
|
+
/** Read the config from the first root that has one; a missing file everywhere yields the defaults. */
|
|
98
|
+
function loadConfig(...roots) {
|
|
99
|
+
for (const root of roots) {
|
|
100
|
+
const file = node_path_1.default.join(root, exports.configFile);
|
|
101
|
+
if (!node_fs_1.default.existsSync(file))
|
|
102
|
+
continue;
|
|
103
|
+
let parsed;
|
|
104
|
+
try {
|
|
105
|
+
parsed = JSON.parse(node_fs_1.default.readFileSync(file, 'utf8'));
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw new Error(`Could not read ${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
109
|
+
}
|
|
110
|
+
return parseConfig(parsed);
|
|
111
|
+
}
|
|
112
|
+
return parseConfig({});
|
|
113
|
+
}
|
|
114
|
+
exports.loadConfig = loadConfig;
|
|
115
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/features/worktree/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveTarget = exports.gitDir = exports.treeState = exports.listWorktrees = exports.gitOk = exports.git = exports.lines = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const lines = (text) => text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
9
|
+
exports.lines = lines;
|
|
10
|
+
async function git(run, cwd, args) {
|
|
11
|
+
return (await run('git', args, { cwd, quiet: true })).stdout.trim();
|
|
12
|
+
}
|
|
13
|
+
exports.git = git;
|
|
14
|
+
async function gitOk(run, cwd, args) {
|
|
15
|
+
try {
|
|
16
|
+
await run('git', args, { cwd, quiet: true });
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.gitOk = gitOk;
|
|
24
|
+
async function listWorktrees(run, cwd) {
|
|
25
|
+
const text = (await run('git', ['worktree', 'list', '--porcelain'], { cwd, quiet: true })).stdout;
|
|
26
|
+
return text.split(/\r?\n\r?\n/).map((block) => {
|
|
27
|
+
const entry = {};
|
|
28
|
+
for (const line of (0, exports.lines)(block)) {
|
|
29
|
+
if (line.startsWith('worktree '))
|
|
30
|
+
entry.path = node_path_1.default.resolve(line.slice(9));
|
|
31
|
+
else if (line.startsWith('HEAD '))
|
|
32
|
+
entry.head = line.slice(5);
|
|
33
|
+
else if (line.startsWith('branch '))
|
|
34
|
+
entry.branch = line.slice(7).replace(/^refs\/heads\//, '');
|
|
35
|
+
}
|
|
36
|
+
return entry;
|
|
37
|
+
}).filter((entry) => Boolean(entry.path));
|
|
38
|
+
}
|
|
39
|
+
exports.listWorktrees = listWorktrees;
|
|
40
|
+
/** `dirty` holds `git status --porcelain` lines: tracked and untracked changes. */
|
|
41
|
+
async function treeState(run, cwd) {
|
|
42
|
+
const branch = await git(run, cwd, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
43
|
+
const tip = await git(run, cwd, ['rev-parse', '--short', 'HEAD']);
|
|
44
|
+
const status = (await run('git', ['status', '--porcelain'], { cwd, quiet: true })).stdout;
|
|
45
|
+
return { path: cwd, branch: branch === 'HEAD' ? null : branch, tip, dirty: status.split(/\r?\n/).filter(Boolean) };
|
|
46
|
+
}
|
|
47
|
+
exports.treeState = treeState;
|
|
48
|
+
/** Per-worktree git directory; a safe place for logs and scratch files that never dirties the tree. */
|
|
49
|
+
async function gitDir(run, cwd) {
|
|
50
|
+
return node_path_1.default.resolve(cwd, await git(run, cwd, ['rev-parse', '--absolute-git-dir']));
|
|
51
|
+
}
|
|
52
|
+
exports.gitDir = gitDir;
|
|
53
|
+
async function resolveTarget(run, cwd, requested, configured) {
|
|
54
|
+
const target = requested ?? configured;
|
|
55
|
+
if (!target)
|
|
56
|
+
throw new Error('No target branch: pass --target or set "target" in .azcli/worktree.json');
|
|
57
|
+
if (!(await gitOk(run, cwd, ['rev-parse', '--verify', '--quiet', `refs/heads/${target}`])))
|
|
58
|
+
throw new Error(`Target branch not found: ${target}`);
|
|
59
|
+
return target;
|
|
60
|
+
}
|
|
61
|
+
exports.resolveTarget = resolveTarget;
|
|
62
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/features/worktree/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatStart = exports.startWorktree = exports.pickPort = exports.isPortFree = void 0;
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
9
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
10
|
+
const node_net_1 = __importDefault(require("node:net"));
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const files_1 = require("../../core/files");
|
|
13
|
+
const logger_1 = require("../../core/logger");
|
|
14
|
+
const process_1 = require("../../core/process");
|
|
15
|
+
const config_1 = require("./config");
|
|
16
|
+
const git_1 = require("./git");
|
|
17
|
+
const pollMs = 500;
|
|
18
|
+
const compileGraceMs = 3000;
|
|
19
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
20
|
+
function isPortFree(port) {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const server = node_net_1.default.createServer();
|
|
23
|
+
server.once('error', () => resolve(false));
|
|
24
|
+
server.listen(port, () => server.close(() => resolve(true)));
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.isPortFree = isPortFree;
|
|
28
|
+
/** An explicitly requested port must be free; otherwise take the first free port above the default one. */
|
|
29
|
+
async function pickPort(defaultPort, requested) {
|
|
30
|
+
if (requested !== undefined) {
|
|
31
|
+
if (!(await isPortFree(requested)))
|
|
32
|
+
throw new Error(`Port ${requested} is already in use`);
|
|
33
|
+
return requested;
|
|
34
|
+
}
|
|
35
|
+
for (let port = defaultPort + 1; port < defaultPort + 101; port++)
|
|
36
|
+
if (await isPortFree(port))
|
|
37
|
+
return port;
|
|
38
|
+
throw new Error(`No free port found above ${defaultPort}`);
|
|
39
|
+
}
|
|
40
|
+
exports.pickPort = pickPort;
|
|
41
|
+
function probe(url) {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const request = node_http_1.default.get(url, { timeout: 2000 }, (response) => {
|
|
44
|
+
response.resume();
|
|
45
|
+
resolve(true);
|
|
46
|
+
});
|
|
47
|
+
request.once('timeout', () => request.destroy());
|
|
48
|
+
request.once('error', () => resolve(false));
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function killTree(pid) {
|
|
52
|
+
try {
|
|
53
|
+
if (process.platform === 'win32')
|
|
54
|
+
(0, node_child_process_1.spawnSync)('taskkill', ['/pid', String(pid), '/t', '/f'], { windowsHide: true });
|
|
55
|
+
else
|
|
56
|
+
process.kill(-pid, 'SIGTERM');
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// The process is already gone.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function compileState(log, dev) {
|
|
63
|
+
if (new RegExp(dev.failedPattern, 'i').test(log))
|
|
64
|
+
return 'failed';
|
|
65
|
+
return new RegExp(dev.compiledPattern, 'i').test(log) ? 'ok' : 'unknown';
|
|
66
|
+
}
|
|
67
|
+
function launchEnvironment(root, cwd, dev, port) {
|
|
68
|
+
const env = { ...process.env, [dev.portEnv]: String(port) };
|
|
69
|
+
const key = Object.keys(env).find((name) => name.toUpperCase() === 'PATH') ?? 'PATH';
|
|
70
|
+
const directories = dev.binDirs.flatMap((dir) => [(0, files_1.resolveInside)(root, dir), (0, files_1.resolveInside)(cwd, dir)]);
|
|
71
|
+
env[key] = [...directories, env[key] ?? ''].join(node_path_1.default.delimiter);
|
|
72
|
+
return env;
|
|
73
|
+
}
|
|
74
|
+
async function startWorktree(options, run = process_1.runCommand) {
|
|
75
|
+
const root = node_path_1.default.resolve(options.path);
|
|
76
|
+
if (!node_fs_1.default.existsSync(root))
|
|
77
|
+
throw new Error(`Worktree not found: ${root}`);
|
|
78
|
+
const config = (0, config_1.loadConfig)(root, node_path_1.default.resolve(options.project ?? '.'));
|
|
79
|
+
const dev = config.dev;
|
|
80
|
+
if (!dev)
|
|
81
|
+
throw new Error('Missing "dev" in .azcli/worktree.json. Run "azcli worktree start --help" to see the file format.');
|
|
82
|
+
let pagePath = dev.readyPath;
|
|
83
|
+
if (options.page) {
|
|
84
|
+
if (!(options.page in dev.pages))
|
|
85
|
+
throw new Error(`Unknown page "${options.page}". Configured pages: ${Object.keys(dev.pages).join(', ') || 'none'}`);
|
|
86
|
+
pagePath = dev.pages[options.page];
|
|
87
|
+
}
|
|
88
|
+
if (!options.skipInstall) {
|
|
89
|
+
const install = config.install;
|
|
90
|
+
await run(install.command, install.args, { cwd: install.cwd ? (0, files_1.resolveInside)(root, install.cwd) : root, quiet: options.quiet });
|
|
91
|
+
}
|
|
92
|
+
const port = await pickPort(dev.defaultPort, options.port);
|
|
93
|
+
const cwd = dev.cwd ? (0, files_1.resolveInside)(root, dev.cwd) : root;
|
|
94
|
+
const launch = (0, process_1.resolveCommand)(dev.command, dev.args.map((arg) => arg.replaceAll('{port}', String(port))), cwd, launchEnvironment(root, cwd, dev, port));
|
|
95
|
+
const logDirectory = node_path_1.default.join(await (0, git_1.gitDir)(run, root), 'azcli');
|
|
96
|
+
node_fs_1.default.mkdirSync(logDirectory, { recursive: true });
|
|
97
|
+
const log = node_path_1.default.join(logDirectory, `dev-${port}.log`);
|
|
98
|
+
const report = (fields) => ({
|
|
99
|
+
url: `http://localhost:${port}${pagePath}`, port, log, ...fields,
|
|
100
|
+
});
|
|
101
|
+
const fd = node_fs_1.default.openSync(log, 'w');
|
|
102
|
+
let exit;
|
|
103
|
+
const child = (0, node_child_process_1.spawn)(launch.command, launch.args, {
|
|
104
|
+
cwd,
|
|
105
|
+
env: launchEnvironment(root, cwd, dev, port),
|
|
106
|
+
detached: true,
|
|
107
|
+
stdio: ['ignore', fd, fd],
|
|
108
|
+
windowsHide: true,
|
|
109
|
+
});
|
|
110
|
+
node_fs_1.default.closeSync(fd);
|
|
111
|
+
child.once('error', (error) => { exit = `could not start ${dev.command}: ${error.message}`; });
|
|
112
|
+
child.once('exit', (code, signal) => { exit = signal ? `terminated by ${signal}` : `exit code ${code}`; });
|
|
113
|
+
const readLog = () => node_fs_1.default.readFileSync(log, 'utf8');
|
|
114
|
+
const tail = () => readLog().split(/\r?\n/).filter(Boolean).slice(-20).join('\n');
|
|
115
|
+
const fail = (state, error) => {
|
|
116
|
+
if (state === 'timeout' && child.pid)
|
|
117
|
+
killTree(child.pid);
|
|
118
|
+
return report({ state, compile: compileState(readLog(), dev), pid: child.pid, error, logTail: tail() });
|
|
119
|
+
};
|
|
120
|
+
const timeoutMs = (options.timeout ?? dev.timeoutSeconds) * 1000;
|
|
121
|
+
const started = Date.now();
|
|
122
|
+
const readyUrl = `http://localhost:${port}${dev.readyPath}`;
|
|
123
|
+
if (!options.quiet)
|
|
124
|
+
(0, logger_1.showMessage)(`Waiting for ${readyUrl} (up to ${timeoutMs / 1000}s)`);
|
|
125
|
+
while (!exit) {
|
|
126
|
+
if (await probe(readyUrl))
|
|
127
|
+
break;
|
|
128
|
+
if (Date.now() - started > timeoutMs)
|
|
129
|
+
return fail('timeout', `no response from ${readyUrl} within ${timeoutMs / 1000}s`);
|
|
130
|
+
await sleep(pollMs);
|
|
131
|
+
}
|
|
132
|
+
if (exit)
|
|
133
|
+
return fail('exited', `dev server stopped: ${exit}`);
|
|
134
|
+
const graceEnd = Date.now() + compileGraceMs;
|
|
135
|
+
while (compileState(readLog(), dev) === 'unknown' && Date.now() < graceEnd && !exit)
|
|
136
|
+
await sleep(200);
|
|
137
|
+
if (exit)
|
|
138
|
+
return fail('exited', `dev server stopped: ${exit}`);
|
|
139
|
+
child.unref();
|
|
140
|
+
return report({ state: 'running', compile: compileState(readLog(), dev), pid: child.pid });
|
|
141
|
+
}
|
|
142
|
+
exports.startWorktree = startWorktree;
|
|
143
|
+
function formatStart(report) {
|
|
144
|
+
const output = [
|
|
145
|
+
`state: ${report.state}${report.error ? ` (${report.error})` : ''}`,
|
|
146
|
+
`url: ${report.url}`,
|
|
147
|
+
`pid: ${report.pid ?? 'none'}`,
|
|
148
|
+
`compile: ${report.compile}`,
|
|
149
|
+
`log: ${report.log}`,
|
|
150
|
+
];
|
|
151
|
+
if (report.logTail)
|
|
152
|
+
output.push('last log lines:', report.logTail);
|
|
153
|
+
return output.join('\n');
|
|
154
|
+
}
|
|
155
|
+
exports.formatStart = formatStart;
|
|
156
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/features/worktree/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatStatus = exports.worktreeStatus = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const process_1 = require("../../core/process");
|
|
9
|
+
const config_1 = require("./config");
|
|
10
|
+
const git_1 = require("./git");
|
|
11
|
+
const manifests = new Set(['package.json', 'yarn.lock', 'package-lock.json', 'pnpm-lock.yaml', 'composer.json', 'composer.lock', 'requirements.txt', 'pyproject.toml', 'poetry.lock']);
|
|
12
|
+
const isManifest = (file) => manifests.has(node_path_1.default.posix.basename(file));
|
|
13
|
+
async function worktreeStatus(options, run = process_1.runCommand) {
|
|
14
|
+
const root = node_path_1.default.resolve(options.path);
|
|
15
|
+
const config = (0, config_1.loadConfig)(root, node_path_1.default.resolve(options.project ?? '.'));
|
|
16
|
+
const target = await (0, git_1.resolveTarget)(run, root, options.target, config.target);
|
|
17
|
+
const worktree = await (0, git_1.treeState)(run, root);
|
|
18
|
+
const entry = (await (0, git_1.listWorktrees)(run, root)).find((tree) => tree.branch === target);
|
|
19
|
+
const [behind, ahead] = (await (0, git_1.git)(run, root, ['rev-list', '--left-right', '--count', `${target}...HEAD`])).split(/\s+/).map(Number);
|
|
20
|
+
const mergeBase = await (0, git_1.git)(run, root, ['merge-base', target, 'HEAD']);
|
|
21
|
+
const changed = async (to) => (0, git_1.lines)(await (0, git_1.git)(run, root, ['diff', '--name-only', '--no-renames', mergeBase, to])).filter(isManifest);
|
|
22
|
+
return {
|
|
23
|
+
target,
|
|
24
|
+
worktree,
|
|
25
|
+
targetTree: entry ? await (0, git_1.treeState)(run, entry.path) : null,
|
|
26
|
+
behind,
|
|
27
|
+
ahead,
|
|
28
|
+
merged: await (0, git_1.gitOk)(run, root, ['merge-base', '--is-ancestor', 'HEAD', target]),
|
|
29
|
+
dependencyChanges: { incoming: await changed(target), outgoing: await changed('HEAD') },
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
exports.worktreeStatus = worktreeStatus;
|
|
33
|
+
function describeTree(label, tree) {
|
|
34
|
+
if (!tree)
|
|
35
|
+
return `${label}: not checked out in any worktree`;
|
|
36
|
+
const dirty = tree.dirty.length ? `${tree.dirty.length} changed file(s)` : 'clean';
|
|
37
|
+
return `${label}: ${tree.branch ?? '(detached)'} @ ${tree.tip}, ${dirty}\n ${tree.path}${tree.dirty.map((line) => `\n ${line}`).join('')}`;
|
|
38
|
+
}
|
|
39
|
+
function formatStatus(status) {
|
|
40
|
+
const { incoming, outgoing } = status.dependencyChanges;
|
|
41
|
+
return [
|
|
42
|
+
describeTree('worktree', status.worktree),
|
|
43
|
+
describeTree('target ', status.targetTree),
|
|
44
|
+
`vs ${status.target}: ${status.ahead} ahead, ${status.behind} behind${status.merged ? ' (fully merged into target)' : ''}`,
|
|
45
|
+
`dependency manifests changed on ${status.target}: ${incoming.join(', ') || 'none'}`,
|
|
46
|
+
`dependency manifests changed on branch: ${outgoing.join(', ') || 'none'}`,
|
|
47
|
+
].join('\n');
|
|
48
|
+
}
|
|
49
|
+
exports.formatStatus = formatStatus;
|
|
50
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/features/worktree/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.formatSync = exports.syncWorktree = void 0;
|
|
7
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const process_1 = require("../../core/process");
|
|
10
|
+
const config_1 = require("./config");
|
|
11
|
+
const git_1 = require("./git");
|
|
12
|
+
const stage = (run, cwd, number, file) => run('git', ['show', `:${number}:${file}`], { cwd, quiet: true }).then((result) => result.stdout, () => undefined);
|
|
13
|
+
const squash = (text) => text.replace(/\s+/g, '');
|
|
14
|
+
async function collectConflicts(run, cwd) {
|
|
15
|
+
const files = (0, git_1.lines)(await (0, git_1.git)(run, cwd, ['diff', '--name-only', '--diff-filter=U']));
|
|
16
|
+
const directory = node_path_1.default.join(await (0, git_1.gitDir)(run, cwd), 'azcli', 'conflicts');
|
|
17
|
+
node_fs_1.default.rmSync(directory, { recursive: true, force: true });
|
|
18
|
+
const conflicts = [];
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
const sides = { base: await stage(run, cwd, 1, file), ours: await stage(run, cwd, 2, file), theirs: await stage(run, cwd, 3, file) };
|
|
21
|
+
const conflict = {
|
|
22
|
+
file,
|
|
23
|
+
whitespaceOnly: sides.ours !== undefined && sides.theirs !== undefined && squash(sides.ours) === squash(sides.theirs),
|
|
24
|
+
};
|
|
25
|
+
for (const [name, content] of Object.entries(sides)) {
|
|
26
|
+
if (content === undefined)
|
|
27
|
+
continue;
|
|
28
|
+
const target = node_path_1.default.join(directory, `${file}.${name}`);
|
|
29
|
+
node_fs_1.default.mkdirSync(node_path_1.default.dirname(target), { recursive: true });
|
|
30
|
+
node_fs_1.default.writeFileSync(target, content);
|
|
31
|
+
conflict[name] = target;
|
|
32
|
+
}
|
|
33
|
+
conflicts.push(conflict);
|
|
34
|
+
}
|
|
35
|
+
return conflicts;
|
|
36
|
+
}
|
|
37
|
+
async function assertReady(run, cwd, label) {
|
|
38
|
+
const state = await (0, git_1.treeState)(run, cwd);
|
|
39
|
+
if (!state.branch)
|
|
40
|
+
throw new Error(`${label} is on a detached HEAD: ${cwd}`);
|
|
41
|
+
if (await (0, git_1.gitOk)(run, cwd, ['rev-parse', '--quiet', '--verify', 'MERGE_HEAD']))
|
|
42
|
+
throw new Error(`${label} has a merge in progress: ${cwd}`);
|
|
43
|
+
const tracked = state.dirty.filter((line) => !line.startsWith('??'));
|
|
44
|
+
if (tracked.length)
|
|
45
|
+
throw new Error(`${label} has uncommitted changes; commit or stash them first (${cwd}):\n${tracked.join('\n')}`);
|
|
46
|
+
return state.branch;
|
|
47
|
+
}
|
|
48
|
+
async function merge(run, direction, cwd, into, from) {
|
|
49
|
+
const step = (result, conflicts = []) => ({ direction, cwd, into, from, result, conflicts });
|
|
50
|
+
if (await (0, git_1.gitOk)(run, cwd, ['merge-base', '--is-ancestor', from, 'HEAD']))
|
|
51
|
+
return step('up-to-date');
|
|
52
|
+
try {
|
|
53
|
+
await run('git', ['merge', '--no-edit', from], { cwd, quiet: true });
|
|
54
|
+
return step('merged');
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const conflicts = await collectConflicts(run, cwd);
|
|
58
|
+
if (!conflicts.length)
|
|
59
|
+
throw error;
|
|
60
|
+
return step('conflict', conflicts);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Performs only the requested merge direction(s). On conflict the merge stays in progress in its worktree,
|
|
65
|
+
* so the caller can resolve and commit; nothing is resolved here.
|
|
66
|
+
*/
|
|
67
|
+
async function syncWorktree(options, run = process_1.runCommand) {
|
|
68
|
+
const root = node_path_1.default.resolve(options.path);
|
|
69
|
+
const config = (0, config_1.loadConfig)(root, node_path_1.default.resolve(options.project ?? '.'));
|
|
70
|
+
const target = await (0, git_1.resolveTarget)(run, root, options.target, config.target);
|
|
71
|
+
const branch = await assertReady(run, root, 'Worktree');
|
|
72
|
+
if (branch === target)
|
|
73
|
+
throw new Error(`The worktree is on the target branch itself: ${target}`);
|
|
74
|
+
const targetEntry = (await (0, git_1.listWorktrees)(run, root)).find((tree) => tree.branch === target);
|
|
75
|
+
if (!targetEntry)
|
|
76
|
+
throw new Error(`Target branch "${target}" is not checked out in any worktree`);
|
|
77
|
+
await assertReady(run, targetEntry.path, 'Target worktree');
|
|
78
|
+
const steps = [];
|
|
79
|
+
if (options.direction !== 'out')
|
|
80
|
+
steps.push(await merge(run, 'in', root, branch, target));
|
|
81
|
+
if (options.direction !== 'in' && !steps.some((step) => step.result === 'conflict'))
|
|
82
|
+
steps.push(await merge(run, 'out', targetEntry.path, target, branch));
|
|
83
|
+
return {
|
|
84
|
+
target,
|
|
85
|
+
steps,
|
|
86
|
+
tips: { worktree: await (0, git_1.git)(run, root, ['rev-parse', '--short', 'HEAD']), target: await (0, git_1.git)(run, targetEntry.path, ['rev-parse', '--short', 'HEAD']) },
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
exports.syncWorktree = syncWorktree;
|
|
90
|
+
function formatSync(report) {
|
|
91
|
+
const output = [];
|
|
92
|
+
for (const step of report.steps) {
|
|
93
|
+
output.push(`${step.direction}: merge ${step.from} into ${step.into} -> ${step.result}`);
|
|
94
|
+
for (const conflict of step.conflicts) {
|
|
95
|
+
output.push(` CONFLICT ${conflict.file}${conflict.whitespaceOnly ? ' (whitespace-only)' : ''}`);
|
|
96
|
+
for (const side of ['base', 'ours', 'theirs'])
|
|
97
|
+
if (conflict[side])
|
|
98
|
+
output.push(` ${side}: ${conflict[side]}`);
|
|
99
|
+
}
|
|
100
|
+
if (step.conflicts.length)
|
|
101
|
+
output.push(` The merge is still in progress in ${step.cwd}; resolve, commit, or run "git merge --abort".`);
|
|
102
|
+
}
|
|
103
|
+
output.push(`tips: worktree ${report.tips.worktree}, ${report.target} ${report.tips.target}`);
|
|
104
|
+
return output.join('\n');
|
|
105
|
+
}
|
|
106
|
+
exports.formatSync = formatSync;
|
|
107
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../src/features/worktree/sync.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azrico/azcli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"description": "Project build, publishing, dependency, and AI transcript helpers",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/cli/index.js",
|
|
@@ -38,4 +38,4 @@
|
|
|
38
38
|
"engines": {
|
|
39
39
|
"node": ">=20"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|