Fossil SCM

Add support for annotation in the web interface.

drh 2008-02-04 18:28 trunk
Commit eae7ddfa4e7a5ae90feda01d3c664c1b852d0e3f
2 files changed +99 +5 -1
+99
--- src/diff.c
+++ src/diff.c
@@ -704,5 +704,104 @@
704704
const char *zSrc = x.aOrig[i].zSrc;
705705
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
706706
printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
707707
}
708708
}
709
+
710
+/*
711
+** Create an annotation string based on the manifest id.
712
+*/
713
+static char *annotation_label(int mid, int webLabel){
714
+ char *z;
715
+ z = db_text("?",
716
+ "SELECT"
717
+ " substr(blob.uuid,1,10) ||"
718
+ " ' ' || date(event.mtime) ||"
719
+ " ' (' || substr(event.user || ' ',1,9) || ')'"
720
+ " FROM blob, event"
721
+ " WHERE blob.rid=%d"
722
+ " AND event.objid=%d"
723
+ " AND event.type='ci'",
724
+ mid, mid
725
+ );
726
+ return z;
727
+}
728
+
729
+/*
730
+** Compute a complete annotation on a file. The file is identified
731
+** by its filename number (filename.fnid) and the baseline in which
732
+** it was checked in (mlink.mid).
733
+*/
734
+static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){
735
+ Blob toAnnotate; /* Text of the final version of the file */
736
+ Blob step; /* Text of previous revision */
737
+ int rid;
738
+ int fromid;
739
+ char *zLabel;
740
+ int i;
741
+
742
+ /* Initialize the annotation */
743
+ rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
744
+ if( rid==0 ){
745
+ fossil_panic("no changes to file #%d in manifest #%d", fnid, mid);
746
+ }
747
+ if( !content_get(rid, &toAnnotate) ){
748
+ fossil_panic("unable to retrieve content of artifact #%d", rid);
749
+ }
750
+ annotation_start(p, &toAnnotate);
751
+ fromid = db_int(0,"SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
752
+ zLabel = annotation_label(mid, webLabel);
753
+ if( fromid ){
754
+ content_get(fromid, &step);
755
+ annotation_step(p, &step, zLabel);
756
+ }
757
+
758
+ /* Step back through the change history */
759
+ while( fromid>0 ){
760
+ mid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
761
+ if( mid==0 ) break;
762
+ rid = db_int(-1, "SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
763
+ if( rid<0 ) continue;
764
+ zLabel = annotation_label(mid, webLabel);
765
+ if( rid==0 ) break;
766
+ fromid = rid;
767
+ content_get(fromid, &step);
768
+ annotation_step(p, &step, zLabel);
769
+ }
770
+
771
+ /* Any unannotated lines are due to the last revision seen.
772
+ */
773
+ for(i=0; i<p->nOrig; i++){
774
+ if( p->aOrig[i].zSrc==0 ) p->aOrig[i].zSrc = zLabel;
775
+ }
776
+}
777
+
778
+/*
779
+** WEBPAGE: annotate
780
+**
781
+** Query parameters:
782
+**
783
+** mid=NUM The manifest ID at which to start the annotation
784
+** fnid=NUM The filename ID.
785
+*/
786
+void annotation_page(void){
787
+ int mid = atoi(PD("mid","0"));
788
+ int fnid = atoi(PD("fnid","0"));
789
+ int i;
790
+ Annotator ann;
791
+
792
+ login_check_credentials();
793
+ if( !g.okHistory ){ login_needed(); return; }
794
+ if( mid==0 || fnid==0 ){ cgi_redirect("index"); }
795
+ if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
796
+ cgi_redirect("index");
797
+ }
798
+ style_header("File Annotation");
799
+ annotate_file(&ann, fnid, mid, 1);
800
+ @ <pre>
801
+ for(i=0; i<ann.nOrig; i++){
802
+ ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
803
+ @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
804
+ }
805
+ @ </pre>
806
+ style_footer();
807
+}
709808
--- src/diff.c
+++ src/diff.c
@@ -704,5 +704,104 @@
704 const char *zSrc = x.aOrig[i].zSrc;
705 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
706 printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
707 }
708 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
709
--- src/diff.c
+++ src/diff.c
@@ -704,5 +704,104 @@
704 const char *zSrc = x.aOrig[i].zSrc;
705 if( zSrc==0 ) zSrc = g.argv[g.argc-1];
706 printf("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
707 }
708 }
709
710 /*
711 ** Create an annotation string based on the manifest id.
712 */
713 static char *annotation_label(int mid, int webLabel){
714 char *z;
715 z = db_text("?",
716 "SELECT"
717 " substr(blob.uuid,1,10) ||"
718 " ' ' || date(event.mtime) ||"
719 " ' (' || substr(event.user || ' ',1,9) || ')'"
720 " FROM blob, event"
721 " WHERE blob.rid=%d"
722 " AND event.objid=%d"
723 " AND event.type='ci'",
724 mid, mid
725 );
726 return z;
727 }
728
729 /*
730 ** Compute a complete annotation on a file. The file is identified
731 ** by its filename number (filename.fnid) and the baseline in which
732 ** it was checked in (mlink.mid).
733 */
734 static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){
735 Blob toAnnotate; /* Text of the final version of the file */
736 Blob step; /* Text of previous revision */
737 int rid;
738 int fromid;
739 char *zLabel;
740 int i;
741
742 /* Initialize the annotation */
743 rid = db_int(0, "SELECT fid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
744 if( rid==0 ){
745 fossil_panic("no changes to file #%d in manifest #%d", fnid, mid);
746 }
747 if( !content_get(rid, &toAnnotate) ){
748 fossil_panic("unable to retrieve content of artifact #%d", rid);
749 }
750 annotation_start(p, &toAnnotate);
751 fromid = db_int(0,"SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
752 zLabel = annotation_label(mid, webLabel);
753 if( fromid ){
754 content_get(fromid, &step);
755 annotation_step(p, &step, zLabel);
756 }
757
758 /* Step back through the change history */
759 while( fromid>0 ){
760 mid = db_int(0, "SELECT pid FROM plink WHERE cid=%d AND isprim", mid);
761 if( mid==0 ) break;
762 rid = db_int(-1, "SELECT pid FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid);
763 if( rid<0 ) continue;
764 zLabel = annotation_label(mid, webLabel);
765 if( rid==0 ) break;
766 fromid = rid;
767 content_get(fromid, &step);
768 annotation_step(p, &step, zLabel);
769 }
770
771 /* Any unannotated lines are due to the last revision seen.
772 */
773 for(i=0; i<p->nOrig; i++){
774 if( p->aOrig[i].zSrc==0 ) p->aOrig[i].zSrc = zLabel;
775 }
776 }
777
778 /*
779 ** WEBPAGE: annotate
780 **
781 ** Query parameters:
782 **
783 ** mid=NUM The manifest ID at which to start the annotation
784 ** fnid=NUM The filename ID.
785 */
786 void annotation_page(void){
787 int mid = atoi(PD("mid","0"));
788 int fnid = atoi(PD("fnid","0"));
789 int i;
790 Annotator ann;
791
792 login_check_credentials();
793 if( !g.okHistory ){ login_needed(); return; }
794 if( mid==0 || fnid==0 ){ cgi_redirect("index"); }
795 if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
796 cgi_redirect("index");
797 }
798 style_header("File Annotation");
799 annotate_file(&ann, fnid, mid, 1);
800 @ <pre>
801 for(i=0; i<ann.nOrig; i++){
802 ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0;
803 @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z)
804 }
805 @ </pre>
806 style_footer();
807 }
808
+5 -1
--- src/info.c
+++ src/info.c
@@ -455,11 +455,11 @@
455455
zFilename = PD("name","");
456456
db_prepare(&q,
457457
"SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
458458
" coalesce(event.ecomment, event.comment),"
459459
" coalesce(event.euser, event.user),"
460
- " mlink.pid, mlink.fid"
460
+ " mlink.pid, mlink.fid, mlink.mid, mlink.fnid"
461461
" FROM mlink, blob a, blob b, event"
462462
" WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
463463
" AND a.rid=mlink.mid"
464464
" AND b.rid=mlink.fid"
465465
" AND event.objid=mlink.mid"
@@ -474,10 +474,12 @@
474474
const char *zDate = db_column_text(&q, 2);
475475
const char *zCom = db_column_text(&q, 3);
476476
const char *zUser = db_column_text(&q, 4);
477477
int fpid = db_column_int(&q, 5);
478478
int frid = db_column_int(&q, 6);
479
+ int mid = db_column_int(&q, 7);
480
+ int fnid = db_column_int(&q, 8);
479481
if( memcmp(zDate, zPrevDate, 10) ){
480482
sprintf(zPrevDate, "%.10s", zDate);
481483
@ <tr><td colspan=3>
482484
@ <table cellpadding=2 border=0>
483485
@ <tr><td bgcolor="#a0b5f4" class="border1">
@@ -495,10 +497,12 @@
495497
@ Id: %s(zUuid)/%d(frid)
496498
@ <a href="%s(g.zBaseURL)/fview/%d(frid)">[view]</a>
497499
if( fpid ){
498500
@ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&amp;v2=%d(frid)">[diff]</a>
499501
}
502
+ @ <a href="%s(g.zBaseURL)/annotate?mid=%d(mid)&amp;fnid=%d(fnid)">
503
+ @ [annotate]</a>
500504
@ </td>
501505
}
502506
db_finalize(&q);
503507
@ </table>
504508
style_footer();
505509
--- src/info.c
+++ src/info.c
@@ -455,11 +455,11 @@
455 zFilename = PD("name","");
456 db_prepare(&q,
457 "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
458 " coalesce(event.ecomment, event.comment),"
459 " coalesce(event.euser, event.user),"
460 " mlink.pid, mlink.fid"
461 " FROM mlink, blob a, blob b, event"
462 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
463 " AND a.rid=mlink.mid"
464 " AND b.rid=mlink.fid"
465 " AND event.objid=mlink.mid"
@@ -474,10 +474,12 @@
474 const char *zDate = db_column_text(&q, 2);
475 const char *zCom = db_column_text(&q, 3);
476 const char *zUser = db_column_text(&q, 4);
477 int fpid = db_column_int(&q, 5);
478 int frid = db_column_int(&q, 6);
 
 
479 if( memcmp(zDate, zPrevDate, 10) ){
480 sprintf(zPrevDate, "%.10s", zDate);
481 @ <tr><td colspan=3>
482 @ <table cellpadding=2 border=0>
483 @ <tr><td bgcolor="#a0b5f4" class="border1">
@@ -495,10 +497,12 @@
495 @ Id: %s(zUuid)/%d(frid)
496 @ <a href="%s(g.zBaseURL)/fview/%d(frid)">[view]</a>
497 if( fpid ){
498 @ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&amp;v2=%d(frid)">[diff]</a>
499 }
 
 
500 @ </td>
501 }
502 db_finalize(&q);
503 @ </table>
504 style_footer();
505
--- src/info.c
+++ src/info.c
@@ -455,11 +455,11 @@
455 zFilename = PD("name","");
456 db_prepare(&q,
457 "SELECT a.uuid, substr(b.uuid,1,10), datetime(event.mtime,'localtime'),"
458 " coalesce(event.ecomment, event.comment),"
459 " coalesce(event.euser, event.user),"
460 " mlink.pid, mlink.fid, mlink.mid, mlink.fnid"
461 " FROM mlink, blob a, blob b, event"
462 " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)"
463 " AND a.rid=mlink.mid"
464 " AND b.rid=mlink.fid"
465 " AND event.objid=mlink.mid"
@@ -474,10 +474,12 @@
474 const char *zDate = db_column_text(&q, 2);
475 const char *zCom = db_column_text(&q, 3);
476 const char *zUser = db_column_text(&q, 4);
477 int fpid = db_column_int(&q, 5);
478 int frid = db_column_int(&q, 6);
479 int mid = db_column_int(&q, 7);
480 int fnid = db_column_int(&q, 8);
481 if( memcmp(zDate, zPrevDate, 10) ){
482 sprintf(zPrevDate, "%.10s", zDate);
483 @ <tr><td colspan=3>
484 @ <table cellpadding=2 border=0>
485 @ <tr><td bgcolor="#a0b5f4" class="border1">
@@ -495,10 +497,12 @@
497 @ Id: %s(zUuid)/%d(frid)
498 @ <a href="%s(g.zBaseURL)/fview/%d(frid)">[view]</a>
499 if( fpid ){
500 @ <a href="%s(g.zBaseURL)/fdiff?v1=%d(fpid)&amp;v2=%d(frid)">[diff]</a>
501 }
502 @ <a href="%s(g.zBaseURL)/annotate?mid=%d(mid)&amp;fnid=%d(fnid)">
503 @ [annotate]</a>
504 @ </td>
505 }
506 db_finalize(&q);
507 @ </table>
508 style_footer();
509

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button