Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Enable diff filtering using a regex= query parameter on web pages. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
31dd2c0e3eda218a7370f3ed0adae6fd |
| User & Date: | drh 2013-01-02 01:36:48.408 |
Context
|
2013-01-02
| ||
| 10:47 | Fixed JSON-side warnings reported by Baptiste Daroussin. ... (check-in: 8fec4c959c user: stephan tags: trunk) | |
| 01:36 | Enable diff filtering using a regex= query parameter on web pages. ... (check-in: 31dd2c0e3e user: drh tags: trunk) | |
| 00:58 | Enhance the diff logic so that it can suppress differences that do not match a regular expression. This capability is so far only exposed on the test-diff command. ... (check-in: 97a7b924c0 user: drh tags: trunk) | |
Changes
Changes to src/info.c.
| ︙ | ︙ | |||
285 286 287 288 289 290 291 |
if( cnt ){
@ </ul>
}
}
/*
| | | > > > > > | | > | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
if( cnt ){
@ </ul>
}
}
/*
** Append the difference between artifacts to the output
*/
static void append_diff(
const char *zFrom, /* Diff from this artifact */
const char *zTo, /* ... to this artifact */
u64 diffFlags, /* Diff formatting flags */
ReCompiled *pRe /* Only show change matching this regex */
){
int fromid;
int toid;
Blob from, to, out;
if( zFrom ){
fromid = uuid_to_rid(zFrom, 0);
content_get(fromid, &from);
}else{
blob_zero(&from);
}
if( zTo ){
toid = uuid_to_rid(zTo, 0);
content_get(toid, &to);
}else{
blob_zero(&to);
}
blob_zero(&out);
if( diffFlags & DIFF_SIDEBYSIDE ){
text_diff(&from, &to, &out, pRe, diffFlags | DIFF_HTML);
@ <div class="sbsdiff">
@ %s(blob_str(&out))
@ </div>
}else{
text_diff(&from, &to, &out, pRe, diffFlags | DIFF_LINENO | DIFF_HTML);
@ <div class="udiff">
@ %s(blob_str(&out))
@ </div>
}
blob_reset(&from);
blob_reset(&to);
blob_reset(&out);
}
/*
** Write a line of web-page output that shows changes that have occurred
** to a file between two check-ins.
*/
static void append_file_change_line(
const char *zName, /* Name of the file that has changed */
const char *zOld, /* blob.uuid before change. NULL for added files */
const char *zNew, /* blob.uuid after change. NULL for deletes */
const char *zOldName, /* Prior name. NULL if no name change. */
u64 diffFlags, /* Flags for text_diff(). Zero to omit diffs */
ReCompiled *pRe, /* Only show diffs that match this regex, if not NULL */
int mperm /* executable or symlink permission for zNew */
){
if( !g.perm.Hyperlink ){
if( zNew==0 ){
@ <p>Deleted %h(zName)</p>
}else if( zOld==0 ){
@ <p>Added %h(zName)</p>
}else if( zOldName!=0 && fossil_strcmp(zName,zOldName)!=0 ){
@ <p>Name change from %h(zOldName) to %h(zName)
}else if( fossil_strcmp(zNew, zOld)==0 ){
@ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared")
@ for %h(zName)</p>
}else{
@ <p>Changes to %h(zName)</p>
}
if( diffFlags ){
@ <pre style="white-space:pre;">
append_diff(zOld, zNew, diffFlags, pRe);
@ </pre>
}
}else{
if( zOld && zNew ){
if( fossil_strcmp(zOld, zNew)!=0 ){
@ <p>Modified %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ from %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
|
| ︙ | ︙ | |||
374 375 376 377 378 379 380 |
@ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
}else{
@ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
}
if( diffFlags ){
@ <pre style="white-space:pre;">
| | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 |
@ version %z(href("%R/artifact/%s",zOld))[%S(zOld)]</a>
}else{
@ <p>Added %z(href("%R/finfo?name=%T",zName))%h(zName)</a>
@ version %z(href("%R/artifact/%s",zNew))[%S(zNew)]</a>
}
if( diffFlags ){
@ <pre style="white-space:pre;">
append_diff(zOld, zNew, diffFlags, pRe);
@ </pre>
}else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){
@
@ %z(href("%R/fdiff?v1=%S&v2=%S",zOld,zNew))[diff]</a>
}
@ </p>
}
|
| ︙ | ︙ | |||
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
int isLeaf;
int showDiff; /* True to show diffs */
int sideBySide; /* True for side-by-side diffs */
u64 diffFlags; /* Flag parameter for text_diff() */
const char *zName; /* Name of the checkin to be displayed */
const char *zUuid; /* UUID of zName */
const char *zParent; /* UUID of the parent checkin (if any) */
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(g.argv[2])
style_footer();
return;
}
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
zParent = db_text(0,
"SELECT uuid FROM plink, blob"
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
rid
);
isLeaf = is_a_leaf(rid);
| > > > > | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 |
int isLeaf;
int showDiff; /* True to show diffs */
int sideBySide; /* True for side-by-side diffs */
u64 diffFlags; /* Flag parameter for text_diff() */
const char *zName; /* Name of the checkin to be displayed */
const char *zUuid; /* UUID of zName */
const char *zParent; /* UUID of the parent checkin (if any) */
const char *zRe; /* regex parameter */
ReCompiled *pRe = 0; /* regex */
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
zName = P("name");
rid = name_to_rid_www("name");
if( rid==0 ){
style_header("Check-in Information Error");
@ No such object: %h(g.argv[2])
style_footer();
return;
}
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid);
zParent = db_text(0,
"SELECT uuid FROM plink, blob"
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
rid
);
isLeaf = is_a_leaf(rid);
|
| ︙ | ︙ | |||
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 |
@ show unified diffs</a>
@ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
@ show side-by-side diffs</a>
}
}
@ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
@ patch</a></div>
db_prepare(&q,
"SELECT name,"
" mperm,"
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
" (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
" FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
" WHERE mlink.mid=%d"
" AND (mlink.fid>0"
" OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
" ORDER BY name /*sort*/",
rid, rid
);
diffFlags = construct_diff_flags(showDiff, sideBySide);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q,0);
int mperm = db_column_int(&q, 1);
const char *zOld = db_column_text(&q,2);
const char *zNew = db_column_text(&q,3);
const char *zOldName = db_column_text(&q, 4);
| > > > > | | 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 |
@ show unified diffs</a>
@ %z(xhref("class='button'","%R/vinfo/%T?sbs=1",zName))
@ show side-by-side diffs</a>
}
}
@ %z(xhref("class='button'","%R/vpatch?from=%S&to=%S",zParent,zUuid))
@ patch</a></div>
if( pRe ){
@ <p><b>Only differences that match regular expression "%h(zRe)"
@ are shown.</b></p>
}
db_prepare(&q,
"SELECT name,"
" mperm,"
" (SELECT uuid FROM blob WHERE rid=mlink.pid),"
" (SELECT uuid FROM blob WHERE rid=mlink.fid),"
" (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)"
" FROM mlink JOIN filename ON filename.fnid=mlink.fnid"
" WHERE mlink.mid=%d"
" AND (mlink.fid>0"
" OR mlink.fnid NOT IN (SELECT pfnid FROM mlink WHERE mid=%d))"
" ORDER BY name /*sort*/",
rid, rid
);
diffFlags = construct_diff_flags(showDiff, sideBySide);
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q,0);
int mperm = db_column_int(&q, 1);
const char *zOld = db_column_text(&q,2);
const char *zNew = db_column_text(&q,3);
const char *zOldName = db_column_text(&q, 4);
append_file_change_line(zName, zOld, zNew, zOldName, diffFlags,pRe,mperm);
}
db_finalize(&q);
}
style_footer();
}
/*
|
| ︙ | ︙ | |||
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 |
int sideBySide = 0;
u64 diffFlags = 0;
Manifest *pFrom, *pTo;
ManifestFile *pFileFrom, *pFileTo;
const char *zBranch;
const char *zFrom;
const char *zTo;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
login_anonymous_available();
zBranch = P("branch");
if( zBranch && zBranch[0] ){
cgi_replace_parameter("from", mprintf("root:%s", zBranch));
cgi_replace_parameter("to", zBranch);
}
pTo = vdiff_parse_manifest("to", &ridTo);
if( pTo==0 ) return;
| > > > > | 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 |
int sideBySide = 0;
u64 diffFlags = 0;
Manifest *pFrom, *pTo;
ManifestFile *pFileFrom, *pFileTo;
const char *zBranch;
const char *zFrom;
const char *zTo;
const char *zRe;
ReCompiled *pRe = 0;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
login_anonymous_available();
zRe = P("regex");
if( zRe ) re_compile(&pRe, zRe, 0);
zBranch = P("branch");
if( zBranch && zBranch[0] ){
cgi_replace_parameter("from", mprintf("root:%s", zBranch));
cgi_replace_parameter("to", zBranch);
}
pTo = vdiff_parse_manifest("to", &ridTo);
if( pTo==0 ) return;
|
| ︙ | ︙ | |||
969 970 971 972 973 974 975 |
"%R/vdiff?from=%T&to=%T&detail=%d&sbs=%d",
zTo, zFrom, showDetail, sideBySide);
style_header("Check-in Differences");
@ <h2>Difference From:</h2><blockquote>
checkin_description(ridFrom);
@ </blockquote><h2>To:</h2><blockquote>
checkin_description(ridTo);
| | > > > > > | | | | 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 |
"%R/vdiff?from=%T&to=%T&detail=%d&sbs=%d",
zTo, zFrom, showDetail, sideBySide);
style_header("Check-in Differences");
@ <h2>Difference From:</h2><blockquote>
checkin_description(ridFrom);
@ </blockquote><h2>To:</h2><blockquote>
checkin_description(ridTo);
@ </blockquote>
if( pRe ){
@ <p><b>Only differences that match regular expression "%h(zRe)"
@ are shown.</b></p>
}
@<hr /><p>
manifest_file_rewind(pFrom);
pFileFrom = manifest_file_next(pFrom, 0);
manifest_file_rewind(pTo);
pFileTo = manifest_file_next(pTo, 0);
diffFlags = construct_diff_flags(showDetail, sideBySide);
while( pFileFrom || pFileTo ){
int cmp;
if( pFileFrom==0 ){
cmp = +1;
}else if( pFileTo==0 ){
cmp = -1;
}else{
cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName);
}
if( cmp<0 ){
append_file_change_line(pFileFrom->zName,
pFileFrom->zUuid, 0, 0, diffFlags, pRe, 0);
pFileFrom = manifest_file_next(pFrom, 0);
}else if( cmp>0 ){
append_file_change_line(pFileTo->zName,
0, pFileTo->zUuid, 0, diffFlags, pRe,
manifest_file_mperm(pFileTo));
pFileTo = manifest_file_next(pTo, 0);
}else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){
/* No changes */
pFileFrom = manifest_file_next(pFrom, 0);
pFileTo = manifest_file_next(pTo, 0);
}else{
append_file_change_line(pFileFrom->zName,
pFileFrom->zUuid,
pFileTo->zUuid, 0, diffFlags, pRe,
manifest_file_mperm(pFileTo));
pFileFrom = manifest_file_next(pFrom, 0);
pFileTo = manifest_file_next(pTo, 0);
}
}
manifest_destroy(pFrom);
manifest_destroy(pTo);
|
| ︙ | ︙ | |||
1254 1255 1256 1257 1258 1259 1260 | } return objType; } /* ** WEBPAGE: fdiff | | > > > | 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 |
}
return objType;
}
/*
** WEBPAGE: fdiff
** URL: fdiff?v1=UUID&v2=UUID&patch&sbs=BOOLEAN®ex=REGEX
**
** Two arguments, v1 and v2, identify the files to be diffed. Show the
** difference between the two artifacts. Show diff side by side unless sbs
** is 0. Generate plaintext if "patch" is present.
*/
void diff_page(void){
int v1, v2;
int isPatch;
int sideBySide;
Blob c1, c2, diff, *pOut;
char *zV1;
char *zV2;
const char *zRe;
ReCompiled *pRe = 0;
u64 diffFlags;
const char *zStyle = "sbsdiff";
const char *zReErr = 0;
login_check_credentials();
if( !g.perm.Read ){ login_needed(); return; }
v1 = name_to_rid_www("v1");
v2 = name_to_rid_www("v2");
if( v1==0 || v2==0 ) fossil_redirect_home();
sideBySide = atoi(PD("sbs","1"));
|
| ︙ | ︙ | |||
1294 1295 1296 1297 1298 1299 1300 1301 1302 |
if( sideBySide ){
zStyle = "sbsdiff";
}else{
diffFlags |= DIFF_LINENO;
zStyle = "udiff";
}
}
content_get(v1, &c1);
content_get(v2, &c2);
| > > | | 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 |
if( sideBySide ){
zStyle = "sbsdiff";
}else{
diffFlags |= DIFF_LINENO;
zStyle = "udiff";
}
}
zRe = P("regex");
if( zRe ) zReErr = re_compile(&pRe, zRe, 0);
content_get(v1, &c1);
content_get(v2, &c2);
text_diff(&c1, &c2, pOut, pRe, diffFlags);
blob_reset(&c1);
blob_reset(&c2);
if( !isPatch ){
style_header("Diff");
style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch",
g.zTop, P("v1"), P("v2"));
if( !sideBySide ){
|
| ︙ | ︙ | |||
1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 |
}else{
@ <h2>Differences From
@ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
object_description(v1, 0, 0);
@ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
object_description(v2, 0, 0);
}
@ <hr />
@ <div class="%s(zStyle)">
@ %s(blob_str(&diff))
@ </div>
blob_reset(&diff);
style_footer();
}
| > > > > | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 |
}else{
@ <h2>Differences From
@ Artifact %z(href("%R/artifact/%S",zV1))[%S(zV1)]</a>:</h2>
object_description(v1, 0, 0);
@ <h2>To Artifact %z(href("%R/artifact/%S",zV2))[%S(zV2)]</a>:</h2>
object_description(v2, 0, 0);
}
if( pRe ){
@ <b>Only differences that match regular expression "%h(zRe)"
@ are shown.</b>
}
@ <hr />
@ <div class="%s(zStyle)">
@ %s(blob_str(&diff))
@ </div>
blob_reset(&diff);
style_footer();
}
|
| ︙ | ︙ |