summaryrefslogtreecommitdiffstats
path: root/index.js
blob: b04fa3a7dfdff9cd9c53923d79adfcfad04fa3db (plain)
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();