Compared to eg. viewcvs, gitweb offers fewer possibilies to do a diff. With viewcvs, you can compare arbitrary version of a file; gitweb only offers diff to previous (or sometimes current) version.
As git offers an infinite number of possible (and maybe useful) diffs, I added to each each compareable object two links: * "base": Select this object as parent * "diff": Diff against the last select parent
The selected parent object is stored as a cookie, so it is possible to do a diff between objects shown on different pages.
The whole is implemented in JavaScript on the client side (tested with IE 6 and Mozilla). On the server side, only the JavaScript file is included in the output (see below). The link generation is done completely in the browser.
The patch offers the following possibilies:
* Compare any commit with an other commit
Passes the hashes of the two commits as h and hp to commitdiff
function. The output includes the message of one commit, which can
be confusing.
* Compare any blob with an other blob
This feature is based on the blobdiff function. There are two types
of blob:
- blobs in the tree view can be compared with any blob in the tree view.
- blobs in the history view can only be compared with any blob with
the same file name in the history view.
* Compare trees
gitweb currently has no function for comparing trees. I currently
misused blobdiff for this. The content of the diff is OK, only the
filenames are wrong/destroyed. Additionally gitweb issus some "Use
of uninitialized value" message to the error log.A proper implementation would need new function in gitweb.cgi, basically git_commitdiff removing the requirement, that the hashes must be a commit.
Is there an interest these function?
mfg Martin Kögler
Patch for gitweb.cgi (in function git_footer_html):
---------------------------------------------------
+ print '<script type="text/javascript" src="gitweb.js"></script>';
print "</body>\n" .
"</html>";File gitweb.js:
---------------
function getCookie(name)
{
var name=name+"=";
var c=document.cookie;
var p=c.indexOf(name);
if(p==-1)
return null;
c=c.substr(p+name.length,c.length);
p=c.indexOf(";");
if(p==-1)
return c;
else
return c.substr(0, p);
}function insertAfter(elem, node)
{
if(node.nextSibling)
node.parentNode.insertBefore(elem, node.nextSibling);
else
node.parentNode.appendChild(elem);
}function createLink(href, linktext)
{
var l=document.createElement("a");
l.appendChild(document.createTextNode(linktext));
l.href=href;
return l;
}function createLinkGroup(href1, basetxt, href2, difftxt)
{
var l=document.createElement("span");
l.appendChild(document.createTextNode(" ("));
l.appendChild(createLink(href1, basetxt));
l.appendChild(document.createTextNode(" | "));
l.appendChild(createLink(href2, difftxt));
l.appendChild(document.createTextNode(") "));
return l;
}function GitRef()
{
this.t=null;
this.h=null;
this.hb=null;
this.f=null;
this.ToRef=ToRef;
}function ToRef()
{
var parts=new Array();
if(this.f)
parts.push("f="+this.f);
if(this.h)
parts.push("h="+this.h);
if(this.hb)
parts.push("hb="+this.hb);
if(this.t)
parts.push("t="+this.t);
return parts.join("@");
}function splitGitRef(ref)
{
var parts=ref.split("@");
var res=new GitRef();
var i;
for(i=0;i<parts.length;i++)
{
var p=parts[i].split("=");
res[p[0]]=p[1];
}
return res;
}function GitURL(base)
{
this.base=base;
this.p=null;
this.a=null;
this.f=null;
this.fp=null;
this.h=null;
this.hp=null;
this.hb=null;
this.hpb=null;
this.pg=null;
this.o=null;
this.s=null;
this.st=null;
this.ToURL=ToURL;
this.ToRef=UrlToRef;
this.ToDUrl=ToDUrl;
}function ToURL()
{
var parts=new Array();
if(this.p)
parts.push("p="+this.p);
if(this.a)
parts.push("a="+this.a);
if(this.f)
parts.push("f="+this.f);
if(this.fp)
parts.push("fp="+this.fp);
if(this.h)
parts.push("h="+this.h);
if(this.hp)
parts.push("hp="+this.hp);
if(this.hb)
parts.push("hb="+this.hb);
if(this.hpb)
parts.push("hpb="+this.hpb);
if(this.o)
parts.push("o="+this.o);
if(this.s)
parts.push("s="+this.s);
if(this.st)
parts.push("st="+this.st);
return this.base+"?"+parts.join(";");
}function UrlToRef(type)
{
var res=new GitRef;
res.f=this.f;
res.h=this.h;
res.hb=this.hb;
res.t=type;
return res.ToRef();
}function ToDUrl(type)
{
var res=new GitURL(this.base);
res.f=this.f;
res.h=this.h;
res.hb=this.hb;
res.p=this.p;
res.a=type;
return res.ToURL();
}function splitGitURL(url)
{
var Urls=url.split("?");
var res=new GitURL(Urls[0]);
if(Urls.length>1)
{
var parts=Urls[1].split(";");
var i;
for(i=0;i<parts.length;i++)
{
var p=parts[i].split("=");
res[p[0]]=p[1];
}
}
return res;
}function GitAddLinks()
{
var links=document.getElementsByTagName("a");
var i;
for(i=0;i<links.length;i++)
{
var link=links[i];
if(link.innerHTML=='commit')
{
var url=splitGitURL(link.href);
if(!url.h)
continue;
var l=createLinkGroup("javascript:base('"+url.ToRef('commit')+"')","base",
"javascript:diff('"+url.ToDUrl('commit')+"')","diff");
insertAfter(l, link);
}
if(link.innerHTML=='blob')
{
var url=splitGitURL(link.href);
if(!url.h&&!(url.hb&&url.f))
continue;
var l=createLinkGroup("javascript:base('"+url.ToRef('blob')+"')","base",
"javascript:diff('"+url.ToDUrl('blob')+"')","diff");
insertAfter(l, link);
}
if(link.innerHTML=='tree')
{
var url=splitGitURL(link.href);
if(!url.h)
continue;
var l=createLinkGroup("javascript:base('"+url.ToRef('tree')+"')","base",
"javascript:diff('"+url.ToDUrl('tree')+"')","diff");
insertAfter(l, link);
}
}
}function base(ref)
{
document.cookie="basename="+ref;
}function diff(url)
{
var c=getCookie("basename");
if (!c)
{
alert("no diff base selected");
return;
}
c=splitGitRef(c);
url=splitGitURL(url); if(c.t=='commit'&&url.a=='commit')
{
url.a='commitdiff';
if(!c.h||!url.h)
{
alert("commit diff not possible");
return;
}
url.hb=null;
url.f=null;
url.hp=c.h;
document.location.href=url.ToURL();
return;
}
if(c.t=='blob'&&url.a=='blob')
{
url.a='blobdiff';
if(c.h&&url.h)
{
url.hb=null;
url.hp=c.h;
url.fp=c.f;
}
else if (c.hb&&url.hb&&url.f&&c.f)
{
if (url.f!=c.f)
{
alert("file name do not match");
return;
}
url.h=null;
url.hpb=c.hb;
url.fp=c.f;
}
else
{
alert("blob diff not possible");
return;
}
document.location.href=url.ToURL();
return;
}
if(c.t=='tree'&&url.a=='tree')
{
url.a='blobdiff';
if(c.h&&url.h)
{
url.hb=null;
url.hp=c.h;
url.fp=c.f;
document.location.href=url.ToURL();
return;
}
}
alert("diff not possible");
}GitAddLinks();