Fossil SCM

Merge from trunk.

jan 2011-04-02 14:42 UTC jan-clientcert merge
Commit e4ebc85e66cf8da8f31227ada77547cc1d401aa0
+97 -10
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
3636
*/
3737
void bisect_path(void){
3838
PathNode *p;
3939
bisect.bad = db_lget_int("bisect-bad", 0);
4040
if( bisect.bad==0 ){
41
- bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
42
- db_lset_int("bisect-bad", bisect.bad);
41
+ fossil_fatal("no \"bad\" version has been identified");
4342
}
4443
bisect.good = db_lget_int("bisect-good", 0);
4544
if( bisect.good==0 ){
46
- bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
47
- db_lset_int("bisect-good", bisect.good);
45
+ fossil_fatal("no \"good\" version has been identified");
4846
}
49
- p = path_shortest(bisect.good, bisect.bad, 0);
47
+ p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
5048
if( p==0 ){
5149
char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
5250
char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
5351
fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
5452
zGood, zBad);
5553
}
5654
}
55
+
56
+/*
57
+** The set of all bisect options.
58
+*/
59
+static const struct {
60
+ const char *zName;
61
+ const char *zDefault;
62
+ const char *zDesc;
63
+} aBisectOption[] = {
64
+ { "auto-next", "on", "Automatically run \"bisect next\" after each "
65
+ "\"bisect good\" or \"bisect bad\"" },
66
+ { "direct-only", "on", "Follow only primary parent-child links, not "
67
+ "merges\n" },
68
+};
69
+
70
+/*
71
+** Return the value of a boolean bisect option.
72
+*/
73
+int bisect_option(const char *zName){
74
+ unsigned int i;
75
+ int r = -1;
76
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
77
+ if( strcmp(zName, aBisectOption[i].zName)==0 ){
78
+ char *zLabel = mprintf("bisect-%s", zName);
79
+ char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault);
80
+ if( is_truth(z) ) r = 1;
81
+ if( is_false(z) ) r = 0;
82
+ if( r<0 ) r = is_truth(aBisectOption[i].zDefault);
83
+ free(zLabel);
84
+ break;
85
+ }
86
+ }
87
+ assert( r>=0 );
88
+ return r;
89
+}
5790
5891
/*
5992
** COMMAND: bisect
6093
**
6194
** Usage: %fossil bisect SUBCOMMAND ...
@@ -75,10 +108,15 @@
75108
** fossil bisect next
76109
**
77110
** Update to the next version that is halfway between the working and
78111
** non-working versions.
79112
**
113
+** fossil bisect options ?NAME? ?VALUE?
114
+**
115
+** List all bisect options, or the value of a single option, or set the
116
+** value of a bisect option.
117
+**
80118
** fossil bisect reset
81119
**
82120
** Reinitialize a bisect session. This cancels prior bisect history
83121
** and allows a bisect session to start over from the beginning.
84122
**
@@ -88,10 +126,13 @@
88126
*/
89127
void bisect_cmd(void){
90128
int n;
91129
const char *zCmd;
92130
db_must_be_within_tree();
131
+ if( g.argc<3 ){
132
+ usage("bisect SUBCOMMAND ARGS...");
133
+ }
93134
zCmd = g.argv[2];
94135
n = strlen(zCmd);
95136
if( n==0 ) zCmd = "-";
96137
if( memcmp(zCmd, "bad", n)==0 ){
97138
int ridBad;
@@ -99,19 +140,38 @@
99140
ridBad = db_lget_int("checkout",0);
100141
}else{
101142
ridBad = name_to_rid(g.argv[3]);
102143
}
103144
db_lset_int("bisect-bad", ridBad);
145
+ if( ridBad>0
146
+ && bisect_option("auto-next")
147
+ && db_lget_int("bisect-good",0)>0
148
+ ){
149
+ zCmd = "next";
150
+ n = 4;
151
+ }else{
152
+ return;
153
+ }
104154
}else if( memcmp(zCmd, "good", n)==0 ){
105155
int ridGood;
106156
if( g.argc==3 ){
107157
ridGood = db_lget_int("checkout",0);
108158
}else{
109159
ridGood = name_to_rid(g.argv[3]);
110160
}
111161
db_lset_int("bisect-good", ridGood);
112
- }else if( memcmp(zCmd, "next", n)==0 ){
162
+ if( ridGood>0
163
+ && bisect_option("auto-next")
164
+ && db_lget_int("bisect-bad",0)>0
165
+ ){
166
+ zCmd = "next";
167
+ n = 4;
168
+ }else{
169
+ return;
170
+ }
171
+ }
172
+ if( memcmp(zCmd, "next", n)==0 ){
113173
PathNode *pMid;
114174
bisect_path();
115175
pMid = path_midpoint();
116176
if( pMid==0 ){
117177
fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -119,16 +179,43 @@
119179
g.argv[1] = "update";
120180
g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
121181
g.argc = 3;
122182
g.fNoSync = 1;
123183
update_cmd();
184
+ }else if( memcmp(zCmd, "options", n)==0 ){
185
+ if( g.argc==3 ){
186
+ unsigned int i;
187
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
188
+ char *z = mprintf("bisect-%s", aBisectOption[i].zName);
189
+ printf(" %-15s %-6s ", aBisectOption[i].zName,
190
+ db_lget(z, (char*)aBisectOption[i].zDefault));
191
+ fossil_free(z);
192
+ comment_print(aBisectOption[i].zDesc, 27, 79);
193
+ }
194
+ }else if( g.argc==4 || g.argc==5 ){
195
+ unsigned int i;
196
+ n = strlen(g.argv[3]);
197
+ for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
198
+ if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
199
+ char *z = mprintf("bisect-%s", aBisectOption[i].zName);
200
+ if( g.argc==5 ){
201
+ db_lset(z, g.argv[4]);
202
+ }
203
+ printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
204
+ fossil_free(z);
205
+ break;
206
+ }
207
+ }
208
+ if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
209
+ fossil_fatal("no such bisect option: %s", g.argv[3]);
210
+ }
211
+ }else{
212
+ usage("bisect option ?NAME? ?VALUE?");
213
+ }
124214
}else if( memcmp(zCmd, "reset", n)==0 ){
125215
db_multi_exec(
126
- "REPLACE INTO vvar(name, value) "
127
- " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
128
- "REPLACE INTO vvar(name, value) "
129
- " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
216
+ "DELETE FROM vvar WHERE name IN ('bisect-good', 'bisect-bad');"
130217
);
131218
}else if( memcmp(zCmd, "vlist", n)==0 ){
132219
PathNode *p;
133220
int vid = db_lget_int("checkout", 0);
134221
int n;
135222
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
36 */
37 void bisect_path(void){
38 PathNode *p;
39 bisect.bad = db_lget_int("bisect-bad", 0);
40 if( bisect.bad==0 ){
41 bisect.bad = db_int(0, "SELECT cid FROM plink ORDER BY mtime DESC LIMIT 1");
42 db_lset_int("bisect-bad", bisect.bad);
43 }
44 bisect.good = db_lget_int("bisect-good", 0);
45 if( bisect.good==0 ){
46 bisect.good = db_int(0,"SELECT pid FROM plink ORDER BY mtime LIMIT 1");
47 db_lset_int("bisect-good", bisect.good);
48 }
49 p = path_shortest(bisect.good, bisect.bad, 0);
50 if( p==0 ){
51 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
52 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
53 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
54 zGood, zBad);
55 }
56 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
58 /*
59 ** COMMAND: bisect
60 **
61 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -75,10 +108,15 @@
75 ** fossil bisect next
76 **
77 ** Update to the next version that is halfway between the working and
78 ** non-working versions.
79 **
 
 
 
 
 
80 ** fossil bisect reset
81 **
82 ** Reinitialize a bisect session. This cancels prior bisect history
83 ** and allows a bisect session to start over from the beginning.
84 **
@@ -88,10 +126,13 @@
88 */
89 void bisect_cmd(void){
90 int n;
91 const char *zCmd;
92 db_must_be_within_tree();
 
 
 
93 zCmd = g.argv[2];
94 n = strlen(zCmd);
95 if( n==0 ) zCmd = "-";
96 if( memcmp(zCmd, "bad", n)==0 ){
97 int ridBad;
@@ -99,19 +140,38 @@
99 ridBad = db_lget_int("checkout",0);
100 }else{
101 ridBad = name_to_rid(g.argv[3]);
102 }
103 db_lset_int("bisect-bad", ridBad);
 
 
 
 
 
 
 
 
 
104 }else if( memcmp(zCmd, "good", n)==0 ){
105 int ridGood;
106 if( g.argc==3 ){
107 ridGood = db_lget_int("checkout",0);
108 }else{
109 ridGood = name_to_rid(g.argv[3]);
110 }
111 db_lset_int("bisect-good", ridGood);
112 }else if( memcmp(zCmd, "next", n)==0 ){
 
 
 
 
 
 
 
 
 
 
113 PathNode *pMid;
114 bisect_path();
115 pMid = path_midpoint();
116 if( pMid==0 ){
117 fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -119,16 +179,43 @@
119 g.argv[1] = "update";
120 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
121 g.argc = 3;
122 g.fNoSync = 1;
123 update_cmd();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124 }else if( memcmp(zCmd, "reset", n)==0 ){
125 db_multi_exec(
126 "REPLACE INTO vvar(name, value) "
127 " SELECT 'bisect-good', pid FROM plink ORDER BY mtime LIMIT 1;"
128 "REPLACE INTO vvar(name, value) "
129 " SELECT 'bisect-bad', cid FROM plink ORDER BY mtime DESC LIMIT 1;"
130 );
131 }else if( memcmp(zCmd, "vlist", n)==0 ){
132 PathNode *p;
133 int vid = db_lget_int("checkout", 0);
134 int n;
135
--- src/bisect.c
+++ src/bisect.c
@@ -36,26 +36,59 @@
36 */
37 void bisect_path(void){
38 PathNode *p;
39 bisect.bad = db_lget_int("bisect-bad", 0);
40 if( bisect.bad==0 ){
41 fossil_fatal("no \"bad\" version has been identified");
 
42 }
43 bisect.good = db_lget_int("bisect-good", 0);
44 if( bisect.good==0 ){
45 fossil_fatal("no \"good\" version has been identified");
 
46 }
47 p = path_shortest(bisect.good, bisect.bad, bisect_option("direct-only"));
48 if( p==0 ){
49 char *zBad = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.bad);
50 char *zGood = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", bisect.good);
51 fossil_fatal("no path from good ([%S]) to bad ([%S]) or back",
52 zGood, zBad);
53 }
54 }
55
56 /*
57 ** The set of all bisect options.
58 */
59 static const struct {
60 const char *zName;
61 const char *zDefault;
62 const char *zDesc;
63 } aBisectOption[] = {
64 { "auto-next", "on", "Automatically run \"bisect next\" after each "
65 "\"bisect good\" or \"bisect bad\"" },
66 { "direct-only", "on", "Follow only primary parent-child links, not "
67 "merges\n" },
68 };
69
70 /*
71 ** Return the value of a boolean bisect option.
72 */
73 int bisect_option(const char *zName){
74 unsigned int i;
75 int r = -1;
76 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
77 if( strcmp(zName, aBisectOption[i].zName)==0 ){
78 char *zLabel = mprintf("bisect-%s", zName);
79 char *z = db_lget(zLabel, (char*)aBisectOption[i].zDefault);
80 if( is_truth(z) ) r = 1;
81 if( is_false(z) ) r = 0;
82 if( r<0 ) r = is_truth(aBisectOption[i].zDefault);
83 free(zLabel);
84 break;
85 }
86 }
87 assert( r>=0 );
88 return r;
89 }
90
91 /*
92 ** COMMAND: bisect
93 **
94 ** Usage: %fossil bisect SUBCOMMAND ...
@@ -75,10 +108,15 @@
108 ** fossil bisect next
109 **
110 ** Update to the next version that is halfway between the working and
111 ** non-working versions.
112 **
113 ** fossil bisect options ?NAME? ?VALUE?
114 **
115 ** List all bisect options, or the value of a single option, or set the
116 ** value of a bisect option.
117 **
118 ** fossil bisect reset
119 **
120 ** Reinitialize a bisect session. This cancels prior bisect history
121 ** and allows a bisect session to start over from the beginning.
122 **
@@ -88,10 +126,13 @@
126 */
127 void bisect_cmd(void){
128 int n;
129 const char *zCmd;
130 db_must_be_within_tree();
131 if( g.argc<3 ){
132 usage("bisect SUBCOMMAND ARGS...");
133 }
134 zCmd = g.argv[2];
135 n = strlen(zCmd);
136 if( n==0 ) zCmd = "-";
137 if( memcmp(zCmd, "bad", n)==0 ){
138 int ridBad;
@@ -99,19 +140,38 @@
140 ridBad = db_lget_int("checkout",0);
141 }else{
142 ridBad = name_to_rid(g.argv[3]);
143 }
144 db_lset_int("bisect-bad", ridBad);
145 if( ridBad>0
146 && bisect_option("auto-next")
147 && db_lget_int("bisect-good",0)>0
148 ){
149 zCmd = "next";
150 n = 4;
151 }else{
152 return;
153 }
154 }else if( memcmp(zCmd, "good", n)==0 ){
155 int ridGood;
156 if( g.argc==3 ){
157 ridGood = db_lget_int("checkout",0);
158 }else{
159 ridGood = name_to_rid(g.argv[3]);
160 }
161 db_lset_int("bisect-good", ridGood);
162 if( ridGood>0
163 && bisect_option("auto-next")
164 && db_lget_int("bisect-bad",0)>0
165 ){
166 zCmd = "next";
167 n = 4;
168 }else{
169 return;
170 }
171 }
172 if( memcmp(zCmd, "next", n)==0 ){
173 PathNode *pMid;
174 bisect_path();
175 pMid = path_midpoint();
176 if( pMid==0 ){
177 fossil_fatal("bisect is done - there are no more intermediate versions");
@@ -119,16 +179,43 @@
179 g.argv[1] = "update";
180 g.argv[2] = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", pMid->rid);
181 g.argc = 3;
182 g.fNoSync = 1;
183 update_cmd();
184 }else if( memcmp(zCmd, "options", n)==0 ){
185 if( g.argc==3 ){
186 unsigned int i;
187 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
188 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
189 printf(" %-15s %-6s ", aBisectOption[i].zName,
190 db_lget(z, (char*)aBisectOption[i].zDefault));
191 fossil_free(z);
192 comment_print(aBisectOption[i].zDesc, 27, 79);
193 }
194 }else if( g.argc==4 || g.argc==5 ){
195 unsigned int i;
196 n = strlen(g.argv[3]);
197 for(i=0; i<sizeof(aBisectOption)/sizeof(aBisectOption[0]); i++){
198 if( memcmp(g.argv[3], aBisectOption[i].zName, n)==0 ){
199 char *z = mprintf("bisect-%s", aBisectOption[i].zName);
200 if( g.argc==5 ){
201 db_lset(z, g.argv[4]);
202 }
203 printf("%s\n", db_lget(z, (char*)aBisectOption[i].zDefault));
204 fossil_free(z);
205 break;
206 }
207 }
208 if( i>=sizeof(aBisectOption)/sizeof(aBisectOption[0]) ){
209 fossil_fatal("no such bisect option: %s", g.argv[3]);
210 }
211 }else{
212 usage("bisect option ?NAME? ?VALUE?");
213 }
214 }else if( memcmp(zCmd, "reset", n)==0 ){
215 db_multi_exec(
216 "DELETE FROM vvar WHERE name IN ('bisect-good', 'bisect-bad');"
 
 
 
217 );
218 }else if( memcmp(zCmd, "vlist", n)==0 ){
219 PathNode *p;
220 int vid = db_lget_int("checkout", 0);
221 int n;
222
+11 -1
--- src/info.c
+++ src/info.c
@@ -1442,18 +1442,18 @@
14421442
{ "#b0b0b0", 0 },
14431443
{ "#c0c0c0", 0 },
14441444
{ "#d0d0d0", 0 },
14451445
{ "#e0e0e0", 0 },
14461446
1447
- { "#c0ffc0", 0 },
14481447
{ "#c0fff0", 0 },
14491448
{ "#c0f0ff", 0 },
14501449
{ "#d0c0ff", 0 },
14511450
{ "#ffc0ff", 0 },
14521451
{ "#ffc0d0", 0 },
14531452
{ "#fff0c0", 0 },
14541453
{ "#f0ffc0", 0 },
1454
+ { "#c0ffc0", 0 },
14551455
14561456
{ "#a8d3c0", 0 },
14571457
{ "#a8c7d3", 0 },
14581458
{ "#aaa8d3", 0 },
14591459
{ "#cba8d3", 0 },
@@ -1468,10 +1468,20 @@
14681468
{ "#ab8eb2", 0 },
14691469
{ "#b28e9e", 0 },
14701470
{ "#b2988e", 0 },
14711471
{ "#b0b28e", 0 },
14721472
{ "#95b28e", 0 },
1473
+
1474
+ { "#80d6b0", 0 },
1475
+ { "#80bbd6", 0 },
1476
+ { "#8680d6", 0 },
1477
+ { "#c680d6", 0 },
1478
+ { "#d680a6", 0 },
1479
+ { "#d69b80", 0 },
1480
+ { "#d1d680", 0 },
1481
+ { "#91d680", 0 },
1482
+
14731483
14741484
{ "custom", "##" },
14751485
};
14761486
int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
14771487
int stdClrFound = 0;
14781488
--- src/info.c
+++ src/info.c
@@ -1442,18 +1442,18 @@
1442 { "#b0b0b0", 0 },
1443 { "#c0c0c0", 0 },
1444 { "#d0d0d0", 0 },
1445 { "#e0e0e0", 0 },
1446
1447 { "#c0ffc0", 0 },
1448 { "#c0fff0", 0 },
1449 { "#c0f0ff", 0 },
1450 { "#d0c0ff", 0 },
1451 { "#ffc0ff", 0 },
1452 { "#ffc0d0", 0 },
1453 { "#fff0c0", 0 },
1454 { "#f0ffc0", 0 },
 
1455
1456 { "#a8d3c0", 0 },
1457 { "#a8c7d3", 0 },
1458 { "#aaa8d3", 0 },
1459 { "#cba8d3", 0 },
@@ -1468,10 +1468,20 @@
1468 { "#ab8eb2", 0 },
1469 { "#b28e9e", 0 },
1470 { "#b2988e", 0 },
1471 { "#b0b28e", 0 },
1472 { "#95b28e", 0 },
 
 
 
 
 
 
 
 
 
 
1473
1474 { "custom", "##" },
1475 };
1476 int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1477 int stdClrFound = 0;
1478
--- src/info.c
+++ src/info.c
@@ -1442,18 +1442,18 @@
1442 { "#b0b0b0", 0 },
1443 { "#c0c0c0", 0 },
1444 { "#d0d0d0", 0 },
1445 { "#e0e0e0", 0 },
1446
 
1447 { "#c0fff0", 0 },
1448 { "#c0f0ff", 0 },
1449 { "#d0c0ff", 0 },
1450 { "#ffc0ff", 0 },
1451 { "#ffc0d0", 0 },
1452 { "#fff0c0", 0 },
1453 { "#f0ffc0", 0 },
1454 { "#c0ffc0", 0 },
1455
1456 { "#a8d3c0", 0 },
1457 { "#a8c7d3", 0 },
1458 { "#aaa8d3", 0 },
1459 { "#cba8d3", 0 },
@@ -1468,10 +1468,20 @@
1468 { "#ab8eb2", 0 },
1469 { "#b28e9e", 0 },
1470 { "#b2988e", 0 },
1471 { "#b0b28e", 0 },
1472 { "#95b28e", 0 },
1473
1474 { "#80d6b0", 0 },
1475 { "#80bbd6", 0 },
1476 { "#8680d6", 0 },
1477 { "#c680d6", 0 },
1478 { "#d680a6", 0 },
1479 { "#d69b80", 0 },
1480 { "#d1d680", 0 },
1481 { "#91d680", 0 },
1482
1483
1484 { "custom", "##" },
1485 };
1486 int nColor = sizeof(aColor)/sizeof(aColor[0])-1;
1487 int stdClrFound = 0;
1488
--- src/style.c
+++ src/style.c
@@ -739,10 +739,15 @@
739739
},
740740
{ "span.brokenlink",
741741
"a broken hyperlink",
742742
@ color: red;
743743
},
744
+ { "ul.filelist",
745
+ "List of files in a timeline",
746
+ @ margin-top: 3px;
747
+ @ line-height: 100%;
748
+ },
744749
{ 0,
745750
0,
746751
0
747752
}
748753
};
749754
--- src/style.c
+++ src/style.c
@@ -739,10 +739,15 @@
739 },
740 { "span.brokenlink",
741 "a broken hyperlink",
742 @ color: red;
743 },
 
 
 
 
 
744 { 0,
745 0,
746 0
747 }
748 };
749
--- src/style.c
+++ src/style.c
@@ -739,10 +739,15 @@
739 },
740 { "span.brokenlink",
741 "a broken hyperlink",
742 @ color: red;
743 },
744 { "ul.filelist",
745 "List of files in a timeline",
746 @ margin-top: 3px;
747 @ line-height: 100%;
748 },
749 { 0,
750 0,
751 0
752 }
753 };
754
--- src/timeline.c
+++ src/timeline.c
@@ -128,10 +128,11 @@
128128
#define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
129129
#define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
130130
#define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
131131
#define TIMELINE_GRAPH 0x0008 /* Compute a graph */
132132
#define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
133
+#define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
133134
#endif
134135
135136
/*
136137
** Output a timeline in the web format given a query. The query
137138
** should return these columns:
@@ -161,10 +162,12 @@
161162
int prevTagid = 0;
162163
int suppressCnt = 0;
163164
char zPrevDate[20];
164165
GraphContext *pGraph = 0;
165166
int prevWasDivider = 0; /* True if previous output row was <hr> */
167
+ int fchngQueryInit = 0; /* True if fchngQuery is initialized */
168
+ Stmt fchngQuery; /* Query for file changes on check-ins */
166169
167170
zPrevDate[0] = 0;
168171
mxWikiLen = db_get_int("timeline-max-comment", 0);
169172
if( db_get_boolean("timeline-block-markup", 0) ){
170173
wikiFlags = WIKI_INLINE;
@@ -339,10 +342,47 @@
339342
340343
/* Generate extra hyperlinks at the end of the comment */
341344
if( xExtra ){
342345
xExtra(rid);
343346
}
347
+
348
+ /* Generate the file-change list if requested */
349
+ if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' ){
350
+ int inUl = 0;
351
+ if( !fchngQueryInit ){
352
+ db_prepare(&fchngQuery,
353
+ "SELECT (pid==0) AS isnew,"
354
+ " (fid==0) AS isdel,"
355
+ " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name"
356
+ " FROM mlink"
357
+ " WHERE mid=:mid AND pid!=fid"
358
+ " ORDER BY 3"
359
+ );
360
+ fchngQueryInit = 1;
361
+ }
362
+ db_bind_int(&fchngQuery, ":mid", rid);
363
+ while( db_step(&fchngQuery)==SQLITE_ROW ){
364
+ const char *zFilename = db_column_text(&fchngQuery, 2);
365
+ int isNew = db_column_int(&fchngQuery, 0);
366
+ int isDel = db_column_int(&fchngQuery, 1);
367
+ if( !inUl ){
368
+ @ <ul class="filelist">
369
+ inUl = 1;
370
+ }
371
+ if( isNew ){
372
+ @ <li> %h(zFilename) (new file)</li>
373
+ }else if( isDel ){
374
+ @ <li> %h(zFilename) (deleted)</li>
375
+ }else{
376
+ @ <li> %h(zFilename) </li>
377
+ }
378
+ }
379
+ db_reset(&fchngQuery);
380
+ if( inUl ){
381
+ @ </ul>
382
+ }
383
+ }
344384
@ </td></tr>
345385
}
346386
if( suppressCnt ){
347387
@ <tr><td /><td /><td>
348388
@ <span class="timelineDisabled">... %d(suppressCnt) similar
@@ -362,10 +402,11 @@
362402
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
363403
@ </td></tr>
364404
}
365405
}
366406
@ </table>
407
+ if( fchngQueryInit ) db_finalize(&fchngQuery);
367408
timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
368409
}
369410
370411
/*
371412
** Generate all of the necessary javascript to generate a timeline
@@ -736,10 +777,11 @@
736777
** u=USER only if belonging to this user
737778
** y=TYPE 'ci', 'w', 't', 'e'
738779
** s=TEXT string search (comment and brief)
739780
** ng Suppress the graph if present
740781
** nd Suppress "divider" lines
782
+** fc Show details of files changed
741783
** f=RID Show family (immediate parents and children) of RID
742784
** from=RID Path from...
743785
** to=RID ... to this
744786
** nomerge ... avoid merge links on the path
745787
**
@@ -807,10 +849,14 @@
807849
blob_zero(&sql);
808850
blob_zero(&desc);
809851
blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
810852
blob_append(&sql, timeline_query_for_www(), -1);
811853
url_initialize(&url, "timeline");
854
+ if( P("fc")!=0 || P("detail")!=0 ){
855
+ tmFlags |= TIMELINE_FCHANGES;
856
+ url_add_parameter(&url, "fc", 0);
857
+ }
812858
if( !useDividers ) url_add_parameter(&url, "nd", 0);
813859
if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
814860
/* If from= and to= are present, display all nodes on a path connecting
815861
** the two */
816862
PathNode *p = 0;
@@ -1101,10 +1147,17 @@
11011147
if( nEntry>20 ){
11021148
timeline_submenu(&url, "20 Entries", "n", "20", 0);
11031149
}
11041150
if( nEntry<200 ){
11051151
timeline_submenu(&url, "200 Entries", "n", "200", 0);
1152
+ }
1153
+ if( zType[0]=='a' || zType[0]=='c' ){
1154
+ if( tmFlags & TIMELINE_FCHANGES ){
1155
+ timeline_submenu(&url, "Hide Files", "fc", 0, 0);
1156
+ }else{
1157
+ timeline_submenu(&url, "Show Files", "fc", "", 0);
1158
+ }
11061159
}
11071160
}
11081161
}
11091162
if( P("showsql") ){
11101163
@ <blockquote>%h(blob_str(&sql))</blockquote>
11111164
--- src/timeline.c
+++ src/timeline.c
@@ -128,10 +128,11 @@
128 #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
129 #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
130 #define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
131 #define TIMELINE_GRAPH 0x0008 /* Compute a graph */
132 #define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
 
133 #endif
134
135 /*
136 ** Output a timeline in the web format given a query. The query
137 ** should return these columns:
@@ -161,10 +162,12 @@
161 int prevTagid = 0;
162 int suppressCnt = 0;
163 char zPrevDate[20];
164 GraphContext *pGraph = 0;
165 int prevWasDivider = 0; /* True if previous output row was <hr> */
 
 
166
167 zPrevDate[0] = 0;
168 mxWikiLen = db_get_int("timeline-max-comment", 0);
169 if( db_get_boolean("timeline-block-markup", 0) ){
170 wikiFlags = WIKI_INLINE;
@@ -339,10 +342,47 @@
339
340 /* Generate extra hyperlinks at the end of the comment */
341 if( xExtra ){
342 xExtra(rid);
343 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344 @ </td></tr>
345 }
346 if( suppressCnt ){
347 @ <tr><td /><td /><td>
348 @ <span class="timelineDisabled">... %d(suppressCnt) similar
@@ -362,10 +402,11 @@
362 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
363 @ </td></tr>
364 }
365 }
366 @ </table>
 
367 timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
368 }
369
370 /*
371 ** Generate all of the necessary javascript to generate a timeline
@@ -736,10 +777,11 @@
736 ** u=USER only if belonging to this user
737 ** y=TYPE 'ci', 'w', 't', 'e'
738 ** s=TEXT string search (comment and brief)
739 ** ng Suppress the graph if present
740 ** nd Suppress "divider" lines
 
741 ** f=RID Show family (immediate parents and children) of RID
742 ** from=RID Path from...
743 ** to=RID ... to this
744 ** nomerge ... avoid merge links on the path
745 **
@@ -807,10 +849,14 @@
807 blob_zero(&sql);
808 blob_zero(&desc);
809 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
810 blob_append(&sql, timeline_query_for_www(), -1);
811 url_initialize(&url, "timeline");
 
 
 
 
812 if( !useDividers ) url_add_parameter(&url, "nd", 0);
813 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
814 /* If from= and to= are present, display all nodes on a path connecting
815 ** the two */
816 PathNode *p = 0;
@@ -1101,10 +1147,17 @@
1101 if( nEntry>20 ){
1102 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1103 }
1104 if( nEntry<200 ){
1105 timeline_submenu(&url, "200 Entries", "n", "200", 0);
 
 
 
 
 
 
 
1106 }
1107 }
1108 }
1109 if( P("showsql") ){
1110 @ <blockquote>%h(blob_str(&sql))</blockquote>
1111
--- src/timeline.c
+++ src/timeline.c
@@ -128,10 +128,11 @@
128 #define TIMELINE_ARTID 0x0001 /* Show artifact IDs on non-check-in lines */
129 #define TIMELINE_LEAFONLY 0x0002 /* Show "Leaf", but not "Merge", "Fork" etc */
130 #define TIMELINE_BRIEF 0x0004 /* Combine adjacent elements of same object */
131 #define TIMELINE_GRAPH 0x0008 /* Compute a graph */
132 #define TIMELINE_DISJOINT 0x0010 /* Elements are not contiguous */
133 #define TIMELINE_FCHANGES 0x0020 /* Detail file changes */
134 #endif
135
136 /*
137 ** Output a timeline in the web format given a query. The query
138 ** should return these columns:
@@ -161,10 +162,12 @@
162 int prevTagid = 0;
163 int suppressCnt = 0;
164 char zPrevDate[20];
165 GraphContext *pGraph = 0;
166 int prevWasDivider = 0; /* True if previous output row was <hr> */
167 int fchngQueryInit = 0; /* True if fchngQuery is initialized */
168 Stmt fchngQuery; /* Query for file changes on check-ins */
169
170 zPrevDate[0] = 0;
171 mxWikiLen = db_get_int("timeline-max-comment", 0);
172 if( db_get_boolean("timeline-block-markup", 0) ){
173 wikiFlags = WIKI_INLINE;
@@ -339,10 +342,47 @@
342
343 /* Generate extra hyperlinks at the end of the comment */
344 if( xExtra ){
345 xExtra(rid);
346 }
347
348 /* Generate the file-change list if requested */
349 if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' ){
350 int inUl = 0;
351 if( !fchngQueryInit ){
352 db_prepare(&fchngQuery,
353 "SELECT (pid==0) AS isnew,"
354 " (fid==0) AS isdel,"
355 " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name"
356 " FROM mlink"
357 " WHERE mid=:mid AND pid!=fid"
358 " ORDER BY 3"
359 );
360 fchngQueryInit = 1;
361 }
362 db_bind_int(&fchngQuery, ":mid", rid);
363 while( db_step(&fchngQuery)==SQLITE_ROW ){
364 const char *zFilename = db_column_text(&fchngQuery, 2);
365 int isNew = db_column_int(&fchngQuery, 0);
366 int isDel = db_column_int(&fchngQuery, 1);
367 if( !inUl ){
368 @ <ul class="filelist">
369 inUl = 1;
370 }
371 if( isNew ){
372 @ <li> %h(zFilename) (new file)</li>
373 }else if( isDel ){
374 @ <li> %h(zFilename) (deleted)</li>
375 }else{
376 @ <li> %h(zFilename) </li>
377 }
378 }
379 db_reset(&fchngQuery);
380 if( inUl ){
381 @ </ul>
382 }
383 }
384 @ </td></tr>
385 }
386 if( suppressCnt ){
387 @ <tr><td /><td /><td>
388 @ <span class="timelineDisabled">... %d(suppressCnt) similar
@@ -362,10 +402,11 @@
402 @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
403 @ </td></tr>
404 }
405 }
406 @ </table>
407 if( fchngQueryInit ) db_finalize(&fchngQuery);
408 timeline_output_graph_javascript(pGraph, (tmFlags & TIMELINE_DISJOINT)!=0);
409 }
410
411 /*
412 ** Generate all of the necessary javascript to generate a timeline
@@ -736,10 +777,11 @@
777 ** u=USER only if belonging to this user
778 ** y=TYPE 'ci', 'w', 't', 'e'
779 ** s=TEXT string search (comment and brief)
780 ** ng Suppress the graph if present
781 ** nd Suppress "divider" lines
782 ** fc Show details of files changed
783 ** f=RID Show family (immediate parents and children) of RID
784 ** from=RID Path from...
785 ** to=RID ... to this
786 ** nomerge ... avoid merge links on the path
787 **
@@ -807,10 +849,14 @@
849 blob_zero(&sql);
850 blob_zero(&desc);
851 blob_append(&sql, "INSERT OR IGNORE INTO timeline ", -1);
852 blob_append(&sql, timeline_query_for_www(), -1);
853 url_initialize(&url, "timeline");
854 if( P("fc")!=0 || P("detail")!=0 ){
855 tmFlags |= TIMELINE_FCHANGES;
856 url_add_parameter(&url, "fc", 0);
857 }
858 if( !useDividers ) url_add_parameter(&url, "nd", 0);
859 if( ((from_rid && to_rid) || (me_rid && you_rid)) && g.okRead ){
860 /* If from= and to= are present, display all nodes on a path connecting
861 ** the two */
862 PathNode *p = 0;
@@ -1101,10 +1147,17 @@
1147 if( nEntry>20 ){
1148 timeline_submenu(&url, "20 Entries", "n", "20", 0);
1149 }
1150 if( nEntry<200 ){
1151 timeline_submenu(&url, "200 Entries", "n", "200", 0);
1152 }
1153 if( zType[0]=='a' || zType[0]=='c' ){
1154 if( tmFlags & TIMELINE_FCHANGES ){
1155 timeline_submenu(&url, "Hide Files", "fc", 0, 0);
1156 }else{
1157 timeline_submenu(&url, "Show Files", "fc", "", 0);
1158 }
1159 }
1160 }
1161 }
1162 if( P("showsql") ){
1163 @ <blockquote>%h(blob_str(&sql))</blockquote>
1164
+4 -2
--- src/url.c
+++ src/url.c
@@ -355,14 +355,16 @@
355355
blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356356
if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357357
zSep = "&amp;";
358358
}
359359
if( zName1 && zValue1 ){
360
- blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
360
+ blob_appendf(&p->url, "%s%s", zSep, zName1);
361
+ if( zValue1[0] ) blob_appendf(&p->url, "=%T", zValue1);
361362
}
362363
if( zName2 && zValue2 ){
363
- blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
364
+ blob_appendf(&p->url, "%s%s", zSep, zName2);
365
+ if( zValue2[0] ) blob_appendf(&p->url, "=%T", zValue2);
364366
}
365367
return blob_str(&p->url);
366368
}
367369
368370
/*
369371
--- src/url.c
+++ src/url.c
@@ -355,14 +355,16 @@
355 blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356 if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357 zSep = "&amp;";
358 }
359 if( zName1 && zValue1 ){
360 blob_appendf(&p->url, "%s%s=%T", zSep, zName1, zValue1);
 
361 }
362 if( zName2 && zValue2 ){
363 blob_appendf(&p->url, "%s%s=%T", zSep, zName2, zValue2);
 
364 }
365 return blob_str(&p->url);
366 }
367
368 /*
369
--- src/url.c
+++ src/url.c
@@ -355,14 +355,16 @@
355 blob_appendf(&p->url, "%s%s", zSep, p->azName[i]);
356 if( z && z[0] ) blob_appendf(&p->url, "=%T", z);
357 zSep = "&amp;";
358 }
359 if( zName1 && zValue1 ){
360 blob_appendf(&p->url, "%s%s", zSep, zName1);
361 if( zValue1[0] ) blob_appendf(&p->url, "=%T", zValue1);
362 }
363 if( zName2 && zValue2 ){
364 blob_appendf(&p->url, "%s%s", zSep, zName2);
365 if( zValue2[0] ) blob_appendf(&p->url, "=%T", zValue2);
366 }
367 return blob_str(&p->url);
368 }
369
370 /*
371

Keyboard Shortcuts

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