<!-- Copyright (c) Perforce Software, Inc., 1997-2010. All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. User contributed content on the Perforce Public Depot is not supported by Perforce, although it may be supported by its author. This applies to all contributions even those submitted by Perforce employees. --> <html> <head> <title>Pending Integrations</title> <link rel="stylesheet" type="text/css" href="applets.css" /> <script type="text/javascript"> function defaultUser() { document.getElementById('branchuser').value = P4JsApi.encodeForHTMLAttribute(P4JsApi.getUser()); } // defaultUser function getPendingIntegs() { var maxFiles = document.getElementById('maxfiles').value; var maxBranches = document.getElementById('maxbranches').value; P4JsApi.setWebKitDeveloperExtrasEnabled(true); var table = document.getElementById('pendingintegs'); for(var i = table.rows.length; i > 1;i--) { table.deleteRow(i -1); } // get all branch specs owned by current user var branchuser = document.getElementById('branchuser').value; var branchfilter = document.getElementById('branchfilter').value; var branchescmd = 'branches'; if(branchuser != '') { branchescmd = branchescmd + ' -u ' + branchuser; } if(branchfilter != '') { branchescmd = branchescmd + ' -e "' + branchfilter + '"'; } var branches = P4JsApi.p4(branchescmd); for (var i = 0; i < branches.size && i < maxBranches; i++) { var branch = branches.data[i]; // get view var branchspec = P4JsApi.p4("branch -o " + branch.Branch); var origview = branchspec.data[0].View0; var indexofdiv = origview.lastIndexOf("//"); var view = P4JsApi.encodeForHTML(origview.substring(0,indexofdiv)) + "<br> " + P4JsApi.encodeForHTML(origview.substring(indexofdiv)); var fullview = '<b>View</b><br>' + branchspec.data[0].View0; var k = 1; while(typeof branchspec.data[0]["View" + k] != "undefined") { fullview = fullview + "<br>" + branchspec.data[0]["View" + k]; k++; } // complete view var fullviewdiv = document.createElement("div"); fullviewdiv.id = 'tooltip_' + i; fullviewdiv.className = 'tooltip'; fullviewdiv.innerHTML = fullview; document.getElementById('thebody').appendChild(fullviewdiv); // get pending forward integs (changelists) var fpendingCL = P4JsApi.p4("interchanges -b " + branch.Branch); var found = 0; var fpendingCLlist = '<ul>'; for (var j = 0; j < fpendingCL.size && j < maxFiles; j++) { if(fpendingCL.data[j].change) { found = 1; fpendingCLlist = fpendingCLlist + "<li>" + P4JsApi.encodeForHTML(fpendingCL.data[j].change) + ": " + getJobsFixed(fpendingCL.data[j].change, branch.Branch, ''); } } // all forward pending integs if(fpendingCL.size > maxFiles) { fpendingCLlist = fpendingCLlist + "<br><i>... and " + (fpendingCL.size - maxFiles)+ " more</i>"; } // more than max files to show fpendingCLlist = fpendingCLlist + "</ul>"; if(found == 0) { fpendingCLlist = "<i>None found</i>"; } console.log(fpendingCLlist); // get pending reverse integs var rpendingCL = P4JsApi.p4("interchanges -r -b " + branch.Branch); found = 0; var rpendingCLlist = '<ul>'; for (var j = 0; j < rpendingCL.size && j < maxFiles; j++) { if(rpendingCL.data[j].change) { found = 1; rpendingCLlist = rpendingCLlist + "<li>" + P4JsApi.encodeForHTML(rpendingCL.data[j].change) + ": " + getJobsFixed(rpendingCL.data[j].change, branch.Branch, '-r'); } } // all reverse pending integs if(rpendingCL.size > maxFiles) { rpendingCLlist = rpendingCLlist + "<br><i>... and " + (rpendingCL.size - maxFiles)+ " more</i>"; } // more than max files to show rpendingCLlist = rpendingCLlist + "</ul>"; if(found == 0) { rpendingCLlist = "<i>None found</i>"; } console.log(rpendingCLlist); // get pending forward integs var fpending = P4JsApi.p4("integrate -n -b " + branch.Branch); var fpendinglist = ''; for (var j = 0; j < fpending.size && j < maxFiles; j++) { fpendinglist = fpendinglist + P4JsApi.encodeForHTML(fpending.data[j].depotFile) + "<br>"; } // all forward pending integs if(fpending.size > maxFiles) { fpendinglist = fpendinglist + "<i>... and " + (fpending.size - maxFiles)+ " more</i>"; } // more than max files to show console.log(fpendinglist); // get pending reverse integs var rpending = P4JsApi.p4("integrate -n -r -b " + branch.Branch); var rpendinglist = ''; for (var j = 0; j < rpending.size && j < maxFiles; j++) { rpendinglist = rpendinglist + P4JsApi.encodeForHTML(rpending.data[j].depotFile) + "<br>"; } // all reverse pending integs if(rpending.size > maxFiles) { rpendinglist = rpendinglist + "<i>... and " + (rpending.size - maxFiles)+ " more</i>"; } // more than max files to show console.log(rpendinglist); // add branch to table var row = document.createElement("tr"); row.innerHTML = "<td class='applet colone'>" + P4JsApi.encodeForHTML(branch.Branch) + "</td>" + "<td id='tdview_" + i + "' class='applet coltwo' onmouseover='tooltip_show(\"tooltip_" + i + "\", \"tdview_" + i + "\");' onmouseout='tooltip_hide(\"tooltip_" + i + "\");'>" + view + "</td>" + "<td class='applet colinterchanges'>" + "<div class='interchanges'>" + fpendingCLlist + "</div>" + "</td>" + "<td class='applet colinterchanges'>" + "<div class='interchanges'>" + rpendingCLlist + "</div>" + "</td>" + "<td class='applet colinteg'>" + "<div class='integ'>" + fpendinglist + "</div>" + "</td>" + "<td class='applet colinteg'>" + "<div class='integ'>" + rpendinglist + "</div>" + "</td>"; table.appendChild(row); } // all branches owned by user } // getPendingIntegs function getJobsFixed(cl, branch, direction) { var jobs = P4JsApi.p4("fixes -c " + cl); var joblist = ''; for (var j = 0; j < jobs.size; j++) { joblist = joblist + "<a href='#' onclick='integJob(\"" + jobs.data[j].Job + "\", \"" + branch + "\", \"" + direction + "\")'>" + P4JsApi.encodeForHTML(jobs.data[j].Job) + "</a>" + ", "; } // all jobs return joblist; } // getJobsFixed function logObject(o) { for(var k in o) { console.log(k, o[k]); } } // logObject function integJob(jobId, branch, direction) { var cls = P4JsApi.p4("fixes -j " + jobId); var results = ''; var found = 0; for (var j = (cls.size - 1); j >= 0; j--) { var cl = cls.data[j].Change; found = 1; var integCmd = "integ " + direction + " -b " + branch + " //...@" + cl + ",@" + cl; results = results + "> " + integCmd + "\r\n"; var result = P4JsApi.p4(integCmd); if(result.data[0].action) { results = results + ">> " + result.size + " files integrated\r\n"; } else { results = results + ">> " + result.data[0].p4ERROR.message + "\r\n"; } logObject(result.data[0]); } // all changelists if(found > 0) { results = "Now review any pending files in the default changelist, resolve, and submit!\r\nLog:\r\n" + results; } document.getElementById('jobintegresults').innerHTML = P4JsApi.encodeForHTML(results); } // integJob function tooltip_findPosX(obj) { var curleft = 0; if (obj.offsetParent) { while (obj.offsetParent) { curleft += obj.offsetLeft obj = obj.offsetParent; } } else if (obj.x) curleft += obj.x; return curleft; } // tooltip_findPosX function tooltip_findPosY(obj) { var curtop = 0; if (obj.offsetParent) { while (obj.offsetParent) { curtop += obj.offsetTop obj = obj.offsetParent; } } else if (obj.y) curtop += obj.y; return curtop; } // tooltip_findPosY function tooltip_show(tooltipId, parentId) { it = document.getElementById(tooltipId); if ((it.style.top == '' || it.style.top == 0) && (it.style.left == '' || it.style.left == 0)) { // need to fixate default size (MSIE problem) it.style.width = it.offsetWidth + 'px'; it.style.height = it.offsetHeight + 'px'; img = document.getElementById(parentId); // if tooltip is too wide, shift left to be within parent x = tooltip_findPosX(img); y = tooltip_findPosY(img); it.style.top = y + 'px'; it.style.left = x + 'px'; } it.style.visibility = 'visible'; } // tooltip_show function tooltip_hide(id) { it = document.getElementById(id); it.style.visibility = 'hidden'; } // tooltip_hide </script> </head> <body onload="defaultUser(); getPendingIntegs();" id="thebody"> <table class="eighty applet"> <tr> <th class="filter">User</th> <th class="filter">Filter</th> <th class="filter">Max Branches</th> <th class="filter">Max Files</th> </tr> <tr> <td class="filter"><input type="text" value="" id="branchuser"/></td> <td class="filter"><input type="text" value="" id="branchfilter"/></td> <td class="filter"><input type="text" value="10" id="maxbranches"/></td> <td class="filter"><input type="text" value="20" id="maxfiles"/></td> </tr> <tr> <td class="filter" align="center" colspan="4"><input type="button" value="Load" onclick="getPendingIntegs();"/></td> </tr> </table> <br> <table id="pendingintegs" class="applet interchanges"> <tr> <th scope="col" class="applet colone">Branch</th> <th scope="col" class="applet coltwo">View (first line)</th> <th scope="col" class="applet colinterchanges">Pending Changelists and Jobs</th> <th scope="col" class="applet colinterchanges">Reverse Pending Changelists and Jobs</th> <th scope="col" class="applet colinteg">Pending Files</th> <th scope="col" class="applet colinteg">Reverse Pending Files</th> </tr> </table> <br> <textarea class="results" id="jobintegresults" readonly="readonly"> </textarea> </body> </html>
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 7957 | Randy DeFauw |
Added a very simple promote-by-job function. Added interchanges output. REQUIRES 2011.1 P4V. |
||
#4 | 7725 | Randy DeFauw |
New features: CSS for style Documentation applet Provide flexible branch filtering Display full branch view in tool-tip Limit number of branches/files displayed |
||
#3 | 7681 | Randy DeFauw | add copyright and license info | ||
#2 | 7672 | Randy DeFauw | Use scroll bars when the list of pending file integs is long | ||
#1 | 7669 | Randy DeFauw | Adding example P4JsApi applet showing pending integrations |