Fossil SCM

Pull the latest changes from trunk into windows-i18n.

drh 2011-05-12 12:14 windows-i18n merge
Commit f25b6c00c8c77799a687a9953034f1ff51d593d1
+26 -11
--- src/descendants.c
+++ src/descendants.c
@@ -159,60 +159,75 @@
159159
** the "ok" table.
160160
*/
161161
void compute_ancestors(int rid, int N){
162162
Bag seen;
163163
PQueue queue;
164
+ Stmt ins;
165
+ Stmt q;
164166
bag_init(&seen);
165167
pqueue_init(&queue);
166168
bag_insert(&seen, rid);
167169
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
+ );
168175
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);
175180
while( db_step(&q)==SQLITE_ROW ){
176181
int pid = db_column_int(&q, 0);
177182
double mtime = db_column_double(&q, 1);
178183
if( bag_insert(&seen, pid) ){
179184
pqueue_insert(&queue, pid, -mtime, 0);
180185
}
181186
}
182
- db_finalize(&q);
187
+ db_reset(&q);
183188
}
184189
bag_clear(&seen);
185190
pqueue_clear(&queue);
191
+ db_finalize(&ins);
192
+ db_finalize(&q);
186193
}
187194
188195
/*
189196
** Load the record ID rid and up to N-1 closest descendants into
190197
** the "ok" table.
191198
*/
192199
void compute_descendants(int rid, int N){
193200
Bag seen;
194201
PQueue queue;
202
+ Stmt ins;
203
+ Stmt q;
204
+
195205
bag_init(&seen);
196206
pqueue_init(&queue);
197207
bag_insert(&seen, rid);
198208
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");
199211
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);
203216
while( db_step(&q)==SQLITE_ROW ){
204217
int pid = db_column_int(&q, 0);
205218
double mtime = db_column_double(&q, 1);
206219
if( bag_insert(&seen, pid) ){
207220
pqueue_insert(&queue, pid, mtime, 0);
208221
}
209222
}
210
- db_finalize(&q);
223
+ db_reset(&q);
211224
}
212225
bag_clear(&seen);
213226
pqueue_clear(&queue);
227
+ db_finalize(&ins);
228
+ db_finalize(&q);
214229
}
215230
216231
/*
217232
** COMMAND: descendants
218233
**
219234
--- 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 @@
747747
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
748748
fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
749749
}
750750
}
751751
752
+/* Annotation flags */
753
+#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
754
+
752755
/*
753756
** Compute a complete annotation on a file. The file is identified
754757
** by its filename number (filename.fnid) and the baseline in which
755758
** it was checked in (mlink.mid).
756759
*/
@@ -757,11 +760,12 @@
757760
static void annotate_file(
758761
Annotator *p, /* The annotator */
759762
int fnid, /* The name of the file to be annotated */
760763
int mid, /* The specific version of the file for this step */
761764
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 */
763767
){
764768
Blob toAnnotate; /* Text of the final version of the file */
765769
Blob step; /* Text of previous revision */
766770
int rid; /* Artifact ID of the file being annotated */
767771
char *zLabel; /* Label to apply to a line */
@@ -778,19 +782,21 @@
778782
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
779783
compute_ancestors(mid, 1000000000);
780784
annotation_start(p, &toAnnotate);
781785
782786
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), "
784790
" coalesce(event.euser,event.user) "
785
- " FROM mlink, blob, event"
791
+ " FROM mlink, event"
786792
" WHERE mlink.fnid=%d"
787793
" AND mlink.mid IN ok"
788
- " AND blob.rid=mlink.mid"
789794
" AND event.objid=mlink.mid"
790795
" ORDER BY event.mtime DESC"
791796
" LIMIT %d",
797
+ (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
792798
fnid,
793799
iLimit>0 ? iLimit : 10000000
794800
);
795801
while( db_step(&q)==SQLITE_ROW ){
796802
int pid = db_column_int(&q, 0);
@@ -826,10 +832,11 @@
826832
void annotation_page(void){
827833
int mid;
828834
int fnid;
829835
int i;
830836
int iLimit;
837
+ int annFlags = 0;
831838
Annotator ann;
832839
833840
login_check_credentials();
834841
if( !g.okRead ){ login_needed(); return; }
835842
mid = name_to_rid(PD("checkin","0"));
@@ -838,11 +845,12 @@
838845
iLimit = atoi(PD("limit","-1"));
839846
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
840847
fossil_redirect_home();
841848
}
842849
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);
844852
if( P("log") ){
845853
int i;
846854
@ <h2>Versions analyzed:</h2>
847855
@ <ol>
848856
for(i=0; i<ann.nVers; i++){
@@ -870,10 +878,11 @@
870878
** the file was last modified.
871879
**
872880
** Options:
873881
** --limit N Only look backwards in time by N versions
874882
** --log List all versions analyzed
883
+** --filevers Show file version numbers rather than check-in versions
875884
*/
876885
void annotate_cmd(void){
877886
int fnid; /* Filename ID */
878887
int fid; /* File instance ID */
879888
int mid; /* Manifest where file was checked in */
@@ -882,15 +891,18 @@
882891
Annotator ann; /* The annotation of the file */
883892
int i; /* Loop counter */
884893
const char *zLimit; /* The value to the --limit option */
885894
int iLimit; /* How far back in time to look */
886895
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 */
887898
888899
zLimit = find_option("limit",0,1);
889900
if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
890901
iLimit = atoi(zLimit);
891902
showLog = find_option("log",0,0)!=0;
903
+ fileVers = find_option("filevers",0,0)!=0;
892904
db_must_be_within_tree();
893905
if (g.argc<3) {
894906
usage("FILENAME");
895907
}
896908
file_tree_name(g.argv[2], &treename, 1);
@@ -905,11 +917,12 @@
905917
}
906918
mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
907919
if( mid==0 ){
908920
fossil_panic("unable to find manifest");
909921
}
910
- annotate_file(&ann, fnid, mid, 0, iLimit);
922
+ if( fileVers ) annFlags |= ANN_FILE_VERS;
923
+ annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
911924
if( showLog ){
912925
for(i=0; i<ann.nVers; i++){
913926
printf("version %3d: %s\n", i+1, ann.azVers[i]);
914927
}
915928
printf("---------------------------------------------------\n");
916929
--- 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 @@
747747
if( zSrc==0 ) zSrc = g.argv[g.argc-1];
748748
fossil_print("%10s: %.*s\n", zSrc, x.aOrig[i].n, x.aOrig[i].z);
749749
}
750750
}
751751
752
+/* Annotation flags */
753
+#define ANN_FILE_VERS 0x001 /* Show file version rather than commit version */
754
+
752755
/*
753756
** Compute a complete annotation on a file. The file is identified
754757
** by its filename number (filename.fnid) and the baseline in which
755758
** it was checked in (mlink.mid).
756759
*/
@@ -757,11 +760,12 @@
757760
static void annotate_file(
758761
Annotator *p, /* The annotator */
759762
int fnid, /* The name of the file to be annotated */
760763
int mid, /* The specific version of the file for this step */
761764
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 */
763767
){
764768
Blob toAnnotate; /* Text of the final version of the file */
765769
Blob step; /* Text of previous revision */
766770
int rid; /* Artifact ID of the file being annotated */
767771
char *zLabel; /* Label to apply to a line */
@@ -778,19 +782,21 @@
778782
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
779783
compute_ancestors(mid, 1000000000);
780784
annotation_start(p, &toAnnotate);
781785
782786
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), "
784790
" coalesce(event.euser,event.user) "
785
- " FROM mlink, blob, event"
791
+ " FROM mlink, event"
786792
" WHERE mlink.fnid=%d"
787793
" AND mlink.mid IN ok"
788
- " AND blob.rid=mlink.mid"
789794
" AND event.objid=mlink.mid"
790795
" ORDER BY event.mtime DESC"
791796
" LIMIT %d",
797
+ (annFlags & ANN_FILE_VERS)!=0 ? "fid" : "mid",
792798
fnid,
793799
iLimit>0 ? iLimit : 10000000
794800
);
795801
while( db_step(&q)==SQLITE_ROW ){
796802
int pid = db_column_int(&q, 0);
@@ -826,10 +832,11 @@
826832
void annotation_page(void){
827833
int mid;
828834
int fnid;
829835
int i;
830836
int iLimit;
837
+ int annFlags = 0;
831838
Annotator ann;
832839
833840
login_check_credentials();
834841
if( !g.okRead ){ login_needed(); return; }
835842
mid = name_to_rid(PD("checkin","0"));
@@ -838,11 +845,12 @@
838845
iLimit = atoi(PD("limit","-1"));
839846
if( !db_exists("SELECT 1 FROM mlink WHERE mid=%d AND fnid=%d",mid,fnid) ){
840847
fossil_redirect_home();
841848
}
842849
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);
844852
if( P("log") ){
845853
int i;
846854
@ <h2>Versions analyzed:</h2>
847855
@ <ol>
848856
for(i=0; i<ann.nVers; i++){
@@ -870,10 +878,11 @@
870878
** the file was last modified.
871879
**
872880
** Options:
873881
** --limit N Only look backwards in time by N versions
874882
** --log List all versions analyzed
883
+** --filevers Show file version numbers rather than check-in versions
875884
*/
876885
void annotate_cmd(void){
877886
int fnid; /* Filename ID */
878887
int fid; /* File instance ID */
879888
int mid; /* Manifest where file was checked in */
@@ -882,15 +891,18 @@
882891
Annotator ann; /* The annotation of the file */
883892
int i; /* Loop counter */
884893
const char *zLimit; /* The value to the --limit option */
885894
int iLimit; /* How far back in time to look */
886895
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 */
887898
888899
zLimit = find_option("limit",0,1);
889900
if( zLimit==0 || zLimit[0]==0 ) zLimit = "-1";
890901
iLimit = atoi(zLimit);
891902
showLog = find_option("log",0,0)!=0;
903
+ fileVers = find_option("filevers",0,0)!=0;
892904
db_must_be_within_tree();
893905
if (g.argc<3) {
894906
usage("FILENAME");
895907
}
896908
file_tree_name(g.argv[2], &treename, 1);
@@ -905,11 +917,12 @@
905917
}
906918
mid = db_int(0, "SELECT mid FROM mlink WHERE fid=%d AND fnid=%d", fid, fnid);
907919
if( mid==0 ){
908920
fossil_panic("unable to find manifest");
909921
}
910
- annotate_file(&ann, fnid, mid, 0, iLimit);
922
+ if( fileVers ) annFlags |= ANN_FILE_VERS;
923
+ annotate_file(&ann, fnid, mid, 0, iLimit, annFlags);
911924
if( showLog ){
912925
for(i=0; i<ann.nVers; i++){
913926
printf("version %3d: %s\n", i+1, ann.azVers[i]);
914927
}
915928
printf("---------------------------------------------------\n");
916929
--- 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 @@
186186
187187
/*
188188
** WEBPAGE: finfo
189189
** URL: /finfo?name=FILENAME
190190
**
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
192198
*/
193199
void finfo_page(void){
194200
Stmt q;
195201
const char *zFilename;
196202
char zPrevDate[20];
203
+ const char *zA;
204
+ const char *zB;
205
+ int n;
197206
Blob title;
207
+ Blob sql;
198208
GraphContext *pGraph;
199209
200210
login_check_credentials();
201211
if( !g.okRead ){ login_needed(); return; }
202212
style_header("File History");
203213
login_anonymous_available();
204214
205215
zPrevDate[0] = 0;
206216
zFilename = PD("name","");
207
- db_prepare(&q,
217
+ blob_zero(&sql);
218
+ blob_appendf(&sql,
208219
"SELECT"
209220
" datetime(event.mtime,'localtime')," /* Date of change */
210221
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
211222
" coalesce(event.euser, event.user)," /* User who made chng */
212223
" mlink.pid," /* Parent rid */
@@ -217,15 +228,26 @@
217228
" event.bgcolor," /* Background color */
218229
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
219230
" AND tagxref.rid=mlink.mid)" /* Tags */
220231
" FROM mlink, event"
221232
" 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",
224234
TAG_BRANCH,
225235
zFilename
226236
);
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);
227249
blob_zero(&title);
228250
blob_appendf(&title, "History of ");
229251
hyperlinked_path(zFilename, &title, 0);
230252
@ <h2>%b(&title)</h2>
231253
blob_reset(&title);
@@ -246,11 +268,11 @@
246268
int gidx;
247269
char zTime[10];
248270
char zShort[20];
249271
char zShortCkin[20];
250272
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);
252274
if( memcmp(zDate, zPrevDate, 10) ){
253275
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254276
@ <tr><td>
255277
@ <div class="divider">%s(zPrevDate)</div>
256278
@ </td></tr>
@@ -291,18 +313,19 @@
291313
}
292314
@ </td></tr>
293315
}
294316
db_finalize(&q);
295317
if( pGraph ){
296
- graph_finish(pGraph, 1);
318
+ graph_finish(pGraph, 0);
297319
if( pGraph->nErr ){
298320
graph_free(pGraph);
299321
pGraph = 0;
300322
}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>
302325
@ </td></tr>
303326
}
304327
}
305328
@ </table>
306
- timeline_output_graph_javascript(pGraph, 1);
329
+ timeline_output_graph_javascript(pGraph, 0);
307330
style_footer();
308331
}
309332
--- 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 @@
186186
187187
/*
188188
** WEBPAGE: finfo
189189
** URL: /finfo?name=FILENAME
190190
**
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
192198
*/
193199
void finfo_page(void){
194200
Stmt q;
195201
const char *zFilename;
196202
char zPrevDate[20];
203
+ const char *zA;
204
+ const char *zB;
205
+ int n;
197206
Blob title;
207
+ Blob sql;
198208
GraphContext *pGraph;
199209
200210
login_check_credentials();
201211
if( !g.okRead ){ login_needed(); return; }
202212
style_header("File History");
203213
login_anonymous_available();
204214
205215
zPrevDate[0] = 0;
206216
zFilename = PD("name","");
207
- db_prepare(&q,
217
+ blob_zero(&sql);
218
+ blob_appendf(&sql,
208219
"SELECT"
209220
" datetime(event.mtime,'localtime')," /* Date of change */
210221
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
211222
" coalesce(event.euser, event.user)," /* User who made chng */
212223
" mlink.pid," /* Parent rid */
@@ -217,15 +228,26 @@
217228
" event.bgcolor," /* Background color */
218229
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
219230
" AND tagxref.rid=mlink.mid)" /* Tags */
220231
" FROM mlink, event"
221232
" 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",
224234
TAG_BRANCH,
225235
zFilename
226236
);
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);
227249
blob_zero(&title);
228250
blob_appendf(&title, "History of ");
229251
hyperlinked_path(zFilename, &title, 0);
230252
@ <h2>%b(&title)</h2>
231253
blob_reset(&title);
@@ -246,11 +268,11 @@
246268
int gidx;
247269
char zTime[10];
248270
char zShort[20];
249271
char zShortCkin[20];
250272
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);
252274
if( memcmp(zDate, zPrevDate, 10) ){
253275
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
254276
@ <tr><td>
255277
@ <div class="divider">%s(zPrevDate)</div>
256278
@ </td></tr>
@@ -291,18 +313,19 @@
291313
}
292314
@ </td></tr>
293315
}
294316
db_finalize(&q);
295317
if( pGraph ){
296
- graph_finish(pGraph, 1);
318
+ graph_finish(pGraph, 0);
297319
if( pGraph->nErr ){
298320
graph_free(pGraph);
299321
pGraph = 0;
300322
}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>
302325
@ </td></tr>
303326
}
304327
}
305328
@ </table>
306
- timeline_output_graph_javascript(pGraph, 1);
329
+ timeline_output_graph_javascript(pGraph, 0);
307330
style_footer();
308331
}
309332
--- 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 @@
306306
}
307307
}
308308
pChild->mergeIn[pParent->mergeOut/4] = (pParent->mergeOut&3)+1;
309309
}
310310
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
+
311326
312327
/*
313328
** Compute the complete graph
314329
*/
315330
void graph_finish(GraphContext *p, int omitDescenders){
316331
GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent;
317332
int i;
318333
u32 mask;
319334
u32 inUse;
320
- int hasDup = 0; /* True if one or more isDup entries */
335
+ int hasDup = 0; /* True if one or more isDup entries */
321336
const char *zTrunk;
322337
323338
if( p==0 || p->pFirst==0 || p->nErr ) return;
324339
p->nErr = 1; /* Assume an error until proven otherwise */
325340
@@ -390,10 +405,11 @@
390405
** Strive to put the "trunk" branch on far left.
391406
*/
392407
zTrunk = persistBranchName(p, "trunk");
393408
for(i=0; i<2; i++){
394409
for(pRow=p->pLast; pRow; pRow=pRow->pPrev){
410
+ if( pRow->isDup ) continue;
395411
if( i==0 ){
396412
if( pRow->zBranch!=zTrunk ) continue;
397413
}else {
398414
if( pRow->iRail>=0 ) continue;
399415
}
@@ -435,14 +451,11 @@
435451
}
436452
}
437453
continue;
438454
}
439455
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;
444457
}else{
445458
assert( pRow->nParent>0 );
446459
parentRid = pRow->aParent[0];
447460
pParent = hashFind(p, parentRid);
448461
if( pParent==0 ){
@@ -515,27 +528,34 @@
515528
516529
/*
517530
** Insert merge rails from primaries to duplicates.
518531
*/
519532
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;
520539
for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
521540
if( !pRow->isDup ) continue;
541
+ pRow->iRail = dupRail;
522542
pDesc = hashFind(p, pRow->rid);
523543
assert( pDesc!=0 && pDesc!=pRow );
524544
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
+ }
525552
}
526
- if( p->mxRail>=GR_MAX_RAIL ) return;
553
+ if( mxRail>=GR_MAX_RAIL ) return;
527554
}
528555
529556
/*
530557
** Find the maximum rail number.
531558
*/
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);
540560
p->nErr = 0;
541561
}
542562
--- 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 @@
407407
408408
/*
409409
** Malloc and free routines that cannot fail
410410
*/
411411
void *fossil_malloc(size_t n){
412
- void *p = malloc(n);
412
+ void *p = malloc(n==0 ? 1 : n);
413413
if( p==0 ) fossil_panic("out of memory");
414414
return p;
415415
}
416416
void fossil_free(void *p){
417417
free(p);
418418
--- 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 @@
407407
408408
/*
409409
** Malloc and free routines that cannot fail
410410
*/
411411
void *fossil_malloc(size_t n){
412
- void *p = malloc(n);
412
+ void *p = malloc(n==0 ? 1 : n);
413413
if( p==0 ) fossil_panic("out of memory");
414414
return p;
415415
}
416416
void fossil_free(void *p){
417417
free(p);
418418
--- 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

Keyboard Shortcuts

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