bstack 0.2.0 → 0.2.2

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.
Files changed (2) hide show
  1. package/dist/bstack.js +39 -2
  2. package/package.json +1 -1
package/dist/bstack.js CHANGED
@@ -5,7 +5,7 @@ import { randomUUID } from "node:crypto";
5
5
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
6
6
  import { dirname } from "node:path";
7
7
  //#region package.json
8
- var version = "0.2.0";
8
+ var version = "0.2.2";
9
9
  //#endregion
10
10
  //#region src/command.ts
11
11
  var CommandError = class extends Error {
@@ -411,6 +411,13 @@ var GhPlatform = class {
411
411
  args.push(String(stackNumber), ...branches);
412
412
  this.gh(args);
413
413
  }
414
+ unstack(stackNumber) {
415
+ this.gh([
416
+ "stack",
417
+ "unstack",
418
+ String(stackNumber)
419
+ ]);
420
+ }
414
421
  editPullRequest(pr, change) {
415
422
  if (pr.title === change.subject && pr.body === change.body) return;
416
423
  this.gh([
@@ -552,6 +559,20 @@ function syncStack(repository, github, options) {
552
559
  if (evolution.kind === "full") {
553
560
  reporter.progress(`Linking ${changes.length} pull requests as a native GitHub stack`);
554
561
  github.linkStack(changes.map((change) => change.remoteBranch), base, remote, options.open);
562
+ } else if (evolution.kind === "rebuild") {
563
+ reporter.progress(`Rebuilding stack #${evolution.stackNumber} to insert pull requests`);
564
+ github.unstack(evolution.stackNumber);
565
+ try {
566
+ github.linkStack(changes.map((change) => change.remoteBranch), base, remote, options.open);
567
+ } catch (error) {
568
+ reporter.progress("Rebuild failed; restoring the previous native GitHub stack");
569
+ try {
570
+ github.linkStack(previous.changes.map((change) => change.remoteBranch), base, remote, false);
571
+ } catch (rollbackError) {
572
+ throw new Error(`Stack rebuild failed: ${errorMessage(error)}\nRestoring the previous stack also failed: ${errorMessage(rollbackError)}`);
573
+ }
574
+ throw error;
575
+ }
555
576
  } else if (evolution.kind === "append") {
556
577
  reporter.progress(`Appending ${evolution.branches.length} pull request${evolution.branches.length === 1 ? "" : "s"} to stack #${evolution.stackNumber}`);
557
578
  github.appendToStack(evolution.stackNumber, evolution.branches, remote, options.open);
@@ -568,7 +589,7 @@ function syncStack(repository, github, options) {
568
589
  github.editPullRequest(pr, changes[index]);
569
590
  reporter.progress(`PR #${pr.number}: ${changes[index].subject}`);
570
591
  }
571
- const stackNumber = previous?.stackNumber ?? (pullRequests.length > 1 ? github.stackNumberForPullRequest(pullRequests[0].number) : void 0);
592
+ const stackNumber = evolution.kind === "rebuild" ? github.stackNumberForPullRequest(pullRequests[0].number) : previous?.stackNumber ?? (pullRequests.length > 1 ? github.stackNumberForPullRequest(pullRequests[0].number) : void 0);
572
593
  const synchronizedChanges = changes.map((change, index) => ({
573
594
  id: change.id,
574
595
  remoteBranch: change.remoteBranch,
@@ -597,6 +618,14 @@ function analyzeEvolution(previous, changes, github) {
597
618
  if (!previous) return { kind: "full" };
598
619
  const previousIds = previous.changes.map((change) => change.id);
599
620
  const currentIds = changes.map((change) => change.id);
621
+ if (isSubsequence(previousIds, currentIds)) {
622
+ if (previousIds.every((id, index) => currentIds[index] === id)) return { kind: "full" };
623
+ const stackNumber = previous.stackNumber ?? github.stackNumberForPullRequest(previous.changes[0].pullRequest);
624
+ return stackNumber === void 0 ? { kind: "full" } : {
625
+ kind: "rebuild",
626
+ stackNumber
627
+ };
628
+ }
600
629
  const firstCurrentIndex = previousIds.indexOf(currentIds[0]);
601
630
  if (firstCurrentIndex === -1) throw new Error("The current commits do not continue the previously submitted stack");
602
631
  const removedPrefix = previous.changes.slice(0, firstCurrentIndex);
@@ -618,6 +647,14 @@ function analyzeEvolution(previous, changes, github) {
618
647
  branches: appended.map((change) => change.remoteBranch)
619
648
  };
620
649
  }
650
+ function isSubsequence(expected, actual) {
651
+ let expectedIndex = 0;
652
+ for (const value of actual) if (value === expected[expectedIndex]) expectedIndex++;
653
+ return expectedIndex === expected.length;
654
+ }
655
+ function errorMessage(error) {
656
+ return error instanceof Error ? error.message : String(error);
657
+ }
621
658
  function writeUpdatedState(store, state, previous, updated) {
622
659
  const stacks = previous ? state.stacks.map((stack) => stack === previous ? updated : stack) : [...state.stacks, updated];
623
660
  store.write({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bstack",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "packageManager": "pnpm@11.5.1",
5
5
  "description": "Create native GitHub stacked pull requests from a linear series of commits",
6
6
  "repository": {