[RFC] More diff possibilities in gitweb

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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();
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]