@akanjs/devkit 3.0.0-alpha.112 → 3.0.0-alpha.113

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akanjs/devkit",
3
- "version": "3.0.0-alpha.112",
3
+ "version": "3.0.0-alpha.113",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -44,7 +44,7 @@
44
44
  "@langchain/openai": "^1.4.6",
45
45
  "@tailwindcss/node": "^4.3.0",
46
46
  "@trapezedev/project": "^7.1.4",
47
- "akanjs": "3.0.0-alpha.112",
47
+ "akanjs": "3.0.0-alpha.113",
48
48
  "chalk": "^5.6.2",
49
49
  "commander": "^14.0.3",
50
50
  "dayjs": "^1.11.20",
package/subspace.test.ts CHANGED
@@ -202,6 +202,21 @@ describe("Subspace push", () => {
202
202
  expect(manifest.akan.source.hash).toMatch(/^[0-9a-f]{32}$/);
203
203
  });
204
204
 
205
+ test("ships a library file the workspace deleted, instead of reading it off the clone's stale index", async () => {
206
+ const { wsRoot, bareRoot, workRoot, subspace } = await makeMirror("moved-served", "moved-private", "moved-kit");
207
+ expect((await subspace.push("develop", { verify: false })).outcome).toBe("pushed");
208
+
209
+ await rm(path.join(wsRoot, "libs/moved-kit/common/helper.ts"));
210
+ await write(path.join(wsRoot, "libs/moved-kit/common/renamed.ts"), "export const helper = 1;\n");
211
+ await git(wsRoot, ["add", "-A"]);
212
+ await git(wsRoot, ["commit", "--quiet", "-m", "move the helper"]);
213
+
214
+ expect((await subspace.push("develop", { verify: false })).outcome).toBe("pushed");
215
+ const subspaceRoot = await cloneSubspace(workRoot, bareRoot, "moved-check");
216
+ expect(await FileSys.fileExists(path.join(subspaceRoot, "libs/moved-kit/common/helper.ts"))).toBe(false);
217
+ expect(await FileSys.fileExists(path.join(subspaceRoot, "libs/moved-kit/common/renamed.ts"))).toBe(true);
218
+ });
219
+
205
220
  test("is idempotent — a second push with no workspace change is skipped", async () => {
206
221
  const { subspace } = await makeMirror("idem-served", "idem-private", "idem-kit");
207
222
  expect((await subspace.push("develop", { verify: false })).outcome).toBe("pushed");
package/subspace.ts CHANGED
@@ -232,7 +232,7 @@ export class Subspace {
232
232
  }
233
233
  const clone = new Executor(`subspace-${this.name}`, this.#clonePath);
234
234
  await clone.spawn("git", ["fetch", "--quiet", "origin", branch]);
235
- await clone.spawn("git", ["checkout", "--quiet", "-B", branch, `origin/${branch}`]);
235
+ await clone.spawn("git", ["checkout", "--quiet", "-f", "-B", branch, `origin/${branch}`]);
236
236
  await clone.spawn("git", ["clean", "-qfd"]);
237
237
  return clone;
238
238
  }
@@ -462,10 +462,17 @@ export class Subspace {
462
462
  "--",
463
463
  `libs/${lib}`,
464
464
  ]);
465
- const files = listed
465
+ const candidates = listed
466
466
  .split("\0")
467
467
  .filter((file) => !!file && !this.#isSubspaceOwned(file))
468
468
  .sort();
469
+ //* `--cached` reads the clone's index, which the slice replaced the members without updating — so it still
470
+ //* names every file the workspace has deleted or moved since the last push, and opening one throws. The
471
+ //* index is only reconciled by the `git add -A` a push commits with, long after the stamp is written.
472
+ const present = await Promise.all(
473
+ candidates.map(async (file) => await FileSys.entryExists(path.join(this.#clonePath, file))),
474
+ );
475
+ const files = candidates.filter((_, index) => present[index]);
469
476
  const hasher = new Bun.CryptoHasher("sha256");
470
477
  for (const file of files) {
471
478
  const content = await FileSys.readText(path.join(this.#clonePath, file));