Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch retro-sbsdiff Excluding Merge-Ins
This is equivalent to a diff from dc96d73dd0 to eae55eeafc
2012-02-04
| ||
21:09 | Merge the retro-sbsdiff changes into trunk. check-in: 72c0183ac8 user: drh tags: trunk | |
20:36 | Make the default font size is smaller for side-by-side diff. Fix the context-diff so that it understands the dc=N query parameter. Closed-Leaf check-in: eae55eeafc user: drh tags: retro-sbsdiff | |
20:16 | Suppress the top divider on a context-diff with line numbers. check-in: 43cbe9dd5a user: drh tags: retro-sbsdiff | |
15:02 | Merge recent trunk changes into the retro-sbsdiff branch. check-in: 066adeedfe user: drh tags: retro-sbsdiff | |
14:58 | Make sure diff output is flushed to screen in a timely manner. check-in: dc96d73dd0 user: drh tags: trunk | |
14:48 | User-contributed patch to the debian/makedeb.sh script for generating a debian package for Fossil. check-in: 7b1fd597b4 user: drh tags: trunk | |
Changes to src/diff.c.
23 23 #include <assert.h> 24 24 25 25 26 26 #if INTERFACE 27 27 /* 28 28 ** Allowed flag parameters to the text_diff() and html_sbsdiff() funtions: 29 29 */ 30 -#define DIFF_CONTEXT_MASK 0x0000fff /* Lines of context. Default if 0 */ 31 -#define DIFF_WIDTH_MASK 0x00ff000 /* side-by-side column width */ 32 -#define DIFF_IGNORE_EOLWS 0x0100000 /* Ignore end-of-line whitespace */ 33 -#define DIFF_SIDEBYSIDE 0x0200000 /* Generate a side-by-side diff */ 34 -#define DIFF_NEWFILE 0x0400000 /* Missing files are as empty files */ 30 +#define DIFF_CONTEXT_MASK 0x0000ffff /* Lines of context. Default if 0 */ 31 +#define DIFF_WIDTH_MASK 0x00ff0000 /* side-by-side column width */ 32 +#define DIFF_IGNORE_EOLWS 0x01000000 /* Ignore end-of-line whitespace */ 33 +#define DIFF_SIDEBYSIDE 0x02000000 /* Generate a side-by-side diff */ 34 +#define DIFF_NEWFILE 0x04000000 /* Missing files are as empty files */ 35 +#define DIFF_INLINE 0x08000000 /* Inline (not side-by-side) diff */ 36 +#define DIFF_HTML 0x10000000 /* Render for HTML */ 37 +#define DIFF_LINENO 0x20000000 /* Show line numbers in context diff */ 35 38 36 39 #endif /* INTERFACE */ 37 40 38 41 /* 39 42 ** Maximum length of a line in a text file. (8192) 40 43 */ 41 44 #define LENGTH_MASK_SZ 13 ................................................................................ 144 147 static int same_dline(DLine *pA, DLine *pB){ 145 148 return pA->h==pB->h && memcmp(pA->z,pB->z,pA->h & LENGTH_MASK)==0; 146 149 } 147 150 148 151 /* 149 152 ** Append a single line of "diff" output to pOut. 150 153 */ 151 -static void appendDiffLine(Blob *pOut, char *zPrefix, DLine *pLine){ 152 - blob_append(pOut, zPrefix, 1); 153 - blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); 154 +static void appendDiffLine(Blob *pOut, char cPrefix, DLine *pLine, int html){ 155 + blob_append(pOut, &cPrefix, 1); 156 + if( html ){ 157 + char *zHtml; 158 + if( cPrefix=='+' ){ 159 + blob_append(pOut, "<span class=\"diffadd\">", -1); 160 + }else if( cPrefix=='-' ){ 161 + blob_append(pOut, "<span class=\"diffrm\">", -1); 162 + } 163 + zHtml = htmlize(pLine->z, (pLine->h & LENGTH_MASK)); 164 + blob_append(pOut, zHtml, -1); 165 + fossil_free(zHtml); 166 + if( cPrefix!=' ' ){ 167 + blob_append(pOut, "</span>", -1); 168 + } 169 + }else{ 170 + blob_append(pOut, pLine->z, pLine->h & LENGTH_MASK); 171 + } 154 172 blob_append(pOut, "\n", 1); 155 173 } 174 + 175 +/* 176 +** Append line numbers to the context diff output. Zero or negative numbers 177 +** are blanks. 178 +*/ 179 +static void appendDiffLineno(Blob *pOut, int lnA, int lnB, int html){ 180 + if( html ) blob_append(pOut, "<span class=\"diffln\">", -1); 181 + if( lnA>0 ){ 182 + blob_appendf(pOut, "%6d ", lnA); 183 + }else{ 184 + blob_append(pOut, " ", 7); 185 + } 186 + if( lnB>0 ){ 187 + blob_appendf(pOut, "%6d ", lnB); 188 + }else{ 189 + blob_append(pOut, " ", 8); 190 + } 191 + if( html ) blob_append(pOut, "</span>", -1); 192 +} 156 193 157 194 /* 158 195 ** Expand the size of aEdit[] array to hold nEdit elements. 159 196 */ 160 197 static void expandEdit(DContext *p, int nEdit){ 161 198 p->aEdit = fossil_realloc(p->aEdit, nEdit*sizeof(int)); 162 199 p->nEditAlloc = nEdit; ................................................................................ 196 233 } 197 234 198 235 199 236 /* 200 237 ** Given a diff context in which the aEdit[] array has been filled 201 238 ** in, compute a context diff into pOut. 202 239 */ 203 -static void contextDiff(DContext *p, Blob *pOut, int nContext){ 240 +static void contextDiff( 241 + DContext *p, /* The difference */ 242 + Blob *pOut, /* Output a context diff to here */ 243 + int nContext, /* Number of lines of context */ 244 + int showLn, /* Show line numbers */ 245 + int html /* Render as HTML */ 246 +){ 204 247 DLine *A; /* Left side of the diff */ 205 248 DLine *B; /* Right side of the diff */ 206 249 int a = 0; /* Index of next line in A[] */ 207 250 int b = 0; /* Index of next line in B[] */ 208 251 int *R; /* Array of COPY/DELETE/INSERT triples */ 209 252 int r; /* Index into R[] */ 210 253 int nr; /* Number of COPY/DELETE/INSERT triples to process */ ................................................................................ 250 293 nb += R[r+i*3]; 251 294 } 252 295 /* 253 296 * If the patch changes an empty file or results in an empty file, 254 297 * the block header must use 0,0 as position indicator and not 1,0. 255 298 * Otherwise, patch would be confused and may reject the diff. 256 299 */ 257 - blob_appendf(pOut,"@@ -%d,%d +%d,%d @@\n", 258 - na ? a+skip+1 : 0, na, 259 - nb ? b+skip+1 : 0, nb); 300 + if( showLn ){ 301 + if( r==0 ){ 302 + /* Do not show a top divider */ 303 + }else if( html ){ 304 + blob_appendf(pOut, "<span class=\"diffhr\">%.80c</span>\n", '.'); 305 + }else{ 306 + blob_appendf(pOut, "%.80c\n", '.'); 307 + } 308 + }else{ 309 + if( html ) blob_appendf(pOut, "<span class=\"diffln\">"); 310 + blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", 311 + na ? a+skip+1 : 0, na, 312 + nb ? b+skip+1 : 0, nb); 313 + if( html ) blob_appendf(pOut, "</span>"); 314 + blob_append(pOut, "\n", 1); 315 + } 260 316 261 317 /* Show the initial common area */ 262 318 a += skip; 263 319 b += skip; 264 320 m = R[r] - skip; 265 321 for(j=0; j<m; j++){ 266 - appendDiffLine(pOut, " ", &A[a+j]); 322 + if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); 323 + appendDiffLine(pOut, ' ', &A[a+j], html); 267 324 } 268 325 a += m; 269 326 b += m; 270 327 271 328 /* Show the differences */ 272 329 for(i=0; i<nr; i++){ 273 330 m = R[r+i*3+1]; 274 331 for(j=0; j<m; j++){ 275 - appendDiffLine(pOut, "-", &A[a+j]); 332 + if( showLn ) appendDiffLineno(pOut, a+j+1, 0, html); 333 + appendDiffLine(pOut, '-', &A[a+j], html); 276 334 } 277 335 a += m; 278 336 m = R[r+i*3+2]; 279 337 for(j=0; j<m; j++){ 280 - appendDiffLine(pOut, "+", &B[b+j]); 338 + if( showLn ) appendDiffLineno(pOut, 0, b+j+1, html); 339 + appendDiffLine(pOut, '+', &B[b+j], html); 281 340 } 282 341 b += m; 283 342 if( i<nr-1 ){ 284 343 m = R[r+i*3+3]; 285 344 for(j=0; j<m; j++){ 286 - appendDiffLine(pOut, " ", &B[b+j]); 345 + if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); 346 + appendDiffLine(pOut, ' ', &B[b+j], html); 287 347 } 288 348 b += m; 289 349 a += m; 290 350 } 291 351 } 292 352 293 353 /* Show the final common area */ 294 354 assert( nr==i ); 295 355 m = R[r+nr*3]; 296 356 if( m>nContext ) m = nContext; 297 357 for(j=0; j<m; j++){ 298 - appendDiffLine(pOut, " ", &B[b+j]); 358 + if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1, html); 359 + appendDiffLine(pOut, ' ', &B[b+j], html); 299 360 } 300 361 } 301 362 } 302 363 303 364 /* 304 -** Write a 6-digit line number into the buffer z[]. z[] is guaranteed to 305 -** have space for at least 7 characters. 365 +** Status of a single output line 306 366 */ 307 -static void sbsWriteLineno(char *z, int ln){ 308 - sqlite3_snprintf(7, z, "%6d", ln+1); 309 - z[6] = ' '; 310 -} 367 +typedef struct SbsLine SbsLine; 368 +struct SbsLine { 369 + char *zLine; /* The output line under construction */ 370 + int n; /* Index of next unused slot in the zLine[] */ 371 + int width; /* Maximum width of a column in the output */ 372 + unsigned char escHtml; /* True to escape html characters */ 373 +}; 374 + 375 +/* 376 +** Flags for sbsWriteText() 377 +*/ 378 +#define SBS_NEWLINE 0x0001 /* End with \n\000 */ 379 +#define SBS_PAD 0x0002 /* Pad output to width spaces */ 380 +#define SBS_ENDSPAN 0x0004 /* Write a </span> after text */ 311 381 312 382 /* 313 383 ** Write up to width characters of pLine into z[]. Translate tabs into 314 -** spaces. If trunc is true, then append \n\000 after the last character 315 -** written. 384 +** spaces. Add a newline if SBS_NEWLINE is set. Translate HTML characters 385 +** if SBS_HTML is set. Pad the rendering out width bytes if SBS_PAD is set. 316 386 */ 317 -static int sbsWriteText(char *z, DLine *pLine, int width, int trunc){ 387 +static void sbsWriteText(SbsLine *p, DLine *pLine, unsigned flags){ 318 388 int n = pLine->h & LENGTH_MASK; 319 389 int i, j; 320 390 const char *zIn = pLine->z; 321 - for(i=j=0; i<n && j<width; i++){ 391 + char *z = &p->zLine[p->n]; 392 + int w = p->width; 393 + if( n>w ) n = w; 394 + for(i=j=0; i<n; i++){ 322 395 char c = zIn[i]; 323 396 if( c=='\t' ){ 324 397 z[j++] = ' '; 325 - while( (j&7)!=0 && j<width ) z[j++] = ' '; 398 + while( (j&7)!=0 && j<n ) z[j++] = ' '; 326 399 }else if( c=='\r' || c=='\f' ){ 327 400 z[j++] = ' '; 401 + }else if( c=='<' && p->escHtml ){ 402 + memcpy(&z[j], "<", 4); 403 + j += 4; 404 + }else if( c=='&' && p->escHtml ){ 405 + memcpy(&z[j], "&", 5); 406 + j += 5; 407 + }else if( c=='>' && p->escHtml ){ 408 + memcpy(&z[j], ">", 4); 409 + j += 4; 328 410 }else{ 329 411 z[j++] = c; 330 412 } 331 413 } 332 - if( trunc ){ 414 + if( (flags & SBS_ENDSPAN) && p->escHtml ){ 415 + memcpy(&z[j], "</span>", 7); 416 + j += 7; 417 + } 418 + if( (flags & SBS_PAD)!=0 ){ 419 + while( i<w ){ i++; z[j++] = ' '; } 420 + } 421 + if( flags & SBS_NEWLINE ){ 333 422 z[j++] = '\n'; 334 - z[j] = 0; 335 423 } 336 - return j; 424 + p->n += j; 425 +} 426 + 427 +/* 428 +** Append a string to an SbSLine with coding, interpretation, or padding. 429 +*/ 430 +static void sbsWrite(SbsLine *p, const char *zIn, int nIn){ 431 + memcpy(p->zLine+p->n, zIn, nIn); 432 + p->n += nIn; 433 +} 434 + 435 +/* 436 +** Append n spaces to the string. 437 +*/ 438 +static void sbsWriteSpace(SbsLine *p, int n){ 439 + while( n-- ) p->zLine[p->n++] = ' '; 440 +} 441 + 442 +/* 443 +** Append a string to the output only if we are rendering HTML. 444 +*/ 445 +static void sbsWriteHtml(SbsLine *p, const char *zIn){ 446 + if( p->escHtml ) sbsWrite(p, zIn, strlen(zIn)); 447 +} 448 + 449 +/* 450 +** Write a 6-digit line number followed by a single space onto the line. 451 +*/ 452 +static void sbsWriteLineno(SbsLine *p, int ln){ 453 + sbsWriteHtml(p, "<span class=\"diffln\">"); 454 + sqlite3_snprintf(7, &p->zLine[p->n], "%5d ", ln+1); 455 + p->n += 6; 456 + sbsWriteHtml(p, "</span>"); 457 + p->zLine[p->n++] = ' '; 337 458 } 338 459 339 460 340 461 /* 341 462 ** Given a diff context in which the aEdit[] array has been filled 342 463 ** in, compute a side-by-side diff into pOut. 343 464 */ 344 -static void sbsDiff(DContext *p, Blob *pOut, int nContext, int width){ 465 +static void sbsDiff( 466 + DContext *p, /* The computed diff */ 467 + Blob *pOut, /* Write the results here */ 468 + int nContext, /* Number of lines of context around each change */ 469 + int width, /* Width of each column of output */ 470 + int escHtml /* True to generate HTML output */ 471 +){ 345 472 DLine *A; /* Left side of the diff */ 346 473 DLine *B; /* Right side of the diff */ 347 474 int a = 0; /* Index of next line in A[] */ 348 475 int b = 0; /* Index of next line in B[] */ 349 476 int *R; /* Array of COPY/DELETE/INSERT triples */ 350 477 int r; /* Index into R[] */ 351 478 int nr; /* Number of COPY/DELETE/INSERT triples to process */ 352 479 int mxr; /* Maximum value for r */ 353 480 int na, nb; /* Number of lines shown from A and B */ 354 481 int i, j; /* Loop counters */ 355 482 int m, ma, mb;/* Number of lines to output */ 356 483 int skip; /* Number of lines to skip */ 357 - int mxLine; /* Length of a line of text */ 358 - char *zLine; /* A line of text being formatted */ 359 - int len; /* Length of an output line */ 484 + SbsLine s; /* Output line buffer */ 360 485 361 - mxLine = width*2 + 2*7 + 3 + 1; 362 - zLine = fossil_malloc( mxLine + 1 ); 363 - if( zLine==0 ) return; 364 - zLine[mxLine] = 0; 486 + s.zLine = fossil_malloc( 10*width + 100 ); 487 + if( s.zLine==0 ) return; 488 + s.width = width; 489 + s.escHtml = escHtml; 365 490 A = p->aFrom; 366 491 B = p->aTo; 367 492 R = p->aEdit; 368 493 mxr = p->nEdit; 369 494 while( mxr>2 && R[mxr-1]==0 && R[mxr-2]==0 ){ mxr -= 3; } 370 495 for(r=0; r<mxr; r += 3*nr){ 371 496 /* Figure out how many triples to show in a single block */ ................................................................................ 398 523 nb += R[r+i*3]; 399 524 } 400 525 /* 401 526 * If the patch changes an empty file or results in an empty file, 402 527 * the block header must use 0,0 as position indicator and not 1,0. 403 528 * Otherwise, patch would be confused and may reject the diff. 404 529 */ 405 - if( r>0 ) blob_appendf(pOut,"%.*c\n", width*2+16, '.'); 530 + if( r>0 ){ 531 + if( escHtml ){ 532 + blob_appendf(pOut, "<span class=\"diffhr\">%.*c</span>\n", 533 + width*2+16, '.'); 534 + }else{ 535 + blob_appendf(pOut, "%.*c\n", width*2+16, '.'); 536 + } 537 + } 406 538 407 539 /* Show the initial common area */ 408 540 a += skip; 409 541 b += skip; 410 542 m = R[r] - skip; 411 543 for(j=0; j<m; j++){ 412 - memset(zLine, ' ', mxLine); 413 - sbsWriteLineno(zLine, a+j); 414 - sbsWriteText(&zLine[7], &A[a+j], width, 0); 415 - sbsWriteLineno(&zLine[width+10], b+j); 416 - len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1); 417 - blob_append(pOut, zLine, len+width+17); 544 + s.n = 0; 545 + sbsWriteLineno(&s, a+j); 546 + sbsWriteText(&s, &A[a+j], SBS_PAD); 547 + sbsWrite(&s, " ", 3); 548 + sbsWriteLineno(&s, b+j); 549 + sbsWriteText(&s, &B[b+j], SBS_NEWLINE); 550 + blob_append(pOut, s.zLine, s.n); 418 551 } 419 552 a += m; 420 553 b += m; 421 554 422 555 /* Show the differences */ 423 556 for(i=0; i<nr; i++){ 424 557 ma = R[r+i*3+1]; 425 558 mb = R[r+i*3+2]; 426 559 m = ma<mb ? ma : mb; 427 560 for(j=0; j<m; j++){ 428 - memset(zLine, ' ', mxLine); 429 - sbsWriteLineno(zLine, a+j); 430 - sbsWriteText(&zLine[7], &A[a+j], width, 0); 431 - zLine[width+8] = '|'; 432 - sbsWriteLineno(&zLine[width+10], b+j); 433 - len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1); 434 - blob_append(pOut, zLine, len+width+17); 561 + s.n = 0; 562 + sbsWriteLineno(&s, a+j); 563 + sbsWriteHtml(&s, "<span class=\"diffchng\">"); 564 + sbsWriteText(&s, &A[a+j], SBS_PAD | SBS_ENDSPAN); 565 + sbsWrite(&s, " | ", 3); 566 + sbsWriteLineno(&s, b+j); 567 + sbsWriteHtml(&s, "<span class=\"diffchng\">"); 568 + sbsWriteText(&s, &B[b+j], SBS_NEWLINE | SBS_ENDSPAN); 569 + blob_append(pOut, s.zLine, s.n); 435 570 } 436 571 a += m; 437 572 b += m; 438 573 ma -= m; 439 574 mb -= m; 440 575 for(j=0; j<ma; j++){ 441 - memset(zLine, ' ', width+7); 442 - sbsWriteLineno(zLine, a+j); 443 - sbsWriteText(&zLine[7], &A[a+j], width, 0); 444 - zLine[width+8] = '<'; 445 - zLine[width+9] = '\n'; 446 - zLine[width+10] = 0; 447 - blob_append(pOut, zLine, width+10); 576 + s.n = 0; 577 + sbsWriteLineno(&s, a+j); 578 + sbsWriteHtml(&s, "<span class=\"diffrm\">"); 579 + sbsWriteText(&s, &A[a+j], SBS_PAD | SBS_ENDSPAN); 580 + sbsWrite(&s, " <\n", 3); 581 + blob_append(pOut, s.zLine, s.n); 448 582 } 449 583 a += ma; 450 584 for(j=0; j<mb; j++){ 451 - memset(zLine, ' ', mxLine); 452 - zLine[width+8] = '>'; 453 - sbsWriteLineno(&zLine[width+10], b+j); 454 - len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1); 455 - blob_append(pOut, zLine, len+width+17); 585 + s.n = 0; 586 + sbsWriteSpace(&s, width + 7); 587 + sbsWrite(&s, " > ", 3); 588 + sbsWriteLineno(&s, b+j); 589 + sbsWriteHtml(&s, "<span class=\"diffadd\">"); 590 + sbsWriteText(&s, &B[b+j], SBS_NEWLINE | SBS_ENDSPAN); 591 + blob_append(pOut, s.zLine, s.n); 456 592 } 457 593 b += mb; 458 594 if( i<nr-1 ){ 459 595 m = R[r+i*3+3]; 460 596 for(j=0; j<m; j++){ 461 - memset(zLine, ' ', mxLine); 462 - sbsWriteLineno(zLine, a+j); 463 - sbsWriteText(&zLine[7], &A[a+j], width, 0); 464 - sbsWriteLineno(&zLine[width+10], b+j); 465 - len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1); 466 - blob_append(pOut, zLine, len+width+17); 597 + s.n = 0; 598 + sbsWriteLineno(&s, a+j); 599 + sbsWriteText(&s, &A[a+j], SBS_PAD); 600 + sbsWrite(&s, " ", 3); 601 + sbsWriteLineno(&s, b+j); 602 + sbsWriteText(&s, &B[b+j], SBS_NEWLINE); 603 + blob_append(pOut, s.zLine, s.n); 467 604 } 468 605 b += m; 469 606 a += m; 470 607 } 471 608 } 472 609 473 610 /* Show the final common area */ 474 611 assert( nr==i ); 475 612 m = R[r+nr*3]; 476 613 if( m>nContext ) m = nContext; 477 614 for(j=0; j<m; j++){ 478 - memset(zLine, ' ', mxLine); 479 - sbsWriteLineno(zLine, a+j); 480 - sbsWriteText(&zLine[7], &A[a+j], width, 0); 481 - sbsWriteLineno(&zLine[width+10], b+j); 482 - len = sbsWriteText(&zLine[width+17], &B[b+j], width, 1); 483 - blob_append(pOut, zLine, len+width+17); 615 + s.n = 0; 616 + sbsWriteLineno(&s, a+j); 617 + sbsWriteText(&s, &A[a+j], SBS_PAD); 618 + sbsWrite(&s, " ", 3); 619 + sbsWriteLineno(&s, b+j); 620 + sbsWriteText(&s, &B[b+j], SBS_NEWLINE); 621 + blob_append(pOut, s.zLine, s.n); 484 622 } 485 623 } 486 - free(zLine); 624 + free(s.zLine); 487 625 } 488 626 489 627 /* 490 628 ** Compute the optimal longest common subsequence (LCS) using an 491 629 ** exhaustive search. This version of the LCS is only used for 492 630 ** shorter input strings since runtime is O(N*N) where N is the 493 631 ** input string length. ................................................................................ 784 922 } 785 923 786 924 /* Compute the difference */ 787 925 diff_all(&c); 788 926 789 927 if( pOut ){ 790 928 /* Compute a context or side-by-side diff into pOut */ 929 + int escHtml = (diffFlags & DIFF_HTML)!=0; 791 930 if( diffFlags & DIFF_SIDEBYSIDE ){ 792 931 int width = diff_width(diffFlags); 793 - sbsDiff(&c, pOut, nContext, width); 932 + sbsDiff(&c, pOut, nContext, width, escHtml); 794 933 }else{ 795 - contextDiff(&c, pOut, nContext); 934 + int showLn = (diffFlags & DIFF_LINENO)!=0; 935 + contextDiff(&c, pOut, nContext, showLn, escHtml); 796 936 } 797 937 free(c.aFrom); 798 938 free(c.aTo); 799 939 free(c.aEdit); 800 940 return 0; 801 941 }else{ 802 942 /* If a context diff is not requested, then return the ................................................................................ 803 943 ** array of COPY/DELETE/INSERT triples. 804 944 */ 805 945 free(c.aFrom); 806 946 free(c.aTo); 807 947 return c.aEdit; 808 948 } 809 949 } 810 - 811 -/* 812 -** Copy a line with a limit. Used for side-by-side diffs to enforce a maximum 813 -** line length limit. 814 -*/ 815 -static char *copylimline(char *out, DLine *dl, int lim){ 816 - int len; 817 - len = dl->h & LENGTH_MASK; 818 - if( lim && len > lim ){ 819 - memcpy(out, dl->z, lim-3); 820 - memcpy(&out[lim-3], "...", 4); 821 - }else{ 822 - memcpy(out, dl->z, len); 823 - out[len] = '\0'; 824 - } 825 - return out; 826 -} 827 - 828 -/* 829 -** Output table body of a side-by-side diff. Prior to the call, the caller 830 -** should have output: 831 -** <table class="sbsdiff"> 832 -** <tr><th colspan="2" class="diffhdr">Old title</th><th/> 833 -** <th colspan="2" class="diffhdr">New title</th></tr> 834 -** 835 -** And after the call, it should output: 836 -** </table> 837 -** 838 -** Some good reference diffs in the fossil repository for testing: 839 -** /vdiff?from=080d27a&to=4b0f813&detail=1 840 -** /vdiff?from=636804745b&to=c1d78e0556&detail=1 841 -** /vdiff?from=c0b6c28d29&to=25169506b7&detail=1 842 -** /vdiff?from=e3d022dffa&to=48bcfbd47b&detail=1 843 -*/ 844 -int html_sbsdiff( 845 - Blob *pA_Blob, /* FROM file */ 846 - Blob *pB_Blob, /* TO file */ 847 - int nContext, /* Amount of context to unified diff */ 848 - int ignoreEolWs /* Ignore whitespace at the end of lines */ 849 -){ 850 - DContext c; 851 - int i; 852 - int iFrom, iTo; 853 - char *linebuf; 854 - int collim=0; /* Currently not settable; allows a column limit for diffs */ 855 - int allowExp=0; /* Currently not settable; (dis)allow expansion of rows */ 856 - 857 - /* Prepare the input files */ 858 - memset(&c, 0, sizeof(c)); 859 - c.aFrom = break_into_lines(blob_str(pA_Blob), blob_size(pA_Blob), 860 - &c.nFrom, ignoreEolWs); 861 - c.aTo = break_into_lines(blob_str(pB_Blob), blob_size(pB_Blob), 862 - &c.nTo, ignoreEolWs); 863 - if( c.aFrom==0 || c.aTo==0 ){ 864 - free(c.aFrom); 865 - free(c.aTo); 866 - /* Note: This would be generated within a table. */ 867 - @ <p class="generalError" style="white-space: nowrap">cannot compute 868 - @ difference between binary files</p> 869 - return 0; 870 - } 871 - 872 - collim = collim < 4 ? 0 : collim; 873 - 874 - /* Compute the difference */ 875 - diff_all(&c); 876 - 877 - linebuf = fossil_malloc(LENGTH_MASK+1); 878 - if( !linebuf ){ 879 - free(c.aFrom); 880 - free(c.aTo); 881 - free(c.aEdit); 882 - return 0; 883 - } 884 - 885 - iFrom=iTo=0; 886 - i=0; 887 - while( i<c.nEdit ){ 888 - int j; 889 - /* Copied lines */ 890 - for( j=0; j<c.aEdit[i]; j++){ 891 - /* Hide lines which are copied and are further away from block boundaries 892 - ** than nContext lines. For each block with hidden lines, show a row 893 - ** notifying the user about the hidden rows. 894 - */ 895 - if( j<nContext || j>c.aEdit[i]-nContext-1 ){ 896 - @ <tr> 897 - }else if( j==nContext && j<c.aEdit[i]-nContext-1 ){ 898 - @ <tr> 899 - @ <td class="meta" colspan="5" style="white-space: nowrap;"> 900 - @ %d(c.aEdit[i]-2*nContext) hidden lines</td> 901 - @ </tr> 902 - if( !allowExp ) 903 - continue; 904 - @ <tr style="display:none;"> 905 - }else{ 906 - if( !allowExp ) 907 - continue; 908 - @ <tr style="display:none;"> 909 - } 910 - 911 - copylimline(linebuf, &c.aFrom[iFrom+j], collim); 912 - @ <td class="lineno">%d(iFrom+j+1)</td> 913 - @ <td class="srcline">%h(linebuf)</td> 914 - 915 - @ <td> </td> 916 - 917 - copylimline(linebuf, &c.aTo[iTo+j], collim); 918 - @ <td class="lineno">%d(iTo+j+1)</td> 919 - @ <td class="srcline">%h(linebuf)</td> 920 - 921 - @ </tr> 922 - } 923 - iFrom+=c.aEdit[i]; 924 - iTo+=c.aEdit[i]; 925 - 926 - if( c.aEdit[i+1]!=0 && c.aEdit[i+2]!=0 ){ 927 - int lim; 928 - lim = c.aEdit[i+1] > c.aEdit[i+2] ? c.aEdit[i+1] : c.aEdit[i+2]; 929 - 930 - /* Assume changed lines */ 931 - for( j=0; j<lim; j++ ){ 932 - @ <tr> 933 - 934 - if( j<c.aEdit[i+1] ){ 935 - copylimline(linebuf, &c.aFrom[iFrom+j], collim); 936 - @ <td class="changed lineno">%d(iFrom+j+1)</td> 937 - @ <td class="changed srcline">%h(linebuf)</td> 938 - }else{ 939 - @ <td colspan="2" class="changedvoid"/> 940 - } 941 - 942 - @ <td class="changed">|</td> 943 - 944 - if( j<c.aEdit[i+2] ){ 945 - copylimline(linebuf, &c.aTo[iTo+j], collim); 946 - @ <td class="changed lineno">%d(iTo+j+1)</td> 947 - @ <td class="changed srcline">%h(linebuf)</td> 948 - }else{ 949 - @ <td colspan="2" class="changedvoid"/> 950 - } 951 - 952 - @ </tr> 953 - } 954 - iFrom+=c.aEdit[i+1]; 955 - iTo+=c.aEdit[i+2]; 956 - }else{ 957 - 958 - /* Process deleted lines */ 959 - for( j=0; j<c.aEdit[i+1]; j++ ){ 960 - @ <tr> 961 - 962 - copylimline(linebuf, &c.aFrom[iFrom+j], collim); 963 - @ <td class="removed lineno">%d(iFrom+j+1)</td> 964 - @ <td class="removed srcline">%h(linebuf)</td> 965 - @ <td><</td> 966 - @ <td colspan="2" class="removedvoid"/> 967 - @ </tr> 968 - } 969 - iFrom+=c.aEdit[i+1]; 970 - 971 - /* Process inserted lines */ 972 - for( j=0; j<c.aEdit[i+2]; j++ ){ 973 - @ <tr> 974 - @ <td colspan="2" class="addedvoid"/> 975 - @ <td>></td> 976 - copylimline(linebuf, &c.aTo[iTo+j], collim); 977 - @ <td class="added lineno">%d(iTo+j+1)</td> 978 - @ <td class="added srcline">%h(linebuf)</td> 979 - @ </tr> 980 - } 981 - iTo+=c.aEdit[i+2]; 982 - } 983 - 984 - i+=3; 985 - } 986 - 987 - free(linebuf); 988 - free(c.aFrom); 989 - free(c.aTo); 990 - free(c.aEdit); 991 - return 1; 992 -} 993 - 994 950 995 951 /* 996 952 ** COMMAND: test-rawdiff 997 953 */ 998 954 void test_rawdiff_cmd(void){ 999 955 Blob a, b; 1000 956 int r; ................................................................................ 1017 973 /* 1018 974 ** Process diff-related command-line options and return an appropriate 1019 975 ** "diffFlags" integer. 1020 976 ** 1021 977 ** --side-by-side|-y Side-by-side diff. DIFF_SIDEBYSIDE 1022 978 ** --context|-c N N lines of context. DIFF_CONTEXT_MASK 1023 979 ** --width|-W N N character lines. DIFF_WIDTH_MASK 980 +** --html Format for HTML DIFF_HTML 981 +** --linenum|-n Show line numbers DIFF_LINENO 1024 982 */ 1025 983 int diff_options(void){ 1026 984 int diffFlags = 0; 1027 985 const char *z; 1028 986 int f; 1029 987 if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; 1030 988 if( (z = find_option("context","c",1))!=0 && (f = atoi(z))>0 ){ ................................................................................ 1032 990 diffFlags |= f; 1033 991 } 1034 992 if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ 1035 993 f *= DIFF_CONTEXT_MASK+1; 1036 994 if( f > DIFF_WIDTH_MASK ) f = DIFF_CONTEXT_MASK; 1037 995 diffFlags |= f; 1038 996 } 997 + if( find_option("html",0,0)!=0 ) diffFlags |= DIFF_HTML; 998 + if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; 1039 999 return diffFlags; 1040 1000 } 1041 1001 1042 1002 /* 1043 1003 ** COMMAND: test-udiff 1044 1004 ** 1045 1005 ** Print the difference between two files. The usual diff options apply.
Changes to src/info.c.
249 249 } 250 250 } 251 251 252 252 253 253 /* 254 254 ** Append the difference between two RIDs to the output 255 255 */ 256 -static void append_diff(const char *zFrom, const char *zTo){ 256 +static void append_diff(const char *zFrom, const char *zTo, int diffFlags){ 257 257 int fromid; 258 258 int toid; 259 259 Blob from, to, out; 260 260 if( zFrom ){ 261 261 fromid = uuid_to_rid(zFrom, 0); 262 262 content_get(fromid, &from); 263 263 }else{ ................................................................................ 266 266 if( zTo ){ 267 267 toid = uuid_to_rid(zTo, 0); 268 268 content_get(toid, &to); 269 269 }else{ 270 270 blob_zero(&to); 271 271 } 272 272 blob_zero(&out); 273 - text_diff(&from, &to, &out, DIFF_IGNORE_EOLWS | 5); 274 - @ %h(blob_str(&out)) 273 + if( diffFlags & DIFF_SIDEBYSIDE ){ 274 + text_diff(&from, &to, &out, diffFlags | DIFF_HTML); 275 + @ <div class="sbsdiff"> 276 + @ %s(blob_str(&out)) 277 + @ </div> 278 + }else{ 279 + text_diff(&from, &to, &out, diffFlags | DIFF_LINENO | DIFF_HTML); 280 + @ <div class="udiff"> 281 + @ %s(blob_str(&out)) 282 + @ </div> 283 + } 275 284 blob_reset(&from); 276 285 blob_reset(&to); 277 286 blob_reset(&out); 278 287 } 279 288 280 - 281 -/* 282 -** Write the difference between two RIDs to the output 283 -*/ 284 -static void generate_sbsdiff(const char *zFrom, const char *zTo){ 285 - int fromid; 286 - int toid; 287 - Blob from, to; 288 - if( zFrom ){ 289 - fromid = uuid_to_rid(zFrom, 0); 290 - content_get(fromid, &from); 291 - }else{ 292 - blob_zero(&from); 293 - } 294 - if( zTo ){ 295 - toid = uuid_to_rid(zTo, 0); 296 - content_get(toid, &to); 297 - }else{ 298 - blob_zero(&to); 299 - } 300 - @ <table class="sbsdiff"> 301 - @ <tr><th colspan="2" class="diffhdr">Old (%S(zFrom))</th><th/> 302 - @ <th colspan="2" class="diffhdr">New (%S(zTo))</th></tr> 303 - html_sbsdiff(&from, &to, 5, 1); 304 - @ </table> 305 - blob_reset(&from); 306 - blob_reset(&to); 307 -} 308 - 309 289 310 290 /* 311 291 ** Write a line of web-page output that shows changes that have occurred 312 292 ** to a file between two check-ins. 313 293 */ 314 294 static void append_file_change_line( 315 295 const char *zName, /* Name of the file that has changed */ 316 296 const char *zOld, /* blob.uuid before change. NULL for added files */ 317 297 const char *zNew, /* blob.uuid after change. NULL for deletes */ 318 298 const char *zOldName, /* Prior name. NULL if no name change. */ 319 - int showDiff, /* Show edit diffs if true */ 320 - int sideBySide, /* Show diffs side-by-side */ 299 + int diffFlags, /* Flags for text_diff(). Zero to omit diffs */ 321 300 int mperm /* executable or symlink permission for zNew */ 322 301 ){ 323 302 if( !g.perm.History ){ 324 303 if( zNew==0 ){ 325 304 @ <p>Deleted %h(zName)</p> 326 305 }else if( zOld==0 ){ 327 306 @ <p>Added %h(zName)</p> ................................................................................ 329 308 @ <p>Name change from %h(zOldName) to %h(zName) 330 309 }else if( fossil_strcmp(zNew, zOld)==0 ){ 331 310 @ <p>Execute permission %s(( mperm==PERM_EXE )?"set":"cleared") 332 311 @ for %h(zName)</p> 333 312 }else{ 334 313 @ <p>Changes to %h(zName)</p> 335 314 } 336 - if( showDiff ){ 337 - if( sideBySide ){ 338 - generate_sbsdiff(zOld, zNew); 339 - }else{ 340 - @ <blockquote><pre> 341 - append_diff(zOld, zNew); 342 - @ </pre></blockquote> 343 - } 315 + if( diffFlags ){ 316 + @ <pre style="white-space:pre;"> 317 + append_diff(zOld, zNew, diffFlags); 318 + @ </pre> 344 319 } 345 320 }else{ 346 321 if( zOld && zNew ){ 347 322 if( fossil_strcmp(zOld, zNew)!=0 ){ 348 323 @ <p>Modified <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 349 324 @ from <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> 350 325 @ to <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)].</a> ................................................................................ 359 334 }else if( zOld ){ 360 335 @ <p>Deleted <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 361 336 @ version <a href="%s(g.zTop)/artifact/%s(zOld)">[%S(zOld)]</a> 362 337 }else{ 363 338 @ <p>Added <a href="%s(g.zTop)/finfo?name=%T(zName)">%h(zName)</a> 364 339 @ version <a href="%s(g.zTop)/artifact/%s(zNew)">[%S(zNew)]</a> 365 340 } 366 - if( showDiff ){ 367 - if( sideBySide ){ 368 - generate_sbsdiff(zOld, zNew); 369 - }else{ 370 - @ <blockquote><pre> 371 - append_diff(zOld, zNew); 372 - @ </pre></blockquote> 373 - } 341 + if( diffFlags ){ 342 + @ <pre style="white-space:pre;"> 343 + append_diff(zOld, zNew, diffFlags); 344 + @ </pre> 374 345 }else if( zOld && zNew && fossil_strcmp(zOld,zNew)!=0 ){ 375 346 @ 376 347 @ <a href="%s(g.zTop)/fdiff?v1=%S(zOld)&v2=%S(zNew)">[diff]</a> 377 348 } 378 349 @ </p> 379 350 } 380 351 } 352 + 353 +/* 354 +** Construct an appropriate diffFlag for text_diff() based on query 355 +** parameters and the to boolean arguments. 356 +*/ 357 +static int construct_diff_flags(int showDiff, int sideBySide){ 358 + int diffFlags; 359 + if( showDiff==0 ){ 360 + diffFlags = 0; /* Zero means do not show any diff */ 361 + }else{ 362 + int x; 363 + if( sideBySide ){ 364 + diffFlags = DIFF_SIDEBYSIDE | DIFF_IGNORE_EOLWS; 365 + 366 + /* "dw" query parameter determines width of each column */ 367 + x = atoi(PD("dw","80"))*(DIFF_CONTEXT_MASK+1); 368 + if( x<0 || x>DIFF_WIDTH_MASK ) x = DIFF_WIDTH_MASK; 369 + diffFlags += x; 370 + }else{ 371 + diffFlags = DIFF_INLINE | DIFF_IGNORE_EOLWS; 372 + } 373 + 374 + /* "dc" query parameter determines lines of context */ 375 + x = atoi(PD("dc","7")); 376 + if( x<0 || x>DIFF_CONTEXT_MASK ) x = DIFF_CONTEXT_MASK; 377 + diffFlags += x; 378 + } 379 + return diffFlags; 380 +} 381 381 382 382 383 383 /* 384 384 ** WEBPAGE: vinfo 385 385 ** WEBPAGE: ci 386 386 ** URL: /ci?name=RID|ARTIFACTID 387 387 ** ................................................................................ 395 395 ** shown, without diffs. This behavior is inverted if the 396 396 ** "show-version-diffs" setting is turned on. 397 397 */ 398 398 void ci_page(void){ 399 399 Stmt q; 400 400 int rid; 401 401 int isLeaf; 402 - int showDiff; 403 - int sideBySide; 402 + int showDiff; /* True to show diffs */ 403 + int sideBySide; /* True for side-by-side diffs */ 404 + int diffFlags; /* Flag parameter for text_diff() */ 404 405 const char *zName; /* Name of the checkin to be displayed */ 405 406 const char *zUuid; /* UUID of zName */ 406 407 const char *zParent; /* UUID of the parent checkin (if any) */ 407 408 408 409 login_check_credentials(); 409 410 if( !g.perm.Read ){ login_needed(); return; } 410 411 zName = P("name"); ................................................................................ 593 594 " (SELECT uuid FROM blob WHERE rid=mlink.fid)," 594 595 " (SELECT name FROM filename WHERE filename.fnid=mlink.pfnid)" 595 596 " FROM mlink JOIN filename ON filename.fnid=mlink.fnid" 596 597 " WHERE mlink.mid=%d" 597 598 " ORDER BY name /*sort*/", 598 599 rid 599 600 ); 601 + diffFlags = construct_diff_flags(showDiff, sideBySide); 600 602 while( db_step(&q)==SQLITE_ROW ){ 601 603 const char *zName = db_column_text(&q,0); 602 604 int mperm = db_column_int(&q, 1); 603 605 const char *zOld = db_column_text(&q,2); 604 606 const char *zNew = db_column_text(&q,3); 605 607 const char *zOldName = db_column_text(&q, 4); 606 - append_file_change_line(zName, zOld, zNew, zOldName, showDiff, 607 - sideBySide, mperm); 608 + append_file_change_line(zName, zOld, zNew, zOldName, diffFlags, mperm); 608 609 } 609 610 db_finalize(&q); 610 611 } 611 612 style_footer(); 612 613 } 613 614 614 615 /* ................................................................................ 758 759 ** 759 760 ** Show all differences between two checkins. 760 761 */ 761 762 void vdiff_page(void){ 762 763 int ridFrom, ridTo; 763 764 int showDetail = 0; 764 765 int sideBySide = 0; 766 + int diffFlags = 0; 765 767 Manifest *pFrom, *pTo; 766 768 ManifestFile *pFileFrom, *pFileTo; 767 769 768 770 login_check_credentials(); 769 771 if( !g.perm.Read ){ login_needed(); return; } 770 772 login_anonymous_available(); 771 773 772 774 pFrom = vdiff_parse_manifest("from", &ridFrom); 773 775 if( pFrom==0 ) return; 774 776 pTo = vdiff_parse_manifest("to", &ridTo); 775 777 if( pTo==0 ) return; 776 - showDetail = atoi(PD("detail","0")); 777 778 sideBySide = atoi(PD("sbs","1")); 779 + showDetail = atoi(PD("detail","0")); 780 + if( !showDetail && sideBySide ) showDetail = 1; 778 781 if( !sideBySide ){ 779 782 style_submenu_element("Side-by-side Diff", "sbsdiff", 780 783 "%s/vdiff?from=%T&to=%T&detail=%d&sbs=1", 781 784 g.zTop, P("from"), P("to"), showDetail); 782 785 }else{ 783 786 style_submenu_element("Unified Diff", "udiff", 784 787 "%s/vdiff?from=%T&to=%T&detail=%d&sbs=0", ................................................................................ 791 794 checkin_description(ridTo); 792 795 @ </blockquote><hr /><p> 793 796 794 797 manifest_file_rewind(pFrom); 795 798 pFileFrom = manifest_file_next(pFrom, 0); 796 799 manifest_file_rewind(pTo); 797 800 pFileTo = manifest_file_next(pTo, 0); 801 + diffFlags = construct_diff_flags(showDetail, sideBySide); 798 802 while( pFileFrom || pFileTo ){ 799 803 int cmp; 800 804 if( pFileFrom==0 ){ 801 805 cmp = +1; 802 806 }else if( pFileTo==0 ){ 803 807 cmp = -1; 804 808 }else{ 805 809 cmp = fossil_strcmp(pFileFrom->zName, pFileTo->zName); 806 810 } 807 811 if( cmp<0 ){ 808 812 append_file_change_line(pFileFrom->zName, 809 - pFileFrom->zUuid, 0, 0, 0, 0, 0); 813 + pFileFrom->zUuid, 0, 0, 0, 0); 810 814 pFileFrom = manifest_file_next(pFrom, 0); 811 815 }else if( cmp>0 ){ 812 816 append_file_change_line(pFileTo->zName, 813 - 0, pFileTo->zUuid, 0, 0, 0, 817 + 0, pFileTo->zUuid, 0, 0, 814 818 manifest_file_mperm(pFileTo)); 815 819 pFileTo = manifest_file_next(pTo, 0); 816 820 }else if( fossil_strcmp(pFileFrom->zUuid, pFileTo->zUuid)==0 ){ 817 821 /* No changes */ 818 822 pFileFrom = manifest_file_next(pFrom, 0); 819 823 pFileTo = manifest_file_next(pTo, 0); 820 824 }else{ 821 825 append_file_change_line(pFileFrom->zName, 822 826 pFileFrom->zUuid, 823 - pFileTo->zUuid, 0, showDetail, sideBySide, 827 + pFileTo->zUuid, 0, diffFlags, 824 828 manifest_file_mperm(pFileTo)); 825 829 pFileFrom = manifest_file_next(pFrom, 0); 826 830 pFileTo = manifest_file_next(pTo, 0); 827 831 } 828 832 } 829 833 manifest_destroy(pFrom); 830 834 manifest_destroy(pTo); ................................................................................ 1067 1071 void diff_page(void){ 1068 1072 int v1, v2; 1069 1073 int isPatch; 1070 1074 int sideBySide; 1071 1075 Blob c1, c2, diff, *pOut; 1072 1076 char *zV1; 1073 1077 char *zV2; 1078 + int diffFlags; 1074 1079 1075 1080 login_check_credentials(); 1076 1081 if( !g.perm.Read ){ login_needed(); return; } 1077 1082 v1 = name_to_rid_www("v1"); 1078 1083 v2 = name_to_rid_www("v2"); 1079 1084 if( v1==0 || v2==0 ) fossil_redirect_home(); 1080 1085 sideBySide = atoi(PD("sbs","1")); 1081 1086 zV1 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v1); 1082 1087 zV2 = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", v2); 1083 1088 isPatch = P("patch")!=0; 1084 1089 if( isPatch ){ 1085 1090 pOut = cgi_output_blob(); 1086 1091 cgi_set_content_type("text/plain"); 1092 + diffFlags = 4; 1087 1093 }else{ 1088 1094 blob_zero(&diff); 1089 1095 pOut = &diff; 1096 + if( sideBySide ){ 1097 + diffFlags = DIFF_IGNORE_EOLWS | DIFF_SIDEBYSIDE | 7; 1098 + }else{ 1099 + diffFlags = DIFF_IGNORE_EOLWS | 7; 1100 + } 1090 1101 } 1091 - if( !sideBySide || isPatch ){ 1092 - content_get(v1, &c1); 1093 - content_get(v2, &c2); 1094 - text_diff(&c1, &c2, pOut, 4 | 0); 1095 - blob_reset(&c1); 1096 - blob_reset(&c2); 1097 - } 1102 + content_get(v1, &c1); 1103 + content_get(v2, &c2); 1104 + text_diff(&c1, &c2, pOut, diffFlags); 1105 + blob_reset(&c1); 1106 + blob_reset(&c2); 1098 1107 if( !isPatch ){ 1099 1108 style_header("Diff"); 1100 1109 style_submenu_element("Patch", "Patch", "%s/fdiff?v1=%T&v2=%T&patch", 1101 1110 g.zTop, P("v1"), P("v2")); 1102 1111 if( !sideBySide ){ 1103 1112 style_submenu_element("Side-by-side Diff", "sbsdiff", 1104 1113 "%s/fdiff?v1=%T&v2=%T&sbs=1", ................................................................................ 1111 1120 1112 1121 @ <h2>Differences From 1113 1122 @ Artifact <a href="%s(g.zTop)/artifact/%S(zV1)">[%S(zV1)]</a>:</h2> 1114 1123 object_description(v1, 0, 0); 1115 1124 @ <h2>To Artifact <a href="%s(g.zTop)/artifact/%S(zV2)">[%S(zV2)]</a>:</h2> 1116 1125 object_description(v2, 0, 0); 1117 1126 @ <hr /> 1118 - if( sideBySide ){ 1119 - generate_sbsdiff(zV1, zV2); 1120 - }else{ 1121 - @ <blockquote><pre> 1122 - @ %h(blob_str(&diff)) 1123 - @ </pre></blockquote> 1124 - } 1127 + @ <pre style="while-space:pre;"> 1128 + @ %h(blob_str(&diff)) 1129 + @ </pre> 1125 1130 blob_reset(&diff); 1126 1131 style_footer(); 1127 1132 } 1128 1133 } 1129 1134 1130 1135 /* 1131 1136 ** WEBPAGE: raw
Changes to src/manifest.c.
1243 1243 } 1244 1244 } 1245 1245 if( p->zBaseline==0 ) return 0; 1246 1246 fetch_baseline(p, 1); 1247 1247 pBase = p->pBaseline; 1248 1248 if( pBase==0 ) return 0; 1249 1249 for(i=0; i<pBase->nFile; i++){ 1250 - if( fossil_stricmp(zName, p->aFile[i].zName)==0 ){ 1251 - return &p->aFile[i]; 1250 + if( fossil_stricmp(zName, pBase->aFile[i].zName)==0 ){ 1251 + return &pBase->aFile[i]; 1252 1252 } 1253 1253 } 1254 1254 return 0; 1255 1255 } 1256 1256 1257 1257 /* 1258 1258 ** Add mlink table entries associated with manifest cid, pChild. The
Changes to src/skins.c.
151 151 @ } 152 152 @ 153 153 @ /* The label/value pairs on (for example) the vinfo page */ 154 154 @ table.label-value th { 155 155 @ vertical-align: top; 156 156 @ text-align: right; 157 157 @ padding: 0.2ex 2ex; 158 -@ } 159 -@ 160 -@ /* Side-by-side diff */ 161 -@ table.sbsdiff { 162 -@ background-color: white; 163 -@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; 164 -@ font-size: 8pt; 165 -@ border-collapse:collapse; 166 -@ white-space: pre; 167 -@ width: 98%; 168 -@ border: 1px #000 dashed; 169 -@ } 170 -@ 171 -@ table.sbsdiff th.diffhdr { 172 -@ border-bottom: dotted; 173 -@ border-width: 1px; 174 -@ } 175 -@ 176 -@ table.sbsdiff tr td { 177 -@ white-space: pre; 178 -@ padding-left: 3px; 179 -@ padding-right: 3px; 180 -@ margin: 0px; 181 -@ } 182 -@ 183 -@ table.sbsdiff tr td.lineno { 184 -@ text-align: right; 185 -@ } 186 -@ 187 -@ table.sbsdiff tr td.meta { 188 -@ color: white; 189 -@ background-color: rgb(20, 20, 20); 190 -@ text-align: center; 191 -@ } 192 -@ 193 -@ table.sbsdiff tr td.added { 194 -@ background-color: rgb(230, 230, 230); 195 -@ } 196 -@ 197 -@ table.sbsdiff tr td.removed { 198 -@ background-color: rgb(200, 200, 200); 199 -@ } 200 -@ 201 -@ table.sbsdiff tr td.changed { 202 -@ background-color: rgb(220, 220, 220); 203 158 @ }'); 204 159 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> 205 160 @ <head> 206 161 @ <title>$<project_name>: $<title></title> 207 162 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" 208 163 @ href="$home/timeline.rss"> 209 164 @ <link rel="stylesheet" href="$home/style.css?blackwhite" type="text/css" ................................................................................ 398 353 @ } 399 354 @ 400 355 @ /* The label/value pairs on (for example) the ci page */ 401 356 @ table.label-value th { 402 357 @ vertical-align: top; 403 358 @ text-align: right; 404 359 @ padding: 0.2ex 2ex; 405 -@ } 406 -@ 407 -@ /* Side-by-side diff */ 408 -@ table.sbsdiff { 409 -@ background-color: #ffffc5; 410 -@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; 411 -@ font-size: 8pt; 412 -@ border-collapse:collapse; 413 -@ white-space: pre; 414 -@ width: 98%; 415 -@ border: 1px #000 dashed; 416 -@ } 417 -@ 418 -@ table.sbsdiff th.diffhdr { 419 -@ border-bottom: dotted; 420 -@ border-width: 1px; 421 -@ } 422 -@ 423 -@ table.sbsdiff tr td { 424 -@ white-space: pre; 425 -@ padding-left: 3px; 426 -@ padding-right: 3px; 427 -@ margin: 0px; 428 -@ } 429 -@ 430 -@ table.sbsdiff tr td.lineno { 431 -@ text-align: right; 432 -@ } 433 -@ 434 -@ table.sbsdiff tr td.meta { 435 -@ background-color: #a09048; 436 -@ text-align: center; 437 -@ } 438 -@ 439 -@ table.sbsdiff tr td.added { 440 -@ background-color: rgb(210, 210, 100); 441 -@ } 442 -@ 443 -@ table.sbsdiff tr td.removed { 444 -@ background-color: rgb(190, 200, 110); 445 -@ } 446 -@ 447 -@ table.sbsdiff tr td.changed { 448 -@ background-color: rgb(200, 210, 120); 449 360 @ }'); 450 361 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> 451 362 @ <head> 452 363 @ <title>$<project_name>: $<title></title> 453 364 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" 454 365 @ href="$home/timeline.rss"> 455 366 @ <link rel="stylesheet" href="$home/style.css?tan" type="text/css" ................................................................................ 678 589 @ } 679 590 @ 680 591 @ /* The label/value pairs on (for example) the ci page */ 681 592 @ table.label-value th { 682 593 @ vertical-align: top; 683 594 @ text-align: right; 684 595 @ padding: 0.2ex 2ex; 685 -@ } 686 -@ 687 -@ /* Side-by-side diff */ 688 -@ table.sbsdiff { 689 -@ background-color: white; 690 -@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; 691 -@ font-size: 6pt; 692 -@ border-collapse:collapse; 693 -@ white-space: pre; 694 -@ width: 98%; 695 -@ border: 1px #000 dashed; 696 -@ } 697 -@ 698 -@ table.sbsdiff th.diffhdr { 699 -@ border-bottom: dotted; 700 -@ border-width: 1px; 701 -@ } 702 -@ 703 -@ table.sbsdiff tr td { 704 -@ white-space: pre; 705 -@ padding-left: 3px; 706 -@ padding-right: 3px; 707 -@ margin: 0px; 708 -@ } 709 -@ 710 -@ table.sbsdiff tr td.lineno { 711 -@ text-align: right; 712 -@ } 713 -@ 714 -@ table.sbsdiff tr td.meta { 715 -@ color: white; 716 -@ background-color: black; 717 -@ text-align: center; 718 -@ } 719 -@ 720 -@ table.sbsdiff tr td.added { 721 -@ background-color: white; 722 -@ } 723 -@ 724 -@ table.sbsdiff tr td.removed { 725 -@ background-color: white; 726 -@ text-decoration: line-through; 727 -@ } 728 -@ 729 -@ table.sbsdiff tr td.changed { 730 -@ background-color: white; 731 596 @ }'); 732 597 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> 733 598 @ <head> 734 599 @ <title>$<project_name>: $<title></title> 735 600 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" 736 601 @ href="$home/timeline.rss"> 737 602 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css" ................................................................................ 1022 887 @ 1023 888 @ table.report tr td { 1024 889 @ padding: 3px 5px; 1025 890 @ } 1026 891 @ 1027 892 @ textarea { 1028 893 @ font-size: 1em; 1029 -@ } 1030 -@ 1031 -@ /* Side-by-side diff */ 1032 -@ table.sbsdiff { 1033 -@ background-color: white; 1034 -@ font-family: Dejavu Sans Mono, Monaco, Lucida Console, monospace; 1035 -@ font-size: 6pt; 1036 -@ border-collapse:collapse; 1037 -@ width: 98%; 1038 -@ border: 1px #000 dashed; 1039 -@ margin-left: auto; 1040 -@ margin-right: auto; 1041 -@ } 1042 -@ 1043 -@ table.sbsdiff th.diffhdr { 1044 -@ border-bottom: dotted; 1045 -@ border-width: 1px; 1046 -@ } 1047 -@ 1048 -@ table.sbsdiff tr td { 1049 -@ padding-left: 3px; 1050 -@ padding-right: 3px; 1051 -@ margin: 0px; 1052 -@ vertical-align: top; 1053 -@ white-space: pre-wrap; 1054 -@ } 1055 -@ 1056 -@ table.sbsdiff tr td.lineno { 1057 -@ text-align: right; 1058 -@ /* border-bottom: 1px solid rgb(220, 220, 220); */ 1059 -@ } 1060 -@ 1061 -@ table.sbsdiff tr td.srcline { 1062 -@ /* max-width: 400px; */ 1063 -@ /* Note: May partially hide long lines without whitespaces */ 1064 -@ /* overflow: hidden; */ 1065 -@ /* border-bottom: 1px solid rgb(220, 220, 220); */ 1066 -@ } 1067 -@ 1068 -@ table.sbsdiff tr td.meta { 1069 -@ background-color: rgb(170, 160, 255); 1070 -@ padding-top: 0.25em; 1071 -@ padding-bottom: 0.25em; 1072 -@ text-align: center; 1073 -@ -moz-border-radius: 5px; 1074 -@ -moz-border-radius: 5px; 1075 -@ -webkit-border-radius: 5px; 1076 -@ -webkit-border-radius: 5px; 1077 -@ -border-radius: 5px; 1078 -@ -border-radius: 5px; 1079 -@ border-radius: 5px; 1080 -@ border-radius: 5px; 1081 -@ } 1082 -@ 1083 -@ table.sbsdiff tr td.added { 1084 -@ background-color: rgb(180, 250, 180); 1085 -@ /* border-bottom: 1px solid rgb(160, 230, 160); */ 1086 -@ } 1087 -@ 1088 -@ table.sbsdiff tr td.removed { 1089 -@ background-color: rgb(250, 130, 130); 1090 -@ /* border-bottom: 1px solid rgb(230, 110, 110); */ 1091 -@ } 1092 -@ 1093 -@ table.sbsdiff tr td.changed { 1094 -@ background-color: rgb(210, 210, 200); 1095 -@ /* border-bottom: 1px solid rgb(190, 190, 180); */ 1096 894 @ }'); 1097 895 @ REPLACE INTO config(name,mtime,value) VALUES('header',now(),'<html> 1098 896 @ <head> 1099 897 @ <title>$<project_name>: $<title></title> 1100 898 @ <link rel="alternate" type="application/rss+xml" title="RSS Feed" 1101 899 @ href="$home/timeline.rss"> 1102 900 @ <link rel="stylesheet" href="$home/style.css?black2" type="text/css"
Changes to src/style.c.
396 396 @ 397 397 @ /* The label/value pairs on (for example) the ci page */ 398 398 @ table.label-value th { 399 399 @ vertical-align: top; 400 400 @ text-align: right; 401 401 @ padding: 0.2ex 2ex; 402 402 @ } 403 -@ 404 -@ /* Side-by-side diff */ 405 -@ table.sbsdiff { 406 -@ background-color: white; 407 -@ font-family: fixed, Dejavu Sans Mono, Monaco, Lucida Console, monospace; 408 -@ font-size: 8pt; 409 -@ border-collapse:collapse; 410 -@ white-space: pre; 411 -@ width: 98%; 412 -@ border: 1px #000 dashed; 413 -@ margin-left: auto; 414 -@ margin-right: auto; 415 -@ } 416 -@ 417 -@ table.sbsdiff th.diffhdr { 418 -@ border-bottom: dotted; 419 -@ border-width: 1px; 420 -@ } 421 -@ 422 -@ table.sbsdiff tr td { 423 -@ white-space: pre; 424 -@ padding-left: 3px; 425 -@ padding-right: 3px; 426 -@ margin: 0px; 427 -@ vertical-align: top; 428 -@ } 429 -@ 430 -@ table.sbsdiff tr td.lineno { 431 -@ text-align: right; 432 -@ } 433 -@ 434 -@ table.sbsdiff tr td.srcline { 435 -@ } 436 -@ 437 -@ table.sbsdiff tr td.meta { 438 -@ background-color: rgb(170, 160, 255); 439 -@ text-align: center; 440 -@ } 441 -@ 442 -@ table.sbsdiff tr td.added { 443 -@ background-color: rgb(180, 250, 180); 444 -@ } 445 -@ table.sbsdiff tr td.addedvoid { 446 -@ background-color: rgb(190, 190, 180); 447 -@ } 448 -@ 449 -@ table.sbsdiff tr td.removed { 450 -@ background-color: rgb(250, 130, 130); 451 -@ } 452 -@ table.sbsdiff tr td.removedvoid { 453 -@ background-color: rgb(190, 190, 180); 454 -@ } 455 -@ 456 -@ table.sbsdiff tr td.changed { 457 -@ background-color: rgb(210, 210, 200); 458 -@ } 459 -@ table.sbsdiff tr td.changedvoid { 460 -@ background-color: rgb(190, 190, 180); 461 -@ } 462 -@ 463 403 ; 464 404 465 405 466 406 /* The following table contains bits of default CSS that must 467 407 ** be included if they are not found in the application-defined 468 408 ** CSS. 469 409 */ ................................................................................ 809 749 @ color: red; 810 750 }, 811 751 { "ul.filelist", 812 752 "List of files in a timeline", 813 753 @ margin-top: 3px; 814 754 @ line-height: 100%; 815 755 }, 756 + { "div.sbsdiff", 757 + "side-by-side diff display", 758 + @ font-family: monospace; 759 + @ font-size: smaller; 760 + @ white-space: pre; 761 + }, 762 + { "div.udiff", 763 + "context diff display", 764 + @ font-family: monospace; 765 + @ white-space: pre; 766 + }, 767 + { "span.diffchng", 768 + "changes in a diff", 769 + @ background-color: #ffffc8; 770 + }, 771 + { "span.diffadd", 772 + "added code in a diff", 773 + @ background-color: #e0ffe0; 774 + }, 775 + { "span.diffrm", 776 + "deleted in a diff", 777 + @ background-color: #ffe0e0; 778 + }, 779 + { "span.diffhr", 780 + "suppressed lines in a diff", 781 + @ color: #0000ff; 782 + }, 783 + { "span.diffln", 784 + "line nubmers in a diff", 785 + @ color: #a0a0a0; 786 + }, 816 787 { 0, 817 788 0, 818 789 0 819 790 } 820 791 }; 821 792 822 793 /*