@4pm/cli 1.19.3 → 1.19.6
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/dist/index.js +64 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -37503,9 +37503,10 @@ var activityHeartbeatSchema = external_exports.object({
|
|
|
37503
37503
|
});
|
|
37504
37504
|
|
|
37505
37505
|
// src/core/scaffold.ts
|
|
37506
|
-
import { cp, mkdir, rm, writeFile } from "fs/promises";
|
|
37506
|
+
import { cp, mkdir, mkdtemp, rm, writeFile } from "fs/promises";
|
|
37507
37507
|
import { existsSync as existsSync4 } from "fs";
|
|
37508
37508
|
import { execFile as execFile2 } from "child_process";
|
|
37509
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
37509
37510
|
import { dirname as dirname3, join as join6, resolve } from "path";
|
|
37510
37511
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
37511
37512
|
import { promisify as promisify2 } from "util";
|
|
@@ -37595,7 +37596,7 @@ function submodulesOf(repos) {
|
|
|
37595
37596
|
const primary = singleRepo(repos);
|
|
37596
37597
|
return repos.filter((r) => r !== primary && !!r.url && !!(r.subdir ?? "").trim());
|
|
37597
37598
|
}
|
|
37598
|
-
async function attachSubmodules(root, submodules, emit) {
|
|
37599
|
+
async function attachSubmodules(root, submodules, emit, createMissingBranch = false) {
|
|
37599
37600
|
if (submodules.length === 0) return;
|
|
37600
37601
|
if (!existsSync4(join6(root, ".git"))) return;
|
|
37601
37602
|
let added = 0;
|
|
@@ -37612,6 +37613,26 @@ async function attachSubmodules(root, submodules, emit) {
|
|
|
37612
37613
|
}
|
|
37613
37614
|
emit("submodule", `Adding submodule ${sub.url} \u2192 ${dir2}\u2026`);
|
|
37614
37615
|
const b2 = (sub.branch ?? "").trim();
|
|
37616
|
+
if (b2 && createMissingBranch && !await ensureRemoteBranch(sub.url, b2, emit)) {
|
|
37617
|
+
try {
|
|
37618
|
+
await run2("git", ["submodule", "add", sub.url, dir2], { cwd: root, timeout: 12e4 });
|
|
37619
|
+
await run2("git", ["config", "-f", ".gitmodules", `submodule.${dir2}.branch`, b2], { cwd: root, timeout: 3e4 });
|
|
37620
|
+
try {
|
|
37621
|
+
await run2("git", ["checkout", "-b", b2], { cwd: join6(root, dir2), timeout: 3e4 });
|
|
37622
|
+
await run2("git", ["push", "-u", "origin", b2], { cwd: join6(root, dir2), timeout: 12e4 });
|
|
37623
|
+
} catch (pushErr) {
|
|
37624
|
+
const pmsg = pushErr instanceof Error ? pushErr.message : String(pushErr);
|
|
37625
|
+
emit("git-branch-push-failed", `Submodule ${dir2}: branch "${b2}" created locally but the push failed: ${pmsg}`);
|
|
37626
|
+
}
|
|
37627
|
+
added++;
|
|
37628
|
+
continue;
|
|
37629
|
+
} catch (err) {
|
|
37630
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37631
|
+
if (!/already exists|already registered|in the index/i.test(msg)) {
|
|
37632
|
+
throw new Error(`git submodule add ${dir2} failed: ${msg}`);
|
|
37633
|
+
}
|
|
37634
|
+
}
|
|
37635
|
+
}
|
|
37615
37636
|
try {
|
|
37616
37637
|
await run2("git", ["submodule", "add", ...b2 ? ["-b", b2] : [], sub.url, dir2], { cwd: root, timeout: 12e4 });
|
|
37617
37638
|
added++;
|
|
@@ -37654,6 +37675,31 @@ function cloneArgs(url, dest, branch) {
|
|
|
37654
37675
|
const b2 = (branch ?? "").trim();
|
|
37655
37676
|
return b2 ? ["clone", "-b", b2, url, dest] : ["clone", url, dest];
|
|
37656
37677
|
}
|
|
37678
|
+
async function remoteHasBranch(url, branch) {
|
|
37679
|
+
try {
|
|
37680
|
+
const { stdout } = await run2("git", ["ls-remote", "--heads", url, branch], { timeout: 3e4 });
|
|
37681
|
+
return stdout.trim().length > 0;
|
|
37682
|
+
} catch {
|
|
37683
|
+
return false;
|
|
37684
|
+
}
|
|
37685
|
+
}
|
|
37686
|
+
async function ensureRemoteBranch(url, branch, emit) {
|
|
37687
|
+
if (await remoteHasBranch(url, branch)) return true;
|
|
37688
|
+
const tmp = await mkdtemp(join6(tmpdir2(), "4pm-branch-"));
|
|
37689
|
+
try {
|
|
37690
|
+
emit("git", `Branch "${branch}" not found on ${url} \u2014 creating it from the default branch\u2026`);
|
|
37691
|
+
await run2("git", ["clone", "--depth", "1", url, tmp], { timeout: 12e4 });
|
|
37692
|
+
await run2("git", ["checkout", "-b", branch], { cwd: tmp, timeout: 3e4 });
|
|
37693
|
+
await run2("git", ["push", "-u", "origin", branch], { cwd: tmp, timeout: 12e4 });
|
|
37694
|
+
return true;
|
|
37695
|
+
} catch (err) {
|
|
37696
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37697
|
+
emit("git-branch-push-failed", `Could not create branch "${branch}" on ${url}: ${msg}`);
|
|
37698
|
+
return false;
|
|
37699
|
+
} finally {
|
|
37700
|
+
await rm(tmp, { recursive: true, force: true });
|
|
37701
|
+
}
|
|
37702
|
+
}
|
|
37657
37703
|
async function updateRepo(dir2, branch, emit) {
|
|
37658
37704
|
const b2 = (branch ?? "").trim();
|
|
37659
37705
|
emit("git", `Updating repository (fetch + ${b2 ? `checkout ${b2} + ` : ""}fast-forward pull)\u2026`);
|
|
@@ -37683,6 +37729,20 @@ async function provisionRepo(target, repo, emit, opts = {}) {
|
|
|
37683
37729
|
}
|
|
37684
37730
|
return;
|
|
37685
37731
|
}
|
|
37732
|
+
const b2 = (repo.branch ?? "").trim();
|
|
37733
|
+
if (b2 && opts.createMissingBranch && !await remoteHasBranch(repo.url, b2)) {
|
|
37734
|
+
emit("git", `Cloning ${repo.url} (default branch) to create "${b2}"\u2026`);
|
|
37735
|
+
await run2("git", ["clone", repo.url, target], { timeout: 12e4 });
|
|
37736
|
+
await run2("git", ["checkout", "-b", b2], { cwd: target, timeout: 3e4 });
|
|
37737
|
+
try {
|
|
37738
|
+
await run2("git", ["push", "-u", "origin", b2], { cwd: target, timeout: 12e4 });
|
|
37739
|
+
emit("git", `Created and pushed branch "${b2}".`);
|
|
37740
|
+
} catch (err) {
|
|
37741
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
37742
|
+
emit("git-branch-push-failed", `Branch "${b2}" created locally but the push failed: ${msg} \u2014 push it when credentials are available.`);
|
|
37743
|
+
}
|
|
37744
|
+
return;
|
|
37745
|
+
}
|
|
37686
37746
|
emit("git", `Cloning ${repo.url}\u2026`);
|
|
37687
37747
|
await run2("git", cloneArgs(repo.url, target, repo.branch), { timeout: 12e4 });
|
|
37688
37748
|
}
|
|
@@ -37716,9 +37776,9 @@ async function scaffoldProject(payload, profileDir2, onProgress) {
|
|
|
37716
37776
|
const repo = singleRepo(reposOf(payload.spec));
|
|
37717
37777
|
if (!repo) throw new Error("A project must declare one repo (ADR-0314).");
|
|
37718
37778
|
emit("git", "Cloning repository\u2026");
|
|
37719
|
-
await provisionRepo(target, repo, emit);
|
|
37779
|
+
await provisionRepo(target, repo, emit, { createMissingBranch: true });
|
|
37720
37780
|
await scaffoldRepo(target, payload.projectName, payload.spec, emit);
|
|
37721
|
-
await attachSubmodules(target, submodulesOf(reposOf(payload.spec)), emit);
|
|
37781
|
+
await attachSubmodules(target, submodulesOf(reposOf(payload.spec)), emit, true);
|
|
37722
37782
|
emit("version", "Writing .4pm/.4pm.json\u2026");
|
|
37723
37783
|
await writeTemplateMarker(target);
|
|
37724
37784
|
onProgress?.({ projectId: payload.projectId, step: "done", message: "Scaffold complete.", done: true });
|