Fossil SCM

Merge trunk

baruch 2015-01-28 11:17 svn-import merge
Commit 4aa351bba8350caf1ad11b11b64f23c2c450216e
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-1.30
1
+1.31
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.30
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.31
2
--- skins/eagle/footer.txt
+++ skins/eagle/footer.txt
@@ -11,14 +11,15 @@
1111
return [string range $version 1 [expr {$length - 2}]]
1212
}
1313
set version [getVersion $manifest_version]
1414
set tclVersion [getTclVersion]
1515
set fossilUrl https://www.fossil-scm.org
16
+ set fossilDate [string range $manifest_date 0 9]T[string range $manifest_date 11 end]
1617
</th1>
1718
This page was generated in about
1819
<th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
1920
<a href="$fossilUrl/">Fossil</a>
2021
version $release_version $tclVersion
2122
<a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
22
- <a href="$fossilUrl/index.html/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
23
+ <a href="$fossilUrl/index.html/timeline?c=$fossilDate&amp;y=ci">$manifest_date</a>
2324
</div>
2425
</body></html>
2526
--- skins/eagle/footer.txt
+++ skins/eagle/footer.txt
@@ -11,14 +11,15 @@
11 return [string range $version 1 [expr {$length - 2}]]
12 }
13 set version [getVersion $manifest_version]
14 set tclVersion [getTclVersion]
15 set fossilUrl https://www.fossil-scm.org
 
16 </th1>
17 This page was generated in about
18 <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
19 <a href="$fossilUrl/">Fossil</a>
20 version $release_version $tclVersion
21 <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
22 <a href="$fossilUrl/index.html/timeline?c=$manifest_date&amp;y=ci">$manifest_date</a>
23 </div>
24 </body></html>
25
--- skins/eagle/footer.txt
+++ skins/eagle/footer.txt
@@ -11,14 +11,15 @@
11 return [string range $version 1 [expr {$length - 2}]]
12 }
13 set version [getVersion $manifest_version]
14 set tclVersion [getTclVersion]
15 set fossilUrl https://www.fossil-scm.org
16 set fossilDate [string range $manifest_date 0 9]T[string range $manifest_date 11 end]
17 </th1>
18 This page was generated in about
19 <th1>puts [expr {([utime]+[stime]+1000)/1000*0.001}]</th1>s by
20 <a href="$fossilUrl/">Fossil</a>
21 version $release_version $tclVersion
22 <a href="$fossilUrl/index.html/info/$version">$manifest_version</a>
23 <a href="$fossilUrl/index.html/timeline?c=$fossilDate&amp;y=ci">$manifest_date</a>
24 </div>
25 </body></html>
26
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -73,11 +73,11 @@
7373
<a href="$logourl">
7474
<img src="$logo_image_url" border="0" alt="$project_name">
7575
</a>
7676
</div>
7777
<div class="title">$<title></div>
78
- <div class="status"><th1>
78
+ <div class="status"><nobr><th1>
7979
if {[info exists login]} {
8080
puts "Logged in as $login"
8181
} else {
8282
puts "Not logged in"
8383
}
@@ -86,12 +86,19 @@
8686
<script>
8787
function updateClock(){
8888
var e = document.getElementById("clock");
8989
if(e){
9090
var d = new Date();
91
- e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
92
- setTimeout("updateClock();",(60-d.getSeconds())*1000);
91
+ function f(n) {
92
+ return n < 10 ? '0' + n : n;
93
+ }
94
+ e.innerHTML = d.getUTCFullYear()+ '-' +
95
+ f(d.getUTCMonth() + 1) + '-' +
96
+ f(d.getUTCDate()) + ' ' +
97
+ f(d.getUTCHours()) + ':' +
98
+ f(d.getUTCMinutes());
99
+ setTimeout("updateClock();",(60-d.getUTCSeconds())*1000);
93100
}
94101
}
95102
updateClock();
96103
</script>
97104
<div class="mainmenu">
98105
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -73,11 +73,11 @@
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
75 </a>
76 </div>
77 <div class="title">$<title></div>
78 <div class="status"><th1>
79 if {[info exists login]} {
80 puts "Logged in as $login"
81 } else {
82 puts "Not logged in"
83 }
@@ -86,12 +86,19 @@
86 <script>
87 function updateClock(){
88 var e = document.getElementById("clock");
89 if(e){
90 var d = new Date();
91 e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
92 setTimeout("updateClock();",(60-d.getSeconds())*1000);
 
 
 
 
 
 
 
93 }
94 }
95 updateClock();
96 </script>
97 <div class="mainmenu">
98
--- skins/eagle/header.txt
+++ skins/eagle/header.txt
@@ -73,11 +73,11 @@
73 <a href="$logourl">
74 <img src="$logo_image_url" border="0" alt="$project_name">
75 </a>
76 </div>
77 <div class="title">$<title></div>
78 <div class="status"><nobr><th1>
79 if {[info exists login]} {
80 puts "Logged in as $login"
81 } else {
82 puts "Not logged in"
83 }
@@ -86,12 +86,19 @@
86 <script>
87 function updateClock(){
88 var e = document.getElementById("clock");
89 if(e){
90 var d = new Date();
91 function f(n) {
92 return n < 10 ? '0' + n : n;
93 }
94 e.innerHTML = d.getUTCFullYear()+ '-' +
95 f(d.getUTCMonth() + 1) + '-' +
96 f(d.getUTCDate()) + ' ' +
97 f(d.getUTCHours()) + ':' +
98 f(d.getUTCMinutes());
99 setTimeout("updateClock();",(60-d.getUTCSeconds())*1000);
100 }
101 }
102 updateClock();
103 </script>
104 <div class="mainmenu">
105
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -86,12 +86,19 @@
8686
<script>
8787
function updateClock(){
8888
var e = document.getElementById("clock");
8989
if(e){
9090
var d = new Date();
91
- e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
92
- setTimeout("updateClock();",(60-d.getSeconds())*1000);
91
+ function f(n) {
92
+ return n < 10 ? '0' + n : n;
93
+ }
94
+ e.innerHTML = d.getUTCFullYear()+ '-' +
95
+ f(d.getUTCMonth() + 1) + '-' +
96
+ f(d.getUTCDate()) + ' ' +
97
+ f(d.getUTCHours()) + ':' +
98
+ f(d.getUTCMinutes());
99
+ setTimeout("updateClock();",(60-d.getUTCSeconds())*1000);
93100
}
94101
}
95102
updateClock();
96103
</script>
97104
<div class="mainmenu">
98105
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -86,12 +86,19 @@
86 <script>
87 function updateClock(){
88 var e = document.getElementById("clock");
89 if(e){
90 var d = new Date();
91 e.innerHTML=d.toISOString().replace("T"," ").replace(/:\d\d\.\d+Z/,"");
92 setTimeout("updateClock();",(60-d.getSeconds())*1000);
 
 
 
 
 
 
 
93 }
94 }
95 updateClock();
96 </script>
97 <div class="mainmenu">
98
--- skins/enhanced1/header.txt
+++ skins/enhanced1/header.txt
@@ -86,12 +86,19 @@
86 <script>
87 function updateClock(){
88 var e = document.getElementById("clock");
89 if(e){
90 var d = new Date();
91 function f(n) {
92 return n < 10 ? '0' + n : n;
93 }
94 e.innerHTML = d.getUTCFullYear()+ '-' +
95 f(d.getUTCMonth() + 1) + '-' +
96 f(d.getUTCDate()) + ' ' +
97 f(d.getUTCHours()) + ':' +
98 f(d.getUTCMinutes());
99 setTimeout("updateClock();",(60-d.getUTCSeconds())*1000);
100 }
101 }
102 updateClock();
103 </script>
104 <div class="mainmenu">
105
--- skins/etienne1/css.txt
+++ skins/etienne1/css.txt
@@ -30,10 +30,44 @@
3030
.title h1:after {
3131
content: " / ";
3232
color: #777;
3333
font-weight: normal;
3434
}
35
+
36
+.content h1 {
37
+ font-size: 1.25em;
38
+}
39
+.content h2 {
40
+ font-size: 1.15em;
41
+}
42
+.content h2 {
43
+ font-size: 1.05em;
44
+ font-weight: bold;
45
+}
46
+
47
+.section {
48
+ font-size: 1em;
49
+ font-weight: bold;
50
+ background-color: #f5f5f5;
51
+ border: 1px solid #d8d8d8;
52
+ border-radius: 3px 3px 0 0;
53
+ padding: 9px 10px 10px;
54
+ margin: 10px 0;
55
+}
56
+
57
+.sectionmenu {
58
+ border: 1px solid #d8d8d8;
59
+ border-radius: 0 0 3px 3px;
60
+ border-top: 0;
61
+ margin-top: -10px;
62
+ margin-bottom: 10px;
63
+ padding: 10px;
64
+}
65
+.sectionmenu a {
66
+ display: inline-block;
67
+ margin-right: 1em;
68
+}
3569
3670
.status {
3771
float:right;
3872
font-size:.7em;
3973
padding-top:50px;
@@ -80,11 +114,11 @@
80114
border-top-right-radius: 5px;
81115
}
82116
83117
.content {
84118
padding-top: 10px;
85
- font-size:.9em;
119
+ font-size:.8em;
86120
color: #444;
87121
}
88122
89123
.udiff, .sbsdiff,
90124
.content blockquote {
91125
--- skins/etienne1/css.txt
+++ skins/etienne1/css.txt
@@ -30,10 +30,44 @@
30 .title h1:after {
31 content: " / ";
32 color: #777;
33 font-weight: normal;
34 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36 .status {
37 float:right;
38 font-size:.7em;
39 padding-top:50px;
@@ -80,11 +114,11 @@
80 border-top-right-radius: 5px;
81 }
82
83 .content {
84 padding-top: 10px;
85 font-size:.9em;
86 color: #444;
87 }
88
89 .udiff, .sbsdiff,
90 .content blockquote {
91
--- skins/etienne1/css.txt
+++ skins/etienne1/css.txt
@@ -30,10 +30,44 @@
30 .title h1:after {
31 content: " / ";
32 color: #777;
33 font-weight: normal;
34 }
35
36 .content h1 {
37 font-size: 1.25em;
38 }
39 .content h2 {
40 font-size: 1.15em;
41 }
42 .content h2 {
43 font-size: 1.05em;
44 font-weight: bold;
45 }
46
47 .section {
48 font-size: 1em;
49 font-weight: bold;
50 background-color: #f5f5f5;
51 border: 1px solid #d8d8d8;
52 border-radius: 3px 3px 0 0;
53 padding: 9px 10px 10px;
54 margin: 10px 0;
55 }
56
57 .sectionmenu {
58 border: 1px solid #d8d8d8;
59 border-radius: 0 0 3px 3px;
60 border-top: 0;
61 margin-top: -10px;
62 margin-bottom: 10px;
63 padding: 10px;
64 }
65 .sectionmenu a {
66 display: inline-block;
67 margin-right: 1em;
68 }
69
70 .status {
71 float:right;
72 font-size:.7em;
73 padding-top:50px;
@@ -80,11 +114,11 @@
114 border-top-right-radius: 5px;
115 }
116
117 .content {
118 padding-top: 10px;
119 font-size:.8em;
120 color: #444;
121 }
122
123 .udiff, .sbsdiff,
124 .content blockquote {
125
+2 -2
--- src/branch.c
+++ src/branch.c
@@ -302,11 +302,11 @@
302302
fossil_fatal("branch subcommand should be one of: "
303303
"new list ls");
304304
}
305305
}
306306
307
-static char brlistQuery[] =
307
+static const char brlistQuery[] =
308308
@ SELECT
309309
@ tagxref.value,
310310
@ max(event.mtime),
311311
@ EXISTS(SELECT 1 FROM tagxref AS tx
312312
@ WHERE tx.rid=tagxref.rid
@@ -343,11 +343,11 @@
343343
login_check_credentials();
344344
if( !g.perm.Read ){ login_needed(); return; }
345345
style_header("Branches");
346346
style_adunit_config(ADUNIT_RIGHT_OK);
347347
login_anonymous_available();
348
-
348
+
349349
db_prepare(&q, brlistQuery/*works-like:""*/);
350350
rNow = db_double(0.0, "SELECT julianday('now')");
351351
@ <div class="brlist"><table id="branchlisttable">
352352
@ <thead><tr>
353353
@ <th>Branch Name</th>
354354
--- src/branch.c
+++ src/branch.c
@@ -302,11 +302,11 @@
302 fossil_fatal("branch subcommand should be one of: "
303 "new list ls");
304 }
305 }
306
307 static char brlistQuery[] =
308 @ SELECT
309 @ tagxref.value,
310 @ max(event.mtime),
311 @ EXISTS(SELECT 1 FROM tagxref AS tx
312 @ WHERE tx.rid=tagxref.rid
@@ -343,11 +343,11 @@
343 login_check_credentials();
344 if( !g.perm.Read ){ login_needed(); return; }
345 style_header("Branches");
346 style_adunit_config(ADUNIT_RIGHT_OK);
347 login_anonymous_available();
348
349 db_prepare(&q, brlistQuery/*works-like:""*/);
350 rNow = db_double(0.0, "SELECT julianday('now')");
351 @ <div class="brlist"><table id="branchlisttable">
352 @ <thead><tr>
353 @ <th>Branch Name</th>
354
--- src/branch.c
+++ src/branch.c
@@ -302,11 +302,11 @@
302 fossil_fatal("branch subcommand should be one of: "
303 "new list ls");
304 }
305 }
306
307 static const char brlistQuery[] =
308 @ SELECT
309 @ tagxref.value,
310 @ max(event.mtime),
311 @ EXISTS(SELECT 1 FROM tagxref AS tx
312 @ WHERE tx.rid=tagxref.rid
@@ -343,11 +343,11 @@
343 login_check_credentials();
344 if( !g.perm.Read ){ login_needed(); return; }
345 style_header("Branches");
346 style_adunit_config(ADUNIT_RIGHT_OK);
347 login_anonymous_available();
348
349 db_prepare(&q, brlistQuery/*works-like:""*/);
350 rNow = db_double(0.0, "SELECT julianday('now')");
351 @ <div class="brlist"><table id="branchlisttable">
352 @ <thead><tr>
353 @ <th>Branch Name</th>
354
+3 -3
--- src/browse.c
+++ src/browse.c
@@ -888,11 +888,11 @@
888888
889889
/*
890890
** SQL used to compute the age of all files in checkin :ckin whose
891891
** names match :glob
892892
*/
893
-static const char zComputeFileAgeSetup[] =
893
+static const char zComputeFileAgeSetup[] =
894894
@ CREATE TABLE IF NOT EXISTS temp.fileage(
895895
@ fnid INTEGER PRIMARY KEY,
896896
@ fid INTEGER,
897897
@ mid INTEGER,
898898
@ mtime DATETIME,
@@ -899,11 +899,11 @@
899899
@ pathname TEXT
900900
@ );
901901
@ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
902902
;
903903
904
-static const char zComputeFileAgeRun[] =
904
+static const char zComputeFileAgeRun[] =
905905
@ WITH RECURSIVE
906906
@ ckin(x) AS (VALUES(:ckin) UNION ALL
907907
@ SELECT pid FROM ckin, plink WHERE cid=x AND isprim)
908908
@ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
909909
@ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name
@@ -1025,11 +1025,11 @@
10251025
style_header("File Ages");
10261026
zGlob = P("glob");
10271027
compute_fileage(rid,zGlob);
10281028
db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
10291029
1030
- @ <h2>Files in
1030
+ @ <h2>Files in
10311031
@ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a>
10321032
if( zGlob && zGlob[0] ){
10331033
@ that match "%h(zGlob)" and
10341034
}
10351035
@ ordered by check-in time</h2>
10361036
--- src/browse.c
+++ src/browse.c
@@ -888,11 +888,11 @@
888
889 /*
890 ** SQL used to compute the age of all files in checkin :ckin whose
891 ** names match :glob
892 */
893 static const char zComputeFileAgeSetup[] =
894 @ CREATE TABLE IF NOT EXISTS temp.fileage(
895 @ fnid INTEGER PRIMARY KEY,
896 @ fid INTEGER,
897 @ mid INTEGER,
898 @ mtime DATETIME,
@@ -899,11 +899,11 @@
899 @ pathname TEXT
900 @ );
901 @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
902 ;
903
904 static const char zComputeFileAgeRun[] =
905 @ WITH RECURSIVE
906 @ ckin(x) AS (VALUES(:ckin) UNION ALL
907 @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim)
908 @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
909 @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name
@@ -1025,11 +1025,11 @@
1025 style_header("File Ages");
1026 zGlob = P("glob");
1027 compute_fileage(rid,zGlob);
1028 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1029
1030 @ <h2>Files in
1031 @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a>
1032 if( zGlob && zGlob[0] ){
1033 @ that match "%h(zGlob)" and
1034 }
1035 @ ordered by check-in time</h2>
1036
--- src/browse.c
+++ src/browse.c
@@ -888,11 +888,11 @@
888
889 /*
890 ** SQL used to compute the age of all files in checkin :ckin whose
891 ** names match :glob
892 */
893 static const char zComputeFileAgeSetup[] =
894 @ CREATE TABLE IF NOT EXISTS temp.fileage(
895 @ fnid INTEGER PRIMARY KEY,
896 @ fid INTEGER,
897 @ mid INTEGER,
898 @ mtime DATETIME,
@@ -899,11 +899,11 @@
899 @ pathname TEXT
900 @ );
901 @ CREATE VIRTUAL TABLE IF NOT EXISTS temp.foci USING files_of_checkin;
902 ;
903
904 static const char zComputeFileAgeRun[] =
905 @ WITH RECURSIVE
906 @ ckin(x) AS (VALUES(:ckin) UNION ALL
907 @ SELECT pid FROM ckin, plink WHERE cid=x AND isprim)
908 @ INSERT OR IGNORE INTO fileage(fnid, fid, mid, mtime, pathname)
909 @ SELECT mlink.fnid, mlink.fid, x, event.mtime, filename.name
@@ -1025,11 +1025,11 @@
1025 style_header("File Ages");
1026 zGlob = P("glob");
1027 compute_fileage(rid,zGlob);
1028 db_multi_exec("CREATE INDEX fileage_ix1 ON fileage(mid,pathname);");
1029
1030 @ <h2>Files in
1031 @ %z(href("%R/info?name=%T",zUuid))[%S(zUuid)]</a>
1032 if( zGlob && zGlob[0] ){
1033 @ that match "%h(zGlob)" and
1034 }
1035 @ ordered by check-in time</h2>
1036
+1 -1
--- src/cgi.c
+++ src/cgi.c
@@ -1756,11 +1756,11 @@
17561756
fd = dup(connection);
17571757
if( fd!=0 ) nErr++;
17581758
close(1);
17591759
fd = dup(connection);
17601760
if( fd!=1 ) nErr++;
1761
- if( !g.fHttpTrace && !g.fSqlTrace ){
1761
+ if( !g.fAnyTrace ){
17621762
close(2);
17631763
fd = dup(connection);
17641764
if( fd!=2 ) nErr++;
17651765
}
17661766
close(connection);
17671767
--- src/cgi.c
+++ src/cgi.c
@@ -1756,11 +1756,11 @@
1756 fd = dup(connection);
1757 if( fd!=0 ) nErr++;
1758 close(1);
1759 fd = dup(connection);
1760 if( fd!=1 ) nErr++;
1761 if( !g.fHttpTrace && !g.fSqlTrace ){
1762 close(2);
1763 fd = dup(connection);
1764 if( fd!=2 ) nErr++;
1765 }
1766 close(connection);
1767
--- src/cgi.c
+++ src/cgi.c
@@ -1756,11 +1756,11 @@
1756 fd = dup(connection);
1757 if( fd!=0 ) nErr++;
1758 close(1);
1759 fd = dup(connection);
1760 if( fd!=1 ) nErr++;
1761 if( !g.fAnyTrace ){
1762 close(2);
1763 fd = dup(connection);
1764 if( fd!=2 ) nErr++;
1765 }
1766 close(connection);
1767
+31 -5
--- src/db.c
+++ src/db.c
@@ -770,12 +770,12 @@
770770
void db_sym2rid_function(
771771
sqlite3_context *context,
772772
int argc,
773773
sqlite3_value **argv
774774
){
775
- char const * arg;
776
- char const * type;
775
+ const char *arg;
776
+ const char *type;
777777
if(1 != argc && 2 != argc){
778778
sqlite3_result_error(context, "Expecting one or two arguments", -1);
779779
return;
780780
}
781781
arg = (const char*)sqlite3_value_text(argv[0]);
@@ -795,11 +795,11 @@
795795
}
796796
}
797797
}
798798
799799
/*
800
-** Register the SQL functions that are useful both to the internal
800
+** Register the SQL functions that are useful both to the internal
801801
** representation and to the "fossil sql" command.
802802
*/
803803
void db_add_aux_functions(sqlite3 *db){
804804
sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
805805
db_checkin_mtime_function, 0, 0);
@@ -840,11 +840,11 @@
840840
);
841841
sqlite3_create_function(
842842
db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
843843
);
844844
if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
845
- db_add_aux_functions(db);
845
+ db_add_aux_functions(db);
846846
re_add_sql_func(db); /* The REGEXP operator */
847847
foci_register(db); /* The "files_of_checkin" virtual table */
848848
sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
849849
return db;
850850
}
@@ -1175,10 +1175,37 @@
11751175
g.zRepositoryName = mprintf("%s", zDbName);
11761176
db_open_or_attach(g.zRepositoryName, "repository", 0);
11771177
g.repositoryOpen = 1;
11781178
/* Cache "allow-symlinks" option, because we'll need it on every stat call */
11791179
g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
1180
+ g.zAuxSchema = db_get("aux-schema","");
1181
+
1182
+ /* Verify that the PLINK table has a new column added by the
1183
+ ** 2014-11-28 schema change. Create it if necessary. This code
1184
+ ** can be removed in the future, once all users have upgraded to the
1185
+ ** 2014-11-28 or later schema.
1186
+ */
1187
+ if( !db_table_has_column("repository","plink","baseid") ){
1188
+ db_multi_exec(
1189
+ "ALTER TABLE %s.plink ADD COLUMN baseid;", db_name("repository")
1190
+ );
1191
+ }
1192
+
1193
+ /* Verify that the MLINK table has the newer columns added by the
1194
+ ** 2015-01-24 schema change. Create them if necessary. This code
1195
+ ** can be removed in the future, once all users have upgraded to the
1196
+ ** 2015-01-24 or later schema.
1197
+ */
1198
+ if( !db_table_has_column("repository","mlink","isaux") ){
1199
+ db_begin_transaction();
1200
+ db_multi_exec(
1201
+ "ALTER TABLE %s.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1202
+ "ALTER TABLE %s.mlink ADD COLUMN isaux INTEGER DEFAULT 0;",
1203
+ db_name("repository"), db_name("repository")
1204
+ );
1205
+ db_end_transaction(0);
1206
+ }
11801207
}
11811208
11821209
/*
11831210
** Flags for the db_find_and_open_repository() function.
11841211
*/
@@ -1242,11 +1269,10 @@
12421269
12431270
/*
12441271
** Return TRUE if the schema is out-of-date
12451272
*/
12461273
int db_schema_is_outofdate(void){
1247
- if( g.zAuxSchema==0 ) g.zAuxSchema = db_get("aux-schema","");
12481274
return strcmp(g.zAuxSchema,AUX_SCHEMA_MIN)<0
12491275
|| strcmp(g.zAuxSchema,AUX_SCHEMA_MAX)>0;
12501276
}
12511277
12521278
/*
12531279
--- src/db.c
+++ src/db.c
@@ -770,12 +770,12 @@
770 void db_sym2rid_function(
771 sqlite3_context *context,
772 int argc,
773 sqlite3_value **argv
774 ){
775 char const * arg;
776 char const * type;
777 if(1 != argc && 2 != argc){
778 sqlite3_result_error(context, "Expecting one or two arguments", -1);
779 return;
780 }
781 arg = (const char*)sqlite3_value_text(argv[0]);
@@ -795,11 +795,11 @@
795 }
796 }
797 }
798
799 /*
800 ** Register the SQL functions that are useful both to the internal
801 ** representation and to the "fossil sql" command.
802 */
803 void db_add_aux_functions(sqlite3 *db){
804 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
805 db_checkin_mtime_function, 0, 0);
@@ -840,11 +840,11 @@
840 );
841 sqlite3_create_function(
842 db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
843 );
844 if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
845 db_add_aux_functions(db);
846 re_add_sql_func(db); /* The REGEXP operator */
847 foci_register(db); /* The "files_of_checkin" virtual table */
848 sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
849 return db;
850 }
@@ -1175,10 +1175,37 @@
1175 g.zRepositoryName = mprintf("%s", zDbName);
1176 db_open_or_attach(g.zRepositoryName, "repository", 0);
1177 g.repositoryOpen = 1;
1178 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1179 g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1180 }
1181
1182 /*
1183 ** Flags for the db_find_and_open_repository() function.
1184 */
@@ -1242,11 +1269,10 @@
1242
1243 /*
1244 ** Return TRUE if the schema is out-of-date
1245 */
1246 int db_schema_is_outofdate(void){
1247 if( g.zAuxSchema==0 ) g.zAuxSchema = db_get("aux-schema","");
1248 return strcmp(g.zAuxSchema,AUX_SCHEMA_MIN)<0
1249 || strcmp(g.zAuxSchema,AUX_SCHEMA_MAX)>0;
1250 }
1251
1252 /*
1253
--- src/db.c
+++ src/db.c
@@ -770,12 +770,12 @@
770 void db_sym2rid_function(
771 sqlite3_context *context,
772 int argc,
773 sqlite3_value **argv
774 ){
775 const char *arg;
776 const char *type;
777 if(1 != argc && 2 != argc){
778 sqlite3_result_error(context, "Expecting one or two arguments", -1);
779 return;
780 }
781 arg = (const char*)sqlite3_value_text(argv[0]);
@@ -795,11 +795,11 @@
795 }
796 }
797 }
798
799 /*
800 ** Register the SQL functions that are useful both to the internal
801 ** representation and to the "fossil sql" command.
802 */
803 void db_add_aux_functions(sqlite3 *db){
804 sqlite3_create_function(db, "checkin_mtime", 2, SQLITE_UTF8, 0,
805 db_checkin_mtime_function, 0, 0);
@@ -840,11 +840,11 @@
840 );
841 sqlite3_create_function(
842 db, "if_selected", 3, SQLITE_UTF8, 0, file_is_selected,0,0
843 );
844 if( g.fSqlTrace ) sqlite3_trace(db, db_sql_trace, 0);
845 db_add_aux_functions(db);
846 re_add_sql_func(db); /* The REGEXP operator */
847 foci_register(db); /* The "files_of_checkin" virtual table */
848 sqlite3_exec(db, "PRAGMA foreign_keys=OFF;", 0, 0, 0);
849 return db;
850 }
@@ -1175,10 +1175,37 @@
1175 g.zRepositoryName = mprintf("%s", zDbName);
1176 db_open_or_attach(g.zRepositoryName, "repository", 0);
1177 g.repositoryOpen = 1;
1178 /* Cache "allow-symlinks" option, because we'll need it on every stat call */
1179 g.allowSymlinks = db_get_boolean("allow-symlinks", 0);
1180 g.zAuxSchema = db_get("aux-schema","");
1181
1182 /* Verify that the PLINK table has a new column added by the
1183 ** 2014-11-28 schema change. Create it if necessary. This code
1184 ** can be removed in the future, once all users have upgraded to the
1185 ** 2014-11-28 or later schema.
1186 */
1187 if( !db_table_has_column("repository","plink","baseid") ){
1188 db_multi_exec(
1189 "ALTER TABLE %s.plink ADD COLUMN baseid;", db_name("repository")
1190 );
1191 }
1192
1193 /* Verify that the MLINK table has the newer columns added by the
1194 ** 2015-01-24 schema change. Create them if necessary. This code
1195 ** can be removed in the future, once all users have upgraded to the
1196 ** 2015-01-24 or later schema.
1197 */
1198 if( !db_table_has_column("repository","mlink","isaux") ){
1199 db_begin_transaction();
1200 db_multi_exec(
1201 "ALTER TABLE %s.mlink ADD COLUMN pmid INTEGER DEFAULT 0;"
1202 "ALTER TABLE %s.mlink ADD COLUMN isaux INTEGER DEFAULT 0;",
1203 db_name("repository"), db_name("repository")
1204 );
1205 db_end_transaction(0);
1206 }
1207 }
1208
1209 /*
1210 ** Flags for the db_find_and_open_repository() function.
1211 */
@@ -1242,11 +1269,10 @@
1269
1270 /*
1271 ** Return TRUE if the schema is out-of-date
1272 */
1273 int db_schema_is_outofdate(void){
 
1274 return strcmp(g.zAuxSchema,AUX_SCHEMA_MIN)<0
1275 || strcmp(g.zAuxSchema,AUX_SCHEMA_MAX)>0;
1276 }
1277
1278 /*
1279
+68 -54
--- src/finfo.c
+++ src/finfo.c
@@ -284,110 +284,92 @@
284284
** b=DATE Only show changes before DATE
285285
** n=NUM Show the first NUM changes only
286286
** brbg Background color by branch name
287287
** ubg Background color by user name
288288
** ci=UUID Ancestors of a particular check-in
289
-** fco=BOOL Show only first occurrence of each version if true (default)
290289
*/
291290
void finfo_page(void){
292291
Stmt q;
293292
const char *zFilename;
294293
char zPrevDate[20];
295294
const char *zA;
296295
const char *zB;
297296
int n;
298297
int baseCheckin;
299
-
298
+ int fnid;
299
+ Bag ancestor;
300300
Blob title;
301301
Blob sql;
302302
HQuery url;
303303
GraphContext *pGraph;
304304
int brBg = P("brbg")!=0;
305305
int uBg = P("ubg")!=0;
306
- int firstChngOnly = atoi(PD("fco","1"))!=0;
307306
int fDebug = atoi(PD("debug","0"));
307
+ int fShowId = P("showid")!=0;
308308
309309
login_check_credentials();
310310
if( !g.perm.Read ){ login_needed(); return; }
311311
style_header("File History");
312312
login_anonymous_available();
313313
url_initialize(&url, "finfo");
314314
if( brBg ) url_add_parameter(&url, "brbg", 0);
315315
if( uBg ) url_add_parameter(&url, "ubg", 0);
316316
baseCheckin = name_to_rid_www("ci");
317
- if( baseCheckin ) firstChngOnly = 1;
318
- if( !firstChngOnly ) url_add_parameter(&url, "fco", "0");
319
-
320317
zPrevDate[0] = 0;
321318
zFilename = PD("name","");
319
+ fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
320
+ if( fnid==0 ){
321
+ @ No such file: %h(zFilename)
322
+ style_footer();
323
+ return;
324
+ }
325
+ if( baseCheckin ){
326
+ int baseFid = db_int(0,
327
+ "SELECT fid FROM mlink WHERE fnid=%d AND mid=%d",
328
+ fnid, baseCheckin
329
+ );
330
+ bag_init(&ancestor);
331
+ if( baseFid ) bag_insert(&ancestor, baseFid);
332
+ }
322333
url_add_parameter(&url, "name", zFilename);
323334
blob_zero(&sql);
324335
blob_append_sql(&sql,
325336
"SELECT"
326
- " datetime(event.mtime%s)," /* Date of change */
337
+ " datetime(min(event.mtime)%s)," /* Date of change */
327338
" coalesce(event.ecomment, event.comment)," /* Check-in comment */
328339
" coalesce(event.euser, event.user)," /* User who made chng */
329340
" mlink.pid," /* Parent file rid */
330341
" mlink.fid," /* File rid */
331342
" (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
332343
" (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */
333344
" (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
334345
" event.bgcolor," /* Background color */
335346
" (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
336
- " AND tagxref.rid=mlink.mid)," /* Tags */
347
+ " AND tagxref.rid=mlink.mid)," /* Branchname */
337348
" mlink.mid," /* check-in ID */
338
- " mlink.pfnid", /* Previous filename */
339
- timeline_utc(), TAG_BRANCH
340
- );
341
- if( firstChngOnly ){
342
-#if 0
343
- blob_append_sql(&sql, ", min(event.mtime)");
344
-#else
345
- blob_append_sql(&sql,
346
- ", min(CASE (SELECT value FROM tagxref"
347
- " WHERE tagtype>0 AND tagid=%d"
348
- " AND tagxref.rid=mlink.mid)"
349
- " WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
350
- TAG_BRANCH);
351
-#endif
352
- }
353
- blob_append_sql(&sql,
349
+ " mlink.pfnid" /* Previous filename */
354350
" FROM mlink, event"
355
- " WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q)"
351
+ " WHERE mlink.fnid=%d"
356352
" AND event.objid=mlink.mid",
357
- zFilename
353
+ timeline_utc(), TAG_BRANCH, fnid
358354
);
359
- if( baseCheckin ){
360
- compute_direct_ancestors(baseCheckin, 10000000);
361
- blob_append_sql(&sql," AND mlink.mid IN (SELECT rid FROM ancestor)");
362
- }
363355
if( (zA = P("a"))!=0 ){
364356
blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zA);
365357
url_add_parameter(&url, "a", zA);
366358
}
367359
if( (zB = P("b"))!=0 ){
368360
blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB);
369361
url_add_parameter(&url, "b", zB);
370362
}
371
- if( firstChngOnly ){
372
- blob_append_sql(&sql, " GROUP BY mlink.fid");
373
- }
374
- blob_append_sql(&sql," ORDER BY event.mtime DESC /*sort*/");
363
+ blob_append_sql(&sql,
364
+ " GROUP BY mlink.fid"
365
+ " ORDER BY event.mtime DESC /*sort*/"
366
+ );
375367
if( (n = atoi(PD("n","0")))>0 ){
376368
blob_append_sql(&sql, " LIMIT %d", n);
377369
url_add_parameter(&url, "n", P("n"));
378370
}
379
- if( baseCheckin==0 ){
380
- if( firstChngOnly ){
381
- style_submenu_element("Full", "Show all changes","%s",
382
- url_render(&url, "fco", "0", 0, 0));
383
- }else{
384
- style_submenu_element("Simplified",
385
- "Show only first use of a change","%s",
386
- url_render(&url, "fco", 0, 0, 0));
387
- }
388
- }
389371
db_prepare(&q, "%s", blob_sql_text(&sql));
390372
if( P("showsql")!=0 ){
391373
@ <p>SQL: %h(blob_str(&sql))</p>
392374
}
393375
blob_reset(&sql);
@@ -395,15 +377,18 @@
395377
if( baseCheckin ){
396378
char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
397379
char *zLink = href("%R/info/%s", zUuid);
398380
blob_appendf(&title, "Ancestors of file ");
399381
hyperlinked_path(zFilename, &title, zUuid, "tree", "");
382
+ if( fShowId ) blob_appendf(&title, " (%d)", fnid);
400383
blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
384
+ if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
401385
fossil_free(zUuid);
402386
}else{
403387
blob_appendf(&title, "History of files named ");
404388
hyperlinked_path(zFilename, &title, 0, "tree", "");
389
+ if( fShowId ) blob_appendf(&title, " (%d)", fnid);
405390
}
406391
@ <h2>%b(&title)</h2>
407392
blob_reset(&title);
408393
pGraph = graph_init();
409394
@ <div id="canvas" style="position:relative;width:1px;height:1px;"
@@ -422,17 +407,36 @@
422407
const char *zBr = db_column_text(&q, 9);
423408
int fmid = db_column_int(&q, 10);
424409
int pfnid = db_column_int(&q, 11);
425410
int gidx;
426411
char zTime[10];
412
+ int nParent = 0;
413
+ int aParent[GR_MAX_RAIL];
414
+ static Stmt qparent;
415
+
416
+ if( baseCheckin && frid && !bag_find(&ancestor, frid) ) continue;
417
+ db_static_prepare(&qparent,
418
+ "SELECT DISTINCT pid FROM mlink"
419
+ " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid"
420
+ " ORDER BY isaux /*sort*/"
421
+ );
422
+ db_bind_int(&qparent, ":fid", frid);
423
+ db_bind_int(&qparent, ":mid", fmid);
424
+ db_bind_int(&qparent, ":fnid", fnid);
425
+ while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){
426
+ aParent[nParent] = db_column_int(&qparent, 0);
427
+ if( baseCheckin ) bag_insert(&ancestor, aParent[nParent]);
428
+ nParent++;
429
+ }
430
+ db_reset(&qparent);
427431
if( zBr==0 ) zBr = "trunk";
428432
if( uBg ){
429433
zBgClr = hash_color(zUser);
430434
}else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
431435
zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
432436
}
433
- gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,
437
+ gidx = graph_add_row(pGraph, frid, nParent, aParent, zBr, zBgClr,
434438
zUuid, 0);
435439
if( strncmp(zDate, zPrevDate, 10) ){
436440
sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
437441
@ <tr><td>
438442
@ <div class="divider">%s(zPrevDate)</div>
@@ -447,19 +451,23 @@
447451
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
448452
}else{
449453
@ <td class="timelineTableCell">
450454
}
451455
if( zUuid ){
452
- if( fpid==0 ){
456
+ if( nParent==0 ){
453457
@ <b>Added</b>
454458
}else if( pfnid ){
455459
char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
456460
pfnid);
457461
@ <b>Renamed</b> from
458462
@ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
459463
}
460
- @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in
464
+ @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a>
465
+ if( fShowId ){
466
+ @ (%d(frid))
467
+ }
468
+ @ part of check-in
461469
}else{
462470
char *zNewName;
463471
zNewName = db_text(0,
464472
"SELECT name FROM filename WHERE fnid = "
465473
" (SELECT fnid FROM mlink"
@@ -473,13 +481,16 @@
473481
}else{
474482
@ <b>Deleted</b> by check-in
475483
}
476484
}
477485
hyperlink_to_uuid(zCkin);
486
+ if( fShowId ){
487
+ @ (%d(fmid))
488
+ }
478489
@ %W(zCom) (user:
479490
hyperlink_to_user(zUser, zDate, "");
480
- @ branch: %h(zBr))
491
+ @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>
481492
if( g.perm.Hyperlink && zUuid ){
482493
const char *z = zFilename;
483494
@ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
484495
@ [annotate]</a>
485496
@ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
@@ -488,23 +499,26 @@
488499
if( fpid ){
489500
@ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
490501
}
491502
}
492503
if( fDebug & FINFO_DEBUG_MLINK ){
493
- int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
494
- int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
495
- @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
496
- if( srcid ){
497
- @ srcid=%d(srcid)
504
+ int ii;
505
+ @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
506
+ if( nParent>0 ){
507
+ @ parents=%d(aParent[0])
508
+ for(ii=1; ii<nParent; ii++){
509
+ @ %d(aParent[ii])
510
+ }
498511
}
512
+ @ %z(href("%R/finfo?name=%T&ci=%s&debug=1",zFilename,zCkin))[ancestry]</a>
499513
}
500514
tag_private_status(frid);
501515
@ </td></tr>
502516
}
503517
db_finalize(&q);
504518
if( pGraph ){
505
- graph_finish(pGraph, 0);
519
+ graph_finish(pGraph, 1);
506520
if( pGraph->nErr ){
507521
graph_free(pGraph);
508522
pGraph = 0;
509523
}else{
510524
int w = (pGraph->mxRail+1)*pGraph->iRailPitch + 10;
511525
--- src/finfo.c
+++ src/finfo.c
@@ -284,110 +284,92 @@
284 ** b=DATE Only show changes before DATE
285 ** n=NUM Show the first NUM changes only
286 ** brbg Background color by branch name
287 ** ubg Background color by user name
288 ** ci=UUID Ancestors of a particular check-in
289 ** fco=BOOL Show only first occurrence of each version if true (default)
290 */
291 void finfo_page(void){
292 Stmt q;
293 const char *zFilename;
294 char zPrevDate[20];
295 const char *zA;
296 const char *zB;
297 int n;
298 int baseCheckin;
299
 
300 Blob title;
301 Blob sql;
302 HQuery url;
303 GraphContext *pGraph;
304 int brBg = P("brbg")!=0;
305 int uBg = P("ubg")!=0;
306 int firstChngOnly = atoi(PD("fco","1"))!=0;
307 int fDebug = atoi(PD("debug","0"));
 
308
309 login_check_credentials();
310 if( !g.perm.Read ){ login_needed(); return; }
311 style_header("File History");
312 login_anonymous_available();
313 url_initialize(&url, "finfo");
314 if( brBg ) url_add_parameter(&url, "brbg", 0);
315 if( uBg ) url_add_parameter(&url, "ubg", 0);
316 baseCheckin = name_to_rid_www("ci");
317 if( baseCheckin ) firstChngOnly = 1;
318 if( !firstChngOnly ) url_add_parameter(&url, "fco", "0");
319
320 zPrevDate[0] = 0;
321 zFilename = PD("name","");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322 url_add_parameter(&url, "name", zFilename);
323 blob_zero(&sql);
324 blob_append_sql(&sql,
325 "SELECT"
326 " datetime(event.mtime%s)," /* Date of change */
327 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
328 " coalesce(event.euser, event.user)," /* User who made chng */
329 " mlink.pid," /* Parent file rid */
330 " mlink.fid," /* File rid */
331 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
332 " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */
333 " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
334 " event.bgcolor," /* Background color */
335 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
336 " AND tagxref.rid=mlink.mid)," /* Tags */
337 " mlink.mid," /* check-in ID */
338 " mlink.pfnid", /* Previous filename */
339 timeline_utc(), TAG_BRANCH
340 );
341 if( firstChngOnly ){
342 #if 0
343 blob_append_sql(&sql, ", min(event.mtime)");
344 #else
345 blob_append_sql(&sql,
346 ", min(CASE (SELECT value FROM tagxref"
347 " WHERE tagtype>0 AND tagid=%d"
348 " AND tagxref.rid=mlink.mid)"
349 " WHEN 'trunk' THEN event.mtime-10000 ELSE event.mtime END)",
350 TAG_BRANCH);
351 #endif
352 }
353 blob_append_sql(&sql,
354 " FROM mlink, event"
355 " WHERE mlink.fnid IN (SELECT fnid FROM filename WHERE name=%Q)"
356 " AND event.objid=mlink.mid",
357 zFilename
358 );
359 if( baseCheckin ){
360 compute_direct_ancestors(baseCheckin, 10000000);
361 blob_append_sql(&sql," AND mlink.mid IN (SELECT rid FROM ancestor)");
362 }
363 if( (zA = P("a"))!=0 ){
364 blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zA);
365 url_add_parameter(&url, "a", zA);
366 }
367 if( (zB = P("b"))!=0 ){
368 blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB);
369 url_add_parameter(&url, "b", zB);
370 }
371 if( firstChngOnly ){
372 blob_append_sql(&sql, " GROUP BY mlink.fid");
373 }
374 blob_append_sql(&sql," ORDER BY event.mtime DESC /*sort*/");
375 if( (n = atoi(PD("n","0")))>0 ){
376 blob_append_sql(&sql, " LIMIT %d", n);
377 url_add_parameter(&url, "n", P("n"));
378 }
379 if( baseCheckin==0 ){
380 if( firstChngOnly ){
381 style_submenu_element("Full", "Show all changes","%s",
382 url_render(&url, "fco", "0", 0, 0));
383 }else{
384 style_submenu_element("Simplified",
385 "Show only first use of a change","%s",
386 url_render(&url, "fco", 0, 0, 0));
387 }
388 }
389 db_prepare(&q, "%s", blob_sql_text(&sql));
390 if( P("showsql")!=0 ){
391 @ <p>SQL: %h(blob_str(&sql))</p>
392 }
393 blob_reset(&sql);
@@ -395,15 +377,18 @@
395 if( baseCheckin ){
396 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
397 char *zLink = href("%R/info/%s", zUuid);
398 blob_appendf(&title, "Ancestors of file ");
399 hyperlinked_path(zFilename, &title, zUuid, "tree", "");
 
400 blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
 
401 fossil_free(zUuid);
402 }else{
403 blob_appendf(&title, "History of files named ");
404 hyperlinked_path(zFilename, &title, 0, "tree", "");
 
405 }
406 @ <h2>%b(&title)</h2>
407 blob_reset(&title);
408 pGraph = graph_init();
409 @ <div id="canvas" style="position:relative;width:1px;height:1px;"
@@ -422,17 +407,36 @@
422 const char *zBr = db_column_text(&q, 9);
423 int fmid = db_column_int(&q, 10);
424 int pfnid = db_column_int(&q, 11);
425 int gidx;
426 char zTime[10];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427 if( zBr==0 ) zBr = "trunk";
428 if( uBg ){
429 zBgClr = hash_color(zUser);
430 }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
431 zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
432 }
433 gidx = graph_add_row(pGraph, frid, fpid>0 ? 1 : 0, &fpid, zBr, zBgClr,
434 zUuid, 0);
435 if( strncmp(zDate, zPrevDate, 10) ){
436 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
437 @ <tr><td>
438 @ <div class="divider">%s(zPrevDate)</div>
@@ -447,19 +451,23 @@
447 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
448 }else{
449 @ <td class="timelineTableCell">
450 }
451 if( zUuid ){
452 if( fpid==0 ){
453 @ <b>Added</b>
454 }else if( pfnid ){
455 char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
456 pfnid);
457 @ <b>Renamed</b> from
458 @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
459 }
460 @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a> part of check-in
 
 
 
 
461 }else{
462 char *zNewName;
463 zNewName = db_text(0,
464 "SELECT name FROM filename WHERE fnid = "
465 " (SELECT fnid FROM mlink"
@@ -473,13 +481,16 @@
473 }else{
474 @ <b>Deleted</b> by check-in
475 }
476 }
477 hyperlink_to_uuid(zCkin);
 
 
 
478 @ %W(zCom) (user:
479 hyperlink_to_user(zUser, zDate, "");
480 @ branch: %h(zBr))
481 if( g.perm.Hyperlink && zUuid ){
482 const char *z = zFilename;
483 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
484 @ [annotate]</a>
485 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
@@ -488,23 +499,26 @@
488 if( fpid ){
489 @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
490 }
491 }
492 if( fDebug & FINFO_DEBUG_MLINK ){
493 int srcid = db_int(0, "SELECT srcid FROM delta WHERE rid=%d", frid);
494 int sz = db_int(0, "SELECT length(content) FROM blob WHERE rid=%d", frid);
495 @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid) sz=%d(sz)
496 if( srcid ){
497 @ srcid=%d(srcid)
 
 
498 }
 
499 }
500 tag_private_status(frid);
501 @ </td></tr>
502 }
503 db_finalize(&q);
504 if( pGraph ){
505 graph_finish(pGraph, 0);
506 if( pGraph->nErr ){
507 graph_free(pGraph);
508 pGraph = 0;
509 }else{
510 int w = (pGraph->mxRail+1)*pGraph->iRailPitch + 10;
511
--- src/finfo.c
+++ src/finfo.c
@@ -284,110 +284,92 @@
284 ** b=DATE Only show changes before DATE
285 ** n=NUM Show the first NUM changes only
286 ** brbg Background color by branch name
287 ** ubg Background color by user name
288 ** ci=UUID Ancestors of a particular check-in
 
289 */
290 void finfo_page(void){
291 Stmt q;
292 const char *zFilename;
293 char zPrevDate[20];
294 const char *zA;
295 const char *zB;
296 int n;
297 int baseCheckin;
298 int fnid;
299 Bag ancestor;
300 Blob title;
301 Blob sql;
302 HQuery url;
303 GraphContext *pGraph;
304 int brBg = P("brbg")!=0;
305 int uBg = P("ubg")!=0;
 
306 int fDebug = atoi(PD("debug","0"));
307 int fShowId = P("showid")!=0;
308
309 login_check_credentials();
310 if( !g.perm.Read ){ login_needed(); return; }
311 style_header("File History");
312 login_anonymous_available();
313 url_initialize(&url, "finfo");
314 if( brBg ) url_add_parameter(&url, "brbg", 0);
315 if( uBg ) url_add_parameter(&url, "ubg", 0);
316 baseCheckin = name_to_rid_www("ci");
 
 
 
317 zPrevDate[0] = 0;
318 zFilename = PD("name","");
319 fnid = db_int(0, "SELECT fnid FROM filename WHERE name=%Q", zFilename);
320 if( fnid==0 ){
321 @ No such file: %h(zFilename)
322 style_footer();
323 return;
324 }
325 if( baseCheckin ){
326 int baseFid = db_int(0,
327 "SELECT fid FROM mlink WHERE fnid=%d AND mid=%d",
328 fnid, baseCheckin
329 );
330 bag_init(&ancestor);
331 if( baseFid ) bag_insert(&ancestor, baseFid);
332 }
333 url_add_parameter(&url, "name", zFilename);
334 blob_zero(&sql);
335 blob_append_sql(&sql,
336 "SELECT"
337 " datetime(min(event.mtime)%s)," /* Date of change */
338 " coalesce(event.ecomment, event.comment)," /* Check-in comment */
339 " coalesce(event.euser, event.user)," /* User who made chng */
340 " mlink.pid," /* Parent file rid */
341 " mlink.fid," /* File rid */
342 " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */
343 " (SELECT uuid FROM blob WHERE rid=mlink.fid)," /* Current file uuid */
344 " (SELECT uuid FROM blob WHERE rid=mlink.mid)," /* Check-in uuid */
345 " event.bgcolor," /* Background color */
346 " (SELECT value FROM tagxref WHERE tagid=%d AND tagtype>0"
347 " AND tagxref.rid=mlink.mid)," /* Branchname */
348 " mlink.mid," /* check-in ID */
349 " mlink.pfnid" /* Previous filename */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350 " FROM mlink, event"
351 " WHERE mlink.fnid=%d"
352 " AND event.objid=mlink.mid",
353 timeline_utc(), TAG_BRANCH, fnid
354 );
 
 
 
 
355 if( (zA = P("a"))!=0 ){
356 blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zA);
357 url_add_parameter(&url, "a", zA);
358 }
359 if( (zB = P("b"))!=0 ){
360 blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB);
361 url_add_parameter(&url, "b", zB);
362 }
363 blob_append_sql(&sql,
364 " GROUP BY mlink.fid"
365 " ORDER BY event.mtime DESC /*sort*/"
366 );
367 if( (n = atoi(PD("n","0")))>0 ){
368 blob_append_sql(&sql, " LIMIT %d", n);
369 url_add_parameter(&url, "n", P("n"));
370 }
 
 
 
 
 
 
 
 
 
 
371 db_prepare(&q, "%s", blob_sql_text(&sql));
372 if( P("showsql")!=0 ){
373 @ <p>SQL: %h(blob_str(&sql))</p>
374 }
375 blob_reset(&sql);
@@ -395,15 +377,18 @@
377 if( baseCheckin ){
378 char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin);
379 char *zLink = href("%R/info/%s", zUuid);
380 blob_appendf(&title, "Ancestors of file ");
381 hyperlinked_path(zFilename, &title, zUuid, "tree", "");
382 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
383 blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid);
384 if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin);
385 fossil_free(zUuid);
386 }else{
387 blob_appendf(&title, "History of files named ");
388 hyperlinked_path(zFilename, &title, 0, "tree", "");
389 if( fShowId ) blob_appendf(&title, " (%d)", fnid);
390 }
391 @ <h2>%b(&title)</h2>
392 blob_reset(&title);
393 pGraph = graph_init();
394 @ <div id="canvas" style="position:relative;width:1px;height:1px;"
@@ -422,17 +407,36 @@
407 const char *zBr = db_column_text(&q, 9);
408 int fmid = db_column_int(&q, 10);
409 int pfnid = db_column_int(&q, 11);
410 int gidx;
411 char zTime[10];
412 int nParent = 0;
413 int aParent[GR_MAX_RAIL];
414 static Stmt qparent;
415
416 if( baseCheckin && frid && !bag_find(&ancestor, frid) ) continue;
417 db_static_prepare(&qparent,
418 "SELECT DISTINCT pid FROM mlink"
419 " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid"
420 " ORDER BY isaux /*sort*/"
421 );
422 db_bind_int(&qparent, ":fid", frid);
423 db_bind_int(&qparent, ":mid", fmid);
424 db_bind_int(&qparent, ":fnid", fnid);
425 while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){
426 aParent[nParent] = db_column_int(&qparent, 0);
427 if( baseCheckin ) bag_insert(&ancestor, aParent[nParent]);
428 nParent++;
429 }
430 db_reset(&qparent);
431 if( zBr==0 ) zBr = "trunk";
432 if( uBg ){
433 zBgClr = hash_color(zUser);
434 }else if( brBg || zBgClr==0 || zBgClr[0]==0 ){
435 zBgClr = strcmp(zBr,"trunk")==0 ? "" : hash_color(zBr);
436 }
437 gidx = graph_add_row(pGraph, frid, nParent, aParent, zBr, zBgClr,
438 zUuid, 0);
439 if( strncmp(zDate, zPrevDate, 10) ){
440 sqlite3_snprintf(sizeof(zPrevDate), zPrevDate, "%.10s", zDate);
441 @ <tr><td>
442 @ <div class="divider">%s(zPrevDate)</div>
@@ -447,19 +451,23 @@
451 @ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
452 }else{
453 @ <td class="timelineTableCell">
454 }
455 if( zUuid ){
456 if( nParent==0 ){
457 @ <b>Added</b>
458 }else if( pfnid ){
459 char *zPrevName = db_text(0, "SELECT name FROM filename WHERE fnid=%d",
460 pfnid);
461 @ <b>Renamed</b> from
462 @ %z(href("%R/finfo?name=%t", zPrevName))%h(zPrevName)</a>
463 }
464 @ %z(href("%R/artifact/%s",zUuid))[%S(zUuid)]</a>
465 if( fShowId ){
466 @ (%d(frid))
467 }
468 @ part of check-in
469 }else{
470 char *zNewName;
471 zNewName = db_text(0,
472 "SELECT name FROM filename WHERE fnid = "
473 " (SELECT fnid FROM mlink"
@@ -473,13 +481,16 @@
481 }else{
482 @ <b>Deleted</b> by check-in
483 }
484 }
485 hyperlink_to_uuid(zCkin);
486 if( fShowId ){
487 @ (%d(fmid))
488 }
489 @ %W(zCom) (user:
490 hyperlink_to_user(zUser, zDate, "");
491 @ branch: %z(href("%R/timeline?t=%T&n=200",zBr))%h(zBr)</a>
492 if( g.perm.Hyperlink && zUuid ){
493 const char *z = zFilename;
494 @ %z(href("%R/annotate?filename=%h&checkin=%s",z,zCkin))
495 @ [annotate]</a>
496 @ %z(href("%R/blame?filename=%h&checkin=%s",z,zCkin))
@@ -488,23 +499,26 @@
499 if( fpid ){
500 @ %z(href("%R/fdiff?sbs=1&v1=%s&v2=%s",zPUuid,zUuid))[diff]</a>
501 }
502 }
503 if( fDebug & FINFO_DEBUG_MLINK ){
504 int ii;
505 @ <br>fid=%d(frid) pid=%d(fpid) mid=%d(fmid)
506 if( nParent>0 ){
507 @ parents=%d(aParent[0])
508 for(ii=1; ii<nParent; ii++){
509 @ %d(aParent[ii])
510 }
511 }
512 @ %z(href("%R/finfo?name=%T&ci=%s&debug=1",zFilename,zCkin))[ancestry]</a>
513 }
514 tag_private_status(frid);
515 @ </td></tr>
516 }
517 db_finalize(&q);
518 if( pGraph ){
519 graph_finish(pGraph, 1);
520 if( pGraph->nErr ){
521 graph_free(pGraph);
522 pGraph = 0;
523 }else{
524 int w = (pGraph->mxRail+1)*pGraph->iRailPitch + 10;
525
+21
--- src/graph.c
+++ src/graph.c
@@ -378,10 +378,31 @@
378378
i--;
379379
}
380380
}
381381
}
382382
}
383
+
384
+ /* If the primary parent is in a different branch, but there are
385
+ ** other parents in the same branch, reorder the parents to make
386
+ ** the parent from the same branch the primary parent.
387
+ */
388
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
389
+ if( pRow->isDup ) continue;
390
+ if( pRow->nParent<2 ) continue; /* Not a fork */
391
+ pParent = hashFind(p, pRow->aParent[0]);
392
+ if( pParent==0 ) continue; /* Parent off-screen */
393
+ if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */
394
+ for(i=1; i<pRow->nParent; i++){
395
+ pParent = hashFind(p, pRow->aParent[i]);
396
+ if( pParent && pParent->zBranch==pRow->zBranch ){
397
+ int t = pRow->aParent[0];
398
+ pRow->aParent[0] = pRow->aParent[i];
399
+ pRow->aParent[i] = t;
400
+ break;
401
+ }
402
+ }
403
+ }
383404
384405
385406
/* Find the pChild pointer for each node.
386407
**
387408
** The pChild points to the node directly above on the same rail.
388409
--- src/graph.c
+++ src/graph.c
@@ -378,10 +378,31 @@
378 i--;
379 }
380 }
381 }
382 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
384
385 /* Find the pChild pointer for each node.
386 **
387 ** The pChild points to the node directly above on the same rail.
388
--- src/graph.c
+++ src/graph.c
@@ -378,10 +378,31 @@
378 i--;
379 }
380 }
381 }
382 }
383
384 /* If the primary parent is in a different branch, but there are
385 ** other parents in the same branch, reorder the parents to make
386 ** the parent from the same branch the primary parent.
387 */
388 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
389 if( pRow->isDup ) continue;
390 if( pRow->nParent<2 ) continue; /* Not a fork */
391 pParent = hashFind(p, pRow->aParent[0]);
392 if( pParent==0 ) continue; /* Parent off-screen */
393 if( pParent->zBranch==pRow->zBranch ) continue; /* Same branch */
394 for(i=1; i<pRow->nParent; i++){
395 pParent = hashFind(p, pRow->aParent[i]);
396 if( pParent && pParent->zBranch==pRow->zBranch ){
397 int t = pRow->aParent[0];
398 pRow->aParent[0] = pRow->aParent[i];
399 pRow->aParent[i] = t;
400 break;
401 }
402 }
403 }
404
405
406 /* Find the pChild pointer for each node.
407 **
408 ** The pChild points to the node directly above on the same rail.
409
+6 -6
--- src/http.c
+++ src/http.c
@@ -155,11 +155,11 @@
155155
blob_reset(&x);
156156
return ( c!='n' && c!='N' );
157157
}
158158
159159
/*
160
-** Get the HTTP Basic Authorization credentials from the user
160
+** Get the HTTP Basic Authorization credentials from the user
161161
** when 401 is received.
162162
*/
163163
char *prompt_for_httpauth_creds(void){
164164
Blob x;
165165
char *zUser;
@@ -266,11 +266,11 @@
266266
transport_send(&g.url, &hdr);
267267
transport_send(&g.url, &payload);
268268
blob_reset(&hdr);
269269
blob_reset(&payload);
270270
transport_flip(&g.url);
271
-
271
+
272272
/*
273273
** Read and interpret the server reply
274274
*/
275275
closeConnection = 1;
276276
iLength = -1;
@@ -333,11 +333,11 @@
333333
for(i=9; zLine[i] && zLine[i]==' '; i++){}
334334
if( zLine[i]==0 ){
335335
fossil_warning("malformed redirect: %s", zLine);
336336
goto write_err;
337337
}
338
- j = strlen(zLine) - 1;
338
+ j = strlen(zLine) - 1;
339339
while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
340340
j -= 4;
341341
zLine[j] = 0;
342342
}
343343
transport_close(&g.url);
@@ -349,11 +349,11 @@
349349
g.zHttpAuth = get_httpauth();
350350
return http_exchange(pSend, pReply, useLogin, maxRedirect);
351351
}else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
352352
if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
353353
isCompressed = 0;
354
- }else if( fossil_strnicmp(&zLine[14],
354
+ }else if( fossil_strnicmp(&zLine[14],
355355
"application/x-fossil-uncompressed", -1)==0 ){
356356
isCompressed = 0;
357357
}else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
358358
isError = 1;
359359
}
@@ -411,12 +411,12 @@
411411
}else{
412412
transport_rewind(&g.url);
413413
}
414414
return 0;
415415
416
- /*
416
+ /*
417417
** Jump to here if an error is seen.
418418
*/
419419
write_err:
420420
transport_close(&g.url);
421
- return 1;
421
+ return 1;
422422
}
423423
--- src/http.c
+++ src/http.c
@@ -155,11 +155,11 @@
155 blob_reset(&x);
156 return ( c!='n' && c!='N' );
157 }
158
159 /*
160 ** Get the HTTP Basic Authorization credentials from the user
161 ** when 401 is received.
162 */
163 char *prompt_for_httpauth_creds(void){
164 Blob x;
165 char *zUser;
@@ -266,11 +266,11 @@
266 transport_send(&g.url, &hdr);
267 transport_send(&g.url, &payload);
268 blob_reset(&hdr);
269 blob_reset(&payload);
270 transport_flip(&g.url);
271
272 /*
273 ** Read and interpret the server reply
274 */
275 closeConnection = 1;
276 iLength = -1;
@@ -333,11 +333,11 @@
333 for(i=9; zLine[i] && zLine[i]==' '; i++){}
334 if( zLine[i]==0 ){
335 fossil_warning("malformed redirect: %s", zLine);
336 goto write_err;
337 }
338 j = strlen(zLine) - 1;
339 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
340 j -= 4;
341 zLine[j] = 0;
342 }
343 transport_close(&g.url);
@@ -349,11 +349,11 @@
349 g.zHttpAuth = get_httpauth();
350 return http_exchange(pSend, pReply, useLogin, maxRedirect);
351 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
352 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
353 isCompressed = 0;
354 }else if( fossil_strnicmp(&zLine[14],
355 "application/x-fossil-uncompressed", -1)==0 ){
356 isCompressed = 0;
357 }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
358 isError = 1;
359 }
@@ -411,12 +411,12 @@
411 }else{
412 transport_rewind(&g.url);
413 }
414 return 0;
415
416 /*
417 ** Jump to here if an error is seen.
418 */
419 write_err:
420 transport_close(&g.url);
421 return 1;
422 }
423
--- src/http.c
+++ src/http.c
@@ -155,11 +155,11 @@
155 blob_reset(&x);
156 return ( c!='n' && c!='N' );
157 }
158
159 /*
160 ** Get the HTTP Basic Authorization credentials from the user
161 ** when 401 is received.
162 */
163 char *prompt_for_httpauth_creds(void){
164 Blob x;
165 char *zUser;
@@ -266,11 +266,11 @@
266 transport_send(&g.url, &hdr);
267 transport_send(&g.url, &payload);
268 blob_reset(&hdr);
269 blob_reset(&payload);
270 transport_flip(&g.url);
271
272 /*
273 ** Read and interpret the server reply
274 */
275 closeConnection = 1;
276 iLength = -1;
@@ -333,11 +333,11 @@
333 for(i=9; zLine[i] && zLine[i]==' '; i++){}
334 if( zLine[i]==0 ){
335 fossil_warning("malformed redirect: %s", zLine);
336 goto write_err;
337 }
338 j = strlen(zLine) - 1;
339 while( j>4 && fossil_strcmp(&zLine[j-4],"/xfer")==0 ){
340 j -= 4;
341 zLine[j] = 0;
342 }
343 transport_close(&g.url);
@@ -349,11 +349,11 @@
349 g.zHttpAuth = get_httpauth();
350 return http_exchange(pSend, pReply, useLogin, maxRedirect);
351 }else if( fossil_strnicmp(zLine, "content-type: ", 14)==0 ){
352 if( fossil_strnicmp(&zLine[14], "application/x-fossil-debug", -1)==0 ){
353 isCompressed = 0;
354 }else if( fossil_strnicmp(&zLine[14],
355 "application/x-fossil-uncompressed", -1)==0 ){
356 isCompressed = 0;
357 }else if( fossil_strnicmp(&zLine[14], "application/x-fossil", -1)!=0 ){
358 isError = 1;
359 }
@@ -411,12 +411,12 @@
411 }else{
412 transport_rewind(&g.url);
413 }
414 return 0;
415
416 /*
417 ** Jump to here if an error is seen.
418 */
419 write_err:
420 transport_close(&g.url);
421 return 1;
422 }
423
--- src/http_socket.c
+++ src/http_socket.c
@@ -223,15 +223,22 @@
223223
** so rcvfrom gets populated. For hostnames with more than one IP (or
224224
** if overridden in ~/.ssh/config) the rcvfrom may not match the host
225225
** to which we connect.
226226
*/
227227
void socket_ssh_resolve_addr(UrlData *pUrlData){
228
- struct hostent *pHost; /* Used to make best effort for rcvfrom */
229
- struct sockaddr_in addr;
230
-
231
- memset(&addr, 0, sizeof(addr));
232
- pHost = gethostbyname(pUrlData->name);
233
- if( pHost!=0 ){
234
- memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
235
- g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
228
+ struct addrinfo *ai = 0;
229
+ struct addrinfo hints;
230
+ char zRemote[NI_MAXHOST];
231
+ hints.ai_family = AF_UNSPEC;
232
+ hints.ai_socktype = SOCK_STREAM;
233
+ hints.ai_protocol = IPPROTO_TCP;
234
+ if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
235
+ && ai!=0
236
+ && getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
237
+ sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
238
+ g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
239
+ }
240
+ if( ai ) freeaddrinfo(ai);
241
+ if( g.zIpAddr==0 ){
242
+ g.zIpAddr = mprintf("%s", pUrlData->name);
236243
}
237244
}
238245
--- src/http_socket.c
+++ src/http_socket.c
@@ -223,15 +223,22 @@
223 ** so rcvfrom gets populated. For hostnames with more than one IP (or
224 ** if overridden in ~/.ssh/config) the rcvfrom may not match the host
225 ** to which we connect.
226 */
227 void socket_ssh_resolve_addr(UrlData *pUrlData){
228 struct hostent *pHost; /* Used to make best effort for rcvfrom */
229 struct sockaddr_in addr;
230
231 memset(&addr, 0, sizeof(addr));
232 pHost = gethostbyname(pUrlData->name);
233 if( pHost!=0 ){
234 memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
235 g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
 
 
 
 
 
 
 
236 }
237 }
238
--- src/http_socket.c
+++ src/http_socket.c
@@ -223,15 +223,22 @@
223 ** so rcvfrom gets populated. For hostnames with more than one IP (or
224 ** if overridden in ~/.ssh/config) the rcvfrom may not match the host
225 ** to which we connect.
226 */
227 void socket_ssh_resolve_addr(UrlData *pUrlData){
228 struct addrinfo *ai = 0;
229 struct addrinfo hints;
230 char zRemote[NI_MAXHOST];
231 hints.ai_family = AF_UNSPEC;
232 hints.ai_socktype = SOCK_STREAM;
233 hints.ai_protocol = IPPROTO_TCP;
234 if( getaddrinfo(pUrlData->name, NULL, &hints, &ai)==0
235 && ai!=0
236 && getnameinfo(ai->ai_addr, ai->ai_addrlen, zRemote,
237 sizeof(zRemote), 0, 0, NI_NUMERICHOST)==0 ){
238 g.zIpAddr = mprintf("%s (%s)", zRemote, pUrlData->name);
239 }
240 if( ai ) freeaddrinfo(ai);
241 if( g.zIpAddr==0 ){
242 g.zIpAddr = mprintf("%s", pUrlData->name);
243 }
244 }
245
--- src/http_transport.c
+++ src/http_transport.c
@@ -87,11 +87,11 @@
8787
8888
/*
8989
** SSH initialization of the transport layer
9090
*/
9191
int transport_ssh_open(UrlData *pUrlData){
92
- /* For SSH we need to create and run SSH fossil http
92
+ /* For SSH we need to create and run SSH fossil http
9393
** to talk to the remote machine.
9494
*/
9595
const char *zSsh; /* The base SSH command */
9696
Blob zCmd; /* The SSH command */
9797
char *zHost; /* The host name to contact */
9898
--- src/http_transport.c
+++ src/http_transport.c
@@ -87,11 +87,11 @@
87
88 /*
89 ** SSH initialization of the transport layer
90 */
91 int transport_ssh_open(UrlData *pUrlData){
92 /* For SSH we need to create and run SSH fossil http
93 ** to talk to the remote machine.
94 */
95 const char *zSsh; /* The base SSH command */
96 Blob zCmd; /* The SSH command */
97 char *zHost; /* The host name to contact */
98
--- src/http_transport.c
+++ src/http_transport.c
@@ -87,11 +87,11 @@
87
88 /*
89 ** SSH initialization of the transport layer
90 */
91 int transport_ssh_open(UrlData *pUrlData){
92 /* For SSH we need to create and run SSH fossil http
93 ** to talk to the remote machine.
94 */
95 const char *zSsh; /* The base SSH command */
96 Blob zCmd; /* The SSH command */
97 char *zHost; /* The host name to contact */
98
+1 -1
--- src/info.c
+++ src/info.c
@@ -714,11 +714,11 @@
714714
" mperm,"
715715
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
716716
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
717717
" (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
718718
" FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
719
- " WHERE mlink.mid=%d"
719
+ " WHERE mlink.mid=%d AND NOT mlink.isaux"
720720
" AND (mlink.fid>0"
721721
" OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
722722
" ORDER BY name /*sort*/",
723723
rid, rid
724724
);
725725
--- src/info.c
+++ src/info.c
@@ -714,11 +714,11 @@
714 " mperm,"
715 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
716 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
717 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
718 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
719 " WHERE mlink.mid=%d"
720 " AND (mlink.fid>0"
721 " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
722 " ORDER BY name /*sort*/",
723 rid, rid
724 );
725
--- src/info.c
+++ src/info.c
@@ -714,11 +714,11 @@
714 " mperm,"
715 " (SELECT uuid FROM blob WHERE rid=mlink.pid),"
716 " (SELECT uuid FROM blob WHERE rid=mlink.fid),"
717 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
718 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
719 " WHERE mlink.mid=%d AND NOT mlink.isaux"
720 " AND (mlink.fid>0"
721 " OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
722 " ORDER BY name /*sort*/",
723 rid, rid
724 );
725
+3 -2
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143143
int fSqlTrace; /* True if --sqltrace flag is present */
144144
int fSqlStats; /* True if --sqltrace or --sqlstats are present */
145145
int fSqlPrint; /* True if -sqlprint flag is present */
146146
int fQuiet; /* True if -quiet flag is present */
147147
int fHttpTrace; /* Trace outbound HTTP requests */
148
+ int fAnyTrace; /* Any kind of tracing */
148149
char *zHttpAuth; /* HTTP Authorization user:pass information */
149150
int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
150151
int fSshTrace; /* Trace the SSH setup traffic */
151152
int fSshClient; /* HTTP client flags for SSH client */
152153
char *zSshCmd; /* SSH command string */
@@ -658,15 +659,15 @@
658659
g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
659660
g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
660661
g.fSshClient = 0;
661662
g.zSshCmd = 0;
662663
if( g.fSqlTrace ) g.fSqlStats = 1;
663
- g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
664664
g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
665665
#ifdef FOSSIL_ENABLE_TH1_HOOKS
666666
g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
667667
#endif
668
+ g.fAnyTrace = g.fSqlTrace|g.fSystemTrace|g.fSshTrace|g.fHttpTrace;
668669
g.zHttpAuth = 0;
669670
g.zLogin = find_option("user", "U", 1);
670671
g.zSSLIdentity = find_option("ssl-identity", 0, 1);
671672
g.zErrlog = find_option("errorlog", 0, 1);
672673
fossil_init_flags_from_options();
@@ -1873,11 +1874,11 @@
18731874
}
18741875
if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
18751876
/* debug: FILENAME
18761877
**
18771878
** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
1878
- ** into FILENAME.
1879
+ ** into FILENAME.
18791880
*/
18801881
g.fDebug = fossil_fopen(blob_str(&value), "ab");
18811882
blob_reset(&value);
18821883
continue;
18831884
}
18841885
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143 int fSqlTrace; /* True if --sqltrace flag is present */
144 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
145 int fSqlPrint; /* True if -sqlprint flag is present */
146 int fQuiet; /* True if -quiet flag is present */
147 int fHttpTrace; /* Trace outbound HTTP requests */
 
148 char *zHttpAuth; /* HTTP Authorization user:pass information */
149 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
150 int fSshTrace; /* Trace the SSH setup traffic */
151 int fSshClient; /* HTTP client flags for SSH client */
152 char *zSshCmd; /* SSH command string */
@@ -658,15 +659,15 @@
658 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
659 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
660 g.fSshClient = 0;
661 g.zSshCmd = 0;
662 if( g.fSqlTrace ) g.fSqlStats = 1;
663 g.fSqlPrint = find_option("sqlprint", 0, 0)!=0;
664 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
665 #ifdef FOSSIL_ENABLE_TH1_HOOKS
666 g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
667 #endif
 
668 g.zHttpAuth = 0;
669 g.zLogin = find_option("user", "U", 1);
670 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
671 g.zErrlog = find_option("errorlog", 0, 1);
672 fossil_init_flags_from_options();
@@ -1873,11 +1874,11 @@
1873 }
1874 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1875 /* debug: FILENAME
1876 **
1877 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
1878 ** into FILENAME.
1879 */
1880 g.fDebug = fossil_fopen(blob_str(&value), "ab");
1881 blob_reset(&value);
1882 continue;
1883 }
1884
--- src/main.c
+++ src/main.c
@@ -143,10 +143,11 @@
143 int fSqlTrace; /* True if --sqltrace flag is present */
144 int fSqlStats; /* True if --sqltrace or --sqlstats are present */
145 int fSqlPrint; /* True if -sqlprint flag is present */
146 int fQuiet; /* True if -quiet flag is present */
147 int fHttpTrace; /* Trace outbound HTTP requests */
148 int fAnyTrace; /* Any kind of tracing */
149 char *zHttpAuth; /* HTTP Authorization user:pass information */
150 int fSystemTrace; /* Trace calls to fossil_system(), --systemtrace */
151 int fSshTrace; /* Trace the SSH setup traffic */
152 int fSshClient; /* HTTP client flags for SSH client */
153 char *zSshCmd; /* SSH command string */
@@ -658,15 +659,15 @@
659 g.fSystemTrace = find_option("systemtrace", 0, 0)!=0;
660 g.fSshTrace = find_option("sshtrace", 0, 0)!=0;
661 g.fSshClient = 0;
662 g.zSshCmd = 0;
663 if( g.fSqlTrace ) g.fSqlStats = 1;
 
664 g.fHttpTrace = find_option("httptrace", 0, 0)!=0;
665 #ifdef FOSSIL_ENABLE_TH1_HOOKS
666 g.fNoThHook = find_option("no-th-hook", 0, 0)!=0;
667 #endif
668 g.fAnyTrace = g.fSqlTrace|g.fSystemTrace|g.fSshTrace|g.fHttpTrace;
669 g.zHttpAuth = 0;
670 g.zLogin = find_option("user", "U", 1);
671 g.zSSLIdentity = find_option("ssl-identity", 0, 1);
672 g.zErrlog = find_option("errorlog", 0, 1);
673 fossil_init_flags_from_options();
@@ -1873,11 +1874,11 @@
1874 }
1875 if( blob_eq(&key, "debug:") && blob_token(&line, &value) ){
1876 /* debug: FILENAME
1877 **
1878 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
1879 ** into FILENAME.
1880 */
1881 g.fDebug = fossil_fopen(blob_str(&value), "ab");
1882 blob_reset(&value);
1883 continue;
1884 }
1885
+15 -2
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104104
$(SRCDIR)/sitemap.c \
105105
$(SRCDIR)/skins.c \
106106
$(SRCDIR)/sqlcmd.c \
107107
$(SRCDIR)/stash.c \
108108
$(SRCDIR)/stat.c \
109
+ $(SRCDIR)/statrep.c \
109110
$(SRCDIR)/style.c \
110111
$(SRCDIR)/sync.c \
111112
$(SRCDIR)/tag.c \
112113
$(SRCDIR)/tar.c \
113114
$(SRCDIR)/th_main.c \
@@ -155,11 +156,12 @@
155156
$(SRCDIR)/../skins/plain_gray/footer.txt \
156157
$(SRCDIR)/../skins/plain_gray/header.txt \
157158
$(SRCDIR)/../skins/rounded1/css.txt \
158159
$(SRCDIR)/../skins/rounded1/footer.txt \
159160
$(SRCDIR)/../skins/rounded1/header.txt \
160
- $(SRCDIR)/diff.tcl
161
+ $(SRCDIR)/diff.tcl \
162
+ $(SRCDIR)/markdown.md
161163
162164
TRANS_SRC = \
163165
$(OBJDIR)/add_.c \
164166
$(OBJDIR)/allrepo_.c \
165167
$(OBJDIR)/attach_.c \
@@ -250,10 +252,11 @@
250252
$(OBJDIR)/sitemap_.c \
251253
$(OBJDIR)/skins_.c \
252254
$(OBJDIR)/sqlcmd_.c \
253255
$(OBJDIR)/stash_.c \
254256
$(OBJDIR)/stat_.c \
257
+ $(OBJDIR)/statrep_.c \
255258
$(OBJDIR)/style_.c \
256259
$(OBJDIR)/sync_.c \
257260
$(OBJDIR)/tag_.c \
258261
$(OBJDIR)/tar_.c \
259262
$(OBJDIR)/th_main_.c \
@@ -369,10 +372,11 @@
369372
$(OBJDIR)/sitemap.o \
370373
$(OBJDIR)/skins.o \
371374
$(OBJDIR)/sqlcmd.o \
372375
$(OBJDIR)/stash.o \
373376
$(OBJDIR)/stat.o \
377
+ $(OBJDIR)/statrep.o \
374378
$(OBJDIR)/style.o \
375379
$(OBJDIR)/sync.o \
376380
$(OBJDIR)/tag.o \
377381
$(OBJDIR)/tar.o \
378382
$(OBJDIR)/th_main.o \
@@ -502,11 +506,11 @@
502506
503507
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
504508
$(OBJDIR)/mkindex $(TRANS_SRC) >$@
505509
506510
$(OBJDIR)/builtin_data.h: $(OBJDIR)/mkbuiltin $(EXTRA_FILES)
507
- $(OBJDIR)/mkbuiltin $(EXTRA_FILES) >$@
511
+ $(OBJDIR)/mkbuiltin --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
508512
509513
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
510514
$(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
511515
$(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
512516
$(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -597,10 +601,11 @@
597601
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
598602
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
599603
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
600604
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
601605
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
606
+ $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
602607
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
603608
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
604609
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
605610
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
606611
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1364,10 +1369,18 @@
13641369
13651370
$(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
13661371
$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
13671372
13681373
$(OBJDIR)/stat.h: $(OBJDIR)/headers
1374
+
1375
+$(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(OBJDIR)/translate
1376
+ $(OBJDIR)/translate $(SRCDIR)/statrep.c >$@
1377
+
1378
+$(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1379
+ $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1380
+
1381
+$(OBJDIR)/statrep.h: $(OBJDIR)/headers
13691382
13701383
$(OBJDIR)/style_.c: $(SRCDIR)/style.c $(OBJDIR)/translate
13711384
$(OBJDIR)/translate $(SRCDIR)/style.c >$@
13721385
13731386
$(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
13741387
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/sitemap.c \
105 $(SRCDIR)/skins.c \
106 $(SRCDIR)/sqlcmd.c \
107 $(SRCDIR)/stash.c \
108 $(SRCDIR)/stat.c \
 
109 $(SRCDIR)/style.c \
110 $(SRCDIR)/sync.c \
111 $(SRCDIR)/tag.c \
112 $(SRCDIR)/tar.c \
113 $(SRCDIR)/th_main.c \
@@ -155,11 +156,12 @@
155 $(SRCDIR)/../skins/plain_gray/footer.txt \
156 $(SRCDIR)/../skins/plain_gray/header.txt \
157 $(SRCDIR)/../skins/rounded1/css.txt \
158 $(SRCDIR)/../skins/rounded1/footer.txt \
159 $(SRCDIR)/../skins/rounded1/header.txt \
160 $(SRCDIR)/diff.tcl
 
161
162 TRANS_SRC = \
163 $(OBJDIR)/add_.c \
164 $(OBJDIR)/allrepo_.c \
165 $(OBJDIR)/attach_.c \
@@ -250,10 +252,11 @@
250 $(OBJDIR)/sitemap_.c \
251 $(OBJDIR)/skins_.c \
252 $(OBJDIR)/sqlcmd_.c \
253 $(OBJDIR)/stash_.c \
254 $(OBJDIR)/stat_.c \
 
255 $(OBJDIR)/style_.c \
256 $(OBJDIR)/sync_.c \
257 $(OBJDIR)/tag_.c \
258 $(OBJDIR)/tar_.c \
259 $(OBJDIR)/th_main_.c \
@@ -369,10 +372,11 @@
369 $(OBJDIR)/sitemap.o \
370 $(OBJDIR)/skins.o \
371 $(OBJDIR)/sqlcmd.o \
372 $(OBJDIR)/stash.o \
373 $(OBJDIR)/stat.o \
 
374 $(OBJDIR)/style.o \
375 $(OBJDIR)/sync.o \
376 $(OBJDIR)/tag.o \
377 $(OBJDIR)/tar.o \
378 $(OBJDIR)/th_main.o \
@@ -502,11 +506,11 @@
502
503 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
504 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
505
506 $(OBJDIR)/builtin_data.h: $(OBJDIR)/mkbuiltin $(EXTRA_FILES)
507 $(OBJDIR)/mkbuiltin $(EXTRA_FILES) >$@
508
509 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
510 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
511 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
512 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -597,10 +601,11 @@
597 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
598 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
599 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
600 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
601 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
 
602 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
603 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
604 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
605 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
606 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1364,10 +1369,18 @@
1364
1365 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1366 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1367
1368 $(OBJDIR)/stat.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1369
1370 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(OBJDIR)/translate
1371 $(OBJDIR)/translate $(SRCDIR)/style.c >$@
1372
1373 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1374
--- src/main.mk
+++ src/main.mk
@@ -104,10 +104,11 @@
104 $(SRCDIR)/sitemap.c \
105 $(SRCDIR)/skins.c \
106 $(SRCDIR)/sqlcmd.c \
107 $(SRCDIR)/stash.c \
108 $(SRCDIR)/stat.c \
109 $(SRCDIR)/statrep.c \
110 $(SRCDIR)/style.c \
111 $(SRCDIR)/sync.c \
112 $(SRCDIR)/tag.c \
113 $(SRCDIR)/tar.c \
114 $(SRCDIR)/th_main.c \
@@ -155,11 +156,12 @@
156 $(SRCDIR)/../skins/plain_gray/footer.txt \
157 $(SRCDIR)/../skins/plain_gray/header.txt \
158 $(SRCDIR)/../skins/rounded1/css.txt \
159 $(SRCDIR)/../skins/rounded1/footer.txt \
160 $(SRCDIR)/../skins/rounded1/header.txt \
161 $(SRCDIR)/diff.tcl \
162 $(SRCDIR)/markdown.md
163
164 TRANS_SRC = \
165 $(OBJDIR)/add_.c \
166 $(OBJDIR)/allrepo_.c \
167 $(OBJDIR)/attach_.c \
@@ -250,10 +252,11 @@
252 $(OBJDIR)/sitemap_.c \
253 $(OBJDIR)/skins_.c \
254 $(OBJDIR)/sqlcmd_.c \
255 $(OBJDIR)/stash_.c \
256 $(OBJDIR)/stat_.c \
257 $(OBJDIR)/statrep_.c \
258 $(OBJDIR)/style_.c \
259 $(OBJDIR)/sync_.c \
260 $(OBJDIR)/tag_.c \
261 $(OBJDIR)/tar_.c \
262 $(OBJDIR)/th_main_.c \
@@ -369,10 +372,11 @@
372 $(OBJDIR)/sitemap.o \
373 $(OBJDIR)/skins.o \
374 $(OBJDIR)/sqlcmd.o \
375 $(OBJDIR)/stash.o \
376 $(OBJDIR)/stat.o \
377 $(OBJDIR)/statrep.o \
378 $(OBJDIR)/style.o \
379 $(OBJDIR)/sync.o \
380 $(OBJDIR)/tag.o \
381 $(OBJDIR)/tar.o \
382 $(OBJDIR)/th_main.o \
@@ -502,11 +506,11 @@
506
507 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(OBJDIR)/mkindex
508 $(OBJDIR)/mkindex $(TRANS_SRC) >$@
509
510 $(OBJDIR)/builtin_data.h: $(OBJDIR)/mkbuiltin $(EXTRA_FILES)
511 $(OBJDIR)/mkbuiltin --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
512
513 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(OBJDIR)/makeheaders $(OBJDIR)/VERSION.h
514 $(OBJDIR)/makeheaders $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
515 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
516 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -597,10 +601,11 @@
601 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
602 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
603 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
604 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
605 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
606 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
607 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
608 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
609 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
610 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
611 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1364,10 +1369,18 @@
1369
1370 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1371 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1372
1373 $(OBJDIR)/stat.h: $(OBJDIR)/headers
1374
1375 $(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(OBJDIR)/translate
1376 $(OBJDIR)/translate $(SRCDIR)/statrep.c >$@
1377
1378 $(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1379 $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1380
1381 $(OBJDIR)/statrep.h: $(OBJDIR)/headers
1382
1383 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(OBJDIR)/translate
1384 $(OBJDIR)/translate $(SRCDIR)/style.c >$@
1385
1386 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1387
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -110,10 +110,11 @@
110110
sitemap
111111
skins
112112
sqlcmd
113113
stash
114114
stat
115
+ statrep
115116
style
116117
sync
117118
tag
118119
tar
119120
th_main
@@ -142,10 +143,11 @@
142143
143144
# Additional resource files that get built into the executable.
144145
#
145146
set extra_files {
146147
diff.tcl
148
+ markdown.md
147149
../skins/*/*.txt
148150
}
149151
150152
# Options used to compile the included SQLite library.
151153
#
@@ -372,11 +374,11 @@
372374
set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
373375
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
374376
writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
375377
376378
writeln "\$(OBJDIR)/builtin_data.h: \$(OBJDIR)/mkbuiltin \$(EXTRA_FILES)"
377
-writeln "\t\$(OBJDIR)/mkbuiltin \$(EXTRA_FILES) >\$@\n"
379
+writeln "\t\$(OBJDIR)/mkbuiltin --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
378380
379381
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
380382
writeln "\t\$(OBJDIR)/makeheaders $mhargs"
381383
writeln "\ttouch \$(OBJDIR)/headers"
382384
writeln "\$(OBJDIR)/headers: Makefile"
@@ -1025,11 +1027,11 @@
10251027
append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
10261028
writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
10271029
writeln "\t\$(MKINDEX) \$(TRANS_SRC) >\$@\n"
10281030
10291031
writeln "\$(OBJDIR)/builtin_data.h:\t\$(MKBUILTIN) \$(EXTRA_FILES)"
1030
-writeln "\t\$(MKBUILTIN) \$(EXTRA_FILES) >\$@\n"
1032
+writeln "\t\$(MKBUILTIN) --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
10311033
10321034
writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(MAKEHEADERS) \$(OBJDIR)/VERSION.h"
10331035
writeln "\t\$(MAKEHEADERS) $mhargs"
10341036
writeln "\techo Done >\$(OBJDIR)/headers\n"
10351037
writeln "\$(OBJDIR)/headers: Makefile\n"
@@ -1204,11 +1206,11 @@
12041206
12051207
page_index.h: mkindex$E $(SRC)
12061208
+$** > $@
12071209
12081210
builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1209
- +$** > $@
1211
+ mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
12101212
12111213
clean:
12121214
-del $(OBJDIR)\*.obj
12131215
-del *.obj *_.c *.h *.map
12141216
@@ -1598,11 +1600,11 @@
15981600
15991601
page_index.h: mkindex$E $(SRC)
16001602
$** > $@
16011603
16021604
builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1603
- $** > $@
1605
+ mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
16041606
16051607
clean:
16061608
-del $(OX)\*.obj
16071609
-del *.obj
16081610
-del *_.c
@@ -1830,11 +1832,11 @@
18301832
# generate the index source, containing all web references,..
18311833
page_index.h: $(TRANSLATEDSRC) mkindex.exe
18321834
mkindex.exe $(TRANSLATEDSRC) >$@
18331835
18341836
builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
1835
- mkbuiltin.exe $(EXTRA_FILES) >$@
1837
+ mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
18361838
18371839
# extracting version info from manifest
18381840
VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
18391841
version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
18401842
18411843
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -110,10 +110,11 @@
110 sitemap
111 skins
112 sqlcmd
113 stash
114 stat
 
115 style
116 sync
117 tag
118 tar
119 th_main
@@ -142,10 +143,11 @@
142
143 # Additional resource files that get built into the executable.
144 #
145 set extra_files {
146 diff.tcl
 
147 ../skins/*/*.txt
148 }
149
150 # Options used to compile the included SQLite library.
151 #
@@ -372,11 +374,11 @@
372 set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
373 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
374 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
375
376 writeln "\$(OBJDIR)/builtin_data.h: \$(OBJDIR)/mkbuiltin \$(EXTRA_FILES)"
377 writeln "\t\$(OBJDIR)/mkbuiltin \$(EXTRA_FILES) >\$@\n"
378
379 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
380 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
381 writeln "\ttouch \$(OBJDIR)/headers"
382 writeln "\$(OBJDIR)/headers: Makefile"
@@ -1025,11 +1027,11 @@
1025 append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
1026 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
1027 writeln "\t\$(MKINDEX) \$(TRANS_SRC) >\$@\n"
1028
1029 writeln "\$(OBJDIR)/builtin_data.h:\t\$(MKBUILTIN) \$(EXTRA_FILES)"
1030 writeln "\t\$(MKBUILTIN) \$(EXTRA_FILES) >\$@\n"
1031
1032 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(MAKEHEADERS) \$(OBJDIR)/VERSION.h"
1033 writeln "\t\$(MAKEHEADERS) $mhargs"
1034 writeln "\techo Done >\$(OBJDIR)/headers\n"
1035 writeln "\$(OBJDIR)/headers: Makefile\n"
@@ -1204,11 +1206,11 @@
1204
1205 page_index.h: mkindex$E $(SRC)
1206 +$** > $@
1207
1208 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1209 +$** > $@
1210
1211 clean:
1212 -del $(OBJDIR)\*.obj
1213 -del *.obj *_.c *.h *.map
1214
@@ -1598,11 +1600,11 @@
1598
1599 page_index.h: mkindex$E $(SRC)
1600 $** > $@
1601
1602 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1603 $** > $@
1604
1605 clean:
1606 -del $(OX)\*.obj
1607 -del *.obj
1608 -del *_.c
@@ -1830,11 +1832,11 @@
1830 # generate the index source, containing all web references,..
1831 page_index.h: $(TRANSLATEDSRC) mkindex.exe
1832 mkindex.exe $(TRANSLATEDSRC) >$@
1833
1834 builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
1835 mkbuiltin.exe $(EXTRA_FILES) >$@
1836
1837 # extracting version info from manifest
1838 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
1839 version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
1840
1841
--- src/makemake.tcl
+++ src/makemake.tcl
@@ -110,10 +110,11 @@
110 sitemap
111 skins
112 sqlcmd
113 stash
114 stat
115 statrep
116 style
117 sync
118 tag
119 tar
120 th_main
@@ -142,10 +143,11 @@
143
144 # Additional resource files that get built into the executable.
145 #
146 set extra_files {
147 diff.tcl
148 markdown.md
149 ../skins/*/*.txt
150 }
151
152 # Options used to compile the included SQLite library.
153 #
@@ -372,11 +374,11 @@
374 set mhargs [string map [list <<<NEXT_LINE>>> \\\n\t] $mhargs]
375 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(OBJDIR)/mkindex"
376 writeln "\t\$(OBJDIR)/mkindex \$(TRANS_SRC) >\$@\n"
377
378 writeln "\$(OBJDIR)/builtin_data.h: \$(OBJDIR)/mkbuiltin \$(EXTRA_FILES)"
379 writeln "\t\$(OBJDIR)/mkbuiltin --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
380
381 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(OBJDIR)/makeheaders \$(OBJDIR)/VERSION.h"
382 writeln "\t\$(OBJDIR)/makeheaders $mhargs"
383 writeln "\ttouch \$(OBJDIR)/headers"
384 writeln "\$(OBJDIR)/headers: Makefile"
@@ -1025,11 +1027,11 @@
1027 append mhargs " \\\n\t\t\$(OBJDIR)/VERSION.h"
1028 writeln "\$(OBJDIR)/page_index.h: \$(TRANS_SRC) \$(MKINDEX)"
1029 writeln "\t\$(MKINDEX) \$(TRANS_SRC) >\$@\n"
1030
1031 writeln "\$(OBJDIR)/builtin_data.h:\t\$(MKBUILTIN) \$(EXTRA_FILES)"
1032 writeln "\t\$(MKBUILTIN) --prefix \$(SRCDIR)/ \$(EXTRA_FILES) >\$@\n"
1033
1034 writeln "\$(OBJDIR)/headers:\t\$(OBJDIR)/page_index.h \$(OBJDIR)/builtin_data.h \$(MAKEHEADERS) \$(OBJDIR)/VERSION.h"
1035 writeln "\t\$(MAKEHEADERS) $mhargs"
1036 writeln "\techo Done >\$(OBJDIR)/headers\n"
1037 writeln "\$(OBJDIR)/headers: Makefile\n"
@@ -1204,11 +1206,11 @@
1206
1207 page_index.h: mkindex$E $(SRC)
1208 +$** > $@
1209
1210 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1211 mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
1212
1213 clean:
1214 -del $(OBJDIR)\*.obj
1215 -del *.obj *_.c *.h *.map
1216
@@ -1598,11 +1600,11 @@
1600
1601 page_index.h: mkindex$E $(SRC)
1602 $** > $@
1603
1604 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
1605 mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
1606
1607 clean:
1608 -del $(OX)\*.obj
1609 -del *.obj
1610 -del *_.c
@@ -1830,11 +1832,11 @@
1832 # generate the index source, containing all web references,..
1833 page_index.h: $(TRANSLATEDSRC) mkindex.exe
1834 mkindex.exe $(TRANSLATEDSRC) >$@
1835
1836 builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
1837 mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
1838
1839 # extracting version info from manifest
1840 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
1841 version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
1842
1843
+64 -53
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
11851185
/*
11861186
** Add a single entry to the mlink table. Also add the filename to
11871187
** the filename table if it is not there already.
11881188
*/
11891189
static void add_one_mlink(
1190
+ int pmid, /* The parent manifest */
1191
+ const char *zFromUuid, /* UUID for content in parent */
11901192
int mid, /* The record ID of the manifest */
1191
- const char *zFromUuid, /* UUID for the mlink.pid. "" to add file */
1192
- const char *zToUuid, /* UUID for the mlink.fid. "" to delete */
1193
+ const char *zToUuid, /* UUID for content in child */
11931194
const char *zFilename, /* Filename */
11941195
const char *zPrior, /* Previous filename. NULL if unchanged */
11951196
int isPublic, /* True if mid is not a private manifest */
1197
+ int isPrimary, /* pmid is the primary parent of mid */
11961198
int mperm /* 1: exec, 2: symlink */
11971199
){
11981200
int fnid, pfnid, pid, fid;
11991201
static Stmt s1;
12001202
@@ -1214,19 +1216,21 @@
12141216
}else{
12151217
fid = uuid_to_rid(zToUuid, 1);
12161218
if( isPublic ) content_make_public(fid);
12171219
}
12181220
db_static_prepare(&s1,
1219
- "INSERT INTO mlink(mid,pid,fid,fnid,pfnid,mperm)"
1220
- "VALUES(:m,:p,:f,:n,:pfn,:mp)"
1221
+ "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1222
+ "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
12211223
);
12221224
db_bind_int(&s1, ":m", mid);
1223
- db_bind_int(&s1, ":p", pid);
12241225
db_bind_int(&s1, ":f", fid);
1226
+ db_bind_int(&s1, ":pm", pmid);
1227
+ db_bind_int(&s1, ":p", pid);
12251228
db_bind_int(&s1, ":n", fnid);
12261229
db_bind_int(&s1, ":pfn", pfnid);
12271230
db_bind_int(&s1, ":mp", mperm);
1231
+ db_bind_int(&s1, ":isaux", isPrimary==0);
12281232
db_exec(&s1);
12291233
if( pid && fid ){
12301234
content_deltify(pid, fid, 0);
12311235
}
12321236
}
@@ -1340,24 +1344,29 @@
13401344
**
13411345
** Deleted files have mlink.fid=0.
13421346
** Added files have mlink.pid=0.
13431347
** Edited files have both mlink.pid!=0 and mlink.fid!=0
13441348
*/
1345
-static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
1349
+static void add_mlink(
1350
+ int pmid, Manifest *pParent, /* Parent check-in */
1351
+ int mid, Manifest *pChild, /* The child check-in */
1352
+ int isPrim /* TRUE if pmid is the primary parent of mid */
1353
+){
13461354
Blob otherContent;
13471355
int otherRid;
13481356
int i, rc;
13491357
ManifestFile *pChildFile, *pParentFile;
13501358
Manifest **ppOther;
13511359
static Stmt eq;
13521360
int isPublic; /* True if pChild is non-private */
13531361
1354
- /* If mlink table entires are already set for cid, then abort early
1355
- ** doing no work.
1362
+ /* If mlink table entires are already exist for the pmid-to-mid transition,
1363
+ ** then abort early doing no work.
13561364
*/
1357
- db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid");
1358
- db_bind_int(&eq, ":mid", cid);
1365
+ db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid AND pmid=:pmid");
1366
+ db_bind_int(&eq, ":mid", mid);
1367
+ db_bind_int(&eq, ":pmid", pmid);
13591368
rc = db_step(&eq);
13601369
db_reset(&eq);
13611370
if( rc==SQLITE_ROW ) return;
13621371
13631372
/* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
13641373
** Fetch the baseline checkins for both.
13651374
*/
13661375
assert( pParent==0 || pChild==0 );
13671376
if( pParent==0 ){
13681377
ppOther = &pParent;
1369
- otherRid = pid;
1378
+ otherRid = pmid;
13701379
}else{
13711380
ppOther = &pChild;
1372
- otherRid = cid;
1381
+ otherRid = mid;
13731382
}
13741383
if( (*ppOther = manifest_cache_find(otherRid))==0 ){
13751384
content_get(otherRid, &otherContent);
13761385
if( blob_size(&otherContent)==0 ) return;
13771386
*ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
13791388
}
13801389
if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
13811390
manifest_destroy(*ppOther);
13821391
return;
13831392
}
1384
- isPublic = !content_is_private(cid);
1393
+ isPublic = !content_is_private(mid);
13851394
13861395
/* Try to make the parent manifest a delta from the child, if that
13871396
** is an appropriate thing to do. For a new baseline, make the
13881397
** previous baseline a delta from the current baseline.
13891398
*/
13901399
if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1391
- content_deltify(pid, cid, 0);
1400
+ content_deltify(pmid, mid, 0);
13921401
}else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1393
- content_deltify(pParent->pBaseline->rid, cid, 0);
1402
+ content_deltify(pParent->pBaseline->rid, mid, 0);
13941403
}
13951404
13961405
/* Remember all children less than a few seconds younger than their parent,
13971406
** as we might want to fudge the times for those children.
13981407
*/
@@ -1412,31 +1421,32 @@
14121421
int mperm = manifest_file_mperm(pChildFile);
14131422
if( pChildFile->zPrior ){
14141423
pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
14151424
if( pParentFile ){
14161425
/* File with name change */
1417
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1418
- pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
1426
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1427
+ pChildFile->zName, pChildFile->zPrior,
1428
+ isPublic, isPrim, mperm);
14191429
}else{
14201430
/* File name changed, but the old name is not found in the parent!
14211431
** Treat this like a new file. */
1422
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1423
- isPublic, mperm);
1432
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1433
+ isPublic, isPrim, mperm);
14241434
}
14251435
}else{
14261436
pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
14271437
if( pParentFile==0 ){
14281438
if( pChildFile->zUuid ){
14291439
/* A new file */
1430
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1431
- isPublic, mperm);
1440
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1441
+ isPublic, isPrim, mperm);
14321442
}
14331443
}else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
14341444
|| manifest_file_mperm(pParentFile)!=mperm ){
14351445
/* Changes in file content or permissions */
1436
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1437
- pChildFile->zName, 0, isPublic, mperm);
1446
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1447
+ pChildFile->zName, 0, isPublic, isPrim, mperm);
14381448
}
14391449
}
14401450
}
14411451
if( pParent->zBaseline && pChild->zBaseline ){
14421452
/* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
14481458
pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
14491459
if( pChildFile==0 ){
14501460
/* The child file reverts to baseline. Show this as a change */
14511461
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14521462
if( pChildFile ){
1453
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1454
- pChildFile->zName, 0, isPublic,
1463
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1464
+ pChildFile->zName, 0, isPublic, isPrim,
14551465
manifest_file_mperm(pChildFile));
14561466
}
14571467
}
14581468
}else{
14591469
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14601470
if( pChildFile ){
14611471
/* File resurrected in the child after having been deleted in
14621472
** the parent. Show this as an added file. */
1463
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1464
- isPublic, manifest_file_mperm(pChildFile));
1473
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1474
+ isPublic, isPrim, manifest_file_mperm(pChildFile));
14651475
}
14661476
}
14671477
}
14681478
}else if( pChild->zBaseline==0 ){
14691479
/* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
14701480
** but are missing from pChild and mark them as having been deleted. */
14711481
manifest_file_rewind(pParent);
14721482
while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
14731483
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14741484
if( pChildFile==0 && pParentFile->zUuid!=0 ){
1475
- add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1476
- isPublic, 0);
1485
+ add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
1486
+ isPublic, isPrim, 0);
14771487
}
14781488
}
14791489
}
14801490
manifest_cache_insert(*ppOther);
14811491
}
@@ -1779,45 +1789,46 @@
17791789
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
17801790
uuid_to_rid(p->zBaseline,1));
17811791
}else{
17821792
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
17831793
}
1784
- (void)db_schema_is_outofdate(); /* Make sure g.zAuxSchema is initialized */
17851794
for(i=0; i<p->nParent; i++){
17861795
int pid = uuid_to_rid(p->azParent[i], 1);
1787
- if( strcmp(g.zAuxSchema,"2014-11-24 20:35")>=0 ){
1788
- /* Support for PLINK.BASEID added on 2014-11-24 */
1789
- db_multi_exec(
1790
- "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1791
- "VALUES(%d, %d, %d, %.17g, %s)",
1792
- pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1793
- }else{
1794
- /* Continue to work with older schema to avoid an unnecessary
1795
- ** rebuild */
1796
- db_multi_exec(
1797
- "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
1798
- "VALUES(%d, %d, %d, %.17g)",
1799
- pid, rid, i==0, p->rDate);
1800
- }
1801
- if( i==0 ){
1802
- add_mlink(pid, 0, rid, p);
1803
- parentid = pid;
1804
- }
1805
- }
1806
- db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
1796
+ db_multi_exec(
1797
+ "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1798
+ "VALUES(%d, %d, %d, %.17g, %s)",
1799
+ pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1800
+ add_mlink(pid, 0, rid, p, i==0);
1801
+ if( i==0 ) parentid = pid;
1802
+ }
1803
+ if( p->nParent>1 ){
1804
+ /* Remove incorrect MLINK create-file entries that arise when a
1805
+ ** file is added by merge. */
1806
+ db_multi_exec(
1807
+ "DELETE FROM mlink"
1808
+ " WHERE mid=%d"
1809
+ " AND pid=0"
1810
+ " AND fnid IN "
1811
+ " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1812
+ " HAVING count(*)<%d)",
1813
+ rid, rid, p->nParent
1814
+ );
1815
+ }
1816
+ db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
18071817
while( db_step(&q)==SQLITE_ROW ){
18081818
int cid = db_column_int(&q, 0);
1809
- add_mlink(rid, p, cid, 0);
1819
+ int isprim = db_column_int(&q, 1);
1820
+ add_mlink(rid, p, cid, 0, isprim);
18101821
}
18111822
db_finalize(&q);
18121823
if( p->nParent==0 ){
18131824
/* For root files (files without parents) add mlink entries
18141825
** showing all content as new. */
18151826
int isPublic = !content_is_private(rid);
18161827
for(i=0; i<p->nFile; i++){
1817
- add_one_mlink(rid, 0, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1818
- isPublic, manifest_file_mperm(&p->aFile[i]));
1828
+ add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1829
+ isPublic, 1, manifest_file_mperm(&p->aFile[i]));
18191830
}
18201831
}
18211832
db_multi_exec(
18221833
"REPLACE INTO event(type,mtime,objid,user,comment,"
18231834
"bgcolor,euser,ecomment,omtime)"
18241835
18251836
ADDED src/markdown.md
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
1185 /*
1186 ** Add a single entry to the mlink table. Also add the filename to
1187 ** the filename table if it is not there already.
1188 */
1189 static void add_one_mlink(
 
 
1190 int mid, /* The record ID of the manifest */
1191 const char *zFromUuid, /* UUID for the mlink.pid. "" to add file */
1192 const char *zToUuid, /* UUID for the mlink.fid. "" to delete */
1193 const char *zFilename, /* Filename */
1194 const char *zPrior, /* Previous filename. NULL if unchanged */
1195 int isPublic, /* True if mid is not a private manifest */
 
1196 int mperm /* 1: exec, 2: symlink */
1197 ){
1198 int fnid, pfnid, pid, fid;
1199 static Stmt s1;
1200
@@ -1214,19 +1216,21 @@
1214 }else{
1215 fid = uuid_to_rid(zToUuid, 1);
1216 if( isPublic ) content_make_public(fid);
1217 }
1218 db_static_prepare(&s1,
1219 "INSERT INTO mlink(mid,pid,fid,fnid,pfnid,mperm)"
1220 "VALUES(:m,:p,:f,:n,:pfn,:mp)"
1221 );
1222 db_bind_int(&s1, ":m", mid);
1223 db_bind_int(&s1, ":p", pid);
1224 db_bind_int(&s1, ":f", fid);
 
 
1225 db_bind_int(&s1, ":n", fnid);
1226 db_bind_int(&s1, ":pfn", pfnid);
1227 db_bind_int(&s1, ":mp", mperm);
 
1228 db_exec(&s1);
1229 if( pid && fid ){
1230 content_deltify(pid, fid, 0);
1231 }
1232 }
@@ -1340,24 +1344,29 @@
1340 **
1341 ** Deleted files have mlink.fid=0.
1342 ** Added files have mlink.pid=0.
1343 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
1344 */
1345 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
 
 
 
 
1346 Blob otherContent;
1347 int otherRid;
1348 int i, rc;
1349 ManifestFile *pChildFile, *pParentFile;
1350 Manifest **ppOther;
1351 static Stmt eq;
1352 int isPublic; /* True if pChild is non-private */
1353
1354 /* If mlink table entires are already set for cid, then abort early
1355 ** doing no work.
1356 */
1357 db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid");
1358 db_bind_int(&eq, ":mid", cid);
 
1359 rc = db_step(&eq);
1360 db_reset(&eq);
1361 if( rc==SQLITE_ROW ) return;
1362
1363 /* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
1364 ** Fetch the baseline checkins for both.
1365 */
1366 assert( pParent==0 || pChild==0 );
1367 if( pParent==0 ){
1368 ppOther = &pParent;
1369 otherRid = pid;
1370 }else{
1371 ppOther = &pChild;
1372 otherRid = cid;
1373 }
1374 if( (*ppOther = manifest_cache_find(otherRid))==0 ){
1375 content_get(otherRid, &otherContent);
1376 if( blob_size(&otherContent)==0 ) return;
1377 *ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
1379 }
1380 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1381 manifest_destroy(*ppOther);
1382 return;
1383 }
1384 isPublic = !content_is_private(cid);
1385
1386 /* Try to make the parent manifest a delta from the child, if that
1387 ** is an appropriate thing to do. For a new baseline, make the
1388 ** previous baseline a delta from the current baseline.
1389 */
1390 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1391 content_deltify(pid, cid, 0);
1392 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1393 content_deltify(pParent->pBaseline->rid, cid, 0);
1394 }
1395
1396 /* Remember all children less than a few seconds younger than their parent,
1397 ** as we might want to fudge the times for those children.
1398 */
@@ -1412,31 +1421,32 @@
1412 int mperm = manifest_file_mperm(pChildFile);
1413 if( pChildFile->zPrior ){
1414 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
1415 if( pParentFile ){
1416 /* File with name change */
1417 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1418 pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
 
1419 }else{
1420 /* File name changed, but the old name is not found in the parent!
1421 ** Treat this like a new file. */
1422 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1423 isPublic, mperm);
1424 }
1425 }else{
1426 pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
1427 if( pParentFile==0 ){
1428 if( pChildFile->zUuid ){
1429 /* A new file */
1430 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1431 isPublic, mperm);
1432 }
1433 }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
1434 || manifest_file_mperm(pParentFile)!=mperm ){
1435 /* Changes in file content or permissions */
1436 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1437 pChildFile->zName, 0, isPublic, mperm);
1438 }
1439 }
1440 }
1441 if( pParent->zBaseline && pChild->zBaseline ){
1442 /* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
1448 pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
1449 if( pChildFile==0 ){
1450 /* The child file reverts to baseline. Show this as a change */
1451 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1452 if( pChildFile ){
1453 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1454 pChildFile->zName, 0, isPublic,
1455 manifest_file_mperm(pChildFile));
1456 }
1457 }
1458 }else{
1459 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1460 if( pChildFile ){
1461 /* File resurrected in the child after having been deleted in
1462 ** the parent. Show this as an added file. */
1463 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1464 isPublic, manifest_file_mperm(pChildFile));
1465 }
1466 }
1467 }
1468 }else if( pChild->zBaseline==0 ){
1469 /* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
1470 ** but are missing from pChild and mark them as having been deleted. */
1471 manifest_file_rewind(pParent);
1472 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1473 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1474 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1475 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1476 isPublic, 0);
1477 }
1478 }
1479 }
1480 manifest_cache_insert(*ppOther);
1481 }
@@ -1779,45 +1789,46 @@
1779 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1780 uuid_to_rid(p->zBaseline,1));
1781 }else{
1782 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1783 }
1784 (void)db_schema_is_outofdate(); /* Make sure g.zAuxSchema is initialized */
1785 for(i=0; i<p->nParent; i++){
1786 int pid = uuid_to_rid(p->azParent[i], 1);
1787 if( strcmp(g.zAuxSchema,"2014-11-24 20:35")>=0 ){
1788 /* Support for PLINK.BASEID added on 2014-11-24 */
1789 db_multi_exec(
1790 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1791 "VALUES(%d, %d, %d, %.17g, %s)",
1792 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1793 }else{
1794 /* Continue to work with older schema to avoid an unnecessary
1795 ** rebuild */
1796 db_multi_exec(
1797 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
1798 "VALUES(%d, %d, %d, %.17g)",
1799 pid, rid, i==0, p->rDate);
1800 }
1801 if( i==0 ){
1802 add_mlink(pid, 0, rid, p);
1803 parentid = pid;
1804 }
1805 }
1806 db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
 
1807 while( db_step(&q)==SQLITE_ROW ){
1808 int cid = db_column_int(&q, 0);
1809 add_mlink(rid, p, cid, 0);
 
1810 }
1811 db_finalize(&q);
1812 if( p->nParent==0 ){
1813 /* For root files (files without parents) add mlink entries
1814 ** showing all content as new. */
1815 int isPublic = !content_is_private(rid);
1816 for(i=0; i<p->nFile; i++){
1817 add_one_mlink(rid, 0, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1818 isPublic, manifest_file_mperm(&p->aFile[i]));
1819 }
1820 }
1821 db_multi_exec(
1822 "REPLACE INTO event(type,mtime,objid,user,comment,"
1823 "bgcolor,euser,ecomment,omtime)"
1824
1825 DDED src/markdown.md
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
1185 /*
1186 ** Add a single entry to the mlink table. Also add the filename to
1187 ** the filename table if it is not there already.
1188 */
1189 static void add_one_mlink(
1190 int pmid, /* The parent manifest */
1191 const char *zFromUuid, /* UUID for content in parent */
1192 int mid, /* The record ID of the manifest */
1193 const char *zToUuid, /* UUID for content in child */
 
1194 const char *zFilename, /* Filename */
1195 const char *zPrior, /* Previous filename. NULL if unchanged */
1196 int isPublic, /* True if mid is not a private manifest */
1197 int isPrimary, /* pmid is the primary parent of mid */
1198 int mperm /* 1: exec, 2: symlink */
1199 ){
1200 int fnid, pfnid, pid, fid;
1201 static Stmt s1;
1202
@@ -1214,19 +1216,21 @@
1216 }else{
1217 fid = uuid_to_rid(zToUuid, 1);
1218 if( isPublic ) content_make_public(fid);
1219 }
1220 db_static_prepare(&s1,
1221 "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1222 "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1223 );
1224 db_bind_int(&s1, ":m", mid);
 
1225 db_bind_int(&s1, ":f", fid);
1226 db_bind_int(&s1, ":pm", pmid);
1227 db_bind_int(&s1, ":p", pid);
1228 db_bind_int(&s1, ":n", fnid);
1229 db_bind_int(&s1, ":pfn", pfnid);
1230 db_bind_int(&s1, ":mp", mperm);
1231 db_bind_int(&s1, ":isaux", isPrimary==0);
1232 db_exec(&s1);
1233 if( pid && fid ){
1234 content_deltify(pid, fid, 0);
1235 }
1236 }
@@ -1340,24 +1344,29 @@
1344 **
1345 ** Deleted files have mlink.fid=0.
1346 ** Added files have mlink.pid=0.
1347 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
1348 */
1349 static void add_mlink(
1350 int pmid, Manifest *pParent, /* Parent check-in */
1351 int mid, Manifest *pChild, /* The child check-in */
1352 int isPrim /* TRUE if pmid is the primary parent of mid */
1353 ){
1354 Blob otherContent;
1355 int otherRid;
1356 int i, rc;
1357 ManifestFile *pChildFile, *pParentFile;
1358 Manifest **ppOther;
1359 static Stmt eq;
1360 int isPublic; /* True if pChild is non-private */
1361
1362 /* If mlink table entires are already exist for the pmid-to-mid transition,
1363 ** then abort early doing no work.
1364 */
1365 db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid AND pmid=:pmid");
1366 db_bind_int(&eq, ":mid", mid);
1367 db_bind_int(&eq, ":pmid", pmid);
1368 rc = db_step(&eq);
1369 db_reset(&eq);
1370 if( rc==SQLITE_ROW ) return;
1371
1372 /* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
1373 ** Fetch the baseline checkins for both.
1374 */
1375 assert( pParent==0 || pChild==0 );
1376 if( pParent==0 ){
1377 ppOther = &pParent;
1378 otherRid = pmid;
1379 }else{
1380 ppOther = &pChild;
1381 otherRid = mid;
1382 }
1383 if( (*ppOther = manifest_cache_find(otherRid))==0 ){
1384 content_get(otherRid, &otherContent);
1385 if( blob_size(&otherContent)==0 ) return;
1386 *ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
1388 }
1389 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1390 manifest_destroy(*ppOther);
1391 return;
1392 }
1393 isPublic = !content_is_private(mid);
1394
1395 /* Try to make the parent manifest a delta from the child, if that
1396 ** is an appropriate thing to do. For a new baseline, make the
1397 ** previous baseline a delta from the current baseline.
1398 */
1399 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1400 content_deltify(pmid, mid, 0);
1401 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1402 content_deltify(pParent->pBaseline->rid, mid, 0);
1403 }
1404
1405 /* Remember all children less than a few seconds younger than their parent,
1406 ** as we might want to fudge the times for those children.
1407 */
@@ -1412,31 +1421,32 @@
1421 int mperm = manifest_file_mperm(pChildFile);
1422 if( pChildFile->zPrior ){
1423 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
1424 if( pParentFile ){
1425 /* File with name change */
1426 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1427 pChildFile->zName, pChildFile->zPrior,
1428 isPublic, isPrim, mperm);
1429 }else{
1430 /* File name changed, but the old name is not found in the parent!
1431 ** Treat this like a new file. */
1432 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1433 isPublic, isPrim, mperm);
1434 }
1435 }else{
1436 pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
1437 if( pParentFile==0 ){
1438 if( pChildFile->zUuid ){
1439 /* A new file */
1440 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1441 isPublic, isPrim, mperm);
1442 }
1443 }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
1444 || manifest_file_mperm(pParentFile)!=mperm ){
1445 /* Changes in file content or permissions */
1446 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1447 pChildFile->zName, 0, isPublic, isPrim, mperm);
1448 }
1449 }
1450 }
1451 if( pParent->zBaseline && pChild->zBaseline ){
1452 /* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
1458 pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
1459 if( pChildFile==0 ){
1460 /* The child file reverts to baseline. Show this as a change */
1461 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1462 if( pChildFile ){
1463 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1464 pChildFile->zName, 0, isPublic, isPrim,
1465 manifest_file_mperm(pChildFile));
1466 }
1467 }
1468 }else{
1469 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1470 if( pChildFile ){
1471 /* File resurrected in the child after having been deleted in
1472 ** the parent. Show this as an added file. */
1473 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1474 isPublic, isPrim, manifest_file_mperm(pChildFile));
1475 }
1476 }
1477 }
1478 }else if( pChild->zBaseline==0 ){
1479 /* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
1480 ** but are missing from pChild and mark them as having been deleted. */
1481 manifest_file_rewind(pParent);
1482 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1483 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1484 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1485 add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
1486 isPublic, isPrim, 0);
1487 }
1488 }
1489 }
1490 manifest_cache_insert(*ppOther);
1491 }
@@ -1779,45 +1789,46 @@
1789 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1790 uuid_to_rid(p->zBaseline,1));
1791 }else{
1792 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1793 }
 
1794 for(i=0; i<p->nParent; i++){
1795 int pid = uuid_to_rid(p->azParent[i], 1);
1796 db_multi_exec(
1797 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1798 "VALUES(%d, %d, %d, %.17g, %s)",
1799 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1800 add_mlink(pid, 0, rid, p, i==0);
1801 if( i==0 ) parentid = pid;
1802 }
1803 if( p->nParent>1 ){
1804 /* Remove incorrect MLINK create-file entries that arise when a
1805 ** file is added by merge. */
1806 db_multi_exec(
1807 "DELETE FROM mlink"
1808 " WHERE mid=%d"
1809 " AND pid=0"
1810 " AND fnid IN "
1811 " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1812 " HAVING count(*)<%d)",
1813 rid, rid, p->nParent
1814 );
1815 }
1816 db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1817 while( db_step(&q)==SQLITE_ROW ){
1818 int cid = db_column_int(&q, 0);
1819 int isprim = db_column_int(&q, 1);
1820 add_mlink(rid, p, cid, 0, isprim);
1821 }
1822 db_finalize(&q);
1823 if( p->nParent==0 ){
1824 /* For root files (files without parents) add mlink entries
1825 ** showing all content as new. */
1826 int isPublic = !content_is_private(rid);
1827 for(i=0; i<p->nFile; i++){
1828 add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1829 isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1830 }
1831 }
1832 db_multi_exec(
1833 "REPLACE INTO event(type,mtime,objid,user,comment,"
1834 "bgcolor,euser,ecomment,omtime)"
1835
1836 DDED src/markdown.md
+64 -53
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
11851185
/*
11861186
** Add a single entry to the mlink table. Also add the filename to
11871187
** the filename table if it is not there already.
11881188
*/
11891189
static void add_one_mlink(
1190
+ int pmid, /* The parent manifest */
1191
+ const char *zFromUuid, /* UUID for content in parent */
11901192
int mid, /* The record ID of the manifest */
1191
- const char *zFromUuid, /* UUID for the mlink.pid. "" to add file */
1192
- const char *zToUuid, /* UUID for the mlink.fid. "" to delete */
1193
+ const char *zToUuid, /* UUID for content in child */
11931194
const char *zFilename, /* Filename */
11941195
const char *zPrior, /* Previous filename. NULL if unchanged */
11951196
int isPublic, /* True if mid is not a private manifest */
1197
+ int isPrimary, /* pmid is the primary parent of mid */
11961198
int mperm /* 1: exec, 2: symlink */
11971199
){
11981200
int fnid, pfnid, pid, fid;
11991201
static Stmt s1;
12001202
@@ -1214,19 +1216,21 @@
12141216
}else{
12151217
fid = uuid_to_rid(zToUuid, 1);
12161218
if( isPublic ) content_make_public(fid);
12171219
}
12181220
db_static_prepare(&s1,
1219
- "INSERT INTO mlink(mid,pid,fid,fnid,pfnid,mperm)"
1220
- "VALUES(:m,:p,:f,:n,:pfn,:mp)"
1221
+ "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1222
+ "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
12211223
);
12221224
db_bind_int(&s1, ":m", mid);
1223
- db_bind_int(&s1, ":p", pid);
12241225
db_bind_int(&s1, ":f", fid);
1226
+ db_bind_int(&s1, ":pm", pmid);
1227
+ db_bind_int(&s1, ":p", pid);
12251228
db_bind_int(&s1, ":n", fnid);
12261229
db_bind_int(&s1, ":pfn", pfnid);
12271230
db_bind_int(&s1, ":mp", mperm);
1231
+ db_bind_int(&s1, ":isaux", isPrimary==0);
12281232
db_exec(&s1);
12291233
if( pid && fid ){
12301234
content_deltify(pid, fid, 0);
12311235
}
12321236
}
@@ -1340,24 +1344,29 @@
13401344
**
13411345
** Deleted files have mlink.fid=0.
13421346
** Added files have mlink.pid=0.
13431347
** Edited files have both mlink.pid!=0 and mlink.fid!=0
13441348
*/
1345
-static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
1349
+static void add_mlink(
1350
+ int pmid, Manifest *pParent, /* Parent check-in */
1351
+ int mid, Manifest *pChild, /* The child check-in */
1352
+ int isPrim /* TRUE if pmid is the primary parent of mid */
1353
+){
13461354
Blob otherContent;
13471355
int otherRid;
13481356
int i, rc;
13491357
ManifestFile *pChildFile, *pParentFile;
13501358
Manifest **ppOther;
13511359
static Stmt eq;
13521360
int isPublic; /* True if pChild is non-private */
13531361
1354
- /* If mlink table entires are already set for cid, then abort early
1355
- ** doing no work.
1362
+ /* If mlink table entires are already exist for the pmid-to-mid transition,
1363
+ ** then abort early doing no work.
13561364
*/
1357
- db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid");
1358
- db_bind_int(&eq, ":mid", cid);
1365
+ db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid AND pmid=:pmid");
1366
+ db_bind_int(&eq, ":mid", mid);
1367
+ db_bind_int(&eq, ":pmid", pmid);
13591368
rc = db_step(&eq);
13601369
db_reset(&eq);
13611370
if( rc==SQLITE_ROW ) return;
13621371
13631372
/* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
13641373
** Fetch the baseline checkins for both.
13651374
*/
13661375
assert( pParent==0 || pChild==0 );
13671376
if( pParent==0 ){
13681377
ppOther = &pParent;
1369
- otherRid = pid;
1378
+ otherRid = pmid;
13701379
}else{
13711380
ppOther = &pChild;
1372
- otherRid = cid;
1381
+ otherRid = mid;
13731382
}
13741383
if( (*ppOther = manifest_cache_find(otherRid))==0 ){
13751384
content_get(otherRid, &otherContent);
13761385
if( blob_size(&otherContent)==0 ) return;
13771386
*ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
13791388
}
13801389
if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
13811390
manifest_destroy(*ppOther);
13821391
return;
13831392
}
1384
- isPublic = !content_is_private(cid);
1393
+ isPublic = !content_is_private(mid);
13851394
13861395
/* Try to make the parent manifest a delta from the child, if that
13871396
** is an appropriate thing to do. For a new baseline, make the
13881397
** previous baseline a delta from the current baseline.
13891398
*/
13901399
if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1391
- content_deltify(pid, cid, 0);
1400
+ content_deltify(pmid, mid, 0);
13921401
}else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1393
- content_deltify(pParent->pBaseline->rid, cid, 0);
1402
+ content_deltify(pParent->pBaseline->rid, mid, 0);
13941403
}
13951404
13961405
/* Remember all children less than a few seconds younger than their parent,
13971406
** as we might want to fudge the times for those children.
13981407
*/
@@ -1412,31 +1421,32 @@
14121421
int mperm = manifest_file_mperm(pChildFile);
14131422
if( pChildFile->zPrior ){
14141423
pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
14151424
if( pParentFile ){
14161425
/* File with name change */
1417
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1418
- pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
1426
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1427
+ pChildFile->zName, pChildFile->zPrior,
1428
+ isPublic, isPrim, mperm);
14191429
}else{
14201430
/* File name changed, but the old name is not found in the parent!
14211431
** Treat this like a new file. */
1422
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1423
- isPublic, mperm);
1432
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1433
+ isPublic, isPrim, mperm);
14241434
}
14251435
}else{
14261436
pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
14271437
if( pParentFile==0 ){
14281438
if( pChildFile->zUuid ){
14291439
/* A new file */
1430
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1431
- isPublic, mperm);
1440
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1441
+ isPublic, isPrim, mperm);
14321442
}
14331443
}else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
14341444
|| manifest_file_mperm(pParentFile)!=mperm ){
14351445
/* Changes in file content or permissions */
1436
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1437
- pChildFile->zName, 0, isPublic, mperm);
1446
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1447
+ pChildFile->zName, 0, isPublic, isPrim, mperm);
14381448
}
14391449
}
14401450
}
14411451
if( pParent->zBaseline && pChild->zBaseline ){
14421452
/* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
14481458
pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
14491459
if( pChildFile==0 ){
14501460
/* The child file reverts to baseline. Show this as a change */
14511461
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14521462
if( pChildFile ){
1453
- add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1454
- pChildFile->zName, 0, isPublic,
1463
+ add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1464
+ pChildFile->zName, 0, isPublic, isPrim,
14551465
manifest_file_mperm(pChildFile));
14561466
}
14571467
}
14581468
}else{
14591469
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14601470
if( pChildFile ){
14611471
/* File resurrected in the child after having been deleted in
14621472
** the parent. Show this as an added file. */
1463
- add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1464
- isPublic, manifest_file_mperm(pChildFile));
1473
+ add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1474
+ isPublic, isPrim, manifest_file_mperm(pChildFile));
14651475
}
14661476
}
14671477
}
14681478
}else if( pChild->zBaseline==0 ){
14691479
/* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
14701480
** but are missing from pChild and mark them as having been deleted. */
14711481
manifest_file_rewind(pParent);
14721482
while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
14731483
pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
14741484
if( pChildFile==0 && pParentFile->zUuid!=0 ){
1475
- add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1476
- isPublic, 0);
1485
+ add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
1486
+ isPublic, isPrim, 0);
14771487
}
14781488
}
14791489
}
14801490
manifest_cache_insert(*ppOther);
14811491
}
@@ -1779,45 +1789,46 @@
17791789
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
17801790
uuid_to_rid(p->zBaseline,1));
17811791
}else{
17821792
sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
17831793
}
1784
- (void)db_schema_is_outofdate(); /* Make sure g.zAuxSchema is initialized */
17851794
for(i=0; i<p->nParent; i++){
17861795
int pid = uuid_to_rid(p->azParent[i], 1);
1787
- if( strcmp(g.zAuxSchema,"2014-11-24 20:35")>=0 ){
1788
- /* Support for PLINK.BASEID added on 2014-11-24 */
1789
- db_multi_exec(
1790
- "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1791
- "VALUES(%d, %d, %d, %.17g, %s)",
1792
- pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1793
- }else{
1794
- /* Continue to work with older schema to avoid an unnecessary
1795
- ** rebuild */
1796
- db_multi_exec(
1797
- "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
1798
- "VALUES(%d, %d, %d, %.17g)",
1799
- pid, rid, i==0, p->rDate);
1800
- }
1801
- if( i==0 ){
1802
- add_mlink(pid, 0, rid, p);
1803
- parentid = pid;
1804
- }
1805
- }
1806
- db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
1796
+ db_multi_exec(
1797
+ "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1798
+ "VALUES(%d, %d, %d, %.17g, %s)",
1799
+ pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1800
+ add_mlink(pid, 0, rid, p, i==0);
1801
+ if( i==0 ) parentid = pid;
1802
+ }
1803
+ if( p->nParent>1 ){
1804
+ /* Remove incorrect MLINK create-file entries that arise when a
1805
+ ** file is added by merge. */
1806
+ db_multi_exec(
1807
+ "DELETE FROM mlink"
1808
+ " WHERE mid=%d"
1809
+ " AND pid=0"
1810
+ " AND fnid IN "
1811
+ " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1812
+ " HAVING count(*)<%d)",
1813
+ rid, rid, p->nParent
1814
+ );
1815
+ }
1816
+ db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
18071817
while( db_step(&q)==SQLITE_ROW ){
18081818
int cid = db_column_int(&q, 0);
1809
- add_mlink(rid, p, cid, 0);
1819
+ int isprim = db_column_int(&q, 1);
1820
+ add_mlink(rid, p, cid, 0, isprim);
18101821
}
18111822
db_finalize(&q);
18121823
if( p->nParent==0 ){
18131824
/* For root files (files without parents) add mlink entries
18141825
** showing all content as new. */
18151826
int isPublic = !content_is_private(rid);
18161827
for(i=0; i<p->nFile; i++){
1817
- add_one_mlink(rid, 0, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1818
- isPublic, manifest_file_mperm(&p->aFile[i]));
1828
+ add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1829
+ isPublic, 1, manifest_file_mperm(&p->aFile[i]));
18191830
}
18201831
}
18211832
db_multi_exec(
18221833
"REPLACE INTO event(type,mtime,objid,user,comment,"
18231834
"bgcolor,euser,ecomment,omtime)"
18241835
18251836
ADDED src/markdown.md
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
1185 /*
1186 ** Add a single entry to the mlink table. Also add the filename to
1187 ** the filename table if it is not there already.
1188 */
1189 static void add_one_mlink(
 
 
1190 int mid, /* The record ID of the manifest */
1191 const char *zFromUuid, /* UUID for the mlink.pid. "" to add file */
1192 const char *zToUuid, /* UUID for the mlink.fid. "" to delete */
1193 const char *zFilename, /* Filename */
1194 const char *zPrior, /* Previous filename. NULL if unchanged */
1195 int isPublic, /* True if mid is not a private manifest */
 
1196 int mperm /* 1: exec, 2: symlink */
1197 ){
1198 int fnid, pfnid, pid, fid;
1199 static Stmt s1;
1200
@@ -1214,19 +1216,21 @@
1214 }else{
1215 fid = uuid_to_rid(zToUuid, 1);
1216 if( isPublic ) content_make_public(fid);
1217 }
1218 db_static_prepare(&s1,
1219 "INSERT INTO mlink(mid,pid,fid,fnid,pfnid,mperm)"
1220 "VALUES(:m,:p,:f,:n,:pfn,:mp)"
1221 );
1222 db_bind_int(&s1, ":m", mid);
1223 db_bind_int(&s1, ":p", pid);
1224 db_bind_int(&s1, ":f", fid);
 
 
1225 db_bind_int(&s1, ":n", fnid);
1226 db_bind_int(&s1, ":pfn", pfnid);
1227 db_bind_int(&s1, ":mp", mperm);
 
1228 db_exec(&s1);
1229 if( pid && fid ){
1230 content_deltify(pid, fid, 0);
1231 }
1232 }
@@ -1340,24 +1344,29 @@
1340 **
1341 ** Deleted files have mlink.fid=0.
1342 ** Added files have mlink.pid=0.
1343 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
1344 */
1345 static void add_mlink(int pid, Manifest *pParent, int cid, Manifest *pChild){
 
 
 
 
1346 Blob otherContent;
1347 int otherRid;
1348 int i, rc;
1349 ManifestFile *pChildFile, *pParentFile;
1350 Manifest **ppOther;
1351 static Stmt eq;
1352 int isPublic; /* True if pChild is non-private */
1353
1354 /* If mlink table entires are already set for cid, then abort early
1355 ** doing no work.
1356 */
1357 db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid");
1358 db_bind_int(&eq, ":mid", cid);
 
1359 rc = db_step(&eq);
1360 db_reset(&eq);
1361 if( rc==SQLITE_ROW ) return;
1362
1363 /* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
1364 ** Fetch the baseline checkins for both.
1365 */
1366 assert( pParent==0 || pChild==0 );
1367 if( pParent==0 ){
1368 ppOther = &pParent;
1369 otherRid = pid;
1370 }else{
1371 ppOther = &pChild;
1372 otherRid = cid;
1373 }
1374 if( (*ppOther = manifest_cache_find(otherRid))==0 ){
1375 content_get(otherRid, &otherContent);
1376 if( blob_size(&otherContent)==0 ) return;
1377 *ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
1379 }
1380 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1381 manifest_destroy(*ppOther);
1382 return;
1383 }
1384 isPublic = !content_is_private(cid);
1385
1386 /* Try to make the parent manifest a delta from the child, if that
1387 ** is an appropriate thing to do. For a new baseline, make the
1388 ** previous baseline a delta from the current baseline.
1389 */
1390 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1391 content_deltify(pid, cid, 0);
1392 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1393 content_deltify(pParent->pBaseline->rid, cid, 0);
1394 }
1395
1396 /* Remember all children less than a few seconds younger than their parent,
1397 ** as we might want to fudge the times for those children.
1398 */
@@ -1412,31 +1421,32 @@
1412 int mperm = manifest_file_mperm(pChildFile);
1413 if( pChildFile->zPrior ){
1414 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
1415 if( pParentFile ){
1416 /* File with name change */
1417 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1418 pChildFile->zName, pChildFile->zPrior, isPublic, mperm);
 
1419 }else{
1420 /* File name changed, but the old name is not found in the parent!
1421 ** Treat this like a new file. */
1422 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1423 isPublic, mperm);
1424 }
1425 }else{
1426 pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
1427 if( pParentFile==0 ){
1428 if( pChildFile->zUuid ){
1429 /* A new file */
1430 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1431 isPublic, mperm);
1432 }
1433 }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
1434 || manifest_file_mperm(pParentFile)!=mperm ){
1435 /* Changes in file content or permissions */
1436 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1437 pChildFile->zName, 0, isPublic, mperm);
1438 }
1439 }
1440 }
1441 if( pParent->zBaseline && pChild->zBaseline ){
1442 /* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
1448 pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
1449 if( pChildFile==0 ){
1450 /* The child file reverts to baseline. Show this as a change */
1451 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1452 if( pChildFile ){
1453 add_one_mlink(cid, pParentFile->zUuid, pChildFile->zUuid,
1454 pChildFile->zName, 0, isPublic,
1455 manifest_file_mperm(pChildFile));
1456 }
1457 }
1458 }else{
1459 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1460 if( pChildFile ){
1461 /* File resurrected in the child after having been deleted in
1462 ** the parent. Show this as an added file. */
1463 add_one_mlink(cid, 0, pChildFile->zUuid, pChildFile->zName, 0,
1464 isPublic, manifest_file_mperm(pChildFile));
1465 }
1466 }
1467 }
1468 }else if( pChild->zBaseline==0 ){
1469 /* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
1470 ** but are missing from pChild and mark them as having been deleted. */
1471 manifest_file_rewind(pParent);
1472 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1473 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1474 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1475 add_one_mlink(cid, pParentFile->zUuid, 0, pParentFile->zName, 0,
1476 isPublic, 0);
1477 }
1478 }
1479 }
1480 manifest_cache_insert(*ppOther);
1481 }
@@ -1779,45 +1789,46 @@
1779 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1780 uuid_to_rid(p->zBaseline,1));
1781 }else{
1782 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1783 }
1784 (void)db_schema_is_outofdate(); /* Make sure g.zAuxSchema is initialized */
1785 for(i=0; i<p->nParent; i++){
1786 int pid = uuid_to_rid(p->azParent[i], 1);
1787 if( strcmp(g.zAuxSchema,"2014-11-24 20:35")>=0 ){
1788 /* Support for PLINK.BASEID added on 2014-11-24 */
1789 db_multi_exec(
1790 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1791 "VALUES(%d, %d, %d, %.17g, %s)",
1792 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1793 }else{
1794 /* Continue to work with older schema to avoid an unnecessary
1795 ** rebuild */
1796 db_multi_exec(
1797 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime)"
1798 "VALUES(%d, %d, %d, %.17g)",
1799 pid, rid, i==0, p->rDate);
1800 }
1801 if( i==0 ){
1802 add_mlink(pid, 0, rid, p);
1803 parentid = pid;
1804 }
1805 }
1806 db_prepare(&q, "SELECT cid FROM plink WHERE pid=%d AND isprim", rid);
 
1807 while( db_step(&q)==SQLITE_ROW ){
1808 int cid = db_column_int(&q, 0);
1809 add_mlink(rid, p, cid, 0);
 
1810 }
1811 db_finalize(&q);
1812 if( p->nParent==0 ){
1813 /* For root files (files without parents) add mlink entries
1814 ** showing all content as new. */
1815 int isPublic = !content_is_private(rid);
1816 for(i=0; i<p->nFile; i++){
1817 add_one_mlink(rid, 0, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1818 isPublic, manifest_file_mperm(&p->aFile[i]));
1819 }
1820 }
1821 db_multi_exec(
1822 "REPLACE INTO event(type,mtime,objid,user,comment,"
1823 "bgcolor,euser,ecomment,omtime)"
1824
1825 DDED src/markdown.md
--- src/manifest.c
+++ src/manifest.c
@@ -1185,16 +1185,18 @@
1185 /*
1186 ** Add a single entry to the mlink table. Also add the filename to
1187 ** the filename table if it is not there already.
1188 */
1189 static void add_one_mlink(
1190 int pmid, /* The parent manifest */
1191 const char *zFromUuid, /* UUID for content in parent */
1192 int mid, /* The record ID of the manifest */
1193 const char *zToUuid, /* UUID for content in child */
 
1194 const char *zFilename, /* Filename */
1195 const char *zPrior, /* Previous filename. NULL if unchanged */
1196 int isPublic, /* True if mid is not a private manifest */
1197 int isPrimary, /* pmid is the primary parent of mid */
1198 int mperm /* 1: exec, 2: symlink */
1199 ){
1200 int fnid, pfnid, pid, fid;
1201 static Stmt s1;
1202
@@ -1214,19 +1216,21 @@
1216 }else{
1217 fid = uuid_to_rid(zToUuid, 1);
1218 if( isPublic ) content_make_public(fid);
1219 }
1220 db_static_prepare(&s1,
1221 "INSERT INTO mlink(mid,fid,pmid,pid,fnid,pfnid,mperm,isaux)"
1222 "VALUES(:m,:f,:pm,:p,:n,:pfn,:mp,:isaux)"
1223 );
1224 db_bind_int(&s1, ":m", mid);
 
1225 db_bind_int(&s1, ":f", fid);
1226 db_bind_int(&s1, ":pm", pmid);
1227 db_bind_int(&s1, ":p", pid);
1228 db_bind_int(&s1, ":n", fnid);
1229 db_bind_int(&s1, ":pfn", pfnid);
1230 db_bind_int(&s1, ":mp", mperm);
1231 db_bind_int(&s1, ":isaux", isPrimary==0);
1232 db_exec(&s1);
1233 if( pid && fid ){
1234 content_deltify(pid, fid, 0);
1235 }
1236 }
@@ -1340,24 +1344,29 @@
1344 **
1345 ** Deleted files have mlink.fid=0.
1346 ** Added files have mlink.pid=0.
1347 ** Edited files have both mlink.pid!=0 and mlink.fid!=0
1348 */
1349 static void add_mlink(
1350 int pmid, Manifest *pParent, /* Parent check-in */
1351 int mid, Manifest *pChild, /* The child check-in */
1352 int isPrim /* TRUE if pmid is the primary parent of mid */
1353 ){
1354 Blob otherContent;
1355 int otherRid;
1356 int i, rc;
1357 ManifestFile *pChildFile, *pParentFile;
1358 Manifest **ppOther;
1359 static Stmt eq;
1360 int isPublic; /* True if pChild is non-private */
1361
1362 /* If mlink table entires are already exist for the pmid-to-mid transition,
1363 ** then abort early doing no work.
1364 */
1365 db_static_prepare(&eq, "SELECT 1 FROM mlink WHERE mid=:mid AND pmid=:pmid");
1366 db_bind_int(&eq, ":mid", mid);
1367 db_bind_int(&eq, ":pmid", pmid);
1368 rc = db_step(&eq);
1369 db_reset(&eq);
1370 if( rc==SQLITE_ROW ) return;
1371
1372 /* Compute the value of the missing pParent or pChild parameter.
@@ -1364,14 +1373,14 @@
1373 ** Fetch the baseline checkins for both.
1374 */
1375 assert( pParent==0 || pChild==0 );
1376 if( pParent==0 ){
1377 ppOther = &pParent;
1378 otherRid = pmid;
1379 }else{
1380 ppOther = &pChild;
1381 otherRid = mid;
1382 }
1383 if( (*ppOther = manifest_cache_find(otherRid))==0 ){
1384 content_get(otherRid, &otherContent);
1385 if( blob_size(&otherContent)==0 ) return;
1386 *ppOther = manifest_parse(&otherContent, otherRid, 0);
@@ -1379,20 +1388,20 @@
1388 }
1389 if( fetch_baseline(pParent, 0) || fetch_baseline(pChild, 0) ){
1390 manifest_destroy(*ppOther);
1391 return;
1392 }
1393 isPublic = !content_is_private(mid);
1394
1395 /* Try to make the parent manifest a delta from the child, if that
1396 ** is an appropriate thing to do. For a new baseline, make the
1397 ** previous baseline a delta from the current baseline.
1398 */
1399 if( (pParent->zBaseline==0)==(pChild->zBaseline==0) ){
1400 content_deltify(pmid, mid, 0);
1401 }else if( pChild->zBaseline==0 && pParent->zBaseline!=0 ){
1402 content_deltify(pParent->pBaseline->rid, mid, 0);
1403 }
1404
1405 /* Remember all children less than a few seconds younger than their parent,
1406 ** as we might want to fudge the times for those children.
1407 */
@@ -1412,31 +1421,32 @@
1421 int mperm = manifest_file_mperm(pChildFile);
1422 if( pChildFile->zPrior ){
1423 pParentFile = manifest_file_seek(pParent, pChildFile->zPrior, 0);
1424 if( pParentFile ){
1425 /* File with name change */
1426 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1427 pChildFile->zName, pChildFile->zPrior,
1428 isPublic, isPrim, mperm);
1429 }else{
1430 /* File name changed, but the old name is not found in the parent!
1431 ** Treat this like a new file. */
1432 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1433 isPublic, isPrim, mperm);
1434 }
1435 }else{
1436 pParentFile = manifest_file_seek(pParent, pChildFile->zName, 0);
1437 if( pParentFile==0 ){
1438 if( pChildFile->zUuid ){
1439 /* A new file */
1440 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1441 isPublic, isPrim, mperm);
1442 }
1443 }else if( fossil_strcmp(pChildFile->zUuid, pParentFile->zUuid)!=0
1444 || manifest_file_mperm(pParentFile)!=mperm ){
1445 /* Changes in file content or permissions */
1446 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1447 pChildFile->zName, 0, isPublic, isPrim, mperm);
1448 }
1449 }
1450 }
1451 if( pParent->zBaseline && pChild->zBaseline ){
1452 /* Both parent and child are delta manifests. Look for files that
@@ -1448,22 +1458,22 @@
1458 pChildFile = manifest_file_seek_base(pChild, pParentFile->zName, 0);
1459 if( pChildFile==0 ){
1460 /* The child file reverts to baseline. Show this as a change */
1461 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1462 if( pChildFile ){
1463 add_one_mlink(pmid, pParentFile->zUuid, mid, pChildFile->zUuid,
1464 pChildFile->zName, 0, isPublic, isPrim,
1465 manifest_file_mperm(pChildFile));
1466 }
1467 }
1468 }else{
1469 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1470 if( pChildFile ){
1471 /* File resurrected in the child after having been deleted in
1472 ** the parent. Show this as an added file. */
1473 add_one_mlink(pmid, 0, mid, pChildFile->zUuid, pChildFile->zName, 0,
1474 isPublic, isPrim, manifest_file_mperm(pChildFile));
1475 }
1476 }
1477 }
1478 }else if( pChild->zBaseline==0 ){
1479 /* pChild is a baseline. Look for files that are present in pParent
@@ -1470,12 +1480,12 @@
1480 ** but are missing from pChild and mark them as having been deleted. */
1481 manifest_file_rewind(pParent);
1482 while( (pParentFile = manifest_file_next(pParent,0))!=0 ){
1483 pChildFile = manifest_file_seek(pChild, pParentFile->zName, 0);
1484 if( pChildFile==0 && pParentFile->zUuid!=0 ){
1485 add_one_mlink(pmid, pParentFile->zUuid, mid, 0, pParentFile->zName, 0,
1486 isPublic, isPrim, 0);
1487 }
1488 }
1489 }
1490 manifest_cache_insert(*ppOther);
1491 }
@@ -1779,45 +1789,46 @@
1789 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "%d",
1790 uuid_to_rid(p->zBaseline,1));
1791 }else{
1792 sqlite3_snprintf(sizeof(zBaseId), zBaseId, "NULL");
1793 }
 
1794 for(i=0; i<p->nParent; i++){
1795 int pid = uuid_to_rid(p->azParent[i], 1);
1796 db_multi_exec(
1797 "INSERT OR IGNORE INTO plink(pid, cid, isprim, mtime, baseid)"
1798 "VALUES(%d, %d, %d, %.17g, %s)",
1799 pid, rid, i==0, p->rDate, zBaseId/*safe-for-%s*/);
1800 add_mlink(pid, 0, rid, p, i==0);
1801 if( i==0 ) parentid = pid;
1802 }
1803 if( p->nParent>1 ){
1804 /* Remove incorrect MLINK create-file entries that arise when a
1805 ** file is added by merge. */
1806 db_multi_exec(
1807 "DELETE FROM mlink"
1808 " WHERE mid=%d"
1809 " AND pid=0"
1810 " AND fnid IN "
1811 " (SELECT fnid FROM mlink WHERE mid=%d GROUP BY fnid"
1812 " HAVING count(*)<%d)",
1813 rid, rid, p->nParent
1814 );
1815 }
1816 db_prepare(&q, "SELECT cid, isprim FROM plink WHERE pid=%d", rid);
1817 while( db_step(&q)==SQLITE_ROW ){
1818 int cid = db_column_int(&q, 0);
1819 int isprim = db_column_int(&q, 1);
1820 add_mlink(rid, p, cid, 0, isprim);
1821 }
1822 db_finalize(&q);
1823 if( p->nParent==0 ){
1824 /* For root files (files without parents) add mlink entries
1825 ** showing all content as new. */
1826 int isPublic = !content_is_private(rid);
1827 for(i=0; i<p->nFile; i++){
1828 add_one_mlink(0, 0, rid, p->aFile[i].zUuid, p->aFile[i].zName, 0,
1829 isPublic, 1, manifest_file_mperm(&p->aFile[i]));
1830 }
1831 }
1832 db_multi_exec(
1833 "REPLACE INTO event(type,mtime,objid,user,comment,"
1834 "bgcolor,euser,ecomment,omtime)"
1835
1836 DDED src/markdown.md
--- a/src/markdown.md
+++ b/src/markdown.md
@@ -0,0 +1,224 @@
1
+# Markdown formatting rules
2
+
3
+In addition to its native Wiki formatting syntax, Fossil supports Mark down syntax as specified by
4
+[John Gruber's original Markdown implementation](http://daringfireba
5
+[syntax description](http://daringfireball.net/projects/markdown/syntax), of which the page you
6
+are reading is an extract.
7
+
8
+This page itself uses Markdown formatting.
9
+
10
+## Summary
11
+
12
+ - Block elements
13
+
14
+ * A **paragraph** is a group of consecutive lines. Paragraphs are separated by blank lines.
15
+
16
+ * A **Header** is a line of text underlined with equal signs or hyphens, or prefixed by a
17
+ in s, or prefixed by a
18
+ number of hash marks.
19
+
20
+ * **Block quotes** are blocks of text prefixed by '>'.
21
+
22
+ * **Ordered list** items are prefixed by a number and a period. **Unordered list** items
23
+ are prefixed by a hyphen, asterisk or plus sign. Pre
24
+
25
+ * **Code blocks** are formed by lines of text (possibly including empty lines) prefixed by
26
+ at least 4 spaces or a tab.
27
+
28
+ * A **horizontal rule** is a line consisting of 3 or more asterisks, hyphens or underscores,
29
+ with optional whitespace between them.
30
+
31
+ - Span elements
32
+
33
+ * 3 types of **links** exist:
34
+
35
+ - **automatic links** are URLs or email addresses enclosed in angle brackets
36
+ ('<' and '>'), and are displayed as such.
37
+
38
+ - **inline links** consist of the displayed link text in squ
39
+ followed by the
40
+
41
+ - **reference links** separate _link instance_ from _link definition_. A link instance efinition_. A link instance
42
+ consists of the displayed link text
43
+ in square brackets. in square brackets.
44
+ The corresponding link definition can occur anywhere on the page, and consists
45
+ of the link definition name in s a colon, whitespace and the
46
+ link target.
47
+
48
+ * **Emphasis** can be given by wrapping text in one or two asterisks or underscores - use
49
+ one for HTML `<em>`, and two for `<strong>` emphasis.
50
+
51
+ * A **code span** is text wrapped in backticks ('`').
52
+
53
+ * **Images** use a syntax much like inline or reference links, # Markdown formatting rules
54
+
55
+In addition to its native Wiki formatting syntax, Fossil supports Markdown syntax as specified by
56
+[John Gruber's original Markdown implementation](http://daringfireball.net/projects/markdown/).
57
+For lots of examples - not repeated here - please refer to its
58
+[syntax description](http://daringfireball.net/projects/markdown/syntax), of which the page you
59
+are reading is an extract.
60
+
61
+This page itself uses Markdown formatting.
62
+
63
+## Summary
64
+
65
+ - Block elements
66
+
67
+ * A **paragraph** is a group of consecutive lines. Paragraphs are separated by blank lines.
68
+
69
+ * A **Header** is a line of text underlined with equal signs or hyphens, or prefixed by a
70
+ number of hash marks.
71
+
72
+ * **Block quotes** are blocks of text prefixed by '>'.
73
+
74
+ * **Ordered list** items are prefixed by a number and a period. **Unordered list** items
75
+ are prefixed by a hyphen, asterisk or plus sign. Prefix and item text are separated by
76
+ whitespace.
77
+
78
+ * **Code blocks** are formed by lines of text (possibly including empty lines) prefixed by
79
+ at least 4 spaces or a tab.
80
+
81
+ * A **horizontal rule** is a line consisting of 3 or more asterisks, hyphens or underscores,
82
+ with optional whitespace between them.
83
+
84
+ - Span elements
85
+
86
+ * 3 types of **links** exist:
87
+
88
+ - **automatic links** are URLs or email addresses enclosed in angle brackets
89
+ a * **Emphasis** can be given by wrapping text in one or two asterisks or underscores - use
90
+ one for HTML `<em>`, and two for `<strong>` emphasis.
91
+
92
+ * A **code span** is text wrapped in backticks ('`').
93
+
94
+ * **Images** use a syntax much like inline or reference links, but with alt attribute text
95
+ ('img alt=...') instead of link text, and the first pair of square
96
+ brackets m prefix; the items will be
97
+renumbered during rendering. However, future implementations may
98
+for the first item in a list indicates an offset to be used for subsequent items.
99
+
100
+For list items spanning multiple lines, subsequent lines can be indented using an arbitrary amount
101
+of whitespace.
102
+
103
+List items will be wrapped in HTML `<p>` tags if they are separated by blank lines.
104
+
105
+A list item may span multiple paragraphs. At least the first line
106
+be indented using at least 4 spaces or a tab character.
107
+
108
+Block quotes within list items must have their '>' delimiters indented using 4 up to 7 spaces.
109
+
110
+Code blocks within list items need to be indented _twice_, that is, using 8 spaces or 2 tab
111
+characters.
112
+
113
+### Code blocks
114
+
115
+Lines within a code block are rendered verbatim using HTML `<pre>` and `<code>` tags, except that
116
+HTML punctuation characters like '<' and '&' are automatically converted to HTML entities. Thus,
117
+there is no need to explicitly escape HTML syntax within a code block.
118
+
119
+A code block runs until the first non blank line with indent less than 4 spaces or 1 tab character.
120
+
121
+
122
+Regular Markdown syntax is not processed within code blocks.
123
+
124
+### Links
125
+
126
+#### Automatic links
127
+
128
+When rendering automatic links to email addresses, HTML enco
129
+prevent some spambots from harvesting.
130
+
131
+#### Inline links
132
+
133
+Links to resources on the same server can use relative paths (i.e. can start with a '/').
134
+
135
+An optional title for the link (e.g. to have mouseover text in the b rowser) may be given behind
136
+the link target but within the parentheses, in single and double quo
137
+link target by whitespace.
138
+link target by whitespace.
139
+
140
+# reference link consists of
141
+>
142
+> - one or more _link instances_ at appropriate locations in the page text
143
+> - a single _link definition_ at an arbit
144
+> During rendering, each link instance is resolved, and the corresponding definition is
145
+> filled in. No separate link definition clauses occu r in the rendered output.
146
+>
147
+> There are 3 fields involved in link instances and definitions:
148
+>
149
+> - link text (i.e. the text that is displayed at the resulting link)
150
+> - link definition name (i.e. an unique ID binding link instances to link definition)
151
+> - link target (a target URL for the link)
152
+
153
+Multiple link instances may reference the same link definition using its link definition
154
+name.
155
+
156
+Link definition names are case insensitive, and may contain letters, numbers, spaces and
157
+punctuation.
158
+
159
+##### Link instance
160
+
161
+A space may be inserted between the bracket pairs for link text and link definition name.
162
+
163
+A link instance can use an _implicit link definition name_ shortcut, in which case the link
164
+text is used as the link definition name. The second set of brackets then remains empty, e.g.
165
+'[Google][]' ('Google' being used as both link text and link definition name).
166
+
167
+##### Link definition
168
+
169
+The first bracket pair containing the link definition name may be indented using up to 3 spaces.
170
+
171
+The link target may optionally be surrounded by angle brackets ('<' and '>').
172
+
173
+A link target may be followed by an optional title (e.g. to have mouseover text in the browser).
174
+This title may be enclosed in parentheses, single or double quotes.
175
+
176
+Link definitions may be split into 2 lines, with the title on the second line, arbitrarily
177
+indented. This may be more visually pleasing when using long link targets.
178
+
179
+### Emphasis
180
+
181
+The same character(s) used for starting the emphasis must be used to end it; don't mix
182
+asterisks and underscores.
183
+
184
+Emphasis can be used in the middle of a word. That is, there need not be whitespace on either
185
+side of emphasis start or end punctuation characters.
186
+
187
+### Code spans
188
+
189
+To include a literal backtick character in a code span, use multiple backticks as opening and
190
+closing delimiters.
191
+
192
+Whitespace may exist immediately after the opening delimiter and b Markdown formatting rules
193
+
194
+In addition to its native Wiki formatting syntax, Fossil supports Markdown syntax as specified by
195
+[John Gruber's original Markdown implementation](http://daringfireball.net/projects/markdown/).
196
+For lots of examples - not repeated here - please refer to its
197
+[syntax description](http://daringfireball.net/projects/markdownr
198
+a HTML block level construct (`<div>`, `<table>` etc) must be separated from surrounding
199
+context using blank lines, and must both occur at the start of a line.
200
+
201
+No extra unwanted `<p>` HTML tags are added around HTML block level tags.
202
+
203
+Markdown formatting within HTML block level tags is not processed; however, formatting within
204
+span level tags (e.g. `<mark>`) is processed normally.
205
+
206
+### Escaping Markdown punctuation
207
+
208
+The following punctuation characters can be escaped using backslash:
209
+
210
+ - \\ backslash
211
+ - ` backtick
212
+ - * asterisk
213
+ - _ underscore
214
+ - {} curly braces
215
+ - [] square brackets
216
+ - () parentheses
217
+ - # hash mark
218
+ - + plus sign
219
+ - - minus sign (hyphen)
220
+ - . dot
221
+ - ! exclamation mark
222
+
223
+To render a literal backslash, use 2 backslashes ('\\\\').
224
+
--- a/src/markdown.md
+++ b/src/markdown.md
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/markdown.md
+++ b/src/markdown.md
@@ -0,0 +1,224 @@
1 # Markdown formatting rules
2
3 In addition to its native Wiki formatting syntax, Fossil supports Mark down syntax as specified by
4 [John Gruber's original Markdown implementation](http://daringfireba
5 [syntax description](http://daringfireball.net/projects/markdown/syntax), of which the page you
6 are reading is an extract.
7
8 This page itself uses Markdown formatting.
9
10 ## Summary
11
12 - Block elements
13
14 * A **paragraph** is a group of consecutive lines. Paragraphs are separated by blank lines.
15
16 * A **Header** is a line of text underlined with equal signs or hyphens, or prefixed by a
17 in s, or prefixed by a
18 number of hash marks.
19
20 * **Block quotes** are blocks of text prefixed by '>'.
21
22 * **Ordered list** items are prefixed by a number and a period. **Unordered list** items
23 are prefixed by a hyphen, asterisk or plus sign. Pre
24
25 * **Code blocks** are formed by lines of text (possibly including empty lines) prefixed by
26 at least 4 spaces or a tab.
27
28 * A **horizontal rule** is a line consisting of 3 or more asterisks, hyphens or underscores,
29 with optional whitespace between them.
30
31 - Span elements
32
33 * 3 types of **links** exist:
34
35 - **automatic links** are URLs or email addresses enclosed in angle brackets
36 ('<' and '>'), and are displayed as such.
37
38 - **inline links** consist of the displayed link text in squ
39 followed by the
40
41 - **reference links** separate _link instance_ from _link definition_. A link instance efinition_. A link instance
42 consists of the displayed link text
43 in square brackets. in square brackets.
44 The corresponding link definition can occur anywhere on the page, and consists
45 of the link definition name in s a colon, whitespace and the
46 link target.
47
48 * **Emphasis** can be given by wrapping text in one or two asterisks or underscores - use
49 one for HTML `<em>`, and two for `<strong>` emphasis.
50
51 * A **code span** is text wrapped in backticks ('`').
52
53 * **Images** use a syntax much like inline or reference links, # Markdown formatting rules
54
55 In addition to its native Wiki formatting syntax, Fossil supports Markdown syntax as specified by
56 [John Gruber's original Markdown implementation](http://daringfireball.net/projects/markdown/).
57 For lots of examples - not repeated here - please refer to its
58 [syntax description](http://daringfireball.net/projects/markdown/syntax), of which the page you
59 are reading is an extract.
60
61 This page itself uses Markdown formatting.
62
63 ## Summary
64
65 - Block elements
66
67 * A **paragraph** is a group of consecutive lines. Paragraphs are separated by blank lines.
68
69 * A **Header** is a line of text underlined with equal signs or hyphens, or prefixed by a
70 number of hash marks.
71
72 * **Block quotes** are blocks of text prefixed by '>'.
73
74 * **Ordered list** items are prefixed by a number and a period. **Unordered list** items
75 are prefixed by a hyphen, asterisk or plus sign. Prefix and item text are separated by
76 whitespace.
77
78 * **Code blocks** are formed by lines of text (possibly including empty lines) prefixed by
79 at least 4 spaces or a tab.
80
81 * A **horizontal rule** is a line consisting of 3 or more asterisks, hyphens or underscores,
82 with optional whitespace between them.
83
84 - Span elements
85
86 * 3 types of **links** exist:
87
88 - **automatic links** are URLs or email addresses enclosed in angle brackets
89 a * **Emphasis** can be given by wrapping text in one or two asterisks or underscores - use
90 one for HTML `<em>`, and two for `<strong>` emphasis.
91
92 * A **code span** is text wrapped in backticks ('`').
93
94 * **Images** use a syntax much like inline or reference links, but with alt attribute text
95 ('img alt=...') instead of link text, and the first pair of square
96 brackets m prefix; the items will be
97 renumbered during rendering. However, future implementations may
98 for the first item in a list indicates an offset to be used for subsequent items.
99
100 For list items spanning multiple lines, subsequent lines can be indented using an arbitrary amount
101 of whitespace.
102
103 List items will be wrapped in HTML `<p>` tags if they are separated by blank lines.
104
105 A list item may span multiple paragraphs. At least the first line
106 be indented using at least 4 spaces or a tab character.
107
108 Block quotes within list items must have their '>' delimiters indented using 4 up to 7 spaces.
109
110 Code blocks within list items need to be indented _twice_, that is, using 8 spaces or 2 tab
111 characters.
112
113 ### Code blocks
114
115 Lines within a code block are rendered verbatim using HTML `<pre>` and `<code>` tags, except that
116 HTML punctuation characters like '<' and '&' are automatically converted to HTML entities. Thus,
117 there is no need to explicitly escape HTML syntax within a code block.
118
119 A code block runs until the first non blank line with indent less than 4 spaces or 1 tab character.
120
121
122 Regular Markdown syntax is not processed within code blocks.
123
124 ### Links
125
126 #### Automatic links
127
128 When rendering automatic links to email addresses, HTML enco
129 prevent some spambots from harvesting.
130
131 #### Inline links
132
133 Links to resources on the same server can use relative paths (i.e. can start with a '/').
134
135 An optional title for the link (e.g. to have mouseover text in the b rowser) may be given behind
136 the link target but within the parentheses, in single and double quo
137 link target by whitespace.
138 link target by whitespace.
139
140 # reference link consists of
141 >
142 > - one or more _link instances_ at appropriate locations in the page text
143 > - a single _link definition_ at an arbit
144 > During rendering, each link instance is resolved, and the corresponding definition is
145 > filled in. No separate link definition clauses occu r in the rendered output.
146 >
147 > There are 3 fields involved in link instances and definitions:
148 >
149 > - link text (i.e. the text that is displayed at the resulting link)
150 > - link definition name (i.e. an unique ID binding link instances to link definition)
151 > - link target (a target URL for the link)
152
153 Multiple link instances may reference the same link definition using its link definition
154 name.
155
156 Link definition names are case insensitive, and may contain letters, numbers, spaces and
157 punctuation.
158
159 ##### Link instance
160
161 A space may be inserted between the bracket pairs for link text and link definition name.
162
163 A link instance can use an _implicit link definition name_ shortcut, in which case the link
164 text is used as the link definition name. The second set of brackets then remains empty, e.g.
165 '[Google][]' ('Google' being used as both link text and link definition name).
166
167 ##### Link definition
168
169 The first bracket pair containing the link definition name may be indented using up to 3 spaces.
170
171 The link target may optionally be surrounded by angle brackets ('<' and '>').
172
173 A link target may be followed by an optional title (e.g. to have mouseover text in the browser).
174 This title may be enclosed in parentheses, single or double quotes.
175
176 Link definitions may be split into 2 lines, with the title on the second line, arbitrarily
177 indented. This may be more visually pleasing when using long link targets.
178
179 ### Emphasis
180
181 The same character(s) used for starting the emphasis must be used to end it; don't mix
182 asterisks and underscores.
183
184 Emphasis can be used in the middle of a word. That is, there need not be whitespace on either
185 side of emphasis start or end punctuation characters.
186
187 ### Code spans
188
189 To include a literal backtick character in a code span, use multiple backticks as opening and
190 closing delimiters.
191
192 Whitespace may exist immediately after the opening delimiter and b Markdown formatting rules
193
194 In addition to its native Wiki formatting syntax, Fossil supports Markdown syntax as specified by
195 [John Gruber's original Markdown implementation](http://daringfireball.net/projects/markdown/).
196 For lots of examples - not repeated here - please refer to its
197 [syntax description](http://daringfireball.net/projects/markdownr
198 a HTML block level construct (`<div>`, `<table>` etc) must be separated from surrounding
199 context using blank lines, and must both occur at the start of a line.
200
201 No extra unwanted `<p>` HTML tags are added around HTML block level tags.
202
203 Markdown formatting within HTML block level tags is not processed; however, formatting within
204 span level tags (e.g. `<mark>`) is processed normally.
205
206 ### Escaping Markdown punctuation
207
208 The following punctuation characters can be escaped using backslash:
209
210 - \\ backslash
211 - ` backtick
212 - * asterisk
213 - _ underscore
214 - {} curly braces
215 - [] square brackets
216 - () parentheses
217 - # hash mark
218 - + plus sign
219 - - minus sign (hyphen)
220 - . dot
221 - ! exclamation mark
222
223 To render a literal backslash, use 2 backslashes ('\\\\').
224
+5 -5
--- src/md5.c
+++ src/md5.c
@@ -177,11 +177,11 @@
177177
178178
/*
179179
* Update context to reflect the concatenation of another buffer full
180180
* of bytes.
181181
*/
182
-static
182
+static
183183
void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){
184184
struct Context *ctx = (struct Context *)pCtx;
185185
uint32 t;
186186
187187
/* Update bitcount */
@@ -224,11 +224,11 @@
224224
225225
memcpy(ctx->in, buf, len);
226226
}
227227
228228
/*
229
- * Final wrapup - pad to 64-byte boundary with the bit pattern
229
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
230230
* 1 0* (64-bit count of bits processed, MSB-first)
231231
*/
232232
static void MD5Final(unsigned char digest[16], MD5Context *pCtx){
233233
struct Context *ctx = (struct Context *)pCtx;
234234
unsigned count;
@@ -274,11 +274,11 @@
274274
** "unsigned char digest[16]" in the calling function. The MD5
275275
** digest is stored in the first 16 bytes. zBuf should
276276
** be "char zBuf[33]".
277277
*/
278278
static void DigestToBase16(unsigned char *digest, char *zBuf){
279
- static char const zEncode[] = "0123456789abcdef";
279
+ static const char zEncode[] = "0123456789abcdef";
280280
int i, j;
281281
282282
for(j=i=0; i<16; i++){
283283
int a = digest[i];
284284
zBuf[j++] = zEncode[(a>>4)&0xf];
@@ -343,11 +343,11 @@
343343
return zResult;
344344
}
345345
346346
/*
347347
** Finish the incremental MD5 checksum. Store the result in blob pOut
348
-** if pOut!=0. Also return a pointer to the result.
348
+** if pOut!=0. Also return a pointer to the result.
349349
**
350350
** This resets the incremental checksum preparing for the next round
351351
** of computation. The return pointer points to a static buffer that
352352
** is overwritten by subsequent calls to this function.
353353
*/
@@ -431,11 +431,11 @@
431431
*/
432432
void md5sum_test(void){
433433
int i;
434434
Blob in;
435435
Blob cksum;
436
-
436
+
437437
for(i=2; i<g.argc; i++){
438438
blob_init(&cksum, "********** not found ***********", -1);
439439
if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
440440
blob_read_from_channel(&in, stdin, -1);
441441
md5sum_blob(&in, &cksum);
442442
--- src/md5.c
+++ src/md5.c
@@ -177,11 +177,11 @@
177
178 /*
179 * Update context to reflect the concatenation of another buffer full
180 * of bytes.
181 */
182 static
183 void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){
184 struct Context *ctx = (struct Context *)pCtx;
185 uint32 t;
186
187 /* Update bitcount */
@@ -224,11 +224,11 @@
224
225 memcpy(ctx->in, buf, len);
226 }
227
228 /*
229 * Final wrapup - pad to 64-byte boundary with the bit pattern
230 * 1 0* (64-bit count of bits processed, MSB-first)
231 */
232 static void MD5Final(unsigned char digest[16], MD5Context *pCtx){
233 struct Context *ctx = (struct Context *)pCtx;
234 unsigned count;
@@ -274,11 +274,11 @@
274 ** "unsigned char digest[16]" in the calling function. The MD5
275 ** digest is stored in the first 16 bytes. zBuf should
276 ** be "char zBuf[33]".
277 */
278 static void DigestToBase16(unsigned char *digest, char *zBuf){
279 static char const zEncode[] = "0123456789abcdef";
280 int i, j;
281
282 for(j=i=0; i<16; i++){
283 int a = digest[i];
284 zBuf[j++] = zEncode[(a>>4)&0xf];
@@ -343,11 +343,11 @@
343 return zResult;
344 }
345
346 /*
347 ** Finish the incremental MD5 checksum. Store the result in blob pOut
348 ** if pOut!=0. Also return a pointer to the result.
349 **
350 ** This resets the incremental checksum preparing for the next round
351 ** of computation. The return pointer points to a static buffer that
352 ** is overwritten by subsequent calls to this function.
353 */
@@ -431,11 +431,11 @@
431 */
432 void md5sum_test(void){
433 int i;
434 Blob in;
435 Blob cksum;
436
437 for(i=2; i<g.argc; i++){
438 blob_init(&cksum, "********** not found ***********", -1);
439 if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
440 blob_read_from_channel(&in, stdin, -1);
441 md5sum_blob(&in, &cksum);
442
--- src/md5.c
+++ src/md5.c
@@ -177,11 +177,11 @@
177
178 /*
179 * Update context to reflect the concatenation of another buffer full
180 * of bytes.
181 */
182 static
183 void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){
184 struct Context *ctx = (struct Context *)pCtx;
185 uint32 t;
186
187 /* Update bitcount */
@@ -224,11 +224,11 @@
224
225 memcpy(ctx->in, buf, len);
226 }
227
228 /*
229 * Final wrapup - pad to 64-byte boundary with the bit pattern
230 * 1 0* (64-bit count of bits processed, MSB-first)
231 */
232 static void MD5Final(unsigned char digest[16], MD5Context *pCtx){
233 struct Context *ctx = (struct Context *)pCtx;
234 unsigned count;
@@ -274,11 +274,11 @@
274 ** "unsigned char digest[16]" in the calling function. The MD5
275 ** digest is stored in the first 16 bytes. zBuf should
276 ** be "char zBuf[33]".
277 */
278 static void DigestToBase16(unsigned char *digest, char *zBuf){
279 static const char zEncode[] = "0123456789abcdef";
280 int i, j;
281
282 for(j=i=0; i<16; i++){
283 int a = digest[i];
284 zBuf[j++] = zEncode[(a>>4)&0xf];
@@ -343,11 +343,11 @@
343 return zResult;
344 }
345
346 /*
347 ** Finish the incremental MD5 checksum. Store the result in blob pOut
348 ** if pOut!=0. Also return a pointer to the result.
349 **
350 ** This resets the incremental checksum preparing for the next round
351 ** of computation. The return pointer points to a static buffer that
352 ** is overwritten by subsequent calls to this function.
353 */
@@ -431,11 +431,11 @@
431 */
432 void md5sum_test(void){
433 int i;
434 Blob in;
435 Blob cksum;
436
437 for(i=2; i<g.argc; i++){
438 blob_init(&cksum, "********** not found ***********", -1);
439 if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
440 blob_read_from_channel(&in, stdin, -1);
441 md5sum_blob(&in, &cksum);
442
+11 -12
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -80,15 +80,22 @@
8080
8181
int main(int argc, char **argv){
8282
int i, sz;
8383
int j, n;
8484
Resource *aRes;
85
- int nRes = argc-1;
85
+ int nRes;
8686
unsigned char *pData;
8787
int nErr = 0;
8888
int nSkip;
89
+ int nPrefix = 0;
8990
91
+ if( argc>3 && strcmp(argv[1],"--prefix")==0 ){
92
+ nPrefix = (int)strlen(argv[2]);
93
+ argc -= 2;
94
+ argv += 2;
95
+ }
96
+ nRes = argc - 1;
9097
aRes = malloc( nRes*sizeof(aRes[0]) );
9198
if( aRes==0 ){
9299
fprintf(stderr, "malloc failed\n");
93100
return 1;
94101
}
@@ -141,25 +148,17 @@
141148
printf(" int nByte;\n");
142149
printf("};\n");
143150
printf("static const BuiltinFileTable aBuiltinFiles[] = {\n");
144151
for(i=0; i<nRes; i++){
145152
const char *z = aRes[i].zName;
146
- const char *zTail;
147
- int nSlash = 0;
148
- zTail = z;
149
- while( z && z[0] ){
150
- if( z[0]=='/' || z[0]=='\\' ){
151
- nSlash++;
152
- if( nSlash<=2 || z[-1]=='.' ) zTail = &z[1];
153
- }
154
- z++;
155
- }
156
- aRes[i].zName = zTail;
153
+ if( strlen(z)>=nPrefix ) z += nPrefix;
154
+ while( z[0]=='.' || z[0]=='/' ){ z++; }
155
+ aRes[i].zName = z;
157156
}
158157
qsort(aRes, nRes, sizeof(aRes[0]), compareResource);
159158
for(i=0; i<nRes; i++){
160159
printf(" { \"%s\", bidata%d, %d },\n",
161160
aRes[i].zName, aRes[i].idx, aRes[i].nByte);
162161
}
163162
printf("};\n");
164163
return nErr;
165164
}
166165
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -80,15 +80,22 @@
80
81 int main(int argc, char **argv){
82 int i, sz;
83 int j, n;
84 Resource *aRes;
85 int nRes = argc-1;
86 unsigned char *pData;
87 int nErr = 0;
88 int nSkip;
 
89
 
 
 
 
 
 
90 aRes = malloc( nRes*sizeof(aRes[0]) );
91 if( aRes==0 ){
92 fprintf(stderr, "malloc failed\n");
93 return 1;
94 }
@@ -141,25 +148,17 @@
141 printf(" int nByte;\n");
142 printf("};\n");
143 printf("static const BuiltinFileTable aBuiltinFiles[] = {\n");
144 for(i=0; i<nRes; i++){
145 const char *z = aRes[i].zName;
146 const char *zTail;
147 int nSlash = 0;
148 zTail = z;
149 while( z && z[0] ){
150 if( z[0]=='/' || z[0]=='\\' ){
151 nSlash++;
152 if( nSlash<=2 || z[-1]=='.' ) zTail = &z[1];
153 }
154 z++;
155 }
156 aRes[i].zName = zTail;
157 }
158 qsort(aRes, nRes, sizeof(aRes[0]), compareResource);
159 for(i=0; i<nRes; i++){
160 printf(" { \"%s\", bidata%d, %d },\n",
161 aRes[i].zName, aRes[i].idx, aRes[i].nByte);
162 }
163 printf("};\n");
164 return nErr;
165 }
166
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -80,15 +80,22 @@
80
81 int main(int argc, char **argv){
82 int i, sz;
83 int j, n;
84 Resource *aRes;
85 int nRes;
86 unsigned char *pData;
87 int nErr = 0;
88 int nSkip;
89 int nPrefix = 0;
90
91 if( argc>3 && strcmp(argv[1],"--prefix")==0 ){
92 nPrefix = (int)strlen(argv[2]);
93 argc -= 2;
94 argv += 2;
95 }
96 nRes = argc - 1;
97 aRes = malloc( nRes*sizeof(aRes[0]) );
98 if( aRes==0 ){
99 fprintf(stderr, "malloc failed\n");
100 return 1;
101 }
@@ -141,25 +148,17 @@
148 printf(" int nByte;\n");
149 printf("};\n");
150 printf("static const BuiltinFileTable aBuiltinFiles[] = {\n");
151 for(i=0; i<nRes; i++){
152 const char *z = aRes[i].zName;
153 if( strlen(z)>=nPrefix ) z += nPrefix;
154 while( z[0]=='.' || z[0]=='/' ){ z++; }
155 aRes[i].zName = z;
 
 
 
 
 
 
 
 
156 }
157 qsort(aRes, nRes, sizeof(aRes[0]), compareResource);
158 for(i=0; i<nRes; i++){
159 printf(" { \"%s\", bidata%d, %d },\n",
160 aRes[i].zName, aRes[i].idx, aRes[i].nByte);
161 }
162 printf("};\n");
163 return nErr;
164 }
165
+9 -9
--- src/regexp.c
+++ src/regexp.c
@@ -127,11 +127,11 @@
127127
pSet->aState[pSet->nState++] = newState;
128128
}
129129
130130
/* Extract the next unicode character from *pzIn and return it. Advance
131131
** *pzIn to the first byte past the end of the character returned. To
132
-** be clear: this routine converts utf8 to unicode. This routine is
132
+** be clear: this routine converts utf8 to unicode. This routine is
133133
** optimized for the common case where the next character is a single byte.
134134
*/
135135
static unsigned re_next_char(ReInput *p){
136136
unsigned c;
137137
if( p->i>=p->mx ) return 0;
@@ -191,16 +191,16 @@
191191
int rc = 0;
192192
ReInput in;
193193
194194
in.z = zIn;
195195
in.i = 0;
196
- in.mx = nIn>=0 ? nIn : strlen((char const*)zIn);
196
+ in.mx = nIn>=0 ? nIn : strlen((const char*)zIn);
197197
198198
/* Look for the initial prefix match, if there is one. */
199199
if( pRe->nInit ){
200200
unsigned char x = pRe->zInit[0];
201
- while( in.i+pRe->nInit<=in.mx
201
+ while( in.i+pRe->nInit<=in.mx
202202
&& (zIn[in.i]!=x ||
203203
strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
204204
){
205205
in.i++;
206206
}
@@ -303,11 +303,11 @@
303303
}
304304
}
305305
}
306306
if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
307307
if( hit ) re_add_state(pNext, x+n);
308
- break;
308
+ break;
309309
}
310310
}
311311
}
312312
}
313313
for(i=0; i<pNext->nState; i++){
@@ -464,11 +464,11 @@
464464
const char *zErr;
465465
while( (c = p->xNextChar(&p->sIn))!=0 ){
466466
iStart = p->nState;
467467
switch( c ){
468468
case '|':
469
- case '$':
469
+ case '$':
470470
case ')': {
471471
p->sIn.i--;
472472
return 0;
473473
}
474474
case '(': {
@@ -480,11 +480,11 @@
480480
}
481481
case '.': {
482482
if( rePeek(p)=='*' ){
483483
re_append(p, RE_OP_ANYSTAR, 0);
484484
p->sIn.i++;
485
- }else{
485
+ }else{
486486
re_append(p, RE_OP_ANY, 0);
487487
}
488488
break;
489489
}
490490
case '*': {
@@ -652,11 +652,11 @@
652652
}
653653
654654
/* The following is a performance optimization. If the regex begins with
655655
** ".*" (if the input regex lacks an initial "^") and afterwards there are
656656
** one or more matching characters, enter those matching characters into
657
- ** zInit[]. The re_match() routine can then search ahead in the input
657
+ ** zInit[]. The re_match() routine can then search ahead in the input
658658
** string looking for the initial match without having to run the whole
659659
** regex engine over the string. Do not worry able trying to match
660660
** unicode characters beyond plane 0 - those are very rare and this is
661661
** just an optimization. */
662662
if( pRe->aOp[0]==RE_OP_ANYSTAR ){
@@ -689,12 +689,12 @@
689689
** A REGEXP B
690690
**
691691
** is implemented as regexp(B,A).
692692
*/
693693
static void re_sql_func(
694
- sqlite3_context *context,
695
- int argc,
694
+ sqlite3_context *context,
695
+ int argc,
696696
sqlite3_value **argv
697697
){
698698
ReCompiled *pRe; /* Compiled regular expression */
699699
const char *zPattern; /* The regular expression */
700700
const unsigned char *zStr;/* String being searched */
701701
--- src/regexp.c
+++ src/regexp.c
@@ -127,11 +127,11 @@
127 pSet->aState[pSet->nState++] = newState;
128 }
129
130 /* Extract the next unicode character from *pzIn and return it. Advance
131 ** *pzIn to the first byte past the end of the character returned. To
132 ** be clear: this routine converts utf8 to unicode. This routine is
133 ** optimized for the common case where the next character is a single byte.
134 */
135 static unsigned re_next_char(ReInput *p){
136 unsigned c;
137 if( p->i>=p->mx ) return 0;
@@ -191,16 +191,16 @@
191 int rc = 0;
192 ReInput in;
193
194 in.z = zIn;
195 in.i = 0;
196 in.mx = nIn>=0 ? nIn : strlen((char const*)zIn);
197
198 /* Look for the initial prefix match, if there is one. */
199 if( pRe->nInit ){
200 unsigned char x = pRe->zInit[0];
201 while( in.i+pRe->nInit<=in.mx
202 && (zIn[in.i]!=x ||
203 strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
204 ){
205 in.i++;
206 }
@@ -303,11 +303,11 @@
303 }
304 }
305 }
306 if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
307 if( hit ) re_add_state(pNext, x+n);
308 break;
309 }
310 }
311 }
312 }
313 for(i=0; i<pNext->nState; i++){
@@ -464,11 +464,11 @@
464 const char *zErr;
465 while( (c = p->xNextChar(&p->sIn))!=0 ){
466 iStart = p->nState;
467 switch( c ){
468 case '|':
469 case '$':
470 case ')': {
471 p->sIn.i--;
472 return 0;
473 }
474 case '(': {
@@ -480,11 +480,11 @@
480 }
481 case '.': {
482 if( rePeek(p)=='*' ){
483 re_append(p, RE_OP_ANYSTAR, 0);
484 p->sIn.i++;
485 }else{
486 re_append(p, RE_OP_ANY, 0);
487 }
488 break;
489 }
490 case '*': {
@@ -652,11 +652,11 @@
652 }
653
654 /* The following is a performance optimization. If the regex begins with
655 ** ".*" (if the input regex lacks an initial "^") and afterwards there are
656 ** one or more matching characters, enter those matching characters into
657 ** zInit[]. The re_match() routine can then search ahead in the input
658 ** string looking for the initial match without having to run the whole
659 ** regex engine over the string. Do not worry able trying to match
660 ** unicode characters beyond plane 0 - those are very rare and this is
661 ** just an optimization. */
662 if( pRe->aOp[0]==RE_OP_ANYSTAR ){
@@ -689,12 +689,12 @@
689 ** A REGEXP B
690 **
691 ** is implemented as regexp(B,A).
692 */
693 static void re_sql_func(
694 sqlite3_context *context,
695 int argc,
696 sqlite3_value **argv
697 ){
698 ReCompiled *pRe; /* Compiled regular expression */
699 const char *zPattern; /* The regular expression */
700 const unsigned char *zStr;/* String being searched */
701
--- src/regexp.c
+++ src/regexp.c
@@ -127,11 +127,11 @@
127 pSet->aState[pSet->nState++] = newState;
128 }
129
130 /* Extract the next unicode character from *pzIn and return it. Advance
131 ** *pzIn to the first byte past the end of the character returned. To
132 ** be clear: this routine converts utf8 to unicode. This routine is
133 ** optimized for the common case where the next character is a single byte.
134 */
135 static unsigned re_next_char(ReInput *p){
136 unsigned c;
137 if( p->i>=p->mx ) return 0;
@@ -191,16 +191,16 @@
191 int rc = 0;
192 ReInput in;
193
194 in.z = zIn;
195 in.i = 0;
196 in.mx = nIn>=0 ? nIn : strlen((const char*)zIn);
197
198 /* Look for the initial prefix match, if there is one. */
199 if( pRe->nInit ){
200 unsigned char x = pRe->zInit[0];
201 while( in.i+pRe->nInit<=in.mx
202 && (zIn[in.i]!=x ||
203 strncmp((const char*)zIn+in.i, (const char*)pRe->zInit, pRe->nInit)!=0)
204 ){
205 in.i++;
206 }
@@ -303,11 +303,11 @@
303 }
304 }
305 }
306 if( pRe->aOp[x]==RE_OP_CC_EXC ) hit = !hit;
307 if( hit ) re_add_state(pNext, x+n);
308 break;
309 }
310 }
311 }
312 }
313 for(i=0; i<pNext->nState; i++){
@@ -464,11 +464,11 @@
464 const char *zErr;
465 while( (c = p->xNextChar(&p->sIn))!=0 ){
466 iStart = p->nState;
467 switch( c ){
468 case '|':
469 case '$':
470 case ')': {
471 p->sIn.i--;
472 return 0;
473 }
474 case '(': {
@@ -480,11 +480,11 @@
480 }
481 case '.': {
482 if( rePeek(p)=='*' ){
483 re_append(p, RE_OP_ANYSTAR, 0);
484 p->sIn.i++;
485 }else{
486 re_append(p, RE_OP_ANY, 0);
487 }
488 break;
489 }
490 case '*': {
@@ -652,11 +652,11 @@
652 }
653
654 /* The following is a performance optimization. If the regex begins with
655 ** ".*" (if the input regex lacks an initial "^") and afterwards there are
656 ** one or more matching characters, enter those matching characters into
657 ** zInit[]. The re_match() routine can then search ahead in the input
658 ** string looking for the initial match without having to run the whole
659 ** regex engine over the string. Do not worry able trying to match
660 ** unicode characters beyond plane 0 - those are very rare and this is
661 ** just an optimization. */
662 if( pRe->aOp[0]==RE_OP_ANYSTAR ){
@@ -689,12 +689,12 @@
689 ** A REGEXP B
690 **
691 ** is implemented as regexp(B,A).
692 */
693 static void re_sql_func(
694 sqlite3_context *context,
695 int argc,
696 sqlite3_value **argv
697 ){
698 ReCompiled *pRe; /* Compiled regular expression */
699 const char *zPattern; /* The regular expression */
700 const unsigned char *zStr;/* String being searched */
701
+32 -9
--- src/schema.c
+++ src/schema.c
@@ -12,11 +12,11 @@
1212
** Author contact information:
1313
** [email protected]
1414
** http://www.hwaci.com/drh/
1515
**
1616
*******************************************************************************
17
-**
17
+**
1818
** This file contains string constants that implement the database schema.
1919
*/
2020
#include "config.h"
2121
#include "schema.h"
2222
@@ -45,11 +45,14 @@
4545
** we have to execute special procedures to update the schema. When
4646
** the aux schema changes, all we need to do is rebuild the database.
4747
*/
4848
#define CONTENT_SCHEMA "2"
4949
#define AUX_SCHEMA_MIN "2011-04-25 19:50"
50
-#define AUX_SCHEMA_MAX "2014-11-24 20:35"
50
+#define AUX_SCHEMA_MAX "2015-01-24"
51
+/* NB: Some features require the latest schema. Warning or error messages
52
+** will appear if an older schema is used. However, the older schemas are
53
+** adequate for many common functions. */
5154
5255
#endif /* INTERFACE */
5356
5457
5558
/*
@@ -81,11 +84,11 @@
8184
@ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content
8285
@ content BLOB, -- Compressed content of this record
8386
@ CHECK( length(uuid)==40 AND rid>0 )
8487
@ );
8588
@ CREATE TABLE delta(
86
-@ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
89
+@ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
8790
@ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
8891
@ );
8992
@ CREATE INDEX delta_i1 ON delta(srcid);
9093
@
9194
@ -------------------------------------------------------------------------
@@ -227,21 +230,41 @@
227230
@ name TEXT UNIQUE -- Name of file page
228231
@ );
229232
@
230233
@ -- Linkages between checkins, files created by each checkin, and
231234
@ -- the names of those files.
235
+@ --
236
+@ -- Each entry represents a file that changed content from pid to fid
237
+@ -- due to the check-in that goes from pmid to mid. fnid is the name
238
+@ -- of the file in the mid check-in. If the file was renamed as part
239
+@ -- of the mid check-in, then pfnid is the previous filename.
240
+@
241
+@ -- There can be multiple entries for (mid,fid) if the mid checkin was
242
+@ -- a merge. Entries with isaux==0 are from the primary parent. Merge
243
+@ -- parents have isaux set to true.
244
+@ --
245
+@ -- Field name mnemonics:
246
+@ -- mid = Manifest ID. (Each check-in is stored as a "Manifest")
247
+@ -- fid = File ID.
248
+@ -- pmid = Parent Manifest ID.
249
+@ -- pid = Parent file ID.
250
+@ -- fnid = File Name ID.
251
+@ -- pfnid = Parent File Name ID.
252
+@ -- isaux = pmid IS AUXiliary parent, not primary parent
232253
@ --
233254
@ -- pid==0 if the file is added by checkin mid.
234255
@ -- fid==0 if the file is removed by checkin mid.
235256
@ --
236257
@ CREATE TABLE mlink(
237
-@ mid INTEGER REFERENCES blob, -- Manifest ID where change occurs
238
-@ pid INTEGER REFERENCES blob, -- File ID in parent manifest
239
-@ fid INTEGER REFERENCES blob, -- Changed file ID in this manifest
258
+@ mid INTEGER REFERENCES plink(cid), -- Checkin that contains fid
259
+@ fid INTEGER REFERENCES blob, -- New file content. 0 if deleted
260
+@ pmid INTEGER REFERENCES plink(cid), -- Checkin that contains pid
261
+@ pid INTEGER REFERENCES blob, -- Prev file content. 0 if new
240262
@ fnid INTEGER REFERENCES filename, -- Name of the file
241263
@ pfnid INTEGER REFERENCES filename, -- Previous name. 0 if unchanged
242
-@ mperm INTEGER -- File permissions. 1==exec
264
+@ mperm INTEGER, -- File permissions. 1==exec
265
+@ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary
243266
@ );
244267
@ CREATE INDEX mlink_i1 ON mlink(mid);
245268
@ CREATE INDEX mlink_i2 ON mlink(fnid);
246269
@ CREATE INDEX mlink_i3 ON mlink(fid);
247270
@ CREATE INDEX mlink_i4 ON mlink(pid);
@@ -251,11 +274,11 @@
251274
@ CREATE TABLE plink(
252275
@ pid INTEGER REFERENCES blob, -- Parent manifest
253276
@ cid INTEGER REFERENCES blob, -- Child manifest
254277
@ isprim BOOLEAN, -- pid is the primary parent of cid
255278
@ mtime DATETIME, -- the date/time stamp on cid. Julian day.
256
-@ baseid INTEGER REFERENCES blob, -- Baseline if child is a delta manifest
279
+@ baseid INTEGER REFERENCES blob, -- Baseline if cid is a delta manifest.
257280
@ UNIQUE(pid, cid)
258281
@ );
259282
@ CREATE INDEX plink_i2 ON plink(cid,pid);
260283
@
261284
@ -- A "leaf" checkin is a checkin that has no children in the same
@@ -488,11 +511,11 @@
488511
@ -- current version of the file is already in the repository.
489512
@ --
490513
@ CREATE TABLE vfile(
491514
@ id INTEGER PRIMARY KEY, -- ID of the checked out file
492515
@ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
493
-@ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add 4:i-chng 5:i-add
516
+@ chnged INT DEFAULT 0, -- 0:unchng 1:edit 2:m-chng 3:m-add 4:i-chng 5:i-add
494517
@ deleted BOOLEAN DEFAULT 0, -- True if deleted
495518
@ isexe BOOLEAN, -- True if file should be executable
496519
@ islink BOOLEAN, -- True if file should be symlink
497520
@ rid INTEGER, -- Originally from this repository record
498521
@ mrid INTEGER, -- Based on this record due to a merge
499522
--- src/schema.c
+++ src/schema.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains string constants that implement the database schema.
19 */
20 #include "config.h"
21 #include "schema.h"
22
@@ -45,11 +45,14 @@
45 ** we have to execute special procedures to update the schema. When
46 ** the aux schema changes, all we need to do is rebuild the database.
47 */
48 #define CONTENT_SCHEMA "2"
49 #define AUX_SCHEMA_MIN "2011-04-25 19:50"
50 #define AUX_SCHEMA_MAX "2014-11-24 20:35"
 
 
 
51
52 #endif /* INTERFACE */
53
54
55 /*
@@ -81,11 +84,11 @@
81 @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content
82 @ content BLOB, -- Compressed content of this record
83 @ CHECK( length(uuid)==40 AND rid>0 )
84 @ );
85 @ CREATE TABLE delta(
86 @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
87 @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
88 @ );
89 @ CREATE INDEX delta_i1 ON delta(srcid);
90 @
91 @ -------------------------------------------------------------------------
@@ -227,21 +230,41 @@
227 @ name TEXT UNIQUE -- Name of file page
228 @ );
229 @
230 @ -- Linkages between checkins, files created by each checkin, and
231 @ -- the names of those files.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232 @ --
233 @ -- pid==0 if the file is added by checkin mid.
234 @ -- fid==0 if the file is removed by checkin mid.
235 @ --
236 @ CREATE TABLE mlink(
237 @ mid INTEGER REFERENCES blob, -- Manifest ID where change occurs
238 @ pid INTEGER REFERENCES blob, -- File ID in parent manifest
239 @ fid INTEGER REFERENCES blob, -- Changed file ID in this manifest
 
240 @ fnid INTEGER REFERENCES filename, -- Name of the file
241 @ pfnid INTEGER REFERENCES filename, -- Previous name. 0 if unchanged
242 @ mperm INTEGER -- File permissions. 1==exec
 
243 @ );
244 @ CREATE INDEX mlink_i1 ON mlink(mid);
245 @ CREATE INDEX mlink_i2 ON mlink(fnid);
246 @ CREATE INDEX mlink_i3 ON mlink(fid);
247 @ CREATE INDEX mlink_i4 ON mlink(pid);
@@ -251,11 +274,11 @@
251 @ CREATE TABLE plink(
252 @ pid INTEGER REFERENCES blob, -- Parent manifest
253 @ cid INTEGER REFERENCES blob, -- Child manifest
254 @ isprim BOOLEAN, -- pid is the primary parent of cid
255 @ mtime DATETIME, -- the date/time stamp on cid. Julian day.
256 @ baseid INTEGER REFERENCES blob, -- Baseline if child is a delta manifest
257 @ UNIQUE(pid, cid)
258 @ );
259 @ CREATE INDEX plink_i2 ON plink(cid,pid);
260 @
261 @ -- A "leaf" checkin is a checkin that has no children in the same
@@ -488,11 +511,11 @@
488 @ -- current version of the file is already in the repository.
489 @ --
490 @ CREATE TABLE vfile(
491 @ id INTEGER PRIMARY KEY, -- ID of the checked out file
492 @ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
493 @ chnged INT DEFAULT 0, -- 0:unchnged 1:edited 2:m-chng 3:m-add 4:i-chng 5:i-add
494 @ deleted BOOLEAN DEFAULT 0, -- True if deleted
495 @ isexe BOOLEAN, -- True if file should be executable
496 @ islink BOOLEAN, -- True if file should be symlink
497 @ rid INTEGER, -- Originally from this repository record
498 @ mrid INTEGER, -- Based on this record due to a merge
499
--- src/schema.c
+++ src/schema.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 ** http://www.hwaci.com/drh/
15 **
16 *******************************************************************************
17 **
18 ** This file contains string constants that implement the database schema.
19 */
20 #include "config.h"
21 #include "schema.h"
22
@@ -45,11 +45,14 @@
45 ** we have to execute special procedures to update the schema. When
46 ** the aux schema changes, all we need to do is rebuild the database.
47 */
48 #define CONTENT_SCHEMA "2"
49 #define AUX_SCHEMA_MIN "2011-04-25 19:50"
50 #define AUX_SCHEMA_MAX "2015-01-24"
51 /* NB: Some features require the latest schema. Warning or error messages
52 ** will appear if an older schema is used. However, the older schemas are
53 ** adequate for many common functions. */
54
55 #endif /* INTERFACE */
56
57
58 /*
@@ -81,11 +84,11 @@
84 @ uuid TEXT UNIQUE NOT NULL, -- SHA1 hash of the content
85 @ content BLOB, -- Compressed content of this record
86 @ CHECK( length(uuid)==40 AND rid>0 )
87 @ );
88 @ CREATE TABLE delta(
89 @ rid INTEGER PRIMARY KEY, -- BLOB that is delta-compressed
90 @ srcid INTEGER NOT NULL REFERENCES blob -- Baseline for delta-compression
91 @ );
92 @ CREATE INDEX delta_i1 ON delta(srcid);
93 @
94 @ -------------------------------------------------------------------------
@@ -227,21 +230,41 @@
230 @ name TEXT UNIQUE -- Name of file page
231 @ );
232 @
233 @ -- Linkages between checkins, files created by each checkin, and
234 @ -- the names of those files.
235 @ --
236 @ -- Each entry represents a file that changed content from pid to fid
237 @ -- due to the check-in that goes from pmid to mid. fnid is the name
238 @ -- of the file in the mid check-in. If the file was renamed as part
239 @ -- of the mid check-in, then pfnid is the previous filename.
240 @
241 @ -- There can be multiple entries for (mid,fid) if the mid checkin was
242 @ -- a merge. Entries with isaux==0 are from the primary parent. Merge
243 @ -- parents have isaux set to true.
244 @ --
245 @ -- Field name mnemonics:
246 @ -- mid = Manifest ID. (Each check-in is stored as a "Manifest")
247 @ -- fid = File ID.
248 @ -- pmid = Parent Manifest ID.
249 @ -- pid = Parent file ID.
250 @ -- fnid = File Name ID.
251 @ -- pfnid = Parent File Name ID.
252 @ -- isaux = pmid IS AUXiliary parent, not primary parent
253 @ --
254 @ -- pid==0 if the file is added by checkin mid.
255 @ -- fid==0 if the file is removed by checkin mid.
256 @ --
257 @ CREATE TABLE mlink(
258 @ mid INTEGER REFERENCES plink(cid), -- Checkin that contains fid
259 @ fid INTEGER REFERENCES blob, -- New file content. 0 if deleted
260 @ pmid INTEGER REFERENCES plink(cid), -- Checkin that contains pid
261 @ pid INTEGER REFERENCES blob, -- Prev file content. 0 if new
262 @ fnid INTEGER REFERENCES filename, -- Name of the file
263 @ pfnid INTEGER REFERENCES filename, -- Previous name. 0 if unchanged
264 @ mperm INTEGER, -- File permissions. 1==exec
265 @ isaux BOOLEAN DEFAULT 0 -- TRUE if pmid is the primary
266 @ );
267 @ CREATE INDEX mlink_i1 ON mlink(mid);
268 @ CREATE INDEX mlink_i2 ON mlink(fnid);
269 @ CREATE INDEX mlink_i3 ON mlink(fid);
270 @ CREATE INDEX mlink_i4 ON mlink(pid);
@@ -251,11 +274,11 @@
274 @ CREATE TABLE plink(
275 @ pid INTEGER REFERENCES blob, -- Parent manifest
276 @ cid INTEGER REFERENCES blob, -- Child manifest
277 @ isprim BOOLEAN, -- pid is the primary parent of cid
278 @ mtime DATETIME, -- the date/time stamp on cid. Julian day.
279 @ baseid INTEGER REFERENCES blob, -- Baseline if cid is a delta manifest.
280 @ UNIQUE(pid, cid)
281 @ );
282 @ CREATE INDEX plink_i2 ON plink(cid,pid);
283 @
284 @ -- A "leaf" checkin is a checkin that has no children in the same
@@ -488,11 +511,11 @@
511 @ -- current version of the file is already in the repository.
512 @ --
513 @ CREATE TABLE vfile(
514 @ id INTEGER PRIMARY KEY, -- ID of the checked out file
515 @ vid INTEGER REFERENCES blob, -- The baseline this file is part of.
516 @ chnged INT DEFAULT 0, -- 0:unchng 1:edit 2:m-chng 3:m-add 4:i-chng 5:i-add
517 @ deleted BOOLEAN DEFAULT 0, -- True if deleted
518 @ isexe BOOLEAN, -- True if file should be executable
519 @ islink BOOLEAN, -- True if file should be symlink
520 @ rid INTEGER, -- Originally from this repository record
521 @ mrid INTEGER, -- Based on this record due to a merge
522
+235 -76
--- src/search.c
+++ src/search.c
@@ -26,54 +26,34 @@
2626
#include "config.h"
2727
#include "search.h"
2828
#include <assert.h>
2929
3030
#if INTERFACE
31
+
32
+/* Maximum number of search terms */
33
+#define SEARCH_MAX_TERM 8
34
+
3135
/*
3236
** A compiled search pattern
3337
*/
3438
struct Search {
3539
int nTerm; /* Number of search terms */
3640
struct srchTerm { /* For each search term */
3741
char *z; /* Text */
3842
int n; /* length */
39
- } a[8];
43
+ } a[SEARCH_MAX_TERM];
44
+ /* Snippet controls */
45
+ char *zMarkBegin; /* Start of a match */
46
+ char *zMarkEnd; /* End of a match */
47
+ char *zMarkGap; /* A gap between two matches */
48
+ unsigned fSrchFlg; /* Flags */
4049
};
50
+
51
+#define SRCHFLG_HTML 0x0001 /* Escape snippet text for HTML */
52
+
4153
#endif
4254
43
-/*
44
-** Compile a search pattern
45
-*/
46
-Search *search_init(const char *zPattern){
47
- int nPattern = strlen(zPattern);
48
- Search *p;
49
- char *z;
50
- int i;
51
-
52
- p = fossil_malloc( nPattern + sizeof(*p) + 1);
53
- z = (char*)&p[1];
54
- memcpy(z, zPattern, nPattern+1);
55
- memset(p, 0, sizeof(*p));
56
- while( *z && p->nTerm<sizeof(p->a)/sizeof(p->a[0]) ){
57
- while( !fossil_isalnum(*z) && *z ){ z++; }
58
- if( *z==0 ) break;
59
- p->a[p->nTerm].z = z;
60
- for(i=1; fossil_isalnum(z[i]) || z[i]=='_'; i++){}
61
- p->a[p->nTerm].n = i;
62
- z += i;
63
- p->nTerm++;
64
- }
65
- return p;
66
-}
67
-
68
-
69
-/*
70
-** Destroy a search context.
71
-*/
72
-void search_end(Search *p){
73
- free(p);
74
-}
7555
7656
/*
7757
** Theses characters constitute a word boundary
7858
*/
7959
static const char isBoundary[] = {
@@ -92,64 +72,243 @@
9272
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9373
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9474
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9575
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9676
};
77
+#define ISALNUM(x) (!isBoundary[(x)&0xff])
78
+
79
+/*
80
+** Compile a search pattern
81
+*/
82
+Search *search_init(const char *zPattern){
83
+ int nPattern = strlen(zPattern);
84
+ Search *p;
85
+ char *z;
86
+ int i;
87
+
88
+ p = fossil_malloc( nPattern + sizeof(*p) + 1);
89
+ z = (char*)&p[1];
90
+ memcpy(z, zPattern, nPattern+1);
91
+ memset(p, 0, sizeof(*p));
92
+ while( *z && p->nTerm<SEARCH_MAX_TERM ){
93
+ while( *z && !ISALNUM(*z) ){ z++; }
94
+ if( *z==0 ) break;
95
+ p->a[p->nTerm].z = z;
96
+ for(i=1; ISALNUM(z[i]); i++){}
97
+ p->a[p->nTerm].n = i;
98
+ z += i;
99
+ p->nTerm++;
100
+ }
101
+ return p;
102
+}
103
+
104
+
105
+/*
106
+** Destroy a search context.
107
+*/
108
+void search_end(Search *p){
109
+ free(p);
110
+}
111
+
112
+/*
113
+** Append n bytes of text to snippet zTxt. Encode the text appropriately.
114
+*/
115
+static void snippet_text_append(
116
+ Search *p, /* The search context */
117
+ Blob *pSnip, /* Append to this snippet */
118
+ const char *zTxt, /* Text to append */
119
+ int n /* How many bytes to append */
120
+){
121
+ if( p->fSrchFlg & SRCHFLG_HTML ){
122
+ blob_appendf(pSnip, "%.*h", n, zTxt);
123
+ }else{
124
+ blob_append(pSnip, zTxt, n);
125
+ }
126
+}
97127
98128
/*
99
-** Compare a search pattern against an input string and return a score.
129
+** Compare a search pattern against one or more input strings which
130
+** collectively comprise a document. Return a match score. Optionally
131
+** also return a "snippet".
100132
**
101133
** Scoring:
102134
** * All terms must match at least once or the score is zero
103
-** * 10 bonus points if the first occurrence is an exact match
104
-** * 1 additional point for each subsequent match of the same word
105
-** * Extra points of two consecutive words of the pattern are consecutive
135
+** * One point for each matching term
136
+** * Extra points if consecutive words of the pattern are consecutive
106137
** in the document
107138
*/
108
-int search_score(Search *p, int nDoc, const char **azDoc){
109
- int iPrev = 999;
110
- int score = 10;
111
- int iBonus = 0;
112
- int i, j, k;
113
- const char *zDoc;
114
- unsigned char seen[8];
115
-
116
- memset(seen, 0, sizeof(seen));
117
- for(k=0; k<nDoc; k++){
118
- zDoc = azDoc[k];
139
+static int search_score(
140
+ Search *p, /* Search pattern and flags */
141
+ int nDoc, /* Number of strings in this document */
142
+ const char **azDoc, /* Text of each string */
143
+ Blob *pSnip /* If not NULL: Write a snippet here */
144
+){
145
+ int score; /* Final score */
146
+ int i; /* Offset into current document */
147
+ int ii; /* Loop counter */
148
+ int j; /* Loop over search terms */
149
+ int k; /* Loop over prior terms */
150
+ int iWord = 0; /* Current word number */
151
+ int iDoc; /* Current document number */
152
+ int wantGap = 0; /* True if a zMarkGap is wanted */
153
+ const char *zDoc; /* Current document text */
154
+ const int CTX = 50; /* Amount of snippet context */
155
+ int anMatch[SEARCH_MAX_TERM]; /* Number of terms in best match */
156
+ int aiBestDoc[SEARCH_MAX_TERM]; /* Document containing best match */
157
+ int aiBestOfst[SEARCH_MAX_TERM]; /* Byte offset to start of best match */
158
+ int aiLastDoc[SEARCH_MAX_TERM]; /* Document containing most recent match */
159
+ int aiLastOfst[SEARCH_MAX_TERM]; /* Byte offset to the most recent match */
160
+ int aiWordIdx[SEARCH_MAX_TERM]; /* Word index of most recent match */
161
+
162
+ memset(anMatch, 0, sizeof(anMatch));
163
+ memset(aiWordIdx, 0xff, sizeof(aiWordIdx));
164
+ for(iDoc=0; iDoc<nDoc; iDoc++){
165
+ zDoc = azDoc[iDoc];
119166
if( zDoc==0 ) continue;
167
+ iWord++;
120168
for(i=0; zDoc[i]; i++){
121
- char c = zDoc[i];
122
- if( isBoundary[c&0xff] ) continue;
169
+ if( !ISALNUM(zDoc[i]) ) continue;
170
+ iWord++;
171
+ for(j=0; j<p->nTerm; j++){
172
+ int n = p->a[j].n;
173
+ if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0
174
+ && (!ISALNUM(zDoc[i+n]) || p->a[j].z[n]=='*')
175
+ ){
176
+ aiWordIdx[j] = iWord;
177
+ aiLastDoc[j] = iDoc;
178
+ aiLastOfst[j] = i;
179
+ for(k=1; j-k>=0 && anMatch[j-k] && aiWordIdx[j-k]==iWord-k; k++){}
180
+ for(ii=0; ii<k; ii++){
181
+ if( anMatch[j-ii]<k ){
182
+ anMatch[j-ii] = k;
183
+ aiBestDoc[j-ii] = aiLastDoc[j-ii];
184
+ aiBestOfst[j-ii] = aiLastOfst[j-ii];
185
+ }
186
+ }
187
+ break;
188
+ }
189
+ }
190
+ while( ISALNUM(zDoc[i]) ){ i++; }
191
+ }
192
+ }
193
+
194
+ /* Finished search all documents.
195
+ ** Every term must be seen or else the score is zero
196
+ */
197
+ score = 1;
198
+ for(j=0; j<p->nTerm; j++) score *= anMatch[j];
199
+ if( score==0 || pSnip==0 ) return score;
200
+
201
+
202
+ /* Prepare a snippet that describes the matching text.
203
+ */
204
+ blob_init(pSnip, 0, 0);
205
+
206
+ while(1){
207
+ int iOfst;
208
+ int iTail;
209
+ int iBest;
210
+ for(ii=0; ii<p->nTerm && anMatch[ii]==0; ii++){}
211
+ if( ii>=p->nTerm ) break; /* This is where the loop exits */
212
+ iBest = ii;
213
+ iDoc = aiBestDoc[ii];
214
+ iOfst = aiBestOfst[ii];
215
+ for(; ii<p->nTerm; ii++){
216
+ if( anMatch[ii]==0 ) continue;
217
+ if( aiBestDoc[ii]>iDoc ) continue;
218
+ if( aiBestOfst[ii]>iOfst ) continue;
219
+ iDoc = aiBestDoc[ii];
220
+ iOfst = aiBestOfst[ii];
221
+ iBest = ii;
222
+ }
223
+ iTail = iOfst + p->a[iBest].n;
224
+ anMatch[iBest] = 0;
225
+ for(ii=0; ii<p->nTerm; ii++){
226
+ if( anMatch[ii]==0 ) continue;
227
+ if( aiBestDoc[ii]!=iDoc ) continue;
228
+ if( aiBestOfst[ii]<=iTail+CTX*2 ){
229
+ if( iTail<aiBestOfst[ii]+p->a[ii].n ){
230
+ iTail = aiBestOfst[ii]+p->a[ii].n;
231
+ }
232
+ anMatch[ii] = 0;
233
+ ii = -1;
234
+ continue;
235
+ }
236
+ }
237
+ zDoc = azDoc[iDoc];
238
+ iOfst -= CTX;
239
+ if( iOfst<0 ) iOfst = 0;
240
+ while( iOfst>0 && ISALNUM(zDoc[iOfst-1]) ) iOfst--;
241
+ while( zDoc[iOfst] && !ISALNUM(zDoc[iOfst]) ) iOfst++;
242
+ for(ii=0; ii<CTX && zDoc[iTail]; ii++, iTail++){}
243
+ while( ISALNUM(zDoc[iTail]) ) iTail++;
244
+ if( iOfst>0 || wantGap ) blob_append(pSnip, p->zMarkGap, -1);
245
+ wantGap = zDoc[iTail]!=0;
246
+ zDoc += iOfst;
247
+ iTail -= iOfst;
248
+
249
+ /* Add a snippet segment using characters iOfst..iOfst+iTail from zDoc */
250
+ for(i=0; i<iTail; i++){
251
+ if( !ISALNUM(zDoc[i]) ) continue;
123252
for(j=0; j<p->nTerm; j++){
124253
int n = p->a[j].n;
125
- if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126
- score += 1;
127
- if( !seen[j] ){
128
- if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129
- seen[j] = 1;
130
- }
131
- if( j==iPrev+1 ){
132
- score += iBonus;
133
- }
134
- i += n-1;
135
- iPrev = j;
136
- iBonus = 50;
254
+ if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0
255
+ && (!ISALNUM(zDoc[i+n]) || p->a[j].z[n]=='*')
256
+ ){
257
+ snippet_text_append(p, pSnip, zDoc, i);
258
+ zDoc += i;
259
+ iTail -= i;
260
+ blob_append(pSnip, p->zMarkBegin, -1);
261
+ if( p->a[j].z[n]=='*' ){
262
+ while( ISALNUM(zDoc[n]) ) n++;
263
+ }
264
+ snippet_text_append(p, pSnip, zDoc, n);
265
+ zDoc += n;
266
+ iTail -= n;
267
+ blob_append(pSnip, p->zMarkEnd, -1);
268
+ i = -1;
137269
break;
138
- }
139
- }
140
- iBonus /= 2;
141
- while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142
- }
143
- }
144
-
145
- /* Every term must be seen or else the score is zero */
146
- for(j=0; j<p->nTerm; j++){
147
- if( !seen[j] ) return 0;
148
- }
149
-
150
- return score;
270
+ } /* end-if */
271
+ } /* end for(j) */
272
+ if( j<p->nTerm ){
273
+ while( ISALNUM(zDoc[i]) && i<iTail ){ i++; }
274
+ }
275
+ } /* end for(i) */
276
+ if( iTail>0 ) snippet_text_append(p, pSnip, zDoc, iTail);
277
+ }
278
+ if( wantGap ) blob_append(pSnip, p->zMarkGap, -1);
279
+ return score;
280
+}
281
+
282
+/*
283
+** COMMAND: test-snippet
284
+**
285
+** Usage: fossil test-snippet SEARCHSTRING FILE1 FILE2 ...
286
+*/
287
+void test_snippet_cmd(void){
288
+ Search *p;
289
+ int i;
290
+ Blob x;
291
+ Blob snip;
292
+ int score;
293
+ char *zDoc;
294
+ if( g.argc<4 ) usage("SEARCHSTRING FILE1...");
295
+ p = search_init(g.argv[2]);
296
+ p->zMarkBegin = "[[";
297
+ p->zMarkEnd = "]]";
298
+ p->zMarkGap = " ... ";
299
+ for(i=3; i<g.argc; i++){
300
+ blob_read_from_file(&x, g.argv[i]);
301
+ zDoc = blob_str(&x);
302
+ score = search_score(p, 1, (const char**)&zDoc, &snip);
303
+ fossil_print("%s: %d\n", g.argv[i], score);
304
+ blob_reset(&x);
305
+ if( score ){
306
+ fossil_print("%.78c\n%s\n%.78c\n\n", '=', blob_str(&snip), '=');
307
+ blob_reset(&snip);
308
+ }
309
+ }
151310
}
152311
153312
/*
154313
** This is an SQLite function that scores its input using
155314
** a pre-computed pattern.
@@ -164,11 +323,11 @@
164323
int score;
165324
int i;
166325
167326
azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168327
for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169
- score = search_score(p, argc, azDoc);
328
+ score = search_score(p, argc, azDoc, 0);
170329
fossil_free((void *)azDoc);
171330
sqlite3_result_int(context, score);
172331
}
173332
174333
/*
175334
--- src/search.c
+++ src/search.c
@@ -26,54 +26,34 @@
26 #include "config.h"
27 #include "search.h"
28 #include <assert.h>
29
30 #if INTERFACE
 
 
 
 
31 /*
32 ** A compiled search pattern
33 */
34 struct Search {
35 int nTerm; /* Number of search terms */
36 struct srchTerm { /* For each search term */
37 char *z; /* Text */
38 int n; /* length */
39 } a[8];
 
 
 
 
 
40 };
 
 
 
41 #endif
42
43 /*
44 ** Compile a search pattern
45 */
46 Search *search_init(const char *zPattern){
47 int nPattern = strlen(zPattern);
48 Search *p;
49 char *z;
50 int i;
51
52 p = fossil_malloc( nPattern + sizeof(*p) + 1);
53 z = (char*)&p[1];
54 memcpy(z, zPattern, nPattern+1);
55 memset(p, 0, sizeof(*p));
56 while( *z && p->nTerm<sizeof(p->a)/sizeof(p->a[0]) ){
57 while( !fossil_isalnum(*z) && *z ){ z++; }
58 if( *z==0 ) break;
59 p->a[p->nTerm].z = z;
60 for(i=1; fossil_isalnum(z[i]) || z[i]=='_'; i++){}
61 p->a[p->nTerm].n = i;
62 z += i;
63 p->nTerm++;
64 }
65 return p;
66 }
67
68
69 /*
70 ** Destroy a search context.
71 */
72 void search_end(Search *p){
73 free(p);
74 }
75
76 /*
77 ** Theses characters constitute a word boundary
78 */
79 static const char isBoundary[] = {
@@ -92,64 +72,243 @@
92 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
94 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
98 /*
99 ** Compare a search pattern against an input string and return a score.
 
 
100 **
101 ** Scoring:
102 ** * All terms must match at least once or the score is zero
103 ** * 10 bonus points if the first occurrence is an exact match
104 ** * 1 additional point for each subsequent match of the same word
105 ** * Extra points of two consecutive words of the pattern are consecutive
106 ** in the document
107 */
108 int search_score(Search *p, int nDoc, const char **azDoc){
109 int iPrev = 999;
110 int score = 10;
111 int iBonus = 0;
112 int i, j, k;
113 const char *zDoc;
114 unsigned char seen[8];
115
116 memset(seen, 0, sizeof(seen));
117 for(k=0; k<nDoc; k++){
118 zDoc = azDoc[k];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119 if( zDoc==0 ) continue;
 
120 for(i=0; zDoc[i]; i++){
121 char c = zDoc[i];
122 if( isBoundary[c&0xff] ) continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123 for(j=0; j<p->nTerm; j++){
124 int n = p->a[j].n;
125 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0 ){
126 score += 1;
127 if( !seen[j] ){
128 if( isBoundary[zDoc[i+n]&0xff] ) score += 10;
129 seen[j] = 1;
130 }
131 if( j==iPrev+1 ){
132 score += iBonus;
133 }
134 i += n-1;
135 iPrev = j;
136 iBonus = 50;
 
 
 
137 break;
138 }
139 }
140 iBonus /= 2;
141 while( !isBoundary[zDoc[i]&0xff] ){ i++; }
142 }
143 }
144
145 /* Every term must be seen or else the score is zero */
146 for(j=0; j<p->nTerm; j++){
147 if( !seen[j] ) return 0;
148 }
149
150 return score;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151 }
152
153 /*
154 ** This is an SQLite function that scores its input using
155 ** a pre-computed pattern.
@@ -164,11 +323,11 @@
164 int score;
165 int i;
166
167 azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
168 for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
169 score = search_score(p, argc, azDoc);
170 fossil_free((void *)azDoc);
171 sqlite3_result_int(context, score);
172 }
173
174 /*
175
--- src/search.c
+++ src/search.c
@@ -26,54 +26,34 @@
26 #include "config.h"
27 #include "search.h"
28 #include <assert.h>
29
30 #if INTERFACE
31
32 /* Maximum number of search terms */
33 #define SEARCH_MAX_TERM 8
34
35 /*
36 ** A compiled search pattern
37 */
38 struct Search {
39 int nTerm; /* Number of search terms */
40 struct srchTerm { /* For each search term */
41 char *z; /* Text */
42 int n; /* length */
43 } a[SEARCH_MAX_TERM];
44 /* Snippet controls */
45 char *zMarkBegin; /* Start of a match */
46 char *zMarkEnd; /* End of a match */
47 char *zMarkGap; /* A gap between two matches */
48 unsigned fSrchFlg; /* Flags */
49 };
50
51 #define SRCHFLG_HTML 0x0001 /* Escape snippet text for HTML */
52
53 #endif
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
56 /*
57 ** Theses characters constitute a word boundary
58 */
59 static const char isBoundary[] = {
@@ -92,64 +72,243 @@
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
76 };
77 #define ISALNUM(x) (!isBoundary[(x)&0xff])
78
79 /*
80 ** Compile a search pattern
81 */
82 Search *search_init(const char *zPattern){
83 int nPattern = strlen(zPattern);
84 Search *p;
85 char *z;
86 int i;
87
88 p = fossil_malloc( nPattern + sizeof(*p) + 1);
89 z = (char*)&p[1];
90 memcpy(z, zPattern, nPattern+1);
91 memset(p, 0, sizeof(*p));
92 while( *z && p->nTerm<SEARCH_MAX_TERM ){
93 while( *z && !ISALNUM(*z) ){ z++; }
94 if( *z==0 ) break;
95 p->a[p->nTerm].z = z;
96 for(i=1; ISALNUM(z[i]); i++){}
97 p->a[p->nTerm].n = i;
98 z += i;
99 p->nTerm++;
100 }
101 return p;
102 }
103
104
105 /*
106 ** Destroy a search context.
107 */
108 void search_end(Search *p){
109 free(p);
110 }
111
112 /*
113 ** Append n bytes of text to snippet zTxt. Encode the text appropriately.
114 */
115 static void snippet_text_append(
116 Search *p, /* The search context */
117 Blob *pSnip, /* Append to this snippet */
118 const char *zTxt, /* Text to append */
119 int n /* How many bytes to append */
120 ){
121 if( p->fSrchFlg & SRCHFLG_HTML ){
122 blob_appendf(pSnip, "%.*h", n, zTxt);
123 }else{
124 blob_append(pSnip, zTxt, n);
125 }
126 }
127
128 /*
129 ** Compare a search pattern against one or more input strings which
130 ** collectively comprise a document. Return a match score. Optionally
131 ** also return a "snippet".
132 **
133 ** Scoring:
134 ** * All terms must match at least once or the score is zero
135 ** * One point for each matching term
136 ** * Extra points if consecutive words of the pattern are consecutive
 
137 ** in the document
138 */
139 static int search_score(
140 Search *p, /* Search pattern and flags */
141 int nDoc, /* Number of strings in this document */
142 const char **azDoc, /* Text of each string */
143 Blob *pSnip /* If not NULL: Write a snippet here */
144 ){
145 int score; /* Final score */
146 int i; /* Offset into current document */
147 int ii; /* Loop counter */
148 int j; /* Loop over search terms */
149 int k; /* Loop over prior terms */
150 int iWord = 0; /* Current word number */
151 int iDoc; /* Current document number */
152 int wantGap = 0; /* True if a zMarkGap is wanted */
153 const char *zDoc; /* Current document text */
154 const int CTX = 50; /* Amount of snippet context */
155 int anMatch[SEARCH_MAX_TERM]; /* Number of terms in best match */
156 int aiBestDoc[SEARCH_MAX_TERM]; /* Document containing best match */
157 int aiBestOfst[SEARCH_MAX_TERM]; /* Byte offset to start of best match */
158 int aiLastDoc[SEARCH_MAX_TERM]; /* Document containing most recent match */
159 int aiLastOfst[SEARCH_MAX_TERM]; /* Byte offset to the most recent match */
160 int aiWordIdx[SEARCH_MAX_TERM]; /* Word index of most recent match */
161
162 memset(anMatch, 0, sizeof(anMatch));
163 memset(aiWordIdx, 0xff, sizeof(aiWordIdx));
164 for(iDoc=0; iDoc<nDoc; iDoc++){
165 zDoc = azDoc[iDoc];
166 if( zDoc==0 ) continue;
167 iWord++;
168 for(i=0; zDoc[i]; i++){
169 if( !ISALNUM(zDoc[i]) ) continue;
170 iWord++;
171 for(j=0; j<p->nTerm; j++){
172 int n = p->a[j].n;
173 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0
174 && (!ISALNUM(zDoc[i+n]) || p->a[j].z[n]=='*')
175 ){
176 aiWordIdx[j] = iWord;
177 aiLastDoc[j] = iDoc;
178 aiLastOfst[j] = i;
179 for(k=1; j-k>=0 && anMatch[j-k] && aiWordIdx[j-k]==iWord-k; k++){}
180 for(ii=0; ii<k; ii++){
181 if( anMatch[j-ii]<k ){
182 anMatch[j-ii] = k;
183 aiBestDoc[j-ii] = aiLastDoc[j-ii];
184 aiBestOfst[j-ii] = aiLastOfst[j-ii];
185 }
186 }
187 break;
188 }
189 }
190 while( ISALNUM(zDoc[i]) ){ i++; }
191 }
192 }
193
194 /* Finished search all documents.
195 ** Every term must be seen or else the score is zero
196 */
197 score = 1;
198 for(j=0; j<p->nTerm; j++) score *= anMatch[j];
199 if( score==0 || pSnip==0 ) return score;
200
201
202 /* Prepare a snippet that describes the matching text.
203 */
204 blob_init(pSnip, 0, 0);
205
206 while(1){
207 int iOfst;
208 int iTail;
209 int iBest;
210 for(ii=0; ii<p->nTerm && anMatch[ii]==0; ii++){}
211 if( ii>=p->nTerm ) break; /* This is where the loop exits */
212 iBest = ii;
213 iDoc = aiBestDoc[ii];
214 iOfst = aiBestOfst[ii];
215 for(; ii<p->nTerm; ii++){
216 if( anMatch[ii]==0 ) continue;
217 if( aiBestDoc[ii]>iDoc ) continue;
218 if( aiBestOfst[ii]>iOfst ) continue;
219 iDoc = aiBestDoc[ii];
220 iOfst = aiBestOfst[ii];
221 iBest = ii;
222 }
223 iTail = iOfst + p->a[iBest].n;
224 anMatch[iBest] = 0;
225 for(ii=0; ii<p->nTerm; ii++){
226 if( anMatch[ii]==0 ) continue;
227 if( aiBestDoc[ii]!=iDoc ) continue;
228 if( aiBestOfst[ii]<=iTail+CTX*2 ){
229 if( iTail<aiBestOfst[ii]+p->a[ii].n ){
230 iTail = aiBestOfst[ii]+p->a[ii].n;
231 }
232 anMatch[ii] = 0;
233 ii = -1;
234 continue;
235 }
236 }
237 zDoc = azDoc[iDoc];
238 iOfst -= CTX;
239 if( iOfst<0 ) iOfst = 0;
240 while( iOfst>0 && ISALNUM(zDoc[iOfst-1]) ) iOfst--;
241 while( zDoc[iOfst] && !ISALNUM(zDoc[iOfst]) ) iOfst++;
242 for(ii=0; ii<CTX && zDoc[iTail]; ii++, iTail++){}
243 while( ISALNUM(zDoc[iTail]) ) iTail++;
244 if( iOfst>0 || wantGap ) blob_append(pSnip, p->zMarkGap, -1);
245 wantGap = zDoc[iTail]!=0;
246 zDoc += iOfst;
247 iTail -= iOfst;
248
249 /* Add a snippet segment using characters iOfst..iOfst+iTail from zDoc */
250 for(i=0; i<iTail; i++){
251 if( !ISALNUM(zDoc[i]) ) continue;
252 for(j=0; j<p->nTerm; j++){
253 int n = p->a[j].n;
254 if( sqlite3_strnicmp(p->a[j].z, &zDoc[i], n)==0
255 && (!ISALNUM(zDoc[i+n]) || p->a[j].z[n]=='*')
256 ){
257 snippet_text_append(p, pSnip, zDoc, i);
258 zDoc += i;
259 iTail -= i;
260 blob_append(pSnip, p->zMarkBegin, -1);
261 if( p->a[j].z[n]=='*' ){
262 while( ISALNUM(zDoc[n]) ) n++;
263 }
264 snippet_text_append(p, pSnip, zDoc, n);
265 zDoc += n;
266 iTail -= n;
267 blob_append(pSnip, p->zMarkEnd, -1);
268 i = -1;
269 break;
270 } /* end-if */
271 } /* end for(j) */
272 if( j<p->nTerm ){
273 while( ISALNUM(zDoc[i]) && i<iTail ){ i++; }
274 }
275 } /* end for(i) */
276 if( iTail>0 ) snippet_text_append(p, pSnip, zDoc, iTail);
277 }
278 if( wantGap ) blob_append(pSnip, p->zMarkGap, -1);
279 return score;
280 }
281
282 /*
283 ** COMMAND: test-snippet
284 **
285 ** Usage: fossil test-snippet SEARCHSTRING FILE1 FILE2 ...
286 */
287 void test_snippet_cmd(void){
288 Search *p;
289 int i;
290 Blob x;
291 Blob snip;
292 int score;
293 char *zDoc;
294 if( g.argc<4 ) usage("SEARCHSTRING FILE1...");
295 p = search_init(g.argv[2]);
296 p->zMarkBegin = "[[";
297 p->zMarkEnd = "]]";
298 p->zMarkGap = " ... ";
299 for(i=3; i<g.argc; i++){
300 blob_read_from_file(&x, g.argv[i]);
301 zDoc = blob_str(&x);
302 score = search_score(p, 1, (const char**)&zDoc, &snip);
303 fossil_print("%s: %d\n", g.argv[i], score);
304 blob_reset(&x);
305 if( score ){
306 fossil_print("%.78c\n%s\n%.78c\n\n", '=', blob_str(&snip), '=');
307 blob_reset(&snip);
308 }
309 }
310 }
311
312 /*
313 ** This is an SQLite function that scores its input using
314 ** a pre-computed pattern.
@@ -164,11 +323,11 @@
323 int score;
324 int i;
325
326 azDoc = fossil_malloc( sizeof(const char*)*(argc+1) );
327 for(i=0; i<argc; i++) azDoc[i] = (const char*)sqlite3_value_text(argv[i]);
328 score = search_score(p, argc, azDoc, 0);
329 fossil_free((void *)azDoc);
330 sqlite3_result_int(context, score);
331 }
332
333 /*
334
+16 -20
--- src/setup.c
+++ src/setup.c
@@ -813,17 +813,13 @@
813813
@ <ul>
814814
@ <li><p>
815815
@ No login is required for user <span class="usertype">nobody</span>. The
816816
@ capabilities of the <span class="usertype">nobody</span> user are
817817
@ inherited by all users, regardless of whether or not they are logged in.
818
- @ To disable universal access to the repository, make sure no user named
819
- @ <span class="usertype">nobody</span> exists or that the
818
+ @ To disable universal access to the repository, make sure that the
820819
@ <span class="usertype">nobody</span> user has no capabilities
821820
@ enabled. The password for <span class="usertype">nobody</span> is ignored.
822
- @ To avoid problems with spiders overloading the server, it is recommended
823
- @ that the <span class="capability">h</span> (Hyperlinks) capability be
824
- @ turned off for the <span class="usertype">nobody</span> user.
825821
@ </p></li>
826822
@
827823
@ <li><p>
828824
@ Login is required for user <span class="usertype">anonymous</span> but the
829825
@ password is displayed on the login screen beside the password entry box
@@ -1525,26 +1521,26 @@
15251521
login_needed();
15261522
}
15271523
db_begin_transaction();
15281524
if( P("clear")!=0 ){
15291525
db_multi_exec("DELETE FROM config WHERE name='css'");
1530
- cgi_replace_parameter("css", builtin_text("skins/default.css"));
1526
+ cgi_replace_parameter("css", builtin_text("skins/default/css.txt"));
15311527
db_end_transaction(0);
15321528
cgi_redirect("setup_editcss");
15331529
}
15341530
if( P("submit")!=0 ){
15351531
textarea_attribute(0, 0, 0, "css", "css",
1536
- builtin_text("skins/default.css"), 0);
1532
+ builtin_text("skins/default/css.txt"), 0);
15371533
db_end_transaction(0);
15381534
cgi_redirect("setup_editcss");
15391535
}
15401536
style_header("Edit CSS");
15411537
@ <form action="%s(g.zTop)/setup_editcss" method="post"><div>
15421538
login_insert_csrf_secret();
15431539
@ Edit the CSS below:<br />
15441540
textarea_attribute("", 35, 80, "css", "css",
1545
- builtin_text("skins/default.css"), 0);
1541
+ builtin_text("skins/default/css.txt"), 0);
15461542
@ <br />
15471543
@ <input type="submit" name="submit" value="Apply Changes" />
15481544
@ <input type="submit" name="clear" value="Revert To Default" />
15491545
@ </div></form>
15501546
@ <p><span class="note">Note:</span> Press your browser Reload button after
@@ -1570,17 +1566,17 @@
15701566
login_needed();
15711567
}
15721568
db_begin_transaction();
15731569
if( P("clear")!=0 ){
15741570
db_multi_exec("DELETE FROM config WHERE name='header'");
1575
- cgi_replace_parameter("header", builtin_text("skins/default.header"));
1571
+ cgi_replace_parameter("header", builtin_text("skins/default/header.txt"));
15761572
}else if( P("submit")!=0 ){
15771573
textarea_attribute(0, 0, 0, "header", "header",
1578
- builtin_text("skins/default.header"), 0);
1574
+ builtin_text("skins/default/header.txt"), 0);
15791575
}else if( P("fixbase")!=0 ){
15801576
const char *z = db_get("header",
1581
- (char*)builtin_text("skins/default.header"));
1577
+ (char*)builtin_text("skins/default/header.txt"));
15821578
char *zHead = strstr(z, "<head>");
15831579
if( strstr(z, "<base href=")==0 && zHead!=0 ){
15841580
char *zNew;
15851581
char *zTail = &zHead[6];
15861582
while( fossil_isspace(zTail[0]) ) zTail++;
@@ -1606,11 +1602,11 @@
16061602
login_insert_csrf_secret();
16071603
@ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
16081604
@ generate the beginning of every page through start of the main
16091605
@ menu.</p>
16101606
textarea_attribute("", 35, 80, "header", "header",
1611
- builtin_text("skins/default.header"), 0);
1607
+ builtin_text("skins/default/header.txt"), 0);
16121608
@ <br />
16131609
@ <input type="submit" name="submit" value="Apply Changes" />
16141610
@ <input type="submit" name="clear" value="Revert To Default" />
16151611
@ </div></form>
16161612
@ <hr />
@@ -1617,11 +1613,11 @@
16171613
@ The default header is shown below for reference. Other examples
16181614
@ of headers can be seen on the <a href="setup_skin">skins page</a>.
16191615
@ See also the <a href="setup_editcss">CSS</a> and
16201616
@ <a href="setup_footer">footer</a> editing screens.
16211617
@ <blockquote><pre>
1622
- @ %h(builtin_text("skins/default.header"))
1618
+ @ %h(builtin_text("skins/default/header.txt"))
16231619
@ </pre></blockquote>
16241620
style_footer();
16251621
db_end_transaction(0);
16261622
}
16271623
@@ -1634,20 +1630,20 @@
16341630
login_needed();
16351631
}
16361632
db_begin_transaction();
16371633
if( P("clear")!=0 ){
16381634
db_multi_exec("DELETE FROM config WHERE name='footer'");
1639
- cgi_replace_parameter("footer", builtin_text("skins/default.footer"));
1635
+ cgi_replace_parameter("footer", builtin_text("skins/default/footer.txt"));
16401636
}
16411637
16421638
style_header("Edit Page Footer");
16431639
@ <form action="%s(g.zTop)/setup_footer" method="post"><div>
16441640
login_insert_csrf_secret();
16451641
@ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
16461642
@ generate the end of every page.</p>
16471643
textarea_attribute("", 20, 80, "footer", "footer",
1648
- builtin_text("skins/default.footer"), 0);
1644
+ builtin_text("skins/default/footer.txt"), 0);
16491645
@ <br />
16501646
@ <input type="submit" name="submit" value="Apply Changes" />
16511647
@ <input type="submit" name="clear" value="Revert To Default" />
16521648
@ </div></form>
16531649
@ <hr />
@@ -1654,11 +1650,11 @@
16541650
@ The default footer is shown below for reference. Other examples
16551651
@ of footers can be seen on the <a href="setup_skin">skins page</a>.
16561652
@ See also the <a href="setup_editcss">CSS</a> and
16571653
@ <a href="setup_header">header</a> editing screens.
16581654
@ <blockquote><pre>
1659
- @ %h(builtin_text("skins/default.footer"))
1655
+ @ %h(builtin_text("skins/default/footer.txt"))
16601656
@ </pre></blockquote>
16611657
style_footer();
16621658
db_end_transaction(0);
16631659
}
16641660
@@ -2142,14 +2138,14 @@
21422138
@ <th>User</th>
21432139
@ <th>Page</th>
21442140
@ <th width="60%%">Message</th>
21452141
@ </thead><tbody>
21462142
while( SQLITE_ROW == db_step(&stLog) ){
2147
- char const * zTime = db_column_text(&stLog, 0);
2148
- char const * zUser = db_column_text(&stLog, 1);
2149
- char const * zPage = db_column_text(&stLog, 2);
2150
- char const * zMessage = db_column_text(&stLog, 3);
2143
+ const char *zTime = db_column_text(&stLog, 0);
2144
+ const char *zUser = db_column_text(&stLog, 1);
2145
+ const char *zPage = db_column_text(&stLog, 2);
2146
+ const char *zMessage = db_column_text(&stLog, 3);
21512147
@ <tr class="row%d(counter++%2)">
21522148
@ <td class="adminTime">%s(zTime)</td>
21532149
@ <td>%s(zUser)</td>
21542150
@ <td>%s(zPage)</td>
21552151
@ <td>%h(zMessage)</td>
21562152
--- src/setup.c
+++ src/setup.c
@@ -813,17 +813,13 @@
813 @ <ul>
814 @ <li><p>
815 @ No login is required for user <span class="usertype">nobody</span>. The
816 @ capabilities of the <span class="usertype">nobody</span> user are
817 @ inherited by all users, regardless of whether or not they are logged in.
818 @ To disable universal access to the repository, make sure no user named
819 @ <span class="usertype">nobody</span> exists or that the
820 @ <span class="usertype">nobody</span> user has no capabilities
821 @ enabled. The password for <span class="usertype">nobody</span> is ignored.
822 @ To avoid problems with spiders overloading the server, it is recommended
823 @ that the <span class="capability">h</span> (Hyperlinks) capability be
824 @ turned off for the <span class="usertype">nobody</span> user.
825 @ </p></li>
826 @
827 @ <li><p>
828 @ Login is required for user <span class="usertype">anonymous</span> but the
829 @ password is displayed on the login screen beside the password entry box
@@ -1525,26 +1521,26 @@
1525 login_needed();
1526 }
1527 db_begin_transaction();
1528 if( P("clear")!=0 ){
1529 db_multi_exec("DELETE FROM config WHERE name='css'");
1530 cgi_replace_parameter("css", builtin_text("skins/default.css"));
1531 db_end_transaction(0);
1532 cgi_redirect("setup_editcss");
1533 }
1534 if( P("submit")!=0 ){
1535 textarea_attribute(0, 0, 0, "css", "css",
1536 builtin_text("skins/default.css"), 0);
1537 db_end_transaction(0);
1538 cgi_redirect("setup_editcss");
1539 }
1540 style_header("Edit CSS");
1541 @ <form action="%s(g.zTop)/setup_editcss" method="post"><div>
1542 login_insert_csrf_secret();
1543 @ Edit the CSS below:<br />
1544 textarea_attribute("", 35, 80, "css", "css",
1545 builtin_text("skins/default.css"), 0);
1546 @ <br />
1547 @ <input type="submit" name="submit" value="Apply Changes" />
1548 @ <input type="submit" name="clear" value="Revert To Default" />
1549 @ </div></form>
1550 @ <p><span class="note">Note:</span> Press your browser Reload button after
@@ -1570,17 +1566,17 @@
1570 login_needed();
1571 }
1572 db_begin_transaction();
1573 if( P("clear")!=0 ){
1574 db_multi_exec("DELETE FROM config WHERE name='header'");
1575 cgi_replace_parameter("header", builtin_text("skins/default.header"));
1576 }else if( P("submit")!=0 ){
1577 textarea_attribute(0, 0, 0, "header", "header",
1578 builtin_text("skins/default.header"), 0);
1579 }else if( P("fixbase")!=0 ){
1580 const char *z = db_get("header",
1581 (char*)builtin_text("skins/default.header"));
1582 char *zHead = strstr(z, "<head>");
1583 if( strstr(z, "<base href=")==0 && zHead!=0 ){
1584 char *zNew;
1585 char *zTail = &zHead[6];
1586 while( fossil_isspace(zTail[0]) ) zTail++;
@@ -1606,11 +1602,11 @@
1606 login_insert_csrf_secret();
1607 @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
1608 @ generate the beginning of every page through start of the main
1609 @ menu.</p>
1610 textarea_attribute("", 35, 80, "header", "header",
1611 builtin_text("skins/default.header"), 0);
1612 @ <br />
1613 @ <input type="submit" name="submit" value="Apply Changes" />
1614 @ <input type="submit" name="clear" value="Revert To Default" />
1615 @ </div></form>
1616 @ <hr />
@@ -1617,11 +1613,11 @@
1617 @ The default header is shown below for reference. Other examples
1618 @ of headers can be seen on the <a href="setup_skin">skins page</a>.
1619 @ See also the <a href="setup_editcss">CSS</a> and
1620 @ <a href="setup_footer">footer</a> editing screens.
1621 @ <blockquote><pre>
1622 @ %h(builtin_text("skins/default.header"))
1623 @ </pre></blockquote>
1624 style_footer();
1625 db_end_transaction(0);
1626 }
1627
@@ -1634,20 +1630,20 @@
1634 login_needed();
1635 }
1636 db_begin_transaction();
1637 if( P("clear")!=0 ){
1638 db_multi_exec("DELETE FROM config WHERE name='footer'");
1639 cgi_replace_parameter("footer", builtin_text("skins/default.footer"));
1640 }
1641
1642 style_header("Edit Page Footer");
1643 @ <form action="%s(g.zTop)/setup_footer" method="post"><div>
1644 login_insert_csrf_secret();
1645 @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
1646 @ generate the end of every page.</p>
1647 textarea_attribute("", 20, 80, "footer", "footer",
1648 builtin_text("skins/default.footer"), 0);
1649 @ <br />
1650 @ <input type="submit" name="submit" value="Apply Changes" />
1651 @ <input type="submit" name="clear" value="Revert To Default" />
1652 @ </div></form>
1653 @ <hr />
@@ -1654,11 +1650,11 @@
1654 @ The default footer is shown below for reference. Other examples
1655 @ of footers can be seen on the <a href="setup_skin">skins page</a>.
1656 @ See also the <a href="setup_editcss">CSS</a> and
1657 @ <a href="setup_header">header</a> editing screens.
1658 @ <blockquote><pre>
1659 @ %h(builtin_text("skins/default.footer"))
1660 @ </pre></blockquote>
1661 style_footer();
1662 db_end_transaction(0);
1663 }
1664
@@ -2142,14 +2138,14 @@
2142 @ <th>User</th>
2143 @ <th>Page</th>
2144 @ <th width="60%%">Message</th>
2145 @ </thead><tbody>
2146 while( SQLITE_ROW == db_step(&stLog) ){
2147 char const * zTime = db_column_text(&stLog, 0);
2148 char const * zUser = db_column_text(&stLog, 1);
2149 char const * zPage = db_column_text(&stLog, 2);
2150 char const * zMessage = db_column_text(&stLog, 3);
2151 @ <tr class="row%d(counter++%2)">
2152 @ <td class="adminTime">%s(zTime)</td>
2153 @ <td>%s(zUser)</td>
2154 @ <td>%s(zPage)</td>
2155 @ <td>%h(zMessage)</td>
2156
--- src/setup.c
+++ src/setup.c
@@ -813,17 +813,13 @@
813 @ <ul>
814 @ <li><p>
815 @ No login is required for user <span class="usertype">nobody</span>. The
816 @ capabilities of the <span class="usertype">nobody</span> user are
817 @ inherited by all users, regardless of whether or not they are logged in.
818 @ To disable universal access to the repository, make sure that the
 
819 @ <span class="usertype">nobody</span> user has no capabilities
820 @ enabled. The password for <span class="usertype">nobody</span> is ignored.
 
 
 
821 @ </p></li>
822 @
823 @ <li><p>
824 @ Login is required for user <span class="usertype">anonymous</span> but the
825 @ password is displayed on the login screen beside the password entry box
@@ -1525,26 +1521,26 @@
1521 login_needed();
1522 }
1523 db_begin_transaction();
1524 if( P("clear")!=0 ){
1525 db_multi_exec("DELETE FROM config WHERE name='css'");
1526 cgi_replace_parameter("css", builtin_text("skins/default/css.txt"));
1527 db_end_transaction(0);
1528 cgi_redirect("setup_editcss");
1529 }
1530 if( P("submit")!=0 ){
1531 textarea_attribute(0, 0, 0, "css", "css",
1532 builtin_text("skins/default/css.txt"), 0);
1533 db_end_transaction(0);
1534 cgi_redirect("setup_editcss");
1535 }
1536 style_header("Edit CSS");
1537 @ <form action="%s(g.zTop)/setup_editcss" method="post"><div>
1538 login_insert_csrf_secret();
1539 @ Edit the CSS below:<br />
1540 textarea_attribute("", 35, 80, "css", "css",
1541 builtin_text("skins/default/css.txt"), 0);
1542 @ <br />
1543 @ <input type="submit" name="submit" value="Apply Changes" />
1544 @ <input type="submit" name="clear" value="Revert To Default" />
1545 @ </div></form>
1546 @ <p><span class="note">Note:</span> Press your browser Reload button after
@@ -1570,17 +1566,17 @@
1566 login_needed();
1567 }
1568 db_begin_transaction();
1569 if( P("clear")!=0 ){
1570 db_multi_exec("DELETE FROM config WHERE name='header'");
1571 cgi_replace_parameter("header", builtin_text("skins/default/header.txt"));
1572 }else if( P("submit")!=0 ){
1573 textarea_attribute(0, 0, 0, "header", "header",
1574 builtin_text("skins/default/header.txt"), 0);
1575 }else if( P("fixbase")!=0 ){
1576 const char *z = db_get("header",
1577 (char*)builtin_text("skins/default/header.txt"));
1578 char *zHead = strstr(z, "<head>");
1579 if( strstr(z, "<base href=")==0 && zHead!=0 ){
1580 char *zNew;
1581 char *zTail = &zHead[6];
1582 while( fossil_isspace(zTail[0]) ) zTail++;
@@ -1606,11 +1602,11 @@
1602 login_insert_csrf_secret();
1603 @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
1604 @ generate the beginning of every page through start of the main
1605 @ menu.</p>
1606 textarea_attribute("", 35, 80, "header", "header",
1607 builtin_text("skins/default/header.txt"), 0);
1608 @ <br />
1609 @ <input type="submit" name="submit" value="Apply Changes" />
1610 @ <input type="submit" name="clear" value="Revert To Default" />
1611 @ </div></form>
1612 @ <hr />
@@ -1617,11 +1613,11 @@
1613 @ The default header is shown below for reference. Other examples
1614 @ of headers can be seen on the <a href="setup_skin">skins page</a>.
1615 @ See also the <a href="setup_editcss">CSS</a> and
1616 @ <a href="setup_footer">footer</a> editing screens.
1617 @ <blockquote><pre>
1618 @ %h(builtin_text("skins/default/header.txt"))
1619 @ </pre></blockquote>
1620 style_footer();
1621 db_end_transaction(0);
1622 }
1623
@@ -1634,20 +1630,20 @@
1630 login_needed();
1631 }
1632 db_begin_transaction();
1633 if( P("clear")!=0 ){
1634 db_multi_exec("DELETE FROM config WHERE name='footer'");
1635 cgi_replace_parameter("footer", builtin_text("skins/default/footer.txt"));
1636 }
1637
1638 style_header("Edit Page Footer");
1639 @ <form action="%s(g.zTop)/setup_footer" method="post"><div>
1640 login_insert_csrf_secret();
1641 @ <p>Edit HTML text with embedded TH1 (a Tcl dialect) that will be used to
1642 @ generate the end of every page.</p>
1643 textarea_attribute("", 20, 80, "footer", "footer",
1644 builtin_text("skins/default/footer.txt"), 0);
1645 @ <br />
1646 @ <input type="submit" name="submit" value="Apply Changes" />
1647 @ <input type="submit" name="clear" value="Revert To Default" />
1648 @ </div></form>
1649 @ <hr />
@@ -1654,11 +1650,11 @@
1650 @ The default footer is shown below for reference. Other examples
1651 @ of footers can be seen on the <a href="setup_skin">skins page</a>.
1652 @ See also the <a href="setup_editcss">CSS</a> and
1653 @ <a href="setup_header">header</a> editing screens.
1654 @ <blockquote><pre>
1655 @ %h(builtin_text("skins/default/footer.txt"))
1656 @ </pre></blockquote>
1657 style_footer();
1658 db_end_transaction(0);
1659 }
1660
@@ -2142,14 +2138,14 @@
2138 @ <th>User</th>
2139 @ <th>Page</th>
2140 @ <th width="60%%">Message</th>
2141 @ </thead><tbody>
2142 while( SQLITE_ROW == db_step(&stLog) ){
2143 const char *zTime = db_column_text(&stLog, 0);
2144 const char *zUser = db_column_text(&stLog, 1);
2145 const char *zPage = db_column_text(&stLog, 2);
2146 const char *zMessage = db_column_text(&stLog, 3);
2147 @ <tr class="row%d(counter++%2)">
2148 @ <td class="adminTime">%s(zTime)</td>
2149 @ <td>%s(zUser)</td>
2150 @ <td>%s(zPage)</td>
2151 @ <td>%h(zMessage)</td>
2152
+7 -7
--- src/sha1.c
+++ src/sha1.c
@@ -64,11 +64,11 @@
6464
^block[(i+2)&15]^block[i&15],1))
6565
6666
/*
6767
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
6868
*
69
- * Rl0() for little-endian and Rb0() for big-endian. Endianness is
69
+ * Rl0() for little-endian and Rb0() for big-endian. Endianness is
7070
* determined at run-time.
7171
*/
7272
#define Rl0(v,w,x,y,z,i) \
7373
z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
7474
#define Rb0(v,w,x,y,z,i) \
@@ -217,11 +217,11 @@
217217
** "unsigned char digest[20]" in the calling function. The SHA1
218218
** digest is stored in the first 20 bytes. zBuf should
219219
** be "char zBuf[41]".
220220
*/
221221
static void DigestToBase16(unsigned char *digest, char *zBuf){
222
- static char const zEncode[] = "0123456789abcdef";
222
+ static const char zEncode[] = "0123456789abcdef";
223223
int ix;
224224
225225
for(ix=0; ix<20; ix++){
226226
*zBuf++ = zEncode[(*digest>>4)&0xf];
227227
*zBuf++ = zEncode[*digest++ & 0xf];
@@ -258,11 +258,11 @@
258258
sha1sum_step_text(blob_buffer(p), blob_size(p));
259259
}
260260
261261
/*
262262
** Finish the incremental SHA1 checksum. Store the result in blob pOut
263
-** if pOut!=0. Also return a pointer to the result.
263
+** if pOut!=0. Also return a pointer to the result.
264264
**
265265
** This resets the incremental checksum preparing for the next round
266266
** of computation. The return pointer points to a static buffer that
267267
** is overwritten by subsequent calls to this function.
268268
*/
@@ -295,11 +295,11 @@
295295
296296
if( file_wd_islink(zFilename) ){
297297
/* Instead of file content, return sha1 of link destination path */
298298
Blob destinationPath;
299299
int rc;
300
-
300
+
301301
blob_read_link(&destinationPath, zFilename);
302302
rc = sha1sum_blob(&destinationPath, pCksum);
303303
blob_reset(&destinationPath);
304304
return rc;
305305
}
@@ -363,11 +363,11 @@
363363
return mprintf("%s", zDigest);
364364
}
365365
366366
/*
367367
** Convert a cleartext password for a specific user into a SHA1 hash.
368
-**
368
+**
369369
** The algorithm here is:
370370
**
371371
** SHA1( project-code + "/" + login + "/" + password )
372372
**
373373
** In words: The users login name and password are appended to the
@@ -375,11 +375,11 @@
375375
**
376376
** The result of this function is the shared secret used by a client
377377
** to authenticate to a server for the sync protocol. It is also the
378378
** value stored in the USER.PW field of the database. By mixing in the
379379
** login name and the project id with the hash, different shared secrets
380
-** are obtained even if two users select the same password, or if a
380
+** are obtained even if two users select the same password, or if a
381381
** single user selects the same password for multiple projects.
382382
*/
383383
char *sha1_shared_secret(
384384
const char *zPw, /* The password to encrypt */
385385
const char *zLogin, /* Username */
@@ -457,11 +457,11 @@
457457
*/
458458
void sha1sum_test(void){
459459
int i;
460460
Blob in;
461461
Blob cksum;
462
-
462
+
463463
for(i=2; i<g.argc; i++){
464464
blob_init(&cksum, "************** not found ***************", -1);
465465
if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
466466
blob_read_from_channel(&in, stdin, -1);
467467
sha1sum_blob(&in, &cksum);
468468
--- src/sha1.c
+++ src/sha1.c
@@ -64,11 +64,11 @@
64 ^block[(i+2)&15]^block[i&15],1))
65
66 /*
67 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
68 *
69 * Rl0() for little-endian and Rb0() for big-endian. Endianness is
70 * determined at run-time.
71 */
72 #define Rl0(v,w,x,y,z,i) \
73 z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
74 #define Rb0(v,w,x,y,z,i) \
@@ -217,11 +217,11 @@
217 ** "unsigned char digest[20]" in the calling function. The SHA1
218 ** digest is stored in the first 20 bytes. zBuf should
219 ** be "char zBuf[41]".
220 */
221 static void DigestToBase16(unsigned char *digest, char *zBuf){
222 static char const zEncode[] = "0123456789abcdef";
223 int ix;
224
225 for(ix=0; ix<20; ix++){
226 *zBuf++ = zEncode[(*digest>>4)&0xf];
227 *zBuf++ = zEncode[*digest++ & 0xf];
@@ -258,11 +258,11 @@
258 sha1sum_step_text(blob_buffer(p), blob_size(p));
259 }
260
261 /*
262 ** Finish the incremental SHA1 checksum. Store the result in blob pOut
263 ** if pOut!=0. Also return a pointer to the result.
264 **
265 ** This resets the incremental checksum preparing for the next round
266 ** of computation. The return pointer points to a static buffer that
267 ** is overwritten by subsequent calls to this function.
268 */
@@ -295,11 +295,11 @@
295
296 if( file_wd_islink(zFilename) ){
297 /* Instead of file content, return sha1 of link destination path */
298 Blob destinationPath;
299 int rc;
300
301 blob_read_link(&destinationPath, zFilename);
302 rc = sha1sum_blob(&destinationPath, pCksum);
303 blob_reset(&destinationPath);
304 return rc;
305 }
@@ -363,11 +363,11 @@
363 return mprintf("%s", zDigest);
364 }
365
366 /*
367 ** Convert a cleartext password for a specific user into a SHA1 hash.
368 **
369 ** The algorithm here is:
370 **
371 ** SHA1( project-code + "/" + login + "/" + password )
372 **
373 ** In words: The users login name and password are appended to the
@@ -375,11 +375,11 @@
375 **
376 ** The result of this function is the shared secret used by a client
377 ** to authenticate to a server for the sync protocol. It is also the
378 ** value stored in the USER.PW field of the database. By mixing in the
379 ** login name and the project id with the hash, different shared secrets
380 ** are obtained even if two users select the same password, or if a
381 ** single user selects the same password for multiple projects.
382 */
383 char *sha1_shared_secret(
384 const char *zPw, /* The password to encrypt */
385 const char *zLogin, /* Username */
@@ -457,11 +457,11 @@
457 */
458 void sha1sum_test(void){
459 int i;
460 Blob in;
461 Blob cksum;
462
463 for(i=2; i<g.argc; i++){
464 blob_init(&cksum, "************** not found ***************", -1);
465 if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
466 blob_read_from_channel(&in, stdin, -1);
467 sha1sum_blob(&in, &cksum);
468
--- src/sha1.c
+++ src/sha1.c
@@ -64,11 +64,11 @@
64 ^block[(i+2)&15]^block[i&15],1))
65
66 /*
67 * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
68 *
69 * Rl0() for little-endian and Rb0() for big-endian. Endianness is
70 * determined at run-time.
71 */
72 #define Rl0(v,w,x,y,z,i) \
73 z+=((w&(x^y))^y)+blk0le(i)+0x5A827999+rol(v,5);w=ror(w,2);
74 #define Rb0(v,w,x,y,z,i) \
@@ -217,11 +217,11 @@
217 ** "unsigned char digest[20]" in the calling function. The SHA1
218 ** digest is stored in the first 20 bytes. zBuf should
219 ** be "char zBuf[41]".
220 */
221 static void DigestToBase16(unsigned char *digest, char *zBuf){
222 static const char zEncode[] = "0123456789abcdef";
223 int ix;
224
225 for(ix=0; ix<20; ix++){
226 *zBuf++ = zEncode[(*digest>>4)&0xf];
227 *zBuf++ = zEncode[*digest++ & 0xf];
@@ -258,11 +258,11 @@
258 sha1sum_step_text(blob_buffer(p), blob_size(p));
259 }
260
261 /*
262 ** Finish the incremental SHA1 checksum. Store the result in blob pOut
263 ** if pOut!=0. Also return a pointer to the result.
264 **
265 ** This resets the incremental checksum preparing for the next round
266 ** of computation. The return pointer points to a static buffer that
267 ** is overwritten by subsequent calls to this function.
268 */
@@ -295,11 +295,11 @@
295
296 if( file_wd_islink(zFilename) ){
297 /* Instead of file content, return sha1 of link destination path */
298 Blob destinationPath;
299 int rc;
300
301 blob_read_link(&destinationPath, zFilename);
302 rc = sha1sum_blob(&destinationPath, pCksum);
303 blob_reset(&destinationPath);
304 return rc;
305 }
@@ -363,11 +363,11 @@
363 return mprintf("%s", zDigest);
364 }
365
366 /*
367 ** Convert a cleartext password for a specific user into a SHA1 hash.
368 **
369 ** The algorithm here is:
370 **
371 ** SHA1( project-code + "/" + login + "/" + password )
372 **
373 ** In words: The users login name and password are appended to the
@@ -375,11 +375,11 @@
375 **
376 ** The result of this function is the shared secret used by a client
377 ** to authenticate to a server for the sync protocol. It is also the
378 ** value stored in the USER.PW field of the database. By mixing in the
379 ** login name and the project id with the hash, different shared secrets
380 ** are obtained even if two users select the same password, or if a
381 ** single user selects the same password for multiple projects.
382 */
383 char *sha1_shared_secret(
384 const char *zPw, /* The password to encrypt */
385 const char *zLogin, /* Username */
@@ -457,11 +457,11 @@
457 */
458 void sha1sum_test(void){
459 int i;
460 Blob in;
461 Blob cksum;
462
463 for(i=2; i<g.argc; i++){
464 blob_init(&cksum, "************** not found ***************", -1);
465 if( g.argv[i][0]=='-' && g.argv[i][1]==0 ){
466 blob_read_from_channel(&in, stdin, -1);
467 sha1sum_blob(&in, &cksum);
468
+30 -10
--- src/shell.c
+++ src/shell.c
@@ -104,10 +104,30 @@
104104
/* ctype macros that work with signed characters */
105105
#define IsSpace(X) isspace((unsigned char)X)
106106
#define IsDigit(X) isdigit((unsigned char)X)
107107
#define ToLower(X) (char)tolower((unsigned char)X)
108108
109
+/* On Windows, we normally run with output mode of TEXT so that \n characters
110
+** are automatically translated into \r\n. However, this behavior needs
111
+** to be disabled in some cases (ex: when generating CSV output and when
112
+** rendering quoted strings that contain \n characters). The following
113
+** routines take care of that.
114
+*/
115
+#if defined(_WIN32) || defined(WIN32)
116
+static void setBinaryMode(FILE *out){
117
+ fflush(out);
118
+ _setmode(_fileno(out), _O_BINARY);
119
+}
120
+static void setTextMode(FILE *out){
121
+ fflush(out);
122
+ _setmode(_fileno(out), _O_TEXT);
123
+}
124
+#else
125
+# define setBinaryMode(X)
126
+# define setTextMode(X)
127
+#endif
128
+
109129
110130
/* True if the timer is enabled */
111131
static int enableTimer = 0;
112132
113133
/* Return the current wall-clock time */
@@ -582,10 +602,11 @@
582602
** Output the given string as a quoted string using SQL quoting conventions.
583603
*/
584604
static void output_quoted_string(FILE *out, const char *z){
585605
int i;
586606
int nSingle = 0;
607
+ setBinaryMode(out);
587608
for(i=0; z[i]; i++){
588609
if( z[i]=='\'' ) nSingle++;
589610
}
590611
if( nSingle==0 ){
591612
fprintf(out,"'%s'",z);
@@ -604,10 +625,11 @@
604625
break;
605626
}
606627
}
607628
fprintf(out,"'");
608629
}
630
+ setTextMode(out);
609631
}
610632
611633
/*
612634
** Output the given string as a quoted according to C or TCL quoting rules.
613635
*/
@@ -906,14 +928,11 @@
906928
}
907929
fprintf(p->out, "%s", p->rowSeparator);
908930
break;
909931
}
910932
case MODE_Csv: {
911
-#if defined(WIN32) || defined(_WIN32)
912
- fflush(p->out);
913
- _setmode(_fileno(p->out), _O_BINARY);
914
-#endif
933
+ setBinaryMode(p->out);
915934
if( p->cnt++==0 && p->showHeader ){
916935
for(i=0; i<nArg; i++){
917936
output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
918937
}
919938
fprintf(p->out, "%s", p->rowSeparator);
@@ -922,14 +941,11 @@
922941
for(i=0; i<nArg; i++){
923942
output_csv(p, azArg[i], i<nArg-1);
924943
}
925944
fprintf(p->out, "%s", p->rowSeparator);
926945
}
927
-#if defined(WIN32) || defined(_WIN32)
928
- fflush(p->out);
929
- _setmode(_fileno(p->out), _O_TEXT);
930
-#endif
946
+ setTextMode(p->out);
931947
break;
932948
}
933949
case MODE_Insert: {
934950
p->cnt++;
935951
if( azArg==0 ) break;
@@ -3322,11 +3338,11 @@
33223338
33233339
33243340
#if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
33253341
if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
33263342
extern int sqlite3SelectTrace;
3327
- sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
3343
+ sqlite3SelectTrace = integerValue(azArg[1]);
33283344
}else
33293345
#endif
33303346
33313347
33323348
#ifdef SQLITE_DEBUG
@@ -3528,10 +3544,11 @@
35283544
{ "reserve", SQLITE_TESTCTRL_RESERVE },
35293545
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
35303546
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
35313547
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
35323548
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
3549
+ { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
35333550
};
35343551
int testctrl = -1;
35353552
int rc = 0;
35363553
int i, n;
35373554
open_db(p, 0);
@@ -3594,11 +3611,12 @@
35943611
}
35953612
break;
35963613
35973614
/* sqlite3_test_control(int, int) */
35983615
case SQLITE_TESTCTRL_ASSERT:
3599
- case SQLITE_TESTCTRL_ALWAYS:
3616
+ case SQLITE_TESTCTRL_ALWAYS:
3617
+ case SQLITE_TESTCTRL_NEVER_CORRUPT:
36003618
if( nArg==3 ){
36013619
int opt = booleanValue(azArg[2]);
36023620
rc = sqlite3_test_control(testctrl, opt);
36033621
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
36043622
} else {
@@ -4185,10 +4203,12 @@
41854203
fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
41864204
sqlite3_sourceid(), SQLITE_SOURCE_ID);
41874205
exit(1);
41884206
}
41894207
#endif
4208
+ setBinaryMode(stdin);
4209
+ setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
41904210
Argv0 = argv[0];
41914211
main_init(&data);
41924212
stdin_is_interactive = isatty(0);
41934213
41944214
/* Make sure we have a valid signal handler early, before anything
41954215
--- src/shell.c
+++ src/shell.c
@@ -104,10 +104,30 @@
104 /* ctype macros that work with signed characters */
105 #define IsSpace(X) isspace((unsigned char)X)
106 #define IsDigit(X) isdigit((unsigned char)X)
107 #define ToLower(X) (char)tolower((unsigned char)X)
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
110 /* True if the timer is enabled */
111 static int enableTimer = 0;
112
113 /* Return the current wall-clock time */
@@ -582,10 +602,11 @@
582 ** Output the given string as a quoted string using SQL quoting conventions.
583 */
584 static void output_quoted_string(FILE *out, const char *z){
585 int i;
586 int nSingle = 0;
 
587 for(i=0; z[i]; i++){
588 if( z[i]=='\'' ) nSingle++;
589 }
590 if( nSingle==0 ){
591 fprintf(out,"'%s'",z);
@@ -604,10 +625,11 @@
604 break;
605 }
606 }
607 fprintf(out,"'");
608 }
 
609 }
610
611 /*
612 ** Output the given string as a quoted according to C or TCL quoting rules.
613 */
@@ -906,14 +928,11 @@
906 }
907 fprintf(p->out, "%s", p->rowSeparator);
908 break;
909 }
910 case MODE_Csv: {
911 #if defined(WIN32) || defined(_WIN32)
912 fflush(p->out);
913 _setmode(_fileno(p->out), _O_BINARY);
914 #endif
915 if( p->cnt++==0 && p->showHeader ){
916 for(i=0; i<nArg; i++){
917 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
918 }
919 fprintf(p->out, "%s", p->rowSeparator);
@@ -922,14 +941,11 @@
922 for(i=0; i<nArg; i++){
923 output_csv(p, azArg[i], i<nArg-1);
924 }
925 fprintf(p->out, "%s", p->rowSeparator);
926 }
927 #if defined(WIN32) || defined(_WIN32)
928 fflush(p->out);
929 _setmode(_fileno(p->out), _O_TEXT);
930 #endif
931 break;
932 }
933 case MODE_Insert: {
934 p->cnt++;
935 if( azArg==0 ) break;
@@ -3322,11 +3338,11 @@
3322
3323
3324 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
3325 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
3326 extern int sqlite3SelectTrace;
3327 sqlite3SelectTrace = nArg>=2 ? booleanValue(azArg[1]) : 0xff;
3328 }else
3329 #endif
3330
3331
3332 #ifdef SQLITE_DEBUG
@@ -3528,10 +3544,11 @@
3528 { "reserve", SQLITE_TESTCTRL_RESERVE },
3529 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
3530 { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
3531 { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
3532 { "byteorder", SQLITE_TESTCTRL_BYTEORDER },
 
3533 };
3534 int testctrl = -1;
3535 int rc = 0;
3536 int i, n;
3537 open_db(p, 0);
@@ -3594,11 +3611,12 @@
3594 }
3595 break;
3596
3597 /* sqlite3_test_control(int, int) */
3598 case SQLITE_TESTCTRL_ASSERT:
3599 case SQLITE_TESTCTRL_ALWAYS:
 
3600 if( nArg==3 ){
3601 int opt = booleanValue(azArg[2]);
3602 rc = sqlite3_test_control(testctrl, opt);
3603 fprintf(p->out, "%d (0x%08x)\n", rc, rc);
3604 } else {
@@ -4185,10 +4203,12 @@
4185 fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
4186 sqlite3_sourceid(), SQLITE_SOURCE_ID);
4187 exit(1);
4188 }
4189 #endif
 
 
4190 Argv0 = argv[0];
4191 main_init(&data);
4192 stdin_is_interactive = isatty(0);
4193
4194 /* Make sure we have a valid signal handler early, before anything
4195
--- src/shell.c
+++ src/shell.c
@@ -104,10 +104,30 @@
104 /* ctype macros that work with signed characters */
105 #define IsSpace(X) isspace((unsigned char)X)
106 #define IsDigit(X) isdigit((unsigned char)X)
107 #define ToLower(X) (char)tolower((unsigned char)X)
108
109 /* On Windows, we normally run with output mode of TEXT so that \n characters
110 ** are automatically translated into \r\n. However, this behavior needs
111 ** to be disabled in some cases (ex: when generating CSV output and when
112 ** rendering quoted strings that contain \n characters). The following
113 ** routines take care of that.
114 */
115 #if defined(_WIN32) || defined(WIN32)
116 static void setBinaryMode(FILE *out){
117 fflush(out);
118 _setmode(_fileno(out), _O_BINARY);
119 }
120 static void setTextMode(FILE *out){
121 fflush(out);
122 _setmode(_fileno(out), _O_TEXT);
123 }
124 #else
125 # define setBinaryMode(X)
126 # define setTextMode(X)
127 #endif
128
129
130 /* True if the timer is enabled */
131 static int enableTimer = 0;
132
133 /* Return the current wall-clock time */
@@ -582,10 +602,11 @@
602 ** Output the given string as a quoted string using SQL quoting conventions.
603 */
604 static void output_quoted_string(FILE *out, const char *z){
605 int i;
606 int nSingle = 0;
607 setBinaryMode(out);
608 for(i=0; z[i]; i++){
609 if( z[i]=='\'' ) nSingle++;
610 }
611 if( nSingle==0 ){
612 fprintf(out,"'%s'",z);
@@ -604,10 +625,11 @@
625 break;
626 }
627 }
628 fprintf(out,"'");
629 }
630 setTextMode(out);
631 }
632
633 /*
634 ** Output the given string as a quoted according to C or TCL quoting rules.
635 */
@@ -906,14 +928,11 @@
928 }
929 fprintf(p->out, "%s", p->rowSeparator);
930 break;
931 }
932 case MODE_Csv: {
933 setBinaryMode(p->out);
 
 
 
934 if( p->cnt++==0 && p->showHeader ){
935 for(i=0; i<nArg; i++){
936 output_csv(p, azCol[i] ? azCol[i] : "", i<nArg-1);
937 }
938 fprintf(p->out, "%s", p->rowSeparator);
@@ -922,14 +941,11 @@
941 for(i=0; i<nArg; i++){
942 output_csv(p, azArg[i], i<nArg-1);
943 }
944 fprintf(p->out, "%s", p->rowSeparator);
945 }
946 setTextMode(p->out);
 
 
 
947 break;
948 }
949 case MODE_Insert: {
950 p->cnt++;
951 if( azArg==0 ) break;
@@ -3322,11 +3338,11 @@
3338
3339
3340 #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_SELECTTRACE)
3341 if( c=='s' && n==11 && strncmp(azArg[0], "selecttrace", n)==0 ){
3342 extern int sqlite3SelectTrace;
3343 sqlite3SelectTrace = integerValue(azArg[1]);
3344 }else
3345 #endif
3346
3347
3348 #ifdef SQLITE_DEBUG
@@ -3528,10 +3544,11 @@
3544 { "reserve", SQLITE_TESTCTRL_RESERVE },
3545 { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
3546 { "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
3547 { "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
3548 { "byteorder", SQLITE_TESTCTRL_BYTEORDER },
3549 { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT },
3550 };
3551 int testctrl = -1;
3552 int rc = 0;
3553 int i, n;
3554 open_db(p, 0);
@@ -3594,11 +3611,12 @@
3611 }
3612 break;
3613
3614 /* sqlite3_test_control(int, int) */
3615 case SQLITE_TESTCTRL_ASSERT:
3616 case SQLITE_TESTCTRL_ALWAYS:
3617 case SQLITE_TESTCTRL_NEVER_CORRUPT:
3618 if( nArg==3 ){
3619 int opt = booleanValue(azArg[2]);
3620 rc = sqlite3_test_control(testctrl, opt);
3621 fprintf(p->out, "%d (0x%08x)\n", rc, rc);
3622 } else {
@@ -4185,10 +4203,12 @@
4203 fprintf(stderr, "SQLite header and source version mismatch\n%s\n%s\n",
4204 sqlite3_sourceid(), SQLITE_SOURCE_ID);
4205 exit(1);
4206 }
4207 #endif
4208 setBinaryMode(stdin);
4209 setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */
4210 Argv0 = argv[0];
4211 main_init(&data);
4212 stdin_is_interactive = isatty(0);
4213
4214 /* Make sure we have a valid signal handler early, before anything
4215
+1 -1
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -108,11 +108,11 @@
108108
sqlite3_result_error(context, "input is not zlib compressed", -1);
109109
}
110110
}
111111
112112
/*
113
-** Add the content(), compress(), and decompress() SQL functions to
113
+** Add the content(), compress(), and decompress() SQL functions to
114114
** database connection db.
115115
*/
116116
int add_content_sql_commands(sqlite3 *db){
117117
sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
118118
sqlcmd_content, 0, 0);
119119
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -108,11 +108,11 @@
108 sqlite3_result_error(context, "input is not zlib compressed", -1);
109 }
110 }
111
112 /*
113 ** Add the content(), compress(), and decompress() SQL functions to
114 ** database connection db.
115 */
116 int add_content_sql_commands(sqlite3 *db){
117 sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
118 sqlcmd_content, 0, 0);
119
--- src/sqlcmd.c
+++ src/sqlcmd.c
@@ -108,11 +108,11 @@
108 sqlite3_result_error(context, "input is not zlib compressed", -1);
109 }
110 }
111
112 /*
113 ** Add the content(), compress(), and decompress() SQL functions to
114 ** database connection db.
115 */
116 int add_content_sql_commands(sqlite3 *db){
117 sqlite3_create_function(db, "content", 1, SQLITE_UTF8, 0,
118 sqlcmd_content, 0, 0);
119
+3
--- src/stat.c
+++ src/stat.c
@@ -61,10 +61,11 @@
6161
if( g.perm.Admin ){
6262
style_submenu_element("URLs", "URLs and Checkouts", "urllist");
6363
style_submenu_element("Schema", "Repository Schema", "repo_schema");
6464
style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
6565
}
66
+ style_submenu_element("Activity", "Activity Reports", "reports");
6667
@ <table class="label-value">
6768
@ <tr><th>Repository&nbsp;Size:</th><td>
6869
fsize = file_size(g.zRepositoryName);
6970
bigSizeName(sizeof(zBuf), zBuf, fsize);
7071
@ %s(zBuf)
@@ -133,10 +134,11 @@
133134
@ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
134135
@ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
135136
@ </td></tr>
136137
@ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
137138
@ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
139
+ @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
138140
@ <tr><th>Repository Rebuilt:</th><td>
139141
@ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
140142
@ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
141143
@ <tr><th>Database&nbsp;Stats:</th><td>
142144
zDb = db_name("repository");
@@ -254,10 +256,11 @@
254256
}
255257
#if 0
256258
/* Server-id is not useful information any more */
257259
fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
258260
#endif
261
+ fossil_print("%*s%s\n", colWidth, "schema-version:", g.zAuxSchema);
259262
if( !omitVers ){
260263
fossil_print("%*s%s %s [%s] (%s)\n",
261264
colWidth, "fossil-version:",
262265
MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
263266
COMPILER_NAME);
264267
265268
ADDED src/statrep.c
--- src/stat.c
+++ src/stat.c
@@ -61,10 +61,11 @@
61 if( g.perm.Admin ){
62 style_submenu_element("URLs", "URLs and Checkouts", "urllist");
63 style_submenu_element("Schema", "Repository Schema", "repo_schema");
64 style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
65 }
 
66 @ <table class="label-value">
67 @ <tr><th>Repository&nbsp;Size:</th><td>
68 fsize = file_size(g.zRepositoryName);
69 bigSizeName(sizeof(zBuf), zBuf, fsize);
70 @ %s(zBuf)
@@ -133,10 +134,11 @@
133 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
134 @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
135 @ </td></tr>
136 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
137 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
 
138 @ <tr><th>Repository Rebuilt:</th><td>
139 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
140 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
141 @ <tr><th>Database&nbsp;Stats:</th><td>
142 zDb = db_name("repository");
@@ -254,10 +256,11 @@
254 }
255 #if 0
256 /* Server-id is not useful information any more */
257 fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
258 #endif
 
259 if( !omitVers ){
260 fossil_print("%*s%s %s [%s] (%s)\n",
261 colWidth, "fossil-version:",
262 MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
263 COMPILER_NAME);
264
265 DDED src/statrep.c
--- src/stat.c
+++ src/stat.c
@@ -61,10 +61,11 @@
61 if( g.perm.Admin ){
62 style_submenu_element("URLs", "URLs and Checkouts", "urllist");
63 style_submenu_element("Schema", "Repository Schema", "repo_schema");
64 style_submenu_element("Web-Cache", "Web-Cache Stats", "cachestat");
65 }
66 style_submenu_element("Activity", "Activity Reports", "reports");
67 @ <table class="label-value">
68 @ <tr><th>Repository&nbsp;Size:</th><td>
69 fsize = file_size(g.zRepositoryName);
70 bigSizeName(sizeof(zBuf), zBuf, fsize);
71 @ %s(zBuf)
@@ -133,10 +134,11 @@
134 @ %h(MANIFEST_DATE) %h(MANIFEST_VERSION)
135 @ (%h(RELEASE_VERSION)) [compiled using %h(COMPILER_NAME)]
136 @ </td></tr>
137 @ <tr><th>SQLite&nbsp;Version:</th><td>%.19s(sqlite3_sourceid())
138 @ [%.10s(&sqlite3_sourceid()[20])] (%s(sqlite3_libversion()))</td></tr>
139 @ <tr><th>Schema&nbsp;Version:</th><td>%h(g.zAuxSchema)</td></tr>
140 @ <tr><th>Repository Rebuilt:</th><td>
141 @ %h(db_get_mtime("rebuilt","%Y-%m-%d %H:%M:%S","Never"))
142 @ By Fossil %h(db_get("rebuilt","Unknown"))</td></tr>
143 @ <tr><th>Database&nbsp;Stats:</th><td>
144 zDb = db_name("repository");
@@ -254,10 +256,11 @@
256 }
257 #if 0
258 /* Server-id is not useful information any more */
259 fossil_print("%*s%s\n", colWidth, "server-id:", db_get("server-code", 0));
260 #endif
261 fossil_print("%*s%s\n", colWidth, "schema-version:", g.zAuxSchema);
262 if( !omitVers ){
263 fossil_print("%*s%s %s [%s] (%s)\n",
264 colWidth, "fossil-version:",
265 MANIFEST_DATE, MANIFEST_VERSION, RELEASE_VERSION,
266 COMPILER_NAME);
267
268 DDED src/statrep.c
+535
--- a/src/statrep.c
+++ b/src/statrep.c
@@ -0,0 +1,535 @@
1
+eea"zT
2
+ ;
3
+ @ claT
4
+ ;
5
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
6
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
7
+ style_footer();
8
+}
9
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
10
+ ;
11
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
12
+ style_footer();
13
+}
14
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
15
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
16
+ "ELSE 'ERROR' END;"svg class="pie-chart"
17
+ @ svg class="pie-chart"
18
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
19
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
20
+ , "Sunday"
21
+ };
22
+
23
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
24
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
25
+ ;
26
+ @ claT
27
+ ;
28
+ @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
29
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
30
+ "ELSE 'ERROR' END;"svg class="pie-chart"
31
+ @ svg class="pie-chart"
32
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
33
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
34
+ , "Sunday"
35
+ };
36
+
37
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
38
+ ;
39
+ @ claT
40
+ e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
41
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
42
+ "ELSE 'ERROR' END;"svg class="pie-chart"
43
+ @ svg class="pie-chart"
44
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
45
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
46
+ , "Sunday"
47
+ };
48
+
49
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
50
+ ;
51
+ @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
52
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
53
+ "ELSE 'ERROR' END;"svg class="pie-chart"
54
+ @ svg class="pie-chart"
55
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
56
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
57
+ , "Sunday"
58
+ };
59
+
60
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
61
+ ;
62
+ element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
63
+ ;
64
+ @ claT
65
+ ;
66
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
67
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
68
+ style_footer();
69
+}
70
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
71
+ ;
72
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
73
+ style_footer();
74
+}
75
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
76
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
77
+ "ELSE 'ERROR' END;"svg class="pie-chart"
78
+ @ svg class="pie-chart"
79
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
80
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
81
+ , "Sunday"
82
+ };
83
+
84
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
85
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
86
+ ;
87
+ @ claT
88
+ ;
89
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
90
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
91
+ azYear[n] = fossil_strdup(,0));
92
+ azYear[n+1] = azYear[n];
93
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
94
+ ;
95
+ @ claT
96
+ ;
97
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
98
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
99
+ style_footer();
100
+}
101
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
102
+ ;
103
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
104
+ style_footer();
105
+}
106
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
107
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
108
+ "ELSE 'ERROR' END;"svg class="pie-chart"
109
+ @ svg class="pie-chart"
110
+ @ HQuery url;/* RL for eventbranch linksurl_initialize(&url, "reports");
111
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
112
+ , "Sunday"
113
+ };
114
+
115
+ ;mtime %% 7mt/*
116
+** A helper for the /reports family of pages which prints out a menu
117
+** of links for the various type=XXX flags. zCurrentViewName must be
118
+** the name/value of the 'view' parameter which is in effect at the
119
+** time this is called. e.g. if called from the 'byuser' view then
120
+** zCurrentViewName must be "byuser". Any URL parameters which need to
121
+** be added to the generated URLs should be passed in zParam. The
122
+** caller is expected to have already encoded any zParam in event_types_menu(c><svg</centre>center><svg</centre> "Thursday",
123
+ , "Sunday"
124
+ };
125
+
126
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
127
+ ;
128
+ @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
129
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
130
+ "ELSE 'ERROR' END;"svg class="pie-chart"
131
+ @ svg class="pie-chart"uery url;/* URL for various branch linksurl_initialize(&url, "reports");
132
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>csnter><svg</centre> "Thursday",
133
+ , "Sunday"
134
+ };
135
+
136
+ ;mtime %% 7mtime %% 7Mg.zTop,MoTuesWednThur5Sunday eea"zT
137
+ ;
138
+ element(zMenuName, zMenuNameinsass="pie-chart"
139
+ @ HQuery url;/*ci'>checkin"2;"
140
+ "UPDATE piechareea"zT
141
+ ;
142
+ @ claT
143
+ ;
144
+ even class='lastchngTable'nameeea"zTuserlist","tT}
145
+ style_footer();e'>event; @ class='lastchngTeble'nameeea"zTuserlist","tT}
146
+ style_footer();
147
+}
148
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
149
+ ;
150
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
151
+ style_footer();
152
+}
153
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
154
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
155
+ "ELSE 'ERROR' END;"svg class="pie-chart"
156
+ @ svg class="pie-chart"
157
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
158
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
159
+ , "Sunday"
160
+ };
161
+
162
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
163
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
164
+ ;
165
+ @ claT
166
+ ;
167
+ @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
168
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
169
+ "ELSE 'ERROR' END;"svg class="pie-chart"
170
+ @ svg class="pie-chart"
171
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
172
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
173
+ , "Sunday"
174
+ };
175
+
176
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
177
+ ;
178
+ @ claT
179
+ e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
180
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
181
+ "ELSE 'ERROR' END;"svg class="pie-chart"
182
+ @ svg class="pie-chart"
183
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
184
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
185
+ , "Sunday"
186
+ };
187
+
188
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
189
+ ;
190
+ @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
191
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
192
+ "ELSE 'ERROR' END;"svg class="pie-chart"
193
+ @ svg class="pie-chart"
194
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
195
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
196
+ , "Sunday"
197
+ };
198
+
199
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
200
+ ;
201
+ element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
202
+ ;
203
+ @ claT
204
+ ;
205
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
206
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
207
+ style_footer();
208
+}
209
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
210
+ ;
211
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
212
+ style_footer();
213
+}
214
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
215
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
216
+ "ELSE 'ERROR' END;"svg class="pie-chart"
217
+ @ svg class="pie-chart"
218
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
219
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
220
+ , "Sunday"
221
+ };
222
+
223
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
224
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
225
+ ;
226
+ @ claT
227
+ ;
228
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
229
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
230
+ azYear[n] = fossil_strdup(,0));
231
+ azYear[n+1] = azYear[n];
232
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
233
+ ;
234
+ @ claT
235
+ ;
236
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
237
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
238
+ style_footer();
239
+}
240
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
241
+ ;
242
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
243
+ style_footer();
244
+}
245
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
246
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
247
+ "ELSE 'ERRsR' END;"svg class="pie-chart"
248
+ @ svg class="pie-chart"
249
+ @ Hg.zTop,HQuery url;/* RL for various branch linksurl_initialize(&url, "reports");
250
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
251
+ , "Sunday"
252
+ };
253
+
254
+ ;mtime %% 7mt/*
255
+** A helper for the /reports family of pages which prints out a menu
256
+** of links for the various type=XXX flags. zCurrentViewName must be
257
+** the name/value of the 'view' parameter which is in effect at the
258
+** time this is called. e.g. if called from the 'byuser' view then
259
+** zCurrentViewName must be "byuser". Any URL parameters which need to
260
+** be added to the generated URLs should be passed in zParam. The
261
+** caller is expected to have already encoded any zParam in event_types_menu(c><svg</centre>center><svg</centre> "Thursday",
262
+ , "Sunday"
263
+ };
264
+
265
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
266
+ ;
267
+ @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
268
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
269
+ "ELSE 'ERROR' END;"svg class="pie-chart"
270
+ @ svg class="pie-chart"uery url;/* URL for various branch linksurl_initialize(&url, "reports");
271
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
272
+ , "Sunday"
273
+ };
274
+
275
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
276
+ ;
277
+ element(zMenuName, zMenuNameinsass="pie-chart"
278
+ @ HQuery url;/*ci'>checkin"2;"
279
+ "UPDATE piechareea"zT
280
+ ;
281
+ @ claT
282
+ ;
283
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
284
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
285
+ style_footer();
286
+}
287
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
288
+ ;
289
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
290
+ style_footer();
291
+}
292
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
293
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
294
+ "ELSE 'ERROR' END;"svg class="pie-chart"
295
+ @ svg class="pie-chart"
296
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
297
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
298
+ , "Sunday"
299
+ };
300
+
301
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
302
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
303
+ ;
304
+ @ claT
305
+ ;
306
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
307
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
308
+ azYear[n] = fossil_strdup(,0));
309
+ azYear[n+1] = azYear[n];
310
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
311
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
312
+ style_footer();
313
+}
314
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
315
+ ;
316
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
317
+ style_footer();
318
+}
319
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
320
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
321
+ "ELSE 'ERROR' END;"svg class="pie-chart"
322
+ @ svg class="pie-chart"
323
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
324
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
325
+ , "Sunday"
326
+ };
327
+
328
+ ;mtime %% 7mtimand not empty
329
+** class="pie-chart"slist","tT}
330
+ style_feeaclass='lastchngTable'nameeea"zTuserlist","tT}
331
+ style_footer();
332
+}
333
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
334
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
335
+ "ELSE 'ERROR' END;"svg class="pie-chart"
336
+ @ svg class="pie-chart"
337
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");Blob sql-chart"
338
+ @ HQuery /* SQo_url(&url);url_rese_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
339
+ , "Sunday"
340
+ };
341
+
342
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
343
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
344
+ ;
345
+ @ claT
346
+ ;
347
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
348
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
349
+ azYear[n] = fossil_strdup(,0));
350
+ azYear[n+1] = azYear[n];
351
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
352
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
353
+ style_footer();
354
+}
355
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
356
+ ;
357
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
358
+ unday"
359
+ } NULL );
360
+header, "s) by yearL for various branchmtime %% 7mtime %% 7MoTuesWedme=TABLE piechart(amt,labelpie);
361
+ blob_append_sql(&sqlr5Sunday eea"zT
362
+ ;
363
+ @e><htimeframe,a"/center><svg/centeea"zincludeMonth if( PB("pie") ){ cgi_query_paramete
364
+ " ySizeArraySizeArraySizeeea"zT
365
+ ;
366
+ @ claT
367
+ ;
368
+ @"zT
369
+ ;
370
+ @ claT
371
+ ;
372
+ @ 'lastchngTeble'name claT
373
+ ;
374
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
375
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
376
+ style_footer();Usereea"zT
377
+ ;
378
+ @ claT
379
+ ;
380
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
381
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
382
+ style_footer();
383
+}
384
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
385
+ ;
386
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
387
+ style_footer();
388
+}
389
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
390
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
391
+ "ELSE 'ERROR' END;"svg class="pie-chart"
392
+ @ svg class="pie-chart"
393
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
394
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
395
+ , "Sunday"
396
+ };
397
+
398
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
399
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
400
+ ;
401
+ @ claT
402
+ ;
403
+ @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
404
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
405
+ "ELSE 'ERROR' END;"svg class="pie-chart"
406
+ @ svg class="pie-chart"
407
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
408
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
409
+ , "Sunday"
410
+ };
411
+
412
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
413
+ ;
414
+ @ claT
415
+ e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
416
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
417
+ "ELSE 'ERROR' END;"svg class="pie-chart"
418
+ @ svg class="pie-chart"
419
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
420
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
421
+ , "Sunday"
422
+ };
423
+
424
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
425
+ ;
426
+ @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
427
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
428
+ "ELSE 'ERROR' END;"svg class="pie-chart"
429
+ @ svg class="pie-chart"
430
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
431
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
432
+ , "Sunday"
433
+ };
434
+
435
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
436
+ ;
437
+ element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
438
+ ;
439
+ @ claT
440
+ ;
441
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
442
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
443
+ style_footer();
444
+}
445
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
446
+ ;
447
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
448
+ style_footer();
449
+}
450
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
451
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
452
+ "ELSE 'ERROR' END;"svg class="pie-chart"
453
+ @ svg class="pie-chart"
454
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
455
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
456
+ , "Sunday"
457
+ };
458
+
459
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
460
+ HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
461
+ ;
462
+ @ claT
463
+ ;
464
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
465
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
466
+ azYear[n] = fossil_strdup(,0));
467
+ azYear[n+1] = azYear[n];
468
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
469
+ ;
470
+ @ claT
471
+ ;
472
+ @ class='lastchngTeble'nameeea"zTuserlist","tT}
473
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
474
+ style_footer();
475
+}
476
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
477
+ ;
478
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
479
+ style_footer();
480
+}
481
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
482
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
483
+ "ELSE 'ERROR' END;"svg class="pie-chart"
484
+ @ svg class="pie-chart"
485
+ @ HQuery url;/* RL for various branch linksurl_initialize(&url, "reports");
486
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
487
+ , "Sunday"
488
+ };
489
+
490
+ ;mtime %% 7mt/*
491
+** A helper for the /reports family of pages which prints out a menu
492
+** of links for the various type=XXX flags. zCurrentViewName must be
493
+** the name/value of the 'view' parameter which is in effect at the
494
+** time this is called. e.g. if called from the 'byuser' view then
495
+** zCurrentViewName musa<br>?name=Teea"zT
496
+ ;g.zTop,;
497
+ @ claT
498
+ ;
499
+ @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
500
+ azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
501
+ azYear[n] = fossil_strdup(,0));
502
+ azYear[n+1] = azYear[n];
503
+ if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
504
+ style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
505
+ style_footer();
506
+}
507
+svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
508
+ ;
509
+ @ class='lastchngTable'nameeea"zTuserlist","tT}
510
+ style_footer();
511
+}
512
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
513
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
514
+ "ELSE 'ERROR' END;"svg class="pie-chart"
515
+ @ svg class="pie-chart"
516
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
517
+ cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
518
+ , "Sunday"
519
+ };
520
+
521
+ ;mtime %% 7mtimand not empty
522
+** class="pie-chart"slist","tT}
523
+ style_feeaclass='lastchngTable'nameeea"zTuserlist","tT}
524
+ style_footer();
525
+}
526
+center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
527
+ "UPDATE piechart SEWHEN 5 THEN 'Friday'"
528
+ "ELSE 'ERROR' END;"svg class="pie-chart"
529
+ @ svg class="pie-chart"
530
+ @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");Blob sql-chart"
531
+ @ HQuery /* SQo_url(&url);url_rese_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
532
+ , "Sunday"
533
+ };
534
+
535
+ ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Ge
--- a/src/statrep.c
+++ b/src/statrep.c
@@ -0,0 +1,535 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
--- a/src/statrep.c
+++ b/src/statrep.c
@@ -0,0 +1,535 @@
1 eea"zT
2 ;
3 @ claT
4 ;
5 @ class='lastchngTeble'nameeea"zTuserlist","tT}
6 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
7 style_footer();
8 }
9 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
10 ;
11 @ class='lastchngTable'nameeea"zTuserlist","tT}
12 style_footer();
13 }
14 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
15 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
16 "ELSE 'ERROR' END;"svg class="pie-chart"
17 @ svg class="pie-chart"
18 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
19 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
20 , "Sunday"
21 };
22
23 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
24 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
25 ;
26 @ claT
27 ;
28 @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
29 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
30 "ELSE 'ERROR' END;"svg class="pie-chart"
31 @ svg class="pie-chart"
32 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
33 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
34 , "Sunday"
35 };
36
37 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
38 ;
39 @ claT
40 e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
41 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
42 "ELSE 'ERROR' END;"svg class="pie-chart"
43 @ svg class="pie-chart"
44 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
45 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
46 , "Sunday"
47 };
48
49 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
50 ;
51 @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
52 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
53 "ELSE 'ERROR' END;"svg class="pie-chart"
54 @ svg class="pie-chart"
55 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
56 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
57 , "Sunday"
58 };
59
60 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
61 ;
62 element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
63 ;
64 @ claT
65 ;
66 @ class='lastchngTeble'nameeea"zTuserlist","tT}
67 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
68 style_footer();
69 }
70 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
71 ;
72 @ class='lastchngTable'nameeea"zTuserlist","tT}
73 style_footer();
74 }
75 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
76 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
77 "ELSE 'ERROR' END;"svg class="pie-chart"
78 @ svg class="pie-chart"
79 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
80 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
81 , "Sunday"
82 };
83
84 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
85 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
86 ;
87 @ claT
88 ;
89 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
90 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
91 azYear[n] = fossil_strdup(,0));
92 azYear[n+1] = azYear[n];
93 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
94 ;
95 @ claT
96 ;
97 @ class='lastchngTeble'nameeea"zTuserlist","tT}
98 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
99 style_footer();
100 }
101 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
102 ;
103 @ class='lastchngTable'nameeea"zTuserlist","tT}
104 style_footer();
105 }
106 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
107 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
108 "ELSE 'ERROR' END;"svg class="pie-chart"
109 @ svg class="pie-chart"
110 @ HQuery url;/* RL for eventbranch linksurl_initialize(&url, "reports");
111 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
112 , "Sunday"
113 };
114
115 ;mtime %% 7mt/*
116 ** A helper for the /reports family of pages which prints out a menu
117 ** of links for the various type=XXX flags. zCurrentViewName must be
118 ** the name/value of the 'view' parameter which is in effect at the
119 ** time this is called. e.g. if called from the 'byuser' view then
120 ** zCurrentViewName must be "byuser". Any URL parameters which need to
121 ** be added to the generated URLs should be passed in zParam. The
122 ** caller is expected to have already encoded any zParam in event_types_menu(c><svg</centre>center><svg</centre> "Thursday",
123 , "Sunday"
124 };
125
126 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
127 ;
128 @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
129 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
130 "ELSE 'ERROR' END;"svg class="pie-chart"
131 @ svg class="pie-chart"uery url;/* URL for various branch linksurl_initialize(&url, "reports");
132 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>csnter><svg</centre> "Thursday",
133 , "Sunday"
134 };
135
136 ;mtime %% 7mtime %% 7Mg.zTop,MoTuesWednThur5Sunday eea"zT
137 ;
138 element(zMenuName, zMenuNameinsass="pie-chart"
139 @ HQuery url;/*ci'>checkin"2;"
140 "UPDATE piechareea"zT
141 ;
142 @ claT
143 ;
144 even class='lastchngTable'nameeea"zTuserlist","tT}
145 style_footer();e'>event; @ class='lastchngTeble'nameeea"zTuserlist","tT}
146 style_footer();
147 }
148 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
149 ;
150 @ class='lastchngTable'nameeea"zTuserlist","tT}
151 style_footer();
152 }
153 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
154 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
155 "ELSE 'ERROR' END;"svg class="pie-chart"
156 @ svg class="pie-chart"
157 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
158 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
159 , "Sunday"
160 };
161
162 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
163 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
164 ;
165 @ claT
166 ;
167 @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
168 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
169 "ELSE 'ERROR' END;"svg class="pie-chart"
170 @ svg class="pie-chart"
171 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
172 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
173 , "Sunday"
174 };
175
176 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
177 ;
178 @ claT
179 e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
180 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
181 "ELSE 'ERROR' END;"svg class="pie-chart"
182 @ svg class="pie-chart"
183 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
184 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
185 , "Sunday"
186 };
187
188 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
189 ;
190 @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
191 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
192 "ELSE 'ERROR' END;"svg class="pie-chart"
193 @ svg class="pie-chart"
194 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
195 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
196 , "Sunday"
197 };
198
199 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
200 ;
201 element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
202 ;
203 @ claT
204 ;
205 @ class='lastchngTeble'nameeea"zTuserlist","tT}
206 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
207 style_footer();
208 }
209 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
210 ;
211 @ class='lastchngTable'nameeea"zTuserlist","tT}
212 style_footer();
213 }
214 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
215 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
216 "ELSE 'ERROR' END;"svg class="pie-chart"
217 @ svg class="pie-chart"
218 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
219 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
220 , "Sunday"
221 };
222
223 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
224 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
225 ;
226 @ claT
227 ;
228 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
229 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
230 azYear[n] = fossil_strdup(,0));
231 azYear[n+1] = azYear[n];
232 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
233 ;
234 @ claT
235 ;
236 @ class='lastchngTeble'nameeea"zTuserlist","tT}
237 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
238 style_footer();
239 }
240 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
241 ;
242 @ class='lastchngTable'nameeea"zTuserlist","tT}
243 style_footer();
244 }
245 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
246 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
247 "ELSE 'ERRsR' END;"svg class="pie-chart"
248 @ svg class="pie-chart"
249 @ Hg.zTop,HQuery url;/* RL for various branch linksurl_initialize(&url, "reports");
250 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
251 , "Sunday"
252 };
253
254 ;mtime %% 7mt/*
255 ** A helper for the /reports family of pages which prints out a menu
256 ** of links for the various type=XXX flags. zCurrentViewName must be
257 ** the name/value of the 'view' parameter which is in effect at the
258 ** time this is called. e.g. if called from the 'byuser' view then
259 ** zCurrentViewName must be "byuser". Any URL parameters which need to
260 ** be added to the generated URLs should be passed in zParam. The
261 ** caller is expected to have already encoded any zParam in event_types_menu(c><svg</centre>center><svg</centre> "Thursday",
262 , "Sunday"
263 };
264
265 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
266 ;
267 @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
268 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
269 "ELSE 'ERROR' END;"svg class="pie-chart"
270 @ svg class="pie-chart"uery url;/* URL for various branch linksurl_initialize(&url, "reports");
271 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
272 , "Sunday"
273 };
274
275 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
276 ;
277 element(zMenuName, zMenuNameinsass="pie-chart"
278 @ HQuery url;/*ci'>checkin"2;"
279 "UPDATE piechareea"zT
280 ;
281 @ claT
282 ;
283 @ class='lastchngTeble'nameeea"zTuserlist","tT}
284 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
285 style_footer();
286 }
287 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
288 ;
289 @ class='lastchngTable'nameeea"zTuserlist","tT}
290 style_footer();
291 }
292 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
293 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
294 "ELSE 'ERROR' END;"svg class="pie-chart"
295 @ svg class="pie-chart"
296 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
297 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
298 , "Sunday"
299 };
300
301 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
302 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
303 ;
304 @ claT
305 ;
306 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
307 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
308 azYear[n] = fossil_strdup(,0));
309 azYear[n+1] = azYear[n];
310 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
311 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
312 style_footer();
313 }
314 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
315 ;
316 @ class='lastchngTable'nameeea"zTuserlist","tT}
317 style_footer();
318 }
319 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
320 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
321 "ELSE 'ERROR' END;"svg class="pie-chart"
322 @ svg class="pie-chart"
323 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
324 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
325 , "Sunday"
326 };
327
328 ;mtime %% 7mtimand not empty
329 ** class="pie-chart"slist","tT}
330 style_feeaclass='lastchngTable'nameeea"zTuserlist","tT}
331 style_footer();
332 }
333 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
334 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
335 "ELSE 'ERROR' END;"svg class="pie-chart"
336 @ svg class="pie-chart"
337 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");Blob sql-chart"
338 @ HQuery /* SQo_url(&url);url_rese_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
339 , "Sunday"
340 };
341
342 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
343 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
344 ;
345 @ claT
346 ;
347 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
348 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
349 azYear[n] = fossil_strdup(,0));
350 azYear[n+1] = azYear[n];
351 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
352 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
353 style_footer();
354 }
355 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
356 ;
357 @ class='lastchngTable'nameeea"zTuserlist","tT}
358 unday"
359 } NULL );
360 header, "s) by yearL for various branchmtime %% 7mtime %% 7MoTuesWedme=TABLE piechart(amt,labelpie);
361 blob_append_sql(&sqlr5Sunday eea"zT
362 ;
363 @e><htimeframe,a"/center><svg/centeea"zincludeMonth if( PB("pie") ){ cgi_query_paramete
364 " ySizeArraySizeArraySizeeea"zT
365 ;
366 @ claT
367 ;
368 @"zT
369 ;
370 @ claT
371 ;
372 @ 'lastchngTeble'name claT
373 ;
374 @ class='lastchngTeble'nameeea"zTuserlist","tT}
375 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
376 style_footer();Usereea"zT
377 ;
378 @ claT
379 ;
380 @ class='lastchngTeble'nameeea"zTuserlist","tT}
381 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
382 style_footer();
383 }
384 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
385 ;
386 @ class='lastchngTable'nameeea"zTuserlist","tT}
387 style_footer();
388 }
389 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
390 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
391 "ELSE 'ERROR' END;"svg class="pie-chart"
392 @ svg class="pie-chart"
393 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
394 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
395 , "Sunday"
396 };
397
398 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
399 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
400 ;
401 @ claT
402 ;
403 @ ce><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
404 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
405 "ELSE 'ERROR' END;"svg class="pie-chart"
406 @ svg class="pie-chart"
407 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
408 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
409 , "Sunday"
410 };
411
412 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
413 ;
414 @ claT
415 e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
416 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
417 "ELSE 'ERROR' END;"svg class="pie-chart"
418 @ svg class="pie-chart"
419 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
420 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
421 , "Sunday"
422 };
423
424 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
425 ;
426 @e><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
427 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
428 "ELSE 'ERROR' END;"svg class="pie-chart"
429 @ svg class="pie-chart"
430 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
431 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
432 , "Sunday"
433 };
434
435 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday eea"zT
436 ;
437 element(zMenuName, zMenuName, "%s url_render(pUrl, zParBy File", ny TypeelpiechartTABLE peea"zT
438 ;
439 @ claT
440 ;
441 @ class='lastchngTeble'nameeea"zTuserlist","tT}
442 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
443 style_footer();
444 }
445 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
446 ;
447 @ class='lastchngTable'nameeea"zTuserlist","tT}
448 style_footer();
449 }
450 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
451 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
452 "ELSE 'ERROR' END;"svg class="pie-chart"
453 @ svg class="pie-chart"
454 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
455 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
456 , "Sunday"
457 };
458
459 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Generate a submenu element witrep_submenu(
460 HQuery *pUrl,/* Base URLe><hreea<br>?name=Teea"zT
461 ;
462 @ claT
463 ;
464 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
465 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
466 azYear[n] = fossil_strdup(,0));
467 azYear[n+1] = azYear[n];
468 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) zYear = azYear[0];zT
469 ;
470 @ claT
471 ;
472 @ class='lastchngTeble'nameeea"zTuserlist","tT}
473 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
474 style_footer();
475 }
476 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
477 ;
478 @ class='lastchngTable'nameeea"zTuserlist","tT}
479 style_footer();
480 }
481 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
482 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
483 "ELSE 'ERROR' END;"svg class="pie-chart"
484 @ svg class="pie-chart"
485 @ HQuery url;/* RL for various branch linksurl_initialize(&url, "reports");
486 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
487 , "Sunday"
488 };
489
490 ;mtime %% 7mt/*
491 ** A helper for the /reports family of pages which prints out a menu
492 ** of links for the various type=XXX flags. zCurrentViewName must be
493 ** the name/value of the 'view' parameter which is in effect at the
494 ** time this is called. e.g. if called from the 'byuser' view then
495 ** zCurrentViewName musa<br>?name=Teea"zT
496 ;g.zTop,;
497 @ claT
498 ;
499 @ ce>4) AS yy ORDER BY y DESC", zUserName) ){
500 azYear = fossil_realloc(azYear, sizeof(char*)*(n+2));
501 azYear[n] = fossil_strdup(,0));
502 azYear[n+1] = azYear[n];
503 if( !isValidYear && fossil_strcmp(zYear,azYear[n])==0 ) ='lastchngTeble'nameeea"zTuserlist","tT}
504 style_footer(); @ class='lastchngTeble'nameeea"zTuserlist","tT}
505 style_footer();
506 }
507 svg class="pie-chart"svg class="pie-chart"ArraySizeArraySizeArraySizeeea"zT
508 ;
509 @ class='lastchngTable'nameeea"zTuserlist","tT}
510 style_footer();
511 }
512 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
513 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
514 "ELSE 'ERROR' END;"svg class="pie-chart"
515 @ svg class="pie-chart"
516 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");
517 cgi_query_parameters_to_url(&url);url_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
518 , "Sunday"
519 };
520
521 ;mtime %% 7mtimand not empty
522 ** class="pie-chart"slist","tT}
523 style_feeaclass='lastchngTable'nameeea"zTuserlist","tT}
524 style_footer();
525 }
526 center><svg/centre><hreea"/center><svg/centre><hreea<br>?name=TABLE piechart(amt,labelpiechartTABLE piechart(amt,labelpiechart)"2;"
527 "UPDATE piechart SEWHEN 5 THEN 'Friday'"
528 "ELSE 'ERROR' END;"svg class="pie-chart"
529 @ svg class="pie-chart"
530 @ HQuery url;/* URL for various branch linksurl_initialize(&url, "reports");Blob sql-chart"
531 @ HQuery /* SQo_url(&url);url_rese_reset(&urlcenter><svg</centre>center><svg</centre> "Thursday",
532 , "Sunday"
533 };
534
535 ;mtime %% 7mtime %% 7MoTuesWednThur5Sunday Ge
+1 -1
--- src/style.c
+++ src/style.c
@@ -354,11 +354,11 @@
354354
355355
#if INTERFACE
356356
/* Allowed parameters for style_adunit() */
357357
#define ADUNIT_OFF 0x0001 /* Do not allow ads on this page */
358358
#define ADUNIT_RIGHT_OK 0x0002 /* Right-side vertical ads ok here */
359
-#endif
359
+#endif
360360
361361
/*
362362
** Various page implementations can invoke this interface to let the
363363
** style manager know what kinds of ads are appropriate for this page.
364364
*/
365365
--- src/style.c
+++ src/style.c
@@ -354,11 +354,11 @@
354
355 #if INTERFACE
356 /* Allowed parameters for style_adunit() */
357 #define ADUNIT_OFF 0x0001 /* Do not allow ads on this page */
358 #define ADUNIT_RIGHT_OK 0x0002 /* Right-side vertical ads ok here */
359 #endif
360
361 /*
362 ** Various page implementations can invoke this interface to let the
363 ** style manager know what kinds of ads are appropriate for this page.
364 */
365
--- src/style.c
+++ src/style.c
@@ -354,11 +354,11 @@
354
355 #if INTERFACE
356 /* Allowed parameters for style_adunit() */
357 #define ADUNIT_OFF 0x0001 /* Do not allow ads on this page */
358 #define ADUNIT_RIGHT_OK 0x0002 /* Right-side vertical ads ok here */
359 #endif
360
361 /*
362 ** Various page implementations can invoke this interface to let the
363 ** style manager know what kinds of ads are appropriate for this page.
364 */
365
+1 -1
--- src/tag.c
+++ src/tag.c
@@ -269,11 +269,11 @@
269269
}
270270
g.markPrivate = content_is_private(rid);
271271
zValue = g.argc==5 ? g.argv[4] : 0;
272272
db_begin_transaction();
273273
tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
274
- db_end_transaction(0);
274
+ db_end_transaction(0);
275275
}
276276
277277
/*
278278
** Add a control record to the repository that either creates
279279
** or cancels a tag.
280280
--- src/tag.c
+++ src/tag.c
@@ -269,11 +269,11 @@
269 }
270 g.markPrivate = content_is_private(rid);
271 zValue = g.argc==5 ? g.argv[4] : 0;
272 db_begin_transaction();
273 tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
274 db_end_transaction(0);
275 }
276
277 /*
278 ** Add a control record to the repository that either creates
279 ** or cancels a tag.
280
--- src/tag.c
+++ src/tag.c
@@ -269,11 +269,11 @@
269 }
270 g.markPrivate = content_is_private(rid);
271 zValue = g.argc==5 ? g.argv[4] : 0;
272 db_begin_transaction();
273 tag_insert(zTag, tagtype, zValue, -1, 0.0, rid);
274 db_end_transaction(0);
275 }
276
277 /*
278 ** Add a control record to the repository that either creates
279 ** or cancels a tag.
280
+2 -2
--- src/th_main.c
+++ src/th_main.c
@@ -391,15 +391,15 @@
391391
int argc,
392392
const char **argv,
393393
int *argl
394394
){
395395
int rc = 0;
396
- char const * zArg;
396
+ const char *zArg;
397397
if( argc!=2 ){
398398
return Th_WrongNumArgs(interp, "hasfeature STRING");
399399
}
400
- zArg = (char const*)argv[1];
400
+ zArg = (const char *)argv[1];
401401
if(NULL==zArg){
402402
/* placeholder for following ifdefs... */
403403
}
404404
#if defined(FOSSIL_ENABLE_SSL)
405405
else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
406406
--- src/th_main.c
+++ src/th_main.c
@@ -391,15 +391,15 @@
391 int argc,
392 const char **argv,
393 int *argl
394 ){
395 int rc = 0;
396 char const * zArg;
397 if( argc!=2 ){
398 return Th_WrongNumArgs(interp, "hasfeature STRING");
399 }
400 zArg = (char const*)argv[1];
401 if(NULL==zArg){
402 /* placeholder for following ifdefs... */
403 }
404 #if defined(FOSSIL_ENABLE_SSL)
405 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
406
--- src/th_main.c
+++ src/th_main.c
@@ -391,15 +391,15 @@
391 int argc,
392 const char **argv,
393 int *argl
394 ){
395 int rc = 0;
396 const char *zArg;
397 if( argc!=2 ){
398 return Th_WrongNumArgs(interp, "hasfeature STRING");
399 }
400 zArg = (const char *)argv[1];
401 if(NULL==zArg){
402 /* placeholder for following ifdefs... */
403 }
404 #if defined(FOSSIL_ENABLE_SSL)
405 else if( 0 == fossil_strnicmp( zArg, "ssl\0", 4 ) ){
406
+3 -684
--- src/timeline.c
+++ src/timeline.c
@@ -360,20 +360,20 @@
360360
}
361361
}
362362
}
363363
if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
364364
int nParent = 0;
365
- int aParent[32];
365
+ int aParent[GR_MAX_RAIL];
366366
int gidx;
367367
static Stmt qparent;
368368
db_static_prepare(&qparent,
369369
"SELECT pid FROM plink"
370370
" WHERE cid=:rid AND pid NOT IN phantom"
371371
" ORDER BY isprim DESC /*sort*/"
372372
);
373373
db_bind_int(&qparent, ":rid", rid);
374
- while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
374
+ while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){
375375
aParent[nParent++] = db_column_int(&qparent, 0);
376376
}
377377
db_reset(&qparent);
378378
gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
379379
zUuid, isLeaf);
@@ -1556,11 +1556,11 @@
15561556
}
15571557
}
15581558
if( P("showsql") ){
15591559
@ <blockquote>%h(blob_sql_text(&sql))</blockquote>
15601560
}
1561
- if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID;
1561
+ if( P("showid") ) tmFlags |= TIMELINE_SHOWRID;
15621562
blob_zero(&sql);
15631563
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
15641564
@ <h2>%b(&desc)</h2>
15651565
blob_reset(&desc);
15661566
www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2044,688 +2044,7 @@
20442044
const char *zUuid = db_column_text(&q, 0);
20452045
@ <li>
20462046
@ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
20472047
}
20482048
db_finalize(&q);
2049
- style_footer();
2050
-}
2051
-
2052
-
2053
-/*
2054
-** Used by stats_report_xxxxx() to remember which type of events
2055
-** to show. Populated by stats_report_init_view() and holds the
2056
-** return value of that function.
2057
-*/
2058
-static int statsReportType = 0;
2059
-
2060
-/*
2061
-** Set by stats_report_init_view() to one of the y=XXXX values
2062
-** accepted by /timeline?y=XXXX.
2063
-*/
2064
-static const char *statsReportTimelineYFlag = NULL;
2065
-
2066
-/*
2067
-** Creates a TEMP VIEW named v_reports which is a wrapper around the
2068
-** EVENT table filtered on event.type. It looks for the request
2069
-** parameter 'type' (reminder: we "should" use 'y' for consistency
2070
-** with /timeline, but /reports uses 'y' for the year) and expects it
2071
-** to contain one of the conventional values from event.type or the
2072
-** value "all", which is treated as equivalent to "*". By default (if
2073
-** no 'y' is specified), "*" is assumed (that is also the default for
2074
-** invalid/unknown filter values). That 'y' filter is the one used for
2075
-** the event list. Note that a filter of "*" or "all" is equivalent to
2076
-** querying against the full event table. The view, however, adds an
2077
-** abstraction level to simplify the implementation code for the
2078
-** various /reports pages.
2079
-**
2080
-** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
2081
-** filter it applies, or '*' if no filter is applied (i.e. if "all" is
2082
-** used).
2083
-*/
2084
-static int stats_report_init_view(){
2085
- const char *zType = PD("type","*"); /* analog to /timeline?y=... */
2086
- const char *zRealType = NULL; /* normalized form of zType */
2087
- int rc = 0; /* result code */
2088
- assert( !statsReportType && "Must not be called more than once." );
2089
- switch( (zType && *zType) ? *zType : 0 ){
2090
- case 'c':
2091
- case 'C':
2092
- zRealType = "ci";
2093
- rc = *zRealType;
2094
- break;
2095
- case 'e':
2096
- case 'E':
2097
- zRealType = "e";
2098
- rc = *zRealType;
2099
- break;
2100
- case 'g':
2101
- case 'G':
2102
- zRealType = "g";
2103
- rc = *zRealType;
2104
- break;
2105
- case 't':
2106
- case 'T':
2107
- zRealType = "t";
2108
- rc = *zRealType;
2109
- break;
2110
- case 'w':
2111
- case 'W':
2112
- zRealType = "w";
2113
- rc = *zRealType;
2114
- break;
2115
- default:
2116
- rc = '*';
2117
- break;
2118
- }
2119
- assert(0 != rc);
2120
- if(zRealType){
2121
- statsReportTimelineYFlag = zRealType;
2122
- db_multi_exec("CREATE TEMP VIEW v_reports AS "
2123
- "SELECT * FROM event WHERE type GLOB %Q",
2124
- zRealType);
2125
- }else{
2126
- statsReportTimelineYFlag = "a";
2127
- db_multi_exec("CREATE TEMP VIEW v_reports AS "
2128
- "SELECT * FROM event");
2129
- }
2130
- return statsReportType = rc;
2131
-}
2132
-
2133
-/*
2134
-** Returns a string suitable (for a given value of suitable) for
2135
-** use in a label with the header of the /reports pages, dependent
2136
-** on the 'type' flag. See stats_report_init_view().
2137
-** The returned bytes are static.
2138
-*/
2139
-static const char *stats_report_label_for_type(){
2140
- assert( statsReportType && "Must call stats_report_init_view() first." );
2141
- switch( statsReportType ){
2142
- case 'c':
2143
- return "checkins";
2144
- case 'e':
2145
- return "events";
2146
- case 'w':
2147
- return "wiki changes";
2148
- case 't':
2149
- return "ticket changes";
2150
- case 'g':
2151
- return "tag changes";
2152
- default:
2153
- return "all types";
2154
- }
2155
-}
2156
-
2157
-/*
2158
-** A helper for the /reports family of pages which prints out a menu
2159
-** of links for the various type=XXX flags. zCurrentViewName must be
2160
-** the name/value of the 'view' parameter which is in effect at the
2161
-** time this is called. e.g. if called from the 'byuser' view then
2162
-** zCurrentViewName must be "byuser". Any URL parameters which need to
2163
-** be added to the generated URLs should be passed in zParam. The
2164
-** caller is expected to have already encoded any zParam in the %T or
2165
-** %t encoding. */
2166
-static void stats_report_event_types_menu(const char *zCurrentViewName,
2167
- const char *zParam){
2168
- char *zTop;
2169
- if(zParam && !*zParam){
2170
- zParam = NULL;
2171
- }
2172
- zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2173
- zParam ? "&" : "", zParam);
2174
- cgi_printf("<div>");
2175
- cgi_printf("<span>Types:</span> ");
2176
- if('*' == statsReportType){
2177
- cgi_printf(" <strong>all</strong>", zTop);
2178
- }else{
2179
- cgi_printf(" <a href='%s'>all</a>", zTop);
2180
- }
2181
- if('c' == statsReportType){
2182
- cgi_printf(" <strong>checkins</strong>", zTop);
2183
- }else{
2184
- cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
2185
- }
2186
- if('e' == statsReportType){
2187
- cgi_printf(" <strong>events</strong>", zTop);
2188
- }else{
2189
- cgi_printf(" <a href='%s&type=e'>events</a>", zTop);
2190
- }
2191
- if( 't' == statsReportType ){
2192
- cgi_printf(" <strong>tickets</strong>", zTop);
2193
- }else{
2194
- cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
2195
- }
2196
- if( 'g' == statsReportType ){
2197
- cgi_printf(" <strong>tags</strong>", zTop);
2198
- }else{
2199
- cgi_printf(" <a href='%s&type=g'>tags</a>", zTop);
2200
- }
2201
- if( 'w' == statsReportType ){
2202
- cgi_printf(" <strong>wiki</strong>", zTop);
2203
- }else{
2204
- cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop);
2205
- }
2206
- fossil_free(zTop);
2207
- cgi_printf("</div>");
2208
-}
2209
-
2210
-
2211
-/*
2212
-** Helper for stats_report_by_month_year(), which generates a list of
2213
-** week numbers. zTimeframe should be either a timeframe in the form YYYY
2214
-** or YYYY-MM.
2215
-*/
2216
-static void stats_report_output_week_links(const char *zTimeframe){
2217
- Stmt stWeek = empty_Stmt;
2218
- char yearPart[5] = {0,0,0,0,0};
2219
- memcpy(yearPart, zTimeframe, 4);
2220
- db_prepare(&stWeek,
2221
- "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
2222
- "count(*) AS n, "
2223
- "substr(date(mtime),1,%d) AS ym "
2224
- "FROM v_reports "
2225
- "WHERE ym=%Q AND mtime < current_timestamp "
2226
- "GROUP BY wk ORDER BY wk",
2227
- strlen(zTimeframe),
2228
- zTimeframe);
2229
- while( SQLITE_ROW == db_step(&stWeek) ){
2230
- const char *zWeek = db_column_text(&stWeek,0);
2231
- const int nCount = db_column_int(&stWeek,1);
2232
- cgi_printf("<a href='%s/timeline?"
2233
- "yw=%t-%t&n=%d&y=%s'>%s</a>",
2234
- g.zTop, yearPart, zWeek,
2235
- nCount, statsReportTimelineYFlag, zWeek);
2236
- }
2237
- db_finalize(&stWeek);
2238
-}
2239
-
2240
-/*
2241
-** Implements the "byyear" and "bymonth" reports for /reports.
2242
-** If includeMonth is true then it generates the "bymonth" report,
2243
-** else the "byyear" report. If zUserName is not NULL and not empty
2244
-** then the report is restricted to events created by the named user
2245
-** account.
2246
-*/
2247
-static void stats_report_by_month_year(char includeMonth,
2248
- char includeWeeks,
2249
- const char *zUserName){
2250
- Stmt query = empty_Stmt;
2251
- int nRowNumber = 0; /* current TR number */
2252
- int nEventTotal = 0; /* Total event count */
2253
- int rowClass = 0; /* counter for alternating
2254
- row colors */
2255
- Blob sql = empty_blob; /* SQL */
2256
- const char *zTimeLabel = includeMonth ? "Year/Month" : "Year";
2257
- char zPrevYear[5] = {0}; /* For keeping track of when
2258
- we change years while looping */
2259
- int nEventsPerYear = 0; /* Total event count for the
2260
- current year */
2261
- char showYearTotal = 0; /* Flag telling us when to show
2262
- the per-year event totals */
2263
- Blob header = empty_blob; /* Page header text */
2264
- int nMaxEvents = 1; /* for calculating length of graph
2265
- bars. */
2266
- int iterations = 0; /* number of weeks/months we iterate
2267
- over */
2268
- stats_report_init_view();
2269
- stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
2270
- blob_appendf(&header, "Timeline Events (%s) by year%s",
2271
- stats_report_label_for_type(),
2272
- (includeMonth ? "/month" : ""));
2273
- blob_append_sql(&sql,
2274
- "SELECT substr(date(mtime),1,%d) AS timeframe, "
2275
- "count(*) AS eventCount "
2276
- "FROM v_reports ",
2277
- includeMonth ? 7 : 4);
2278
- if(zUserName&&*zUserName){
2279
- blob_append_sql(&sql, " WHERE user=%Q ", zUserName);
2280
- blob_appendf(&header," for user %q", zUserName);
2281
- }
2282
- blob_append(&sql,
2283
- " GROUP BY timeframe"
2284
- " ORDER BY timeframe DESC",
2285
- -1);
2286
- db_prepare(&query, "%s", blob_sql_text(&sql));
2287
- blob_reset(&sql);
2288
- @ <h1>%b(&header)</h1>
2289
- @ <table class='statistics-report-table-events' border='0' cellpadding='2'
2290
- @ cellspacing='0' id='statsTable'>
2291
- @ <thead>
2292
- @ <th>%s(zTimeLabel)</th>
2293
- @ <th>Events</th>
2294
- @ <th width='90%%'><!-- relative commits graph --></th>
2295
- @ </thead><tbody>
2296
- blob_reset(&header);
2297
- /*
2298
- Run the query twice. The first time we calculate the maximum
2299
- number of events for a given row. Maybe someone with better SQL
2300
- Fu can re-implement this with a single query.
2301
- */
2302
- while( SQLITE_ROW == db_step(&query) ){
2303
- const int nCount = db_column_int(&query, 1);
2304
- if(nCount>nMaxEvents){
2305
- nMaxEvents = nCount;
2306
- }
2307
- ++iterations;
2308
- }
2309
- db_reset(&query);
2310
- while( SQLITE_ROW == db_step(&query) ){
2311
- const char *zTimeframe = db_column_text(&query, 0);
2312
- const int nCount = db_column_int(&query, 1);
2313
- int nSize = nCount
2314
- ? (int)(100 * nCount / nMaxEvents)
2315
- : 1;
2316
- showYearTotal = 0;
2317
- if(!nSize) nSize = 1;
2318
- if(includeMonth){
2319
- /* For Month/year view, add a separator for each distinct year. */
2320
- if(!*zPrevYear ||
2321
- (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
2322
- showYearTotal = *zPrevYear;
2323
- if(showYearTotal){
2324
- rowClass = ++nRowNumber % 2;
2325
- @ <tr class='row%d(rowClass)'>
2326
- @ <td></td>
2327
- @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2328
- @</tr>
2329
- }
2330
- nEventsPerYear = 0;
2331
- memcpy(zPrevYear,zTimeframe,4);
2332
- rowClass = ++nRowNumber % 2;
2333
- @ <tr class='row%d(rowClass)'>
2334
- @ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th>
2335
- @ </tr>
2336
- }
2337
- }
2338
- rowClass = ++nRowNumber % 2;
2339
- nEventTotal += nCount;
2340
- nEventsPerYear += nCount;
2341
- @<tr class='row%d(rowClass)'>
2342
- @ <td>
2343
- if(includeMonth){
2344
- cgi_printf("<a href='%s/timeline?"
2345
- "ym=%t&n=%d&y=%s",
2346
- g.zTop, zTimeframe, nCount,
2347
- statsReportTimelineYFlag );
2348
- /* Reminder: n=nCount is not actually correct for bymonth unless
2349
- that was the only user who caused events.
2350
- */
2351
- if( zUserName && *zUserName ){
2352
- cgi_printf("&u=%t", zUserName);
2353
- }
2354
- cgi_printf("' target='_new'>%s</a>",zTimeframe);
2355
- }else {
2356
- cgi_printf("<a href='?view=byweek&y=%s&type=%c",
2357
- zTimeframe, (char)statsReportType);
2358
- if(zUserName && *zUserName){
2359
- cgi_printf("&u=%t", zUserName);
2360
- }
2361
- cgi_printf("'>%s</a>", zTimeframe);
2362
- }
2363
- @ </td><td>%d(nCount)</td>
2364
- @ <td>
2365
- @ <div class='statistics-report-graph-line'
2366
- @ style='width:%d(nSize)%%;'>&nbsp;</div>
2367
- @ </td>
2368
- @</tr>
2369
- if(includeWeeks){
2370
- /* This part works fine for months but it terribly slow (4.5s on my PC),
2371
- so it's only shown for by-year for now. Suggestions/patches for
2372
- a better/faster layout are welcomed. */
2373
- @ <tr class='row%d(rowClass)'>
2374
- @ <td colspan='2' class='statistics-report-week-number-label'>Week #:</td>
2375
- @ <td class='statistics-report-week-of-year-list'>
2376
- stats_report_output_week_links(zTimeframe);
2377
- @ </td></tr>
2378
- }
2379
-
2380
- /*
2381
- Potential improvement: calculate the min/max event counts and
2382
- use percent-based graph bars.
2383
- */
2384
- }
2385
- db_finalize(&query);
2386
- if(includeMonth && !showYearTotal && *zPrevYear){
2387
- /* Add final year total separator. */
2388
- rowClass = ++nRowNumber % 2;
2389
- @ <tr class='row%d(rowClass)'>
2390
- @ <td></td>
2391
- @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2392
- @</tr>
2393
- }
2394
- @ </tbody></table>
2395
- if(nEventTotal){
2396
- const char *zAvgLabel = includeMonth ? "month" : "year";
2397
- int nAvg = iterations ? (nEventTotal/iterations) : 0;
2398
- @ <br><div>Total events: %d(nEventTotal)
2399
- @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2400
- @ </div>
2401
- }
2402
- if( !includeMonth ){
2403
- output_table_sorting_javascript("statsTable","tnx",-1);
2404
- }
2405
-}
2406
-
2407
-/*
2408
-** Implements the "byuser" view for /reports.
2409
-*/
2410
-static void stats_report_by_user(){
2411
- Stmt query = empty_Stmt;
2412
- int nRowNumber = 0; /* current TR number */
2413
- int nEventTotal = 0; /* Total event count */
2414
- int rowClass = 0; /* counter for alternating
2415
- row colors */
2416
- int nMaxEvents = 1; /* max number of events for
2417
- all rows. */
2418
- stats_report_init_view();
2419
- stats_report_event_types_menu("byuser", NULL);
2420
- db_prepare(&query,
2421
- "SELECT user, "
2422
- "COUNT(*) AS eventCount "
2423
- "FROM v_reports "
2424
- "GROUP BY user ORDER BY eventCount DESC");
2425
- @ <h1>Timeline Events
2426
- @ (%s(stats_report_label_for_type())) by User</h1>
2427
- @ <table class='statistics-report-table-events' border='0'
2428
- @ cellpadding='2' cellspacing='0' id='statsTable'>
2429
- @ <thead><tr>
2430
- @ <th>User</th>
2431
- @ <th>Events</th>
2432
- @ <th width='90%%'><!-- relative commits graph --></th>
2433
- @ </tr></thead><tbody>
2434
- while( SQLITE_ROW == db_step(&query) ){
2435
- const int nCount = db_column_int(&query, 1);
2436
- if(nCount>nMaxEvents){
2437
- nMaxEvents = nCount;
2438
- }
2439
- }
2440
- db_reset(&query);
2441
- while( SQLITE_ROW == db_step(&query) ){
2442
- const char *zUser = db_column_text(&query, 0);
2443
- const int nCount = db_column_int(&query, 1);
2444
- int nSize = nCount
2445
- ? (int)(100 * nCount / nMaxEvents)
2446
- : 0;
2447
- if(!nCount) continue /* arguable! Possible? */;
2448
- else if(!nSize) nSize = 1;
2449
- rowClass = ++nRowNumber % 2;
2450
- nEventTotal += nCount;
2451
- @<tr class='row%d(rowClass)'>
2452
- @ <td>
2453
- @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2454
- @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td>
2455
- @ <td>
2456
- @ <div class='statistics-report-graph-line'
2457
- @ style='width:%d(nSize)%%;'>&nbsp;</div>
2458
- @ </td>
2459
- @</tr>
2460
- /*
2461
- Potential improvement: calculate the min/max event counts and
2462
- use percent-based graph bars.
2463
- */
2464
- }
2465
- @ </tbody></table>
2466
- db_finalize(&query);
2467
- output_table_sorting_javascript("statsTable","tkx",2);
2468
-}
2469
-
2470
-/*
2471
-** Implements the "byweekday" view for /reports.
2472
-*/
2473
-static void stats_report_day_of_week(){
2474
- Stmt query = empty_Stmt;
2475
- int nRowNumber = 0; /* current TR number */
2476
- int nEventTotal = 0; /* Total event count */
2477
- int rowClass = 0; /* counter for alternating
2478
- row colors */
2479
- int nMaxEvents = 1; /* max number of events for
2480
- all rows. */
2481
- static const char *const daysOfWeek[] = {
2482
- "Monday", "Tuesday", "Wednesday", "Thursday",
2483
- "Friday", "Saturday", "Sunday"
2484
- };
2485
-
2486
- stats_report_init_view();
2487
- stats_report_event_types_menu("byweekday", NULL);
2488
- db_prepare(&query,
2489
- "SELECT cast(mtime %% 7 AS INTEGER) dow, "
2490
- "COUNT(*) AS eventCount "
2491
- "FROM v_reports "
2492
- "GROUP BY dow ORDER BY dow");
2493
- @ <h1>Timeline Events
2494
- @ (%s(stats_report_label_for_type())) by Day of the Week</h1>
2495
- @ <table class='statistics-report-table-events' border='0'
2496
- @ cellpadding='2' cellspacing='0' id='statsTable'>
2497
- @ <thead><tr>
2498
- @ <th>DoW</th>
2499
- @ <th>Day</th>
2500
- @ <th>Events</th>
2501
- @ <th width='90%%'><!-- relative commits graph --></th>
2502
- @ </tr></thead><tbody>
2503
- while( SQLITE_ROW == db_step(&query) ){
2504
- const int nCount = db_column_int(&query, 1);
2505
- if(nCount>nMaxEvents){
2506
- nMaxEvents = nCount;
2507
- }
2508
- }
2509
- db_reset(&query);
2510
- while( SQLITE_ROW == db_step(&query) ){
2511
- const int dayNum =db_column_int(&query, 0);
2512
- const int nCount = db_column_int(&query, 1);
2513
- int nSize = nCount
2514
- ? (int)(100 * nCount / nMaxEvents)
2515
- : 0;
2516
- if(!nCount) continue /* arguable! Possible? */;
2517
- else if(!nSize) nSize = 1;
2518
- rowClass = ++nRowNumber % 2;
2519
- nEventTotal += nCount;
2520
- @<tr class='row%d(rowClass)'>
2521
- @ <td>%d(dayNum)</td>
2522
- @ <td>%s(daysOfWeek[dayNum])</td>
2523
- @ <td>%d(nCount)</td>
2524
- @ <td>
2525
- @ <div class='statistics-report-graph-line'
2526
- @ style='width:%d(nSize)%%;'>&nbsp;</div>
2527
- @ </td>
2528
- @</tr>
2529
- }
2530
- @ </tbody></table>
2531
- db_finalize(&query);
2532
- output_table_sorting_javascript("statsTable","ntnx",1);
2533
-}
2534
-
2535
-
2536
-/*
2537
-** Helper for stats_report_by_month_year(), which generates a list of
2538
-** week numbers. zTimeframe should be either a timeframe in the form YYYY
2539
-** or YYYY-MM.
2540
-*/
2541
-static void stats_report_year_weeks(const char *zUserName){
2542
- const char *zYear = P("y");
2543
- int nYear = zYear ? strlen(zYear) : 0;
2544
- int i = 0;
2545
- Stmt qYears = empty_Stmt;
2546
- char *zDefaultYear = NULL;
2547
- Blob sql = empty_blob;
2548
- int nMaxEvents = 1; /* max number of events for
2549
- all rows. */
2550
- int iterations = 0; /* # of active time periods. */
2551
- stats_report_init_view();
2552
- if(4==nYear){
2553
- Blob urlParams = empty_blob;
2554
- blob_appendf(&urlParams, "y=%T", zYear);
2555
- stats_report_event_types_menu("byweek", blob_str(&urlParams));
2556
- blob_reset(&urlParams);
2557
- }else{
2558
- stats_report_event_types_menu("byweek", NULL);
2559
- }
2560
- blob_append(&sql,
2561
- "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2562
- "FROM v_reports WHERE 1 ", -1);
2563
- if(zUserName&&*zUserName){
2564
- blob_append_sql(&sql,"AND user=%Q ", zUserName);
2565
- }
2566
- blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2567
- db_prepare(&qYears, "%s", blob_sql_text(&sql));
2568
- blob_reset(&sql);
2569
- cgi_printf("Select year: ");
2570
- while( SQLITE_ROW == db_step(&qYears) ){
2571
- const char *zT = db_column_text(&qYears, 0);
2572
- if( i++ ){
2573
- cgi_printf(" ");
2574
- }
2575
- cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2576
- (char)statsReportType);
2577
- if(zUserName && *zUserName){
2578
- cgi_printf("&user=%t",zUserName);
2579
- }
2580
- cgi_printf("'>%s</a>",zT);
2581
- }
2582
- db_finalize(&qYears);
2583
- cgi_printf("<br/>");
2584
- if(!zYear || !*zYear){
2585
- zDefaultYear = db_text("????", "SELECT strftime('%%Y')");
2586
- zYear = zDefaultYear;
2587
- nYear = 4;
2588
- }
2589
- if(4 == nYear){
2590
- Stmt stWeek = empty_Stmt;
2591
- int rowCount = 0;
2592
- int total = 0;
2593
- Blob header = empty_blob;
2594
- blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
2595
- "of %h", stats_report_label_for_type(),
2596
- zYear);
2597
- blob_append_sql(&sql,
2598
- "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
2599
- "count(*) AS n "
2600
- "FROM v_reports "
2601
- "WHERE %Q=substr(date(mtime),1,4) "
2602
- "AND mtime < current_timestamp ",
2603
- zYear);
2604
- if(zUserName&&*zUserName){
2605
- blob_append_sql(&sql, " AND user=%Q ", zUserName);
2606
- blob_appendf(&header," for user %h", zUserName);
2607
- }
2608
- blob_append_sql(&sql, "GROUP BY wk ORDER BY wk DESC");
2609
- cgi_printf("<h1>%h</h1>", blob_str(&header));
2610
- blob_reset(&header);
2611
- cgi_printf("<table class='statistics-report-table-events' "
2612
- "border='0' cellpadding='2' width='100%%' "
2613
- "cellspacing='0' id='statsTable'>");
2614
- cgi_printf("<thead><tr>"
2615
- "<th>Week</th>"
2616
- "<th>Events</th>"
2617
- "<th width='90%%'><!-- relative commits graph --></th>"
2618
- "</tr></thead>"
2619
- "<tbody>");
2620
- db_prepare(&stWeek, "%s", blob_sql_text(&sql));
2621
- blob_reset(&sql);
2622
- while( SQLITE_ROW == db_step(&stWeek) ){
2623
- const int nCount = db_column_int(&stWeek, 1);
2624
- if(nCount>nMaxEvents){
2625
- nMaxEvents = nCount;
2626
- }
2627
- ++iterations;
2628
- }
2629
- db_reset(&stWeek);
2630
- while( SQLITE_ROW == db_step(&stWeek) ){
2631
- const char *zWeek = db_column_text(&stWeek,0);
2632
- const int nCount = db_column_int(&stWeek,1);
2633
- int nSize = nCount
2634
- ? (int)(100 * nCount / nMaxEvents)
2635
- : 0;
2636
- if(!nSize) nSize = 1;
2637
- total += nCount;
2638
- cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2639
- cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d&y=%s",
2640
- g.zTop, zYear, zWeek, nCount,
2641
- statsReportTimelineYFlag);
2642
- if(zUserName && *zUserName){
2643
- cgi_printf("&u=%t",zUserName);
2644
- }
2645
- cgi_printf("'>%s</a></td>",zWeek);
2646
-
2647
- cgi_printf("<td>%d</td>",nCount);
2648
- cgi_printf("<td>");
2649
- if(nCount){
2650
- cgi_printf("<div class='statistics-report-graph-line'"
2651
- "style='width:%d%%;'>&nbsp;</div>",
2652
- nSize);
2653
- }
2654
- cgi_printf("</td></tr>");
2655
- }
2656
- db_finalize(&stWeek);
2657
- free(zDefaultYear);
2658
- cgi_printf("</tbody></table>");
2659
- if(total){
2660
- int nAvg = iterations ? (total/iterations) : 0;
2661
- cgi_printf("<br><div>Total events: %d<br>"
2662
- "Average per active week: %d</div>",
2663
- total, nAvg);
2664
- }
2665
- output_table_sorting_javascript("statsTable","tnx",-1);
2666
- }
2667
-}
2668
-
2669
-/*
2670
-** WEBPAGE: reports
2671
-**
2672
-** Shows activity reports for the repository.
2673
-**
2674
-** Query Parameters:
2675
-**
2676
-** view=REPORT_NAME Valid values: bymonth, byyear, byuser
2677
-** user=NAME Restricts statistics to the given user
2678
-** type=TYPE Restricts the report to a specific event type:
2679
-** ci (checkin), w (wiki), t (ticket), g (tag)
2680
-** Defaulting to all event types.
2681
-**
2682
-** The view-specific query parameters include:
2683
-**
2684
-** view=byweek:
2685
-**
2686
-** y=YYYY The year to report (default is the server's
2687
-** current year).
2688
-*/
2689
-void stats_report_page(){
2690
- HQuery url; /* URL for various branch links */
2691
- const char *zView = P("view"); /* Which view/report to show. */
2692
- const char *zUserName = P("user");
2693
-
2694
- login_check_credentials();
2695
- if( !g.perm.Read ){ login_needed(); return; }
2696
- if(!zUserName) zUserName = P("u");
2697
- url_initialize(&url, "reports");
2698
- if(zUserName && *zUserName){
2699
- url_add_parameter(&url,"user", zUserName);
2700
- timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
2701
- }
2702
- timeline_submenu(&url, "By Year", "view", "byyear", 0);
2703
- timeline_submenu(&url, "By Month", "view", "bymonth", 0);
2704
- timeline_submenu(&url, "By Week", "view", "byweek", 0);
2705
- timeline_submenu(&url, "By Weekday", "view", "byweekday", 0);
2706
- timeline_submenu(&url, "By User", "view", "byuser", "user");
2707
- url_reset(&url);
2708
- style_header("Activity Reports");
2709
- if(0==fossil_strcmp(zView,"byyear")){
2710
- stats_report_by_month_year(0, 0, zUserName);
2711
- }else if(0==fossil_strcmp(zView,"bymonth")){
2712
- stats_report_by_month_year(1, 0, zUserName);
2713
- }else if(0==fossil_strcmp(zView,"byweek")){
2714
- stats_report_year_weeks(zUserName);
2715
- }else if(0==fossil_strcmp(zView,"byuser")){
2716
- stats_report_by_user();
2717
- }else if(0==fossil_strcmp(zView,"byweekday")){
2718
- stats_report_day_of_week();
2719
- }else{
2720
- @ <h1>Select a report to show:</h1>
2721
- @ <ul>
2722
- @ <li><a href='?view=byyear'>Events by year</a></li>
2723
- @ <li><a href='?view=bymonth'>Events by month</a></li>
2724
- @ <li><a href='?view=byweek'>Events by calendar week</a></li>
2725
- @ <li><a href='?view=byweekday'>Events by day of the week</a></li>
2726
- @ <li><a href='?view=byuser'>Events by user</a></li>
2727
- @ </ul>
2728
- }
2729
-
27302049
style_footer();
27312050
}
27322051
--- src/timeline.c
+++ src/timeline.c
@@ -360,20 +360,20 @@
360 }
361 }
362 }
363 if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
364 int nParent = 0;
365 int aParent[32];
366 int gidx;
367 static Stmt qparent;
368 db_static_prepare(&qparent,
369 "SELECT pid FROM plink"
370 " WHERE cid=:rid AND pid NOT IN phantom"
371 " ORDER BY isprim DESC /*sort*/"
372 );
373 db_bind_int(&qparent, ":rid", rid);
374 while( db_step(&qparent)==SQLITE_ROW && nParent<32 ){
375 aParent[nParent++] = db_column_int(&qparent, 0);
376 }
377 db_reset(&qparent);
378 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
379 zUuid, isLeaf);
@@ -1556,11 +1556,11 @@
1556 }
1557 }
1558 if( P("showsql") ){
1559 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1560 }
1561 if( P("showrid") ) tmFlags |= TIMELINE_SHOWRID;
1562 blob_zero(&sql);
1563 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1564 @ <h2>%b(&desc)</h2>
1565 blob_reset(&desc);
1566 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2044,688 +2044,7 @@
2044 const char *zUuid = db_column_text(&q, 0);
2045 @ <li>
2046 @ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
2047 }
2048 db_finalize(&q);
2049 style_footer();
2050 }
2051
2052
2053 /*
2054 ** Used by stats_report_xxxxx() to remember which type of events
2055 ** to show. Populated by stats_report_init_view() and holds the
2056 ** return value of that function.
2057 */
2058 static int statsReportType = 0;
2059
2060 /*
2061 ** Set by stats_report_init_view() to one of the y=XXXX values
2062 ** accepted by /timeline?y=XXXX.
2063 */
2064 static const char *statsReportTimelineYFlag = NULL;
2065
2066 /*
2067 ** Creates a TEMP VIEW named v_reports which is a wrapper around the
2068 ** EVENT table filtered on event.type. It looks for the request
2069 ** parameter 'type' (reminder: we "should" use 'y' for consistency
2070 ** with /timeline, but /reports uses 'y' for the year) and expects it
2071 ** to contain one of the conventional values from event.type or the
2072 ** value "all", which is treated as equivalent to "*". By default (if
2073 ** no 'y' is specified), "*" is assumed (that is also the default for
2074 ** invalid/unknown filter values). That 'y' filter is the one used for
2075 ** the event list. Note that a filter of "*" or "all" is equivalent to
2076 ** querying against the full event table. The view, however, adds an
2077 ** abstraction level to simplify the implementation code for the
2078 ** various /reports pages.
2079 **
2080 ** Returns one of: 'c', 'w', 'g', 't', 'e', representing the type of
2081 ** filter it applies, or '*' if no filter is applied (i.e. if "all" is
2082 ** used).
2083 */
2084 static int stats_report_init_view(){
2085 const char *zType = PD("type","*"); /* analog to /timeline?y=... */
2086 const char *zRealType = NULL; /* normalized form of zType */
2087 int rc = 0; /* result code */
2088 assert( !statsReportType && "Must not be called more than once." );
2089 switch( (zType && *zType) ? *zType : 0 ){
2090 case 'c':
2091 case 'C':
2092 zRealType = "ci";
2093 rc = *zRealType;
2094 break;
2095 case 'e':
2096 case 'E':
2097 zRealType = "e";
2098 rc = *zRealType;
2099 break;
2100 case 'g':
2101 case 'G':
2102 zRealType = "g";
2103 rc = *zRealType;
2104 break;
2105 case 't':
2106 case 'T':
2107 zRealType = "t";
2108 rc = *zRealType;
2109 break;
2110 case 'w':
2111 case 'W':
2112 zRealType = "w";
2113 rc = *zRealType;
2114 break;
2115 default:
2116 rc = '*';
2117 break;
2118 }
2119 assert(0 != rc);
2120 if(zRealType){
2121 statsReportTimelineYFlag = zRealType;
2122 db_multi_exec("CREATE TEMP VIEW v_reports AS "
2123 "SELECT * FROM event WHERE type GLOB %Q",
2124 zRealType);
2125 }else{
2126 statsReportTimelineYFlag = "a";
2127 db_multi_exec("CREATE TEMP VIEW v_reports AS "
2128 "SELECT * FROM event");
2129 }
2130 return statsReportType = rc;
2131 }
2132
2133 /*
2134 ** Returns a string suitable (for a given value of suitable) for
2135 ** use in a label with the header of the /reports pages, dependent
2136 ** on the 'type' flag. See stats_report_init_view().
2137 ** The returned bytes are static.
2138 */
2139 static const char *stats_report_label_for_type(){
2140 assert( statsReportType && "Must call stats_report_init_view() first." );
2141 switch( statsReportType ){
2142 case 'c':
2143 return "checkins";
2144 case 'e':
2145 return "events";
2146 case 'w':
2147 return "wiki changes";
2148 case 't':
2149 return "ticket changes";
2150 case 'g':
2151 return "tag changes";
2152 default:
2153 return "all types";
2154 }
2155 }
2156
2157 /*
2158 ** A helper for the /reports family of pages which prints out a menu
2159 ** of links for the various type=XXX flags. zCurrentViewName must be
2160 ** the name/value of the 'view' parameter which is in effect at the
2161 ** time this is called. e.g. if called from the 'byuser' view then
2162 ** zCurrentViewName must be "byuser". Any URL parameters which need to
2163 ** be added to the generated URLs should be passed in zParam. The
2164 ** caller is expected to have already encoded any zParam in the %T or
2165 ** %t encoding. */
2166 static void stats_report_event_types_menu(const char *zCurrentViewName,
2167 const char *zParam){
2168 char *zTop;
2169 if(zParam && !*zParam){
2170 zParam = NULL;
2171 }
2172 zTop = mprintf("%s/reports?view=%s%s%s", g.zTop, zCurrentViewName,
2173 zParam ? "&" : "", zParam);
2174 cgi_printf("<div>");
2175 cgi_printf("<span>Types:</span> ");
2176 if('*' == statsReportType){
2177 cgi_printf(" <strong>all</strong>", zTop);
2178 }else{
2179 cgi_printf(" <a href='%s'>all</a>", zTop);
2180 }
2181 if('c' == statsReportType){
2182 cgi_printf(" <strong>checkins</strong>", zTop);
2183 }else{
2184 cgi_printf(" <a href='%s&type=ci'>checkins</a>", zTop);
2185 }
2186 if('e' == statsReportType){
2187 cgi_printf(" <strong>events</strong>", zTop);
2188 }else{
2189 cgi_printf(" <a href='%s&type=e'>events</a>", zTop);
2190 }
2191 if( 't' == statsReportType ){
2192 cgi_printf(" <strong>tickets</strong>", zTop);
2193 }else{
2194 cgi_printf(" <a href='%s&type=t'>tickets</a>", zTop);
2195 }
2196 if( 'g' == statsReportType ){
2197 cgi_printf(" <strong>tags</strong>", zTop);
2198 }else{
2199 cgi_printf(" <a href='%s&type=g'>tags</a>", zTop);
2200 }
2201 if( 'w' == statsReportType ){
2202 cgi_printf(" <strong>wiki</strong>", zTop);
2203 }else{
2204 cgi_printf(" <a href='%s&type=w'>wiki</a>", zTop);
2205 }
2206 fossil_free(zTop);
2207 cgi_printf("</div>");
2208 }
2209
2210
2211 /*
2212 ** Helper for stats_report_by_month_year(), which generates a list of
2213 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2214 ** or YYYY-MM.
2215 */
2216 static void stats_report_output_week_links(const char *zTimeframe){
2217 Stmt stWeek = empty_Stmt;
2218 char yearPart[5] = {0,0,0,0,0};
2219 memcpy(yearPart, zTimeframe, 4);
2220 db_prepare(&stWeek,
2221 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
2222 "count(*) AS n, "
2223 "substr(date(mtime),1,%d) AS ym "
2224 "FROM v_reports "
2225 "WHERE ym=%Q AND mtime < current_timestamp "
2226 "GROUP BY wk ORDER BY wk",
2227 strlen(zTimeframe),
2228 zTimeframe);
2229 while( SQLITE_ROW == db_step(&stWeek) ){
2230 const char *zWeek = db_column_text(&stWeek,0);
2231 const int nCount = db_column_int(&stWeek,1);
2232 cgi_printf("<a href='%s/timeline?"
2233 "yw=%t-%t&n=%d&y=%s'>%s</a>",
2234 g.zTop, yearPart, zWeek,
2235 nCount, statsReportTimelineYFlag, zWeek);
2236 }
2237 db_finalize(&stWeek);
2238 }
2239
2240 /*
2241 ** Implements the "byyear" and "bymonth" reports for /reports.
2242 ** If includeMonth is true then it generates the "bymonth" report,
2243 ** else the "byyear" report. If zUserName is not NULL and not empty
2244 ** then the report is restricted to events created by the named user
2245 ** account.
2246 */
2247 static void stats_report_by_month_year(char includeMonth,
2248 char includeWeeks,
2249 const char *zUserName){
2250 Stmt query = empty_Stmt;
2251 int nRowNumber = 0; /* current TR number */
2252 int nEventTotal = 0; /* Total event count */
2253 int rowClass = 0; /* counter for alternating
2254 row colors */
2255 Blob sql = empty_blob; /* SQL */
2256 const char *zTimeLabel = includeMonth ? "Year/Month" : "Year";
2257 char zPrevYear[5] = {0}; /* For keeping track of when
2258 we change years while looping */
2259 int nEventsPerYear = 0; /* Total event count for the
2260 current year */
2261 char showYearTotal = 0; /* Flag telling us when to show
2262 the per-year event totals */
2263 Blob header = empty_blob; /* Page header text */
2264 int nMaxEvents = 1; /* for calculating length of graph
2265 bars. */
2266 int iterations = 0; /* number of weeks/months we iterate
2267 over */
2268 stats_report_init_view();
2269 stats_report_event_types_menu( includeMonth ? "bymonth" : "byyear", NULL );
2270 blob_appendf(&header, "Timeline Events (%s) by year%s",
2271 stats_report_label_for_type(),
2272 (includeMonth ? "/month" : ""));
2273 blob_append_sql(&sql,
2274 "SELECT substr(date(mtime),1,%d) AS timeframe, "
2275 "count(*) AS eventCount "
2276 "FROM v_reports ",
2277 includeMonth ? 7 : 4);
2278 if(zUserName&&*zUserName){
2279 blob_append_sql(&sql, " WHERE user=%Q ", zUserName);
2280 blob_appendf(&header," for user %q", zUserName);
2281 }
2282 blob_append(&sql,
2283 " GROUP BY timeframe"
2284 " ORDER BY timeframe DESC",
2285 -1);
2286 db_prepare(&query, "%s", blob_sql_text(&sql));
2287 blob_reset(&sql);
2288 @ <h1>%b(&header)</h1>
2289 @ <table class='statistics-report-table-events' border='0' cellpadding='2'
2290 @ cellspacing='0' id='statsTable'>
2291 @ <thead>
2292 @ <th>%s(zTimeLabel)</th>
2293 @ <th>Events</th>
2294 @ <th width='90%%'><!-- relative commits graph --></th>
2295 @ </thead><tbody>
2296 blob_reset(&header);
2297 /*
2298 Run the query twice. The first time we calculate the maximum
2299 number of events for a given row. Maybe someone with better SQL
2300 Fu can re-implement this with a single query.
2301 */
2302 while( SQLITE_ROW == db_step(&query) ){
2303 const int nCount = db_column_int(&query, 1);
2304 if(nCount>nMaxEvents){
2305 nMaxEvents = nCount;
2306 }
2307 ++iterations;
2308 }
2309 db_reset(&query);
2310 while( SQLITE_ROW == db_step(&query) ){
2311 const char *zTimeframe = db_column_text(&query, 0);
2312 const int nCount = db_column_int(&query, 1);
2313 int nSize = nCount
2314 ? (int)(100 * nCount / nMaxEvents)
2315 : 1;
2316 showYearTotal = 0;
2317 if(!nSize) nSize = 1;
2318 if(includeMonth){
2319 /* For Month/year view, add a separator for each distinct year. */
2320 if(!*zPrevYear ||
2321 (0!=fossil_strncmp(zPrevYear,zTimeframe,4))){
2322 showYearTotal = *zPrevYear;
2323 if(showYearTotal){
2324 rowClass = ++nRowNumber % 2;
2325 @ <tr class='row%d(rowClass)'>
2326 @ <td></td>
2327 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2328 @</tr>
2329 }
2330 nEventsPerYear = 0;
2331 memcpy(zPrevYear,zTimeframe,4);
2332 rowClass = ++nRowNumber % 2;
2333 @ <tr class='row%d(rowClass)'>
2334 @ <th colspan='3' class='statistics-report-row-year'>%s(zPrevYear)</th>
2335 @ </tr>
2336 }
2337 }
2338 rowClass = ++nRowNumber % 2;
2339 nEventTotal += nCount;
2340 nEventsPerYear += nCount;
2341 @<tr class='row%d(rowClass)'>
2342 @ <td>
2343 if(includeMonth){
2344 cgi_printf("<a href='%s/timeline?"
2345 "ym=%t&n=%d&y=%s",
2346 g.zTop, zTimeframe, nCount,
2347 statsReportTimelineYFlag );
2348 /* Reminder: n=nCount is not actually correct for bymonth unless
2349 that was the only user who caused events.
2350 */
2351 if( zUserName && *zUserName ){
2352 cgi_printf("&u=%t", zUserName);
2353 }
2354 cgi_printf("' target='_new'>%s</a>",zTimeframe);
2355 }else {
2356 cgi_printf("<a href='?view=byweek&y=%s&type=%c",
2357 zTimeframe, (char)statsReportType);
2358 if(zUserName && *zUserName){
2359 cgi_printf("&u=%t", zUserName);
2360 }
2361 cgi_printf("'>%s</a>", zTimeframe);
2362 }
2363 @ </td><td>%d(nCount)</td>
2364 @ <td>
2365 @ <div class='statistics-report-graph-line'
2366 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2367 @ </td>
2368 @</tr>
2369 if(includeWeeks){
2370 /* This part works fine for months but it terribly slow (4.5s on my PC),
2371 so it's only shown for by-year for now. Suggestions/patches for
2372 a better/faster layout are welcomed. */
2373 @ <tr class='row%d(rowClass)'>
2374 @ <td colspan='2' class='statistics-report-week-number-label'>Week #:</td>
2375 @ <td class='statistics-report-week-of-year-list'>
2376 stats_report_output_week_links(zTimeframe);
2377 @ </td></tr>
2378 }
2379
2380 /*
2381 Potential improvement: calculate the min/max event counts and
2382 use percent-based graph bars.
2383 */
2384 }
2385 db_finalize(&query);
2386 if(includeMonth && !showYearTotal && *zPrevYear){
2387 /* Add final year total separator. */
2388 rowClass = ++nRowNumber % 2;
2389 @ <tr class='row%d(rowClass)'>
2390 @ <td></td>
2391 @ <td colspan='2'>Yearly total: %d(nEventsPerYear)</td>
2392 @</tr>
2393 }
2394 @ </tbody></table>
2395 if(nEventTotal){
2396 const char *zAvgLabel = includeMonth ? "month" : "year";
2397 int nAvg = iterations ? (nEventTotal/iterations) : 0;
2398 @ <br><div>Total events: %d(nEventTotal)
2399 @ <br>Average per active %s(zAvgLabel): %d(nAvg)
2400 @ </div>
2401 }
2402 if( !includeMonth ){
2403 output_table_sorting_javascript("statsTable","tnx",-1);
2404 }
2405 }
2406
2407 /*
2408 ** Implements the "byuser" view for /reports.
2409 */
2410 static void stats_report_by_user(){
2411 Stmt query = empty_Stmt;
2412 int nRowNumber = 0; /* current TR number */
2413 int nEventTotal = 0; /* Total event count */
2414 int rowClass = 0; /* counter for alternating
2415 row colors */
2416 int nMaxEvents = 1; /* max number of events for
2417 all rows. */
2418 stats_report_init_view();
2419 stats_report_event_types_menu("byuser", NULL);
2420 db_prepare(&query,
2421 "SELECT user, "
2422 "COUNT(*) AS eventCount "
2423 "FROM v_reports "
2424 "GROUP BY user ORDER BY eventCount DESC");
2425 @ <h1>Timeline Events
2426 @ (%s(stats_report_label_for_type())) by User</h1>
2427 @ <table class='statistics-report-table-events' border='0'
2428 @ cellpadding='2' cellspacing='0' id='statsTable'>
2429 @ <thead><tr>
2430 @ <th>User</th>
2431 @ <th>Events</th>
2432 @ <th width='90%%'><!-- relative commits graph --></th>
2433 @ </tr></thead><tbody>
2434 while( SQLITE_ROW == db_step(&query) ){
2435 const int nCount = db_column_int(&query, 1);
2436 if(nCount>nMaxEvents){
2437 nMaxEvents = nCount;
2438 }
2439 }
2440 db_reset(&query);
2441 while( SQLITE_ROW == db_step(&query) ){
2442 const char *zUser = db_column_text(&query, 0);
2443 const int nCount = db_column_int(&query, 1);
2444 int nSize = nCount
2445 ? (int)(100 * nCount / nMaxEvents)
2446 : 0;
2447 if(!nCount) continue /* arguable! Possible? */;
2448 else if(!nSize) nSize = 1;
2449 rowClass = ++nRowNumber % 2;
2450 nEventTotal += nCount;
2451 @<tr class='row%d(rowClass)'>
2452 @ <td>
2453 @ <a href="?view=bymonth&user=%h(zUser)&type=%c((char)statsReportType)">%h(zUser)</a>
2454 @ </td><td data-sortkey='%08x(-nCount)'>%d(nCount)</td>
2455 @ <td>
2456 @ <div class='statistics-report-graph-line'
2457 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2458 @ </td>
2459 @</tr>
2460 /*
2461 Potential improvement: calculate the min/max event counts and
2462 use percent-based graph bars.
2463 */
2464 }
2465 @ </tbody></table>
2466 db_finalize(&query);
2467 output_table_sorting_javascript("statsTable","tkx",2);
2468 }
2469
2470 /*
2471 ** Implements the "byweekday" view for /reports.
2472 */
2473 static void stats_report_day_of_week(){
2474 Stmt query = empty_Stmt;
2475 int nRowNumber = 0; /* current TR number */
2476 int nEventTotal = 0; /* Total event count */
2477 int rowClass = 0; /* counter for alternating
2478 row colors */
2479 int nMaxEvents = 1; /* max number of events for
2480 all rows. */
2481 static const char *const daysOfWeek[] = {
2482 "Monday", "Tuesday", "Wednesday", "Thursday",
2483 "Friday", "Saturday", "Sunday"
2484 };
2485
2486 stats_report_init_view();
2487 stats_report_event_types_menu("byweekday", NULL);
2488 db_prepare(&query,
2489 "SELECT cast(mtime %% 7 AS INTEGER) dow, "
2490 "COUNT(*) AS eventCount "
2491 "FROM v_reports "
2492 "GROUP BY dow ORDER BY dow");
2493 @ <h1>Timeline Events
2494 @ (%s(stats_report_label_for_type())) by Day of the Week</h1>
2495 @ <table class='statistics-report-table-events' border='0'
2496 @ cellpadding='2' cellspacing='0' id='statsTable'>
2497 @ <thead><tr>
2498 @ <th>DoW</th>
2499 @ <th>Day</th>
2500 @ <th>Events</th>
2501 @ <th width='90%%'><!-- relative commits graph --></th>
2502 @ </tr></thead><tbody>
2503 while( SQLITE_ROW == db_step(&query) ){
2504 const int nCount = db_column_int(&query, 1);
2505 if(nCount>nMaxEvents){
2506 nMaxEvents = nCount;
2507 }
2508 }
2509 db_reset(&query);
2510 while( SQLITE_ROW == db_step(&query) ){
2511 const int dayNum =db_column_int(&query, 0);
2512 const int nCount = db_column_int(&query, 1);
2513 int nSize = nCount
2514 ? (int)(100 * nCount / nMaxEvents)
2515 : 0;
2516 if(!nCount) continue /* arguable! Possible? */;
2517 else if(!nSize) nSize = 1;
2518 rowClass = ++nRowNumber % 2;
2519 nEventTotal += nCount;
2520 @<tr class='row%d(rowClass)'>
2521 @ <td>%d(dayNum)</td>
2522 @ <td>%s(daysOfWeek[dayNum])</td>
2523 @ <td>%d(nCount)</td>
2524 @ <td>
2525 @ <div class='statistics-report-graph-line'
2526 @ style='width:%d(nSize)%%;'>&nbsp;</div>
2527 @ </td>
2528 @</tr>
2529 }
2530 @ </tbody></table>
2531 db_finalize(&query);
2532 output_table_sorting_javascript("statsTable","ntnx",1);
2533 }
2534
2535
2536 /*
2537 ** Helper for stats_report_by_month_year(), which generates a list of
2538 ** week numbers. zTimeframe should be either a timeframe in the form YYYY
2539 ** or YYYY-MM.
2540 */
2541 static void stats_report_year_weeks(const char *zUserName){
2542 const char *zYear = P("y");
2543 int nYear = zYear ? strlen(zYear) : 0;
2544 int i = 0;
2545 Stmt qYears = empty_Stmt;
2546 char *zDefaultYear = NULL;
2547 Blob sql = empty_blob;
2548 int nMaxEvents = 1; /* max number of events for
2549 all rows. */
2550 int iterations = 0; /* # of active time periods. */
2551 stats_report_init_view();
2552 if(4==nYear){
2553 Blob urlParams = empty_blob;
2554 blob_appendf(&urlParams, "y=%T", zYear);
2555 stats_report_event_types_menu("byweek", blob_str(&urlParams));
2556 blob_reset(&urlParams);
2557 }else{
2558 stats_report_event_types_menu("byweek", NULL);
2559 }
2560 blob_append(&sql,
2561 "SELECT DISTINCT substr(date(mtime),1,4) AS y "
2562 "FROM v_reports WHERE 1 ", -1);
2563 if(zUserName&&*zUserName){
2564 blob_append_sql(&sql,"AND user=%Q ", zUserName);
2565 }
2566 blob_append(&sql,"GROUP BY y ORDER BY y", -1);
2567 db_prepare(&qYears, "%s", blob_sql_text(&sql));
2568 blob_reset(&sql);
2569 cgi_printf("Select year: ");
2570 while( SQLITE_ROW == db_step(&qYears) ){
2571 const char *zT = db_column_text(&qYears, 0);
2572 if( i++ ){
2573 cgi_printf(" ");
2574 }
2575 cgi_printf("<a href='?view=byweek&y=%s&type=%c", zT,
2576 (char)statsReportType);
2577 if(zUserName && *zUserName){
2578 cgi_printf("&user=%t",zUserName);
2579 }
2580 cgi_printf("'>%s</a>",zT);
2581 }
2582 db_finalize(&qYears);
2583 cgi_printf("<br/>");
2584 if(!zYear || !*zYear){
2585 zDefaultYear = db_text("????", "SELECT strftime('%%Y')");
2586 zYear = zDefaultYear;
2587 nYear = 4;
2588 }
2589 if(4 == nYear){
2590 Stmt stWeek = empty_Stmt;
2591 int rowCount = 0;
2592 int total = 0;
2593 Blob header = empty_blob;
2594 blob_appendf(&header, "Timeline events (%s) for the calendar weeks "
2595 "of %h", stats_report_label_for_type(),
2596 zYear);
2597 blob_append_sql(&sql,
2598 "SELECT DISTINCT strftime('%%W',mtime) AS wk, "
2599 "count(*) AS n "
2600 "FROM v_reports "
2601 "WHERE %Q=substr(date(mtime),1,4) "
2602 "AND mtime < current_timestamp ",
2603 zYear);
2604 if(zUserName&&*zUserName){
2605 blob_append_sql(&sql, " AND user=%Q ", zUserName);
2606 blob_appendf(&header," for user %h", zUserName);
2607 }
2608 blob_append_sql(&sql, "GROUP BY wk ORDER BY wk DESC");
2609 cgi_printf("<h1>%h</h1>", blob_str(&header));
2610 blob_reset(&header);
2611 cgi_printf("<table class='statistics-report-table-events' "
2612 "border='0' cellpadding='2' width='100%%' "
2613 "cellspacing='0' id='statsTable'>");
2614 cgi_printf("<thead><tr>"
2615 "<th>Week</th>"
2616 "<th>Events</th>"
2617 "<th width='90%%'><!-- relative commits graph --></th>"
2618 "</tr></thead>"
2619 "<tbody>");
2620 db_prepare(&stWeek, "%s", blob_sql_text(&sql));
2621 blob_reset(&sql);
2622 while( SQLITE_ROW == db_step(&stWeek) ){
2623 const int nCount = db_column_int(&stWeek, 1);
2624 if(nCount>nMaxEvents){
2625 nMaxEvents = nCount;
2626 }
2627 ++iterations;
2628 }
2629 db_reset(&stWeek);
2630 while( SQLITE_ROW == db_step(&stWeek) ){
2631 const char *zWeek = db_column_text(&stWeek,0);
2632 const int nCount = db_column_int(&stWeek,1);
2633 int nSize = nCount
2634 ? (int)(100 * nCount / nMaxEvents)
2635 : 0;
2636 if(!nSize) nSize = 1;
2637 total += nCount;
2638 cgi_printf("<tr class='row%d'>", ++rowCount % 2 );
2639 cgi_printf("<td><a href='%s/timeline?yw=%t-%s&n=%d&y=%s",
2640 g.zTop, zYear, zWeek, nCount,
2641 statsReportTimelineYFlag);
2642 if(zUserName && *zUserName){
2643 cgi_printf("&u=%t",zUserName);
2644 }
2645 cgi_printf("'>%s</a></td>",zWeek);
2646
2647 cgi_printf("<td>%d</td>",nCount);
2648 cgi_printf("<td>");
2649 if(nCount){
2650 cgi_printf("<div class='statistics-report-graph-line'"
2651 "style='width:%d%%;'>&nbsp;</div>",
2652 nSize);
2653 }
2654 cgi_printf("</td></tr>");
2655 }
2656 db_finalize(&stWeek);
2657 free(zDefaultYear);
2658 cgi_printf("</tbody></table>");
2659 if(total){
2660 int nAvg = iterations ? (total/iterations) : 0;
2661 cgi_printf("<br><div>Total events: %d<br>"
2662 "Average per active week: %d</div>",
2663 total, nAvg);
2664 }
2665 output_table_sorting_javascript("statsTable","tnx",-1);
2666 }
2667 }
2668
2669 /*
2670 ** WEBPAGE: reports
2671 **
2672 ** Shows activity reports for the repository.
2673 **
2674 ** Query Parameters:
2675 **
2676 ** view=REPORT_NAME Valid values: bymonth, byyear, byuser
2677 ** user=NAME Restricts statistics to the given user
2678 ** type=TYPE Restricts the report to a specific event type:
2679 ** ci (checkin), w (wiki), t (ticket), g (tag)
2680 ** Defaulting to all event types.
2681 **
2682 ** The view-specific query parameters include:
2683 **
2684 ** view=byweek:
2685 **
2686 ** y=YYYY The year to report (default is the server's
2687 ** current year).
2688 */
2689 void stats_report_page(){
2690 HQuery url; /* URL for various branch links */
2691 const char *zView = P("view"); /* Which view/report to show. */
2692 const char *zUserName = P("user");
2693
2694 login_check_credentials();
2695 if( !g.perm.Read ){ login_needed(); return; }
2696 if(!zUserName) zUserName = P("u");
2697 url_initialize(&url, "reports");
2698 if(zUserName && *zUserName){
2699 url_add_parameter(&url,"user", zUserName);
2700 timeline_submenu(&url, "(Remove User Flag)", "view", zView, "user");
2701 }
2702 timeline_submenu(&url, "By Year", "view", "byyear", 0);
2703 timeline_submenu(&url, "By Month", "view", "bymonth", 0);
2704 timeline_submenu(&url, "By Week", "view", "byweek", 0);
2705 timeline_submenu(&url, "By Weekday", "view", "byweekday", 0);
2706 timeline_submenu(&url, "By User", "view", "byuser", "user");
2707 url_reset(&url);
2708 style_header("Activity Reports");
2709 if(0==fossil_strcmp(zView,"byyear")){
2710 stats_report_by_month_year(0, 0, zUserName);
2711 }else if(0==fossil_strcmp(zView,"bymonth")){
2712 stats_report_by_month_year(1, 0, zUserName);
2713 }else if(0==fossil_strcmp(zView,"byweek")){
2714 stats_report_year_weeks(zUserName);
2715 }else if(0==fossil_strcmp(zView,"byuser")){
2716 stats_report_by_user();
2717 }else if(0==fossil_strcmp(zView,"byweekday")){
2718 stats_report_day_of_week();
2719 }else{
2720 @ <h1>Select a report to show:</h1>
2721 @ <ul>
2722 @ <li><a href='?view=byyear'>Events by year</a></li>
2723 @ <li><a href='?view=bymonth'>Events by month</a></li>
2724 @ <li><a href='?view=byweek'>Events by calendar week</a></li>
2725 @ <li><a href='?view=byweekday'>Events by day of the week</a></li>
2726 @ <li><a href='?view=byuser'>Events by user</a></li>
2727 @ </ul>
2728 }
2729
2730 style_footer();
2731 }
2732
--- src/timeline.c
+++ src/timeline.c
@@ -360,20 +360,20 @@
360 }
361 }
362 }
363 if( zType[0]=='c' && (pGraph || (tmFlags & TIMELINE_BRCOLOR)!=0) ){
364 int nParent = 0;
365 int aParent[GR_MAX_RAIL];
366 int gidx;
367 static Stmt qparent;
368 db_static_prepare(&qparent,
369 "SELECT pid FROM plink"
370 " WHERE cid=:rid AND pid NOT IN phantom"
371 " ORDER BY isprim DESC /*sort*/"
372 );
373 db_bind_int(&qparent, ":rid", rid);
374 while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){
375 aParent[nParent++] = db_column_int(&qparent, 0);
376 }
377 db_reset(&qparent);
378 gidx = graph_add_row(pGraph, rid, nParent, aParent, zBr, zBgClr,
379 zUuid, isLeaf);
@@ -1556,11 +1556,11 @@
1556 }
1557 }
1558 if( P("showsql") ){
1559 @ <blockquote>%h(blob_sql_text(&sql))</blockquote>
1560 }
1561 if( P("showid") ) tmFlags |= TIMELINE_SHOWRID;
1562 blob_zero(&sql);
1563 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby DESC /*scan*/");
1564 @ <h2>%b(&desc)</h2>
1565 blob_reset(&desc);
1566 www_print_timeline(&q, tmFlags, zThisUser, zThisTag, 0);
@@ -2044,688 +2044,7 @@
2044 const char *zUuid = db_column_text(&q, 0);
2045 @ <li>
2046 @ <a href="%s(g.zTop)/timeline?p=%s(zUuid)&amp;d=%s(zUuid)&amp;unhide">%S(zUuid)</a>
2047 }
2048 db_finalize(&q);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2049 style_footer();
2050 }
2051
+11 -1
--- src/url.c
+++ src/url.c
@@ -158,12 +158,22 @@
158158
zLogin = mprintf("%t@", pUrlData->user);
159159
for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
160160
pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
161161
i = j;
162162
}else{
163
- for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
163
+ int inSquare = 0;
164
+ int n;
165
+ for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
166
+ if( c=='[' ) inSquare = 1;
167
+ if( c==']' ) inSquare = 0;
168
+ }
164169
pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
170
+ n = strlen(pUrlData->name);
171
+ if( pUrlData->name[0]=='[' && n>2 && pUrlData->name[n-1]==']' ){
172
+ pUrlData->name++;
173
+ pUrlData->name[n-2] = 0;
174
+ }
165175
zLogin = mprintf("");
166176
}
167177
url_tolower(pUrlData->name);
168178
if( c==':' ){
169179
pUrlData->port = 0;
170180
--- src/url.c
+++ src/url.c
@@ -158,12 +158,22 @@
158 zLogin = mprintf("%t@", pUrlData->user);
159 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
160 pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
161 i = j;
162 }else{
163 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
 
 
 
 
 
164 pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
 
 
 
 
 
165 zLogin = mprintf("");
166 }
167 url_tolower(pUrlData->name);
168 if( c==':' ){
169 pUrlData->port = 0;
170
--- src/url.c
+++ src/url.c
@@ -158,12 +158,22 @@
158 zLogin = mprintf("%t@", pUrlData->user);
159 for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
160 pUrlData->name = mprintf("%.*s", j-i-1, &zUrl[i+1]);
161 i = j;
162 }else{
163 int inSquare = 0;
164 int n;
165 for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
166 if( c=='[' ) inSquare = 1;
167 if( c==']' ) inSquare = 0;
168 }
169 pUrlData->name = mprintf("%.*s", i-iStart, &zUrl[iStart]);
170 n = strlen(pUrlData->name);
171 if( pUrlData->name[0]=='[' && n>2 && pUrlData->name[n-1]==']' ){
172 pUrlData->name++;
173 pUrlData->name[n-2] = 0;
174 }
175 zLogin = mprintf("");
176 }
177 url_tolower(pUrlData->name);
178 if( c==':' ){
179 pUrlData->port = 0;
180
+22 -1
--- src/wiki.c
+++ src/wiki.c
@@ -155,10 +155,30 @@
155155
@ <pre>
156156
@ %h(blob_str(pWiki))
157157
@ </pre>
158158
}
159159
}
160
+
161
+/*
162
+** WEBPAGE: md_rules
163
+**
164
+** Show a summary of the Markdown wiki formatting rules.
165
+*/
166
+void markdown_rules_page(void){
167
+ Blob x;
168
+ int fTxt = P("txt")!=0;
169
+ style_header("Markdown Formatting Rules");
170
+ if( fTxt ){
171
+ style_submenu_element("Formatted", "Formatted", "%R/md_rules");
172
+ }else{
173
+ style_submenu_element("Plain-Text", "Plain-Text", "%R/md_rules?txt=1");
174
+ }
175
+ blob_init(&x, builtin_text("markdown.md"), -1);
176
+ wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown");
177
+ blob_reset(&x);
178
+ style_footer();
179
+}
160180
161181
/*
162182
** Returns non-zero if moderation is required for wiki changes and wiki
163183
** attachments.
164184
*/
@@ -213,11 +233,12 @@
213233
@ <li> %z(href("%R/wiki?name=%t",zHomePageName))
214234
@ %h(zHomePageName)</a> project home page.</li>
215235
}
216236
}
217237
@ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
218
- @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li>
238
+ @ <li> Formatting rules for %z(href("%R/wiki_rules"))Fossil Wiki</a> and for
239
+ @ %z(href("%R/md_rules"))Markdown Wiki</a>.</li>
219240
@ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
220241
@ to experiment.</li>
221242
if( g.perm.NewWiki ){
222243
@ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
223244
if( g.perm.Write ){
224245
--- src/wiki.c
+++ src/wiki.c
@@ -155,10 +155,30 @@
155 @ <pre>
156 @ %h(blob_str(pWiki))
157 @ </pre>
158 }
159 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
161 /*
162 ** Returns non-zero if moderation is required for wiki changes and wiki
163 ** attachments.
164 */
@@ -213,11 +233,12 @@
213 @ <li> %z(href("%R/wiki?name=%t",zHomePageName))
214 @ %h(zHomePageName)</a> project home page.</li>
215 }
216 }
217 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
218 @ <li> %z(href("%R/wiki_rules"))Formatting rules</a> for wiki.</li>
 
219 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
220 @ to experiment.</li>
221 if( g.perm.NewWiki ){
222 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
223 if( g.perm.Write ){
224
--- src/wiki.c
+++ src/wiki.c
@@ -155,10 +155,30 @@
155 @ <pre>
156 @ %h(blob_str(pWiki))
157 @ </pre>
158 }
159 }
160
161 /*
162 ** WEBPAGE: md_rules
163 **
164 ** Show a summary of the Markdown wiki formatting rules.
165 */
166 void markdown_rules_page(void){
167 Blob x;
168 int fTxt = P("txt")!=0;
169 style_header("Markdown Formatting Rules");
170 if( fTxt ){
171 style_submenu_element("Formatted", "Formatted", "%R/md_rules");
172 }else{
173 style_submenu_element("Plain-Text", "Plain-Text", "%R/md_rules?txt=1");
174 }
175 blob_init(&x, builtin_text("markdown.md"), -1);
176 wiki_render_by_mimetype(&x, fTxt ? "text/plain" : "text/x-markdown");
177 blob_reset(&x);
178 style_footer();
179 }
180
181 /*
182 ** Returns non-zero if moderation is required for wiki changes and wiki
183 ** attachments.
184 */
@@ -213,11 +233,12 @@
233 @ <li> %z(href("%R/wiki?name=%t",zHomePageName))
234 @ %h(zHomePageName)</a> project home page.</li>
235 }
236 }
237 @ <li> %z(href("%R/timeline?y=w"))Recent changes</a> to wiki pages.</li>
238 @ <li> Formatting rules for %z(href("%R/wiki_rules"))Fossil Wiki</a> and for
239 @ %z(href("%R/md_rules"))Markdown Wiki</a>.</li>
240 @ <li> Use the %z(href("%R/wiki?name=Sandbox"))Sandbox</a>
241 @ to experiment.</li>
242 if( g.perm.NewWiki ){
243 @ <li> Create a %z(href("%R/wikinew"))new wiki page</a>.</li>
244 if( g.perm.Write ){
245
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -141,11 +141,11 @@
141141
# generate the index source, containing all web references,..
142142
page_index.h: $(TRANSLATEDSRC) mkindex.exe
143143
mkindex.exe $(TRANSLATEDSRC) >$@
144144
145145
builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
146
- mkbuiltin.exe $(EXTRA_FILES) >$@
146
+ mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
147147
148148
# extracting version info from manifest
149149
VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
150150
version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
151151
152152
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -141,11 +141,11 @@
141 # generate the index source, containing all web references,..
142 page_index.h: $(TRANSLATEDSRC) mkindex.exe
143 mkindex.exe $(TRANSLATEDSRC) >$@
144
145 builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
146 mkbuiltin.exe $(EXTRA_FILES) >$@
147
148 # extracting version info from manifest
149 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
150 version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
151
152
--- win/Makefile.PellesCGMake
+++ win/Makefile.PellesCGMake
@@ -141,11 +141,11 @@
141 # generate the index source, containing all web references,..
142 page_index.h: $(TRANSLATEDSRC) mkindex.exe
143 mkindex.exe $(TRANSLATEDSRC) >$@
144
145 builtin_data.h: $(EXTRA_FILES) mkbuiltin.exe
146 mkbuiltin.exe --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
147
148 # extracting version info from manifest
149 VERSION.h: version.exe ..\manifest.uuid ..\manifest ..\VERSION
150 version.exe ..\manifest.uuid ..\manifest ..\VERSION >$@
151
152
+11 -5
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
2828
2929
SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
3030
3131
SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
3232
33
-SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
33
+SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
3434
35
-OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
35
+OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
3636
3737
3838
RC=$(DMDIR)\bin\rcc
3939
RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
4040
@@ -49,11 +49,11 @@
4949
5050
$(OBJDIR)\fossil.res: $B\win\fossil.rc
5151
$(RC) $(RCFLAGS) -o$@ $**
5252
5353
$(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54
- +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
54
+ +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
5555
+echo fossil >> $@
5656
+echo fossil >> $@
5757
+echo $(LIBS) >> $@
5858
+echo. >> $@
5959
+echo fossil >> $@
@@ -96,11 +96,11 @@
9696
9797
page_index.h: mkindex$E $(SRC)
9898
+$** > $@
9999
100100
builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
101
- +$** > $@
101
+ mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
102102
103103
clean:
104104
-del $(OBJDIR)\*.obj
105105
-del *.obj *_.c *.h *.map
106106
@@ -674,10 +674,16 @@
674674
$(OBJDIR)\stat$O : stat_.c stat.h
675675
$(TCC) -o$@ -c stat_.c
676676
677677
stat_.c : $(SRCDIR)\stat.c
678678
+translate$E $** > $@
679
+
680
+$(OBJDIR)\statrep$O : statrep_.c statrep.h
681
+ $(TCC) -o$@ -c statrep_.c
682
+
683
+statrep_.c : $(SRCDIR)\statrep.c
684
+ +translate$E $** > $@
679685
680686
$(OBJDIR)\style$O : style_.c style.h
681687
$(TCC) -o$@ -c style_.c
682688
683689
style_.c : $(SRCDIR)\style.c
@@ -826,7 +832,7 @@
826832
827833
zip_.c : $(SRCDIR)\zip.c
828834
+translate$E $** > $@
829835
830836
headers: makeheaders$E page_index.h builtin_data.h VERSION.h
831
- +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
837
+ +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
832838
@copy /Y nul: headers
833839
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -96,11 +96,11 @@
96
97 page_index.h: mkindex$E $(SRC)
98 +$** > $@
99
100 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
101 +$** > $@
102
103 clean:
104 -del $(OBJDIR)\*.obj
105 -del *.obj *_.c *.h *.map
106
@@ -674,10 +674,16 @@
674 $(OBJDIR)\stat$O : stat_.c stat.h
675 $(TCC) -o$@ -c stat_.c
676
677 stat_.c : $(SRCDIR)\stat.c
678 +translate$E $** > $@
 
 
 
 
 
 
679
680 $(OBJDIR)\style$O : style_.c style.h
681 $(TCC) -o$@ -c style_.c
682
683 style_.c : $(SRCDIR)\style.c
@@ -826,7 +832,7 @@
826
827 zip_.c : $(SRCDIR)\zip.c
828 +translate$E $** > $@
829
830 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
831 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
832 @copy /Y nul: headers
833
--- win/Makefile.dmc
+++ win/Makefile.dmc
@@ -28,13 +28,13 @@
28
29 SQLITE_OPTIONS = -DNDEBUG=1 -DSQLITE_OMIT_LOAD_EXTENSION=1 -DSQLITE_ENABLE_LOCKING_STYLE=0 -DSQLITE_THREADSAFE=0 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_OMIT_DEPRECATED -DSQLITE_ENABLE_EXPLAIN_COMMENTS
30
31 SHELL_OPTIONS = -Dmain=sqlite3_shell -DSQLITE_OMIT_LOAD_EXTENSION=1 -DUSE_SYSTEM_SQLITE=$(USE_SYSTEM_SQLITE) -DSQLITE_SHELL_DBNAME_PROC=fossil_open -Daccess=file_access -Dsystem=fossil_system -Dgetenv=fossil_getenv -Dfopen=fossil_fopen
32
33 SRC = add_.c allrepo_.c attach_.c bag_.c bisect_.c blob_.c branch_.c browse_.c builtin_.c bundle_.c cache_.c captcha_.c cgi_.c checkin_.c checkout_.c clearsign_.c clone_.c comformat_.c configure_.c content_.c db_.c delta_.c deltacmd_.c descendants_.c diff_.c diffcmd_.c doc_.c encode_.c event_.c export_.c file_.c finfo_.c foci_.c fusefs_.c glob_.c graph_.c gzip_.c http_.c http_socket_.c http_ssl_.c http_transport_.c import_.c info_.c json_.c json_artifact_.c json_branch_.c json_config_.c json_diff_.c json_dir_.c json_finfo_.c json_login_.c json_query_.c json_report_.c json_status_.c json_tag_.c json_timeline_.c json_user_.c json_wiki_.c leaf_.c loadctrl_.c login_.c lookslike_.c main_.c manifest_.c markdown_.c markdown_html_.c md5_.c merge_.c merge3_.c moderate_.c name_.c path_.c pivot_.c popen_.c pqueue_.c printf_.c publish_.c purge_.c rebuild_.c regexp_.c report_.c rss_.c schema_.c search_.c setup_.c sha1_.c shun_.c sitemap_.c skins_.c sqlcmd_.c stash_.c stat_.c statrep_.c style_.c sync_.c tag_.c tar_.c th_main_.c timeline_.c tkt_.c tktsetup_.c undo_.c unicode_.c update_.c url_.c user_.c utf8_.c util_.c verify_.c vfile_.c wiki_.c wikiformat_.c winfile_.c winhttp_.c wysiwyg_.c xfer_.c xfersetup_.c zip_.c
34
35 OBJ = $(OBJDIR)\add$O $(OBJDIR)\allrepo$O $(OBJDIR)\attach$O $(OBJDIR)\bag$O $(OBJDIR)\bisect$O $(OBJDIR)\blob$O $(OBJDIR)\branch$O $(OBJDIR)\browse$O $(OBJDIR)\builtin$O $(OBJDIR)\bundle$O $(OBJDIR)\cache$O $(OBJDIR)\captcha$O $(OBJDIR)\cgi$O $(OBJDIR)\checkin$O $(OBJDIR)\checkout$O $(OBJDIR)\clearsign$O $(OBJDIR)\clone$O $(OBJDIR)\comformat$O $(OBJDIR)\configure$O $(OBJDIR)\content$O $(OBJDIR)\db$O $(OBJDIR)\delta$O $(OBJDIR)\deltacmd$O $(OBJDIR)\descendants$O $(OBJDIR)\diff$O $(OBJDIR)\diffcmd$O $(OBJDIR)\doc$O $(OBJDIR)\encode$O $(OBJDIR)\event$O $(OBJDIR)\export$O $(OBJDIR)\file$O $(OBJDIR)\finfo$O $(OBJDIR)\foci$O $(OBJDIR)\fusefs$O $(OBJDIR)\glob$O $(OBJDIR)\graph$O $(OBJDIR)\gzip$O $(OBJDIR)\http$O $(OBJDIR)\http_socket$O $(OBJDIR)\http_ssl$O $(OBJDIR)\http_transport$O $(OBJDIR)\import$O $(OBJDIR)\info$O $(OBJDIR)\json$O $(OBJDIR)\json_artifact$O $(OBJDIR)\json_branch$O $(OBJDIR)\json_config$O $(OBJDIR)\json_diff$O $(OBJDIR)\json_dir$O $(OBJDIR)\json_finfo$O $(OBJDIR)\json_login$O $(OBJDIR)\json_query$O $(OBJDIR)\json_report$O $(OBJDIR)\json_status$O $(OBJDIR)\json_tag$O $(OBJDIR)\json_timeline$O $(OBJDIR)\json_user$O $(OBJDIR)\json_wiki$O $(OBJDIR)\leaf$O $(OBJDIR)\loadctrl$O $(OBJDIR)\login$O $(OBJDIR)\lookslike$O $(OBJDIR)\main$O $(OBJDIR)\manifest$O $(OBJDIR)\markdown$O $(OBJDIR)\markdown_html$O $(OBJDIR)\md5$O $(OBJDIR)\merge$O $(OBJDIR)\merge3$O $(OBJDIR)\moderate$O $(OBJDIR)\name$O $(OBJDIR)\path$O $(OBJDIR)\pivot$O $(OBJDIR)\popen$O $(OBJDIR)\pqueue$O $(OBJDIR)\printf$O $(OBJDIR)\publish$O $(OBJDIR)\purge$O $(OBJDIR)\rebuild$O $(OBJDIR)\regexp$O $(OBJDIR)\report$O $(OBJDIR)\rss$O $(OBJDIR)\schema$O $(OBJDIR)\search$O $(OBJDIR)\setup$O $(OBJDIR)\sha1$O $(OBJDIR)\shun$O $(OBJDIR)\sitemap$O $(OBJDIR)\skins$O $(OBJDIR)\sqlcmd$O $(OBJDIR)\stash$O $(OBJDIR)\stat$O $(OBJDIR)\statrep$O $(OBJDIR)\style$O $(OBJDIR)\sync$O $(OBJDIR)\tag$O $(OBJDIR)\tar$O $(OBJDIR)\th_main$O $(OBJDIR)\timeline$O $(OBJDIR)\tkt$O $(OBJDIR)\tktsetup$O $(OBJDIR)\undo$O $(OBJDIR)\unicode$O $(OBJDIR)\update$O $(OBJDIR)\url$O $(OBJDIR)\user$O $(OBJDIR)\utf8$O $(OBJDIR)\util$O $(OBJDIR)\verify$O $(OBJDIR)\vfile$O $(OBJDIR)\wiki$O $(OBJDIR)\wikiformat$O $(OBJDIR)\winfile$O $(OBJDIR)\winhttp$O $(OBJDIR)\wysiwyg$O $(OBJDIR)\xfer$O $(OBJDIR)\xfersetup$O $(OBJDIR)\zip$O $(OBJDIR)\shell$O $(OBJDIR)\sqlite3$O $(OBJDIR)\th$O $(OBJDIR)\th_lang$O
36
37
38 RC=$(DMDIR)\bin\rcc
39 RCFLAGS=-32 -w1 -I$(SRCDIR) /D__DMC__
40
@@ -49,11 +49,11 @@
49
50 $(OBJDIR)\fossil.res: $B\win\fossil.rc
51 $(RC) $(RCFLAGS) -o$@ $**
52
53 $(OBJDIR)\link: $B\win\Makefile.dmc $(OBJDIR)\fossil.res
54 +echo add allrepo attach bag bisect blob branch browse builtin bundle cache captcha cgi checkin checkout clearsign clone comformat configure content db delta deltacmd descendants diff diffcmd doc encode event export file finfo foci fusefs glob graph gzip http http_socket http_ssl http_transport import info json json_artifact json_branch json_config json_diff json_dir json_finfo json_login json_query json_report json_status json_tag json_timeline json_user json_wiki leaf loadctrl login lookslike main manifest markdown markdown_html md5 merge merge3 moderate name path pivot popen pqueue printf publish purge rebuild regexp report rss schema search setup sha1 shun sitemap skins sqlcmd stash stat statrep style sync tag tar th_main timeline tkt tktsetup undo unicode update url user utf8 util verify vfile wiki wikiformat winfile winhttp wysiwyg xfer xfersetup zip shell sqlite3 th th_lang > $@
55 +echo fossil >> $@
56 +echo fossil >> $@
57 +echo $(LIBS) >> $@
58 +echo. >> $@
59 +echo fossil >> $@
@@ -96,11 +96,11 @@
96
97 page_index.h: mkindex$E $(SRC)
98 +$** > $@
99
100 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
101 mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
102
103 clean:
104 -del $(OBJDIR)\*.obj
105 -del *.obj *_.c *.h *.map
106
@@ -674,10 +674,16 @@
674 $(OBJDIR)\stat$O : stat_.c stat.h
675 $(TCC) -o$@ -c stat_.c
676
677 stat_.c : $(SRCDIR)\stat.c
678 +translate$E $** > $@
679
680 $(OBJDIR)\statrep$O : statrep_.c statrep.h
681 $(TCC) -o$@ -c statrep_.c
682
683 statrep_.c : $(SRCDIR)\statrep.c
684 +translate$E $** > $@
685
686 $(OBJDIR)\style$O : style_.c style.h
687 $(TCC) -o$@ -c style_.c
688
689 style_.c : $(SRCDIR)\style.c
@@ -826,7 +832,7 @@
832
833 zip_.c : $(SRCDIR)\zip.c
834 +translate$E $** > $@
835
836 headers: makeheaders$E page_index.h builtin_data.h VERSION.h
837 +makeheaders$E add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h bisect_.c:bisect.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h builtin_.c:builtin.h bundle_.c:bundle.h cache_.c:cache.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h export_.c:export.h file_.c:file.h finfo_.c:finfo.h foci_.c:foci.h fusefs_.c:fusefs.h glob_.c:glob.h graph_.c:graph.h gzip_.c:gzip.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h import_.c:import.h info_.c:info.h json_.c:json.h json_artifact_.c:json_artifact.h json_branch_.c:json_branch.h json_config_.c:json_config.h json_diff_.c:json_diff.h json_dir_.c:json_dir.h json_finfo_.c:json_finfo.h json_login_.c:json_login.h json_query_.c:json_query.h json_report_.c:json_report.h json_status_.c:json_status.h json_tag_.c:json_tag.h json_timeline_.c:json_timeline.h json_user_.c:json_user.h json_wiki_.c:json_wiki.h leaf_.c:leaf.h loadctrl_.c:loadctrl.h login_.c:login.h lookslike_.c:lookslike.h main_.c:main.h manifest_.c:manifest.h markdown_.c:markdown.h markdown_html_.c:markdown_html.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h moderate_.c:moderate.h name_.c:name.h path_.c:path.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h publish_.c:publish.h purge_.c:purge.h rebuild_.c:rebuild.h regexp_.c:regexp.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h sitemap_.c:sitemap.h skins_.c:skins.h sqlcmd_.c:sqlcmd.h stash_.c:stash.h stat_.c:stat.h statrep_.c:statrep.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h tar_.c:tar.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h unicode_.c:unicode.h update_.c:update.h url_.c:url.h user_.c:user.h utf8_.c:utf8.h util_.c:util.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winfile_.c:winfile.h winhttp_.c:winhttp.h wysiwyg_.c:wysiwyg.h xfer_.c:xfer.h xfersetup_.c:xfersetup.h zip_.c:zip.h $(SRCDIR)\sqlite3.h $(SRCDIR)\th.h VERSION.h $(SRCDIR)\cson_amalgamation.h
838 @copy /Y nul: headers
839
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -457,10 +457,11 @@
457457
$(SRCDIR)/sitemap.c \
458458
$(SRCDIR)/skins.c \
459459
$(SRCDIR)/sqlcmd.c \
460460
$(SRCDIR)/stash.c \
461461
$(SRCDIR)/stat.c \
462
+ $(SRCDIR)/statrep.c \
462463
$(SRCDIR)/style.c \
463464
$(SRCDIR)/sync.c \
464465
$(SRCDIR)/tag.c \
465466
$(SRCDIR)/tar.c \
466467
$(SRCDIR)/th_main.c \
@@ -508,11 +509,12 @@
508509
$(SRCDIR)/../skins/plain_gray/footer.txt \
509510
$(SRCDIR)/../skins/plain_gray/header.txt \
510511
$(SRCDIR)/../skins/rounded1/css.txt \
511512
$(SRCDIR)/../skins/rounded1/footer.txt \
512513
$(SRCDIR)/../skins/rounded1/header.txt \
513
- $(SRCDIR)/diff.tcl
514
+ $(SRCDIR)/diff.tcl \
515
+ $(SRCDIR)/markdown.md
514516
515517
TRANS_SRC = \
516518
$(OBJDIR)/add_.c \
517519
$(OBJDIR)/allrepo_.c \
518520
$(OBJDIR)/attach_.c \
@@ -603,10 +605,11 @@
603605
$(OBJDIR)/sitemap_.c \
604606
$(OBJDIR)/skins_.c \
605607
$(OBJDIR)/sqlcmd_.c \
606608
$(OBJDIR)/stash_.c \
607609
$(OBJDIR)/stat_.c \
610
+ $(OBJDIR)/statrep_.c \
608611
$(OBJDIR)/style_.c \
609612
$(OBJDIR)/sync_.c \
610613
$(OBJDIR)/tag_.c \
611614
$(OBJDIR)/tar_.c \
612615
$(OBJDIR)/th_main_.c \
@@ -722,10 +725,11 @@
722725
$(OBJDIR)/sitemap.o \
723726
$(OBJDIR)/skins.o \
724727
$(OBJDIR)/sqlcmd.o \
725728
$(OBJDIR)/stash.o \
726729
$(OBJDIR)/stat.o \
730
+ $(OBJDIR)/statrep.o \
727731
$(OBJDIR)/style.o \
728732
$(OBJDIR)/sync.o \
729733
$(OBJDIR)/tag.o \
730734
$(OBJDIR)/tar.o \
731735
$(OBJDIR)/th_main.o \
@@ -939,11 +943,11 @@
939943
940944
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
941945
$(MKINDEX) $(TRANS_SRC) >$@
942946
943947
$(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
944
- $(MKBUILTIN) $(EXTRA_FILES) >$@
948
+ $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
945949
946950
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
947951
$(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
948952
$(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
949953
$(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1034,10 +1038,11 @@
10341038
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
10351039
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
10361040
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
10371041
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
10381042
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1043
+ $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
10391044
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
10401045
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
10411046
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
10421047
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
10431048
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1803,10 +1808,18 @@
18031808
18041809
$(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
18051810
$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
18061811
18071812
$(OBJDIR)/stat.h: $(OBJDIR)/headers
1813
+
1814
+$(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(TRANSLATE)
1815
+ $(TRANSLATE) $(SRCDIR)/statrep.c >$@
1816
+
1817
+$(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1818
+ $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1819
+
1820
+$(OBJDIR)/statrep.h: $(OBJDIR)/headers
18081821
18091822
$(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
18101823
$(TRANSLATE) $(SRCDIR)/style.c >$@
18111824
18121825
$(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
18131826
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -457,10 +457,11 @@
457 $(SRCDIR)/sitemap.c \
458 $(SRCDIR)/skins.c \
459 $(SRCDIR)/sqlcmd.c \
460 $(SRCDIR)/stash.c \
461 $(SRCDIR)/stat.c \
 
462 $(SRCDIR)/style.c \
463 $(SRCDIR)/sync.c \
464 $(SRCDIR)/tag.c \
465 $(SRCDIR)/tar.c \
466 $(SRCDIR)/th_main.c \
@@ -508,11 +509,12 @@
508 $(SRCDIR)/../skins/plain_gray/footer.txt \
509 $(SRCDIR)/../skins/plain_gray/header.txt \
510 $(SRCDIR)/../skins/rounded1/css.txt \
511 $(SRCDIR)/../skins/rounded1/footer.txt \
512 $(SRCDIR)/../skins/rounded1/header.txt \
513 $(SRCDIR)/diff.tcl
 
514
515 TRANS_SRC = \
516 $(OBJDIR)/add_.c \
517 $(OBJDIR)/allrepo_.c \
518 $(OBJDIR)/attach_.c \
@@ -603,10 +605,11 @@
603 $(OBJDIR)/sitemap_.c \
604 $(OBJDIR)/skins_.c \
605 $(OBJDIR)/sqlcmd_.c \
606 $(OBJDIR)/stash_.c \
607 $(OBJDIR)/stat_.c \
 
608 $(OBJDIR)/style_.c \
609 $(OBJDIR)/sync_.c \
610 $(OBJDIR)/tag_.c \
611 $(OBJDIR)/tar_.c \
612 $(OBJDIR)/th_main_.c \
@@ -722,10 +725,11 @@
722 $(OBJDIR)/sitemap.o \
723 $(OBJDIR)/skins.o \
724 $(OBJDIR)/sqlcmd.o \
725 $(OBJDIR)/stash.o \
726 $(OBJDIR)/stat.o \
 
727 $(OBJDIR)/style.o \
728 $(OBJDIR)/sync.o \
729 $(OBJDIR)/tag.o \
730 $(OBJDIR)/tar.o \
731 $(OBJDIR)/th_main.o \
@@ -939,11 +943,11 @@
939
940 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
941 $(MKINDEX) $(TRANS_SRC) >$@
942
943 $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
944 $(MKBUILTIN) $(EXTRA_FILES) >$@
945
946 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
947 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
948 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
949 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1034,10 +1038,11 @@
1034 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1035 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1036 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1037 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1038 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
 
1039 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1040 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1041 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1042 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1043 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1803,10 +1808,18 @@
1803
1804 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1805 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1806
1807 $(OBJDIR)/stat.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1808
1809 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
1810 $(TRANSLATE) $(SRCDIR)/style.c >$@
1811
1812 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1813
--- win/Makefile.mingw
+++ win/Makefile.mingw
@@ -457,10 +457,11 @@
457 $(SRCDIR)/sitemap.c \
458 $(SRCDIR)/skins.c \
459 $(SRCDIR)/sqlcmd.c \
460 $(SRCDIR)/stash.c \
461 $(SRCDIR)/stat.c \
462 $(SRCDIR)/statrep.c \
463 $(SRCDIR)/style.c \
464 $(SRCDIR)/sync.c \
465 $(SRCDIR)/tag.c \
466 $(SRCDIR)/tar.c \
467 $(SRCDIR)/th_main.c \
@@ -508,11 +509,12 @@
509 $(SRCDIR)/../skins/plain_gray/footer.txt \
510 $(SRCDIR)/../skins/plain_gray/header.txt \
511 $(SRCDIR)/../skins/rounded1/css.txt \
512 $(SRCDIR)/../skins/rounded1/footer.txt \
513 $(SRCDIR)/../skins/rounded1/header.txt \
514 $(SRCDIR)/diff.tcl \
515 $(SRCDIR)/markdown.md
516
517 TRANS_SRC = \
518 $(OBJDIR)/add_.c \
519 $(OBJDIR)/allrepo_.c \
520 $(OBJDIR)/attach_.c \
@@ -603,10 +605,11 @@
605 $(OBJDIR)/sitemap_.c \
606 $(OBJDIR)/skins_.c \
607 $(OBJDIR)/sqlcmd_.c \
608 $(OBJDIR)/stash_.c \
609 $(OBJDIR)/stat_.c \
610 $(OBJDIR)/statrep_.c \
611 $(OBJDIR)/style_.c \
612 $(OBJDIR)/sync_.c \
613 $(OBJDIR)/tag_.c \
614 $(OBJDIR)/tar_.c \
615 $(OBJDIR)/th_main_.c \
@@ -722,10 +725,11 @@
725 $(OBJDIR)/sitemap.o \
726 $(OBJDIR)/skins.o \
727 $(OBJDIR)/sqlcmd.o \
728 $(OBJDIR)/stash.o \
729 $(OBJDIR)/stat.o \
730 $(OBJDIR)/statrep.o \
731 $(OBJDIR)/style.o \
732 $(OBJDIR)/sync.o \
733 $(OBJDIR)/tag.o \
734 $(OBJDIR)/tar.o \
735 $(OBJDIR)/th_main.o \
@@ -939,11 +943,11 @@
943
944 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
945 $(MKINDEX) $(TRANS_SRC) >$@
946
947 $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
948 $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
949
950 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
951 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
952 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
953 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1034,10 +1038,11 @@
1038 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1039 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1040 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1041 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1042 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1043 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1044 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1045 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1046 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1047 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1048 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1803,10 +1808,18 @@
1808
1809 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1810 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1811
1812 $(OBJDIR)/stat.h: $(OBJDIR)/headers
1813
1814 $(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(TRANSLATE)
1815 $(TRANSLATE) $(SRCDIR)/statrep.c >$@
1816
1817 $(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1818 $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1819
1820 $(OBJDIR)/statrep.h: $(OBJDIR)/headers
1821
1822 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
1823 $(TRANSLATE) $(SRCDIR)/style.c >$@
1824
1825 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1826
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -457,10 +457,11 @@
457457
$(SRCDIR)/sitemap.c \
458458
$(SRCDIR)/skins.c \
459459
$(SRCDIR)/sqlcmd.c \
460460
$(SRCDIR)/stash.c \
461461
$(SRCDIR)/stat.c \
462
+ $(SRCDIR)/statrep.c \
462463
$(SRCDIR)/style.c \
463464
$(SRCDIR)/sync.c \
464465
$(SRCDIR)/tag.c \
465466
$(SRCDIR)/tar.c \
466467
$(SRCDIR)/th_main.c \
@@ -496,20 +497,24 @@
496497
$(SRCDIR)/../skins/eagle/footer.txt \
497498
$(SRCDIR)/../skins/eagle/header.txt \
498499
$(SRCDIR)/../skins/enhanced1/css.txt \
499500
$(SRCDIR)/../skins/enhanced1/footer.txt \
500501
$(SRCDIR)/../skins/enhanced1/header.txt \
502
+ $(SRCDIR)/../skins/etienne1/css.txt \
503
+ $(SRCDIR)/../skins/etienne1/footer.txt \
504
+ $(SRCDIR)/../skins/etienne1/header.txt \
501505
$(SRCDIR)/../skins/khaki/css.txt \
502506
$(SRCDIR)/../skins/khaki/footer.txt \
503507
$(SRCDIR)/../skins/khaki/header.txt \
504508
$(SRCDIR)/../skins/plain_gray/css.txt \
505509
$(SRCDIR)/../skins/plain_gray/footer.txt \
506510
$(SRCDIR)/../skins/plain_gray/header.txt \
507511
$(SRCDIR)/../skins/rounded1/css.txt \
508512
$(SRCDIR)/../skins/rounded1/footer.txt \
509513
$(SRCDIR)/../skins/rounded1/header.txt \
510
- $(SRCDIR)/diff.tcl
514
+ $(SRCDIR)/diff.tcl \
515
+ $(SRCDIR)/markdown.md
511516
512517
TRANS_SRC = \
513518
$(OBJDIR)/add_.c \
514519
$(OBJDIR)/allrepo_.c \
515520
$(OBJDIR)/attach_.c \
@@ -600,10 +605,11 @@
600605
$(OBJDIR)/sitemap_.c \
601606
$(OBJDIR)/skins_.c \
602607
$(OBJDIR)/sqlcmd_.c \
603608
$(OBJDIR)/stash_.c \
604609
$(OBJDIR)/stat_.c \
610
+ $(OBJDIR)/statrep_.c \
605611
$(OBJDIR)/style_.c \
606612
$(OBJDIR)/sync_.c \
607613
$(OBJDIR)/tag_.c \
608614
$(OBJDIR)/tar_.c \
609615
$(OBJDIR)/th_main_.c \
@@ -719,10 +725,11 @@
719725
$(OBJDIR)/sitemap.o \
720726
$(OBJDIR)/skins.o \
721727
$(OBJDIR)/sqlcmd.o \
722728
$(OBJDIR)/stash.o \
723729
$(OBJDIR)/stat.o \
730
+ $(OBJDIR)/statrep.o \
724731
$(OBJDIR)/style.o \
725732
$(OBJDIR)/sync.o \
726733
$(OBJDIR)/tag.o \
727734
$(OBJDIR)/tar.o \
728735
$(OBJDIR)/th_main.o \
@@ -936,11 +943,11 @@
936943
937944
$(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
938945
$(MKINDEX) $(TRANS_SRC) >$@
939946
940947
$(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
941
- $(MKBUILTIN) $(EXTRA_FILES) >$@
948
+ $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
942949
943950
$(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
944951
$(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
945952
$(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
946953
$(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1031,10 +1038,11 @@
10311038
$(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
10321039
$(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
10331040
$(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
10341041
$(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
10351042
$(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1043
+ $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
10361044
$(OBJDIR)/style_.c:$(OBJDIR)/style.h \
10371045
$(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
10381046
$(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
10391047
$(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
10401048
$(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1800,10 +1808,18 @@
18001808
18011809
$(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
18021810
$(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
18031811
18041812
$(OBJDIR)/stat.h: $(OBJDIR)/headers
1813
+
1814
+$(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(TRANSLATE)
1815
+ $(TRANSLATE) $(SRCDIR)/statrep.c >$@
1816
+
1817
+$(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1818
+ $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1819
+
1820
+$(OBJDIR)/statrep.h: $(OBJDIR)/headers
18051821
18061822
$(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
18071823
$(TRANSLATE) $(SRCDIR)/style.c >$@
18081824
18091825
$(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
18101826
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -457,10 +457,11 @@
457 $(SRCDIR)/sitemap.c \
458 $(SRCDIR)/skins.c \
459 $(SRCDIR)/sqlcmd.c \
460 $(SRCDIR)/stash.c \
461 $(SRCDIR)/stat.c \
 
462 $(SRCDIR)/style.c \
463 $(SRCDIR)/sync.c \
464 $(SRCDIR)/tag.c \
465 $(SRCDIR)/tar.c \
466 $(SRCDIR)/th_main.c \
@@ -496,20 +497,24 @@
496 $(SRCDIR)/../skins/eagle/footer.txt \
497 $(SRCDIR)/../skins/eagle/header.txt \
498 $(SRCDIR)/../skins/enhanced1/css.txt \
499 $(SRCDIR)/../skins/enhanced1/footer.txt \
500 $(SRCDIR)/../skins/enhanced1/header.txt \
 
 
 
501 $(SRCDIR)/../skins/khaki/css.txt \
502 $(SRCDIR)/../skins/khaki/footer.txt \
503 $(SRCDIR)/../skins/khaki/header.txt \
504 $(SRCDIR)/../skins/plain_gray/css.txt \
505 $(SRCDIR)/../skins/plain_gray/footer.txt \
506 $(SRCDIR)/../skins/plain_gray/header.txt \
507 $(SRCDIR)/../skins/rounded1/css.txt \
508 $(SRCDIR)/../skins/rounded1/footer.txt \
509 $(SRCDIR)/../skins/rounded1/header.txt \
510 $(SRCDIR)/diff.tcl
 
511
512 TRANS_SRC = \
513 $(OBJDIR)/add_.c \
514 $(OBJDIR)/allrepo_.c \
515 $(OBJDIR)/attach_.c \
@@ -600,10 +605,11 @@
600 $(OBJDIR)/sitemap_.c \
601 $(OBJDIR)/skins_.c \
602 $(OBJDIR)/sqlcmd_.c \
603 $(OBJDIR)/stash_.c \
604 $(OBJDIR)/stat_.c \
 
605 $(OBJDIR)/style_.c \
606 $(OBJDIR)/sync_.c \
607 $(OBJDIR)/tag_.c \
608 $(OBJDIR)/tar_.c \
609 $(OBJDIR)/th_main_.c \
@@ -719,10 +725,11 @@
719 $(OBJDIR)/sitemap.o \
720 $(OBJDIR)/skins.o \
721 $(OBJDIR)/sqlcmd.o \
722 $(OBJDIR)/stash.o \
723 $(OBJDIR)/stat.o \
 
724 $(OBJDIR)/style.o \
725 $(OBJDIR)/sync.o \
726 $(OBJDIR)/tag.o \
727 $(OBJDIR)/tar.o \
728 $(OBJDIR)/th_main.o \
@@ -936,11 +943,11 @@
936
937 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
938 $(MKINDEX) $(TRANS_SRC) >$@
939
940 $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
941 $(MKBUILTIN) $(EXTRA_FILES) >$@
942
943 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
944 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
945 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
946 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1031,10 +1038,11 @@
1031 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1032 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1033 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1034 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1035 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
 
1036 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1037 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1038 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1039 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1040 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1800,10 +1808,18 @@
1800
1801 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1802 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1803
1804 $(OBJDIR)/stat.h: $(OBJDIR)/headers
 
 
 
 
 
 
 
 
1805
1806 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
1807 $(TRANSLATE) $(SRCDIR)/style.c >$@
1808
1809 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1810
--- win/Makefile.mingw.mistachkin
+++ win/Makefile.mingw.mistachkin
@@ -457,10 +457,11 @@
457 $(SRCDIR)/sitemap.c \
458 $(SRCDIR)/skins.c \
459 $(SRCDIR)/sqlcmd.c \
460 $(SRCDIR)/stash.c \
461 $(SRCDIR)/stat.c \
462 $(SRCDIR)/statrep.c \
463 $(SRCDIR)/style.c \
464 $(SRCDIR)/sync.c \
465 $(SRCDIR)/tag.c \
466 $(SRCDIR)/tar.c \
467 $(SRCDIR)/th_main.c \
@@ -496,20 +497,24 @@
497 $(SRCDIR)/../skins/eagle/footer.txt \
498 $(SRCDIR)/../skins/eagle/header.txt \
499 $(SRCDIR)/../skins/enhanced1/css.txt \
500 $(SRCDIR)/../skins/enhanced1/footer.txt \
501 $(SRCDIR)/../skins/enhanced1/header.txt \
502 $(SRCDIR)/../skins/etienne1/css.txt \
503 $(SRCDIR)/../skins/etienne1/footer.txt \
504 $(SRCDIR)/../skins/etienne1/header.txt \
505 $(SRCDIR)/../skins/khaki/css.txt \
506 $(SRCDIR)/../skins/khaki/footer.txt \
507 $(SRCDIR)/../skins/khaki/header.txt \
508 $(SRCDIR)/../skins/plain_gray/css.txt \
509 $(SRCDIR)/../skins/plain_gray/footer.txt \
510 $(SRCDIR)/../skins/plain_gray/header.txt \
511 $(SRCDIR)/../skins/rounded1/css.txt \
512 $(SRCDIR)/../skins/rounded1/footer.txt \
513 $(SRCDIR)/../skins/rounded1/header.txt \
514 $(SRCDIR)/diff.tcl \
515 $(SRCDIR)/markdown.md
516
517 TRANS_SRC = \
518 $(OBJDIR)/add_.c \
519 $(OBJDIR)/allrepo_.c \
520 $(OBJDIR)/attach_.c \
@@ -600,10 +605,11 @@
605 $(OBJDIR)/sitemap_.c \
606 $(OBJDIR)/skins_.c \
607 $(OBJDIR)/sqlcmd_.c \
608 $(OBJDIR)/stash_.c \
609 $(OBJDIR)/stat_.c \
610 $(OBJDIR)/statrep_.c \
611 $(OBJDIR)/style_.c \
612 $(OBJDIR)/sync_.c \
613 $(OBJDIR)/tag_.c \
614 $(OBJDIR)/tar_.c \
615 $(OBJDIR)/th_main_.c \
@@ -719,10 +725,11 @@
725 $(OBJDIR)/sitemap.o \
726 $(OBJDIR)/skins.o \
727 $(OBJDIR)/sqlcmd.o \
728 $(OBJDIR)/stash.o \
729 $(OBJDIR)/stat.o \
730 $(OBJDIR)/statrep.o \
731 $(OBJDIR)/style.o \
732 $(OBJDIR)/sync.o \
733 $(OBJDIR)/tag.o \
734 $(OBJDIR)/tar.o \
735 $(OBJDIR)/th_main.o \
@@ -936,11 +943,11 @@
943
944 $(OBJDIR)/page_index.h: $(TRANS_SRC) $(MKINDEX)
945 $(MKINDEX) $(TRANS_SRC) >$@
946
947 $(OBJDIR)/builtin_data.h: $(MKBUILTIN) $(EXTRA_FILES)
948 $(MKBUILTIN) --prefix $(SRCDIR)/ $(EXTRA_FILES) >$@
949
950 $(OBJDIR)/headers: $(OBJDIR)/page_index.h $(OBJDIR)/builtin_data.h $(MAKEHEADERS) $(OBJDIR)/VERSION.h
951 $(MAKEHEADERS) $(OBJDIR)/add_.c:$(OBJDIR)/add.h \
952 $(OBJDIR)/allrepo_.c:$(OBJDIR)/allrepo.h \
953 $(OBJDIR)/attach_.c:$(OBJDIR)/attach.h \
@@ -1031,10 +1038,11 @@
1038 $(OBJDIR)/sitemap_.c:$(OBJDIR)/sitemap.h \
1039 $(OBJDIR)/skins_.c:$(OBJDIR)/skins.h \
1040 $(OBJDIR)/sqlcmd_.c:$(OBJDIR)/sqlcmd.h \
1041 $(OBJDIR)/stash_.c:$(OBJDIR)/stash.h \
1042 $(OBJDIR)/stat_.c:$(OBJDIR)/stat.h \
1043 $(OBJDIR)/statrep_.c:$(OBJDIR)/statrep.h \
1044 $(OBJDIR)/style_.c:$(OBJDIR)/style.h \
1045 $(OBJDIR)/sync_.c:$(OBJDIR)/sync.h \
1046 $(OBJDIR)/tag_.c:$(OBJDIR)/tag.h \
1047 $(OBJDIR)/tar_.c:$(OBJDIR)/tar.h \
1048 $(OBJDIR)/th_main_.c:$(OBJDIR)/th_main.h \
@@ -1800,10 +1808,18 @@
1808
1809 $(OBJDIR)/stat.o: $(OBJDIR)/stat_.c $(OBJDIR)/stat.h $(SRCDIR)/config.h
1810 $(XTCC) -o $(OBJDIR)/stat.o -c $(OBJDIR)/stat_.c
1811
1812 $(OBJDIR)/stat.h: $(OBJDIR)/headers
1813
1814 $(OBJDIR)/statrep_.c: $(SRCDIR)/statrep.c $(TRANSLATE)
1815 $(TRANSLATE) $(SRCDIR)/statrep.c >$@
1816
1817 $(OBJDIR)/statrep.o: $(OBJDIR)/statrep_.c $(OBJDIR)/statrep.h $(SRCDIR)/config.h
1818 $(XTCC) -o $(OBJDIR)/statrep.o -c $(OBJDIR)/statrep_.c
1819
1820 $(OBJDIR)/statrep.h: $(OBJDIR)/headers
1821
1822 $(OBJDIR)/style_.c: $(SRCDIR)/style.c $(TRANSLATE)
1823 $(TRANSLATE) $(SRCDIR)/style.c >$@
1824
1825 $(OBJDIR)/style.o: $(OBJDIR)/style_.c $(OBJDIR)/style.h $(SRCDIR)/config.h
1826
+13 -2
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -296,10 +296,11 @@
296296
sitemap_.c \
297297
skins_.c \
298298
sqlcmd_.c \
299299
stash_.c \
300300
stat_.c \
301
+ statrep_.c \
301302
style_.c \
302303
sync_.c \
303304
tag_.c \
304305
tar_.c \
305306
th_main_.c \
@@ -346,11 +347,12 @@
346347
$(SRCDIR)\../skins/plain_gray/footer.txt \
347348
$(SRCDIR)\../skins/plain_gray/header.txt \
348349
$(SRCDIR)\../skins/rounded1/css.txt \
349350
$(SRCDIR)\../skins/rounded1/footer.txt \
350351
$(SRCDIR)\../skins/rounded1/header.txt \
351
- $(SRCDIR)\diff.tcl
352
+ $(SRCDIR)\diff.tcl \
353
+ $(SRCDIR)\markdown.md
352354
353355
OBJ = $(OX)\add$O \
354356
$(OX)\allrepo$O \
355357
$(OX)\attach$O \
356358
$(OX)\bag$O \
@@ -443,10 +445,11 @@
443445
$(OX)\skins$O \
444446
$(OX)\sqlcmd$O \
445447
$(OX)\sqlite3$O \
446448
$(OX)\stash$O \
447449
$(OX)\stat$O \
450
+ $(OX)\statrep$O \
448451
$(OX)\style$O \
449452
$(OX)\sync$O \
450453
$(OX)\tag$O \
451454
$(OX)\tar$O \
452455
$(OX)\th$O \
@@ -617,10 +620,11 @@
617620
echo $(OX)\skins.obj >> $@
618621
echo $(OX)\sqlcmd.obj >> $@
619622
echo $(OX)\sqlite3.obj >> $@
620623
echo $(OX)\stash.obj >> $@
621624
echo $(OX)\stat.obj >> $@
625
+ echo $(OX)\statrep.obj >> $@
622626
echo $(OX)\style.obj >> $@
623627
echo $(OX)\sync.obj >> $@
624628
echo $(OX)\tag.obj >> $@
625629
echo $(OX)\tar.obj >> $@
626630
echo $(OX)\th.obj >> $@
@@ -698,11 +702,11 @@
698702
699703
page_index.h: mkindex$E $(SRC)
700704
$** > $@
701705
702706
builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
703
- $** > $@
707
+ mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
704708
705709
clean:
706710
-del $(OX)\*.obj
707711
-del *.obj
708712
-del *_.c
@@ -1295,10 +1299,16 @@
12951299
$(OX)\stat$O : stat_.c stat.h
12961300
$(TCC) /Fo$@ -c stat_.c
12971301
12981302
stat_.c : $(SRCDIR)\stat.c
12991303
translate$E $** > $@
1304
+
1305
+$(OX)\statrep$O : statrep_.c statrep.h
1306
+ $(TCC) /Fo$@ -c statrep_.c
1307
+
1308
+statrep_.c : $(SRCDIR)\statrep.c
1309
+ translate$E $** > $@
13001310
13011311
$(OX)\style$O : style_.c style.h
13021312
$(TCC) /Fo$@ -c style_.c
13031313
13041314
style_.c : $(SRCDIR)\style.c
@@ -1542,10 +1552,11 @@
15421552
sitemap_.c:sitemap.h \
15431553
skins_.c:skins.h \
15441554
sqlcmd_.c:sqlcmd.h \
15451555
stash_.c:stash.h \
15461556
stat_.c:stat.h \
1557
+ statrep_.c:statrep.h \
15471558
style_.c:style.h \
15481559
sync_.c:sync.h \
15491560
tag_.c:tag.h \
15501561
tar_.c:tar.h \
15511562
th_main_.c:th_main.h \
15521563
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -296,10 +296,11 @@
296 sitemap_.c \
297 skins_.c \
298 sqlcmd_.c \
299 stash_.c \
300 stat_.c \
 
301 style_.c \
302 sync_.c \
303 tag_.c \
304 tar_.c \
305 th_main_.c \
@@ -346,11 +347,12 @@
346 $(SRCDIR)\../skins/plain_gray/footer.txt \
347 $(SRCDIR)\../skins/plain_gray/header.txt \
348 $(SRCDIR)\../skins/rounded1/css.txt \
349 $(SRCDIR)\../skins/rounded1/footer.txt \
350 $(SRCDIR)\../skins/rounded1/header.txt \
351 $(SRCDIR)\diff.tcl
 
352
353 OBJ = $(OX)\add$O \
354 $(OX)\allrepo$O \
355 $(OX)\attach$O \
356 $(OX)\bag$O \
@@ -443,10 +445,11 @@
443 $(OX)\skins$O \
444 $(OX)\sqlcmd$O \
445 $(OX)\sqlite3$O \
446 $(OX)\stash$O \
447 $(OX)\stat$O \
 
448 $(OX)\style$O \
449 $(OX)\sync$O \
450 $(OX)\tag$O \
451 $(OX)\tar$O \
452 $(OX)\th$O \
@@ -617,10 +620,11 @@
617 echo $(OX)\skins.obj >> $@
618 echo $(OX)\sqlcmd.obj >> $@
619 echo $(OX)\sqlite3.obj >> $@
620 echo $(OX)\stash.obj >> $@
621 echo $(OX)\stat.obj >> $@
 
622 echo $(OX)\style.obj >> $@
623 echo $(OX)\sync.obj >> $@
624 echo $(OX)\tag.obj >> $@
625 echo $(OX)\tar.obj >> $@
626 echo $(OX)\th.obj >> $@
@@ -698,11 +702,11 @@
698
699 page_index.h: mkindex$E $(SRC)
700 $** > $@
701
702 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
703 $** > $@
704
705 clean:
706 -del $(OX)\*.obj
707 -del *.obj
708 -del *_.c
@@ -1295,10 +1299,16 @@
1295 $(OX)\stat$O : stat_.c stat.h
1296 $(TCC) /Fo$@ -c stat_.c
1297
1298 stat_.c : $(SRCDIR)\stat.c
1299 translate$E $** > $@
 
 
 
 
 
 
1300
1301 $(OX)\style$O : style_.c style.h
1302 $(TCC) /Fo$@ -c style_.c
1303
1304 style_.c : $(SRCDIR)\style.c
@@ -1542,10 +1552,11 @@
1542 sitemap_.c:sitemap.h \
1543 skins_.c:skins.h \
1544 sqlcmd_.c:sqlcmd.h \
1545 stash_.c:stash.h \
1546 stat_.c:stat.h \
 
1547 style_.c:style.h \
1548 sync_.c:sync.h \
1549 tag_.c:tag.h \
1550 tar_.c:tar.h \
1551 th_main_.c:th_main.h \
1552
--- win/Makefile.msc
+++ win/Makefile.msc
@@ -296,10 +296,11 @@
296 sitemap_.c \
297 skins_.c \
298 sqlcmd_.c \
299 stash_.c \
300 stat_.c \
301 statrep_.c \
302 style_.c \
303 sync_.c \
304 tag_.c \
305 tar_.c \
306 th_main_.c \
@@ -346,11 +347,12 @@
347 $(SRCDIR)\../skins/plain_gray/footer.txt \
348 $(SRCDIR)\../skins/plain_gray/header.txt \
349 $(SRCDIR)\../skins/rounded1/css.txt \
350 $(SRCDIR)\../skins/rounded1/footer.txt \
351 $(SRCDIR)\../skins/rounded1/header.txt \
352 $(SRCDIR)\diff.tcl \
353 $(SRCDIR)\markdown.md
354
355 OBJ = $(OX)\add$O \
356 $(OX)\allrepo$O \
357 $(OX)\attach$O \
358 $(OX)\bag$O \
@@ -443,10 +445,11 @@
445 $(OX)\skins$O \
446 $(OX)\sqlcmd$O \
447 $(OX)\sqlite3$O \
448 $(OX)\stash$O \
449 $(OX)\stat$O \
450 $(OX)\statrep$O \
451 $(OX)\style$O \
452 $(OX)\sync$O \
453 $(OX)\tag$O \
454 $(OX)\tar$O \
455 $(OX)\th$O \
@@ -617,10 +620,11 @@
620 echo $(OX)\skins.obj >> $@
621 echo $(OX)\sqlcmd.obj >> $@
622 echo $(OX)\sqlite3.obj >> $@
623 echo $(OX)\stash.obj >> $@
624 echo $(OX)\stat.obj >> $@
625 echo $(OX)\statrep.obj >> $@
626 echo $(OX)\style.obj >> $@
627 echo $(OX)\sync.obj >> $@
628 echo $(OX)\tag.obj >> $@
629 echo $(OX)\tar.obj >> $@
630 echo $(OX)\th.obj >> $@
@@ -698,11 +702,11 @@
702
703 page_index.h: mkindex$E $(SRC)
704 $** > $@
705
706 builtin_data.h: mkbuiltin$E $(EXTRA_FILES)
707 mkbuiltin$E --prefix $(SRCDIR)/ $(EXTRA_FILES) > $@
708
709 clean:
710 -del $(OX)\*.obj
711 -del *.obj
712 -del *_.c
@@ -1295,10 +1299,16 @@
1299 $(OX)\stat$O : stat_.c stat.h
1300 $(TCC) /Fo$@ -c stat_.c
1301
1302 stat_.c : $(SRCDIR)\stat.c
1303 translate$E $** > $@
1304
1305 $(OX)\statrep$O : statrep_.c statrep.h
1306 $(TCC) /Fo$@ -c statrep_.c
1307
1308 statrep_.c : $(SRCDIR)\statrep.c
1309 translate$E $** > $@
1310
1311 $(OX)\style$O : style_.c style.h
1312 $(TCC) /Fo$@ -c style_.c
1313
1314 style_.c : $(SRCDIR)\style.c
@@ -1542,10 +1552,11 @@
1552 sitemap_.c:sitemap.h \
1553 skins_.c:skins.h \
1554 sqlcmd_.c:sqlcmd.h \
1555 stash_.c:stash.h \
1556 stat_.c:stat.h \
1557 statrep_.c:statrep.h \
1558 style_.c:style.h \
1559 sync_.c:sync.h \
1560 tag_.c:tag.h \
1561 tar_.c:tar.h \
1562 th_main_.c:th_main.h \
1563

Keyboard Shortcuts

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