Fossil SCM
merge trunk. <p>simplify utf-8 continuation byte checking, using a loop in stead of separater 2/3/4-byte versions.
Commit
2f7ac60f78e68d1e20e4f79d2d9b68097e0d2200
Parent
879012769b2dfc2…
13 files changed
+1
-1
+18
-25
+18
-25
+12
-9
+44
-37
+6
+1
-1
+1
+25
-17
+1
-1
+19
-8
+44
+44
+1
-1
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -800,11 +800,11 @@ | ||
| 800 | 800 | ** The if stops us from trying to create a directory of a drive letter |
| 801 | 801 | ** C: in this example. |
| 802 | 802 | */ |
| 803 | 803 | if( !(i==2 && zName[1]==':') ){ |
| 804 | 804 | #endif |
| 805 | - if( file_mkdir(zName, 1) ){ | |
| 805 | + if( file_mkdir(zName, 1) && file_isdir(zName)!=1 ){ | |
| 806 | 806 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 807 | 807 | return 0; |
| 808 | 808 | } |
| 809 | 809 | #if defined(_WIN32) |
| 810 | 810 | } |
| 811 | 811 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -800,11 +800,11 @@ | |
| 800 | ** The if stops us from trying to create a directory of a drive letter |
| 801 | ** C: in this example. |
| 802 | */ |
| 803 | if( !(i==2 && zName[1]==':') ){ |
| 804 | #endif |
| 805 | if( file_mkdir(zName, 1) ){ |
| 806 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 807 | return 0; |
| 808 | } |
| 809 | #if defined(_WIN32) |
| 810 | } |
| 811 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -800,11 +800,11 @@ | |
| 800 | ** The if stops us from trying to create a directory of a drive letter |
| 801 | ** C: in this example. |
| 802 | */ |
| 803 | if( !(i==2 && zName[1]==':') ){ |
| 804 | #endif |
| 805 | if( file_mkdir(zName, 1) && file_isdir(zName)!=1 ){ |
| 806 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 807 | return 0; |
| 808 | } |
| 809 | #if defined(_WIN32) |
| 810 | } |
| 811 |
+18
-25
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | for(i=0; i<nLine; i++){ |
| 155 | 155 | a[i].z = z; |
| 156 | 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | 157 | k = j; |
| 158 | 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | - for(h=0, x=0; x<k; x++){ | |
| 159 | + for(h=0, x=0; x<=k; x++){ | |
| 160 | 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | 161 | } |
| 162 | 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | 163 | h2 = h % nLine; |
| 164 | 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | ||
| 181 | 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | 183 | ** updated so the continuation bytes are not checked again. |
| 184 | 184 | */ |
| 185 | 185 | #define CHECKUTF8(c) \ |
| 186 | -if( c<0xC0 ){ \ | |
| 187 | - result |= 4; /* Invalid 1-byte UTF-8, continue */ \ | |
| 188 | -}else if( c<0xE0 ){ \ | |
| 189 | - if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ | |
| 190 | - result |= 4; /* Invalid 2-byte UTF-8, continue */ \ | |
| 191 | - }else{ \ | |
| 192 | - --n; ++j; ++z; \ | |
| 193 | - } \ | |
| 194 | -}else if( c<0xF0 ){ \ | |
| 195 | - if( n<3 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) ){ \ | |
| 196 | - result |= 4; /* Invalid 3-byte UTF-8, continue */ \ | |
| 197 | - }else{ \ | |
| 198 | - n-=2; j+=2; z+=2; \ | |
| 199 | - } \ | |
| 200 | -}else if( c<0xF8 ){ \ | |
| 201 | - if( n<4 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) || ((z[3]&0xC0)!=0x80) ){ \ | |
| 202 | - result |= 4; /* Invalid 4-byte UTF-8, continue */ \ | |
| 203 | - }else{ \ | |
| 204 | - n-=3; j+=3; z+=3; \ | |
| 205 | - } \ | |
| 206 | -}else{ \ | |
| 207 | - result |= 4; /* Invalid multi-byte UTF-8, continue */ \ | |
| 208 | -} | |
| 186 | +if( c<0xC0 || c>=0xF8 ){ \ | |
| 187 | + result |= 4; /* Invalid 1-byte or multibyte UTF-8, continue */ \ | |
| 188 | +}else do{ \ | |
| 189 | + /* Check if all continuation bytes >=0x80 and <0xC0 */ \ | |
| 190 | + if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ | |
| 191 | + result |= 4; /* Invalid continuation byte, continue */ \ | |
| 192 | + break; \ | |
| 193 | + }else{ \ | |
| 194 | + /* prepare for checking remaining continuation bytes */ \ | |
| 195 | + c<<=2; --n; ++j; ++z; \ | |
| 196 | + } \ | |
| 197 | +}while( c>=0xC0 ); | |
| 209 | 198 | |
| 210 | 199 | /* |
| 211 | 200 | ** This function attempts to scan each logical line within the blob to |
| 212 | 201 | ** determine the type of content it appears to contain. Possible return |
| 213 | 202 | ** values are: |
| @@ -836,11 +825,15 @@ | ||
| 836 | 825 | if( nPrefix+nSuffix==nLeft ){ |
| 837 | 826 | sbsWriteLineno(p, lnLeft); |
| 838 | 827 | p->iStart2 = p->iEnd2 = 0; |
| 839 | 828 | p->iStart = p->iEnd = -1; |
| 840 | 829 | sbsWriteText(p, pLeft, SBS_PAD); |
| 841 | - sbsWrite(p, nLeft==nRight ? " " : " | ", 3); | |
| 830 | + if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ | |
| 831 | + sbsWrite(p, " ", 3); | |
| 832 | + }else{ | |
| 833 | + sbsWrite(p, " | ", 3); | |
| 834 | + } | |
| 842 | 835 | sbsWriteLineno(p, lnRight); |
| 843 | 836 | p->iStart = nPrefix; |
| 844 | 837 | p->iEnd = nRight - nSuffix; |
| 845 | 838 | p->zStart = zClassAdd; |
| 846 | 839 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 847 | 840 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | for(i=0; i<nLine; i++){ |
| 155 | a[i].z = z; |
| 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | k = j; |
| 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | for(h=0, x=0; x<k; x++){ |
| 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | } |
| 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | h2 = h % nLine; |
| 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | |
| 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | ** updated so the continuation bytes are not checked again. |
| 184 | */ |
| 185 | #define CHECKUTF8(c) \ |
| 186 | if( c<0xC0 ){ \ |
| 187 | result |= 4; /* Invalid 1-byte UTF-8, continue */ \ |
| 188 | }else if( c<0xE0 ){ \ |
| 189 | if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ |
| 190 | result |= 4; /* Invalid 2-byte UTF-8, continue */ \ |
| 191 | }else{ \ |
| 192 | --n; ++j; ++z; \ |
| 193 | } \ |
| 194 | }else if( c<0xF0 ){ \ |
| 195 | if( n<3 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) ){ \ |
| 196 | result |= 4; /* Invalid 3-byte UTF-8, continue */ \ |
| 197 | }else{ \ |
| 198 | n-=2; j+=2; z+=2; \ |
| 199 | } \ |
| 200 | }else if( c<0xF8 ){ \ |
| 201 | if( n<4 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) || ((z[3]&0xC0)!=0x80) ){ \ |
| 202 | result |= 4; /* Invalid 4-byte UTF-8, continue */ \ |
| 203 | }else{ \ |
| 204 | n-=3; j+=3; z+=3; \ |
| 205 | } \ |
| 206 | }else{ \ |
| 207 | result |= 4; /* Invalid multi-byte UTF-8, continue */ \ |
| 208 | } |
| 209 | |
| 210 | /* |
| 211 | ** This function attempts to scan each logical line within the blob to |
| 212 | ** determine the type of content it appears to contain. Possible return |
| 213 | ** values are: |
| @@ -836,11 +825,15 @@ | |
| 836 | if( nPrefix+nSuffix==nLeft ){ |
| 837 | sbsWriteLineno(p, lnLeft); |
| 838 | p->iStart2 = p->iEnd2 = 0; |
| 839 | p->iStart = p->iEnd = -1; |
| 840 | sbsWriteText(p, pLeft, SBS_PAD); |
| 841 | sbsWrite(p, nLeft==nRight ? " " : " | ", 3); |
| 842 | sbsWriteLineno(p, lnRight); |
| 843 | p->iStart = nPrefix; |
| 844 | p->iEnd = nRight - nSuffix; |
| 845 | p->zStart = zClassAdd; |
| 846 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 847 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | for(i=0; i<nLine; i++){ |
| 155 | a[i].z = z; |
| 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | k = j; |
| 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | for(h=0, x=0; x<=k; x++){ |
| 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | } |
| 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | h2 = h % nLine; |
| 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | |
| 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | ** updated so the continuation bytes are not checked again. |
| 184 | */ |
| 185 | #define CHECKUTF8(c) \ |
| 186 | if( c<0xC0 || c>=0xF8 ){ \ |
| 187 | result |= 4; /* Invalid 1-byte or multibyte UTF-8, continue */ \ |
| 188 | }else do{ \ |
| 189 | /* Check if all continuation bytes >=0x80 and <0xC0 */ \ |
| 190 | if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ |
| 191 | result |= 4; /* Invalid continuation byte, continue */ \ |
| 192 | break; \ |
| 193 | }else{ \ |
| 194 | /* prepare for checking remaining continuation bytes */ \ |
| 195 | c<<=2; --n; ++j; ++z; \ |
| 196 | } \ |
| 197 | }while( c>=0xC0 ); |
| 198 | |
| 199 | /* |
| 200 | ** This function attempts to scan each logical line within the blob to |
| 201 | ** determine the type of content it appears to contain. Possible return |
| 202 | ** values are: |
| @@ -836,11 +825,15 @@ | |
| 825 | if( nPrefix+nSuffix==nLeft ){ |
| 826 | sbsWriteLineno(p, lnLeft); |
| 827 | p->iStart2 = p->iEnd2 = 0; |
| 828 | p->iStart = p->iEnd = -1; |
| 829 | sbsWriteText(p, pLeft, SBS_PAD); |
| 830 | if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ |
| 831 | sbsWrite(p, " ", 3); |
| 832 | }else{ |
| 833 | sbsWrite(p, " | ", 3); |
| 834 | } |
| 835 | sbsWriteLineno(p, lnRight); |
| 836 | p->iStart = nPrefix; |
| 837 | p->iEnd = nRight - nSuffix; |
| 838 | p->zStart = zClassAdd; |
| 839 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 840 |
+18
-25
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | for(i=0; i<nLine; i++){ |
| 155 | 155 | a[i].z = z; |
| 156 | 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | 157 | k = j; |
| 158 | 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | - for(h=0, x=0; x<k; x++){ | |
| 159 | + for(h=0, x=0; x<=k; x++){ | |
| 160 | 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | 161 | } |
| 162 | 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | 163 | h2 = h % nLine; |
| 164 | 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | ||
| 181 | 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | 183 | ** updated so the continuation bytes are not checked again. |
| 184 | 184 | */ |
| 185 | 185 | #define CHECKUTF8(c) \ |
| 186 | -if( c<0xC0 ){ \ | |
| 187 | - result |= 4; /* Invalid 1-byte UTF-8, continue */ \ | |
| 188 | -}else if( c<0xE0 ){ \ | |
| 189 | - if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ | |
| 190 | - result |= 4; /* Invalid 2-byte UTF-8, continue */ \ | |
| 191 | - }else{ \ | |
| 192 | - --n; ++j; ++z; \ | |
| 193 | - } \ | |
| 194 | -}else if( c<0xF0 ){ \ | |
| 195 | - if( n<3 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) ){ \ | |
| 196 | - result |= 4; /* Invalid 3-byte UTF-8, continue */ \ | |
| 197 | - }else{ \ | |
| 198 | - n-=2; j+=2; z+=2; \ | |
| 199 | - } \ | |
| 200 | -}else if( c<0xF8 ){ \ | |
| 201 | - if( n<4 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) || ((z[3]&0xC0)!=0x80) ){ \ | |
| 202 | - result |= 4; /* Invalid 4-byte UTF-8, continue */ \ | |
| 203 | - }else{ \ | |
| 204 | - n-=3; j+=3; z+=3; \ | |
| 205 | - } \ | |
| 206 | -}else{ \ | |
| 207 | - result |= 4; /* Invalid multi-byte UTF-8, continue */ \ | |
| 208 | -} | |
| 186 | +if( c<0xC0 || c>=0xF8 ){ \ | |
| 187 | + result |= 4; /* Invalid 1-byte or multibyte UTF-8, continue */ \ | |
| 188 | +}else do{ \ | |
| 189 | + /* Check if all continuation bytes >=0x80 and <0xC0 */ \ | |
| 190 | + if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ | |
| 191 | + result |= 4; /* Invalid continuation byte, continue */ \ | |
| 192 | + break; \ | |
| 193 | + }else{ \ | |
| 194 | + /* prepare for checking remaining continuation bytes */ \ | |
| 195 | + c<<=2; --n; ++j; ++z; \ | |
| 196 | + } \ | |
| 197 | +}while( c>=0xC0 ); | |
| 209 | 198 | |
| 210 | 199 | /* |
| 211 | 200 | ** This function attempts to scan each logical line within the blob to |
| 212 | 201 | ** determine the type of content it appears to contain. Possible return |
| 213 | 202 | ** values are: |
| @@ -836,11 +825,15 @@ | ||
| 836 | 825 | if( nPrefix+nSuffix==nLeft ){ |
| 837 | 826 | sbsWriteLineno(p, lnLeft); |
| 838 | 827 | p->iStart2 = p->iEnd2 = 0; |
| 839 | 828 | p->iStart = p->iEnd = -1; |
| 840 | 829 | sbsWriteText(p, pLeft, SBS_PAD); |
| 841 | - sbsWrite(p, nLeft==nRight ? " " : " | ", 3); | |
| 830 | + if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ | |
| 831 | + sbsWrite(p, " ", 3); | |
| 832 | + }else{ | |
| 833 | + sbsWrite(p, " | ", 3); | |
| 834 | + } | |
| 842 | 835 | sbsWriteLineno(p, lnRight); |
| 843 | 836 | p->iStart = nPrefix; |
| 844 | 837 | p->iEnd = nRight - nSuffix; |
| 845 | 838 | p->zStart = zClassAdd; |
| 846 | 839 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 847 | 840 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | for(i=0; i<nLine; i++){ |
| 155 | a[i].z = z; |
| 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | k = j; |
| 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | for(h=0, x=0; x<k; x++){ |
| 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | } |
| 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | h2 = h % nLine; |
| 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | |
| 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | ** updated so the continuation bytes are not checked again. |
| 184 | */ |
| 185 | #define CHECKUTF8(c) \ |
| 186 | if( c<0xC0 ){ \ |
| 187 | result |= 4; /* Invalid 1-byte UTF-8, continue */ \ |
| 188 | }else if( c<0xE0 ){ \ |
| 189 | if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ |
| 190 | result |= 4; /* Invalid 2-byte UTF-8, continue */ \ |
| 191 | }else{ \ |
| 192 | --n; ++j; ++z; \ |
| 193 | } \ |
| 194 | }else if( c<0xF0 ){ \ |
| 195 | if( n<3 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) ){ \ |
| 196 | result |= 4; /* Invalid 3-byte UTF-8, continue */ \ |
| 197 | }else{ \ |
| 198 | n-=2; j+=2; z+=2; \ |
| 199 | } \ |
| 200 | }else if( c<0xF8 ){ \ |
| 201 | if( n<4 || ((z[1]&0xC0)!=0x80) || ((z[2]&0xC0)!=0x80) || ((z[3]&0xC0)!=0x80) ){ \ |
| 202 | result |= 4; /* Invalid 4-byte UTF-8, continue */ \ |
| 203 | }else{ \ |
| 204 | n-=3; j+=3; z+=3; \ |
| 205 | } \ |
| 206 | }else{ \ |
| 207 | result |= 4; /* Invalid multi-byte UTF-8, continue */ \ |
| 208 | } |
| 209 | |
| 210 | /* |
| 211 | ** This function attempts to scan each logical line within the blob to |
| 212 | ** determine the type of content it appears to contain. Possible return |
| 213 | ** values are: |
| @@ -836,11 +825,15 @@ | |
| 836 | if( nPrefix+nSuffix==nLeft ){ |
| 837 | sbsWriteLineno(p, lnLeft); |
| 838 | p->iStart2 = p->iEnd2 = 0; |
| 839 | p->iStart = p->iEnd = -1; |
| 840 | sbsWriteText(p, pLeft, SBS_PAD); |
| 841 | sbsWrite(p, nLeft==nRight ? " " : " | ", 3); |
| 842 | sbsWriteLineno(p, lnRight); |
| 843 | p->iStart = nPrefix; |
| 844 | p->iEnd = nRight - nSuffix; |
| 845 | p->zStart = zClassAdd; |
| 846 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 847 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -154,11 +154,11 @@ | |
| 154 | for(i=0; i<nLine; i++){ |
| 155 | a[i].z = z; |
| 156 | for(j=0; z[j] && z[j]!='\n'; j++){} |
| 157 | k = j; |
| 158 | while( ignoreWS && k>0 && fossil_isspace(z[k-1]) ){ k--; } |
| 159 | for(h=0, x=0; x<=k; x++){ |
| 160 | h = h ^ (h<<2) ^ z[x]; |
| 161 | } |
| 162 | a[i].h = h = (h<<LENGTH_MASK_SZ) | k;; |
| 163 | h2 = h % nLine; |
| 164 | a[i].iNext = a[h2].iHash; |
| @@ -181,33 +181,22 @@ | |
| 181 | ** Any invalid byte causes bit 2 of result to be set (result |= 4), |
| 182 | ** otherwise for valid multibyte utf-8 sequences n, j and z are |
| 183 | ** updated so the continuation bytes are not checked again. |
| 184 | */ |
| 185 | #define CHECKUTF8(c) \ |
| 186 | if( c<0xC0 || c>=0xF8 ){ \ |
| 187 | result |= 4; /* Invalid 1-byte or multibyte UTF-8, continue */ \ |
| 188 | }else do{ \ |
| 189 | /* Check if all continuation bytes >=0x80 and <0xC0 */ \ |
| 190 | if( n<2 || ((z[1]&0xC0)!=0x80) ){ \ |
| 191 | result |= 4; /* Invalid continuation byte, continue */ \ |
| 192 | break; \ |
| 193 | }else{ \ |
| 194 | /* prepare for checking remaining continuation bytes */ \ |
| 195 | c<<=2; --n; ++j; ++z; \ |
| 196 | } \ |
| 197 | }while( c>=0xC0 ); |
| 198 | |
| 199 | /* |
| 200 | ** This function attempts to scan each logical line within the blob to |
| 201 | ** determine the type of content it appears to contain. Possible return |
| 202 | ** values are: |
| @@ -836,11 +825,15 @@ | |
| 825 | if( nPrefix+nSuffix==nLeft ){ |
| 826 | sbsWriteLineno(p, lnLeft); |
| 827 | p->iStart2 = p->iEnd2 = 0; |
| 828 | p->iStart = p->iEnd = -1; |
| 829 | sbsWriteText(p, pLeft, SBS_PAD); |
| 830 | if( nLeft==nRight && zLeft[nLeft]==zRight[nRight] ){ |
| 831 | sbsWrite(p, " ", 3); |
| 832 | }else{ |
| 833 | sbsWrite(p, " | ", 3); |
| 834 | } |
| 835 | sbsWriteLineno(p, lnRight); |
| 836 | p->iStart = nPrefix; |
| 837 | p->iEnd = nRight - nSuffix; |
| 838 | p->zStart = zClassAdd; |
| 839 | sbsWriteText(p, pRight, SBS_NEWLINE); |
| 840 |
+12
-9
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -457,11 +457,12 @@ | ||
| 457 | 457 | content_get(ridm, &m); |
| 458 | 458 | if( isBinary ){ |
| 459 | 459 | rc = -1; |
| 460 | 460 | blob_zero(&r); |
| 461 | 461 | }else{ |
| 462 | - rc = merge_3way(&p, zFullPath, &m, &r); | |
| 462 | + unsigned mergeFlags = nochangeFlag ? MERGE_DRYRUN : 0; | |
| 463 | + rc = merge_3way(&p, zFullPath, &m, &r, mergeFlags); | |
| 463 | 464 | } |
| 464 | 465 | if( rc>=0 ){ |
| 465 | 466 | if( !nochangeFlag ){ |
| 466 | 467 | blob_write_to_file(&r, zFullPath); |
| 467 | 468 | file_wd_setexe(zFullPath, isExe); |
| @@ -549,18 +550,20 @@ | ||
| 549 | 550 | db_finalize(&q); |
| 550 | 551 | |
| 551 | 552 | |
| 552 | 553 | /* Report on conflicts |
| 553 | 554 | */ |
| 554 | - if( !nochangeFlag ){ | |
| 555 | - if( nConflict ){ | |
| 556 | - fossil_print("WARNING: %d merge conflicts", nConflict); | |
| 557 | - } | |
| 558 | - if( nOverwrite ){ | |
| 559 | - fossil_warning("WARNING: %d unmanaged files were overwritten", | |
| 560 | - nOverwrite); | |
| 561 | - } | |
| 555 | + if( nConflict ){ | |
| 556 | + fossil_warning("WARNING: %d merge conflicts", nConflict); | |
| 557 | + } | |
| 558 | + if( nOverwrite ){ | |
| 559 | + fossil_warning("WARNING: %d unmanaged files were overwritten", | |
| 560 | + nOverwrite); | |
| 561 | + } | |
| 562 | + if( nochangeFlag ){ | |
| 563 | + fossil_warning("REMINDER: this was a dry run -" | |
| 564 | + " no file were actually changed."); | |
| 562 | 565 | } |
| 563 | 566 | |
| 564 | 567 | /* |
| 565 | 568 | ** Clean up the mid and pid VFILE entries. Then commit the changes. |
| 566 | 569 | */ |
| 567 | 570 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -457,11 +457,12 @@ | |
| 457 | content_get(ridm, &m); |
| 458 | if( isBinary ){ |
| 459 | rc = -1; |
| 460 | blob_zero(&r); |
| 461 | }else{ |
| 462 | rc = merge_3way(&p, zFullPath, &m, &r); |
| 463 | } |
| 464 | if( rc>=0 ){ |
| 465 | if( !nochangeFlag ){ |
| 466 | blob_write_to_file(&r, zFullPath); |
| 467 | file_wd_setexe(zFullPath, isExe); |
| @@ -549,18 +550,20 @@ | |
| 549 | db_finalize(&q); |
| 550 | |
| 551 | |
| 552 | /* Report on conflicts |
| 553 | */ |
| 554 | if( !nochangeFlag ){ |
| 555 | if( nConflict ){ |
| 556 | fossil_print("WARNING: %d merge conflicts", nConflict); |
| 557 | } |
| 558 | if( nOverwrite ){ |
| 559 | fossil_warning("WARNING: %d unmanaged files were overwritten", |
| 560 | nOverwrite); |
| 561 | } |
| 562 | } |
| 563 | |
| 564 | /* |
| 565 | ** Clean up the mid and pid VFILE entries. Then commit the changes. |
| 566 | */ |
| 567 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -457,11 +457,12 @@ | |
| 457 | content_get(ridm, &m); |
| 458 | if( isBinary ){ |
| 459 | rc = -1; |
| 460 | blob_zero(&r); |
| 461 | }else{ |
| 462 | unsigned mergeFlags = nochangeFlag ? MERGE_DRYRUN : 0; |
| 463 | rc = merge_3way(&p, zFullPath, &m, &r, mergeFlags); |
| 464 | } |
| 465 | if( rc>=0 ){ |
| 466 | if( !nochangeFlag ){ |
| 467 | blob_write_to_file(&r, zFullPath); |
| 468 | file_wd_setexe(zFullPath, isExe); |
| @@ -549,18 +550,20 @@ | |
| 550 | db_finalize(&q); |
| 551 | |
| 552 | |
| 553 | /* Report on conflicts |
| 554 | */ |
| 555 | if( nConflict ){ |
| 556 | fossil_warning("WARNING: %d merge conflicts", nConflict); |
| 557 | } |
| 558 | if( nOverwrite ){ |
| 559 | fossil_warning("WARNING: %d unmanaged files were overwritten", |
| 560 | nOverwrite); |
| 561 | } |
| 562 | if( nochangeFlag ){ |
| 563 | fossil_warning("REMINDER: this was a dry run -" |
| 564 | " no file were actually changed."); |
| 565 | } |
| 566 | |
| 567 | /* |
| 568 | ** Clean up the mid and pid VFILE entries. Then commit the changes. |
| 569 | */ |
| 570 |
+44
-37
| --- src/merge3.c | ||
| +++ src/merge3.c | ||
| @@ -59,11 +59,11 @@ | ||
| 59 | 59 | |
| 60 | 60 | /* |
| 61 | 61 | ** Look at the next edit triple in both aC1 and aC2. (An "edit triple" is |
| 62 | 62 | ** three integers describing the number of copies, deletes, and inserts in |
| 63 | 63 | ** moving from the original to the edited copy of the file.) If the three |
| 64 | -** integers of the edit triples describe an identical edit, then return 1. | |
| 64 | +** integers of the edit triples describe an identical edit, then return 1. | |
| 65 | 65 | ** If the edits are different, return 0. |
| 66 | 66 | */ |
| 67 | 67 | static int sameEdit( |
| 68 | 68 | int *aC1, /* Array of edit integers for file 1 */ |
| 69 | 69 | int *aC2, /* Array of edit integers for file 2 */ |
| @@ -154,11 +154,11 @@ | ||
| 154 | 154 | ** common origin at pPivot. Apply the changes of pPivot ==> pV1 |
| 155 | 155 | ** to pV2. |
| 156 | 156 | ** |
| 157 | 157 | ** The return is 0 upon complete success. If any input file is binary, |
| 158 | 158 | ** -1 is returned and pOut is unmodified. If there are merge |
| 159 | -** conflicts, the merge proceeds as best as it can and the number | |
| 159 | +** conflicts, the merge proceeds as best as it can and the number | |
| 160 | 160 | ** of conflicts is returns |
| 161 | 161 | */ |
| 162 | 162 | static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ |
| 163 | 163 | int *aC1; /* Changes from pPivot to pV1 */ |
| 164 | 164 | int *aC2; /* Changes from pPivot to pV2 */ |
| @@ -406,10 +406,17 @@ | ||
| 406 | 406 | } |
| 407 | 407 | } |
| 408 | 408 | return blob_str(&x); |
| 409 | 409 | } |
| 410 | 410 | |
| 411 | +#if INTERFACE | |
| 412 | +/* | |
| 413 | +** Flags to the 3-way merger | |
| 414 | +*/ | |
| 415 | +#define MERGE_DRYRUN 0x0001 | |
| 416 | +#endif | |
| 417 | + | |
| 411 | 418 | |
| 412 | 419 | /* |
| 413 | 420 | ** This routine is a wrapper around blob_merge() with the following |
| 414 | 421 | ** enhancements: |
| 415 | 422 | ** |
| @@ -428,59 +435,59 @@ | ||
| 428 | 435 | */ |
| 429 | 436 | int merge_3way( |
| 430 | 437 | Blob *pPivot, /* Common ancestor (older) */ |
| 431 | 438 | const char *zV1, /* Name of file for version merging into (mine) */ |
| 432 | 439 | Blob *pV2, /* Version merging from (yours) */ |
| 433 | - Blob *pOut /* Output written here */ | |
| 440 | + Blob *pOut, /* Output written here */ | |
| 441 | + unsigned mergeFlags /* Flags that control operation */ | |
| 434 | 442 | ){ |
| 435 | 443 | Blob v1; /* Content of zV1 */ |
| 436 | 444 | int rc; /* Return code of subroutines and this routine */ |
| 437 | - char *zPivot; /* Name of the pivot file */ | |
| 438 | - char *zOrig; /* Name of the original content file */ | |
| 439 | - char *zOther; /* Name of the merge file */ | |
| 440 | 445 | |
| 441 | 446 | blob_read_from_file(&v1, zV1); |
| 442 | 447 | rc = blob_merge(pPivot, &v1, pV2, pOut); |
| 443 | - if( rc!=0 ){ | |
| 448 | + if( rc!=0 && (mergeFlags & MERGE_DRYRUN)==0 ){ | |
| 449 | + char *zPivot; /* Name of the pivot file */ | |
| 450 | + char *zOrig; /* Name of the original content file */ | |
| 451 | + char *zOther; /* Name of the merge file */ | |
| 452 | + | |
| 444 | 453 | zPivot = file_newname(zV1, "baseline", 1); |
| 445 | 454 | blob_write_to_file(pPivot, zPivot); |
| 446 | 455 | zOrig = file_newname(zV1, "original", 1); |
| 447 | 456 | blob_write_to_file(&v1, zOrig); |
| 448 | 457 | zOther = file_newname(zV1, "merge", 1); |
| 449 | 458 | blob_write_to_file(pV2, zOther); |
| 450 | - } | |
| 451 | - if( rc>0 ){ | |
| 452 | - const char *zGMerge; /* Name of the gmerge command */ | |
| 453 | - | |
| 454 | - zGMerge = db_get("gmerge-command", 0); | |
| 455 | - if( zGMerge && zGMerge[0] ){ | |
| 456 | - char *zOut; /* Temporary output file */ | |
| 457 | - char *zCmd; /* Command to invoke */ | |
| 458 | - const char *azSubst[8]; /* Strings to be substituted */ | |
| 459 | - | |
| 460 | - zOut = file_newname(zV1, "output", 1); | |
| 461 | - azSubst[0] = "%baseline"; azSubst[1] = zPivot; | |
| 462 | - azSubst[2] = "%original"; azSubst[3] = zOrig; | |
| 463 | - azSubst[4] = "%merge"; azSubst[5] = zOther; | |
| 464 | - azSubst[6] = "%output"; azSubst[7] = zOut; | |
| 465 | - zCmd = string_subst(zGMerge, 8, azSubst); | |
| 466 | - printf("%s\n", zCmd); fflush(stdout); | |
| 467 | - fossil_system(zCmd); | |
| 468 | - if( file_wd_size(zOut)>=0 ){ | |
| 469 | - blob_read_from_file(pOut, zOut); | |
| 470 | - file_delete(zPivot); | |
| 471 | - file_delete(zOrig); | |
| 472 | - file_delete(zOther); | |
| 473 | - file_delete(zOut); | |
| 474 | - } | |
| 475 | - fossil_free(zCmd); | |
| 476 | - fossil_free(zOut); | |
| 477 | - } | |
| 478 | - } | |
| 479 | - if( rc!=0 ){ | |
| 459 | + if( rc>0 ){ | |
| 460 | + const char *zGMerge; /* Name of the gmerge command */ | |
| 461 | + | |
| 462 | + zGMerge = db_get("gmerge-command", 0); | |
| 463 | + if( zGMerge && zGMerge[0] ){ | |
| 464 | + char *zOut; /* Temporary output file */ | |
| 465 | + char *zCmd; /* Command to invoke */ | |
| 466 | + const char *azSubst[8]; /* Strings to be substituted */ | |
| 467 | + | |
| 468 | + zOut = file_newname(zV1, "output", 1); | |
| 469 | + azSubst[0] = "%baseline"; azSubst[1] = zPivot; | |
| 470 | + azSubst[2] = "%original"; azSubst[3] = zOrig; | |
| 471 | + azSubst[4] = "%merge"; azSubst[5] = zOther; | |
| 472 | + azSubst[6] = "%output"; azSubst[7] = zOut; | |
| 473 | + zCmd = string_subst(zGMerge, 8, azSubst); | |
| 474 | + printf("%s\n", zCmd); fflush(stdout); | |
| 475 | + fossil_system(zCmd); | |
| 476 | + if( file_wd_size(zOut)>=0 ){ | |
| 477 | + blob_read_from_file(pOut, zOut); | |
| 478 | + file_delete(zPivot); | |
| 479 | + file_delete(zOrig); | |
| 480 | + file_delete(zOther); | |
| 481 | + file_delete(zOut); | |
| 482 | + } | |
| 483 | + fossil_free(zCmd); | |
| 484 | + fossil_free(zOut); | |
| 485 | + } | |
| 486 | + } | |
| 480 | 487 | fossil_free(zPivot); |
| 481 | 488 | fossil_free(zOrig); |
| 482 | 489 | fossil_free(zOther); |
| 483 | 490 | } |
| 484 | 491 | blob_reset(&v1); |
| 485 | 492 | return rc; |
| 486 | 493 | } |
| 487 | 494 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -59,11 +59,11 @@ | |
| 59 | |
| 60 | /* |
| 61 | ** Look at the next edit triple in both aC1 and aC2. (An "edit triple" is |
| 62 | ** three integers describing the number of copies, deletes, and inserts in |
| 63 | ** moving from the original to the edited copy of the file.) If the three |
| 64 | ** integers of the edit triples describe an identical edit, then return 1. |
| 65 | ** If the edits are different, return 0. |
| 66 | */ |
| 67 | static int sameEdit( |
| 68 | int *aC1, /* Array of edit integers for file 1 */ |
| 69 | int *aC2, /* Array of edit integers for file 2 */ |
| @@ -154,11 +154,11 @@ | |
| 154 | ** common origin at pPivot. Apply the changes of pPivot ==> pV1 |
| 155 | ** to pV2. |
| 156 | ** |
| 157 | ** The return is 0 upon complete success. If any input file is binary, |
| 158 | ** -1 is returned and pOut is unmodified. If there are merge |
| 159 | ** conflicts, the merge proceeds as best as it can and the number |
| 160 | ** of conflicts is returns |
| 161 | */ |
| 162 | static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ |
| 163 | int *aC1; /* Changes from pPivot to pV1 */ |
| 164 | int *aC2; /* Changes from pPivot to pV2 */ |
| @@ -406,10 +406,17 @@ | |
| 406 | } |
| 407 | } |
| 408 | return blob_str(&x); |
| 409 | } |
| 410 | |
| 411 | |
| 412 | /* |
| 413 | ** This routine is a wrapper around blob_merge() with the following |
| 414 | ** enhancements: |
| 415 | ** |
| @@ -428,59 +435,59 @@ | |
| 428 | */ |
| 429 | int merge_3way( |
| 430 | Blob *pPivot, /* Common ancestor (older) */ |
| 431 | const char *zV1, /* Name of file for version merging into (mine) */ |
| 432 | Blob *pV2, /* Version merging from (yours) */ |
| 433 | Blob *pOut /* Output written here */ |
| 434 | ){ |
| 435 | Blob v1; /* Content of zV1 */ |
| 436 | int rc; /* Return code of subroutines and this routine */ |
| 437 | char *zPivot; /* Name of the pivot file */ |
| 438 | char *zOrig; /* Name of the original content file */ |
| 439 | char *zOther; /* Name of the merge file */ |
| 440 | |
| 441 | blob_read_from_file(&v1, zV1); |
| 442 | rc = blob_merge(pPivot, &v1, pV2, pOut); |
| 443 | if( rc!=0 ){ |
| 444 | zPivot = file_newname(zV1, "baseline", 1); |
| 445 | blob_write_to_file(pPivot, zPivot); |
| 446 | zOrig = file_newname(zV1, "original", 1); |
| 447 | blob_write_to_file(&v1, zOrig); |
| 448 | zOther = file_newname(zV1, "merge", 1); |
| 449 | blob_write_to_file(pV2, zOther); |
| 450 | } |
| 451 | if( rc>0 ){ |
| 452 | const char *zGMerge; /* Name of the gmerge command */ |
| 453 | |
| 454 | zGMerge = db_get("gmerge-command", 0); |
| 455 | if( zGMerge && zGMerge[0] ){ |
| 456 | char *zOut; /* Temporary output file */ |
| 457 | char *zCmd; /* Command to invoke */ |
| 458 | const char *azSubst[8]; /* Strings to be substituted */ |
| 459 | |
| 460 | zOut = file_newname(zV1, "output", 1); |
| 461 | azSubst[0] = "%baseline"; azSubst[1] = zPivot; |
| 462 | azSubst[2] = "%original"; azSubst[3] = zOrig; |
| 463 | azSubst[4] = "%merge"; azSubst[5] = zOther; |
| 464 | azSubst[6] = "%output"; azSubst[7] = zOut; |
| 465 | zCmd = string_subst(zGMerge, 8, azSubst); |
| 466 | printf("%s\n", zCmd); fflush(stdout); |
| 467 | fossil_system(zCmd); |
| 468 | if( file_wd_size(zOut)>=0 ){ |
| 469 | blob_read_from_file(pOut, zOut); |
| 470 | file_delete(zPivot); |
| 471 | file_delete(zOrig); |
| 472 | file_delete(zOther); |
| 473 | file_delete(zOut); |
| 474 | } |
| 475 | fossil_free(zCmd); |
| 476 | fossil_free(zOut); |
| 477 | } |
| 478 | } |
| 479 | if( rc!=0 ){ |
| 480 | fossil_free(zPivot); |
| 481 | fossil_free(zOrig); |
| 482 | fossil_free(zOther); |
| 483 | } |
| 484 | blob_reset(&v1); |
| 485 | return rc; |
| 486 | } |
| 487 |
| --- src/merge3.c | |
| +++ src/merge3.c | |
| @@ -59,11 +59,11 @@ | |
| 59 | |
| 60 | /* |
| 61 | ** Look at the next edit triple in both aC1 and aC2. (An "edit triple" is |
| 62 | ** three integers describing the number of copies, deletes, and inserts in |
| 63 | ** moving from the original to the edited copy of the file.) If the three |
| 64 | ** integers of the edit triples describe an identical edit, then return 1. |
| 65 | ** If the edits are different, return 0. |
| 66 | */ |
| 67 | static int sameEdit( |
| 68 | int *aC1, /* Array of edit integers for file 1 */ |
| 69 | int *aC2, /* Array of edit integers for file 2 */ |
| @@ -154,11 +154,11 @@ | |
| 154 | ** common origin at pPivot. Apply the changes of pPivot ==> pV1 |
| 155 | ** to pV2. |
| 156 | ** |
| 157 | ** The return is 0 upon complete success. If any input file is binary, |
| 158 | ** -1 is returned and pOut is unmodified. If there are merge |
| 159 | ** conflicts, the merge proceeds as best as it can and the number |
| 160 | ** of conflicts is returns |
| 161 | */ |
| 162 | static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ |
| 163 | int *aC1; /* Changes from pPivot to pV1 */ |
| 164 | int *aC2; /* Changes from pPivot to pV2 */ |
| @@ -406,10 +406,17 @@ | |
| 406 | } |
| 407 | } |
| 408 | return blob_str(&x); |
| 409 | } |
| 410 | |
| 411 | #if INTERFACE |
| 412 | /* |
| 413 | ** Flags to the 3-way merger |
| 414 | */ |
| 415 | #define MERGE_DRYRUN 0x0001 |
| 416 | #endif |
| 417 | |
| 418 | |
| 419 | /* |
| 420 | ** This routine is a wrapper around blob_merge() with the following |
| 421 | ** enhancements: |
| 422 | ** |
| @@ -428,59 +435,59 @@ | |
| 435 | */ |
| 436 | int merge_3way( |
| 437 | Blob *pPivot, /* Common ancestor (older) */ |
| 438 | const char *zV1, /* Name of file for version merging into (mine) */ |
| 439 | Blob *pV2, /* Version merging from (yours) */ |
| 440 | Blob *pOut, /* Output written here */ |
| 441 | unsigned mergeFlags /* Flags that control operation */ |
| 442 | ){ |
| 443 | Blob v1; /* Content of zV1 */ |
| 444 | int rc; /* Return code of subroutines and this routine */ |
| 445 | |
| 446 | blob_read_from_file(&v1, zV1); |
| 447 | rc = blob_merge(pPivot, &v1, pV2, pOut); |
| 448 | if( rc!=0 && (mergeFlags & MERGE_DRYRUN)==0 ){ |
| 449 | char *zPivot; /* Name of the pivot file */ |
| 450 | char *zOrig; /* Name of the original content file */ |
| 451 | char *zOther; /* Name of the merge file */ |
| 452 | |
| 453 | zPivot = file_newname(zV1, "baseline", 1); |
| 454 | blob_write_to_file(pPivot, zPivot); |
| 455 | zOrig = file_newname(zV1, "original", 1); |
| 456 | blob_write_to_file(&v1, zOrig); |
| 457 | zOther = file_newname(zV1, "merge", 1); |
| 458 | blob_write_to_file(pV2, zOther); |
| 459 | if( rc>0 ){ |
| 460 | const char *zGMerge; /* Name of the gmerge command */ |
| 461 | |
| 462 | zGMerge = db_get("gmerge-command", 0); |
| 463 | if( zGMerge && zGMerge[0] ){ |
| 464 | char *zOut; /* Temporary output file */ |
| 465 | char *zCmd; /* Command to invoke */ |
| 466 | const char *azSubst[8]; /* Strings to be substituted */ |
| 467 | |
| 468 | zOut = file_newname(zV1, "output", 1); |
| 469 | azSubst[0] = "%baseline"; azSubst[1] = zPivot; |
| 470 | azSubst[2] = "%original"; azSubst[3] = zOrig; |
| 471 | azSubst[4] = "%merge"; azSubst[5] = zOther; |
| 472 | azSubst[6] = "%output"; azSubst[7] = zOut; |
| 473 | zCmd = string_subst(zGMerge, 8, azSubst); |
| 474 | printf("%s\n", zCmd); fflush(stdout); |
| 475 | fossil_system(zCmd); |
| 476 | if( file_wd_size(zOut)>=0 ){ |
| 477 | blob_read_from_file(pOut, zOut); |
| 478 | file_delete(zPivot); |
| 479 | file_delete(zOrig); |
| 480 | file_delete(zOther); |
| 481 | file_delete(zOut); |
| 482 | } |
| 483 | fossil_free(zCmd); |
| 484 | fossil_free(zOut); |
| 485 | } |
| 486 | } |
| 487 | fossil_free(zPivot); |
| 488 | fossil_free(zOrig); |
| 489 | fossil_free(zOther); |
| 490 | } |
| 491 | blob_reset(&v1); |
| 492 | return rc; |
| 493 | } |
| 494 |
+6
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1098,10 +1098,16 @@ | ||
| 1098 | 1098 | onoff_attribute("Allow block-markup in timeline", |
| 1099 | 1099 | "timeline-block-markup", "tbm", 0); |
| 1100 | 1100 | @ <p>In timeline displays, check-in comments can be displayed with or |
| 1101 | 1101 | @ without block markup (paragraphs, tables, etc.)</p> |
| 1102 | 1102 | |
| 1103 | + @ <hr /> | |
| 1104 | + onoff_attribute("Plaintext comments on timelines", | |
| 1105 | + "timeline-plaintext", "tpt", 0); | |
| 1106 | + @ <p>In timeline displays, check-in comments are displayed literally, | |
| 1107 | + @ without any wiki or HTML interpretation.</p> | |
| 1108 | + | |
| 1103 | 1109 | @ <hr /> |
| 1104 | 1110 | onoff_attribute("Use Universal Coordinated Time (UTC)", |
| 1105 | 1111 | "timeline-utc", "utc", 1); |
| 1106 | 1112 | @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or |
| 1107 | 1113 | @ Zulu) instead of in local time. On this server, local time is currently |
| 1108 | 1114 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1098,10 +1098,16 @@ | |
| 1098 | onoff_attribute("Allow block-markup in timeline", |
| 1099 | "timeline-block-markup", "tbm", 0); |
| 1100 | @ <p>In timeline displays, check-in comments can be displayed with or |
| 1101 | @ without block markup (paragraphs, tables, etc.)</p> |
| 1102 | |
| 1103 | @ <hr /> |
| 1104 | onoff_attribute("Use Universal Coordinated Time (UTC)", |
| 1105 | "timeline-utc", "utc", 1); |
| 1106 | @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or |
| 1107 | @ Zulu) instead of in local time. On this server, local time is currently |
| 1108 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1098,10 +1098,16 @@ | |
| 1098 | onoff_attribute("Allow block-markup in timeline", |
| 1099 | "timeline-block-markup", "tbm", 0); |
| 1100 | @ <p>In timeline displays, check-in comments can be displayed with or |
| 1101 | @ without block markup (paragraphs, tables, etc.)</p> |
| 1102 | |
| 1103 | @ <hr /> |
| 1104 | onoff_attribute("Plaintext comments on timelines", |
| 1105 | "timeline-plaintext", "tpt", 0); |
| 1106 | @ <p>In timeline displays, check-in comments are displayed literally, |
| 1107 | @ without any wiki or HTML interpretation.</p> |
| 1108 | |
| 1109 | @ <hr /> |
| 1110 | onoff_attribute("Use Universal Coordinated Time (UTC)", |
| 1111 | "timeline-utc", "utc", 1); |
| 1112 | @ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or |
| 1113 | @ Zulu) instead of in local time. On this server, local time is currently |
| 1114 |
+1
-1
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -253,11 +253,11 @@ | ||
| 253 | 253 | if( isLink || isNewLink ){ |
| 254 | 254 | rc = -1; |
| 255 | 255 | blob_zero(&b); /* because we reset it later */ |
| 256 | 256 | fossil_print("***** Cannot merge symlink %s\n", zNew); |
| 257 | 257 | }else{ |
| 258 | - rc = merge_3way(&a, zOPath, &b, &out); | |
| 258 | + rc = merge_3way(&a, zOPath, &b, &out, 0); | |
| 259 | 259 | blob_write_to_file(&out, zNPath); |
| 260 | 260 | blob_reset(&out); |
| 261 | 261 | file_wd_setexe(zNPath, isExec); |
| 262 | 262 | } |
| 263 | 263 | if( rc ){ |
| 264 | 264 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -253,11 +253,11 @@ | |
| 253 | if( isLink || isNewLink ){ |
| 254 | rc = -1; |
| 255 | blob_zero(&b); /* because we reset it later */ |
| 256 | fossil_print("***** Cannot merge symlink %s\n", zNew); |
| 257 | }else{ |
| 258 | rc = merge_3way(&a, zOPath, &b, &out); |
| 259 | blob_write_to_file(&out, zNPath); |
| 260 | blob_reset(&out); |
| 261 | file_wd_setexe(zNPath, isExec); |
| 262 | } |
| 263 | if( rc ){ |
| 264 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -253,11 +253,11 @@ | |
| 253 | if( isLink || isNewLink ){ |
| 254 | rc = -1; |
| 255 | blob_zero(&b); /* because we reset it later */ |
| 256 | fossil_print("***** Cannot merge symlink %s\n", zNew); |
| 257 | }else{ |
| 258 | rc = merge_3way(&a, zOPath, &b, &out, 0); |
| 259 | blob_write_to_file(&out, zNPath); |
| 260 | blob_reset(&out); |
| 261 | file_wd_setexe(zNPath, isExec); |
| 262 | } |
| 263 | if( rc ){ |
| 264 |
+1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -667,10 +667,11 @@ | ||
| 667 | 667 | }, |
| 668 | 668 | { "ul.browser", |
| 669 | 669 | "format for the list in the file browser", |
| 670 | 670 | @ margin-left: 0.5em; |
| 671 | 671 | @ padding-left: 0.5em; |
| 672 | + @ white-space: nowrap; | |
| 672 | 673 | }, |
| 673 | 674 | { "table.login_out", |
| 674 | 675 | "table format for login/out label/input table", |
| 675 | 676 | @ text-align: left; |
| 676 | 677 | @ margin-right: 10px; |
| 677 | 678 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -667,10 +667,11 @@ | |
| 667 | }, |
| 668 | { "ul.browser", |
| 669 | "format for the list in the file browser", |
| 670 | @ margin-left: 0.5em; |
| 671 | @ padding-left: 0.5em; |
| 672 | }, |
| 673 | { "table.login_out", |
| 674 | "table format for login/out label/input table", |
| 675 | @ text-align: left; |
| 676 | @ margin-right: 10px; |
| 677 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -667,10 +667,11 @@ | |
| 667 | }, |
| 668 | { "ul.browser", |
| 669 | "format for the list in the file browser", |
| 670 | @ margin-left: 0.5em; |
| 671 | @ padding-left: 0.5em; |
| 672 | @ white-space: nowrap; |
| 673 | }, |
| 674 | { "table.login_out", |
| 675 | "table format for login/out label/input table", |
| 676 | @ text-align: left; |
| 677 | @ margin-right: 10px; |
| 678 |
+25
-17
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -192,10 +192,11 @@ | ||
| 192 | 192 | const char *zThisUser, /* Suppress links to this user */ |
| 193 | 193 | const char *zThisTag, /* Suppress links to this tag */ |
| 194 | 194 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 195 | 195 | ){ |
| 196 | 196 | int wikiFlags; |
| 197 | + int plainText; | |
| 197 | 198 | int mxWikiLen; |
| 198 | 199 | Blob comment; |
| 199 | 200 | int prevTagid = 0; |
| 200 | 201 | int suppressCnt = 0; |
| 201 | 202 | char zPrevDate[20]; |
| @@ -205,10 +206,11 @@ | ||
| 205 | 206 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 206 | 207 | static Stmt qbranch; |
| 207 | 208 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 208 | 209 | |
| 209 | 210 | zPrevDate[0] = 0; |
| 211 | + plainText = db_get_int("timeline-plaintext", 0); | |
| 210 | 212 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 211 | 213 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 212 | 214 | wikiFlags = WIKI_INLINE; |
| 213 | 215 | }else{ |
| 214 | 216 | wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; |
| @@ -285,11 +287,11 @@ | ||
| 285 | 287 | @ <td class="timelineGraph"> |
| 286 | 288 | if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0; |
| 287 | 289 | if( zType[0]=='c' |
| 288 | 290 | && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0) |
| 289 | 291 | ){ |
| 290 | - db_reset(&qbranch); | |
| 292 | + db_reset(&qbranch); | |
| 291 | 293 | db_bind_int(&qbranch, ":rid", rid); |
| 292 | 294 | if( db_step(&qbranch)==SQLITE_ROW ){ |
| 293 | 295 | zBr = db_column_text(&qbranch, 0); |
| 294 | 296 | }else{ |
| 295 | 297 | zBr = "trunk"; |
| @@ -353,12 +355,18 @@ | ||
| 353 | 355 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 354 | 356 | Blob truncated; |
| 355 | 357 | blob_zero(&truncated); |
| 356 | 358 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 357 | 359 | blob_append(&truncated, "...", 3); |
| 358 | - wiki_convert(&truncated, 0, wikiFlags); | |
| 360 | + if( plainText ){ | |
| 361 | + @ %h(blob_str(&truncated)) | |
| 362 | + }else{ | |
| 363 | + wiki_convert(&truncated, 0, wikiFlags); | |
| 364 | + } | |
| 359 | 365 | blob_reset(&truncated); |
| 366 | + }else if( plainText ){ | |
| 367 | + @ %h(blob_str(&comment)); | |
| 360 | 368 | }else{ |
| 361 | 369 | wiki_convert(&comment, 0, wikiFlags); |
| 362 | 370 | } |
| 363 | 371 | blob_reset(&comment); |
| 364 | 372 | |
| @@ -365,11 +373,11 @@ | ||
| 365 | 373 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 366 | 374 | ** with a hyperlink to another timeline for that user. |
| 367 | 375 | */ |
| 368 | 376 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 369 | 377 | if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ |
| 370 | - char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); | |
| 378 | + char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); | |
| 371 | 379 | @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") |
| 372 | 380 | }else{ |
| 373 | 381 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 374 | 382 | } |
| 375 | 383 | |
| @@ -390,11 +398,11 @@ | ||
| 390 | 398 | while( z && z[0] ){ |
| 391 | 399 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 392 | 400 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 393 | 401 | blob_appendf(&links, |
| 394 | 402 | "%z%#h</a>%.2s", |
| 395 | - href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i] | |
| 403 | + href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i] | |
| 396 | 404 | ); |
| 397 | 405 | }else{ |
| 398 | 406 | blob_appendf(&links, "%#h", i+2, z); |
| 399 | 407 | } |
| 400 | 408 | if( z[i]==0 ) break; |
| @@ -415,11 +423,11 @@ | ||
| 415 | 423 | |
| 416 | 424 | /* Generate the file-change list if requested */ |
| 417 | 425 | if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){ |
| 418 | 426 | int inUl = 0; |
| 419 | 427 | if( !fchngQueryInit ){ |
| 420 | - db_prepare(&fchngQuery, | |
| 428 | + db_prepare(&fchngQuery, | |
| 421 | 429 | "SELECT (pid==0) AS isnew," |
| 422 | 430 | " (fid==0) AS isdel," |
| 423 | 431 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 424 | 432 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 425 | 433 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| @@ -484,11 +492,11 @@ | ||
| 484 | 492 | pGraph = 0; |
| 485 | 493 | }else{ |
| 486 | 494 | /* style is not moved to css, because this is |
| 487 | 495 | ** a technical div for the timeline graph |
| 488 | 496 | */ |
| 489 | - @ <tr><td /><td> | |
| 497 | + @ <tr><td></td><td> | |
| 490 | 498 | @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 491 | 499 | @ </td></tr> |
| 492 | 500 | } |
| 493 | 501 | } |
| 494 | 502 | @ </table> |
| @@ -653,11 +661,11 @@ | ||
| 653 | 661 | @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5); |
| 654 | 662 | if( !omitDescenders ){ |
| 655 | 663 | @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5); |
| 656 | 664 | @ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2); |
| 657 | 665 | @ if( p.d ) drawUpArrow(p.x, p.y+6, btm); |
| 658 | - } | |
| 666 | + } | |
| 659 | 667 | @ if( p.mo>0 ){ |
| 660 | 668 | @ var x1 = p.mo + left - 1; |
| 661 | 669 | @ var y1 = p.y-3; |
| 662 | 670 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 663 | 671 | @ var u = rowinfo[p.mu-1]; |
| @@ -758,11 +766,11 @@ | ||
| 758 | 766 | |
| 759 | 767 | /* |
| 760 | 768 | ** Create a temporary table suitable for storing timeline data. |
| 761 | 769 | */ |
| 762 | 770 | static void timeline_temp_table(void){ |
| 763 | - static const char zSql[] = | |
| 771 | + static const char zSql[] = | |
| 764 | 772 | @ CREATE TEMP TABLE IF NOT EXISTS timeline( |
| 765 | 773 | @ rid INTEGER PRIMARY KEY, |
| 766 | 774 | @ uuid TEXT, |
| 767 | 775 | @ timestamp TEXT, |
| 768 | 776 | @ comment TEXT, |
| @@ -799,11 +807,11 @@ | ||
| 799 | 807 | @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid |
| 800 | 808 | @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags, |
| 801 | 809 | @ tagid AS tagid, |
| 802 | 810 | @ brief AS brief, |
| 803 | 811 | @ event.mtime AS mtime |
| 804 | - @ FROM event CROSS JOIN blob | |
| 812 | + @ FROM event CROSS JOIN blob | |
| 805 | 813 | @ WHERE blob.rid=event.objid |
| 806 | 814 | ; |
| 807 | 815 | if( zBase==0 ){ |
| 808 | 816 | zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH); |
| 809 | 817 | } |
| @@ -1167,24 +1175,24 @@ | ||
| 1167 | 1175 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1168 | 1176 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1169 | 1177 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1170 | 1178 | if( rAfter>0.0 ){ |
| 1171 | 1179 | if( rBefore>0.0 ){ |
| 1172 | - blob_appendf(&sql, | |
| 1180 | + blob_appendf(&sql, | |
| 1173 | 1181 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1174 | 1182 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1175 | 1183 | url_add_parameter(&url, "a", zAfter); |
| 1176 | 1184 | url_add_parameter(&url, "b", zBefore); |
| 1177 | 1185 | nEntry = 1000000; |
| 1178 | 1186 | }else{ |
| 1179 | - blob_appendf(&sql, | |
| 1187 | + blob_appendf(&sql, | |
| 1180 | 1188 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1181 | 1189 | rAfter-ONE_SECOND); |
| 1182 | 1190 | url_add_parameter(&url, "a", zAfter); |
| 1183 | 1191 | } |
| 1184 | 1192 | }else if( rBefore>0.0 ){ |
| 1185 | - blob_appendf(&sql, | |
| 1193 | + blob_appendf(&sql, | |
| 1186 | 1194 | " AND event.mtime<=%.17g ORDER BY event.mtime DESC", |
| 1187 | 1195 | rBefore+ONE_SECOND); |
| 1188 | 1196 | url_add_parameter(&url, "b", zBefore); |
| 1189 | 1197 | }else if( rCirca>0.0 ){ |
| 1190 | 1198 | Blob sql2; |
| @@ -1300,11 +1308,11 @@ | ||
| 1300 | 1308 | /* |
| 1301 | 1309 | ** The input query q selects various records. Print a human-readable |
| 1302 | 1310 | ** summary of those records. |
| 1303 | 1311 | ** |
| 1304 | 1312 | ** Limit the number of entries printed to nLine. |
| 1305 | -** | |
| 1313 | +** | |
| 1306 | 1314 | ** The query should return these columns: |
| 1307 | 1315 | ** |
| 1308 | 1316 | ** 0. rid |
| 1309 | 1317 | ** 1. uuid |
| 1310 | 1318 | ** 2. Date/Time |
| @@ -1334,11 +1342,11 @@ | ||
| 1334 | 1342 | int nParent = db_column_int(q, 5); |
| 1335 | 1343 | char *zFree = 0; |
| 1336 | 1344 | int n = 0; |
| 1337 | 1345 | char zPrefix[80]; |
| 1338 | 1346 | char zUuid[UUID_SIZE+1]; |
| 1339 | - | |
| 1347 | + | |
| 1340 | 1348 | sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId); |
| 1341 | 1349 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 1342 | 1350 | fossil_print("=== %.10s ===\n", zDate); |
| 1343 | 1351 | memcpy(zPrevDate, zDate, 10); |
| 1344 | 1352 | nLine++; |
| @@ -1368,11 +1376,11 @@ | ||
| 1368 | 1376 | nLine += comment_print(zFree, 9, 79); |
| 1369 | 1377 | sqlite3_free(zFree); |
| 1370 | 1378 | |
| 1371 | 1379 | if(showfiles){ |
| 1372 | 1380 | if( !fchngQueryInit ){ |
| 1373 | - db_prepare(&fchngQuery, | |
| 1381 | + db_prepare(&fchngQuery, | |
| 1374 | 1382 | "SELECT (pid==0) AS isnew," |
| 1375 | 1383 | " (fid==0) AS isdel," |
| 1376 | 1384 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 1377 | 1385 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 1378 | 1386 | " (SELECT uuid FROM blob WHERE rid=pid)" |
| @@ -1385,11 +1393,11 @@ | ||
| 1385 | 1393 | db_bind_int(&fchngQuery, ":mid", rid); |
| 1386 | 1394 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 1387 | 1395 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 1388 | 1396 | int isNew = db_column_int(&fchngQuery, 0); |
| 1389 | 1397 | int isDel = db_column_int(&fchngQuery, 1); |
| 1390 | - if( isNew ){ | |
| 1398 | + if( isNew ){ | |
| 1391 | 1399 | fossil_print(" ADDED %s\n",zFilename); |
| 1392 | 1400 | }else if( isDel ){ |
| 1393 | 1401 | fossil_print(" DELETED %s\n",zFilename); |
| 1394 | 1402 | }else{ |
| 1395 | 1403 | fossil_print(" EDITED %s\n", zFilename); |
| @@ -1404,11 +1412,11 @@ | ||
| 1404 | 1412 | /* |
| 1405 | 1413 | ** Return a pointer to a static string that forms the basis for |
| 1406 | 1414 | ** a timeline query for display on a TTY. |
| 1407 | 1415 | */ |
| 1408 | 1416 | const char *timeline_query_for_tty(void){ |
| 1409 | - static const char zBaseSql[] = | |
| 1417 | + static const char zBaseSql[] = | |
| 1410 | 1418 | @ SELECT |
| 1411 | 1419 | @ blob.rid AS rid, |
| 1412 | 1420 | @ uuid, |
| 1413 | 1421 | @ datetime(event.mtime,'localtime') AS mDateTime, |
| 1414 | 1422 | @ coalesce(ecomment,comment) |
| 1415 | 1423 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -192,10 +192,11 @@ | |
| 192 | const char *zThisUser, /* Suppress links to this user */ |
| 193 | const char *zThisTag, /* Suppress links to this tag */ |
| 194 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 195 | ){ |
| 196 | int wikiFlags; |
| 197 | int mxWikiLen; |
| 198 | Blob comment; |
| 199 | int prevTagid = 0; |
| 200 | int suppressCnt = 0; |
| 201 | char zPrevDate[20]; |
| @@ -205,10 +206,11 @@ | |
| 205 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 206 | static Stmt qbranch; |
| 207 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 208 | |
| 209 | zPrevDate[0] = 0; |
| 210 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 211 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 212 | wikiFlags = WIKI_INLINE; |
| 213 | }else{ |
| 214 | wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; |
| @@ -285,11 +287,11 @@ | |
| 285 | @ <td class="timelineGraph"> |
| 286 | if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0; |
| 287 | if( zType[0]=='c' |
| 288 | && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0) |
| 289 | ){ |
| 290 | db_reset(&qbranch); |
| 291 | db_bind_int(&qbranch, ":rid", rid); |
| 292 | if( db_step(&qbranch)==SQLITE_ROW ){ |
| 293 | zBr = db_column_text(&qbranch, 0); |
| 294 | }else{ |
| 295 | zBr = "trunk"; |
| @@ -353,12 +355,18 @@ | |
| 353 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 354 | Blob truncated; |
| 355 | blob_zero(&truncated); |
| 356 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 357 | blob_append(&truncated, "...", 3); |
| 358 | wiki_convert(&truncated, 0, wikiFlags); |
| 359 | blob_reset(&truncated); |
| 360 | }else{ |
| 361 | wiki_convert(&comment, 0, wikiFlags); |
| 362 | } |
| 363 | blob_reset(&comment); |
| 364 | |
| @@ -365,11 +373,11 @@ | |
| 365 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 366 | ** with a hyperlink to another timeline for that user. |
| 367 | */ |
| 368 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 369 | if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ |
| 370 | char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); |
| 371 | @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") |
| 372 | }else{ |
| 373 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 374 | } |
| 375 | |
| @@ -390,11 +398,11 @@ | |
| 390 | while( z && z[0] ){ |
| 391 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 392 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 393 | blob_appendf(&links, |
| 394 | "%z%#h</a>%.2s", |
| 395 | href("%R/timeline?r=%#t&nd&c=%s",i,z,zDate), i,z, &z[i] |
| 396 | ); |
| 397 | }else{ |
| 398 | blob_appendf(&links, "%#h", i+2, z); |
| 399 | } |
| 400 | if( z[i]==0 ) break; |
| @@ -415,11 +423,11 @@ | |
| 415 | |
| 416 | /* Generate the file-change list if requested */ |
| 417 | if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){ |
| 418 | int inUl = 0; |
| 419 | if( !fchngQueryInit ){ |
| 420 | db_prepare(&fchngQuery, |
| 421 | "SELECT (pid==0) AS isnew," |
| 422 | " (fid==0) AS isdel," |
| 423 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 424 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 425 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| @@ -484,11 +492,11 @@ | |
| 484 | pGraph = 0; |
| 485 | }else{ |
| 486 | /* style is not moved to css, because this is |
| 487 | ** a technical div for the timeline graph |
| 488 | */ |
| 489 | @ <tr><td /><td> |
| 490 | @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 491 | @ </td></tr> |
| 492 | } |
| 493 | } |
| 494 | @ </table> |
| @@ -653,11 +661,11 @@ | |
| 653 | @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5); |
| 654 | if( !omitDescenders ){ |
| 655 | @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5); |
| 656 | @ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2); |
| 657 | @ if( p.d ) drawUpArrow(p.x, p.y+6, btm); |
| 658 | } |
| 659 | @ if( p.mo>0 ){ |
| 660 | @ var x1 = p.mo + left - 1; |
| 661 | @ var y1 = p.y-3; |
| 662 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 663 | @ var u = rowinfo[p.mu-1]; |
| @@ -758,11 +766,11 @@ | |
| 758 | |
| 759 | /* |
| 760 | ** Create a temporary table suitable for storing timeline data. |
| 761 | */ |
| 762 | static void timeline_temp_table(void){ |
| 763 | static const char zSql[] = |
| 764 | @ CREATE TEMP TABLE IF NOT EXISTS timeline( |
| 765 | @ rid INTEGER PRIMARY KEY, |
| 766 | @ uuid TEXT, |
| 767 | @ timestamp TEXT, |
| 768 | @ comment TEXT, |
| @@ -799,11 +807,11 @@ | |
| 799 | @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid |
| 800 | @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags, |
| 801 | @ tagid AS tagid, |
| 802 | @ brief AS brief, |
| 803 | @ event.mtime AS mtime |
| 804 | @ FROM event CROSS JOIN blob |
| 805 | @ WHERE blob.rid=event.objid |
| 806 | ; |
| 807 | if( zBase==0 ){ |
| 808 | zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH); |
| 809 | } |
| @@ -1167,24 +1175,24 @@ | |
| 1167 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1168 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1169 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1170 | if( rAfter>0.0 ){ |
| 1171 | if( rBefore>0.0 ){ |
| 1172 | blob_appendf(&sql, |
| 1173 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1174 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1175 | url_add_parameter(&url, "a", zAfter); |
| 1176 | url_add_parameter(&url, "b", zBefore); |
| 1177 | nEntry = 1000000; |
| 1178 | }else{ |
| 1179 | blob_appendf(&sql, |
| 1180 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1181 | rAfter-ONE_SECOND); |
| 1182 | url_add_parameter(&url, "a", zAfter); |
| 1183 | } |
| 1184 | }else if( rBefore>0.0 ){ |
| 1185 | blob_appendf(&sql, |
| 1186 | " AND event.mtime<=%.17g ORDER BY event.mtime DESC", |
| 1187 | rBefore+ONE_SECOND); |
| 1188 | url_add_parameter(&url, "b", zBefore); |
| 1189 | }else if( rCirca>0.0 ){ |
| 1190 | Blob sql2; |
| @@ -1300,11 +1308,11 @@ | |
| 1300 | /* |
| 1301 | ** The input query q selects various records. Print a human-readable |
| 1302 | ** summary of those records. |
| 1303 | ** |
| 1304 | ** Limit the number of entries printed to nLine. |
| 1305 | ** |
| 1306 | ** The query should return these columns: |
| 1307 | ** |
| 1308 | ** 0. rid |
| 1309 | ** 1. uuid |
| 1310 | ** 2. Date/Time |
| @@ -1334,11 +1342,11 @@ | |
| 1334 | int nParent = db_column_int(q, 5); |
| 1335 | char *zFree = 0; |
| 1336 | int n = 0; |
| 1337 | char zPrefix[80]; |
| 1338 | char zUuid[UUID_SIZE+1]; |
| 1339 | |
| 1340 | sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId); |
| 1341 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 1342 | fossil_print("=== %.10s ===\n", zDate); |
| 1343 | memcpy(zPrevDate, zDate, 10); |
| 1344 | nLine++; |
| @@ -1368,11 +1376,11 @@ | |
| 1368 | nLine += comment_print(zFree, 9, 79); |
| 1369 | sqlite3_free(zFree); |
| 1370 | |
| 1371 | if(showfiles){ |
| 1372 | if( !fchngQueryInit ){ |
| 1373 | db_prepare(&fchngQuery, |
| 1374 | "SELECT (pid==0) AS isnew," |
| 1375 | " (fid==0) AS isdel," |
| 1376 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 1377 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 1378 | " (SELECT uuid FROM blob WHERE rid=pid)" |
| @@ -1385,11 +1393,11 @@ | |
| 1385 | db_bind_int(&fchngQuery, ":mid", rid); |
| 1386 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 1387 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 1388 | int isNew = db_column_int(&fchngQuery, 0); |
| 1389 | int isDel = db_column_int(&fchngQuery, 1); |
| 1390 | if( isNew ){ |
| 1391 | fossil_print(" ADDED %s\n",zFilename); |
| 1392 | }else if( isDel ){ |
| 1393 | fossil_print(" DELETED %s\n",zFilename); |
| 1394 | }else{ |
| 1395 | fossil_print(" EDITED %s\n", zFilename); |
| @@ -1404,11 +1412,11 @@ | |
| 1404 | /* |
| 1405 | ** Return a pointer to a static string that forms the basis for |
| 1406 | ** a timeline query for display on a TTY. |
| 1407 | */ |
| 1408 | const char *timeline_query_for_tty(void){ |
| 1409 | static const char zBaseSql[] = |
| 1410 | @ SELECT |
| 1411 | @ blob.rid AS rid, |
| 1412 | @ uuid, |
| 1413 | @ datetime(event.mtime,'localtime') AS mDateTime, |
| 1414 | @ coalesce(ecomment,comment) |
| 1415 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -192,10 +192,11 @@ | |
| 192 | const char *zThisUser, /* Suppress links to this user */ |
| 193 | const char *zThisTag, /* Suppress links to this tag */ |
| 194 | void (*xExtra)(int) /* Routine to call on each line of display */ |
| 195 | ){ |
| 196 | int wikiFlags; |
| 197 | int plainText; |
| 198 | int mxWikiLen; |
| 199 | Blob comment; |
| 200 | int prevTagid = 0; |
| 201 | int suppressCnt = 0; |
| 202 | char zPrevDate[20]; |
| @@ -205,10 +206,11 @@ | |
| 206 | Stmt fchngQuery; /* Query for file changes on check-ins */ |
| 207 | static Stmt qbranch; |
| 208 | int pendingEndTr = 0; /* True if a </td></tr> is needed */ |
| 209 | |
| 210 | zPrevDate[0] = 0; |
| 211 | plainText = db_get_int("timeline-plaintext", 0); |
| 212 | mxWikiLen = db_get_int("timeline-max-comment", 0); |
| 213 | if( db_get_boolean("timeline-block-markup", 0) ){ |
| 214 | wikiFlags = WIKI_INLINE; |
| 215 | }else{ |
| 216 | wikiFlags = WIKI_INLINE | WIKI_NOBLOCK; |
| @@ -285,11 +287,11 @@ | |
| 287 | @ <td class="timelineGraph"> |
| 288 | if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0; |
| 289 | if( zType[0]=='c' |
| 290 | && (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0) |
| 291 | ){ |
| 292 | db_reset(&qbranch); |
| 293 | db_bind_int(&qbranch, ":rid", rid); |
| 294 | if( db_step(&qbranch)==SQLITE_ROW ){ |
| 295 | zBr = db_column_text(&qbranch, 0); |
| 296 | }else{ |
| 297 | zBr = "trunk"; |
| @@ -353,12 +355,18 @@ | |
| 355 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| 356 | Blob truncated; |
| 357 | blob_zero(&truncated); |
| 358 | blob_append(&truncated, blob_buffer(&comment), mxWikiLen); |
| 359 | blob_append(&truncated, "...", 3); |
| 360 | if( plainText ){ |
| 361 | @ %h(blob_str(&truncated)) |
| 362 | }else{ |
| 363 | wiki_convert(&truncated, 0, wikiFlags); |
| 364 | } |
| 365 | blob_reset(&truncated); |
| 366 | }else if( plainText ){ |
| 367 | @ %h(blob_str(&comment)); |
| 368 | }else{ |
| 369 | wiki_convert(&comment, 0, wikiFlags); |
| 370 | } |
| 371 | blob_reset(&comment); |
| 372 | |
| @@ -365,11 +373,11 @@ | |
| 373 | /* Generate the "user: USERNAME" at the end of the comment, together |
| 374 | ** with a hyperlink to another timeline for that user. |
| 375 | */ |
| 376 | if( zTagList && zTagList[0]==0 ) zTagList = 0; |
| 377 | if( g.perm.Hyperlink && fossil_strcmp(zUser, zThisUser)!=0 ){ |
| 378 | char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate); |
| 379 | @ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051") |
| 380 | }else{ |
| 381 | @ (user: %h(zUser)%s(zTagList?",":"\051") |
| 382 | } |
| 383 | |
| @@ -390,11 +398,11 @@ | |
| 398 | while( z && z[0] ){ |
| 399 | for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){} |
| 400 | if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){ |
| 401 | blob_appendf(&links, |
| 402 | "%z%#h</a>%.2s", |
| 403 | href("%R/timeline?r=%#t&nd&c=%t",i,z,zDate), i,z, &z[i] |
| 404 | ); |
| 405 | }else{ |
| 406 | blob_appendf(&links, "%#h", i+2, z); |
| 407 | } |
| 408 | if( z[i]==0 ) break; |
| @@ -415,11 +423,11 @@ | |
| 423 | |
| 424 | /* Generate the file-change list if requested */ |
| 425 | if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){ |
| 426 | int inUl = 0; |
| 427 | if( !fchngQueryInit ){ |
| 428 | db_prepare(&fchngQuery, |
| 429 | "SELECT (pid==0) AS isnew," |
| 430 | " (fid==0) AS isdel," |
| 431 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 432 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 433 | " (SELECT uuid FROM blob WHERE rid=pid)," |
| @@ -484,11 +492,11 @@ | |
| 492 | pGraph = 0; |
| 493 | }else{ |
| 494 | /* style is not moved to css, because this is |
| 495 | ** a technical div for the timeline graph |
| 496 | */ |
| 497 | @ <tr><td></td><td> |
| 498 | @ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div> |
| 499 | @ </td></tr> |
| 500 | } |
| 501 | } |
| 502 | @ </table> |
| @@ -653,11 +661,11 @@ | |
| 661 | @ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5); |
| 662 | if( !omitDescenders ){ |
| 663 | @ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5); |
| 664 | @ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2); |
| 665 | @ if( p.d ) drawUpArrow(p.x, p.y+6, btm); |
| 666 | } |
| 667 | @ if( p.mo>0 ){ |
| 668 | @ var x1 = p.mo + left - 1; |
| 669 | @ var y1 = p.y-3; |
| 670 | @ var x0 = x1>p.x ? p.x+7 : p.x-6; |
| 671 | @ var u = rowinfo[p.mu-1]; |
| @@ -758,11 +766,11 @@ | |
| 766 | |
| 767 | /* |
| 768 | ** Create a temporary table suitable for storing timeline data. |
| 769 | */ |
| 770 | static void timeline_temp_table(void){ |
| 771 | static const char zSql[] = |
| 772 | @ CREATE TEMP TABLE IF NOT EXISTS timeline( |
| 773 | @ rid INTEGER PRIMARY KEY, |
| 774 | @ uuid TEXT, |
| 775 | @ timestamp TEXT, |
| 776 | @ comment TEXT, |
| @@ -799,11 +807,11 @@ | |
| 807 | @ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid |
| 808 | @ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags, |
| 809 | @ tagid AS tagid, |
| 810 | @ brief AS brief, |
| 811 | @ event.mtime AS mtime |
| 812 | @ FROM event CROSS JOIN blob |
| 813 | @ WHERE blob.rid=event.objid |
| 814 | ; |
| 815 | if( zBase==0 ){ |
| 816 | zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH); |
| 817 | } |
| @@ -1167,24 +1175,24 @@ | |
| 1175 | rBefore = symbolic_name_to_mtime(zBefore); |
| 1176 | rAfter = symbolic_name_to_mtime(zAfter); |
| 1177 | rCirca = symbolic_name_to_mtime(zCirca); |
| 1178 | if( rAfter>0.0 ){ |
| 1179 | if( rBefore>0.0 ){ |
| 1180 | blob_appendf(&sql, |
| 1181 | " AND event.mtime>=%.17g AND event.mtime<=%.17g" |
| 1182 | " ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND); |
| 1183 | url_add_parameter(&url, "a", zAfter); |
| 1184 | url_add_parameter(&url, "b", zBefore); |
| 1185 | nEntry = 1000000; |
| 1186 | }else{ |
| 1187 | blob_appendf(&sql, |
| 1188 | " AND event.mtime>=%.17g ORDER BY event.mtime ASC", |
| 1189 | rAfter-ONE_SECOND); |
| 1190 | url_add_parameter(&url, "a", zAfter); |
| 1191 | } |
| 1192 | }else if( rBefore>0.0 ){ |
| 1193 | blob_appendf(&sql, |
| 1194 | " AND event.mtime<=%.17g ORDER BY event.mtime DESC", |
| 1195 | rBefore+ONE_SECOND); |
| 1196 | url_add_parameter(&url, "b", zBefore); |
| 1197 | }else if( rCirca>0.0 ){ |
| 1198 | Blob sql2; |
| @@ -1300,11 +1308,11 @@ | |
| 1308 | /* |
| 1309 | ** The input query q selects various records. Print a human-readable |
| 1310 | ** summary of those records. |
| 1311 | ** |
| 1312 | ** Limit the number of entries printed to nLine. |
| 1313 | ** |
| 1314 | ** The query should return these columns: |
| 1315 | ** |
| 1316 | ** 0. rid |
| 1317 | ** 1. uuid |
| 1318 | ** 2. Date/Time |
| @@ -1334,11 +1342,11 @@ | |
| 1342 | int nParent = db_column_int(q, 5); |
| 1343 | char *zFree = 0; |
| 1344 | int n = 0; |
| 1345 | char zPrefix[80]; |
| 1346 | char zUuid[UUID_SIZE+1]; |
| 1347 | |
| 1348 | sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId); |
| 1349 | if( memcmp(zDate, zPrevDate, 10) ){ |
| 1350 | fossil_print("=== %.10s ===\n", zDate); |
| 1351 | memcpy(zPrevDate, zDate, 10); |
| 1352 | nLine++; |
| @@ -1368,11 +1376,11 @@ | |
| 1376 | nLine += comment_print(zFree, 9, 79); |
| 1377 | sqlite3_free(zFree); |
| 1378 | |
| 1379 | if(showfiles){ |
| 1380 | if( !fchngQueryInit ){ |
| 1381 | db_prepare(&fchngQuery, |
| 1382 | "SELECT (pid==0) AS isnew," |
| 1383 | " (fid==0) AS isdel," |
| 1384 | " (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name," |
| 1385 | " (SELECT uuid FROM blob WHERE rid=fid)," |
| 1386 | " (SELECT uuid FROM blob WHERE rid=pid)" |
| @@ -1385,11 +1393,11 @@ | |
| 1393 | db_bind_int(&fchngQuery, ":mid", rid); |
| 1394 | while( db_step(&fchngQuery)==SQLITE_ROW ){ |
| 1395 | const char *zFilename = db_column_text(&fchngQuery, 2); |
| 1396 | int isNew = db_column_int(&fchngQuery, 0); |
| 1397 | int isDel = db_column_int(&fchngQuery, 1); |
| 1398 | if( isNew ){ |
| 1399 | fossil_print(" ADDED %s\n",zFilename); |
| 1400 | }else if( isDel ){ |
| 1401 | fossil_print(" DELETED %s\n",zFilename); |
| 1402 | }else{ |
| 1403 | fossil_print(" EDITED %s\n", zFilename); |
| @@ -1404,11 +1412,11 @@ | |
| 1412 | /* |
| 1413 | ** Return a pointer to a static string that forms the basis for |
| 1414 | ** a timeline query for display on a TTY. |
| 1415 | */ |
| 1416 | const char *timeline_query_for_tty(void){ |
| 1417 | static const char zBaseSql[] = |
| 1418 | @ SELECT |
| 1419 | @ blob.rid AS rid, |
| 1420 | @ uuid, |
| 1421 | @ datetime(event.mtime,'localtime') AS mDateTime, |
| 1422 | @ coalesce(ecomment,comment) |
| 1423 |
+1
-1
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -322,11 +322,11 @@ | ||
| 322 | 322 | ** Complete the undo process is one is currently in process. |
| 323 | 323 | */ |
| 324 | 324 | void undo_finish(void){ |
| 325 | 325 | if( undoActive ){ |
| 326 | 326 | if( undoNeedRollback ){ |
| 327 | - fossil_print("\"fossil undo\" is available to undo changes" | |
| 327 | + fossil_print(" \"fossil undo\" is available to undo changes" | |
| 328 | 328 | " to the working checkout.\n"); |
| 329 | 329 | } |
| 330 | 330 | undoActive = 0; |
| 331 | 331 | undoNeedRollback = 0; |
| 332 | 332 | } |
| 333 | 333 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -322,11 +322,11 @@ | |
| 322 | ** Complete the undo process is one is currently in process. |
| 323 | */ |
| 324 | void undo_finish(void){ |
| 325 | if( undoActive ){ |
| 326 | if( undoNeedRollback ){ |
| 327 | fossil_print("\"fossil undo\" is available to undo changes" |
| 328 | " to the working checkout.\n"); |
| 329 | } |
| 330 | undoActive = 0; |
| 331 | undoNeedRollback = 0; |
| 332 | } |
| 333 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -322,11 +322,11 @@ | |
| 322 | ** Complete the undo process is one is currently in process. |
| 323 | */ |
| 324 | void undo_finish(void){ |
| 325 | if( undoActive ){ |
| 326 | if( undoNeedRollback ){ |
| 327 | fossil_print(" \"fossil undo\" is available to undo changes" |
| 328 | " to the working checkout.\n"); |
| 329 | } |
| 330 | undoActive = 0; |
| 331 | undoNeedRollback = 0; |
| 332 | } |
| 333 |
+19
-8
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -217,19 +217,20 @@ | ||
| 217 | 217 | " islinkv BOOLEAN," /* True if current file is a link */ |
| 218 | 218 | " islinkt BOOLEAN," /* True if target file is a link */ |
| 219 | 219 | " ridv INTEGER," /* Record ID for current version */ |
| 220 | 220 | " ridt INTEGER," /* Record ID for target */ |
| 221 | 221 | " isexe BOOLEAN," /* Does target have execute permission? */ |
| 222 | + " deleted BOOLEAN DEFAULT 0,"/* File marke by "rm" to become unmanaged */ | |
| 222 | 223 | " fnt TEXT" /* Filename of same file on target version */ |
| 223 | 224 | ");" |
| 224 | 225 | ); |
| 225 | 226 | |
| 226 | 227 | /* Add files found in the current version |
| 227 | 228 | */ |
| 228 | 229 | db_multi_exec( |
| 229 | - "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" | |
| 230 | - " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged" | |
| 230 | + "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged,deleted)" | |
| 231 | + " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged, deleted" | |
| 231 | 232 | " FROM vfile WHERE vid=%d", |
| 232 | 233 | vid |
| 233 | 234 | ); |
| 234 | 235 | |
| 235 | 236 | /* Compute file name changes on V->T. Record name changes in files that |
| @@ -339,11 +340,11 @@ | ||
| 339 | 340 | ** Alter the content of the checkout so that it conforms with the |
| 340 | 341 | ** target |
| 341 | 342 | */ |
| 342 | 343 | db_prepare(&q, |
| 343 | 344 | "SELECT fn, idv, ridv, idt, ridt, chnged, fnt," |
| 344 | - " isexe, islinkv, islinkt FROM fv ORDER BY 1" | |
| 345 | + " isexe, islinkv, islinkt, deleted FROM fv ORDER BY 1" | |
| 345 | 346 | ); |
| 346 | 347 | db_prepare(&mtimeXfer, |
| 347 | 348 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 348 | 349 | " WHERE id=:idt" |
| 349 | 350 | ); |
| @@ -359,43 +360,52 @@ | ||
| 359 | 360 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 360 | 361 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 361 | 362 | int isexe = db_column_int(&q, 7); /* EXE perm for new file */ |
| 362 | 363 | int islinkv = db_column_int(&q, 8); /* Is current file is a link */ |
| 363 | 364 | int islinkt = db_column_int(&q, 9); /* Is target file is a link */ |
| 365 | + int deleted = db_column_int(&q, 10); /* Marked for deletion */ | |
| 364 | 366 | char *zFullPath; /* Full pathname of the file */ |
| 365 | 367 | char *zFullNewPath; /* Full pathname of dest */ |
| 366 | 368 | char nameChng; /* True if the name changed */ |
| 367 | 369 | |
| 368 | 370 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| 369 | 371 | zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); |
| 370 | 372 | nameChng = fossil_strcmp(zName, zNewName); |
| 371 | 373 | nUpdate++; |
| 374 | + if( deleted ){ | |
| 375 | + db_multi_exec("UPDATE vfile SET deleted=1 WHERE id=%d", idt); | |
| 376 | + } | |
| 372 | 377 | if( idv>0 && ridv==0 && idt>0 && ridt>0 ){ |
| 373 | 378 | /* Conflict. This file has been added to the current checkout |
| 374 | 379 | ** but also exists in the target checkout. Use the current version. |
| 375 | 380 | */ |
| 376 | 381 | fossil_print("CONFLICT %s\n", zName); |
| 377 | 382 | nConflict++; |
| 378 | 383 | }else if( idt>0 && idv==0 ){ |
| 379 | 384 | /* File added in the target. */ |
| 380 | 385 | if( file_wd_isfile_or_link(zFullPath) ){ |
| 381 | - fossil_print("ADD %s (overwrites an unmanaged file)\n", zName); | |
| 386 | + fossil_print("ADD %s - overwrites an unmanaged file\n", zName); | |
| 382 | 387 | nOverwrite++; |
| 383 | 388 | }else{ |
| 384 | 389 | fossil_print("ADD %s\n", zName); |
| 385 | 390 | } |
| 386 | 391 | undo_save(zName); |
| 387 | 392 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 388 | - }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){ | |
| 393 | + }else if( idt>0 && idv>0 && ridt!=ridv && (chnged==0 || deleted) ){ | |
| 389 | 394 | /* The file is unedited. Change it to the target version */ |
| 390 | 395 | undo_save(zName); |
| 391 | - fossil_print("UPDATE %s\n", zName); | |
| 396 | + if( deleted ){ | |
| 397 | + fossil_print("UPDATE %s - change to unmanged file\n", zName); | |
| 398 | + }else{ | |
| 399 | + fossil_print("UPDATE %s\n", zName); | |
| 400 | + } | |
| 392 | 401 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 393 | 402 | }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){ |
| 394 | 403 | /* The file missing from the local check-out. Restore it to the |
| 395 | 404 | ** version that appears in the target. */ |
| 396 | - fossil_print("UPDATE %s\n", zName); | |
| 405 | + fossil_print("UPDATE %s%s\n", zName, | |
| 406 | + deleted?" - change to unmanaged file":""); | |
| 397 | 407 | undo_save(zName); |
| 398 | 408 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 399 | 409 | }else if( idt==0 && idv>0 ){ |
| 400 | 410 | if( ridv==0 ){ |
| 401 | 411 | /* Added in current checkout. Continue to hold the file as |
| @@ -423,14 +433,15 @@ | ||
| 423 | 433 | } |
| 424 | 434 | if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){ |
| 425 | 435 | fossil_print("***** Cannot merge symlink %s\n", zNewName); |
| 426 | 436 | nConflict++; |
| 427 | 437 | }else{ |
| 438 | + unsigned mergeFlags = nochangeFlag ? MERGE_DRYRUN : 0; | |
| 428 | 439 | undo_save(zName); |
| 429 | 440 | content_get(ridt, &t); |
| 430 | 441 | content_get(ridv, &v); |
| 431 | - rc = merge_3way(&v, zFullPath, &t, &r); | |
| 442 | + rc = merge_3way(&v, zFullPath, &t, &r, mergeFlags); | |
| 432 | 443 | if( rc>=0 ){ |
| 433 | 444 | if( !nochangeFlag ){ |
| 434 | 445 | blob_write_to_file(&r, zFullNewPath); |
| 435 | 446 | file_wd_setexe(zFullNewPath, isexe); |
| 436 | 447 | } |
| 437 | 448 | |
| 438 | 449 | ADDED test/update-test-1.sh |
| 439 | 450 | ADDED test/update-test-2.sh |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -217,19 +217,20 @@ | |
| 217 | " islinkv BOOLEAN," /* True if current file is a link */ |
| 218 | " islinkt BOOLEAN," /* True if target file is a link */ |
| 219 | " ridv INTEGER," /* Record ID for current version */ |
| 220 | " ridt INTEGER," /* Record ID for target */ |
| 221 | " isexe BOOLEAN," /* Does target have execute permission? */ |
| 222 | " fnt TEXT" /* Filename of same file on target version */ |
| 223 | ");" |
| 224 | ); |
| 225 | |
| 226 | /* Add files found in the current version |
| 227 | */ |
| 228 | db_multi_exec( |
| 229 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged)" |
| 230 | " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged" |
| 231 | " FROM vfile WHERE vid=%d", |
| 232 | vid |
| 233 | ); |
| 234 | |
| 235 | /* Compute file name changes on V->T. Record name changes in files that |
| @@ -339,11 +340,11 @@ | |
| 339 | ** Alter the content of the checkout so that it conforms with the |
| 340 | ** target |
| 341 | */ |
| 342 | db_prepare(&q, |
| 343 | "SELECT fn, idv, ridv, idt, ridt, chnged, fnt," |
| 344 | " isexe, islinkv, islinkt FROM fv ORDER BY 1" |
| 345 | ); |
| 346 | db_prepare(&mtimeXfer, |
| 347 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 348 | " WHERE id=:idt" |
| 349 | ); |
| @@ -359,43 +360,52 @@ | |
| 359 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 360 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 361 | int isexe = db_column_int(&q, 7); /* EXE perm for new file */ |
| 362 | int islinkv = db_column_int(&q, 8); /* Is current file is a link */ |
| 363 | int islinkt = db_column_int(&q, 9); /* Is target file is a link */ |
| 364 | char *zFullPath; /* Full pathname of the file */ |
| 365 | char *zFullNewPath; /* Full pathname of dest */ |
| 366 | char nameChng; /* True if the name changed */ |
| 367 | |
| 368 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| 369 | zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); |
| 370 | nameChng = fossil_strcmp(zName, zNewName); |
| 371 | nUpdate++; |
| 372 | if( idv>0 && ridv==0 && idt>0 && ridt>0 ){ |
| 373 | /* Conflict. This file has been added to the current checkout |
| 374 | ** but also exists in the target checkout. Use the current version. |
| 375 | */ |
| 376 | fossil_print("CONFLICT %s\n", zName); |
| 377 | nConflict++; |
| 378 | }else if( idt>0 && idv==0 ){ |
| 379 | /* File added in the target. */ |
| 380 | if( file_wd_isfile_or_link(zFullPath) ){ |
| 381 | fossil_print("ADD %s (overwrites an unmanaged file)\n", zName); |
| 382 | nOverwrite++; |
| 383 | }else{ |
| 384 | fossil_print("ADD %s\n", zName); |
| 385 | } |
| 386 | undo_save(zName); |
| 387 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 388 | }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){ |
| 389 | /* The file is unedited. Change it to the target version */ |
| 390 | undo_save(zName); |
| 391 | fossil_print("UPDATE %s\n", zName); |
| 392 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 393 | }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){ |
| 394 | /* The file missing from the local check-out. Restore it to the |
| 395 | ** version that appears in the target. */ |
| 396 | fossil_print("UPDATE %s\n", zName); |
| 397 | undo_save(zName); |
| 398 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 399 | }else if( idt==0 && idv>0 ){ |
| 400 | if( ridv==0 ){ |
| 401 | /* Added in current checkout. Continue to hold the file as |
| @@ -423,14 +433,15 @@ | |
| 423 | } |
| 424 | if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){ |
| 425 | fossil_print("***** Cannot merge symlink %s\n", zNewName); |
| 426 | nConflict++; |
| 427 | }else{ |
| 428 | undo_save(zName); |
| 429 | content_get(ridt, &t); |
| 430 | content_get(ridv, &v); |
| 431 | rc = merge_3way(&v, zFullPath, &t, &r); |
| 432 | if( rc>=0 ){ |
| 433 | if( !nochangeFlag ){ |
| 434 | blob_write_to_file(&r, zFullNewPath); |
| 435 | file_wd_setexe(zFullNewPath, isexe); |
| 436 | } |
| 437 | |
| 438 | DDED test/update-test-1.sh |
| 439 | DDED test/update-test-2.sh |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -217,19 +217,20 @@ | |
| 217 | " islinkv BOOLEAN," /* True if current file is a link */ |
| 218 | " islinkt BOOLEAN," /* True if target file is a link */ |
| 219 | " ridv INTEGER," /* Record ID for current version */ |
| 220 | " ridt INTEGER," /* Record ID for target */ |
| 221 | " isexe BOOLEAN," /* Does target have execute permission? */ |
| 222 | " deleted BOOLEAN DEFAULT 0,"/* File marke by "rm" to become unmanaged */ |
| 223 | " fnt TEXT" /* Filename of same file on target version */ |
| 224 | ");" |
| 225 | ); |
| 226 | |
| 227 | /* Add files found in the current version |
| 228 | */ |
| 229 | db_multi_exec( |
| 230 | "INSERT OR IGNORE INTO fv(fn,fnt,idv,idt,ridv,ridt,isexe,chnged,deleted)" |
| 231 | " SELECT pathname, pathname, id, 0, rid, 0, isexe, chnged, deleted" |
| 232 | " FROM vfile WHERE vid=%d", |
| 233 | vid |
| 234 | ); |
| 235 | |
| 236 | /* Compute file name changes on V->T. Record name changes in files that |
| @@ -339,11 +340,11 @@ | |
| 340 | ** Alter the content of the checkout so that it conforms with the |
| 341 | ** target |
| 342 | */ |
| 343 | db_prepare(&q, |
| 344 | "SELECT fn, idv, ridv, idt, ridt, chnged, fnt," |
| 345 | " isexe, islinkv, islinkt, deleted FROM fv ORDER BY 1" |
| 346 | ); |
| 347 | db_prepare(&mtimeXfer, |
| 348 | "UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)" |
| 349 | " WHERE id=:idt" |
| 350 | ); |
| @@ -359,43 +360,52 @@ | |
| 360 | int chnged = db_column_int(&q, 5); /* Current is edited */ |
| 361 | const char *zNewName = db_column_text(&q,6);/* New filename */ |
| 362 | int isexe = db_column_int(&q, 7); /* EXE perm for new file */ |
| 363 | int islinkv = db_column_int(&q, 8); /* Is current file is a link */ |
| 364 | int islinkt = db_column_int(&q, 9); /* Is target file is a link */ |
| 365 | int deleted = db_column_int(&q, 10); /* Marked for deletion */ |
| 366 | char *zFullPath; /* Full pathname of the file */ |
| 367 | char *zFullNewPath; /* Full pathname of dest */ |
| 368 | char nameChng; /* True if the name changed */ |
| 369 | |
| 370 | zFullPath = mprintf("%s%s", g.zLocalRoot, zName); |
| 371 | zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); |
| 372 | nameChng = fossil_strcmp(zName, zNewName); |
| 373 | nUpdate++; |
| 374 | if( deleted ){ |
| 375 | db_multi_exec("UPDATE vfile SET deleted=1 WHERE id=%d", idt); |
| 376 | } |
| 377 | if( idv>0 && ridv==0 && idt>0 && ridt>0 ){ |
| 378 | /* Conflict. This file has been added to the current checkout |
| 379 | ** but also exists in the target checkout. Use the current version. |
| 380 | */ |
| 381 | fossil_print("CONFLICT %s\n", zName); |
| 382 | nConflict++; |
| 383 | }else if( idt>0 && idv==0 ){ |
| 384 | /* File added in the target. */ |
| 385 | if( file_wd_isfile_or_link(zFullPath) ){ |
| 386 | fossil_print("ADD %s - overwrites an unmanaged file\n", zName); |
| 387 | nOverwrite++; |
| 388 | }else{ |
| 389 | fossil_print("ADD %s\n", zName); |
| 390 | } |
| 391 | undo_save(zName); |
| 392 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 393 | }else if( idt>0 && idv>0 && ridt!=ridv && (chnged==0 || deleted) ){ |
| 394 | /* The file is unedited. Change it to the target version */ |
| 395 | undo_save(zName); |
| 396 | if( deleted ){ |
| 397 | fossil_print("UPDATE %s - change to unmanged file\n", zName); |
| 398 | }else{ |
| 399 | fossil_print("UPDATE %s\n", zName); |
| 400 | } |
| 401 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 402 | }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){ |
| 403 | /* The file missing from the local check-out. Restore it to the |
| 404 | ** version that appears in the target. */ |
| 405 | fossil_print("UPDATE %s%s\n", zName, |
| 406 | deleted?" - change to unmanaged file":""); |
| 407 | undo_save(zName); |
| 408 | if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); |
| 409 | }else if( idt==0 && idv>0 ){ |
| 410 | if( ridv==0 ){ |
| 411 | /* Added in current checkout. Continue to hold the file as |
| @@ -423,14 +433,15 @@ | |
| 433 | } |
| 434 | if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){ |
| 435 | fossil_print("***** Cannot merge symlink %s\n", zNewName); |
| 436 | nConflict++; |
| 437 | }else{ |
| 438 | unsigned mergeFlags = nochangeFlag ? MERGE_DRYRUN : 0; |
| 439 | undo_save(zName); |
| 440 | content_get(ridt, &t); |
| 441 | content_get(ridv, &v); |
| 442 | rc = merge_3way(&v, zFullPath, &t, &r, mergeFlags); |
| 443 | if( rc>=0 ){ |
| 444 | if( !nochangeFlag ){ |
| 445 | blob_write_to_file(&r, zFullNewPath); |
| 446 | file_wd_setexe(zFullNewPath, isexe); |
| 447 | } |
| 448 | |
| 449 | DDED test/update-test-1.sh |
| 450 | DDED test/update-test-2.sh |
+44
| --- a/test/update-test-1.sh | ||
| +++ b/test/update-test-1.sh | ||
| @@ -0,0 +1,44 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# | |
| 3 | +# Run this script in an empty directory. A single argument is the full | |
| 4 | +# pathname of the fossil binary. Example: | |
| 5 | +# | |
| 6 | +# sh update-test-1.sh /home/drh/fossil/m1/fossil | |
| 7 | +# | |
| 8 | +export FOSSIL=$1 | |
| 9 | +rm -rf aaa bbb update-test-1.fossil | |
| 10 | + | |
| 11 | +# Create a test repository | |
| 12 | +$FOSSIL new update-test-1.fossil | |
| 13 | + | |
| 14 | +# In checkout aaa, add file one.txt | |
| 15 | +mkdir aaa | |
| 16 | +cd aaa | |
| 17 | +$FOSSIL open ../update-test-1.fossil | |
| 18 | +echo one >one.txt | |
| 19 | +$FOSSIL add one.txt | |
| 20 | +$FOSSIL commit -m add-one --tag add-one | |
| 21 | + | |
| 22 | +# Open checkout bbb. | |
| 23 | +mkdir ../bbb | |
| 24 | +cd ../bbb | |
| 25 | +$FOSSIL open ../update-test-1.fossil | |
| 26 | + | |
| 27 | +# Back in aaa, add file two.txt | |
| 28 | +cd ../aaa | |
| 29 | +echo two >two.txt | |
| 30 | +$FOSSIL add two.txt | |
| 31 | +$FOSSIL commit -m add-two --tag add-two | |
| 32 | + | |
| 33 | +# In bbb, delete file one.txt. Then update the change from aaa that | |
| 34 | +# adds file two. Verify that one.txt says deleted. | |
| 35 | +cd ../bbb | |
| 36 | +$FOSSIL rm one.txt | |
| 37 | +$FOSSIL changes | |
| 38 | +echo '========================================================================' | |
| 39 | +$FOSSIL update | |
| 40 | +echo '======== The previous should show "ADD two.txt" ========================' | |
| 41 | +$FOSSIL changes | |
| 42 | +echo '======== The previous should show "DELETE one.txt" =====================' | |
| 43 | +$FOSSIL commit --test -m check-in | |
| 44 | +echo '======== Only file two.txt is checked in ===============================' |
| --- a/test/update-test-1.sh | |
| +++ b/test/update-test-1.sh | |
| @@ -0,0 +1,44 @@ | |
| --- a/test/update-test-1.sh | |
| +++ b/test/update-test-1.sh | |
| @@ -0,0 +1,44 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this script in an empty directory. A single argument is the full |
| 4 | # pathname of the fossil binary. Example: |
| 5 | # |
| 6 | # sh update-test-1.sh /home/drh/fossil/m1/fossil |
| 7 | # |
| 8 | export FOSSIL=$1 |
| 9 | rm -rf aaa bbb update-test-1.fossil |
| 10 | |
| 11 | # Create a test repository |
| 12 | $FOSSIL new update-test-1.fossil |
| 13 | |
| 14 | # In checkout aaa, add file one.txt |
| 15 | mkdir aaa |
| 16 | cd aaa |
| 17 | $FOSSIL open ../update-test-1.fossil |
| 18 | echo one >one.txt |
| 19 | $FOSSIL add one.txt |
| 20 | $FOSSIL commit -m add-one --tag add-one |
| 21 | |
| 22 | # Open checkout bbb. |
| 23 | mkdir ../bbb |
| 24 | cd ../bbb |
| 25 | $FOSSIL open ../update-test-1.fossil |
| 26 | |
| 27 | # Back in aaa, add file two.txt |
| 28 | cd ../aaa |
| 29 | echo two >two.txt |
| 30 | $FOSSIL add two.txt |
| 31 | $FOSSIL commit -m add-two --tag add-two |
| 32 | |
| 33 | # In bbb, delete file one.txt. Then update the change from aaa that |
| 34 | # adds file two. Verify that one.txt says deleted. |
| 35 | cd ../bbb |
| 36 | $FOSSIL rm one.txt |
| 37 | $FOSSIL changes |
| 38 | echo '========================================================================' |
| 39 | $FOSSIL update |
| 40 | echo '======== The previous should show "ADD two.txt" ========================' |
| 41 | $FOSSIL changes |
| 42 | echo '======== The previous should show "DELETE one.txt" =====================' |
| 43 | $FOSSIL commit --test -m check-in |
| 44 | echo '======== Only file two.txt is checked in ===============================' |
+44
| --- a/test/update-test-2.sh | ||
| +++ b/test/update-test-2.sh | ||
| @@ -0,0 +1,44 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +# | |
| 3 | +# Run this script in an empty directory. A single argument is the full | |
| 4 | +# pathname of the fossil binary. Example: | |
| 5 | +# | |
| 6 | +# sh update-test-2.sh /home/drh/fossil/m1/fossil | |
| 7 | +# | |
| 8 | +export FOSSIL=$1 | |
| 9 | +rm -rf aaa bbb update-test-2.fossil | |
| 10 | + | |
| 11 | +# Create a test repository | |
| 12 | +$FOSSIL new update-test-2.fossil | |
| 13 | + | |
| 14 | +# In checkout aaa, add file one.txt. | |
| 15 | +mkdir aaa | |
| 16 | +cd aaa | |
| 17 | +$FOSSIL open ../update-test-2.fossil | |
| 18 | +echo one >one.txt | |
| 19 | +$FOSSIL add one.txt | |
| 20 | +$FOSSIL commit -m add-one --tag add-one | |
| 21 | + | |
| 22 | +# Create checkout bbb. | |
| 23 | +mkdir ../bbb | |
| 24 | +cd ../bbb | |
| 25 | +$FOSSIL open ../update-test-2.fossil | |
| 26 | + | |
| 27 | +# Back in aaa, make changes to one.txt. Add file two.txt. | |
| 28 | +cd ../aaa | |
| 29 | +echo change >>one.txt | |
| 30 | +echo two >two.txt | |
| 31 | +$FOSSIL add two.txt | |
| 32 | +$FOSSIL commit -m 'chng one and add two' --tag add-two | |
| 33 | + | |
| 34 | +# In bbb, remove one.txt, then update. | |
| 35 | +cd ../bbb | |
| 36 | +$FOSSIL rm one.txt | |
| 37 | +$FOSSIL changes | |
| 38 | +echo '========================================================================' | |
| 39 | +$FOSSIL update | |
| 40 | +echo '======== Previous should show "ADD two.txt" and conflict on one.txt ====' | |
| 41 | +$FOSSIL changes | |
| 42 | +echo '======== The previous should show "DELETE one.txt" =====================' | |
| 43 | +$FOSSIL commit --test -m 'check-in' | |
| 44 | +echo '======== Only file two.txt is checked in ===============================' |
| --- a/test/update-test-2.sh | |
| +++ b/test/update-test-2.sh | |
| @@ -0,0 +1,44 @@ | |
| --- a/test/update-test-2.sh | |
| +++ b/test/update-test-2.sh | |
| @@ -0,0 +1,44 @@ | |
| 1 | #!/bin/sh |
| 2 | # |
| 3 | # Run this script in an empty directory. A single argument is the full |
| 4 | # pathname of the fossil binary. Example: |
| 5 | # |
| 6 | # sh update-test-2.sh /home/drh/fossil/m1/fossil |
| 7 | # |
| 8 | export FOSSIL=$1 |
| 9 | rm -rf aaa bbb update-test-2.fossil |
| 10 | |
| 11 | # Create a test repository |
| 12 | $FOSSIL new update-test-2.fossil |
| 13 | |
| 14 | # In checkout aaa, add file one.txt. |
| 15 | mkdir aaa |
| 16 | cd aaa |
| 17 | $FOSSIL open ../update-test-2.fossil |
| 18 | echo one >one.txt |
| 19 | $FOSSIL add one.txt |
| 20 | $FOSSIL commit -m add-one --tag add-one |
| 21 | |
| 22 | # Create checkout bbb. |
| 23 | mkdir ../bbb |
| 24 | cd ../bbb |
| 25 | $FOSSIL open ../update-test-2.fossil |
| 26 | |
| 27 | # Back in aaa, make changes to one.txt. Add file two.txt. |
| 28 | cd ../aaa |
| 29 | echo change >>one.txt |
| 30 | echo two >two.txt |
| 31 | $FOSSIL add two.txt |
| 32 | $FOSSIL commit -m 'chng one and add two' --tag add-two |
| 33 | |
| 34 | # In bbb, remove one.txt, then update. |
| 35 | cd ../bbb |
| 36 | $FOSSIL rm one.txt |
| 37 | $FOSSIL changes |
| 38 | echo '========================================================================' |
| 39 | $FOSSIL update |
| 40 | echo '======== Previous should show "ADD two.txt" and conflict on one.txt ====' |
| 41 | $FOSSIL changes |
| 42 | echo '======== The previous should show "DELETE one.txt" =====================' |
| 43 | $FOSSIL commit --test -m 'check-in' |
| 44 | echo '======== Only file two.txt is checked in ===============================' |