Add several fixes and improvements in the identification of the last release gitHead: - If there is no last release, unshallow the repo in order to retrieve all existing commits - If git head is not present in last release, try to retrieve it from git tag with format ‘v\<version\>’ or ‘\<version\>’ - If the last release git head cannot be determined and found in commit history, unshallow the repo and try again - Throw a ENOGITHEAD error if the gitHead for the last release cannot be found in the npm metadata nor in the git tags, preventing to make release based on the all the commits in the repo as before - Add integration test for the scenario with a packed repo from which `npm republish` fails to read the git head Fix #447, Fix #393, Fix #280, Fix #276
110 lines
3.2 KiB
JavaScript
110 lines
3.2 KiB
JavaScript
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<Commit>} 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<string>} messages commit messages.
|
|
*
|
|
* @returns {Array<Commit>} 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<string>} 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<string>} 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']);
|
|
}
|