Reputation: 100370
In order to know what's actually been committed to a project in production, we are going to display the Git log to admins - this serve as a makeshift changelog.
I have this routine on a Node.js Express server:
router.get('/changelog/json', ac.allow('ROLE_ADMIN'), function (req, res, next) {
const k = cp.spawn('bash');
k.stdin.write('git log --pretty=format:\'{%n "commit": "%H",%n "abbreviated_commit": "%h",%n "tree": "%T",%n "abbreviated_tree": "%t",%n "parent": "%P",%n "abbreviated_parent": "%p",%n "refs": "%D",%n "encoding": "%e",%n "subject": "%s",%n "sanitized_subject_line": "%f",%n "body": "%b",%n "commit_notes": "%N",%n "verification_flag": "%G?",%n "signer": "%GS",%n "signer_key": "%GK",%n "author": {%n "name": "%aN",%n "email": "%aE",%n "date": "%aD"%n },%n "commiter": {%n "name": "%cN",%n "email": "%cE",%n "date": "%cD"%n }%n},\'\n')
k.stdin.end();
k.stdout.pipe(res);
});
this sort of works, but we don't actually get a JSON array, we just get comma separate JSON strings.
I got this info form here: https://gist.github.com/varemenos/e95c2e098e657c7688fd https://git-scm.com/docs/pretty-formats
does anyone know how I can construct a JSON array from the stdout from the Git command?
I tried this:
router.get('/json', ac.allow('ROLE_ADMIN'), function (req, res, next) {
const p = createParser();
const k = cp.spawn('bash', [], {
cwd: global.cdtProjectRoot
});
const items = [];
k.stdin.write('git log --pretty=format:\'{%n "commit": "%H",%n "abbreviated_commit": "%h",%n "tree": "%T",%n "abbreviated_tree": "%t",%n "parent": "%P",%n "abbreviated_parent": "%p",%n "refs": "%D",%n "encoding": "%e",%n "subject": "%s",%n "sanitized_subject_line": "%f",%n "body": "%b",%n "commit_notes": "%N",%n "verification_flag": "%G?",%n "signer": "%GS",%n "signer_key": "%GK",%n "author": {%n "name": "%aN",%n "email": "%aE",%n "date": "%aD"%n },%n "commiter": {%n "name": "%cN",%n "email": "%cE",%n "date": "%cD"%n }%n},\'\n')
k.stdin.end();
k.stdout.pipe(p).on('data', function (d) {
// d would be a parsed JSON object
items.push(d);
})
.once('error', next)
.once('end', function () {
res.json({
success: items
})
})
});
My parser transform works, because I use it in another project, so it's something about the format of the JSON coming from the stdout that's causing the problem - the 'data' event handler never sees any data.
Upvotes: 1
Views: 1706
Reputation: 100370
This worked for me, I had to improve the git log format option:
router.get('/json', ac.allow('ROLE_ADMIN'), function (req, res, next) {
const p = createParser();
const k = cp.spawn('bash');
let items = [];
k.stdin.write(`git log -300 --pretty=format:'{"commit":"%H","sanitized_subject_line":"%f","commit_notes":"%N","author":"%aN","date":"%aD"}'`);
k.stdin.end('\n');
k.stdout.pipe(p).on('data', function (d) {
items.push(JSON.parse(d));
})
.once('error', next)
.once('end', function () {
res.json({
success: items
})
})
});
createParser looks like this:
const stream = require("stream");
exports.createParser = function () {
let lastLineData = '';
let strm = new stream.Transform({
objectMode: true,
transform: function (chunk, encoding, cb) {
let _this = this;
let data = String(chunk);
if (lastLineData) {
data = lastLineData + data;
}
let lines = data.split('\n');
lastLineData = lines.splice(lines.length - 1, 1)[0];
lines.forEach(function (l) {
l && _this.push(l);
});
cb();
},
flush: function (cb) {
if (lastLineData) {
this.push(lastLineData);
}
lastLineData = '';
cb();
}
});
return strm;
};
this might barf if there are certain characters in the git log fields, like Author, but I think the built-in field "sanitized_subject_line" will save our skin a bit when it comes to removing bad chars from commit messages.
Upvotes: 1