UNPKG

long-git-cli

Version:

A CLI tool for Git tag management.

175 lines 5.19 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TAG_FORMATS = void 0; exports.parseTagFormat = parseTagFormat; exports.parseTag = parseTag; exports.detectTagFormat = detectTagFormat; exports.incrementVersion = incrementVersion; exports.formatTag = formatTag; exports.compareVersions = compareVersions; exports.findLatestTag = findLatestTag; exports.generateNextTag = generateNextTag; /** * 预定义的 Tag 格式 */ exports.TAG_FORMATS = { TEST: { prefix: 'test-v', pattern: '00.00.0000' }, UAT: { prefix: 'uat-v', pattern: '00.00.0000' }, PROD: { prefix: 'v', pattern: '00.00.0000' }, }; /** * 解析 tag 格式配置 * @param format 格式字符串,如 'test-v00.00.0000' */ function parseTagFormat(format) { /** 提取前缀(非数字部分) */ const match = format.match(/^([^\d]+)([\d.]+)$/); if (!match) { throw new Error(`无效的 tag 格式: ${format}`); } return { prefix: match[1], pattern: match[2], }; } /** * 解析 tag 字符串,提取版本号信息 * @param tag tag 字符串 * @param format 可选的格式配置,如果不提供则自动检测 */ function parseTag(tag, format) { let prefix; let pattern; if (format) { prefix = format.prefix; pattern = format.pattern; } else { /** 自动检测格式 */ const detectedFormat = detectTagFormat(tag); if (!detectedFormat) { throw new Error(`无法识别的 tag 格式: ${tag}`); } prefix = detectedFormat.prefix; pattern = detectedFormat.pattern; } /** 移除前缀 */ if (!tag.startsWith(prefix)) { throw new Error(`tag "${tag}" 不匹配前缀 "${prefix}"`); } const versionPart = tag.substring(prefix.length); /** 解析版本号 */ const parts = versionPart.split('.'); if (parts.length !== 3) { throw new Error(`无效的版本号格式: ${versionPart},期望 3 个部分`); } return { version: tag, major: parseInt(parts[0], 10), minor: parseInt(parts[1], 10), patch: parseInt(parts[2], 10), build: parseInt(parts[2], 10), }; } /** * 自动检测 tag 格式 */ function detectTagFormat(tag) { /** 尝试匹配已知格式 */ for (const format of Object.values(exports.TAG_FORMATS)) { if (tag.startsWith(format.prefix)) { return format; } } /** 尝试通用匹配 */ const match = tag.match(/^([^\d]+)([\d.]+)$/); if (match) { return { prefix: match[1], pattern: match[2].replace(/\d/g, '0'), }; } return null; } /** * 递增版本号,将 build 和 patch 版本号加 1 */ function incrementVersion(tagInfo) { return { ...tagInfo, build: tagInfo.build + 1, patch: tagInfo.build + 1, }; } /** * 格式化版本信息为 tag 字符串 * @param tagInfo 版本信息 * @param format 格式配置 */ function formatTag(tagInfo, format) { const patternParts = format.pattern.split('.'); const major = tagInfo.major.toString().padStart(patternParts[0].length, '0'); const minor = tagInfo.minor.toString().padStart(patternParts[1].length, '0'); const build = tagInfo.build.toString().padStart(patternParts[2].length, '0'); return `${format.prefix}${major}.${minor}.${build}`; } /** * 比较两个版本号的大小 */ function compareVersions(a, b) { if (a.major !== b.major) return a.major - b.major; if (a.minor !== b.minor) return a.minor - b.minor; return a.build - b.build; } /** * 查找匹配格式的最新 tag * @param tags tag 列表 * @param format 格式配置 */ function findLatestTag(tags, format) { /** 过滤匹配前缀的 tags */ const matchedTags = tags.filter((tag) => tag.startsWith(format.prefix)); if (matchedTags.length === 0) { return null; } /** 解析并排序 */ const parsedTags = matchedTags .map((tag) => { try { return parseTag(tag, format); } catch { return null; } }) .filter((t) => t !== null); if (parsedTags.length === 0) { return null; } /** 按版本号排序,返回最新的 */ parsedTags.sort(compareVersions); return parsedTags[parsedTags.length - 1].version; } /** * 生成下一个 tag * @param tags 现有 tag 列表 * @param format 格式配置 */ function generateNextTag(tags, format) { const latestTag = findLatestTag(tags, format); if (!latestTag) { /** 如果没有现有 tag,返回初始版本 */ const patternParts = format.pattern.split('.'); const major = '0'.repeat(patternParts[0].length); const minor = '0'.repeat(patternParts[1].length); const build = '1'.padStart(patternParts[2].length, '0'); return `${format.prefix}${major}.${minor}.${build}`; } /** 递增版本号 */ const tagInfo = parseTag(latestTag, format); const nextTagInfo = incrementVersion(tagInfo); return formatTag(nextTagInfo, format); } //# sourceMappingURL=tag.js.map