@markjaquith/agency 2.74.0 → 3.1.0
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 +29 -122
- package/cli-main.ts +10 -28
- package/cli.ts +1 -17
- package/package.json +1 -2
- package/schemas/agency-graph-v1.schema.json +1 -1
- package/src/cli-parser.test.ts +5 -19
- package/src/cli-parser.ts +12 -30
- package/src/cli.test.ts +6 -6
- package/src/commands/archive.test.ts +73 -1
- package/src/commands/archive.ts +18 -7
- package/src/commands/context.test.ts +0 -67
- package/src/commands/init.test.ts +1 -2
- package/src/commands/pr.test.ts +2 -87
- package/src/commands/pr.ts +2 -79
- package/src/commands/push.test.ts +1 -2
- package/src/graph-schema.ts +1 -1
- package/src/services/ArchiveBulkService.test.ts +1 -142
- package/src/services/ArchiveService.test.ts +1 -172
- package/src/services/ArchiveService.ts +59 -27
- package/src/services/ContextService.ts +3 -47
- package/src/services/DoctorService.ts +8 -24
- package/src/services/GraphService.test.ts +1 -0
- package/src/services/GraphService.ts +2 -5
- package/src/services/PhaseService.ts +70 -191
- package/src/services/PullRequestService.test.ts +1 -45
- package/src/services/PullRequestService.ts +1 -22
- package/src/services/PushService.test.ts +29 -295
- package/src/services/PushService.ts +10 -239
- package/src/services/RepositoryService.test.ts +1 -61
- package/src/services/RepositoryService.ts +2 -13
- package/src/services/ReviewService.test.ts +1 -84
- package/src/services/ReviewService.ts +9 -48
- package/src/services/SyncService.test.ts +0 -81
- package/src/services/SyncService.ts +12 -39
- package/src/services/TaskPhaseService.test.ts +0 -80
- package/src/services/TaskService.ts +1 -9
- package/src/services/VersionControlService.test.ts +4 -117
- package/src/services/VersionControlService.ts +3 -426
- package/src/services/WorkbaseService.test.ts +0 -20
- package/src/services/WorkbaseService.ts +1 -18
- package/src/services/WorktreeService.test.ts +1 -705
- package/src/services/WorktreeService.ts +395 -1604
- package/src/services/push-validation.ts +0 -7
- package/src/test-utils.ts +0 -4
- package/src/workbase/AGENTS.md +4 -5
- package/src/workbase/checkout-command.test.ts +1 -1
- package/src/workbase/checkout-command.ts +1 -1
- package/src/workbase/delivery-command.test.ts +4 -35
- package/src/workbase/delivery-command.ts +2 -15
- package/src/workbase/schemas.test.ts +0 -19
- package/src/workbase/schemas.ts +1 -2
- package/src/commands/vcs.test.ts +0 -75
- package/src/commands/vcs.ts +0 -72
- package/src/services/VcsMigrationService.test.ts +0 -348
- package/src/services/VcsMigrationService.ts +0 -857
- package/src/vcs-status-fast.ts +0 -310
- package/src/workbase/version-control.ts +0 -5
- package/src/workbase/workspace-command.test.ts +0 -70
- package/src/workbase/workspace-command.ts +0 -63
|
@@ -22,18 +22,6 @@ const git = async (args: string[], cwd?: string) => {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const jj = async (args: string[], cwd?: string) => {
|
|
26
|
-
const process = Bun.spawn(["jj", ...args], {
|
|
27
|
-
cwd,
|
|
28
|
-
stdout: "pipe",
|
|
29
|
-
stderr: "pipe",
|
|
30
|
-
})
|
|
31
|
-
await process.exited
|
|
32
|
-
if (process.exitCode !== 0) {
|
|
33
|
-
throw new Error(await new Response(process.stderr).text())
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
25
|
describe("SyncService", () => {
|
|
38
26
|
let root: string
|
|
39
27
|
let originalPath: string | undefined
|
|
@@ -126,75 +114,6 @@ pr: null
|
|
|
126
114
|
expect(await Bun.file(join(root, "repos/agency")).exists()).toBe(false)
|
|
127
115
|
})
|
|
128
116
|
|
|
129
|
-
test("reconciles jj workspaces through the jj backend", async () => {
|
|
130
|
-
if (!Bun.which("jj")) return
|
|
131
|
-
const repository = join(root, "repos/agency")
|
|
132
|
-
await rm(repository, { recursive: true, force: true })
|
|
133
|
-
await jj([
|
|
134
|
-
"git",
|
|
135
|
-
"clone",
|
|
136
|
-
"--no-colocate",
|
|
137
|
-
join(root, "source"),
|
|
138
|
-
repository,
|
|
139
|
-
])
|
|
140
|
-
expect(await Bun.file(join(repository, ".git")).exists()).toBe(false)
|
|
141
|
-
await Bun.write(
|
|
142
|
-
join(root, "agency.json"),
|
|
143
|
-
JSON.stringify({ version: 2, vcs: "jj" }),
|
|
144
|
-
)
|
|
145
|
-
await runTestEffect(
|
|
146
|
-
TaskService.pipe(
|
|
147
|
-
Effect.flatMap((service) =>
|
|
148
|
-
service.create(
|
|
149
|
-
{
|
|
150
|
-
id: "jj-sync",
|
|
151
|
-
ticketUrl: null,
|
|
152
|
-
repo: "agency",
|
|
153
|
-
branch: "task/jj-sync",
|
|
154
|
-
base: "main",
|
|
155
|
-
},
|
|
156
|
-
root,
|
|
157
|
-
),
|
|
158
|
-
),
|
|
159
|
-
),
|
|
160
|
-
)
|
|
161
|
-
const capture = join(root, "gh-capture")
|
|
162
|
-
process.env.GH_CAPTURE = capture
|
|
163
|
-
|
|
164
|
-
const planned = await runTestEffect(
|
|
165
|
-
SyncService.pipe(
|
|
166
|
-
Effect.flatMap((service) => service.reconcile({ cwd: root })),
|
|
167
|
-
),
|
|
168
|
-
)
|
|
169
|
-
expect(planned.changes).toContainEqual(
|
|
170
|
-
expect.objectContaining({
|
|
171
|
-
kind: "materialize-workspace",
|
|
172
|
-
target: "task:jj-sync",
|
|
173
|
-
status: "planned",
|
|
174
|
-
}),
|
|
175
|
-
)
|
|
176
|
-
const invocation = await Bun.file(capture).text()
|
|
177
|
-
expect(invocation).toContain("--repo\n")
|
|
178
|
-
expect(invocation).not.toContain("baseRepository")
|
|
179
|
-
expect(invocation).toContain("GIT_DIR=")
|
|
180
|
-
expect(invocation).toContain(".jj")
|
|
181
|
-
|
|
182
|
-
const applied = await runTestEffect(
|
|
183
|
-
SyncService.pipe(
|
|
184
|
-
Effect.flatMap((service) =>
|
|
185
|
-
service.reconcile({ cwd: root, apply: true }),
|
|
186
|
-
),
|
|
187
|
-
),
|
|
188
|
-
)
|
|
189
|
-
expect(applied.executions[0]?.checkouts[0]).toMatchObject({
|
|
190
|
-
exists: true,
|
|
191
|
-
registered: true,
|
|
192
|
-
branch: "task/jj-sync",
|
|
193
|
-
dirty: false,
|
|
194
|
-
})
|
|
195
|
-
delete process.env.GH_CAPTURE
|
|
196
|
-
})
|
|
197
|
-
|
|
198
117
|
test("observes drift without mutation and applies only safe transitions", async () => {
|
|
199
118
|
await runTestEffect(
|
|
200
119
|
TaskService.pipe(
|
|
@@ -352,7 +352,7 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
352
352
|
const registered: RegisteredWorktree[] = []
|
|
353
353
|
for (const item of listed.right) {
|
|
354
354
|
registered.push({
|
|
355
|
-
head:
|
|
355
|
+
head: item.commit,
|
|
356
356
|
branch: item.branch,
|
|
357
357
|
path: (yield* fs.exists(item.path))
|
|
358
358
|
? yield* fs.realPath(item.path)
|
|
@@ -421,9 +421,6 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
421
421
|
env: resolved.environment,
|
|
422
422
|
})
|
|
423
423
|
} else if (!config.delivery && existing) {
|
|
424
|
-
const environment = yield* Effect.either(
|
|
425
|
-
backend.gitEnvironment(repositoryPath),
|
|
426
|
-
)
|
|
427
424
|
result = yield* runExternal(
|
|
428
425
|
[
|
|
429
426
|
"gh",
|
|
@@ -435,13 +432,10 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
435
432
|
],
|
|
436
433
|
{
|
|
437
434
|
cwd: repositoryPath,
|
|
438
|
-
env:
|
|
435
|
+
env: {},
|
|
439
436
|
},
|
|
440
437
|
)
|
|
441
438
|
} else if (!config.delivery) {
|
|
442
|
-
const environment = yield* Effect.either(
|
|
443
|
-
backend.gitEnvironment(repositoryPath),
|
|
444
|
-
)
|
|
445
439
|
result = yield* runExternal(
|
|
446
440
|
[
|
|
447
441
|
"gh",
|
|
@@ -458,7 +452,7 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
458
452
|
],
|
|
459
453
|
{
|
|
460
454
|
cwd: repositoryPath,
|
|
461
|
-
env:
|
|
455
|
+
env: {},
|
|
462
456
|
},
|
|
463
457
|
)
|
|
464
458
|
}
|
|
@@ -550,34 +544,15 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
550
544
|
: (yield* fs.isDirectory(codePath))
|
|
551
545
|
? join(yield* fs.realPath(codePath), checkout.repo)
|
|
552
546
|
: resolve(checkoutPath)
|
|
553
|
-
|
|
554
|
-
if (backend.kind === "jj" && atPath && "branch" in checkout) {
|
|
555
|
-
atPath = { ...atPath, branch: checkout.branch }
|
|
556
|
-
}
|
|
557
|
-
if (
|
|
558
|
-
backend.kind === "jj" &&
|
|
559
|
-
atPath &&
|
|
560
|
-
exists &&
|
|
561
|
-
atPath.head === null
|
|
562
|
-
) {
|
|
563
|
-
atPath = {
|
|
564
|
-
...atPath,
|
|
565
|
-
head: yield* backend.workspaceHead(checkoutPath),
|
|
566
|
-
}
|
|
567
|
-
}
|
|
547
|
+
const atPath = registered.find((item) => item.path === expectedPath)
|
|
568
548
|
const branchRef =
|
|
569
|
-
"branch" in checkout
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
? registered.find(
|
|
577
|
-
(item) =>
|
|
578
|
-
item.branch === branchRef && item.path !== expectedPath,
|
|
579
|
-
)
|
|
580
|
-
: undefined
|
|
549
|
+
"branch" in checkout ? `refs/heads/${checkout.branch}` : null
|
|
550
|
+
const branchElsewhere = branchRef
|
|
551
|
+
? registered.find(
|
|
552
|
+
(item) =>
|
|
553
|
+
item.branch === branchRef && item.path !== expectedPath,
|
|
554
|
+
)
|
|
555
|
+
: undefined
|
|
581
556
|
if ("branch" in checkout && !exists && !branchElsewhere) {
|
|
582
557
|
const branch = yield* backend.resolveRevision(
|
|
583
558
|
repositoryPath,
|
|
@@ -773,9 +748,7 @@ export class SyncService extends Effect.Service<SyncService>()("SyncService", {
|
|
|
773
748
|
head: checkout.resolvedCommit,
|
|
774
749
|
branch:
|
|
775
750
|
checkout.kind === "writable"
|
|
776
|
-
?
|
|
777
|
-
? checkout.requestedRef
|
|
778
|
-
: `refs/heads/${checkout.requestedRef}`
|
|
751
|
+
? `refs/heads/${checkout.requestedRef}`
|
|
779
752
|
: null,
|
|
780
753
|
dirty: false,
|
|
781
754
|
})
|
|
@@ -7,13 +7,6 @@ import { EpicService } from "./EpicService"
|
|
|
7
7
|
import { TaskService } from "./TaskService"
|
|
8
8
|
import { PhaseService } from "./PhaseService"
|
|
9
9
|
import { PullRequestService } from "./PullRequestService"
|
|
10
|
-
import { WorktreeService } from "./WorktreeService"
|
|
11
|
-
|
|
12
|
-
const run = async (args: string[], cwd?: string) => {
|
|
13
|
-
const child = Bun.spawn(args, { cwd, stdout: "pipe", stderr: "pipe" })
|
|
14
|
-
const exitCode = await child.exited
|
|
15
|
-
if (exitCode !== 0) throw new Error(await new Response(child.stderr).text())
|
|
16
|
-
}
|
|
17
10
|
|
|
18
11
|
describe("task and phase services", () => {
|
|
19
12
|
let root: string
|
|
@@ -528,79 +521,6 @@ describe("task and phase services", () => {
|
|
|
528
521
|
})
|
|
529
522
|
})
|
|
530
523
|
|
|
531
|
-
test("recreates jj workspaces when converting a task to phases", async () => {
|
|
532
|
-
if (!Bun.which("jj")) return
|
|
533
|
-
const source = join(root, "source")
|
|
534
|
-
const repository = join(root, "repos/agency")
|
|
535
|
-
await rm(repository, { recursive: true, force: true })
|
|
536
|
-
await mkdir(source)
|
|
537
|
-
await run(["git", "init", "--initial-branch=main"], source)
|
|
538
|
-
await run(["git", "config", "user.email", "test@example.com"], source)
|
|
539
|
-
await run(["git", "config", "user.name", "Test"], source)
|
|
540
|
-
await Bun.write(join(source, "README.md"), "example\n")
|
|
541
|
-
await run(["git", "add", "README.md"], source)
|
|
542
|
-
await run(["git", "commit", "-m", "initial"], source)
|
|
543
|
-
await run(["git", "clone", source, repository])
|
|
544
|
-
await run(["jj", "git", "init", "--colocate", repository])
|
|
545
|
-
await Bun.write(
|
|
546
|
-
join(root, "agency.json"),
|
|
547
|
-
JSON.stringify({ version: 2, vcs: "jj" }),
|
|
548
|
-
)
|
|
549
|
-
await runTestEffect(
|
|
550
|
-
TaskService.pipe(
|
|
551
|
-
Effect.flatMap((service) =>
|
|
552
|
-
service.create(
|
|
553
|
-
{
|
|
554
|
-
id: "jj-single",
|
|
555
|
-
ticketUrl: null,
|
|
556
|
-
repo: "agency",
|
|
557
|
-
branch: "task/jj-single",
|
|
558
|
-
base: "main",
|
|
559
|
-
},
|
|
560
|
-
root,
|
|
561
|
-
),
|
|
562
|
-
),
|
|
563
|
-
),
|
|
564
|
-
)
|
|
565
|
-
const workspace = await runTestEffect(
|
|
566
|
-
WorktreeService.pipe(
|
|
567
|
-
Effect.flatMap((service) =>
|
|
568
|
-
service.materialize("jj-single", undefined, root),
|
|
569
|
-
),
|
|
570
|
-
),
|
|
571
|
-
)
|
|
572
|
-
|
|
573
|
-
await runTestEffect(
|
|
574
|
-
PhaseService.pipe(
|
|
575
|
-
Effect.flatMap((service) =>
|
|
576
|
-
service.create(
|
|
577
|
-
{
|
|
578
|
-
taskId: "jj-single",
|
|
579
|
-
id: "extra",
|
|
580
|
-
firstPhase: "implementation",
|
|
581
|
-
repo: "agency",
|
|
582
|
-
branch: "task/extra",
|
|
583
|
-
base: "main",
|
|
584
|
-
},
|
|
585
|
-
root,
|
|
586
|
-
),
|
|
587
|
-
),
|
|
588
|
-
),
|
|
589
|
-
)
|
|
590
|
-
|
|
591
|
-
const moved = join(
|
|
592
|
-
root,
|
|
593
|
-
"tasks/jj-single/phases/implementation/code/agency",
|
|
594
|
-
)
|
|
595
|
-
expect(await Bun.file(workspace.codePath).exists()).toBe(false)
|
|
596
|
-
expect(await Bun.file(join(moved, "README.md")).text()).toBe("example\n")
|
|
597
|
-
const listed = Bun.spawnSync(
|
|
598
|
-
["jj", "-R", repository, "workspace", "list", "-T", 'root ++ "\\n"'],
|
|
599
|
-
{ stdout: "pipe" },
|
|
600
|
-
)
|
|
601
|
-
expect(new TextDecoder().decode(listed.stdout)).toContain(moved)
|
|
602
|
-
})
|
|
603
|
-
|
|
604
524
|
test("preserves non-PR completion when converting a task to phases", async () => {
|
|
605
525
|
await runTestEffect(
|
|
606
526
|
TaskService.pipe(
|
|
@@ -4,7 +4,6 @@ import { readdir } from "node:fs/promises"
|
|
|
4
4
|
import { join } from "node:path"
|
|
5
5
|
import { FileSystemService } from "./FileSystemService"
|
|
6
6
|
import { WorkbaseService, type ValidationReport } from "./WorkbaseService"
|
|
7
|
-
import { VersionControlService } from "./VersionControlService"
|
|
8
7
|
import { EpicService, type EpicRecord } from "./EpicService"
|
|
9
8
|
import {
|
|
10
9
|
EntityId,
|
|
@@ -231,7 +230,6 @@ export class TaskService extends Effect.Service<TaskService>()("TaskService", {
|
|
|
231
230
|
const fs = yield* FileSystemService
|
|
232
231
|
const workbase = yield* WorkbaseService
|
|
233
232
|
const epics = yield* EpicService
|
|
234
|
-
const versionControl = yield* VersionControlService
|
|
235
233
|
const root = yield* workbase.discover(startPath)
|
|
236
234
|
const id = yield* decodeId(input.id)
|
|
237
235
|
const directory = join(root, "tasks", id)
|
|
@@ -375,13 +373,7 @@ export class TaskService extends Effect.Service<TaskService>()("TaskService", {
|
|
|
375
373
|
const updated = formatMarkdownDocument(epicData, parsed.body)
|
|
376
374
|
writes.push({ path: parentEpic.path, content: updated })
|
|
377
375
|
}
|
|
378
|
-
|
|
379
|
-
if (input.review) {
|
|
380
|
-
const backend = yield* versionControl.forWorkbase(root)
|
|
381
|
-
reviewEnvironment = yield* backend.gitEnvironment(
|
|
382
|
-
join(root, "repos", input.review.repo),
|
|
383
|
-
)
|
|
384
|
-
}
|
|
376
|
+
const reviewEnvironment: Record<string, string> = {}
|
|
385
377
|
yield* runLifecycleTransaction({
|
|
386
378
|
root,
|
|
387
379
|
preconditions: [
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from "bun:test"
|
|
2
2
|
import { Effect, Layer } from "effect"
|
|
3
|
-
import { mkdir, realpath, stat } from "node:fs/promises"
|
|
4
3
|
import { join } from "node:path"
|
|
5
4
|
import { cleanupTempDir, createTempDir, runTestEffect } from "../test-utils"
|
|
6
5
|
import {
|
|
@@ -8,13 +7,6 @@ import {
|
|
|
8
7
|
VersionControlService,
|
|
9
8
|
} from "./VersionControlService"
|
|
10
9
|
import { FileSystemService } from "./FileSystemService"
|
|
11
|
-
import { preferredVersionControl } from "../workbase/version-control"
|
|
12
|
-
|
|
13
|
-
const run = async (args: string[], cwd?: string) => {
|
|
14
|
-
const child = Bun.spawn(args, { cwd, stdout: "pipe", stderr: "pipe" })
|
|
15
|
-
const exitCode = await child.exited
|
|
16
|
-
if (exitCode !== 0) throw new Error(await new Response(child.stderr).text())
|
|
17
|
-
}
|
|
18
10
|
|
|
19
11
|
describe("VersionControlService", () => {
|
|
20
12
|
const roots: string[] = []
|
|
@@ -23,11 +15,6 @@ describe("VersionControlService", () => {
|
|
|
23
15
|
await Promise.all(roots.splice(0).map(cleanupTempDir))
|
|
24
16
|
})
|
|
25
17
|
|
|
26
|
-
test("prefers jj when available and falls back to Git", () => {
|
|
27
|
-
expect(preferredVersionControl(() => "/usr/bin/jj")).toBe("jj")
|
|
28
|
-
expect(preferredVersionControl(() => null)).toBe("git")
|
|
29
|
-
})
|
|
30
|
-
|
|
31
18
|
test("inspects a Git repository with one subprocess", async () => {
|
|
32
19
|
const commands: readonly string[][] = []
|
|
33
20
|
const fileSystem = {
|
|
@@ -61,115 +48,15 @@ describe("VersionControlService", () => {
|
|
|
61
48
|
})
|
|
62
49
|
})
|
|
63
50
|
|
|
64
|
-
test("selects
|
|
65
|
-
for (const kind of ["git", "jj"] as const) {
|
|
66
|
-
const root = await createTempDir()
|
|
67
|
-
roots.push(root)
|
|
68
|
-
await Bun.write(
|
|
69
|
-
join(root, "agency.json"),
|
|
70
|
-
JSON.stringify({ version: 2, vcs: kind }),
|
|
71
|
-
)
|
|
72
|
-
const selected = await runTestEffect(
|
|
73
|
-
VersionControlService.pipe(
|
|
74
|
-
Effect.flatMap((service) => service.forWorkbase(root)),
|
|
75
|
-
),
|
|
76
|
-
)
|
|
77
|
-
expect(selected.kind).toBe(kind)
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
test("initializes and manages jj workspaces", async () => {
|
|
82
|
-
if (!Bun.which("jj")) return
|
|
83
|
-
const root = await createTempDir()
|
|
84
|
-
roots.push(root)
|
|
85
|
-
await Bun.write(
|
|
86
|
-
join(root, "agency.json"),
|
|
87
|
-
JSON.stringify({ version: 2, vcs: "jj" }),
|
|
88
|
-
)
|
|
89
|
-
const repository = join(root, "repository")
|
|
90
|
-
const workspace = join(root, "workspace")
|
|
91
|
-
await mkdir(repository)
|
|
92
|
-
await run(["git", "init", "--initial-branch=main"], repository)
|
|
93
|
-
await run(["git", "config", "user.email", "test@example.com"], repository)
|
|
94
|
-
await run(["git", "config", "user.name", "Test"], repository)
|
|
95
|
-
await Bun.write(join(repository, "README.md"), "example\n")
|
|
96
|
-
await run(["git", "add", "README.md"], repository)
|
|
97
|
-
await run(["git", "commit", "-m", "initial"], repository)
|
|
98
|
-
|
|
99
|
-
const backend = await runTestEffect(
|
|
100
|
-
VersionControlService.pipe(
|
|
101
|
-
Effect.flatMap((service) => service.forWorkbase(root)),
|
|
102
|
-
),
|
|
103
|
-
)
|
|
104
|
-
await runTestEffect(backend.initializeRepository(repository))
|
|
105
|
-
expect((await stat(join(repository, ".jj"))).isDirectory()).toBe(true)
|
|
106
|
-
|
|
107
|
-
const revision = await runTestEffect(
|
|
108
|
-
backend.resolveRevision(repository, "main"),
|
|
109
|
-
)
|
|
110
|
-
expect(revision).toMatch(/^[0-9a-f]{40}$/)
|
|
111
|
-
await runTestEffect(
|
|
112
|
-
backend.createWorkspace({
|
|
113
|
-
repositoryPath: repository,
|
|
114
|
-
workspacePath: workspace,
|
|
115
|
-
workspaceName: "agency-test",
|
|
116
|
-
revision: revision!,
|
|
117
|
-
branch: "task/test",
|
|
118
|
-
}),
|
|
119
|
-
)
|
|
120
|
-
const canonicalWorkspace = await realpath(workspace)
|
|
121
|
-
expect(
|
|
122
|
-
(await runTestEffect(backend.listWorkspaces(repository))).some(
|
|
123
|
-
(item) =>
|
|
124
|
-
item.name === "agency-test" && item.path === canonicalWorkspace,
|
|
125
|
-
),
|
|
126
|
-
).toBe(true)
|
|
127
|
-
|
|
128
|
-
await runTestEffect(
|
|
129
|
-
backend.removeWorkspace({
|
|
130
|
-
repositoryPath: repository,
|
|
131
|
-
workspacePath: workspace,
|
|
132
|
-
workspaceName: "agency-test",
|
|
133
|
-
}),
|
|
134
|
-
)
|
|
135
|
-
expect(await Bun.file(workspace).exists()).toBe(false)
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
test("clones non-colocated jj repositories and exposes their backing Git directory", async () => {
|
|
139
|
-
if (!Bun.which("jj")) return
|
|
51
|
+
test("selects Git for legacy and explicit Git workbases", async () => {
|
|
140
52
|
const root = await createTempDir()
|
|
141
53
|
roots.push(root)
|
|
142
|
-
await Bun.write(
|
|
143
|
-
|
|
144
|
-
JSON.stringify({ version: 2, vcs: "jj" }),
|
|
145
|
-
)
|
|
146
|
-
const source = join(root, "source")
|
|
147
|
-
const repository = join(root, "repository")
|
|
148
|
-
await mkdir(source)
|
|
149
|
-
await run(["git", "init", "--initial-branch=main"], source)
|
|
150
|
-
await run(["git", "config", "user.email", "test@example.com"], source)
|
|
151
|
-
await run(["git", "config", "user.name", "Test"], source)
|
|
152
|
-
await Bun.write(join(source, "README.md"), "example\n")
|
|
153
|
-
await run(["git", "add", "README.md"], source)
|
|
154
|
-
await run(["git", "commit", "-m", "initial"], source)
|
|
155
|
-
|
|
156
|
-
const backend = await runTestEffect(
|
|
54
|
+
await Bun.write(join(root, "agency.json"), JSON.stringify({ version: 2 }))
|
|
55
|
+
const selected = await runTestEffect(
|
|
157
56
|
VersionControlService.pipe(
|
|
158
57
|
Effect.flatMap((service) => service.forWorkbase(root)),
|
|
159
58
|
),
|
|
160
59
|
)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
expect((await stat(join(repository, ".jj"))).isDirectory()).toBe(true)
|
|
164
|
-
expect(await Bun.file(join(repository, ".git")).exists()).toBe(false)
|
|
165
|
-
const environment: Record<string, string> = await runTestEffect(
|
|
166
|
-
backend.gitEnvironment(repository),
|
|
167
|
-
)
|
|
168
|
-
expect(environment.GIT_DIR).toContain(join(repository, ".jj"))
|
|
169
|
-
expect((await stat(environment.GIT_DIR!)).isDirectory()).toBe(true)
|
|
170
|
-
expect(await runTestEffect(backend.inspectRepository(repository))).toEqual({
|
|
171
|
-
kind: "repository",
|
|
172
|
-
remote: await realpath(source),
|
|
173
|
-
})
|
|
60
|
+
expect(selected.kind).toBe("git")
|
|
174
61
|
})
|
|
175
62
|
})
|