Fossil SCM

merge trunk. <p>simplify utf-8 continuation byte checking, using a loop in stead of separater 2/3/4-byte versions.

jan.nijtmans 2012-11-07 09:43 improve_commit_warning merge
Commit 2f7ac60f78e68d1e20e4f79d2d9b68097e0d2200
+1 -1
--- src/blob.c
+++ src/blob.c
@@ -800,11 +800,11 @@
800800
** The if stops us from trying to create a directory of a drive letter
801801
** C: in this example.
802802
*/
803803
if( !(i==2 && zName[1]==':') ){
804804
#endif
805
- if( file_mkdir(zName, 1) ){
805
+ if( file_mkdir(zName, 1) && file_isdir(zName)!=1 ){
806806
fossil_fatal_recursive("unable to create directory %s", zName);
807807
return 0;
808808
}
809809
#if defined(_WIN32)
810810
}
811811
--- 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 @@
154154
for(i=0; i<nLine; i++){
155155
a[i].z = z;
156156
for(j=0; z[j] && z[j]!='\n'; j++){}
157157
k = j;
158158
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++){
160160
h = h ^ (h<<2) ^ z[x];
161161
}
162162
a[i].h = h = (h<<LENGTH_MASK_SZ) | k;;
163163
h2 = h % nLine;
164164
a[i].iNext = a[h2].iHash;
@@ -181,33 +181,22 @@
181181
** Any invalid byte causes bit 2 of result to be set (result |= 4),
182182
** otherwise for valid multibyte utf-8 sequences n, j and z are
183183
** updated so the continuation bytes are not checked again.
184184
*/
185185
#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 );
209198
210199
/*
211200
** This function attempts to scan each logical line within the blob to
212201
** determine the type of content it appears to contain. Possible return
213202
** values are:
@@ -836,11 +825,15 @@
836825
if( nPrefix+nSuffix==nLeft ){
837826
sbsWriteLineno(p, lnLeft);
838827
p->iStart2 = p->iEnd2 = 0;
839828
p->iStart = p->iEnd = -1;
840829
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
+ }
842835
sbsWriteLineno(p, lnRight);
843836
p->iStart = nPrefix;
844837
p->iEnd = nRight - nSuffix;
845838
p->zStart = zClassAdd;
846839
sbsWriteText(p, pRight, SBS_NEWLINE);
847840
--- 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 @@
154154
for(i=0; i<nLine; i++){
155155
a[i].z = z;
156156
for(j=0; z[j] && z[j]!='\n'; j++){}
157157
k = j;
158158
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++){
160160
h = h ^ (h<<2) ^ z[x];
161161
}
162162
a[i].h = h = (h<<LENGTH_MASK_SZ) | k;;
163163
h2 = h % nLine;
164164
a[i].iNext = a[h2].iHash;
@@ -181,33 +181,22 @@
181181
** Any invalid byte causes bit 2 of result to be set (result |= 4),
182182
** otherwise for valid multibyte utf-8 sequences n, j and z are
183183
** updated so the continuation bytes are not checked again.
184184
*/
185185
#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 );
209198
210199
/*
211200
** This function attempts to scan each logical line within the blob to
212201
** determine the type of content it appears to contain. Possible return
213202
** values are:
@@ -836,11 +825,15 @@
836825
if( nPrefix+nSuffix==nLeft ){
837826
sbsWriteLineno(p, lnLeft);
838827
p->iStart2 = p->iEnd2 = 0;
839828
p->iStart = p->iEnd = -1;
840829
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
+ }
842835
sbsWriteLineno(p, lnRight);
843836
p->iStart = nPrefix;
844837
p->iEnd = nRight - nSuffix;
845838
p->zStart = zClassAdd;
846839
sbsWriteText(p, pRight, SBS_NEWLINE);
847840
--- 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 @@
457457
content_get(ridm, &m);
458458
if( isBinary ){
459459
rc = -1;
460460
blob_zero(&r);
461461
}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);
463464
}
464465
if( rc>=0 ){
465466
if( !nochangeFlag ){
466467
blob_write_to_file(&r, zFullPath);
467468
file_wd_setexe(zFullPath, isExe);
@@ -549,18 +550,20 @@
549550
db_finalize(&q);
550551
551552
552553
/* Report on conflicts
553554
*/
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.");
562565
}
563566
564567
/*
565568
** Clean up the mid and pid VFILE entries. Then commit the changes.
566569
*/
567570
--- 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 @@
5959
6060
/*
6161
** Look at the next edit triple in both aC1 and aC2. (An "edit triple" is
6262
** three integers describing the number of copies, deletes, and inserts in
6363
** 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.
6565
** If the edits are different, return 0.
6666
*/
6767
static int sameEdit(
6868
int *aC1, /* Array of edit integers for file 1 */
6969
int *aC2, /* Array of edit integers for file 2 */
@@ -154,11 +154,11 @@
154154
** common origin at pPivot. Apply the changes of pPivot ==> pV1
155155
** to pV2.
156156
**
157157
** The return is 0 upon complete success. If any input file is binary,
158158
** -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
160160
** of conflicts is returns
161161
*/
162162
static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){
163163
int *aC1; /* Changes from pPivot to pV1 */
164164
int *aC2; /* Changes from pPivot to pV2 */
@@ -406,10 +406,17 @@
406406
}
407407
}
408408
return blob_str(&x);
409409
}
410410
411
+#if INTERFACE
412
+/*
413
+** Flags to the 3-way merger
414
+*/
415
+#define MERGE_DRYRUN 0x0001
416
+#endif
417
+
411418
412419
/*
413420
** This routine is a wrapper around blob_merge() with the following
414421
** enhancements:
415422
**
@@ -428,59 +435,59 @@
428435
*/
429436
int merge_3way(
430437
Blob *pPivot, /* Common ancestor (older) */
431438
const char *zV1, /* Name of file for version merging into (mine) */
432439
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 */
434442
){
435443
Blob v1; /* Content of zV1 */
436444
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 */
440445
441446
blob_read_from_file(&v1, zV1);
442447
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
+
444453
zPivot = file_newname(zV1, "baseline", 1);
445454
blob_write_to_file(pPivot, zPivot);
446455
zOrig = file_newname(zV1, "original", 1);
447456
blob_write_to_file(&v1, zOrig);
448457
zOther = file_newname(zV1, "merge", 1);
449458
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
+ }
480487
fossil_free(zPivot);
481488
fossil_free(zOrig);
482489
fossil_free(zOther);
483490
}
484491
blob_reset(&v1);
485492
return rc;
486493
}
487494
--- 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
--- src/setup.c
+++ src/setup.c
@@ -1098,10 +1098,16 @@
10981098
onoff_attribute("Allow block-markup in timeline",
10991099
"timeline-block-markup", "tbm", 0);
11001100
@ <p>In timeline displays, check-in comments can be displayed with or
11011101
@ without block markup (paragraphs, tables, etc.)</p>
11021102
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
+
11031109
@ <hr />
11041110
onoff_attribute("Use Universal Coordinated Time (UTC)",
11051111
"timeline-utc", "utc", 1);
11061112
@ <p>Show times as UTC (also sometimes called Greenwich Mean Time (GMT) or
11071113
@ Zulu) instead of in local time. On this server, local time is currently
11081114
--- 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 @@
253253
if( isLink || isNewLink ){
254254
rc = -1;
255255
blob_zero(&b); /* because we reset it later */
256256
fossil_print("***** Cannot merge symlink %s\n", zNew);
257257
}else{
258
- rc = merge_3way(&a, zOPath, &b, &out);
258
+ rc = merge_3way(&a, zOPath, &b, &out, 0);
259259
blob_write_to_file(&out, zNPath);
260260
blob_reset(&out);
261261
file_wd_setexe(zNPath, isExec);
262262
}
263263
if( rc ){
264264
--- 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
--- src/style.c
+++ src/style.c
@@ -667,10 +667,11 @@
667667
},
668668
{ "ul.browser",
669669
"format for the list in the file browser",
670670
@ margin-left: 0.5em;
671671
@ padding-left: 0.5em;
672
+ @ white-space: nowrap;
672673
},
673674
{ "table.login_out",
674675
"table format for login/out label/input table",
675676
@ text-align: left;
676677
@ margin-right: 10px;
677678
--- 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 @@
192192
const char *zThisUser, /* Suppress links to this user */
193193
const char *zThisTag, /* Suppress links to this tag */
194194
void (*xExtra)(int) /* Routine to call on each line of display */
195195
){
196196
int wikiFlags;
197
+ int plainText;
197198
int mxWikiLen;
198199
Blob comment;
199200
int prevTagid = 0;
200201
int suppressCnt = 0;
201202
char zPrevDate[20];
@@ -205,10 +206,11 @@
205206
Stmt fchngQuery; /* Query for file changes on check-ins */
206207
static Stmt qbranch;
207208
int pendingEndTr = 0; /* True if a </td></tr> is needed */
208209
209210
zPrevDate[0] = 0;
211
+ plainText = db_get_int("timeline-plaintext", 0);
210212
mxWikiLen = db_get_int("timeline-max-comment", 0);
211213
if( db_get_boolean("timeline-block-markup", 0) ){
212214
wikiFlags = WIKI_INLINE;
213215
}else{
214216
wikiFlags = WIKI_INLINE | WIKI_NOBLOCK;
@@ -285,11 +287,11 @@
285287
@ <td class="timelineGraph">
286288
if( tmFlags & TIMELINE_UCOLOR ) zBgClr = zUser ? hash_color(zUser) : 0;
287289
if( zType[0]=='c'
288290
&& (pGraph || zBgClr==0 || (tmFlags & TIMELINE_BRCOLOR)!=0)
289291
){
290
- db_reset(&qbranch);
292
+ db_reset(&qbranch);
291293
db_bind_int(&qbranch, ":rid", rid);
292294
if( db_step(&qbranch)==SQLITE_ROW ){
293295
zBr = db_column_text(&qbranch, 0);
294296
}else{
295297
zBr = "trunk";
@@ -353,12 +355,18 @@
353355
if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
354356
Blob truncated;
355357
blob_zero(&truncated);
356358
blob_append(&truncated, blob_buffer(&comment), mxWikiLen);
357359
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
+ }
359365
blob_reset(&truncated);
366
+ }else if( plainText ){
367
+ @ %h(blob_str(&comment));
360368
}else{
361369
wiki_convert(&comment, 0, wikiFlags);
362370
}
363371
blob_reset(&comment);
364372
@@ -365,11 +373,11 @@
365373
/* Generate the "user: USERNAME" at the end of the comment, together
366374
** with a hyperlink to another timeline for that user.
367375
*/
368376
if( zTagList && zTagList[0]==0 ) zTagList = 0;
369377
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&amp;c=%t&amp;nd", zUser, zDate);
371379
@ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
372380
}else{
373381
@ (user: %h(zUser)%s(zTagList?",":"\051")
374382
}
375383
@@ -390,11 +398,11 @@
390398
while( z && z[0] ){
391399
for(i=0; z[i] && (z[i]!=',' || z[i+1]!=' '); i++){}
392400
if( zThisTag==0 || memcmp(z, zThisTag, i)!=0 || zThisTag[i]!=0 ){
393401
blob_appendf(&links,
394402
"%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&amp;nd&amp;c=%t",i,z,zDate), i,z, &z[i]
396404
);
397405
}else{
398406
blob_appendf(&links, "%#h", i+2, z);
399407
}
400408
if( z[i]==0 ) break;
@@ -415,11 +423,11 @@
415423
416424
/* Generate the file-change list if requested */
417425
if( (tmFlags & TIMELINE_FCHANGES)!=0 && zType[0]=='c' && g.perm.Hyperlink ){
418426
int inUl = 0;
419427
if( !fchngQueryInit ){
420
- db_prepare(&fchngQuery,
428
+ db_prepare(&fchngQuery,
421429
"SELECT (pid==0) AS isnew,"
422430
" (fid==0) AS isdel,"
423431
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
424432
" (SELECT uuid FROM blob WHERE rid=fid),"
425433
" (SELECT uuid FROM blob WHERE rid=pid),"
@@ -484,11 +492,11 @@
484492
pGraph = 0;
485493
}else{
486494
/* style is not moved to css, because this is
487495
** a technical div for the timeline graph
488496
*/
489
- @ <tr><td /><td>
497
+ @ <tr><td></td><td>
490498
@ <div id="grbtm" style="width:%d(pGraph->mxRail*20+30)px;"></div>
491499
@ </td></tr>
492500
}
493501
}
494502
@ </table>
@@ -653,11 +661,11 @@
653661
@ if( p.u>0 ) drawUpArrow(p.x, rowinfo[p.u-1].y+6, p.y-5);
654662
if( !omitDescenders ){
655663
@ if( p.u==0 ) drawUpArrow(p.x, 0, p.y-5);
656664
@ if( p.f&1 ) drawBox("black",p.x-1,p.y-1,p.x+2,p.y+2);
657665
@ if( p.d ) drawUpArrow(p.x, p.y+6, btm);
658
- }
666
+ }
659667
@ if( p.mo>0 ){
660668
@ var x1 = p.mo + left - 1;
661669
@ var y1 = p.y-3;
662670
@ var x0 = x1>p.x ? p.x+7 : p.x-6;
663671
@ var u = rowinfo[p.mu-1];
@@ -758,11 +766,11 @@
758766
759767
/*
760768
** Create a temporary table suitable for storing timeline data.
761769
*/
762770
static void timeline_temp_table(void){
763
- static const char zSql[] =
771
+ static const char zSql[] =
764772
@ CREATE TEMP TABLE IF NOT EXISTS timeline(
765773
@ rid INTEGER PRIMARY KEY,
766774
@ uuid TEXT,
767775
@ timestamp TEXT,
768776
@ comment TEXT,
@@ -799,11 +807,11 @@
799807
@ WHERE tagname GLOB 'sym-*' AND tag.tagid=tagxref.tagid
800808
@ AND tagxref.rid=blob.rid AND tagxref.tagtype>0) AS tags,
801809
@ tagid AS tagid,
802810
@ brief AS brief,
803811
@ event.mtime AS mtime
804
- @ FROM event CROSS JOIN blob
812
+ @ FROM event CROSS JOIN blob
805813
@ WHERE blob.rid=event.objid
806814
;
807815
if( zBase==0 ){
808816
zBase = mprintf(zBaseSql, TAG_BRANCH, TAG_BRANCH);
809817
}
@@ -1167,24 +1175,24 @@
11671175
rBefore = symbolic_name_to_mtime(zBefore);
11681176
rAfter = symbolic_name_to_mtime(zAfter);
11691177
rCirca = symbolic_name_to_mtime(zCirca);
11701178
if( rAfter>0.0 ){
11711179
if( rBefore>0.0 ){
1172
- blob_appendf(&sql,
1180
+ blob_appendf(&sql,
11731181
" AND event.mtime>=%.17g AND event.mtime<=%.17g"
11741182
" ORDER BY event.mtime ASC", rAfter-ONE_SECOND, rBefore+ONE_SECOND);
11751183
url_add_parameter(&url, "a", zAfter);
11761184
url_add_parameter(&url, "b", zBefore);
11771185
nEntry = 1000000;
11781186
}else{
1179
- blob_appendf(&sql,
1187
+ blob_appendf(&sql,
11801188
" AND event.mtime>=%.17g ORDER BY event.mtime ASC",
11811189
rAfter-ONE_SECOND);
11821190
url_add_parameter(&url, "a", zAfter);
11831191
}
11841192
}else if( rBefore>0.0 ){
1185
- blob_appendf(&sql,
1193
+ blob_appendf(&sql,
11861194
" AND event.mtime<=%.17g ORDER BY event.mtime DESC",
11871195
rBefore+ONE_SECOND);
11881196
url_add_parameter(&url, "b", zBefore);
11891197
}else if( rCirca>0.0 ){
11901198
Blob sql2;
@@ -1300,11 +1308,11 @@
13001308
/*
13011309
** The input query q selects various records. Print a human-readable
13021310
** summary of those records.
13031311
**
13041312
** Limit the number of entries printed to nLine.
1305
-**
1313
+**
13061314
** The query should return these columns:
13071315
**
13081316
** 0. rid
13091317
** 1. uuid
13101318
** 2. Date/Time
@@ -1334,11 +1342,11 @@
13341342
int nParent = db_column_int(q, 5);
13351343
char *zFree = 0;
13361344
int n = 0;
13371345
char zPrefix[80];
13381346
char zUuid[UUID_SIZE+1];
1339
-
1347
+
13401348
sqlite3_snprintf(sizeof(zUuid), zUuid, "%.10s", zId);
13411349
if( memcmp(zDate, zPrevDate, 10) ){
13421350
fossil_print("=== %.10s ===\n", zDate);
13431351
memcpy(zPrevDate, zDate, 10);
13441352
nLine++;
@@ -1368,11 +1376,11 @@
13681376
nLine += comment_print(zFree, 9, 79);
13691377
sqlite3_free(zFree);
13701378
13711379
if(showfiles){
13721380
if( !fchngQueryInit ){
1373
- db_prepare(&fchngQuery,
1381
+ db_prepare(&fchngQuery,
13741382
"SELECT (pid==0) AS isnew,"
13751383
" (fid==0) AS isdel,"
13761384
" (SELECT name FROM filename WHERE fnid=mlink.fnid) AS name,"
13771385
" (SELECT uuid FROM blob WHERE rid=fid),"
13781386
" (SELECT uuid FROM blob WHERE rid=pid)"
@@ -1385,11 +1393,11 @@
13851393
db_bind_int(&fchngQuery, ":mid", rid);
13861394
while( db_step(&fchngQuery)==SQLITE_ROW ){
13871395
const char *zFilename = db_column_text(&fchngQuery, 2);
13881396
int isNew = db_column_int(&fchngQuery, 0);
13891397
int isDel = db_column_int(&fchngQuery, 1);
1390
- if( isNew ){
1398
+ if( isNew ){
13911399
fossil_print(" ADDED %s\n",zFilename);
13921400
}else if( isDel ){
13931401
fossil_print(" DELETED %s\n",zFilename);
13941402
}else{
13951403
fossil_print(" EDITED %s\n", zFilename);
@@ -1404,11 +1412,11 @@
14041412
/*
14051413
** Return a pointer to a static string that forms the basis for
14061414
** a timeline query for display on a TTY.
14071415
*/
14081416
const char *timeline_query_for_tty(void){
1409
- static const char zBaseSql[] =
1417
+ static const char zBaseSql[] =
14101418
@ SELECT
14111419
@ blob.rid AS rid,
14121420
@ uuid,
14131421
@ datetime(event.mtime,'localtime') AS mDateTime,
14141422
@ coalesce(ecomment,comment)
14151423
--- 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&amp;c=%t&amp;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&amp;nd&amp;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 @@
322322
** Complete the undo process is one is currently in process.
323323
*/
324324
void undo_finish(void){
325325
if( undoActive ){
326326
if( undoNeedRollback ){
327
- fossil_print("\"fossil undo\" is available to undo changes"
327
+ fossil_print(" \"fossil undo\" is available to undo changes"
328328
" to the working checkout.\n");
329329
}
330330
undoActive = 0;
331331
undoNeedRollback = 0;
332332
}
333333
--- 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 @@
217217
" islinkv BOOLEAN," /* True if current file is a link */
218218
" islinkt BOOLEAN," /* True if target file is a link */
219219
" ridv INTEGER," /* Record ID for current version */
220220
" ridt INTEGER," /* Record ID for target */
221221
" isexe BOOLEAN," /* Does target have execute permission? */
222
+ " deleted BOOLEAN DEFAULT 0,"/* File marke by "rm" to become unmanaged */
222223
" fnt TEXT" /* Filename of same file on target version */
223224
");"
224225
);
225226
226227
/* Add files found in the current version
227228
*/
228229
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"
231232
" FROM vfile WHERE vid=%d",
232233
vid
233234
);
234235
235236
/* Compute file name changes on V->T. Record name changes in files that
@@ -339,11 +340,11 @@
339340
** Alter the content of the checkout so that it conforms with the
340341
** target
341342
*/
342343
db_prepare(&q,
343344
"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"
345346
);
346347
db_prepare(&mtimeXfer,
347348
"UPDATE vfile SET mtime=(SELECT mtime FROM vfile WHERE id=:idv)"
348349
" WHERE id=:idt"
349350
);
@@ -359,43 +360,52 @@
359360
int chnged = db_column_int(&q, 5); /* Current is edited */
360361
const char *zNewName = db_column_text(&q,6);/* New filename */
361362
int isexe = db_column_int(&q, 7); /* EXE perm for new file */
362363
int islinkv = db_column_int(&q, 8); /* Is current file is a link */
363364
int islinkt = db_column_int(&q, 9); /* Is target file is a link */
365
+ int deleted = db_column_int(&q, 10); /* Marked for deletion */
364366
char *zFullPath; /* Full pathname of the file */
365367
char *zFullNewPath; /* Full pathname of dest */
366368
char nameChng; /* True if the name changed */
367369
368370
zFullPath = mprintf("%s%s", g.zLocalRoot, zName);
369371
zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
370372
nameChng = fossil_strcmp(zName, zNewName);
371373
nUpdate++;
374
+ if( deleted ){
375
+ db_multi_exec("UPDATE vfile SET deleted=1 WHERE id=%d", idt);
376
+ }
372377
if( idv>0 && ridv==0 && idt>0 && ridt>0 ){
373378
/* Conflict. This file has been added to the current checkout
374379
** but also exists in the target checkout. Use the current version.
375380
*/
376381
fossil_print("CONFLICT %s\n", zName);
377382
nConflict++;
378383
}else if( idt>0 && idv==0 ){
379384
/* File added in the target. */
380385
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);
382387
nOverwrite++;
383388
}else{
384389
fossil_print("ADD %s\n", zName);
385390
}
386391
undo_save(zName);
387392
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) ){
389394
/* The file is unedited. Change it to the target version */
390395
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
+ }
392401
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
393402
}else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){
394403
/* The file missing from the local check-out. Restore it to the
395404
** 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":"");
397407
undo_save(zName);
398408
if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
399409
}else if( idt==0 && idv>0 ){
400410
if( ridv==0 ){
401411
/* Added in current checkout. Continue to hold the file as
@@ -423,14 +433,15 @@
423433
}
424434
if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){
425435
fossil_print("***** Cannot merge symlink %s\n", zNewName);
426436
nConflict++;
427437
}else{
438
+ unsigned mergeFlags = nochangeFlag ? MERGE_DRYRUN : 0;
428439
undo_save(zName);
429440
content_get(ridt, &t);
430441
content_get(ridv, &v);
431
- rc = merge_3way(&v, zFullPath, &t, &r);
442
+ rc = merge_3way(&v, zFullPath, &t, &r, mergeFlags);
432443
if( rc>=0 ){
433444
if( !nochangeFlag ){
434445
blob_write_to_file(&r, zFullNewPath);
435446
file_wd_setexe(zFullNewPath, isexe);
436447
}
437448
438449
ADDED test/update-test-1.sh
439450
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
--- 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 ==============================='
--- 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 ==============================='

Keyboard Shortcuts

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