diff options
author | Milo Casagrande <milo.casagrande@linaro.org> | 2015-02-02 10:11:55 +0100 |
---|---|---|
committer | Milo Casagrande <milo.casagrande@linaro.org> | 2015-02-02 10:11:55 +0100 |
commit | dd094018abf4497d52a5875318f29d0cbc11a14a (patch) | |
tree | 28e68e8233c48b483b1cb55aa0f08887e558d719 | |
parent | 39f1216862f233e63be77117d845098350446854 (diff) |
Add new bisect JavaScript library.
Change-Id: I52c034b99d01dec1f56da751306df817fceced47
-rw-r--r-- | app/dashboard/static/js/linaro-bisect-0.0.1.js | 436 |
1 files changed, 309 insertions, 127 deletions
diff --git a/app/dashboard/static/js/linaro-bisect-0.0.1.js b/app/dashboard/static/js/linaro-bisect-0.0.1.js index 2396b20..8c549b7 100644 --- a/app/dashboard/static/js/linaro-bisect-0.0.1.js +++ b/app/dashboard/static/js/linaro-bisect-0.0.1.js @@ -14,6 +14,71 @@ var Bisect = (function() { 'use strict'; + var bisectBootComparisonDescription, + bisectBuildComparisonDescription, + buildTooltipTitleF, + buildTooltipLinkF, + bootTooltipLinkF, + bootTooltipTitleF, + gitDescribeCellF, + commitCellF, + bisectScriptElementF, + BisectElements; + + // Object prototype that should be passed to fillBisctTable function. + BisectElements = { + // The ID of the div containing the bisect table. + tableDivID: null, + // The ID of the table element. + tableID: null, + // The ID of the table tbody element. + tableBodyID: null, + // The div element that contains all the bisect DOM. + contentDivID: null, + // The ID of the div with the loading content text. + loadingDivID: null, + // The ID of the element with the loading text. + loadingContentID: null, + // The text to substitute. + loadingContentText: null, + // The ID of the element that store the good commit. + goodCommitID: null, + // The ID of the element that store the bad commit. + badCommitID: null, + // The ID of the element that contains the bisect script. + bisectScriptContainerID: null, + // Where the bisect script should be placed. + bisectScriptContentID: null, + // The ID of the element that should contain the bisect comparison + // description. + bisectCompareDescriptionID: null, + // The bisect data of the previous bisect (for comparison). + prevBisect: null + }; + + // Format strings used to build links, tooltips, labels... + // They require the sprintf JavaScript library. + bootTooltipTitleF = 'Boot report details for %s ‐ %s'; + bootTooltipLinkF = '<a href="/boot/all/job/%s/kernel/%s">%s</a>'; + buildTooltipLinkF = '<a href="/build/%s/kernel/%s">%s</a>'; + buildTooltipTitleF = 'Build details for %s ‐ %s'; + gitDescribeCellF = '<td><span class="bisect-tooltip"><span ' + + 'rel="tooltip" data-toggle="tooltip" title="%s"><span ' + + 'class="bisect-text">%s</span></span></span></td>'; + commitCellF = '<td class="%s"><a href="%s">%s ' + + '<i class="fa fa-external-link"></i></a></td>'; + + bisectBootComparisonDescription = 'The comparison with the ' + + '«%s» tree is based on the boot reports with the same ' + + 'board, lab name and defconfig values.'; + bisectBuildComparisonDescription = 'The comparison with the ' + + '«%s» tree is based on the build reports with the same ' + + 'defconfig value.'; + + bisectScriptElementF = '<span rel="tooltip" data-toggle="tooltip"' + + 'title="%s"><a download="%s" href="%s">' + + '<i class="fa fa-download"></i></a></span>'; + // Create a simple bash script for git bisection. // `badCommit`: The starting point for the bisect script. // `goodCommit`: The end point. @@ -28,64 +93,168 @@ var Bisect = (function() { encodeURIComponent(bisectScript); } - // Fill up the bisect summary element in a page. - // `badCommit`: The bad commit value. - // `goodCommit`: The good commit value. - // `badCommitEl`: The DOM element ID where the bad commit should be shown. - // `goodCommitEl`: The DOM element ID where the good commit should be shown. - // `bisectScriptEl`: The DOM element ID where the bisect script should be - // placed. - // `bisectScriptElContainer`: The DOM element ID that contains the bisect - // script. - function fillBisectSummary( - badCommit, - goodCommit, - badCommitEl, - goodCommitEl, - bisectScriptEl, - bisectScriptElContainer) - { + function bisectCompareShellScript(badCommit, goodCommits) { + var bisectScript = ''; + + if (badCommit !== null && goodCommits.length > 0) { + bisectScript = '#!/bin/bash\ngit bisect start\n'; + bisectScript += sprintf('git bisect bad %s\n', badCommit); + goodCommits.forEach(function(element) { + bisectScript += sprintf('git bisect good %s\n', element); + }); + } + + return sprintf( + 'data:text/plain;charset=UTF-8,%s', + encodeURIComponent(bisectScript)); + } + + function bisectComparedToSummary( + bisectElements, bisectType, comparedCommits) { + var prevData = null, + prevBadCommit = null, + prevGoodCommit = null, + prevGoodCommitDate = null, + otherCommitDate = null, + otherCommitsArray = [], + prevCommitInserted = false; + + if (comparedCommits.length > 0) { + prevData = bisectElements.prevBisect; + prevBadCommit = prevData.bad_commit; + prevGoodCommit = prevData.good_commit; + + if (prevGoodCommit !== null) { + prevGoodCommitDate = new Date( + prevData.good_commit_date.$date); + } + + comparedCommits.forEach(function(element) { + if (bisectType === 'boot') { + otherCommitDate = new Date( + element.boot_created_on.$date); + } else if (bisectType === 'build') { + otherCommitDate = new Date( + element.defconfig_created.$date); + } + + if (!prevCommitInserted && prevGoodCommitDate !== null && + prevGoodCommitDate < otherCommitDate) { + otherCommitsArray.push(prevGoodCommit); + otherCommitsArray.push(element.git_commit); + prevCommitInserted = true; + } else { + otherCommitsArray.push(element.git_commit); + } + }); + + if (bisectType === 'boot') { + JSBase.replaceContentByID( + bisectElements.bisectScriptContentID, + sprintf( + bisectScriptElementF, + 'Download boot bisect comparison script', + 'bisect-compared.sh', + bisectCompareShellScript( + prevBadCommit, otherCommitsArray) + ) + ); + } else if (bisectType === 'build') { + JSBase.replaceContentByID( + bisectElements.bisectScriptContentID, + sprintf( + bisectScriptElementF, + 'Download build bisect comparison script', + 'bisect-compared.sh', + bisectCompareShellScript( + prevBadCommit, otherCommitsArray) + ) + ); + } + + JSBase.removeCssClassForID( + bisectElements.bisectScriptContainerID, 'hidden'); + } else { + JSBase.removeElementByID( + bisectElements.bisectScriptContainerID); + } + } + + function bisectSummary(badCommit, goodCommit, bisectElements, bisectType) { if (badCommit !== null) { JSBase.replaceContentByID( - badCommitEl, - '<span class="text-danger">' + badCommit + '</span>' - ); + bisectElements.badCommitID, + '<span class="text-danger">' + badCommit + '</span>'); } else { JSBase.replaceContentByID( - badCommitEl, - '<span class="text-warning">' + - 'No corresponding bad commit found</span>' - ); + bisectElements.badCommitID, + '<span class="text-warning">No bad commit found</span>'); } if (goodCommit !== null) { JSBase.replaceContentByID( - goodCommitEl, - '<span class="text-success">' + goodCommit + '</span>' - ); + bisectElements.goodCommitID, + '<span class="text-success">' + goodCommit + '</span>'); } else { JSBase.replaceContentByID( - goodCommitEl, - '<span class="text-warning">No good commit found</span>' - ); + bisectElements.goodCommitID, + '<span class="text-warning">No good commit found</span>'); } if (badCommit !== null && goodCommit !== null) { - JSBase.removeCssClassForID('hidden'); - JSBase.replaceContentByID( - bisectScriptEl, - '<span rel="tooltip" data-toggle="tooltip"' + - 'title="Download boot bisect script">' + - '<a download="bisect.sh" href="' + - bisectShellScript(badCommit, goodCommit) + - '"><i class="fa fa-download"></i></a></span>' - ); + JSBase.removeCssClassForID( + bisectElements.bisectScriptContainerID, 'hidden'); + if (bisectType === 'boot') { + JSBase.replaceContentByID( + bisectElements.bisectScriptContentID, + sprintf( + bisectScriptElementF, + 'Download boot bisect script', + 'bisect.sh', + bisectShellScript(badCommit, goodCommit) + ) + ); + } else if (bisectType === 'build') { + JSBase.replaceContentByID( + bisectElements.bisectScriptContentID, + sprintf( + bisectScriptElementF, + 'Download build bisect script', + 'bisect.sh', + bisectShellScript(badCommit, goodCommit) + ) + ); + } + } else { + JSBase.removeElementByID( + bisectElements.bisectScriptContainerID); + } + } + + // Fill up the bisect summary element in a page. + // `badCommit`: The bad commit value. + // `goodCommit`: The good commit value. + // `bisectElements`: The BisectElements object with DOM ids and other data. + // `bisectType`: The type of the bisect (boot, build). + // `compareGoodCommits`: The good commits for the comparison. + // `isBisectComparison`: If this is for a comparison bisect or not. + function fillBisectSummary( + badCommit, + goodCommit, + bisectElements, + bisectType, + compareGoodCommits, + isBisectComparison) + { + if (isBisectComparison) { + bisectComparedToSummary( + bisectElements, bisectType, compareGoodCommits); } else { - JSBase.removeContentByID(bisectScriptElContainer); + bisectSummary(badCommit, goodCommit, bisectElements, bisectType); } } - function createBisectTableRow(bisectData, job) { - var status = bisectData.boot_status, + function parseBisectDataToRow(bisectData, job, bisectType) { + var bisectStatus = null, gitDescribeVal = bisectData.git_describe, gitCommit = bisectData.git_commit, gitURL = bisectData.git_url, @@ -96,54 +265,56 @@ var Bisect = (function() { goodCommitCell = '', badCommitCell = '', unknownCommitCell = '', - row = '<tr></tr>'; + row = '<tr></tr>', + goodCommit = null; + + if (bisectData.hasOwnProperty('status')) { + bisectStatus = bisectData.status; + } else { + bisectStatus = bisectData.boot_status; + } if (gitCommit === '' || gitCommit === undefined) { gitCommit = null; } if (gitCommit !== null) { - tooltipLink = '<a href="/boot/all/job/' + job + - '/kernel/' + gitDescribeVal + '">' + - gitDescribeVal + '</a>'; - - tooltipTitle = 'Boot report details for ' + job + - ' ‐ ' + gitDescribeVal; + if (bisectType === 'boot') { + tooltipLink = sprintf( + bootTooltipLinkF, job, gitDescribeVal, gitDescribeVal); + tooltipTitle = sprintf(bootTooltipTitleF, job, gitDescribeVal); + } else if (bisectType === 'build') { + tooltipLink = sprintf( + buildTooltipLinkF, job, gitDescribeVal, gitDescribeVal); + tooltipTitle = sprintf(buildTooltipTitleF, job, gitDescribeVal); + } else { + tooltipLink = gitDescribeVal; + } - gitDescribeCell = '<td><span class="bisect-tooltip">' + - '<span rel="tooltip" data-toggle="tooltip" ' + - 'title="' + tooltipTitle + '">' + - '<span class="bisect-text">' + tooltipLink + - '</span></span></span></td>'; + gitDescribeCell = sprintf( + gitDescribeCellF, tooltipTitle, tooltipLink); - gitURLs = JSBase.translateCommitURL( - gitURL, gitCommit); + gitURLs = JSBase.translateCommitURL(gitURL, gitCommit); - switch (status) { + switch (bisectStatus) { case 'PASS': - goodCommitCell = '<td class="bg-success">' + - '<a href="' + gitURLs[1] + '">' + gitCommit + - ' <i class="fa fa-external-link">' + - '</i></a></td>'; + goodCommit = bisectData; + goodCommitCell = sprintf( + commitCellF, 'bg-success', gitURLs[1], gitCommit); badCommitCell = '<td class="bg-danger"></td>'; unknownCommitCell = '<td class="bg-warning"></td>'; break; case 'FAIL': goodCommitCell = '<td class="bg-success"></td>'; - badCommitCell = '<td class="bg-danger"><a href="' + - gitURLs[1] + '">' + gitCommit + - ' <i class="fa fa-external-link">' + - '</i></a></td>'; + badCommitCell = sprintf( + commitCellF, 'bg-danger', gitURLs[1], gitCommit); unknownCommitCell = '<td class="bg-warning"></td>'; break; default: goodCommitCell = '<td class="bg-success"></td>'; badCommitCell = '<td class="bg-danger"></td>'; - unknownCommitCell = '<td class="bg-warning">' + - '<a href="' + - gitURLs[1] + '">' + gitCommit + - ' <i class="fa fa-external-link">' + - '</i></a></td>'; + unknownCommitCell = sprintf( + commitCellF, 'bg-warning', gitURLs[1], gitCommit); break; } @@ -151,42 +322,41 @@ var Bisect = (function() { unknownCommitCell + goodCommitCell + '</tr>'; } - return row; + return [row, goodCommit]; } // Populate a bisect table based on the provided DOM elements. - // `data`: The bisect JSON data to analyze. - function fillBisectTable( - data, - tableElementDiv, - tableElementID, - tableBodyElement, - contentElement, - loadingContentDiv, - loadingContentElement, - loadingText, - showSummary, - badCommitElement, - goodCommitElement, - bisectScriptElement, - bisectScriptContainerElement) - { - JSBase.replaceContentByID(loadingContentElement, loadingText); + // `bisectData`: The bisect JSON data to analyze. + // `bisectElements`: The BisectElements data structure that contains the + // DOM element IDs and other necessary data. + // `isBisectComparison`: If the bisect is a comparison one or not. + function fillBisectTable(bisectData, bisectElements, isBisectComparison) { + JSBase.replaceContentByID( + bisectElements.loadingContentID, + bisectElements.loadingContentText); - var localResult = data.result[0], + var localResult = bisectData.result[0], localData = localResult.bisect_data, localLen = localData.length, i = 0, tableRows = '', + bisectType = null, job = null, badCommit = null, - goodCommit = null; + goodCommit = null, + rowResult = null, + // Contain the good commits for comparison purposes. + compareGoodCommits = []; - job = localResult.compare_to; badCommit = localResult.bad_commit; goodCommit = localResult.good_commit; + bisectType = localResult.type; - if (job === null || job === undefined || job === '') { + // Retrieve the job value in case the 'compare_to' field is empty. + // It is empty in the case of a normal bisect. + if (isBisectComparison) { + job = localResult.compare_to; + } else { job = localResult.job; } @@ -198,51 +368,63 @@ var Bisect = (function() { goodCommit = null; } - if (showSummary && badCommit === null && goodCommit === null) { - JSBase.removeContentByID(loadingContentDiv); - JSBase.removeContentByID(tableElementDiv); - JSBase.replaceContentByID( - contentElement, - '<div class="pull-center">' + - '<strong>No valid bisect data found.</strong></div>' - ); - JSBase.showContentByID(contentElement); - } else { - if (localLen === 0) { - JSBase.removeContentByID(loadingContentDiv); - JSBase.removeContentByID(tableElementID); + // If it is a comparison bisect, add the description to the summary. + if (isBisectComparison) { + if (bisectType === 'boot') { + JSBase.replaceContentByID( + bisectElements.bisectCompareDescriptionID, + '<p>' + sprintf(bisectBootComparisonDescription, job) + + '</p>' + ); + } else if (bisectType === 'build') { JSBase.replaceContentByID( - tableElementDiv, - '<div class="pull-center">' + - '<strong>' + - 'No bisect data available to compare with.<strong>' + - '</div>' + bisectElements.bisectCompareDescriptionID, + '<p>' + sprintf(bisectBuildComparisonDescription, job) + + '</p>' ); - JSBase.showContentByID(contentElement); } else { - for (i; i < localLen; i = i + 1) { - tableRows += createBisectTableRow(localData[i], job); - } + JSBase.removeElementByID( + bisectElements.bisectCompareDescriptionID); + } + } - if (showSummary) { - fillBisectSummary( - badCommit, - goodCommit, - badCommitElement, - goodCommitElement, - bisectScriptElement, - bisectScriptContainerElement - ); - } + if (localLen === 0) { + JSBase.removeElementByID(bisectElements.tableID); + JSBase.replaceContentByID( + bisectElements.contentDivID, + '<div class="pull-center"><strong>' + + 'No bisect data available.<strong></div>' + ); + } else { + for (i; i < localLen; i = i + 1) { + rowResult = parseBisectDataToRow( + localData[i], job, bisectType); - JSBase.removeContentByID(loadingContentDiv); - JSBase.replaceContentByID(tableBodyElement, tableRows); - JSBase.showContentByID(contentElement); + tableRows += rowResult[0]; + if (rowResult[1] !== null) { + compareGoodCommits.push(rowResult[1]); + } } + + fillBisectSummary( + badCommit, + goodCommit, + bisectElements, + bisectType, + compareGoodCommits, + isBisectComparison + ); + + JSBase.replaceContentByID(bisectElements.tableBodyID, tableRows); } + + JSBase.removeElementByID(bisectElements.loadingDivID); + JSBase.showElementByID(bisectElements.contentDivID); } return { + BisectElements: BisectElements, + bisectCompareShellScript: bisectCompareShellScript, bisectShellScript: bisectShellScript, fillBisectTable: fillBisectTable }; |