git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC] More diff possibilities in gitweb
@ 2007-03-17 15:17 Martin Koegler
  2007-03-17 18:04 ` Johannes Schindelin
  2007-03-17 21:51 ` Jakub Narebski
  0 siblings, 2 replies; 9+ messages in thread
From: Martin Koegler @ 2007-03-17 15:17 UTC (permalink / raw)
  To: git

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();

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-03-20  1:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-17 15:17 [RFC] More diff possibilities in gitweb Martin Koegler
2007-03-17 18:04 ` Johannes Schindelin
2007-03-18 14:14   ` Martin Koegler
2007-03-18 23:20     ` Jakub Narebski
2007-03-19 22:03       ` Martin Koegler
2007-03-20  1:41         ` Jakub Narebski
2007-03-17 21:51 ` Jakub Narebski
2007-03-18 15:02   ` Martin Koegler
2007-03-18 21:55     ` Jakub Narebski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).