versionary 0.4.0 → 0.5.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.
@@ -14,7 +14,9 @@ const node_path_1 = __importDefault(require("node:path"));
14
14
  const load_config_js_1 = require("../../config/load-config.js");
15
15
  const changelog_js_1 = require("../../domain/release/changelog.js");
16
16
  const plan_js_1 = require("../../domain/release/plan.js");
17
+ const package_context_js_1 = require("../../domain/strategy/package-context.js");
17
18
  const resolve_js_1 = require("../../domain/strategy/resolve.js");
19
+ const rust_js_1 = require("../../domain/strategy/rust.js");
18
20
  const capabilities_js_1 = require("../../plugins/capabilities.js");
19
21
  const runtime_js_1 = require("../../plugins/runtime.js");
20
22
  const artifact_rules_js_1 = require("./artifact-rules.js");
@@ -74,7 +76,27 @@ function prepareSimpleReleasePr(cwd = process.cwd(), options = {}) {
74
76
  throw new Error("No releasable commits found. Nothing to open a release PR for.");
75
77
  }
76
78
  ensureCleanWorktree(cwd, options.logger);
77
- const updatedVersionFiles = strategy.writeVersion(cwd, loaded.config, plan.nextVersion);
79
+ const updatedVersionFiles = [];
80
+ const rustManifestVersionTargets = {};
81
+ if (plan.packages && plan.packages.length > 0) {
82
+ for (const packagePlan of plan.packages) {
83
+ if (!packagePlan.nextVersion) {
84
+ continue;
85
+ }
86
+ const packageConfig = loaded.config.packages?.[packagePlan.path] ?? {};
87
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, packagePlan.path, packageConfig);
88
+ const packageUpdated = packageContext.strategy.writeVersion(cwd, packageContext.config, packagePlan.nextVersion);
89
+ updatedVersionFiles.push(...packageUpdated);
90
+ if (packageContext.strategy.name === rust_js_1.rustVersionStrategy.name) {
91
+ rustManifestVersionTargets[packageContext.versionFile] =
92
+ packagePlan.nextVersion;
93
+ }
94
+ }
95
+ updatedVersionFiles.push(...(0, rust_js_1.applyRustWorkspaceDependencyUpdates)(cwd, rustManifestVersionTargets));
96
+ }
97
+ else {
98
+ updatedVersionFiles.push(...strategy.writeVersion(cwd, loaded.config, plan.nextVersion));
99
+ }
78
100
  const updatedArtifactFiles = (0, artifact_rules_js_1.applyConfiguredArtifactRules)(cwd, loaded.config, plan);
79
101
  const section = (0, changelog_js_1.renderSimpleChangelog)(plan);
80
102
  (0, changelog_js_1.prependChangelog)(cwd, plan.changelogFile, section);
@@ -9,7 +9,9 @@ const node_path_1 = __importDefault(require("node:path"));
9
9
  const state_js_1 = require("../../app/release/state.js");
10
10
  const load_config_js_1 = require("../../config/load-config.js");
11
11
  const commits_js_1 = require("../../infra/git/commits.js");
12
+ const package_context_js_1 = require("../strategy/package-context.js");
12
13
  const resolve_js_1 = require("../strategy/resolve.js");
14
+ const rust_js_1 = require("../strategy/rust.js");
13
15
  const semver_js_1 = require("./semver.js");
14
16
  function getMode(configMode) {
15
17
  return configMode ?? "independent";
@@ -21,11 +23,6 @@ function createSimplePlan(cwd = process.cwd()) {
21
23
  const changelogFile = loaded.config["changelog-file"] ?? "CHANGELOG.md";
22
24
  const releaseBranchPrefix = loaded.config["release-branch"] ?? "versionary/release";
23
25
  const baselineSha = (0, state_js_1.readBaselineSha)(cwd) ?? loaded.config["bootstrap-sha"] ?? null;
24
- const versionPath = node_path_1.default.join(cwd, versionFile);
25
- if (!node_fs_1.default.existsSync(versionPath)) {
26
- throw new Error(`Versionary requires ${versionFile} to exist.`);
27
- }
28
- const currentVersion = strategy.readVersion(cwd, loaded.config);
29
26
  const allowStableMajor = loaded.config["allow-stable-major"] ?? false;
30
27
  const configuredPackages = Object.entries(loaded.config.packages ?? {}).map(([pkgPath, cfg]) => ({
31
28
  path: pkgPath,
@@ -34,6 +31,11 @@ function createSimplePlan(cwd = process.cwd()) {
34
31
  const monorepoMode = getMode(loaded.config["monorepo-mode"]);
35
32
  const hasPackages = configuredPackages.length > 0;
36
33
  if (!hasPackages) {
34
+ const versionPath = node_path_1.default.join(cwd, versionFile);
35
+ if (!node_fs_1.default.existsSync(versionPath)) {
36
+ throw new Error(`Versionary requires ${versionFile} to exist.`);
37
+ }
38
+ const currentVersion = strategy.readVersion(cwd, loaded.config);
37
39
  const parsedCommits = (0, commits_js_1.getParsedCommitsSinceLastTag)(cwd, baselineSha);
38
40
  const effectiveCommits = (0, commits_js_1.applyRevertSuppression)(parsedCommits);
39
41
  const commits = effectiveCommits;
@@ -55,29 +57,70 @@ function createSimplePlan(cwd = process.cwd()) {
55
57
  }
56
58
  const packagePlans = configuredPackages
57
59
  .map((pkg) => {
60
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, pkg.path, pkg);
61
+ const packageCurrentVersion = packageContext.strategy.readVersion(cwd, packageContext.config);
58
62
  const parsedCommits = (0, commits_js_1.getParsedCommitsForPath)(cwd, baselineSha, pkg.path, pkg["exclude-paths"] ?? []);
59
63
  const effectiveCommits = (0, commits_js_1.applyRevertSuppression)(parsedCommits);
60
64
  const commits = effectiveCommits;
61
65
  const releaseType = (0, commits_js_1.analyzeParsedCommits)(parsedCommits);
62
66
  const nextVersion = releaseType
63
- ? (0, semver_js_1.bumpVersion)(currentVersion, releaseType, { allowStableMajor })
67
+ ? (0, semver_js_1.bumpVersion)(packageCurrentVersion, releaseType, { allowStableMajor })
64
68
  : null;
65
69
  return {
66
70
  path: pkg.path,
67
71
  releaseType,
68
- currentVersion,
72
+ currentVersion: packageCurrentVersion,
69
73
  nextVersion,
70
74
  commits,
71
75
  parsedCommits,
72
76
  };
73
77
  })
74
78
  .sort((a, b) => a.path.localeCompare(b.path));
79
+ const rustManifestVersionTargets = {};
80
+ const rustPackageManifestByPath = {};
81
+ const packageCurrentVersionByPath = {};
82
+ for (const packagePlan of packagePlans) {
83
+ const packageConfig = loaded.config.packages?.[packagePlan.path] ?? {};
84
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(loaded.config, packagePlan.path, packageConfig);
85
+ if (packageContext.strategy.name === rust_js_1.rustVersionStrategy.name) {
86
+ rustPackageManifestByPath[packagePlan.path] = (0, rust_js_1.toCargoManifestPath)(packagePlan.path);
87
+ }
88
+ packageCurrentVersionByPath[packagePlan.path] = packagePlan.currentVersion;
89
+ if (packageContext.strategy.name === rust_js_1.rustVersionStrategy.name) {
90
+ const next = packagePlan.nextVersion;
91
+ if (next) {
92
+ rustManifestVersionTargets[packageContext.versionFile] = next;
93
+ }
94
+ }
95
+ }
96
+ const impactedRustManifests = (0, rust_js_1.detectRustDependencyImpact)(cwd, rustManifestVersionTargets, Object.values(rustPackageManifestByPath));
97
+ const impactedPaths = new Set();
98
+ for (const [pkgPath, manifest] of Object.entries(rustPackageManifestByPath)) {
99
+ if (impactedRustManifests.includes(manifest)) {
100
+ impactedPaths.add(pkgPath);
101
+ }
102
+ }
103
+ const adjustedPackages = packagePlans.map((pkgPlan) => {
104
+ if (pkgPlan.nextVersion || !impactedPaths.has(pkgPlan.path)) {
105
+ return pkgPlan;
106
+ }
107
+ const current = packageCurrentVersionByPath[pkgPlan.path] ?? pkgPlan.currentVersion;
108
+ return {
109
+ ...pkgPlan,
110
+ releaseType: "patch",
111
+ nextVersion: (0, semver_js_1.bumpVersion)(current, "patch", { allowStableMajor }),
112
+ };
113
+ });
75
114
  if (monorepoMode === "fixed") {
76
- const fixedType = (0, commits_js_1.analyzeParsedCommits)(packagePlans.flatMap((pkgPlan) => pkgPlan.parsedCommits));
115
+ const fixedType = (0, commits_js_1.analyzeParsedCommits)(adjustedPackages.flatMap((pkgPlan) => pkgPlan.parsedCommits));
116
+ const fixedBaseVersion = adjustedPackages.find((pkgPlan) => pkgPlan.path === ".")
117
+ ?.currentVersion ??
118
+ adjustedPackages[0]?.currentVersion ??
119
+ "0.0.0";
77
120
  const fixedNextVersion = fixedType
78
- ? (0, semver_js_1.bumpVersion)(currentVersion, fixedType, { allowStableMajor })
121
+ ? (0, semver_js_1.bumpVersion)(fixedBaseVersion, fixedType, { allowStableMajor })
79
122
  : null;
80
- const adjusted = packagePlans.map((pkgPlan) => ({
123
+ const adjusted = adjustedPackages.map((pkgPlan) => ({
81
124
  ...pkgPlan,
82
125
  releaseType: fixedType,
83
126
  nextVersion: fixedNextVersion,
@@ -85,7 +128,7 @@ function createSimplePlan(cwd = process.cwd()) {
85
128
  return {
86
129
  mode: "simple",
87
130
  releaseType: fixedType,
88
- currentVersion,
131
+ currentVersion: fixedBaseVersion,
89
132
  nextVersion: fixedNextVersion,
90
133
  versionFile,
91
134
  changelogFile,
@@ -95,20 +138,23 @@ function createSimplePlan(cwd = process.cwd()) {
95
138
  packages: adjusted,
96
139
  };
97
140
  }
98
- const overallType = (0, commits_js_1.analyzeParsedCommits)(packagePlans.flatMap((pkgPlan) => pkgPlan.parsedCommits));
141
+ const overallType = (0, commits_js_1.analyzeParsedCommits)(adjustedPackages.flatMap((pkgPlan) => pkgPlan.parsedCommits));
142
+ const overallBaseVersion = adjustedPackages.find((pkgPlan) => pkgPlan.path === ".")?.currentVersion ??
143
+ adjustedPackages[0]?.currentVersion ??
144
+ "0.0.0";
99
145
  const overallNextVersion = overallType
100
- ? (0, semver_js_1.bumpVersion)(currentVersion, overallType, { allowStableMajor })
146
+ ? (0, semver_js_1.bumpVersion)(overallBaseVersion, overallType, { allowStableMajor })
101
147
  : null;
102
148
  return {
103
149
  mode: "simple",
104
150
  releaseType: overallType,
105
- currentVersion,
151
+ currentVersion: overallBaseVersion,
106
152
  nextVersion: overallNextVersion,
107
153
  versionFile,
108
154
  changelogFile,
109
155
  releaseBranchPrefix,
110
156
  baselineSha,
111
- commits: packagePlans.flatMap((pkgPlan) => pkgPlan.commits),
112
- packages: packagePlans,
157
+ commits: adjustedPackages.flatMap((pkgPlan) => pkgPlan.commits),
158
+ packages: adjustedPackages,
113
159
  };
114
160
  }
@@ -0,0 +1,7 @@
1
+ import type { VersionaryConfig, VersionaryPackage } from "../../types/config.js";
2
+ import type { VersionStrategy } from "./types.js";
3
+ export declare function resolvePackageStrategyContext(rootConfig: VersionaryConfig, packagePath: string, packageConfig: VersionaryPackage): {
4
+ strategy: VersionStrategy;
5
+ config: VersionaryConfig;
6
+ versionFile: string;
7
+ };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.resolvePackageStrategyContext = resolvePackageStrategyContext;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const resolve_js_1 = require("./resolve.js");
9
+ function withVersionFile(config, versionFile) {
10
+ return {
11
+ ...config,
12
+ "version-file": versionFile,
13
+ };
14
+ }
15
+ function resolvePackageStrategyContext(rootConfig, packagePath, packageConfig) {
16
+ const packageReleaseType = packageConfig["release-type"];
17
+ const baseConfig = packageReleaseType
18
+ ? {
19
+ ...rootConfig,
20
+ "release-type": packageReleaseType,
21
+ }
22
+ : { ...rootConfig };
23
+ const baseStrategy = (0, resolve_js_1.resolveVersionStrategy)(baseConfig);
24
+ if (!packageReleaseType) {
25
+ const versionFile = baseConfig["version-file"] ?? baseStrategy.getVersionFile(baseConfig);
26
+ const config = withVersionFile(baseConfig, versionFile);
27
+ return {
28
+ strategy: baseStrategy,
29
+ config,
30
+ versionFile,
31
+ };
32
+ }
33
+ const packageVersionFile = packagePath === "."
34
+ ? (baseConfig["version-file"] ?? baseStrategy.getVersionFile(baseConfig))
35
+ : node_path_1.default.posix.join(packagePath, baseStrategy.getVersionFile({
36
+ ...baseConfig,
37
+ "version-file": undefined,
38
+ }));
39
+ const config = withVersionFile({
40
+ ...baseConfig,
41
+ packages: undefined,
42
+ }, packageVersionFile);
43
+ const strategy = (0, resolve_js_1.resolveVersionStrategy)(config);
44
+ return {
45
+ strategy,
46
+ config,
47
+ versionFile: packageVersionFile,
48
+ };
49
+ }
@@ -1,2 +1,5 @@
1
1
  import type { VersionStrategy } from "./types.js";
2
+ export declare function applyRustWorkspaceDependencyUpdates(cwd: string, manifestToVersion: Record<string, string>): string[];
3
+ export declare function detectRustDependencyImpact(cwd: string, manifestToVersion: Record<string, string>, candidateManifests: string[]): string[];
4
+ export declare function toCargoManifestPath(packagePath: string): string;
2
5
  export declare const rustVersionStrategy: VersionStrategy;
@@ -4,6 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.rustVersionStrategy = void 0;
7
+ exports.applyRustWorkspaceDependencyUpdates = applyRustWorkspaceDependencyUpdates;
8
+ exports.detectRustDependencyImpact = detectRustDependencyImpact;
9
+ exports.toCargoManifestPath = toCargoManifestPath;
7
10
  const node_fs_1 = __importDefault(require("node:fs"));
8
11
  const node_path_1 = __importDefault(require("node:path"));
9
12
  const toml_1 = __importDefault(require("@iarna/toml"));
@@ -74,6 +77,25 @@ function findCargoManifestDirectories(rootDir) {
74
77
  }
75
78
  return [...results].sort((a, b) => a.localeCompare(b));
76
79
  }
80
+ function collectAllCrateManifests(cwd) {
81
+ const manifests = [];
82
+ const cargoDirs = findCargoManifestDirectories(cwd);
83
+ for (const dir of cargoDirs) {
84
+ const manifest = dir === "."
85
+ ? "Cargo.toml"
86
+ : normalizeSlashPath(node_path_1.default.posix.join(dir, "Cargo.toml"));
87
+ const manifestPath = node_path_1.default.join(cwd, manifest);
88
+ if (!node_fs_1.default.existsSync(manifestPath)) {
89
+ continue;
90
+ }
91
+ const cargoTomlRaw = node_fs_1.default.readFileSync(manifestPath, "utf8");
92
+ if (!isCrateManifest(manifest, cargoTomlRaw)) {
93
+ continue;
94
+ }
95
+ manifests.push(manifest);
96
+ }
97
+ return manifests.sort((a, b) => a.localeCompare(b));
98
+ }
77
99
  function parseCargoManifest(versionFile, cargoTomlRaw) {
78
100
  let parsed;
79
101
  try {
@@ -156,7 +178,7 @@ function resolveWorkspaceMemberManifests(rootDir, workspaceTable) {
156
178
  });
157
179
  return filtered.sort((a, b) => a.localeCompare(b));
158
180
  }
159
- function collectRustTargetManifests(cwd, versionFile) {
181
+ function collectRustTargetManifests(cwd, versionFile, includeWorkspaceMembers) {
160
182
  if (node_path_1.default.basename(versionFile) !== "Cargo.toml") {
161
183
  throw new Error(`Rust strategy requires "version-file" to point to a Cargo.toml manifest (received "${versionFile}").`);
162
184
  }
@@ -168,7 +190,9 @@ function collectRustTargetManifests(cwd, versionFile) {
168
190
  const parsedRoot = parseCargoManifest(versionFile, rootRaw);
169
191
  const rootIsCrate = parsedRoot.packageTable !== null;
170
192
  const rootDir = node_path_1.default.dirname(rootManifestPath);
171
- const workspaceMembers = resolveWorkspaceMemberManifests(rootDir, parsedRoot.workspaceTable);
193
+ const workspaceMembers = includeWorkspaceMembers
194
+ ? resolveWorkspaceMemberManifests(rootDir, parsedRoot.workspaceTable)
195
+ : [];
172
196
  if (rootIsCrate) {
173
197
  const relRoot = normalizeSlashPath(node_path_1.default.relative(cwd, rootManifestPath));
174
198
  return [...new Set([relRoot, ...workspaceMembers])].sort((a, b) => a.localeCompare(b));
@@ -263,21 +287,22 @@ function parseDependencyName(line) {
263
287
  const match = line.match(/^\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z0-9_-]+))\s*=/u);
264
288
  return match?.[1] ?? match?.[2] ?? match?.[3] ?? null;
265
289
  }
266
- function writeInternalDependencyVersionInLine(line, dependencyName, internalCrates, version) {
267
- if (!internalCrates.has(dependencyName)) {
290
+ function writeInternalDependencyVersionInLine(line, dependencyName, versionByDependency) {
291
+ const nextVersion = versionByDependency.get(dependencyName);
292
+ if (!nextVersion) {
268
293
  return line;
269
294
  }
270
295
  const stringVersionMatch = line.match(/^(\s*(?:"[^"]+"|'[^']+'|[A-Za-z0-9_-]+)\s*=\s*)(["'])([^"']*)(\2)(\s*(?:#.*)?)?$/u);
271
296
  if (stringVersionMatch) {
272
297
  const [, prefix = "", quote = '"', , , suffix = ""] = stringVersionMatch;
273
- return `${prefix}${quote}${version}${quote}${suffix}`;
298
+ return `${prefix}${quote}${nextVersion}${quote}${suffix}`;
274
299
  }
275
300
  const inlineTableMatch = line.match(/^(\s*(?:"[^"]+"|'[^']+'|[A-Za-z0-9_-]+)\s*=\s*\{)(.*)(\}\s*(?:#.*)?)$/u);
276
301
  if (!inlineTableMatch) {
277
302
  return line;
278
303
  }
279
304
  const [, prefix = "", tableBody = "", suffix = ""] = inlineTableMatch;
280
- const updatedTableBody = tableBody.replace(/(\bversion\s*=\s*)(["'])([^"']*)(\2)/u, `$1$2${version}$4`);
305
+ const updatedTableBody = tableBody.replace(/(\bversion\s*=\s*)(["'])([^"']*)(\2)/u, `$1$2${nextVersion}$4`);
281
306
  if (updatedTableBody === tableBody) {
282
307
  return line;
283
308
  }
@@ -287,6 +312,16 @@ function writeInternalDependencyVersions(cargoTomlRaw, internalCrates, version)
287
312
  if (internalCrates.size === 0) {
288
313
  return cargoTomlRaw;
289
314
  }
315
+ const versionByDependency = new Map();
316
+ for (const crateName of internalCrates) {
317
+ versionByDependency.set(crateName, version);
318
+ }
319
+ return writeMappedDependencyVersions(cargoTomlRaw, versionByDependency);
320
+ }
321
+ function writeMappedDependencyVersions(cargoTomlRaw, versionByDependency) {
322
+ if (versionByDependency.size === 0) {
323
+ return cargoTomlRaw;
324
+ }
290
325
  const lineEnding = cargoTomlRaw.includes("\r\n") ? "\r\n" : "\n";
291
326
  const hasFinalLineEnding = cargoTomlRaw.endsWith("\n") || cargoTomlRaw.endsWith("\r\n");
292
327
  const lines = cargoTomlRaw.split(/\r?\n/u);
@@ -305,7 +340,7 @@ function writeInternalDependencyVersions(cargoTomlRaw, internalCrates, version)
305
340
  if (!dependencyName) {
306
341
  continue;
307
342
  }
308
- lines[index] = writeInternalDependencyVersionInLine(line, dependencyName, internalCrates, version);
343
+ lines[index] = writeInternalDependencyVersionInLine(line, dependencyName, versionByDependency);
309
344
  }
310
345
  let updated = lines.join(lineEnding);
311
346
  if (hasFinalLineEnding && !updated.endsWith(lineEnding)) {
@@ -316,6 +351,79 @@ function writeInternalDependencyVersions(cargoTomlRaw, internalCrates, version)
316
351
  }
317
352
  return updated;
318
353
  }
354
+ function readPackageNameForManifest(cwd, manifest) {
355
+ const manifestPath = node_path_1.default.join(cwd, manifest);
356
+ const cargoTomlRaw = node_fs_1.default.readFileSync(manifestPath, "utf8");
357
+ if (!isCrateManifest(manifest, cargoTomlRaw)) {
358
+ throw new Error(`Configured rust target "${manifest}" is not a Rust crate manifest to update.`);
359
+ }
360
+ return readCargoPackageName(cargoTomlRaw, manifest);
361
+ }
362
+ function applyRustWorkspaceDependencyUpdates(cwd, manifestToVersion) {
363
+ const versionByDependency = new Map();
364
+ for (const [manifest, version] of Object.entries(manifestToVersion)) {
365
+ if (!version) {
366
+ continue;
367
+ }
368
+ const crateName = readPackageNameForManifest(cwd, manifest);
369
+ versionByDependency.set(crateName, version);
370
+ }
371
+ if (versionByDependency.size === 0) {
372
+ return [];
373
+ }
374
+ const updatedFiles = [];
375
+ const manifests = collectAllCrateManifests(cwd);
376
+ for (const manifest of manifests) {
377
+ const manifestPath = node_path_1.default.join(cwd, manifest);
378
+ if (!node_fs_1.default.existsSync(manifestPath)) {
379
+ continue;
380
+ }
381
+ const cargoTomlRaw = node_fs_1.default.readFileSync(manifestPath, "utf8");
382
+ if (!isCrateManifest(manifest, cargoTomlRaw)) {
383
+ continue;
384
+ }
385
+ const next = writeMappedDependencyVersions(cargoTomlRaw, versionByDependency);
386
+ if (next !== cargoTomlRaw) {
387
+ node_fs_1.default.writeFileSync(manifestPath, next, "utf8");
388
+ updatedFiles.push(manifest);
389
+ }
390
+ }
391
+ return updatedFiles;
392
+ }
393
+ function detectRustDependencyImpact(cwd, manifestToVersion, candidateManifests) {
394
+ const versionByDependency = new Map();
395
+ for (const [manifest, version] of Object.entries(manifestToVersion)) {
396
+ if (!version) {
397
+ continue;
398
+ }
399
+ const crateName = readPackageNameForManifest(cwd, manifest);
400
+ versionByDependency.set(crateName, version);
401
+ }
402
+ if (versionByDependency.size === 0) {
403
+ return [];
404
+ }
405
+ const impacted = [];
406
+ for (const manifest of [...new Set(candidateManifests)].sort((a, b) => a.localeCompare(b))) {
407
+ const manifestPath = node_path_1.default.join(cwd, manifest);
408
+ if (!node_fs_1.default.existsSync(manifestPath)) {
409
+ continue;
410
+ }
411
+ const cargoTomlRaw = node_fs_1.default.readFileSync(manifestPath, "utf8");
412
+ if (!isCrateManifest(manifest, cargoTomlRaw)) {
413
+ continue;
414
+ }
415
+ const next = writeMappedDependencyVersions(cargoTomlRaw, versionByDependency);
416
+ if (next !== cargoTomlRaw) {
417
+ impacted.push(manifest);
418
+ }
419
+ }
420
+ return impacted;
421
+ }
422
+ function toCargoManifestPath(packagePath) {
423
+ return packagePath === "."
424
+ ? "Cargo.toml"
425
+ : normalizeSlashPath(node_path_1.default.posix.join(packagePath, "Cargo.toml"));
426
+ }
319
427
  exports.rustVersionStrategy = {
320
428
  name: "rust",
321
429
  getVersionFile(config) {
@@ -323,7 +431,7 @@ exports.rustVersionStrategy = {
323
431
  },
324
432
  readVersion(cwd, config) {
325
433
  const versionFile = this.getVersionFile(config);
326
- const manifests = collectRustTargetManifests(cwd, versionFile);
434
+ const manifests = collectRustTargetManifests(cwd, versionFile, !config.packages);
327
435
  const selectedManifest = manifests[0];
328
436
  if (!selectedManifest) {
329
437
  throw new Error(`Configured rust target "${versionFile}" did not resolve to a Rust crate manifest.`);
@@ -333,7 +441,7 @@ exports.rustVersionStrategy = {
333
441
  },
334
442
  writeVersion(cwd, config, version) {
335
443
  const versionFile = this.getVersionFile(config);
336
- const manifests = collectRustTargetManifests(cwd, versionFile);
444
+ const manifests = collectRustTargetManifests(cwd, versionFile, !config.packages);
337
445
  const updatedFiles = [];
338
446
  const internalCrates = new Set();
339
447
  for (const manifest of manifests) {
@@ -7,6 +7,7 @@ exports.verifyProject = verifyProject;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
9
  const load_config_js_1 = require("../config/load-config.js");
10
+ const package_context_js_1 = require("../domain/strategy/package-context.js");
10
11
  const resolve_js_1 = require("../domain/strategy/resolve.js");
11
12
  function verifyProject(cwd = process.cwd()) {
12
13
  const checks = [];
@@ -25,7 +26,7 @@ function verifyProject(cwd = process.cwd()) {
25
26
  details: exists ? "Version file exists" : `Missing ${versionFile}`,
26
27
  });
27
28
  if (config.config.packages) {
28
- for (const pkgPathRaw of Object.keys(config.config.packages)) {
29
+ for (const [pkgPathRaw, packageConfig] of Object.entries(config.config.packages)) {
29
30
  const pkgPath = node_path_1.default.join(cwd, pkgPathRaw);
30
31
  const exists = node_fs_1.default.existsSync(pkgPath);
31
32
  checks.push({
@@ -33,6 +34,18 @@ function verifyProject(cwd = process.cwd()) {
33
34
  ok: exists,
34
35
  details: exists ? "Path exists" : `Missing path: ${pkgPathRaw}`,
35
36
  });
37
+ if (exists) {
38
+ const packageContext = (0, package_context_js_1.resolvePackageStrategyContext)(config.config, pkgPathRaw, packageConfig);
39
+ const packageVersionFile = packageContext.versionFile;
40
+ const packageVersionExists = node_fs_1.default.existsSync(node_path_1.default.join(cwd, packageVersionFile));
41
+ checks.push({
42
+ name: `version-file:${packageVersionFile}`,
43
+ ok: packageVersionExists,
44
+ details: packageVersionExists
45
+ ? "Version file exists"
46
+ : `Missing ${packageVersionFile}`,
47
+ });
48
+ }
36
49
  }
37
50
  }
38
51
  const ok = checks.every((c) => c.ok);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "versionary",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Automatic release framework based on conventional commits and semantic versioning",
5
5
  "keywords": [
6
6
  "releasing",