git-release-manager
Version:
A tool to generate release notes from git commit history
140 lines • 6.25 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveReference = resolveReference;
exports.determineType = determineType;
const simple_git_1 = __importDefault(require("simple-git"));
const ReferenceTypesEnum_1 = require("../../changes/types/ReferenceTypesEnum");
const date_1 = require("../../../utils/date");
const branchUtils_1 = require("./branchUtils");
const tagUtils_1 = require("./tagUtils");
const commitUtils_1 = require("./commitUtils");
const git = (0, simple_git_1.default)();
/**
* Resolves a Git reference to its commit hash and associated metadata.
*
* @param value - The reference value to resolve. This can be a commit hash, branch name, tag name, or date.
* @param isStart - Optional flag indicating whether to resolve the reference as the start of a range.
* @returns A promise that resolves to a `GitReference` object containing the resolved reference details, or `null` if the reference could not be resolved.
*
* The function determines the type of the reference (commit, reference, date, tag, or branch) and resolves it accordingly.
* If the reference is `null`, it resolves to the first or last commit based on the `isStart` flag.
* If the reference is a date, it resolves to the first or last commit after or before the date, respectively.
* If the reference is a branch, it validates the branch and resolves to the first or last commit in the branch based on the `isStart` flag.
*
* @throws Will throw an error if the reference type is unsupported or if the reference could not be resolved.
*/
async function resolveReference(value, isStart) {
let type;
let reference = null;
if (!value) {
type = ReferenceTypesEnum_1.ReferenceTypesEnum.commit;
value = null;
try {
if (isStart) {
const logs = await git.log(['--reverse']);
reference = logs.all.length ? logs.all[0].hash : null;
}
else {
reference = await git.revparse(['HEAD']);
}
}
catch (error) {
console.error('Error resolving first/last commit:', error);
return null;
}
}
else {
type = await determineType(value);
try {
switch (type) {
case ReferenceTypesEnum_1.ReferenceTypesEnum.commit:
case ReferenceTypesEnum_1.ReferenceTypesEnum.ref:
reference = await git.revparse([value]);
break;
case ReferenceTypesEnum_1.ReferenceTypesEnum.date: {
const formattedDate = (0, date_1.formatISO8601)(value);
if (isStart) {
const logsAfter = await git.log(['--after', formattedDate, '--reverse']);
reference = logsAfter.all.length ? logsAfter.all[0].hash : null;
}
else {
const logsBefore = await git.log(['--before', formattedDate]);
reference = logsBefore.latest ? logsBefore.latest.hash : null;
}
break;
}
case ReferenceTypesEnum_1.ReferenceTypesEnum.tag:
reference = await git.revparse([value]);
break;
case ReferenceTypesEnum_1.ReferenceTypesEnum.branch: {
const isValidBranch = await (0, branchUtils_1.isGitBranch)(value);
if (!isValidBranch) {
throw new Error(`Invalid branch: ${value}`);
}
if (isStart) {
const logsInBranch = await git.log([value]);
reference = logsInBranch.all.length ? logsInBranch.all[logsInBranch.all.length - 1].hash : null;
}
else {
reference = await git.revparse([value]);
}
break;
}
default:
throw new Error(`Unsupported reference type for: ${value}`);
}
if (!reference) {
throw new Error(`Could not resolve reference: ${value}`);
}
}
catch (error) {
console.error(`Error resolving reference: ${value}`, error);
throw error;
}
}
if (!reference) {
throw new Error('Commit ID is null');
}
const rawResult = await git.raw(['show', '-s', '--format=%ci', reference]);
const dateRegex = /\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [+-]\d{4}/;
const match = rawResult.match(dateRegex);
if (!match) {
throw new Error('Could not extract date from git show output');
}
const date = (0, date_1.formatISO8601)(match[0].trim());
return {
name: reference,
value,
type,
reference,
date,
};
}
async function determineType(value) {
const commitRegex = /^[a-f0-9]{7,40}$/i;
const dateRegex = /^(\d{4})-(\d{2})-(\d{2})[T\s](\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|([+-]\d{2}:\d{2}))?$/;
const semanticTagRegex = /^v?\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+(\.[a-zA-Z0-9.-]+)*)?$/;
const refRegex = /^(HEAD(~\d+)?|[a-zA-Z0-9._-]+)$/;
if (RegExp(commitRegex).exec(value) && (await (0, commitUtils_1.isGitCommit)(value))) {
return ReferenceTypesEnum_1.ReferenceTypesEnum.commit;
}
else if (RegExp(dateRegex).exec(value)) {
return ReferenceTypesEnum_1.ReferenceTypesEnum.date;
}
else if (semanticTagRegex.test(value) && (await (0, tagUtils_1.isGitTag)(value))) {
return ReferenceTypesEnum_1.ReferenceTypesEnum.tag;
}
else if (refRegex.test(value)) {
if (await (0, branchUtils_1.isGitBranch)(value)) {
return ReferenceTypesEnum_1.ReferenceTypesEnum.branch;
}
if (await (0, tagUtils_1.isGitTag)(value)) {
return ReferenceTypesEnum_1.ReferenceTypesEnum.tag;
}
return ReferenceTypesEnum_1.ReferenceTypesEnum.ref;
}
}
//# sourceMappingURL=referenceUtils.js.map