Check-in [840699ecd9]
Not logged in
Overview

SHA1 Hash:840699ecd967d5ba36ce79f0231989f4f4d6a7f6
Date: 2008-02-08 21:23:56
User: drh
Comment:Improvements to annotated diffs - now takes into account contributions from other branches.
Timelines: ancestors | descendants | both | trunk
Other Links: files | ZIP archive | manifest

Tags And Properties
Changes
[hide diffs]

Modified src/diff.c from [fa6ef41ff5] to [a8aca97812].

@@ -562,19 +562,17 @@
 ** of the following structure.
 */
 typedef struct Annotator Annotator;
 struct Annotator {
   DContext c;       /* The diff-engine context */
-  Blob blobTo;      /* Blob to free at next step */
-  int nOrig;        /* Number of lines in original file */
-  int nNoSrc;       /* Number of uncompleted aOrig[].zSrc entries */
   struct {          /* Lines of the original files... */
     const char *z;       /* The text of the line */
     int n;               /* Number of bytes (omitting trailing space and \n) */
     const char *zSrc;    /* Tag showing origin of this line */
   } *aOrig;
-  int *aMap;        /* Map lines for c.aTo into aOrig */
+  int nOrig;        /* Number of elements in aOrig[] */
+  int nNoSrc;       /* Number of entries where aOrig[].zSrc==NULL */
 };
 
 /*
 ** Initialize the annotation process by specifying the file that is
 ** to be annotated.  The annotator takes control of the input Blob and
@@ -586,22 +584,18 @@
   memset(p, 0, sizeof(*p));
   p->c.aTo = break_into_lines(blob_str(pInput), &p->c.nTo);
   if( p->c.aTo==0 ){
     return 1;
   }
-  p->aMap = malloc( sizeof(int)*p->c.nTo );
-  if( p->aMap==0 ) fossil_panic("out of memory");
-  for(i=0; i<p->c.nTo; i++) p->aMap[i] = i;
   p->aOrig = malloc( sizeof(p->aOrig[0])*p->c.nTo );
   if( p->aOrig==0 ) fossil_panic("out of memory");
   for(i=0; i<p->c.nTo; i++){
     p->aOrig[i].z = p->c.aTo[i].z;
     p->aOrig[i].n = p->c.aTo[i].h & LENGTH_MASK;
     p->aOrig[i].zSrc = 0;
   }
   p->nOrig = p->c.nTo;
-  p->nNoSrc = p->c.nTo;
   return 0;
 }
 
 /*
 ** The input pParent is the next most recent ancestor of the file
@@ -610,70 +604,41 @@
 ** on each line of the file being annotated that was contributed by
 ** pParent.  Memory to hold zPName is leaked.
 */
 static int annotation_step(Annotator *p, Blob *pParent, char *zPName){
   int i, j;
-  int lnTo, lnFrom;
-  int *aFromMap;
+  int lnTo;
 
   /* Prepare the parent file to be diffed */
   p->c.aFrom = break_into_lines(blob_str(pParent), &p->c.nFrom);
   if( p->c.aFrom==0 ){
     return 1;
   }
 
-  /* Compute the differences going from pParent to the last file
-  ** processed */
+  /* Compute the differences going from pParent to the file being
+  ** annotated. */
   diff_all(&p->c);
 
   /* Where new lines are inserted on this difference, record the
   ** zPName as the source of the new line.
   */
   for(i=lnTo=0; i<p->c.nEdit; i+=3){
-    lnTo += p->c.aEdit[i];
-    for(j=0; j<p->c.aEdit[i+2]; j++, lnTo++){
-      int x = p->aMap[lnTo];
-      if( x>=0 && p->aOrig[x].zSrc==0 ){
-        p->aOrig[x].zSrc = zPName;
-        p->nNoSrc--;
-      }
-    }
-  }
-
-  /* We will be converting aFrom into aTo for the next step.  Compute
-  ** a map from the aFrom into the original file being annotated.
-  */
-  aFromMap = malloc( sizeof(int)*p->c.nFrom );
-  if( aFromMap==0 ){
-    fossil_panic("out of memory");
-  }
-  for(i=lnTo=lnFrom=0; i<p->c.nEdit; i+=3){
-    for(j=0; j<p->c.aEdit[i]; j++){
-      aFromMap[lnFrom++] = p->aMap[lnTo++];
-    }
-    for(j=0; j<p->c.aEdit[i+1]; j++){
-      aFromMap[lnFrom++] = -1;
+    for(j=0; j<p->c.aEdit[i]; j++, lnTo++){
+      p->aOrig[lnTo].zSrc = zPName;
     }
     lnTo += p->c.aEdit[i+2];
   }
-  assert( lnFrom==p->c.nFrom );
-  free(p->aMap);
-  p->aMap = aFromMap;
 
   /* Clear out the diff results */
   free(p->c.aEdit);
   p->c.aEdit = 0;
   p->c.nEdit = 0;
   p->c.nEditAlloc = 0;
 
-  /* Move aFrom over to aTo in preparation for the next step */
-  free(p->c.aTo);
-  if( blob_buffer(&p->blobTo) ) blob_reset(&p->blobTo);
-  p->blobTo = *pParent;
-  blob_zero(pParent);
-  p->c.aTo = p->c.aFrom;
-  p->c.nTo = p->c.nFrom;
+  /* Clear out the from file */
+  free(p->c.aFrom);
+  blob_zero(pParent);
 
   /* Return no errors */
   return 0;
 }
 
@@ -706,75 +671,55 @@
     printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
   }
 }
 
 /*
-** Create an annotation string based on the manifest id.
-*/
-static char *annotation_label(int mid, int webLabel){
-  char *z;
-  z = db_text("?",
-    "SELECT"
-    "   substr(blob.uuid,1,10) ||"
-    "   ' ' || date(event.mtime) ||"
-    "   ' (' || substr(event.user || '        ',1,9) || ')'"
-    "  FROM blob, event"
-    " WHERE blob.rid=%d"
-    "   AND event.objid=%d"
-    "   AND event.type='ci'",
-    mid, mid
-  );
-  return z;
-}
-
-/*
 ** Compute a complete annotation on a file.  The file is identified
 ** by its filename number (filename.fnid) and the baseline in which
 ** it was checked in (mlink.mid).
 */
 static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){
   Blob toAnnotate;     /* Text of the final version of the file */
   Blob step;           /* Text of previous revision */
-  int rid;
-  int fromid;
-  char *zLabel;
-  int i;
+  int rid;             /* Artifact ID of the file being annotated */
+  char *zLabel;        /* Label to apply to a line */
+  Stmt q;              /* Query returning all ancestor versions */
 
   /* Initialize the annotation */
   rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
   if( rid==0 ){
-    fossil_panic("no changes to file #%d in manifest #%d", fnid, mid);
+    fossil_panic("file #%d is unchanged in manifest #%d", fnid, mid);
   }
   if( !content_get(rid, &toAnnotate) ){
     fossil_panic("unable to retrieve content of artifact #%d", rid);
   }
-  annotation_start(p, &toAnnotate);
-  fromid = db_int(0,"SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
-  zLabel = annotation_label(mid, webLabel);
-  if( fromid ){
-    content_get(fromid, &step);
-    annotation_step(p, &step, zLabel);
-  }
+  db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
+  compute_ancestors(mid, 1000000000);
+  annotation_start(p, &toAnnotate);
 
-  /* Step back through the change history */
-  while( fromid>0 ){
-    mid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
-    if( mid==0 ) break;
-    rid = db_int(-1, "SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
-    if( rid<0 ) continue;
-    zLabel = annotation_label(mid, webLabel);
-    if( rid==0 ) break;
-    fromid = rid;
-    content_get(fromid, &step);
+  db_prepare(&q,
+    "SELECT mlink.fid, blob.uuid, date(event.mtime), event.user "
+    "  FROM mlink, blob, event"
+    " WHERE mlink.fnid=%d"
+    "   AND mlink.mid IN ok"
+    "   AND blob.rid=mlink.mid"
+    "   AND event.objid=mlink.mid"
+    " ORDER BY event.mtime DESC",
+    fnid
+  );
+  while( db_step(&q)==SQLITE_ROW ){
+    int pid = db_column_int(&q, 0);
+    const char *zUuid = db_column_text(&q, 1);
+    const char *zDate = db_column_text(&q, 2);
+    const char *zUser = db_column_text(&q, 3);
+    zLabel = mprintf("<a href='%s/info/%s'>%.10s</a> %s %9.9s",
+                     g.zBaseURL, zUuid, zUuid, zDate, zUser);
+    content_get(pid, &step);
     annotation_step(p, &step, zLabel);
+    blob_reset(&step);
   }
-
-  /* Any unannotated lines are due to the last revision seen.
-  */
-  for(i=0; i<p->nOrig; i++){
-    if( p->aOrig[i].zSrc==0 ) p->aOrig[i].zSrc = zLabel;
-  }
+  db_finalize(&q);
 }
 
 /*
 ** WEBPAGE: annotate
 **