UNPKG

12.8 kBJavaScriptView Raw
1var Promise = require('promise'),
2 childProcess = require('child_process'),
3 spawn = require('child_process').spawn,
4 diffParse = require('parse-diff'),
5 logParse = require('./parse-log.js').logParse,
6 util = require('util'),
7 formatBuilder = require('../git-format-builder'),
8 globalErrorHandler = require('../global-error-handler'),
9 consoleFileLogger = require("../sl-logger.js").consoleFileLogger;
10
11var GIT_ROOT_DIR_COMMAND = " rev-parse --show-toplevel";
12var GIT_LS_FILES_COMMAND = " ls-tree --full-tree -r --name-only HEAD";
13var MAX_BUFFER_VALUE = 1024 * 1024 * 200; //200 Mb, instead of 200Kb
14
15function Git(cfg) {
16 this.getCfg = function getCfg() { return cfg; }
17}
18
19Git.prototype.getGitPath = function getGitPath() {
20 return (this.getCfg() || {}).gitPath || 'git';
21 // /tools/arch/Linux_2.6.32-x86_64/gcc-4.9.1-buildrel/bin/git
22}
23
24Git.prototype.detectCommitVersion = function detectCommitVersion(handlerParams, logger) {
25 var gitPath = this.getGitPath();
26 var cfg = this.getCfg();
27 var log = logger? logger.child({methodName: "detectCommitVersion"}) : consoleFileLogger("detectCommitVersion");
28 var p = new Promise(function (resolve, reject) {
29 try {
30 log.info('GIT: invoking git log -n 1.');
31 log.info('GIT PATH: '+gitPath);
32 var cmd = gitPath + " log -n 1 --pretty=format:%H";
33 var gitLogOutput = childProcess.exec(cmd, {
34 cwd: handlerParams.buildArguments.workspacepath,
35 //maxBuffer: 1024 * 1024 * 200 //200 Mb, instead of 200Kb
36 }, function (error, stdout, stderr) {
37 //debuglog('stdout: ' + stdout);
38 if (error !== null) {
39 handleChildProcessError(error, stderr, log);
40 reject(error);
41 return;
42 }
43 var commit = stdout.toString().trim();
44 resolve(commit);
45 });
46 } catch (e) {
47 globalErrorHandler.setLastError(e, 'GIT log error in detectCommitVersion: ');
48 reject(e);
49 }
50 });
51 return p;
52}
53
54Git.prototype.getBranchHistory = function getBranchHistory(handlerParams, logger) {
55 var gitPath = this.getGitPath();
56 var cfg = this.getCfg();
57 var log = logger? logger.child({methodName: "getBranchHistory"}) : consoleFileLogger("getBranchHistory");
58 var p = new Promise(function (resolve, reject) {
59 var historyLength = getHistoryLength(cfg, log);
60 log.info('GIT: invoking git log to get branch history');
61 log.info('GIT PATH: ' + gitPath);
62 var format = new formatBuilder().withCommit().withAuthorName().withAuthorEmail().withCommitterName().withCommitTerEmail()
63 .withAuthorDate().withCommitterDate().withTitle().build();;
64 var gitLogOutput = childProcess.exec(gitPath + ' log -n ' + historyLength + ' --format='+format, {
65 cwd: handlerParams.buildArguments.workspacepath,
66 maxBuffer: MAX_BUFFER_VALUE
67 }, function (error, stdout, stderr) {
68 if (error !== null) {
69 handleChildProcessError(error, stderr, log)
70 reject(error);
71 return;
72 }
73 gitLog = handleBranchHistoryOutput(stdout, handlerParams, log);
74 resolve(gitLog);
75 });
76 });
77 return p;
78}
79
80Git.prototype.getContributors = function getContributors(handlerParams, logger){
81 var gitPath = this.getGitPath();
82 var cfg = this.getCfg();
83 var log = logger? logger.child({methodName: "getContributors"}) : consoleFileLogger("getContributors");
84 var p = new Promise(function (resolve, reject) {
85 var historyLength = getHistoryLength(cfg, log);
86 var format = new formatBuilder().withAuthorName("contributorName").withAuthorEmail("contributorEmail").build();
87 var gitLogOutput = childProcess.exec(gitPath + ' log -n ' + historyLength +' --all --format=' + format, {
88 cwd: handlerParams.buildArguments.workspacepath,
89 maxBuffer: MAX_BUFFER_VALUE
90 }, function (error, stdout, stderr) {
91 if (error !== null) {
92 handleChildProcessError(error, stderr, log);
93 reject(error);
94 return
95 }
96 contributorsLog = handleContributorsOutput(stdout, log);
97 resolve(contributorsLog);
98 });
99 })
100 return p;
101}
102
103Git.prototype.getCommitsPerFile = function getCommitsPerFile(handlerParams, logger){
104 var gitPath = this.getGitPath();
105 var cfg = this.getCfg();
106 var log = logger? logger.child({methodName: "getCommitsPerFile"}) : consoleFileLogger("getCommitsPerFile");
107 var historyLength = getHistoryLength(cfg, log);
108 var p = new Promise(function (resolve, reject) {
109 var commitToIndexMap = handlerParams.commitToIndexMap;
110 if(!commitToIndexMap){
111 logger.error("Cannot get commits for file, Commits log map is null or undefined");
112 resolve('');
113 }
114 var gitLogOutput = childProcess.exec(gitPath + ' log -' + historyLength + ' --name-only --pretty=format:hash:%H', {
115 cwd: handlerParams.buildArguments.workspacepath,
116 maxBuffer: MAX_BUFFER_VALUE
117 }, function (error, stdout, stderr) {
118 if (error !== null) {
119 handleChildProcessError(error, stderr, log);
120 reject(error);
121 return
122 }
123 var fileToCommitMap = handleCommitsPerFileOutput(stdout, commitToIndexMap, log);
124 resolve(fileToCommitMap);
125 });
126 })
127 return p;
128}
129
130Git.prototype.getRepositoryUrl = function getRepositoryUrl(handlerParams, logger) {
131 var gitPath = this.getGitPath();
132 var log = logger? logger.child({methodName: "getRepositoryUrl"}) : consoleFileLogger("getRepositoryUrl");
133 var p = new Promise(function (resolve, reject) {
134 var gitLogOutput = childProcess.exec(gitPath + ' remote -v', {
135 cwd: handlerParams.buildArguments.workspacepath,
136 maxBuffer: MAX_BUFFER_VALUE
137 }, function (error, stdout, stderr) {
138 if (error !== null) {
139 handleChildProcessError(error, stderr, log);
140 reject(error);
141 return;
142 }
143 try {
144 var repositoryUrl = '';
145 if (stdout.toString()) {
146 repositoryUrl = logParse(stdout.toString());
147 repositoryUrl = repositoryUrl[0].split('\t').map(function (l) {return l.trim()})[1].replace(' (fetch)', '');
148 }
149 resolve(repositoryUrl);
150 }
151 catch (e) {
152 globalErrorHandler.setLastError(e, 'Cannot get repository url due to an error: ');
153 resolve('');
154 }
155 });
156 })
157 return p;
158}
159
160Git.prototype.getRootDirectory = function getRootDirectory(handlerParams) {
161 var gitPath = this.getGitPath();
162 return new Promise(function (resolve, reject) {
163 childProcess.exec(gitPath + GIT_ROOT_DIR_COMMAND,{cwd: handlerParams.buildArguments.workspacepath} , function (error, stdout, stderr) {
164 if (error) {
165 handleChildProcessError(error, stderr, log);
166 reject(error);
167 }
168 if(stderr){
169 reject(stderr);
170 }
171 var rootDirPath = stdout.toString().trim();
172 resolve(rootDirPath);
173 })
174 });
175}
176
177Git.prototype.getFiles = function getGitFiles(handlerParams) {
178 var gitPath = this.getGitPath();
179 return new Promise(function (resolve, reject) {
180 childProcess.exec(gitPath + GIT_LS_FILES_COMMAND,{
181 cwd: handlerParams.buildArguments.workspacepath,
182 maxBuffer: MAX_BUFFER_VALUE
183 } , function (error, stdout, stderr) {
184 if (error) {
185 handleChildProcessError(error, stderr, log);
186 reject(error);
187 }
188 if(stderr){
189 reject(stderr);
190 }
191 var result = stdout.toString() || "";
192 var gitFilesList = result.trim().split("\n");
193 resolve(gitFilesList);
194 })
195 });
196}
197
198function createCommitLogEntry(line, handlerParams){
199 var lineObject = JSON.parse(line);
200 var authorEmail = lineObject.authorEmail;
201 var authorIndex = handlerParams.emailToIndexMap[authorEmail];
202 var commitLogEntry={
203 contributorIndex : authorIndex,
204 commit: lineObject.commit,
205 committerDate: parseInt(lineObject.committerDate),
206 authorDate: parseInt(lineObject.authorDate),
207 title: lineObject.title
208 }
209 return commitLogEntry;
210}
211
212function logJsonParsError(logger, line, field, err) {
213 logger.warn("Unsupported string format \"" + line + "\" .'" + field + "' may not be shown in dashboard")
214 logger.debug("Error:", err)
215}
216
217function handleBranchHistoryOutput(stdout, handlerParams, logger){
218 var commitHistory = [];
219 var commitLog = [];
220 var commitToIndexMap ={};
221 var sendContributors = handlerParams.buildArguments.sendContributors;
222 var lines = stdout.toString().split('\n');
223 lines.forEach(function (line,index) {
224 if(!line || line.trim().length == 0){
225 return
226 }
227 line = line.trim();
228 line = fixUnSupportedJsonCharacters(line);
229 try {
230 var gitLogEntry;
231 if(sendContributors) {
232 gitLogEntry = createCommitLogEntry(line, handlerParams)
233 }else{
234 gitLogEntry = JSON.parse(line);
235 }
236 commitHistory.push(gitLogEntry.commit);
237 commitLog.push(gitLogEntry);
238 commitToIndexMap[gitLogEntry.commit] = index;
239 }
240 catch (err) {
241 logJsonParsError(logger, line, "commit-log", err);
242 }
243 });
244 var gitLog = {
245 commitHistory: commitHistory,
246 commitLog: commitLog
247 };
248 if(sendContributors){
249 gitLog.commitToIndexMap = commitToIndexMap;
250 }
251 return gitLog;
252}
253
254function handleContributorsOutput(stdout, logger){
255 var contributors=[]
256 var emailToIndexMap= {}
257 var lines = stdout.toString().split('\n');
258 var contributorIndex = 0;
259 lines.forEach(function (line, lineIndex) {
260 if(!line || line.trim().length == 0){
261 return
262 }
263 line = line.trim();
264 try {
265 line = fixUnSupportedJsonCharacters(line);
266 var contributorData = JSON.parse(line);
267 if(!emailToIndexMap.hasOwnProperty(contributorData.contributorEmail)) {
268 contributors.push(contributorData);
269 emailToIndexMap[contributorData.contributorEmail] = contributorIndex++;
270 }
271 }
272 catch (err) {
273 logJsonParsError(logger, line, "contributor", err);
274 }
275 })
276 var contributorsLog ={
277 contributors : contributors,
278 emailToIndexMap : emailToIndexMap
279 }
280 return contributorsLog;
281}
282
283function handleCommitsPerFileOutput(stdout, commitToIndexMap, log) {
284 var fileToCommitMap = {}
285 var commits = stdout.toString().split('hash:');
286 try {
287 commits.forEach(function (currCommit) {
288 currCommit = currCommit.trim();
289 var commitData = currCommit.split('\n');
290 if(commitData.length < 2){
291 return
292 }
293 var commitHash = commitData[0];
294 for(var i=1;i<commitData.length;i++){
295 if(fileToCommitMap[commitData[i]]){
296 fileToCommitMap[commitData[i]].push(commitToIndexMap[commitHash])
297 }else{
298 fileToCommitMap[commitData[i]] =[commitToIndexMap[commitHash]]
299 }
300 }
301 })
302 }
303 catch (e) {
304 log.error("File to commit map error: " + e);
305 }
306 return fileToCommitMap;
307}
308
309function handleChildProcessError(error, stderr, log){
310 globalErrorHandler.setLastError(error, 'GIT log error: ');
311 log.error('GIT log error: ' + error);
312 log.error('stderr: ' + stderr);
313}
314
315function getHistoryLength(cfg, log) {
316 var historyLength = 100;
317 if (cfg.branchHistoryLength) {
318 var v = parseInt(cfg.branchHistoryLength);
319 if (v < 1 || Number.isNaN(v)) {
320 log.error("An invalid value was specified for branchHistoryLength in sealights.json: " + cfg.branchHistoryLength + ". Valid values are positive integers. Defaulting to " + historyLength);
321
322 }
323 else {
324 historyLength = v;
325 }
326
327 }
328 return historyLength;
329
330}
331
332function fixUnSupportedJsonCharacters(entry){
333 // Backslashes ar not supported by json format so we replace it to double slashes.
334 // For more info please see 'http://json.org/' (the string schema).
335 return entry.replace(/\\/g, "\\\\");
336}
337
338module.exports = Git;