Fossil SCM

Begin work merging new_brlist_page() into brlist_page(). Annoyance: The new open/closed checkboxes don't quite work the way I want them to work. Deselecting both has the effect of selecting both. This makes sense in that if neither the open nor closed query parameters are given, everything should be displayed, rather than nothing. Yet, the user interface would be nicer if deselecting the only selected checkbox causes the other checkbox to be selected. This can't be done with straight HTML because deselecting the checkbox removes it from the query string, and the server does not know which checkbox was deselected so it cannot force the other one to become selected. As far as I know, JavaScript is required. Bug: Non-aggregate HAVING clause expressions are evaluated on an arbitrarily chosen row within each group. This breaks closed and open filtering for the command-line branch command and the new checkboxes. But shouldn't this also break non-aggregate result expressions? Wish: Filter on normal/hidden branches too. Wish: If a merged-to branch is hidden, don't show it in the resolution column, instead show something else. The latest merged-to? The earliest merged-to?

andygoth 2016-11-16 21:59 UTC trunk
Commit a6a4482056851df4b3d194d1b524d6e252e92df0
1 file changed +101 -186
+101 -186
--- src/branch.c
+++ src/branch.c
@@ -187,62 +187,63 @@
187187
*/
188188
#define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
189189
#define BRL_OPEN_ONLY 0x002 /* Show only open branches */
190190
#define BRL_BOTH 0x003 /* Show both open and closed branches */
191191
#define BRL_OPEN_CLOSED_MASK 0x003
192
-#define BRL_MTIME 0x004 /* Include lastest check-in time */
193
-#define BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/
192
+#define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
194193
195194
#endif /* INTERFACE */
196195
197196
/*
198197
** Prepare a query that will list branches.
199
-**
200
-** If (which<0) then the query pulls only closed branches. If
201
-** (which>0) then the query pulls all (closed and opened)
202
-** branches. Else the query pulls currently-opened branches.
203198
*/
204199
void branch_prepare_list_query(Stmt *pQuery, int brFlags){
205
- switch( brFlags & BRL_OPEN_CLOSED_MASK ){
206
- case BRL_CLOSED_ONLY: {
207
- db_prepare(pQuery,
208
- "SELECT value FROM tagxref"
209
- " WHERE tagid=%d AND value NOT NULL "
210
- "EXCEPT "
211
- "SELECT value FROM tagxref"
212
- " WHERE tagid=%d"
213
- " AND rid IN leaf"
214
- " AND NOT %z"
215
- " ORDER BY value COLLATE nocase /*sort*/",
216
- TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
217
- );
218
- break;
219
- }
220
- case BRL_BOTH: {
221
- db_prepare(pQuery,
222
- "SELECT DISTINCT value FROM tagxref"
223
- " WHERE tagid=%d AND value NOT NULL"
224
- " AND rid IN leaf"
225
- " ORDER BY value COLLATE nocase /*sort*/",
226
- TAG_BRANCH
227
- );
228
- break;
229
- }
230
- case BRL_OPEN_ONLY: {
231
- db_prepare(pQuery,
232
- "SELECT DISTINCT value FROM tagxref"
233
- " WHERE tagid=%d AND value NOT NULL"
234
- " AND rid IN leaf"
235
- " AND NOT %z"
236
- " ORDER BY value COLLATE nocase /*sort*/",
237
- TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
238
- );
239
- break;
240
- }
241
- }
242
-}
243
-
200
+ Blob sql = BLOB_INITIALIZER;
201
+ blob_zero(&sql);
202
+
203
+ /* Begin the query. */
204
+ blob_append_sql(&sql,
205
+ "SELECT tagxref.value AS name"
206
+ ", max(event.mtime) AS mtime"
207
+ ", %z AS closed"
208
+ ", (SELECT tagxref.value"
209
+ " FROM plink CROSS JOIN tagxref"
210
+ " WHERE plink.pid=event.objid"
211
+ " AND tagxref.rid=plink.cid"
212
+ " AND tagxref.tagid=%d"
213
+ " AND tagtype>0) AS mergeto"
214
+ ", count(*) AS cicount"
215
+ ", (SELECT uuid FROM blob WHERE rid=tagxref.rid) AS latest"
216
+ ", event.bgcolor AS bgcolor"
217
+ " FROM tagxref, tag, event"
218
+ " WHERE tagxref.tagid=tag.tagid"
219
+ " AND tagxref.tagtype>0"
220
+ " AND tag.tagname='branch'"
221
+ " AND event.objid=tagxref.rid",
222
+ leaf_is_closed_sql("tagxref.rid"), TAG_BRANCH);
223
+
224
+ /* Group by name to implement the cicount column. */
225
+ blob_append_sql(&sql, " GROUP BY name");
226
+
227
+ /* Apply open/closed filtering if requested. */
228
+ if( (brFlags & BRL_OPEN_CLOSED_MASK)==BRL_CLOSED_ONLY ){
229
+ blob_append_sql(&sql, " HAVING min(closed)");
230
+ }else if( (brFlags & BRL_OPEN_CLOSED_MASK)==BRL_OPEN_ONLY ){
231
+ blob_append_sql(&sql, " HAVING NOT min(closed)");
232
+ }
233
+
234
+ /* Apply the requested sort order. */
235
+ if( brFlags & BRL_ORDERBY_MTIME ){
236
+ blob_append_sql(&sql, " ORDER BY mtime DESC");
237
+ }else{
238
+ blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
239
+ }
240
+
241
+ /* Prepare the query. */
242
+ db_prepare(pQuery, "%s", blob_sql_text(&sql));
243
+ blob_reset(&sql);
244
+}
244245
245246
/*
246247
** COMMAND: branch
247248
**
248249
** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
@@ -307,63 +308,79 @@
307308
fossil_fatal("branch subcommand should be one of: "
308309
"new list ls");
309310
}
310311
}
311312
312
-static const char brlistQuery[] =
313
-@ SELECT
314
-@ tagxref.value,
315
-@ max(event.mtime),
316
-@ EXISTS(SELECT 1 FROM tagxref AS tx
317
-@ WHERE tx.rid=tagxref.rid
318
-@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
319
-@ AND tx.tagtype>0),
320
-@ (SELECT tagxref.value
321
-@ FROM plink CROSS JOIN tagxref
322
-@ WHERE plink.pid=event.objid
323
-@ AND tagxref.rid=plink.cid
324
-@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
325
-@ AND tagtype>0),
326
-@ count(*),
327
-@ (SELECT uuid FROM blob WHERE rid=tagxref.rid),
328
-@ event.bgcolor
329
-@ FROM tagxref, tag, event
330
-@ WHERE tagxref.tagid=tag.tagid
331
-@ AND tagxref.tagtype>0
332
-@ AND tag.tagname='branch'
333
-@ AND event.objid=tagxref.rid
334
-@ GROUP BY 1
335
-@ ORDER BY 2 DESC;
336
-;
337
-
338313
/*
339
-** This is the new-style branch-list page that shows the branch names
340
-** together with their ages (time of last check-in) and whether or not
341
-** they are closed or merged to another branch.
314
+** WEBPAGE: brlist
315
+** Show a sortable list of branches.
316
+**
317
+** Query parameters:
342318
**
343
-** Control jumps to this routine from brlist_page() (the /brlist handler)
344
-** if there are no query parameters.
319
+** all Same as open&closed
320
+** open Show open branches
321
+** closed Show closed branches
322
+** colors Show assigned branch colors (alias: colortest)
345323
*/
346
-static void new_brlist_page(void){
324
+void brlist_page(void){
347325
Stmt q;
348326
double rNow;
349
- int show_colors = PB("colors");
327
+ int colors, flags = BRL_ORDERBY_MTIME;
328
+
329
+ /* Intepret colortest as colors=1. */
330
+ if( PB("colortest") ){
331
+ cgi_replace_query_parameter("colors", "1");
332
+ }
333
+ cgi_delete_query_parameter("colortest");
334
+
335
+ /* Interpret all as open=1&closed=1&normal=1&hidden=1. */
336
+ if( PB("all") ){
337
+ cgi_replace_query_parameter("open", "1");
338
+ cgi_replace_query_parameter("closed", "1");
339
+/* cgi_replace_query_parameter("normal", "1");
340
+ cgi_replace_query_parameter("hidden", "1");*/
341
+ }
342
+ cgi_delete_query_parameter("all");
343
+
344
+ /* Interpret open=0&closed=0 (or omitted) as open=1&closed=1. */
345
+ if( !PB("open") && !PB("closed") ){
346
+ cgi_replace_query_parameter("open", "1");
347
+ cgi_replace_query_parameter("closed", "1");
348
+ }
349
+
350
+ /* Interpret normal=0&hidden=0 (or omitted) as normal=1&hidden=1. */
351
+/*if( !PB("normal") && !PB("hidden") ){
352
+ cgi_replace_query_parameter("normal", "1");
353
+ cgi_replace_query_parameter("hidden", "1");
354
+ }*/
355
+
356
+ /* Process query parameters. */
357
+ colors = PB("colors");
358
+ if( PB("open" ) ){flags |= BRL_OPEN_ONLY ;}
359
+ if( PB("closed") ){flags |= BRL_CLOSED_ONLY;}
360
+
350361
login_check_credentials();
351362
if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
352363
style_header("Branches");
353364
style_adunit_config(ADUNIT_RIGHT_OK);
354
- style_submenu_checkbox("colors", "Use Branch Colors", 0);
365
+ style_submenu_checkbox("colors", "Colors", 0);
366
+ style_submenu_checkbox("open", "Open", 0);
367
+ style_submenu_checkbox("closed", "Closed", 0);
368
+/*style_submenu_checkbox("normal", "Normal", 0);
369
+ style_submenu_checkbox("hidden", "Hidden", 0);*/
355370
login_anonymous_available();
356371
357
- db_prepare(&q, brlistQuery/*works-like:""*/);
372
+ branch_prepare_list_query(&q, flags);
358373
rNow = db_double(0.0, "SELECT julianday('now')");
359374
@ <div class="brlist"><table id="branchlisttable">
360375
@ <thead><tr>
361376
@ <th>Branch Name</th>
362377
@ <th>Age</th>
363378
@ <th>Check-ins</th>
379
+ if( (flags & BRL_OPEN_CLOSED_MASK) == BRL_BOTH ){
364380
@ <th>Status</th>
381
+ }
365382
@ <th>Resolution</th>
366383
@ </tr></thead><tbody>
367384
while( db_step(&q)==SQLITE_ROW ){
368385
const char *zBranch = db_column_text(&q, 0);
369386
double rMtime = db_column_double(&q, 1);
@@ -380,20 +397,22 @@
380397
zBgClr = 0;
381398
}else{
382399
zBgClr = hash_color(zBranch);
383400
}
384401
}
385
- if( zBgClr && zBgClr[0] && show_colors ){
402
+ if( zBgClr && zBgClr[0] && colors ){
386403
@ <tr style="background-color:%s(zBgClr)">
387404
}else{
388405
@ <tr>
389406
}
390407
@ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
391408
@ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
392409
@ <td>%d(nCkin)</td>
393410
fossil_free(zAge);
394
- @ <td>%s(isClosed?"closed":"")</td>
411
+ if( (flags & BRL_OPEN_CLOSED_MASK) == BRL_BOTH ){
412
+ @ <td>%s(isClosed?"closed":"")</td>
413
+ }
395414
if( zMergeTo ){
396415
@ <td>merged into
397416
@ %z(href("%R/timeline?f=%!S",zLastCkin))%h(zMergeTo)</a></td>
398417
}else{
399418
@ <td></td>
@@ -404,114 +423,10 @@
404423
db_finalize(&q);
405424
output_table_sorting_javascript("branchlisttable","tkNtt",2);
406425
style_footer();
407426
}
408427
409
-/*
410
-** WEBPAGE: brlist
411
-** Show a list of branches. With no query parameters, a sortable table
412
-** is used to show all branches. If query parameters are present a
413
-** fixed bullet list is shown.
414
-**
415
-** Query parameters:
416
-**
417
-** all Show all branches
418
-** closed Show only closed branches
419
-** open Show only open branches (default behavior)
420
-** colortest Show all branches with automatic color
421
-*/
422
-void brlist_page(void){
423
- Stmt q;
424
- int cnt;
425
- int showClosed = P("closed")!=0;
426
- int showAll = P("all")!=0;
427
- int showOpen = P("open")!=0;
428
- int colorTest = P("colortest")!=0;
429
- int brFlags = BRL_OPEN_ONLY;
430
-
431
- if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
432
- new_brlist_page();
433
- return;
434
- }
435
- login_check_credentials();
436
- if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
437
- if( colorTest ){
438
- showClosed = 0;
439
- showAll = 1;
440
- }
441
- if( showAll ) brFlags = BRL_BOTH;
442
- if( showClosed ) brFlags = BRL_CLOSED_ONLY;
443
-
444
- style_header("%s", showClosed ? "Closed Branches" :
445
- showAll ? "All Branches" : "Open Branches");
446
- style_submenu_element("Timeline", "brtimeline");
447
- if( showClosed ){
448
- style_submenu_element("All", "brlist?all");
449
- style_submenu_element("Open", "brlist?open");
450
- }else if( showAll ){
451
- style_submenu_element("Closed", "brlist?closed");
452
- style_submenu_element("Open", "brlist");
453
- }else{
454
- style_submenu_element("All", "brlist?all");
455
- style_submenu_element("Closed", "brlist?closed");
456
- }
457
- if( !colorTest ){
458
- style_submenu_element("Color-Test", "brlist?colortest");
459
- }else{
460
- style_submenu_element("All", "brlist?all");
461
- }
462
- login_anonymous_available();
463
-#if 0
464
- style_sidebox_begin("Nomenclature:", "33%");
465
- @ <ol>
466
- @ <li> An <div class="sideboxDescribed">%z(href("brlist"))
467
- @ open branch</a></div> is a branch that has one or more
468
- @ <div class="sideboxDescribed">%z(href("leaves"))open leaves.</a></div>
469
- @ The presence of open leaves presumably means
470
- @ that the branch is still being extended with new check-ins.</li>
471
- @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
472
- @ closed branch</a></div> is a branch with only
473
- @ <div class="sideboxDescribed">%z(href("leaves?closed"))
474
- @ closed leaves</a></div>.
475
- @ Closed branches are fixed and do not change (unless they are first
476
- @ reopened).</li>
477
- @ </ol>
478
- style_sidebox_end();
479
-#endif
480
-
481
- branch_prepare_list_query(&q, brFlags);
482
- cnt = 0;
483
- while( db_step(&q)==SQLITE_ROW ){
484
- const char *zBr = db_column_text(&q, 0);
485
- if( cnt==0 ){
486
- if( colorTest ){
487
- @ <h2>Default background colors for all branches:</h2>
488
- }else if( showClosed ){
489
- @ <h2>Closed Branches:</h2>
490
- }else if( showAll ){
491
- @ <h2>All Branches:</h2>
492
- }else{
493
- @ <h2>Open Branches:</h2>
494
- }
495
- @ <ul>
496
- cnt++;
497
- }
498
- if( colorTest ){
499
- const char *zColor = hash_color(zBr);
500
- @ <li><span style="background-color: %s(zColor)">
501
- @ %h(zBr) &rarr; %s(zColor)</span></li>
502
- }else{
503
- @ <li>%z(href("%R/timeline?r=%T&n=200",zBr))%h(zBr)</a></li>
504
- }
505
- }
506
- if( cnt ){
507
- @ </ul>
508
- }
509
- db_finalize(&q);
510
- style_footer();
511
-}
512
-
513428
/*
514429
** This routine is called while for each check-in that is rendered by
515430
** the timeline of a "brlist" page. Add some additional hyperlinks
516431
** to the end of the line.
517432
*/
518433
--- src/branch.c
+++ src/branch.c
@@ -187,62 +187,63 @@
187 */
188 #define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
189 #define BRL_OPEN_ONLY 0x002 /* Show only open branches */
190 #define BRL_BOTH 0x003 /* Show both open and closed branches */
191 #define BRL_OPEN_CLOSED_MASK 0x003
192 #define BRL_MTIME 0x004 /* Include lastest check-in time */
193 #define BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/
194
195 #endif /* INTERFACE */
196
197 /*
198 ** Prepare a query that will list branches.
199 **
200 ** If (which<0) then the query pulls only closed branches. If
201 ** (which>0) then the query pulls all (closed and opened)
202 ** branches. Else the query pulls currently-opened branches.
203 */
204 void branch_prepare_list_query(Stmt *pQuery, int brFlags){
205 switch( brFlags & BRL_OPEN_CLOSED_MASK ){
206 case BRL_CLOSED_ONLY: {
207 db_prepare(pQuery,
208 "SELECT value FROM tagxref"
209 " WHERE tagid=%d AND value NOT NULL "
210 "EXCEPT "
211 "SELECT value FROM tagxref"
212 " WHERE tagid=%d"
213 " AND rid IN leaf"
214 " AND NOT %z"
215 " ORDER BY value COLLATE nocase /*sort*/",
216 TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
217 );
218 break;
219 }
220 case BRL_BOTH: {
221 db_prepare(pQuery,
222 "SELECT DISTINCT value FROM tagxref"
223 " WHERE tagid=%d AND value NOT NULL"
224 " AND rid IN leaf"
225 " ORDER BY value COLLATE nocase /*sort*/",
226 TAG_BRANCH
227 );
228 break;
229 }
230 case BRL_OPEN_ONLY: {
231 db_prepare(pQuery,
232 "SELECT DISTINCT value FROM tagxref"
233 " WHERE tagid=%d AND value NOT NULL"
234 " AND rid IN leaf"
235 " AND NOT %z"
236 " ORDER BY value COLLATE nocase /*sort*/",
237 TAG_BRANCH, leaf_is_closed_sql("tagxref.rid")
238 );
239 break;
240 }
241 }
242 }
243
 
 
 
 
 
 
244
245 /*
246 ** COMMAND: branch
247 **
248 ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
@@ -307,63 +308,79 @@
307 fossil_fatal("branch subcommand should be one of: "
308 "new list ls");
309 }
310 }
311
312 static const char brlistQuery[] =
313 @ SELECT
314 @ tagxref.value,
315 @ max(event.mtime),
316 @ EXISTS(SELECT 1 FROM tagxref AS tx
317 @ WHERE tx.rid=tagxref.rid
318 @ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed')
319 @ AND tx.tagtype>0),
320 @ (SELECT tagxref.value
321 @ FROM plink CROSS JOIN tagxref
322 @ WHERE plink.pid=event.objid
323 @ AND tagxref.rid=plink.cid
324 @ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch')
325 @ AND tagtype>0),
326 @ count(*),
327 @ (SELECT uuid FROM blob WHERE rid=tagxref.rid),
328 @ event.bgcolor
329 @ FROM tagxref, tag, event
330 @ WHERE tagxref.tagid=tag.tagid
331 @ AND tagxref.tagtype>0
332 @ AND tag.tagname='branch'
333 @ AND event.objid=tagxref.rid
334 @ GROUP BY 1
335 @ ORDER BY 2 DESC;
336 ;
337
338 /*
339 ** This is the new-style branch-list page that shows the branch names
340 ** together with their ages (time of last check-in) and whether or not
341 ** they are closed or merged to another branch.
 
342 **
343 ** Control jumps to this routine from brlist_page() (the /brlist handler)
344 ** if there are no query parameters.
 
 
345 */
346 static void new_brlist_page(void){
347 Stmt q;
348 double rNow;
349 int show_colors = PB("colors");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350 login_check_credentials();
351 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
352 style_header("Branches");
353 style_adunit_config(ADUNIT_RIGHT_OK);
354 style_submenu_checkbox("colors", "Use Branch Colors", 0);
 
 
 
 
355 login_anonymous_available();
356
357 db_prepare(&q, brlistQuery/*works-like:""*/);
358 rNow = db_double(0.0, "SELECT julianday('now')");
359 @ <div class="brlist"><table id="branchlisttable">
360 @ <thead><tr>
361 @ <th>Branch Name</th>
362 @ <th>Age</th>
363 @ <th>Check-ins</th>
 
364 @ <th>Status</th>
 
365 @ <th>Resolution</th>
366 @ </tr></thead><tbody>
367 while( db_step(&q)==SQLITE_ROW ){
368 const char *zBranch = db_column_text(&q, 0);
369 double rMtime = db_column_double(&q, 1);
@@ -380,20 +397,22 @@
380 zBgClr = 0;
381 }else{
382 zBgClr = hash_color(zBranch);
383 }
384 }
385 if( zBgClr && zBgClr[0] && show_colors ){
386 @ <tr style="background-color:%s(zBgClr)">
387 }else{
388 @ <tr>
389 }
390 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
391 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
392 @ <td>%d(nCkin)</td>
393 fossil_free(zAge);
394 @ <td>%s(isClosed?"closed":"")</td>
 
 
395 if( zMergeTo ){
396 @ <td>merged into
397 @ %z(href("%R/timeline?f=%!S",zLastCkin))%h(zMergeTo)</a></td>
398 }else{
399 @ <td></td>
@@ -404,114 +423,10 @@
404 db_finalize(&q);
405 output_table_sorting_javascript("branchlisttable","tkNtt",2);
406 style_footer();
407 }
408
409 /*
410 ** WEBPAGE: brlist
411 ** Show a list of branches. With no query parameters, a sortable table
412 ** is used to show all branches. If query parameters are present a
413 ** fixed bullet list is shown.
414 **
415 ** Query parameters:
416 **
417 ** all Show all branches
418 ** closed Show only closed branches
419 ** open Show only open branches (default behavior)
420 ** colortest Show all branches with automatic color
421 */
422 void brlist_page(void){
423 Stmt q;
424 int cnt;
425 int showClosed = P("closed")!=0;
426 int showAll = P("all")!=0;
427 int showOpen = P("open")!=0;
428 int colorTest = P("colortest")!=0;
429 int brFlags = BRL_OPEN_ONLY;
430
431 if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){
432 new_brlist_page();
433 return;
434 }
435 login_check_credentials();
436 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
437 if( colorTest ){
438 showClosed = 0;
439 showAll = 1;
440 }
441 if( showAll ) brFlags = BRL_BOTH;
442 if( showClosed ) brFlags = BRL_CLOSED_ONLY;
443
444 style_header("%s", showClosed ? "Closed Branches" :
445 showAll ? "All Branches" : "Open Branches");
446 style_submenu_element("Timeline", "brtimeline");
447 if( showClosed ){
448 style_submenu_element("All", "brlist?all");
449 style_submenu_element("Open", "brlist?open");
450 }else if( showAll ){
451 style_submenu_element("Closed", "brlist?closed");
452 style_submenu_element("Open", "brlist");
453 }else{
454 style_submenu_element("All", "brlist?all");
455 style_submenu_element("Closed", "brlist?closed");
456 }
457 if( !colorTest ){
458 style_submenu_element("Color-Test", "brlist?colortest");
459 }else{
460 style_submenu_element("All", "brlist?all");
461 }
462 login_anonymous_available();
463 #if 0
464 style_sidebox_begin("Nomenclature:", "33%");
465 @ <ol>
466 @ <li> An <div class="sideboxDescribed">%z(href("brlist"))
467 @ open branch</a></div> is a branch that has one or more
468 @ <div class="sideboxDescribed">%z(href("leaves"))open leaves.</a></div>
469 @ The presence of open leaves presumably means
470 @ that the branch is still being extended with new check-ins.</li>
471 @ <li> A <div class="sideboxDescribed">%z(href("brlist?closed"))
472 @ closed branch</a></div> is a branch with only
473 @ <div class="sideboxDescribed">%z(href("leaves?closed"))
474 @ closed leaves</a></div>.
475 @ Closed branches are fixed and do not change (unless they are first
476 @ reopened).</li>
477 @ </ol>
478 style_sidebox_end();
479 #endif
480
481 branch_prepare_list_query(&q, brFlags);
482 cnt = 0;
483 while( db_step(&q)==SQLITE_ROW ){
484 const char *zBr = db_column_text(&q, 0);
485 if( cnt==0 ){
486 if( colorTest ){
487 @ <h2>Default background colors for all branches:</h2>
488 }else if( showClosed ){
489 @ <h2>Closed Branches:</h2>
490 }else if( showAll ){
491 @ <h2>All Branches:</h2>
492 }else{
493 @ <h2>Open Branches:</h2>
494 }
495 @ <ul>
496 cnt++;
497 }
498 if( colorTest ){
499 const char *zColor = hash_color(zBr);
500 @ <li><span style="background-color: %s(zColor)">
501 @ %h(zBr) &rarr; %s(zColor)</span></li>
502 }else{
503 @ <li>%z(href("%R/timeline?r=%T&n=200",zBr))%h(zBr)</a></li>
504 }
505 }
506 if( cnt ){
507 @ </ul>
508 }
509 db_finalize(&q);
510 style_footer();
511 }
512
513 /*
514 ** This routine is called while for each check-in that is rendered by
515 ** the timeline of a "brlist" page. Add some additional hyperlinks
516 ** to the end of the line.
517 */
518
--- src/branch.c
+++ src/branch.c
@@ -187,62 +187,63 @@
187 */
188 #define BRL_CLOSED_ONLY 0x001 /* Show only closed branches */
189 #define BRL_OPEN_ONLY 0x002 /* Show only open branches */
190 #define BRL_BOTH 0x003 /* Show both open and closed branches */
191 #define BRL_OPEN_CLOSED_MASK 0x003
192 #define BRL_ORDERBY_MTIME 0x004 /* Sort by MTIME. (otherwise sort by name)*/
 
193
194 #endif /* INTERFACE */
195
196 /*
197 ** Prepare a query that will list branches.
 
 
 
 
198 */
199 void branch_prepare_list_query(Stmt *pQuery, int brFlags){
200 Blob sql = BLOB_INITIALIZER;
201 blob_zero(&sql);
202
203 /* Begin the query. */
204 blob_append_sql(&sql,
205 "SELECT tagxref.value AS name"
206 ", max(event.mtime) AS mtime"
207 ", %z AS closed"
208 ", (SELECT tagxref.value"
209 " FROM plink CROSS JOIN tagxref"
210 " WHERE plink.pid=event.objid"
211 " AND tagxref.rid=plink.cid"
212 " AND tagxref.tagid=%d"
213 " AND tagtype>0) AS mergeto"
214 ", count(*) AS cicount"
215 ", (SELECT uuid FROM blob WHERE rid=tagxref.rid) AS latest"
216 ", event.bgcolor AS bgcolor"
217 " FROM tagxref, tag, event"
218 " WHERE tagxref.tagid=tag.tagid"
219 " AND tagxref.tagtype>0"
220 " AND tag.tagname='branch'"
221 " AND event.objid=tagxref.rid",
222 leaf_is_closed_sql("tagxref.rid"), TAG_BRANCH);
223
224 /* Group by name to implement the cicount column. */
225 blob_append_sql(&sql, " GROUP BY name");
226
227 /* Apply open/closed filtering if requested. */
228 if( (brFlags & BRL_OPEN_CLOSED_MASK)==BRL_CLOSED_ONLY ){
229 blob_append_sql(&sql, " HAVING min(closed)");
230 }else if( (brFlags & BRL_OPEN_CLOSED_MASK)==BRL_OPEN_ONLY ){
231 blob_append_sql(&sql, " HAVING NOT min(closed)");
232 }
233
234 /* Apply the requested sort order. */
235 if( brFlags & BRL_ORDERBY_MTIME ){
236 blob_append_sql(&sql, " ORDER BY mtime DESC");
237 }else{
238 blob_append_sql(&sql, " ORDER BY name COLLATE nocase");
239 }
240
241 /* Prepare the query. */
242 db_prepare(pQuery, "%s", blob_sql_text(&sql));
243 blob_reset(&sql);
244 }
245
246 /*
247 ** COMMAND: branch
248 **
249 ** Usage: %fossil branch SUBCOMMAND ... ?OPTIONS?
@@ -307,63 +308,79 @@
308 fossil_fatal("branch subcommand should be one of: "
309 "new list ls");
310 }
311 }
312
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313 /*
314 ** WEBPAGE: brlist
315 ** Show a sortable list of branches.
316 **
317 ** Query parameters:
318 **
319 ** all Same as open&closed
320 ** open Show open branches
321 ** closed Show closed branches
322 ** colors Show assigned branch colors (alias: colortest)
323 */
324 void brlist_page(void){
325 Stmt q;
326 double rNow;
327 int colors, flags = BRL_ORDERBY_MTIME;
328
329 /* Intepret colortest as colors=1. */
330 if( PB("colortest") ){
331 cgi_replace_query_parameter("colors", "1");
332 }
333 cgi_delete_query_parameter("colortest");
334
335 /* Interpret all as open=1&closed=1&normal=1&hidden=1. */
336 if( PB("all") ){
337 cgi_replace_query_parameter("open", "1");
338 cgi_replace_query_parameter("closed", "1");
339 /* cgi_replace_query_parameter("normal", "1");
340 cgi_replace_query_parameter("hidden", "1");*/
341 }
342 cgi_delete_query_parameter("all");
343
344 /* Interpret open=0&closed=0 (or omitted) as open=1&closed=1. */
345 if( !PB("open") && !PB("closed") ){
346 cgi_replace_query_parameter("open", "1");
347 cgi_replace_query_parameter("closed", "1");
348 }
349
350 /* Interpret normal=0&hidden=0 (or omitted) as normal=1&hidden=1. */
351 /*if( !PB("normal") && !PB("hidden") ){
352 cgi_replace_query_parameter("normal", "1");
353 cgi_replace_query_parameter("hidden", "1");
354 }*/
355
356 /* Process query parameters. */
357 colors = PB("colors");
358 if( PB("open" ) ){flags |= BRL_OPEN_ONLY ;}
359 if( PB("closed") ){flags |= BRL_CLOSED_ONLY;}
360
361 login_check_credentials();
362 if( !g.perm.Read ){ login_needed(g.anon.Read); return; }
363 style_header("Branches");
364 style_adunit_config(ADUNIT_RIGHT_OK);
365 style_submenu_checkbox("colors", "Colors", 0);
366 style_submenu_checkbox("open", "Open", 0);
367 style_submenu_checkbox("closed", "Closed", 0);
368 /*style_submenu_checkbox("normal", "Normal", 0);
369 style_submenu_checkbox("hidden", "Hidden", 0);*/
370 login_anonymous_available();
371
372 branch_prepare_list_query(&q, flags);
373 rNow = db_double(0.0, "SELECT julianday('now')");
374 @ <div class="brlist"><table id="branchlisttable">
375 @ <thead><tr>
376 @ <th>Branch Name</th>
377 @ <th>Age</th>
378 @ <th>Check-ins</th>
379 if( (flags & BRL_OPEN_CLOSED_MASK) == BRL_BOTH ){
380 @ <th>Status</th>
381 }
382 @ <th>Resolution</th>
383 @ </tr></thead><tbody>
384 while( db_step(&q)==SQLITE_ROW ){
385 const char *zBranch = db_column_text(&q, 0);
386 double rMtime = db_column_double(&q, 1);
@@ -380,20 +397,22 @@
397 zBgClr = 0;
398 }else{
399 zBgClr = hash_color(zBranch);
400 }
401 }
402 if( zBgClr && zBgClr[0] && colors ){
403 @ <tr style="background-color:%s(zBgClr)">
404 }else{
405 @ <tr>
406 }
407 @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a></td>
408 @ <td data-sortkey="%016llx(-iMtime)">%s(zAge)</td>
409 @ <td>%d(nCkin)</td>
410 fossil_free(zAge);
411 if( (flags & BRL_OPEN_CLOSED_MASK) == BRL_BOTH ){
412 @ <td>%s(isClosed?"closed":"")</td>
413 }
414 if( zMergeTo ){
415 @ <td>merged into
416 @ %z(href("%R/timeline?f=%!S",zLastCkin))%h(zMergeTo)</a></td>
417 }else{
418 @ <td></td>
@@ -404,114 +423,10 @@
423 db_finalize(&q);
424 output_table_sorting_javascript("branchlisttable","tkNtt",2);
425 style_footer();
426 }
427
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428 /*
429 ** This routine is called while for each check-in that is rendered by
430 ** the timeline of a "brlist" page. Add some additional hyperlinks
431 ** to the end of the line.
432 */
433

Keyboard Shortcuts

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