Fossil SCM
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]
Commit
bd36723c3d771114390e8791924825e4d57be6a8
Parent
e56a4ec3ad16e33…
1 file changed
+48
-5
+48
-5
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -633,10 +633,12 @@ | ||
| 633 | 633 | int n; /* Number of bytes (omitting trailing space and \n) */ |
| 634 | 634 | const char *zSrc; /* Tag showing origin of this line */ |
| 635 | 635 | } *aOrig; |
| 636 | 636 | int nOrig; /* Number of elements in aOrig[] */ |
| 637 | 637 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 638 | + int nVers; /* Number of versions analyzed */ | |
| 639 | + char **azVers; /* Names of versions analyzed */ | |
| 638 | 640 | }; |
| 639 | 641 | |
| 640 | 642 | /* |
| 641 | 643 | ** Initialize the annotation process by specifying the file that is |
| 642 | 644 | ** to be annotated. The annotator takes control of the input Blob and |
| @@ -739,11 +741,17 @@ | ||
| 739 | 741 | /* |
| 740 | 742 | ** Compute a complete annotation on a file. The file is identified |
| 741 | 743 | ** by its filename number (filename.fnid) and the baseline in which |
| 742 | 744 | ** it was checked in (mlink.mid). |
| 743 | 745 | */ |
| 744 | -static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){ | |
| 746 | +static void annotate_file( | |
| 747 | + Annotator *p, /* The annotator */ | |
| 748 | + int fnid, /* The name of the file to be annotated */ | |
| 749 | + int mid, /* The specific version of the file for this step */ | |
| 750 | + int webLabel, /* Use web-style annotations if true */ | |
| 751 | + int iLimit /* Limit the number of levels if greater than zero */ | |
| 752 | +){ | |
| 745 | 753 | Blob toAnnotate; /* Text of the final version of the file */ |
| 746 | 754 | Blob step; /* Text of previous revision */ |
| 747 | 755 | int rid; /* Artifact ID of the file being annotated */ |
| 748 | 756 | char *zLabel; /* Label to apply to a line */ |
| 749 | 757 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -766,12 +774,14 @@ | ||
| 766 | 774 | " FROM mlink, blob, event" |
| 767 | 775 | " WHERE mlink.fnid=%d" |
| 768 | 776 | " AND mlink.mid IN ok" |
| 769 | 777 | " AND blob.rid=mlink.mid" |
| 770 | 778 | " AND event.objid=mlink.mid" |
| 771 | - " ORDER BY event.mtime DESC", | |
| 772 | - fnid | |
| 779 | + " ORDER BY event.mtime DESC" | |
| 780 | + " LIMIT %d", | |
| 781 | + fnid, | |
| 782 | + iLimit>0 ? iLimit : 10000000 | |
| 773 | 783 | ); |
| 774 | 784 | while( db_step(&q)==SQLITE_ROW ){ |
| 775 | 785 | int pid = db_column_int(&q, 0); |
| 776 | 786 | const char *zUuid = db_column_text(&q, 1); |
| 777 | 787 | const char *zDate = db_column_text(&q, 2); |
| @@ -782,10 +792,13 @@ | ||
| 782 | 792 | g.zTop, zUuid, zUuid, zDate, zUser |
| 783 | 793 | ); |
| 784 | 794 | }else{ |
| 785 | 795 | zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser); |
| 786 | 796 | } |
| 797 | + p->nVers++; | |
| 798 | + p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); | |
| 799 | + p->azVers[p->nVers-1] = zLabel; | |
| 787 | 800 | content_get(pid, &step); |
| 788 | 801 | annotation_step(p, &step, zLabel); |
| 789 | 802 | blob_reset(&step); |
| 790 | 803 | } |
| 791 | 804 | db_finalize(&q); |
| @@ -801,22 +814,35 @@ | ||
| 801 | 814 | */ |
| 802 | 815 | void annotation_page(void){ |
| 803 | 816 | int mid; |
| 804 | 817 | int fnid; |
| 805 | 818 | int i; |
| 819 | + int iLimit; | |
| 806 | 820 | Annotator ann; |
| 807 | 821 | |
| 808 | 822 | login_check_credentials(); |
| 809 | 823 | if( !g.okRead ){ login_needed(); return; } |
| 810 | 824 | mid = name_to_rid(PD("checkin","0")); |
| 811 | 825 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename")); |
| 812 | 826 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 827 | + iLimit = atoi(PD("limit","-1")); | |
| 813 | 828 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 814 | 829 | fossil_redirect_home(); |
| 815 | 830 | } |
| 816 | 831 | style_header("File Annotation"); |
| 817 | - annotate_file(&ann, fnid, mid, g.okHistory); | |
| 832 | + annotate_file(&ann, fnid, mid, g.okHistory, iLimit); | |
| 833 | + if( P("log") ){ | |
| 834 | + int i; | |
| 835 | + @ <h2>Versions analyzed:</h2> | |
| 836 | + @ <ol> | |
| 837 | + for(i=0; i<ann.nVers; i++){ | |
| 838 | + @ <li><tt>%s(ann.azVers[i])</tt></li> | |
| 839 | + } | |
| 840 | + @ </ol> | |
| 841 | + @ <hr> | |
| 842 | + @ <h2>Annotation:</h2> | |
| 843 | + } | |
| 818 | 844 | @ <pre> |
| 819 | 845 | for(i=0; i<ann.nOrig; i++){ |
| 820 | 846 | ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0; |
| 821 | 847 | @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z) |
| 822 | 848 | } |
| @@ -829,20 +855,31 @@ | ||
| 829 | 855 | ** |
| 830 | 856 | ** %fossil annotate FILENAME |
| 831 | 857 | ** |
| 832 | 858 | ** Output the text of a file with markings to show when each line of |
| 833 | 859 | ** the file was last modified. |
| 860 | +** | |
| 861 | +** Options: | |
| 862 | +** --limit N Only look backwards in time by N versions | |
| 863 | +** --log List all versions analyzed | |
| 834 | 864 | */ |
| 835 | 865 | void annotate_cmd(void){ |
| 836 | 866 | int fnid; /* Filename ID */ |
| 837 | 867 | int fid; /* File instance ID */ |
| 838 | 868 | int mid; /* Manifest where file was checked in */ |
| 839 | 869 | Blob treename; /* FILENAME translated to canonical form */ |
| 840 | 870 | char *zFilename; /* Cannonical filename */ |
| 841 | 871 | Annotator ann; /* The annotation of the file */ |
| 842 | 872 | int i; /* Loop counter */ |
| 873 | + const char *zLimit; /* The value to the --limit option */ | |
| 874 | + int iLimit; /* How far back in time to look */ | |
| 875 | + int showLog; /* True to show the log */ | |
| 843 | 876 | |
| 877 | + zLimit = find_option("limit",0,1); | |
| 878 | + if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; | |
| 879 | + iLimit = atoi(zLimit); | |
| 880 | + showLog = find_option("log",0,0)!=0; | |
| 844 | 881 | db_must_be_within_tree(); |
| 845 | 882 | if (g.argc<3) { |
| 846 | 883 | usage("FILENAME"); |
| 847 | 884 | } |
| 848 | 885 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -857,10 +894,16 @@ | ||
| 857 | 894 | } |
| 858 | 895 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 859 | 896 | if( mid==0 ){ |
| 860 | 897 | fossil_panic("unable to find manifest"); |
| 861 | 898 | } |
| 862 | - annotate_file(&ann, fnid, mid, 0); | |
| 899 | + annotate_file(&ann, fnid, mid, 0, iLimit); | |
| 900 | + if( showLog ){ | |
| 901 | + for(i=0; i<ann.nVers; i++){ | |
| 902 | + printf("version %3d: %s\n", i+1, ann.azVers[i]); | |
| 903 | + } | |
| 904 | + printf("---------------------------------------------------\n"); | |
| 905 | + } | |
| 863 | 906 | for(i=0; i<ann.nOrig; i++){ |
| 864 | 907 | printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 865 | 908 | } |
| 866 | 909 | } |
| 867 | 910 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -633,10 +633,12 @@ | |
| 633 | int n; /* Number of bytes (omitting trailing space and \n) */ |
| 634 | const char *zSrc; /* Tag showing origin of this line */ |
| 635 | } *aOrig; |
| 636 | int nOrig; /* Number of elements in aOrig[] */ |
| 637 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 638 | }; |
| 639 | |
| 640 | /* |
| 641 | ** Initialize the annotation process by specifying the file that is |
| 642 | ** to be annotated. The annotator takes control of the input Blob and |
| @@ -739,11 +741,17 @@ | |
| 739 | /* |
| 740 | ** Compute a complete annotation on a file. The file is identified |
| 741 | ** by its filename number (filename.fnid) and the baseline in which |
| 742 | ** it was checked in (mlink.mid). |
| 743 | */ |
| 744 | static void annotate_file(Annotator *p, int fnid, int mid, int webLabel){ |
| 745 | Blob toAnnotate; /* Text of the final version of the file */ |
| 746 | Blob step; /* Text of previous revision */ |
| 747 | int rid; /* Artifact ID of the file being annotated */ |
| 748 | char *zLabel; /* Label to apply to a line */ |
| 749 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -766,12 +774,14 @@ | |
| 766 | " FROM mlink, blob, event" |
| 767 | " WHERE mlink.fnid=%d" |
| 768 | " AND mlink.mid IN ok" |
| 769 | " AND blob.rid=mlink.mid" |
| 770 | " AND event.objid=mlink.mid" |
| 771 | " ORDER BY event.mtime DESC", |
| 772 | fnid |
| 773 | ); |
| 774 | while( db_step(&q)==SQLITE_ROW ){ |
| 775 | int pid = db_column_int(&q, 0); |
| 776 | const char *zUuid = db_column_text(&q, 1); |
| 777 | const char *zDate = db_column_text(&q, 2); |
| @@ -782,10 +792,13 @@ | |
| 782 | g.zTop, zUuid, zUuid, zDate, zUser |
| 783 | ); |
| 784 | }else{ |
| 785 | zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser); |
| 786 | } |
| 787 | content_get(pid, &step); |
| 788 | annotation_step(p, &step, zLabel); |
| 789 | blob_reset(&step); |
| 790 | } |
| 791 | db_finalize(&q); |
| @@ -801,22 +814,35 @@ | |
| 801 | */ |
| 802 | void annotation_page(void){ |
| 803 | int mid; |
| 804 | int fnid; |
| 805 | int i; |
| 806 | Annotator ann; |
| 807 | |
| 808 | login_check_credentials(); |
| 809 | if( !g.okRead ){ login_needed(); return; } |
| 810 | mid = name_to_rid(PD("checkin","0")); |
| 811 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename")); |
| 812 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 813 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 814 | fossil_redirect_home(); |
| 815 | } |
| 816 | style_header("File Annotation"); |
| 817 | annotate_file(&ann, fnid, mid, g.okHistory); |
| 818 | @ <pre> |
| 819 | for(i=0; i<ann.nOrig; i++){ |
| 820 | ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0; |
| 821 | @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z) |
| 822 | } |
| @@ -829,20 +855,31 @@ | |
| 829 | ** |
| 830 | ** %fossil annotate FILENAME |
| 831 | ** |
| 832 | ** Output the text of a file with markings to show when each line of |
| 833 | ** the file was last modified. |
| 834 | */ |
| 835 | void annotate_cmd(void){ |
| 836 | int fnid; /* Filename ID */ |
| 837 | int fid; /* File instance ID */ |
| 838 | int mid; /* Manifest where file was checked in */ |
| 839 | Blob treename; /* FILENAME translated to canonical form */ |
| 840 | char *zFilename; /* Cannonical filename */ |
| 841 | Annotator ann; /* The annotation of the file */ |
| 842 | int i; /* Loop counter */ |
| 843 | |
| 844 | db_must_be_within_tree(); |
| 845 | if (g.argc<3) { |
| 846 | usage("FILENAME"); |
| 847 | } |
| 848 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -857,10 +894,16 @@ | |
| 857 | } |
| 858 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 859 | if( mid==0 ){ |
| 860 | fossil_panic("unable to find manifest"); |
| 861 | } |
| 862 | annotate_file(&ann, fnid, mid, 0); |
| 863 | for(i=0; i<ann.nOrig; i++){ |
| 864 | printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 865 | } |
| 866 | } |
| 867 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -633,10 +633,12 @@ | |
| 633 | int n; /* Number of bytes (omitting trailing space and \n) */ |
| 634 | const char *zSrc; /* Tag showing origin of this line */ |
| 635 | } *aOrig; |
| 636 | int nOrig; /* Number of elements in aOrig[] */ |
| 637 | int nNoSrc; /* Number of entries where aOrig[].zSrc==NULL */ |
| 638 | int nVers; /* Number of versions analyzed */ |
| 639 | char **azVers; /* Names of versions analyzed */ |
| 640 | }; |
| 641 | |
| 642 | /* |
| 643 | ** Initialize the annotation process by specifying the file that is |
| 644 | ** to be annotated. The annotator takes control of the input Blob and |
| @@ -739,11 +741,17 @@ | |
| 741 | /* |
| 742 | ** Compute a complete annotation on a file. The file is identified |
| 743 | ** by its filename number (filename.fnid) and the baseline in which |
| 744 | ** it was checked in (mlink.mid). |
| 745 | */ |
| 746 | static void annotate_file( |
| 747 | Annotator *p, /* The annotator */ |
| 748 | int fnid, /* The name of the file to be annotated */ |
| 749 | int mid, /* The specific version of the file for this step */ |
| 750 | int webLabel, /* Use web-style annotations if true */ |
| 751 | int iLimit /* Limit the number of levels if greater than zero */ |
| 752 | ){ |
| 753 | Blob toAnnotate; /* Text of the final version of the file */ |
| 754 | Blob step; /* Text of previous revision */ |
| 755 | int rid; /* Artifact ID of the file being annotated */ |
| 756 | char *zLabel; /* Label to apply to a line */ |
| 757 | Stmt q; /* Query returning all ancestor versions */ |
| @@ -766,12 +774,14 @@ | |
| 774 | " FROM mlink, blob, event" |
| 775 | " WHERE mlink.fnid=%d" |
| 776 | " AND mlink.mid IN ok" |
| 777 | " AND blob.rid=mlink.mid" |
| 778 | " AND event.objid=mlink.mid" |
| 779 | " ORDER BY event.mtime DESC" |
| 780 | " LIMIT %d", |
| 781 | fnid, |
| 782 | iLimit>0 ? iLimit : 10000000 |
| 783 | ); |
| 784 | while( db_step(&q)==SQLITE_ROW ){ |
| 785 | int pid = db_column_int(&q, 0); |
| 786 | const char *zUuid = db_column_text(&q, 1); |
| 787 | const char *zDate = db_column_text(&q, 2); |
| @@ -782,10 +792,13 @@ | |
| 792 | g.zTop, zUuid, zUuid, zDate, zUser |
| 793 | ); |
| 794 | }else{ |
| 795 | zLabel = mprintf("%.10s %s %9.9s", zUuid, zDate, zUser); |
| 796 | } |
| 797 | p->nVers++; |
| 798 | p->azVers = fossil_realloc(p->azVers, p->nVers*sizeof(p->azVers[0]) ); |
| 799 | p->azVers[p->nVers-1] = zLabel; |
| 800 | content_get(pid, &step); |
| 801 | annotation_step(p, &step, zLabel); |
| 802 | blob_reset(&step); |
| 803 | } |
| 804 | db_finalize(&q); |
| @@ -801,22 +814,35 @@ | |
| 814 | */ |
| 815 | void annotation_page(void){ |
| 816 | int mid; |
| 817 | int fnid; |
| 818 | int i; |
| 819 | int iLimit; |
| 820 | Annotator ann; |
| 821 | |
| 822 | login_check_credentials(); |
| 823 | if( !g.okRead ){ login_needed(); return; } |
| 824 | mid = name_to_rid(PD("checkin","0")); |
| 825 | fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", P("filename")); |
| 826 | if( mid==0 || fnid==0 ){ fossil_redirect_home(); } |
| 827 | iLimit = atoi(PD("limit","-1")); |
| 828 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 829 | fossil_redirect_home(); |
| 830 | } |
| 831 | style_header("File Annotation"); |
| 832 | annotate_file(&ann, fnid, mid, g.okHistory, iLimit); |
| 833 | if( P("log") ){ |
| 834 | int i; |
| 835 | @ <h2>Versions analyzed:</h2> |
| 836 | @ <ol> |
| 837 | for(i=0; i<ann.nVers; i++){ |
| 838 | @ <li><tt>%s(ann.azVers[i])</tt></li> |
| 839 | } |
| 840 | @ </ol> |
| 841 | @ <hr> |
| 842 | @ <h2>Annotation:</h2> |
| 843 | } |
| 844 | @ <pre> |
| 845 | for(i=0; i<ann.nOrig; i++){ |
| 846 | ((char*)ann.aOrig[i].z)[ann.aOrig[i].n] = 0; |
| 847 | @ %s(ann.aOrig[i].zSrc): %h(ann.aOrig[i].z) |
| 848 | } |
| @@ -829,20 +855,31 @@ | |
| 855 | ** |
| 856 | ** %fossil annotate FILENAME |
| 857 | ** |
| 858 | ** Output the text of a file with markings to show when each line of |
| 859 | ** the file was last modified. |
| 860 | ** |
| 861 | ** Options: |
| 862 | ** --limit N Only look backwards in time by N versions |
| 863 | ** --log List all versions analyzed |
| 864 | */ |
| 865 | void annotate_cmd(void){ |
| 866 | int fnid; /* Filename ID */ |
| 867 | int fid; /* File instance ID */ |
| 868 | int mid; /* Manifest where file was checked in */ |
| 869 | Blob treename; /* FILENAME translated to canonical form */ |
| 870 | char *zFilename; /* Cannonical filename */ |
| 871 | Annotator ann; /* The annotation of the file */ |
| 872 | int i; /* Loop counter */ |
| 873 | const char *zLimit; /* The value to the --limit option */ |
| 874 | int iLimit; /* How far back in time to look */ |
| 875 | int showLog; /* True to show the log */ |
| 876 | |
| 877 | zLimit = find_option("limit",0,1); |
| 878 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 879 | iLimit = atoi(zLimit); |
| 880 | showLog = find_option("log",0,0)!=0; |
| 881 | db_must_be_within_tree(); |
| 882 | if (g.argc<3) { |
| 883 | usage("FILENAME"); |
| 884 | } |
| 885 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -857,10 +894,16 @@ | |
| 894 | } |
| 895 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 896 | if( mid==0 ){ |
| 897 | fossil_panic("unable to find manifest"); |
| 898 | } |
| 899 | annotate_file(&ann, fnid, mid, 0, iLimit); |
| 900 | if( showLog ){ |
| 901 | for(i=0; i<ann.nVers; i++){ |
| 902 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 903 | } |
| 904 | printf("---------------------------------------------------\n"); |
| 905 | } |
| 906 | for(i=0; i<ann.nOrig; i++){ |
| 907 | printf("%s: %.*s\n", ann.aOrig[i].zSrc, ann.aOrig[i].n, ann.aOrig[i].z); |
| 908 | } |
| 909 | } |
| 910 |