1 | #!/usr/bin/env node
|
2 |
|
3 | console.log('running commit-wizard in folder %s', process.cwd());
|
4 | const la = require('lazy-ass');
|
5 | const check = require('check-more-types');
|
6 | const join = require('path').join;
|
7 | const pkgPath = join(process.cwd(), 'package.json');
|
8 | const pkg = require(pkgPath);
|
9 | const preGit = require('pre-git');
|
10 | const git = require('ggit');
|
11 | const chalk = require('chalk');
|
12 | const log = require('debug')('pre-git');
|
13 | la(check.fn(log), 'missing debug log', log);
|
14 |
|
15 |
|
16 | const Promise = require('bluebird');
|
17 |
|
18 | const label = 'pre-commit';
|
19 |
|
20 | const config = pkg.config &&
|
21 | pkg.config['pre-git'];
|
22 |
|
23 | const wizard = preGit.wizard();
|
24 | la(check.maybe.object(wizard),
|
25 | 'could not get commit message wizard', wizard);
|
26 |
|
27 | function getPreCommitCommands(config) {
|
28 | if (!config) {
|
29 | return;
|
30 | }
|
31 | const preCommit = config[label];
|
32 | if (check.unemptyString(preCommit)) {
|
33 | return [preCommit];
|
34 | }
|
35 | return preCommit;
|
36 | }
|
37 |
|
38 | function hasPreCommitCommands(config) {
|
39 | return check.unemptyArray(getPreCommitCommands(config));
|
40 | }
|
41 |
|
42 | var start = Promise.resolve(git.hasChanges())
|
43 | .then(function (hasSomethingToCommit) {
|
44 | if (!hasSomethingToCommit) {
|
45 | console.log('Nothing to commit');
|
46 | process.exit(0);
|
47 | }
|
48 | });
|
49 |
|
50 | if (hasPreCommitCommands(config)) {
|
51 | console.log('package %s has pre-commit commands', pkg.name);
|
52 | console.log(getPreCommitCommands(config).join(', '));
|
53 | const run = preGit.run;
|
54 | la(check.fn(run), 'missing pre git run');
|
55 | const runLabeled = run.bind(null, label);
|
56 |
|
57 | start = start
|
58 | .then(runLabeled)
|
59 | .then(() => console.log('finished pre-commit check'));
|
60 | }
|
61 |
|
62 |
|
63 | function guideUserMock() {
|
64 | return Promise.resolve('fix(git): fixing commit wizard');
|
65 | }
|
66 |
|
67 | function guideUser() {
|
68 | if (!wizard) {
|
69 | console.error(chalk.yellow('You have not set the commit message format'));
|
70 | console.error('This wizard does not know what to ask you');
|
71 | console.error('Maybe try setting up "simple" commit message format');
|
72 | console.error('See',
|
73 | chalk.underline('https://github.com/bahmutov/pre-git#validating-commit-message'));
|
74 | return Promise.reject(new Error('Missing commit format name'));
|
75 | }
|
76 |
|
77 | const inquirer = require('inquirer');
|
78 |
|
79 | return new Promise(function (resolve, reject) {
|
80 | wizard.prompter(inquirer, (message) => {
|
81 | if (!message) {
|
82 | return reject(new Error('No commit message'));
|
83 | }
|
84 | return resolve(message);
|
85 | });
|
86 | });
|
87 | }
|
88 |
|
89 | function commitWithMessage(commitMessage) {
|
90 | la(check.unemptyString(commitMessage), 'missing commit message', commitMessage);
|
91 | const gitCommit = git.commit;
|
92 | return gitCommit(commitMessage)
|
93 | .then(console.log.bind(console));
|
94 | }
|
95 |
|
96 | function errorMessage(err) {
|
97 | return err instanceof Error ? err.message : err;
|
98 | }
|
99 |
|
100 | function firstLine(str) {
|
101 | la(check.string(str), 'expected a string, got', str);
|
102 | return str.split('\n').shift();
|
103 | }
|
104 |
|
105 | function isValidMessage(message) {
|
106 | if (!wizard) {
|
107 | return message;
|
108 | }
|
109 |
|
110 | la(check.unemptyString(message), 'missing message');
|
111 |
|
112 | const first = firstLine(message);
|
113 |
|
114 | if (!check.unemptyString(first)) {
|
115 | return Promise.reject(new Error('missing first line'));
|
116 | }
|
117 | if (check.fn(wizard.validate)) {
|
118 | if (!wizard.validate(message)) {
|
119 | return Promise.reject(new Error('Invalid commit message\n' + message));
|
120 | }
|
121 | }
|
122 | return message;
|
123 | }
|
124 |
|
125 | function success() {
|
126 | console.log('commit wizard has finished');
|
127 | }
|
128 |
|
129 | start
|
130 | .then(guideUser)
|
131 | .then((message) => message.trim())
|
132 | .tap((message) => console.log(message))
|
133 | .then(isValidMessage)
|
134 | .then(commitWithMessage)
|
135 | .then(success)
|
136 | .catch((err) => {
|
137 | console.error(errorMessage(err));
|
138 | process.exit(-1);
|
139 | })
|
140 | .done();
|
141 |
|