UNPKG

quality-bot

Version:

QBot Online Code Review Application

245 lines (232 loc) 8.47 kB
const simpleGit = require('simple-git'); const fs = require('fs') const localStorage = require('localStorage'); const messageService = require('./message-service'); const documentService = require('./document-service'); const qbot = require('./qbot-service'); const Utils = require('./utils'); let commentDetails = []; const git = simpleGit(); const parseData = async () => { const nameCommand = 'config --get user.name'.split(' '); let name = await git.raw(nameCommand); const arg = process.argv; let command = 'config --get user.qbot-token-local'.split(' '); const coreHooksPath = await getExistingCoreHooksPath(); const localCoreHooksPath = await getExistingLocalCoreHooksPath(); const globalCoreHooksPath = await getExistingGlobalCoreHooksPath(); if ((coreHooksPath && localCoreHooksPath && globalCoreHooksPath) || (coreHooksPath && localCoreHooksPath && !globalCoreHooksPath)) { command = 'config --get user.qbot-token-local'.split(' '); } else if (coreHooksPath && !localCoreHooksPath && globalCoreHooksPath) { command = 'config --get user.qbot-token-global'.split(' '); } let token = await git.raw(command); if (arg.length > 3 && arg[3] && arg[3].includes('--token')) { let splittedArgument = arg[3].split("="); token = splittedArgument[1]; } return { command: arg.length >= 3 ? arg[2] : '', token: token, username: name } } const extractWords = (str) => { const words = []; for (let i = 0; i < str.length; i++) { if (str.charAt(i) === '@' && str.charAt(i - 1) === '@') { const stopIndex = str.indexOf('@@', i); if (stopIndex !== -1) words.push(str.substring(i + 1, stopIndex)); } } return words; } const extractName = (str) => { const words = []; for (let i = 0; i < str.length; i++) { if (str.charAt(i) === '/' && str.charAt(i - 1) === 'a') { const stopIndex = str.indexOf('b/', i); if (stopIndex !== -1) words.push(str.substring(i + 1, stopIndex)); } } return words; } const getChangedLineNumber = (data) => { const finalData = {}; data.forEach(e => { if (e) { const fileName = extractName(e)[0] && extractName(e)[0].trim(); if (fileName) { let list = extractWords(e); list = list.filter((e, i) => i % 2 === 0); if (list.length) { finalData[fileName] = []; list.map(e => { let range = e.split('+')[1]; range = range.split(','); for (let i = 0; i < (range[1] || 1); i++) { finalData[fileName].push(+range[0] + i); } if ((e.includes('-') && e.includes('+')) || e.includes('+')) { if (finalData[fileName].length === 0) { finalData[fileName].push(null); } } }); } } } }); return finalData; } const review = async (data) => { if (!data.token) { messageService.invalidToken(); return; } const fileList = await Utils.getFileList(); if (!fileList.length) { messageService.noFiles(); return; } const command = 'diff --unified=0 --staged'.split(' '); const different = await git.raw(command); const changedLine = getChangedLineNumber(different.split('diff --git ')); let filesToRemove = []; let totalNull = []; if (fileList.length) { fileList.forEach(file => { changedLine[file].forEach(lineNumbers => { if (lineNumbers === null) { totalNull.push(null); } }) if (totalNull.length == changedLine[file].length) { filesToRemove.push(file); } }); } const finalFileList = fileList.filter(function (x) { return filesToRemove.indexOf(x) < 0; }); let comments = 0, i = 0; let repoDetails = null; if (finalFileList.length === 0) { messageService.success(); return []; } else { await getAuthToken(data); repoDetails = await getRepoDetails(data); const reviewDetails = await reviewFiles(repoDetails, finalFileList, changedLine, data, comments, i); return reviewDetails; } } const getExistingCoreHooksPath = async () => { const command = 'config --get core.hookspath'.split(' '); const coreHooksPath = await git.raw(command); return coreHooksPath ? coreHooksPath.trim() : ''; } const getExistingLocalCoreHooksPath = async () => { const command = 'config --get --local core.hookspath'.split(' '); const coreHooksPath = await git.raw(command); return coreHooksPath ? coreHooksPath.trim() : ''; } const getExistingGlobalCoreHooksPath = async () => { const command = 'config --get --global core.hookspath'.split(' '); const coreHooksPath = await git.raw(command); return coreHooksPath ? coreHooksPath.trim() : ''; } const getRepoDetails = async (data) => { let repoDetails = null; try { repoDetails = await qbot.repoDetails(data.token); } catch (err) { messageService.serverError( (err.response && err.response.data) && err.response.data.message || err.message); process.exit(1); } return repoDetails; } const getAuthToken = async (data) => { let jwtToken = null; try { jwtToken = await qbot.getAuthToken(data.token, data.username); localStorage.setItem("bearerToken", jwtToken.data.accessToken); } catch (err) { messageService.serverError( (err.response && err.response.data) && err.response.data.message || err.message); process.exit(1); } } const reviewFiles = async (repoDetails, fileList, changedLine, data, comments, i) => { const nameCommand = 'config --get user.name'.split(' '); let name = await git.raw(nameCommand); if (repoDetails.data && repoDetails.data.id && repoDetails.data.organizationId) { await fileList.forEach(async (e) => { let fileContent = ''; try { fileContent = fs.readFileSync(e, 'utf8'); } catch (err) { messageService.invalidLocation(err.message); process.exit(1); } try { const res = await qbot.review({ projectId: repoDetails.data.id, organizationId: repoDetails.data.organizationId, fileName: e, fileContent: fileContent, changedLineNumber: changedLine[e] || [] }, data.token); if (res.data) { comments = (res.data.length || 0) + comments; if (res.data.length) { res.data.forEach(data => { commentDetails.push(data); messageService.comments(data); }); } } // Final Part i++; if (fileList.length === i) { if (comments === 0) { messageService.success(); } else { documentService.createReportFile(commentDetails, name, fileList.length, repoDetails); messageService.commentsInfo(comments, fileList); } } } catch (err) { messageService.serverError( (err.response && err.response.data) && err.response.data.message || err.message); process.exit(1); } }); } else { messageService.serverError("Repository is not configured. Please contact your project manager to configure the repository."); process.exit(1); } return { comments, i }; } module.exports = { parseData, review, getExistingCoreHooksPath, getExistingLocalCoreHooksPath, getExistingGlobalCoreHooksPath, }