@cvr/stacked 0.4.4 → 0.6.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/bin/stacked +0 -0
- package/package.json +1 -1
- package/skills/stacked/SKILL.md +27 -13
- package/src/commands/adopt.ts +9 -0
- package/src/commands/amend.ts +54 -18
- package/src/commands/clean.ts +6 -4
- package/src/commands/create.ts +4 -0
- package/src/commands/delete.ts +1 -0
- package/src/commands/detect.ts +68 -9
- package/src/commands/doctor.ts +34 -5
- package/src/commands/helpers/pr-metadata.ts +12 -4
- package/src/commands/index.ts +1 -1
- package/src/commands/init.ts +19 -10
- package/src/commands/log.ts +12 -2
- package/src/commands/reorder.ts +2 -0
- package/src/commands/stacks.ts +2 -2
- package/src/commands/submit.ts +33 -6
- package/src/commands/sync.ts +130 -35
- package/src/errors/index.ts +2 -0
- package/src/main.ts +15 -5
- package/src/services/Git.ts +39 -4
- package/src/services/GitEs.ts +104 -12
- package/src/services/Stack.ts +62 -18
package/src/services/Stack.ts
CHANGED
|
@@ -22,6 +22,7 @@ const StackRecordSchema = Schema.Struct({
|
|
|
22
22
|
const BranchRecordSchema = Schema.Struct({
|
|
23
23
|
stack: Schema.String,
|
|
24
24
|
parent: Schema.NullOr(Schema.String),
|
|
25
|
+
syncedOnto: Schema.optional(Schema.NullOr(Schema.String)),
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
const StackFileV2Schema = Schema.Struct({
|
|
@@ -54,7 +55,14 @@ interface CanonicalStackFile {
|
|
|
54
55
|
readonly trunk: string;
|
|
55
56
|
readonly stacks: Readonly<Record<string, { readonly root: string }>>;
|
|
56
57
|
readonly branches: Readonly<
|
|
57
|
-
Record<
|
|
58
|
+
Record<
|
|
59
|
+
string,
|
|
60
|
+
{
|
|
61
|
+
readonly stack: string;
|
|
62
|
+
readonly parent: string | null;
|
|
63
|
+
readonly syncedOnto?: string | null | undefined;
|
|
64
|
+
}
|
|
65
|
+
>
|
|
58
66
|
>;
|
|
59
67
|
readonly mergedBranches: readonly string[];
|
|
60
68
|
}
|
|
@@ -224,7 +232,10 @@ const rewriteStackBranches = (
|
|
|
224
232
|
stackName: string,
|
|
225
233
|
branches: readonly string[],
|
|
226
234
|
): CanonicalStackFile => {
|
|
227
|
-
const nextBranches: Record<
|
|
235
|
+
const nextBranches: Record<
|
|
236
|
+
string,
|
|
237
|
+
{ stack: string; parent: string | null; syncedOnto?: string | null }
|
|
238
|
+
> = {
|
|
228
239
|
...data.branches,
|
|
229
240
|
};
|
|
230
241
|
|
|
@@ -237,9 +248,11 @@ const rewriteStackBranches = (
|
|
|
237
248
|
for (let i = 0; i < branches.length; i++) {
|
|
238
249
|
const branch = branches[i];
|
|
239
250
|
if (branch === undefined) continue;
|
|
251
|
+
const existing = data.branches[branch];
|
|
240
252
|
nextBranches[branch] = {
|
|
241
253
|
stack: stackName,
|
|
242
254
|
parent: i === 0 ? null : (branches[i - 1] ?? null),
|
|
255
|
+
...(existing?.syncedOnto != null ? { syncedOnto: existing.syncedOnto } : {}),
|
|
243
256
|
};
|
|
244
257
|
}
|
|
245
258
|
|
|
@@ -252,10 +265,8 @@ const rewriteStackBranches = (
|
|
|
252
265
|
};
|
|
253
266
|
}
|
|
254
267
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return data;
|
|
258
|
-
}
|
|
268
|
+
// branches.length > 0 guaranteed by the early return above
|
|
269
|
+
const root = branches[0] as string;
|
|
259
270
|
|
|
260
271
|
return {
|
|
261
272
|
...data,
|
|
@@ -276,7 +287,10 @@ const renameStackRefs = (
|
|
|
276
287
|
if (stackRecord === undefined) return data;
|
|
277
288
|
|
|
278
289
|
const { [oldName]: _, ...restStacks } = data.stacks;
|
|
279
|
-
const branches: Record<
|
|
290
|
+
const branches: Record<
|
|
291
|
+
string,
|
|
292
|
+
{ stack: string; parent: string | null; syncedOnto?: string | null }
|
|
293
|
+
> = {};
|
|
280
294
|
|
|
281
295
|
for (const [branch, record] of Object.entries(data.branches)) {
|
|
282
296
|
branches[branch] = {
|
|
@@ -586,6 +600,33 @@ const makeStackService = ({
|
|
|
586
600
|
});
|
|
587
601
|
}),
|
|
588
602
|
|
|
603
|
+
getSyncedOnto: Effect.fn("StackService.getSyncedOnto")(function* (branch: string) {
|
|
604
|
+
const data = yield* loadData();
|
|
605
|
+
const record = data.branches[branch];
|
|
606
|
+
if (record === undefined) return null;
|
|
607
|
+
return record.syncedOnto ?? null;
|
|
608
|
+
}),
|
|
609
|
+
|
|
610
|
+
updateSyncedOnto: Effect.fn("StackService.updateSyncedOnto")(function* (
|
|
611
|
+
branch: string,
|
|
612
|
+
oid: string | null,
|
|
613
|
+
) {
|
|
614
|
+
const data = yield* loadData();
|
|
615
|
+
const record = data.branches[branch];
|
|
616
|
+
if (record === undefined) {
|
|
617
|
+
return yield* new StackError({
|
|
618
|
+
message: `Branch "${branch}" not found in stack metadata`,
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
yield* saveData({
|
|
622
|
+
...data,
|
|
623
|
+
branches: {
|
|
624
|
+
...data.branches,
|
|
625
|
+
[branch]: { ...record, syncedOnto: oid },
|
|
626
|
+
},
|
|
627
|
+
});
|
|
628
|
+
}),
|
|
629
|
+
|
|
589
630
|
getTrunk: Effect.fn("StackService.getTrunk")(function* () {
|
|
590
631
|
const data = yield* loadData();
|
|
591
632
|
return data.trunk;
|
|
@@ -632,25 +673,28 @@ export class StackService extends ServiceMap.Service<
|
|
|
632
673
|
branch: string,
|
|
633
674
|
) => Effect.Effect<{ name: string; stack: Stack } | null, StackError>;
|
|
634
675
|
readonly detectTrunkCandidate: () => Effect.Effect<Option.Option<string>, never>;
|
|
676
|
+
readonly getSyncedOnto: (branch: string) => Effect.Effect<string | null, StackError>;
|
|
677
|
+
readonly updateSyncedOnto: (
|
|
678
|
+
branch: string,
|
|
679
|
+
oid: string | null,
|
|
680
|
+
) => Effect.Effect<void, StackError>;
|
|
635
681
|
readonly getTrunk: () => Effect.Effect<string, StackError>;
|
|
636
682
|
readonly setTrunk: (name: string) => Effect.Effect<void, StackError>;
|
|
637
683
|
}
|
|
638
684
|
>()("@cvr/stacked/services/Stack/StackService") {
|
|
639
|
-
static layer: Layer.Layer<StackService,
|
|
685
|
+
static layer: Layer.Layer<StackService, StackError, GitService> = Layer.effect(
|
|
640
686
|
StackService,
|
|
641
687
|
Effect.gen(function* () {
|
|
642
688
|
const git = yield* GitService;
|
|
643
689
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
return `${gitDir}/stacked.json`;
|
|
653
|
-
});
|
|
690
|
+
// Resolve git dir once at construction time, then capture in closure
|
|
691
|
+
const gitDir = yield* git
|
|
692
|
+
.revParse("--absolute-git-dir")
|
|
693
|
+
.pipe(
|
|
694
|
+
Effect.mapError((e) => new StackError({ message: `Not a git repository: ${e.message}` })),
|
|
695
|
+
);
|
|
696
|
+
const resolvedStackFilePath = `${gitDir}/stacked.json`;
|
|
697
|
+
const stackFilePath = () => Effect.succeed(resolvedStackFilePath);
|
|
654
698
|
|
|
655
699
|
const StackFileJson = Schema.fromJsonString(
|
|
656
700
|
Schema.Union([StackFileV1Schema, StackFileV2Schema]),
|