Fossil SCM
Added showFiles=bool/--show-files option to /json/timeline/ci.
Commit
98e24465c2f3c9898e894d9286e6a38380272966
Parent
c1914eaa7944d9c…
1 file changed
+73
-1
+73
-1
| --- src/json_timeline.c | ||
| +++ src/json_timeline.c | ||
| @@ -192,10 +192,60 @@ | ||
| 192 | 192 | if(pPayload){ |
| 193 | 193 | cson_object_set(pPayload, "limit",cson_value_new_integer(limit)); |
| 194 | 194 | } |
| 195 | 195 | |
| 196 | 196 | } |
| 197 | + | |
| 198 | +static cson_value * json_timeline_get_changed_files(int rid){ | |
| 199 | + cson_value * rowsV = NULL; | |
| 200 | + cson_array * rows = NULL; | |
| 201 | + Stmt q; | |
| 202 | + db_prepare(&q, | |
| 203 | +#if 0 | |
| 204 | + "SELECT (mlink.pid==0) AS isNew," | |
| 205 | + " (mlink.fid==0) AS isDel," | |
| 206 | + " filename.name AS name" | |
| 207 | + " FROM mlink, filename" | |
| 208 | + " WHERE mid=%d" | |
| 209 | + " AND pid!=fid" | |
| 210 | + " AND filename.fnid=mlink.fnid" | |
| 211 | + " ORDER BY 3 /*sort*/", | |
| 212 | +#else | |
| 213 | + "SELECT (pid==0) AS isnew," | |
| 214 | + " (fid==0) AS isdel," | |
| 215 | + " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," | |
| 216 | + " (SELECT uuid FROM blob WHERE rid=fid)," | |
| 217 | + " (SELECT uuid FROM blob WHERE rid=pid)" | |
| 218 | + " FROM mlink" | |
| 219 | + " WHERE mid=%d AND pid!=fid" | |
| 220 | + " ORDER BY 3 /*sort*/", | |
| 221 | +#endif | |
| 222 | + rid | |
| 223 | + ); | |
| 224 | + while( (SQLITE_ROW == db_step(&q)) ){ | |
| 225 | + cson_value * rowV = cson_value_new_object(); | |
| 226 | + cson_object * row = cson_value_get_object(rowV); | |
| 227 | + int const isNew = db_column_int(&q,0); | |
| 228 | + int const isDel = db_column_int(&q,1); | |
| 229 | + if(!rowsV){ | |
| 230 | + rowsV = cson_value_new_array(); | |
| 231 | + rows = cson_value_get_array(rowsV); | |
| 232 | + } | |
| 233 | + cson_object_set(row, "name", json_new_string(db_column_text(&q,2))); | |
| 234 | + cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3))); | |
| 235 | + cson_object_set(row, "prevUuid", json_new_string(db_column_text(&q,4))); | |
| 236 | + cson_object_set(row, "state", | |
| 237 | + json_new_string(isNew | |
| 238 | + ? "added" | |
| 239 | + : (isDel | |
| 240 | + ? "removed" | |
| 241 | + : "modified"))); | |
| 242 | + cson_array_append( rows, rowV ); | |
| 243 | + } | |
| 244 | + db_finalize(&q); | |
| 245 | + return rowsV; | |
| 246 | +} | |
| 197 | 247 | /* |
| 198 | 248 | ** Implementation of /json/timeline/ci. |
| 199 | 249 | ** |
| 200 | 250 | ** Still a few TODOs (like figuring out how to structure |
| 201 | 251 | ** inheritance info). |
| @@ -205,16 +255,22 @@ | ||
| 205 | 255 | cson_object * pay = NULL; |
| 206 | 256 | cson_value * tmp = NULL; |
| 207 | 257 | cson_value * listV = NULL; |
| 208 | 258 | cson_array * list = NULL; |
| 209 | 259 | int check = 0; |
| 260 | + int showFiles = 0; | |
| 210 | 261 | Stmt q; |
| 211 | 262 | Blob sql = empty_blob; |
| 212 | 263 | if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){ |
| 213 | 264 | g.json.resultCode = FSL_JSON_E_DENIED; |
| 214 | 265 | return NULL; |
| 215 | 266 | } |
| 267 | + if( g.isHTTP ){ | |
| 268 | + showFiles = json_getenv_bool("showFiles",0); | |
| 269 | + }else{ | |
| 270 | + showFiles = 0!=find_option("show-files", "f",0); | |
| 271 | + } | |
| 216 | 272 | payV = cson_value_new_object(); |
| 217 | 273 | pay = cson_value_get_object(payV); |
| 218 | 274 | json_timeline_setup_sql( "ci", &sql, pay ); |
| 219 | 275 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 220 | 276 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| @@ -232,19 +288,24 @@ | ||
| 232 | 288 | blob_reset(&sql); |
| 233 | 289 | blob_append(&sql, "SELECT " |
| 234 | 290 | " rid AS rid," |
| 235 | 291 | " uuid AS uuid," |
| 236 | 292 | " mtime AS timestamp," |
| 293 | +#if 0 | |
| 237 | 294 | " timestampString AS timestampString," |
| 295 | +#endif | |
| 238 | 296 | " comment AS comment, " |
| 239 | 297 | " user AS user," |
| 240 | 298 | " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */ |
| 241 | 299 | " bgColor AS bgColor," /* why always null? */ |
| 242 | 300 | " eventType AS eventType," |
| 243 | - " tags AS tags," /*FIXME: split this into | |
| 301 | + " tags AS tags" /*FIXME: split this into | |
| 244 | 302 | a JSON array*/ |
| 303 | +#if 0 | |
| 304 | + /*tagId is always null?*/ | |
| 245 | 305 | " tagId AS tagId" |
| 306 | +#endif | |
| 246 | 307 | " FROM json_timeline" |
| 247 | 308 | " ORDER BY sortId", |
| 248 | 309 | -1); |
| 249 | 310 | db_prepare(&q,blob_buffer(&sql)); |
| 250 | 311 | blob_reset(&sql); |
| @@ -252,10 +313,11 @@ | ||
| 252 | 313 | list = cson_value_get_array(listV); |
| 253 | 314 | tmp = listV; |
| 254 | 315 | SET("timeline"); |
| 255 | 316 | while( (SQLITE_ROW == db_step(&q) )){ |
| 256 | 317 | /* convert each row into a JSON object...*/ |
| 318 | + int const rid = db_column_int(&q,0); | |
| 257 | 319 | cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt); |
| 258 | 320 | cson_object * row = cson_value_get_object(rowV); |
| 259 | 321 | cson_string const * tagsStr = NULL; |
| 260 | 322 | if(!row){ |
| 261 | 323 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, |
| @@ -287,10 +349,16 @@ | ||
| 287 | 349 | cson_object_set(row,"isLeaf", |
| 288 | 350 | cson_value_get_integer(tmp) |
| 289 | 351 | ? cson_value_true() |
| 290 | 352 | : cson_value_false()); |
| 291 | 353 | tmp = NULL; |
| 354 | + } | |
| 355 | + if( showFiles ){ | |
| 356 | + cson_value * flist = json_timeline_get_changed_files(rid); | |
| 357 | + if(flist){ | |
| 358 | + cson_object_set(row,"files",flist); | |
| 359 | + } | |
| 292 | 360 | } |
| 293 | 361 | } |
| 294 | 362 | db_finalize(&q); |
| 295 | 363 | #undef SET |
| 296 | 364 | goto ok; |
| @@ -338,11 +406,13 @@ | ||
| 338 | 406 | |
| 339 | 407 | blob_reset(&sql); |
| 340 | 408 | blob_append(&sql, "SELECT rid AS rid," |
| 341 | 409 | " uuid AS uuid," |
| 342 | 410 | " mtime AS timestamp," |
| 411 | +#if 0 | |
| 343 | 412 | " timestampString AS timestampString," |
| 413 | +#endif | |
| 344 | 414 | " comment AS comment, " |
| 345 | 415 | " user AS user," |
| 346 | 416 | " eventType AS eventType" |
| 347 | 417 | #if 0 |
| 348 | 418 | /* can wiki pages have tags? */ |
| @@ -425,11 +495,13 @@ | ||
| 425 | 495 | |
| 426 | 496 | blob_reset(&sql); |
| 427 | 497 | blob_append(&sql, "SELECT rid AS rid," |
| 428 | 498 | " uuid AS uuid," |
| 429 | 499 | " mtime AS timestamp," |
| 500 | +#if 0 | |
| 430 | 501 | " timestampString AS timestampString," |
| 502 | +#endif | |
| 431 | 503 | " user AS user," |
| 432 | 504 | " eventType AS eventType," |
| 433 | 505 | " comment AS comment," |
| 434 | 506 | " brief AS briefComment" |
| 435 | 507 | " FROM json_timeline" |
| 436 | 508 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -192,10 +192,60 @@ | |
| 192 | if(pPayload){ |
| 193 | cson_object_set(pPayload, "limit",cson_value_new_integer(limit)); |
| 194 | } |
| 195 | |
| 196 | } |
| 197 | /* |
| 198 | ** Implementation of /json/timeline/ci. |
| 199 | ** |
| 200 | ** Still a few TODOs (like figuring out how to structure |
| 201 | ** inheritance info). |
| @@ -205,16 +255,22 @@ | |
| 205 | cson_object * pay = NULL; |
| 206 | cson_value * tmp = NULL; |
| 207 | cson_value * listV = NULL; |
| 208 | cson_array * list = NULL; |
| 209 | int check = 0; |
| 210 | Stmt q; |
| 211 | Blob sql = empty_blob; |
| 212 | if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){ |
| 213 | g.json.resultCode = FSL_JSON_E_DENIED; |
| 214 | return NULL; |
| 215 | } |
| 216 | payV = cson_value_new_object(); |
| 217 | pay = cson_value_get_object(payV); |
| 218 | json_timeline_setup_sql( "ci", &sql, pay ); |
| 219 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 220 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| @@ -232,19 +288,24 @@ | |
| 232 | blob_reset(&sql); |
| 233 | blob_append(&sql, "SELECT " |
| 234 | " rid AS rid," |
| 235 | " uuid AS uuid," |
| 236 | " mtime AS timestamp," |
| 237 | " timestampString AS timestampString," |
| 238 | " comment AS comment, " |
| 239 | " user AS user," |
| 240 | " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */ |
| 241 | " bgColor AS bgColor," /* why always null? */ |
| 242 | " eventType AS eventType," |
| 243 | " tags AS tags," /*FIXME: split this into |
| 244 | a JSON array*/ |
| 245 | " tagId AS tagId" |
| 246 | " FROM json_timeline" |
| 247 | " ORDER BY sortId", |
| 248 | -1); |
| 249 | db_prepare(&q,blob_buffer(&sql)); |
| 250 | blob_reset(&sql); |
| @@ -252,10 +313,11 @@ | |
| 252 | list = cson_value_get_array(listV); |
| 253 | tmp = listV; |
| 254 | SET("timeline"); |
| 255 | while( (SQLITE_ROW == db_step(&q) )){ |
| 256 | /* convert each row into a JSON object...*/ |
| 257 | cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt); |
| 258 | cson_object * row = cson_value_get_object(rowV); |
| 259 | cson_string const * tagsStr = NULL; |
| 260 | if(!row){ |
| 261 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, |
| @@ -287,10 +349,16 @@ | |
| 287 | cson_object_set(row,"isLeaf", |
| 288 | cson_value_get_integer(tmp) |
| 289 | ? cson_value_true() |
| 290 | : cson_value_false()); |
| 291 | tmp = NULL; |
| 292 | } |
| 293 | } |
| 294 | db_finalize(&q); |
| 295 | #undef SET |
| 296 | goto ok; |
| @@ -338,11 +406,13 @@ | |
| 338 | |
| 339 | blob_reset(&sql); |
| 340 | blob_append(&sql, "SELECT rid AS rid," |
| 341 | " uuid AS uuid," |
| 342 | " mtime AS timestamp," |
| 343 | " timestampString AS timestampString," |
| 344 | " comment AS comment, " |
| 345 | " user AS user," |
| 346 | " eventType AS eventType" |
| 347 | #if 0 |
| 348 | /* can wiki pages have tags? */ |
| @@ -425,11 +495,13 @@ | |
| 425 | |
| 426 | blob_reset(&sql); |
| 427 | blob_append(&sql, "SELECT rid AS rid," |
| 428 | " uuid AS uuid," |
| 429 | " mtime AS timestamp," |
| 430 | " timestampString AS timestampString," |
| 431 | " user AS user," |
| 432 | " eventType AS eventType," |
| 433 | " comment AS comment," |
| 434 | " brief AS briefComment" |
| 435 | " FROM json_timeline" |
| 436 |
| --- src/json_timeline.c | |
| +++ src/json_timeline.c | |
| @@ -192,10 +192,60 @@ | |
| 192 | if(pPayload){ |
| 193 | cson_object_set(pPayload, "limit",cson_value_new_integer(limit)); |
| 194 | } |
| 195 | |
| 196 | } |
| 197 | |
| 198 | static cson_value * json_timeline_get_changed_files(int rid){ |
| 199 | cson_value * rowsV = NULL; |
| 200 | cson_array * rows = NULL; |
| 201 | Stmt q; |
| 202 | db_prepare(&q, |
| 203 | #if 0 |
| 204 | "SELECT (mlink.pid==0) AS isNew," |
| 205 | " (mlink.fid==0) AS isDel," |
| 206 | " filename.name AS name" |
| 207 | " FROM mlink, filename" |
| 208 | " WHERE mid=%d" |
| 209 | " AND pid!=fid" |
| 210 | " AND filename.fnid=mlink.fnid" |
| 211 | " ORDER BY 3 /*sort*/", |
| 212 | #else |
| 213 | "SELECT (pid==0) AS isnew," |
| 214 | " (fid==0) AS isdel," |
| 215 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 216 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 217 | " (SELECT uuid FROM blob WHERE rid=pid)" |
| 218 | " FROM mlink" |
| 219 | " WHERE mid=%d AND pid!=fid" |
| 220 | " ORDER BY 3 /*sort*/", |
| 221 | #endif |
| 222 | rid |
| 223 | ); |
| 224 | while( (SQLITE_ROW == db_step(&q)) ){ |
| 225 | cson_value * rowV = cson_value_new_object(); |
| 226 | cson_object * row = cson_value_get_object(rowV); |
| 227 | int const isNew = db_column_int(&q,0); |
| 228 | int const isDel = db_column_int(&q,1); |
| 229 | if(!rowsV){ |
| 230 | rowsV = cson_value_new_array(); |
| 231 | rows = cson_value_get_array(rowsV); |
| 232 | } |
| 233 | cson_object_set(row, "name", json_new_string(db_column_text(&q,2))); |
| 234 | cson_object_set(row, "uuid", json_new_string(db_column_text(&q,3))); |
| 235 | cson_object_set(row, "prevUuid", json_new_string(db_column_text(&q,4))); |
| 236 | cson_object_set(row, "state", |
| 237 | json_new_string(isNew |
| 238 | ? "added" |
| 239 | : (isDel |
| 240 | ? "removed" |
| 241 | : "modified"))); |
| 242 | cson_array_append( rows, rowV ); |
| 243 | } |
| 244 | db_finalize(&q); |
| 245 | return rowsV; |
| 246 | } |
| 247 | /* |
| 248 | ** Implementation of /json/timeline/ci. |
| 249 | ** |
| 250 | ** Still a few TODOs (like figuring out how to structure |
| 251 | ** inheritance info). |
| @@ -205,16 +255,22 @@ | |
| 255 | cson_object * pay = NULL; |
| 256 | cson_value * tmp = NULL; |
| 257 | cson_value * listV = NULL; |
| 258 | cson_array * list = NULL; |
| 259 | int check = 0; |
| 260 | int showFiles = 0; |
| 261 | Stmt q; |
| 262 | Blob sql = empty_blob; |
| 263 | if( !g.perm.Read/* && !g.perm.RdTkt && !g.perm.RdWiki*/ ){ |
| 264 | g.json.resultCode = FSL_JSON_E_DENIED; |
| 265 | return NULL; |
| 266 | } |
| 267 | if( g.isHTTP ){ |
| 268 | showFiles = json_getenv_bool("showFiles",0); |
| 269 | }else{ |
| 270 | showFiles = 0!=find_option("show-files", "f",0); |
| 271 | } |
| 272 | payV = cson_value_new_object(); |
| 273 | pay = cson_value_get_object(payV); |
| 274 | json_timeline_setup_sql( "ci", &sql, pay ); |
| 275 | #define SET(K) if(0!=(check=cson_object_set(pay,K,tmp))){ \ |
| 276 | g.json.resultCode = (cson_rc.AllocError==check) \ |
| @@ -232,19 +288,24 @@ | |
| 288 | blob_reset(&sql); |
| 289 | blob_append(&sql, "SELECT " |
| 290 | " rid AS rid," |
| 291 | " uuid AS uuid," |
| 292 | " mtime AS timestamp," |
| 293 | #if 0 |
| 294 | " timestampString AS timestampString," |
| 295 | #endif |
| 296 | " comment AS comment, " |
| 297 | " user AS user," |
| 298 | " isLeaf AS isLeaf," /*FIXME: convert to JSON bool */ |
| 299 | " bgColor AS bgColor," /* why always null? */ |
| 300 | " eventType AS eventType," |
| 301 | " tags AS tags" /*FIXME: split this into |
| 302 | a JSON array*/ |
| 303 | #if 0 |
| 304 | /*tagId is always null?*/ |
| 305 | " tagId AS tagId" |
| 306 | #endif |
| 307 | " FROM json_timeline" |
| 308 | " ORDER BY sortId", |
| 309 | -1); |
| 310 | db_prepare(&q,blob_buffer(&sql)); |
| 311 | blob_reset(&sql); |
| @@ -252,10 +313,11 @@ | |
| 313 | list = cson_value_get_array(listV); |
| 314 | tmp = listV; |
| 315 | SET("timeline"); |
| 316 | while( (SQLITE_ROW == db_step(&q) )){ |
| 317 | /* convert each row into a JSON object...*/ |
| 318 | int const rid = db_column_int(&q,0); |
| 319 | cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt); |
| 320 | cson_object * row = cson_value_get_object(rowV); |
| 321 | cson_string const * tagsStr = NULL; |
| 322 | if(!row){ |
| 323 | json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, |
| @@ -287,10 +349,16 @@ | |
| 349 | cson_object_set(row,"isLeaf", |
| 350 | cson_value_get_integer(tmp) |
| 351 | ? cson_value_true() |
| 352 | : cson_value_false()); |
| 353 | tmp = NULL; |
| 354 | } |
| 355 | if( showFiles ){ |
| 356 | cson_value * flist = json_timeline_get_changed_files(rid); |
| 357 | if(flist){ |
| 358 | cson_object_set(row,"files",flist); |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | db_finalize(&q); |
| 363 | #undef SET |
| 364 | goto ok; |
| @@ -338,11 +406,13 @@ | |
| 406 | |
| 407 | blob_reset(&sql); |
| 408 | blob_append(&sql, "SELECT rid AS rid," |
| 409 | " uuid AS uuid," |
| 410 | " mtime AS timestamp," |
| 411 | #if 0 |
| 412 | " timestampString AS timestampString," |
| 413 | #endif |
| 414 | " comment AS comment, " |
| 415 | " user AS user," |
| 416 | " eventType AS eventType" |
| 417 | #if 0 |
| 418 | /* can wiki pages have tags? */ |
| @@ -425,11 +495,13 @@ | |
| 495 | |
| 496 | blob_reset(&sql); |
| 497 | blob_append(&sql, "SELECT rid AS rid," |
| 498 | " uuid AS uuid," |
| 499 | " mtime AS timestamp," |
| 500 | #if 0 |
| 501 | " timestampString AS timestampString," |
| 502 | #endif |
| 503 | " user AS user," |
| 504 | " eventType AS eventType," |
| 505 | " comment AS comment," |
| 506 | " brief AS briefComment" |
| 507 | " FROM json_timeline" |
| 508 |