Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch conflict-tracking Excluding Merge-Ins
This is equivalent to a diff from e40e4faabb to 65f495bc06
2012-10-22
| ||
13:23 | Merge the changes to show unresolved conflicts in "fossil status" and to prevent committing unresolved conflicts. check-in: 7d34d1748a user: drh tags: trunk | |
2012-10-21
| ||
00:54 | Fix a crash bug that comes up when trying to view the history of files whose names contain charaters that require URL escapes. This is a cherry-pick of [65f495bc06767] which was committed to the wrong branch. check-in: 9c6f9e7a8c user: drh tags: trunk | |
00:52 | Fix a crash bug that comes up when trying to view the history of files whose names contain charaters that require URL escapes. Closed-Leaf check-in: 65f495bc06 user: drh tags: conflict-tracking | |
2012-10-20
| ||
00:29 | Report unresolved conflicts on "fossil status". Refuse to commit with unresolved conflicts if the --conflict flag is omitted from "fossil commit". check-in: 1fb2ca625b user: drh tags: conflict-tracking | |
2012-10-19
| ||
18:36 | Add a mention of the ability to do dynamic loading of Tcl to the change log. (This change originally checked into the wrong branch.) check-in: e40e4faabb user: drh tags: trunk | |
17:04 | Fix a typo in the Style document. check-in: 2116906fb1 user: drh tags: trunk | |
Changes to src/checkin.c.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 ... 974 975 976 977 978 979 980 981 982 983 984 985 986 987 ... 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 .... 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 .... 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 .... 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 |
}else if( isDeleted ){ blob_appendf(report, "DELETED %s\n", zDisplayName); }else if( isChnged==2 ){ blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); }else if( isChnged==3 ){ blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); }else if( isChnged==1 ){ blob_appendf(report, "EDITED %s\n", zDisplayName); }else if( isRenamed ){ blob_appendf(report, "RENAMED %s\n", zDisplayName); } free(zFullName); } blob_reset(&rewrittenPathname); db_finalize(&q); ................................................................................ ** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment ** --delta use a delta manifest in the commit process ** --force|-f allow forking with this commit ** --message-file|-M FILE read the commit comment from given file ** --nosign do not attempt to sign this commit with gpg ** --private do not sync changes and their descendants ** --tag TAG-NAME assign given tag TAG-NAME to the checkin ** ** See also: branch, changes, checkout, extra, sync */ void commit_cmd(void){ int hasChanges; /* True if unsaved changes exist */ int vid; /* blob-id of parent version */ int nrid; /* blob-id of a modified file */ ................................................................................ Stmt q; /* Query to find files that have been modified */ char *zUuid; /* UUID of the new check-in */ int noSign = 0; /* True to omit signing the manifest using GPG */ int isAMerge = 0; /* True if checking in a merge */ int forceFlag = 0; /* Force a fork */ int forceDelta = 0; /* Force a delta-manifest */ int forceBaseline = 0; /* Force a baseline-manifest */ char *zManifestFile; /* Name of the manifest file */ int useCksum; /* True if checksums should be computed and verified */ int outputManifest; /* True to output "manifest" and "manifest.uuid" */ int testRun; /* True for a test run. Debugging only */ const char *zBranch; /* Create a new branch with this name */ const char *zBrClr; /* Set background color when branching */ const char *zColor; /* One-time check-in color */ ................................................................................ const char **azTag = 0;/* Array of all --tag arguments */ Blob manifest; /* Manifest in baseline form */ Blob muuid; /* Manifest uuid */ Blob cksum1, cksum2; /* Before and after commit checksums */ Blob cksum1b; /* Checksum recorded in the manifest */ int szD; /* Size of the delta manifest */ int szB; /* Size of the baseline manifest */ url_proxy_options(); noSign = find_option("nosign",0,0)!=0; forceDelta = find_option("delta",0,0)!=0; forceBaseline = find_option("baseline",0,0)!=0; if( forceDelta && forceBaseline ){ fossil_fatal("cannot use --delta and --baseline together"); ................................................................................ if( find_option("private",0,0) ){ g.markPrivate = 1; if( zBranch==0 ) zBranch = "private"; if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */ } zDateOvrd = find_option("date-override",0,1); zUserOvrd = find_option("user-override",0,1); db_must_be_within_tree(); noSign = db_get_boolean("omitsign", 0)|noSign; if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } useCksum = db_get_boolean("repo-cksum", 1); outputManifest = db_get_boolean("manifest", 0); verify_all_options(); ................................................................................ } /* Step 1: Insert records for all modified files into the blob ** table. If there were arguments passed to this command, only ** the identified fils are inserted (if they have been modified). */ db_prepare(&q, "SELECT id, %Q || pathname, mrid, %s FROM vfile " "WHERE chnged==1 AND NOT deleted AND is_selected(id)", g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob","")) ); while( db_step(&q)==SQLITE_ROW ){ int id, rid; const char *zFullname; Blob content; int crnlOk; id = db_column_int(&q, 0); zFullname = db_column_text(&q, 1); rid = db_column_int(&q, 2); crnlOk = db_column_int(&q, 3); blob_zero(&content); if( file_wd_islink(zFullname) ){ /* Instead of file content, put link destination path */ blob_read_link(&content, zFullname); }else{ blob_read_from_file(&content, zFullname); } if( !crnlOk ) cr_warning(&content, zFullname); nrid = content_put(&content); blob_reset(&content); if( rid>0 ){ content_deltify(rid, nrid, 0); } db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); } db_finalize(&q); /* Create the new manifest */ if( blob_size(&comment)==0 ){ blob_append(&comment, "(no comment)", -1); } if( forceDelta ){ blob_zero(&manifest); |
> > > | > > > > > | | > > > > > > > > > |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 ... 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 ... 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 .... 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 .... 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 .... 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 |
}else if( isDeleted ){ blob_appendf(report, "DELETED %s\n", zDisplayName); }else if( isChnged==2 ){ blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName); }else if( isChnged==3 ){ blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName); }else if( isChnged==1 ){ if( file_contains_merge_marker(zFullName) ){ blob_appendf(report, "CONFLICT %s\n", zDisplayName); }else{ blob_appendf(report, "EDITED %s\n", zDisplayName); } }else if( isRenamed ){ blob_appendf(report, "RENAMED %s\n", zDisplayName); } free(zFullName); } blob_reset(&rewrittenPathname); db_finalize(&q); ................................................................................ ** --comment|-m COMMENT-TEXT use COMMENT-TEXT as commit comment ** --delta use a delta manifest in the commit process ** --force|-f allow forking with this commit ** --message-file|-M FILE read the commit comment from given file ** --nosign do not attempt to sign this commit with gpg ** --private do not sync changes and their descendants ** --tag TAG-NAME assign given tag TAG-NAME to the checkin ** --conflict allow unresolved merge conflicts ** ** See also: branch, changes, checkout, extra, sync */ void commit_cmd(void){ int hasChanges; /* True if unsaved changes exist */ int vid; /* blob-id of parent version */ int nrid; /* blob-id of a modified file */ ................................................................................ Stmt q; /* Query to find files that have been modified */ char *zUuid; /* UUID of the new check-in */ int noSign = 0; /* True to omit signing the manifest using GPG */ int isAMerge = 0; /* True if checking in a merge */ int forceFlag = 0; /* Force a fork */ int forceDelta = 0; /* Force a delta-manifest */ int forceBaseline = 0; /* Force a baseline-manifest */ int allowConflict = 0; /* Allow unresolve merge conflicts */ char *zManifestFile; /* Name of the manifest file */ int useCksum; /* True if checksums should be computed and verified */ int outputManifest; /* True to output "manifest" and "manifest.uuid" */ int testRun; /* True for a test run. Debugging only */ const char *zBranch; /* Create a new branch with this name */ const char *zBrClr; /* Set background color when branching */ const char *zColor; /* One-time check-in color */ ................................................................................ const char **azTag = 0;/* Array of all --tag arguments */ Blob manifest; /* Manifest in baseline form */ Blob muuid; /* Manifest uuid */ Blob cksum1, cksum2; /* Before and after commit checksums */ Blob cksum1b; /* Checksum recorded in the manifest */ int szD; /* Size of the delta manifest */ int szB; /* Size of the baseline manifest */ int nConflict = 0; /* Number of unresolved merge conflicts */ url_proxy_options(); noSign = find_option("nosign",0,0)!=0; forceDelta = find_option("delta",0,0)!=0; forceBaseline = find_option("baseline",0,0)!=0; if( forceDelta && forceBaseline ){ fossil_fatal("cannot use --delta and --baseline together"); ................................................................................ if( find_option("private",0,0) ){ g.markPrivate = 1; if( zBranch==0 ) zBranch = "private"; if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */ } zDateOvrd = find_option("date-override",0,1); zUserOvrd = find_option("user-override",0,1); allowConflict = find_option("conflict",0,0)!=0; db_must_be_within_tree(); noSign = db_get_boolean("omitsign", 0)|noSign; if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; } useCksum = db_get_boolean("repo-cksum", 1); outputManifest = db_get_boolean("manifest", 0); verify_all_options(); ................................................................................ } /* Step 1: Insert records for all modified files into the blob ** table. If there were arguments passed to this command, only ** the identified fils are inserted (if they have been modified). */ db_prepare(&q, "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile " "WHERE chnged==1 AND NOT deleted AND is_selected(id)", g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob","")) ); while( db_step(&q)==SQLITE_ROW ){ int id, rid; const char *zFullname; Blob content; int crnlOk, chnged; id = db_column_int(&q, 0); zFullname = db_column_text(&q, 1); rid = db_column_int(&q, 2); crnlOk = db_column_int(&q, 3); chnged = db_column_int(&q, 4); blob_zero(&content); if( file_wd_islink(zFullname) ){ /* Instead of file content, put link destination path */ blob_read_link(&content, zFullname); }else{ blob_read_from_file(&content, zFullname); } if( !crnlOk ) cr_warning(&content, zFullname); if( chnged==1 && contains_merge_marker(&content) ){ nConflict++; fossil_print("possible unresolved merge conflict in %s\n", zFullname+strlen(g.zLocalRoot)); } nrid = content_put(&content); blob_reset(&content); if( rid>0 ){ content_deltify(rid, nrid, 0); } db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id); db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid); } db_finalize(&q); if( nConflict && !allowConflict ){ fossil_fatal("abort due to unresolve merge conflicts"); } /* Create the new manifest */ if( blob_size(&comment)==0 ){ blob_append(&comment, "(no comment)", -1); } if( forceDelta ){ blob_zero(&manifest); |
Changes to src/finfo.c.
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
} blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); if( (n = atoi(PD("n","0")))>0 ){ blob_appendf(&sql, " LIMIT %d", n); url_add_parameter(&url, "n", P("n")); } if( firstChngOnly ){ style_submenu_element("Full", "Show all changes", url_render(&url, "fco", "0", 0, 0)); }else{ style_submenu_element("Simplified", "Show only first use of a change", url_render(&url, "fco", "1", 0, 0)); } db_prepare(&q, blob_str(&sql)); blob_reset(&sql); blob_zero(&title); blob_appendf(&title, "History of "); hyperlinked_path(zFilename, &title, 0); |
| | |
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
} blob_appendf(&sql," ORDER BY event.mtime DESC /*sort*/"); if( (n = atoi(PD("n","0")))>0 ){ blob_appendf(&sql, " LIMIT %d", n); url_add_parameter(&url, "n", P("n")); } if( firstChngOnly ){ style_submenu_element("Full", "Show all changes","%s", url_render(&url, "fco", "0", 0, 0)); }else{ style_submenu_element("Simplified", "Show only first use of a change","%s", url_render(&url, "fco", "1", 0, 0)); } db_prepare(&q, blob_str(&sql)); blob_reset(&sql); blob_zero(&title); blob_appendf(&title, "History of "); hyperlinked_path(zFilename, &title, 0); |
Changes to src/merge3.c.
131 132 133 134 135 136 137 138 139 140 141 142 143 144 ... 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 ... 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 ... 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
blob_copy_lines(pOut, pSrc, aC[i+2]); sz -= aC[i] + aC[i+1]; i += 3; } return i; } /* ** Do a three-way merge. Initialize pOut to contain the result. ** ** The merge is an edit against pV2. Both pV1 and pV2 have a ** common origin at pPivot. Apply the changes of pPivot ==> pV1 ................................................................................ static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ static const char zBegin[] = "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n"; static const char zMid1[] = "======= COMMON ANCESTOR content follows ============================\n"; static const char zMid2[] = "======= MERGED IN content follows ==================================\n"; static const char zEnd[] = ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; blob_zero(pOut); /* Merge results stored in pOut */ /* Compute the edits that occur from pPivot => pV1 (into aC1) ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is ** an array of integer triples. Within each triple, the first integer ** is the number of lines of text to copy directly from the pivot, ................................................................................ */ int sz = 1; /* Size of the conflict in lines */ nConflict++; while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){ sz++; } DEBUG( printf("CONFLICT %d\n", sz); ) blob_appendf(pOut, zBegin); i1 = output_one_side(pOut, pV1, aC1, i1, sz); blob_appendf(pOut, zMid1); blob_copy_lines(pOut, pPivot, sz); blob_appendf(pOut, zMid2); i2 = output_one_side(pOut, pV2, aC2, i2, sz); blob_appendf(pOut, zEnd); } /* If we are finished with an edit triple, advance to the next ** triple. */ if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3; if( i2<limit2 && aC2[i2]==0 && aC2[i2+1]==0 && aC2[i2+2]==0 ) i2+=3; ................................................................................ blob_copy_lines(pOut, pV2, aC2[i2+2]); } free(aC1); free(aC2); return nConflict; } /* ** COMMAND: test-3-way-merge ** ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED ** ** Combine change in going from PIVOT->VERSION1 with the change going |
> > > > > > > > > > < < < < < < < < | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 ... 162 163 164 165 166 167 168 169 170 171 172 173 174 175 ... 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 ... 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
blob_copy_lines(pOut, pSrc, aC[i+2]); sz -= aC[i] + aC[i+1]; i += 3; } return i; } /* ** Text of boundary markers for merge conflicts. */ static char const * const mergeMarker[] = { /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n", "======= COMMON ANCESTOR content follows ============================\n", "======= MERGED IN content follows ==================================\n", ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" }; /* ** Do a three-way merge. Initialize pOut to contain the result. ** ** The merge is an edit against pV2. Both pV1 and pV2 have a ** common origin at pPivot. Apply the changes of pPivot ==> pV1 ................................................................................ static int blob_merge(Blob *pPivot, Blob *pV1, Blob *pV2, Blob *pOut){ int *aC1; /* Changes from pPivot to pV1 */ int *aC2; /* Changes from pPivot to pV2 */ int i1, i2; /* Index into aC1[] and aC2[] */ int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */ int limit1, limit2; /* Sizes of aC1[] and aC2[] */ int nConflict = 0; /* Number of merge conflicts seen so far */ blob_zero(pOut); /* Merge results stored in pOut */ /* Compute the edits that occur from pPivot => pV1 (into aC1) ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is ** an array of integer triples. Within each triple, the first integer ** is the number of lines of text to copy directly from the pivot, ................................................................................ */ int sz = 1; /* Size of the conflict in lines */ nConflict++; while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){ sz++; } DEBUG( printf("CONFLICT %d\n", sz); ) blob_appendf(pOut, mergeMarker[0]); i1 = output_one_side(pOut, pV1, aC1, i1, sz); blob_appendf(pOut, mergeMarker[1]); blob_copy_lines(pOut, pPivot, sz); blob_appendf(pOut, mergeMarker[2]); i2 = output_one_side(pOut, pV2, aC2, i2, sz); blob_appendf(pOut, mergeMarker[3]); } /* If we are finished with an edit triple, advance to the next ** triple. */ if( i1<limit1 && aC1[i1]==0 && aC1[i1+1]==0 && aC1[i1+2]==0 ) i1+=3; if( i2<limit2 && aC2[i2]==0 && aC2[i2+1]==0 && aC2[i2+2]==0 ) i2+=3; ................................................................................ blob_copy_lines(pOut, pV2, aC2[i2+2]); } free(aC1); free(aC2); return nConflict; } /* ** Return true if the input string contains a merge marker on a line by ** itself. */ int contains_merge_marker(Blob *p){ int i, j; int len = (int)strlen(mergeMarker[0]); const char *z = blob_buffer(p); int n = blob_size(p) - len + 1; assert( len==(int)strlen(mergeMarker[1]) ); assert( len==(int)strlen(mergeMarker[2]) ); assert( len==(int)strlen(mergeMarker[3]) ); assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 ); for(i=0; i<n; ){ for(j=0; j<4; j++){ if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1; } while( i<n && z[i]!='\n' ){ i++; } while( i<n && z[i]=='\n' ){ i++; } } return 0; } /* ** Return true if the named file contains an unresolved merge marker line. */ int file_contains_merge_marker(const char *zFullpath){ Blob file; int rc; blob_read_from_file(&file, zFullpath); rc = contains_merge_marker(&file); blob_reset(&file); return rc; } /* ** COMMAND: test-3-way-merge ** ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED ** ** Combine change in going from PIVOT->VERSION1 with the change going |