Fossil SCM
Implement -p|--prototype option for diff command. This commit introduces support for displaying in the chunk header which C function each change is in. Tested on OpenBSD, Ubuntu, and macOS.
Commit
792674372e7d6a8e70552e991163f61ca3d72ec97273ad8b1e7773dc37f8e40b
Parent
ba95498d36d0176…
2 files changed
+134
+7
+134
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -47,10 +47,11 @@ | ||
| 47 | 47 | #define DIFF_JSON 0x00010000 /* JSON output */ |
| 48 | 48 | #define DIFF_DEBUG 0x00020000 /* Debugging diff output */ |
| 49 | 49 | #define DIFF_RAW 0x00040000 /* Raw triples - for debugging */ |
| 50 | 50 | #define DIFF_TCL 0x00080000 /* For the --tk option */ |
| 51 | 51 | #define DIFF_INCBINARY 0x00100000 /* The --diff-binary option */ |
| 52 | +#define DIFF_PROTOTYPE 0x00200000 /* Function prototype in chunk head */ | |
| 52 | 53 | |
| 53 | 54 | /* |
| 54 | 55 | ** These error messages are shared in multiple locations. They are defined |
| 55 | 56 | ** here for consistency. |
| 56 | 57 | */ |
| @@ -97,10 +98,21 @@ | ||
| 97 | 98 | u32 nFile; /* Number of files diffed so far */ |
| 98 | 99 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 99 | 100 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 100 | 101 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 101 | 102 | const char *zLeftHash; /* HASH-id of the left file */ |
| 103 | + struct { | |
| 104 | + /* | |
| 105 | + * DIFF_PROTOTYPE (fossil diff -p|--prototype) data types for matching | |
| 106 | + * each chunk change in the diff to it's enclosing function. | |
| 107 | + */ | |
| 108 | + const Blob *pFileLHS; /* Pointer to "from" file content */ | |
| 109 | + char *zSignature; /* Enclosing function signature */ | |
| 110 | + uint32_t iLastMatch; /* Line index of the last function match */ | |
| 111 | + uint32_t iLastLine; /* Starting line index of the last chunk scanned */ | |
| 112 | + size_t iOffset; /* Byte offset into pFileLHS->aData of iLastMatch */ | |
| 113 | + } proto; | |
| 102 | 114 | }; |
| 103 | 115 | |
| 104 | 116 | #endif /* INTERFACE */ |
| 105 | 117 | |
| 106 | 118 | /* |
| @@ -362,10 +374,117 @@ | ||
| 362 | 374 | blob_appendf(pOut, "%6d ", lnB); |
| 363 | 375 | }else{ |
| 364 | 376 | blob_append(pOut, " ", 8); |
| 365 | 377 | } |
| 366 | 378 | } |
| 379 | + | |
| 380 | +/* | |
| 381 | +** Starting from iSeek lines, copy n lines from pSrc to pDest. The seek starts | |
| 382 | +** from iOffset bytes into pSrc->aData. This routine does _not_ modify pSrc. | |
| 383 | +*/ | |
| 384 | +static void blob_copy_lines_from( | |
| 385 | + Blob * const pDest, /* Destination blob */ | |
| 386 | + const Blob * const pSrc, /* Source blob from which to copy line(s) */ | |
| 387 | + size_t *iOffset, /* Begin seek from this byte offset */ | |
| 388 | + size_t iSeek, /* Skip this many lines before copying */ | |
| 389 | + size_t n /* Copy this many lines */ | |
| 390 | +){ | |
| 391 | + const char *z = (const char *)pSrc->aData; | |
| 392 | + size_t idx = *iOffset, ln = 0, start = 0; | |
| 393 | + | |
| 394 | + if( n==0 ){ | |
| 395 | + return; | |
| 396 | + } | |
| 397 | + | |
| 398 | + while( idx<pSrc->nUsed ){ | |
| 399 | + if( z[idx]=='\n' ){ | |
| 400 | + if( ++ln==iSeek ){ | |
| 401 | + start = idx + 1; /* skip '\n' */ | |
| 402 | + } | |
| 403 | + if( ln==iSeek + n ){ | |
| 404 | + ++idx; | |
| 405 | + break; | |
| 406 | + } | |
| 407 | + } | |
| 408 | + ++idx; | |
| 409 | + } | |
| 410 | + | |
| 411 | + if( pDest ){ | |
| 412 | + blob_append(pDest, &pSrc->aData[start], idx - start - 1); /* trim '\n' */ | |
| 413 | + } | |
| 414 | + *iOffset = start; | |
| 415 | + return; | |
| 416 | +} | |
| 417 | + | |
| 418 | +#define starts_with(_str, _pfx) (fossil_strncmp(_str, _pfx, sizeof(_pfx)-1)==0) | |
| 419 | + | |
| 420 | +/* | |
| 421 | + * Scan the diffed file from the line preceding the start of the current chunk | |
| 422 | + * for the enclosing function in which the change resides. Return first match. | |
| 423 | + */ | |
| 424 | +static char * matchChunkFunction( | |
| 425 | + DiffConfig *const pCfg, /* Diff config options */ | |
| 426 | + uint32_t iPos /* Line position in file from which to start scan */ | |
| 427 | +){ | |
| 428 | + Blob pBuf; /* Matching function prototype */ | |
| 429 | + const char *zLine; /* Text of line being scanned */ | |
| 430 | + char *zSpec = NULL; /* Access specifier: private, protected, public */ | |
| 431 | + size_t iOffset; /* Byte offset to the last matching line */ | |
| 432 | + uint32_t iLast; /* Line index to start of the last chunk matched */ | |
| 433 | + | |
| 434 | + blob_zero(&pBuf); | |
| 435 | + iLast = pCfg->proto.iLastLine; | |
| 436 | + pCfg->proto.iLastLine = iPos; | |
| 437 | + iOffset = pCfg->proto.iOffset; /* Begin seeking from last match */ | |
| 438 | + | |
| 439 | + /* Scan backwards from the line immediately preceding this chunk. */ | |
| 440 | + while( iPos > 1 && iPos > iLast ){ | |
| 441 | + blob_copy_lines_from(&pBuf, pCfg->proto.pFileLHS, &iOffset, | |
| 442 | + iPos - pCfg->proto.iLastMatch, 1); | |
| 443 | + zLine = blob_str(&pBuf); | |
| 444 | + if ( zLine ){ | |
| 445 | + /* | |
| 446 | + * GNU C and MSVC allow '$' in identifier names. | |
| 447 | + * https://gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html | |
| 448 | + * https://docs.microsoft.com/en-us/cpp/cpp/identifiers-cpp | |
| 449 | + */ | |
| 450 | + if( fossil_isalpha(zLine[0]) || zLine[0] == '_' || zLine[0] == '$' ){ | |
| 451 | + if( starts_with(zLine, "private:") ){ | |
| 452 | + if( !zSpec ){ | |
| 453 | + zSpec = " (private)"; | |
| 454 | + } | |
| 455 | + }else if( starts_with(zLine, "protected:") ){ | |
| 456 | + if( !zSpec ){ | |
| 457 | + zSpec = " (protected)"; | |
| 458 | + } | |
| 459 | + }else if( starts_with(zLine, "public:") ){ | |
| 460 | + if( !zSpec ){ | |
| 461 | + zSpec = " (public)"; | |
| 462 | + } | |
| 463 | + }else{ | |
| 464 | + /* Don't exceed 80 cols: chunk header consumes ~25, cap sig at 55. */ | |
| 465 | + char *zSig = mprintf("%s%s", zLine, zSpec ? zSpec : ""); | |
| 466 | + fossil_free(pCfg->proto.zSignature); | |
| 467 | + pCfg->proto.zSignature = mprintf("%.55s", zSig); | |
| 468 | + /* | |
| 469 | + * It's expensive to seek from the beginning of the file when diffing | |
| 470 | + * large files, so record byte offset and line index of this match. | |
| 471 | + */ | |
| 472 | + pCfg->proto.iLastMatch = iPos; | |
| 473 | + pCfg->proto.iOffset = iOffset; | |
| 474 | + fossil_free(zSig); | |
| 475 | + blob_reset(&pBuf); | |
| 476 | + return pCfg->proto.zSignature; | |
| 477 | + } | |
| 478 | + } | |
| 479 | + } | |
| 480 | + iOffset = pCfg->proto.iOffset; /* No match, revert offset to previous */ | |
| 481 | + blob_reset(&pBuf); | |
| 482 | + --iPos; | |
| 483 | + } | |
| 484 | + return pCfg->proto.iLastMatch > 0 ? pCfg->proto.zSignature : NULL; | |
| 485 | +} | |
| 367 | 486 | |
| 368 | 487 | /* |
| 369 | 488 | ** Output a patch-style text diff. |
| 370 | 489 | */ |
| 371 | 490 | static void contextDiff( |
| @@ -447,10 +566,16 @@ | ||
| 447 | 566 | * Otherwise, patch would be confused and may reject the diff. |
| 448 | 567 | */ |
| 449 | 568 | blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", |
| 450 | 569 | na ? a+skip+1 : a+skip, na, |
| 451 | 570 | nb ? b+skip+1 : b+skip, nb); |
| 571 | + if((DIFF_PROTOTYPE & pCfg->diffFlags) && a+skip > 1) { | |
| 572 | + char *f = matchChunkFunction(pCfg, (a+skip) - 1); | |
| 573 | + if( f != NULL ){ | |
| 574 | + blob_appendf(pOut, " %s", f); | |
| 575 | + } | |
| 576 | + } | |
| 452 | 577 | blob_append(pOut, "\n", 1); |
| 453 | 578 | } |
| 454 | 579 | |
| 455 | 580 | /* Show the initial common area */ |
| 456 | 581 | a += skip; |
| @@ -495,10 +620,11 @@ | ||
| 495 | 620 | for(j=0; j<m; j++){ |
| 496 | 621 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1); |
| 497 | 622 | appendDiffLine(pOut, ' ', &A[a+j]); |
| 498 | 623 | } |
| 499 | 624 | } |
| 625 | + fossil_free(pCfg->proto.zSignature); | |
| 500 | 626 | } |
| 501 | 627 | |
| 502 | 628 | #define MX_CSN 8 /* Maximum number of change spans across a change region */ |
| 503 | 629 | |
| 504 | 630 | /* |
| @@ -2699,10 +2825,14 @@ | ||
| 2699 | 2825 | DiffConfig *pCfg /* Configuration options */ |
| 2700 | 2826 | ){ |
| 2701 | 2827 | int ignoreWs; /* Ignore whitespace */ |
| 2702 | 2828 | DContext c; |
| 2703 | 2829 | |
| 2830 | + if( pCfg->diffFlags & DIFF_PROTOTYPE ){ | |
| 2831 | + memset(&pCfg->proto, 0, sizeof(pCfg->proto)); | |
| 2832 | + pCfg->proto.pFileLHS = pA_Blob; | |
| 2833 | + } | |
| 2704 | 2834 | if( pCfg->diffFlags & DIFF_INVERT ){ |
| 2705 | 2835 | Blob *pTemp = pA_Blob; |
| 2706 | 2836 | pA_Blob = pB_Blob; |
| 2707 | 2837 | pB_Blob = pTemp; |
| 2708 | 2838 | } |
| @@ -2825,10 +2955,11 @@ | ||
| 2825 | 2955 | ** --html Format for HTML DIFF_HTML |
| 2826 | 2956 | ** --invert Invert the diff DIFF_INVERT |
| 2827 | 2957 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 2828 | 2958 | ** --noopt Disable optimization DIFF_NOOPT |
| 2829 | 2959 | ** --numstat Show change counts DIFF_NUMSTAT |
| 2960 | +** -p|--prototype Show enclosing function DIFF_PROTOTYPE | |
| 2830 | 2961 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| 2831 | 2962 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 2832 | 2963 | ** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS |
| 2833 | 2964 | ** -W|--width N N character lines. wColumn |
| 2834 | 2965 | ** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE |
| @@ -2843,10 +2974,13 @@ | ||
| 2843 | 2974 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| 2844 | 2975 | diffFlags = DIFF_IGNORE_EOLWS; |
| 2845 | 2976 | } |
| 2846 | 2977 | if( find_option("ignore-all-space","w",0)!=0 ){ |
| 2847 | 2978 | diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ |
| 2979 | + } | |
| 2980 | + if( find_option("prototype","p",0)!=0 ){ | |
| 2981 | + diffFlags = DIFF_PROTOTYPE; | |
| 2848 | 2982 | } |
| 2849 | 2983 | if( find_option("strip-trailing-cr",0,0)!=0 ){ |
| 2850 | 2984 | diffFlags |= DIFF_STRIP_EOLCR; |
| 2851 | 2985 | } |
| 2852 | 2986 | if( !bUnifiedTextOnly ){ |
| 2853 | 2987 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | #define DIFF_JSON 0x00010000 /* JSON output */ |
| 48 | #define DIFF_DEBUG 0x00020000 /* Debugging diff output */ |
| 49 | #define DIFF_RAW 0x00040000 /* Raw triples - for debugging */ |
| 50 | #define DIFF_TCL 0x00080000 /* For the --tk option */ |
| 51 | #define DIFF_INCBINARY 0x00100000 /* The --diff-binary option */ |
| 52 | |
| 53 | /* |
| 54 | ** These error messages are shared in multiple locations. They are defined |
| 55 | ** here for consistency. |
| 56 | */ |
| @@ -97,10 +98,21 @@ | |
| 97 | u32 nFile; /* Number of files diffed so far */ |
| 98 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 99 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 100 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 101 | const char *zLeftHash; /* HASH-id of the left file */ |
| 102 | }; |
| 103 | |
| 104 | #endif /* INTERFACE */ |
| 105 | |
| 106 | /* |
| @@ -362,10 +374,117 @@ | |
| 362 | blob_appendf(pOut, "%6d ", lnB); |
| 363 | }else{ |
| 364 | blob_append(pOut, " ", 8); |
| 365 | } |
| 366 | } |
| 367 | |
| 368 | /* |
| 369 | ** Output a patch-style text diff. |
| 370 | */ |
| 371 | static void contextDiff( |
| @@ -447,10 +566,16 @@ | |
| 447 | * Otherwise, patch would be confused and may reject the diff. |
| 448 | */ |
| 449 | blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", |
| 450 | na ? a+skip+1 : a+skip, na, |
| 451 | nb ? b+skip+1 : b+skip, nb); |
| 452 | blob_append(pOut, "\n", 1); |
| 453 | } |
| 454 | |
| 455 | /* Show the initial common area */ |
| 456 | a += skip; |
| @@ -495,10 +620,11 @@ | |
| 495 | for(j=0; j<m; j++){ |
| 496 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1); |
| 497 | appendDiffLine(pOut, ' ', &A[a+j]); |
| 498 | } |
| 499 | } |
| 500 | } |
| 501 | |
| 502 | #define MX_CSN 8 /* Maximum number of change spans across a change region */ |
| 503 | |
| 504 | /* |
| @@ -2699,10 +2825,14 @@ | |
| 2699 | DiffConfig *pCfg /* Configuration options */ |
| 2700 | ){ |
| 2701 | int ignoreWs; /* Ignore whitespace */ |
| 2702 | DContext c; |
| 2703 | |
| 2704 | if( pCfg->diffFlags & DIFF_INVERT ){ |
| 2705 | Blob *pTemp = pA_Blob; |
| 2706 | pA_Blob = pB_Blob; |
| 2707 | pB_Blob = pTemp; |
| 2708 | } |
| @@ -2825,10 +2955,11 @@ | |
| 2825 | ** --html Format for HTML DIFF_HTML |
| 2826 | ** --invert Invert the diff DIFF_INVERT |
| 2827 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 2828 | ** --noopt Disable optimization DIFF_NOOPT |
| 2829 | ** --numstat Show change counts DIFF_NUMSTAT |
| 2830 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| 2831 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 2832 | ** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS |
| 2833 | ** -W|--width N N character lines. wColumn |
| 2834 | ** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE |
| @@ -2843,10 +2974,13 @@ | |
| 2843 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| 2844 | diffFlags = DIFF_IGNORE_EOLWS; |
| 2845 | } |
| 2846 | if( find_option("ignore-all-space","w",0)!=0 ){ |
| 2847 | diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ |
| 2848 | } |
| 2849 | if( find_option("strip-trailing-cr",0,0)!=0 ){ |
| 2850 | diffFlags |= DIFF_STRIP_EOLCR; |
| 2851 | } |
| 2852 | if( !bUnifiedTextOnly ){ |
| 2853 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -47,10 +47,11 @@ | |
| 47 | #define DIFF_JSON 0x00010000 /* JSON output */ |
| 48 | #define DIFF_DEBUG 0x00020000 /* Debugging diff output */ |
| 49 | #define DIFF_RAW 0x00040000 /* Raw triples - for debugging */ |
| 50 | #define DIFF_TCL 0x00080000 /* For the --tk option */ |
| 51 | #define DIFF_INCBINARY 0x00100000 /* The --diff-binary option */ |
| 52 | #define DIFF_PROTOTYPE 0x00200000 /* Function prototype in chunk head */ |
| 53 | |
| 54 | /* |
| 55 | ** These error messages are shared in multiple locations. They are defined |
| 56 | ** here for consistency. |
| 57 | */ |
| @@ -97,10 +98,21 @@ | |
| 98 | u32 nFile; /* Number of files diffed so far */ |
| 99 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 100 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 101 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 102 | const char *zLeftHash; /* HASH-id of the left file */ |
| 103 | struct { |
| 104 | /* |
| 105 | * DIFF_PROTOTYPE (fossil diff -p|--prototype) data types for matching |
| 106 | * each chunk change in the diff to it's enclosing function. |
| 107 | */ |
| 108 | const Blob *pFileLHS; /* Pointer to "from" file content */ |
| 109 | char *zSignature; /* Enclosing function signature */ |
| 110 | uint32_t iLastMatch; /* Line index of the last function match */ |
| 111 | uint32_t iLastLine; /* Starting line index of the last chunk scanned */ |
| 112 | size_t iOffset; /* Byte offset into pFileLHS->aData of iLastMatch */ |
| 113 | } proto; |
| 114 | }; |
| 115 | |
| 116 | #endif /* INTERFACE */ |
| 117 | |
| 118 | /* |
| @@ -362,10 +374,117 @@ | |
| 374 | blob_appendf(pOut, "%6d ", lnB); |
| 375 | }else{ |
| 376 | blob_append(pOut, " ", 8); |
| 377 | } |
| 378 | } |
| 379 | |
| 380 | /* |
| 381 | ** Starting from iSeek lines, copy n lines from pSrc to pDest. The seek starts |
| 382 | ** from iOffset bytes into pSrc->aData. This routine does _not_ modify pSrc. |
| 383 | */ |
| 384 | static void blob_copy_lines_from( |
| 385 | Blob * const pDest, /* Destination blob */ |
| 386 | const Blob * const pSrc, /* Source blob from which to copy line(s) */ |
| 387 | size_t *iOffset, /* Begin seek from this byte offset */ |
| 388 | size_t iSeek, /* Skip this many lines before copying */ |
| 389 | size_t n /* Copy this many lines */ |
| 390 | ){ |
| 391 | const char *z = (const char *)pSrc->aData; |
| 392 | size_t idx = *iOffset, ln = 0, start = 0; |
| 393 | |
| 394 | if( n==0 ){ |
| 395 | return; |
| 396 | } |
| 397 | |
| 398 | while( idx<pSrc->nUsed ){ |
| 399 | if( z[idx]=='\n' ){ |
| 400 | if( ++ln==iSeek ){ |
| 401 | start = idx + 1; /* skip '\n' */ |
| 402 | } |
| 403 | if( ln==iSeek + n ){ |
| 404 | ++idx; |
| 405 | break; |
| 406 | } |
| 407 | } |
| 408 | ++idx; |
| 409 | } |
| 410 | |
| 411 | if( pDest ){ |
| 412 | blob_append(pDest, &pSrc->aData[start], idx - start - 1); /* trim '\n' */ |
| 413 | } |
| 414 | *iOffset = start; |
| 415 | return; |
| 416 | } |
| 417 | |
| 418 | #define starts_with(_str, _pfx) (fossil_strncmp(_str, _pfx, sizeof(_pfx)-1)==0) |
| 419 | |
| 420 | /* |
| 421 | * Scan the diffed file from the line preceding the start of the current chunk |
| 422 | * for the enclosing function in which the change resides. Return first match. |
| 423 | */ |
| 424 | static char * matchChunkFunction( |
| 425 | DiffConfig *const pCfg, /* Diff config options */ |
| 426 | uint32_t iPos /* Line position in file from which to start scan */ |
| 427 | ){ |
| 428 | Blob pBuf; /* Matching function prototype */ |
| 429 | const char *zLine; /* Text of line being scanned */ |
| 430 | char *zSpec = NULL; /* Access specifier: private, protected, public */ |
| 431 | size_t iOffset; /* Byte offset to the last matching line */ |
| 432 | uint32_t iLast; /* Line index to start of the last chunk matched */ |
| 433 | |
| 434 | blob_zero(&pBuf); |
| 435 | iLast = pCfg->proto.iLastLine; |
| 436 | pCfg->proto.iLastLine = iPos; |
| 437 | iOffset = pCfg->proto.iOffset; /* Begin seeking from last match */ |
| 438 | |
| 439 | /* Scan backwards from the line immediately preceding this chunk. */ |
| 440 | while( iPos > 1 && iPos > iLast ){ |
| 441 | blob_copy_lines_from(&pBuf, pCfg->proto.pFileLHS, &iOffset, |
| 442 | iPos - pCfg->proto.iLastMatch, 1); |
| 443 | zLine = blob_str(&pBuf); |
| 444 | if ( zLine ){ |
| 445 | /* |
| 446 | * GNU C and MSVC allow '$' in identifier names. |
| 447 | * https://gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html |
| 448 | * https://docs.microsoft.com/en-us/cpp/cpp/identifiers-cpp |
| 449 | */ |
| 450 | if( fossil_isalpha(zLine[0]) || zLine[0] == '_' || zLine[0] == '$' ){ |
| 451 | if( starts_with(zLine, "private:") ){ |
| 452 | if( !zSpec ){ |
| 453 | zSpec = " (private)"; |
| 454 | } |
| 455 | }else if( starts_with(zLine, "protected:") ){ |
| 456 | if( !zSpec ){ |
| 457 | zSpec = " (protected)"; |
| 458 | } |
| 459 | }else if( starts_with(zLine, "public:") ){ |
| 460 | if( !zSpec ){ |
| 461 | zSpec = " (public)"; |
| 462 | } |
| 463 | }else{ |
| 464 | /* Don't exceed 80 cols: chunk header consumes ~25, cap sig at 55. */ |
| 465 | char *zSig = mprintf("%s%s", zLine, zSpec ? zSpec : ""); |
| 466 | fossil_free(pCfg->proto.zSignature); |
| 467 | pCfg->proto.zSignature = mprintf("%.55s", zSig); |
| 468 | /* |
| 469 | * It's expensive to seek from the beginning of the file when diffing |
| 470 | * large files, so record byte offset and line index of this match. |
| 471 | */ |
| 472 | pCfg->proto.iLastMatch = iPos; |
| 473 | pCfg->proto.iOffset = iOffset; |
| 474 | fossil_free(zSig); |
| 475 | blob_reset(&pBuf); |
| 476 | return pCfg->proto.zSignature; |
| 477 | } |
| 478 | } |
| 479 | } |
| 480 | iOffset = pCfg->proto.iOffset; /* No match, revert offset to previous */ |
| 481 | blob_reset(&pBuf); |
| 482 | --iPos; |
| 483 | } |
| 484 | return pCfg->proto.iLastMatch > 0 ? pCfg->proto.zSignature : NULL; |
| 485 | } |
| 486 | |
| 487 | /* |
| 488 | ** Output a patch-style text diff. |
| 489 | */ |
| 490 | static void contextDiff( |
| @@ -447,10 +566,16 @@ | |
| 566 | * Otherwise, patch would be confused and may reject the diff. |
| 567 | */ |
| 568 | blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", |
| 569 | na ? a+skip+1 : a+skip, na, |
| 570 | nb ? b+skip+1 : b+skip, nb); |
| 571 | if((DIFF_PROTOTYPE & pCfg->diffFlags) && a+skip > 1) { |
| 572 | char *f = matchChunkFunction(pCfg, (a+skip) - 1); |
| 573 | if( f != NULL ){ |
| 574 | blob_appendf(pOut, " %s", f); |
| 575 | } |
| 576 | } |
| 577 | blob_append(pOut, "\n", 1); |
| 578 | } |
| 579 | |
| 580 | /* Show the initial common area */ |
| 581 | a += skip; |
| @@ -495,10 +620,11 @@ | |
| 620 | for(j=0; j<m; j++){ |
| 621 | if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1); |
| 622 | appendDiffLine(pOut, ' ', &A[a+j]); |
| 623 | } |
| 624 | } |
| 625 | fossil_free(pCfg->proto.zSignature); |
| 626 | } |
| 627 | |
| 628 | #define MX_CSN 8 /* Maximum number of change spans across a change region */ |
| 629 | |
| 630 | /* |
| @@ -2699,10 +2825,14 @@ | |
| 2825 | DiffConfig *pCfg /* Configuration options */ |
| 2826 | ){ |
| 2827 | int ignoreWs; /* Ignore whitespace */ |
| 2828 | DContext c; |
| 2829 | |
| 2830 | if( pCfg->diffFlags & DIFF_PROTOTYPE ){ |
| 2831 | memset(&pCfg->proto, 0, sizeof(pCfg->proto)); |
| 2832 | pCfg->proto.pFileLHS = pA_Blob; |
| 2833 | } |
| 2834 | if( pCfg->diffFlags & DIFF_INVERT ){ |
| 2835 | Blob *pTemp = pA_Blob; |
| 2836 | pA_Blob = pB_Blob; |
| 2837 | pB_Blob = pTemp; |
| 2838 | } |
| @@ -2825,10 +2955,11 @@ | |
| 2955 | ** --html Format for HTML DIFF_HTML |
| 2956 | ** --invert Invert the diff DIFF_INVERT |
| 2957 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 2958 | ** --noopt Disable optimization DIFF_NOOPT |
| 2959 | ** --numstat Show change counts DIFF_NUMSTAT |
| 2960 | ** -p|--prototype Show enclosing function DIFF_PROTOTYPE |
| 2961 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| 2962 | ** --unified Unified diff. ~DIFF_SIDEBYSIDE |
| 2963 | ** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS |
| 2964 | ** -W|--width N N character lines. wColumn |
| 2965 | ** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE |
| @@ -2843,10 +2974,13 @@ | |
| 2974 | if( find_option("ignore-trailing-space","Z",0)!=0 ){ |
| 2975 | diffFlags = DIFF_IGNORE_EOLWS; |
| 2976 | } |
| 2977 | if( find_option("ignore-all-space","w",0)!=0 ){ |
| 2978 | diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ |
| 2979 | } |
| 2980 | if( find_option("prototype","p",0)!=0 ){ |
| 2981 | diffFlags = DIFF_PROTOTYPE; |
| 2982 | } |
| 2983 | if( find_option("strip-trailing-cr",0,0)!=0 ){ |
| 2984 | diffFlags |= DIFF_STRIP_EOLCR; |
| 2985 | } |
| 2986 | if( !bUnifiedTextOnly ){ |
| 2987 |
+7
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -1026,10 +1026,16 @@ | ||
| 1026 | 1026 | ** when using an external diff program. |
| 1027 | 1027 | ** |
| 1028 | 1028 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1029 | 1029 | ** as binary when considering if they should be used with external diff program. |
| 1030 | 1030 | ** This option overrides the "binary-glob" setting. |
| 1031 | +** | |
| 1032 | +** The "--prototype" option is specific to C/C++ source code, and only applies | |
| 1033 | +** to the standard unified diff, where the enclosing function of each change | |
| 1034 | +** will be shown in the chunk header; for example: | |
| 1035 | +** | |
| 1036 | +** @@ -2360,10 +2361,11 @@ draw_commits(struct fnc_view *view) | |
| 1031 | 1037 | ** |
| 1032 | 1038 | ** These command show differences between managed files. Use the "fossil xdiff" |
| 1033 | 1039 | ** command to see differences in unmanaged files. |
| 1034 | 1040 | ** |
| 1035 | 1041 | ** Options: |
| @@ -1043,10 +1049,11 @@ | ||
| 1043 | 1049 | ** --command PROG External diff program. Overrides "diff-command" |
| 1044 | 1050 | ** -c|--context N Show N lines of context around each change |
| 1045 | 1051 | ** --diff-binary BOOL Include binary files with external commands |
| 1046 | 1052 | ** --exec-abs-paths Force absolute path names on external commands |
| 1047 | 1053 | ** --exec-rel-paths Force relative path names on external commands |
| 1054 | +** -p|--prototype Show which C function each change is in | |
| 1048 | 1055 | ** -r|--from VERSION Select VERSION as source for the diff |
| 1049 | 1056 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 1050 | 1057 | ** -i|--internal Use internal diff logic |
| 1051 | 1058 | ** --json Output formatted as JSON |
| 1052 | 1059 | ** -N|--new-file Alias for --verbose |
| 1053 | 1060 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1026,10 +1026,16 @@ | |
| 1026 | ** when using an external diff program. |
| 1027 | ** |
| 1028 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1029 | ** as binary when considering if they should be used with external diff program. |
| 1030 | ** This option overrides the "binary-glob" setting. |
| 1031 | ** |
| 1032 | ** These command show differences between managed files. Use the "fossil xdiff" |
| 1033 | ** command to see differences in unmanaged files. |
| 1034 | ** |
| 1035 | ** Options: |
| @@ -1043,10 +1049,11 @@ | |
| 1043 | ** --command PROG External diff program. Overrides "diff-command" |
| 1044 | ** -c|--context N Show N lines of context around each change |
| 1045 | ** --diff-binary BOOL Include binary files with external commands |
| 1046 | ** --exec-abs-paths Force absolute path names on external commands |
| 1047 | ** --exec-rel-paths Force relative path names on external commands |
| 1048 | ** -r|--from VERSION Select VERSION as source for the diff |
| 1049 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 1050 | ** -i|--internal Use internal diff logic |
| 1051 | ** --json Output formatted as JSON |
| 1052 | ** -N|--new-file Alias for --verbose |
| 1053 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -1026,10 +1026,16 @@ | |
| 1026 | ** when using an external diff program. |
| 1027 | ** |
| 1028 | ** The "--binary" option causes files matching the glob PATTERN to be treated |
| 1029 | ** as binary when considering if they should be used with external diff program. |
| 1030 | ** This option overrides the "binary-glob" setting. |
| 1031 | ** |
| 1032 | ** The "--prototype" option is specific to C/C++ source code, and only applies |
| 1033 | ** to the standard unified diff, where the enclosing function of each change |
| 1034 | ** will be shown in the chunk header; for example: |
| 1035 | ** |
| 1036 | ** @@ -2360,10 +2361,11 @@ draw_commits(struct fnc_view *view) |
| 1037 | ** |
| 1038 | ** These command show differences between managed files. Use the "fossil xdiff" |
| 1039 | ** command to see differences in unmanaged files. |
| 1040 | ** |
| 1041 | ** Options: |
| @@ -1043,10 +1049,11 @@ | |
| 1049 | ** --command PROG External diff program. Overrides "diff-command" |
| 1050 | ** -c|--context N Show N lines of context around each change |
| 1051 | ** --diff-binary BOOL Include binary files with external commands |
| 1052 | ** --exec-abs-paths Force absolute path names on external commands |
| 1053 | ** --exec-rel-paths Force relative path names on external commands |
| 1054 | ** -p|--prototype Show which C function each change is in |
| 1055 | ** -r|--from VERSION Select VERSION as source for the diff |
| 1056 | ** -w|--ignore-all-space Ignore white space when comparing lines |
| 1057 | ** -i|--internal Use internal diff logic |
| 1058 | ** --json Output formatted as JSON |
| 1059 | ** -N|--new-file Alias for --verbose |
| 1060 |