| | @@ -21,10 +21,11 @@ |
| 21 | 21 | |
| 22 | 22 | #if INTERFACE |
| 23 | 23 | #include "json_detail.h" |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | +static cson_value * json_timeline_branch(); |
| 26 | 27 | static cson_value * json_timeline_ci(); |
| 27 | 28 | static cson_value * json_timeline_ticket(); |
| 28 | 29 | /* |
| 29 | 30 | ** Mapping of /json/timeline/XXX commands/paths to callbacks. |
| 30 | 31 | */ |
| | @@ -31,10 +32,11 @@ |
| 31 | 32 | static const JsonPageDef JsonPageDefs_Timeline[] = { |
| 32 | 33 | /* the short forms are only enabled in CLI mode, to avoid |
| 33 | 34 | that we end up with HTTP clients using 3 different names |
| 34 | 35 | for the same requests. |
| 35 | 36 | */ |
| 37 | +{"branch", json_timeline_branch, 0}, |
| 36 | 38 | {"c", json_timeline_ci, -1}, |
| 37 | 39 | {"checkin", json_timeline_ci, 0}, |
| 38 | 40 | {"ci", json_timeline_ci, -1}, |
| 39 | 41 | {"com", json_timeline_ci, -1}, |
| 40 | 42 | {"commit", json_timeline_ci, 0}, |
| | @@ -111,13 +113,13 @@ |
| 111 | 113 | @ blob.rid IN leaf, |
| 112 | 114 | @ bgcolor, |
| 113 | 115 | @ event.type, |
| 114 | 116 | @ (SELECT group_concat(substr(tagname,5), ',') FROM tag, tagxref |
| 115 | 117 | @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid |
| 116 | | - @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0), |
| 117 | | - @ tagid, |
| 118 | | - @ brief |
| 118 | + @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) as tags, |
| 119 | + @ tagid as tagId, |
| 120 | + @ brief as brief |
| 119 | 121 | @ FROM event JOIN blob |
| 120 | 122 | @ WHERE blob.rid=event.objid |
| 121 | 123 | ; |
| 122 | 124 | return zBaseSql; |
| 123 | 125 | } |
| | @@ -343,10 +345,75 @@ |
| 343 | 345 | cson_array_append( rows, rowV ); |
| 344 | 346 | } |
| 345 | 347 | db_finalize(&q); |
| 346 | 348 | return rowsV; |
| 347 | 349 | } |
| 350 | + |
| 351 | +static cson_value * json_timeline_branch(){ |
| 352 | + cson_value * pay = NULL; |
| 353 | + Blob sql = empty_blob; |
| 354 | + Stmt q = empty_Stmt; |
| 355 | + if(!g.perm.Read){ |
| 356 | + json_set_err(FSL_JSON_E_DENIED, |
| 357 | + "Requires 'o' permissions."); |
| 358 | + return NULL; |
| 359 | + } |
| 360 | + json_timeline_temp_table(); |
| 361 | + blob_append(&sql, |
| 362 | + "SELECT" |
| 363 | + " blob.rid AS rid," |
| 364 | + " uuid AS uuid," |
| 365 | + " datetime(event.mtime,'utc') as mtime," |
| 366 | + " coalesce(ecomment, comment) as comment," |
| 367 | + " coalesce(euser, user) as user," |
| 368 | + " blob.rid IN leaf as isLeaf," |
| 369 | + " bgcolor as bgColor" |
| 370 | + " FROM event JOIN blob" |
| 371 | + " WHERE blob.rid=event.objid", |
| 372 | + -1); |
| 373 | + |
| 374 | + blob_appendf(&sql, |
| 375 | + " AND event.type='ci'" |
| 376 | + " AND blob.rid IN (SELECT rid FROM tagxref" |
| 377 | + " WHERE tagtype>0 AND tagid=%d AND srcid!=0)" |
| 378 | + " ORDER BY event.mtime DESC", |
| 379 | + TAG_BRANCH); |
| 380 | + db_prepare(&q,"%s", blob_str(&sql)); |
| 381 | + blob_reset(&sql); |
| 382 | + pay = json_stmt_to_array_of_obj(&q, NULL); |
| 383 | + db_finalize(&q); |
| 384 | + assert(NULL != pay); |
| 385 | + if(pay){ |
| 386 | + /* get the array-form tags of each record. */ |
| 387 | + cson_string * tags = cson_new_string("tags",4); |
| 388 | + cson_string * isLeaf = cson_new_string("isLeaf",6); |
| 389 | + cson_value_add_reference( cson_string_value(tags) ); |
| 390 | + cson_value_add_reference( cson_string_value(isLeaf) ); |
| 391 | + cson_array * ar = cson_value_get_array(pay); |
| 392 | + unsigned int i = 0; |
| 393 | + unsigned int len = cson_array_length_get(ar); |
| 394 | + for( ; i < len; ++i ){ |
| 395 | + cson_object * row = cson_value_get_object(cson_array_get(ar,i)); |
| 396 | + int rid = cson_value_get_integer(cson_object_get(row,"rid")); |
| 397 | + if(row>0) { |
| 398 | + cson_object_set_s(row, tags, json_tags_for_rid(rid,0)); |
| 399 | + cson_object_set_s(row, isLeaf, json_value_to_bool(cson_object_get(row,"isLeaf"))); |
| 400 | + } |
| 401 | + } |
| 402 | + cson_value_free( cson_string_value(tags) ); |
| 403 | + cson_value_free( cson_string_value(isLeaf) ); |
| 404 | + } |
| 405 | + |
| 406 | + goto end; |
| 407 | + error: |
| 408 | + assert( 0 != g.json.resultCode ); |
| 409 | + cson_value_free(pay); |
| 410 | + |
| 411 | + end: |
| 412 | + return pay; |
| 413 | +} |
| 414 | + |
| 348 | 415 | /* |
| 349 | 416 | ** Implementation of /json/timeline/ci. |
| 350 | 417 | ** |
| 351 | 418 | ** Still a few TODOs (like figuring out how to structure |
| 352 | 419 | ** inheritance info). |
| | @@ -410,11 +477,11 @@ |
| 410 | 477 | /*tagId is always null?*/ |
| 411 | 478 | " tagId AS tagId" |
| 412 | 479 | # endif |
| 413 | 480 | #endif |
| 414 | 481 | " FROM json_timeline" |
| 415 | | - " ORDER BY sortId"); |
| 482 | + " ORDER BY rowid"); |
| 416 | 483 | listV = cson_value_new_array(); |
| 417 | 484 | list = cson_value_get_array(listV); |
| 418 | 485 | tmp = listV; |
| 419 | 486 | SET("timeline"); |
| 420 | 487 | while( (SQLITE_ROW == db_step(&q) )){ |
| | @@ -496,11 +563,11 @@ |
| 496 | 563 | " tags AS tags," /*FIXME: split this into |
| 497 | 564 | a JSON array*/ |
| 498 | 565 | " tagId AS tagId," |
| 499 | 566 | #endif |
| 500 | 567 | " FROM json_timeline" |
| 501 | | - " ORDER BY sortId", |
| 568 | + " ORDER BY rowid", |
| 502 | 569 | -1); |
| 503 | 570 | listV = cson_value_new_array(); |
| 504 | 571 | list = cson_value_get_array(listV); |
| 505 | 572 | tmp = listV; |
| 506 | 573 | SET("timeline"); |
| | @@ -572,11 +639,11 @@ |
| 572 | 639 | " user AS user," |
| 573 | 640 | " eventType AS eventType," |
| 574 | 641 | " comment AS comment," |
| 575 | 642 | " brief AS briefComment" |
| 576 | 643 | " FROM json_timeline" |
| 577 | | - " ORDER BY sortId", |
| 644 | + " ORDER BY rowid", |
| 578 | 645 | -1); |
| 579 | 646 | listV = cson_value_new_array(); |
| 580 | 647 | list = cson_value_get_array(listV); |
| 581 | 648 | tmp = listV; |
| 582 | 649 | SET("timeline"); |
| 583 | 650 | |