Fossil

Check-in [bd36723c]
Login

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

Overview
Comment:Add --limit and --log options to the "annotate" command and corresponding query parameters to the web annotation interface. Part of the investigation of ticket [f0f9aff371f26b4]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: bd36723c3d771114390e8791924825e4d57be6a8
User & Date: drh 2011-05-06 14:36:51
Context
2011-05-06
16:32
Improvements to the annotation algorithm so that if a line changes from X to Y then back to X, the annotation shows the second X not the first. Ticket [f0f9aff371f26] check-in: 73c38a3a user: drh tags: trunk
14:36
Add --limit and --log options to the "annotate" command and corresponding query parameters to the web annotation interface. Part of the investigation of ticket [f0f9aff371f26b4] check-in: bd36723c user: drh tags: trunk
13:13
Fix a bug in the sub-repository detection logic. Ticket [b733bba0b7319ef2]. check-in: e56a4ec3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/diff.c.

631
632
633
634
635
636
637


638
639
640
641
642
643
644
...
737
738
739
740
741
742
743
744






745
746
747
748
749
750
751
...
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
...
799
800
801
802
803
804
805

806
807
808
809
810
811
812

813
814
815
816
817











818
819
820
821
822
823
824
...
827
828
829
830
831
832
833




834
835
836
837
838
839
840
841
842



843




844
845
846
847
848
849
850
...
855
856
857
858
859
860
861
862






863
864
865
866
  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 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
** will release it when it is finished with it.
*/
................................................................................
}

/*
** 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;             /* 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 */
................................................................................
    "SELECT mlink.fid, blob.uuid, date(event.mtime), "
    "       coalesce(event.euser,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);
    if( webLabel ){
................................................................................
      zLabel = mprintf(
          "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 
          g.zTop, zUuid, zUuid, zDate, zUser
      );
    }else{
      zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
    }



    content_get(pid, &step);
    annotation_step(p, &step, zLabel);
    blob_reset(&step);
  }
  db_finalize(&q);
}

................................................................................
**    checkin=ID          The manifest ID at which to start the annotation
**    filename=FILENAME   The filename.
*/
void annotation_page(void){
  int mid;
  int fnid;
  int i;

  Annotator ann;

  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }
  mid = name_to_rid(PD("checkin","0"));
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }

  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");
  annotate_file(&ann, fnid, mid, g.okHistory);











  @ <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();
................................................................................
/*
** COMMAND: annotate
**
** %fossil annotate FILENAME
**
** Output the text of a file with markings to show when each line of
** the file was last modified.




*/
void annotate_cmd(void){
  int fnid;         /* Filename ID */
  int fid;          /* File instance ID */
  int mid;          /* Manifest where file was checked in */
  Blob treename;    /* FILENAME translated to canonical form */
  char *zFilename;  /* Cannonical filename */
  Annotator ann;    /* The annotation of the file */
  int i;            /* Loop counter */








  db_must_be_within_tree();
  if (g.argc<3) {
    usage("FILENAME");
  }
  file_tree_name(g.argv[2], &treename, 1);
  zFilename = blob_str(&treename);
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
................................................................................
  if( fid==0 ){
    fossil_fatal("not part of current checkout: %s", zFilename);
  }
  mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
  if( mid==0 ){
    fossil_panic("unable to find manifest");
  }
  annotate_file(&ann, fnid, mid, 0);






  for(i=0; i<ann.nOrig; i++){
    printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
  }
}







>
>







 







|
>
>
>
>
>
>







 







|
>
|
>







 







>
>
>







 







>







>




|
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>









>
>
>

>
>
>
>







 







|
>
>
>
>
>
>




631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
...
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
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
...
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
...
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
  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 nOrig;        /* Number of elements in aOrig[] */
  int nNoSrc;       /* Number of entries where aOrig[].zSrc==NULL */
  int nVers;        /* Number of versions analyzed */
  char **azVers;    /* Names of versions analyzed */
};

/*
** Initialize the annotation process by specifying the file that is
** to be annotated.  The annotator takes control of the input Blob and
** will release it when it is finished with it.
*/
................................................................................
}

/*
** 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,        /* The annotator */
  int fnid,            /* The name of the file to be annotated */
  int mid,             /* The specific version of the file for this step */
  int webLabel,        /* Use web-style annotations if true */
  int iLimit           /* Limit the number of levels if greater than zero */
){
  Blob toAnnotate;     /* Text of the final version of the file */
  Blob step;           /* Text of previous revision */
  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 */
................................................................................
    "SELECT mlink.fid, blob.uuid, date(event.mtime), "
    "       coalesce(event.euser,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"
    " LIMIT %d",
    fnid,
    iLimit>0 ? iLimit : 10000000
  );
  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);
    if( webLabel ){
................................................................................
      zLabel = mprintf(
          "<a href='%s/info/%s' target='infowindow'>%.10s</a> %s %9.9s", 
          g.zTop, zUuid, zUuid, zDate, zUser
      );
    }else{
      zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser);
    }
    p->nVers++;
    p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) );
    p->azVers[p->nVers-1] = zLabel;
    content_get(pid, &step);
    annotation_step(p, &step, zLabel);
    blob_reset(&step);
  }
  db_finalize(&q);
}

................................................................................
**    checkin=ID          The manifest ID at which to start the annotation
**    filename=FILENAME   The filename.
*/
void annotation_page(void){
  int mid;
  int fnid;
  int i;
  int iLimit;
  Annotator ann;

  login_check_credentials();
  if( !g.okRead ){ login_needed(); return; }
  mid = name_to_rid(PD("checkin","0"));
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename"));
  if( mid==0 || fnid==0 ){ fossil_redirect_home(); }
  iLimit = atoi(PD("limit","-1"));
  if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
    fossil_redirect_home();
  }
  style_header("File Annotation");
  annotate_file(&ann, fnid, mid, g.okHistory, iLimit);
  if( P("log") ){
    int i;
    @ <h2>Versions analyzed:</h2>
    @ <ol>
    for(i=0; i<ann.nVers; i++){
      @ <li><tt>%s(ann.azVers[i])</tt></li>
    }
    @ </ol>
    @ <hr>
    @ <h2>Annotation:</h2>
  }
  @ <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();
................................................................................
/*
** COMMAND: annotate
**
** %fossil annotate FILENAME
**
** Output the text of a file with markings to show when each line of
** the file was last modified.
**
** Options:
**   --limit N       Only look backwards in time by N versions
**   --log           List all versions analyzed
*/
void annotate_cmd(void){
  int fnid;         /* Filename ID */
  int fid;          /* File instance ID */
  int mid;          /* Manifest where file was checked in */
  Blob treename;    /* FILENAME translated to canonical form */
  char *zFilename;  /* Cannonical filename */
  Annotator ann;    /* The annotation of the file */
  int i;            /* Loop counter */
  const char *zLimit; /* The value to the --limit option */
  int iLimit;       /* How far back in time to look */
  int showLog;      /* True to show the log */

  zLimit = find_option("limit",0,1);
  if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
  iLimit = atoi(zLimit);
  showLog = find_option("log",0,0)!=0;
  db_must_be_within_tree();
  if (g.argc<3) {
    usage("FILENAME");
  }
  file_tree_name(g.argv[2], &treename, 1);
  zFilename = blob_str(&treename);
  fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
................................................................................
  if( fid==0 ){
    fossil_fatal("not part of current checkout: %s", zFilename);
  }
  mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
  if( mid==0 ){
    fossil_panic("unable to find manifest");
  }
  annotate_file(&ann, fnid, mid, 0, iLimit);
  if( showLog ){
    for(i=0; i<ann.nVers; i++){
      printf("version %3d: %s\n", i+1, ann.azVers[i]);
    }
    printf("---------------------------------------------------\n");
  }
  for(i=0; i<ann.nOrig; i++){
    printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z);
  }
}