lerna
Version:
Lerna is a fast, modern build system for managing and publishing multiple JavaScript/TypeScript packages from the same repository
812 lines (807 loc) • 28.1 kB
JavaScript
import {
gitPush
} from "./chunk-7CE6W7VR.js";
import {
gitTag
} from "./chunk-NLQX4D3A.js";
import {
isAnythingCommitted
} from "./chunk-UGM6LAJ4.js";
import {
isBehindUpstream
} from "./chunk-NFRKDJAE.js";
import {
isBreakingChange
} from "./chunk-BLBEQEOI.js";
import {
makePromptVersion
} from "./chunk-4SBEQS72.js";
import {
remoteBranchExists
} from "./chunk-WKFTBBVB.js";
import {
updateLockfileVersion
} from "./chunk-DZSBX7VM.js";
import {
createRelease,
createReleaseClient
} from "./chunk-IKWGB6FU.js";
import {
getCurrentBranch
} from "./chunk-IXOVJCOO.js";
import {
gitAdd
} from "./chunk-3JVNTSAN.js";
import {
gitCommit
} from "./chunk-YNT6CFMU.js";
import {
Command,
ValidationError,
applyBuildMetadata,
checkWorkingTree,
collectProjectUpdates,
collectProjects,
colorize,
createRunner,
exec,
execPackageManager,
execPackageManagerSync,
formatJSON,
getPackage,
getPackagesForOption,
npmlog_default,
output,
prereleaseIdFromVersion,
promptConfirmation,
recommendVersion,
runProjectsTopologically,
throwIfUncommitted,
updateChangelog
} from "./chunk-WC2B4V4E.js";
// libs/commands/version/src/index.ts
import dedent from "dedent";
import execa from "execa";
import fs2 from "fs";
import minimatch from "minimatch";
import os from "os";
import pMap from "p-map";
import path2 from "path";
import semver from "semver";
// libs/commands/version/src/lib/update-bun-lockfile.ts
import fs from "fs";
import path from "path";
var LOCKFILE_NAMES = ["bun.lockb", "bun.lock"];
var BACKUP_SUFFIX = ".lerna-backup";
async function updateBunLockfile({
rootPath,
npmClientArgs,
runScriptsOnLockfileUpdate,
execOpts
}) {
const candidates = LOCKFILE_NAMES.map((name) => path.join(rootPath, name));
const staleLockfiles = candidates.filter((candidate) => fs.existsSync(candidate));
if (staleLockfiles.length === 0) {
npmlog_default.verbose(
"version",
`No bun lockfile (${LOCKFILE_NAMES.join(", ")}) found at the repo root, skipping lockfile update`
);
return [];
}
npmlog_default.verbose("version", `Updating root ${staleLockfiles.map((p) => path.basename(p)).join(", ")}`);
const backups = [];
try {
for (const lockfilePath of staleLockfiles) {
const backupPath = `${lockfilePath}${BACKUP_SUFFIX}`;
fs.renameSync(lockfilePath, backupPath);
backups.push([lockfilePath, backupPath]);
}
await execPackageManager(
"bun",
[
"install",
"--lockfile-only",
!runScriptsOnLockfileUpdate ? "--ignore-scripts" : "",
...npmClientArgs
].filter(Boolean),
execOpts
);
} catch (err) {
restoreBackups(backups, candidates);
npmlog_default.error(
"version",
"Failed to update the bun lockfile via `bun install --lockfile-only`. The original lockfile(s) have been restored. Ensure bun is installed and on your PATH."
);
throw err;
}
for (const [, backupPath] of backups) {
try {
fs.unlinkSync(backupPath);
} catch (cleanupErr) {
npmlog_default.warn("version", `Could not remove lockfile backup ${backupPath}: ${cleanupErr}`);
}
}
const changedFiles = new Set(staleLockfiles);
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
changedFiles.add(candidate);
}
}
return Array.from(changedFiles);
}
function restoreBackups(backups, candidates) {
try {
for (const candidate of candidates) {
if (fs.existsSync(candidate)) {
fs.unlinkSync(candidate);
}
}
for (const [lockfilePath, backupPath] of backups) {
if (fs.existsSync(backupPath)) {
fs.renameSync(backupPath, lockfilePath);
}
}
} catch (restoreErr) {
npmlog_default.error(
"version",
`Failed to restore the original bun lockfile(s): ${restoreErr}. Backup files with the ${BACKUP_SUFFIX} suffix may remain next to them for manual recovery.`
);
}
}
// libs/commands/version/src/index.ts
function factory(argv, preInitializedProjectData) {
return new VersionCommand(argv, preInitializedProjectData);
}
var VersionCommand = class extends Command {
commitAndTag;
pushToRemote;
allowBranch;
gitRemote;
tagPrefix;
releaseClient;
releaseNotes;
gitOpts;
savePrefix;
currentBranch;
updates = [];
tags;
globalVersion;
hasRootedLeaf;
runPackageLifecycle;
runRootLifecycle;
updatesVersions;
packagesToVersion;
projectsWithPackage = [];
premajorVersionBump;
get otherCommandConfigs() {
return ["publish"];
}
get requiresGit() {
return !!(this.commitAndTag || this.pushToRemote || this.options.allowBranch || this.options.conventionalCommits);
}
/**
* Due to lerna publish's legacy of being backwards compatible with running versioning and publishing
* in a single step, we need to be able to receive any project data which might already exist from the
* publish command (in the case that it invokes the version command from within its implementation details).
*/
constructor(argv, preInitializedProjectData) {
super(argv, { skipValidations: false, preInitializedProjectData });
}
configureProperties() {
super.configureProperties();
const {
amend,
commitHooks = true,
gitRemote = "origin",
gitTagVersion = true,
granularPathspec = true,
push = true,
signGitCommit,
signoffGitCommit,
signGitTag,
forceGitTag,
tagVersionPrefix = "v",
premajorVersionBump = "default",
message
} = this.options;
this.gitRemote = gitRemote;
this.tagPrefix = tagVersionPrefix;
this.commitAndTag = gitTagVersion;
this.pushToRemote = gitTagVersion && amend !== true && push;
const overrideMessage = amend && !!message;
this.premajorVersionBump = premajorVersionBump;
this.releaseClient = this.pushToRemote && this.options.createRelease && createReleaseClient(this.options.createRelease);
this.releaseNotes = [];
if (this.releaseClient && this.options.conventionalCommits !== true) {
throw new ValidationError("ERELEASE", "To create a release, you must enable --conventional-commits");
}
if (this.releaseClient && this.options.changelog === false) {
throw new ValidationError("ERELEASE", "To create a release, you cannot pass --no-changelog");
}
this.gitOpts = {
amend,
commitHooks,
granularPathspec,
signGitCommit,
signoffGitCommit,
signGitTag,
forceGitTag,
overrideMessage
};
this.savePrefix = this.options.exact ? "" : "^";
}
async initialize() {
if (!this.project.isIndependent()) {
this.logger.info("current version", this.project.version);
}
if (this.requiresGit) {
if (!isAnythingCommitted(this.execOpts)) {
throw new ValidationError(
"ENOCOMMIT",
"No commits in this repository. Please commit something before using version."
);
}
this.currentBranch = getCurrentBranch(this.execOpts);
if (this.currentBranch === "HEAD") {
throw new ValidationError(
"ENOGIT",
"Detached git HEAD, please checkout a branch to choose versions."
);
}
if (this.pushToRemote && !remoteBranchExists(this.gitRemote, this.currentBranch, this.execOpts)) {
throw new ValidationError(
"ENOREMOTEBRANCH",
dedent`
Branch '${this.currentBranch}' doesn't exist in remote '${this.gitRemote}'.
If this is a new branch, please make sure you push it to the remote first.
`
);
}
if (this.options.allowBranch && ![].concat(this.options.allowBranch).some((x) => minimatch(this.currentBranch, x))) {
throw new ValidationError(
"ENOTALLOWED",
dedent`
Branch '${this.currentBranch}' is restricted from versioning due to allowBranch config.
Please consider the reasons for this restriction before overriding the option.
`
);
}
if (this.commitAndTag && this.pushToRemote && isBehindUpstream(this.gitRemote, this.currentBranch, this.execOpts)) {
const message = `Local branch '${this.currentBranch}' is behind remote upstream ${this.gitRemote}/${this.currentBranch}`;
if (this.options.ci && this.options.ciBehindBehavior === "skip") {
this.logger.warn("EBEHIND", `${message}, exiting`);
return false;
}
throw new ValidationError(
"EBEHIND",
dedent`
${message}
Please merge remote changes into '${this.currentBranch}' with 'git pull'
`
);
}
} else {
this.logger.notice(
"FYI",
"git repository validation has been skipped, please ensure your version bumps are correct"
);
}
if (this.options.conventionalPrerelease && this.options.conventionalGraduate) {
throw new ValidationError(
"ENOTALLOWED",
dedent`
--conventional-prerelease cannot be combined with --conventional-graduate.
`
);
}
this.projectsWithPackage = Object.values(this.projectGraph.nodes).filter((node) => !!node.package);
this.updates = collectProjectUpdates(
this.projectsWithPackage,
this.projectGraph,
this.execOpts,
this.options
).filter((node) => {
const pkg = getPackage(node);
if (pkg.private && this.options.private === false) {
return false;
}
if (!pkg.version) {
if (pkg.private) {
this.logger.info("version", "Skipping unversioned private package %j", pkg.name);
} else {
throw new ValidationError(
"ENOVERSION",
dedent`
A version field is required in ${pkg.name}'s package.json file.
If you wish to keep the package unversioned, it must be made private.
`
);
}
}
return !!pkg.version;
});
if (!this.updates.length) {
this.logger.success("", `No changed packages to ${this.composed ? "publish" : "version"}`);
return false;
}
this.hasRootedLeaf = !!this.projectGraph.nodes[this.project.manifest.name];
if (this.hasRootedLeaf && !this.composed) {
this.logger.info("version", "rooted leaf detected, skipping synthetic root lifecycles");
}
this.runPackageLifecycle = createRunner({ ...this.options, stdio: "inherit" });
this.runRootLifecycle = /^(pre|post)?version$/.test(process.env["npm_lifecycle_event"]) ? (stage) => {
this.logger.warn("lifecycle", "Skipping root %j because it has already been called", stage);
} : (stage) => this.runPackageLifecycle(this.project.manifest, stage);
if (this.commitAndTag && this.gitOpts.amend !== true) {
const { forcePublish, conventionalCommits, conventionalGraduate } = this.options;
const checkUncommittedOnly = forcePublish || conventionalCommits && conventionalGraduate;
const check = checkUncommittedOnly ? throwIfUncommitted : checkWorkingTree;
await check(this.execOpts);
} else {
this.logger.warn("version", "Skipping working tree validation, proceed at your own risk");
}
const versions = await this.getVersionsForUpdates();
this.setUpdatesForVersions(versions);
return this.confirmVersions();
}
async execute() {
const tasks = [() => this.updatePackageVersions()];
if (this.commitAndTag) {
tasks.push(() => this.commitAndTagUpdates());
} else {
this.logger.info("execute", "Skipping git tag/commit");
}
if (this.pushToRemote) {
tasks.push(() => this.gitPushToRemote());
} else {
this.logger.info("execute", "Skipping git push");
}
if (this.releaseClient) {
this.logger.info("execute", "Creating releases...");
tasks.push(
() => createRelease(
this.releaseClient,
{
type: this.options.createRelease,
tags: this.tags,
tagVersionSeparator: this.options.tagVersionSeparator || "@",
releaseNotes: this.releaseNotes
},
{ gitRemote: this.options.gitRemote, execOpts: this.execOpts }
)
);
} else {
this.logger.info("execute", "Skipping releases");
}
for (const task of tasks) {
await task();
}
if (!this.composed) {
this.logger.success("version", "finished");
}
return {
updates: this.updates,
updatesVersions: this.updatesVersions
};
}
/**
* Gets a mapping of project names to their package's new version.
* @returns {Promise<Record<string, string>>} A map of project names to their package's new versions
*/
getVersionsForUpdates() {
const independentVersions = this.project.isIndependent();
const { bump, conventionalCommits, preid } = this.options;
const repoVersion = bump ? semver.clean(bump) : "";
const increment = bump && !semver.valid(bump) ? bump : "";
const resolvePrereleaseId = (existingPreid) => preid || existingPreid || "alpha";
const makeGlobalVersionPredicate = (nextVersion) => {
this.globalVersion = nextVersion;
return () => nextVersion;
};
let predicate;
if (repoVersion) {
predicate = makeGlobalVersionPredicate(applyBuildMetadata(repoVersion, this.options.buildMetadata));
} else if (increment && independentVersions) {
predicate = (node) => applyBuildMetadata(
semver.inc(node.version, increment, resolvePrereleaseId(node.prereleaseId)),
this.options.buildMetadata
);
} else if (increment) {
const baseVersion = this.project.version;
const prereleaseId = prereleaseIdFromVersion(baseVersion);
const nextVersion = applyBuildMetadata(
semver.inc(baseVersion, increment, resolvePrereleaseId(prereleaseId)),
this.options.buildMetadata
);
predicate = makeGlobalVersionPredicate(nextVersion);
} else if (conventionalCommits) {
return this.recommendVersions(resolvePrereleaseId);
} else if (independentVersions) {
predicate = makePromptVersion(resolvePrereleaseId, this.options.buildMetadata);
} else {
const baseVersion = this.project.version;
const prereleaseId = prereleaseIdFromVersion(baseVersion);
const node = { version: baseVersion, prereleaseId };
const prompt = makePromptVersion(resolvePrereleaseId, this.options.buildMetadata);
predicate = prompt(node).then(makeGlobalVersionPredicate);
}
return Promise.resolve(predicate).then(
(getVersion) => this.reduceVersions((node) => {
const pkg = getPackage(node);
return getVersion({
version: pkg.version,
name: pkg.name,
prereleaseId: prereleaseIdFromVersion(pkg.version)
});
})
);
}
async reduceVersions(getVersion) {
const versionMap = /* @__PURE__ */ new Map();
for (const node of this.updates) {
const version = await Promise.resolve(getVersion(node));
versionMap.set(node.name, version);
}
return versionMap;
}
getPrereleasePackageNames() {
const prereleasePackageNames = getPackagesForOption(this.options.conventionalPrerelease);
const isCandidate = prereleasePackageNames.has("*") ? () => true : (node, name) => prereleasePackageNames.has(name);
return collectProjects(this.projectsWithPackage, this.projectGraph, { isCandidate }).map(
(pkg) => pkg.name
);
}
async recommendVersions(resolvePrereleaseId) {
const independentVersions = this.project.isIndependent();
const { buildMetadata, changelogPreset, conventionalGraduate, conventionalBumpPrerelease } = this.options;
const rootPath = this.project.manifest.location;
const type = independentVersions ? "independent" : "fixed";
const prereleasePackageNames = this.getPrereleasePackageNames();
const graduatePackageNames = Array.from(getPackagesForOption(conventionalGraduate));
const shouldPrerelease = (name) => prereleasePackageNames && prereleasePackageNames.includes(name);
const shouldGraduate = (name) => graduatePackageNames.includes("*") || graduatePackageNames.includes(name);
const getPrereleaseId = (node) => {
if (!shouldGraduate(node.name) && (shouldPrerelease(node.name) || node.prereleaseId)) {
return resolvePrereleaseId(node.prereleaseId);
}
return void 0;
};
if (type === "fixed") {
this.setGlobalVersionFloor();
}
const versions = await this.reduceVersions((node) => {
const pkg = getPackage(node);
return recommendVersion(
pkg,
type,
{
changelogPreset,
rootPath,
tagPrefix: this.tagPrefix,
prereleaseId: getPrereleaseId({
name: node.name,
prereleaseId: prereleaseIdFromVersion(pkg.version)
}),
conventionalBumpPrerelease,
buildMetadata
},
this.premajorVersionBump
);
});
if (type === "fixed") {
this.globalVersion = await this.setGlobalVersionCeiling(versions);
}
return versions;
}
setGlobalVersionFloor() {
const globalVersion = this.project.version;
for (const node of this.updates) {
const pkg = getPackage(node);
if (semver.lt(pkg.version, globalVersion)) {
this.logger.verbose(
"version",
`Overriding version of ${pkg.name} from ${pkg.version} to ${globalVersion}`
);
pkg.set("version", globalVersion);
}
}
}
setGlobalVersionCeiling(versions) {
let highestVersion = this.project.version;
versions.forEach((bump) => {
if (bump && semver.gt(bump, highestVersion)) {
highestVersion = bump;
}
});
versions.forEach((_, name) => versions.set(name, highestVersion));
return highestVersion;
}
setUpdatesForVersions(versions) {
if (this.project.isIndependent() || versions.size === this.projectsWithPackage.length) {
this.updatesVersions = versions;
} else {
let hasBreakingChange;
for (const [name, bump] of versions) {
const pkg = getPackage(this.projectGraph.nodes[name]);
hasBreakingChange = hasBreakingChange || isBreakingChange(pkg.version, bump);
}
if (hasBreakingChange) {
this.updates = this.projectsWithPackage;
if (this.options.private === false) {
this.updates = this.updates.filter((node) => !getPackage(node).private);
}
this.updatesVersions = new Map(this.updates.map((node) => [node.name, this.globalVersion]));
} else {
this.updatesVersions = versions;
}
}
this.packagesToVersion = this.updates.map((node) => getPackage(node));
}
confirmVersions() {
if (this.options.json) {
const updatedProjectsJson = formatJSON(this.updates, ({ name }) => ({
newVersion: this.updatesVersions.get(name)
}));
output(updatedProjectsJson);
} else {
const changes = this.updates.map((node) => {
const pkg = getPackage(node);
let line = ` - ${pkg.name}: ${pkg.version} => ${this.updatesVersions.get(node.name)}`;
if (pkg.private) {
line += ` (${colorize("red", "private")})`;
}
return line;
});
output("");
output("Changes:");
output(changes.join(os.EOL));
output("");
}
if (this.options.yes) {
this.logger.info("auto-confirmed", "");
return true;
}
const message = this.composed ? "Are you sure you want to publish these packages?" : "Are you sure you want to create these versions?";
return promptConfirmation(message);
}
async updatePackageVersions() {
const {
conventionalCommits,
changelogPreset,
changelogEntryAdditionalMarkdown,
changelog = true,
runScriptsOnLockfileUpdate = false,
syncDistVersion = false
} = this.options;
const independentVersions = this.project.isIndependent();
const rootPath = this.project.manifest.location;
const changedFiles = /* @__PURE__ */ new Set();
if (!this.hasRootedLeaf) {
await this.runRootLifecycle("preversion");
}
const actions = [
(node) => this.runPackageLifecycle(getPackage(node), "preversion").then(() => node),
// manifest may be mutated by any previous lifecycle
(node) => getPackage(node).refresh().then(() => node),
(node) => {
const pkg = getPackage(node);
pkg.version = this.updatesVersions.get(node.name);
this.updateDependencies(node);
return Promise.all([
updateLockfileVersion(pkg),
pkg.serialize(),
pkg.syncDistVersion(syncDistVersion)
]).then(([lockfilePath]) => {
changedFiles.add(pkg.manifestLocation);
if (lockfilePath) {
changedFiles.add(lockfilePath);
}
return node;
});
},
(node) => this.runPackageLifecycle(getPackage(node), "version").then(() => node)
];
if (conventionalCommits && changelog) {
const type = independentVersions ? "independent" : "fixed";
actions.push(
(node) => updateChangelog(getPackage(node), type, {
changelogPreset,
changelogEntryAdditionalMarkdown,
rootPath,
tagPrefix: this.tagPrefix
}).then(({ logPath, newEntry }) => {
changedFiles.add(logPath);
if (independentVersions) {
this.releaseNotes.push({
name: getPackage(node).name,
notes: newEntry
});
}
return node;
})
);
}
const mapUpdate = async (node) => {
let result = node;
for (const action of actions) {
result = await action(result);
}
return result;
};
await runProjectsTopologically(this.updates, this.projectGraph, mapUpdate, {
concurrency: this.concurrency,
rejectCycles: this.options.rejectCycles
});
if (!independentVersions) {
this.project.version = this.globalVersion;
if (conventionalCommits && changelog) {
const { logPath, newEntry } = await updateChangelog(this.project.manifest, "root", {
changelogPreset,
changelogEntryAdditionalMarkdown,
rootPath,
tagPrefix: this.tagPrefix,
version: this.globalVersion
});
changedFiles.add(logPath);
this.releaseNotes.push({
name: "fixed",
notes: newEntry
});
}
const lernaConfigLocation = await Promise.resolve(this.project.serializeConfig());
changedFiles.add(lernaConfigLocation);
}
const npmClientArgsRaw = this.options.npmClientArgs || [];
const npmClientArgs = npmClientArgsRaw.reduce(
(args, arg) => args.concat(arg.split(/\s|,/)),
[]
);
if (!this.hasRootedLeaf) {
await this.runRootLifecycle("version");
}
if (this.options.npmClient === "pnpm") {
this.logger.verbose("version", "Updating root pnpm-lock.yaml");
await execPackageManager(
"pnpm",
[
"install",
"--lockfile-only",
!runScriptsOnLockfileUpdate ? "--ignore-scripts" : "",
...npmClientArgs
].filter(Boolean),
this.execOpts
);
const lockfilePath = path2.join(this.project.rootPath, "pnpm-lock.yaml");
changedFiles.add(lockfilePath);
}
if (this.options.npmClient === "bun") {
const bunLockfiles = await updateBunLockfile({
rootPath: this.project.rootPath,
npmClientArgs,
runScriptsOnLockfileUpdate,
execOpts: this.execOpts
});
for (const lockfilePath of bunLockfiles) {
changedFiles.add(lockfilePath);
}
}
if (this.options.npmClient === "yarn") {
const yarnVersion = execPackageManagerSync("yarn", ["--version"], this.execOpts);
this.logger.verbose("version", `Detected yarn version ${yarnVersion}`);
if (semver.gte(yarnVersion, "2.0.0")) {
this.logger.verbose("version", "Updating root yarn.lock");
await execPackageManager("yarn", ["install", "--mode", "update-lockfile", ...npmClientArgs], {
...this.execOpts,
env: {
...process.env,
YARN_ENABLE_SCRIPTS: "false"
}
});
const lockfilePath = path2.join(this.project.rootPath, "yarn.lock");
changedFiles.add(lockfilePath);
}
}
if (this.options.npmClient === "npm" || !this.options.npmClient) {
const lockfilePath = path2.join(this.project.rootPath, "package-lock.json");
if (fs2.existsSync(lockfilePath)) {
this.logger.verbose("version", "Updating root package-lock.json");
await exec(
"npm",
[
"install",
"--package-lock-only",
!runScriptsOnLockfileUpdate ? "--ignore-scripts" : "",
...npmClientArgs
].filter(Boolean),
this.execOpts
);
changedFiles.add(lockfilePath);
}
}
if (this.commitAndTag) {
await gitAdd(Array.from(changedFiles), this.gitOpts, this.execOpts);
}
}
updateDependencies(node) {
const dependencies = this.projectGraph.localPackageDependencies[node.name] || [];
const pkg = getPackage(node);
dependencies.forEach((dep) => {
const depVersion = this.updatesVersions.get(dep.target);
if (
// only update if the dependency version is being changed
depVersion && // don't overwrite local file: specifiers, they only change during publish
dep.targetResolvedNpaResult.type !== "directory"
) {
pkg.updateLocalDependency(dep.targetResolvedNpaResult, depVersion, this.savePrefix);
}
});
}
async commitAndTagUpdates() {
let tags = [];
if (this.project.isIndependent()) {
tags = await this.gitCommitAndTagVersionForUpdates();
} else {
tags = await this.gitCommitAndTagVersion();
}
this.tags = tags;
await pMap(this.packagesToVersion, (pkg) => this.runPackageLifecycle(pkg, "postversion"));
if (!this.hasRootedLeaf) {
await this.runRootLifecycle("postversion");
}
}
async gitCommitAndTagVersionForUpdates() {
const tagVersionSeparator = this.options.tagVersionSeparator || "@";
const tags = this.updates.map((node) => {
const pkg = getPackage(node);
return `${pkg.name}${tagVersionSeparator}${this.updatesVersions.get(node.name)}`;
});
const subject = this.options.message || "Publish";
const message = tags.reduce((msg, tag) => `${msg}${os.EOL} - ${tag}`, `${subject}${os.EOL}`);
if (await this.hasChanges()) {
await gitCommit(message, this.gitOpts, this.execOpts);
}
if (this.gitOpts.signGitTag) {
for (const tag of tags) await gitTag(tag, this.gitOpts, this.execOpts, this.options.gitTagCommand);
} else {
await Promise.all(
tags.map((tag) => gitTag(tag, this.gitOpts, this.execOpts, this.options.gitTagCommand))
);
}
return tags;
}
async gitCommitAndTagVersion() {
const version = this.globalVersion;
const tag = `${this.tagPrefix}${version}`;
const message = this.options.message ? this.options.message.replace(/%s/g, tag).replace(/%v/g, version) : tag;
if (await this.hasChanges()) {
await gitCommit(message, this.gitOpts, this.execOpts);
}
await gitTag(tag, this.gitOpts, this.execOpts, this.options.gitTagCommand);
return [tag];
}
gitPushToRemote() {
this.logger.info("git", "Pushing tags...");
return gitPush(this.gitRemote, this.currentBranch, this.execOpts);
}
async hasChanges() {
try {
await execa("git", ["diff", "--staged", "--quiet"], {
stdio: "pipe",
...this.execOpts,
cwd: this.execOpts.cwd
// force it to a string
});
} catch (e) {
return true;
}
return void 0;
}
};
var commonJsExport = Object.assign(factory, { VersionCommand });
var src_default = commonJsExport;
export {
factory,
VersionCommand,
commonJsExport,
src_default
};