Fossil SCM
If unable to get good alignment between two diff block, try merging the current diff block with the subsequent diff block, if it is nearby.
Commit
45c91a66701d5fc8d864e75211e8d4f69ec7e88fc07b939c156c2c14a1b4f6d8
Parent
2e583d2a2ca36c1…
1 file changed
+28
+28
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -913,10 +913,14 @@ | ||
| 913 | 913 | ** |
| 914 | 914 | ** 1. Delete the next line of pLeft. |
| 915 | 915 | ** 2. Insert the next line of pRight. |
| 916 | 916 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 917 | 917 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 918 | +** | |
| 919 | +** The (4) case only happens when we cannot get a reasonable alignment between | |
| 920 | +** the two blocks. If any return value is (4), then all return values will | |
| 921 | +** be (4). | |
| 918 | 922 | ** |
| 919 | 923 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 920 | 924 | ** adding a cost to each match based on how well the two rows match |
| 921 | 925 | ** each other. Insertion and deletion costs are 50. Match costs |
| 922 | 926 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| @@ -1855,10 +1859,20 @@ | ||
| 1855 | 1859 | p->width = diff_width(diffFlags); |
| 1856 | 1860 | p->pOut = pOut; |
| 1857 | 1861 | return p; |
| 1858 | 1862 | } |
| 1859 | 1863 | /****************************************************************************/ |
| 1864 | + | |
| 1865 | +/* | |
| 1866 | +** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a | |
| 1867 | +** pair of adjacent differences. Return true if the gap between these | |
| 1868 | +** two differences is so small that they should be rendered as a single | |
| 1869 | +** edit. | |
| 1870 | +*/ | |
| 1871 | +static int smallGap(const int *R){ | |
| 1872 | + return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8; | |
| 1873 | +} | |
| 1860 | 1874 | |
| 1861 | 1875 | /* |
| 1862 | 1876 | ** Format a diff using a DiffBuilder object |
| 1863 | 1877 | */ |
| 1864 | 1878 | static void formatDiff( |
| @@ -1961,11 +1975,25 @@ | ||
| 1961 | 1975 | for(i=0; i<nr; i++){ |
| 1962 | 1976 | unsigned char *alignment; |
| 1963 | 1977 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1964 | 1978 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1965 | 1979 | |
| 1980 | + /* Try to find an alignment for the lines within this one block */ | |
| 1966 | 1981 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1982 | + | |
| 1983 | + /* If we could not get a good alignment, try merging the current | |
| 1984 | + ** block with subsequent blocks, if the subsequent blocks are | |
| 1985 | + ** nearby */ | |
| 1986 | + while( alignment[0]==4 && i<nr-1 && smallGap(&R[r+i*3]) ){ | |
| 1987 | + i++; | |
| 1988 | + m = R[r+i*3]; | |
| 1989 | + ma += R[r+i*3+1] + m; | |
| 1990 | + mb += R[r+i*3+2] + m; | |
| 1991 | + fossil_free(alignment); | |
| 1992 | + alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); | |
| 1993 | + } | |
| 1994 | + | |
| 1967 | 1995 | for(j=0; ma+mb>0; j++){ |
| 1968 | 1996 | switch( alignment[j] ){ |
| 1969 | 1997 | case 1: { |
| 1970 | 1998 | /* Delete one line from the left */ |
| 1971 | 1999 | pBuilder->xDelete(pBuilder, &A[a]); |
| 1972 | 2000 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -913,10 +913,14 @@ | |
| 913 | ** |
| 914 | ** 1. Delete the next line of pLeft. |
| 915 | ** 2. Insert the next line of pRight. |
| 916 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 917 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 918 | ** |
| 919 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 920 | ** adding a cost to each match based on how well the two rows match |
| 921 | ** each other. Insertion and deletion costs are 50. Match costs |
| 922 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| @@ -1855,10 +1859,20 @@ | |
| 1855 | p->width = diff_width(diffFlags); |
| 1856 | p->pOut = pOut; |
| 1857 | return p; |
| 1858 | } |
| 1859 | /****************************************************************************/ |
| 1860 | |
| 1861 | /* |
| 1862 | ** Format a diff using a DiffBuilder object |
| 1863 | */ |
| 1864 | static void formatDiff( |
| @@ -1961,11 +1975,25 @@ | |
| 1961 | for(i=0; i<nr; i++){ |
| 1962 | unsigned char *alignment; |
| 1963 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1964 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1965 | |
| 1966 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1967 | for(j=0; ma+mb>0; j++){ |
| 1968 | switch( alignment[j] ){ |
| 1969 | case 1: { |
| 1970 | /* Delete one line from the left */ |
| 1971 | pBuilder->xDelete(pBuilder, &A[a]); |
| 1972 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -913,10 +913,14 @@ | |
| 913 | ** |
| 914 | ** 1. Delete the next line of pLeft. |
| 915 | ** 2. Insert the next line of pRight. |
| 916 | ** 3. The next line of pLeft changes into the next line of pRight. |
| 917 | ** 4. Delete one line from pLeft and add one line to pRight. |
| 918 | ** |
| 919 | ** The (4) case only happens when we cannot get a reasonable alignment between |
| 920 | ** the two blocks. If any return value is (4), then all return values will |
| 921 | ** be (4). |
| 922 | ** |
| 923 | ** Algorithm: Wagner's minimum edit-distance algorithm, modified by |
| 924 | ** adding a cost to each match based on how well the two rows match |
| 925 | ** each other. Insertion and deletion costs are 50. Match costs |
| 926 | ** are between 0 and 100 where 0 is a perfect match 100 is a complete |
| @@ -1855,10 +1859,20 @@ | |
| 1859 | p->width = diff_width(diffFlags); |
| 1860 | p->pOut = pOut; |
| 1861 | return p; |
| 1862 | } |
| 1863 | /****************************************************************************/ |
| 1864 | |
| 1865 | /* |
| 1866 | ** R[] is an array of six integer, two COPY/DELETE/INSERT triples for a |
| 1867 | ** pair of adjacent differences. Return true if the gap between these |
| 1868 | ** two differences is so small that they should be rendered as a single |
| 1869 | ** edit. |
| 1870 | */ |
| 1871 | static int smallGap(const int *R){ |
| 1872 | return R[3]<=2 || R[3]<=(R[1]+R[2]+R[4]+R[5])/8; |
| 1873 | } |
| 1874 | |
| 1875 | /* |
| 1876 | ** Format a diff using a DiffBuilder object |
| 1877 | */ |
| 1878 | static void formatDiff( |
| @@ -1961,11 +1975,25 @@ | |
| 1975 | for(i=0; i<nr; i++){ |
| 1976 | unsigned char *alignment; |
| 1977 | ma = R[r+i*3+1]; /* Lines on left but not on right */ |
| 1978 | mb = R[r+i*3+2]; /* Lines on right but not on left */ |
| 1979 | |
| 1980 | /* Try to find an alignment for the lines within this one block */ |
| 1981 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1982 | |
| 1983 | /* If we could not get a good alignment, try merging the current |
| 1984 | ** block with subsequent blocks, if the subsequent blocks are |
| 1985 | ** nearby */ |
| 1986 | while( alignment[0]==4 && i<nr-1 && smallGap(&R[r+i*3]) ){ |
| 1987 | i++; |
| 1988 | m = R[r+i*3]; |
| 1989 | ma += R[r+i*3+1] + m; |
| 1990 | mb += R[r+i*3+2] + m; |
| 1991 | fossil_free(alignment); |
| 1992 | alignment = diffBlockAlignment(&A[a], ma, &B[b], mb, diffFlags); |
| 1993 | } |
| 1994 | |
| 1995 | for(j=0; ma+mb>0; j++){ |
| 1996 | switch( alignment[j] ){ |
| 1997 | case 1: { |
| 1998 | /* Delete one line from the left */ |
| 1999 | pBuilder->xDelete(pBuilder, &A[a]); |
| 2000 |