Fossil SCM

If the gdiff-command setting is undefined and if "tclsh" and "wish" are on PATH, then the various "gdiff" commands always try to use --tk as the graphical diff, rather than searching for an external diff program.

drh 2025-03-17 16:31 trunk
Commit 5bec7a698eb110ef490671d652c1953e0f07b7c77e0d84a3df5e759b78afde75
+35 -3
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -1191,10 +1191,31 @@
11911191
}
11921192
}
11931193
}
11941194
return zResult;
11951195
}
1196
+
1197
+/*
1198
+** Return true if it reasonable to run "diff -tk" for "gdiff".
1199
+**
1200
+** Details: Return true if all of the following are true:
1201
+**
1202
+** (1) The isGDiff flags is true
1203
+** (2) The "gdiff-command" setting is undefined
1204
+** (3) There is a "tclsh" on PATH
1205
+** (4) There is a "wish" on PATH
1206
+*/
1207
+int gdiff_using_tk(int isGdiff){
1208
+ if( isGdiff
1209
+ && db_get("gdiff-command","")[0]==0
1210
+ && fossil_app_on_path("tclsh",0)
1211
+ && fossil_app_on_path("wish",0)
1212
+ ){
1213
+ return 1;
1214
+ }
1215
+ return 0;
1216
+}
11961217
11971218
/*
11981219
** Show diff output in a Tcl/Tk window, in response to the --tk option
11991220
** to the diff command.
12001221
**
@@ -1292,11 +1313,12 @@
12921313
** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
12931314
**
12941315
** Show the difference between the current version of each of the FILEs
12951316
** specified (as they exist on disk) and that same file as it was checked-
12961317
** out. Or if the FILE arguments are omitted, show all unsaved changes
1297
-** currently in the working check-out.
1318
+** currently in the working check-out. The "gdiff" variant means to
1319
+** to use a GUI diff.
12981320
**
12991321
** The default output format is a "unified patch" (the same as the
13001322
** output of "diff -u" on most unix systems). Many alternative formats
13011323
** are available. A few of the more useful alternatives:
13021324
**
@@ -1386,15 +1408,15 @@
13861408
int againstUndo = 0; /* Diff against files in the undo buffer */
13871409
FileDirList *pFileDir = 0; /* Restrict the diff to these files */
13881410
DiffConfig DCfg; /* Diff configuration object */
13891411
int bFromIsDir = 0; /* True if zFrom is a directory name */
13901412
1391
- if( find_option("tk",0,0)!=0 || has_option("tclsh") ){
1413
+ isGDiff = g.argv[1][0]=='g';
1414
+ if( find_option("tk",0,0)!=0|| has_option("tclsh") ){
13921415
diff_tk("diff", 2);
13931416
return;
13941417
}
1395
- isGDiff = g.argv[1][0]=='g';
13961418
zFrom = find_option("from", "r", 1);
13971419
zTo = find_option("to", 0, 1);
13981420
zCheckin = find_option("checkin", "ci", 1);
13991421
zBranch = find_option("branch", 0, 1);
14001422
againstUndo = find_option("undo",0,0)!=0;
@@ -1406,10 +1428,11 @@
14061428
if( zTo || zFrom || zCheckin ){
14071429
fossil_fatal("cannot use --from, --to, or --checkin with --branch");
14081430
}
14091431
zTo = zBranch;
14101432
zFrom = mprintf("root:%s", zBranch);
1433
+ zBranch = 0;
14111434
}
14121435
if( zCheckin!=0 && (zFrom!=0 || zTo!=0) ){
14131436
fossil_fatal("cannot use --checkin together with --from or --to");
14141437
}
14151438
if( 0==zCheckin ){
@@ -1420,10 +1443,19 @@
14201443
}else{
14211444
db_find_and_open_repository(0, 0);
14221445
}
14231446
}else{
14241447
db_find_and_open_repository(0, 0);
1448
+ }
1449
+ if( gdiff_using_tk(isGDiff) ){
1450
+ restore_option("--from", zFrom, 1);
1451
+ restore_option("--to", zTo, 1);
1452
+ restore_option("--checkin", zCheckin, 1);
1453
+ restore_option("--branch", zBranch, 1);
1454
+ if( againstUndo ) restore_option("--undo", 0, 0);
1455
+ diff_tk("diff", 2);
1456
+ return;
14251457
}
14261458
determine_exec_relative_option(1);
14271459
if( zFrom!=file_tail(zFrom)
14281460
&& file_isdir(zFrom, ExtFILE)==1
14291461
&& !db_exists("SELECT 1 FROM tag WHERE tagname='sym-%q'", zFrom)
14301462
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -1191,10 +1191,31 @@
1191 }
1192 }
1193 }
1194 return zResult;
1195 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1196
1197 /*
1198 ** Show diff output in a Tcl/Tk window, in response to the --tk option
1199 ** to the diff command.
1200 **
@@ -1292,11 +1313,12 @@
1292 ** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
1293 **
1294 ** Show the difference between the current version of each of the FILEs
1295 ** specified (as they exist on disk) and that same file as it was checked-
1296 ** out. Or if the FILE arguments are omitted, show all unsaved changes
1297 ** currently in the working check-out.
 
1298 **
1299 ** The default output format is a "unified patch" (the same as the
1300 ** output of "diff -u" on most unix systems). Many alternative formats
1301 ** are available. A few of the more useful alternatives:
1302 **
@@ -1386,15 +1408,15 @@
1386 int againstUndo = 0; /* Diff against files in the undo buffer */
1387 FileDirList *pFileDir = 0; /* Restrict the diff to these files */
1388 DiffConfig DCfg; /* Diff configuration object */
1389 int bFromIsDir = 0; /* True if zFrom is a directory name */
1390
1391 if( find_option("tk",0,0)!=0 || has_option("tclsh") ){
 
1392 diff_tk("diff", 2);
1393 return;
1394 }
1395 isGDiff = g.argv[1][0]=='g';
1396 zFrom = find_option("from", "r", 1);
1397 zTo = find_option("to", 0, 1);
1398 zCheckin = find_option("checkin", "ci", 1);
1399 zBranch = find_option("branch", 0, 1);
1400 againstUndo = find_option("undo",0,0)!=0;
@@ -1406,10 +1428,11 @@
1406 if( zTo || zFrom || zCheckin ){
1407 fossil_fatal("cannot use --from, --to, or --checkin with --branch");
1408 }
1409 zTo = zBranch;
1410 zFrom = mprintf("root:%s", zBranch);
 
1411 }
1412 if( zCheckin!=0 && (zFrom!=0 || zTo!=0) ){
1413 fossil_fatal("cannot use --checkin together with --from or --to");
1414 }
1415 if( 0==zCheckin ){
@@ -1420,10 +1443,19 @@
1420 }else{
1421 db_find_and_open_repository(0, 0);
1422 }
1423 }else{
1424 db_find_and_open_repository(0, 0);
 
 
 
 
 
 
 
 
 
1425 }
1426 determine_exec_relative_option(1);
1427 if( zFrom!=file_tail(zFrom)
1428 && file_isdir(zFrom, ExtFILE)==1
1429 && !db_exists("SELECT 1 FROM tag WHERE tagname='sym-%q'", zFrom)
1430
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -1191,10 +1191,31 @@
1191 }
1192 }
1193 }
1194 return zResult;
1195 }
1196
1197 /*
1198 ** Return true if it reasonable to run "diff -tk" for "gdiff".
1199 **
1200 ** Details: Return true if all of the following are true:
1201 **
1202 ** (1) The isGDiff flags is true
1203 ** (2) The "gdiff-command" setting is undefined
1204 ** (3) There is a "tclsh" on PATH
1205 ** (4) There is a "wish" on PATH
1206 */
1207 int gdiff_using_tk(int isGdiff){
1208 if( isGdiff
1209 && db_get("gdiff-command","")[0]==0
1210 && fossil_app_on_path("tclsh",0)
1211 && fossil_app_on_path("wish",0)
1212 ){
1213 return 1;
1214 }
1215 return 0;
1216 }
1217
1218 /*
1219 ** Show diff output in a Tcl/Tk window, in response to the --tk option
1220 ** to the diff command.
1221 **
@@ -1292,11 +1313,12 @@
1313 ** Usage: %fossil diff|gdiff ?OPTIONS? ?FILE1? ?FILE2 ...?
1314 **
1315 ** Show the difference between the current version of each of the FILEs
1316 ** specified (as they exist on disk) and that same file as it was checked-
1317 ** out. Or if the FILE arguments are omitted, show all unsaved changes
1318 ** currently in the working check-out. The "gdiff" variant means to
1319 ** to use a GUI diff.
1320 **
1321 ** The default output format is a "unified patch" (the same as the
1322 ** output of "diff -u" on most unix systems). Many alternative formats
1323 ** are available. A few of the more useful alternatives:
1324 **
@@ -1386,15 +1408,15 @@
1408 int againstUndo = 0; /* Diff against files in the undo buffer */
1409 FileDirList *pFileDir = 0; /* Restrict the diff to these files */
1410 DiffConfig DCfg; /* Diff configuration object */
1411 int bFromIsDir = 0; /* True if zFrom is a directory name */
1412
1413 isGDiff = g.argv[1][0]=='g';
1414 if( find_option("tk",0,0)!=0|| has_option("tclsh") ){
1415 diff_tk("diff", 2);
1416 return;
1417 }
 
1418 zFrom = find_option("from", "r", 1);
1419 zTo = find_option("to", 0, 1);
1420 zCheckin = find_option("checkin", "ci", 1);
1421 zBranch = find_option("branch", 0, 1);
1422 againstUndo = find_option("undo",0,0)!=0;
@@ -1406,10 +1428,11 @@
1428 if( zTo || zFrom || zCheckin ){
1429 fossil_fatal("cannot use --from, --to, or --checkin with --branch");
1430 }
1431 zTo = zBranch;
1432 zFrom = mprintf("root:%s", zBranch);
1433 zBranch = 0;
1434 }
1435 if( zCheckin!=0 && (zFrom!=0 || zTo!=0) ){
1436 fossil_fatal("cannot use --checkin together with --from or --to");
1437 }
1438 if( 0==zCheckin ){
@@ -1420,10 +1443,19 @@
1443 }else{
1444 db_find_and_open_repository(0, 0);
1445 }
1446 }else{
1447 db_find_and_open_repository(0, 0);
1448 }
1449 if( gdiff_using_tk(isGDiff) ){
1450 restore_option("--from", zFrom, 1);
1451 restore_option("--to", zTo, 1);
1452 restore_option("--checkin", zCheckin, 1);
1453 restore_option("--branch", zBranch, 1);
1454 if( againstUndo ) restore_option("--undo", 0, 0);
1455 diff_tk("diff", 2);
1456 return;
1457 }
1458 determine_exec_relative_option(1);
1459 if( zFrom!=file_tail(zFrom)
1460 && file_isdir(zFrom, ExtFILE)==1
1461 && !db_exists("SELECT 1 FROM tag WHERE tagname='sym-%q'", zFrom)
1462
+11 -5
--- src/main.c
+++ src/main.c
@@ -998,15 +998,12 @@
998998
999999
/*
10001000
** Remove n elements from g.argv beginning with the i-th element.
10011001
*/
10021002
static void remove_from_argv(int i, int n){
1003
- int j;
1004
- for(j=i+n; j<g.argc; i++, j++){
1005
- g.argv[i] = g.argv[j];
1006
- }
1007
- g.argc = i;
1003
+ memmove(&g.argv[i], &g.argv[i+n], sizeof(g.argv[i])*(g.argc-i-n));
1004
+ g.argc -= n;
10081005
}
10091006
10101007
10111008
/*
10121009
** Look for a command-line option. If present, remove it from the
@@ -1065,10 +1062,19 @@
10651062
break;
10661063
}
10671064
}
10681065
return zReturn;
10691066
}
1067
+
1068
+/*
1069
+** Restore an option previously removed by find_option().
1070
+*/
1071
+void restore_option(const char *zName, const char *zValue, int hasOpt){
1072
+ if( zValue==0 && hasOpt ) return;
1073
+ g.argv[g.argc++] = (char*)zName;
1074
+ if( hasOpt ) g.argv[g.argc++] = (char*)zValue;
1075
+}
10701076
10711077
/* Return true if zOption exists in the command-line arguments,
10721078
** but do not remove it from the list or otherwise process it.
10731079
*/
10741080
int has_option(const char *zOption){
10751081
--- src/main.c
+++ src/main.c
@@ -998,15 +998,12 @@
998
999 /*
1000 ** Remove n elements from g.argv beginning with the i-th element.
1001 */
1002 static void remove_from_argv(int i, int n){
1003 int j;
1004 for(j=i+n; j<g.argc; i++, j++){
1005 g.argv[i] = g.argv[j];
1006 }
1007 g.argc = i;
1008 }
1009
1010
1011 /*
1012 ** Look for a command-line option. If present, remove it from the
@@ -1065,10 +1062,19 @@
1065 break;
1066 }
1067 }
1068 return zReturn;
1069 }
 
 
 
 
 
 
 
 
 
1070
1071 /* Return true if zOption exists in the command-line arguments,
1072 ** but do not remove it from the list or otherwise process it.
1073 */
1074 int has_option(const char *zOption){
1075
--- src/main.c
+++ src/main.c
@@ -998,15 +998,12 @@
998
999 /*
1000 ** Remove n elements from g.argv beginning with the i-th element.
1001 */
1002 static void remove_from_argv(int i, int n){
1003 memmove(&g.argv[i], &g.argv[i+n], sizeof(g.argv[i])*(g.argc-i-n));
1004 g.argc -= n;
 
 
 
1005 }
1006
1007
1008 /*
1009 ** Look for a command-line option. If present, remove it from the
@@ -1065,10 +1062,19 @@
1062 break;
1063 }
1064 }
1065 return zReturn;
1066 }
1067
1068 /*
1069 ** Restore an option previously removed by find_option().
1070 */
1071 void restore_option(const char *zName, const char *zValue, int hasOpt){
1072 if( zValue==0 && hasOpt ) return;
1073 g.argv[g.argc++] = (char*)zName;
1074 if( hasOpt ) g.argv[g.argc++] = (char*)zValue;
1075 }
1076
1077 /* Return true if zOption exists in the command-line arguments,
1078 ** but do not remove it from the list or otherwise process it.
1079 */
1080 int has_option(const char *zOption){
1081
--- src/patch.c
+++ src/patch.c
@@ -1122,10 +1122,14 @@
11221122
db_close(0);
11231123
diff_tk("patch diff", 3);
11241124
return;
11251125
}
11261126
db_find_and_open_repository(0, 0);
1127
+ if( gdiff_using_tk(zCmd[0]=='g') ){
1128
+ diff_tk("patch diff", 3);
1129
+ return;
1130
+ }
11271131
if( find_option("force","f",0) ) flags |= PATCH_FORCE;
11281132
diff_options(&DCfg, zCmd[0]=='g', 0);
11291133
verify_all_options();
11301134
zIn = patch_find_patch_filename("apply");
11311135
patch_attach(zIn, stdin, 0);
11321136
--- src/patch.c
+++ src/patch.c
@@ -1122,10 +1122,14 @@
1122 db_close(0);
1123 diff_tk("patch diff", 3);
1124 return;
1125 }
1126 db_find_and_open_repository(0, 0);
 
 
 
 
1127 if( find_option("force","f",0) ) flags |= PATCH_FORCE;
1128 diff_options(&DCfg, zCmd[0]=='g', 0);
1129 verify_all_options();
1130 zIn = patch_find_patch_filename("apply");
1131 patch_attach(zIn, stdin, 0);
1132
--- src/patch.c
+++ src/patch.c
@@ -1122,10 +1122,14 @@
1122 db_close(0);
1123 diff_tk("patch diff", 3);
1124 return;
1125 }
1126 db_find_and_open_repository(0, 0);
1127 if( gdiff_using_tk(zCmd[0]=='g') ){
1128 diff_tk("patch diff", 3);
1129 return;
1130 }
1131 if( find_option("force","f",0) ) flags |= PATCH_FORCE;
1132 diff_options(&DCfg, zCmd[0]=='g', 0);
1133 verify_all_options();
1134 zIn = patch_find_patch_filename("apply");
1135 patch_attach(zIn, stdin, 0);
1136
+1 -1
--- src/stash.c
+++ src/stash.c
@@ -756,11 +756,11 @@
756756
DiffConfig DCfg;
757757
758758
if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){
759759
fBaseline = 1;
760760
}
761
- if( find_option("tk",0,0)!=0 ){
761
+ if( find_option("tk",0,0)!=0 || gdiff_using_tk(zCmd[0]=='g') ){
762762
db_close(0);
763763
diff_tk(fBaseline ? "stash show" : "stash diff", 3);
764764
return;
765765
}
766766
diff_options(&DCfg, zCmd[0]=='g', 0);
767767
--- src/stash.c
+++ src/stash.c
@@ -756,11 +756,11 @@
756 DiffConfig DCfg;
757
758 if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){
759 fBaseline = 1;
760 }
761 if( find_option("tk",0,0)!=0 ){
762 db_close(0);
763 diff_tk(fBaseline ? "stash show" : "stash diff", 3);
764 return;
765 }
766 diff_options(&DCfg, zCmd[0]=='g', 0);
767
--- src/stash.c
+++ src/stash.c
@@ -756,11 +756,11 @@
756 DiffConfig DCfg;
757
758 if( strstr(zCmd,"show")!=0 || strstr(zCmd,"cat")!=0 ){
759 fBaseline = 1;
760 }
761 if( find_option("tk",0,0)!=0 || gdiff_using_tk(zCmd[0]=='g') ){
762 db_close(0);
763 diff_tk(fBaseline ? "stash show" : "stash diff", 3);
764 return;
765 }
766 diff_options(&DCfg, zCmd[0]=='g', 0);
767

Keyboard Shortcuts

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