submodule-version 3.2.7 → 3.3.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/src/sv.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  PubGrub,
6
6
  IOverride,
7
7
  TDependencies,
8
+ TIsCandidateCompatible,
8
9
  TPubGrubResult,
9
10
  } from './PubGrub';
10
11
  import { EntryStore } from './entryStore';
@@ -126,14 +127,20 @@ export class SV {
126
127
 
127
128
  private explicitModulesDir?: string;
128
129
 
130
+ private isCandidateCompatible?: TIsCandidateCompatible;
131
+
129
132
  constructor (
130
133
  projectDir: string,
131
134
  modulesDir?: string,
132
- options: { githubToken?: string } = {},
135
+ options: {
136
+ githubToken?: string,
137
+ isCandidateCompatible?: TIsCandidateCompatible,
138
+ } = {},
133
139
  ) {
134
140
  RunOptions.cwd = projectDir;
135
141
  RunOptions.modulesDir = modulesDir || DEFAULT_MODULES_DIR;
136
142
  this.explicitModulesDir = modulesDir;
143
+ this.isCandidateCompatible = options.isCandidateCompatible;
137
144
  git.api.setToken(options.githubToken);
138
145
  }
139
146
 
@@ -167,7 +174,7 @@ export class SV {
167
174
  private resolveDeps = async (
168
175
  rootDeps: TDependencies,
169
176
  ): Promise<TPubGrubResult> => {
170
- const resolver = new PubGrub(this.store);
177
+ const resolver = new PubGrub(this.store, this.isCandidateCompatible);
171
178
 
172
179
  try {
173
180
  return await resolver.resolve(rootDeps);
@@ -602,7 +609,7 @@ export class SV {
602
609
 
603
610
  const tags = await git.local.tagsAtHead(dir);
604
611
 
605
- return versionUtil.latest(tags) || null;
612
+ return versionUtil.sort(tags)[0] || null;
606
613
  };
607
614
 
608
615
  // eslint-disable-next-line class-methods-use-this
@@ -675,29 +682,37 @@ export class SV {
675
682
  await git.local.addRemote(dir, repoUrl);
676
683
  }
677
684
 
685
+ const versions = await git.local.listTags(dir);
678
686
  const currentTag = await this.currentVersion(module);
679
- const latestKnown = await this.latestVersion(module);
687
+ const latestKnown = versionUtil.latest(versions) || '0.0.0';
688
+ const fromOldVersion = !!currentTag && currentTag !== latestKnown;
680
689
 
681
- if (currentTag && latestKnown && currentTag !== latestKnown) {
682
- throw new GitError('GIT_NOT_LATEST_VERSION');
683
- }
690
+ const next = fromOldVersion
691
+ ? versionUtil.nextPatchVersion(currentTag, versions)
692
+ : versionUtil.bump(latestKnown, bump);
684
693
 
685
- await git.local.ensureBranch(dir);
694
+ if (fromOldVersion) {
695
+ /* Старую стабильную линию не смешиваем с основной веткой: имя ветки
696
+ * совпадает с автоматически рассчитанной prerelease-версией. */
697
+ await git.local.createBranch(dir, next);
698
+ } else {
699
+ await git.local.ensureBranch(dir);
686
700
 
687
- if (await git.local.isRemoteAhead(dir)) {
688
- await git.local.pullRebaseAutostash(dir);
689
- }
701
+ if (await git.local.isRemoteAhead(dir)) {
702
+ await git.local.pullRebaseAutostash(dir);
703
+ }
690
704
 
691
- const dirty = await git.local.hasChanges(dir);
692
- const headTag = await this.currentVersion(module);
705
+ const dirty = await git.local.hasChanges(dir);
706
+ const headTag = await this.currentVersion(module);
693
707
 
694
- if (!dirty && headTag) {
695
- await git.local.push(dir, headTag);
708
+ if (!dirty && headTag) {
709
+ await git.local.push(dir, headTag);
710
+ this.store.clear();
696
711
 
697
- return headTag;
712
+ return headTag;
713
+ }
698
714
  }
699
715
 
700
- const next = versionUtil.bump(await this.latestVersion(module), bump);
701
716
  const pkg = await pkgJSONManager.read(module);
702
717
 
703
718
  if (pkg) {
@@ -711,6 +726,9 @@ export class SV {
711
726
 
712
727
  await git.local.addTag(dir, next);
713
728
  await git.local.push(dir, next);
729
+ /* publish меняет набор доступных тегов вне EntryStore. Следующий put
730
+ * обязан загрузить новый каталог, а не получить snapshot до публикации. */
731
+ this.store.clear();
714
732
 
715
733
  return next;
716
734
  };
@@ -59,4 +59,20 @@ describe('versionUtil.bump', () => {
59
59
  ] as const)('bumps %s', (kind, expected) => {
60
60
  expect(versionUtil.bump('1.2.3', kind)).toBe(expected);
61
61
  });
62
+
63
+ it('increments the patch branch suffix for a non-latest release', () => {
64
+ expect(versionUtil.nextPatchVersion('1.0.2', [
65
+ '2.0.0',
66
+ '1.0.2-patch.1',
67
+ '1.0.2-patch.3',
68
+ '1.0.1-patch.9',
69
+ ])).toBe('1.0.2-patch.4');
70
+ });
71
+
72
+ it('continues the same patch line from a patch tag', () => {
73
+ expect(versionUtil.nextPatchVersion('1.0.2-patch.4', [
74
+ '2.0.0',
75
+ '1.0.2-patch.4',
76
+ ])).toBe('1.0.2-patch.5');
77
+ });
62
78
  });
@@ -86,6 +86,29 @@ const bump = (
86
86
  return next;
87
87
  };
88
88
 
89
+ /* Публикация с не последнего тега образует отдельную patch-линейку:
90
+ * 1.0.2 -> 1.0.2-patch.1, затем автоматически .2, .3 и т.д. */
91
+ const nextPatchVersion = (version: string, versions: string[]): string => {
92
+ const parsed = semver.parse(version);
93
+
94
+ if (!parsed) throw new Error(`Invalid semantic version: ${version}`);
95
+
96
+ const base = `${parsed.major}.${parsed.minor}.${parsed.patch}`;
97
+ const prefix = `${base}-patch.`;
98
+
99
+ const numbers = versions.flatMap(candidate => {
100
+ if (!candidate.startsWith(prefix)) return [];
101
+
102
+ const value = candidate.slice(prefix.length);
103
+
104
+ return /^\d+$/.test(value) ? [Number(value)] : [];
105
+ });
106
+
107
+ const next = (numbers.length ? Math.max(...numbers) : 0) + 1;
108
+
109
+ return `${prefix}${next}`;
110
+ };
111
+
89
112
  export const versionUtil = {
90
113
  normalizeConstraint,
91
114
  validate,
@@ -100,4 +123,5 @@ export const versionUtil = {
100
123
  intersects,
101
124
  isSubset,
102
125
  bump,
126
+ nextPatchVersion,
103
127
  };