Fossil SCM
Pull the latest changes from trunk into windows-i18n.
Commit
f25b6c00c8c77799a687a9953034f1ff51d593d1
Parent
b33032ae401a8d6…
8 files changed
+26
-11
+19
-6
+19
-6
+31
-8
+31
-8
+34
-14
+1
-1
+1
-1
+26
-11
| --- src/descendants.c | ||
| +++ src/descendants.c | ||
| @@ -159,60 +159,75 @@ | ||
| 159 | 159 | ** the "ok" table. |
| 160 | 160 | */ |
| 161 | 161 | void compute_ancestors(int rid, int N){ |
| 162 | 162 | Bag seen; |
| 163 | 163 | PQueue queue; |
| 164 | + Stmt ins; | |
| 165 | + Stmt q; | |
| 164 | 166 | bag_init(&seen); |
| 165 | 167 | pqueue_init(&queue); |
| 166 | 168 | bag_insert(&seen, rid); |
| 167 | 169 | pqueue_insert(&queue, rid, 0.0, 0); |
| 170 | + db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); | |
| 171 | + db_prepare(&q, | |
| 172 | + "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" | |
| 173 | + " WHERE a.cid=:rid" | |
| 174 | + ); | |
| 168 | 175 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 169 | - Stmt q; | |
| 170 | - db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid); | |
| 171 | - db_prepare(&q, | |
| 172 | - "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" | |
| 173 | - " WHERE a.cid=%d", rid | |
| 174 | - ); | |
| 176 | + db_bind_int(&ins, ":rid", rid); | |
| 177 | + db_step(&ins); | |
| 178 | + db_reset(&ins); | |
| 179 | + db_bind_int(&q, ":rid", rid); | |
| 175 | 180 | while( db_step(&q)==SQLITE_ROW ){ |
| 176 | 181 | int pid = db_column_int(&q, 0); |
| 177 | 182 | double mtime = db_column_double(&q, 1); |
| 178 | 183 | if( bag_insert(&seen, pid) ){ |
| 179 | 184 | pqueue_insert(&queue, pid, -mtime, 0); |
| 180 | 185 | } |
| 181 | 186 | } |
| 182 | - db_finalize(&q); | |
| 187 | + db_reset(&q); | |
| 183 | 188 | } |
| 184 | 189 | bag_clear(&seen); |
| 185 | 190 | pqueue_clear(&queue); |
| 191 | + db_finalize(&ins); | |
| 192 | + db_finalize(&q); | |
| 186 | 193 | } |
| 187 | 194 | |
| 188 | 195 | /* |
| 189 | 196 | ** Load the record ID rid and up to N-1 closest descendants into |
| 190 | 197 | ** the "ok" table. |
| 191 | 198 | */ |
| 192 | 199 | void compute_descendants(int rid, int N){ |
| 193 | 200 | Bag seen; |
| 194 | 201 | PQueue queue; |
| 202 | + Stmt ins; | |
| 203 | + Stmt q; | |
| 204 | + | |
| 195 | 205 | bag_init(&seen); |
| 196 | 206 | pqueue_init(&queue); |
| 197 | 207 | bag_insert(&seen, rid); |
| 198 | 208 | pqueue_insert(&queue, rid, 0.0, 0); |
| 209 | + db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); | |
| 210 | + db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid"); | |
| 199 | 211 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 200 | - Stmt q; | |
| 201 | - db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid); | |
| 202 | - db_prepare(&q,"SELECT cid, mtime FROM plink WHERE pid=%d", rid); | |
| 212 | + db_bind_int(&ins, ":rid", rid); | |
| 213 | + db_step(&ins); | |
| 214 | + db_reset(&ins); | |
| 215 | + db_bind_int(&q, ":rid", rid); | |
| 203 | 216 | while( db_step(&q)==SQLITE_ROW ){ |
| 204 | 217 | int pid = db_column_int(&q, 0); |
| 205 | 218 | double mtime = db_column_double(&q, 1); |
| 206 | 219 | if( bag_insert(&seen, pid) ){ |
| 207 | 220 | pqueue_insert(&queue, pid, mtime, 0); |
| 208 | 221 | } |
| 209 | 222 | } |
| 210 | - db_finalize(&q); | |
| 223 | + db_reset(&q); | |
| 211 | 224 | } |
| 212 | 225 | bag_clear(&seen); |
| 213 | 226 | pqueue_clear(&queue); |
| 227 | + db_finalize(&ins); | |
| 228 | + db_finalize(&q); | |
| 214 | 229 | } |
| 215 | 230 | |
| 216 | 231 | /* |
| 217 | 232 | ** COMMAND: descendants |
| 218 | 233 | ** |
| 219 | 234 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -159,60 +159,75 @@ | |
| 159 | ** the "ok" table. |
| 160 | */ |
| 161 | void compute_ancestors(int rid, int N){ |
| 162 | Bag seen; |
| 163 | PQueue queue; |
| 164 | bag_init(&seen); |
| 165 | pqueue_init(&queue); |
| 166 | bag_insert(&seen, rid); |
| 167 | pqueue_insert(&queue, rid, 0.0, 0); |
| 168 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 169 | Stmt q; |
| 170 | db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid); |
| 171 | db_prepare(&q, |
| 172 | "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" |
| 173 | " WHERE a.cid=%d", rid |
| 174 | ); |
| 175 | while( db_step(&q)==SQLITE_ROW ){ |
| 176 | int pid = db_column_int(&q, 0); |
| 177 | double mtime = db_column_double(&q, 1); |
| 178 | if( bag_insert(&seen, pid) ){ |
| 179 | pqueue_insert(&queue, pid, -mtime, 0); |
| 180 | } |
| 181 | } |
| 182 | db_finalize(&q); |
| 183 | } |
| 184 | bag_clear(&seen); |
| 185 | pqueue_clear(&queue); |
| 186 | } |
| 187 | |
| 188 | /* |
| 189 | ** Load the record ID rid and up to N-1 closest descendants into |
| 190 | ** the "ok" table. |
| 191 | */ |
| 192 | void compute_descendants(int rid, int N){ |
| 193 | Bag seen; |
| 194 | PQueue queue; |
| 195 | bag_init(&seen); |
| 196 | pqueue_init(&queue); |
| 197 | bag_insert(&seen, rid); |
| 198 | pqueue_insert(&queue, rid, 0.0, 0); |
| 199 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 200 | Stmt q; |
| 201 | db_multi_exec("INSERT OR IGNORE INTO ok VALUES(%d)", rid); |
| 202 | db_prepare(&q,"SELECT cid, mtime FROM plink WHERE pid=%d", rid); |
| 203 | while( db_step(&q)==SQLITE_ROW ){ |
| 204 | int pid = db_column_int(&q, 0); |
| 205 | double mtime = db_column_double(&q, 1); |
| 206 | if( bag_insert(&seen, pid) ){ |
| 207 | pqueue_insert(&queue, pid, mtime, 0); |
| 208 | } |
| 209 | } |
| 210 | db_finalize(&q); |
| 211 | } |
| 212 | bag_clear(&seen); |
| 213 | pqueue_clear(&queue); |
| 214 | } |
| 215 | |
| 216 | /* |
| 217 | ** COMMAND: descendants |
| 218 | ** |
| 219 |
| --- src/descendants.c | |
| +++ src/descendants.c | |
| @@ -159,60 +159,75 @@ | |
| 159 | ** the "ok" table. |
| 160 | */ |
| 161 | void compute_ancestors(int rid, int N){ |
| 162 | Bag seen; |
| 163 | PQueue queue; |
| 164 | Stmt ins; |
| 165 | Stmt q; |
| 166 | bag_init(&seen); |
| 167 | pqueue_init(&queue); |
| 168 | bag_insert(&seen, rid); |
| 169 | pqueue_insert(&queue, rid, 0.0, 0); |
| 170 | db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); |
| 171 | db_prepare(&q, |
| 172 | "SELECT a.pid, b.mtime FROM plink a LEFT JOIN plink b ON b.cid=a.pid" |
| 173 | " WHERE a.cid=:rid" |
| 174 | ); |
| 175 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 176 | db_bind_int(&ins, ":rid", rid); |
| 177 | db_step(&ins); |
| 178 | db_reset(&ins); |
| 179 | db_bind_int(&q, ":rid", rid); |
| 180 | while( db_step(&q)==SQLITE_ROW ){ |
| 181 | int pid = db_column_int(&q, 0); |
| 182 | double mtime = db_column_double(&q, 1); |
| 183 | if( bag_insert(&seen, pid) ){ |
| 184 | pqueue_insert(&queue, pid, -mtime, 0); |
| 185 | } |
| 186 | } |
| 187 | db_reset(&q); |
| 188 | } |
| 189 | bag_clear(&seen); |
| 190 | pqueue_clear(&queue); |
| 191 | db_finalize(&ins); |
| 192 | db_finalize(&q); |
| 193 | } |
| 194 | |
| 195 | /* |
| 196 | ** Load the record ID rid and up to N-1 closest descendants into |
| 197 | ** the "ok" table. |
| 198 | */ |
| 199 | void compute_descendants(int rid, int N){ |
| 200 | Bag seen; |
| 201 | PQueue queue; |
| 202 | Stmt ins; |
| 203 | Stmt q; |
| 204 | |
| 205 | bag_init(&seen); |
| 206 | pqueue_init(&queue); |
| 207 | bag_insert(&seen, rid); |
| 208 | pqueue_insert(&queue, rid, 0.0, 0); |
| 209 | db_prepare(&ins, "INSERT OR IGNORE INTO ok VALUES(:rid)"); |
| 210 | db_prepare(&q, "SELECT cid, mtime FROM plink WHERE pid=:rid"); |
| 211 | while( (N--)>0 && (rid = pqueue_extract(&queue, 0))!=0 ){ |
| 212 | db_bind_int(&ins, ":rid", rid); |
| 213 | db_step(&ins); |
| 214 | db_reset(&ins); |
| 215 | db_bind_int(&q, ":rid", rid); |
| 216 | while( db_step(&q)==SQLITE_ROW ){ |
| 217 | int pid = db_column_int(&q, 0); |
| 218 | double mtime = db_column_double(&q, 1); |
| 219 | if( bag_insert(&seen, pid) ){ |
| 220 | pqueue_insert(&queue, pid, mtime, 0); |
| 221 | } |
| 222 | } |
| 223 | db_reset(&q); |
| 224 | } |
| 225 | bag_clear(&seen); |
| 226 | pqueue_clear(&queue); |
| 227 | db_finalize(&ins); |
| 228 | db_finalize(&q); |
| 229 | } |
| 230 | |
| 231 | /* |
| 232 | ** COMMAND: descendants |
| 233 | ** |
| 234 |
+19
-6
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -747,10 +747,13 @@ | ||
| 747 | 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | 749 | } |
| 750 | 750 | } |
| 751 | 751 | |
| 752 | +/* Annotation flags */ | |
| 753 | +#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */ | |
| 754 | + | |
| 752 | 755 | /* |
| 753 | 756 | ** Compute a complete annotation on a file. The file is identified |
| 754 | 757 | ** by its filename number (filename.fnid) and the baseline in which |
| 755 | 758 | ** it was checked in (mlink.mid). |
| 756 | 759 | */ |
| @@ -757,11 +760,12 @@ | ||
| 757 | 760 | static void annotate_file( |
| 758 | 761 | Annotator *p, /* The annotator */ |
| 759 | 762 | int fnid, /* The name of the file to be annotated */ |
| 760 | 763 | int mid, /* The specific version of the file for this step */ |
| 761 | 764 | int webLabel, /* Use web-style annotations if true */ |
| 762 | - int iLimit /* Limit the number of levels if greater than zero */ | |
| 765 | + int iLimit, /* Limit the number of levels if greater than zero */ | |
| 766 | + int annFlags /* Flags to alter the annotation */ | |
| 763 | 767 | ){ |
| 764 | 768 | Blob toAnnotate; /* Text of the final version of the file */ |
| 765 | 769 | Blob step; /* Text of previous revision */ |
| 766 | 770 | int rid; /* Artifact ID of the file being annotated */ |
| 767 | 771 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | ||
| 778 | 782 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 779 | 783 | compute_ancestors(mid, 1000000000); |
| 780 | 784 | annotation_start(p, &toAnnotate); |
| 781 | 785 | |
| 782 | 786 | db_prepare(&q, |
| 783 | - "SELECT mlink.fid, blob.uuid, date(event.mtime), " | |
| 787 | + "SELECT mlink.fid," | |
| 788 | + " (SELECT uuid FROM blob WHERE rid=mlink.%s)," | |
| 789 | + " date(event.mtime), " | |
| 784 | 790 | " coalesce(event.euser,event.user) " |
| 785 | - " FROM mlink, blob, event" | |
| 791 | + " FROM mlink, event" | |
| 786 | 792 | " WHERE mlink.fnid=%d" |
| 787 | 793 | " AND mlink.mid IN ok" |
| 788 | - " AND blob.rid=mlink.mid" | |
| 789 | 794 | " AND event.objid=mlink.mid" |
| 790 | 795 | " ORDER BY event.mtime DESC" |
| 791 | 796 | " LIMIT %d", |
| 797 | + (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid", | |
| 792 | 798 | fnid, |
| 793 | 799 | iLimit>0 ? iLimit : 10000000 |
| 794 | 800 | ); |
| 795 | 801 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | 802 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | ||
| 826 | 832 | void annotation_page(void){ |
| 827 | 833 | int mid; |
| 828 | 834 | int fnid; |
| 829 | 835 | int i; |
| 830 | 836 | int iLimit; |
| 837 | + int annFlags = 0; | |
| 831 | 838 | Annotator ann; |
| 832 | 839 | |
| 833 | 840 | login_check_credentials(); |
| 834 | 841 | if( !g.okRead ){ login_needed(); return; } |
| 835 | 842 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | ||
| 838 | 845 | iLimit = atoi(PD("limit","-1")); |
| 839 | 846 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 840 | 847 | fossil_redirect_home(); |
| 841 | 848 | } |
| 842 | 849 | style_header("File Annotation"); |
| 843 | - annotate_file(&ann, fnid, mid, g.okHistory, iLimit); | |
| 850 | + if( P("filevers") ) annFlags |= ANN_FILE_VERS; | |
| 851 | + annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags); | |
| 844 | 852 | if( P("log") ){ |
| 845 | 853 | int i; |
| 846 | 854 | @ <h2>Versions analyzed:</h2> |
| 847 | 855 | @ <ol> |
| 848 | 856 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | ||
| 870 | 878 | ** the file was last modified. |
| 871 | 879 | ** |
| 872 | 880 | ** Options: |
| 873 | 881 | ** --limit N Only look backwards in time by N versions |
| 874 | 882 | ** --log List all versions analyzed |
| 883 | +** --filevers Show file version numbers rather than check-in versions | |
| 875 | 884 | */ |
| 876 | 885 | void annotate_cmd(void){ |
| 877 | 886 | int fnid; /* Filename ID */ |
| 878 | 887 | int fid; /* File instance ID */ |
| 879 | 888 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | ||
| 882 | 891 | Annotator ann; /* The annotation of the file */ |
| 883 | 892 | int i; /* Loop counter */ |
| 884 | 893 | const char *zLimit; /* The value to the --limit option */ |
| 885 | 894 | int iLimit; /* How far back in time to look */ |
| 886 | 895 | int showLog; /* True to show the log */ |
| 896 | + int fileVers; /* Show file version instead of check-in versions */ | |
| 897 | + int annFlags = 0; /* Flags to control annotation properties */ | |
| 887 | 898 | |
| 888 | 899 | zLimit = find_option("limit",0,1); |
| 889 | 900 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 890 | 901 | iLimit = atoi(zLimit); |
| 891 | 902 | showLog = find_option("log",0,0)!=0; |
| 903 | + fileVers = find_option("filevers",0,0)!=0; | |
| 892 | 904 | db_must_be_within_tree(); |
| 893 | 905 | if (g.argc<3) { |
| 894 | 906 | usage("FILENAME"); |
| 895 | 907 | } |
| 896 | 908 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | ||
| 905 | 917 | } |
| 906 | 918 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 907 | 919 | if( mid==0 ){ |
| 908 | 920 | fossil_panic("unable to find manifest"); |
| 909 | 921 | } |
| 910 | - annotate_file(&ann, fnid, mid, 0, iLimit); | |
| 922 | + if( fileVers ) annFlags |= ANN_FILE_VERS; | |
| 923 | + annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); | |
| 911 | 924 | if( showLog ){ |
| 912 | 925 | for(i=0; i<ann.nVers; i++){ |
| 913 | 926 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 914 | 927 | } |
| 915 | 928 | printf("---------------------------------------------------\n"); |
| 916 | 929 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -747,10 +747,13 @@ | |
| 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | /* |
| 753 | ** Compute a complete annotation on a file. The file is identified |
| 754 | ** by its filename number (filename.fnid) and the baseline in which |
| 755 | ** it was checked in (mlink.mid). |
| 756 | */ |
| @@ -757,11 +760,12 @@ | |
| 757 | static void annotate_file( |
| 758 | Annotator *p, /* The annotator */ |
| 759 | int fnid, /* The name of the file to be annotated */ |
| 760 | int mid, /* The specific version of the file for this step */ |
| 761 | int webLabel, /* Use web-style annotations if true */ |
| 762 | int iLimit /* Limit the number of levels if greater than zero */ |
| 763 | ){ |
| 764 | Blob toAnnotate; /* Text of the final version of the file */ |
| 765 | Blob step; /* Text of previous revision */ |
| 766 | int rid; /* Artifact ID of the file being annotated */ |
| 767 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | |
| 778 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 779 | compute_ancestors(mid, 1000000000); |
| 780 | annotation_start(p, &toAnnotate); |
| 781 | |
| 782 | db_prepare(&q, |
| 783 | "SELECT mlink.fid, blob.uuid, date(event.mtime), " |
| 784 | " coalesce(event.euser,event.user) " |
| 785 | " FROM mlink, blob, event" |
| 786 | " WHERE mlink.fnid=%d" |
| 787 | " AND mlink.mid IN ok" |
| 788 | " AND blob.rid=mlink.mid" |
| 789 | " AND event.objid=mlink.mid" |
| 790 | " ORDER BY event.mtime DESC" |
| 791 | " LIMIT %d", |
| 792 | fnid, |
| 793 | iLimit>0 ? iLimit : 10000000 |
| 794 | ); |
| 795 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | |
| 826 | void annotation_page(void){ |
| 827 | int mid; |
| 828 | int fnid; |
| 829 | int i; |
| 830 | int iLimit; |
| 831 | Annotator ann; |
| 832 | |
| 833 | login_check_credentials(); |
| 834 | if( !g.okRead ){ login_needed(); return; } |
| 835 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | |
| 838 | iLimit = atoi(PD("limit","-1")); |
| 839 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 840 | fossil_redirect_home(); |
| 841 | } |
| 842 | style_header("File Annotation"); |
| 843 | annotate_file(&ann, fnid, mid, g.okHistory, iLimit); |
| 844 | if( P("log") ){ |
| 845 | int i; |
| 846 | @ <h2>Versions analyzed:</h2> |
| 847 | @ <ol> |
| 848 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | |
| 870 | ** the file was last modified. |
| 871 | ** |
| 872 | ** Options: |
| 873 | ** --limit N Only look backwards in time by N versions |
| 874 | ** --log List all versions analyzed |
| 875 | */ |
| 876 | void annotate_cmd(void){ |
| 877 | int fnid; /* Filename ID */ |
| 878 | int fid; /* File instance ID */ |
| 879 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | |
| 882 | Annotator ann; /* The annotation of the file */ |
| 883 | int i; /* Loop counter */ |
| 884 | const char *zLimit; /* The value to the --limit option */ |
| 885 | int iLimit; /* How far back in time to look */ |
| 886 | int showLog; /* True to show the log */ |
| 887 | |
| 888 | zLimit = find_option("limit",0,1); |
| 889 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 890 | iLimit = atoi(zLimit); |
| 891 | showLog = find_option("log",0,0)!=0; |
| 892 | db_must_be_within_tree(); |
| 893 | if (g.argc<3) { |
| 894 | usage("FILENAME"); |
| 895 | } |
| 896 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | |
| 905 | } |
| 906 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 907 | if( mid==0 ){ |
| 908 | fossil_panic("unable to find manifest"); |
| 909 | } |
| 910 | annotate_file(&ann, fnid, mid, 0, iLimit); |
| 911 | if( showLog ){ |
| 912 | for(i=0; i<ann.nVers; i++){ |
| 913 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 914 | } |
| 915 | printf("---------------------------------------------------\n"); |
| 916 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -747,10 +747,13 @@ | |
| 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | /* Annotation flags */ |
| 753 | #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */ |
| 754 | |
| 755 | /* |
| 756 | ** Compute a complete annotation on a file. The file is identified |
| 757 | ** by its filename number (filename.fnid) and the baseline in which |
| 758 | ** it was checked in (mlink.mid). |
| 759 | */ |
| @@ -757,11 +760,12 @@ | |
| 760 | static void annotate_file( |
| 761 | Annotator *p, /* The annotator */ |
| 762 | int fnid, /* The name of the file to be annotated */ |
| 763 | int mid, /* The specific version of the file for this step */ |
| 764 | int webLabel, /* Use web-style annotations if true */ |
| 765 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 766 | int annFlags /* Flags to alter the annotation */ |
| 767 | ){ |
| 768 | Blob toAnnotate; /* Text of the final version of the file */ |
| 769 | Blob step; /* Text of previous revision */ |
| 770 | int rid; /* Artifact ID of the file being annotated */ |
| 771 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | |
| 782 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 783 | compute_ancestors(mid, 1000000000); |
| 784 | annotation_start(p, &toAnnotate); |
| 785 | |
| 786 | db_prepare(&q, |
| 787 | "SELECT mlink.fid," |
| 788 | " (SELECT uuid FROM blob WHERE rid=mlink.%s)," |
| 789 | " date(event.mtime), " |
| 790 | " coalesce(event.euser,event.user) " |
| 791 | " FROM mlink, event" |
| 792 | " WHERE mlink.fnid=%d" |
| 793 | " AND mlink.mid IN ok" |
| 794 | " AND event.objid=mlink.mid" |
| 795 | " ORDER BY event.mtime DESC" |
| 796 | " LIMIT %d", |
| 797 | (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid", |
| 798 | fnid, |
| 799 | iLimit>0 ? iLimit : 10000000 |
| 800 | ); |
| 801 | while( db_step(&q)==SQLITE_ROW ){ |
| 802 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | |
| 832 | void annotation_page(void){ |
| 833 | int mid; |
| 834 | int fnid; |
| 835 | int i; |
| 836 | int iLimit; |
| 837 | int annFlags = 0; |
| 838 | Annotator ann; |
| 839 | |
| 840 | login_check_credentials(); |
| 841 | if( !g.okRead ){ login_needed(); return; } |
| 842 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | |
| 845 | iLimit = atoi(PD("limit","-1")); |
| 846 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 847 | fossil_redirect_home(); |
| 848 | } |
| 849 | style_header("File Annotation"); |
| 850 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 851 | annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags); |
| 852 | if( P("log") ){ |
| 853 | int i; |
| 854 | @ <h2>Versions analyzed:</h2> |
| 855 | @ <ol> |
| 856 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | |
| 878 | ** the file was last modified. |
| 879 | ** |
| 880 | ** Options: |
| 881 | ** --limit N Only look backwards in time by N versions |
| 882 | ** --log List all versions analyzed |
| 883 | ** --filevers Show file version numbers rather than check-in versions |
| 884 | */ |
| 885 | void annotate_cmd(void){ |
| 886 | int fnid; /* Filename ID */ |
| 887 | int fid; /* File instance ID */ |
| 888 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | |
| 891 | Annotator ann; /* The annotation of the file */ |
| 892 | int i; /* Loop counter */ |
| 893 | const char *zLimit; /* The value to the --limit option */ |
| 894 | int iLimit; /* How far back in time to look */ |
| 895 | int showLog; /* True to show the log */ |
| 896 | int fileVers; /* Show file version instead of check-in versions */ |
| 897 | int annFlags = 0; /* Flags to control annotation properties */ |
| 898 | |
| 899 | zLimit = find_option("limit",0,1); |
| 900 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 901 | iLimit = atoi(zLimit); |
| 902 | showLog = find_option("log",0,0)!=0; |
| 903 | fileVers = find_option("filevers",0,0)!=0; |
| 904 | db_must_be_within_tree(); |
| 905 | if (g.argc<3) { |
| 906 | usage("FILENAME"); |
| 907 | } |
| 908 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | |
| 917 | } |
| 918 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 919 | if( mid==0 ){ |
| 920 | fossil_panic("unable to find manifest"); |
| 921 | } |
| 922 | if( fileVers ) annFlags |= ANN_FILE_VERS; |
| 923 | annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); |
| 924 | if( showLog ){ |
| 925 | for(i=0; i<ann.nVers; i++){ |
| 926 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 927 | } |
| 928 | printf("---------------------------------------------------\n"); |
| 929 |
+19
-6
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -747,10 +747,13 @@ | ||
| 747 | 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | 749 | } |
| 750 | 750 | } |
| 751 | 751 | |
| 752 | +/* Annotation flags */ | |
| 753 | +#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */ | |
| 754 | + | |
| 752 | 755 | /* |
| 753 | 756 | ** Compute a complete annotation on a file. The file is identified |
| 754 | 757 | ** by its filename number (filename.fnid) and the baseline in which |
| 755 | 758 | ** it was checked in (mlink.mid). |
| 756 | 759 | */ |
| @@ -757,11 +760,12 @@ | ||
| 757 | 760 | static void annotate_file( |
| 758 | 761 | Annotator *p, /* The annotator */ |
| 759 | 762 | int fnid, /* The name of the file to be annotated */ |
| 760 | 763 | int mid, /* The specific version of the file for this step */ |
| 761 | 764 | int webLabel, /* Use web-style annotations if true */ |
| 762 | - int iLimit /* Limit the number of levels if greater than zero */ | |
| 765 | + int iLimit, /* Limit the number of levels if greater than zero */ | |
| 766 | + int annFlags /* Flags to alter the annotation */ | |
| 763 | 767 | ){ |
| 764 | 768 | Blob toAnnotate; /* Text of the final version of the file */ |
| 765 | 769 | Blob step; /* Text of previous revision */ |
| 766 | 770 | int rid; /* Artifact ID of the file being annotated */ |
| 767 | 771 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | ||
| 778 | 782 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 779 | 783 | compute_ancestors(mid, 1000000000); |
| 780 | 784 | annotation_start(p, &toAnnotate); |
| 781 | 785 | |
| 782 | 786 | db_prepare(&q, |
| 783 | - "SELECT mlink.fid, blob.uuid, date(event.mtime), " | |
| 787 | + "SELECT mlink.fid," | |
| 788 | + " (SELECT uuid FROM blob WHERE rid=mlink.%s)," | |
| 789 | + " date(event.mtime), " | |
| 784 | 790 | " coalesce(event.euser,event.user) " |
| 785 | - " FROM mlink, blob, event" | |
| 791 | + " FROM mlink, event" | |
| 786 | 792 | " WHERE mlink.fnid=%d" |
| 787 | 793 | " AND mlink.mid IN ok" |
| 788 | - " AND blob.rid=mlink.mid" | |
| 789 | 794 | " AND event.objid=mlink.mid" |
| 790 | 795 | " ORDER BY event.mtime DESC" |
| 791 | 796 | " LIMIT %d", |
| 797 | + (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid", | |
| 792 | 798 | fnid, |
| 793 | 799 | iLimit>0 ? iLimit : 10000000 |
| 794 | 800 | ); |
| 795 | 801 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | 802 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | ||
| 826 | 832 | void annotation_page(void){ |
| 827 | 833 | int mid; |
| 828 | 834 | int fnid; |
| 829 | 835 | int i; |
| 830 | 836 | int iLimit; |
| 837 | + int annFlags = 0; | |
| 831 | 838 | Annotator ann; |
| 832 | 839 | |
| 833 | 840 | login_check_credentials(); |
| 834 | 841 | if( !g.okRead ){ login_needed(); return; } |
| 835 | 842 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | ||
| 838 | 845 | iLimit = atoi(PD("limit","-1")); |
| 839 | 846 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 840 | 847 | fossil_redirect_home(); |
| 841 | 848 | } |
| 842 | 849 | style_header("File Annotation"); |
| 843 | - annotate_file(&ann, fnid, mid, g.okHistory, iLimit); | |
| 850 | + if( P("filevers") ) annFlags |= ANN_FILE_VERS; | |
| 851 | + annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags); | |
| 844 | 852 | if( P("log") ){ |
| 845 | 853 | int i; |
| 846 | 854 | @ <h2>Versions analyzed:</h2> |
| 847 | 855 | @ <ol> |
| 848 | 856 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | ||
| 870 | 878 | ** the file was last modified. |
| 871 | 879 | ** |
| 872 | 880 | ** Options: |
| 873 | 881 | ** --limit N Only look backwards in time by N versions |
| 874 | 882 | ** --log List all versions analyzed |
| 883 | +** --filevers Show file version numbers rather than check-in versions | |
| 875 | 884 | */ |
| 876 | 885 | void annotate_cmd(void){ |
| 877 | 886 | int fnid; /* Filename ID */ |
| 878 | 887 | int fid; /* File instance ID */ |
| 879 | 888 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | ||
| 882 | 891 | Annotator ann; /* The annotation of the file */ |
| 883 | 892 | int i; /* Loop counter */ |
| 884 | 893 | const char *zLimit; /* The value to the --limit option */ |
| 885 | 894 | int iLimit; /* How far back in time to look */ |
| 886 | 895 | int showLog; /* True to show the log */ |
| 896 | + int fileVers; /* Show file version instead of check-in versions */ | |
| 897 | + int annFlags = 0; /* Flags to control annotation properties */ | |
| 887 | 898 | |
| 888 | 899 | zLimit = find_option("limit",0,1); |
| 889 | 900 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 890 | 901 | iLimit = atoi(zLimit); |
| 891 | 902 | showLog = find_option("log",0,0)!=0; |
| 903 | + fileVers = find_option("filevers",0,0)!=0; | |
| 892 | 904 | db_must_be_within_tree(); |
| 893 | 905 | if (g.argc<3) { |
| 894 | 906 | usage("FILENAME"); |
| 895 | 907 | } |
| 896 | 908 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | ||
| 905 | 917 | } |
| 906 | 918 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 907 | 919 | if( mid==0 ){ |
| 908 | 920 | fossil_panic("unable to find manifest"); |
| 909 | 921 | } |
| 910 | - annotate_file(&ann, fnid, mid, 0, iLimit); | |
| 922 | + if( fileVers ) annFlags |= ANN_FILE_VERS; | |
| 923 | + annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); | |
| 911 | 924 | if( showLog ){ |
| 912 | 925 | for(i=0; i<ann.nVers; i++){ |
| 913 | 926 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 914 | 927 | } |
| 915 | 928 | printf("---------------------------------------------------\n"); |
| 916 | 929 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -747,10 +747,13 @@ | |
| 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | /* |
| 753 | ** Compute a complete annotation on a file. The file is identified |
| 754 | ** by its filename number (filename.fnid) and the baseline in which |
| 755 | ** it was checked in (mlink.mid). |
| 756 | */ |
| @@ -757,11 +760,12 @@ | |
| 757 | static void annotate_file( |
| 758 | Annotator *p, /* The annotator */ |
| 759 | int fnid, /* The name of the file to be annotated */ |
| 760 | int mid, /* The specific version of the file for this step */ |
| 761 | int webLabel, /* Use web-style annotations if true */ |
| 762 | int iLimit /* Limit the number of levels if greater than zero */ |
| 763 | ){ |
| 764 | Blob toAnnotate; /* Text of the final version of the file */ |
| 765 | Blob step; /* Text of previous revision */ |
| 766 | int rid; /* Artifact ID of the file being annotated */ |
| 767 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | |
| 778 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 779 | compute_ancestors(mid, 1000000000); |
| 780 | annotation_start(p, &toAnnotate); |
| 781 | |
| 782 | db_prepare(&q, |
| 783 | "SELECT mlink.fid, blob.uuid, date(event.mtime), " |
| 784 | " coalesce(event.euser,event.user) " |
| 785 | " FROM mlink, blob, event" |
| 786 | " WHERE mlink.fnid=%d" |
| 787 | " AND mlink.mid IN ok" |
| 788 | " AND blob.rid=mlink.mid" |
| 789 | " AND event.objid=mlink.mid" |
| 790 | " ORDER BY event.mtime DESC" |
| 791 | " LIMIT %d", |
| 792 | fnid, |
| 793 | iLimit>0 ? iLimit : 10000000 |
| 794 | ); |
| 795 | while( db_step(&q)==SQLITE_ROW ){ |
| 796 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | |
| 826 | void annotation_page(void){ |
| 827 | int mid; |
| 828 | int fnid; |
| 829 | int i; |
| 830 | int iLimit; |
| 831 | Annotator ann; |
| 832 | |
| 833 | login_check_credentials(); |
| 834 | if( !g.okRead ){ login_needed(); return; } |
| 835 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | |
| 838 | iLimit = atoi(PD("limit","-1")); |
| 839 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 840 | fossil_redirect_home(); |
| 841 | } |
| 842 | style_header("File Annotation"); |
| 843 | annotate_file(&ann, fnid, mid, g.okHistory, iLimit); |
| 844 | if( P("log") ){ |
| 845 | int i; |
| 846 | @ <h2>Versions analyzed:</h2> |
| 847 | @ <ol> |
| 848 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | |
| 870 | ** the file was last modified. |
| 871 | ** |
| 872 | ** Options: |
| 873 | ** --limit N Only look backwards in time by N versions |
| 874 | ** --log List all versions analyzed |
| 875 | */ |
| 876 | void annotate_cmd(void){ |
| 877 | int fnid; /* Filename ID */ |
| 878 | int fid; /* File instance ID */ |
| 879 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | |
| 882 | Annotator ann; /* The annotation of the file */ |
| 883 | int i; /* Loop counter */ |
| 884 | const char *zLimit; /* The value to the --limit option */ |
| 885 | int iLimit; /* How far back in time to look */ |
| 886 | int showLog; /* True to show the log */ |
| 887 | |
| 888 | zLimit = find_option("limit",0,1); |
| 889 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 890 | iLimit = atoi(zLimit); |
| 891 | showLog = find_option("log",0,0)!=0; |
| 892 | db_must_be_within_tree(); |
| 893 | if (g.argc<3) { |
| 894 | usage("FILENAME"); |
| 895 | } |
| 896 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | |
| 905 | } |
| 906 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 907 | if( mid==0 ){ |
| 908 | fossil_panic("unable to find manifest"); |
| 909 | } |
| 910 | annotate_file(&ann, fnid, mid, 0, iLimit); |
| 911 | if( showLog ){ |
| 912 | for(i=0; i<ann.nVers; i++){ |
| 913 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 914 | } |
| 915 | printf("---------------------------------------------------\n"); |
| 916 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -747,10 +747,13 @@ | |
| 747 | if( zSrc==0 ) zSrc = g.argv[g.argc-1]; |
| 748 | fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z); |
| 749 | } |
| 750 | } |
| 751 | |
| 752 | /* Annotation flags */ |
| 753 | #define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */ |
| 754 | |
| 755 | /* |
| 756 | ** Compute a complete annotation on a file. The file is identified |
| 757 | ** by its filename number (filename.fnid) and the baseline in which |
| 758 | ** it was checked in (mlink.mid). |
| 759 | */ |
| @@ -757,11 +760,12 @@ | |
| 760 | static void annotate_file( |
| 761 | Annotator *p, /* The annotator */ |
| 762 | int fnid, /* The name of the file to be annotated */ |
| 763 | int mid, /* The specific version of the file for this step */ |
| 764 | int webLabel, /* Use web-style annotations if true */ |
| 765 | int iLimit, /* Limit the number of levels if greater than zero */ |
| 766 | int annFlags /* Flags to alter the annotation */ |
| 767 | ){ |
| 768 | Blob toAnnotate; /* Text of the final version of the file */ |
| 769 | Blob step; /* Text of previous revision */ |
| 770 | int rid; /* Artifact ID of the file being annotated */ |
| 771 | char *zLabel; /* Label to apply to a line */ |
| @@ -778,19 +782,21 @@ | |
| 782 | db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)"); |
| 783 | compute_ancestors(mid, 1000000000); |
| 784 | annotation_start(p, &toAnnotate); |
| 785 | |
| 786 | db_prepare(&q, |
| 787 | "SELECT mlink.fid," |
| 788 | " (SELECT uuid FROM blob WHERE rid=mlink.%s)," |
| 789 | " date(event.mtime), " |
| 790 | " coalesce(event.euser,event.user) " |
| 791 | " FROM mlink, event" |
| 792 | " WHERE mlink.fnid=%d" |
| 793 | " AND mlink.mid IN ok" |
| 794 | " AND event.objid=mlink.mid" |
| 795 | " ORDER BY event.mtime DESC" |
| 796 | " LIMIT %d", |
| 797 | (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid", |
| 798 | fnid, |
| 799 | iLimit>0 ? iLimit : 10000000 |
| 800 | ); |
| 801 | while( db_step(&q)==SQLITE_ROW ){ |
| 802 | int pid = db_column_int(&q, 0); |
| @@ -826,10 +832,11 @@ | |
| 832 | void annotation_page(void){ |
| 833 | int mid; |
| 834 | int fnid; |
| 835 | int i; |
| 836 | int iLimit; |
| 837 | int annFlags = 0; |
| 838 | Annotator ann; |
| 839 | |
| 840 | login_check_credentials(); |
| 841 | if( !g.okRead ){ login_needed(); return; } |
| 842 | mid = name_to_rid(PD("checkin","0")); |
| @@ -838,11 +845,12 @@ | |
| 845 | iLimit = atoi(PD("limit","-1")); |
| 846 | if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){ |
| 847 | fossil_redirect_home(); |
| 848 | } |
| 849 | style_header("File Annotation"); |
| 850 | if( P("filevers") ) annFlags |= ANN_FILE_VERS; |
| 851 | annotate_file(&ann, fnid, mid, g.okHistory, iLimit, annFlags); |
| 852 | if( P("log") ){ |
| 853 | int i; |
| 854 | @ <h2>Versions analyzed:</h2> |
| 855 | @ <ol> |
| 856 | for(i=0; i<ann.nVers; i++){ |
| @@ -870,10 +878,11 @@ | |
| 878 | ** the file was last modified. |
| 879 | ** |
| 880 | ** Options: |
| 881 | ** --limit N Only look backwards in time by N versions |
| 882 | ** --log List all versions analyzed |
| 883 | ** --filevers Show file version numbers rather than check-in versions |
| 884 | */ |
| 885 | void annotate_cmd(void){ |
| 886 | int fnid; /* Filename ID */ |
| 887 | int fid; /* File instance ID */ |
| 888 | int mid; /* Manifest where file was checked in */ |
| @@ -882,15 +891,18 @@ | |
| 891 | Annotator ann; /* The annotation of the file */ |
| 892 | int i; /* Loop counter */ |
| 893 | const char *zLimit; /* The value to the --limit option */ |
| 894 | int iLimit; /* How far back in time to look */ |
| 895 | int showLog; /* True to show the log */ |
| 896 | int fileVers; /* Show file version instead of check-in versions */ |
| 897 | int annFlags = 0; /* Flags to control annotation properties */ |
| 898 | |
| 899 | zLimit = find_option("limit",0,1); |
| 900 | if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1"; |
| 901 | iLimit = atoi(zLimit); |
| 902 | showLog = find_option("log",0,0)!=0; |
| 903 | fileVers = find_option("filevers",0,0)!=0; |
| 904 | db_must_be_within_tree(); |
| 905 | if (g.argc<3) { |
| 906 | usage("FILENAME"); |
| 907 | } |
| 908 | file_tree_name(g.argv[2], &treename, 1); |
| @@ -905,11 +917,12 @@ | |
| 917 | } |
| 918 | mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid); |
| 919 | if( mid==0 ){ |
| 920 | fossil_panic("unable to find manifest"); |
| 921 | } |
| 922 | if( fileVers ) annFlags |= ANN_FILE_VERS; |
| 923 | annotate_file(&ann, fnid, mid, 0, iLimit, annFlags); |
| 924 | if( showLog ){ |
| 925 | for(i=0; i<ann.nVers; i++){ |
| 926 | printf("version %3d: %s\n", i+1, ann.azVers[i]); |
| 927 | } |
| 928 | printf("---------------------------------------------------\n"); |
| 929 |
+31
-8
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -186,27 +186,38 @@ | ||
| 186 | 186 | |
| 187 | 187 | /* |
| 188 | 188 | ** WEBPAGE: finfo |
| 189 | 189 | ** URL: /finfo?name=FILENAME |
| 190 | 190 | ** |
| 191 | -** Show the complete change history for a single file. | |
| 191 | +** Show the change history for a single file. | |
| 192 | +** | |
| 193 | +** Additional query parameters: | |
| 194 | +** | |
| 195 | +** a=DATE Only show changes after DATE | |
| 196 | +** b=DATE Only show changes before DATE | |
| 197 | +** n=NUM Show the first NUM changes only | |
| 192 | 198 | */ |
| 193 | 199 | void finfo_page(void){ |
| 194 | 200 | Stmt q; |
| 195 | 201 | const char *zFilename; |
| 196 | 202 | char zPrevDate[20]; |
| 203 | + const char *zA; | |
| 204 | + const char *zB; | |
| 205 | + int n; | |
| 197 | 206 | Blob title; |
| 207 | + Blob sql; | |
| 198 | 208 | GraphContext *pGraph; |
| 199 | 209 | |
| 200 | 210 | login_check_credentials(); |
| 201 | 211 | if( !g.okRead ){ login_needed(); return; } |
| 202 | 212 | style_header("File History"); |
| 203 | 213 | login_anonymous_available(); |
| 204 | 214 | |
| 205 | 215 | zPrevDate[0] = 0; |
| 206 | 216 | zFilename = PD("name",""); |
| 207 | - db_prepare(&q, | |
| 217 | + blob_zero(&sql); | |
| 218 | + blob_appendf(&sql, | |
| 208 | 219 | "SELECT" |
| 209 | 220 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 210 | 221 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 211 | 222 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 212 | 223 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | ||
| 217 | 228 | " event.bgcolor," /* Background color */ |
| 218 | 229 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 219 | 230 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 220 | 231 | " FROM mlink, event" |
| 221 | 232 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 222 | - " AND event.objid=mlink.mid" | |
| 223 | - " ORDER BY event.mtime DESC /*sort*/", | |
| 233 | + " AND event.objid=mlink.mid", | |
| 224 | 234 | TAG_BRANCH, |
| 225 | 235 | zFilename |
| 226 | 236 | ); |
| 237 | + if( (zA = P("a"))!=0 ){ | |
| 238 | + blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); | |
| 239 | + } | |
| 240 | + if( (zB = P("b"))!=0 ){ | |
| 241 | + blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB); | |
| 242 | + } | |
| 243 | + blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); | |
| 244 | + if( (n = atoi(PD("n","0")))>0 ){ | |
| 245 | + blob_appendf(&sql, " LIMIT %d", n); | |
| 246 | + } | |
| 247 | + db_prepare(&q, blob_str(&sql)); | |
| 248 | + blob_reset(&sql); | |
| 227 | 249 | blob_zero(&title); |
| 228 | 250 | blob_appendf(&title, "History of "); |
| 229 | 251 | hyperlinked_path(zFilename, &title, 0); |
| 230 | 252 | @ <h2>%b(&title)</h2> |
| 231 | 253 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | ||
| 246 | 268 | int gidx; |
| 247 | 269 | char zTime[10]; |
| 248 | 270 | char zShort[20]; |
| 249 | 271 | char zShortCkin[20]; |
| 250 | 272 | if( zBr==0 ) zBr = "trunk"; |
| 251 | - gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1); | |
| 273 | + gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0); | |
| 252 | 274 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 253 | 275 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 254 | 276 | @ <tr><td> |
| 255 | 277 | @ <div class="divider">%s(zPrevDate)</div> |
| 256 | 278 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | ||
| 291 | 313 | } |
| 292 | 314 | @ </td></tr> |
| 293 | 315 | } |
| 294 | 316 | db_finalize(&q); |
| 295 | 317 | if( pGraph ){ |
| 296 | - graph_finish(pGraph, 1); | |
| 318 | + graph_finish(pGraph, 0); | |
| 297 | 319 | if( pGraph->nErr ){ |
| 298 | 320 | graph_free(pGraph); |
| 299 | 321 | pGraph = 0; |
| 300 | 322 | }else{ |
| 301 | - @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> | |
| 323 | + @ <tr><td></td><td> | |
| 324 | + @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> | |
| 302 | 325 | @ </td></tr> |
| 303 | 326 | } |
| 304 | 327 | } |
| 305 | 328 | @ </table> |
| 306 | - timeline_output_graph_javascript(pGraph, 1); | |
| 329 | + timeline_output_graph_javascript(pGraph, 0); | |
| 307 | 330 | style_footer(); |
| 308 | 331 | } |
| 309 | 332 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -186,27 +186,38 @@ | |
| 186 | |
| 187 | /* |
| 188 | ** WEBPAGE: finfo |
| 189 | ** URL: /finfo?name=FILENAME |
| 190 | ** |
| 191 | ** Show the complete change history for a single file. |
| 192 | */ |
| 193 | void finfo_page(void){ |
| 194 | Stmt q; |
| 195 | const char *zFilename; |
| 196 | char zPrevDate[20]; |
| 197 | Blob title; |
| 198 | GraphContext *pGraph; |
| 199 | |
| 200 | login_check_credentials(); |
| 201 | if( !g.okRead ){ login_needed(); return; } |
| 202 | style_header("File History"); |
| 203 | login_anonymous_available(); |
| 204 | |
| 205 | zPrevDate[0] = 0; |
| 206 | zFilename = PD("name",""); |
| 207 | db_prepare(&q, |
| 208 | "SELECT" |
| 209 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 210 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 211 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 212 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | |
| 217 | " event.bgcolor," /* Background color */ |
| 218 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 219 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 220 | " FROM mlink, event" |
| 221 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 222 | " AND event.objid=mlink.mid" |
| 223 | " ORDER BY event.mtime DESC /*sort*/", |
| 224 | TAG_BRANCH, |
| 225 | zFilename |
| 226 | ); |
| 227 | blob_zero(&title); |
| 228 | blob_appendf(&title, "History of "); |
| 229 | hyperlinked_path(zFilename, &title, 0); |
| 230 | @ <h2>%b(&title)</h2> |
| 231 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | |
| 246 | int gidx; |
| 247 | char zTime[10]; |
| 248 | char zShort[20]; |
| 249 | char zShortCkin[20]; |
| 250 | if( zBr==0 ) zBr = "trunk"; |
| 251 | gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1); |
| 252 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 253 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 254 | @ <tr><td> |
| 255 | @ <div class="divider">%s(zPrevDate)</div> |
| 256 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | |
| 291 | } |
| 292 | @ </td></tr> |
| 293 | } |
| 294 | db_finalize(&q); |
| 295 | if( pGraph ){ |
| 296 | graph_finish(pGraph, 1); |
| 297 | if( pGraph->nErr ){ |
| 298 | graph_free(pGraph); |
| 299 | pGraph = 0; |
| 300 | }else{ |
| 301 | @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 302 | @ </td></tr> |
| 303 | } |
| 304 | } |
| 305 | @ </table> |
| 306 | timeline_output_graph_javascript(pGraph, 1); |
| 307 | style_footer(); |
| 308 | } |
| 309 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -186,27 +186,38 @@ | |
| 186 | |
| 187 | /* |
| 188 | ** WEBPAGE: finfo |
| 189 | ** URL: /finfo?name=FILENAME |
| 190 | ** |
| 191 | ** Show the change history for a single file. |
| 192 | ** |
| 193 | ** Additional query parameters: |
| 194 | ** |
| 195 | ** a=DATE Only show changes after DATE |
| 196 | ** b=DATE Only show changes before DATE |
| 197 | ** n=NUM Show the first NUM changes only |
| 198 | */ |
| 199 | void finfo_page(void){ |
| 200 | Stmt q; |
| 201 | const char *zFilename; |
| 202 | char zPrevDate[20]; |
| 203 | const char *zA; |
| 204 | const char *zB; |
| 205 | int n; |
| 206 | Blob title; |
| 207 | Blob sql; |
| 208 | GraphContext *pGraph; |
| 209 | |
| 210 | login_check_credentials(); |
| 211 | if( !g.okRead ){ login_needed(); return; } |
| 212 | style_header("File History"); |
| 213 | login_anonymous_available(); |
| 214 | |
| 215 | zPrevDate[0] = 0; |
| 216 | zFilename = PD("name",""); |
| 217 | blob_zero(&sql); |
| 218 | blob_appendf(&sql, |
| 219 | "SELECT" |
| 220 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 221 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 222 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 223 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | |
| 228 | " event.bgcolor," /* Background color */ |
| 229 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 230 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 231 | " FROM mlink, event" |
| 232 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 233 | " AND event.objid=mlink.mid", |
| 234 | TAG_BRANCH, |
| 235 | zFilename |
| 236 | ); |
| 237 | if( (zA = P("a"))!=0 ){ |
| 238 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); |
| 239 | } |
| 240 | if( (zB = P("b"))!=0 ){ |
| 241 | blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB); |
| 242 | } |
| 243 | blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); |
| 244 | if( (n = atoi(PD("n","0")))>0 ){ |
| 245 | blob_appendf(&sql, " LIMIT %d", n); |
| 246 | } |
| 247 | db_prepare(&q, blob_str(&sql)); |
| 248 | blob_reset(&sql); |
| 249 | blob_zero(&title); |
| 250 | blob_appendf(&title, "History of "); |
| 251 | hyperlinked_path(zFilename, &title, 0); |
| 252 | @ <h2>%b(&title)</h2> |
| 253 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | |
| 268 | int gidx; |
| 269 | char zTime[10]; |
| 270 | char zShort[20]; |
| 271 | char zShortCkin[20]; |
| 272 | if( zBr==0 ) zBr = "trunk"; |
| 273 | gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0); |
| 274 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 275 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 276 | @ <tr><td> |
| 277 | @ <div class="divider">%s(zPrevDate)</div> |
| 278 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | |
| 313 | } |
| 314 | @ </td></tr> |
| 315 | } |
| 316 | db_finalize(&q); |
| 317 | if( pGraph ){ |
| 318 | graph_finish(pGraph, 0); |
| 319 | if( pGraph->nErr ){ |
| 320 | graph_free(pGraph); |
| 321 | pGraph = 0; |
| 322 | }else{ |
| 323 | @ <tr><td></td><td> |
| 324 | @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 325 | @ </td></tr> |
| 326 | } |
| 327 | } |
| 328 | @ </table> |
| 329 | timeline_output_graph_javascript(pGraph, 0); |
| 330 | style_footer(); |
| 331 | } |
| 332 |
+31
-8
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -186,27 +186,38 @@ | ||
| 186 | 186 | |
| 187 | 187 | /* |
| 188 | 188 | ** WEBPAGE: finfo |
| 189 | 189 | ** URL: /finfo?name=FILENAME |
| 190 | 190 | ** |
| 191 | -** Show the complete change history for a single file. | |
| 191 | +** Show the change history for a single file. | |
| 192 | +** | |
| 193 | +** Additional query parameters: | |
| 194 | +** | |
| 195 | +** a=DATE Only show changes after DATE | |
| 196 | +** b=DATE Only show changes before DATE | |
| 197 | +** n=NUM Show the first NUM changes only | |
| 192 | 198 | */ |
| 193 | 199 | void finfo_page(void){ |
| 194 | 200 | Stmt q; |
| 195 | 201 | const char *zFilename; |
| 196 | 202 | char zPrevDate[20]; |
| 203 | + const char *zA; | |
| 204 | + const char *zB; | |
| 205 | + int n; | |
| 197 | 206 | Blob title; |
| 207 | + Blob sql; | |
| 198 | 208 | GraphContext *pGraph; |
| 199 | 209 | |
| 200 | 210 | login_check_credentials(); |
| 201 | 211 | if( !g.okRead ){ login_needed(); return; } |
| 202 | 212 | style_header("File History"); |
| 203 | 213 | login_anonymous_available(); |
| 204 | 214 | |
| 205 | 215 | zPrevDate[0] = 0; |
| 206 | 216 | zFilename = PD("name",""); |
| 207 | - db_prepare(&q, | |
| 217 | + blob_zero(&sql); | |
| 218 | + blob_appendf(&sql, | |
| 208 | 219 | "SELECT" |
| 209 | 220 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 210 | 221 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 211 | 222 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 212 | 223 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | ||
| 217 | 228 | " event.bgcolor," /* Background color */ |
| 218 | 229 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 219 | 230 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 220 | 231 | " FROM mlink, event" |
| 221 | 232 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 222 | - " AND event.objid=mlink.mid" | |
| 223 | - " ORDER BY event.mtime DESC /*sort*/", | |
| 233 | + " AND event.objid=mlink.mid", | |
| 224 | 234 | TAG_BRANCH, |
| 225 | 235 | zFilename |
| 226 | 236 | ); |
| 237 | + if( (zA = P("a"))!=0 ){ | |
| 238 | + blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); | |
| 239 | + } | |
| 240 | + if( (zB = P("b"))!=0 ){ | |
| 241 | + blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB); | |
| 242 | + } | |
| 243 | + blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); | |
| 244 | + if( (n = atoi(PD("n","0")))>0 ){ | |
| 245 | + blob_appendf(&sql, " LIMIT %d", n); | |
| 246 | + } | |
| 247 | + db_prepare(&q, blob_str(&sql)); | |
| 248 | + blob_reset(&sql); | |
| 227 | 249 | blob_zero(&title); |
| 228 | 250 | blob_appendf(&title, "History of "); |
| 229 | 251 | hyperlinked_path(zFilename, &title, 0); |
| 230 | 252 | @ <h2>%b(&title)</h2> |
| 231 | 253 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | ||
| 246 | 268 | int gidx; |
| 247 | 269 | char zTime[10]; |
| 248 | 270 | char zShort[20]; |
| 249 | 271 | char zShortCkin[20]; |
| 250 | 272 | if( zBr==0 ) zBr = "trunk"; |
| 251 | - gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1); | |
| 273 | + gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0); | |
| 252 | 274 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 253 | 275 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 254 | 276 | @ <tr><td> |
| 255 | 277 | @ <div class="divider">%s(zPrevDate)</div> |
| 256 | 278 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | ||
| 291 | 313 | } |
| 292 | 314 | @ </td></tr> |
| 293 | 315 | } |
| 294 | 316 | db_finalize(&q); |
| 295 | 317 | if( pGraph ){ |
| 296 | - graph_finish(pGraph, 1); | |
| 318 | + graph_finish(pGraph, 0); | |
| 297 | 319 | if( pGraph->nErr ){ |
| 298 | 320 | graph_free(pGraph); |
| 299 | 321 | pGraph = 0; |
| 300 | 322 | }else{ |
| 301 | - @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> | |
| 323 | + @ <tr><td></td><td> | |
| 324 | + @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> | |
| 302 | 325 | @ </td></tr> |
| 303 | 326 | } |
| 304 | 327 | } |
| 305 | 328 | @ </table> |
| 306 | - timeline_output_graph_javascript(pGraph, 1); | |
| 329 | + timeline_output_graph_javascript(pGraph, 0); | |
| 307 | 330 | style_footer(); |
| 308 | 331 | } |
| 309 | 332 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -186,27 +186,38 @@ | |
| 186 | |
| 187 | /* |
| 188 | ** WEBPAGE: finfo |
| 189 | ** URL: /finfo?name=FILENAME |
| 190 | ** |
| 191 | ** Show the complete change history for a single file. |
| 192 | */ |
| 193 | void finfo_page(void){ |
| 194 | Stmt q; |
| 195 | const char *zFilename; |
| 196 | char zPrevDate[20]; |
| 197 | Blob title; |
| 198 | GraphContext *pGraph; |
| 199 | |
| 200 | login_check_credentials(); |
| 201 | if( !g.okRead ){ login_needed(); return; } |
| 202 | style_header("File History"); |
| 203 | login_anonymous_available(); |
| 204 | |
| 205 | zPrevDate[0] = 0; |
| 206 | zFilename = PD("name",""); |
| 207 | db_prepare(&q, |
| 208 | "SELECT" |
| 209 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 210 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 211 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 212 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | |
| 217 | " event.bgcolor," /* Background color */ |
| 218 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 219 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 220 | " FROM mlink, event" |
| 221 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 222 | " AND event.objid=mlink.mid" |
| 223 | " ORDER BY event.mtime DESC /*sort*/", |
| 224 | TAG_BRANCH, |
| 225 | zFilename |
| 226 | ); |
| 227 | blob_zero(&title); |
| 228 | blob_appendf(&title, "History of "); |
| 229 | hyperlinked_path(zFilename, &title, 0); |
| 230 | @ <h2>%b(&title)</h2> |
| 231 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | |
| 246 | int gidx; |
| 247 | char zTime[10]; |
| 248 | char zShort[20]; |
| 249 | char zShortCkin[20]; |
| 250 | if( zBr==0 ) zBr = "trunk"; |
| 251 | gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 1); |
| 252 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 253 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 254 | @ <tr><td> |
| 255 | @ <div class="divider">%s(zPrevDate)</div> |
| 256 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | |
| 291 | } |
| 292 | @ </td></tr> |
| 293 | } |
| 294 | db_finalize(&q); |
| 295 | if( pGraph ){ |
| 296 | graph_finish(pGraph, 1); |
| 297 | if( pGraph->nErr ){ |
| 298 | graph_free(pGraph); |
| 299 | pGraph = 0; |
| 300 | }else{ |
| 301 | @ <tr><td></td><td><div style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 302 | @ </td></tr> |
| 303 | } |
| 304 | } |
| 305 | @ </table> |
| 306 | timeline_output_graph_javascript(pGraph, 1); |
| 307 | style_footer(); |
| 308 | } |
| 309 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -186,27 +186,38 @@ | |
| 186 | |
| 187 | /* |
| 188 | ** WEBPAGE: finfo |
| 189 | ** URL: /finfo?name=FILENAME |
| 190 | ** |
| 191 | ** Show the change history for a single file. |
| 192 | ** |
| 193 | ** Additional query parameters: |
| 194 | ** |
| 195 | ** a=DATE Only show changes after DATE |
| 196 | ** b=DATE Only show changes before DATE |
| 197 | ** n=NUM Show the first NUM changes only |
| 198 | */ |
| 199 | void finfo_page(void){ |
| 200 | Stmt q; |
| 201 | const char *zFilename; |
| 202 | char zPrevDate[20]; |
| 203 | const char *zA; |
| 204 | const char *zB; |
| 205 | int n; |
| 206 | Blob title; |
| 207 | Blob sql; |
| 208 | GraphContext *pGraph; |
| 209 | |
| 210 | login_check_credentials(); |
| 211 | if( !g.okRead ){ login_needed(); return; } |
| 212 | style_header("File History"); |
| 213 | login_anonymous_available(); |
| 214 | |
| 215 | zPrevDate[0] = 0; |
| 216 | zFilename = PD("name",""); |
| 217 | blob_zero(&sql); |
| 218 | blob_appendf(&sql, |
| 219 | "SELECT" |
| 220 | " datetime(event.mtime,'localtime')," /* Date of change */ |
| 221 | " coalesce(event.ecomment, event.comment)," /* Check-in comment */ |
| 222 | " coalesce(event.euser, event.user)," /* User who made chng */ |
| 223 | " mlink.pid," /* Parent rid */ |
| @@ -217,15 +228,26 @@ | |
| 228 | " event.bgcolor," /* Background color */ |
| 229 | " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0" |
| 230 | " AND tagxref.rid=mlink.mid)" /* Tags */ |
| 231 | " FROM mlink, event" |
| 232 | " WHERE mlink.fnid=(SELECT fnid FROM filename WHERE name=%Q)" |
| 233 | " AND event.objid=mlink.mid", |
| 234 | TAG_BRANCH, |
| 235 | zFilename |
| 236 | ); |
| 237 | if( (zA = P("a"))!=0 ){ |
| 238 | blob_appendf(&sql, " AND event.mtime>=julianday('%q')", zA); |
| 239 | } |
| 240 | if( (zB = P("b"))!=0 ){ |
| 241 | blob_appendf(&sql, " AND event.mtime<=julianday('%q')", zB); |
| 242 | } |
| 243 | blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); |
| 244 | if( (n = atoi(PD("n","0")))>0 ){ |
| 245 | blob_appendf(&sql, " LIMIT %d", n); |
| 246 | } |
| 247 | db_prepare(&q, blob_str(&sql)); |
| 248 | blob_reset(&sql); |
| 249 | blob_zero(&title); |
| 250 | blob_appendf(&title, "History of "); |
| 251 | hyperlinked_path(zFilename, &title, 0); |
| 252 | @ <h2>%b(&title)</h2> |
| 253 | blob_reset(&title); |
| @@ -246,11 +268,11 @@ | |
| 268 | int gidx; |
| 269 | char zTime[10]; |
| 270 | char zShort[20]; |
| 271 | char zShortCkin[20]; |
| 272 | if( zBr==0 ) zBr = "trunk"; |
| 273 | gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr, 0); |
| 274 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 275 | sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate); |
| 276 | @ <tr><td> |
| 277 | @ <div class="divider">%s(zPrevDate)</div> |
| 278 | @ </td></tr> |
| @@ -291,18 +313,19 @@ | |
| 313 | } |
| 314 | @ </td></tr> |
| 315 | } |
| 316 | db_finalize(&q); |
| 317 | if( pGraph ){ |
| 318 | graph_finish(pGraph, 0); |
| 319 | if( pGraph->nErr ){ |
| 320 | graph_free(pGraph); |
| 321 | pGraph = 0; |
| 322 | }else{ |
| 323 | @ <tr><td></td><td> |
| 324 | @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 325 | @ </td></tr> |
| 326 | } |
| 327 | } |
| 328 | @ </table> |
| 329 | timeline_output_graph_javascript(pGraph, 0); |
| 330 | style_footer(); |
| 331 | } |
| 332 |
+34
-14
| --- src/graph.c | ||
| +++ src/graph.c | ||
| @@ -306,20 +306,35 @@ | ||
| 306 | 306 | } |
| 307 | 307 | } |
| 308 | 308 | pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; |
| 309 | 309 | } |
| 310 | 310 | |
| 311 | +/* | |
| 312 | +** Compute the maximum rail number. | |
| 313 | +*/ | |
| 314 | +static void find_max_rail(GraphContext *p){ | |
| 315 | + GraphRow *pRow; | |
| 316 | + p->mxRail = 0; | |
| 317 | + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ | |
| 318 | + if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; | |
| 319 | + if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; | |
| 320 | + while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ | |
| 321 | + p->mxRail++; | |
| 322 | + } | |
| 323 | + } | |
| 324 | +} | |
| 325 | + | |
| 311 | 326 | |
| 312 | 327 | /* |
| 313 | 328 | ** Compute the complete graph |
| 314 | 329 | */ |
| 315 | 330 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 316 | 331 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 317 | 332 | int i; |
| 318 | 333 | u32 mask; |
| 319 | 334 | u32 inUse; |
| 320 | - int hasDup = 0; /* True if one or more isDup entries */ | |
| 335 | + int hasDup = 0; /* True if one or more isDup entries */ | |
| 321 | 336 | const char *zTrunk; |
| 322 | 337 | |
| 323 | 338 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 324 | 339 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 325 | 340 | |
| @@ -390,10 +405,11 @@ | ||
| 390 | 405 | ** Strive to put the "trunk" branch on far left. |
| 391 | 406 | */ |
| 392 | 407 | zTrunk = persistBranchName(p, "trunk"); |
| 393 | 408 | for(i=0; i<2; i++){ |
| 394 | 409 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 410 | + if( pRow->isDup ) continue; | |
| 395 | 411 | if( i==0 ){ |
| 396 | 412 | if( pRow->zBranch!=zTrunk ) continue; |
| 397 | 413 | }else { |
| 398 | 414 | if( pRow->iRail>=0 ) continue; |
| 399 | 415 | } |
| @@ -435,14 +451,11 @@ | ||
| 435 | 451 | } |
| 436 | 452 | } |
| 437 | 453 | continue; |
| 438 | 454 | } |
| 439 | 455 | if( pRow->isDup ){ |
| 440 | - pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0); | |
| 441 | - if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 442 | - pDesc = pRow; | |
| 443 | - pParent = 0; | |
| 456 | + continue; | |
| 444 | 457 | }else{ |
| 445 | 458 | assert( pRow->nParent>0 ); |
| 446 | 459 | parentRid = pRow->aParent[0]; |
| 447 | 460 | pParent = hashFind(p, parentRid); |
| 448 | 461 | if( pParent==0 ){ |
| @@ -515,27 +528,34 @@ | ||
| 515 | 528 | |
| 516 | 529 | /* |
| 517 | 530 | ** Insert merge rails from primaries to duplicates. |
| 518 | 531 | */ |
| 519 | 532 | if( hasDup ){ |
| 533 | + int dupRail; | |
| 534 | + int mxRail; | |
| 535 | + find_max_rail(p); | |
| 536 | + mxRail = p->mxRail; | |
| 537 | + dupRail = mxRail+1; | |
| 538 | + if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 520 | 539 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 521 | 540 | if( !pRow->isDup ) continue; |
| 541 | + pRow->iRail = dupRail; | |
| 522 | 542 | pDesc = hashFind(p, pRow->rid); |
| 523 | 543 | assert( pDesc!=0 && pDesc!=pRow ); |
| 524 | 544 | createMergeRiser(p, pDesc, pRow); |
| 545 | + if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4; | |
| 546 | + } | |
| 547 | + if( dupRail<=mxRail ){ | |
| 548 | + dupRail = mxRail+1; | |
| 549 | + for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ | |
| 550 | + if( pRow->isDup ) pRow->iRail = dupRail; | |
| 551 | + } | |
| 525 | 552 | } |
| 526 | - if( p->mxRail>=GR_MAX_RAIL ) return; | |
| 553 | + if( mxRail>=GR_MAX_RAIL ) return; | |
| 527 | 554 | } |
| 528 | 555 | |
| 529 | 556 | /* |
| 530 | 557 | ** Find the maximum rail number. |
| 531 | 558 | */ |
| 532 | - p->mxRail = 0; | |
| 533 | - for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ | |
| 534 | - if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; | |
| 535 | - if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; | |
| 536 | - while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ | |
| 537 | - p->mxRail++; | |
| 538 | - } | |
| 539 | - } | |
| 559 | + find_max_rail(p); | |
| 540 | 560 | p->nErr = 0; |
| 541 | 561 | } |
| 542 | 562 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -306,20 +306,35 @@ | |
| 306 | } |
| 307 | } |
| 308 | pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; |
| 309 | } |
| 310 | |
| 311 | |
| 312 | /* |
| 313 | ** Compute the complete graph |
| 314 | */ |
| 315 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 316 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 317 | int i; |
| 318 | u32 mask; |
| 319 | u32 inUse; |
| 320 | int hasDup = 0; /* True if one or more isDup entries */ |
| 321 | const char *zTrunk; |
| 322 | |
| 323 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 324 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 325 | |
| @@ -390,10 +405,11 @@ | |
| 390 | ** Strive to put the "trunk" branch on far left. |
| 391 | */ |
| 392 | zTrunk = persistBranchName(p, "trunk"); |
| 393 | for(i=0; i<2; i++){ |
| 394 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 395 | if( i==0 ){ |
| 396 | if( pRow->zBranch!=zTrunk ) continue; |
| 397 | }else { |
| 398 | if( pRow->iRail>=0 ) continue; |
| 399 | } |
| @@ -435,14 +451,11 @@ | |
| 435 | } |
| 436 | } |
| 437 | continue; |
| 438 | } |
| 439 | if( pRow->isDup ){ |
| 440 | pRow->iRail = findFreeRail(p, pRow->idx, pRow->idx, inUse, 0); |
| 441 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 442 | pDesc = pRow; |
| 443 | pParent = 0; |
| 444 | }else{ |
| 445 | assert( pRow->nParent>0 ); |
| 446 | parentRid = pRow->aParent[0]; |
| 447 | pParent = hashFind(p, parentRid); |
| 448 | if( pParent==0 ){ |
| @@ -515,27 +528,34 @@ | |
| 515 | |
| 516 | /* |
| 517 | ** Insert merge rails from primaries to duplicates. |
| 518 | */ |
| 519 | if( hasDup ){ |
| 520 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 521 | if( !pRow->isDup ) continue; |
| 522 | pDesc = hashFind(p, pRow->rid); |
| 523 | assert( pDesc!=0 && pDesc!=pRow ); |
| 524 | createMergeRiser(p, pDesc, pRow); |
| 525 | } |
| 526 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 527 | } |
| 528 | |
| 529 | /* |
| 530 | ** Find the maximum rail number. |
| 531 | */ |
| 532 | p->mxRail = 0; |
| 533 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 534 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 535 | if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; |
| 536 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 537 | p->mxRail++; |
| 538 | } |
| 539 | } |
| 540 | p->nErr = 0; |
| 541 | } |
| 542 |
| --- src/graph.c | |
| +++ src/graph.c | |
| @@ -306,20 +306,35 @@ | |
| 306 | } |
| 307 | } |
| 308 | pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1; |
| 309 | } |
| 310 | |
| 311 | /* |
| 312 | ** Compute the maximum rail number. |
| 313 | */ |
| 314 | static void find_max_rail(GraphContext *p){ |
| 315 | GraphRow *pRow; |
| 316 | p->mxRail = 0; |
| 317 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 318 | if( pRow->iRail>p->mxRail ) p->mxRail = pRow->iRail; |
| 319 | if( pRow->mergeOut/4>p->mxRail ) p->mxRail = pRow->mergeOut/4; |
| 320 | while( p->mxRail<GR_MAX_RAIL && pRow->mergeDown>((1<<(p->mxRail+1))-1) ){ |
| 321 | p->mxRail++; |
| 322 | } |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | |
| 327 | /* |
| 328 | ** Compute the complete graph |
| 329 | */ |
| 330 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 331 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 332 | int i; |
| 333 | u32 mask; |
| 334 | u32 inUse; |
| 335 | int hasDup = 0; /* True if one or more isDup entries */ |
| 336 | const char *zTrunk; |
| 337 | |
| 338 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 339 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 340 | |
| @@ -390,10 +405,11 @@ | |
| 405 | ** Strive to put the "trunk" branch on far left. |
| 406 | */ |
| 407 | zTrunk = persistBranchName(p, "trunk"); |
| 408 | for(i=0; i<2; i++){ |
| 409 | for(pRow=p->pLast; pRow; pRow=pRow->pPrev){ |
| 410 | if( pRow->isDup ) continue; |
| 411 | if( i==0 ){ |
| 412 | if( pRow->zBranch!=zTrunk ) continue; |
| 413 | }else { |
| 414 | if( pRow->iRail>=0 ) continue; |
| 415 | } |
| @@ -435,14 +451,11 @@ | |
| 451 | } |
| 452 | } |
| 453 | continue; |
| 454 | } |
| 455 | if( pRow->isDup ){ |
| 456 | continue; |
| 457 | }else{ |
| 458 | assert( pRow->nParent>0 ); |
| 459 | parentRid = pRow->aParent[0]; |
| 460 | pParent = hashFind(p, parentRid); |
| 461 | if( pParent==0 ){ |
| @@ -515,27 +528,34 @@ | |
| 528 | |
| 529 | /* |
| 530 | ** Insert merge rails from primaries to duplicates. |
| 531 | */ |
| 532 | if( hasDup ){ |
| 533 | int dupRail; |
| 534 | int mxRail; |
| 535 | find_max_rail(p); |
| 536 | mxRail = p->mxRail; |
| 537 | dupRail = mxRail+1; |
| 538 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 539 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 540 | if( !pRow->isDup ) continue; |
| 541 | pRow->iRail = dupRail; |
| 542 | pDesc = hashFind(p, pRow->rid); |
| 543 | assert( pDesc!=0 && pDesc!=pRow ); |
| 544 | createMergeRiser(p, pDesc, pRow); |
| 545 | if( pDesc->mergeOut/4>mxRail ) mxRail = pDesc->mergeOut/4; |
| 546 | } |
| 547 | if( dupRail<=mxRail ){ |
| 548 | dupRail = mxRail+1; |
| 549 | for(pRow=p->pFirst; pRow; pRow=pRow->pNext){ |
| 550 | if( pRow->isDup ) pRow->iRail = dupRail; |
| 551 | } |
| 552 | } |
| 553 | if( mxRail>=GR_MAX_RAIL ) return; |
| 554 | } |
| 555 | |
| 556 | /* |
| 557 | ** Find the maximum rail number. |
| 558 | */ |
| 559 | find_max_rail(p); |
| 560 | p->nErr = 0; |
| 561 | } |
| 562 |
+1
-1
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -407,11 +407,11 @@ | ||
| 407 | 407 | |
| 408 | 408 | /* |
| 409 | 409 | ** Malloc and free routines that cannot fail |
| 410 | 410 | */ |
| 411 | 411 | void *fossil_malloc(size_t n){ |
| 412 | - void *p = malloc(n); | |
| 412 | + void *p = malloc(n==0 ? 1 : n); | |
| 413 | 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | 414 | return p; |
| 415 | 415 | } |
| 416 | 416 | void fossil_free(void *p){ |
| 417 | 417 | free(p); |
| 418 | 418 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* |
| 409 | ** Malloc and free routines that cannot fail |
| 410 | */ |
| 411 | void *fossil_malloc(size_t n){ |
| 412 | void *p = malloc(n); |
| 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | return p; |
| 415 | } |
| 416 | void fossil_free(void *p){ |
| 417 | free(p); |
| 418 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* |
| 409 | ** Malloc and free routines that cannot fail |
| 410 | */ |
| 411 | void *fossil_malloc(size_t n){ |
| 412 | void *p = malloc(n==0 ? 1 : n); |
| 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | return p; |
| 415 | } |
| 416 | void fossil_free(void *p){ |
| 417 | free(p); |
| 418 |
+1
-1
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -407,11 +407,11 @@ | ||
| 407 | 407 | |
| 408 | 408 | /* |
| 409 | 409 | ** Malloc and free routines that cannot fail |
| 410 | 410 | */ |
| 411 | 411 | void *fossil_malloc(size_t n){ |
| 412 | - void *p = malloc(n); | |
| 412 | + void *p = malloc(n==0 ? 1 : n); | |
| 413 | 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | 414 | return p; |
| 415 | 415 | } |
| 416 | 416 | void fossil_free(void *p){ |
| 417 | 417 | free(p); |
| 418 | 418 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* |
| 409 | ** Malloc and free routines that cannot fail |
| 410 | */ |
| 411 | void *fossil_malloc(size_t n){ |
| 412 | void *p = malloc(n); |
| 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | return p; |
| 415 | } |
| 416 | void fossil_free(void *p){ |
| 417 | free(p); |
| 418 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -407,11 +407,11 @@ | |
| 407 | |
| 408 | /* |
| 409 | ** Malloc and free routines that cannot fail |
| 410 | */ |
| 411 | void *fossil_malloc(size_t n){ |
| 412 | void *p = malloc(n==0 ? 1 : n); |
| 413 | if( p==0 ) fossil_panic("out of memory"); |
| 414 | return p; |
| 415 | } |
| 416 | void fossil_free(void *p){ |
| 417 | free(p); |
| 418 |