Fossil SCM
Improve the "fossil merge-info --tk" GUI by adding a new menu to show two-way diffs between selected columns. This enhancement required other diff-related enhancements: (1) add the --label option to all diff commands. (2) Add the new "fossil fdiff" command.
Commit
e54a4b5fa96df3313ce22ae22794034f926e604c3e821a3008c9cdb3f06bf80f
Parent
97aee327ef8e144…
5 files changed
+52
-3
+32
-12
+2
+70
-4
+43
-11
+52
-3
| --- src/diff.c | ||
| +++ src/diff.c | ||
| @@ -108,10 +108,11 @@ | ||
| 108 | 108 | u32 nFile; /* Number of files diffed so far */ |
| 109 | 109 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 110 | 110 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 111 | 111 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 112 | 112 | const char *zLeftHash; /* HASH-id of the left file */ |
| 113 | + const char *azLabel[2]; /* Optional labels for left and right files */ | |
| 113 | 114 | }; |
| 114 | 115 | |
| 115 | 116 | #endif /* INTERFACE */ |
| 116 | 117 | |
| 117 | 118 | /* |
| @@ -3236,10 +3237,11 @@ | ||
| 3236 | 3237 | ** --dark Use dark mode for Tcl/Tk and HTML output |
| 3237 | 3238 | ** --html Format for HTML DIFF_HTML |
| 3238 | 3239 | ** -i|--internal Use built-in diff, not an external tool |
| 3239 | 3240 | ** --invert Invert the diff DIFF_INVERT |
| 3240 | 3241 | ** --json Output formatted as JSON |
| 3242 | +** --label NAME Column label. Can be repeated once. | |
| 3241 | 3243 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 3242 | 3244 | ** -N|--new-file Alias for --verbose |
| 3243 | 3245 | ** --noopt Disable optimization DIFF_NOOPT |
| 3244 | 3246 | ** --numstat Show change counts DIFF_NUMSTAT |
| 3245 | 3247 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| @@ -3308,10 +3310,14 @@ | ||
| 3308 | 3310 | } |
| 3309 | 3311 | } |
| 3310 | 3312 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3311 | 3313 | pCfg->wColumn = f; |
| 3312 | 3314 | } |
| 3315 | + pCfg->azLabel[0] = find_option("label",0,1); | |
| 3316 | + if( pCfg->azLabel[0] ){ | |
| 3317 | + pCfg->azLabel[1] = find_option("label",0,1); | |
| 3318 | + } | |
| 3313 | 3319 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3314 | 3320 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 3315 | 3321 | if( find_option("numstat",0,0)!=0 ) diffFlags |= DIFF_NUMSTAT; |
| 3316 | 3322 | if( find_option("versions","h",0)!=0 ) diffFlags |= DIFF_SHOW_VERS; |
| 3317 | 3323 | if( find_option("dark",0,0)!=0 ) diffFlags |= DIFF_DARKMODE; |
| @@ -3353,13 +3359,10 @@ | ||
| 3353 | 3359 | ** computing differences between files that are under management. |
| 3354 | 3360 | ** |
| 3355 | 3361 | ** This command prints the differences between the two files FILE1 and FILE2. |
| 3356 | 3362 | ** all of the usual diff formatting options (--tk, --by, -c N, etc.) apply. |
| 3357 | 3363 | ** See the "diff" command for a full list of command-line options. |
| 3358 | -** | |
| 3359 | -** This command used to be called "test-diff". The older "test-diff" spelling | |
| 3360 | -** still works, for compatibility. | |
| 3361 | 3364 | */ |
| 3362 | 3365 | void xdiff_cmd(void){ |
| 3363 | 3366 | Blob a, b, out; |
| 3364 | 3367 | const char *zRe; /* Regex filter for diff output */ |
| 3365 | 3368 | DiffConfig DCfg; |
| @@ -3381,10 +3384,56 @@ | ||
| 3381 | 3384 | blob_zero(&out); |
| 3382 | 3385 | diff_begin(&DCfg); |
| 3383 | 3386 | diff_print_filenames(g.argv[2], g.argv[3], &DCfg, &out); |
| 3384 | 3387 | blob_read_from_file(&a, g.argv[2], ExtFILE); |
| 3385 | 3388 | blob_read_from_file(&b, g.argv[3], ExtFILE); |
| 3389 | + text_diff(&a, &b, &out, &DCfg); | |
| 3390 | + blob_write_to_file(&out, "-"); | |
| 3391 | + diff_end(&DCfg, 0); | |
| 3392 | + re_free(DCfg.pRe); | |
| 3393 | +} | |
| 3394 | + | |
| 3395 | +/* | |
| 3396 | +** COMMAND: fdiff | |
| 3397 | +** | |
| 3398 | +** Usage: %fossil fdiff [options] HASH1 HASH2 | |
| 3399 | +** | |
| 3400 | +** Compute a diff between two artifacts in a repository (either a repository | |
| 3401 | +** identified by the "-R FILENAME" option, or the repository that contains | |
| 3402 | +** the working directory). | |
| 3403 | +** | |
| 3404 | +** All of the usual diff formatting options (--tk, --by, -c N, etc.) apply. | |
| 3405 | +** See the "diff" command for a full list of command-line options. | |
| 3406 | +*/ | |
| 3407 | +void fdiff_cmd(void){ | |
| 3408 | + Blob a, b, out; | |
| 3409 | + const char *zRe; /* Regex filter for diff output */ | |
| 3410 | + int rid; | |
| 3411 | + DiffConfig DCfg; | |
| 3412 | + | |
| 3413 | + if( find_option("tk",0,0)!=0 ){ | |
| 3414 | + diff_tk("fdiff", 2); | |
| 3415 | + return; | |
| 3416 | + } | |
| 3417 | + find_option("i",0,0); | |
| 3418 | + find_option("v",0,0); | |
| 3419 | + diff_options(&DCfg, 0, 0); | |
| 3420 | + zRe = find_option("regexp","e",1); | |
| 3421 | + if( zRe ){ | |
| 3422 | + const char *zErr = re_compile(&DCfg.pRe, zRe, 0); | |
| 3423 | + if( zErr ) fossil_fatal("regex error: %s", zErr); | |
| 3424 | + } | |
| 3425 | + db_find_and_open_repository(0, 0); | |
| 3426 | + verify_all_options(); | |
| 3427 | + if( g.argc!=4 ) usage("HASH1 HASH2"); | |
| 3428 | + blob_zero(&out); | |
| 3429 | + diff_begin(&DCfg); | |
| 3430 | + diff_print_filenames(g.argv[2], g.argv[3], &DCfg, &out); | |
| 3431 | + rid = name_to_typed_rid(g.argv[2], 0); | |
| 3432 | + content_get(rid, &a); | |
| 3433 | + rid = name_to_typed_rid(g.argv[3], 0); | |
| 3434 | + content_get(rid, &b); | |
| 3386 | 3435 | text_diff(&a, &b, &out, &DCfg); |
| 3387 | 3436 | blob_write_to_file(&out, "-"); |
| 3388 | 3437 | diff_end(&DCfg, 0); |
| 3389 | 3438 | re_free(DCfg.pRe); |
| 3390 | 3439 | } |
| 3391 | 3440 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -108,10 +108,11 @@ | |
| 108 | u32 nFile; /* Number of files diffed so far */ |
| 109 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 110 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 111 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 112 | const char *zLeftHash; /* HASH-id of the left file */ |
| 113 | }; |
| 114 | |
| 115 | #endif /* INTERFACE */ |
| 116 | |
| 117 | /* |
| @@ -3236,10 +3237,11 @@ | |
| 3236 | ** --dark Use dark mode for Tcl/Tk and HTML output |
| 3237 | ** --html Format for HTML DIFF_HTML |
| 3238 | ** -i|--internal Use built-in diff, not an external tool |
| 3239 | ** --invert Invert the diff DIFF_INVERT |
| 3240 | ** --json Output formatted as JSON |
| 3241 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 3242 | ** -N|--new-file Alias for --verbose |
| 3243 | ** --noopt Disable optimization DIFF_NOOPT |
| 3244 | ** --numstat Show change counts DIFF_NUMSTAT |
| 3245 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| @@ -3308,10 +3310,14 @@ | |
| 3308 | } |
| 3309 | } |
| 3310 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3311 | pCfg->wColumn = f; |
| 3312 | } |
| 3313 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3314 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 3315 | if( find_option("numstat",0,0)!=0 ) diffFlags |= DIFF_NUMSTAT; |
| 3316 | if( find_option("versions","h",0)!=0 ) diffFlags |= DIFF_SHOW_VERS; |
| 3317 | if( find_option("dark",0,0)!=0 ) diffFlags |= DIFF_DARKMODE; |
| @@ -3353,13 +3359,10 @@ | |
| 3353 | ** computing differences between files that are under management. |
| 3354 | ** |
| 3355 | ** This command prints the differences between the two files FILE1 and FILE2. |
| 3356 | ** all of the usual diff formatting options (--tk, --by, -c N, etc.) apply. |
| 3357 | ** See the "diff" command for a full list of command-line options. |
| 3358 | ** |
| 3359 | ** This command used to be called "test-diff". The older "test-diff" spelling |
| 3360 | ** still works, for compatibility. |
| 3361 | */ |
| 3362 | void xdiff_cmd(void){ |
| 3363 | Blob a, b, out; |
| 3364 | const char *zRe; /* Regex filter for diff output */ |
| 3365 | DiffConfig DCfg; |
| @@ -3381,10 +3384,56 @@ | |
| 3381 | blob_zero(&out); |
| 3382 | diff_begin(&DCfg); |
| 3383 | diff_print_filenames(g.argv[2], g.argv[3], &DCfg, &out); |
| 3384 | blob_read_from_file(&a, g.argv[2], ExtFILE); |
| 3385 | blob_read_from_file(&b, g.argv[3], ExtFILE); |
| 3386 | text_diff(&a, &b, &out, &DCfg); |
| 3387 | blob_write_to_file(&out, "-"); |
| 3388 | diff_end(&DCfg, 0); |
| 3389 | re_free(DCfg.pRe); |
| 3390 | } |
| 3391 |
| --- src/diff.c | |
| +++ src/diff.c | |
| @@ -108,10 +108,11 @@ | |
| 108 | u32 nFile; /* Number of files diffed so far */ |
| 109 | const char *zDiffCmd; /* External diff command to use instead of builtin */ |
| 110 | const char *zBinGlob; /* GLOB pattern for binary files */ |
| 111 | ReCompiled *pRe; /* Show only changes matching this pattern */ |
| 112 | const char *zLeftHash; /* HASH-id of the left file */ |
| 113 | const char *azLabel[2]; /* Optional labels for left and right files */ |
| 114 | }; |
| 115 | |
| 116 | #endif /* INTERFACE */ |
| 117 | |
| 118 | /* |
| @@ -3236,10 +3237,11 @@ | |
| 3237 | ** --dark Use dark mode for Tcl/Tk and HTML output |
| 3238 | ** --html Format for HTML DIFF_HTML |
| 3239 | ** -i|--internal Use built-in diff, not an external tool |
| 3240 | ** --invert Invert the diff DIFF_INVERT |
| 3241 | ** --json Output formatted as JSON |
| 3242 | ** --label NAME Column label. Can be repeated once. |
| 3243 | ** -n|--linenum Show line numbers DIFF_LINENO |
| 3244 | ** -N|--new-file Alias for --verbose |
| 3245 | ** --noopt Disable optimization DIFF_NOOPT |
| 3246 | ** --numstat Show change counts DIFF_NUMSTAT |
| 3247 | ** --strip-trailing-cr Strip trailing CR DIFF_STRIP_EOLCR |
| @@ -3308,10 +3310,14 @@ | |
| 3310 | } |
| 3311 | } |
| 3312 | if( (z = find_option("width","W",1))!=0 && (f = atoi(z))>0 ){ |
| 3313 | pCfg->wColumn = f; |
| 3314 | } |
| 3315 | pCfg->azLabel[0] = find_option("label",0,1); |
| 3316 | if( pCfg->azLabel[0] ){ |
| 3317 | pCfg->azLabel[1] = find_option("label",0,1); |
| 3318 | } |
| 3319 | if( find_option("linenum","n",0)!=0 ) diffFlags |= DIFF_LINENO; |
| 3320 | if( find_option("noopt",0,0)!=0 ) diffFlags |= DIFF_NOOPT; |
| 3321 | if( find_option("numstat",0,0)!=0 ) diffFlags |= DIFF_NUMSTAT; |
| 3322 | if( find_option("versions","h",0)!=0 ) diffFlags |= DIFF_SHOW_VERS; |
| 3323 | if( find_option("dark",0,0)!=0 ) diffFlags |= DIFF_DARKMODE; |
| @@ -3353,13 +3359,10 @@ | |
| 3359 | ** computing differences between files that are under management. |
| 3360 | ** |
| 3361 | ** This command prints the differences between the two files FILE1 and FILE2. |
| 3362 | ** all of the usual diff formatting options (--tk, --by, -c N, etc.) apply. |
| 3363 | ** See the "diff" command for a full list of command-line options. |
| 3364 | */ |
| 3365 | void xdiff_cmd(void){ |
| 3366 | Blob a, b, out; |
| 3367 | const char *zRe; /* Regex filter for diff output */ |
| 3368 | DiffConfig DCfg; |
| @@ -3381,10 +3384,56 @@ | |
| 3384 | blob_zero(&out); |
| 3385 | diff_begin(&DCfg); |
| 3386 | diff_print_filenames(g.argv[2], g.argv[3], &DCfg, &out); |
| 3387 | blob_read_from_file(&a, g.argv[2], ExtFILE); |
| 3388 | blob_read_from_file(&b, g.argv[3], ExtFILE); |
| 3389 | text_diff(&a, &b, &out, &DCfg); |
| 3390 | blob_write_to_file(&out, "-"); |
| 3391 | diff_end(&DCfg, 0); |
| 3392 | re_free(DCfg.pRe); |
| 3393 | } |
| 3394 | |
| 3395 | /* |
| 3396 | ** COMMAND: fdiff |
| 3397 | ** |
| 3398 | ** Usage: %fossil fdiff [options] HASH1 HASH2 |
| 3399 | ** |
| 3400 | ** Compute a diff between two artifacts in a repository (either a repository |
| 3401 | ** identified by the "-R FILENAME" option, or the repository that contains |
| 3402 | ** the working directory). |
| 3403 | ** |
| 3404 | ** All of the usual diff formatting options (--tk, --by, -c N, etc.) apply. |
| 3405 | ** See the "diff" command for a full list of command-line options. |
| 3406 | */ |
| 3407 | void fdiff_cmd(void){ |
| 3408 | Blob a, b, out; |
| 3409 | const char *zRe; /* Regex filter for diff output */ |
| 3410 | int rid; |
| 3411 | DiffConfig DCfg; |
| 3412 | |
| 3413 | if( find_option("tk",0,0)!=0 ){ |
| 3414 | diff_tk("fdiff", 2); |
| 3415 | return; |
| 3416 | } |
| 3417 | find_option("i",0,0); |
| 3418 | find_option("v",0,0); |
| 3419 | diff_options(&DCfg, 0, 0); |
| 3420 | zRe = find_option("regexp","e",1); |
| 3421 | if( zRe ){ |
| 3422 | const char *zErr = re_compile(&DCfg.pRe, zRe, 0); |
| 3423 | if( zErr ) fossil_fatal("regex error: %s", zErr); |
| 3424 | } |
| 3425 | db_find_and_open_repository(0, 0); |
| 3426 | verify_all_options(); |
| 3427 | if( g.argc!=4 ) usage("HASH1 HASH2"); |
| 3428 | blob_zero(&out); |
| 3429 | diff_begin(&DCfg); |
| 3430 | diff_print_filenames(g.argv[2], g.argv[3], &DCfg, &out); |
| 3431 | rid = name_to_typed_rid(g.argv[2], 0); |
| 3432 | content_get(rid, &a); |
| 3433 | rid = name_to_typed_rid(g.argv[3], 0); |
| 3434 | content_get(rid, &b); |
| 3435 | text_diff(&a, &b, &out, &DCfg); |
| 3436 | blob_write_to_file(&out, "-"); |
| 3437 | diff_end(&DCfg, 0); |
| 3438 | re_free(DCfg.pRe); |
| 3439 | } |
| 3440 |
+32
-12
| --- src/diff.tcl | ||
| +++ src/diff.tcl | ||
| @@ -110,34 +110,54 @@ | ||
| 110 | 110 | |
| 111 | 111 | set fromIndex [lsearch -glob $fossilcmd *-from] |
| 112 | 112 | set toIndex [lsearch -glob $fossilcmd *-to] |
| 113 | 113 | set branchIndex [lsearch -glob $fossilcmd *-branch] |
| 114 | 114 | set checkinIndex [lsearch -glob $fossilcmd *-checkin] |
| 115 | - if {[string match *?--external-baseline* $fossilcmd]} { | |
| 116 | - set fA {external baseline} | |
| 115 | + if {[lsearch -glob $fossilcmd *-label]>=0} { | |
| 116 | + set fA {} | |
| 117 | + set fB {} | |
| 117 | 118 | } else { |
| 118 | - set fA {base check-in} | |
| 119 | - } | |
| 120 | - set fB {current check-out} | |
| 121 | - if {$fromIndex > -1} {set fA [lindex $fossilcmd $fromIndex+1]} | |
| 122 | - if {$toIndex > -1} {set fB [lindex $fossilcmd $toIndex+1]} | |
| 123 | - if {$branchIndex > -1} {set fA "branch point"; set fB "leaf of branch '[lindex $fossilcmd $branchIndex+1]'"} | |
| 124 | - if {$checkinIndex > -1} {set fA "primary parent"; set fB [lindex $fossilcmd $checkinIndex+1]} | |
| 125 | - | |
| 119 | + if {[string match *?--external-baseline* $fossilcmd]} { | |
| 120 | + set fA {external baseline} | |
| 121 | + } else { | |
| 122 | + set fA {base check-in} | |
| 123 | + } | |
| 124 | + set fB {current check-out} | |
| 125 | + if {$fromIndex > -1} { | |
| 126 | + set fA [lindex $fossilcmd $fromIndex+1] | |
| 127 | + } | |
| 128 | + if {$toIndex > -1} { | |
| 129 | + set fB [lindex $fossilcmd $toIndex+1] | |
| 130 | + } | |
| 131 | + if {$branchIndex > -1} { | |
| 132 | + set fA "branch point"; set fB "leaf of branch '[lindex $fossilcmd $branchIndex+1]'" | |
| 133 | + } | |
| 134 | + if {$checkinIndex > -1} { | |
| 135 | + set fA "primary parent"; set fB [lindex $fossilcmd $checkinIndex+1] | |
| 136 | + } | |
| 137 | + } | |
| 126 | 138 | |
| 127 | 139 | while {[set line [getLine $difftxt $N ii]] != -1} { |
| 128 | 140 | switch -- [lindex $line 0] { |
| 129 | 141 | FILE { |
| 130 | 142 | incr nDiffs |
| 131 | 143 | foreach wx [list [string length $n1] [string length $n2]] { |
| 132 | 144 | if {$wx>$widths(ln)} {set widths(ln) $wx} |
| 133 | 145 | } |
| 134 | 146 | .lnA insert end \n fn \n - |
| 135 | - .txtA insert end "[lindex $line 1] ($fA)\n" fn \n - | |
| 147 | + if {$fA==""} { | |
| 148 | + .txtA insert end "[lindex $line 1]\n" fn \n - | |
| 149 | + } else { | |
| 150 | + .txtA insert end "[lindex $line 1] ($fA)\n" fn \n - | |
| 151 | + } | |
| 136 | 152 | .mkr insert end \n fn \n - |
| 137 | 153 | .lnB insert end \n fn \n - |
| 138 | - .txtB insert end "[lindex $line 2] ($fB)\n" fn \n - | |
| 154 | + if {$fB==""} { | |
| 155 | + .txtB insert end "[lindex $line 2]\n" fn \n - | |
| 156 | + } else { | |
| 157 | + .txtB insert end "[lindex $line 2] ($fB)\n" fn \n - | |
| 158 | + } | |
| 139 | 159 | .wfiles.lb insert end [lindex $line 2] |
| 140 | 160 | set n1 0 |
| 141 | 161 | set n2 0 |
| 142 | 162 | } |
| 143 | 163 | SKIP { |
| 144 | 164 |
| --- src/diff.tcl | |
| +++ src/diff.tcl | |
| @@ -110,34 +110,54 @@ | |
| 110 | |
| 111 | set fromIndex [lsearch -glob $fossilcmd *-from] |
| 112 | set toIndex [lsearch -glob $fossilcmd *-to] |
| 113 | set branchIndex [lsearch -glob $fossilcmd *-branch] |
| 114 | set checkinIndex [lsearch -glob $fossilcmd *-checkin] |
| 115 | if {[string match *?--external-baseline* $fossilcmd]} { |
| 116 | set fA {external baseline} |
| 117 | } else { |
| 118 | set fA {base check-in} |
| 119 | } |
| 120 | set fB {current check-out} |
| 121 | if {$fromIndex > -1} {set fA [lindex $fossilcmd $fromIndex+1]} |
| 122 | if {$toIndex > -1} {set fB [lindex $fossilcmd $toIndex+1]} |
| 123 | if {$branchIndex > -1} {set fA "branch point"; set fB "leaf of branch '[lindex $fossilcmd $branchIndex+1]'"} |
| 124 | if {$checkinIndex > -1} {set fA "primary parent"; set fB [lindex $fossilcmd $checkinIndex+1]} |
| 125 | |
| 126 | |
| 127 | while {[set line [getLine $difftxt $N ii]] != -1} { |
| 128 | switch -- [lindex $line 0] { |
| 129 | FILE { |
| 130 | incr nDiffs |
| 131 | foreach wx [list [string length $n1] [string length $n2]] { |
| 132 | if {$wx>$widths(ln)} {set widths(ln) $wx} |
| 133 | } |
| 134 | .lnA insert end \n fn \n - |
| 135 | .txtA insert end "[lindex $line 1] ($fA)\n" fn \n - |
| 136 | .mkr insert end \n fn \n - |
| 137 | .lnB insert end \n fn \n - |
| 138 | .txtB insert end "[lindex $line 2] ($fB)\n" fn \n - |
| 139 | .wfiles.lb insert end [lindex $line 2] |
| 140 | set n1 0 |
| 141 | set n2 0 |
| 142 | } |
| 143 | SKIP { |
| 144 |
| --- src/diff.tcl | |
| +++ src/diff.tcl | |
| @@ -110,34 +110,54 @@ | |
| 110 | |
| 111 | set fromIndex [lsearch -glob $fossilcmd *-from] |
| 112 | set toIndex [lsearch -glob $fossilcmd *-to] |
| 113 | set branchIndex [lsearch -glob $fossilcmd *-branch] |
| 114 | set checkinIndex [lsearch -glob $fossilcmd *-checkin] |
| 115 | if {[lsearch -glob $fossilcmd *-label]>=0} { |
| 116 | set fA {} |
| 117 | set fB {} |
| 118 | } else { |
| 119 | if {[string match *?--external-baseline* $fossilcmd]} { |
| 120 | set fA {external baseline} |
| 121 | } else { |
| 122 | set fA {base check-in} |
| 123 | } |
| 124 | set fB {current check-out} |
| 125 | if {$fromIndex > -1} { |
| 126 | set fA [lindex $fossilcmd $fromIndex+1] |
| 127 | } |
| 128 | if {$toIndex > -1} { |
| 129 | set fB [lindex $fossilcmd $toIndex+1] |
| 130 | } |
| 131 | if {$branchIndex > -1} { |
| 132 | set fA "branch point"; set fB "leaf of branch '[lindex $fossilcmd $branchIndex+1]'" |
| 133 | } |
| 134 | if {$checkinIndex > -1} { |
| 135 | set fA "primary parent"; set fB [lindex $fossilcmd $checkinIndex+1] |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | while {[set line [getLine $difftxt $N ii]] != -1} { |
| 140 | switch -- [lindex $line 0] { |
| 141 | FILE { |
| 142 | incr nDiffs |
| 143 | foreach wx [list [string length $n1] [string length $n2]] { |
| 144 | if {$wx>$widths(ln)} {set widths(ln) $wx} |
| 145 | } |
| 146 | .lnA insert end \n fn \n - |
| 147 | if {$fA==""} { |
| 148 | .txtA insert end "[lindex $line 1]\n" fn \n - |
| 149 | } else { |
| 150 | .txtA insert end "[lindex $line 1] ($fA)\n" fn \n - |
| 151 | } |
| 152 | .mkr insert end \n fn \n - |
| 153 | .lnB insert end \n fn \n - |
| 154 | if {$fB==""} { |
| 155 | .txtB insert end "[lindex $line 2]\n" fn \n - |
| 156 | } else { |
| 157 | .txtB insert end "[lindex $line 2] ($fB)\n" fn \n - |
| 158 | } |
| 159 | .wfiles.lb insert end [lindex $line 2] |
| 160 | set n1 0 |
| 161 | set n2 0 |
| 162 | } |
| 163 | SKIP { |
| 164 |
+2
| --- src/diffcmd.c | ||
| +++ src/diffcmd.c | ||
| @@ -164,10 +164,12 @@ | ||
| 164 | 164 | ){ |
| 165 | 165 | u64 diffFlags = pCfg->diffFlags; |
| 166 | 166 | /* Standardize on /dev/null, regardless of platform. */ |
| 167 | 167 | if( pCfg->diffFlags & DIFF_FILE_ADDED ) zLeft = "/dev/null"; |
| 168 | 168 | if( pCfg->diffFlags & DIFF_FILE_DELETED ) zRight = "/dev/null"; |
| 169 | + if( pCfg->azLabel[0] ) zLeft = pCfg->azLabel[0]; | |
| 170 | + if( pCfg->azLabel[1] ) zRight = pCfg->azLabel[1]; | |
| 169 | 171 | if( diffFlags & (DIFF_BRIEF|DIFF_RAW) ){ |
| 170 | 172 | /* no-op */ |
| 171 | 173 | }else if( diffFlags & DIFF_DEBUG ){ |
| 172 | 174 | blob_appendf(pOut, "FILE-LEFT %s\nFILE-RIGHT %s\n", zLeft, zRight); |
| 173 | 175 | }else if( diffFlags & DIFF_WEBPAGE ){ |
| 174 | 176 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -164,10 +164,12 @@ | |
| 164 | ){ |
| 165 | u64 diffFlags = pCfg->diffFlags; |
| 166 | /* Standardize on /dev/null, regardless of platform. */ |
| 167 | if( pCfg->diffFlags & DIFF_FILE_ADDED ) zLeft = "/dev/null"; |
| 168 | if( pCfg->diffFlags & DIFF_FILE_DELETED ) zRight = "/dev/null"; |
| 169 | if( diffFlags & (DIFF_BRIEF|DIFF_RAW) ){ |
| 170 | /* no-op */ |
| 171 | }else if( diffFlags & DIFF_DEBUG ){ |
| 172 | blob_appendf(pOut, "FILE-LEFT %s\nFILE-RIGHT %s\n", zLeft, zRight); |
| 173 | }else if( diffFlags & DIFF_WEBPAGE ){ |
| 174 |
| --- src/diffcmd.c | |
| +++ src/diffcmd.c | |
| @@ -164,10 +164,12 @@ | |
| 164 | ){ |
| 165 | u64 diffFlags = pCfg->diffFlags; |
| 166 | /* Standardize on /dev/null, regardless of platform. */ |
| 167 | if( pCfg->diffFlags & DIFF_FILE_ADDED ) zLeft = "/dev/null"; |
| 168 | if( pCfg->diffFlags & DIFF_FILE_DELETED ) zRight = "/dev/null"; |
| 169 | if( pCfg->azLabel[0] ) zLeft = pCfg->azLabel[0]; |
| 170 | if( pCfg->azLabel[1] ) zRight = pCfg->azLabel[1]; |
| 171 | if( diffFlags & (DIFF_BRIEF|DIFF_RAW) ){ |
| 172 | /* no-op */ |
| 173 | }else if( diffFlags & DIFF_DEBUG ){ |
| 174 | blob_appendf(pOut, "FILE-LEFT %s\nFILE-RIGHT %s\n", zLeft, zRight); |
| 175 | }else if( diffFlags & DIFF_WEBPAGE ){ |
| 176 |
+70
-4
| --- src/merge.c | ||
| +++ src/merge.c | ||
| @@ -44,10 +44,11 @@ | ||
| 44 | 44 | bDebug = find_option("debug",0,0)!=0; |
| 45 | 45 | verify_all_options(); |
| 46 | 46 | |
| 47 | 47 | blob_zero(&script); |
| 48 | 48 | blob_appendf(&script, "set ncontext %d\n", nContext); |
| 49 | + blob_appendf(&script, "set fossilexe {\"%/\"}\n", g.nameOfExe); | |
| 49 | 50 | blob_appendf(&script, "set fossilcmd {| \"%/\" merge-info}\n", |
| 50 | 51 | g.nameOfExe); |
| 51 | 52 | blob_appendf(&script, "set filelist [list"); |
| 52 | 53 | if( g.argc==2 ){ |
| 53 | 54 | /* No files named on the command-line. Use every file mentioned |
| @@ -241,10 +242,55 @@ | ||
| 241 | 242 | blob_reset(&v1); |
| 242 | 243 | blob_reset(&v2); |
| 243 | 244 | blob_reset(&out); |
| 244 | 245 | db_finalize(&q); |
| 245 | 246 | } |
| 247 | + | |
| 248 | +/* | |
| 249 | +** Respond to one of the options --diff12, --diff13, or --diff23. | |
| 250 | +** | |
| 251 | +** The diffMode is one of 12, 13, or 23 according to which option provoked | |
| 252 | +** this routine. zFile is the name of the file on which to run the | |
| 253 | +** two-way diff. | |
| 254 | +** | |
| 255 | +** This routine constructs a sub-command that runs "fossil diff" to show | |
| 256 | +** the appropriate two-way diff. | |
| 257 | +*/ | |
| 258 | +static void merge_two_way_file_diff( | |
| 259 | + int diffMode, | |
| 260 | + const char *zDiff2, | |
| 261 | + int nContext, | |
| 262 | + int bDark | |
| 263 | +){ | |
| 264 | + int ridLeft; /* RID for the left file */ | |
| 265 | + int ridRight; /* RID for the right file */ | |
| 266 | + char *zLeft; | |
| 267 | + char *zRight; | |
| 268 | + char *zCmd; | |
| 269 | + | |
| 270 | + ridLeft = db_int(0, | |
| 271 | + "SELECT iif(%d,ridp,ridv) FROM mergestat" | |
| 272 | + " WHERE coalesce(fnr,fn)=%Q", | |
| 273 | + diffMode<20, zDiff2 | |
| 274 | + ); | |
| 275 | + ridRight = db_int(0, | |
| 276 | + "SELECT iif(%d,ridv,ridm) FROM mergestat" | |
| 277 | + " WHERE coalesce(fnr,fn)=%Q", | |
| 278 | + (diffMode%10)==2, zDiff2 | |
| 279 | + ); | |
| 280 | + zLeft = mprintf("%s (%s)", zDiff2, diffMode<20 ? "baseline" : "local"); | |
| 281 | + zRight = mprintf("%s (%s)", zDiff2, | |
| 282 | + (diffMode%10)==2 ? "local" : "merge-in"); | |
| 283 | + zCmd = mprintf( | |
| 284 | + "%!$ fdiff --tk --label %!$ --label %!$ -c %d%s rid:%d rid:%d &", | |
| 285 | + g.nameOfExe, zLeft, zRight, nContext, | |
| 286 | + bDark ? " -dark" : "", | |
| 287 | + ridLeft, ridRight); | |
| 288 | + fossil_system(zCmd); | |
| 289 | + return; | |
| 290 | +} | |
| 291 | + | |
| 246 | 292 | |
| 247 | 293 | /* |
| 248 | 294 | ** COMMAND: merge-info |
| 249 | 295 | ** |
| 250 | 296 | ** Usage: %fossil merge-info [OPTIONS] |
| @@ -257,21 +303,26 @@ | ||
| 257 | 303 | ** lines are shown |
| 258 | 304 | ** -c|--context N Show N lines of context around each change, |
| 259 | 305 | ** with negative N meaning show all content. Only |
| 260 | 306 | ** meaningful in combination with --tcl or --tk. |
| 261 | 307 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 308 | +** --tk Bring up a Tcl/Tk GUI that shows the changes | |
| 309 | +** associated with the most recent merge. | |
| 310 | +** | |
| 311 | +** Options used internally by --tk: | |
| 312 | +** --diff12 FILE Bring up a separate --tk diff for just the baseline | |
| 313 | +** and local variants of FILE. | |
| 314 | +** --diff13 FILE Like --diff12 but for baseline versus merge-in | |
| 315 | +** --diff23 FILE Like --diff12 but for local versus merge-in | |
| 262 | 316 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| 263 | 317 | ** information needed to display the changes to |
| 264 | 318 | ** FILE caused by the most recent merge. FILE must |
| 265 | 319 | ** be a pathname relative to the root of the check-out. |
| 266 | -** --tk Bring up a Tcl/Tk GUI that shows the changes | |
| 267 | -** associated with the most recent merge. | |
| 268 | 320 | ** |
| 269 | -** Additional debugging options available only when --tk is used: | |
| 321 | +** Debugging options available only when --tk is used: | |
| 270 | 322 | ** --debug Show sub-commands run to implement --tk |
| 271 | 323 | ** --script FILE Write script used to implement --tk into FILE |
| 272 | - | |
| 273 | 324 | */ |
| 274 | 325 | void merge_info_cmd(void){ |
| 275 | 326 | const char *zCnt; |
| 276 | 327 | const char *zTcl; |
| 277 | 328 | int bTk; |
| @@ -279,17 +330,28 @@ | ||
| 279 | 330 | int bAll; |
| 280 | 331 | int nContext; |
| 281 | 332 | Stmt q; |
| 282 | 333 | const char *zWhere; |
| 283 | 334 | int cnt = 0; |
| 335 | + const char *zDiff2 = 0; | |
| 336 | + int diffMode = 0; | |
| 284 | 337 | |
| 285 | 338 | db_must_be_within_tree(); |
| 286 | 339 | zTcl = find_option("tcl", 0, 1); |
| 287 | 340 | bTk = find_option("tk", 0, 0)!=0; |
| 288 | 341 | zCnt = find_option("context", "c", 1); |
| 289 | 342 | bDark = find_option("dark", 0, 0)!=0; |
| 290 | 343 | bAll = find_option("all", "a", 0)!=0; |
| 344 | + if( (zDiff2 = find_option("diff12", 0, 1))!=0 ){ | |
| 345 | + diffMode = 12; | |
| 346 | + }else | |
| 347 | + if( (zDiff2 = find_option("diff13", 0, 1))!=0 ){ | |
| 348 | + diffMode = 13; | |
| 349 | + }else | |
| 350 | + if( (zDiff2 = find_option("diff23", 0, 1))!=0 ){ | |
| 351 | + diffMode = 23; | |
| 352 | + } | |
| 291 | 353 | if( bTk==0 ){ |
| 292 | 354 | verify_all_options(); |
| 293 | 355 | if( g.argc>2 ){ |
| 294 | 356 | usage("[OPTIONS]"); |
| 295 | 357 | } |
| @@ -313,10 +375,14 @@ | ||
| 313 | 375 | return; |
| 314 | 376 | } |
| 315 | 377 | if( zTcl ){ |
| 316 | 378 | merge_info_tcl(zTcl, nContext); |
| 317 | 379 | return; |
| 380 | + } | |
| 381 | + if( diffMode ){ | |
| 382 | + merge_two_way_file_diff(diffMode, zDiff2, nContext, bDark); | |
| 383 | + return; | |
| 318 | 384 | } |
| 319 | 385 | if( bAll ){ |
| 320 | 386 | zWhere = ""; |
| 321 | 387 | }else{ |
| 322 | 388 | zWhere = "WHERE op IN ('MERGE','CONFLICT','ERROR')"; |
| 323 | 389 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -44,10 +44,11 @@ | |
| 44 | bDebug = find_option("debug",0,0)!=0; |
| 45 | verify_all_options(); |
| 46 | |
| 47 | blob_zero(&script); |
| 48 | blob_appendf(&script, "set ncontext %d\n", nContext); |
| 49 | blob_appendf(&script, "set fossilcmd {| \"%/\" merge-info}\n", |
| 50 | g.nameOfExe); |
| 51 | blob_appendf(&script, "set filelist [list"); |
| 52 | if( g.argc==2 ){ |
| 53 | /* No files named on the command-line. Use every file mentioned |
| @@ -241,10 +242,55 @@ | |
| 241 | blob_reset(&v1); |
| 242 | blob_reset(&v2); |
| 243 | blob_reset(&out); |
| 244 | db_finalize(&q); |
| 245 | } |
| 246 | |
| 247 | /* |
| 248 | ** COMMAND: merge-info |
| 249 | ** |
| 250 | ** Usage: %fossil merge-info [OPTIONS] |
| @@ -257,21 +303,26 @@ | |
| 257 | ** lines are shown |
| 258 | ** -c|--context N Show N lines of context around each change, |
| 259 | ** with negative N meaning show all content. Only |
| 260 | ** meaningful in combination with --tcl or --tk. |
| 261 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 262 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| 263 | ** information needed to display the changes to |
| 264 | ** FILE caused by the most recent merge. FILE must |
| 265 | ** be a pathname relative to the root of the check-out. |
| 266 | ** --tk Bring up a Tcl/Tk GUI that shows the changes |
| 267 | ** associated with the most recent merge. |
| 268 | ** |
| 269 | ** Additional debugging options available only when --tk is used: |
| 270 | ** --debug Show sub-commands run to implement --tk |
| 271 | ** --script FILE Write script used to implement --tk into FILE |
| 272 | |
| 273 | */ |
| 274 | void merge_info_cmd(void){ |
| 275 | const char *zCnt; |
| 276 | const char *zTcl; |
| 277 | int bTk; |
| @@ -279,17 +330,28 @@ | |
| 279 | int bAll; |
| 280 | int nContext; |
| 281 | Stmt q; |
| 282 | const char *zWhere; |
| 283 | int cnt = 0; |
| 284 | |
| 285 | db_must_be_within_tree(); |
| 286 | zTcl = find_option("tcl", 0, 1); |
| 287 | bTk = find_option("tk", 0, 0)!=0; |
| 288 | zCnt = find_option("context", "c", 1); |
| 289 | bDark = find_option("dark", 0, 0)!=0; |
| 290 | bAll = find_option("all", "a", 0)!=0; |
| 291 | if( bTk==0 ){ |
| 292 | verify_all_options(); |
| 293 | if( g.argc>2 ){ |
| 294 | usage("[OPTIONS]"); |
| 295 | } |
| @@ -313,10 +375,14 @@ | |
| 313 | return; |
| 314 | } |
| 315 | if( zTcl ){ |
| 316 | merge_info_tcl(zTcl, nContext); |
| 317 | return; |
| 318 | } |
| 319 | if( bAll ){ |
| 320 | zWhere = ""; |
| 321 | }else{ |
| 322 | zWhere = "WHERE op IN ('MERGE','CONFLICT','ERROR')"; |
| 323 |
| --- src/merge.c | |
| +++ src/merge.c | |
| @@ -44,10 +44,11 @@ | |
| 44 | bDebug = find_option("debug",0,0)!=0; |
| 45 | verify_all_options(); |
| 46 | |
| 47 | blob_zero(&script); |
| 48 | blob_appendf(&script, "set ncontext %d\n", nContext); |
| 49 | blob_appendf(&script, "set fossilexe {\"%/\"}\n", g.nameOfExe); |
| 50 | blob_appendf(&script, "set fossilcmd {| \"%/\" merge-info}\n", |
| 51 | g.nameOfExe); |
| 52 | blob_appendf(&script, "set filelist [list"); |
| 53 | if( g.argc==2 ){ |
| 54 | /* No files named on the command-line. Use every file mentioned |
| @@ -241,10 +242,55 @@ | |
| 242 | blob_reset(&v1); |
| 243 | blob_reset(&v2); |
| 244 | blob_reset(&out); |
| 245 | db_finalize(&q); |
| 246 | } |
| 247 | |
| 248 | /* |
| 249 | ** Respond to one of the options --diff12, --diff13, or --diff23. |
| 250 | ** |
| 251 | ** The diffMode is one of 12, 13, or 23 according to which option provoked |
| 252 | ** this routine. zFile is the name of the file on which to run the |
| 253 | ** two-way diff. |
| 254 | ** |
| 255 | ** This routine constructs a sub-command that runs "fossil diff" to show |
| 256 | ** the appropriate two-way diff. |
| 257 | */ |
| 258 | static void merge_two_way_file_diff( |
| 259 | int diffMode, |
| 260 | const char *zDiff2, |
| 261 | int nContext, |
| 262 | int bDark |
| 263 | ){ |
| 264 | int ridLeft; /* RID for the left file */ |
| 265 | int ridRight; /* RID for the right file */ |
| 266 | char *zLeft; |
| 267 | char *zRight; |
| 268 | char *zCmd; |
| 269 | |
| 270 | ridLeft = db_int(0, |
| 271 | "SELECT iif(%d,ridp,ridv) FROM mergestat" |
| 272 | " WHERE coalesce(fnr,fn)=%Q", |
| 273 | diffMode<20, zDiff2 |
| 274 | ); |
| 275 | ridRight = db_int(0, |
| 276 | "SELECT iif(%d,ridv,ridm) FROM mergestat" |
| 277 | " WHERE coalesce(fnr,fn)=%Q", |
| 278 | (diffMode%10)==2, zDiff2 |
| 279 | ); |
| 280 | zLeft = mprintf("%s (%s)", zDiff2, diffMode<20 ? "baseline" : "local"); |
| 281 | zRight = mprintf("%s (%s)", zDiff2, |
| 282 | (diffMode%10)==2 ? "local" : "merge-in"); |
| 283 | zCmd = mprintf( |
| 284 | "%!$ fdiff --tk --label %!$ --label %!$ -c %d%s rid:%d rid:%d &", |
| 285 | g.nameOfExe, zLeft, zRight, nContext, |
| 286 | bDark ? " -dark" : "", |
| 287 | ridLeft, ridRight); |
| 288 | fossil_system(zCmd); |
| 289 | return; |
| 290 | } |
| 291 | |
| 292 | |
| 293 | /* |
| 294 | ** COMMAND: merge-info |
| 295 | ** |
| 296 | ** Usage: %fossil merge-info [OPTIONS] |
| @@ -257,21 +303,26 @@ | |
| 303 | ** lines are shown |
| 304 | ** -c|--context N Show N lines of context around each change, |
| 305 | ** with negative N meaning show all content. Only |
| 306 | ** meaningful in combination with --tcl or --tk. |
| 307 | ** --dark Use dark mode for the Tcl/Tk-based GUI |
| 308 | ** --tk Bring up a Tcl/Tk GUI that shows the changes |
| 309 | ** associated with the most recent merge. |
| 310 | ** |
| 311 | ** Options used internally by --tk: |
| 312 | ** --diff12 FILE Bring up a separate --tk diff for just the baseline |
| 313 | ** and local variants of FILE. |
| 314 | ** --diff13 FILE Like --diff12 but for baseline versus merge-in |
| 315 | ** --diff23 FILE Like --diff12 but for local versus merge-in |
| 316 | ** --tcl FILE Generate (to stdout) a TCL list containing |
| 317 | ** information needed to display the changes to |
| 318 | ** FILE caused by the most recent merge. FILE must |
| 319 | ** be a pathname relative to the root of the check-out. |
| 320 | ** |
| 321 | ** Debugging options available only when --tk is used: |
| 322 | ** --debug Show sub-commands run to implement --tk |
| 323 | ** --script FILE Write script used to implement --tk into FILE |
| 324 | */ |
| 325 | void merge_info_cmd(void){ |
| 326 | const char *zCnt; |
| 327 | const char *zTcl; |
| 328 | int bTk; |
| @@ -279,17 +330,28 @@ | |
| 330 | int bAll; |
| 331 | int nContext; |
| 332 | Stmt q; |
| 333 | const char *zWhere; |
| 334 | int cnt = 0; |
| 335 | const char *zDiff2 = 0; |
| 336 | int diffMode = 0; |
| 337 | |
| 338 | db_must_be_within_tree(); |
| 339 | zTcl = find_option("tcl", 0, 1); |
| 340 | bTk = find_option("tk", 0, 0)!=0; |
| 341 | zCnt = find_option("context", "c", 1); |
| 342 | bDark = find_option("dark", 0, 0)!=0; |
| 343 | bAll = find_option("all", "a", 0)!=0; |
| 344 | if( (zDiff2 = find_option("diff12", 0, 1))!=0 ){ |
| 345 | diffMode = 12; |
| 346 | }else |
| 347 | if( (zDiff2 = find_option("diff13", 0, 1))!=0 ){ |
| 348 | diffMode = 13; |
| 349 | }else |
| 350 | if( (zDiff2 = find_option("diff23", 0, 1))!=0 ){ |
| 351 | diffMode = 23; |
| 352 | } |
| 353 | if( bTk==0 ){ |
| 354 | verify_all_options(); |
| 355 | if( g.argc>2 ){ |
| 356 | usage("[OPTIONS]"); |
| 357 | } |
| @@ -313,10 +375,14 @@ | |
| 375 | return; |
| 376 | } |
| 377 | if( zTcl ){ |
| 378 | merge_info_tcl(zTcl, nContext); |
| 379 | return; |
| 380 | } |
| 381 | if( diffMode ){ |
| 382 | merge_two_way_file_diff(diffMode, zDiff2, nContext, bDark); |
| 383 | return; |
| 384 | } |
| 385 | if( bAll ){ |
| 386 | zWhere = ""; |
| 387 | }else{ |
| 388 | zWhere = "WHERE op IN ('MERGE','CONFLICT','ERROR')"; |
| 389 |
+43
-11
| --- src/merge.tcl | ||
| +++ src/merge.tcl | ||
| @@ -1,23 +1,27 @@ | ||
| 1 | 1 | # Show details of a 3-way merge operation. The left-most column is the |
| 2 | 2 | # common ancestor. The next two columns are edits of that common ancestor. |
| 3 | 3 | # The right-most column is the result of the merge. |
| 4 | 4 | # |
| 5 | -# There is always a "fossilcmd" variable which tells the script how to | |
| 6 | -# invoke Fossil to get the information it needs. This script will | |
| 7 | -# automatically append "-c N" to tell Fossil how much context it wants. | |
| 5 | +# Several variables will have been initialized: | |
| 6 | +# | |
| 7 | +# ncontext The number of lines of context to show on each change | |
| 8 | +# | |
| 9 | +# fossilexe Pathname of the fossil program | |
| 10 | +# | |
| 11 | +# filelist A list of "merge-type filename" pairs. | |
| 12 | +# | |
| 13 | +# darkmode Boolean. True for dark mode | |
| 14 | +# | |
| 15 | +# debug Boolean. True for debugging output | |
| 8 | 16 | # |
| 9 | 17 | # If the "filelist" global variable is defined, then it is a list of |
| 10 | 18 | # alternating "merge-type names" (ex: UPDATE, MERGE, CONFLICT, ERROR) and |
| 11 | 19 | # filenames. In that case, the initial display shows the changes for |
| 12 | 20 | # the first pair on the list and there is a optionmenu that allows the |
| 13 | 21 | # user to select other fiels on the list. |
| 14 | 22 | # |
| 15 | -# There should also be a global variable named "ncontext" which is the | |
| 16 | -# number of lines of context to display. The value of this variable | |
| 17 | -# controls the "-c N" argument that is appended to fossilcmd. | |
| 18 | -# | |
| 19 | 23 | # This header comment is stripped off by the "mkbuiltin.c" program. |
| 20 | 24 | # |
| 21 | 25 | package require Tk |
| 22 | 26 | |
| 23 | 27 | array set CFG_light { |
| @@ -93,19 +97,19 @@ | ||
| 93 | 97 | regexp {[a-z]+} $c type |
| 94 | 98 | return $type |
| 95 | 99 | } |
| 96 | 100 | |
| 97 | 101 | proc readMerge {args} { |
| 98 | - global fossilcmd ncontext current_file debug | |
| 102 | + global fossilexe ncontext current_file debug | |
| 99 | 103 | if {$ncontext=="All"} { |
| 100 | - set cmd "$fossilcmd -c -1" | |
| 104 | + set cmd "| $fossilexe merge-info -c -1" | |
| 101 | 105 | } else { |
| 102 | - set cmd "$fossilcmd -c $ncontext" | |
| 106 | + set cmd "| $fossilexe merge-info -c $ncontext" | |
| 103 | 107 | } |
| 104 | 108 | if {[info exists current_file]} { |
| 105 | 109 | regsub {^[A-Z]+ } $current_file {} fn |
| 106 | - append cmd " -tcl [list $fn]" | |
| 110 | + lappend cmd -tcl $fn | |
| 107 | 111 | } |
| 108 | 112 | if {$debug} { |
| 109 | 113 | regsub {^\| +} $cmd {} cmd2 |
| 110 | 114 | puts $cmd2 |
| 111 | 115 | flush stdout |
| @@ -342,10 +346,37 @@ | ||
| 342 | 346 | bind . <$key> "scroll-$axis $args; break" |
| 343 | 347 | bind . <Shift-$key> continue |
| 344 | 348 | } |
| 345 | 349 | |
| 346 | 350 | frame .bb |
| 351 | +::ttk::menubutton .bb.diff2 -text {2-way diffs} -menu .bb.diff2.m | |
| 352 | +menu .bb.diff2.m | |
| 353 | +.bb.diff2.m add command -label {baseline vs. local} -command {two-way 12} | |
| 354 | +.bb.diff2.m add command -label {baseline vs. merge-in} -command {two-way 13} | |
| 355 | +.bb.diff2.m add command -label {local vs. merge-in} -command {two-way 23} | |
| 356 | + | |
| 357 | +# Bring up a separate two-way diff between a pair of columns | |
| 358 | +# the argument is one of: | |
| 359 | +# 12 Baseline versus Local | |
| 360 | +# 13 Baseline versus Merge-in | |
| 361 | +# 23 Local versus Merge-in | |
| 362 | +# | |
| 363 | +proc two-way {mode} { | |
| 364 | + global current_file fossilexe debug darkmode ncontext | |
| 365 | + regsub {^[A-Z]+ } $current_file {} fn | |
| 366 | + set cmd $fossilexe | |
| 367 | + lappend cmd merge-info --diff$mode $fn -c $ncontext | |
| 368 | + if {$darkmode} { | |
| 369 | + lappend cmd --dark | |
| 370 | + } | |
| 371 | + if {$debug} { | |
| 372 | + puts $cmd | |
| 373 | + flush stdout | |
| 374 | + } | |
| 375 | + exec {*}$cmd & | |
| 376 | +} | |
| 377 | + | |
| 347 | 378 | set useOptionMenu 1 |
| 348 | 379 | if {[info exists filelist]} { |
| 349 | 380 | set current_file "[lindex $filelist 0] [lindex $filelist 1]" |
| 350 | 381 | if {[llength $filelist]>2} { |
| 351 | 382 | trace add variable current_file write readMerge |
| @@ -580,10 +611,11 @@ | ||
| 580 | 611 | set ::search $w |
| 581 | 612 | } |
| 582 | 613 | ::ttk::button .bb.quit -text {Quit} -command exit |
| 583 | 614 | ::ttk::button .bb.search -text {Search} -command searchOnOff |
| 584 | 615 | pack .bb.quit -side left |
| 616 | +pack .bb.diff2 -side left | |
| 585 | 617 | if {[winfo exists .bb.files]} { |
| 586 | 618 | pack .bb.files -side left |
| 587 | 619 | } |
| 588 | 620 | pack .bb.ctxtag .bb.ctx -side left |
| 589 | 621 | pack .bb.search -side left |
| 590 | 622 |
| --- src/merge.tcl | |
| +++ src/merge.tcl | |
| @@ -1,23 +1,27 @@ | |
| 1 | # Show details of a 3-way merge operation. The left-most column is the |
| 2 | # common ancestor. The next two columns are edits of that common ancestor. |
| 3 | # The right-most column is the result of the merge. |
| 4 | # |
| 5 | # There is always a "fossilcmd" variable which tells the script how to |
| 6 | # invoke Fossil to get the information it needs. This script will |
| 7 | # automatically append "-c N" to tell Fossil how much context it wants. |
| 8 | # |
| 9 | # If the "filelist" global variable is defined, then it is a list of |
| 10 | # alternating "merge-type names" (ex: UPDATE, MERGE, CONFLICT, ERROR) and |
| 11 | # filenames. In that case, the initial display shows the changes for |
| 12 | # the first pair on the list and there is a optionmenu that allows the |
| 13 | # user to select other fiels on the list. |
| 14 | # |
| 15 | # There should also be a global variable named "ncontext" which is the |
| 16 | # number of lines of context to display. The value of this variable |
| 17 | # controls the "-c N" argument that is appended to fossilcmd. |
| 18 | # |
| 19 | # This header comment is stripped off by the "mkbuiltin.c" program. |
| 20 | # |
| 21 | package require Tk |
| 22 | |
| 23 | array set CFG_light { |
| @@ -93,19 +97,19 @@ | |
| 93 | regexp {[a-z]+} $c type |
| 94 | return $type |
| 95 | } |
| 96 | |
| 97 | proc readMerge {args} { |
| 98 | global fossilcmd ncontext current_file debug |
| 99 | if {$ncontext=="All"} { |
| 100 | set cmd "$fossilcmd -c -1" |
| 101 | } else { |
| 102 | set cmd "$fossilcmd -c $ncontext" |
| 103 | } |
| 104 | if {[info exists current_file]} { |
| 105 | regsub {^[A-Z]+ } $current_file {} fn |
| 106 | append cmd " -tcl [list $fn]" |
| 107 | } |
| 108 | if {$debug} { |
| 109 | regsub {^\| +} $cmd {} cmd2 |
| 110 | puts $cmd2 |
| 111 | flush stdout |
| @@ -342,10 +346,37 @@ | |
| 342 | bind . <$key> "scroll-$axis $args; break" |
| 343 | bind . <Shift-$key> continue |
| 344 | } |
| 345 | |
| 346 | frame .bb |
| 347 | set useOptionMenu 1 |
| 348 | if {[info exists filelist]} { |
| 349 | set current_file "[lindex $filelist 0] [lindex $filelist 1]" |
| 350 | if {[llength $filelist]>2} { |
| 351 | trace add variable current_file write readMerge |
| @@ -580,10 +611,11 @@ | |
| 580 | set ::search $w |
| 581 | } |
| 582 | ::ttk::button .bb.quit -text {Quit} -command exit |
| 583 | ::ttk::button .bb.search -text {Search} -command searchOnOff |
| 584 | pack .bb.quit -side left |
| 585 | if {[winfo exists .bb.files]} { |
| 586 | pack .bb.files -side left |
| 587 | } |
| 588 | pack .bb.ctxtag .bb.ctx -side left |
| 589 | pack .bb.search -side left |
| 590 |
| --- src/merge.tcl | |
| +++ src/merge.tcl | |
| @@ -1,23 +1,27 @@ | |
| 1 | # Show details of a 3-way merge operation. The left-most column is the |
| 2 | # common ancestor. The next two columns are edits of that common ancestor. |
| 3 | # The right-most column is the result of the merge. |
| 4 | # |
| 5 | # Several variables will have been initialized: |
| 6 | # |
| 7 | # ncontext The number of lines of context to show on each change |
| 8 | # |
| 9 | # fossilexe Pathname of the fossil program |
| 10 | # |
| 11 | # filelist A list of "merge-type filename" pairs. |
| 12 | # |
| 13 | # darkmode Boolean. True for dark mode |
| 14 | # |
| 15 | # debug Boolean. True for debugging output |
| 16 | # |
| 17 | # If the "filelist" global variable is defined, then it is a list of |
| 18 | # alternating "merge-type names" (ex: UPDATE, MERGE, CONFLICT, ERROR) and |
| 19 | # filenames. In that case, the initial display shows the changes for |
| 20 | # the first pair on the list and there is a optionmenu that allows the |
| 21 | # user to select other fiels on the list. |
| 22 | # |
| 23 | # This header comment is stripped off by the "mkbuiltin.c" program. |
| 24 | # |
| 25 | package require Tk |
| 26 | |
| 27 | array set CFG_light { |
| @@ -93,19 +97,19 @@ | |
| 97 | regexp {[a-z]+} $c type |
| 98 | return $type |
| 99 | } |
| 100 | |
| 101 | proc readMerge {args} { |
| 102 | global fossilexe ncontext current_file debug |
| 103 | if {$ncontext=="All"} { |
| 104 | set cmd "| $fossilexe merge-info -c -1" |
| 105 | } else { |
| 106 | set cmd "| $fossilexe merge-info -c $ncontext" |
| 107 | } |
| 108 | if {[info exists current_file]} { |
| 109 | regsub {^[A-Z]+ } $current_file {} fn |
| 110 | lappend cmd -tcl $fn |
| 111 | } |
| 112 | if {$debug} { |
| 113 | regsub {^\| +} $cmd {} cmd2 |
| 114 | puts $cmd2 |
| 115 | flush stdout |
| @@ -342,10 +346,37 @@ | |
| 346 | bind . <$key> "scroll-$axis $args; break" |
| 347 | bind . <Shift-$key> continue |
| 348 | } |
| 349 | |
| 350 | frame .bb |
| 351 | ::ttk::menubutton .bb.diff2 -text {2-way diffs} -menu .bb.diff2.m |
| 352 | menu .bb.diff2.m |
| 353 | .bb.diff2.m add command -label {baseline vs. local} -command {two-way 12} |
| 354 | .bb.diff2.m add command -label {baseline vs. merge-in} -command {two-way 13} |
| 355 | .bb.diff2.m add command -label {local vs. merge-in} -command {two-way 23} |
| 356 | |
| 357 | # Bring up a separate two-way diff between a pair of columns |
| 358 | # the argument is one of: |
| 359 | # 12 Baseline versus Local |
| 360 | # 13 Baseline versus Merge-in |
| 361 | # 23 Local versus Merge-in |
| 362 | # |
| 363 | proc two-way {mode} { |
| 364 | global current_file fossilexe debug darkmode ncontext |
| 365 | regsub {^[A-Z]+ } $current_file {} fn |
| 366 | set cmd $fossilexe |
| 367 | lappend cmd merge-info --diff$mode $fn -c $ncontext |
| 368 | if {$darkmode} { |
| 369 | lappend cmd --dark |
| 370 | } |
| 371 | if {$debug} { |
| 372 | puts $cmd |
| 373 | flush stdout |
| 374 | } |
| 375 | exec {*}$cmd & |
| 376 | } |
| 377 | |
| 378 | set useOptionMenu 1 |
| 379 | if {[info exists filelist]} { |
| 380 | set current_file "[lindex $filelist 0] [lindex $filelist 1]" |
| 381 | if {[llength $filelist]>2} { |
| 382 | trace add variable current_file write readMerge |
| @@ -580,10 +611,11 @@ | |
| 611 | set ::search $w |
| 612 | } |
| 613 | ::ttk::button .bb.quit -text {Quit} -command exit |
| 614 | ::ttk::button .bb.search -text {Search} -command searchOnOff |
| 615 | pack .bb.quit -side left |
| 616 | pack .bb.diff2 -side left |
| 617 | if {[winfo exists .bb.files]} { |
| 618 | pack .bb.files -side left |
| 619 | } |
| 620 | pack .bb.ctxtag .bb.ctx -side left |
| 621 | pack .bb.search -side left |
| 622 |