Skip to content

Commit

Permalink
feat: improve commit printing
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Sep 28, 2024
1 parent 2ff30dd commit aaad54d
Show file tree
Hide file tree
Showing 3 changed files with 318 additions and 117 deletions.
118 changes: 1 addition & 117 deletions src/get-new-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as ezSpawn from '@jsdevtools/ez-spawn'
import c from 'picocolors'
import prompts from 'prompts'
import semver, { clean as cleanVersion, valid as isValidVersion, SemVer } from 'semver'
import { printRecentCommits } from './print-commits'
import { isPrerelease, releaseTypes } from './release-type'

/**
Expand Down Expand Up @@ -153,120 +154,3 @@ async function promptForNewVersion(operation: Operation): Promise<Operation> {
return operation.update({ release: answers.release, newVersion })
}
}

const messageColorMap: Record<string, (c: string) => string> = {
chore: c.gray,
fix: c.yellow,
feat: c.green,
refactor: c.cyan,
docs: c.blue,
doc: c.blue,
ci: c.gray,
build: c.gray,
}

export async function printRecentCommits(operation: Operation): Promise<void> {
let sha: string | undefined
sha ||= await ezSpawn
.async(
'git',
['rev-list', '-n', '1', `v${operation.state.currentVersion}`],
{ stdio: 'pipe' },
)
.then(res => res.stdout.trim())
.catch(() => undefined)
sha ||= await ezSpawn
.async(
'git',
['rev-list', '-n', '1', operation.state.currentVersion],
{ stdio: 'pipe' },
)
.then(res => res.stdout.trim())
.catch(() => undefined)

if (!sha) {
console.log(
c.blue(`i`)
+ c.gray(` Failed to locate the previous tag ${c.yellow(`v${operation.state.currentVersion}`)}`),
)
return
}

const message = await ezSpawn.async(
'git',
[
'--no-pager',
'log',
`${sha}..HEAD`,
'--oneline',
],
{ stdio: 'pipe' },
)

const lines = message
.stdout
.toString()
.trim()
.split(/\n/g)

if (!lines.length) {
console.log()
console.log(c.blue(`i`) + c.gray(` No commits since ${operation.state.currentVersion}`))
console.log()
return
}

interface ParsedCommit {
hash: string
tag: string
message: string
color: (c: string) => string
}

const parsed = lines.map((line): ParsedCommit => {
const [hash, ...parts] = line.split(' ')
const message = parts.join(' ')
const match = message.match(/^(\w+)(\([^)]+\))?(!)?:(.*)$/)
if (match) {
let color = messageColorMap[match[1].toLowerCase()] || ((c: string) => c)
if (match[3] === '!') {
color = c.red
}
const tag = [match[1], match[2], match[3]].filter(Boolean).join('')
return {
hash,
tag,
message: match[4].trim(),
color,
}
}
return {
hash,
tag: '',
message,
color: c => c,
}
})
const tagLength = parsed.map(({ tag }) => tag.length).reduce((a, b) => Math.max(a, b), 0)
const prettified = parsed.map(({ hash, tag, message, color }) => {
const paddedTag = tag.padStart(tagLength + 2, ' ')
return [
c.dim(hash),
' ',
color === c.gray ? color(paddedTag) : c.bold(color(paddedTag)),
c.dim(':'),
' ',
color === c.gray ? color(message) : message,
].join('')
})

console.log()
console.log(
c.bold(
`${c.green(lines.length)} Commits since ${c.gray(sha.slice(0, 7))}:`,
),
)
console.log()
console.log(prettified.reverse().join('\n'))
console.log()
}
149 changes: 149 additions & 0 deletions src/print-commits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import type { Operation } from './operation'
import * as ezSpawn from '@jsdevtools/ez-spawn'
import c from 'picocolors'

const messageColorMap: Record<string, (c: string) => string> = {
chore: c.gray,
fix: c.yellow,
feat: c.green,
refactor: c.cyan,
docs: c.blue,
doc: c.blue,
ci: c.gray,
build: c.gray,
}

interface ParsedCommit {
hash: string
message: string
tag: string
breaking?: boolean
scope: string
color: (c: string) => string
}

export function parseCommits(raw: string) {
const lines = raw
.toString()
.trim()
.split(/\n/g)

if (!lines.length) {
return []
}

return lines
.map((line): ParsedCommit => {
const [hash, ...parts] = line.split(' ')
const message = parts.join(' ')
const match = message.match(/^(\w+)(!)?(\([^)]+\))?:(.*)$/)
if (match) {
let color = messageColorMap[match[1].toLowerCase()] || ((c: string) => c)
if (match[2] === '!') {
color = s => c.inverse(c.red(s))
}
const tag = [match[1], match[2]].filter(Boolean).join('')
const scope = match[3] || ''
return {
hash,
tag,
message: match[4].trim(),
scope,
breaking: match[2] === '!',
color,
}
}
return {
hash,
tag: '',
message,
scope: '',
color: c => c,
}
})
.reverse()
}

export function formatParsedCommits(commits: ParsedCommit[]) {
const tagLength = commits.map(({ tag }) => tag.length).reduce((a, b) => Math.max(a, b), 0)
let scopeLength = commits.map(({ scope }) => scope.length).reduce((a, b) => Math.max(a, b), 0)
if (scopeLength)
scopeLength += 2

return commits.map(({ hash, tag, message, scope, color }) => {
const paddedTag = tag.padStart(tagLength + 1, ' ')
const paddedScope = !scope
? ' '.repeat(scopeLength)
: c.dim('(') + scope.slice(1, -1) + c.dim(')') + ' '.repeat(scopeLength - scope.length)

return [
c.dim(hash),
' ',
color === c.gray ? color(paddedTag) : c.bold(color(paddedTag)),
' ',
paddedScope,
c.dim(':'),
' ',
color === c.gray ? color(message) : message,
].join('')
})
}

export async function printRecentCommits(operation: Operation): Promise<void> {
let sha: string | undefined
sha ||= await ezSpawn
.async(
'git',
['rev-list', '-n', '1', `v${operation.state.currentVersion}`],
{ stdio: 'pipe' },
)
.then(res => res.stdout.trim())
.catch(() => undefined)
sha ||= await ezSpawn
.async(
'git',
['rev-list', '-n', '1', operation.state.currentVersion],
{ stdio: 'pipe' },
)
.then(res => res.stdout.trim())
.catch(() => undefined)

if (!sha) {
console.log(
c.blue(`i`)
+ c.gray(` Failed to locate the previous tag ${c.yellow(`v${operation.state.currentVersion}`)}`),
)
return
}

const { stdout } = await ezSpawn.async(
'git',
[
'--no-pager',
'log',
`${sha}..HEAD`,
'--oneline',
],
{ stdio: 'pipe' },
)

const parsed = parseCommits(stdout.toString().trim())
const prettified = formatParsedCommits(parsed)

if (!parsed.length) {
console.log()
console.log(c.blue(`i`) + c.gray(` No commits since ${operation.state.currentVersion}`))
console.log()
return
}

console.log()
console.log(
c.bold(
`${c.green(parsed.length)} Commits since ${c.gray(sha.slice(0, 7))}:`,
),
)
console.log()
console.log(prettified.join('\n'))
console.log()
}
Loading

0 comments on commit aaad54d

Please sign in to comment.