1 | var check = require('check-more-types')
|
2 | var moment = require('moment')
|
3 | var spawn = require('child_process').spawn
|
4 | var path = require('path')
|
5 | var getGitRootFolder = require('./repo-root')
|
6 | var debug = require('debug')('ggit')
|
7 |
|
8 |
|
9 | function gitLog (filename, commits, cb, err, rootFolder) {
|
10 | debug('gitLog, err?', err)
|
11 |
|
12 | if (err) {
|
13 | throw err
|
14 | }
|
15 | check.maybe.string(filename, 'missing filename')
|
16 | check.verify.positiveNumber(commits, 'invalid number of commits', commits)
|
17 | check.verify.fn(cb, 'callback should be a function')
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | var args = ['log', '--name-status', '-n ' + commits]
|
23 | debug('gitLog args', args)
|
24 |
|
25 | if (filename) {
|
26 | debug('gitLog uses filename', filename)
|
27 | check.verify.string(rootFolder, 'could not find git root folder')
|
28 | rootFolder = rootFolder.trim()
|
29 | rootFolder = rootFolder.replace(/\//g, '\\')
|
30 |
|
31 | console.log('filename', filename)
|
32 | console.log('repo root folder', rootFolder)
|
33 | var workingFolder = process.cwd()
|
34 | console.log('working folder', workingFolder)
|
35 |
|
36 | var relativePath = path.relative(workingFolder, filename)
|
37 |
|
38 | args.push(relativePath)
|
39 | }
|
40 |
|
41 | debug('git log command', args)
|
42 | var git = spawn('git', args)
|
43 |
|
44 | commits = []
|
45 | git.stdout.setEncoding('utf-8')
|
46 | git.stdout.on('data', function (data) {
|
47 | data.trim()
|
48 |
|
49 |
|
50 | var separatedData = data.split('\ncommit ')
|
51 | separatedData = separatedData.filter(function (str) {
|
52 | str.trim()
|
53 | return str && str !== '\n'
|
54 | })
|
55 | var info = separatedData.map(parseCommit)
|
56 | commits = commits.concat(info)
|
57 | })
|
58 |
|
59 | git.stderr.setEncoding('utf-8')
|
60 | git.stderr.on('data', function (data) {
|
61 | if (filename) {
|
62 | throw new Error('Could not get git log for\n' + filename + '\n' + data)
|
63 | } else {
|
64 | throw new Error('Could not get git log\n' + data)
|
65 | }
|
66 | })
|
67 |
|
68 | git.on('exit', function () {
|
69 | debug('returning', commits.length, 'commits')
|
70 | cb(commits)
|
71 | })
|
72 | }
|
73 |
|
74 | function parseCommit (data) {
|
75 | check.verify.string(data, 'null commit data')
|
76 | data = data.trim()
|
77 |
|
78 | var lines = data.split('\n')
|
79 | console.assert(lines.length > 3, 'invalid commit\n', data)
|
80 |
|
81 | var commitLine = lines[0].trim()
|
82 | if (commitLine.indexOf('commit ') === 0) {
|
83 | commitLine = commitLine.substr('commit '.length)
|
84 | }
|
85 |
|
86 | var authorLine = lines[1].split(':')[1].trim()
|
87 | var dateLine = lines[2]
|
88 | dateLine = dateLine.substr(dateLine.indexOf(':') + 1)
|
89 | dateLine = dateLine.trim()
|
90 |
|
91 |
|
92 | lines.splice(0, 3)
|
93 | lines = lines.filter(function (str) {
|
94 | return str
|
95 | })
|
96 | lines = lines.map(function (str) {
|
97 | str = str.trim()
|
98 | return str
|
99 | })
|
100 |
|
101 | var files = []
|
102 | lines = lines.filter(function (str) {
|
103 |
|
104 | if (
|
105 | str.indexOf('M') === 0 ||
|
106 | str.indexOf('A') === 0 ||
|
107 | str.indexOf('D') === 0
|
108 | ) {
|
109 | files.push({
|
110 | name: str.substr(1).trim(),
|
111 | status: str[0]
|
112 | })
|
113 | return false
|
114 | } else {
|
115 | return true
|
116 | }
|
117 | })
|
118 |
|
119 | var description = lines.join('\n')
|
120 | return {
|
121 | commit: '' + commitLine.trim(),
|
122 | author: authorLine.trim(),
|
123 | date: moment(new Date(dateLine)),
|
124 | description: description.trim(),
|
125 | files: files
|
126 | }
|
127 | }
|
128 |
|
129 | function getGitLog (filename, commits, cb) {
|
130 | if (filename) {
|
131 | check.verify.string(filename, 'expected filename')
|
132 | filename = path.resolve(filename)
|
133 | console.log('fetching', commits, 'history for', filename)
|
134 | }
|
135 | commits = commits || 30
|
136 | check.verify.positiveNumber(commits, 'invalid max number of commits', commits)
|
137 | check.verify.fn(cb, 'expect callback function, not', cb)
|
138 |
|
139 | getGitRootFolder(gitLog.bind(null, filename, commits, cb))
|
140 | }
|
141 |
|
142 | module.exports = {
|
143 | getGitLog: getGitLog,
|
144 | parseCommit: parseCommit
|
145 | }
|