Fossil SCM
Enhance the /finfo webpage so that when it is showing the ancestors of a particular check-in, it only shows direct ancestors, the same as the /annotate and /blame pages.
Commit
f8db2c7489ad5babd360d3d6721b3cd9cfe3e571
Parent
dfa8efc5acbb88e…
1 file changed
+44
-31
+44
-31
| --- src/finfo.c | ||
| +++ src/finfo.c | ||
| @@ -299,19 +299,19 @@ | ||
| 299 | 299 | const char *zA; |
| 300 | 300 | const char *zB; |
| 301 | 301 | int n; |
| 302 | 302 | int baseCheckin; |
| 303 | 303 | int fnid; |
| 304 | - Bag ancestor; | |
| 305 | 304 | Blob title; |
| 306 | 305 | Blob sql; |
| 307 | 306 | HQuery url; |
| 308 | 307 | GraphContext *pGraph; |
| 309 | 308 | int brBg = P("brbg")!=0; |
| 310 | 309 | int uBg = P("ubg")!=0; |
| 311 | 310 | int fDebug = atoi(PD("debug","0")); |
| 312 | 311 | int fShowId = P("showid")!=0; |
| 312 | + Stmt qparent; | |
| 313 | 313 | |
| 314 | 314 | login_check_credentials(); |
| 315 | 315 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 316 | 316 | style_header("File History"); |
| 317 | 317 | login_anonymous_available(); |
| @@ -326,16 +326,11 @@ | ||
| 326 | 326 | @ No such file: %h(zFilename) |
| 327 | 327 | style_footer(); |
| 328 | 328 | return; |
| 329 | 329 | } |
| 330 | 330 | if( baseCheckin ){ |
| 331 | - int baseFid = db_int(0, | |
| 332 | - "SELECT fid FROM mlink WHERE fnid=%d AND mid=%d", | |
| 333 | - fnid, baseCheckin | |
| 334 | - ); | |
| 335 | - bag_init(&ancestor); | |
| 336 | - if( baseFid ) bag_insert(&ancestor, baseFid); | |
| 331 | + compute_direct_ancestors(baseCheckin); | |
| 337 | 332 | } |
| 338 | 333 | url_add_parameter(&url, "name", zFilename); |
| 339 | 334 | blob_zero(&sql); |
| 340 | 335 | blob_append_sql(&sql, |
| 341 | 336 | "SELECT" |
| @@ -363,23 +358,30 @@ | ||
| 363 | 358 | } |
| 364 | 359 | if( (zB = P("b"))!=0 ){ |
| 365 | 360 | blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB); |
| 366 | 361 | url_add_parameter(&url, "b", zB); |
| 367 | 362 | } |
| 368 | - /* We only want each version of a file to appear on the graph once, | |
| 369 | - ** at its earliest appearance. All the other times that it gets merged | |
| 370 | - ** into this or that branch can be ignored. An exception is for when | |
| 371 | - ** files are deleted (when they have mlink.fid==0). If the same file | |
| 372 | - ** is deleted in multiple places, we want to show each deletion, so | |
| 373 | - ** use a "fake fid" which is derived from the parent-fid for grouping. | |
| 374 | - ** The same fake-fid must be used on the graph. | |
| 375 | - */ | |
| 376 | - blob_append_sql(&sql, | |
| 377 | - " GROUP BY" | |
| 378 | - " CASE WHEN mlink.fid>0 THEN mlink.fid ELSE mlink.pid+1000000000 END" | |
| 379 | - " ORDER BY event.mtime DESC /*sort*/" | |
| 380 | - ); | |
| 363 | + if( baseCheckin ){ | |
| 364 | + blob_append_sql(&sql, | |
| 365 | + " AND mlink.mid IN (SELECT rid FROM ancestor)" | |
| 366 | + " GROUP BY mlink.fid" | |
| 367 | + ); | |
| 368 | + }else{ | |
| 369 | + /* We only want each version of a file to appear on the graph once, | |
| 370 | + ** at its earliest appearance. All the other times that it gets merged | |
| 371 | + ** into this or that branch can be ignored. An exception is for when | |
| 372 | + ** files are deleted (when they have mlink.fid==0). If the same file | |
| 373 | + ** is deleted in multiple places, we want to show each deletion, so | |
| 374 | + ** use a "fake fid" which is derived from the parent-fid for grouping. | |
| 375 | + ** The same fake-fid must be used on the graph. | |
| 376 | + */ | |
| 377 | + blob_append_sql(&sql, | |
| 378 | + " GROUP BY" | |
| 379 | + " CASE WHEN mlink.fid>0 THEN mlink.fid ELSE mlink.pid+1000000000 END" | |
| 380 | + ); | |
| 381 | + } | |
| 382 | + blob_append_sql(&sql, " ORDER BY event.mtime DESC /*sort*/"); | |
| 381 | 383 | if( (n = atoi(PD("n","0")))>0 ){ |
| 382 | 384 | blob_append_sql(&sql, " LIMIT %d", n); |
| 383 | 385 | url_add_parameter(&url, "n", P("n")); |
| 384 | 386 | } |
| 385 | 387 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| @@ -389,12 +391,16 @@ | ||
| 389 | 391 | blob_reset(&sql); |
| 390 | 392 | blob_zero(&title); |
| 391 | 393 | if( baseCheckin ){ |
| 392 | 394 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin); |
| 393 | 395 | char *zLink = href("%R/info/%!S", zUuid); |
| 394 | - blob_appendf(&title, "Ancestors of file "); | |
| 395 | - hyperlinked_path(zFilename, &title, zUuid, "tree", ""); | |
| 396 | + if( n>0 ){ | |
| 397 | + blob_appendf(&title, "First %d ancestors of file ", n); | |
| 398 | + }else{ | |
| 399 | + blob_appendf(&title, "Ancestors of file "); | |
| 400 | + } | |
| 401 | + blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>", zFilename, zFilename); | |
| 396 | 402 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 397 | 403 | blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid); |
| 398 | 404 | if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin); |
| 399 | 405 | fossil_free(zUuid); |
| 400 | 406 | }else{ |
| @@ -404,10 +410,24 @@ | ||
| 404 | 410 | } |
| 405 | 411 | @ <h2>%b(&title)</h2> |
| 406 | 412 | blob_reset(&title); |
| 407 | 413 | pGraph = graph_init(); |
| 408 | 414 | @ <table id="timelineTable" class="timelineTable"> |
| 415 | + if( baseCheckin ){ | |
| 416 | + db_prepare(&qparent, | |
| 417 | + "SELECT DISTINCT pid FROM mlink" | |
| 418 | + " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" | |
| 419 | + " AND pmid IN (SELECT rid FROM ancestor)" | |
| 420 | + " ORDER BY isaux /*sort*/" | |
| 421 | + ); | |
| 422 | + }else{ | |
| 423 | + db_prepare(&qparent, | |
| 424 | + "SELECT DISTINCT pid FROM mlink" | |
| 425 | + " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" | |
| 426 | + " ORDER BY isaux /*sort*/" | |
| 427 | + ); | |
| 428 | + } | |
| 409 | 429 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | 430 | const char *zDate = db_column_text(&q, 0); |
| 411 | 431 | const char *zCom = db_column_text(&q, 1); |
| 412 | 432 | const char *zUser = db_column_text(&q, 2); |
| 413 | 433 | int fpid = db_column_int(&q, 3); |
| @@ -421,24 +441,16 @@ | ||
| 421 | 441 | int pfnid = db_column_int(&q, 11); |
| 422 | 442 | int gidx; |
| 423 | 443 | char zTime[10]; |
| 424 | 444 | int nParent = 0; |
| 425 | 445 | int aParent[GR_MAX_RAIL]; |
| 426 | - static Stmt qparent; | |
| 427 | - | |
| 428 | - if( baseCheckin && frid && !bag_find(&ancestor, frid) ) continue; | |
| 429 | - db_static_prepare(&qparent, | |
| 430 | - "SELECT DISTINCT pid FROM mlink" | |
| 431 | - " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" | |
| 432 | - " ORDER BY isaux /*sort*/" | |
| 433 | - ); | |
| 446 | + | |
| 434 | 447 | db_bind_int(&qparent, ":fid", frid); |
| 435 | 448 | db_bind_int(&qparent, ":mid", fmid); |
| 436 | 449 | db_bind_int(&qparent, ":fnid", fnid); |
| 437 | 450 | while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ |
| 438 | 451 | aParent[nParent] = db_column_int(&qparent, 0); |
| 439 | - if( baseCheckin ) bag_insert(&ancestor, aParent[nParent]); | |
| 440 | 452 | nParent++; |
| 441 | 453 | } |
| 442 | 454 | db_reset(&qparent); |
| 443 | 455 | if( zBr==0 ) zBr = "trunk"; |
| 444 | 456 | if( uBg ){ |
| @@ -528,10 +540,11 @@ | ||
| 528 | 540 | } |
| 529 | 541 | tag_private_status(frid); |
| 530 | 542 | @ </td></tr> |
| 531 | 543 | } |
| 532 | 544 | db_finalize(&q); |
| 545 | + db_finalize(&qparent); | |
| 533 | 546 | if( pGraph ){ |
| 534 | 547 | graph_finish(pGraph, 1); |
| 535 | 548 | if( pGraph->nErr ){ |
| 536 | 549 | graph_free(pGraph); |
| 537 | 550 | pGraph = 0; |
| 538 | 551 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -299,19 +299,19 @@ | |
| 299 | const char *zA; |
| 300 | const char *zB; |
| 301 | int n; |
| 302 | int baseCheckin; |
| 303 | int fnid; |
| 304 | Bag ancestor; |
| 305 | Blob title; |
| 306 | Blob sql; |
| 307 | HQuery url; |
| 308 | GraphContext *pGraph; |
| 309 | int brBg = P("brbg")!=0; |
| 310 | int uBg = P("ubg")!=0; |
| 311 | int fDebug = atoi(PD("debug","0")); |
| 312 | int fShowId = P("showid")!=0; |
| 313 | |
| 314 | login_check_credentials(); |
| 315 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 316 | style_header("File History"); |
| 317 | login_anonymous_available(); |
| @@ -326,16 +326,11 @@ | |
| 326 | @ No such file: %h(zFilename) |
| 327 | style_footer(); |
| 328 | return; |
| 329 | } |
| 330 | if( baseCheckin ){ |
| 331 | int baseFid = db_int(0, |
| 332 | "SELECT fid FROM mlink WHERE fnid=%d AND mid=%d", |
| 333 | fnid, baseCheckin |
| 334 | ); |
| 335 | bag_init(&ancestor); |
| 336 | if( baseFid ) bag_insert(&ancestor, baseFid); |
| 337 | } |
| 338 | url_add_parameter(&url, "name", zFilename); |
| 339 | blob_zero(&sql); |
| 340 | blob_append_sql(&sql, |
| 341 | "SELECT" |
| @@ -363,23 +358,30 @@ | |
| 363 | } |
| 364 | if( (zB = P("b"))!=0 ){ |
| 365 | blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB); |
| 366 | url_add_parameter(&url, "b", zB); |
| 367 | } |
| 368 | /* We only want each version of a file to appear on the graph once, |
| 369 | ** at its earliest appearance. All the other times that it gets merged |
| 370 | ** into this or that branch can be ignored. An exception is for when |
| 371 | ** files are deleted (when they have mlink.fid==0). If the same file |
| 372 | ** is deleted in multiple places, we want to show each deletion, so |
| 373 | ** use a "fake fid" which is derived from the parent-fid for grouping. |
| 374 | ** The same fake-fid must be used on the graph. |
| 375 | */ |
| 376 | blob_append_sql(&sql, |
| 377 | " GROUP BY" |
| 378 | " CASE WHEN mlink.fid>0 THEN mlink.fid ELSE mlink.pid+1000000000 END" |
| 379 | " ORDER BY event.mtime DESC /*sort*/" |
| 380 | ); |
| 381 | if( (n = atoi(PD("n","0")))>0 ){ |
| 382 | blob_append_sql(&sql, " LIMIT %d", n); |
| 383 | url_add_parameter(&url, "n", P("n")); |
| 384 | } |
| 385 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| @@ -389,12 +391,16 @@ | |
| 389 | blob_reset(&sql); |
| 390 | blob_zero(&title); |
| 391 | if( baseCheckin ){ |
| 392 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin); |
| 393 | char *zLink = href("%R/info/%!S", zUuid); |
| 394 | blob_appendf(&title, "Ancestors of file "); |
| 395 | hyperlinked_path(zFilename, &title, zUuid, "tree", ""); |
| 396 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 397 | blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid); |
| 398 | if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin); |
| 399 | fossil_free(zUuid); |
| 400 | }else{ |
| @@ -404,10 +410,24 @@ | |
| 404 | } |
| 405 | @ <h2>%b(&title)</h2> |
| 406 | blob_reset(&title); |
| 407 | pGraph = graph_init(); |
| 408 | @ <table id="timelineTable" class="timelineTable"> |
| 409 | while( db_step(&q)==SQLITE_ROW ){ |
| 410 | const char *zDate = db_column_text(&q, 0); |
| 411 | const char *zCom = db_column_text(&q, 1); |
| 412 | const char *zUser = db_column_text(&q, 2); |
| 413 | int fpid = db_column_int(&q, 3); |
| @@ -421,24 +441,16 @@ | |
| 421 | int pfnid = db_column_int(&q, 11); |
| 422 | int gidx; |
| 423 | char zTime[10]; |
| 424 | int nParent = 0; |
| 425 | int aParent[GR_MAX_RAIL]; |
| 426 | static Stmt qparent; |
| 427 | |
| 428 | if( baseCheckin && frid && !bag_find(&ancestor, frid) ) continue; |
| 429 | db_static_prepare(&qparent, |
| 430 | "SELECT DISTINCT pid FROM mlink" |
| 431 | " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" |
| 432 | " ORDER BY isaux /*sort*/" |
| 433 | ); |
| 434 | db_bind_int(&qparent, ":fid", frid); |
| 435 | db_bind_int(&qparent, ":mid", fmid); |
| 436 | db_bind_int(&qparent, ":fnid", fnid); |
| 437 | while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ |
| 438 | aParent[nParent] = db_column_int(&qparent, 0); |
| 439 | if( baseCheckin ) bag_insert(&ancestor, aParent[nParent]); |
| 440 | nParent++; |
| 441 | } |
| 442 | db_reset(&qparent); |
| 443 | if( zBr==0 ) zBr = "trunk"; |
| 444 | if( uBg ){ |
| @@ -528,10 +540,11 @@ | |
| 528 | } |
| 529 | tag_private_status(frid); |
| 530 | @ </td></tr> |
| 531 | } |
| 532 | db_finalize(&q); |
| 533 | if( pGraph ){ |
| 534 | graph_finish(pGraph, 1); |
| 535 | if( pGraph->nErr ){ |
| 536 | graph_free(pGraph); |
| 537 | pGraph = 0; |
| 538 |
| --- src/finfo.c | |
| +++ src/finfo.c | |
| @@ -299,19 +299,19 @@ | |
| 299 | const char *zA; |
| 300 | const char *zB; |
| 301 | int n; |
| 302 | int baseCheckin; |
| 303 | int fnid; |
| 304 | Blob title; |
| 305 | Blob sql; |
| 306 | HQuery url; |
| 307 | GraphContext *pGraph; |
| 308 | int brBg = P("brbg")!=0; |
| 309 | int uBg = P("ubg")!=0; |
| 310 | int fDebug = atoi(PD("debug","0")); |
| 311 | int fShowId = P("showid")!=0; |
| 312 | Stmt qparent; |
| 313 | |
| 314 | login_check_credentials(); |
| 315 | if( !g.perm.Read ){ login_needed(g.anon.Read); return; } |
| 316 | style_header("File History"); |
| 317 | login_anonymous_available(); |
| @@ -326,16 +326,11 @@ | |
| 326 | @ No such file: %h(zFilename) |
| 327 | style_footer(); |
| 328 | return; |
| 329 | } |
| 330 | if( baseCheckin ){ |
| 331 | compute_direct_ancestors(baseCheckin); |
| 332 | } |
| 333 | url_add_parameter(&url, "name", zFilename); |
| 334 | blob_zero(&sql); |
| 335 | blob_append_sql(&sql, |
| 336 | "SELECT" |
| @@ -363,23 +358,30 @@ | |
| 358 | } |
| 359 | if( (zB = P("b"))!=0 ){ |
| 360 | blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zB); |
| 361 | url_add_parameter(&url, "b", zB); |
| 362 | } |
| 363 | if( baseCheckin ){ |
| 364 | blob_append_sql(&sql, |
| 365 | " AND mlink.mid IN (SELECT rid FROM ancestor)" |
| 366 | " GROUP BY mlink.fid" |
| 367 | ); |
| 368 | }else{ |
| 369 | /* We only want each version of a file to appear on the graph once, |
| 370 | ** at its earliest appearance. All the other times that it gets merged |
| 371 | ** into this or that branch can be ignored. An exception is for when |
| 372 | ** files are deleted (when they have mlink.fid==0). If the same file |
| 373 | ** is deleted in multiple places, we want to show each deletion, so |
| 374 | ** use a "fake fid" which is derived from the parent-fid for grouping. |
| 375 | ** The same fake-fid must be used on the graph. |
| 376 | */ |
| 377 | blob_append_sql(&sql, |
| 378 | " GROUP BY" |
| 379 | " CASE WHEN mlink.fid>0 THEN mlink.fid ELSE mlink.pid+1000000000 END" |
| 380 | ); |
| 381 | } |
| 382 | blob_append_sql(&sql, " ORDER BY event.mtime DESC /*sort*/"); |
| 383 | if( (n = atoi(PD("n","0")))>0 ){ |
| 384 | blob_append_sql(&sql, " LIMIT %d", n); |
| 385 | url_add_parameter(&url, "n", P("n")); |
| 386 | } |
| 387 | db_prepare(&q, "%s", blob_sql_text(&sql)); |
| @@ -389,12 +391,16 @@ | |
| 391 | blob_reset(&sql); |
| 392 | blob_zero(&title); |
| 393 | if( baseCheckin ){ |
| 394 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", baseCheckin); |
| 395 | char *zLink = href("%R/info/%!S", zUuid); |
| 396 | if( n>0 ){ |
| 397 | blob_appendf(&title, "First %d ancestors of file ", n); |
| 398 | }else{ |
| 399 | blob_appendf(&title, "Ancestors of file "); |
| 400 | } |
| 401 | blob_appendf(&title,"<a href='%R/finfo?name=%T'>%h</a>", zFilename, zFilename); |
| 402 | if( fShowId ) blob_appendf(&title, " (%d)", fnid); |
| 403 | blob_appendf(&title, " from check-in %z%S</a>", zLink, zUuid); |
| 404 | if( fShowId ) blob_appendf(&title, " (%d)", baseCheckin); |
| 405 | fossil_free(zUuid); |
| 406 | }else{ |
| @@ -404,10 +410,24 @@ | |
| 410 | } |
| 411 | @ <h2>%b(&title)</h2> |
| 412 | blob_reset(&title); |
| 413 | pGraph = graph_init(); |
| 414 | @ <table id="timelineTable" class="timelineTable"> |
| 415 | if( baseCheckin ){ |
| 416 | db_prepare(&qparent, |
| 417 | "SELECT DISTINCT pid FROM mlink" |
| 418 | " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" |
| 419 | " AND pmid IN (SELECT rid FROM ancestor)" |
| 420 | " ORDER BY isaux /*sort*/" |
| 421 | ); |
| 422 | }else{ |
| 423 | db_prepare(&qparent, |
| 424 | "SELECT DISTINCT pid FROM mlink" |
| 425 | " WHERE fid=:fid AND mid=:mid AND pid>0 AND fnid=:fnid" |
| 426 | " ORDER BY isaux /*sort*/" |
| 427 | ); |
| 428 | } |
| 429 | while( db_step(&q)==SQLITE_ROW ){ |
| 430 | const char *zDate = db_column_text(&q, 0); |
| 431 | const char *zCom = db_column_text(&q, 1); |
| 432 | const char *zUser = db_column_text(&q, 2); |
| 433 | int fpid = db_column_int(&q, 3); |
| @@ -421,24 +441,16 @@ | |
| 441 | int pfnid = db_column_int(&q, 11); |
| 442 | int gidx; |
| 443 | char zTime[10]; |
| 444 | int nParent = 0; |
| 445 | int aParent[GR_MAX_RAIL]; |
| 446 | |
| 447 | db_bind_int(&qparent, ":fid", frid); |
| 448 | db_bind_int(&qparent, ":mid", fmid); |
| 449 | db_bind_int(&qparent, ":fnid", fnid); |
| 450 | while( db_step(&qparent)==SQLITE_ROW && nParent<ArraySize(aParent) ){ |
| 451 | aParent[nParent] = db_column_int(&qparent, 0); |
| 452 | nParent++; |
| 453 | } |
| 454 | db_reset(&qparent); |
| 455 | if( zBr==0 ) zBr = "trunk"; |
| 456 | if( uBg ){ |
| @@ -528,10 +540,11 @@ | |
| 540 | } |
| 541 | tag_private_status(frid); |
| 542 | @ </td></tr> |
| 543 | } |
| 544 | db_finalize(&q); |
| 545 | db_finalize(&qparent); |
| 546 | if( pGraph ){ |
| 547 | graph_finish(pGraph, 1); |
| 548 | if( pGraph->nErr ){ |
| 549 | graph_free(pGraph); |
| 550 | pGraph = 0; |
| 551 |