1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
var Promise = require('bluebird');
var git = require('nodegit');
var moment = require('moment');
var _ = require('lodash');
var config = {
// Maximum time diff between 2 subsequent commits in minutes which are
// counted to be in the same coding "session"
maxCommitDiffInMinutes: 240,
// How many minutes should be added for the first commit of coding session
firstCommitAdditionInMinutes: 120
}
function main() {
commits('.').then(function(commits) {
var work = {
total: {
hours: estimateHours(_.pluck(commits, 'date')),
commits: commits.length
}
};
console.log(JSON.stringify(work, undefined, 2));
}).catch(function(e) {
console.error(e.stack);
});
}
// Estimates spent working hours based on commit dates
function estimateHours(dates) {
if (dates.length < 2) {
return 0;
}
// Oldest commit first, newest last
var sortedDates = dates.sort().reverse();
var hours = _.reduce(dates, function(hours, date, index) {
var previousDate = dates[index - 1];
var diffInMinutes = (date - previousDate) / 1000 / 60;
// Check if commits are counted to be in same coding session
if (diffInMinutes < config.maxCommitDiffInMinutes) {
return hours + (diffInMinutes / 60);
}
// The date difference is too big to be inside single coding session
// The work of first commit of a session cannot be seen in git history,
// so we make a blunt estimate of it
return hours + (config.firstCommitAdditionInMinutes / 60);
}, 0);
return Math.round(hours);
}
// Promisify nodegit's API of getting all commits in repository
function commits(gitPath) {
return new Promise(function(resolve, reject) {
git.Repo.open(gitPath, function(err, repo) {
if (err) {
reject(err);
return;
}
repo.getMaster(function(err, branch) {
if (err) {
reject(err);
return;
}
var history = branch.history();
var commits = [];
history.on("commit", function(commit) {
var commitData = {
sha: commit.sha(),
date: commit.date(),
message: commit.message(),
author: {
name: commit.author().name(),
email: commit.author().email()
}
}
commits.push(commitData);
});
history.on("end", function() {
resolve(commits);
});
// Start emitting events.
history.start();
});
});
});
}
main();
|