Update release-notes script

This commit is contained in:
pancake 2016-05-24 01:12:22 +02:00
parent 00626b9b02
commit 403b2c2257
5 changed files with 385 additions and 186 deletions

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2012-2014 - pancake */
/* radare - LGPL - Copyright 2012-2016 - pancake */
#include <r_anal.h>
@ -95,7 +95,7 @@ R_API char *r_anal_data_to_string(RAnalData *d) {
line = malloc (mallocsz);
if (!line) {
eprintf ("Cannot allocate %"PFMT64d" bytes\n", mallocsz);
eprintf ("Cannot allocate %d bytes\n", mallocsz);
return NULL;
}
snprintf (line, mallocsz, "0x%08" PFMT64x " ", d->addr);

View File

@ -1249,7 +1249,8 @@ R_API int r_anal_str_to_fcn(RAnal *a, RAnalFunction *f, const char *sig) {
/* Add 'function' keyword */
str = malloc (strlen(sig) + 10);
if (!str) {
eprintf ("Cannot allocate %d bytes\n", strlen(sig) + 10);
const int length = strlen (sig) + 10;
eprintf ("Cannot allocate %d bytes\n", length);
return false;
}
strcpy (str, "function ");

View File

@ -1,183 +0,0 @@
'use strict';
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)
};
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);
});
}
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);
});
}
function countWord(x,y) {
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),
}
}
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
};
}
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',
];
var count = 0;
var doner = [];
var ready = false;
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;

375
sys/release-notes/index.js Executable file
View File

@ -0,0 +1,375 @@
#!/usr/bin/env node
'use strict';
const exec = require('child_process').exec;
const spawn = require('child_process').spawn;
const AsciiTable = require('ascii-table');
const lastTag = '0.10.2';
const curVersion = '0.10.3';
const showOnlyFinalReport = true;
const codeName = 'Tooth';
const topTen = 0;
const topFive = 999;
const authorAlias = {
'sirmy15': 'ret2libc',
'ahmedsoliman0x666': 'oddcoder',
'jroi.martin': 'nibble',
'ayman.khamouma': 'ayman',
'rlaemmert': 'defragger',
'maijin21': 'maijin',
'krytarowski': 'kamil',
'rakholiyajenish.07': 'p4n74',
'P4N74': 'p4n74',
'damien': 'damo22',
'alvaro.felipe91': 'alvarofe',
'lol': 'gk',
'github.jdrake': 'jduck',
'andrey.torsunov': 'torsunov',
'gautier.colajanni': 'gautier',
'davide.balzarotti': 'davide',
'eternalsushant': 'sushant',
'Qwokka': 'qwokka',
'naveenboggarapu': 'naveen',
'anton.kochkov': 'xvilka',
'a.kochkov': 'xvilka',
'incredible.angst': 'kolen',
};
const columns = [ 'name', 'commits', 'fix', 'add', 'leak', 'update', 'r2pm', 'clean', 'esil', 'endian', 'commits', 'authors' ];
const paths = [
'', // total
'binr/r2pm/d',
'binr/radare2',
'binr/rabin2',
'binr/radiff2',
'binr/rahash2',
'binr/ragg2',
'libr/hash',
'libr/debug',
'libr/bin',
'libr/core',
'libr/crypto',
'libr/cons',
'libr/anal',
'libr/asm',
'libr/util',
'libr/bp',
'libr/egg',
/*
'libr/flags',
'libr/diff',
'libr/search',
'shlr/sdb',
*/
'shlr/tcc',
'shlr/bochs',
'man',
];
function execute(command, cb){
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) => {
const 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) {
path = __dirname + '/../../' + path;
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 realname = line.substring(8);
const author = renderAuthor(realname);
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) {
const doh = {
hash: commit,
date: date,
msg: message.trim()
};
o.commits.push(doh);
message = '';
date = '';
}
commit = line.substring(7);
} else if (line[0] == ' ') {
message += line.trim() + '\n';
}
}
cb (o);
});
}
function countWord(x,y) {
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),
debug: countWord(o.commits, /debug/i),
type: countWord(o.commits, /type/i),
oob: countWord(o.commits, /oob/i),
honor: countWord(o.commits, /honor/i),
update: countWord(o.commits, /update/i),
r2pm: countWord(o.commits, /r2pm/i),
clean: countWord(o.commits, /clean/i),
'import': countWord(o.commits, /import/i),
endian: countWord(o.commits, /endian/i),
indent: countWord(o.commits, /indent/i),
command: countWord(o.commits, /command/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;
});
if (topTen > 0) {
r = r.slice(0, topTen);
}
return {
count: Object.keys(o.authors).length,
authors: r
};
}
String.prototype.repeat = function(times) {
return (new Array(times + 1)).join(this);
};
function printMdList(mdList, listLevel) {
const elems = Object.keys(mdList);
elems.forEach(function(elem) {
if (elem === 'priv' || elem == 'path') {
return;
}
if (typeof mdList[elem] === 'object') {
console.log('\t'.repeat(listLevel) + '- ' + elem + ':');
return printMdList(mdList[elem], listLevel + 1);
} else {
const elemName = isNaN(elem) ? (elem + ': ') : '';
console.log ('\t'.repeat(listLevel) + '- ' + elemName + mdList[elem]);
}
});
}
function findStatsFor(as, x) {
for (let c of as) {
if (c.path == x) {
return c;
}
}
return undefined;
}
function renderAuthor(str) {
for (let k in authorAlias) {
const v = authorAlias[k];
if (str.indexOf (k) != -1) {
return v;
// return str.replace(k, v);
}
}
const res = str.match(/<([^@]*)/g);
if (res !== null) {
return res[0].substring(1).replace('@', '').trim();
}
return str;
}
function getAuthor(str) {
const space = str.indexOf(' ');
if (space !== -1) {
return str.substring(space).trim();
}
return str;
}
var first = true;
function printFinalReportTable(obj) {
function getFinalReportFor(x) {
const arr = [];
arr.push(x);
let o = findStatsFor(obj, x);
for (let col of columns.slice(1)) {
const ocol = o[col];
if (typeof ocol === 'undefined') {
if (first) {
first = false;
} else {
let last = topFive;
let auth = '';
for (let a of o.ranking.authors) {
auth += getAuthor(a) + ' ';
if (!last--) break;
}
arr.push (auth);
}
} else {
arr.push (o[col]);
}
}
return arr;
}
const table = new AsciiTable('Release ' + curVersion)
paths.forEach((path) => {
table.addRow(getFinalReportFor(path));
});
table.setHeading(columns);
console.log('```');
console.log(table.toString())
console.log('```');
}
function getLogMessages(x) {
let msg = '';
for (let m of x) {
msg += m.msg;
}
return msg;
}
function main() {
let count = 0;
let doner = [];
let ready = false;
console.log('Release ' + curVersion);
console.log('==============');
console.log();
console.log('Project: radare2');
console.log('Codename: ' + codeName);
console.log('Date: ' + new Date().toString());
console.log('Website: http://radare.org');
console.log('Tarball: https://github.com/radare/radare2/releases');
for (let onePath of paths) {
count ++;
getChangelog(lastTag, onePath, function(o) {
getDifflines(lastTag, onePath, function(d) {
let r = computeStats (o);
r.path = onePath;
r.ranking = computeRanking (o);
r.diff = d;
r.priv = {
commits: o.commits
};
doner.push (r);
count --;
if (count == 0 && ready) {
if (!showOnlyFinalReport) {
for (let oneDoner of doner) {
printMdList(oneDoner, 0);
console.log('\n');
}
}
for (let oneDoner of doner) {
if (oneDoner.path == '') {
console.log();
console.log('Numbers:');
console.log('--------');
let r = oneDoner.ranking;
oneDoner.ranking = {};
printMdList(oneDoner, 0);
oneDoner.ranking = r;
printFinalReportTable(doner);
console.log();
console.log('Contributors:');
console.log('-------------');
console.log();
printMdList(oneDoner.ranking.authors, 0);
console.log();
console.log('Changes:');
console.log('--------');
console.log();
console.log('Commits:');
console.log('--------');
const logMessages = getLogMessages(oneDoner.priv.commits);
console.log(logMessages);
}
}
}
});
});
}
ready = true;
}
main();

View File

@ -0,0 +1,6 @@
{
"dependencies": {
"ascii-table": "*"
},
"version": "0.1.0"
}