Fossil

Check-in [eae7ddfa4e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add support for annotation in the web interface.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: eae7ddfa4e7a5ae90feda01d3c664c1b852d0e3f
User & Date: drh 2008-02-04 18:28:55.000
Context
2008-02-04
19:07
On the printf extension converters (ex: %T, %w) the "alternate form flag" (ex: %#T, %#w) means first read an integer from the argument list and then only process that number of characters from the string or blob that is read next from the argument list. ... (check-in: 8c3ec00311 user: drh tags: trunk)
18:28
Add support for annotation in the web interface. ... (check-in: eae7ddfa4e user: drh tags: trunk)
17:34
Allow manifests with zero files. This fixes a problem in which some files do not appear in the filename table. ... (check-in: c8da83ca36 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/diff.c.
702
703
704
705
706
707
708



































































































  }
  for(i=0; i<x.nOrig; i++){
    const char *zSrc = x.aOrig[i].zSrc;
    if( zSrc==0 ) zSrc = g.argv[g.argc-1];
    printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
  }
}










































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  }
  for(i=0; i<x.nOrig; i++){
    const char *zSrc = x.aOrig[i].zSrc;
    if( zSrc==0 ) zSrc = g.argv[g.argc-1];
    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;

  /* 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);
  }
  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);
  }

  /* 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);
    annotation_step(p, &step, zLabel);
  }

  /* 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;
  }
}

/*
** WEBPAGE: annotate
**
** Query parameters:
**
**    mid=NUM      The manifest ID at which to start the annotation
**    fnid=NUM     The filename ID.
*/
void annotation_page(void){
  int mid = atoi(PD("mid","0"));
  int fnid = atoi(PD("fnid","0"));
  int i;
  Annotator ann;

  login_check_credentials();
  if( !g.okHistory ){ login_needed(); return; }
  if( mid==0 || fnid==0 ){ cgi_redirect("index"); }
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    cgi_redirect("index");
  }
  style_header("File Annotation");
  annotate_file(&ann, fnid, mid, 1);
  @ <pre>
  for(i=0; i<ann.nOrig; i++){
    ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
    @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
  }
  @ </pre>
  style_footer();
}
Changes to src/info.c.
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478


479
480
481
482
483
484
485

  zPrevDate[0] = 0;
  zFilename = PD("name","");
  db_prepare(&q,
    "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
    "       coalesce(event.ecomment, event.comment),"
    "       coalesce(event.euser, event.user),"
    "       mlink.pid, mlink.fid"
    "  FROM mlink, blob a, blob b, event"
    " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
    "   AND a.rid=mlink.mid"
    "   AND b.rid=mlink.fid"
    "   AND event.objid=mlink.mid"
    " ORDER BY event.mtime DESC",
    zFilename
  );
  @ <h2>History of %h(zFilename)</h2>
  @ <table cellspacing=0 border=0 cellpadding=0>
  while( db_step(&q)==SQLITE_ROW ){
    const char *zVers = db_column_text(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zCom = db_column_text(&q, 3);
    const char *zUser = db_column_text(&q, 4);
    int fpid = db_column_int(&q, 5);
    int frid = db_column_int(&q, 6);


    if( memcmp(zDate, zPrevDate, 10) ){
      sprintf(zPrevDate, "%.10s", zDate);
      @ <tr><td colspan=3>
      @ <table cellpadding=2 border=0>
      @ <tr><td bgcolor="#a0b5f4" class="border1">
      @ <table cellpadding=2 cellspacing=0 border=0><tr>
      @ <td bgcolor="#d0d9f4" class="bkgnd1">%s(zPrevDate)</td>







|


















>
>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487

  zPrevDate[0] = 0;
  zFilename = PD("name","");
  db_prepare(&q,
    "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
    "       coalesce(event.ecomment, event.comment),"
    "       coalesce(event.euser, event.user),"
    "       mlink.pid, mlink.fid, mlink.mid, mlink.fnid"
    "  FROM mlink, blob a, blob b, event"
    " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
    "   AND a.rid=mlink.mid"
    "   AND b.rid=mlink.fid"
    "   AND event.objid=mlink.mid"
    " ORDER BY event.mtime DESC",
    zFilename
  );
  @ <h2>History of %h(zFilename)</h2>
  @ <table cellspacing=0 border=0 cellpadding=0>
  while( db_step(&q)==SQLITE_ROW ){
    const char *zVers = db_column_text(&q, 0);
    const char *zUuid = db_column_text(&q, 1);
    const char *zDate = db_column_text(&q, 2);
    const char *zCom = db_column_text(&q, 3);
    const char *zUser = db_column_text(&q, 4);
    int fpid = db_column_int(&q, 5);
    int frid = db_column_int(&q, 6);
    int mid = db_column_int(&q, 7);
    int fnid = db_column_int(&q, 8);
    if( memcmp(zDate, zPrevDate, 10) ){
      sprintf(zPrevDate, "%.10s", zDate);
      @ <tr><td colspan=3>
      @ <table cellpadding=2 border=0>
      @ <tr><td bgcolor="#a0b5f4" class="border1">
      @ <table cellpadding=2 cellspacing=0 border=0><tr>
      @ <td bgcolor="#d0d9f4" class="bkgnd1">%s(zPrevDate)</td>
493
494
495
496
497
498
499


500
501
502
503
504
505
506
    hyperlink_to_uuid(zVers);
    @ %h(zCom) (By: %h(zUser))
    @ Id: %s(zUuid)/%d(frid)
    @ <a href="%s(g.zBaseURL)/fview/%d(frid)">[view]</a>
    if( fpid ){
      @ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&amp;v2=%d(frid)">[diff]</a>
    }


    @ </td>
  }
  db_finalize(&q);
  @ </table>
  style_footer();
}








>
>







495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
    hyperlink_to_uuid(zVers);
    @ %h(zCom) (By: %h(zUser))
    @ Id: %s(zUuid)/%d(frid)
    @ <a href="%s(g.zBaseURL)/fview/%d(frid)">[view]</a>
    if( fpid ){
      @ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&amp;v2=%d(frid)">[diff]</a>
    }
    @ <a href="%s(g.zBaseURL)/annotate?mid=%d(mid)&amp;fnid=%d(fnid)">
    @ [annotate]</a>
    @ </td>
  }
  db_finalize(&q);
  @ </table>
  style_footer();
}