import {mkdir} from 'fs-extra'; import tempy from 'tempy'; import execa from 'execa'; import pMapSeries from 'p-map-series'; /** * Commit message informations. * * @typedef {Object} Commit * @property {string} branch The commit branch. * @property {string} hash The commit hash. * @property {string} message The commit message. */ /** * Create a temporary git repository and change the current working directory to the repository root. * * @method gitCommits * @param {Array} commits the created commits. * * @return {string} The path of the repository. */ export async function gitRepo() { const dir = tempy.directory(); process.chdir(dir); await mkdir('git-templates'); await execa('git', ['init', '--template=./git-templates']); await gitCheckout('master'); return dir; } /** * Create commits on the current git repository. * * @param {Array} messages commit messages. * * @returns {Array} commits the created commits, in reverse order (to match `git log` order). */ export async function gitCommits(messages) { return (await pMapSeries(messages, async msg => { const {stdout} = await execa('git', ['commit', '-m', msg, '--allow-empty', '--no-gpg-sign']); const [, branch, hash, message] = /^\[(\w+)\(?.*?\)?(\w+)\] (.+)$/.exec(stdout); return {branch, hash, message}; })).reverse(); } /** * Checkout a branch on the current git repository. * * @param {string} branch Branch name. * @param {boolean} create `true` to create the branche ans switch, `false` to only switch. */ export async function gitCheckout(branch, create = true) { await execa('git', ['checkout', create ? '-b' : null, branch]); } /** * @return {string} The sha of the head commit in the current git repository. */ export async function gitHead() { return (await execa('git', ['rev-parse', 'HEAD'])).stdout; } /** * Create a tag on the head commit in the current git repository. * * @param {string} tagName The tag name to create. */ export async function gitTagVersion(tagName) { await execa('git', ['tag', tagName]); } /** * @return {Array} The list of tags from the current git repository. */ export async function gitTags() { return (await execa('git', ['tag'])).stdout.split('\n').filter(tag => !!tag); } /** * @return {Array} The list of commit sha from the current git repository. */ export async function gitLog() { return (await execa('git', ['log', '--format=format:%H'])).stdout.split('\n').filter(sha => !!sha); } /** * Create a shallow clone of a git repository and change the current working directory to the cloned repository root. * The shallow will contain a limited number of commit and no tags. * * @param {string} origin The path of the repository to clone. * @param {number} [depth=1] The number of commit to clone. * @return {string} The path of the cloned repository. */ export async function gitShallowClone(origin, depth = 1) { const dir = tempy.directory(); process.chdir(dir); await execa('git', ['clone', '--no-hardlinks', '--no-tags', '--depth', depth, `file://${origin}`, dir]); return dir; } /** * Pack heads and tags of the current git repository. */ export async function gitPackRefs() { await execa('git', ['pack-refs', '--all']); }