Fossil SCM
By default, the merge-info command only shows "interesting" change - actual merges, errors, and conflicts. Use the --all option to see everything.
Commit
b764f2d007a380d3347b4419a9231fb2d6a1832ac7526f8ad70714e633359a16
Parent
a199d970a551972…
2 files changed
+56
-23
+7
-4
+56
-23
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -24,11 +24,11 @@ | ||
| 24 | 24 | |
| 25 | 25 | |
| 26 | 26 | /* |
| 27 | 27 | ** Bring up a Tcl/Tk GUI to show details of the most recent merge. |
| 28 | 28 | */ |
| 29 | -static void merge_info_tk(int bDark, int nContext){ | |
| 29 | +static void merge_info_tk(int bDark, int bAll, int nContext){ | |
| 30 | 30 | int i; |
| 31 | 31 | Blob script; |
| 32 | 32 | const char *zTempFile = 0; |
| 33 | 33 | char *zCmd; |
| 34 | 34 | const char *zTclsh; |
| @@ -48,36 +48,45 @@ | ||
| 48 | 48 | blob_appendf(&script, "set filelist [list"); |
| 49 | 49 | if( g.argc==2 ){ |
| 50 | 50 | /* No files named on the command-line. Use every file mentioned |
| 51 | 51 | ** in the MERGESTAT table to generate the file list. */ |
| 52 | 52 | Stmt q; |
| 53 | + int cnt; | |
| 53 | 54 | db_prepare(&q, |
| 54 | - "SELECT coalesce(fnr,fn) FROM mergestat ORDER BY 1" | |
| 55 | + "SELECT coalesce(fnr,fn), op FROM mergestat %s ORDER BY 1", | |
| 56 | + bAll ? "" : "WHERE op IN ('MERGE','CONFLICT')" /*safe-for-%s*/ | |
| 55 | 57 | ); |
| 56 | 58 | while( db_step(&q)==SQLITE_ROW ){ |
| 57 | - blob_append_char(&script, ' '); | |
| 59 | + blob_appendf(&script," %s ", db_column_text(&q,1)); | |
| 58 | 60 | blob_append_tcl_literal(&script, db_column_text(&q,0), |
| 59 | 61 | db_column_bytes(&q,0)); |
| 62 | + cnt++; | |
| 63 | + } | |
| 64 | + db_finalize(&q); | |
| 65 | + if( cnt==0 ){ | |
| 66 | + fossil_print( | |
| 67 | + "No interesting changes in this merge. Use --all to see everything\n" | |
| 68 | + ); | |
| 69 | + return; | |
| 60 | 70 | } |
| 61 | 71 | }else{ |
| 62 | 72 | /* Use only files named on the command-line in the file list. |
| 63 | 73 | ** But verify each file named is actually found in the MERGESTAT |
| 64 | 74 | ** table first. */ |
| 65 | 75 | for(i=2; i<g.argc; i++){ |
| 66 | 76 | char *zFile; /* Input filename */ |
| 67 | 77 | char *zTreename; /* Name of the file in the tree */ |
| 68 | 78 | Blob fname; /* Filename relative to root */ |
| 79 | + char *zOp; /* Operation on this file */ | |
| 69 | 80 | zFile = mprintf("%/", g.argv[i]); |
| 70 | 81 | file_tree_name(zFile, &fname, 0, 1); |
| 82 | + fossil_free(zFile); | |
| 71 | 83 | zTreename = blob_str(&fname); |
| 72 | - if( !db_exists("SELECT 1 FROM mergestat WHERE fn=%Q OR fnr=%Q", | |
| 73 | - zTreename, zTreename) ){ | |
| 74 | - fossil_fatal("file \"%s\" is not part of the most recent merge", | |
| 75 | - g.argv[i]); | |
| 76 | - } | |
| 77 | - blob_append_char(&script, ' '); | |
| 78 | - fossil_free(zFile); | |
| 84 | + zOp = db_text(0, "SELECT op FROM mergestat WHERE fn=%Q or fnr=%Q", | |
| 85 | + zTreename, zTreename); | |
| 86 | + blob_appendf(&script, " %s ", zOp); | |
| 87 | + fossil_free(zOp); | |
| 79 | 88 | blob_append_tcl_literal(&script, zTreename, (int)strlen(zTreename)); |
| 80 | 89 | blob_reset(&fname); |
| 81 | 90 | } |
| 82 | 91 | } |
| 83 | 92 | blob_appendf(&script, "]\n"); |
| @@ -235,10 +244,12 @@ | ||
| 235 | 244 | ** table. The plan moving forward is that it can generate data for |
| 236 | 245 | ** a Tk-based GUI to show the details of the merge. This command is |
| 237 | 246 | ** a work-in-progress. |
| 238 | 247 | ** |
| 239 | 248 | ** Options: |
| 249 | +** -a|--all Show all changes. Normally only merges, conflicts, | |
| 250 | +** and errors are shown. | |
| 240 | 251 | ** -c|--context N Show N lines of context around each change, |
| 241 | 252 | ** with negative N meaning show all content. Only |
| 242 | 253 | ** meaningful in combination with --tcl or --tk. |
| 243 | 254 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 244 | 255 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| @@ -251,19 +262,23 @@ | ||
| 251 | 262 | */ |
| 252 | 263 | void merge_info_cmd(void){ |
| 253 | 264 | const char *zCnt; |
| 254 | 265 | const char *zTcl; |
| 255 | 266 | int bTk; |
| 256 | - int bDark = 0; | |
| 267 | + int bDark; | |
| 268 | + int bAll; | |
| 257 | 269 | int nContext; |
| 258 | 270 | Stmt q; |
| 271 | + const char *zWhere; | |
| 272 | + int cnt = 0; | |
| 259 | 273 | |
| 260 | 274 | db_must_be_within_tree(); |
| 261 | 275 | zTcl = find_option("tcl", 0, 1); |
| 262 | 276 | bTk = find_option("tk", 0, 0)!=0; |
| 263 | 277 | zCnt = find_option("context", "c", 1); |
| 264 | - bDark = find_option("dark", 0, 0)!=0; | |
| 278 | + bDark = find_option("dark", 0, 0)!=0; | |
| 279 | + bAll = find_option("all", "a", 0)!=0; | |
| 265 | 280 | if( bTk==0 ){ |
| 266 | 281 | verify_all_options(); |
| 267 | 282 | if( g.argc>2 ){ |
| 268 | 283 | usage("[OPTIONS]"); |
| 269 | 284 | } |
| @@ -281,33 +296,47 @@ | ||
| 281 | 296 | fossil_print("No merge data is available\n"); |
| 282 | 297 | } |
| 283 | 298 | return; |
| 284 | 299 | } |
| 285 | 300 | if( bTk ){ |
| 286 | - merge_info_tk(bDark, nContext); | |
| 301 | + merge_info_tk(bDark, bAll, nContext); | |
| 287 | 302 | return; |
| 288 | 303 | } |
| 289 | 304 | if( zTcl ){ |
| 290 | 305 | merge_info_tcl(zTcl, nContext); |
| 291 | 306 | return; |
| 292 | 307 | } |
| 308 | + if( bAll ){ | |
| 309 | + zWhere = ""; | |
| 310 | + }else{ | |
| 311 | + zWhere = "WHERE op IN ('MERGE','CONFLICT','ERROR')"; | |
| 312 | + } | |
| 293 | 313 | db_prepare(&q, |
| 294 | - /* 0 1 2 3 4 */ | |
| 295 | - "SELECT op, fn, fnr, nc, msg FROM mergestat ORDER BY coalesce(fnr,fn)" | |
| 314 | + /* 0 1 2 */ | |
| 315 | + "SELECT op, coalesce(fnr,fn), msg" | |
| 316 | + " FROM mergestat" | |
| 317 | + " %s" | |
| 318 | + " ORDER BY coalesce(fnr,fn)", | |
| 319 | + zWhere /*safe-for-%s*/ | |
| 296 | 320 | ); |
| 297 | 321 | while( db_step(&q)==SQLITE_ROW ){ |
| 298 | 322 | const char *zOp = db_column_text(&q, 0); |
| 299 | - const char *zName = db_column_text(&q, 2); | |
| 300 | - const char *zErr = db_column_text(&q, 4); | |
| 301 | - if( zName==0 ) zName = db_column_text(&q, 1); | |
| 302 | - if( zErr ){ | |
| 303 | - fossil_print("%-7s %s ** %s **\n", zOp, zName, zErr); | |
| 323 | + const char *zName = db_column_text(&q, 1); | |
| 324 | + const char *zErr = db_column_text(&q, 2); | |
| 325 | + if( zErr && fossil_strcmp(zOp,"CONFLICT")!=0 ){ | |
| 326 | + fossil_print("%-9s %s (%s)\n", zOp, zName, zErr); | |
| 304 | 327 | }else{ |
| 305 | - fossil_print("%-7s %s\n", zOp, zName); | |
| 328 | + fossil_print("%-9s %s\n", zOp, zName); | |
| 306 | 329 | } |
| 330 | + cnt++; | |
| 307 | 331 | } |
| 308 | 332 | db_finalize(&q); |
| 333 | + if( !bAll && cnt==0 ){ | |
| 334 | + fossil_print( | |
| 335 | + "No interesting change in this merge. Use --all to see everything.\n" | |
| 336 | + ); | |
| 337 | + } | |
| 309 | 338 | } |
| 310 | 339 | |
| 311 | 340 | /* |
| 312 | 341 | ** Erase all information about prior merges. Do this, for example, after |
| 313 | 342 | ** a commit. |
| @@ -1202,10 +1231,11 @@ | ||
| 1202 | 1231 | int islinkv = db_column_int(&q, 7); |
| 1203 | 1232 | int islinkm = db_column_int(&q, 8); |
| 1204 | 1233 | int chnged = db_column_int(&q, 11); |
| 1205 | 1234 | int rc; |
| 1206 | 1235 | char *zFullPath; |
| 1236 | + const char *zType = "MERGE"; | |
| 1207 | 1237 | Blob m, p, r; |
| 1208 | 1238 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 1209 | 1239 | if( verboseFlag ){ |
| 1210 | 1240 | fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n", |
| 1211 | 1241 | zName, ridp, ridm, ridv); |
| @@ -1215,11 +1245,11 @@ | ||
| 1215 | 1245 | if( islinkv || islinkm ){ |
| 1216 | 1246 | fossil_print("***** Cannot merge symlink %s\n", zName); |
| 1217 | 1247 | nConflict++; |
| 1218 | 1248 | db_multi_exec( |
| 1219 | 1249 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,fnm,ridm,fnr,nc,msg)" |
| 1220 | - "VALUES('MERGE',%Q,%d,%Q,%d,%Q,%d,%Q,1,'cannot merge symlink')", | |
| 1250 | + "VALUES('ERROR',%Q,%d,%Q,%d,%Q,%d,%Q,1,'cannot merge symlink')", | |
| 1221 | 1251 | /* fnp */ db_column_text(&q, 9), |
| 1222 | 1252 | /* ridp */ ridp, |
| 1223 | 1253 | /* fn */ zName, |
| 1224 | 1254 | /* ridv */ ridv, |
| 1225 | 1255 | /* fnm */ db_column_text(&q, 10), |
| @@ -1254,21 +1284,24 @@ | ||
| 1254 | 1284 | fossil_print("***** %d merge conflict%s in %s\n", |
| 1255 | 1285 | rc, rc>1 ? "s" : "", zName); |
| 1256 | 1286 | nConflict++; |
| 1257 | 1287 | nc = rc; |
| 1258 | 1288 | zErrMsg = "merge conflicts"; |
| 1289 | + zType = "CONFLICT"; | |
| 1259 | 1290 | } |
| 1260 | 1291 | }else{ |
| 1261 | 1292 | fossil_print("***** Cannot merge binary file %s\n", zName); |
| 1262 | 1293 | nConflict++; |
| 1263 | 1294 | nc = 1; |
| 1264 | 1295 | zErrMsg = "cannot merge binary file"; |
| 1296 | + zType = "ERROR"; | |
| 1265 | 1297 | } |
| 1266 | 1298 | db_multi_exec( |
| 1267 | 1299 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,sz,fnm,ridm,fnr,nc,msg)" |
| 1268 | - "VALUES('MERGE',%Q,%d,%Q,iif(%d,%d,NULL),iif(%d,%d,NULL),%Q,%d," | |
| 1300 | + "VALUES(%Q,%Q,%d,%Q,iif(%d,%d,NULL),iif(%d,%d,NULL),%Q,%d," | |
| 1269 | 1301 | "%Q,%d,%Q)", |
| 1302 | + /* op */ zType, | |
| 1270 | 1303 | /* fnp */ db_column_text(&q, 9), |
| 1271 | 1304 | /* ridp */ ridp, |
| 1272 | 1305 | /* fn */ zName, |
| 1273 | 1306 | /* ridv */ chnged==0, ridv, |
| 1274 | 1307 | /* sz */ chnged!=0, sz, |
| 1275 | 1308 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -24,11 +24,11 @@ | |
| 24 | |
| 25 | |
| 26 | /* |
| 27 | ** Bring up a Tcl/Tk GUI to show details of the most recent merge. |
| 28 | */ |
| 29 | static void merge_info_tk(int bDark, int nContext){ |
| 30 | int i; |
| 31 | Blob script; |
| 32 | const char *zTempFile = 0; |
| 33 | char *zCmd; |
| 34 | const char *zTclsh; |
| @@ -48,36 +48,45 @@ | |
| 48 | blob_appendf(&script, "set filelist [list"); |
| 49 | if( g.argc==2 ){ |
| 50 | /* No files named on the command-line. Use every file mentioned |
| 51 | ** in the MERGESTAT table to generate the file list. */ |
| 52 | Stmt q; |
| 53 | db_prepare(&q, |
| 54 | "SELECT coalesce(fnr,fn) FROM mergestat ORDER BY 1" |
| 55 | ); |
| 56 | while( db_step(&q)==SQLITE_ROW ){ |
| 57 | blob_append_char(&script, ' '); |
| 58 | blob_append_tcl_literal(&script, db_column_text(&q,0), |
| 59 | db_column_bytes(&q,0)); |
| 60 | } |
| 61 | }else{ |
| 62 | /* Use only files named on the command-line in the file list. |
| 63 | ** But verify each file named is actually found in the MERGESTAT |
| 64 | ** table first. */ |
| 65 | for(i=2; i<g.argc; i++){ |
| 66 | char *zFile; /* Input filename */ |
| 67 | char *zTreename; /* Name of the file in the tree */ |
| 68 | Blob fname; /* Filename relative to root */ |
| 69 | zFile = mprintf("%/", g.argv[i]); |
| 70 | file_tree_name(zFile, &fname, 0, 1); |
| 71 | zTreename = blob_str(&fname); |
| 72 | if( !db_exists("SELECT 1 FROM mergestat WHERE fn=%Q OR fnr=%Q", |
| 73 | zTreename, zTreename) ){ |
| 74 | fossil_fatal("file \"%s\" is not part of the most recent merge", |
| 75 | g.argv[i]); |
| 76 | } |
| 77 | blob_append_char(&script, ' '); |
| 78 | fossil_free(zFile); |
| 79 | blob_append_tcl_literal(&script, zTreename, (int)strlen(zTreename)); |
| 80 | blob_reset(&fname); |
| 81 | } |
| 82 | } |
| 83 | blob_appendf(&script, "]\n"); |
| @@ -235,10 +244,12 @@ | |
| 235 | ** table. The plan moving forward is that it can generate data for |
| 236 | ** a Tk-based GUI to show the details of the merge. This command is |
| 237 | ** a work-in-progress. |
| 238 | ** |
| 239 | ** Options: |
| 240 | ** -c|--context N Show N lines of context around each change, |
| 241 | ** with negative N meaning show all content. Only |
| 242 | ** meaningful in combination with --tcl or --tk. |
| 243 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 244 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| @@ -251,19 +262,23 @@ | |
| 251 | */ |
| 252 | void merge_info_cmd(void){ |
| 253 | const char *zCnt; |
| 254 | const char *zTcl; |
| 255 | int bTk; |
| 256 | int bDark = 0; |
| 257 | int nContext; |
| 258 | Stmt q; |
| 259 | |
| 260 | db_must_be_within_tree(); |
| 261 | zTcl = find_option("tcl", 0, 1); |
| 262 | bTk = find_option("tk", 0, 0)!=0; |
| 263 | zCnt = find_option("context", "c", 1); |
| 264 | bDark = find_option("dark", 0, 0)!=0; |
| 265 | if( bTk==0 ){ |
| 266 | verify_all_options(); |
| 267 | if( g.argc>2 ){ |
| 268 | usage("[OPTIONS]"); |
| 269 | } |
| @@ -281,33 +296,47 @@ | |
| 281 | fossil_print("No merge data is available\n"); |
| 282 | } |
| 283 | return; |
| 284 | } |
| 285 | if( bTk ){ |
| 286 | merge_info_tk(bDark, nContext); |
| 287 | return; |
| 288 | } |
| 289 | if( zTcl ){ |
| 290 | merge_info_tcl(zTcl, nContext); |
| 291 | return; |
| 292 | } |
| 293 | db_prepare(&q, |
| 294 | /* 0 1 2 3 4 */ |
| 295 | "SELECT op, fn, fnr, nc, msg FROM mergestat ORDER BY coalesce(fnr,fn)" |
| 296 | ); |
| 297 | while( db_step(&q)==SQLITE_ROW ){ |
| 298 | const char *zOp = db_column_text(&q, 0); |
| 299 | const char *zName = db_column_text(&q, 2); |
| 300 | const char *zErr = db_column_text(&q, 4); |
| 301 | if( zName==0 ) zName = db_column_text(&q, 1); |
| 302 | if( zErr ){ |
| 303 | fossil_print("%-7s %s ** %s **\n", zOp, zName, zErr); |
| 304 | }else{ |
| 305 | fossil_print("%-7s %s\n", zOp, zName); |
| 306 | } |
| 307 | } |
| 308 | db_finalize(&q); |
| 309 | } |
| 310 | |
| 311 | /* |
| 312 | ** Erase all information about prior merges. Do this, for example, after |
| 313 | ** a commit. |
| @@ -1202,10 +1231,11 @@ | |
| 1202 | int islinkv = db_column_int(&q, 7); |
| 1203 | int islinkm = db_column_int(&q, 8); |
| 1204 | int chnged = db_column_int(&q, 11); |
| 1205 | int rc; |
| 1206 | char *zFullPath; |
| 1207 | Blob m, p, r; |
| 1208 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 1209 | if( verboseFlag ){ |
| 1210 | fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n", |
| 1211 | zName, ridp, ridm, ridv); |
| @@ -1215,11 +1245,11 @@ | |
| 1215 | if( islinkv || islinkm ){ |
| 1216 | fossil_print("***** Cannot merge symlink %s\n", zName); |
| 1217 | nConflict++; |
| 1218 | db_multi_exec( |
| 1219 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,fnm,ridm,fnr,nc,msg)" |
| 1220 | "VALUES('MERGE',%Q,%d,%Q,%d,%Q,%d,%Q,1,'cannot merge symlink')", |
| 1221 | /* fnp */ db_column_text(&q, 9), |
| 1222 | /* ridp */ ridp, |
| 1223 | /* fn */ zName, |
| 1224 | /* ridv */ ridv, |
| 1225 | /* fnm */ db_column_text(&q, 10), |
| @@ -1254,21 +1284,24 @@ | |
| 1254 | fossil_print("***** %d merge conflict%s in %s\n", |
| 1255 | rc, rc>1 ? "s" : "", zName); |
| 1256 | nConflict++; |
| 1257 | nc = rc; |
| 1258 | zErrMsg = "merge conflicts"; |
| 1259 | } |
| 1260 | }else{ |
| 1261 | fossil_print("***** Cannot merge binary file %s\n", zName); |
| 1262 | nConflict++; |
| 1263 | nc = 1; |
| 1264 | zErrMsg = "cannot merge binary file"; |
| 1265 | } |
| 1266 | db_multi_exec( |
| 1267 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,sz,fnm,ridm,fnr,nc,msg)" |
| 1268 | "VALUES('MERGE',%Q,%d,%Q,iif(%d,%d,NULL),iif(%d,%d,NULL),%Q,%d," |
| 1269 | "%Q,%d,%Q)", |
| 1270 | /* fnp */ db_column_text(&q, 9), |
| 1271 | /* ridp */ ridp, |
| 1272 | /* fn */ zName, |
| 1273 | /* ridv */ chnged==0, ridv, |
| 1274 | /* sz */ chnged!=0, sz, |
| 1275 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -24,11 +24,11 @@ | |
| 24 | |
| 25 | |
| 26 | /* |
| 27 | ** Bring up a Tcl/Tk GUI to show details of the most recent merge. |
| 28 | */ |
| 29 | static void merge_info_tk(int bDark, int bAll, int nContext){ |
| 30 | int i; |
| 31 | Blob script; |
| 32 | const char *zTempFile = 0; |
| 33 | char *zCmd; |
| 34 | const char *zTclsh; |
| @@ -48,36 +48,45 @@ | |
| 48 | blob_appendf(&script, "set filelist [list"); |
| 49 | if( g.argc==2 ){ |
| 50 | /* No files named on the command-line. Use every file mentioned |
| 51 | ** in the MERGESTAT table to generate the file list. */ |
| 52 | Stmt q; |
| 53 | int cnt; |
| 54 | db_prepare(&q, |
| 55 | "SELECT coalesce(fnr,fn), op FROM mergestat %s ORDER BY 1", |
| 56 | bAll ? "" : "WHERE op IN ('MERGE','CONFLICT')" /*safe-for-%s*/ |
| 57 | ); |
| 58 | while( db_step(&q)==SQLITE_ROW ){ |
| 59 | blob_appendf(&script," %s ", db_column_text(&q,1)); |
| 60 | blob_append_tcl_literal(&script, db_column_text(&q,0), |
| 61 | db_column_bytes(&q,0)); |
| 62 | cnt++; |
| 63 | } |
| 64 | db_finalize(&q); |
| 65 | if( cnt==0 ){ |
| 66 | fossil_print( |
| 67 | "No interesting changes in this merge. Use --all to see everything\n" |
| 68 | ); |
| 69 | return; |
| 70 | } |
| 71 | }else{ |
| 72 | /* Use only files named on the command-line in the file list. |
| 73 | ** But verify each file named is actually found in the MERGESTAT |
| 74 | ** table first. */ |
| 75 | for(i=2; i<g.argc; i++){ |
| 76 | char *zFile; /* Input filename */ |
| 77 | char *zTreename; /* Name of the file in the tree */ |
| 78 | Blob fname; /* Filename relative to root */ |
| 79 | char *zOp; /* Operation on this file */ |
| 80 | zFile = mprintf("%/", g.argv[i]); |
| 81 | file_tree_name(zFile, &fname, 0, 1); |
| 82 | fossil_free(zFile); |
| 83 | zTreename = blob_str(&fname); |
| 84 | zOp = db_text(0, "SELECT op FROM mergestat WHERE fn=%Q or fnr=%Q", |
| 85 | zTreename, zTreename); |
| 86 | blob_appendf(&script, " %s ", zOp); |
| 87 | fossil_free(zOp); |
| 88 | blob_append_tcl_literal(&script, zTreename, (int)strlen(zTreename)); |
| 89 | blob_reset(&fname); |
| 90 | } |
| 91 | } |
| 92 | blob_appendf(&script, "]\n"); |
| @@ -235,10 +244,12 @@ | |
| 244 | ** table. The plan moving forward is that it can generate data for |
| 245 | ** a Tk-based GUI to show the details of the merge. This command is |
| 246 | ** a work-in-progress. |
| 247 | ** |
| 248 | ** Options: |
| 249 | ** -a|--all Show all changes. Normally only merges, conflicts, |
| 250 | ** and errors are shown. |
| 251 | ** -c|--context N Show N lines of context around each change, |
| 252 | ** with negative N meaning show all content. Only |
| 253 | ** meaningful in combination with --tcl or --tk. |
| 254 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 255 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| @@ -251,19 +262,23 @@ | |
| 262 | */ |
| 263 | void merge_info_cmd(void){ |
| 264 | const char *zCnt; |
| 265 | const char *zTcl; |
| 266 | int bTk; |
| 267 | int bDark; |
| 268 | int bAll; |
| 269 | int nContext; |
| 270 | Stmt q; |
| 271 | const char *zWhere; |
| 272 | int cnt = 0; |
| 273 | |
| 274 | db_must_be_within_tree(); |
| 275 | zTcl = find_option("tcl", 0, 1); |
| 276 | bTk = find_option("tk", 0, 0)!=0; |
| 277 | zCnt = find_option("context", "c", 1); |
| 278 | bDark = find_option("dark", 0, 0)!=0; |
| 279 | bAll = find_option("all", "a", 0)!=0; |
| 280 | if( bTk==0 ){ |
| 281 | verify_all_options(); |
| 282 | if( g.argc>2 ){ |
| 283 | usage("[OPTIONS]"); |
| 284 | } |
| @@ -281,33 +296,47 @@ | |
| 296 | fossil_print("No merge data is available\n"); |
| 297 | } |
| 298 | return; |
| 299 | } |
| 300 | if( bTk ){ |
| 301 | merge_info_tk(bDark, bAll, nContext); |
| 302 | return; |
| 303 | } |
| 304 | if( zTcl ){ |
| 305 | merge_info_tcl(zTcl, nContext); |
| 306 | return; |
| 307 | } |
| 308 | if( bAll ){ |
| 309 | zWhere = ""; |
| 310 | }else{ |
| 311 | zWhere = "WHERE op IN ('MERGE','CONFLICT','ERROR')"; |
| 312 | } |
| 313 | db_prepare(&q, |
| 314 | /* 0 1 2 */ |
| 315 | "SELECT op, coalesce(fnr,fn), msg" |
| 316 | " FROM mergestat" |
| 317 | " %s" |
| 318 | " ORDER BY coalesce(fnr,fn)", |
| 319 | zWhere /*safe-for-%s*/ |
| 320 | ); |
| 321 | while( db_step(&q)==SQLITE_ROW ){ |
| 322 | const char *zOp = db_column_text(&q, 0); |
| 323 | const char *zName = db_column_text(&q, 1); |
| 324 | const char *zErr = db_column_text(&q, 2); |
| 325 | if( zErr && fossil_strcmp(zOp,"CONFLICT")!=0 ){ |
| 326 | fossil_print("%-9s %s (%s)\n", zOp, zName, zErr); |
| 327 | }else{ |
| 328 | fossil_print("%-9s %s\n", zOp, zName); |
| 329 | } |
| 330 | cnt++; |
| 331 | } |
| 332 | db_finalize(&q); |
| 333 | if( !bAll && cnt==0 ){ |
| 334 | fossil_print( |
| 335 | "No interesting change in this merge. Use --all to see everything.\n" |
| 336 | ); |
| 337 | } |
| 338 | } |
| 339 | |
| 340 | /* |
| 341 | ** Erase all information about prior merges. Do this, for example, after |
| 342 | ** a commit. |
| @@ -1202,10 +1231,11 @@ | |
| 1231 | int islinkv = db_column_int(&q, 7); |
| 1232 | int islinkm = db_column_int(&q, 8); |
| 1233 | int chnged = db_column_int(&q, 11); |
| 1234 | int rc; |
| 1235 | char *zFullPath; |
| 1236 | const char *zType = "MERGE"; |
| 1237 | Blob m, p, r; |
| 1238 | /* Do a 3-way merge of idp->idm into idp->idv. The results go into idv. */ |
| 1239 | if( verboseFlag ){ |
| 1240 | fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n", |
| 1241 | zName, ridp, ridm, ridv); |
| @@ -1215,11 +1245,11 @@ | |
| 1245 | if( islinkv || islinkm ){ |
| 1246 | fossil_print("***** Cannot merge symlink %s\n", zName); |
| 1247 | nConflict++; |
| 1248 | db_multi_exec( |
| 1249 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,fnm,ridm,fnr,nc,msg)" |
| 1250 | "VALUES('ERROR',%Q,%d,%Q,%d,%Q,%d,%Q,1,'cannot merge symlink')", |
| 1251 | /* fnp */ db_column_text(&q, 9), |
| 1252 | /* ridp */ ridp, |
| 1253 | /* fn */ zName, |
| 1254 | /* ridv */ ridv, |
| 1255 | /* fnm */ db_column_text(&q, 10), |
| @@ -1254,21 +1284,24 @@ | |
| 1284 | fossil_print("***** %d merge conflict%s in %s\n", |
| 1285 | rc, rc>1 ? "s" : "", zName); |
| 1286 | nConflict++; |
| 1287 | nc = rc; |
| 1288 | zErrMsg = "merge conflicts"; |
| 1289 | zType = "CONFLICT"; |
| 1290 | } |
| 1291 | }else{ |
| 1292 | fossil_print("***** Cannot merge binary file %s\n", zName); |
| 1293 | nConflict++; |
| 1294 | nc = 1; |
| 1295 | zErrMsg = "cannot merge binary file"; |
| 1296 | zType = "ERROR"; |
| 1297 | } |
| 1298 | db_multi_exec( |
| 1299 | "INSERT INTO mergestat(op,fnp,ridp,fn,ridv,sz,fnm,ridm,fnr,nc,msg)" |
| 1300 | "VALUES(%Q,%Q,%d,%Q,iif(%d,%d,NULL),iif(%d,%d,NULL),%Q,%d," |
| 1301 | "%Q,%d,%Q)", |
| 1302 | /* op */ zType, |
| 1303 | /* fnp */ db_column_text(&q, 9), |
| 1304 | /* ridp */ ridp, |
| 1305 | /* fn */ zName, |
| 1306 | /* ridv */ chnged==0, ridv, |
| 1307 | /* sz */ chnged!=0, sz, |
| 1308 |
+7
-4
| --- src/merge.tcl | ||
| +++ src/merge.tcl | ||
| @@ -319,15 +319,17 @@ | ||
| 319 | 319 | toplevel .wfiles |
| 320 | 320 | wm withdraw .wfiles |
| 321 | 321 | update idletasks |
| 322 | 322 | wm transient .wfiles . |
| 323 | 323 | wm overrideredirect .wfiles 1 |
| 324 | - set ht [llength $filelist] | |
| 324 | + set ht [expr {[llength $filelist]/2}] | |
| 325 | 325 | if {$ht>$CFG(LB_HEIGHT)} {set ht $CFG(LB_HEIGHT)} |
| 326 | 326 | listbox .wfiles.lb -width 0 -height $ht -activestyle none \ |
| 327 | 327 | -yscroll {.wfiles.sb set} |
| 328 | - .wfiles.lb insert end {*}$filelist | |
| 328 | + foreach {op fn} $filelist { | |
| 329 | + .wfiles.lb insert end [format "%-9s %s" $op $fn] | |
| 330 | + } | |
| 329 | 331 | ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 330 | 332 | grid .wfiles.lb .wfiles.sb -sticky ns |
| 331 | 333 | bind .bb.files <1> { |
| 332 | 334 | set x [winfo rootx %W] |
| 333 | 335 | set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| @@ -337,11 +339,12 @@ | ||
| 337 | 339 | } |
| 338 | 340 | bind .wfiles <FocusOut> {wm withdraw .wfiles} |
| 339 | 341 | bind .wfiles <Escape> {focus .} |
| 340 | 342 | foreach evt {1 Return} { |
| 341 | 343 | bind .wfiles.lb <$evt> { |
| 342 | - readMerge "$::fossilcmd [list [lindex $::filelist [%W curselection]]]" | |
| 344 | + set ii [%W curselection] | |
| 345 | + readMerge "$::fossilcmd [list [lindex $::filelist [expr {$ii*2+1}]]]" | |
| 343 | 346 | focus . |
| 344 | 347 | break |
| 345 | 348 | } |
| 346 | 349 | } |
| 347 | 350 | bind .wfiles.lb <Motion> { |
| @@ -394,11 +397,11 @@ | ||
| 394 | 397 | ::ttk::scrollbar .sbxC -command {.txtC xview} -orient horizontal |
| 395 | 398 | ::ttk::scrollbar .sbxD -command {.txtD xview} -orient horizontal |
| 396 | 399 | frame .spacer |
| 397 | 400 | |
| 398 | 401 | if {[info exists filelist]} { |
| 399 | - readMerge "$fossilcmd [list [lindex $filelist 0]]" | |
| 402 | + readMerge "$fossilcmd [list [lindex $filelist 1]]" | |
| 400 | 403 | } else { |
| 401 | 404 | readMerge $fossilcmd |
| 402 | 405 | } |
| 403 | 406 | update idletasks |
| 404 | 407 | |
| 405 | 408 |
| --- src/merge.tcl | |
| +++ src/merge.tcl | |
| @@ -319,15 +319,17 @@ | |
| 319 | toplevel .wfiles |
| 320 | wm withdraw .wfiles |
| 321 | update idletasks |
| 322 | wm transient .wfiles . |
| 323 | wm overrideredirect .wfiles 1 |
| 324 | set ht [llength $filelist] |
| 325 | if {$ht>$CFG(LB_HEIGHT)} {set ht $CFG(LB_HEIGHT)} |
| 326 | listbox .wfiles.lb -width 0 -height $ht -activestyle none \ |
| 327 | -yscroll {.wfiles.sb set} |
| 328 | .wfiles.lb insert end {*}$filelist |
| 329 | ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 330 | grid .wfiles.lb .wfiles.sb -sticky ns |
| 331 | bind .bb.files <1> { |
| 332 | set x [winfo rootx %W] |
| 333 | set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| @@ -337,11 +339,12 @@ | |
| 337 | } |
| 338 | bind .wfiles <FocusOut> {wm withdraw .wfiles} |
| 339 | bind .wfiles <Escape> {focus .} |
| 340 | foreach evt {1 Return} { |
| 341 | bind .wfiles.lb <$evt> { |
| 342 | readMerge "$::fossilcmd [list [lindex $::filelist [%W curselection]]]" |
| 343 | focus . |
| 344 | break |
| 345 | } |
| 346 | } |
| 347 | bind .wfiles.lb <Motion> { |
| @@ -394,11 +397,11 @@ | |
| 394 | ::ttk::scrollbar .sbxC -command {.txtC xview} -orient horizontal |
| 395 | ::ttk::scrollbar .sbxD -command {.txtD xview} -orient horizontal |
| 396 | frame .spacer |
| 397 | |
| 398 | if {[info exists filelist]} { |
| 399 | readMerge "$fossilcmd [list [lindex $filelist 0]]" |
| 400 | } else { |
| 401 | readMerge $fossilcmd |
| 402 | } |
| 403 | update idletasks |
| 404 | |
| 405 |
| --- src/merge.tcl | |
| +++ src/merge.tcl | |
| @@ -319,15 +319,17 @@ | |
| 319 | toplevel .wfiles |
| 320 | wm withdraw .wfiles |
| 321 | update idletasks |
| 322 | wm transient .wfiles . |
| 323 | wm overrideredirect .wfiles 1 |
| 324 | set ht [expr {[llength $filelist]/2}] |
| 325 | if {$ht>$CFG(LB_HEIGHT)} {set ht $CFG(LB_HEIGHT)} |
| 326 | listbox .wfiles.lb -width 0 -height $ht -activestyle none \ |
| 327 | -yscroll {.wfiles.sb set} |
| 328 | foreach {op fn} $filelist { |
| 329 | .wfiles.lb insert end [format "%-9s %s" $op $fn] |
| 330 | } |
| 331 | ::ttk::scrollbar .wfiles.sb -command {.wfiles.lb yview} |
| 332 | grid .wfiles.lb .wfiles.sb -sticky ns |
| 333 | bind .bb.files <1> { |
| 334 | set x [winfo rootx %W] |
| 335 | set y [expr {[winfo rooty %W]+[winfo height %W]}] |
| @@ -337,11 +339,12 @@ | |
| 339 | } |
| 340 | bind .wfiles <FocusOut> {wm withdraw .wfiles} |
| 341 | bind .wfiles <Escape> {focus .} |
| 342 | foreach evt {1 Return} { |
| 343 | bind .wfiles.lb <$evt> { |
| 344 | set ii [%W curselection] |
| 345 | readMerge "$::fossilcmd [list [lindex $::filelist [expr {$ii*2+1}]]]" |
| 346 | focus . |
| 347 | break |
| 348 | } |
| 349 | } |
| 350 | bind .wfiles.lb <Motion> { |
| @@ -394,11 +397,11 @@ | |
| 397 | ::ttk::scrollbar .sbxC -command {.txtC xview} -orient horizontal |
| 398 | ::ttk::scrollbar .sbxD -command {.txtD xview} -orient horizontal |
| 399 | frame .spacer |
| 400 | |
| 401 | if {[info exists filelist]} { |
| 402 | readMerge "$fossilcmd [list [lindex $filelist 1]]" |
| 403 | } else { |
| 404 | readMerge $fossilcmd |
| 405 | } |
| 406 | update idletasks |
| 407 | |
| 408 |