import { pathExists } from 'fs-extra' import { resolve } from 'path' import execa from 'execa' export function isGitRepo(cwd = '.'): Promise { return pathExists(resolve(cwd, '.git')) } export async function getCurrGitBranch(cwd?: string): Promise { // https://stackoverflow.com/questions/6245570/how-to-get-the-current-branch-name-in-git/6245587#6245587 // git rev-parse --abbrev-ref HEAD const obj = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd }) return obj.stdout } export async function getUnpushedGitCommits(cwd?: string): Promise { try { const branch = await getCurrGitBranch(cwd) // https://stackoverflow.com/questions/2016901/viewing-unpushed-git-commits // git log @{u}.. // @{u} won't work if the local branch isn't configured with an upstream. WTF... const obj = await execa('git', ['log', `origin/${branch}..${branch}`], { cwd, }) return obj.stdout } catch (err) { return '' } } export async function hasUnpushedGitCommits(cwd?: string): Promise { return !!(await getUnpushedGitCommits(cwd)) } export async function getGitStatus(cwd?: string): Promise { // git status --porcelain const obj = await execa('git', ['status', '--porcelain'], { cwd }) return obj.stdout } export async function gitIsClean(cwd?: string): Promise { return !(await getGitStatus(cwd)) } export async function gitNotClean(cwd?: string): Promise { return !!(await getGitStatus(cwd)) } export async function ensureGitClean(cwd?: string): Promise { if (!(await isGitRepo(cwd))) { throw new Error('未检测到 git') } else if (await gitNotClean(cwd)) { throw new Error('检测到有未提交的文件, 请先提交文件.') } } export async function getGitUrl() { // https://stackoverflow.com/questions/15715825/how-do-you-get-the-git-repositorys-name-in-some-git-repository/42543006#42543006 // git config --get remote.origin.url const { stdout } = await execa('git', [ 'config', '--get', 'remote.origin.url', ]) return stdout.trim() } export function parseGitUrl(url: string) { if (url.indexOf('git') === 0) { let str = url.split(':')[1] str = str.replace('.git', '') const names = str.split('/') return { groupName: names[0], projectName: names[1] } } if (url.indexOf('http') === 0) { let str = url str = str.replace('.git', '') const names = str.split('/') const n = names.length return { groupName: names[n - 2], projectName: names[n - 1] } } return { groupName: '', projectName: '' } } export async function getGitNames() { const url = await getGitUrl() return parseGitUrl(url) } export async function getGitBranch() { const { stdout } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD']) return stdout.trim() }