Files
taimed/node_modules/commitplease/index.js
2025-07-24 17:21:45 +08:00

195 lines
5.3 KiB
JavaScript

var fs = require('fs')
var ini = require('ini')
var path = require('path')
var chalk = require('chalk')
var Git = require('git-tools')
var validate = require('./lib/validate')
var sanitize = require('./lib/sanitize')
var defaults = require('./lib/defaults')
// If there is a path in process.env.PATH that looks like this:
// path = prefix + suffix (where suffix is the function argument)
// then slice off the suffix and return the prefix, otherwise undefiend
function sliceEnvPath (suffix) {
var p = process.env.PATH.split(':').filter(
function (p) {return p.endsWith(suffix)}
)
if (p.length === 1) {
p = p[0].split(path.sep)
p = p.slice(0, p.length - suffix.split(path.sep).length)
return p.join(path.sep)
}
return undefined
}
// Need to find the path to the project that is installing or running
// commitplease. Previously, process.cwd() made the job easy but its
// output changed with node v8.1.2 (at least compared to 7.10.0)
function getProjectPath () {
// Rely on npm to inject some path into PATH; However, the injected
// path can both be relative or absolute, so add extra path.resolve()
// During npm install, npm will inject a path that ends with
// commitplease/node_modules/.bin into process.env.PATH
var p = sliceEnvPath(
path.join('node_modules', 'commitplease', 'node_modules', '.bin')
)
if (p !== undefined) {
return path.resolve(p)
}
// During npm run, npm will inject a path that ends with
// node_modules/.bin into process.env.PATH
p = sliceEnvPath(path.join('node_modules', '.bin'))
if (p !== undefined) {
return path.resolve(p)
}
// During git commit there will be no process.env.PATH modifications
// So, assume we are being run by git which will set process.cwd()
// to the root of the project as described in the manual:
// https://git-scm.com/docs/githooks/2.9.0
return path.resolve(process.cwd())
}
function getOptions () {
var projectPath = getProjectPath()
var pkg = path.join(projectPath, 'package.json')
var npm = path.join(projectPath, '.npmrc')
pkg = fs.existsSync(pkg) && require(pkg) || {}
npm = fs.existsSync(npm) && ini.parse(fs.readFileSync(npm, 'utf8')) || {}
pkg = pkg.commitplease || {}
npm = npm.commitplease || {}
var options = Object.assign(pkg, npm)
var base = {
'projectPath': projectPath,
'oldMessagePath': defaults.oldMessagePath,
'oldMessageSeconds': defaults.oldMessageSeconds
}
if (options === undefined ||
options.style === undefined ||
options.style === 'jquery') {
return Object.assign(base, defaults.jquery, options)
} else if (options.style === 'angular') {
return Object.assign(base, defaults.angular, options)
}
console.error(chalk.red(
'Style ' + options.style + ' is not recognised\n' +
'Did you mistype it in package.json?'
))
process.exit(1)
}
function runValidate (message, options) {
var errors = validate(sanitize(message), options)
if (errors.length) {
console.error('Invalid commit message, please fix:\n')
console.error(chalk.red('- ' + errors.join('\n- ')))
console.error()
console.error('Commit message was:')
console.error()
console.error(chalk.green(sanitize(message)))
console.error('\nSee ' + options.guidelinesUrl)
// save a poorly formatted message and reuse it at a later commit
fs.writeFileSync(defaults.oldMessagePath, message)
process.exit(1)
}
}
module.exports = function () {
var argv = process.argv.slice(2)
var help = argv.some(function (value) {
if (value === '-h' || value === '--help') {
return true
}
})
if (argv.length > 1 || help) {
console.log(
'Usage: commitplease [committish]\n\n' +
'committish a commit range passed to git log\n\n' +
'Examples:\n\n' +
'1. Check all commits on branch master:\n' +
'commitplease master\n\n' +
'2. Check all commits on branch feature but not on master:\n' +
'commitplease master..feature\n\n' +
'3. Check the latest 1 commit (n works too):\n' +
'commitplease -1\n\n' +
'4. Check all commits between 84991d and 2021ce\n' +
'commitplease 84991d..2021ce\n\n' +
'5. Check all commits starting with 84991d\n' +
'commitplease 84991d..\n\n' +
'Docs on git commit ranges: https://bit.ly/commit-range'
)
process.exit(0)
}
var options = getOptions()
var message = path.join('.git', 'COMMIT_EDITMSG')
if (path.normalize(argv[0]) === message) {
runValidate(fs.readFileSync(message, 'utf8').toString(), options)
process.exit(0)
}
var committish = 'HEAD'
if (argv.length !== 0) {
committish = argv[0]
}
var repo = new Git(process.cwd())
var secret = '--++== CoMMiTPLeaSe ==++--'
var format = '--format=%B' + secret
repo.exec('log', format, committish, function (error, messages) {
if (error) {
if (/Not a git repository/.test(error.message)) {
console.log(error.message)
process.exit(0)
}
if (/does not have any commits yet/.test(error.message)) {
console.log(error.message)
process.exit(0)
}
console.error(error)
process.exit(1)
}
messages = messages.trim().split(secret)
messages.pop()
for (var i = 0; i < messages.length; ++i) {
runValidate(messages[i], options)
}
})
}
module.exports.defaults = defaults
module.exports.getOptions = getOptions