Fossil SCM
Make two passes through list of local changes so all "one-line" entries are listed first.
Commit
bc56945ea4fe42e4d903f4a6e8e38a55c49a5980c5a13ab9bae771d4cbbc9515
Parent
ccebe22576d1b60…
1 file changed
+81
-43
+81
-43
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -1,18 +1,14 @@ | ||
| 1 | 1 | /*TODO |
| 2 | 2 | ** o Should /file behave differently for non-existent local files? |
| 3 | 3 | ** o Look at adding an "extras" option (non-added, non-ignored files). |
| 4 | -** o Look at sifting out "one line" differences from those with "diff blocks". | |
| 5 | -** Perhaps reset the query and re-run, displaying only non-diff entries the | |
| 6 | -** first time? Or perhaps buffer the output (probably bad idea). | |
| 7 | -** o If I keep the extra <hr/> I've added after a diff-block, is there a way | |
| 8 | -** to avoid the double <hr/> if the last entry has a diff-block? | |
| 9 | 4 | ** o Find a place to add links to /local. |
| 10 | 5 | ** o Remove //TODO TESTING HACK TODO |
| 11 | 6 | ** ?? In hexdump_page(), should content (and downloadName?) be reset/freed? |
| 12 | 7 | ** ?? In the test fossil (\x\$Test\Fossil) there are (at time of writing) two |
| 13 | 8 | ** commits under the same artifact... is this normal? |
| 9 | +** ?? A settings entry to control one- or two-pass mode? | |
| 14 | 10 | */ |
| 15 | 11 | /* |
| 16 | 12 | ** Copyright (c) 2007 D. Richard Hipp |
| 17 | 13 | ** |
| 18 | 14 | ** This program is free software; you can redistribute it and/or |
| @@ -504,29 +500,66 @@ | ||
| 504 | 500 | static void append_local_file_change_line( |
| 505 | 501 | const char *zName, /* Name of the file that has changed */ |
| 506 | 502 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 507 | 503 | int isDeleted, /* Has the file-on-disk been removed from Fossil? */ |
| 508 | 504 | int isChnged, /* Has the file changed in some way (see vfile.c) */ |
| 509 | - int isNew, /* Has the file been ADDed (but not yet committed? */ | |
| 505 | + int isNew, /* Has the file been ADDed but not yet committed? */ | |
| 510 | 506 | int isLink, /* Is the file a symbolic link? */ |
| 511 | 507 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 512 | - ReCompiled *pRe /* Only show diffs that match this regex, if not NULL */ | |
| 508 | + ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ | |
| 509 | + int pass /* 0x01 - Display single-line entries only */ | |
| 510 | + /* 0x02 - Display entries with "diff blocks" only */ | |
| 511 | + /* 0x03 - Display both */ | |
| 513 | 512 | ){ |
| 513 | +#ifndef GLH_NO_DIVIDER | |
| 514 | + /* This remembers whether a side-by-side "diff-block" was shown the last | |
| 515 | + ** time through. If it was, we will add "<hr/>" to better separate the | |
| 516 | + ** blocks and so single-line entries (when not in two-pass mode) are easier | |
| 517 | + ** to spot. | |
| 518 | + */ | |
| 519 | + static int diffShownLastTime = 0; | |
| 520 | +#endif | |
| 514 | 521 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 515 | 522 | int isFilePresent = !file_access(zFullName, F_OK); |
| 516 | - int showDiff = 0; | |
| 517 | -//TODO TESTING HACK TODO | |
| 523 | + /* Determing up-front whether we would be showing a "diff-block" so we can | |
| 524 | + ** filter them according to which pass we are on: the first pass will show | |
| 525 | + ** only the "single-line" entries; the second will show only those with | |
| 526 | + ** diff-blocks. In single-pass mode (the original way), 'pass' will be "3", | |
| 527 | + ** so all entries are shown in their original order. | |
| 528 | + */ | |
| 529 | + int showDiff = ( isDeleted && isFilePresent ) | |
| 530 | + || ( !isDeleted && !isNew && ( ( isChnged == 1 ) | |
| 531 | + || ( isChnged == 2 ) | |
| 532 | + || ( isChnged == 4 ) | |
| 533 | + ) | |
| 534 | + ); | |
| 535 | + /* We don't use 'diffFlags' in these tests so that whether "Hide diffs" is | |
| 536 | + ** in effect or not, the order won't change. | |
| 537 | + */ | |
| 538 | + if( showDiff && (pass == 1) ){ return; } /* Don't do diff on pass 1 of 2 */ | |
| 539 | + if( !showDiff && (pass == 2) ){ return; } /* Don't do line on pass 2 of 2 */ | |
| 540 | +#ifndef GLH_NO_DIVIDER | |
| 541 | + /* If a SBS diff-block was shown by the previous entry, add a divider */ | |
| 542 | + if( diffShownLastTime && (diffFlags & DIFF_SIDEBYSIDE) ){ | |
| 543 | + @ <hr/> | |
| 544 | + } | |
| 545 | + /* Record whether we will be showing a diff-block this time. We DO factor in | |
| 546 | + ** 'diffFlags' here so that in "Hide diffs" mode, we don't get extra lines. | |
| 547 | + */ | |
| 548 | + diffShownLastTime = showDiff && diffFlags; | |
| 549 | +#endif /*GLH_NO_DIVIDER*/ | |
| 550 | +//--------------------------------------------------- TODO TESTING HACK TODO | |
| 518 | 551 | if( strncmp(zName,"aa",2)==0 ){ |
| 519 | 552 | isChnged = atoi(zName+2); |
| 520 | 553 | } |
| 521 | -//TODO TESTING HACK TODO | |
| 554 | +//--------------------------------------------------- TODO TESTING HACK TODO | |
| 522 | 555 | @ <p> |
| 523 | 556 | if( !g.perm.Hyperlink ){ |
| 524 | 557 | if( isDeleted ){ |
| 525 | 558 | if( isFilePresent ){ |
| 526 | 559 | @ Deleted %h(zName) (still present as a local file). |
| 527 | - showDiff = 1; | |
| 560 | + //TODO:Remove? showDiff = 1; | |
| 528 | 561 | }else{ |
| 529 | 562 | @ Deleted %h(zName). |
| 530 | 563 | } |
| 531 | 564 | }else if( isNew ){ |
| 532 | 565 | if( isFilePresent ){ |
| @@ -551,24 +584,23 @@ | ||
| 551 | 584 | case 8: append_status( "lost", "executable", zName, zOld); break; |
| 552 | 585 | case 9: append_status( "lost", "symlink", zName, zOld); break; |
| 553 | 586 | |
| 554 | 587 | default: /* Normal edit */ |
| 555 | 588 | @ Local changes of %h(zName). |
| 556 | - showDiff = 1; | |
| 589 | + //TODO:Remove? showDiff = 1; | |
| 557 | 590 | } |
| 558 | 591 | if( showDiff && diffFlags ){ |
| 559 | 592 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 560 | - @ <hr/> | |
| 561 | 593 | } |
| 562 | - }else{ | |
| 594 | + }else{ /* With hyperlinks */ | |
| 563 | 595 | if( isDeleted ){ |
| 564 | 596 | if( isFilePresent ){ /* DELETEd but still on disk */ |
| 565 | 597 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 566 | 598 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> (still present |
| 567 | 599 | @ as %z(href("%R/file/%T?ci=ckout&annot=removed from checkout",zName)) |
| 568 | 600 | @ [local file]</a>). |
| 569 | - showDiff = 1; | |
| 601 | + //TODO:Remove? showDiff = 1; | |
| 570 | 602 | }else{ /* DELETEd and deleted from disk */ |
| 571 | 603 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 572 | 604 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. |
| 573 | 605 | } |
| 574 | 606 | }else if( isNew ){ |
| @@ -600,25 +632,15 @@ | ||
| 600 | 632 | @ Local changes of |
| 601 | 633 | @ %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 602 | 634 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> to |
| 603 | 635 | @ %z(href("%R/file/%T?ci=ckout&annot=edited locally",zName)) |
| 604 | 636 | @ [local file]</a> |
| 605 | - showDiff = 1; | |
| 637 | + //TODO:Remove? showDiff = 1; | |
| 606 | 638 | } |
| 607 | 639 | if( showDiff ){ |
| 608 | 640 | if( diffFlags ){ |
| 609 | 641 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 610 | - /*TODO | |
| 611 | - ** Not related to the local-mode, but if two or more files have been | |
| 612 | - ** changed in a commit/"local changes", it is sometimes easy to miss | |
| 613 | - ** the switch from one to the other. The following (IMHO) makes things | |
| 614 | - ** clearer, but can mean there's a double rule at the bottom of the | |
| 615 | - ** page. If kept, a similar <hr/> should probably be added to | |
| 616 | - ** append_file_change_line() (but would need to check how things look | |
| 617 | - ** when called from /vinfo). | |
| 618 | - */ | |
| 619 | - @ <hr/> | |
| 620 | 642 | }else if( isChnged ){ |
| 621 | 643 | @ |
| 622 | 644 | @ %z(href("%R/localdiff?name=%T",zName))[diff]</a> |
| 623 | 645 | } |
| 624 | 646 | } |
| @@ -1147,10 +1169,13 @@ | ||
| 1147 | 1169 | if( pRe ){ |
| 1148 | 1170 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 1149 | 1171 | @ are shown.</b></p> |
| 1150 | 1172 | } |
| 1151 | 1173 | if( bLocalMode ){ |
| 1174 | +//--------------------------------------------------- TODO TESTING HACK TODO | |
| 1175 | + int bTwoPass = P("op")==NULL; | |
| 1176 | +//--------------------------------------------------- TODO TESTING HACK TODO | |
| 1152 | 1177 | /* Following SQL taken from diff_against_disk() in diffcmd.c */ |
| 1153 | 1178 | db_begin_transaction(); |
| 1154 | 1179 | db_prepare(&q3, |
| 1155 | 1180 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 1156 | 1181 | " FROM vfile" |
| @@ -1161,31 +1186,44 @@ | ||
| 1161 | 1186 | ); |
| 1162 | 1187 | /* TODO Have the option of showing "extras" (non-ignored files in the |
| 1163 | 1188 | ** checkout directory that have not been ADDed). If done, they should |
| 1164 | 1189 | ** be ahead of any potential "diff-blocks" so they don't get lost |
| 1165 | 1190 | ** (which is the inspiration for...) |
| 1166 | - ** TODO Consider making this two-pass, where the first pass skips anything | |
| 1167 | - ** that would show a diff-block (and the second pass only shows such | |
| 1168 | - ** entries). This would group all "one-line" entries at the top so | |
| 1169 | - ** they are less likely to be missed. | |
| 1170 | 1191 | ** TODO Possibly (at some stage) have an option to commit? |
| 1171 | 1192 | */ |
| 1172 | - while( db_step(&q3)==SQLITE_ROW ){ | |
| 1173 | - const char *zPathname = db_column_text(&q3,0); | |
| 1174 | - int isDeleted = db_column_int(&q3, 1); | |
| 1175 | - int isChnged = db_column_int(&q3,2); | |
| 1176 | - int isNew = db_column_int(&q3,3); | |
| 1177 | - int srcid = db_column_int(&q3, 4); | |
| 1178 | - int isLink = db_column_int(&q3, 5); | |
| 1179 | - char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcid); | |
| 1180 | - append_local_file_change_line(zPathname, zUuid, | |
| 1181 | - isDeleted, isChnged, isNew, isLink, diffFlags,pRe); | |
| 1182 | - free(zUuid); | |
| 1183 | - } | |
| 1184 | - db_finalize(&q3); | |
| 1193 | + /* To prevent single-line diff-entries (those without "diff-blocks") from | |
| 1194 | + ** getting "lost", there's an optional "two-pass" mode for processing | |
| 1195 | + ** differences. If enabled, the first pass will only show one-line entries | |
| 1196 | + ** and the second pass will only show those with diff-blocks. This has the | |
| 1197 | + ** side-effect of altering the order entries are shown in (but within each | |
| 1198 | + ** group the original order is maintained). | |
| 1199 | + ** | |
| 1200 | + ** If disabled, (pass gets set to 3), only one pass is made on which all | |
| 1201 | + ** entries are shown in their "normal" order. | |
| 1202 | + **TODO | |
| 1203 | + ** Add this to the original (non-local) loop? | |
| 1204 | + */ | |
| 1205 | + int pass = bTwoPass?1:3; | |
| 1206 | + do{ | |
| 1207 | + while( db_step(&q3)==SQLITE_ROW ){ | |
| 1208 | + const char *zPathname = db_column_text(&q3,0); | |
| 1209 | + int isDeleted = db_column_int(&q3, 1); | |
| 1210 | + int isChnged = db_column_int(&q3,2); | |
| 1211 | + int isNew = db_column_int(&q3,3); | |
| 1212 | + int srcid = db_column_int(&q3, 4); | |
| 1213 | + int isLink = db_column_int(&q3, 5); | |
| 1214 | + char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcid); | |
| 1215 | + append_local_file_change_line(zPathname, zUuid, | |
| 1216 | + isDeleted, isChnged, isNew, isLink, diffFlags,pRe,pass); | |
| 1217 | + free(zUuid); | |
| 1218 | + } | |
| 1219 | + db_reset(&q3); | |
| 1220 | + }while( ++pass < 3 ); /* Either "1, 2, stop" or "3, stop". */ | |
| 1221 | + db_finalize(&q3); /*TODO: Is this needed if we're reseting? */ | |
| 1185 | 1222 | db_end_transaction(1); /* ROLLBACK */ |
| 1186 | 1223 | }else{ /* Normal, non-local-mode: show diffs against parent */ |
| 1224 | + /*TODO: Implement the optional two-pass code? */ | |
| 1187 | 1225 | db_prepare(&q3, |
| 1188 | 1226 | "SELECT name," |
| 1189 | 1227 | " mperm," |
| 1190 | 1228 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 1191 | 1229 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 1192 | 1230 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1,18 +1,14 @@ | |
| 1 | /*TODO |
| 2 | ** o Should /file behave differently for non-existent local files? |
| 3 | ** o Look at adding an "extras" option (non-added, non-ignored files). |
| 4 | ** o Look at sifting out "one line" differences from those with "diff blocks". |
| 5 | ** Perhaps reset the query and re-run, displaying only non-diff entries the |
| 6 | ** first time? Or perhaps buffer the output (probably bad idea). |
| 7 | ** o If I keep the extra <hr/> I've added after a diff-block, is there a way |
| 8 | ** to avoid the double <hr/> if the last entry has a diff-block? |
| 9 | ** o Find a place to add links to /local. |
| 10 | ** o Remove //TODO TESTING HACK TODO |
| 11 | ** ?? In hexdump_page(), should content (and downloadName?) be reset/freed? |
| 12 | ** ?? In the test fossil (\x\$Test\Fossil) there are (at time of writing) two |
| 13 | ** commits under the same artifact... is this normal? |
| 14 | */ |
| 15 | /* |
| 16 | ** Copyright (c) 2007 D. Richard Hipp |
| 17 | ** |
| 18 | ** This program is free software; you can redistribute it and/or |
| @@ -504,29 +500,66 @@ | |
| 504 | static void append_local_file_change_line( |
| 505 | const char *zName, /* Name of the file that has changed */ |
| 506 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 507 | int isDeleted, /* Has the file-on-disk been removed from Fossil? */ |
| 508 | int isChnged, /* Has the file changed in some way (see vfile.c) */ |
| 509 | int isNew, /* Has the file been ADDed (but not yet committed? */ |
| 510 | int isLink, /* Is the file a symbolic link? */ |
| 511 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 512 | ReCompiled *pRe /* Only show diffs that match this regex, if not NULL */ |
| 513 | ){ |
| 514 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 515 | int isFilePresent = !file_access(zFullName, F_OK); |
| 516 | int showDiff = 0; |
| 517 | //TODO TESTING HACK TODO |
| 518 | if( strncmp(zName,"aa",2)==0 ){ |
| 519 | isChnged = atoi(zName+2); |
| 520 | } |
| 521 | //TODO TESTING HACK TODO |
| 522 | @ <p> |
| 523 | if( !g.perm.Hyperlink ){ |
| 524 | if( isDeleted ){ |
| 525 | if( isFilePresent ){ |
| 526 | @ Deleted %h(zName) (still present as a local file). |
| 527 | showDiff = 1; |
| 528 | }else{ |
| 529 | @ Deleted %h(zName). |
| 530 | } |
| 531 | }else if( isNew ){ |
| 532 | if( isFilePresent ){ |
| @@ -551,24 +584,23 @@ | |
| 551 | case 8: append_status( "lost", "executable", zName, zOld); break; |
| 552 | case 9: append_status( "lost", "symlink", zName, zOld); break; |
| 553 | |
| 554 | default: /* Normal edit */ |
| 555 | @ Local changes of %h(zName). |
| 556 | showDiff = 1; |
| 557 | } |
| 558 | if( showDiff && diffFlags ){ |
| 559 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 560 | @ <hr/> |
| 561 | } |
| 562 | }else{ |
| 563 | if( isDeleted ){ |
| 564 | if( isFilePresent ){ /* DELETEd but still on disk */ |
| 565 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 566 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> (still present |
| 567 | @ as %z(href("%R/file/%T?ci=ckout&annot=removed from checkout",zName)) |
| 568 | @ [local file]</a>). |
| 569 | showDiff = 1; |
| 570 | }else{ /* DELETEd and deleted from disk */ |
| 571 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 572 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. |
| 573 | } |
| 574 | }else if( isNew ){ |
| @@ -600,25 +632,15 @@ | |
| 600 | @ Local changes of |
| 601 | @ %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 602 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> to |
| 603 | @ %z(href("%R/file/%T?ci=ckout&annot=edited locally",zName)) |
| 604 | @ [local file]</a> |
| 605 | showDiff = 1; |
| 606 | } |
| 607 | if( showDiff ){ |
| 608 | if( diffFlags ){ |
| 609 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 610 | /*TODO |
| 611 | ** Not related to the local-mode, but if two or more files have been |
| 612 | ** changed in a commit/"local changes", it is sometimes easy to miss |
| 613 | ** the switch from one to the other. The following (IMHO) makes things |
| 614 | ** clearer, but can mean there's a double rule at the bottom of the |
| 615 | ** page. If kept, a similar <hr/> should probably be added to |
| 616 | ** append_file_change_line() (but would need to check how things look |
| 617 | ** when called from /vinfo). |
| 618 | */ |
| 619 | @ <hr/> |
| 620 | }else if( isChnged ){ |
| 621 | @ |
| 622 | @ %z(href("%R/localdiff?name=%T",zName))[diff]</a> |
| 623 | } |
| 624 | } |
| @@ -1147,10 +1169,13 @@ | |
| 1147 | if( pRe ){ |
| 1148 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 1149 | @ are shown.</b></p> |
| 1150 | } |
| 1151 | if( bLocalMode ){ |
| 1152 | /* Following SQL taken from diff_against_disk() in diffcmd.c */ |
| 1153 | db_begin_transaction(); |
| 1154 | db_prepare(&q3, |
| 1155 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 1156 | " FROM vfile" |
| @@ -1161,31 +1186,44 @@ | |
| 1161 | ); |
| 1162 | /* TODO Have the option of showing "extras" (non-ignored files in the |
| 1163 | ** checkout directory that have not been ADDed). If done, they should |
| 1164 | ** be ahead of any potential "diff-blocks" so they don't get lost |
| 1165 | ** (which is the inspiration for...) |
| 1166 | ** TODO Consider making this two-pass, where the first pass skips anything |
| 1167 | ** that would show a diff-block (and the second pass only shows such |
| 1168 | ** entries). This would group all "one-line" entries at the top so |
| 1169 | ** they are less likely to be missed. |
| 1170 | ** TODO Possibly (at some stage) have an option to commit? |
| 1171 | */ |
| 1172 | while( db_step(&q3)==SQLITE_ROW ){ |
| 1173 | const char *zPathname = db_column_text(&q3,0); |
| 1174 | int isDeleted = db_column_int(&q3, 1); |
| 1175 | int isChnged = db_column_int(&q3,2); |
| 1176 | int isNew = db_column_int(&q3,3); |
| 1177 | int srcid = db_column_int(&q3, 4); |
| 1178 | int isLink = db_column_int(&q3, 5); |
| 1179 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcid); |
| 1180 | append_local_file_change_line(zPathname, zUuid, |
| 1181 | isDeleted, isChnged, isNew, isLink, diffFlags,pRe); |
| 1182 | free(zUuid); |
| 1183 | } |
| 1184 | db_finalize(&q3); |
| 1185 | db_end_transaction(1); /* ROLLBACK */ |
| 1186 | }else{ /* Normal, non-local-mode: show diffs against parent */ |
| 1187 | db_prepare(&q3, |
| 1188 | "SELECT name," |
| 1189 | " mperm," |
| 1190 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 1191 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 1192 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -1,18 +1,14 @@ | |
| 1 | /*TODO |
| 2 | ** o Should /file behave differently for non-existent local files? |
| 3 | ** o Look at adding an "extras" option (non-added, non-ignored files). |
| 4 | ** o Find a place to add links to /local. |
| 5 | ** o Remove //TODO TESTING HACK TODO |
| 6 | ** ?? In hexdump_page(), should content (and downloadName?) be reset/freed? |
| 7 | ** ?? In the test fossil (\x\$Test\Fossil) there are (at time of writing) two |
| 8 | ** commits under the same artifact... is this normal? |
| 9 | ** ?? A settings entry to control one- or two-pass mode? |
| 10 | */ |
| 11 | /* |
| 12 | ** Copyright (c) 2007 D. Richard Hipp |
| 13 | ** |
| 14 | ** This program is free software; you can redistribute it and/or |
| @@ -504,29 +500,66 @@ | |
| 500 | static void append_local_file_change_line( |
| 501 | const char *zName, /* Name of the file that has changed */ |
| 502 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 503 | int isDeleted, /* Has the file-on-disk been removed from Fossil? */ |
| 504 | int isChnged, /* Has the file changed in some way (see vfile.c) */ |
| 505 | int isNew, /* Has the file been ADDed but not yet committed? */ |
| 506 | int isLink, /* Is the file a symbolic link? */ |
| 507 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 508 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 509 | int pass /* 0x01 - Display single-line entries only */ |
| 510 | /* 0x02 - Display entries with "diff blocks" only */ |
| 511 | /* 0x03 - Display both */ |
| 512 | ){ |
| 513 | #ifndef GLH_NO_DIVIDER |
| 514 | /* This remembers whether a side-by-side "diff-block" was shown the last |
| 515 | ** time through. If it was, we will add "<hr/>" to better separate the |
| 516 | ** blocks and so single-line entries (when not in two-pass mode) are easier |
| 517 | ** to spot. |
| 518 | */ |
| 519 | static int diffShownLastTime = 0; |
| 520 | #endif |
| 521 | char *zFullName = mprintf("%s%s", g.zLocalRoot, zName); |
| 522 | int isFilePresent = !file_access(zFullName, F_OK); |
| 523 | /* Determing up-front whether we would be showing a "diff-block" so we can |
| 524 | ** filter them according to which pass we are on: the first pass will show |
| 525 | ** only the "single-line" entries; the second will show only those with |
| 526 | ** diff-blocks. In single-pass mode (the original way), 'pass' will be "3", |
| 527 | ** so all entries are shown in their original order. |
| 528 | */ |
| 529 | int showDiff = ( isDeleted && isFilePresent ) |
| 530 | || ( !isDeleted && !isNew && ( ( isChnged == 1 ) |
| 531 | || ( isChnged == 2 ) |
| 532 | || ( isChnged == 4 ) |
| 533 | ) |
| 534 | ); |
| 535 | /* We don't use 'diffFlags' in these tests so that whether "Hide diffs" is |
| 536 | ** in effect or not, the order won't change. |
| 537 | */ |
| 538 | if( showDiff && (pass == 1) ){ return; } /* Don't do diff on pass 1 of 2 */ |
| 539 | if( !showDiff && (pass == 2) ){ return; } /* Don't do line on pass 2 of 2 */ |
| 540 | #ifndef GLH_NO_DIVIDER |
| 541 | /* If a SBS diff-block was shown by the previous entry, add a divider */ |
| 542 | if( diffShownLastTime && (diffFlags & DIFF_SIDEBYSIDE) ){ |
| 543 | @ <hr/> |
| 544 | } |
| 545 | /* Record whether we will be showing a diff-block this time. We DO factor in |
| 546 | ** 'diffFlags' here so that in "Hide diffs" mode, we don't get extra lines. |
| 547 | */ |
| 548 | diffShownLastTime = showDiff && diffFlags; |
| 549 | #endif /*GLH_NO_DIVIDER*/ |
| 550 | //--------------------------------------------------- TODO TESTING HACK TODO |
| 551 | if( strncmp(zName,"aa",2)==0 ){ |
| 552 | isChnged = atoi(zName+2); |
| 553 | } |
| 554 | //--------------------------------------------------- TODO TESTING HACK TODO |
| 555 | @ <p> |
| 556 | if( !g.perm.Hyperlink ){ |
| 557 | if( isDeleted ){ |
| 558 | if( isFilePresent ){ |
| 559 | @ Deleted %h(zName) (still present as a local file). |
| 560 | //TODO:Remove? showDiff = 1; |
| 561 | }else{ |
| 562 | @ Deleted %h(zName). |
| 563 | } |
| 564 | }else if( isNew ){ |
| 565 | if( isFilePresent ){ |
| @@ -551,24 +584,23 @@ | |
| 584 | case 8: append_status( "lost", "executable", zName, zOld); break; |
| 585 | case 9: append_status( "lost", "symlink", zName, zOld); break; |
| 586 | |
| 587 | default: /* Normal edit */ |
| 588 | @ Local changes of %h(zName). |
| 589 | //TODO:Remove? showDiff = 1; |
| 590 | } |
| 591 | if( showDiff && diffFlags ){ |
| 592 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 593 | } |
| 594 | }else{ /* With hyperlinks */ |
| 595 | if( isDeleted ){ |
| 596 | if( isFilePresent ){ /* DELETEd but still on disk */ |
| 597 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 598 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> (still present |
| 599 | @ as %z(href("%R/file/%T?ci=ckout&annot=removed from checkout",zName)) |
| 600 | @ [local file]</a>). |
| 601 | //TODO:Remove? showDiff = 1; |
| 602 | }else{ /* DELETEd and deleted from disk */ |
| 603 | @ Deleted %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 604 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a>. |
| 605 | } |
| 606 | }else if( isNew ){ |
| @@ -600,25 +632,15 @@ | |
| 632 | @ Local changes of |
| 633 | @ %z(href("%R/finfo?name=%T&m=%!S",zName,zOld))%h(zName)</a> |
| 634 | @ from %z(href("%R/artifact/%!S",zOld))[%S(zOld)]</a> to |
| 635 | @ %z(href("%R/file/%T?ci=ckout&annot=edited locally",zName)) |
| 636 | @ [local file]</a> |
| 637 | //TODO:Remove? showDiff = 1; |
| 638 | } |
| 639 | if( showDiff ){ |
| 640 | if( diffFlags ){ |
| 641 | append_diff(zOld, NULL, zName, diffFlags, pRe); |
| 642 | }else if( isChnged ){ |
| 643 | @ |
| 644 | @ %z(href("%R/localdiff?name=%T",zName))[diff]</a> |
| 645 | } |
| 646 | } |
| @@ -1147,10 +1169,13 @@ | |
| 1169 | if( pRe ){ |
| 1170 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 1171 | @ are shown.</b></p> |
| 1172 | } |
| 1173 | if( bLocalMode ){ |
| 1174 | //--------------------------------------------------- TODO TESTING HACK TODO |
| 1175 | int bTwoPass = P("op")==NULL; |
| 1176 | //--------------------------------------------------- TODO TESTING HACK TODO |
| 1177 | /* Following SQL taken from diff_against_disk() in diffcmd.c */ |
| 1178 | db_begin_transaction(); |
| 1179 | db_prepare(&q3, |
| 1180 | "SELECT pathname, deleted, chnged , rid==0, rid, islink" |
| 1181 | " FROM vfile" |
| @@ -1161,31 +1186,44 @@ | |
| 1186 | ); |
| 1187 | /* TODO Have the option of showing "extras" (non-ignored files in the |
| 1188 | ** checkout directory that have not been ADDed). If done, they should |
| 1189 | ** be ahead of any potential "diff-blocks" so they don't get lost |
| 1190 | ** (which is the inspiration for...) |
| 1191 | ** TODO Possibly (at some stage) have an option to commit? |
| 1192 | */ |
| 1193 | /* To prevent single-line diff-entries (those without "diff-blocks") from |
| 1194 | ** getting "lost", there's an optional "two-pass" mode for processing |
| 1195 | ** differences. If enabled, the first pass will only show one-line entries |
| 1196 | ** and the second pass will only show those with diff-blocks. This has the |
| 1197 | ** side-effect of altering the order entries are shown in (but within each |
| 1198 | ** group the original order is maintained). |
| 1199 | ** |
| 1200 | ** If disabled, (pass gets set to 3), only one pass is made on which all |
| 1201 | ** entries are shown in their "normal" order. |
| 1202 | **TODO |
| 1203 | ** Add this to the original (non-local) loop? |
| 1204 | */ |
| 1205 | int pass = bTwoPass?1:3; |
| 1206 | do{ |
| 1207 | while( db_step(&q3)==SQLITE_ROW ){ |
| 1208 | const char *zPathname = db_column_text(&q3,0); |
| 1209 | int isDeleted = db_column_int(&q3, 1); |
| 1210 | int isChnged = db_column_int(&q3,2); |
| 1211 | int isNew = db_column_int(&q3,3); |
| 1212 | int srcid = db_column_int(&q3, 4); |
| 1213 | int isLink = db_column_int(&q3, 5); |
| 1214 | char *zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", srcid); |
| 1215 | append_local_file_change_line(zPathname, zUuid, |
| 1216 | isDeleted, isChnged, isNew, isLink, diffFlags,pRe,pass); |
| 1217 | free(zUuid); |
| 1218 | } |
| 1219 | db_reset(&q3); |
| 1220 | }while( ++pass < 3 ); /* Either "1, 2, stop" or "3, stop". */ |
| 1221 | db_finalize(&q3); /*TODO: Is this needed if we're reseting? */ |
| 1222 | db_end_transaction(1); /* ROLLBACK */ |
| 1223 | }else{ /* Normal, non-local-mode: show diffs against parent */ |
| 1224 | /*TODO: Implement the optional two-pass code? */ |
| 1225 | db_prepare(&q3, |
| 1226 | "SELECT name," |
| 1227 | " mperm," |
| 1228 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 1229 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| 1230 |