git-stack-cli 2.7.8 → 2.8.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.
@@ -14,10 +14,16 @@ type CommitGroup = {
14
14
  base: null | string;
15
15
  dirty: boolean;
16
16
  commits: Array<git.Commit>;
17
+ master_base: boolean;
17
18
  };
18
19
 
19
- export type SimpleGroup = { id: string; title: string };
20
- type CommitGroupMap = { [sha: string]: SimpleGroup };
20
+ type CommitRangeGroup = {
21
+ id: string;
22
+ title: string;
23
+ master_base: boolean;
24
+ };
25
+
26
+ type CommitGroupMap = { [sha: string]: CommitRangeGroup };
21
27
 
22
28
  export async function range(commit_group_map?: CommitGroupMap) {
23
29
  // gather all open prs in repo first
@@ -25,6 +31,7 @@ export async function range(commit_group_map?: CommitGroupMap) {
25
31
  await github.pr_list();
26
32
 
27
33
  const master_branch = Store.getState().master_branch;
34
+ const master_branch_name = master_branch.replace(/^origin\//, "");
28
35
  const commit_list = await git.get_commits(`${master_branch}..HEAD`);
29
36
 
30
37
  const pr_lookup: Record<string, void | PullRequest> = {};
@@ -37,6 +44,7 @@ export async function range(commit_group_map?: CommitGroupMap) {
37
44
  for (const commit of commit_list) {
38
45
  let id = commit.branch_id;
39
46
  let title = commit.title || id;
47
+ let master_base = commit.master_base;
40
48
 
41
49
  // console.debug({ commit, id });
42
50
 
@@ -47,6 +55,7 @@ export async function range(commit_group_map?: CommitGroupMap) {
47
55
  if (group) {
48
56
  id = group.id;
49
57
  title = group.title;
58
+ master_base = group.master_base;
50
59
  }
51
60
  }
52
61
 
@@ -75,6 +84,7 @@ export async function range(commit_group_map?: CommitGroupMap) {
75
84
  const group = group_map.get(id) || {
76
85
  id,
77
86
  title,
87
+ master_base,
78
88
  pr: null,
79
89
  base: null,
80
90
  dirty: false,
@@ -111,6 +121,7 @@ export async function range(commit_group_map?: CommitGroupMap) {
111
121
 
112
122
  for (let i = 0; i < group_value_list.length; i++) {
113
123
  const group = group_value_list[i];
124
+ const previous_group: undefined | CommitGroup = group_value_list[i - 1];
114
125
 
115
126
  if (group.id !== UNASSIGNED) {
116
127
  let pr_result = pr_lookup[group.id];
@@ -130,17 +141,20 @@ export async function range(commit_group_map?: CommitGroupMap) {
130
141
  }
131
142
 
132
143
  if (i === 0) {
133
- const master_branch_name = master_branch.replace(/^origin\//, "");
134
144
  group.base = master_branch_name;
135
145
  } else {
136
146
  const last_group = group_value_list[i - 1];
137
147
  // console.debug(" ", "last_group", last_group.pr?.title.substring(0, 40));
138
148
  // console.debug(" ", "last_group.id", last_group.id);
139
149
 
140
- // null out base when unassigned and after unassigned
141
- if (group.id === UNASSIGNED) {
150
+ if (group.master_base) {
151
+ // explicitly set base to master when master_base is true
152
+ group.base = master_branch_name;
153
+ } else if (group.id === UNASSIGNED) {
154
+ // null out base when unassigned and after unassigned
142
155
  group.base = null;
143
156
  } else if (last_group.base === null) {
157
+ // null out base when last group base is null
144
158
  group.base = null;
145
159
  } else {
146
160
  group.base = last_group.id;
@@ -151,17 +165,61 @@ export async function range(commit_group_map?: CommitGroupMap) {
151
165
 
152
166
  if (!group.pr) {
153
167
  group.dirty = true;
154
- } else if (group.pr.commits.length !== group.commits.length) {
155
- group.dirty = true;
156
- } else if (group.pr.baseRefName !== group.base) {
157
- group.dirty = true;
158
168
  } else {
159
- for (let i = 0; i < group.pr.commits.length; i++) {
160
- const pr_commit = group.pr.commits[i];
161
- const local_commit = group.commits[i];
169
+ if (group.pr.baseRefName !== group.base) {
170
+ group.dirty = true;
171
+ } else if (group.master_base && i > 0) {
172
+ // special case
173
+ // master_base groups cannot be compared by commit sha
174
+ // instead compare the literal diff local against origin
175
+ // gh pr diff --color=never 110
176
+ // git --no-pager diff --color=never 00c8fe0~1..00c8fe0
177
+ const diff_github = await github.pr_diff(group.pr.number);
178
+ const diff_local = await git.get_diff(group.commits);
179
+ if (diff_github !== diff_local) {
180
+ group.dirty = true;
181
+ }
182
+ } else if (!group.master_base && previous_group && previous_group.master_base) {
183
+ // special case
184
+ // boundary between normal commits and master commits
185
+
186
+ // collect all previous groups for sha comparison
187
+ const all_commits: Array<git.Commit> = [];
188
+ const previous_groups = group_value_list.slice(0, i);
189
+ for (const g of previous_groups) {
190
+ for (const c of g.commits) {
191
+ all_commits.push(c);
192
+ }
193
+ }
194
+ for (const c of group.commits) {
195
+ all_commits.push(c);
196
+ }
162
197
 
163
- if (pr_commit.oid !== local_commit.sha) {
198
+ // compare all commits against pr commits
199
+ if (group.pr.commits.length !== all_commits.length) {
164
200
  group.dirty = true;
201
+ } else {
202
+ for (let i = 0; i < group.pr.commits.length; i++) {
203
+ const pr_commit = group.pr.commits[i];
204
+ const local_commit = all_commits[i];
205
+
206
+ if (pr_commit.oid !== local_commit.sha) {
207
+ group.dirty = true;
208
+ }
209
+ }
210
+ }
211
+ } else if (group.pr.commits.length !== group.commits.length) {
212
+ group.dirty = true;
213
+ } else {
214
+ // if we still haven't marked this dirty, check each commit
215
+ // comapre literal commit shas in group
216
+ for (let i = 0; i < group.pr.commits.length; i++) {
217
+ const pr_commit = group.pr.commits[i];
218
+ const local_commit = group.commits[i];
219
+
220
+ if (pr_commit.oid !== local_commit.sha) {
221
+ group.dirty = true;
222
+ }
165
223
  }
166
224
  }
167
225
  }
@@ -171,8 +171,10 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
171
171
  subject_line: "banana color",
172
172
  branch_id: "AAWsYx1UU",
173
173
  title: "banana",
174
+ master_base: false,
174
175
  },
175
176
  ],
177
+ master_base: false,
176
178
  },
177
179
  {
178
180
  id: "E63ytp5dj",
@@ -244,6 +246,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
244
246
  subject_line: "lemon color",
245
247
  branch_id: "E63ytp5dj",
246
248
  title: "lemon color",
249
+ master_base: false,
247
250
  },
248
251
  {
249
252
  sha: "d36d63499425bb46a1e62c2c9df1a4332b13004f",
@@ -251,6 +254,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
251
254
  subject_line: "cantaloupe color",
252
255
  branch_id: "E63ytp5dj",
253
256
  title: "lemon color",
257
+ master_base: false,
254
258
  },
255
259
  {
256
260
  sha: "4f98dd3e67d03b79d7a12480c7d1c2fcbd186ac5",
@@ -258,6 +262,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
258
262
  subject_line: "banana sweet",
259
263
  branch_id: "E63ytp5dj",
260
264
  title: "lemon color",
265
+ master_base: false,
261
266
  },
262
267
  {
263
268
  sha: "f143d03c723c9f5231a81c1e12098511611898cb",
@@ -265,8 +270,10 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
265
270
  subject_line: "apple sweet",
266
271
  branch_id: "E63ytp5dj",
267
272
  title: "lemon color",
273
+ master_base: false,
268
274
  },
269
275
  ],
276
+ master_base: false,
270
277
  },
271
278
  ],
272
279
  commit_list: [
@@ -276,6 +283,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
276
283
  subject_line: "banana color",
277
284
  branch_id: "AAWsYx1UU",
278
285
  title: "banana",
286
+ master_base: false,
279
287
  },
280
288
  {
281
289
  sha: "3cb22661ecff6c872e96ce9c40b31c824938cab7",
@@ -283,6 +291,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
283
291
  subject_line: "lemon color",
284
292
  branch_id: "E63ytp5dj",
285
293
  title: "lemon color",
294
+ master_base: false,
286
295
  },
287
296
  {
288
297
  sha: "d36d63499425bb46a1e62c2c9df1a4332b13004f",
@@ -290,6 +299,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
290
299
  subject_line: "cantaloupe color",
291
300
  branch_id: "E63ytp5dj",
292
301
  title: "lemon color",
302
+ master_base: false,
293
303
  },
294
304
  {
295
305
  sha: "4f98dd3e67d03b79d7a12480c7d1c2fcbd186ac5",
@@ -297,6 +307,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
297
307
  subject_line: "banana sweet",
298
308
  branch_id: "E63ytp5dj",
299
309
  title: "lemon color",
310
+ master_base: false,
300
311
  },
301
312
  {
302
313
  sha: "f143d03c723c9f5231a81c1e12098511611898cb",
@@ -304,6 +315,7 @@ const SINGLE_COMMIT_EXISTING_GROUP: CommitMetadata.CommitRange = {
304
315
  subject_line: "apple sweet",
305
316
  branch_id: "6Ak-qn+5Z",
306
317
  title: "new group",
318
+ master_base: false,
307
319
  },
308
320
  ],
309
321
  pr_lookup: {
@@ -440,8 +452,10 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
440
452
  subject_line: "banana color",
441
453
  branch_id: "AAWsYx1UU",
442
454
  title: "banana",
455
+ master_base: false,
443
456
  },
444
457
  ],
458
+ master_base: false,
445
459
  },
446
460
  {
447
461
  id: "E63ytp5dj",
@@ -513,6 +527,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
513
527
  subject_line: "lemon color",
514
528
  branch_id: "E63ytp5dj",
515
529
  title: "lemon color",
530
+ master_base: false,
516
531
  },
517
532
  {
518
533
  sha: "d36d63499425bb46a1e62c2c9df1a4332b13004f",
@@ -520,6 +535,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
520
535
  subject_line: "cantaloupe color",
521
536
  branch_id: "E63ytp5dj",
522
537
  title: "lemon color",
538
+ master_base: false,
523
539
  },
524
540
  {
525
541
  sha: "4f98dd3e67d03b79d7a12480c7d1c2fcbd186ac5",
@@ -527,8 +543,10 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
527
543
  subject_line: "banana sweet",
528
544
  branch_id: "E63ytp5dj",
529
545
  title: "lemon color",
546
+ master_base: false,
530
547
  },
531
548
  ],
549
+ master_base: false,
532
550
  },
533
551
  {
534
552
  id: "6Ak-qn+5Z",
@@ -543,8 +561,10 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
543
561
  subject_line: "apple sweet",
544
562
  branch_id: "6Ak-qn+5Z",
545
563
  title: "new group",
564
+ master_base: false,
546
565
  },
547
566
  ],
567
+ master_base: false,
548
568
  },
549
569
  ],
550
570
  commit_list: [
@@ -554,6 +574,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
554
574
  subject_line: "banana color",
555
575
  branch_id: "AAWsYx1UU",
556
576
  title: "banana",
577
+ master_base: false,
557
578
  },
558
579
  {
559
580
  sha: "3cb22661ecff6c872e96ce9c40b31c824938cab7",
@@ -561,6 +582,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
561
582
  subject_line: "lemon color",
562
583
  branch_id: "E63ytp5dj",
563
584
  title: "lemon color",
585
+ master_base: false,
564
586
  },
565
587
  {
566
588
  sha: "d36d63499425bb46a1e62c2c9df1a4332b13004f",
@@ -568,6 +590,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
568
590
  subject_line: "cantaloupe color",
569
591
  branch_id: "E63ytp5dj",
570
592
  title: "lemon color",
593
+ master_base: false,
571
594
  },
572
595
  {
573
596
  sha: "4f98dd3e67d03b79d7a12480c7d1c2fcbd186ac5",
@@ -575,6 +598,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
575
598
  subject_line: "banana sweet",
576
599
  branch_id: "E63ytp5dj",
577
600
  title: "lemon color",
601
+ master_base: false,
578
602
  },
579
603
  {
580
604
  sha: "f143d03c723c9f5231a81c1e12098511611898cb",
@@ -582,6 +606,7 @@ const SINGLE_COMMIT_NEW_GROUP: CommitMetadata.CommitRange = {
582
606
  subject_line: "apple sweet",
583
607
  branch_id: "6Ak-qn+5Z",
584
608
  title: "new group",
609
+ master_base: false,
585
610
  },
586
611
  ],
587
612
  pr_lookup: {
@@ -691,8 +716,10 @@ const COMMIT_MESSAGE_WITH_QUOTES: CommitMetadata.CommitRange = {
691
716
  subject_line: '[new] invalid "by me" quotes',
692
717
  branch_id: "6Ak-qn+5Z",
693
718
  title: '[new] invalid "by me" quotes',
719
+ master_base: false,
694
720
  },
695
721
  ],
722
+ master_base: false,
696
723
  },
697
724
  ],
698
725
  commit_list: [
@@ -702,6 +729,7 @@ const COMMIT_MESSAGE_WITH_QUOTES: CommitMetadata.CommitRange = {
702
729
  subject_line: '[new] invalid "by me" quotes',
703
730
  branch_id: "6Ak-qn+5Z",
704
731
  title: '[new] invalid "by me" quotes',
732
+ master_base: false,
705
733
  },
706
734
  ],
707
735
  pr_lookup: {},
@@ -726,6 +754,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
726
754
  subject_line: "head~7",
727
755
  branch_id: "gs---4gvxa-5v-2mx26",
728
756
  title: "pr-title",
757
+ master_base: false,
729
758
  },
730
759
  {
731
760
  sha: "391476bbfc6b77b60a3ef7fa97155496a9f8f27f",
@@ -733,6 +762,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
733
762
  subject_line: "head~6",
734
763
  branch_id: "gs---4gvxa-5v-2mx26",
735
764
  title: "pr-title",
765
+ master_base: false,
736
766
  },
737
767
  {
738
768
  sha: "5a98cf8f0406712405d41af07c3a012f72ad36fa",
@@ -740,6 +770,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
740
770
  subject_line: "head~5",
741
771
  branch_id: "gs---4gvxa-5v-2mx26",
742
772
  title: "pr-title",
773
+ master_base: false,
743
774
  },
744
775
  {
745
776
  sha: "e820018cb370bb6cda118dc649e841c75d797188",
@@ -747,6 +778,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
747
778
  subject_line: "head~4",
748
779
  branch_id: "gs---4gvxa-5v-2mx26",
749
780
  title: "pr-title",
781
+ master_base: false,
750
782
  },
751
783
  {
752
784
  sha: "e6d1dfc7ec007468712bfc015884cc22bfa79e1d",
@@ -754,6 +786,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
754
786
  subject_line: "head~3",
755
787
  branch_id: "gs---4gvxa-5v-2mx26",
756
788
  title: "pr-title",
789
+ master_base: false,
757
790
  },
758
791
  {
759
792
  sha: "a26f21025a558968554c439ab9b942d5fe84bccb",
@@ -761,8 +794,10 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
761
794
  subject_line: "head~2",
762
795
  branch_id: "gs---4gvxa-5v-2mx26",
763
796
  title: "pr-title",
797
+ master_base: false,
764
798
  },
765
799
  ],
800
+ master_base: false,
766
801
  },
767
802
  {
768
803
  id: "unassigned",
@@ -777,6 +812,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
777
812
  subject_line: "head~1",
778
813
  branch_id: "unassigned",
779
814
  title: "allow_unassigned",
815
+ master_base: false,
780
816
  },
781
817
  {
782
818
  sha: "b61c5b09a4b7c9dcff9a9071386b134997569a01",
@@ -784,8 +820,10 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
784
820
  subject_line: "head",
785
821
  branch_id: "unassigned",
786
822
  title: "allow_unassigned",
823
+ master_base: false,
787
824
  },
788
825
  ],
826
+ master_base: false,
789
827
  },
790
828
  ],
791
829
  commit_list: [
@@ -795,6 +833,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
795
833
  subject_line: "head~7",
796
834
  branch_id: "gs---4gvxa-5v-2mx26",
797
835
  title: "pr-title",
836
+ master_base: false,
798
837
  },
799
838
  {
800
839
  sha: "391476bbfc6b77b60a3ef7fa97155496a9f8f27f",
@@ -802,6 +841,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
802
841
  subject_line: "head~6",
803
842
  branch_id: "gs---4gvxa-5v-2mx26",
804
843
  title: "pr-title",
844
+ master_base: false,
805
845
  },
806
846
  {
807
847
  sha: "5a98cf8f0406712405d41af07c3a012f72ad36fa",
@@ -809,6 +849,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
809
849
  subject_line: "head~5",
810
850
  branch_id: "gs---4gvxa-5v-2mx26",
811
851
  title: "pr-title",
852
+ master_base: false,
812
853
  },
813
854
  {
814
855
  sha: "e820018cb370bb6cda118dc649e841c75d797188",
@@ -816,6 +857,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
816
857
  subject_line: "head~4",
817
858
  branch_id: "gs---4gvxa-5v-2mx26",
818
859
  title: "pr-title",
860
+ master_base: false,
819
861
  },
820
862
  {
821
863
  sha: "e6d1dfc7ec007468712bfc015884cc22bfa79e1d",
@@ -823,6 +865,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
823
865
  subject_line: "head~3",
824
866
  branch_id: "gs---4gvxa-5v-2mx26",
825
867
  title: "pr-title",
868
+ master_base: false,
826
869
  },
827
870
  {
828
871
  sha: "a26f21025a558968554c439ab9b942d5fe84bccb",
@@ -830,6 +873,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
830
873
  subject_line: "head~2",
831
874
  branch_id: "gs---4gvxa-5v-2mx26",
832
875
  title: "pr-title",
876
+ master_base: false,
833
877
  },
834
878
  {
835
879
  sha: "90667fe97e059e8285e070d6268f2b4035b2ebd4",
@@ -837,6 +881,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
837
881
  subject_line: "head~1",
838
882
  branch_id: "unassigned",
839
883
  title: "allow_unassigned",
884
+ master_base: false,
840
885
  },
841
886
  {
842
887
  sha: "b61c5b09a4b7c9dcff9a9071386b134997569a01",
@@ -844,6 +889,7 @@ const SYNC_WITH_UNASSIGNED: CommitMetadata.CommitRange = {
844
889
  subject_line: "head",
845
890
  branch_id: "unassigned",
846
891
  title: "allow_unassigned",
892
+ master_base: false,
847
893
  },
848
894
  ],
849
895
  pr_lookup: {},
@@ -76,6 +76,8 @@ type CommitListArgs = {
76
76
  commit_list: CommitMetadata.CommitRange["commit_list"];
77
77
  };
78
78
 
79
+ type MetadataWriteValues = Parameters<typeof Metadata.write>[1];
80
+
79
81
  GitReviseTodo.todo = function todo(args: CommitListArgs) {
80
82
  const entry_list = [];
81
83
 
@@ -95,7 +97,10 @@ GitReviseTodo.todo = function todo(args: CommitListArgs) {
95
97
  const title = commit.title;
96
98
  invariant(title, "commit.title must exist");
97
99
 
98
- const metadata = { id, title };
100
+ const metadata: MetadataWriteValues = { id, title };
101
+ if (commit.master_base) {
102
+ metadata.base = "master";
103
+ }
99
104
  const unsafe_message_with_id = Metadata.write(commit.full_message, metadata);
100
105
  const message_with_id = unsafe_message_with_id;
101
106
  entry_lines.push(message_with_id);
@@ -2,6 +2,54 @@ import { test, expect } from "bun:test";
2
2
 
3
3
  import * as Metadata from "~/core/Metadata";
4
4
 
5
+ test("read all metadata", () => {
6
+ const body = [
7
+ "[test] read all metadata",
8
+ "",
9
+ "git-stack-id: noah/test---4h783e3zbtavw4",
10
+ "git-stack-title: read all metadata",
11
+ "git-stack-base: master",
12
+ ].join("\n");
13
+
14
+ const metadata = Metadata.read(body);
15
+
16
+ expect(metadata).toEqual({
17
+ subject: "[test] read all metadata",
18
+ id: "noah/test---4h783e3zbtavw4",
19
+ title: "read all metadata",
20
+ base: "master",
21
+ });
22
+ });
23
+
24
+ test("write all metadata", () => {
25
+ const body = [
26
+ "[test] write all metadata",
27
+ "",
28
+ "- details about this commit",
29
+ "",
30
+ "git-stack-id: DdKIFyufW",
31
+ "git-stack-title: old title",
32
+ ].join("\n");
33
+
34
+ const metadata = {
35
+ id: "noah/test---4h783e3zbtavw4",
36
+ title: "read all metadata",
37
+ base: "master",
38
+ };
39
+
40
+ expect(Metadata.write(body, metadata)).toEqual(
41
+ [
42
+ "[test] write all metadata",
43
+ "",
44
+ "- details about this commit",
45
+ "",
46
+ "git-stack-id: noah/test---4h783e3zbtavw4",
47
+ "git-stack-title: read all metadata",
48
+ "git-stack-base: master",
49
+ ].join("\n"),
50
+ );
51
+ });
52
+
5
53
  test("read handles bulleted lists", () => {
6
54
  const body = [
7
55
  "[feat] implement various features",
@@ -20,6 +68,7 @@ test("read handles bulleted lists", () => {
20
68
  subject: "[feat] implement various features",
21
69
  id: "DdKIFyufW",
22
70
  title: "saved group title",
71
+ base: null,
23
72
  });
24
73
  });
25
74
 
@@ -67,6 +116,7 @@ test("read handles slashes in branch name", () => {
67
116
  subject: "[fix] slash in branch name",
68
117
  id: "dev/noah/fix-slash-branch",
69
118
  title: "fix slash branch",
119
+ base: null,
70
120
  });
71
121
  });
72
122
 
@@ -114,6 +164,7 @@ test("read handles double quotes", () => {
114
164
  subject: 'Revert "[abc / 123] subject (#1234)"',
115
165
  id: "dev/noah/fix-slash-branch",
116
166
  title: 'Revert \\"[abc / 123] subject (#1234)\\"',
167
+ base: null,
117
168
  });
118
169
  });
119
170
 
@@ -3,12 +3,14 @@ import { invariant } from "~/core/invariant";
3
3
  type InputMetadataValues = {
4
4
  id: string;
5
5
  title?: string;
6
+ base?: string;
6
7
  };
7
8
 
8
9
  type OutputMetadataValues = {
9
10
  subject: null | string;
10
11
  id: null | string;
11
12
  title: null | string;
13
+ base: null | string;
12
14
  };
13
15
 
14
16
  export function write(message: string, values: InputMetadataValues) {
@@ -23,13 +25,22 @@ export function write(message: string, values: InputMetadataValues) {
23
25
  line_list.push(TEMPLATE.group_title(values.title));
24
26
  }
25
27
 
28
+ if (values.base) {
29
+ line_list.push(TEMPLATE.base(values.base));
30
+ }
31
+
26
32
  let new_message = line_list.join("\n");
27
33
 
28
34
  return new_message;
29
35
  }
30
36
 
31
37
  export function read(message: string): OutputMetadataValues {
32
- const values: OutputMetadataValues = { subject: null, id: null, title: null };
38
+ const values: OutputMetadataValues = {
39
+ subject: null,
40
+ id: null,
41
+ title: null,
42
+ base: null,
43
+ };
33
44
 
34
45
  const match_subject = message.match(RE.subject_line);
35
46
 
@@ -51,6 +62,12 @@ export function read(message: string): OutputMetadataValues {
51
62
  values.title = match_title.groups["title"];
52
63
  }
53
64
 
65
+ const match_base = message.match(RE.base);
66
+
67
+ if (match_base?.groups) {
68
+ values.base = match_base.groups["ref"];
69
+ }
70
+
54
71
  return values;
55
72
  }
56
73
 
@@ -60,6 +77,7 @@ export function remove(message: string) {
60
77
  // remove metadata
61
78
  result = result.replace(new RegExp(RE.stack_id, "gmi"), "");
62
79
  result = result.replace(new RegExp(RE.group_title, "gmi"), "");
80
+ result = result.replace(new RegExp(RE.base, "gmi"), "");
63
81
 
64
82
  result = result.trimEnd();
65
83
 
@@ -74,6 +92,10 @@ const TEMPLATE = {
74
92
  group_title(title: string) {
75
93
  return `git-stack-title: ${title}`;
76
94
  },
95
+
96
+ base(ref: string) {
97
+ return `git-stack-base: ${ref}`;
98
+ },
77
99
  };
78
100
 
79
101
  const RE = {
@@ -82,4 +104,5 @@ const RE = {
82
104
  // https://regex101.com/r/wLmGVq/1
83
105
  stack_id: new RegExp(`${TEMPLATE.stack_id("(?<id>[^\\s]+)")}`, "i"),
84
106
  group_title: new RegExp(TEMPLATE.group_title("(?<title>[^\\n^\\r]+)"), "i"),
107
+ base: new RegExp(`${TEMPLATE.base("(?<ref>[^\\s]+)")}`, "i"),
85
108
  };
@@ -51,6 +51,7 @@ git-stack-title: Github: pr_list duration timer"
51
51
  {
52
52
  "branch_id": null,
53
53
  "full_message": "homebrew-git-stack 2.7.1",
54
+ "master_base": false,
54
55
  "sha": "ba067f8ad641dda7e65e3c2acb2421c955843829",
55
56
  "subject_line": "homebrew-git-stack 2.7.1",
56
57
  "title": null,
@@ -63,6 +64,7 @@ git-stack-title: Github: pr_list duration timer"
63
64
  git-stack-id: noah/paint-test---4gwpqhd033n6y5
64
65
  git-stack-title: Rebase: debug logs"
65
66
  ,
67
+ "master_base": false,
66
68
  "sha": "7c8da9f5fe681fc7459a0e737241df631983cd3c",
67
69
  "subject_line": "Rebase: debug logs",
68
70
  "title": "Rebase: debug logs",
@@ -75,6 +77,7 @@ git-stack-title: Rebase: debug logs"
75
77
  git-stack-id: noah/paint-test---4gwpqirewoudxa
76
78
  git-stack-title: CommitMetadata: track last group id"
77
79
  ,
80
+ "master_base": false,
78
81
  "sha": "47a69d37f8c5cc796884a91fa9e93fc1db5297dd",
79
82
  "subject_line": "CommitMetadata: track last group id",
80
83
  "title": "CommitMetadata: track last group id",
@@ -87,6 +90,7 @@ git-stack-title: CommitMetadata: track last group id"
87
90
  git-stack-id: noah/paint-test---4gwpqjcpu7-isv
88
91
  git-stack-title: Github: pr_list duration timer"
89
92
  ,
93
+ "master_base": false,
90
94
  "sha": "8ccf42a7c72aa194fafc7c326f5874f5a0a009c6",
91
95
  "subject_line": "Github: pr_list duration timer",
92
96
  "title": "Github: pr_list duration timer",