Add markdown output for release notes (#4984)

This commit is contained in:
Boris Ryutin 2016-05-23 21:25:42 +03:00 committed by radare
parent 2c25a8d503
commit dd4f305031

View File

@ -3,161 +3,181 @@
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
function execute(command, cb){
let output = '';
function callback(error, stdout, stderr) {
cb(stdout);
}
exec (command, { maxBuffer: 1024*1024*1024 }, callback)
let output = '';
function callback(error, stdout, stderr) {
cb(stdout);
}
exec (command, { maxBuffer: 1024*1024*1024 }, callback)
};
function getDifflines(upto, path, cb) {
if (typeof upto === 'function') {
cb = upto;
path = '';
upto = '';
} else if (typeof path === 'function') {
cb = path;
path = '';
}
execute('git diff '+upto+'..@ '+path, (log) => {
let o = {
add: 0,
del: 0
};
for (let line of log.split(/\n/g)) {
if (line.match(/^\+/)) {
o.add ++;
} else if (line.match(/^-/)) {
o.del ++;
}
}
o.diff = o.add - o.del;
cb (o);
});
if (typeof upto === 'function') {
cb = upto;
path = '';
upto = '';
} else if (typeof path === 'function') {
cb = path;
path = '';
}
execute('git diff '+upto+'..@ '+path, (log) => {
let o = {
add: 0,
del: 0
};
for (let line of log.split(/\n/g)) {
if (line.match(/^\+/)) {
o.add ++;
} else if (line.match(/^-/)) {
o.del ++;
}
}
o.diff = o.add - o.del;
cb (o);
});
}
function getChangelog(upto, path, cb) {
if (typeof upto === 'function') {
cb = upto;
path = '';
upto = '';
} else if (typeof path === 'function') {
cb = path;
path = '';
}
execute('git log '+upto+'..@ '+path, (log) => {
let o = {
upto: upto,
path: path,
authors: {},
commits: []
};
const lines = log.split('\n');
let date = null;
let commit = null;
let message = '';
for (let line of lines) {
if (line.match("^Author")) {
const author = line.substring(8);
if (o.authors[author] === undefined) {
o.authors[author] = 1;
} else o.authors[author]++;
} else if (line.match("^Date:")) {
date = line.substring(8);
} else if (line.match("^commit")) {
if (commit !== null) {
var doh = {
hash: commit,
date: date,
msg: message.trim()
};
o.commits.push(doh);
message = '';
date = '';
}
commit = line.substring(7);
} else if (line[0] == ' ') {
message += line + '\n';
}
}
cb (o);
});
if (typeof upto === 'function') {
cb = upto;
path = '';
upto = '';
} else if (typeof path === 'function') {
cb = path;
path = '';
}
execute('git log '+upto+'..@ '+path, (log) => {
let o = {
upto: upto,
path: path,
authors: {},
commits: []
};
const lines = log.split('\n');
let date = null;
let commit = null;
let message = '';
for (let line of lines) {
if (line.match("^Author")) {
const author = line.substring(8);
if (o.authors[author] === undefined) {
o.authors[author] = 1;
} else o.authors[author]++;
} else if (line.match("^Date:")) {
date = line.substring(8);
} else if (line.match("^commit")) {
if (commit !== null) {
var doh = {
hash: commit,
date: date,
msg: message.trim()
};
o.commits.push(doh);
message = '';
date = '';
}
commit = line.substring(7);
} else if (line[0] == ' ') {
message += line + '\n';
}
}
cb (o);
});
}
function countWord(x,y) {
let count = 0;
for (let a of x) {
if (a.msg.match(y)) {
count++;
}
}
return count;
let count = 0;
for (let a of x) {
if (a.msg.match(y)) {
count++;
}
}
return count;
}
function computeStats(o) {
return {
commits: o.commits.length,
fix: countWord(o.commits, /fix/i),
crash: countWord(o.commits, /crash/i),
'new': countWord(o.commits, /new/i),
add: countWord(o.commits, /add/i),
anal: countWord(o.commits, /anal/i),
leak: countWord(o.commits, /leak/i),
esil: countWord(o.commits, /esil/i),
enhance: countWord(o.commits, /enhance/i),
}
return {
commits: o.commits.length,
fix: countWord(o.commits, /fix/i),
crash: countWord(o.commits, /crash/i),
'new': countWord(o.commits, /new/i),
add: countWord(o.commits, /add/i),
anal: countWord(o.commits, /anal/i),
leak: countWord(o.commits, /leak/i),
esil: countWord(o.commits, /esil/i),
enhance: countWord(o.commits, /enhance/i),
}
}
function computeRanking(o) {
let r = [];
for (let a in o.authors) {
r.push(o.authors[a]+ ' '+a);
// console.log(a);
}
r = r.sort(function(a, b) {
a = +((a.split(' ')[0]));
b = +((b.split(' ')[0]));
return (a < b) ? 1 : -1;
});
return {
count: Object.keys(o.authors).length,
authors: r
};
let r = [];
for (let a in o.authors) {
r.push(o.authors[a]+ ' '+a);
// console.log(a);
}
r = r.sort(function(a, b) {
a = +((a.split(' ')[0]));
b = +((b.split(' ')[0]));
return (a < b) ? 1 : -1;
});
return {
count: Object.keys(o.authors).length,
authors: r
};
}
String.prototype.repeat = function(times) {
return (new Array(times + 1)).join(this);
};
function printMdList(md_list, list_level) {
var elems = Object.keys(md_list);
elems.forEach(function(elem) {
if (typeof md_list[elem] === "object") {
console.log("\t".repeat(list_level) + "- " + elem + ":");
return printMdList(md_list[elem], list_level + 1);
} else {
var elem_name = isNaN(elem) ? (elem + ": ") : "";
console.log ("\t".repeat(list_level) + "- " + elem_name + md_list[elem]);
}
});
}
const last_tag = '0.10.1';
const paths = [
'', // total
'binr/r2pm/d',
'libr/debug',
'libr/bin',
'libr/core',
'libr/crypto',
'libr/cons',
'libr/anal',
'libr/asm',
'man',
'', // total
'binr/r2pm/d',
'libr/debug',
'libr/bin',
'libr/core',
'libr/crypto',
'libr/cons',
'libr/anal',
'libr/asm',
'man',
];
var count = 0;
var doner = [];
var ready = false;
for (let paz of paths) {
count ++;
getChangelog(last_tag, paz, function(o) {
getDifflines(last_tag, paz, function(d) {
let r = computeStats (o);
r.path = paz;
r.rank = computeRanking (o);
r.diff = d;
doner.push (r);
count --;
if (count == 0 && ready) {
console.log (JSON.stringify (doner));
}
});
});
for (let one_path of paths) {
count ++;
getChangelog(last_tag, one_path, function(o) {
getDifflines(last_tag, one_path, function(d) {
let r = computeStats (o);
r.path = one_path;
r.rank = computeRanking (o);
r.diff = d;
doner.push (r);
count --;
if (count == 0 && ready) {
for(let one_doner of doner) {
printMdList(one_doner, 0);
console.log("\n");
}
}
});
});
}
ready = true;