@multiplatform.one/cli 7.23.0 → 7.23.1
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/lib/commands/merge.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import { tmpdir } from "node:os";
|
|
|
11
11
|
* ours = the project's HEAD (every commit the project made)
|
|
12
12
|
* theirs = the scaffold it is moving to
|
|
13
13
|
*
|
|
14
|
-
* `git merge-tree --write-tree
|
|
14
|
+
* `git merge-tree --write-tree` (git 2.38+) merges the scaffold's
|
|
15
15
|
* evolution with the project's history; the result lands in the index and
|
|
16
16
|
* worktree, never in a commit, so the project commits when it is happy.
|
|
17
17
|
* `.updateignore` entries (exact files or directory prefixes, not globs) and
|
|
@@ -296,6 +296,14 @@ async function mergeScaffolds(request) {
|
|
|
296
296
|
const head = await gitOut(projectDir, ["rev-parse", "HEAD"]);
|
|
297
297
|
const baseCommit = request.baseDir ? await commitTreeFromDir(projectDir, request.baseDir, request.baseLabel) : await emptyCommit(projectDir, request.baseLabel);
|
|
298
298
|
const nextCommit = await commitTreeFromDir(projectDir, request.theirsDir, request.theirsLabel, baseCommit);
|
|
299
|
+
const oursCommit = await gitOut(projectDir, [
|
|
300
|
+
"commit-tree",
|
|
301
|
+
`${head}^{tree}`,
|
|
302
|
+
"-p",
|
|
303
|
+
baseCommit,
|
|
304
|
+
"-m",
|
|
305
|
+
"HEAD"
|
|
306
|
+
]);
|
|
299
307
|
let mergedTree;
|
|
300
308
|
let conflicts = [];
|
|
301
309
|
try {
|
|
@@ -303,8 +311,7 @@ async function mergeScaffolds(request) {
|
|
|
303
311
|
"merge-tree",
|
|
304
312
|
"--write-tree",
|
|
305
313
|
"--name-only",
|
|
306
|
-
|
|
307
|
-
head,
|
|
314
|
+
oursCommit,
|
|
308
315
|
nextCommit
|
|
309
316
|
])).split("\n")[0].trim();
|
|
310
317
|
} catch (err) {
|
package/lib/source.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@multiplatform.one/cli",
|
|
3
|
-
"version": "7.23.
|
|
3
|
+
"version": "7.23.1",
|
|
4
4
|
"description": "multiplatform.one cli — mpo init clones and prunes the monorepo, mpo update merges it back",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"create-multiplatform-app",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"access": "public"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@multiplatform.one/utils": "7.23.
|
|
59
|
+
"@multiplatform.one/utils": "7.23.1",
|
|
60
60
|
"commander": "^14.0.3",
|
|
61
61
|
"dotenv": "^17.4.2",
|
|
62
62
|
"inquirer": "^13.4.2",
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import spawn from "nano-spawn";
|
|
5
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
6
|
+
import { gitOut, mergeScaffolds, threeWayMergePackageJson } from "./merge";
|
|
3
7
|
|
|
4
8
|
const json = (value: unknown) => JSON.stringify(value, null, 2);
|
|
5
9
|
|
|
@@ -79,3 +83,54 @@ describe("threeWayMergePackageJson", () => {
|
|
|
79
83
|
});
|
|
80
84
|
});
|
|
81
85
|
});
|
|
86
|
+
|
|
87
|
+
describe("mergeScaffolds on git 2.38 and 2.39, whose merge-tree has no --merge-base", () => {
|
|
88
|
+
const scratch: string[] = [];
|
|
89
|
+
const path = process.env.PATH;
|
|
90
|
+
|
|
91
|
+
afterEach(() => {
|
|
92
|
+
process.env.PATH = path;
|
|
93
|
+
for (const dir of scratch.splice(0)) rmSync(dir, { recursive: true, force: true });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
function tempDir(files: Record<string, string> = {}): string {
|
|
97
|
+
const dir = mkdtempSync(join(tmpdir(), "mpo-merge-spec-"));
|
|
98
|
+
scratch.push(dir);
|
|
99
|
+
for (const [name, content] of Object.entries(files)) writeFileSync(join(dir, name), content);
|
|
100
|
+
return dir;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
it("merges the scaffold's change into the project through history alone", async () => {
|
|
104
|
+
const shim = tempDir({
|
|
105
|
+
git: `#!/bin/sh\nfor arg in "$@"; do\n case $arg in --merge-base*) exit 129 ;; esac\ndone\nPATH='${path}' exec git "$@"\n`,
|
|
106
|
+
});
|
|
107
|
+
chmodSync(join(shim, "git"), 0o755);
|
|
108
|
+
|
|
109
|
+
const project = tempDir({ "a.txt": "one\n", "b.txt": "b\n", "mine.txt": "mine\n" });
|
|
110
|
+
await spawn("git", ["init", "--quiet"], { cwd: project });
|
|
111
|
+
await spawn("git", ["config", "user.email", "spec@example.com"], { cwd: project });
|
|
112
|
+
await spawn("git", ["config", "user.name", "Spec"], { cwd: project });
|
|
113
|
+
await spawn("git", ["add", "-A"], { cwd: project });
|
|
114
|
+
await spawn("git", ["commit", "--quiet", "-m", "project"], { cwd: project });
|
|
115
|
+
|
|
116
|
+
process.env.PATH = `${shim}:${path}`;
|
|
117
|
+
await expect(
|
|
118
|
+
spawn("git", ["merge-tree", "--write-tree", "--merge-base=HEAD", "HEAD", "HEAD"], {
|
|
119
|
+
cwd: project,
|
|
120
|
+
}),
|
|
121
|
+
).rejects.toMatchObject({ exitCode: 129 });
|
|
122
|
+
|
|
123
|
+
const outcome = await mergeScaffolds({
|
|
124
|
+
projectDir: project,
|
|
125
|
+
baseDir: tempDir({ "a.txt": "one\n", "b.txt": "b\n" }),
|
|
126
|
+
theirsDir: tempDir({ "a.txt": "two\n", "b.txt": "b\n" }),
|
|
127
|
+
baseLabel: "scaffold 1",
|
|
128
|
+
theirsLabel: "scaffold 2",
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(outcome.conflicts).toEqual([]);
|
|
132
|
+
expect(outcome.changed).toBe(true);
|
|
133
|
+
expect(await gitOut(project, ["show", `${outcome.mergedTree}:a.txt`])).toBe("two");
|
|
134
|
+
expect(await gitOut(project, ["show", `${outcome.mergedTree}:mine.txt`])).toBe("mine");
|
|
135
|
+
});
|
|
136
|
+
});
|
package/src/commands/merge.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ours = the project's HEAD (every commit the project made)
|
|
6
6
|
* theirs = the scaffold it is moving to
|
|
7
7
|
*
|
|
8
|
-
* `git merge-tree --write-tree
|
|
8
|
+
* `git merge-tree --write-tree` (git 2.38+) merges the scaffold's
|
|
9
9
|
* evolution with the project's history; the result lands in the index and
|
|
10
10
|
* worktree, never in a commit, so the project commits when it is happy.
|
|
11
11
|
* `.updateignore` entries (exact files or directory prefixes, not globs) and
|
|
@@ -324,6 +324,17 @@ export async function mergeScaffolds(request: MergeRequest): Promise<MergeOutcom
|
|
|
324
324
|
request.theirsLabel,
|
|
325
325
|
baseCommit,
|
|
326
326
|
);
|
|
327
|
+
// merge-tree reads --merge-base only from git 2.40, and Debian bookworm
|
|
328
|
+
// ships 2.39. HEAD's tree on a commit parented by the base hands it the
|
|
329
|
+
// same base through history instead.
|
|
330
|
+
const oursCommit = await gitOut(projectDir, [
|
|
331
|
+
"commit-tree",
|
|
332
|
+
`${head}^{tree}`,
|
|
333
|
+
"-p",
|
|
334
|
+
baseCommit,
|
|
335
|
+
"-m",
|
|
336
|
+
"HEAD",
|
|
337
|
+
]);
|
|
327
338
|
|
|
328
339
|
let mergedTree: string;
|
|
329
340
|
let conflicts: string[] = [];
|
|
@@ -332,8 +343,7 @@ export async function mergeScaffolds(request: MergeRequest): Promise<MergeOutcom
|
|
|
332
343
|
"merge-tree",
|
|
333
344
|
"--write-tree",
|
|
334
345
|
"--name-only",
|
|
335
|
-
|
|
336
|
-
head,
|
|
346
|
+
oursCommit,
|
|
337
347
|
nextCommit,
|
|
338
348
|
]);
|
|
339
349
|
mergedTree = out.split("\n")[0]!.trim();
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* ours = the project's HEAD (every commit the project made)
|
|
6
6
|
* theirs = the scaffold it is moving to
|
|
7
7
|
*
|
|
8
|
-
* `git merge-tree --write-tree
|
|
8
|
+
* `git merge-tree --write-tree` (git 2.38+) merges the scaffold's
|
|
9
9
|
* evolution with the project's history; the result lands in the index and
|
|
10
10
|
* worktree, never in a commit, so the project commits when it is happy.
|
|
11
11
|
* `.updateignore` entries (exact files or directory prefixes, not globs) and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,wBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wCAKzF;AAED,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,mBAG5F;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;AAuED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBrD;AA2ED;0EAC0E;AAC1E,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAerC;AAwDD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8FAA8F;AAC9F,wBAAsB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/commands/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,wBAAsB,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,wCAKzF;AAED,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,mBAG5F;AAED,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIpE;AAED,+EAA+E;AAC/E,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;AAuED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAkBrD;AA2ED;0EAC0E;AAC1E,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAerC;AAwDD,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8FAA8F;AAC9F,wBAAsB,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAqEjF;AAED;2DAC2D;AAC3D,wBAAsB,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAED,gFAAgF;AAChF,wBAAsB,WAAW,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,EACrB,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|