From 76224c40fef862071276c64b5f3d581b745e217d Mon Sep 17 00:00:00 2001 From: Matt Pass Date: Mon, 27 Aug 2012 15:47:48 +0100 Subject: [PATCH] ICErepo plugin added Not quite finished yet, but an early version added for use --- plugins/ice-repo/LICENSE.md | 24 +++ plugins/ice-repo/README.md | 61 ++++++++ plugins/ice-repo/contents.php | 127 +++++++++++++++ plugins/ice-repo/file-control.php | 144 ++++++++++++++++++ plugins/ice-repo/ice-repo.css | 78 ++++++++++ plugins/ice-repo/ice-repo.js | 1 + plugins/ice-repo/images/file-folder-icons.png | Bin 0 -> 6376 bytes plugins/ice-repo/images/ice-repo.gif | Bin 0 -> 1687 bytes plugins/ice-repo/index.php | 76 +++++++-- plugins/ice-repo/lib/base64.js | 5 + plugins/ice-repo/lib/difflib.js | 31 ++++ plugins/ice-repo/lib/github.js | 11 ++ plugins/ice-repo/lib/underscore-min.js | 12 ++ 13 files changed, 559 insertions(+), 11 deletions(-) create mode 100644 plugins/ice-repo/LICENSE.md create mode 100644 plugins/ice-repo/README.md create mode 100644 plugins/ice-repo/contents.php create mode 100644 plugins/ice-repo/file-control.php create mode 100644 plugins/ice-repo/ice-repo.css create mode 100644 plugins/ice-repo/ice-repo.js create mode 100644 plugins/ice-repo/images/file-folder-icons.png create mode 100644 plugins/ice-repo/images/ice-repo.gif create mode 100644 plugins/ice-repo/lib/base64.js create mode 100644 plugins/ice-repo/lib/difflib.js create mode 100644 plugins/ice-repo/lib/github.js create mode 100644 plugins/ice-repo/lib/underscore-min.js diff --git a/plugins/ice-repo/LICENSE.md b/plugins/ice-repo/LICENSE.md new file mode 100644 index 0000000..fb21f97 --- /dev/null +++ b/plugins/ice-repo/LICENSE.md @@ -0,0 +1,24 @@ +Copyright (C) 2012 Matt Pass +Website: mattpass.com +Email: matt@mattpass.com +Twitter: @mattpass + +#ICErepo License +##Standard Open Source Initiative MIT License +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/plugins/ice-repo/README.md b/plugins/ice-repo/README.md new file mode 100644 index 0000000..daca2a6 --- /dev/null +++ b/plugins/ice-repo/README.md @@ -0,0 +1,61 @@ +ICErepo +======= + +Show diffs, push, pull & sync your site and Github repo's. + +While Github has a fantastic website, mobile app, desktop app and of course bash system, there's no web based UI I can find to sync your website code with Github repo's or vice versa. That's what ICErepo provides. + +Originally intended to be a plugin for ICEcoder (https://github.com/mattpass/ICEcoder), I have decided to make it a standalone lib so it can run by itself or easily be integrated into any existing system. + +The aim is a simple UI to view diffs between your server dir's and related Github repo's. This list will consist of new files (those only on server), deleted files (those only on Github) and changed files (files that exist in both places but are different). Files that exist in both locations and the same are not shown to keep things minimalist. + +Users can then to pick & choose the files & folder they'd like to commit, provide a title and message, then commit to Github. As each file is synced by the user to match the server it dissapears from the UI list. Alternatively you can pull files & folders from Github to sync your server dir's with the repo itself. + +Cool huh? + +**Current screnshot:** + +ICErepo screenshot + +This lib uses customised & minified versions of these brilliant and time tested repos: + +Github API lib: https://github.com/michael/github + +JS Diff lib: https://github.com/cemerick/jsdifflib + +###Installation + +####Step 1: Clone the repo + +``` +$ git clone git@github:mattpass/ICErepo +``` + +####Step 2: Enter your auth settings +``` +Open index.php and enter either your Github oauth token or username & password +oauth is recommended here, view http://developer.github.com/v3/oauth/ for info +(If using oauth ensure you have repo scope & your app is granted the URL you'll run under) +``` + +####Step 3: Enter your repo & server dir settings +``` +Also in index.php, enter the repo & corresponding server paths +Enter 'selected' as a 3rd param next to your default repo/server option to autoload that +Finally, set $_SESSION['userLevel'] to be > 0 with your own login system, or simply uncomment line 3 +Upload ICErepo, visit in a web browser & enjoy +``` + +**Dev schedule:** + +**v0.8** +Bug testing, refactoring & optimisation + +**v0.9** +Alpha testing + +**v0.95** +Beta testing + +**v1.0** +Version 1 released \ No newline at end of file diff --git a/plugins/ice-repo/contents.php b/plugins/ice-repo/contents.php new file mode 100644 index 0000000..23e8616 --- /dev/null +++ b/plugins/ice-repo/contents.php @@ -0,0 +1,127 @@ + + + + +ICErepo v<?php echo $version;?> + + + + + + + + + + +getPathname(), $b->getPathname()); +} + +// Class to put forward the values for sorting +class SortingIterator implements IteratorAggregate { + private $iterator = null; + public function __construct(Traversable $iterator, $callback) { + $array = iterator_to_array($iterator); + usort($array, $callback); + $this->iterator = new ArrayIterator($array); + } + public function getIterator() { + return $this->iterator; + } +} + +// Get a full list of dirs & files and begin sorting using above class & function +$repoPath = explode("@",strClean($_POST['repo'])); +$repo = $repoPath[0]; +$path = $repoPath[1]; +$objectList = new SortingIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST), 'alphasort'); + +// Finally, we have our ordered list, so display +$i=0; +$dirListArray = array(); +$dirSHAArray = array(); +$dirTypeArray = array(); +$finfo = finfo_open(FILEINFO_MIME_TYPE); +foreach ($objectList as $objectRef) { + $fileFolderName = rtrim(substr($objectRef->getPathname(), strlen($path)),".."); + if ($objectRef->getFilename()!="." && $fileFolderName[strlen($fileFolderName)-1]!="/") { + $contents = file_get_contents($path.$fileFolderName); + if (strpos(finfo_file($finfo, $path.$fileFolderName),"text")===0) { + $contents = str_replace("\r","",$contents); + }; + $store = "blob ".strlen($contents)."\000".$contents; + $i++; + array_push($dirListArray,ltrim($fileFolderName,"/")); + array_push($dirSHAArray,sha1($store)); + $type = is_dir($path.$fileFolderName) ? "dir" : "file"; + array_push($dirTypeArray,$type); + } +} +finfo_close($finfo); +?> + + + +
+ +
+COMMIT CHANGES:

+
+
+ + + + + + + + + + + +
+
+ +
+ + + + + + + + \ No newline at end of file diff --git a/plugins/ice-repo/file-control.php b/plugins/ice-repo/file-control.php new file mode 100644 index 0000000..0f8820f --- /dev/null +++ b/plugins/ice-repo/file-control.php @@ -0,0 +1,144 @@ + + + + +ICErepo v<?php echo $version;?> + + + + + + + + + + + + + + +
+ +
+ + +
+ '; + echo ''; + echo ''; + echo ''; + echo ''; + for ($i=0;$i'; + } + } + ?> + + + + + +
+ '; + echo htmlentities(file_get_contents($dirArray[$i])); + echo ''; + } + } + ?> +
+ + + + + + \ No newline at end of file diff --git a/plugins/ice-repo/ice-repo.css b/plugins/ice-repo/ice-repo.css new file mode 100644 index 0000000..7f07e56 --- /dev/null +++ b/plugins/ice-repo/ice-repo.css @@ -0,0 +1,78 @@ +/* First, reset everything to a standard */ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + font-family: arial, verdana, helvetica, sans-serif; + border: 0px; + margin: 0px; + padding: 0px; + outline: 0px; + font-size: 12px; + vertical-align: top; +} + +html, body {background-color: #fff; width: 100%} +p {color: #444} +textarea, input {font-family: arial, verdana, helvetica, sans-serif; padding: 4px} + +.header {position: absolute; width: 100%; height: 60px; background: #444; z-index: 1} + +.mainContainer {position: relative; display: block; width: 900px; padding: 20px} + +.blackMask {position: absolute; width: 100%; height: 100%; background: rgba(0,0,0,0.9); z-index: 200} +.loadingMsgCenter {position: absolute; display: inline-block; left: 50%; top: 50%; width: 1px; height: 1px} +.loadingMsgContainer {position: absolute; display: inline-block; left: -30px; top: -7px; width: 60px; height: 14px; background-color: #bbb; color: #222; font-weight: bold; text-align: center; padding: 15px; z-index: 201; + -webkit-box-shadow: 8px 8px 8px 8px rgba(0,0,0,0.4); + -moz-box-shadow: 8px 8px 8px 8px rgba(0,0,0,0.4); + box-shadow: 4px 4px 8px 4px rgba(0,0,0,0.4)} + +.repoFrame {position: absolute; width: 100%; height: 90%; left: 0px; margin-top: 60px} + +.row {position: relative; display: inline-block; background: #ccc; color: #000; width: 880px; padding: 10px 7px; margin-bottom: 2px; cursor: pointer; padding-left: 35px} +.row:hover {background: #888; color: #fff} +.row .icon {display: inline-block; width: 16px; height: 16px; margin-right: 7px; background-image:url(images/file-folder-icons.png); background-repeat: no-repeat} +.row .checkbox {position: absolute; display: inline-block; height: 38px; width: 30px; top: -4px; left: 0px} +.rowContent {position: relative; display: none; background: #eee; width: 100%; height: 300px; padding: 7px; margin-bottom: 10px; overflow: auto} +.pullGithub {position: absolute; display: inline-block; top: 7px; left: 822px; padding: 5px; background: #bbb; color: #444; font-size: 10px; cursor: pointer} +.pullGithubSel {position: absolute; display: inline-block; top: 7px; left: 822px; margin-top: 12px; margin-left: -22px; padding: 5px; background: #bbb; color: #444; font-size: 10px; cursor: pointer} +.version {position: absolute; display: inline-block; width: 100px; left: 1000px; top: 33px; font-size: 10px; color: #bbb; text-align: right} +.logo {position: absolute; left: 1107px; top: 12px} + +.commitPane {position: fixed; background: #ccc; width: 270px; height: 300px; left: 960px; top: 0px; padding: 20px 10px 10px 10px; z-index: 100} +.infoPane {position: fixed; width: 270px; height: 100px; left: 960px; top: 340px; padding: 20px 10px 10px 10px; z-index: 100} + +/* Folder */ +.ext-folder {background-position: -16px 0} + +/* Additional file types */ +.ext-coffee {background-position: -32px 0} +.ext-css {background-position: -48px 0} +.ext-gif {background-position: -64px 0} +.ext-htm {background-position: -80px 0} +.ext-html {background-position: -80px 0} +.ext-jpg {background-position: -96px 0} +.ext-jpeg {background-position: -96px 0} +.ext-js {background-position: -112px 0} +.ext-less {background-position: -128px 0} +.ext-php {background-position: -144px 0} +.ext-png {background-position: -160px 0} +.ext-rb {background-position: -176px 0} +.ext-rbx {background-position: -176px 0} +.ext-rhtml {background-position: -176px 0} +.ext-ruby {background-position: -176px 0} +.ext-txt {background-position: -192px 0} +.ext-zip {background-position: -208px 0} + +table.diff {color: #888; border: 0; white-space: pre-wrap} +table.diff tbody th {color:#888; font-size: 11px; font-weight: normal; padding: 2px; vertical-align:top} +table.diff thead th.texttitle {background: #444; color: #fff; text-align:left; padding: 2px} +table.diff tbody td {width: 100%; font-family: Courier, monospace; vertical-align: top} +table.diff .delete {background: #0b0; color: #fff} +table.diff .insert {background: #b00; color: #fff} +table.diff th.author {display: none} \ No newline at end of file diff --git a/plugins/ice-repo/ice-repo.js b/plugins/ice-repo/ice-repo.js new file mode 100644 index 0000000..360b5a4 --- /dev/null +++ b/plugins/ice-repo/ice-repo.js @@ -0,0 +1 @@ +function diffUsingJS(e,t,n,r){var i=difflib.stringAsLines(e),s=difflib.stringAsLines(t),o=new difflib.SequenceMatcher(i,s),u=o.get_opcodes(),a=get("row"+rowID+"Content","parent");while(a.firstChild)a.removeChild(a.firstChild);var f="";f=f?f:null,a.appendChild(diffview.buildView({baseTextLines:i,newTextLines:s,opcodes:u,baseTextName:n,newTextName:r,contextSize:f,viewType:1}))}top.selRowArray=[],top.selRepoDirArray=[],top.selActionArray=[],doRepo=function(e){document.showRepo.repo.value=e,document.showRepo.submit()},updateSelection=function(e,t,n,r){e.checked?(top.selRowArray.push(t),top.selRepoDirArray.push(n),top.selActionArray.push(r)):(arrayIndex=top.selRowArray.indexOf(t),top.selRowArray.splice(arrayIndex,1),top.selRepoDirArray.splice(arrayIndex,1),top.selActionArray.splice(arrayIndex,1))},getContent=function(e,t){if("undefined"==typeof overOption||!overOption){if("undefined"==typeof lastRow||lastRow!=e||get("row"+e+"Content").innerHTML==""){for(i=1;i<=rowID;i++)get("row"+i+"Content").innerHTML="",get("row"+i+"Content").style.display="none";repo=top.repo+"/"+t,dir=top.path+"/"+t,document.fcForm.rowID.value=e,document.fcForm.repo.value=repo,document.fcForm.dir.value=dir,document.fcForm.action.value="view",document.fcForm.submit()}else get("row"+e+"Content").innerHTML="",get("row"+e+"Content").style.display="none";lastRow=e}},commitChanges=function(){if(top.selRowArray.length>0)if(document.fcForm.title.value!="Title..."&&document.fcForm.message.value!="Message..."){get("blackMask","top").style.display="block",top.selRowValue="",top.selDirValue="",top.selRepoValue="",top.selActionValue="";for(i=0;i0?getData():document.fcForm.submit())}):(removeFirstArrayItems(),rowIDArray.length>0?getData():document.fcForm.submit())},sendData=function(e,t){repo.read("master",filePath,function(n,r){dirContent=document.fcForm.fileContents.value,repoContent=r,diffUsingJS(dirContent,repoContent,e,t),get("row"+rowID+"Content","parent").style.display="inline-block"})},removeFirstArrayItems=function(){rowIDArray.splice(0,1),repoArray.splice(0,1),dirArray.splice(0,1),actionArray.splice(0,1)},hideRow=function(e){top.rowCount--,updateInfo("parent"),get("checkbox"+e,"parent").checked=!1,parent.updateSelection(get("checkbox"+e,"parent")),get("row"+e,"parent").style.display=get("row"+e+"Content","parent").style.display="none"},ffAddOrUpdate=function(e,t,n){repo.write("master",t,document.fcForm["fileContents"+e].value,parent.document.fcForm.title.value+"\n\n"+parent.document.fcForm.message.value,function(n){n?alert("Sorry, there was an error adding "+t):(removeFirstArrayItems(),hideRow(e),top.newCount--,rowIDArray.length>0?startProcess():get("blackMask","top").style.display="none")})},ffDelete=function(e,t,n){repo.remove("master",t,function(n){n?alert("Sorry, there was an error deleting "+t):(removeFirstArrayItems(),hideRow(e),top.deletedCount--,rowIDArray.length>0?startProcess():get("blackMask","top").style.display="none")})},startProcess=function(){if(actionArray[0]=="changed"||actionArray[0]=="new")actionArray[0]=="changed"&&(repoLoc=repoArray[0].replace(repoUser+"/"+repoName+"/","")),actionArray[0]=="new"&&(repoLoc=dirArray[0].replace(top.path,"")),ffAddOrUpdate(rowIDArray[0],repoLoc,actionArray[0]);actionArray[0]=="deleted"&&(repoLoc=repoArray[0].replace(repoUser+"/"+repoName+"/",""),ffDelete(rowIDArray[0],repoLoc,actionArray[0]))},get=function(e,t){return t?window[t].document.getElementById(e):document.getElementById(e)},updateInfo=function(e){get("infoPane",e).innerHTML="INFO:

"+top.rowCount+" files

"+top.changedCount+" changed
"+top.newCount+" new
"+top.deletedCount+" deleted"},gitCommand=function(e,t){if(e=="repo.show"){userRepo=t.split("@")[0].split("/"),dir=t.split("@")[1];var n=github.getRepo(userRepo[0],userRepo[1]);rowID=0,n.getTree("master?recursive=true",function(e,t){for(i=0;i",r+="',r+="
"+dirListArray[i],r+="
Delete from server

",r+="",r+="",top.rowCount++,top.newCount++):dirTypeArray[i]=="file"&&dirSHAArray[i]!=repoSHAArray[repoArrayPos]&&(rowID++,sE=ext=="folder"?' style="cursor: default"':"",cE=ext!="folder"?' onClick="getContent('+rowID+",'"+dirListArray[i]+"')\"":"",gE='onClick="pullContent('+rowID+",'"+top.path+"/"+dirListArray[i]+"','"+dirListArray[i]+"','changed')\"",n+="
",n+="',n+="
"+dirListArray[i],n+="
Pull from Github

",n+="
",n+="",top.rowCount++,top.changedCount++);for(i=0;irepoListArray[i].lastIndexOf(".")?"folder":repoListArray[i].substr(repoListArray[i].lastIndexOf(".")+1),dirArrayPos=="-1"&&(rowID++,sE=ext=="folder"?' style="cursor: default"':"",cE=ext!="folder"?' onClick="getContent('+rowID+",'"+repoListArray[i]+"')\"":"",gE='onClick="pullContent('+rowID+",'"+top.path+"/"+repoListArray[i]+"','"+repoListArray[i]+"','deleted')\"",s+="
",s+="',s+="
"+repoListArray[i],s+="
Pull from Github

",s+="
",s+="",top.rowCount++,top.deletedCount++);n="CHANGED FILES:

"+n,r="NEW FILES:

"+r,s="DELETED FILES:

"+s,get("compareList").innerHTML=n+"

"+r+"

"+s,updateInfo(),get("blackMask","top").style.display="none"})}} \ No newline at end of file diff --git a/plugins/ice-repo/images/file-folder-icons.png b/plugins/ice-repo/images/file-folder-icons.png new file mode 100644 index 0000000000000000000000000000000000000000..6435c782358c7345b5027b001c84426f703afde6 GIT binary patch literal 6376 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 literal 0 HcmV?d00001 diff --git a/plugins/ice-repo/index.php b/plugins/ice-repo/index.php index 297cf45..d0fb9de 100644 --- a/plugins/ice-repo/index.php +++ b/plugins/ice-repo/index.php @@ -1,21 +1,75 @@ + + -Github plugin coming soon! +ICErepo v<?php echo $version;?> + + + + + - + + +
+
+
+ WORKING... +
+
+
-ICErepo - Plugin coming soon! -

+
+ + +
Pull selected from Github
+
+ +
-I'm creating a Github plugin right now which will allow you to sync website code with Github repos. -

-Full details and dev at:
-http://github.com/mattpass/ICErepo -

-Expected launch date:
-Wed 22nd Aug +
+ + + + +
+ + \ No newline at end of file diff --git a/plugins/ice-repo/lib/base64.js b/plugins/ice-repo/lib/base64.js new file mode 100644 index 0000000..672eb27 --- /dev/null +++ b/plugins/ice-repo/lib/base64.js @@ -0,0 +1,5 @@ +// This code was written by Tyler Akins and has been placed in the +// public domain. It would be nice if you left this header intact. +// Base64 code from Tyler Akins -- http://rumkin.com + +var Base64=function(){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",t={encode:function(t){var n="",r,i,s,o,u,a,f,l=0;do r=t.charCodeAt(l++),i=t.charCodeAt(l++),s=t.charCodeAt(l++),o=r>>2,u=(r&3)<<4|i>>4,a=(i&15)<<2|s>>6,f=s&63,isNaN(i)?a=f=64:isNaN(s)&&(f=64),n=n+e.charAt(o)+e.charAt(u)+e.charAt(a)+e.charAt(f);while(l>4,i=(u&15)<<4|a>>2,s=(a&3)<<6|f,n+=String.fromCharCode(r),a!=64&&(n+=String.fromCharCode(i)),f!=64&&(n+=String.fromCharCode(s));while(l + +Copyright (c) 2007, Snowtide Informatics Systems, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * 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. + * Neither the name of the Snowtide Informatics Systems nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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. +***/ +/* Author: Chas Emerick */ +__whitespace={" ":!0," ":!0,"\n":!0,"\f":!0,"\r":!0},difflib={defaultJunkFunction:function(e){return __whitespace.hasOwnProperty(e)},stripLinebreaks:function(e){return e.replace(/^[\n\r]*|[\n\r]*$/g,"")},stringAsLines:function(e){var t=e.indexOf("\n"),n=e.indexOf("\r"),r=t>-1&&n>-1||n<0?"\n":"\r",i=e.split(r);for(var s=0;st[r])return 1}return e.length==t.length?0:e.length=200&&o.length*100>t?(r[s]=1,delete n[s]):o.push(i)}else n[s]=[i]}for(var s in r)r.hasOwnProperty(s)&&delete n[s];var u=this.isjunk,a={};if(u){for(var s in r)r.hasOwnProperty(s)&&u(s)&&(a[s]=1,delete r[s]);for(var s in n)n.hasOwnProperty(s)&&u(s)&&(a[s]=1,delete n[s])}this.isbjunk=difflib.__isindict(a),this.isbpopular=difflib.__isindict(r)},this.find_longest_match=function(e,t,n,r){var i=this.a,s=this.b,o=this.b2j,u=this.isbjunk,a=e,f=n,l=0,c=null,h={},p=[];for(var d=e;d=r)break;v[c]=k=difflib.__dictget(h,c-1,0)+1,k>l&&(a=d-k+1,f=c-k+1,l=k)}h=v}while(a>e&&f>n&&!u(s[f-1])&&i[a-1]==s[f-1])a--,f--,l++;while(a+le&&f>n&&u(s[f-1])&&i[a-1]==s[f-1])a--,f--,l++;while(a+la&&(f.push([r,i,Math.min(s,i+e),o,Math.min(u,o+e)]),i=Math.max(i,s-e),o=Math.max(o,u-e)),f.push([r,i,s,o,u]));return f&&f[f.length-1][0]=="equal"&&f.pop(),f},this.ratio=function(){return matches=difflib.__reduce(function(e,t){return e+t[t.length-1]},this.get_matching_blocks(),0),difflib.__calculate_ratio(matches,this.a.length+this.b.length)},this.quick_ratio=function(){var e,t;if(this.fullbcount==null){this.fullbcount=e={};for(var n=0;n0&&s++;return difflib.__calculate_ratio(s,this.a.length+this.b.length)},this.real_quick_ratio=function(){var e=this.a.length,t=this.b.length;return _calculate_ratio(Math.min(e,t),e+t)},this.isjunk=n?n:difflib.defaultJunkFunction,this.a=this.b=null,this.set_seqs(e,t)}},diffview={buildView:function(e){function a(e,t){var n=document.createElement(e);return n.className=t,n}function f(e,t){var n=document.createElement(e);return n.appendChild(document.createTextNode(t)),n}function l(e,t,n){var r=document.createElement(e);return r.className=t,r.appendChild(document.createTextNode(n)),r}function v(e,t,n,r,i){return t1&&(g>0&&N==o||g==0&&N==0)&&change=="equal"){var C=S-(g==0?1:2)*o;if(C>1){x.push(h=document.createElement("tr")),y+=C,w+=C,N+=C-1,h.appendChild(f("th","...")),u||h.appendChild(l("td","skip","")),h.appendChild(f("th","...")),h.appendChild(l("td","skip",""));if(g+1==r.length)break;continue}}x.push(h=document.createElement("tr")),u?change=="insert"?m(h,null,w++,n,change):change=="replace"?(T.push(d=document.createElement("tr")),y=200&&this.status<300||this.status===304?s(null,o?this.responseText:this.responseText?JSON.parse(this.responseText):!0):s({request:this,error:this.status}))},a.setRequestHeader("Accept","application/vnd.github.raw"),a.setRequestHeader("Content-Type","application/json;charset=UTF-8"),(n.auth=="oauth"&&n.token||n.auth=="basic"&&n.username&&n.password)&&a.setRequestHeader("Authorization",n.auth=="oauth"?"token "+n.token:"Basic "+Base64.encode(n.username+":"+n.password)),i?a.send(JSON.stringify(i)):a.send()}e.Repository=function(e){function u(e,t){if(e===o.branch&&o.sha)return t(null,o.sha);i.getRef("heads/"+e,function(n,r){o.branch=e,o.sha=r,t(n,r)})}var t=e.name,n=e.user,i=this,s="/repos/"+n+"/"+t,o={branch:null,sha:null};this.getRef=function(e,t){r("GET",s+"/git/refs/"+e,null,function(e,n){if(e)return t(e);t(null,n.object.sha)})},this.createRef=function(e,t){r("POST",s+"/git/refs",e,t)},this.deleteRef=function(t,n){r("DELETE",s+"/git/refs/"+t,e,n)},this.listBranches=function(e){r("GET",s+"/git/refs/heads",null,function(t,n){if(t)return e(t);e(null,_.map(n,function(e){return _.last(e.ref.split("/"))}))})},this.getBlob=function(e,t){r("GET",s+"/git/blobs/"+e,null,t,"raw")},this.getSha=function(e,t,n){if(t==="")return i.getRef("heads/"+e,n);i.getTree(e+"?recursive=true",function(e,r){var i=_.select(r,function(e){return e.path===t})[0];n(null,i?i.sha:null)})},this.getTree=function(e,t){r("GET",s+"/git/trees/"+e,null,function(e,n){if(e)return t(e);t(null,n.tree)})},this.postBlob=function(e,t){typeof e=="string"&&(e={content:e,encoding:"utf-8"}),r("POST",s+"/git/blobs",e,function(e,n){if(e)return t(e);t(null,n.sha)})},this.updateTree=function(e,t,n,i){var o={base_tree:e,tree:[{path:t,mode:"100644",type:"blob",sha:n}]};r("POST",s+"/git/trees",o,function(e,t){if(e)return i(e);i(null,t.sha)})},this.postTree=function(e,t){r("POST",s+"/git/trees",{tree:e},function(e,n){if(e)return t(e);t(null,n.sha)})},this.commit=function(t,n,i,u){var a={message:i,author:{name:e.username},parents:[t],tree:n};r("POST",s+"/git/commits",a,function(e,t){o.sha=t.sha;if(e)return u(e);u(null,t.sha)})},this.updateHead=function(e,t,n){r("PATCH",s+"/git/refs/heads/"+e,{sha:t},function(e,t){n(e)})},this.show=function(e){r("GET",s,null,e)},this.contents=function(e,t){r("GET",s+"/contents",{path:e},t)},this.fork=function(e){r("POST",s+"/forks",null,e)},this.createPullRequest=function(e,t){r("POST",s+"/pulls",e,t)},this.read=function(e,t,n){i.getSha(e,t,function(e,t){if(!t)return n("not found",null);i.getBlob(t,function(e,r){n(e,r,t)})})},this.remove=function(e,t,n){u(e,function(r,s){i.getTree(s+"?recursive=true",function(r,o){var u=_.reject(o,function(e){return e.path===t});_.each(u,function(e){e.type==="tree"&&delete e.sha}),i.postTree(u,function(r,o){i.commit(s,o,"Deleted "+t,function(t,r){i.updateHead(e,r,function(e){n(e)})})})})})},this.move=function(e,t,n,r){u(e,function(s,o){i.getTree(o+"?recursive=true",function(s,u){_.each(u,function(e){e.path===t&&(e.path=n),e.type==="tree"&&delete e.sha}),i.postTree(u,function(n,s){i.commit(o,s,"Deleted "+t,function(t,n){i.updateHead(e,n,function(e){r(e)})})})})})},this.write=function(e,t,n,r,s){u(e,function(o,u){if(o)return s(o);i.postBlob(n,function(n,o){if(n)return s(n);i.updateTree(u,t,o,function(t,n){if(t)return s(t);i.commit(u,n,r,function(t,n){if(t)return s(t);i.updateHead(e,n,s)})})})})}},e.Gist=function(e){var t=e.id,n=this,i="/gists/"+t;this.read=function(e){r("GET",i,null,function(t,n){e(t,n)})},this.delete=function(e){r("DELETE",i,null,function(t,n){e(t,n)})},this.fork=function(e){r("POST",i+"/fork",null,function(t,n){e(t,n)})},this.update=function(e,t){r("PATCH",i,e,function(e,n){t(e,n)})}},this.getRepo=function(t,n){return new e.Repository({user:t,name:n})}}}).call(this) \ No newline at end of file diff --git a/plugins/ice-repo/lib/underscore-min.js b/plugins/ice-repo/lib/underscore-min.js new file mode 100644 index 0000000..da9fe29 --- /dev/null +++ b/plugins/ice-repo/lib/underscore-min.js @@ -0,0 +1,12 @@ +// This file contains the select, reject, forEach and has functions +// from underscore.js, then minified to make it extra tiny + +// Underscore.js 1.3.3 +// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. +// Portions of Underscore are inspired or borrowed from Prototype, +// Oliver Steele's Functional, and John Resig's Micro-Templating. +// For all details and documentation: +// http://documentcloud.github.com/underscore + +(function(){var e=this,t=Array.prototype,n=Object.prototype,r=t.forEach,i=t.filter,s=n.hasOwnProperty,o={};_=function(obj) {return new wrapper(obj);};_.filter=_.select=function(e,t,n){var r=[];return e==null?r:i&&e.filter===i?e.filter(t,n):(u(e,function(e,i,s){t.call(n,e,i,s)&&(r[r.length]=e)}),r)},_.reject=function(e,t,n){var r=[];return e==null?r:(u(e,function(e,i,s){t.call(n,e,i,s)||(r[r.length]=e)}),r)};var u=_.each=_.forEach=function(e,t,n){if(e==null)return;if(r&&e.forEach===r)e.forEach(t,n);else if(e.length===+e.length){for(var i=0,s=e.length;i