Fossil SCM

Add the experimental JSON diff output format.

drh 2021-08-30 15:03 diff-color-enhancements
Commit 5d759da71116fbad713f71f52bf8093541889f7a8fcd6c0958697e24c7ebb3ad
1 file changed +82 -2
+82 -2
--- src/diff.c
+++ src/diff.c
@@ -44,12 +44,13 @@
4444
#define DIFF_NOTTOOBIG (((u64)0x08)<<32) /* Only display if not too big */
4545
#define DIFF_STRIP_EOLCR (((u64)0x10)<<32) /* Strip trailing CR */
4646
#define DIFF_SLOW_SBS (((u64)0x20)<<32) /* Better but slower side-by-side */
4747
#define DIFF_WEBPAGE (((u64)0x00040)<<32) /* Complete webpage */
4848
#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 */
5152
5253
/*
5354
** These error messages are shared in multiple locations. They are defined
5455
** here for consistency.
5556
*/
@@ -1719,10 +1720,82 @@
17191720
p->xEnd = dfdebugEnd;
17201721
p->lnLeft = p->lnRight = 0;
17211722
p->pOut = pOut;
17221723
return p;
17231724
}
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
+}
17241797
/****************************************************************************/
17251798
17261799
/*
17271800
** Format a diff using a DiffBuilder object
17281801
*/
@@ -2441,10 +2514,14 @@
24412514
unsigned int r;
24422515
for(r=0; R[r] || R[r+1] || R[r+2]; r += 3){
24432516
blob_appendf(pOut, " copy %6d delete %6d insert %6d\n",
24442517
R[r], R[r+1], R[r+2]);
24452518
}
2519
+ }else if( diffFlags & DIFF_JSON ){
2520
+ DiffBuilder *pBuilder = dfjsonNew(pOut);
2521
+ formatDiff(&c, pRe, diffFlags, pBuilder);
2522
+ blob_append_char(pOut, '\n');
24462523
}else if( diffFlags & DIFF_SIDEBYSIDE ){
24472524
sbsDiff(&c, pOut, pRe, diffFlags);
24482525
}else if( diffFlags & DIFF_DEBUG ){
24492526
DiffBuilder *pBuilder = dfdebugNew(pOut);
24502527
formatDiff(&c, pRe, diffFlags, pBuilder);
@@ -2523,10 +2600,13 @@
25232600
diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER;
25242601
}
25252602
if( find_option("by",0,0)!=0 ){
25262603
diffFlags |= DIFF_HTML|DIFF_WEBPAGE|DIFF_LINENO|DIFF_BROWSER
25272604
|DIFF_SIDEBYSIDE;
2605
+ }
2606
+ if( find_option("json",0,0)!=0 ){
2607
+ diffFlags |= DIFF_JSON;
25282608
}
25292609
25302610
/* Undocumented and unsupported flags used for development
25312611
** debugging and analysis: */
25322612
if( find_option("debug",0,0)!=0 ) diffFlags |= DIFF_DEBUG;
25332613
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button