Fossil SCM
Add the "vpatch" web method that returns the difference between two checkins as text/plain and a a "patch" hyperlink on the checkin information page that jumps to the appropriate vpatch page.
Commit
4bdf71b1ce3e16c5fa309405f183d14b35816f7e
Parent
3b82ee5483bf8aa…
2 files changed
+43
-13
+54
-36
+43
-13
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -24,17 +24,32 @@ | ||
| 24 | 24 | /* |
| 25 | 25 | ** Diff option flags |
| 26 | 26 | */ |
| 27 | 27 | #define DIFF_NEWFILE 0x01 /* Treat non-existing fails as empty files */ |
| 28 | 28 | #define DIFF_NOEOLWS 0x02 /* Ignore whitespace at the end of lines */ |
| 29 | + | |
| 30 | +/* | |
| 31 | +** Output the results of a diff. Output goes to stdout for command-line | |
| 32 | +** or to the CGI/HTTP result buffer for web pages. | |
| 33 | +*/ | |
| 34 | +static void diff_printf(const char *zFormat, ...){ | |
| 35 | + va_list ap; | |
| 36 | + va_start(ap, zFormat); | |
| 37 | + if( g.cgiOutput ){ | |
| 38 | + cgi_vprintf(zFormat, ap); | |
| 39 | + }else{ | |
| 40 | + vprintf(zFormat, ap); | |
| 41 | + } | |
| 42 | + va_end(ap); | |
| 43 | +} | |
| 29 | 44 | |
| 30 | 45 | /* |
| 31 | 46 | ** Print the "Index:" message that patch wants to see at the top of a diff. |
| 32 | 47 | */ |
| 33 | 48 | void diff_print_index(const char *zFile){ |
| 34 | - printf("Index: %s\n=======================================" | |
| 35 | - "============================\n", zFile); | |
| 49 | + diff_printf("Index: %s\n=======================================" | |
| 50 | + "============================\n", zFile); | |
| 36 | 51 | } |
| 37 | 52 | |
| 38 | 53 | /* |
| 39 | 54 | ** Show the difference between two files, one in memory and one on disk. |
| 40 | 55 | ** |
| @@ -67,12 +82,12 @@ | ||
| 67 | 82 | |
| 68 | 83 | /* Compute and output the differences */ |
| 69 | 84 | blob_zero(&out); |
| 70 | 85 | text_diff(pFile1, &file2, &out, 5, ignoreEolWs); |
| 71 | 86 | if( blob_size(&out) ){ |
| 72 | - printf("--- %s\n+++ %s\n", zName, zName2); | |
| 73 | - printf("%s\n", blob_str(&out)); | |
| 87 | + diff_printf("--- %s\n+++ %s\n", zName, zName2); | |
| 88 | + diff_printf("%s\n", blob_str(&out)); | |
| 74 | 89 | } |
| 75 | 90 | |
| 76 | 91 | /* Release memory resources */ |
| 77 | 92 | blob_reset(&file2); |
| 78 | 93 | blob_reset(&out); |
| @@ -126,12 +141,12 @@ | ||
| 126 | 141 | if( zDiffCmd==0 ){ |
| 127 | 142 | Blob out; /* Diff output text */ |
| 128 | 143 | |
| 129 | 144 | blob_zero(&out); |
| 130 | 145 | text_diff(pFile1, pFile2, &out, 5, ignoreEolWs); |
| 131 | - printf("--- %s\n+++ %s\n", zName, zName); | |
| 132 | - printf("%s\n", blob_str(&out)); | |
| 146 | + diff_printf("--- %s\n+++ %s\n", zName, zName); | |
| 147 | + diff_printf("%s\n", blob_str(&out)); | |
| 133 | 148 | |
| 134 | 149 | /* Release memory resources */ |
| 135 | 150 | blob_reset(&out); |
| 136 | 151 | }else{ |
| 137 | 152 | Blob cmd; |
| @@ -246,21 +261,21 @@ | ||
| 246 | 261 | int srcid = db_column_int(&q, 4); |
| 247 | 262 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 248 | 263 | char *zToFree = zFullName; |
| 249 | 264 | int showDiff = 1; |
| 250 | 265 | if( isDeleted ){ |
| 251 | - printf("DELETED %s\n", zPathname); | |
| 266 | + diff_printf("DELETED %s\n", zPathname); | |
| 252 | 267 | if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; } |
| 253 | 268 | }else if( access(zFullName, 0) ){ |
| 254 | - printf("MISSING %s\n", zPathname); | |
| 269 | + diff_printf("MISSING %s\n", zPathname); | |
| 255 | 270 | if( !asNewFile ){ showDiff = 0; } |
| 256 | 271 | }else if( isNew ){ |
| 257 | - printf("ADDED %s\n", zPathname); | |
| 272 | + diff_printf("ADDED %s\n", zPathname); | |
| 258 | 273 | srcid = 0; |
| 259 | 274 | if( !asNewFile ){ showDiff = 0; } |
| 260 | 275 | }else if( isChnged==3 ){ |
| 261 | - printf("ADDED_BY_MERGE %s\n", zPathname); | |
| 276 | + diff_printf("ADDED_BY_MERGE %s\n", zPathname); | |
| 262 | 277 | srcid = 0; |
| 263 | 278 | if( !asNewFile ){ showDiff = 0; } |
| 264 | 279 | } |
| 265 | 280 | if( showDiff ){ |
| 266 | 281 | Blob content; |
| @@ -363,27 +378,27 @@ | ||
| 363 | 378 | cmp = -1; |
| 364 | 379 | }else{ |
| 365 | 380 | cmp = fossil_strcmp(pFromFile->zName, pToFile->zName); |
| 366 | 381 | } |
| 367 | 382 | if( cmp<0 ){ |
| 368 | - printf("DELETED %s\n", pFromFile->zName); | |
| 383 | + diff_printf("DELETED %s\n", pFromFile->zName); | |
| 369 | 384 | if( asNewFlag ){ |
| 370 | 385 | diff_manifest_entry(pFromFile, 0, zDiffCmd, ignoreEolWs); |
| 371 | 386 | } |
| 372 | 387 | pFromFile = manifest_file_next(pFrom,0); |
| 373 | 388 | }else if( cmp>0 ){ |
| 374 | - printf("ADDED %s\n", pToFile->zName); | |
| 389 | + diff_printf("ADDED %s\n", pToFile->zName); | |
| 375 | 390 | if( asNewFlag ){ |
| 376 | 391 | diff_manifest_entry(0, pToFile, zDiffCmd, ignoreEolWs); |
| 377 | 392 | } |
| 378 | 393 | pToFile = manifest_file_next(pTo,0); |
| 379 | 394 | }else if( fossil_strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){ |
| 380 | 395 | /* No changes */ |
| 381 | 396 | pFromFile = manifest_file_next(pFrom,0); |
| 382 | 397 | pToFile = manifest_file_next(pTo,0); |
| 383 | 398 | }else{ |
| 384 | - printf("CHANGED %s\n", pFromFile->zName); | |
| 399 | + diff_printf("CHANGED %s\n", pFromFile->zName); | |
| 385 | 400 | diff_manifest_entry(pFromFile, pToFile, zDiffCmd, ignoreEolWs); |
| 386 | 401 | pFromFile = manifest_file_next(pFrom,0); |
| 387 | 402 | pToFile = manifest_file_next(pTo,0); |
| 388 | 403 | } |
| 389 | 404 | } |
| @@ -460,5 +475,20 @@ | ||
| 460 | 475 | }else{ |
| 461 | 476 | diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags); |
| 462 | 477 | } |
| 463 | 478 | } |
| 464 | 479 | } |
| 480 | + | |
| 481 | +/* | |
| 482 | +** WEBPAGE: vpatch | |
| 483 | +** URL vpatch?from=UUID&to=UUID | |
| 484 | +*/ | |
| 485 | +void vpatch_page(void){ | |
| 486 | + const char *zFrom = P("from"); | |
| 487 | + const char *zTo = P("to"); | |
| 488 | + login_check_credentials(); | |
| 489 | + if( !g.okRead ){ login_needed(); return; } | |
| 490 | + if( zFrom==0 || zTo==0 ) fossil_redirect_home(); | |
| 491 | + | |
| 492 | + cgi_set_content_type("text/plain"); | |
| 493 | + diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE); | |
| 494 | +} | |
| 465 | 495 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -24,17 +24,32 @@ | |
| 24 | /* |
| 25 | ** Diff option flags |
| 26 | */ |
| 27 | #define DIFF_NEWFILE 0x01 /* Treat non-existing fails as empty files */ |
| 28 | #define DIFF_NOEOLWS 0x02 /* Ignore whitespace at the end of lines */ |
| 29 | |
| 30 | /* |
| 31 | ** Print the "Index:" message that patch wants to see at the top of a diff. |
| 32 | */ |
| 33 | void diff_print_index(const char *zFile){ |
| 34 | printf("Index: %s\n=======================================" |
| 35 | "============================\n", zFile); |
| 36 | } |
| 37 | |
| 38 | /* |
| 39 | ** Show the difference between two files, one in memory and one on disk. |
| 40 | ** |
| @@ -67,12 +82,12 @@ | |
| 67 | |
| 68 | /* Compute and output the differences */ |
| 69 | blob_zero(&out); |
| 70 | text_diff(pFile1, &file2, &out, 5, ignoreEolWs); |
| 71 | if( blob_size(&out) ){ |
| 72 | printf("--- %s\n+++ %s\n", zName, zName2); |
| 73 | printf("%s\n", blob_str(&out)); |
| 74 | } |
| 75 | |
| 76 | /* Release memory resources */ |
| 77 | blob_reset(&file2); |
| 78 | blob_reset(&out); |
| @@ -126,12 +141,12 @@ | |
| 126 | if( zDiffCmd==0 ){ |
| 127 | Blob out; /* Diff output text */ |
| 128 | |
| 129 | blob_zero(&out); |
| 130 | text_diff(pFile1, pFile2, &out, 5, ignoreEolWs); |
| 131 | printf("--- %s\n+++ %s\n", zName, zName); |
| 132 | printf("%s\n", blob_str(&out)); |
| 133 | |
| 134 | /* Release memory resources */ |
| 135 | blob_reset(&out); |
| 136 | }else{ |
| 137 | Blob cmd; |
| @@ -246,21 +261,21 @@ | |
| 246 | int srcid = db_column_int(&q, 4); |
| 247 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 248 | char *zToFree = zFullName; |
| 249 | int showDiff = 1; |
| 250 | if( isDeleted ){ |
| 251 | printf("DELETED %s\n", zPathname); |
| 252 | if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; } |
| 253 | }else if( access(zFullName, 0) ){ |
| 254 | printf("MISSING %s\n", zPathname); |
| 255 | if( !asNewFile ){ showDiff = 0; } |
| 256 | }else if( isNew ){ |
| 257 | printf("ADDED %s\n", zPathname); |
| 258 | srcid = 0; |
| 259 | if( !asNewFile ){ showDiff = 0; } |
| 260 | }else if( isChnged==3 ){ |
| 261 | printf("ADDED_BY_MERGE %s\n", zPathname); |
| 262 | srcid = 0; |
| 263 | if( !asNewFile ){ showDiff = 0; } |
| 264 | } |
| 265 | if( showDiff ){ |
| 266 | Blob content; |
| @@ -363,27 +378,27 @@ | |
| 363 | cmp = -1; |
| 364 | }else{ |
| 365 | cmp = fossil_strcmp(pFromFile->zName, pToFile->zName); |
| 366 | } |
| 367 | if( cmp<0 ){ |
| 368 | printf("DELETED %s\n", pFromFile->zName); |
| 369 | if( asNewFlag ){ |
| 370 | diff_manifest_entry(pFromFile, 0, zDiffCmd, ignoreEolWs); |
| 371 | } |
| 372 | pFromFile = manifest_file_next(pFrom,0); |
| 373 | }else if( cmp>0 ){ |
| 374 | printf("ADDED %s\n", pToFile->zName); |
| 375 | if( asNewFlag ){ |
| 376 | diff_manifest_entry(0, pToFile, zDiffCmd, ignoreEolWs); |
| 377 | } |
| 378 | pToFile = manifest_file_next(pTo,0); |
| 379 | }else if( fossil_strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){ |
| 380 | /* No changes */ |
| 381 | pFromFile = manifest_file_next(pFrom,0); |
| 382 | pToFile = manifest_file_next(pTo,0); |
| 383 | }else{ |
| 384 | printf("CHANGED %s\n", pFromFile->zName); |
| 385 | diff_manifest_entry(pFromFile, pToFile, zDiffCmd, ignoreEolWs); |
| 386 | pFromFile = manifest_file_next(pFrom,0); |
| 387 | pToFile = manifest_file_next(pTo,0); |
| 388 | } |
| 389 | } |
| @@ -460,5 +475,20 @@ | |
| 460 | }else{ |
| 461 | diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags); |
| 462 | } |
| 463 | } |
| 464 | } |
| 465 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -24,17 +24,32 @@ | |
| 24 | /* |
| 25 | ** Diff option flags |
| 26 | */ |
| 27 | #define DIFF_NEWFILE 0x01 /* Treat non-existing fails as empty files */ |
| 28 | #define DIFF_NOEOLWS 0x02 /* Ignore whitespace at the end of lines */ |
| 29 | |
| 30 | /* |
| 31 | ** Output the results of a diff. Output goes to stdout for command-line |
| 32 | ** or to the CGI/HTTP result buffer for web pages. |
| 33 | */ |
| 34 | static void diff_printf(const char *zFormat, ...){ |
| 35 | va_list ap; |
| 36 | va_start(ap, zFormat); |
| 37 | if( g.cgiOutput ){ |
| 38 | cgi_vprintf(zFormat, ap); |
| 39 | }else{ |
| 40 | vprintf(zFormat, ap); |
| 41 | } |
| 42 | va_end(ap); |
| 43 | } |
| 44 | |
| 45 | /* |
| 46 | ** Print the "Index:" message that patch wants to see at the top of a diff. |
| 47 | */ |
| 48 | void diff_print_index(const char *zFile){ |
| 49 | diff_printf("Index: %s\n=======================================" |
| 50 | "============================\n", zFile); |
| 51 | } |
| 52 | |
| 53 | /* |
| 54 | ** Show the difference between two files, one in memory and one on disk. |
| 55 | ** |
| @@ -67,12 +82,12 @@ | |
| 82 | |
| 83 | /* Compute and output the differences */ |
| 84 | blob_zero(&out); |
| 85 | text_diff(pFile1, &file2, &out, 5, ignoreEolWs); |
| 86 | if( blob_size(&out) ){ |
| 87 | diff_printf("--- %s\n+++ %s\n", zName, zName2); |
| 88 | diff_printf("%s\n", blob_str(&out)); |
| 89 | } |
| 90 | |
| 91 | /* Release memory resources */ |
| 92 | blob_reset(&file2); |
| 93 | blob_reset(&out); |
| @@ -126,12 +141,12 @@ | |
| 141 | if( zDiffCmd==0 ){ |
| 142 | Blob out; /* Diff output text */ |
| 143 | |
| 144 | blob_zero(&out); |
| 145 | text_diff(pFile1, pFile2, &out, 5, ignoreEolWs); |
| 146 | diff_printf("--- %s\n+++ %s\n", zName, zName); |
| 147 | diff_printf("%s\n", blob_str(&out)); |
| 148 | |
| 149 | /* Release memory resources */ |
| 150 | blob_reset(&out); |
| 151 | }else{ |
| 152 | Blob cmd; |
| @@ -246,21 +261,21 @@ | |
| 261 | int srcid = db_column_int(&q, 4); |
| 262 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 263 | char *zToFree = zFullName; |
| 264 | int showDiff = 1; |
| 265 | if( isDeleted ){ |
| 266 | diff_printf("DELETED %s\n", zPathname); |
| 267 | if( !asNewFile ){ showDiff = 0; zFullName = "/dev/null"; } |
| 268 | }else if( access(zFullName, 0) ){ |
| 269 | diff_printf("MISSING %s\n", zPathname); |
| 270 | if( !asNewFile ){ showDiff = 0; } |
| 271 | }else if( isNew ){ |
| 272 | diff_printf("ADDED %s\n", zPathname); |
| 273 | srcid = 0; |
| 274 | if( !asNewFile ){ showDiff = 0; } |
| 275 | }else if( isChnged==3 ){ |
| 276 | diff_printf("ADDED_BY_MERGE %s\n", zPathname); |
| 277 | srcid = 0; |
| 278 | if( !asNewFile ){ showDiff = 0; } |
| 279 | } |
| 280 | if( showDiff ){ |
| 281 | Blob content; |
| @@ -363,27 +378,27 @@ | |
| 378 | cmp = -1; |
| 379 | }else{ |
| 380 | cmp = fossil_strcmp(pFromFile->zName, pToFile->zName); |
| 381 | } |
| 382 | if( cmp<0 ){ |
| 383 | diff_printf("DELETED %s\n", pFromFile->zName); |
| 384 | if( asNewFlag ){ |
| 385 | diff_manifest_entry(pFromFile, 0, zDiffCmd, ignoreEolWs); |
| 386 | } |
| 387 | pFromFile = manifest_file_next(pFrom,0); |
| 388 | }else if( cmp>0 ){ |
| 389 | diff_printf("ADDED %s\n", pToFile->zName); |
| 390 | if( asNewFlag ){ |
| 391 | diff_manifest_entry(0, pToFile, zDiffCmd, ignoreEolWs); |
| 392 | } |
| 393 | pToFile = manifest_file_next(pTo,0); |
| 394 | }else if( fossil_strcmp(pFromFile->zUuid, pToFile->zUuid)==0 ){ |
| 395 | /* No changes */ |
| 396 | pFromFile = manifest_file_next(pFrom,0); |
| 397 | pToFile = manifest_file_next(pTo,0); |
| 398 | }else{ |
| 399 | diff_printf("CHANGED %s\n", pFromFile->zName); |
| 400 | diff_manifest_entry(pFromFile, pToFile, zDiffCmd, ignoreEolWs); |
| 401 | pFromFile = manifest_file_next(pFrom,0); |
| 402 | pToFile = manifest_file_next(pTo,0); |
| 403 | } |
| 404 | } |
| @@ -460,5 +475,20 @@ | |
| 475 | }else{ |
| 476 | diff_all_two_versions(zFrom, zTo, zDiffCmd, diffFlags); |
| 477 | } |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | /* |
| 482 | ** WEBPAGE: vpatch |
| 483 | ** URL vpatch?from=UUID&to=UUID |
| 484 | */ |
| 485 | void vpatch_page(void){ |
| 486 | const char *zFrom = P("from"); |
| 487 | const char *zTo = P("to"); |
| 488 | login_check_credentials(); |
| 489 | if( !g.okRead ){ login_needed(); return; } |
| 490 | if( zFrom==0 || zTo==0 ) fossil_redirect_home(); |
| 491 | |
| 492 | cgi_set_content_type("text/plain"); |
| 493 | diff_all_two_versions(zFrom, zTo, 0, DIFF_NEWFILE); |
| 494 | } |
| 495 |
+54
-36
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -337,11 +337,13 @@ | ||
| 337 | 337 | void ci_page(void){ |
| 338 | 338 | Stmt q; |
| 339 | 339 | int rid; |
| 340 | 340 | int isLeaf; |
| 341 | 341 | int showDiff; |
| 342 | - const char *zName; | |
| 342 | + const char *zName; /* Name of the checkin to be displayed */ | |
| 343 | + const char *zUuid; /* UUID of zName */ | |
| 344 | + const char *zParent; /* UUID of the parent checkin (if any) */ | |
| 343 | 345 | |
| 344 | 346 | login_check_credentials(); |
| 345 | 347 | if( !g.okRead ){ login_needed(); return; } |
| 346 | 348 | zName = P("name"); |
| 347 | 349 | rid = name_to_rid_www("name"); |
| @@ -349,10 +351,16 @@ | ||
| 349 | 351 | style_header("Check-in Information Error"); |
| 350 | 352 | @ No such object: %h(g.argv[2]) |
| 351 | 353 | style_footer(); |
| 352 | 354 | return; |
| 353 | 355 | } |
| 356 | + zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); | |
| 357 | + zParent = db_text(0, | |
| 358 | + "SELECT uuid FROM plink, blob" | |
| 359 | + " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", | |
| 360 | + rid | |
| 361 | + ); | |
| 354 | 362 | isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid); |
| 355 | 363 | db_prepare(&q, |
| 356 | 364 | "SELECT uuid, datetime(mtime, 'localtime'), user, comment," |
| 357 | 365 | " datetime(omtime, 'localtime')" |
| 358 | 366 | " FROM blob, event" |
| @@ -428,13 +436,19 @@ | ||
| 428 | 436 | } |
| 429 | 437 | if( g.okHistory ){ |
| 430 | 438 | const char *zProjName = db_get("project-name", "unnamed"); |
| 431 | 439 | @ <tr><th>Timelines:</th><td> |
| 432 | 440 | @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a> |
| 433 | - @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> | |
| 434 | - @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> | |
| 435 | - @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> | |
| 441 | + if( zParent ){ | |
| 442 | + @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> | |
| 443 | + } | |
| 444 | + if( !isLeaf ){ | |
| 445 | + @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> | |
| 446 | + } | |
| 447 | + if( zParent && !isLeaf ){ | |
| 448 | + @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> | |
| 449 | + } | |
| 436 | 450 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 437 | 451 | " WHERE rid=%d AND tagtype>0 " |
| 438 | 452 | " AND tag.tagid=tagxref.tagid " |
| 439 | 453 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 440 | 454 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -462,42 +476,46 @@ | ||
| 462 | 476 | style_header("Check-in Information"); |
| 463 | 477 | login_anonymous_available(); |
| 464 | 478 | } |
| 465 | 479 | db_finalize(&q); |
| 466 | 480 | showTags(rid, ""); |
| 467 | - @ <div class="section">Changes</div> | |
| 468 | - showDiff = g.zPath[0]!='c'; | |
| 469 | - if( db_get_boolean("show-version-diffs", 0)==0 ){ | |
| 470 | - showDiff = !showDiff; | |
| 471 | - if( showDiff ){ | |
| 472 | - @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide diffs]</a><br/> | |
| 473 | - }else{ | |
| 474 | - @ <a href="%s(g.zTop)/ci/%T(zName)">[show diffs]</a><br/> | |
| 475 | - } | |
| 476 | - }else{ | |
| 477 | - if( showDiff ){ | |
| 478 | - @ <a href="%s(g.zTop)/ci/%T(zName)">[hide diffs]</a><br/> | |
| 479 | - }else{ | |
| 480 | - @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show diffs]</a><br/> | |
| 481 | - } | |
| 482 | - } | |
| 483 | - db_prepare(&q, | |
| 484 | - "SELECT name," | |
| 485 | - " (SELECT uuid FROM blob WHERE rid=mlink.pid)," | |
| 486 | - " (SELECT uuid FROM blob WHERE rid=mlink.fid)" | |
| 487 | - " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" | |
| 488 | - " WHERE mlink.mid=%d" | |
| 489 | - " ORDER BY name", | |
| 490 | - rid | |
| 491 | - ); | |
| 492 | - while( db_step(&q)==SQLITE_ROW ){ | |
| 493 | - const char *zName = db_column_text(&q,0); | |
| 494 | - const char *zOld = db_column_text(&q,1); | |
| 495 | - const char *zNew = db_column_text(&q,2); | |
| 496 | - append_file_change_line(zName, zOld, zNew, showDiff); | |
| 497 | - } | |
| 498 | - db_finalize(&q); | |
| 481 | + if( zParent ){ | |
| 482 | + @ <div class="section">Changes</div> | |
| 483 | + showDiff = g.zPath[0]!='c'; | |
| 484 | + if( db_get_boolean("show-version-diffs", 0)==0 ){ | |
| 485 | + showDiff = !showDiff; | |
| 486 | + if( showDiff ){ | |
| 487 | + @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide diffs]</a> | |
| 488 | + }else{ | |
| 489 | + @ <a href="%s(g.zTop)/ci/%T(zName)">[show diffs]</a> | |
| 490 | + } | |
| 491 | + }else{ | |
| 492 | + if( showDiff ){ | |
| 493 | + @ <a href="%s(g.zTop)/ci/%T(zName)">[hide diffs]</a> | |
| 494 | + }else{ | |
| 495 | + @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show diffs]</a> | |
| 496 | + } | |
| 497 | + } | |
| 498 | + @ | |
| 499 | + @ <a href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">[patch]</a><br/> | |
| 500 | + db_prepare(&q, | |
| 501 | + "SELECT name," | |
| 502 | + " (SELECT uuid FROM blob WHERE rid=mlink.pid)," | |
| 503 | + " (SELECT uuid FROM blob WHERE rid=mlink.fid)" | |
| 504 | + " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" | |
| 505 | + " WHERE mlink.mid=%d" | |
| 506 | + " ORDER BY name", | |
| 507 | + rid | |
| 508 | + ); | |
| 509 | + while( db_step(&q)==SQLITE_ROW ){ | |
| 510 | + const char *zName = db_column_text(&q,0); | |
| 511 | + const char *zOld = db_column_text(&q,1); | |
| 512 | + const char *zNew = db_column_text(&q,2); | |
| 513 | + append_file_change_line(zName, zOld, zNew, showDiff); | |
| 514 | + } | |
| 515 | + db_finalize(&q); | |
| 516 | + } | |
| 499 | 517 | style_footer(); |
| 500 | 518 | } |
| 501 | 519 | |
| 502 | 520 | /* |
| 503 | 521 | ** WEBPAGE: winfo |
| 504 | 522 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -337,11 +337,13 @@ | |
| 337 | void ci_page(void){ |
| 338 | Stmt q; |
| 339 | int rid; |
| 340 | int isLeaf; |
| 341 | int showDiff; |
| 342 | const char *zName; |
| 343 | |
| 344 | login_check_credentials(); |
| 345 | if( !g.okRead ){ login_needed(); return; } |
| 346 | zName = P("name"); |
| 347 | rid = name_to_rid_www("name"); |
| @@ -349,10 +351,16 @@ | |
| 349 | style_header("Check-in Information Error"); |
| 350 | @ No such object: %h(g.argv[2]) |
| 351 | style_footer(); |
| 352 | return; |
| 353 | } |
| 354 | isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid); |
| 355 | db_prepare(&q, |
| 356 | "SELECT uuid, datetime(mtime, 'localtime'), user, comment," |
| 357 | " datetime(omtime, 'localtime')" |
| 358 | " FROM blob, event" |
| @@ -428,13 +436,19 @@ | |
| 428 | } |
| 429 | if( g.okHistory ){ |
| 430 | const char *zProjName = db_get("project-name", "unnamed"); |
| 431 | @ <tr><th>Timelines:</th><td> |
| 432 | @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a> |
| 433 | @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> |
| 434 | @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> |
| 435 | @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> |
| 436 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 437 | " WHERE rid=%d AND tagtype>0 " |
| 438 | " AND tag.tagid=tagxref.tagid " |
| 439 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 440 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -462,42 +476,46 @@ | |
| 462 | style_header("Check-in Information"); |
| 463 | login_anonymous_available(); |
| 464 | } |
| 465 | db_finalize(&q); |
| 466 | showTags(rid, ""); |
| 467 | @ <div class="section">Changes</div> |
| 468 | showDiff = g.zPath[0]!='c'; |
| 469 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| 470 | showDiff = !showDiff; |
| 471 | if( showDiff ){ |
| 472 | @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide diffs]</a><br/> |
| 473 | }else{ |
| 474 | @ <a href="%s(g.zTop)/ci/%T(zName)">[show diffs]</a><br/> |
| 475 | } |
| 476 | }else{ |
| 477 | if( showDiff ){ |
| 478 | @ <a href="%s(g.zTop)/ci/%T(zName)">[hide diffs]</a><br/> |
| 479 | }else{ |
| 480 | @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show diffs]</a><br/> |
| 481 | } |
| 482 | } |
| 483 | db_prepare(&q, |
| 484 | "SELECT name," |
| 485 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 486 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)" |
| 487 | " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" |
| 488 | " WHERE mlink.mid=%d" |
| 489 | " ORDER BY name", |
| 490 | rid |
| 491 | ); |
| 492 | while( db_step(&q)==SQLITE_ROW ){ |
| 493 | const char *zName = db_column_text(&q,0); |
| 494 | const char *zOld = db_column_text(&q,1); |
| 495 | const char *zNew = db_column_text(&q,2); |
| 496 | append_file_change_line(zName, zOld, zNew, showDiff); |
| 497 | } |
| 498 | db_finalize(&q); |
| 499 | style_footer(); |
| 500 | } |
| 501 | |
| 502 | /* |
| 503 | ** WEBPAGE: winfo |
| 504 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -337,11 +337,13 @@ | |
| 337 | void ci_page(void){ |
| 338 | Stmt q; |
| 339 | int rid; |
| 340 | int isLeaf; |
| 341 | int showDiff; |
| 342 | const char *zName; /* Name of the checkin to be displayed */ |
| 343 | const char *zUuid; /* UUID of zName */ |
| 344 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 345 | |
| 346 | login_check_credentials(); |
| 347 | if( !g.okRead ){ login_needed(); return; } |
| 348 | zName = P("name"); |
| 349 | rid = name_to_rid_www("name"); |
| @@ -349,10 +351,16 @@ | |
| 351 | style_header("Check-in Information Error"); |
| 352 | @ No such object: %h(g.argv[2]) |
| 353 | style_footer(); |
| 354 | return; |
| 355 | } |
| 356 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 357 | zParent = db_text(0, |
| 358 | "SELECT uuid FROM plink, blob" |
| 359 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 360 | rid |
| 361 | ); |
| 362 | isLeaf = !db_exists("SELECT 1 FROM plink WHERE pid=%d", rid); |
| 363 | db_prepare(&q, |
| 364 | "SELECT uuid, datetime(mtime, 'localtime'), user, comment," |
| 365 | " datetime(omtime, 'localtime')" |
| 366 | " FROM blob, event" |
| @@ -428,13 +436,19 @@ | |
| 436 | } |
| 437 | if( g.okHistory ){ |
| 438 | const char *zProjName = db_get("project-name", "unnamed"); |
| 439 | @ <tr><th>Timelines:</th><td> |
| 440 | @ <a href="%s(g.zTop)/timeline?f=%S(zUuid)">family</a> |
| 441 | if( zParent ){ |
| 442 | @ | <a href="%s(g.zTop)/timeline?p=%S(zUuid)">ancestors</a> |
| 443 | } |
| 444 | if( !isLeaf ){ |
| 445 | @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)">descendants</a> |
| 446 | } |
| 447 | if( zParent && !isLeaf ){ |
| 448 | @ | <a href="%s(g.zTop)/timeline?d=%S(zUuid)&p=%S(zUuid)">both</a> |
| 449 | } |
| 450 | db_prepare(&q, "SELECT substr(tag.tagname,5) FROM tagxref, tag " |
| 451 | " WHERE rid=%d AND tagtype>0 " |
| 452 | " AND tag.tagid=tagxref.tagid " |
| 453 | " AND +tag.tagname GLOB 'sym-*'", rid); |
| 454 | while( db_step(&q)==SQLITE_ROW ){ |
| @@ -462,42 +476,46 @@ | |
| 476 | style_header("Check-in Information"); |
| 477 | login_anonymous_available(); |
| 478 | } |
| 479 | db_finalize(&q); |
| 480 | showTags(rid, ""); |
| 481 | if( zParent ){ |
| 482 | @ <div class="section">Changes</div> |
| 483 | showDiff = g.zPath[0]!='c'; |
| 484 | if( db_get_boolean("show-version-diffs", 0)==0 ){ |
| 485 | showDiff = !showDiff; |
| 486 | if( showDiff ){ |
| 487 | @ <a href="%s(g.zTop)/vinfo/%T(zName)">[hide diffs]</a> |
| 488 | }else{ |
| 489 | @ <a href="%s(g.zTop)/ci/%T(zName)">[show diffs]</a> |
| 490 | } |
| 491 | }else{ |
| 492 | if( showDiff ){ |
| 493 | @ <a href="%s(g.zTop)/ci/%T(zName)">[hide diffs]</a> |
| 494 | }else{ |
| 495 | @ <a href="%s(g.zTop)/vinfo/%T(zName)">[show diffs]</a> |
| 496 | } |
| 497 | } |
| 498 | @ |
| 499 | @ <a href="%s(g.zTop)/vpatch?from=%S(zParent)&to=%S(zUuid)">[patch]</a><br/> |
| 500 | db_prepare(&q, |
| 501 | "SELECT name," |
| 502 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 503 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)" |
| 504 | " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" |
| 505 | " WHERE mlink.mid=%d" |
| 506 | " ORDER BY name", |
| 507 | rid |
| 508 | ); |
| 509 | while( db_step(&q)==SQLITE_ROW ){ |
| 510 | const char *zName = db_column_text(&q,0); |
| 511 | const char *zOld = db_column_text(&q,1); |
| 512 | const char *zNew = db_column_text(&q,2); |
| 513 | append_file_change_line(zName, zOld, zNew, showDiff); |
| 514 | } |
| 515 | db_finalize(&q); |
| 516 | } |
| 517 | style_footer(); |
| 518 | } |
| 519 | |
| 520 | /* |
| 521 | ** WEBPAGE: winfo |
| 522 |