Fossil SCM

Merge the changes to show unresolved conflicts in "fossil status" and to prevent committing unresolved conflicts.

drh 2012-10-22 13:23 trunk merge
Commit 7d34d1748a1c72fb4328374a33e084a12351b633
2 files changed +20 -3 +49 -12
+20 -3
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
8787
}else if( isChnged==2 ){
8888
blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
8989
}else if( isChnged==3 ){
9090
blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
9191
}else if( isChnged==1 ){
92
- blob_appendf(report, "EDITED %s\n", zDisplayName);
92
+ if( file_contains_merge_marker(zFullName) ){
93
+ blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94
+ }else{
95
+ blob_appendf(report, "EDITED %s\n", zDisplayName);
96
+ }
9397
}else if( isRenamed ){
9498
blob_appendf(report, "RENAMED %s\n", zDisplayName);
9599
}
96100
free(zFullName);
97101
}
@@ -976,10 +980,11 @@
976980
** --force|-f allow forking with this commit
977981
** --message-file|-M FILE read the commit comment from given file
978982
** --nosign do not attempt to sign this commit with gpg
979983
** --private do not sync changes and their descendants
980984
** --tag TAG-NAME assign given tag TAG-NAME to the checkin
985
+** --conflict allow unresolved merge conflicts
981986
**
982987
** See also: branch, changes, checkout, extra, sync
983988
*/
984989
void commit_cmd(void){
985990
int hasChanges; /* True if unsaved changes exist */
@@ -993,10 +998,11 @@
993998
int noSign = 0; /* True to omit signing the manifest using GPG */
994999
int isAMerge = 0; /* True if checking in a merge */
9951000
int forceFlag = 0; /* Force a fork */
9961001
int forceDelta = 0; /* Force a delta-manifest */
9971002
int forceBaseline = 0; /* Force a baseline-manifest */
1003
+ int allowConflict = 0; /* Allow unresolve merge conflicts */
9981004
char *zManifestFile; /* Name of the manifest file */
9991005
int useCksum; /* True if checksums should be computed and verified */
10001006
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
10011007
int testRun; /* True for a test run. Debugging only */
10021008
const char *zBranch; /* Create a new branch with this name */
@@ -1012,10 +1018,11 @@
10121018
Blob muuid; /* Manifest uuid */
10131019
Blob cksum1, cksum2; /* Before and after commit checksums */
10141020
Blob cksum1b; /* Checksum recorded in the manifest */
10151021
int szD; /* Size of the delta manifest */
10161022
int szB; /* Size of the baseline manifest */
1023
+ int nConflict = 0; /* Number of unresolved merge conflicts */
10171024
10181025
url_proxy_options();
10191026
noSign = find_option("nosign",0,0)!=0;
10201027
forceDelta = find_option("delta",0,0)!=0;
10211028
forceBaseline = find_option("baseline",0,0)!=0;
@@ -1040,10 +1047,11 @@
10401047
if( zBranch==0 ) zBranch = "private";
10411048
if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
10421049
}
10431050
zDateOvrd = find_option("date-override",0,1);
10441051
zUserOvrd = find_option("user-override",0,1);
1052
+ allowConflict = find_option("conflict",0,0)!=0;
10451053
db_must_be_within_tree();
10461054
noSign = db_get_boolean("omitsign", 0)|noSign;
10471055
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
10481056
useCksum = db_get_boolean("repo-cksum", 1);
10491057
outputManifest = db_get_boolean("manifest", 0);
@@ -1194,42 +1202,51 @@
11941202
/* Step 1: Insert records for all modified files into the blob
11951203
** table. If there were arguments passed to this command, only
11961204
** the identified fils are inserted (if they have been modified).
11971205
*/
11981206
db_prepare(&q,
1199
- "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1207
+ "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
12001208
"WHERE chnged==1 AND NOT deleted AND is_selected(id)",
12011209
g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
12021210
);
12031211
while( db_step(&q)==SQLITE_ROW ){
12041212
int id, rid;
12051213
const char *zFullname;
12061214
Blob content;
1207
- int crnlOk;
1215
+ int crnlOk, chnged;
12081216
12091217
id = db_column_int(&q, 0);
12101218
zFullname = db_column_text(&q, 1);
12111219
rid = db_column_int(&q, 2);
12121220
crnlOk = db_column_int(&q, 3);
1221
+ chnged = db_column_int(&q, 4);
12131222
12141223
blob_zero(&content);
12151224
if( file_wd_islink(zFullname) ){
12161225
/* Instead of file content, put link destination path */
12171226
blob_read_link(&content, zFullname);
12181227
}else{
12191228
blob_read_from_file(&content, zFullname);
12201229
}
12211230
if( !crnlOk ) cr_warning(&content, zFullname);
1231
+ if( chnged==1 && contains_merge_marker(&content) ){
1232
+ nConflict++;
1233
+ fossil_print("possible unresolved merge conflict in %s\n",
1234
+ zFullname+strlen(g.zLocalRoot));
1235
+ }
12221236
nrid = content_put(&content);
12231237
blob_reset(&content);
12241238
if( rid>0 ){
12251239
content_deltify(rid, nrid, 0);
12261240
}
12271241
db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
12281242
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
12291243
}
12301244
db_finalize(&q);
1245
+ if( nConflict && !allowConflict ){
1246
+ fossil_fatal("abort due to unresolve merge conflicts");
1247
+ }
12311248
12321249
/* Create the new manifest */
12331250
if( blob_size(&comment)==0 ){
12341251
blob_append(&comment, "(no comment)", -1);
12351252
}
12361253
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 blob_appendf(report, "EDITED %s\n", zDisplayName);
 
 
 
 
93 }else if( isRenamed ){
94 blob_appendf(report, "RENAMED %s\n", zDisplayName);
95 }
96 free(zFullName);
97 }
@@ -976,10 +980,11 @@
976 ** --force|-f allow forking with this commit
977 ** --message-file|-M FILE read the commit comment from given file
978 ** --nosign do not attempt to sign this commit with gpg
979 ** --private do not sync changes and their descendants
980 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
 
981 **
982 ** See also: branch, changes, checkout, extra, sync
983 */
984 void commit_cmd(void){
985 int hasChanges; /* True if unsaved changes exist */
@@ -993,10 +998,11 @@
993 int noSign = 0; /* True to omit signing the manifest using GPG */
994 int isAMerge = 0; /* True if checking in a merge */
995 int forceFlag = 0; /* Force a fork */
996 int forceDelta = 0; /* Force a delta-manifest */
997 int forceBaseline = 0; /* Force a baseline-manifest */
 
998 char *zManifestFile; /* Name of the manifest file */
999 int useCksum; /* True if checksums should be computed and verified */
1000 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1001 int testRun; /* True for a test run. Debugging only */
1002 const char *zBranch; /* Create a new branch with this name */
@@ -1012,10 +1018,11 @@
1012 Blob muuid; /* Manifest uuid */
1013 Blob cksum1, cksum2; /* Before and after commit checksums */
1014 Blob cksum1b; /* Checksum recorded in the manifest */
1015 int szD; /* Size of the delta manifest */
1016 int szB; /* Size of the baseline manifest */
 
1017
1018 url_proxy_options();
1019 noSign = find_option("nosign",0,0)!=0;
1020 forceDelta = find_option("delta",0,0)!=0;
1021 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1040,10 +1047,11 @@
1040 if( zBranch==0 ) zBranch = "private";
1041 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1042 }
1043 zDateOvrd = find_option("date-override",0,1);
1044 zUserOvrd = find_option("user-override",0,1);
 
1045 db_must_be_within_tree();
1046 noSign = db_get_boolean("omitsign", 0)|noSign;
1047 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1048 useCksum = db_get_boolean("repo-cksum", 1);
1049 outputManifest = db_get_boolean("manifest", 0);
@@ -1194,42 +1202,51 @@
1194 /* Step 1: Insert records for all modified files into the blob
1195 ** table. If there were arguments passed to this command, only
1196 ** the identified fils are inserted (if they have been modified).
1197 */
1198 db_prepare(&q,
1199 "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1200 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1201 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1202 );
1203 while( db_step(&q)==SQLITE_ROW ){
1204 int id, rid;
1205 const char *zFullname;
1206 Blob content;
1207 int crnlOk;
1208
1209 id = db_column_int(&q, 0);
1210 zFullname = db_column_text(&q, 1);
1211 rid = db_column_int(&q, 2);
1212 crnlOk = db_column_int(&q, 3);
 
1213
1214 blob_zero(&content);
1215 if( file_wd_islink(zFullname) ){
1216 /* Instead of file content, put link destination path */
1217 blob_read_link(&content, zFullname);
1218 }else{
1219 blob_read_from_file(&content, zFullname);
1220 }
1221 if( !crnlOk ) cr_warning(&content, zFullname);
 
 
 
 
 
1222 nrid = content_put(&content);
1223 blob_reset(&content);
1224 if( rid>0 ){
1225 content_deltify(rid, nrid, 0);
1226 }
1227 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1228 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1229 }
1230 db_finalize(&q);
 
 
 
1231
1232 /* Create the new manifest */
1233 if( blob_size(&comment)==0 ){
1234 blob_append(&comment, "(no comment)", -1);
1235 }
1236
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 if( file_contains_merge_marker(zFullName) ){
93 blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94 }else{
95 blob_appendf(report, "EDITED %s\n", zDisplayName);
96 }
97 }else if( isRenamed ){
98 blob_appendf(report, "RENAMED %s\n", zDisplayName);
99 }
100 free(zFullName);
101 }
@@ -976,10 +980,11 @@
980 ** --force|-f allow forking with this commit
981 ** --message-file|-M FILE read the commit comment from given file
982 ** --nosign do not attempt to sign this commit with gpg
983 ** --private do not sync changes and their descendants
984 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
985 ** --conflict allow unresolved merge conflicts
986 **
987 ** See also: branch, changes, checkout, extra, sync
988 */
989 void commit_cmd(void){
990 int hasChanges; /* True if unsaved changes exist */
@@ -993,10 +998,11 @@
998 int noSign = 0; /* True to omit signing the manifest using GPG */
999 int isAMerge = 0; /* True if checking in a merge */
1000 int forceFlag = 0; /* Force a fork */
1001 int forceDelta = 0; /* Force a delta-manifest */
1002 int forceBaseline = 0; /* Force a baseline-manifest */
1003 int allowConflict = 0; /* Allow unresolve merge conflicts */
1004 char *zManifestFile; /* Name of the manifest file */
1005 int useCksum; /* True if checksums should be computed and verified */
1006 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1007 int testRun; /* True for a test run. Debugging only */
1008 const char *zBranch; /* Create a new branch with this name */
@@ -1012,10 +1018,11 @@
1018 Blob muuid; /* Manifest uuid */
1019 Blob cksum1, cksum2; /* Before and after commit checksums */
1020 Blob cksum1b; /* Checksum recorded in the manifest */
1021 int szD; /* Size of the delta manifest */
1022 int szB; /* Size of the baseline manifest */
1023 int nConflict = 0; /* Number of unresolved merge conflicts */
1024
1025 url_proxy_options();
1026 noSign = find_option("nosign",0,0)!=0;
1027 forceDelta = find_option("delta",0,0)!=0;
1028 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1040,10 +1047,11 @@
1047 if( zBranch==0 ) zBranch = "private";
1048 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1049 }
1050 zDateOvrd = find_option("date-override",0,1);
1051 zUserOvrd = find_option("user-override",0,1);
1052 allowConflict = find_option("conflict",0,0)!=0;
1053 db_must_be_within_tree();
1054 noSign = db_get_boolean("omitsign", 0)|noSign;
1055 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1056 useCksum = db_get_boolean("repo-cksum", 1);
1057 outputManifest = db_get_boolean("manifest", 0);
@@ -1194,42 +1202,51 @@
1202 /* Step 1: Insert records for all modified files into the blob
1203 ** table. If there were arguments passed to this command, only
1204 ** the identified fils are inserted (if they have been modified).
1205 */
1206 db_prepare(&q,
1207 "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
1208 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1209 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1210 );
1211 while( db_step(&q)==SQLITE_ROW ){
1212 int id, rid;
1213 const char *zFullname;
1214 Blob content;
1215 int crnlOk, chnged;
1216
1217 id = db_column_int(&q, 0);
1218 zFullname = db_column_text(&q, 1);
1219 rid = db_column_int(&q, 2);
1220 crnlOk = db_column_int(&q, 3);
1221 chnged = db_column_int(&q, 4);
1222
1223 blob_zero(&content);
1224 if( file_wd_islink(zFullname) ){
1225 /* Instead of file content, put link destination path */
1226 blob_read_link(&content, zFullname);
1227 }else{
1228 blob_read_from_file(&content, zFullname);
1229 }
1230 if( !crnlOk ) cr_warning(&content, zFullname);
1231 if( chnged==1 && contains_merge_marker(&content) ){
1232 nConflict++;
1233 fossil_print("possible unresolved merge conflict in %s\n",
1234 zFullname+strlen(g.zLocalRoot));
1235 }
1236 nrid = content_put(&content);
1237 blob_reset(&content);
1238 if( rid>0 ){
1239 content_deltify(rid, nrid, 0);
1240 }
1241 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1242 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1243 }
1244 db_finalize(&q);
1245 if( nConflict && !allowConflict ){
1246 fossil_fatal("abort due to unresolve merge conflicts");
1247 }
1248
1249 /* Create the new manifest */
1250 if( blob_size(&comment)==0 ){
1251 blob_append(&comment, "(no comment)", -1);
1252 }
1253
+49 -12
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133133
i += 3;
134134
}
135135
return i;
136136
}
137137
138
+/*
139
+** Text of boundary markers for merge conflicts.
140
+*/
141
+static char const * const mergeMarker[] = {
142
+ /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143
+ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144
+ "======= COMMON ANCESTOR content follows ============================\n",
145
+ "======= MERGED IN content follows ==================================\n",
146
+ ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147
+};
138148
139149
140150
/*
141151
** Do a three-way merge. Initialize pOut to contain the result.
142152
**
@@ -154,18 +164,10 @@
154164
int *aC2; /* Changes from pPivot to pV2 */
155165
int i1, i2; /* Index into aC1[] and aC2[] */
156166
int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
157167
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
158168
int nConflict = 0; /* Number of merge conflicts seen so far */
159
- static const char zBegin[] =
160
- "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
161
- static const char zMid1[] =
162
- "======= COMMON ANCESTOR content follows ============================\n";
163
- static const char zMid2[] =
164
- "======= MERGED IN content follows ==================================\n";
165
- static const char zEnd[] =
166
- ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
167169
168170
blob_zero(pOut); /* Merge results stored in pOut */
169171
170172
/* Compute the edits that occur from pPivot => pV1 (into aC1)
171173
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
266268
nConflict++;
267269
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
268270
sz++;
269271
}
270272
DEBUG( printf("CONFLICT %d\n", sz); )
271
- blob_appendf(pOut, zBegin);
273
+ blob_appendf(pOut, mergeMarker[0]);
272274
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
273
- blob_appendf(pOut, zMid1);
275
+ blob_appendf(pOut, mergeMarker[1]);
274276
blob_copy_lines(pOut, pPivot, sz);
275
- blob_appendf(pOut, zMid2);
277
+ blob_appendf(pOut, mergeMarker[2]);
276278
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
277
- blob_appendf(pOut, zEnd);
279
+ blob_appendf(pOut, mergeMarker[3]);
278280
}
279281
280282
/* If we are finished with an edit triple, advance to the next
281283
** triple.
282284
*/
@@ -301,10 +303,45 @@
301303
302304
free(aC1);
303305
free(aC2);
304306
return nConflict;
305307
}
308
+
309
+/*
310
+** Return true if the input string contains a merge marker on a line by
311
+** itself.
312
+*/
313
+int contains_merge_marker(Blob *p){
314
+ int i, j;
315
+ int len = (int)strlen(mergeMarker[0]);
316
+ const char *z = blob_buffer(p);
317
+ int n = blob_size(p) - len + 1;
318
+ assert( len==(int)strlen(mergeMarker[1]) );
319
+ assert( len==(int)strlen(mergeMarker[2]) );
320
+ assert( len==(int)strlen(mergeMarker[3]) );
321
+ assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 );
322
+ for(i=0; i<n; ){
323
+ for(j=0; j<4; j++){
324
+ if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
325
+ }
326
+ while( i<n && z[i]!='\n' ){ i++; }
327
+ while( i<n && z[i]=='\n' ){ i++; }
328
+ }
329
+ return 0;
330
+}
331
+
332
+/*
333
+** Return true if the named file contains an unresolved merge marker line.
334
+*/
335
+int file_contains_merge_marker(const char *zFullpath){
336
+ Blob file;
337
+ int rc;
338
+ blob_read_from_file(&file, zFullpath);
339
+ rc = contains_merge_marker(&file);
340
+ blob_reset(&file);
341
+ return rc;
342
+}
306343
307344
/*
308345
** COMMAND: test-3-way-merge
309346
**
310347
** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
311348
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133 i += 3;
134 }
135 return i;
136 }
137
 
 
 
 
 
 
 
 
 
 
138
139
140 /*
141 ** Do a three-way merge. Initialize pOut to contain the result.
142 **
@@ -154,18 +164,10 @@
154 int *aC2; /* Changes from pPivot to pV2 */
155 int i1, i2; /* Index into aC1[] and aC2[] */
156 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
157 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
158 int nConflict = 0; /* Number of merge conflicts seen so far */
159 static const char zBegin[] =
160 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
161 static const char zMid1[] =
162 "======= COMMON ANCESTOR content follows ============================\n";
163 static const char zMid2[] =
164 "======= MERGED IN content follows ==================================\n";
165 static const char zEnd[] =
166 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
167
168 blob_zero(pOut); /* Merge results stored in pOut */
169
170 /* Compute the edits that occur from pPivot => pV1 (into aC1)
171 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
266 nConflict++;
267 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
268 sz++;
269 }
270 DEBUG( printf("CONFLICT %d\n", sz); )
271 blob_appendf(pOut, zBegin);
272 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
273 blob_appendf(pOut, zMid1);
274 blob_copy_lines(pOut, pPivot, sz);
275 blob_appendf(pOut, zMid2);
276 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
277 blob_appendf(pOut, zEnd);
278 }
279
280 /* If we are finished with an edit triple, advance to the next
281 ** triple.
282 */
@@ -301,10 +303,45 @@
301
302 free(aC1);
303 free(aC2);
304 return nConflict;
305 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
307 /*
308 ** COMMAND: test-3-way-merge
309 **
310 ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
311
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133 i += 3;
134 }
135 return i;
136 }
137
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static char const * const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "======= COMMON ANCESTOR content follows ============================\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
149
150 /*
151 ** Do a three-way merge. Initialize pOut to contain the result.
152 **
@@ -154,18 +164,10 @@
164 int *aC2; /* Changes from pPivot to pV2 */
165 int i1, i2; /* Index into aC1[] and aC2[] */
166 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168 int nConflict = 0; /* Number of merge conflicts seen so far */
 
 
 
 
 
 
 
 
169
170 blob_zero(pOut); /* Merge results stored in pOut */
171
172 /* Compute the edits that occur from pPivot => pV1 (into aC1)
173 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
268 nConflict++;
269 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270 sz++;
271 }
272 DEBUG( printf("CONFLICT %d\n", sz); )
273 blob_appendf(pOut, mergeMarker[0]);
274 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
275 blob_appendf(pOut, mergeMarker[1]);
276 blob_copy_lines(pOut, pPivot, sz);
277 blob_appendf(pOut, mergeMarker[2]);
278 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
279 blob_appendf(pOut, mergeMarker[3]);
280 }
281
282 /* If we are finished with an edit triple, advance to the next
283 ** triple.
284 */
@@ -301,10 +303,45 @@
303
304 free(aC1);
305 free(aC2);
306 return nConflict;
307 }
308
309 /*
310 ** Return true if the input string contains a merge marker on a line by
311 ** itself.
312 */
313 int contains_merge_marker(Blob *p){
314 int i, j;
315 int len = (int)strlen(mergeMarker[0]);
316 const char *z = blob_buffer(p);
317 int n = blob_size(p) - len + 1;
318 assert( len==(int)strlen(mergeMarker[1]) );
319 assert( len==(int)strlen(mergeMarker[2]) );
320 assert( len==(int)strlen(mergeMarker[3]) );
321 assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 );
322 for(i=0; i<n; ){
323 for(j=0; j<4; j++){
324 if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
325 }
326 while( i<n && z[i]!='\n' ){ i++; }
327 while( i<n && z[i]=='\n' ){ i++; }
328 }
329 return 0;
330 }
331
332 /*
333 ** Return true if the named file contains an unresolved merge marker line.
334 */
335 int file_contains_merge_marker(const char *zFullpath){
336 Blob file;
337 int rc;
338 blob_read_from_file(&file, zFullpath);
339 rc = contains_merge_marker(&file);
340 blob_reset(&file);
341 return rc;
342 }
343
344 /*
345 ** COMMAND: test-3-way-merge
346 **
347 ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
348

Keyboard Shortcuts

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