Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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. [closed: feature rejected] |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | diff-show-func |
Files: | files | file ages | folders |
SHA3-256: |
792674372e7d6a8e70552e991163f61c |
User & Date: | jamsek 2022-01-16 10:09:35 |
Original Comment: | 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. |
Context
2022-01-16
| ||
10:09 |
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. [closed: feature rejected] ... (Closed-Leaf check-in: 79267437 user: jamsek tags: diff-show-func) | |
02:03 | When reading POST via TLS, fail fatally on a read error. Add SERVER_SOFTWARE to the environment when running in server mode. ... (check-in: ba95498d user: stephan tags: trunk) | |
Changes
Changes to src/diff.c.
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #define DIFF_WEBPAGE 0x00004000 /* Complete webpage */ #define DIFF_BROWSER 0x00008000 /* The --browser option */ #define DIFF_JSON 0x00010000 /* JSON output */ #define DIFF_DEBUG 0x00020000 /* Debugging diff output */ #define DIFF_RAW 0x00040000 /* Raw triples - for debugging */ #define DIFF_TCL 0x00080000 /* For the --tk option */ #define DIFF_INCBINARY 0x00100000 /* The --diff-binary option */ /* ** These error messages are shared in multiple locations. They are defined ** here for consistency. */ #define DIFF_CANNOT_COMPUTE_BINARY \ "cannot compute difference between binary files\n" | > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #define DIFF_WEBPAGE 0x00004000 /* Complete webpage */ #define DIFF_BROWSER 0x00008000 /* The --browser option */ #define DIFF_JSON 0x00010000 /* JSON output */ #define DIFF_DEBUG 0x00020000 /* Debugging diff output */ #define DIFF_RAW 0x00040000 /* Raw triples - for debugging */ #define DIFF_TCL 0x00080000 /* For the --tk option */ #define DIFF_INCBINARY 0x00100000 /* The --diff-binary option */ #define DIFF_PROTOTYPE 0x00200000 /* Function prototype in chunk head */ /* ** These error messages are shared in multiple locations. They are defined ** here for consistency. */ #define DIFF_CANNOT_COMPUTE_BINARY \ "cannot compute difference between binary files\n" |
︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 | int nContext; /* Number of lines of context */ int wColumn; /* Column width in -y mode */ u32 nFile; /* Number of files diffed so far */ const char *zDiffCmd; /* External diff command to use instead of builtin */ const char *zBinGlob; /* GLOB pattern for binary files */ ReCompiled *pRe; /* Show only changes matching this pattern */ const char *zLeftHash; /* HASH-id of the left file */ }; #endif /* INTERFACE */ /* ** Initialize memory for a DiffConfig based on just a diffFlags integer. */ | > > > > > > > > > > > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | int nContext; /* Number of lines of context */ int wColumn; /* Column width in -y mode */ u32 nFile; /* Number of files diffed so far */ const char *zDiffCmd; /* External diff command to use instead of builtin */ const char *zBinGlob; /* GLOB pattern for binary files */ ReCompiled *pRe; /* Show only changes matching this pattern */ const char *zLeftHash; /* HASH-id of the left file */ struct { /* * DIFF_PROTOTYPE (fossil diff -p|--prototype) data types for matching * each chunk change in the diff to it's enclosing function. */ const Blob *pFileLHS; /* Pointer to "from" file content */ char *zSignature; /* Enclosing function signature */ uint32_t iLastMatch; /* Line index of the last function match */ uint32_t iLastLine; /* Starting line index of the last chunk scanned */ size_t iOffset; /* Byte offset into pFileLHS->aData of iLastMatch */ } proto; }; #endif /* INTERFACE */ /* ** Initialize memory for a DiffConfig based on just a diffFlags integer. */ |
︙ | ︙ | |||
360 361 362 363 364 365 366 367 368 369 370 371 372 373 | } if( lnB>0 ){ blob_appendf(pOut, "%6d ", lnB); }else{ blob_append(pOut, " ", 8); } } /* ** Output a patch-style text diff. */ static void contextDiff( DContext *p, /* The difference */ Blob *pOut, /* Output a context diff to here */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 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 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | } if( lnB>0 ){ blob_appendf(pOut, "%6d ", lnB); }else{ blob_append(pOut, " ", 8); } } /* ** Starting from iSeek lines, copy n lines from pSrc to pDest. The seek starts ** from iOffset bytes into pSrc->aData. This routine does _not_ modify pSrc. */ static void blob_copy_lines_from( Blob * const pDest, /* Destination blob */ const Blob * const pSrc, /* Source blob from which to copy line(s) */ size_t *iOffset, /* Begin seek from this byte offset */ size_t iSeek, /* Skip this many lines before copying */ size_t n /* Copy this many lines */ ){ const char *z = (const char *)pSrc->aData; size_t idx = *iOffset, ln = 0, start = 0; if( n==0 ){ return; } while( idx<pSrc->nUsed ){ if( z[idx]=='\n' ){ if( ++ln==iSeek ){ start = idx + 1; /* skip '\n' */ } if( ln==iSeek + n ){ ++idx; break; } } ++idx; } if( pDest ){ blob_append(pDest, &pSrc->aData[start], idx - start - 1); /* trim '\n' */ } *iOffset = start; return; } #define starts_with(_str, _pfx) (fossil_strncmp(_str, _pfx, sizeof(_pfx)-1)==0) /* * Scan the diffed file from the line preceding the start of the current chunk * for the enclosing function in which the change resides. Return first match. */ static char * matchChunkFunction( DiffConfig *const pCfg, /* Diff config options */ uint32_t iPos /* Line position in file from which to start scan */ ){ Blob pBuf; /* Matching function prototype */ const char *zLine; /* Text of line being scanned */ char *zSpec = NULL; /* Access specifier: private, protected, public */ size_t iOffset; /* Byte offset to the last matching line */ uint32_t iLast; /* Line index to start of the last chunk matched */ blob_zero(&pBuf); iLast = pCfg->proto.iLastLine; pCfg->proto.iLastLine = iPos; iOffset = pCfg->proto.iOffset; /* Begin seeking from last match */ /* Scan backwards from the line immediately preceding this chunk. */ while( iPos > 1 && iPos > iLast ){ blob_copy_lines_from(&pBuf, pCfg->proto.pFileLHS, &iOffset, iPos - pCfg->proto.iLastMatch, 1); zLine = blob_str(&pBuf); if ( zLine ){ /* * GNU C and MSVC allow '$' in identifier names. * https://gcc.gnu.org/onlinedocs/gcc/Dollar-Signs.html * https://docs.microsoft.com/en-us/cpp/cpp/identifiers-cpp */ if( fossil_isalpha(zLine[0]) || zLine[0] == '_' || zLine[0] == '$' ){ if( starts_with(zLine, "private:") ){ if( !zSpec ){ zSpec = " (private)"; } }else if( starts_with(zLine, "protected:") ){ if( !zSpec ){ zSpec = " (protected)"; } }else if( starts_with(zLine, "public:") ){ if( !zSpec ){ zSpec = " (public)"; } }else{ /* Don't exceed 80 cols: chunk header consumes ~25, cap sig at 55. */ char *zSig = mprintf("%s%s", zLine, zSpec ? zSpec : ""); fossil_free(pCfg->proto.zSignature); pCfg->proto.zSignature = mprintf("%.55s", zSig); /* * It's expensive to seek from the beginning of the file when diffing * large files, so record byte offset and line index of this match. */ pCfg->proto.iLastMatch = iPos; pCfg->proto.iOffset = iOffset; fossil_free(zSig); blob_reset(&pBuf); return pCfg->proto.zSignature; } } } iOffset = pCfg->proto.iOffset; /* No match, revert offset to previous */ blob_reset(&pBuf); --iPos; } return pCfg->proto.iLastMatch > 0 ? pCfg->proto.zSignature : NULL; } /* ** Output a patch-style text diff. */ static void contextDiff( DContext *p, /* The difference */ Blob *pOut, /* Output a context diff to here */ |
︙ | ︙ | |||
445 446 447 448 449 450 451 452 453 454 455 456 457 458 | * If the patch changes an empty file or results in an empty file, * the block header must use 0,0 as position indicator and not 1,0. * Otherwise, patch would be confused and may reject the diff. */ blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", na ? a+skip+1 : a+skip, na, nb ? b+skip+1 : b+skip, nb); blob_append(pOut, "\n", 1); } /* Show the initial common area */ a += skip; b += skip; m = R[r] - skip; | > > > > > > | 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | * If the patch changes an empty file or results in an empty file, * the block header must use 0,0 as position indicator and not 1,0. * Otherwise, patch would be confused and may reject the diff. */ blob_appendf(pOut,"@@ -%d,%d +%d,%d @@", na ? a+skip+1 : a+skip, na, nb ? b+skip+1 : b+skip, nb); if((DIFF_PROTOTYPE & pCfg->diffFlags) && a+skip > 1) { char *f = matchChunkFunction(pCfg, (a+skip) - 1); if( f != NULL ){ blob_appendf(pOut, " %s", f); } } blob_append(pOut, "\n", 1); } /* Show the initial common area */ a += skip; b += skip; m = R[r] - skip; |
︙ | ︙ | |||
493 494 495 496 497 498 499 500 501 502 503 504 505 506 | m = R[r+nr*3]; if( m>nContext ) m = nContext; for(j=0; j<m; j++){ if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1); appendDiffLine(pOut, ' ', &A[a+j]); } } } #define MX_CSN 8 /* Maximum number of change spans across a change region */ /* ** A description of zero or more (up to MX_CSN) areas of difference ** between two lines of text. | > | 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | m = R[r+nr*3]; if( m>nContext ) m = nContext; for(j=0; j<m; j++){ if( showLn ) appendDiffLineno(pOut, a+j+1, b+j+1); appendDiffLine(pOut, ' ', &A[a+j]); } } fossil_free(pCfg->proto.zSignature); } #define MX_CSN 8 /* Maximum number of change spans across a change region */ /* ** A description of zero or more (up to MX_CSN) areas of difference ** between two lines of text. |
︙ | ︙ | |||
2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 | Blob *pB_Blob, /* TO file */ Blob *pOut, /* Write diff here if not NULL */ DiffConfig *pCfg /* Configuration options */ ){ int ignoreWs; /* Ignore whitespace */ DContext c; if( pCfg->diffFlags & DIFF_INVERT ){ Blob *pTemp = pA_Blob; pA_Blob = pB_Blob; pB_Blob = pTemp; } ignoreWs = (pCfg->diffFlags & DIFF_IGNORE_ALLWS)!=0; blob_to_utf8_no_bom(pA_Blob, 0); | > > > > | 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 | Blob *pB_Blob, /* TO file */ Blob *pOut, /* Write diff here if not NULL */ DiffConfig *pCfg /* Configuration options */ ){ int ignoreWs; /* Ignore whitespace */ DContext c; if( pCfg->diffFlags & DIFF_PROTOTYPE ){ memset(&pCfg->proto, 0, sizeof(pCfg->proto)); pCfg->proto.pFileLHS = pA_Blob; } if( pCfg->diffFlags & DIFF_INVERT ){ Blob *pTemp = pA_Blob; pA_Blob = pB_Blob; pB_Blob = pTemp; } ignoreWs = (pCfg->diffFlags & DIFF_IGNORE_ALLWS)!=0; blob_to_utf8_no_bom(pA_Blob, 0); |
︙ | ︙ | |||
2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 | ** --brief Show filenames only DIFF_BRIEF ** -c|--context N N lines of context. nContext ** --html Format for HTML DIFF_HTML ** --invert Invert the diff DIFF_INVERT ** -n|--linenum Show line numbers DIFF_LINENO ** --noopt Disable optimization DIFF_NOOPT ** --numstat Show change counts DIFF_NUMSTAT ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR ** --unified Unified diff. ~DIFF_SIDEBYSIDE ** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS ** -W|--width N N character lines. wColumn ** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE ** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS */ void diff_options(DiffConfig *pCfg, int isGDiff, int bUnifiedTextOnly){ u64 diffFlags = 0; const char *z; int f; memset(pCfg, 0, sizeof(*pCfg)); if( find_option("ignore-trailing-space","Z",0)!=0 ){ diffFlags = DIFF_IGNORE_EOLWS; } if( find_option("ignore-all-space","w",0)!=0 ){ diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ } if( find_option("strip-trailing-cr",0,0)!=0 ){ diffFlags |= DIFF_STRIP_EOLCR; } if( !bUnifiedTextOnly ){ if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; if( find_option("yy",0,0)!=0 ){ | > > > > | 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 | ** --brief Show filenames only DIFF_BRIEF ** -c|--context N N lines of context. nContext ** --html Format for HTML DIFF_HTML ** --invert Invert the diff DIFF_INVERT ** -n|--linenum Show line numbers DIFF_LINENO ** --noopt Disable optimization DIFF_NOOPT ** --numstat Show change counts DIFF_NUMSTAT ** -p|--prototype Show enclosing function DIFF_PROTOTYPE ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR ** --unified Unified diff. ~DIFF_SIDEBYSIDE ** -w|--ignore-all-space Ignore all whitespaces DIFF_IGNORE_ALLWS ** -W|--width N N character lines. wColumn ** -y|--side-by-side Side-by-side diff. DIFF_SIDEBYSIDE ** -Z|--ignore-trailing-space Ignore eol-whitespaces DIFF_IGNORE_EOLWS */ void diff_options(DiffConfig *pCfg, int isGDiff, int bUnifiedTextOnly){ u64 diffFlags = 0; const char *z; int f; memset(pCfg, 0, sizeof(*pCfg)); if( find_option("ignore-trailing-space","Z",0)!=0 ){ diffFlags = DIFF_IGNORE_EOLWS; } if( find_option("ignore-all-space","w",0)!=0 ){ diffFlags = DIFF_IGNORE_ALLWS; /* stronger than DIFF_IGNORE_EOLWS */ } if( find_option("prototype","p",0)!=0 ){ diffFlags = DIFF_PROTOTYPE; } if( find_option("strip-trailing-cr",0,0)!=0 ){ diffFlags |= DIFF_STRIP_EOLCR; } if( !bUnifiedTextOnly ){ if( find_option("side-by-side","y",0)!=0 ) diffFlags |= DIFF_SIDEBYSIDE; if( find_option("yy",0,0)!=0 ){ |
︙ | ︙ |
Changes to src/diffcmd.c.
︙ | ︙ | |||
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 | ** ** The "--diff-binary" option enables or disables the inclusion of binary files ** when using an external diff program. ** ** The "--binary" option causes files matching the glob PATTERN to be treated ** as binary when considering if they should be used with external diff program. ** This option overrides the "binary-glob" setting. ** ** These command show differences between managed files. Use the "fossil xdiff" ** command to see differences in unmanaged files. ** ** Options: ** --binary PATTERN Treat files that match the glob PATTERN ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" ** --checkin VERSION Show diff of all changes in VERSION ** --command PROG External diff program. Overrides "diff-command" ** -c|--context N Show N lines of context around each change ** --diff-binary BOOL Include binary files with external commands ** --exec-abs-paths Force absolute path names on external commands ** --exec-rel-paths Force relative path names on external commands ** -r|--from VERSION Select VERSION as source for the diff ** -w|--ignore-all-space Ignore white space when comparing lines ** -i|--internal Use internal diff logic ** --json Output formatted as JSON ** -N|--new-file Alias for --verbose ** --numstat Show only the number of lines delete and added ** -y|--side-by-side Side-by-side diff | > > > > > > > | 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 | ** ** The "--diff-binary" option enables or disables the inclusion of binary files ** when using an external diff program. ** ** The "--binary" option causes files matching the glob PATTERN to be treated ** as binary when considering if they should be used with external diff program. ** This option overrides the "binary-glob" setting. ** ** The "--prototype" option is specific to C/C++ source code, and only applies ** to the standard unified diff, where the enclosing function of each change ** will be shown in the chunk header; for example: ** ** @@ -2360,10 +2361,11 @@ draw_commits(struct fnc_view *view) ** ** These command show differences between managed files. Use the "fossil xdiff" ** command to see differences in unmanaged files. ** ** Options: ** --binary PATTERN Treat files that match the glob PATTERN ** as binary ** --branch BRANCH Show diff of all changes on BRANCH ** --brief Show filenames only ** -b|--browser Show the diff output in a web-browser ** --by Shorthand for "--browser -y" ** --checkin VERSION Show diff of all changes in VERSION ** --command PROG External diff program. Overrides "diff-command" ** -c|--context N Show N lines of context around each change ** --diff-binary BOOL Include binary files with external commands ** --exec-abs-paths Force absolute path names on external commands ** --exec-rel-paths Force relative path names on external commands ** -p|--prototype Show which C function each change is in ** -r|--from VERSION Select VERSION as source for the diff ** -w|--ignore-all-space Ignore white space when comparing lines ** -i|--internal Use internal diff logic ** --json Output formatted as JSON ** -N|--new-file Alias for --verbose ** --numstat Show only the number of lines delete and added ** -y|--side-by-side Side-by-side diff |
︙ | ︙ |