Fossil SCM
Add the experimental JSON diff output format.
Commit
5d759da71116fbad713f71f52bf8093541889f7a8fcd6c0958697e24c7ebb3ad
Parent
9191ea9e63d1697…
1 file changed
+82
-2
+82
-2
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -44,12 +44,13 @@ | ||
| 44 | 44 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | 45 | #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ |
| 46 | 46 | #define DIFF_SLOW_SBS (((u64)0x20)<<32) /* Better but slower side-by-side */ |
| 47 | 47 | #define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */ |
| 48 | 48 | #define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */ |
| 49 | -#define DIFF_DEBUG (((u64)0x00100)<<32) /* Debugging diff output */ | |
| 50 | -#define DIFF_RAW (((u64)0x00200)<<32) /* Raw triples - for debugging */ | |
| 49 | +#define DIFF_JSON (((u64)0x00100)<<32) /* JSON output */ | |
| 50 | +#define DIFF_DEBUG (((u64)0x00200)<<32) /* Debugging diff output */ | |
| 51 | +#define DIFF_RAW (((u64)0x00400)<<32) /* Raw triples - for debugging */ | |
| 51 | 52 | |
| 52 | 53 | /* |
| 53 | 54 | ** These error messages are shared in multiple locations. They are defined |
| 54 | 55 | ** here for consistency. |
| 55 | 56 | */ |
| @@ -1719,10 +1720,82 @@ | ||
| 1719 | 1720 | p->xEnd = dfdebugEnd; |
| 1720 | 1721 | p->lnLeft = p->lnRight = 0; |
| 1721 | 1722 | p->pOut = pOut; |
| 1722 | 1723 | return p; |
| 1723 | 1724 | } |
| 1725 | + | |
| 1726 | +/************************* DiffBuilderJson ********************************/ | |
| 1727 | +static void dfjsonSkip(DiffBuilder *p, unsigned int n){ | |
| 1728 | + blob_appendf(p->pOut, "1,%u,\n", n); | |
| 1729 | +} | |
| 1730 | +static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){ | |
| 1731 | + blob_append(p->pOut, "2,\"",3); | |
| 1732 | + htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); | |
| 1733 | + blob_append(p->pOut, "\",\n",3); | |
| 1734 | +} | |
| 1735 | +static void dfjsonInsert(DiffBuilder *p, const DLine *pLine){ | |
| 1736 | + blob_append(p->pOut, "3,\"",3); | |
| 1737 | + htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); | |
| 1738 | + blob_append(p->pOut, "\",\n",3); | |
| 1739 | +} | |
| 1740 | +static void dfjsonDelete(DiffBuilder *p, const DLine *pLine){ | |
| 1741 | + blob_append(p->pOut, "4,\"",3); | |
| 1742 | + htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); | |
| 1743 | + blob_append(p->pOut, "\",\n",3); | |
| 1744 | +} | |
| 1745 | +static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ | |
| 1746 | + int i; | |
| 1747 | + int x; | |
| 1748 | + ChangeSpan span; | |
| 1749 | + oneLineChange(pX, pY, &span); | |
| 1750 | + blob_appendf(p->pOut, "5,\""); | |
| 1751 | + for(i=x=0; i<span.n; i++){ | |
| 1752 | + int ofst = span.a[i].iStart1; | |
| 1753 | + int len = span.a[i].iLen1; | |
| 1754 | + if( len ){ | |
| 1755 | + htmlize_to_blob(p->pOut, pX->z+x, ofst - x); | |
| 1756 | + x += ofst; | |
| 1757 | + blob_append(p->pOut, "<mark>", 6); | |
| 1758 | + htmlize_to_blob(p->pOut, pX->z+x, len); | |
| 1759 | + x += len; | |
| 1760 | + blob_append(p->pOut, "</mark>", 7); | |
| 1761 | + } | |
| 1762 | + } | |
| 1763 | + if( x<pX->n ) htmlize_to_blob(p->pOut, pX->z+x, pX->n - x); | |
| 1764 | + blob_append(p->pOut, "\",\n \"", -1); | |
| 1765 | + for(i=x=0; i<span.n; i++){ | |
| 1766 | + int ofst = span.a[i].iStart2; | |
| 1767 | + int len = span.a[i].iLen2; | |
| 1768 | + if( len ){ | |
| 1769 | + htmlize_to_blob(p->pOut, pY->z+x, ofst - x); | |
| 1770 | + x += ofst; | |
| 1771 | + blob_append(p->pOut, "<mark>", 6); | |
| 1772 | + htmlize_to_blob(p->pOut, pY->z+x, len); | |
| 1773 | + x += len; | |
| 1774 | + blob_append(p->pOut, "</mark>", 7); | |
| 1775 | + } | |
| 1776 | + } | |
| 1777 | + if( x<pY->n ) htmlize_to_blob(p->pOut, pY->z+x, pY->n - x); | |
| 1778 | + blob_append(p->pOut, "\"\n,", -1); | |
| 1779 | +} | |
| 1780 | +static void dfjsonEnd(DiffBuilder *p){ | |
| 1781 | + blob_append(p->pOut, "0]", 2); | |
| 1782 | + fossil_free(p); | |
| 1783 | +} | |
| 1784 | +static DiffBuilder *dfjsonNew(Blob *pOut){ | |
| 1785 | + DiffBuilder *p = fossil_malloc(sizeof(*p)); | |
| 1786 | + p->xSkip = dfjsonSkip; | |
| 1787 | + p->xCommon = dfjsonCommon; | |
| 1788 | + p->xInsert = dfjsonInsert; | |
| 1789 | + p->xDelete = dfjsonDelete; | |
| 1790 | + p->xEdit = dfjsonEdit; | |
| 1791 | + p->xEnd = dfjsonEnd; | |
| 1792 | + p->lnLeft = p->lnRight = 0; | |
| 1793 | + p->pOut = pOut; | |
| 1794 | + blob_append_char(pOut, '['); | |
| 1795 | + return p; | |
| 1796 | +} | |
| 1724 | 1797 | /****************************************************************************/ |
| 1725 | 1798 | |
| 1726 | 1799 | /* |
| 1727 | 1800 | ** Format a diff using a DiffBuilder object |
| 1728 | 1801 | */ |
| @@ -2441,10 +2514,14 @@ | ||
| 2441 | 2514 | unsigned int r; |
| 2442 | 2515 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 2443 | 2516 | blob_appendf(pOut, " copy %6d delete %6d insert %6d\n", |
| 2444 | 2517 | R[r], R[r+1], R[r+2]); |
| 2445 | 2518 | } |
| 2519 | + }else if( diffFlags & DIFF_JSON ){ | |
| 2520 | + DiffBuilder *pBuilder = dfjsonNew(pOut); | |
| 2521 | + formatDiff(&c, pRe, diffFlags, pBuilder); | |
| 2522 | + blob_append_char(pOut, '\n'); | |
| 2446 | 2523 | }else if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 2447 | 2524 | sbsDiff(&c, pOut, pRe, diffFlags); |
| 2448 | 2525 | }else if( diffFlags & DIFF_DEBUG ){ |
| 2449 | 2526 | DiffBuilder *pBuilder = dfdebugNew(pOut); |
| 2450 | 2527 | formatDiff(&c, pRe, diffFlags, pBuilder); |
| @@ -2523,10 +2600,13 @@ | ||
| 2523 | 2600 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER; |
| 2524 | 2601 | } |
| 2525 | 2602 | if( find_option("by",0,0)!=0 ){ |
| 2526 | 2603 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER |
| 2527 | 2604 | |DIFF_SIDEBYSIDE; |
| 2605 | + } | |
| 2606 | + if( find_option("json",0,0)!=0 ){ | |
| 2607 | + diffFlags |= DIFF_JSON; | |
| 2528 | 2608 | } |
| 2529 | 2609 | |
| 2530 | 2610 | /* Undocumented and unsupported flags used for development |
| 2531 | 2611 | ** debugging and analysis: */ |
| 2532 | 2612 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 2533 | 2613 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -44,12 +44,13 @@ | |
| 44 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ |
| 46 | #define DIFF_SLOW_SBS (((u64)0x20)<<32) /* Better but slower side-by-side */ |
| 47 | #define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */ |
| 48 | #define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */ |
| 49 | #define DIFF_DEBUG (((u64)0x00100)<<32) /* Debugging diff output */ |
| 50 | #define DIFF_RAW (((u64)0x00200)<<32) /* Raw triples - for debugging */ |
| 51 | |
| 52 | /* |
| 53 | ** These error messages are shared in multiple locations. They are defined |
| 54 | ** here for consistency. |
| 55 | */ |
| @@ -1719,10 +1720,82 @@ | |
| 1719 | p->xEnd = dfdebugEnd; |
| 1720 | p->lnLeft = p->lnRight = 0; |
| 1721 | p->pOut = pOut; |
| 1722 | return p; |
| 1723 | } |
| 1724 | /****************************************************************************/ |
| 1725 | |
| 1726 | /* |
| 1727 | ** Format a diff using a DiffBuilder object |
| 1728 | */ |
| @@ -2441,10 +2514,14 @@ | |
| 2441 | unsigned int r; |
| 2442 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 2443 | blob_appendf(pOut, " copy %6d delete %6d insert %6d\n", |
| 2444 | R[r], R[r+1], R[r+2]); |
| 2445 | } |
| 2446 | }else if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 2447 | sbsDiff(&c, pOut, pRe, diffFlags); |
| 2448 | }else if( diffFlags & DIFF_DEBUG ){ |
| 2449 | DiffBuilder *pBuilder = dfdebugNew(pOut); |
| 2450 | formatDiff(&c, pRe, diffFlags, pBuilder); |
| @@ -2523,10 +2600,13 @@ | |
| 2523 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER; |
| 2524 | } |
| 2525 | if( find_option("by",0,0)!=0 ){ |
| 2526 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER |
| 2527 | |DIFF_SIDEBYSIDE; |
| 2528 | } |
| 2529 | |
| 2530 | /* Undocumented and unsupported flags used for development |
| 2531 | ** debugging and analysis: */ |
| 2532 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 2533 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -44,12 +44,13 @@ | |
| 44 | #define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */ |
| 45 | #define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */ |
| 46 | #define DIFF_SLOW_SBS (((u64)0x20)<<32) /* Better but slower side-by-side */ |
| 47 | #define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */ |
| 48 | #define DIFF_BROWSER (((u64)0x00080)<<32) /* The --browser option */ |
| 49 | #define DIFF_JSON (((u64)0x00100)<<32) /* JSON output */ |
| 50 | #define DIFF_DEBUG (((u64)0x00200)<<32) /* Debugging diff output */ |
| 51 | #define DIFF_RAW (((u64)0x00400)<<32) /* Raw triples - for debugging */ |
| 52 | |
| 53 | /* |
| 54 | ** These error messages are shared in multiple locations. They are defined |
| 55 | ** here for consistency. |
| 56 | */ |
| @@ -1719,10 +1720,82 @@ | |
| 1720 | p->xEnd = dfdebugEnd; |
| 1721 | p->lnLeft = p->lnRight = 0; |
| 1722 | p->pOut = pOut; |
| 1723 | return p; |
| 1724 | } |
| 1725 | |
| 1726 | /************************* DiffBuilderJson ********************************/ |
| 1727 | static void dfjsonSkip(DiffBuilder *p, unsigned int n){ |
| 1728 | blob_appendf(p->pOut, "1,%u,\n", n); |
| 1729 | } |
| 1730 | static void dfjsonCommon(DiffBuilder *p, const DLine *pLine){ |
| 1731 | blob_append(p->pOut, "2,\"",3); |
| 1732 | htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); |
| 1733 | blob_append(p->pOut, "\",\n",3); |
| 1734 | } |
| 1735 | static void dfjsonInsert(DiffBuilder *p, const DLine *pLine){ |
| 1736 | blob_append(p->pOut, "3,\"",3); |
| 1737 | htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); |
| 1738 | blob_append(p->pOut, "\",\n",3); |
| 1739 | } |
| 1740 | static void dfjsonDelete(DiffBuilder *p, const DLine *pLine){ |
| 1741 | blob_append(p->pOut, "4,\"",3); |
| 1742 | htmlize_to_blob(p->pOut, pLine->z, (int)pLine->n); |
| 1743 | blob_append(p->pOut, "\",\n",3); |
| 1744 | } |
| 1745 | static void dfjsonEdit(DiffBuilder *p, const DLine *pX, const DLine *pY){ |
| 1746 | int i; |
| 1747 | int x; |
| 1748 | ChangeSpan span; |
| 1749 | oneLineChange(pX, pY, &span); |
| 1750 | blob_appendf(p->pOut, "5,\""); |
| 1751 | for(i=x=0; i<span.n; i++){ |
| 1752 | int ofst = span.a[i].iStart1; |
| 1753 | int len = span.a[i].iLen1; |
| 1754 | if( len ){ |
| 1755 | htmlize_to_blob(p->pOut, pX->z+x, ofst - x); |
| 1756 | x += ofst; |
| 1757 | blob_append(p->pOut, "<mark>", 6); |
| 1758 | htmlize_to_blob(p->pOut, pX->z+x, len); |
| 1759 | x += len; |
| 1760 | blob_append(p->pOut, "</mark>", 7); |
| 1761 | } |
| 1762 | } |
| 1763 | if( x<pX->n ) htmlize_to_blob(p->pOut, pX->z+x, pX->n - x); |
| 1764 | blob_append(p->pOut, "\",\n \"", -1); |
| 1765 | for(i=x=0; i<span.n; i++){ |
| 1766 | int ofst = span.a[i].iStart2; |
| 1767 | int len = span.a[i].iLen2; |
| 1768 | if( len ){ |
| 1769 | htmlize_to_blob(p->pOut, pY->z+x, ofst - x); |
| 1770 | x += ofst; |
| 1771 | blob_append(p->pOut, "<mark>", 6); |
| 1772 | htmlize_to_blob(p->pOut, pY->z+x, len); |
| 1773 | x += len; |
| 1774 | blob_append(p->pOut, "</mark>", 7); |
| 1775 | } |
| 1776 | } |
| 1777 | if( x<pY->n ) htmlize_to_blob(p->pOut, pY->z+x, pY->n - x); |
| 1778 | blob_append(p->pOut, "\"\n,", -1); |
| 1779 | } |
| 1780 | static void dfjsonEnd(DiffBuilder *p){ |
| 1781 | blob_append(p->pOut, "0]", 2); |
| 1782 | fossil_free(p); |
| 1783 | } |
| 1784 | static DiffBuilder *dfjsonNew(Blob *pOut){ |
| 1785 | DiffBuilder *p = fossil_malloc(sizeof(*p)); |
| 1786 | p->xSkip = dfjsonSkip; |
| 1787 | p->xCommon = dfjsonCommon; |
| 1788 | p->xInsert = dfjsonInsert; |
| 1789 | p->xDelete = dfjsonDelete; |
| 1790 | p->xEdit = dfjsonEdit; |
| 1791 | p->xEnd = dfjsonEnd; |
| 1792 | p->lnLeft = p->lnRight = 0; |
| 1793 | p->pOut = pOut; |
| 1794 | blob_append_char(pOut, '['); |
| 1795 | return p; |
| 1796 | } |
| 1797 | /****************************************************************************/ |
| 1798 | |
| 1799 | /* |
| 1800 | ** Format a diff using a DiffBuilder object |
| 1801 | */ |
| @@ -2441,10 +2514,14 @@ | |
| 2514 | unsigned int r; |
| 2515 | for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){ |
| 2516 | blob_appendf(pOut, " copy %6d delete %6d insert %6d\n", |
| 2517 | R[r], R[r+1], R[r+2]); |
| 2518 | } |
| 2519 | }else if( diffFlags & DIFF_JSON ){ |
| 2520 | DiffBuilder *pBuilder = dfjsonNew(pOut); |
| 2521 | formatDiff(&c, pRe, diffFlags, pBuilder); |
| 2522 | blob_append_char(pOut, '\n'); |
| 2523 | }else if( diffFlags & DIFF_SIDEBYSIDE ){ |
| 2524 | sbsDiff(&c, pOut, pRe, diffFlags); |
| 2525 | }else if( diffFlags & DIFF_DEBUG ){ |
| 2526 | DiffBuilder *pBuilder = dfdebugNew(pOut); |
| 2527 | formatDiff(&c, pRe, diffFlags, pBuilder); |
| @@ -2523,10 +2600,13 @@ | |
| 2600 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER; |
| 2601 | } |
| 2602 | if( find_option("by",0,0)!=0 ){ |
| 2603 | diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER |
| 2604 | |DIFF_SIDEBYSIDE; |
| 2605 | } |
| 2606 | if( find_option("json",0,0)!=0 ){ |
| 2607 | diffFlags |= DIFF_JSON; |
| 2608 | } |
| 2609 | |
| 2610 | /* Undocumented and unsupported flags used for development |
| 2611 | ** debugging and analysis: */ |
| 2612 | if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG; |
| 2613 |