Fossil SCM
Enable diff filtering using a regex= query parameter on web pages.
Commit
31dd2c0e3eda218a7370f3ed0adae6fd66d54810
Parent
97a7b924c0e1017…
1 file changed
+45
-13
+45
-13
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -287,13 +287,18 @@ | ||
| 287 | 287 | } |
| 288 | 288 | } |
| 289 | 289 | |
| 290 | 290 | |
| 291 | 291 | /* |
| 292 | -** Append the difference between two RIDs to the output | |
| 292 | +** Append the difference between artifacts to the output | |
| 293 | 293 | */ |
| 294 | -static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){ | |
| 294 | +static void append_diff( | |
| 295 | + const char *zFrom, /* Diff from this artifact */ | |
| 296 | + const char *zTo, /* ... to this artifact */ | |
| 297 | + u64 diffFlags, /* Diff formatting flags */ | |
| 298 | + ReCompiled *pRe /* Only show change matching this regex */ | |
| 299 | +){ | |
| 295 | 300 | int fromid; |
| 296 | 301 | int toid; |
| 297 | 302 | Blob from, to, out; |
| 298 | 303 | if( zFrom ){ |
| 299 | 304 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | ||
| 307 | 312 | }else{ |
| 308 | 313 | blob_zero(&to); |
| 309 | 314 | } |
| 310 | 315 | blob_zero(&out); |
| 311 | 316 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 312 | - text_diff(&from, &to, &out, 0, diffFlags | DIFF_HTML); | |
| 317 | + text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML); | |
| 313 | 318 | @ <div class="sbsdiff"> |
| 314 | 319 | @ %s(blob_str(&out)) |
| 315 | 320 | @ </div> |
| 316 | 321 | }else{ |
| 317 | - text_diff(&from, &to, &out, 0, diffFlags | DIFF_LINENO | DIFF_HTML); | |
| 322 | + text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML); | |
| 318 | 323 | @ <div class="udiff"> |
| 319 | 324 | @ %s(blob_str(&out)) |
| 320 | 325 | @ </div> |
| 321 | 326 | } |
| 322 | 327 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | ||
| 333 | 338 | const char *zName, /* Name of the file that has changed */ |
| 334 | 339 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 335 | 340 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 336 | 341 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 337 | 342 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 343 | + ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ | |
| 338 | 344 | int mperm /* executable or symlink permission for zNew */ |
| 339 | 345 | ){ |
| 340 | 346 | if( !g.perm.Hyperlink ){ |
| 341 | 347 | if( zNew==0 ){ |
| 342 | 348 | @ <p>Deleted %h(zName)</p> |
| @@ -350,11 +356,11 @@ | ||
| 350 | 356 | }else{ |
| 351 | 357 | @ <p>Changes to %h(zName)</p> |
| 352 | 358 | } |
| 353 | 359 | if( diffFlags ){ |
| 354 | 360 | @ <pre style="white-space:pre;"> |
| 355 | - append_diff(zOld, zNew, diffFlags); | |
| 361 | + append_diff(zOld, zNew, diffFlags, pRe); | |
| 356 | 362 | @ </pre> |
| 357 | 363 | } |
| 358 | 364 | }else{ |
| 359 | 365 | if( zOld && zNew ){ |
| 360 | 366 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| @@ -376,11 +382,11 @@ | ||
| 376 | 382 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 377 | 383 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 378 | 384 | } |
| 379 | 385 | if( diffFlags ){ |
| 380 | 386 | @ <pre style="white-space:pre;"> |
| 381 | - append_diff(zOld, zNew, diffFlags); | |
| 387 | + append_diff(zOld, zNew, diffFlags, pRe); | |
| 382 | 388 | @ </pre> |
| 383 | 389 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 384 | 390 | @ |
| 385 | 391 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 386 | 392 | } |
| @@ -444,10 +450,12 @@ | ||
| 444 | 450 | int sideBySide; /* True for side-by-side diffs */ |
| 445 | 451 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 446 | 452 | const char *zName; /* Name of the checkin to be displayed */ |
| 447 | 453 | const char *zUuid; /* UUID of zName */ |
| 448 | 454 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 455 | + const char *zRe; /* regex parameter */ | |
| 456 | + ReCompiled *pRe = 0; /* regex */ | |
| 449 | 457 | |
| 450 | 458 | login_check_credentials(); |
| 451 | 459 | if( !g.perm.Read ){ login_needed(); return; } |
| 452 | 460 | zName = P("name"); |
| 453 | 461 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | ||
| 455 | 463 | style_header("Check-in Information Error"); |
| 456 | 464 | @ No such object: %h(g.argv[2]) |
| 457 | 465 | style_footer(); |
| 458 | 466 | return; |
| 459 | 467 | } |
| 468 | + zRe = P("regex"); | |
| 469 | + if( zRe ) re_compile(&pRe, zRe, 0); | |
| 460 | 470 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 461 | 471 | zParent = db_text(0, |
| 462 | 472 | "SELECT uuid FROM plink, blob" |
| 463 | 473 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 464 | 474 | rid |
| @@ -692,10 +702,14 @@ | ||
| 692 | 702 | @ show side-by-side diffs</a> |
| 693 | 703 | } |
| 694 | 704 | } |
| 695 | 705 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 696 | 706 | @ patch</a></div> |
| 707 | + if( pRe ){ | |
| 708 | + @ <p><b>Only differences that match regular expression "%h(zRe)" | |
| 709 | + @ are shown.</b></p> | |
| 710 | + } | |
| 697 | 711 | db_prepare(&q, |
| 698 | 712 | "SELECT name," |
| 699 | 713 | " mperm," |
| 700 | 714 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 701 | 715 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| @@ -712,11 +726,11 @@ | ||
| 712 | 726 | const char *zName = db_column_text(&q,0); |
| 713 | 727 | int mperm = db_column_int(&q, 1); |
| 714 | 728 | const char *zOld = db_column_text(&q,2); |
| 715 | 729 | const char *zNew = db_column_text(&q,3); |
| 716 | 730 | const char *zOldName = db_column_text(&q, 4); |
| 717 | - append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm); | |
| 731 | + append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); | |
| 718 | 732 | } |
| 719 | 733 | db_finalize(&q); |
| 720 | 734 | } |
| 721 | 735 | style_footer(); |
| 722 | 736 | } |
| @@ -935,15 +949,19 @@ | ||
| 935 | 949 | Manifest *pFrom, *pTo; |
| 936 | 950 | ManifestFile *pFileFrom, *pFileTo; |
| 937 | 951 | const char *zBranch; |
| 938 | 952 | const char *zFrom; |
| 939 | 953 | const char *zTo; |
| 954 | + const char *zRe; | |
| 955 | + ReCompiled *pRe = 0; | |
| 940 | 956 | |
| 941 | 957 | login_check_credentials(); |
| 942 | 958 | if( !g.perm.Read ){ login_needed(); return; } |
| 943 | 959 | login_anonymous_available(); |
| 944 | 960 | |
| 961 | + zRe = P("regex"); | |
| 962 | + if( zRe ) re_compile(&pRe, zRe, 0); | |
| 945 | 963 | zBranch = P("branch"); |
| 946 | 964 | if( zBranch && zBranch[0] ){ |
| 947 | 965 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 948 | 966 | cgi_replace_parameter("to", zBranch); |
| 949 | 967 | } |
| @@ -971,11 +989,16 @@ | ||
| 971 | 989 | style_header("Check-in Differences"); |
| 972 | 990 | @ <h2>Difference From:</h2><blockquote> |
| 973 | 991 | checkin_description(ridFrom); |
| 974 | 992 | @ </blockquote><h2>To:</h2><blockquote> |
| 975 | 993 | checkin_description(ridTo); |
| 976 | - @ </blockquote><hr /><p> | |
| 994 | + @ </blockquote> | |
| 995 | + if( pRe ){ | |
| 996 | + @ <p><b>Only differences that match regular expression "%h(zRe)" | |
| 997 | + @ are shown.</b></p> | |
| 998 | + } | |
| 999 | + @<hr /><p> | |
| 977 | 1000 | |
| 978 | 1001 | manifest_file_rewind(pFrom); |
| 979 | 1002 | pFileFrom = manifest_file_next(pFrom, 0); |
| 980 | 1003 | manifest_file_rewind(pTo); |
| 981 | 1004 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -989,25 +1012,25 @@ | ||
| 989 | 1012 | }else{ |
| 990 | 1013 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 991 | 1014 | } |
| 992 | 1015 | if( cmp<0 ){ |
| 993 | 1016 | append_file_change_line(pFileFrom->zName, |
| 994 | - pFileFrom->zUuid, 0, 0, diffFlags, 0); | |
| 1017 | + pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); | |
| 995 | 1018 | pFileFrom = manifest_file_next(pFrom, 0); |
| 996 | 1019 | }else if( cmp>0 ){ |
| 997 | 1020 | append_file_change_line(pFileTo->zName, |
| 998 | - 0, pFileTo->zUuid, 0, diffFlags, | |
| 1021 | + 0, pFileTo->zUuid, 0, diffFlags, pRe, | |
| 999 | 1022 | manifest_file_mperm(pFileTo)); |
| 1000 | 1023 | pFileTo = manifest_file_next(pTo, 0); |
| 1001 | 1024 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 1002 | 1025 | /* No changes */ |
| 1003 | 1026 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1004 | 1027 | pFileTo = manifest_file_next(pTo, 0); |
| 1005 | 1028 | }else{ |
| 1006 | 1029 | append_file_change_line(pFileFrom->zName, |
| 1007 | 1030 | pFileFrom->zUuid, |
| 1008 | - pFileTo->zUuid, 0, diffFlags, | |
| 1031 | + pFileTo->zUuid, 0, diffFlags, pRe, | |
| 1009 | 1032 | manifest_file_mperm(pFileTo)); |
| 1010 | 1033 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1011 | 1034 | pFileTo = manifest_file_next(pTo, 0); |
| 1012 | 1035 | } |
| 1013 | 1036 | } |
| @@ -1256,11 +1279,11 @@ | ||
| 1256 | 1279 | } |
| 1257 | 1280 | |
| 1258 | 1281 | |
| 1259 | 1282 | /* |
| 1260 | 1283 | ** WEBPAGE: fdiff |
| 1261 | -** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN | |
| 1284 | +** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX | |
| 1262 | 1285 | ** |
| 1263 | 1286 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1264 | 1287 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1265 | 1288 | ** is 0. Generate plaintext if "patch" is present. |
| 1266 | 1289 | */ |
| @@ -1269,12 +1292,15 @@ | ||
| 1269 | 1292 | int isPatch; |
| 1270 | 1293 | int sideBySide; |
| 1271 | 1294 | Blob c1, c2, diff, *pOut; |
| 1272 | 1295 | char *zV1; |
| 1273 | 1296 | char *zV2; |
| 1297 | + const char *zRe; | |
| 1298 | + ReCompiled *pRe = 0; | |
| 1274 | 1299 | u64 diffFlags; |
| 1275 | 1300 | const char *zStyle = "sbsdiff"; |
| 1301 | + const char *zReErr = 0; | |
| 1276 | 1302 | |
| 1277 | 1303 | login_check_credentials(); |
| 1278 | 1304 | if( !g.perm.Read ){ login_needed(); return; } |
| 1279 | 1305 | v1 = name_to_rid_www("v1"); |
| 1280 | 1306 | v2 = name_to_rid_www("v2"); |
| @@ -1296,13 +1322,15 @@ | ||
| 1296 | 1322 | }else{ |
| 1297 | 1323 | diffFlags |= DIFF_LINENO; |
| 1298 | 1324 | zStyle = "udiff"; |
| 1299 | 1325 | } |
| 1300 | 1326 | } |
| 1327 | + zRe = P("regex"); | |
| 1328 | + if( zRe ) zReErr = re_compile(&pRe, zRe, 0); | |
| 1301 | 1329 | content_get(v1, &c1); |
| 1302 | 1330 | content_get(v2, &c2); |
| 1303 | - text_diff(&c1, &c2, pOut, 0, diffFlags); | |
| 1331 | + text_diff(&c1, &c2, pOut, pRe, diffFlags); | |
| 1304 | 1332 | blob_reset(&c1); |
| 1305 | 1333 | blob_reset(&c2); |
| 1306 | 1334 | if( !isPatch ){ |
| 1307 | 1335 | style_header("Diff"); |
| 1308 | 1336 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1326,10 +1354,14 @@ | ||
| 1326 | 1354 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1327 | 1355 | object_description(v1, 0, 0); |
| 1328 | 1356 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1329 | 1357 | object_description(v2, 0, 0); |
| 1330 | 1358 | } |
| 1359 | + if( pRe ){ | |
| 1360 | + @ <b>Only differences that match regular expression "%h(zRe)" | |
| 1361 | + @ are shown.</b> | |
| 1362 | + } | |
| 1331 | 1363 | @ <hr /> |
| 1332 | 1364 | @ <div class="%s(zStyle)"> |
| 1333 | 1365 | @ %s(blob_str(&diff)) |
| 1334 | 1366 | @ </div> |
| 1335 | 1367 | blob_reset(&diff); |
| 1336 | 1368 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -287,13 +287,18 @@ | |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | |
| 291 | /* |
| 292 | ** Append the difference between two RIDs to the output |
| 293 | */ |
| 294 | static void append_diff(const char *zFrom, const char *zTo, u64 diffFlags){ |
| 295 | int fromid; |
| 296 | int toid; |
| 297 | Blob from, to, out; |
| 298 | if( zFrom ){ |
| 299 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | |
| 307 | }else{ |
| 308 | blob_zero(&to); |
| 309 | } |
| 310 | blob_zero(&out); |
| 311 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 312 | text_diff(&from, &to, &out, 0, diffFlags | DIFF_HTML); |
| 313 | @ <div class="sbsdiff"> |
| 314 | @ %s(blob_str(&out)) |
| 315 | @ </div> |
| 316 | }else{ |
| 317 | text_diff(&from, &to, &out, 0, diffFlags | DIFF_LINENO | DIFF_HTML); |
| 318 | @ <div class="udiff"> |
| 319 | @ %s(blob_str(&out)) |
| 320 | @ </div> |
| 321 | } |
| 322 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | |
| 333 | const char *zName, /* Name of the file that has changed */ |
| 334 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 335 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 336 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 337 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 338 | int mperm /* executable or symlink permission for zNew */ |
| 339 | ){ |
| 340 | if( !g.perm.Hyperlink ){ |
| 341 | if( zNew==0 ){ |
| 342 | @ <p>Deleted %h(zName)</p> |
| @@ -350,11 +356,11 @@ | |
| 350 | }else{ |
| 351 | @ <p>Changes to %h(zName)</p> |
| 352 | } |
| 353 | if( diffFlags ){ |
| 354 | @ <pre style="white-space:pre;"> |
| 355 | append_diff(zOld, zNew, diffFlags); |
| 356 | @ </pre> |
| 357 | } |
| 358 | }else{ |
| 359 | if( zOld && zNew ){ |
| 360 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| @@ -376,11 +382,11 @@ | |
| 376 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 377 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 378 | } |
| 379 | if( diffFlags ){ |
| 380 | @ <pre style="white-space:pre;"> |
| 381 | append_diff(zOld, zNew, diffFlags); |
| 382 | @ </pre> |
| 383 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 384 | @ |
| 385 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 386 | } |
| @@ -444,10 +450,12 @@ | |
| 444 | int sideBySide; /* True for side-by-side diffs */ |
| 445 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 446 | const char *zName; /* Name of the checkin to be displayed */ |
| 447 | const char *zUuid; /* UUID of zName */ |
| 448 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 449 | |
| 450 | login_check_credentials(); |
| 451 | if( !g.perm.Read ){ login_needed(); return; } |
| 452 | zName = P("name"); |
| 453 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | |
| 455 | style_header("Check-in Information Error"); |
| 456 | @ No such object: %h(g.argv[2]) |
| 457 | style_footer(); |
| 458 | return; |
| 459 | } |
| 460 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 461 | zParent = db_text(0, |
| 462 | "SELECT uuid FROM plink, blob" |
| 463 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 464 | rid |
| @@ -692,10 +702,14 @@ | |
| 692 | @ show side-by-side diffs</a> |
| 693 | } |
| 694 | } |
| 695 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 696 | @ patch</a></div> |
| 697 | db_prepare(&q, |
| 698 | "SELECT name," |
| 699 | " mperm," |
| 700 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 701 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| @@ -712,11 +726,11 @@ | |
| 712 | const char *zName = db_column_text(&q,0); |
| 713 | int mperm = db_column_int(&q, 1); |
| 714 | const char *zOld = db_column_text(&q,2); |
| 715 | const char *zNew = db_column_text(&q,3); |
| 716 | const char *zOldName = db_column_text(&q, 4); |
| 717 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm); |
| 718 | } |
| 719 | db_finalize(&q); |
| 720 | } |
| 721 | style_footer(); |
| 722 | } |
| @@ -935,15 +949,19 @@ | |
| 935 | Manifest *pFrom, *pTo; |
| 936 | ManifestFile *pFileFrom, *pFileTo; |
| 937 | const char *zBranch; |
| 938 | const char *zFrom; |
| 939 | const char *zTo; |
| 940 | |
| 941 | login_check_credentials(); |
| 942 | if( !g.perm.Read ){ login_needed(); return; } |
| 943 | login_anonymous_available(); |
| 944 | |
| 945 | zBranch = P("branch"); |
| 946 | if( zBranch && zBranch[0] ){ |
| 947 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 948 | cgi_replace_parameter("to", zBranch); |
| 949 | } |
| @@ -971,11 +989,16 @@ | |
| 971 | style_header("Check-in Differences"); |
| 972 | @ <h2>Difference From:</h2><blockquote> |
| 973 | checkin_description(ridFrom); |
| 974 | @ </blockquote><h2>To:</h2><blockquote> |
| 975 | checkin_description(ridTo); |
| 976 | @ </blockquote><hr /><p> |
| 977 | |
| 978 | manifest_file_rewind(pFrom); |
| 979 | pFileFrom = manifest_file_next(pFrom, 0); |
| 980 | manifest_file_rewind(pTo); |
| 981 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -989,25 +1012,25 @@ | |
| 989 | }else{ |
| 990 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 991 | } |
| 992 | if( cmp<0 ){ |
| 993 | append_file_change_line(pFileFrom->zName, |
| 994 | pFileFrom->zUuid, 0, 0, diffFlags, 0); |
| 995 | pFileFrom = manifest_file_next(pFrom, 0); |
| 996 | }else if( cmp>0 ){ |
| 997 | append_file_change_line(pFileTo->zName, |
| 998 | 0, pFileTo->zUuid, 0, diffFlags, |
| 999 | manifest_file_mperm(pFileTo)); |
| 1000 | pFileTo = manifest_file_next(pTo, 0); |
| 1001 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 1002 | /* No changes */ |
| 1003 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1004 | pFileTo = manifest_file_next(pTo, 0); |
| 1005 | }else{ |
| 1006 | append_file_change_line(pFileFrom->zName, |
| 1007 | pFileFrom->zUuid, |
| 1008 | pFileTo->zUuid, 0, diffFlags, |
| 1009 | manifest_file_mperm(pFileTo)); |
| 1010 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1011 | pFileTo = manifest_file_next(pTo, 0); |
| 1012 | } |
| 1013 | } |
| @@ -1256,11 +1279,11 @@ | |
| 1256 | } |
| 1257 | |
| 1258 | |
| 1259 | /* |
| 1260 | ** WEBPAGE: fdiff |
| 1261 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN |
| 1262 | ** |
| 1263 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1264 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1265 | ** is 0. Generate plaintext if "patch" is present. |
| 1266 | */ |
| @@ -1269,12 +1292,15 @@ | |
| 1269 | int isPatch; |
| 1270 | int sideBySide; |
| 1271 | Blob c1, c2, diff, *pOut; |
| 1272 | char *zV1; |
| 1273 | char *zV2; |
| 1274 | u64 diffFlags; |
| 1275 | const char *zStyle = "sbsdiff"; |
| 1276 | |
| 1277 | login_check_credentials(); |
| 1278 | if( !g.perm.Read ){ login_needed(); return; } |
| 1279 | v1 = name_to_rid_www("v1"); |
| 1280 | v2 = name_to_rid_www("v2"); |
| @@ -1296,13 +1322,15 @@ | |
| 1296 | }else{ |
| 1297 | diffFlags |= DIFF_LINENO; |
| 1298 | zStyle = "udiff"; |
| 1299 | } |
| 1300 | } |
| 1301 | content_get(v1, &c1); |
| 1302 | content_get(v2, &c2); |
| 1303 | text_diff(&c1, &c2, pOut, 0, diffFlags); |
| 1304 | blob_reset(&c1); |
| 1305 | blob_reset(&c2); |
| 1306 | if( !isPatch ){ |
| 1307 | style_header("Diff"); |
| 1308 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1326,10 +1354,14 @@ | |
| 1326 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1327 | object_description(v1, 0, 0); |
| 1328 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1329 | object_description(v2, 0, 0); |
| 1330 | } |
| 1331 | @ <hr /> |
| 1332 | @ <div class="%s(zStyle)"> |
| 1333 | @ %s(blob_str(&diff)) |
| 1334 | @ </div> |
| 1335 | blob_reset(&diff); |
| 1336 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -287,13 +287,18 @@ | |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | |
| 291 | /* |
| 292 | ** Append the difference between artifacts to the output |
| 293 | */ |
| 294 | static void append_diff( |
| 295 | const char *zFrom, /* Diff from this artifact */ |
| 296 | const char *zTo, /* ... to this artifact */ |
| 297 | u64 diffFlags, /* Diff formatting flags */ |
| 298 | ReCompiled *pRe /* Only show change matching this regex */ |
| 299 | ){ |
| 300 | int fromid; |
| 301 | int toid; |
| 302 | Blob from, to, out; |
| 303 | if( zFrom ){ |
| 304 | fromid = uuid_to_rid(zFrom, 0); |
| @@ -307,16 +312,16 @@ | |
| 312 | }else{ |
| 313 | blob_zero(&to); |
| 314 | } |
| 315 | blob_zero(&out); |
| 316 | if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 317 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML); |
| 318 | @ <div class="sbsdiff"> |
| 319 | @ %s(blob_str(&out)) |
| 320 | @ </div> |
| 321 | }else{ |
| 322 | text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML); |
| 323 | @ <div class="udiff"> |
| 324 | @ %s(blob_str(&out)) |
| 325 | @ </div> |
| 326 | } |
| 327 | blob_reset(&from); |
| @@ -333,10 +338,11 @@ | |
| 338 | const char *zName, /* Name of the file that has changed */ |
| 339 | const char *zOld, /* blob.uuid before change. NULL for added files */ |
| 340 | const char *zNew, /* blob.uuid after change. NULL for deletes */ |
| 341 | const char *zOldName, /* Prior name. NULL if no name change. */ |
| 342 | u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */ |
| 343 | ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */ |
| 344 | int mperm /* executable or symlink permission for zNew */ |
| 345 | ){ |
| 346 | if( !g.perm.Hyperlink ){ |
| 347 | if( zNew==0 ){ |
| 348 | @ <p>Deleted %h(zName)</p> |
| @@ -350,11 +356,11 @@ | |
| 356 | }else{ |
| 357 | @ <p>Changes to %h(zName)</p> |
| 358 | } |
| 359 | if( diffFlags ){ |
| 360 | @ <pre style="white-space:pre;"> |
| 361 | append_diff(zOld, zNew, diffFlags, pRe); |
| 362 | @ </pre> |
| 363 | } |
| 364 | }else{ |
| 365 | if( zOld && zNew ){ |
| 366 | if( fossil_strcmp(zOld, zNew)!=0 ){ |
| @@ -376,11 +382,11 @@ | |
| 382 | @ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a> |
| 383 | @ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a> |
| 384 | } |
| 385 | if( diffFlags ){ |
| 386 | @ <pre style="white-space:pre;"> |
| 387 | append_diff(zOld, zNew, diffFlags, pRe); |
| 388 | @ </pre> |
| 389 | }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ |
| 390 | @ |
| 391 | @ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a> |
| 392 | } |
| @@ -444,10 +450,12 @@ | |
| 450 | int sideBySide; /* True for side-by-side diffs */ |
| 451 | u64 diffFlags; /* Flag parameter for text_diff() */ |
| 452 | const char *zName; /* Name of the checkin to be displayed */ |
| 453 | const char *zUuid; /* UUID of zName */ |
| 454 | const char *zParent; /* UUID of the parent checkin (if any) */ |
| 455 | const char *zRe; /* regex parameter */ |
| 456 | ReCompiled *pRe = 0; /* regex */ |
| 457 | |
| 458 | login_check_credentials(); |
| 459 | if( !g.perm.Read ){ login_needed(); return; } |
| 460 | zName = P("name"); |
| 461 | rid = name_to_rid_www("name"); |
| @@ -455,10 +463,12 @@ | |
| 463 | style_header("Check-in Information Error"); |
| 464 | @ No such object: %h(g.argv[2]) |
| 465 | style_footer(); |
| 466 | return; |
| 467 | } |
| 468 | zRe = P("regex"); |
| 469 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 470 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 471 | zParent = db_text(0, |
| 472 | "SELECT uuid FROM plink, blob" |
| 473 | " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim", |
| 474 | rid |
| @@ -692,10 +702,14 @@ | |
| 702 | @ show side-by-side diffs</a> |
| 703 | } |
| 704 | } |
| 705 | @ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid)) |
| 706 | @ patch</a></div> |
| 707 | if( pRe ){ |
| 708 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 709 | @ are shown.</b></p> |
| 710 | } |
| 711 | db_prepare(&q, |
| 712 | "SELECT name," |
| 713 | " mperm," |
| 714 | " (SELECT uuid FROM blob WHERE rid=mlink.pid)," |
| 715 | " (SELECT uuid FROM blob WHERE rid=mlink.fid)," |
| @@ -712,11 +726,11 @@ | |
| 726 | const char *zName = db_column_text(&q,0); |
| 727 | int mperm = db_column_int(&q, 1); |
| 728 | const char *zOld = db_column_text(&q,2); |
| 729 | const char *zNew = db_column_text(&q,3); |
| 730 | const char *zOldName = db_column_text(&q, 4); |
| 731 | append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm); |
| 732 | } |
| 733 | db_finalize(&q); |
| 734 | } |
| 735 | style_footer(); |
| 736 | } |
| @@ -935,15 +949,19 @@ | |
| 949 | Manifest *pFrom, *pTo; |
| 950 | ManifestFile *pFileFrom, *pFileTo; |
| 951 | const char *zBranch; |
| 952 | const char *zFrom; |
| 953 | const char *zTo; |
| 954 | const char *zRe; |
| 955 | ReCompiled *pRe = 0; |
| 956 | |
| 957 | login_check_credentials(); |
| 958 | if( !g.perm.Read ){ login_needed(); return; } |
| 959 | login_anonymous_available(); |
| 960 | |
| 961 | zRe = P("regex"); |
| 962 | if( zRe ) re_compile(&pRe, zRe, 0); |
| 963 | zBranch = P("branch"); |
| 964 | if( zBranch && zBranch[0] ){ |
| 965 | cgi_replace_parameter("from", mprintf("root:%s", zBranch)); |
| 966 | cgi_replace_parameter("to", zBranch); |
| 967 | } |
| @@ -971,11 +989,16 @@ | |
| 989 | style_header("Check-in Differences"); |
| 990 | @ <h2>Difference From:</h2><blockquote> |
| 991 | checkin_description(ridFrom); |
| 992 | @ </blockquote><h2>To:</h2><blockquote> |
| 993 | checkin_description(ridTo); |
| 994 | @ </blockquote> |
| 995 | if( pRe ){ |
| 996 | @ <p><b>Only differences that match regular expression "%h(zRe)" |
| 997 | @ are shown.</b></p> |
| 998 | } |
| 999 | @<hr /><p> |
| 1000 | |
| 1001 | manifest_file_rewind(pFrom); |
| 1002 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1003 | manifest_file_rewind(pTo); |
| 1004 | pFileTo = manifest_file_next(pTo, 0); |
| @@ -989,25 +1012,25 @@ | |
| 1012 | }else{ |
| 1013 | cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); |
| 1014 | } |
| 1015 | if( cmp<0 ){ |
| 1016 | append_file_change_line(pFileFrom->zName, |
| 1017 | pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0); |
| 1018 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1019 | }else if( cmp>0 ){ |
| 1020 | append_file_change_line(pFileTo->zName, |
| 1021 | 0, pFileTo->zUuid, 0, diffFlags, pRe, |
| 1022 | manifest_file_mperm(pFileTo)); |
| 1023 | pFileTo = manifest_file_next(pTo, 0); |
| 1024 | }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ |
| 1025 | /* No changes */ |
| 1026 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1027 | pFileTo = manifest_file_next(pTo, 0); |
| 1028 | }else{ |
| 1029 | append_file_change_line(pFileFrom->zName, |
| 1030 | pFileFrom->zUuid, |
| 1031 | pFileTo->zUuid, 0, diffFlags, pRe, |
| 1032 | manifest_file_mperm(pFileTo)); |
| 1033 | pFileFrom = manifest_file_next(pFrom, 0); |
| 1034 | pFileTo = manifest_file_next(pTo, 0); |
| 1035 | } |
| 1036 | } |
| @@ -1256,11 +1279,11 @@ | |
| 1279 | } |
| 1280 | |
| 1281 | |
| 1282 | /* |
| 1283 | ** WEBPAGE: fdiff |
| 1284 | ** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX |
| 1285 | ** |
| 1286 | ** Two arguments, v1 and v2, identify the files to be diffed. Show the |
| 1287 | ** difference between the two artifacts. Show diff side by side unless sbs |
| 1288 | ** is 0. Generate plaintext if "patch" is present. |
| 1289 | */ |
| @@ -1269,12 +1292,15 @@ | |
| 1292 | int isPatch; |
| 1293 | int sideBySide; |
| 1294 | Blob c1, c2, diff, *pOut; |
| 1295 | char *zV1; |
| 1296 | char *zV2; |
| 1297 | const char *zRe; |
| 1298 | ReCompiled *pRe = 0; |
| 1299 | u64 diffFlags; |
| 1300 | const char *zStyle = "sbsdiff"; |
| 1301 | const char *zReErr = 0; |
| 1302 | |
| 1303 | login_check_credentials(); |
| 1304 | if( !g.perm.Read ){ login_needed(); return; } |
| 1305 | v1 = name_to_rid_www("v1"); |
| 1306 | v2 = name_to_rid_www("v2"); |
| @@ -1296,13 +1322,15 @@ | |
| 1322 | }else{ |
| 1323 | diffFlags |= DIFF_LINENO; |
| 1324 | zStyle = "udiff"; |
| 1325 | } |
| 1326 | } |
| 1327 | zRe = P("regex"); |
| 1328 | if( zRe ) zReErr = re_compile(&pRe, zRe, 0); |
| 1329 | content_get(v1, &c1); |
| 1330 | content_get(v2, &c2); |
| 1331 | text_diff(&c1, &c2, pOut, pRe, diffFlags); |
| 1332 | blob_reset(&c1); |
| 1333 | blob_reset(&c2); |
| 1334 | if( !isPatch ){ |
| 1335 | style_header("Diff"); |
| 1336 | style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", |
| @@ -1326,10 +1354,14 @@ | |
| 1354 | @ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2> |
| 1355 | object_description(v1, 0, 0); |
| 1356 | @ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2> |
| 1357 | object_description(v2, 0, 0); |
| 1358 | } |
| 1359 | if( pRe ){ |
| 1360 | @ <b>Only differences that match regular expression "%h(zRe)" |
| 1361 | @ are shown.</b> |
| 1362 | } |
| 1363 | @ <hr /> |
| 1364 | @ <div class="%s(zStyle)"> |
| 1365 | @ %s(blob_str(&diff)) |
| 1366 | @ </div> |
| 1367 | blob_reset(&diff); |
| 1368 |