Skip to content

Commit 3cfdf91

Browse files
committed
Simplifies & refactors the way git log fields are parsed
`--pretty=tformat` string is generated automatically from array of `git log` fields. Each field is separated by a null character, which as far as I know can't appear naturally in any of those fields. Babel now transpiles from .es to .js, which is easier than transpiling to .compiled.js now that there are multiple .es scripts
1 parent 0656ce1 commit 3cfdf91

10 files changed

+165
-244
lines changed

.babelrc

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
{
2-
presets: ['es2015']
2+
presets: ['es2015'],
3+
only: 'scripts/**.es'
34
}

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ npm-debug.log
44
node_modules/
55
assets/
66
gitlogg.json
7-
*.compiled.js
8-
*.compiled.js.map
7+
scripts/**/*.js
8+
scripts/**/*.js.map

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@
2626
"gitlogg": "gitlogg/gitlogg.sh"
2727
},
2828
"scripts": {
29-
"build": "babel --source-maps --out-file scripts/gitlogg-parse-json.compiled.js scripts/gitlogg-parse-json.js",
29+
"build": "babel --source-maps --out-dir scripts scripts",
3030
"test": "GITLOGG_DEV=1 ./gitlogg/gitlogg.sh ./",
3131
"prepublish": "npm run build"
3232
},
3333
"dependencies": {
3434
"chalk": "^1.1.3",
35-
"lodash": "^4.17.2"
35+
"lodash": "^4.17.2",
36+
"which": "^1.2.12"
3637
},
3738
"devDependencies": {
3839
"babel-cli": "^6.18.0",

scripts/git-log-fields.js renamed to scripts/git-log-fields.es

+67-62
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
2-
exports.fields = [ { code: '%H',
1+
2+
const fields = exports.fields = [
3+
{ code: '%H',
34
name: 'commit hash',
45
fullDescription: 'commit hash',
56
description: '',
@@ -38,7 +39,7 @@ exports.fields = [ { code: '%H',
3839
name: 'author name',
3940
fullDescription: 'author name (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
4041
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
41-
identifier: 'author_name_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
42+
identifier: 'author_name_mailmap' },
4243
{ code: '%ae',
4344
name: 'author email',
4445
fullDescription: 'author email',
@@ -48,37 +49,37 @@ exports.fields = [ { code: '%H',
4849
name: 'author email',
4950
fullDescription: 'author email (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
5051
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
51-
identifier: 'author_email_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
52-
{ code: '%ad',
53-
name: 'author date',
54-
fullDescription: 'author date (format respects --date= option)',
55-
description: ' (format respects --date= option)',
56-
identifier: 'author_date_(format_respects_--date=_option)' },
57-
{ code: '%aD',
58-
name: 'author date',
59-
fullDescription: 'author date, RFC2822 style',
60-
description: ', RFC2822 style',
61-
identifier: 'author_date_RFC2822_style' },
52+
identifier: 'author_email_mailmap' },
53+
// { code: '%ad',
54+
// name: 'author date',
55+
// fullDescription: 'author date (format respects --date= option)',
56+
// description: ' (format respects --date= option)',
57+
// identifier: 'author_date_(format_respects_--date=_option)' },
58+
// { code: '%aD',
59+
// name: 'author date',
60+
// fullDescription: 'author date, RFC2822 style',
61+
// description: ', RFC2822 style',
62+
// identifier: 'author_date_RFC2822_style' },
6263
{ code: '%ar',
6364
name: 'author date',
6465
fullDescription: 'author date, relative',
6566
description: ', relative',
6667
identifier: 'author_date_relative' },
67-
{ code: '%at',
68-
name: 'author date',
69-
fullDescription: 'author date, UNIX timestamp',
70-
description: ', UNIX timestamp',
71-
identifier: 'author_date_UNIX_timestamp' },
72-
{ code: '%ai',
73-
name: 'author date',
74-
fullDescription: 'author date, ISO 8601-like format',
75-
description: ', ISO 8601-like format',
76-
identifier: 'author_date_ISO_8601-like_format' },
68+
// { code: '%at',
69+
// name: 'author date',
70+
// fullDescription: 'author date, UNIX timestamp',
71+
// description: ', UNIX timestamp',
72+
// identifier: 'author_date_UNIX_timestamp' },
73+
// { code: '%ai',
74+
// name: 'author date',
75+
// fullDescription: 'author date, ISO 8601-like format',
76+
// description: ', ISO 8601-like format',
77+
// identifier: 'author_date_ISO_8601-like_format' },
7778
{ code: '%aI',
7879
name: 'author date',
7980
fullDescription: 'author date, strict ISO 8601 format',
8081
description: ', strict ISO 8601 format',
81-
identifier: 'author_date_strict_ISO_8601_format' },
82+
identifier: 'author_date' },
8283
{ code: '%cn',
8384
name: 'committer name',
8485
fullDescription: 'committer name',
@@ -88,7 +89,7 @@ exports.fields = [ { code: '%H',
8889
name: 'committer name',
8990
fullDescription: 'committer name (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
9091
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
91-
identifier: 'committer_name_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
92+
identifier: 'committer_name_mailmap' },
9293
{ code: '%ce',
9394
name: 'committer email',
9495
fullDescription: 'committer email',
@@ -98,47 +99,47 @@ exports.fields = [ { code: '%H',
9899
name: 'committer email',
99100
fullDescription: 'committer email (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
100101
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
101-
identifier: 'committer_email_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
102-
{ code: '%cd',
103-
name: 'committer date',
104-
fullDescription: 'committer date (format respects --date= option)',
105-
description: ' (format respects --date= option)',
106-
identifier: 'committer_date_(format_respects_--date=_option)' },
107-
{ code: '%cD',
108-
name: 'committer date',
109-
fullDescription: 'committer date, RFC2822 style',
110-
description: ', RFC2822 style',
111-
identifier: 'committer_date_RFC2822_style' },
102+
identifier: 'committer_email_mailmap' },
103+
// { code: '%cd',
104+
// name: 'committer date',
105+
// fullDescription: 'committer date (format respects --date= option)',
106+
// description: ' (format respects --date= option)',
107+
// identifier: 'committer_date_(format_respects_--date=_option)' },
108+
// { code: '%cD',
109+
// name: 'committer date',
110+
// fullDescription: 'committer date, RFC2822 style',
111+
// description: ', RFC2822 style',
112+
// identifier: 'committer_date_RFC2822_style' },
112113
{ code: '%cr',
113114
name: 'committer date',
114115
fullDescription: 'committer date, relative',
115116
description: ', relative',
116117
identifier: 'committer_date_relative' },
117-
{ code: '%ct',
118-
name: 'committer date',
119-
fullDescription: 'committer date, UNIX timestamp',
120-
description: ', UNIX timestamp',
121-
identifier: 'committer_date_UNIX_timestamp' },
122-
{ code: '%ci',
123-
name: 'committer date',
124-
fullDescription: 'committer date, ISO 8601-like format',
125-
description: ', ISO 8601-like format',
126-
identifier: 'committer_date_ISO_8601-like_format' },
118+
// { code: '%ct',
119+
// name: 'committer date',
120+
// fullDescription: 'committer date, UNIX timestamp',
121+
// description: ', UNIX timestamp',
122+
// identifier: 'committer_date_UNIX_timestamp' },
123+
// { code: '%ci',
124+
// name: 'committer date',
125+
// fullDescription: 'committer date, ISO 8601-like format',
126+
// description: ', ISO 8601-like format',
127+
// identifier: 'committer_date_ISO_8601-like_format' },
127128
{ code: '%cI',
128129
name: 'committer date',
129130
fullDescription: 'committer date, strict ISO 8601 format',
130131
description: ', strict ISO 8601 format',
131-
identifier: 'committer_date_strict_ISO_8601_format' },
132-
{ code: '%d',
133-
name: 'ref names',
134-
fullDescription: 'ref names, like the --decorate option of git-log[1]',
135-
description: ', like the --decorate option of git-log[1]',
136-
identifier: 'ref_names' },
132+
identifier: 'committer_date' },
133+
// { code: '%d',
134+
// name: 'ref names',
135+
// fullDescription: 'ref names, like the --decorate option of git-log[1]',
136+
// description: ', like the --decorate option of git-log[1]',
137+
// identifier: 'ref_names' },
137138
{ code: '%D',
138139
name: 'ref names without the "',
139140
fullDescription: 'ref names without the " (", ")" wrapping.',
140141
description: ' (", ")" wrapping.',
141-
identifier: 'ref_names_without_the_"' },
142+
identifier: 'ref_names' },
142143
{ code: '%e',
143144
name: 'encoding',
144145
fullDescription: 'encoding',
@@ -153,7 +154,7 @@ exports.fields = [ { code: '%H',
153154
name: 'sanitized subject line',
154155
fullDescription: 'sanitized subject line, suitable for a filename',
155156
description: ', suitable for a filename',
156-
identifier: 'sanitized_subject_line' },
157+
identifier: 'sanitized_subject' },
157158
{ code: '%b',
158159
name: 'body',
159160
fullDescription: 'body',
@@ -173,22 +174,22 @@ exports.fields = [ { code: '%H',
173174
name: 'raw verification message from GPG for a signed commit',
174175
fullDescription: 'raw verification message from GPG for a signed commit',
175176
description: '',
176-
identifier: 'raw_verification_message_from_GPG_for_a_signed_commit' },
177+
identifier: 'raw_GPG_verification_message' },
177178
{ code: '%G?',
178179
name: 'show "G" for a good',
179180
fullDescription: 'show "G" for a good (valid) signature, "B" for a bad signature, "U" for a good signature with unknown validity, "X" for a good signature that has expired, "Y" for a good signature made by an expired key, "R" for a good signature made by a revoked key, "E" if the signature cannot be checked (e.g. missing key) and "N" for no signature',
180181
description: ' (valid) signature, "B" for a bad signature, "U" for a good signature with unknown validity, "X" for a good signature that has expired, "Y" for a good signature made by an expired key, "R" for a good signature made by a revoked key, "E" if the signature cannot be checked (e.g. missing key) and "N" for no signature',
181-
identifier: 'show_"G"_for_a_good' },
182+
identifier: 'signature_validity' },
182183
{ code: '%GS',
183184
name: 'show the name of the signer for a signed commit',
184185
fullDescription: 'show the name of the signer for a signed commit',
185186
description: '',
186-
identifier: 'show_the_name_of_the_signer_for_a_signed_commit' },
187+
identifier: 'signer_name' },
187188
{ code: '%GK',
188189
name: 'show the key used to sign a signed commit',
189190
fullDescription: 'show the key used to sign a signed commit',
190191
description: '',
191-
identifier: 'show_the_key_used_to_sign_a_signed_commit' },
192+
identifier: 'key' },
192193
{ code: '%gD',
193194
name: 'reflog selector',
194195
fullDescription: 'reflog selector, e.g., refs/stash@{1} or refs/stash@{2 minutes ago}; the format follows the rules described for the -g option. The portion before the @ is the refname as given on the command line (so git log -g refs/heads/master would yield refs/heads/master@{0}).',
@@ -208,7 +209,7 @@ exports.fields = [ { code: '%H',
208209
name: 'reflog identity name',
209210
fullDescription: 'reflog identity name (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
210211
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
211-
identifier: 'reflog_identity_name_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
212+
identifier: 'reflog_identity_name_mailmap' },
212213
{ code: '%ge',
213214
name: 'reflog identity email',
214215
fullDescription: 'reflog identity email',
@@ -218,9 +219,13 @@ exports.fields = [ { code: '%H',
218219
name: 'reflog identity email',
219220
fullDescription: 'reflog identity email (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
220221
description: ' (respecting .mailmap, see git-shortlog[1] or git-blame[1])',
221-
identifier: 'reflog_identity_email_(respecting_.mailmap_see_git-shortlog[1]_or_git-blame[1])' },
222+
identifier: 'reflog_identity_email_mailmap' },
222223
{ code: '%gs',
223224
name: 'reflog subject',
224225
fullDescription: 'reflog subject',
225226
description: '',
226-
identifier: 'reflog_subject' } ];
227+
identifier: 'reflog_subject' } ];
228+
229+
const formatString = exports.formatString = fields.map(field =>
230+
`${ field.code }%x00`
231+
).join('');

scripts/git-log-fields.generate.js renamed to scripts/git-log-fields.generate.es

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,4 @@ const output = `
153153
exports.fields = ${ inspect(fields) };
154154
`;
155155

156-
fs.writeFileSync(path.join(__dirname, 'git-log-fields.js'), output);
156+
fs.writeFileSync(path.join(__dirname, 'git-log-fields.es'), output);

scripts/gitlogg-generate-log.sh

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ runJs() {
55
shift
66
if [[ "$GITLOGG_DEV" = "" ]]; then
77
# Run precompiled .compiled.js
8-
node "${script%.js}.compiled.js" "$@"
8+
node "${script%.es}.js" "$@"
99
else
1010
# Development: transpile .js at runtime
1111
babel "$script" | node "$@"
1212
fi
1313
}
1414

15-
workerFile="$__dirname/output-intermediate-gitlog.sh"
15+
workerFile="$__dirname/output-intermediate-gitlog.es"
1616

1717
# define path to 'json' parser
18-
jsonParser="$__dirname/gitlogg-parse-json.js"
18+
jsonParser="$__dirname/gitlogg-parse-json.es"
1919

2020
# Display system usage and exit
2121
usage()

scripts/gitlogg-parse-json.es

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
var fs = require('fs'),
2+
path = require('path'),
3+
chalk = require('chalk'),
4+
{chunk} = require('lodash'),
5+
{fields: gitLogFields} = require('./git-log-fields'),
6+
// Read and write from file descriptors. Bash script will hook these up.
7+
input_file = 3,
8+
output_file = 4;
9+
10+
try {
11+
require('source-map-support').install();
12+
} catch(e) {}
13+
14+
console.log(chalk.yellow('Generating JSON output...'));
15+
16+
var changes = function(data, index) {
17+
var v = data.split(',')[index] || 0;
18+
var w = 0;
19+
if (v !== 0) {
20+
var w = v.split(' ')[1]; // the number of changes is second on the array
21+
}
22+
return parseInt(w);
23+
};
24+
25+
console.time(chalk.green('JSON output generated in'));
26+
27+
28+
const fields = [
29+
{identifier: 'repository'},
30+
...gitLogFields,
31+
{identifier: 'shortstats'}
32+
];
33+
34+
let input = fs.readFileSync(input_file, 'utf8').split('\0');
35+
input.shift();
36+
const totalFields = fields.length;
37+
const inputCommits = chunk(input, totalFields);
38+
39+
const output = {};
40+
inputCommits.forEach(item => {
41+
// The last field for each commit includes the trailing newline output by `git log`; remove it
42+
item[totalFields - 1] = item[totalFields - 1].slice(0, -1);
43+
44+
const commit = {};
45+
fields.forEach((field, i) => {
46+
commit[field.identifier] = item[i];
47+
});
48+
const stats = commit.shortstats;
49+
commit.files_changed = changes(stats, 0);
50+
const insertions = commit.insertions = changes(stats, 1);
51+
const deletions = commit.deletions = changes(stats, 2);
52+
commit.impact = insertions - deletions;
53+
// TODO reimplement commit_nr
54+
55+
const repository = commit.repository;
56+
output[repository] = output[repository] || [];
57+
output[repository].push(commit);
58+
});
59+
60+
console.timeEnd(chalk.green('JSON output generated in'));
61+
62+
console.log(chalk.yellow('Writing output to file...'));
63+
64+
fs.writeFileSync(output_file, JSON.stringify(output, null, 2));

0 commit comments

Comments
 (0)