| | @@ -179,47 +179,67 @@ |
| 179 | 179 | |
| 180 | 180 | /* Do an autosync push, if requested */ |
| 181 | 181 | if( !isPrivate ) autosync_loop(SYNC_PUSH, db_get_int("autosync-tries", 1)); |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | +#if INTERFACE |
| 185 | +/* |
| 186 | +** Allows bits in the mBplqFlags parameter to branch_prepare_list_query(). |
| 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 | +#dfeine BRL_ORDERBY_MTIME 0x008 /* Sort by MTIME. (otherwise sort by name)*/ |
| 194 | + |
| 195 | +#endif /* INTERFACE */ |
| 196 | + |
| 184 | 197 | /* |
| 185 | 198 | ** Prepare a query that will list branches. |
| 186 | 199 | ** |
| 187 | 200 | ** If (which<0) then the query pulls only closed branches. If |
| 188 | 201 | ** (which>0) then the query pulls all (closed and opened) |
| 189 | 202 | ** branches. Else the query pulls currently-opened branches. |
| 190 | 203 | */ |
| 191 | | -void branch_prepare_list_query(Stmt *pQuery, int which ){ |
| 192 | | - if( which < 0 ){ |
| 193 | | - db_prepare(pQuery, |
| 194 | | - "SELECT value FROM tagxref" |
| 195 | | - " WHERE tagid=%d AND value NOT NULL " |
| 196 | | - "EXCEPT " |
| 197 | | - "SELECT value FROM tagxref" |
| 198 | | - " WHERE tagid=%d" |
| 199 | | - " AND rid IN leaf" |
| 200 | | - " AND NOT %z" |
| 201 | | - " ORDER BY value COLLATE nocase /*sort*/", |
| 202 | | - TAG_BRANCH, TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 203 | | - ); |
| 204 | | - }else if( which>0 ){ |
| 205 | | - db_prepare(pQuery, |
| 206 | | - "SELECT DISTINCT value FROM tagxref" |
| 207 | | - " WHERE tagid=%d AND value NOT NULL" |
| 208 | | - " AND rid IN leaf" |
| 209 | | - " ORDER BY value COLLATE nocase /*sort*/", |
| 210 | | - TAG_BRANCH |
| 211 | | - ); |
| 212 | | - }else{ |
| 213 | | - db_prepare(pQuery, |
| 214 | | - "SELECT DISTINCT value FROM tagxref" |
| 215 | | - " WHERE tagid=%d AND value NOT NULL" |
| 216 | | - " AND rid IN leaf" |
| 217 | | - " AND NOT %z" |
| 218 | | - " ORDER BY value COLLATE nocase /*sort*/", |
| 219 | | - TAG_BRANCH, leaf_is_closed_sql("tagxref.rid") |
| 220 | | - ); |
| 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 | + } |
| 221 | 241 | } |
| 222 | 242 | } |
| 223 | 243 | |
| 224 | 244 | |
| 225 | 245 | /* |
| | @@ -260,19 +280,20 @@ |
| 260 | 280 | branch_new(); |
| 261 | 281 | }else if( (strncmp(zCmd,"list",n)==0)||(strncmp(zCmd, "ls", n)==0) ){ |
| 262 | 282 | Stmt q; |
| 263 | 283 | int vid; |
| 264 | 284 | char *zCurrent = 0; |
| 265 | | - int showAll = find_option("all","a",0)!=0; |
| 266 | | - int showClosed = find_option("closed","c",0)!=0; |
| 285 | + int brFlags = BRL_OPEN_ONLY; |
| 286 | + if( find_option("all","a",0)!=0 ) brFlags = BRL_BOTH; |
| 287 | + if( find_option("closed","c",0)!=0 ) brFlags = BRL_CLOSED_ONLY; |
| 267 | 288 | |
| 268 | 289 | if( g.localOpen ){ |
| 269 | 290 | vid = db_lget_int("checkout", 0); |
| 270 | 291 | zCurrent = db_text(0, "SELECT value FROM tagxref" |
| 271 | 292 | " WHERE rid=%d AND tagid=%d", vid, TAG_BRANCH); |
| 272 | 293 | } |
| 273 | | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 294 | + branch_prepare_list_query(&q, brFlags); |
| 274 | 295 | while( db_step(&q)==SQLITE_ROW ){ |
| 275 | 296 | const char *zBr = db_column_text(&q, 0); |
| 276 | 297 | int isCur = zCurrent!=0 && fossil_strcmp(zCurrent,zBr)==0; |
| 277 | 298 | fossil_print("%s%s\n", (isCur ? "* " : " "), zBr); |
| 278 | 299 | } |
| | @@ -280,36 +301,128 @@ |
| 280 | 301 | }else{ |
| 281 | 302 | fossil_fatal("branch subcommand should be one of: " |
| 282 | 303 | "new list ls"); |
| 283 | 304 | } |
| 284 | 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=leaf.rid |
| 313 | +@ AND tx.tagid=(SELECT tagid FROM tag WHERE tagname='closed') |
| 314 | +@ AND tx.tagtype>0), |
| 315 | +@ (SELECT tagxref.value |
| 316 | +@ FROM plink CROSS JOIN tagxref |
| 317 | +@ WHERE plink.pid=leaf.rid |
| 318 | +@ AND tagxref.rid=plink.cid |
| 319 | +@ AND tagxref.tagid=(SELECT tagid FROM tag WHERE tagname='branch') |
| 320 | +@ AND tagtype>0) |
| 321 | +@ FROM leaf, tagxref, tag, event |
| 322 | +@ WHERE leaf.rid=tagxref.rid |
| 323 | +@ AND tagxref.tagid=tag.tagid |
| 324 | +@ AND tagxref.tagtype>0 |
| 325 | +@ AND tag.tagname='branch' |
| 326 | +@ AND event.objid=leaf.rid |
| 327 | +@ GROUP BY 1 |
| 328 | +@ ORDER BY %d DESC; |
| 329 | +; |
| 330 | + |
| 331 | +/* |
| 332 | +** This is the new-style branch-list page that shows the branch names |
| 333 | +** together with their ages (time of last check-in) and whether or not |
| 334 | +** they are closed or merged to another branch. |
| 335 | +** |
| 336 | +** Control jumps to this routine from brlist_page() (the /brlist handler) |
| 337 | +** if there are no query parameters. |
| 338 | +*/ |
| 339 | +static void new_brlist_page(void){ |
| 340 | + Stmt q; |
| 341 | + double rNow; |
| 342 | + int orderByMtime = P("mtime")!=0; |
| 343 | + login_check_credentials(); |
| 344 | + if( !g.perm.Read ){ login_needed(); return; } |
| 345 | + style_header("Branches"); |
| 346 | + login_anonymous_available(); |
| 347 | + |
| 348 | + assert( orderByMtime==0 || orderByMtime==1 ); |
| 349 | + db_prepare(&q, brlistQuery/*works-like:"%d"*/, 2-orderByMtime); |
| 350 | + rNow = db_double(0.0, "SELECT julianday('now')"); |
| 351 | + @ <div class="brlist"><table> |
| 352 | + @ <tr> |
| 353 | + @ <th>Branch Name</th> |
| 354 | + @ <th>Age</th> |
| 355 | + @ <th>Status</th> |
| 356 | + @ </tr> |
| 357 | + while( db_step(&q)==SQLITE_ROW ){ |
| 358 | + const char *zBranch = db_column_text(&q, 0); |
| 359 | + double rMtime = db_column_double(&q, 1); |
| 360 | + int isClosed = db_column_int(&q, 2); |
| 361 | + const char *zMergeTo = db_column_text(&q, 3); |
| 362 | + char *zAge = human_readable_age(rNow - rMtime); |
| 363 | + if( zMergeTo && zMergeTo[0]==0 ) zMergeTo = 0; |
| 364 | + @ <tr> |
| 365 | + @ <td>%z(href("%R/timeline?n=100&r=%T",zBranch))%h(zBranch)</a> |
| 366 | + @ <td>%s(zAge) |
| 367 | + fossil_free(zAge); |
| 368 | + if( isClosed && zMergeTo ){ |
| 369 | + @ <td>closed, |
| 370 | + }else if( isClosed ){ |
| 371 | + @ <td>closed |
| 372 | + }else{ |
| 373 | + @ <td> |
| 374 | + } |
| 375 | + if( zMergeTo ){ |
| 376 | + @ merged into %z(href("%R/timeline?r=%T",zMergeTo))%h(zMergeTo)</a> |
| 377 | + } |
| 378 | + @ </tr> |
| 379 | + } |
| 380 | + @ </table></div> |
| 381 | + |
| 382 | + db_finalize(&q); |
| 383 | + style_footer(); |
| 384 | +} |
| 285 | 385 | |
| 286 | 386 | /* |
| 287 | 387 | ** WEBPAGE: brlist |
| 388 | +** Show a list of branches |
| 389 | +** Query parameters: |
| 288 | 390 | ** |
| 289 | | -** Show a timeline of all branches |
| 391 | +** all Show all branches |
| 392 | +** closed Show only closed branches |
| 393 | +** open Show only open branches (default behavior) |
| 394 | +** colortest Show all branches with automatic color |
| 290 | 395 | */ |
| 291 | 396 | void brlist_page(void){ |
| 292 | 397 | Stmt q; |
| 293 | 398 | int cnt; |
| 294 | 399 | int showClosed = P("closed")!=0; |
| 295 | 400 | int showAll = P("all")!=0; |
| 401 | + int showOpen = P("open")!=0; |
| 296 | 402 | int colorTest = P("colortest")!=0; |
| 403 | + int brFlags = BRL_OPEN_ONLY; |
| 297 | 404 | |
| 405 | + if( showClosed==0 && showAll==0 && showOpen==0 && colorTest==0 ){ |
| 406 | + new_brlist_page(); |
| 407 | + return; |
| 408 | + } |
| 298 | 409 | login_check_credentials(); |
| 299 | 410 | if( !g.perm.Read ){ login_needed(); return; } |
| 300 | 411 | if( colorTest ){ |
| 301 | 412 | showClosed = 0; |
| 302 | 413 | showAll = 1; |
| 303 | 414 | } |
| 415 | + if( showAll ) brFlags = BRL_BOTH; |
| 416 | + if( showClosed ) brFlags = BRL_CLOSED_ONLY; |
| 304 | 417 | |
| 305 | 418 | style_header("%s", showClosed ? "Closed Branches" : |
| 306 | 419 | showAll ? "All Branches" : "Open Branches"); |
| 307 | 420 | style_submenu_element("Timeline", "Timeline", "brtimeline"); |
| 308 | 421 | if( showClosed ){ |
| 309 | 422 | style_submenu_element("All", "All", "brlist?all"); |
| 310 | | - style_submenu_element("Open","Open","brlist"); |
| 423 | + style_submenu_element("Open","Open","brlist?open"); |
| 311 | 424 | }else if( showAll ){ |
| 312 | 425 | style_submenu_element("Closed", "Closed", "brlist?closed"); |
| 313 | 426 | style_submenu_element("Open","Open","brlist"); |
| 314 | 427 | }else{ |
| 315 | 428 | style_submenu_element("All", "All", "brlist?all"); |
| | @@ -335,21 +448,21 @@ |
| 335 | 448 | @ Closed branches are fixed and do not change (unless they are first |
| 336 | 449 | @ reopened).</li> |
| 337 | 450 | @ </ol> |
| 338 | 451 | style_sidebox_end(); |
| 339 | 452 | |
| 340 | | - branch_prepare_list_query(&q, showAll?1:(showClosed?-1:0)); |
| 453 | + branch_prepare_list_query(&q, brFlags); |
| 341 | 454 | cnt = 0; |
| 342 | 455 | while( db_step(&q)==SQLITE_ROW ){ |
| 343 | 456 | const char *zBr = db_column_text(&q, 0); |
| 344 | 457 | if( cnt==0 ){ |
| 345 | 458 | if( colorTest ){ |
| 346 | 459 | @ <h2>Default background colors for all branches:</h2> |
| 460 | + }else if( showClosed ){ |
| 461 | + @ <h2>Closed Branches:</h2> |
| 347 | 462 | }else if( showAll ){ |
| 348 | 463 | @ <h2>All Branches:</h2> |
| 349 | | - }else if( showClosed ){ |
| 350 | | - @ <h2>Closed Branches:</h2> |
| 351 | 464 | }else{ |
| 352 | 465 | @ <h2>Open Branches:</h2> |
| 353 | 466 | } |
| 354 | 467 | @ <ul> |
| 355 | 468 | cnt++; |
| 356 | 469 | |