Fossil SCM

merge trunk

jan.nijtmans 2012-10-22 14:56 use-utf8-in-win-external-editor merge
Commit c7703868b39b825e08944bb77fadee014941755e
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-1.23
1
+1.24
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.23
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 1.24
2
+20 -3
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
8787
}else if( isChnged==2 ){
8888
blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
8989
}else if( isChnged==3 ){
9090
blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
9191
}else if( isChnged==1 ){
92
- blob_appendf(report, "EDITED %s\n", zDisplayName);
92
+ if( file_contains_merge_marker(zFullName) ){
93
+ blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94
+ }else{
95
+ blob_appendf(report, "EDITED %s\n", zDisplayName);
96
+ }
9397
}else if( isRenamed ){
9498
blob_appendf(report, "RENAMED %s\n", zDisplayName);
9599
}
96100
free(zFullName);
97101
}
@@ -986,10 +990,11 @@
986990
** --force|-f allow forking with this commit
987991
** --message-file|-M FILE read the commit comment from given file
988992
** --nosign do not attempt to sign this commit with gpg
989993
** --private do not sync changes and their descendants
990994
** --tag TAG-NAME assign given tag TAG-NAME to the checkin
995
+** --conflict allow unresolved merge conflicts
991996
**
992997
** See also: branch, changes, checkout, extra, sync
993998
*/
994999
void commit_cmd(void){
9951000
int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
10031008
int noSign = 0; /* True to omit signing the manifest using GPG */
10041009
int isAMerge = 0; /* True if checking in a merge */
10051010
int forceFlag = 0; /* Force a fork */
10061011
int forceDelta = 0; /* Force a delta-manifest */
10071012
int forceBaseline = 0; /* Force a baseline-manifest */
1013
+ int allowConflict = 0; /* Allow unresolve merge conflicts */
10081014
char *zManifestFile; /* Name of the manifest file */
10091015
int useCksum; /* True if checksums should be computed and verified */
10101016
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
10111017
int testRun; /* True for a test run. Debugging only */
10121018
const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
10221028
Blob muuid; /* Manifest uuid */
10231029
Blob cksum1, cksum2; /* Before and after commit checksums */
10241030
Blob cksum1b; /* Checksum recorded in the manifest */
10251031
int szD; /* Size of the delta manifest */
10261032
int szB; /* Size of the baseline manifest */
1033
+ int nConflict = 0; /* Number of unresolved merge conflicts */
10271034
10281035
url_proxy_options();
10291036
noSign = find_option("nosign",0,0)!=0;
10301037
forceDelta = find_option("delta",0,0)!=0;
10311038
forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
10501057
if( zBranch==0 ) zBranch = "private";
10511058
if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
10521059
}
10531060
zDateOvrd = find_option("date-override",0,1);
10541061
zUserOvrd = find_option("user-override",0,1);
1062
+ allowConflict = find_option("conflict",0,0)!=0;
10551063
db_must_be_within_tree();
10561064
noSign = db_get_boolean("omitsign", 0)|noSign;
10571065
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
10581066
useCksum = db_get_boolean("repo-cksum", 1);
10591067
outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
12551263
/* Step 1: Insert records for all modified files into the blob
12561264
** table. If there were arguments passed to this command, only
12571265
** the identified fils are inserted (if they have been modified).
12581266
*/
12591267
db_prepare(&q,
1260
- "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1268
+ "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
12611269
"WHERE chnged==1 AND NOT deleted AND is_selected(id)",
12621270
g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
12631271
);
12641272
while( db_step(&q)==SQLITE_ROW ){
12651273
int id, rid;
12661274
const char *zFullname;
12671275
Blob content;
1268
- int crnlOk;
1276
+ int crnlOk, chnged;
12691277
12701278
id = db_column_int(&q, 0);
12711279
zFullname = db_column_text(&q, 1);
12721280
rid = db_column_int(&q, 2);
12731281
crnlOk = db_column_int(&q, 3);
1282
+ chnged = db_column_int(&q, 4);
12741283
12751284
blob_zero(&content);
12761285
if( file_wd_islink(zFullname) ){
12771286
/* Instead of file content, put link destination path */
12781287
blob_read_link(&content, zFullname);
12791288
}else{
12801289
blob_read_from_file(&content, zFullname);
12811290
}
12821291
if( !crnlOk ) cr_warning(&content, zFullname);
1292
+ if( chnged==1 && contains_merge_marker(&content) ){
1293
+ nConflict++;
1294
+ fossil_print("possible unresolved merge conflict in %s\n",
1295
+ zFullname+strlen(g.zLocalRoot));
1296
+ }
12831297
nrid = content_put(&content);
12841298
blob_reset(&content);
12851299
if( rid>0 ){
12861300
content_deltify(rid, nrid, 0);
12871301
}
12881302
db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
12891303
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
12901304
}
12911305
db_finalize(&q);
1306
+ if( nConflict && !allowConflict ){
1307
+ fossil_fatal("abort due to unresolve merge conflicts");
1308
+ }
12921309
12931310
/* Create the new manifest */
12941311
if( blob_size(&comment)==0 ){
12951312
blob_append(&comment, "(no comment)", -1);
12961313
}
12971314
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 blob_appendf(report, "EDITED %s\n", zDisplayName);
 
 
 
 
93 }else if( isRenamed ){
94 blob_appendf(report, "RENAMED %s\n", zDisplayName);
95 }
96 free(zFullName);
97 }
@@ -986,10 +990,11 @@
986 ** --force|-f allow forking with this commit
987 ** --message-file|-M FILE read the commit comment from given file
988 ** --nosign do not attempt to sign this commit with gpg
989 ** --private do not sync changes and their descendants
990 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
 
991 **
992 ** See also: branch, changes, checkout, extra, sync
993 */
994 void commit_cmd(void){
995 int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
1003 int noSign = 0; /* True to omit signing the manifest using GPG */
1004 int isAMerge = 0; /* True if checking in a merge */
1005 int forceFlag = 0; /* Force a fork */
1006 int forceDelta = 0; /* Force a delta-manifest */
1007 int forceBaseline = 0; /* Force a baseline-manifest */
 
1008 char *zManifestFile; /* Name of the manifest file */
1009 int useCksum; /* True if checksums should be computed and verified */
1010 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1011 int testRun; /* True for a test run. Debugging only */
1012 const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
1022 Blob muuid; /* Manifest uuid */
1023 Blob cksum1, cksum2; /* Before and after commit checksums */
1024 Blob cksum1b; /* Checksum recorded in the manifest */
1025 int szD; /* Size of the delta manifest */
1026 int szB; /* Size of the baseline manifest */
 
1027
1028 url_proxy_options();
1029 noSign = find_option("nosign",0,0)!=0;
1030 forceDelta = find_option("delta",0,0)!=0;
1031 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
1050 if( zBranch==0 ) zBranch = "private";
1051 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1052 }
1053 zDateOvrd = find_option("date-override",0,1);
1054 zUserOvrd = find_option("user-override",0,1);
 
1055 db_must_be_within_tree();
1056 noSign = db_get_boolean("omitsign", 0)|noSign;
1057 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1058 useCksum = db_get_boolean("repo-cksum", 1);
1059 outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
1255 /* Step 1: Insert records for all modified files into the blob
1256 ** table. If there were arguments passed to this command, only
1257 ** the identified fils are inserted (if they have been modified).
1258 */
1259 db_prepare(&q,
1260 "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1261 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1262 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1263 );
1264 while( db_step(&q)==SQLITE_ROW ){
1265 int id, rid;
1266 const char *zFullname;
1267 Blob content;
1268 int crnlOk;
1269
1270 id = db_column_int(&q, 0);
1271 zFullname = db_column_text(&q, 1);
1272 rid = db_column_int(&q, 2);
1273 crnlOk = db_column_int(&q, 3);
 
1274
1275 blob_zero(&content);
1276 if( file_wd_islink(zFullname) ){
1277 /* Instead of file content, put link destination path */
1278 blob_read_link(&content, zFullname);
1279 }else{
1280 blob_read_from_file(&content, zFullname);
1281 }
1282 if( !crnlOk ) cr_warning(&content, zFullname);
 
 
 
 
 
1283 nrid = content_put(&content);
1284 blob_reset(&content);
1285 if( rid>0 ){
1286 content_deltify(rid, nrid, 0);
1287 }
1288 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1289 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1290 }
1291 db_finalize(&q);
 
 
 
1292
1293 /* Create the new manifest */
1294 if( blob_size(&comment)==0 ){
1295 blob_append(&comment, "(no comment)", -1);
1296 }
1297
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 if( file_contains_merge_marker(zFullName) ){
93 blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94 }else{
95 blob_appendf(report, "EDITED %s\n", zDisplayName);
96 }
97 }else if( isRenamed ){
98 blob_appendf(report, "RENAMED %s\n", zDisplayName);
99 }
100 free(zFullName);
101 }
@@ -986,10 +990,11 @@
990 ** --force|-f allow forking with this commit
991 ** --message-file|-M FILE read the commit comment from given file
992 ** --nosign do not attempt to sign this commit with gpg
993 ** --private do not sync changes and their descendants
994 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
995 ** --conflict allow unresolved merge conflicts
996 **
997 ** See also: branch, changes, checkout, extra, sync
998 */
999 void commit_cmd(void){
1000 int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
1008 int noSign = 0; /* True to omit signing the manifest using GPG */
1009 int isAMerge = 0; /* True if checking in a merge */
1010 int forceFlag = 0; /* Force a fork */
1011 int forceDelta = 0; /* Force a delta-manifest */
1012 int forceBaseline = 0; /* Force a baseline-manifest */
1013 int allowConflict = 0; /* Allow unresolve merge conflicts */
1014 char *zManifestFile; /* Name of the manifest file */
1015 int useCksum; /* True if checksums should be computed and verified */
1016 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1017 int testRun; /* True for a test run. Debugging only */
1018 const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
1028 Blob muuid; /* Manifest uuid */
1029 Blob cksum1, cksum2; /* Before and after commit checksums */
1030 Blob cksum1b; /* Checksum recorded in the manifest */
1031 int szD; /* Size of the delta manifest */
1032 int szB; /* Size of the baseline manifest */
1033 int nConflict = 0; /* Number of unresolved merge conflicts */
1034
1035 url_proxy_options();
1036 noSign = find_option("nosign",0,0)!=0;
1037 forceDelta = find_option("delta",0,0)!=0;
1038 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
1057 if( zBranch==0 ) zBranch = "private";
1058 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1059 }
1060 zDateOvrd = find_option("date-override",0,1);
1061 zUserOvrd = find_option("user-override",0,1);
1062 allowConflict = find_option("conflict",0,0)!=0;
1063 db_must_be_within_tree();
1064 noSign = db_get_boolean("omitsign", 0)|noSign;
1065 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1066 useCksum = db_get_boolean("repo-cksum", 1);
1067 outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
1263 /* Step 1: Insert records for all modified files into the blob
1264 ** table. If there were arguments passed to this command, only
1265 ** the identified fils are inserted (if they have been modified).
1266 */
1267 db_prepare(&q,
1268 "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
1269 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1270 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1271 );
1272 while( db_step(&q)==SQLITE_ROW ){
1273 int id, rid;
1274 const char *zFullname;
1275 Blob content;
1276 int crnlOk, chnged;
1277
1278 id = db_column_int(&q, 0);
1279 zFullname = db_column_text(&q, 1);
1280 rid = db_column_int(&q, 2);
1281 crnlOk = db_column_int(&q, 3);
1282 chnged = db_column_int(&q, 4);
1283
1284 blob_zero(&content);
1285 if( file_wd_islink(zFullname) ){
1286 /* Instead of file content, put link destination path */
1287 blob_read_link(&content, zFullname);
1288 }else{
1289 blob_read_from_file(&content, zFullname);
1290 }
1291 if( !crnlOk ) cr_warning(&content, zFullname);
1292 if( chnged==1 && contains_merge_marker(&content) ){
1293 nConflict++;
1294 fossil_print("possible unresolved merge conflict in %s\n",
1295 zFullname+strlen(g.zLocalRoot));
1296 }
1297 nrid = content_put(&content);
1298 blob_reset(&content);
1299 if( rid>0 ){
1300 content_deltify(rid, nrid, 0);
1301 }
1302 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1303 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1304 }
1305 db_finalize(&q);
1306 if( nConflict && !allowConflict ){
1307 fossil_fatal("abort due to unresolve merge conflicts");
1308 }
1309
1310 /* Create the new manifest */
1311 if( blob_size(&comment)==0 ){
1312 blob_append(&comment, "(no comment)", -1);
1313 }
1314
+20 -3
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
8787
}else if( isChnged==2 ){
8888
blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
8989
}else if( isChnged==3 ){
9090
blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
9191
}else if( isChnged==1 ){
92
- blob_appendf(report, "EDITED %s\n", zDisplayName);
92
+ if( file_contains_merge_marker(zFullName) ){
93
+ blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94
+ }else{
95
+ blob_appendf(report, "EDITED %s\n", zDisplayName);
96
+ }
9397
}else if( isRenamed ){
9498
blob_appendf(report, "RENAMED %s\n", zDisplayName);
9599
}
96100
free(zFullName);
97101
}
@@ -986,10 +990,11 @@
986990
** --force|-f allow forking with this commit
987991
** --message-file|-M FILE read the commit comment from given file
988992
** --nosign do not attempt to sign this commit with gpg
989993
** --private do not sync changes and their descendants
990994
** --tag TAG-NAME assign given tag TAG-NAME to the checkin
995
+** --conflict allow unresolved merge conflicts
991996
**
992997
** See also: branch, changes, checkout, extra, sync
993998
*/
994999
void commit_cmd(void){
9951000
int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
10031008
int noSign = 0; /* True to omit signing the manifest using GPG */
10041009
int isAMerge = 0; /* True if checking in a merge */
10051010
int forceFlag = 0; /* Force a fork */
10061011
int forceDelta = 0; /* Force a delta-manifest */
10071012
int forceBaseline = 0; /* Force a baseline-manifest */
1013
+ int allowConflict = 0; /* Allow unresolve merge conflicts */
10081014
char *zManifestFile; /* Name of the manifest file */
10091015
int useCksum; /* True if checksums should be computed and verified */
10101016
int outputManifest; /* True to output "manifest" and "manifest.uuid" */
10111017
int testRun; /* True for a test run. Debugging only */
10121018
const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
10221028
Blob muuid; /* Manifest uuid */
10231029
Blob cksum1, cksum2; /* Before and after commit checksums */
10241030
Blob cksum1b; /* Checksum recorded in the manifest */
10251031
int szD; /* Size of the delta manifest */
10261032
int szB; /* Size of the baseline manifest */
1033
+ int nConflict = 0; /* Number of unresolved merge conflicts */
10271034
10281035
url_proxy_options();
10291036
noSign = find_option("nosign",0,0)!=0;
10301037
forceDelta = find_option("delta",0,0)!=0;
10311038
forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
10501057
if( zBranch==0 ) zBranch = "private";
10511058
if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
10521059
}
10531060
zDateOvrd = find_option("date-override",0,1);
10541061
zUserOvrd = find_option("user-override",0,1);
1062
+ allowConflict = find_option("conflict",0,0)!=0;
10551063
db_must_be_within_tree();
10561064
noSign = db_get_boolean("omitsign", 0)|noSign;
10571065
if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
10581066
useCksum = db_get_boolean("repo-cksum", 1);
10591067
outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
12551263
/* Step 1: Insert records for all modified files into the blob
12561264
** table. If there were arguments passed to this command, only
12571265
** the identified fils are inserted (if they have been modified).
12581266
*/
12591267
db_prepare(&q,
1260
- "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1268
+ "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
12611269
"WHERE chnged==1 AND NOT deleted AND is_selected(id)",
12621270
g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
12631271
);
12641272
while( db_step(&q)==SQLITE_ROW ){
12651273
int id, rid;
12661274
const char *zFullname;
12671275
Blob content;
1268
- int crnlOk;
1276
+ int crnlOk, chnged;
12691277
12701278
id = db_column_int(&q, 0);
12711279
zFullname = db_column_text(&q, 1);
12721280
rid = db_column_int(&q, 2);
12731281
crnlOk = db_column_int(&q, 3);
1282
+ chnged = db_column_int(&q, 4);
12741283
12751284
blob_zero(&content);
12761285
if( file_wd_islink(zFullname) ){
12771286
/* Instead of file content, put link destination path */
12781287
blob_read_link(&content, zFullname);
12791288
}else{
12801289
blob_read_from_file(&content, zFullname);
12811290
}
12821291
if( !crnlOk ) cr_warning(&content, zFullname);
1292
+ if( chnged==1 && contains_merge_marker(&content) ){
1293
+ nConflict++;
1294
+ fossil_print("possible unresolved merge conflict in %s\n",
1295
+ zFullname+strlen(g.zLocalRoot));
1296
+ }
12831297
nrid = content_put(&content);
12841298
blob_reset(&content);
12851299
if( rid>0 ){
12861300
content_deltify(rid, nrid, 0);
12871301
}
12881302
db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
12891303
db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
12901304
}
12911305
db_finalize(&q);
1306
+ if( nConflict && !allowConflict ){
1307
+ fossil_fatal("abort due to unresolve merge conflicts");
1308
+ }
12921309
12931310
/* Create the new manifest */
12941311
if( blob_size(&comment)==0 ){
12951312
blob_append(&comment, "(no comment)", -1);
12961313
}
12971314
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 blob_appendf(report, "EDITED %s\n", zDisplayName);
 
 
 
 
93 }else if( isRenamed ){
94 blob_appendf(report, "RENAMED %s\n", zDisplayName);
95 }
96 free(zFullName);
97 }
@@ -986,10 +990,11 @@
986 ** --force|-f allow forking with this commit
987 ** --message-file|-M FILE read the commit comment from given file
988 ** --nosign do not attempt to sign this commit with gpg
989 ** --private do not sync changes and their descendants
990 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
 
991 **
992 ** See also: branch, changes, checkout, extra, sync
993 */
994 void commit_cmd(void){
995 int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
1003 int noSign = 0; /* True to omit signing the manifest using GPG */
1004 int isAMerge = 0; /* True if checking in a merge */
1005 int forceFlag = 0; /* Force a fork */
1006 int forceDelta = 0; /* Force a delta-manifest */
1007 int forceBaseline = 0; /* Force a baseline-manifest */
 
1008 char *zManifestFile; /* Name of the manifest file */
1009 int useCksum; /* True if checksums should be computed and verified */
1010 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1011 int testRun; /* True for a test run. Debugging only */
1012 const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
1022 Blob muuid; /* Manifest uuid */
1023 Blob cksum1, cksum2; /* Before and after commit checksums */
1024 Blob cksum1b; /* Checksum recorded in the manifest */
1025 int szD; /* Size of the delta manifest */
1026 int szB; /* Size of the baseline manifest */
 
1027
1028 url_proxy_options();
1029 noSign = find_option("nosign",0,0)!=0;
1030 forceDelta = find_option("delta",0,0)!=0;
1031 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
1050 if( zBranch==0 ) zBranch = "private";
1051 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1052 }
1053 zDateOvrd = find_option("date-override",0,1);
1054 zUserOvrd = find_option("user-override",0,1);
 
1055 db_must_be_within_tree();
1056 noSign = db_get_boolean("omitsign", 0)|noSign;
1057 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1058 useCksum = db_get_boolean("repo-cksum", 1);
1059 outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
1255 /* Step 1: Insert records for all modified files into the blob
1256 ** table. If there were arguments passed to this command, only
1257 ** the identified fils are inserted (if they have been modified).
1258 */
1259 db_prepare(&q,
1260 "SELECT id, %Q || pathname, mrid, %s FROM vfile "
1261 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1262 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1263 );
1264 while( db_step(&q)==SQLITE_ROW ){
1265 int id, rid;
1266 const char *zFullname;
1267 Blob content;
1268 int crnlOk;
1269
1270 id = db_column_int(&q, 0);
1271 zFullname = db_column_text(&q, 1);
1272 rid = db_column_int(&q, 2);
1273 crnlOk = db_column_int(&q, 3);
 
1274
1275 blob_zero(&content);
1276 if( file_wd_islink(zFullname) ){
1277 /* Instead of file content, put link destination path */
1278 blob_read_link(&content, zFullname);
1279 }else{
1280 blob_read_from_file(&content, zFullname);
1281 }
1282 if( !crnlOk ) cr_warning(&content, zFullname);
 
 
 
 
 
1283 nrid = content_put(&content);
1284 blob_reset(&content);
1285 if( rid>0 ){
1286 content_deltify(rid, nrid, 0);
1287 }
1288 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1289 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1290 }
1291 db_finalize(&q);
 
 
 
1292
1293 /* Create the new manifest */
1294 if( blob_size(&comment)==0 ){
1295 blob_append(&comment, "(no comment)", -1);
1296 }
1297
--- src/checkin.c
+++ src/checkin.c
@@ -87,11 +87,15 @@
87 }else if( isChnged==2 ){
88 blob_appendf(report, "UPDATED_BY_MERGE %s\n", zDisplayName);
89 }else if( isChnged==3 ){
90 blob_appendf(report, "ADDED_BY_MERGE %s\n", zDisplayName);
91 }else if( isChnged==1 ){
92 if( file_contains_merge_marker(zFullName) ){
93 blob_appendf(report, "CONFLICT %s\n", zDisplayName);
94 }else{
95 blob_appendf(report, "EDITED %s\n", zDisplayName);
96 }
97 }else if( isRenamed ){
98 blob_appendf(report, "RENAMED %s\n", zDisplayName);
99 }
100 free(zFullName);
101 }
@@ -986,10 +990,11 @@
990 ** --force|-f allow forking with this commit
991 ** --message-file|-M FILE read the commit comment from given file
992 ** --nosign do not attempt to sign this commit with gpg
993 ** --private do not sync changes and their descendants
994 ** --tag TAG-NAME assign given tag TAG-NAME to the checkin
995 ** --conflict allow unresolved merge conflicts
996 **
997 ** See also: branch, changes, checkout, extra, sync
998 */
999 void commit_cmd(void){
1000 int hasChanges; /* True if unsaved changes exist */
@@ -1003,10 +1008,11 @@
1008 int noSign = 0; /* True to omit signing the manifest using GPG */
1009 int isAMerge = 0; /* True if checking in a merge */
1010 int forceFlag = 0; /* Force a fork */
1011 int forceDelta = 0; /* Force a delta-manifest */
1012 int forceBaseline = 0; /* Force a baseline-manifest */
1013 int allowConflict = 0; /* Allow unresolve merge conflicts */
1014 char *zManifestFile; /* Name of the manifest file */
1015 int useCksum; /* True if checksums should be computed and verified */
1016 int outputManifest; /* True to output "manifest" and "manifest.uuid" */
1017 int testRun; /* True for a test run. Debugging only */
1018 const char *zBranch; /* Create a new branch with this name */
@@ -1022,10 +1028,11 @@
1028 Blob muuid; /* Manifest uuid */
1029 Blob cksum1, cksum2; /* Before and after commit checksums */
1030 Blob cksum1b; /* Checksum recorded in the manifest */
1031 int szD; /* Size of the delta manifest */
1032 int szB; /* Size of the baseline manifest */
1033 int nConflict = 0; /* Number of unresolved merge conflicts */
1034
1035 url_proxy_options();
1036 noSign = find_option("nosign",0,0)!=0;
1037 forceDelta = find_option("delta",0,0)!=0;
1038 forceBaseline = find_option("baseline",0,0)!=0;
@@ -1050,10 +1057,11 @@
1057 if( zBranch==0 ) zBranch = "private";
1058 if( zBrClr==0 && zColor==0 ) zBrClr = "#fec084"; /* Orange */
1059 }
1060 zDateOvrd = find_option("date-override",0,1);
1061 zUserOvrd = find_option("user-override",0,1);
1062 allowConflict = find_option("conflict",0,0)!=0;
1063 db_must_be_within_tree();
1064 noSign = db_get_boolean("omitsign", 0)|noSign;
1065 if( db_get_boolean("clearsign", 0)==0 ){ noSign = 1; }
1066 useCksum = db_get_boolean("repo-cksum", 1);
1067 outputManifest = db_get_boolean("manifest", 0);
@@ -1255,42 +1263,51 @@
1263 /* Step 1: Insert records for all modified files into the blob
1264 ** table. If there were arguments passed to this command, only
1265 ** the identified fils are inserted (if they have been modified).
1266 */
1267 db_prepare(&q,
1268 "SELECT id, %Q || pathname, mrid, %s, chnged FROM vfile "
1269 "WHERE chnged==1 AND NOT deleted AND is_selected(id)",
1270 g.zLocalRoot, glob_expr("pathname", db_get("crnl-glob",""))
1271 );
1272 while( db_step(&q)==SQLITE_ROW ){
1273 int id, rid;
1274 const char *zFullname;
1275 Blob content;
1276 int crnlOk, chnged;
1277
1278 id = db_column_int(&q, 0);
1279 zFullname = db_column_text(&q, 1);
1280 rid = db_column_int(&q, 2);
1281 crnlOk = db_column_int(&q, 3);
1282 chnged = db_column_int(&q, 4);
1283
1284 blob_zero(&content);
1285 if( file_wd_islink(zFullname) ){
1286 /* Instead of file content, put link destination path */
1287 blob_read_link(&content, zFullname);
1288 }else{
1289 blob_read_from_file(&content, zFullname);
1290 }
1291 if( !crnlOk ) cr_warning(&content, zFullname);
1292 if( chnged==1 && contains_merge_marker(&content) ){
1293 nConflict++;
1294 fossil_print("possible unresolved merge conflict in %s\n",
1295 zFullname+strlen(g.zLocalRoot));
1296 }
1297 nrid = content_put(&content);
1298 blob_reset(&content);
1299 if( rid>0 ){
1300 content_deltify(rid, nrid, 0);
1301 }
1302 db_multi_exec("UPDATE vfile SET mrid=%d, rid=%d WHERE id=%d", nrid,nrid,id);
1303 db_multi_exec("INSERT OR IGNORE INTO unsent VALUES(%d)", nrid);
1304 }
1305 db_finalize(&q);
1306 if( nConflict && !allowConflict ){
1307 fossil_fatal("abort due to unresolve merge conflicts");
1308 }
1309
1310 /* Create the new manifest */
1311 if( blob_size(&comment)==0 ){
1312 blob_append(&comment, "(no comment)", -1);
1313 }
1314
+2 -2
--- src/doc.c
+++ src/doc.c
@@ -489,14 +489,14 @@
489489
" WHERE objid=%d AND type='ci'", vid));
490490
if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
491491
Blob title, tail;
492492
if( wiki_find_title(&filebody, &title, &tail) ){
493493
style_header(blob_str(&title));
494
- wiki_convert(&tail, 0, 0);
494
+ wiki_convert(&tail, 0, WIKI_BUTTONS);
495495
}else{
496496
style_header("Documentation");
497
- wiki_convert(&filebody, 0, 0);
497
+ wiki_convert(&filebody, 0, WIKI_BUTTONS);
498498
}
499499
style_footer();
500500
}else if( fossil_strcmp(zMime, "text/plain")==0 ){
501501
style_header("Documentation");
502502
@ <blockquote><pre>
503503
--- src/doc.c
+++ src/doc.c
@@ -489,14 +489,14 @@
489 " WHERE objid=%d AND type='ci'", vid));
490 if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
491 Blob title, tail;
492 if( wiki_find_title(&filebody, &title, &tail) ){
493 style_header(blob_str(&title));
494 wiki_convert(&tail, 0, 0);
495 }else{
496 style_header("Documentation");
497 wiki_convert(&filebody, 0, 0);
498 }
499 style_footer();
500 }else if( fossil_strcmp(zMime, "text/plain")==0 ){
501 style_header("Documentation");
502 @ <blockquote><pre>
503
--- src/doc.c
+++ src/doc.c
@@ -489,14 +489,14 @@
489 " WHERE objid=%d AND type='ci'", vid));
490 if( fossil_strcmp(zMime, "application/x-fossil-wiki")==0 ){
491 Blob title, tail;
492 if( wiki_find_title(&filebody, &title, &tail) ){
493 style_header(blob_str(&title));
494 wiki_convert(&tail, 0, WIKI_BUTTONS);
495 }else{
496 style_header("Documentation");
497 wiki_convert(&filebody, 0, WIKI_BUTTONS);
498 }
499 style_footer();
500 }else if( fossil_strcmp(zMime, "text/plain")==0 ){
501 style_header("Documentation");
502 @ <blockquote><pre>
503
+2 -2
--- src/finfo.c
+++ src/finfo.c
@@ -289,14 +289,14 @@
289289
if( (n = atoi(PD("n","0")))>0 ){
290290
blob_appendf(&sql, " LIMIT %d", n);
291291
url_add_parameter(&url, "n", P("n"));
292292
}
293293
if( firstChngOnly ){
294
- style_submenu_element("Full", "Show all changes",
294
+ style_submenu_element("Full", "Show all changes","%s",
295295
url_render(&url, "fco", "0", 0, 0));
296296
}else{
297
- style_submenu_element("Simplified", "Show only first use of a change",
297
+ style_submenu_element("Simplified", "Show only first use of a change","%s",
298298
url_render(&url, "fco", "1", 0, 0));
299299
}
300300
db_prepare(&q, blob_str(&sql));
301301
blob_reset(&sql);
302302
blob_zero(&title);
303303
--- src/finfo.c
+++ src/finfo.c
@@ -289,14 +289,14 @@
289 if( (n = atoi(PD("n","0")))>0 ){
290 blob_appendf(&sql, " LIMIT %d", n);
291 url_add_parameter(&url, "n", P("n"));
292 }
293 if( firstChngOnly ){
294 style_submenu_element("Full", "Show all changes",
295 url_render(&url, "fco", "0", 0, 0));
296 }else{
297 style_submenu_element("Simplified", "Show only first use of a change",
298 url_render(&url, "fco", "1", 0, 0));
299 }
300 db_prepare(&q, blob_str(&sql));
301 blob_reset(&sql);
302 blob_zero(&title);
303
--- src/finfo.c
+++ src/finfo.c
@@ -289,14 +289,14 @@
289 if( (n = atoi(PD("n","0")))>0 ){
290 blob_appendf(&sql, " LIMIT %d", n);
291 url_add_parameter(&url, "n", P("n"));
292 }
293 if( firstChngOnly ){
294 style_submenu_element("Full", "Show all changes","%s",
295 url_render(&url, "fco", "0", 0, 0));
296 }else{
297 style_submenu_element("Simplified", "Show only first use of a change","%s",
298 url_render(&url, "fco", "1", 0, 0));
299 }
300 db_prepare(&q, blob_str(&sql));
301 blob_reset(&sql);
302 blob_zero(&title);
303
+29 -10
--- src/import.c
+++ src/import.c
@@ -12,11 +12,11 @@
1212
** Author contact information:
1313
** [email protected]
1414
**
1515
*******************************************************************************
1616
**
17
-** This file contains code used to import the content of a Git
17
+** This file contains code used to import the content of a Git
1818
** repository in the git-fast-import format as a new Fossil
1919
** repository.
2020
*/
2121
#include "config.h"
2222
#include "import.h"
@@ -24,11 +24,11 @@
2424
2525
#if INTERFACE
2626
/*
2727
** A single file change record.
2828
*/
29
-struct ImportFile {
29
+struct ImportFile {
3030
char *zName; /* Name of a file */
3131
char *zUuid; /* UUID of the file */
3232
char *zPrior; /* Prior name if the name was changed */
3333
char isFrom; /* True if obtained from the parent */
3434
char isExe; /* True if executable */
@@ -80,11 +80,11 @@
8080
8181
/*
8282
** A no-op "xFinish" method
8383
*/
8484
static void finish_noop(void){}
85
-
85
+
8686
/*
8787
** Deallocate the state information.
8888
**
8989
** The azMerge[] and aFile[] arrays are zeroed by allocated space is
9090
** retained unless the freeAll flag is set.
@@ -152,16 +152,16 @@
152152
rid = db_last_insert_rowid();
153153
}
154154
if( zMark ){
155155
db_multi_exec(
156156
"INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
157
- "VALUES(%Q,%d,%B)",
157
+ "VALUES(%Q,%d,%B)",
158158
zMark, rid, &hash
159159
);
160160
db_multi_exec(
161161
"INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
162
- "VALUES(%B,%d,%B)",
162
+ "VALUES(%B,%d,%B)",
163163
&hash, rid, &hash
164164
);
165165
}
166166
if( saveUuid ){
167167
fossil_free(gg.zPrevCheckin);
@@ -182,11 +182,11 @@
182182
blob_reset(&content);
183183
import_reset(0);
184184
}
185185
186186
/*
187
-** Use data accumulated in gg from a "tag" record to add a new
187
+** Use data accumulated in gg from a "tag" record to add a new
188188
** control artifact to the BLOB table.
189189
*/
190190
static void finish_tag(void){
191191
Blob record, cksum;
192192
if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
@@ -223,11 +223,11 @@
223223
224224
/* Forward reference */
225225
static void import_prior_files(void);
226226
227227
/*
228
-** Use data accumulated in gg from a "commit" record to add a new
228
+** Use data accumulated in gg from a "commit" record to add a new
229229
** manifest artifact to the BLOB table.
230230
*/
231231
static void finish_commit(void){
232232
int i;
233233
char *zFromBranch;
@@ -410,11 +410,11 @@
410410
int rid;
411411
ManifestFile *pOld;
412412
ImportFile *pNew;
413413
if( gg.fromLoaded ) return;
414414
gg.fromLoaded = 1;
415
- if( gg.zFrom==0 && gg.zPrevCheckin!=0
415
+ if( gg.zFrom==0 && gg.zPrevCheckin!=0
416416
&& fossil_strcmp(gg.zBranch, gg.zPrevBranch)==0
417417
){
418418
gg.zFrom = gg.zPrevCheckin;
419419
gg.zPrevCheckin = 0;
420420
}
@@ -451,10 +451,27 @@
451451
}
452452
i++;
453453
}
454454
return 0;
455455
}
456
+
457
+/*
458
+** Dequote a fast-export filename. Filenames are normally unquoted. But
459
+** if the contain some obscure special characters, quotes might be added.
460
+*/
461
+static void dequote_git_filename(char *zName){
462
+ int n, i, j;
463
+ if( zName==0 || zName[0]!='"' ) return;
464
+ n = (int)strlen(zName);
465
+ if( zName[n-1]!='"' ) return;
466
+ for(i=0, j=1; j<n-1; j++){
467
+ char c = zName[j];
468
+ if( c=='\\' ) c = zName[++j];
469
+ zName[i++] = c;
470
+ }
471
+ zName[i] = 0;
472
+}
456473
457474
458475
/*
459476
** Read the git-fast-import format from pIn and insert the corresponding
460477
** content into the database.
@@ -596,26 +613,28 @@
596613
import_prior_files();
597614
z = &zLine[2];
598615
zPerm = next_token(&z);
599616
zUuid = next_token(&z);
600617
zName = rest_of_line(&z);
618
+ dequote_git_filename(zName);
601619
i = 0;
602620
pFile = import_find_file(zName, &i, gg.nFile);
603621
if( pFile==0 ){
604622
pFile = import_add_file();
605623
pFile->zName = fossil_strdup(zName);
606624
}
607625
pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
608
- pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
626
+ pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
609627
fossil_free(pFile->zUuid);
610628
pFile->zUuid = resolve_committish(zUuid);
611629
pFile->isFrom = 0;
612630
}else
613631
if( memcmp(zLine, "D ", 2)==0 ){
614632
import_prior_files();
615633
z = &zLine[2];
616634
zName = rest_of_line(&z);
635
+ dequote_git_filename(zName);
617636
i = 0;
618637
while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
619638
if( pFile->isFrom==0 ) continue;
620639
fossil_free(pFile->zName);
621640
fossil_free(pFile->zPrior);
@@ -748,11 +767,11 @@
748767
749768
/* The following temp-tables are used to hold information needed for
750769
** the import.
751770
**
752771
** The XMARK table provides a mapping from fast-import "marks" and symbols
753
- ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
772
+ ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
754773
** Given any valid fast-import symbol, the corresponding fossil rid and
755774
** uuid can found by searching against the xmark.tname field.
756775
**
757776
** The XBRANCH table maps commit marks and symbols into the branch those
758777
** commits belong to. If xbranch.tname is a fast-import symbol for a
759778
--- src/import.c
+++ src/import.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 **
15 *******************************************************************************
16 **
17 ** This file contains code used to import the content of a Git
18 ** repository in the git-fast-import format as a new Fossil
19 ** repository.
20 */
21 #include "config.h"
22 #include "import.h"
@@ -24,11 +24,11 @@
24
25 #if INTERFACE
26 /*
27 ** A single file change record.
28 */
29 struct ImportFile {
30 char *zName; /* Name of a file */
31 char *zUuid; /* UUID of the file */
32 char *zPrior; /* Prior name if the name was changed */
33 char isFrom; /* True if obtained from the parent */
34 char isExe; /* True if executable */
@@ -80,11 +80,11 @@
80
81 /*
82 ** A no-op "xFinish" method
83 */
84 static void finish_noop(void){}
85
86 /*
87 ** Deallocate the state information.
88 **
89 ** The azMerge[] and aFile[] arrays are zeroed by allocated space is
90 ** retained unless the freeAll flag is set.
@@ -152,16 +152,16 @@
152 rid = db_last_insert_rowid();
153 }
154 if( zMark ){
155 db_multi_exec(
156 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
157 "VALUES(%Q,%d,%B)",
158 zMark, rid, &hash
159 );
160 db_multi_exec(
161 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
162 "VALUES(%B,%d,%B)",
163 &hash, rid, &hash
164 );
165 }
166 if( saveUuid ){
167 fossil_free(gg.zPrevCheckin);
@@ -182,11 +182,11 @@
182 blob_reset(&content);
183 import_reset(0);
184 }
185
186 /*
187 ** Use data accumulated in gg from a "tag" record to add a new
188 ** control artifact to the BLOB table.
189 */
190 static void finish_tag(void){
191 Blob record, cksum;
192 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
@@ -223,11 +223,11 @@
223
224 /* Forward reference */
225 static void import_prior_files(void);
226
227 /*
228 ** Use data accumulated in gg from a "commit" record to add a new
229 ** manifest artifact to the BLOB table.
230 */
231 static void finish_commit(void){
232 int i;
233 char *zFromBranch;
@@ -410,11 +410,11 @@
410 int rid;
411 ManifestFile *pOld;
412 ImportFile *pNew;
413 if( gg.fromLoaded ) return;
414 gg.fromLoaded = 1;
415 if( gg.zFrom==0 && gg.zPrevCheckin!=0
416 && fossil_strcmp(gg.zBranch, gg.zPrevBranch)==0
417 ){
418 gg.zFrom = gg.zPrevCheckin;
419 gg.zPrevCheckin = 0;
420 }
@@ -451,10 +451,27 @@
451 }
452 i++;
453 }
454 return 0;
455 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
457
458 /*
459 ** Read the git-fast-import format from pIn and insert the corresponding
460 ** content into the database.
@@ -596,26 +613,28 @@
596 import_prior_files();
597 z = &zLine[2];
598 zPerm = next_token(&z);
599 zUuid = next_token(&z);
600 zName = rest_of_line(&z);
 
601 i = 0;
602 pFile = import_find_file(zName, &i, gg.nFile);
603 if( pFile==0 ){
604 pFile = import_add_file();
605 pFile->zName = fossil_strdup(zName);
606 }
607 pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
608 pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
609 fossil_free(pFile->zUuid);
610 pFile->zUuid = resolve_committish(zUuid);
611 pFile->isFrom = 0;
612 }else
613 if( memcmp(zLine, "D ", 2)==0 ){
614 import_prior_files();
615 z = &zLine[2];
616 zName = rest_of_line(&z);
 
617 i = 0;
618 while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
619 if( pFile->isFrom==0 ) continue;
620 fossil_free(pFile->zName);
621 fossil_free(pFile->zPrior);
@@ -748,11 +767,11 @@
748
749 /* The following temp-tables are used to hold information needed for
750 ** the import.
751 **
752 ** The XMARK table provides a mapping from fast-import "marks" and symbols
753 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
754 ** Given any valid fast-import symbol, the corresponding fossil rid and
755 ** uuid can found by searching against the xmark.tname field.
756 **
757 ** The XBRANCH table maps commit marks and symbols into the branch those
758 ** commits belong to. If xbranch.tname is a fast-import symbol for a
759
--- src/import.c
+++ src/import.c
@@ -12,11 +12,11 @@
12 ** Author contact information:
13 ** [email protected]
14 **
15 *******************************************************************************
16 **
17 ** This file contains code used to import the content of a Git
18 ** repository in the git-fast-import format as a new Fossil
19 ** repository.
20 */
21 #include "config.h"
22 #include "import.h"
@@ -24,11 +24,11 @@
24
25 #if INTERFACE
26 /*
27 ** A single file change record.
28 */
29 struct ImportFile {
30 char *zName; /* Name of a file */
31 char *zUuid; /* UUID of the file */
32 char *zPrior; /* Prior name if the name was changed */
33 char isFrom; /* True if obtained from the parent */
34 char isExe; /* True if executable */
@@ -80,11 +80,11 @@
80
81 /*
82 ** A no-op "xFinish" method
83 */
84 static void finish_noop(void){}
85
86 /*
87 ** Deallocate the state information.
88 **
89 ** The azMerge[] and aFile[] arrays are zeroed by allocated space is
90 ** retained unless the freeAll flag is set.
@@ -152,16 +152,16 @@
152 rid = db_last_insert_rowid();
153 }
154 if( zMark ){
155 db_multi_exec(
156 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
157 "VALUES(%Q,%d,%B)",
158 zMark, rid, &hash
159 );
160 db_multi_exec(
161 "INSERT OR IGNORE INTO xmark(tname, trid, tuuid)"
162 "VALUES(%B,%d,%B)",
163 &hash, rid, &hash
164 );
165 }
166 if( saveUuid ){
167 fossil_free(gg.zPrevCheckin);
@@ -182,11 +182,11 @@
182 blob_reset(&content);
183 import_reset(0);
184 }
185
186 /*
187 ** Use data accumulated in gg from a "tag" record to add a new
188 ** control artifact to the BLOB table.
189 */
190 static void finish_tag(void){
191 Blob record, cksum;
192 if( gg.zDate && gg.zTag && gg.zFrom && gg.zUser ){
@@ -223,11 +223,11 @@
223
224 /* Forward reference */
225 static void import_prior_files(void);
226
227 /*
228 ** Use data accumulated in gg from a "commit" record to add a new
229 ** manifest artifact to the BLOB table.
230 */
231 static void finish_commit(void){
232 int i;
233 char *zFromBranch;
@@ -410,11 +410,11 @@
410 int rid;
411 ManifestFile *pOld;
412 ImportFile *pNew;
413 if( gg.fromLoaded ) return;
414 gg.fromLoaded = 1;
415 if( gg.zFrom==0 && gg.zPrevCheckin!=0
416 && fossil_strcmp(gg.zBranch, gg.zPrevBranch)==0
417 ){
418 gg.zFrom = gg.zPrevCheckin;
419 gg.zPrevCheckin = 0;
420 }
@@ -451,10 +451,27 @@
451 }
452 i++;
453 }
454 return 0;
455 }
456
457 /*
458 ** Dequote a fast-export filename. Filenames are normally unquoted. But
459 ** if the contain some obscure special characters, quotes might be added.
460 */
461 static void dequote_git_filename(char *zName){
462 int n, i, j;
463 if( zName==0 || zName[0]!='"' ) return;
464 n = (int)strlen(zName);
465 if( zName[n-1]!='"' ) return;
466 for(i=0, j=1; j<n-1; j++){
467 char c = zName[j];
468 if( c=='\\' ) c = zName[++j];
469 zName[i++] = c;
470 }
471 zName[i] = 0;
472 }
473
474
475 /*
476 ** Read the git-fast-import format from pIn and insert the corresponding
477 ** content into the database.
@@ -596,26 +613,28 @@
613 import_prior_files();
614 z = &zLine[2];
615 zPerm = next_token(&z);
616 zUuid = next_token(&z);
617 zName = rest_of_line(&z);
618 dequote_git_filename(zName);
619 i = 0;
620 pFile = import_find_file(zName, &i, gg.nFile);
621 if( pFile==0 ){
622 pFile = import_add_file();
623 pFile->zName = fossil_strdup(zName);
624 }
625 pFile->isExe = (fossil_strcmp(zPerm, "100755")==0);
626 pFile->isLink = (fossil_strcmp(zPerm, "120000")==0);
627 fossil_free(pFile->zUuid);
628 pFile->zUuid = resolve_committish(zUuid);
629 pFile->isFrom = 0;
630 }else
631 if( memcmp(zLine, "D ", 2)==0 ){
632 import_prior_files();
633 z = &zLine[2];
634 zName = rest_of_line(&z);
635 dequote_git_filename(zName);
636 i = 0;
637 while( (pFile = import_find_file(zName, &i, gg.nFile))!=0 ){
638 if( pFile->isFrom==0 ) continue;
639 fossil_free(pFile->zName);
640 fossil_free(pFile->zPrior);
@@ -748,11 +767,11 @@
767
768 /* The following temp-tables are used to hold information needed for
769 ** the import.
770 **
771 ** The XMARK table provides a mapping from fast-import "marks" and symbols
772 ** into artifact ids (UUIDs - the 40-byte hex SHA1 hash of artifacts).
773 ** Given any valid fast-import symbol, the corresponding fossil rid and
774 ** uuid can found by searching against the xmark.tname field.
775 **
776 ** The XBRANCH table maps commit marks and symbols into the branch those
777 ** commits belong to. If xbranch.tname is a fast-import symbol for a
778
+49 -12
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133133
i += 3;
134134
}
135135
return i;
136136
}
137137
138
+/*
139
+** Text of boundary markers for merge conflicts.
140
+*/
141
+static char const * const mergeMarker[] = {
142
+ /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143
+ "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144
+ "======= COMMON ANCESTOR content follows ============================\n",
145
+ "======= MERGED IN content follows ==================================\n",
146
+ ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147
+};
138148
139149
140150
/*
141151
** Do a three-way merge. Initialize pOut to contain the result.
142152
**
@@ -154,18 +164,10 @@
154164
int *aC2; /* Changes from pPivot to pV2 */
155165
int i1, i2; /* Index into aC1[] and aC2[] */
156166
int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
157167
int limit1, limit2; /* Sizes of aC1[] and aC2[] */
158168
int nConflict = 0; /* Number of merge conflicts seen so far */
159
- static const char zBegin[] =
160
- "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
161
- static const char zMid1[] =
162
- "======= COMMON ANCESTOR content follows ============================\n";
163
- static const char zMid2[] =
164
- "======= MERGED IN content follows ==================================\n";
165
- static const char zEnd[] =
166
- ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
167169
168170
blob_zero(pOut); /* Merge results stored in pOut */
169171
170172
/* Compute the edits that occur from pPivot => pV1 (into aC1)
171173
** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
266268
nConflict++;
267269
while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
268270
sz++;
269271
}
270272
DEBUG( printf("CONFLICT %d\n", sz); )
271
- blob_appendf(pOut, zBegin);
273
+ blob_appendf(pOut, mergeMarker[0]);
272274
i1 = output_one_side(pOut, pV1, aC1, i1, sz);
273
- blob_appendf(pOut, zMid1);
275
+ blob_appendf(pOut, mergeMarker[1]);
274276
blob_copy_lines(pOut, pPivot, sz);
275
- blob_appendf(pOut, zMid2);
277
+ blob_appendf(pOut, mergeMarker[2]);
276278
i2 = output_one_side(pOut, pV2, aC2, i2, sz);
277
- blob_appendf(pOut, zEnd);
279
+ blob_appendf(pOut, mergeMarker[3]);
278280
}
279281
280282
/* If we are finished with an edit triple, advance to the next
281283
** triple.
282284
*/
@@ -301,10 +303,45 @@
301303
302304
free(aC1);
303305
free(aC2);
304306
return nConflict;
305307
}
308
+
309
+/*
310
+** Return true if the input string contains a merge marker on a line by
311
+** itself.
312
+*/
313
+int contains_merge_marker(Blob *p){
314
+ int i, j;
315
+ int len = (int)strlen(mergeMarker[0]);
316
+ const char *z = blob_buffer(p);
317
+ int n = blob_size(p) - len + 1;
318
+ assert( len==(int)strlen(mergeMarker[1]) );
319
+ assert( len==(int)strlen(mergeMarker[2]) );
320
+ assert( len==(int)strlen(mergeMarker[3]) );
321
+ assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 );
322
+ for(i=0; i<n; ){
323
+ for(j=0; j<4; j++){
324
+ if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
325
+ }
326
+ while( i<n && z[i]!='\n' ){ i++; }
327
+ while( i<n && z[i]=='\n' ){ i++; }
328
+ }
329
+ return 0;
330
+}
331
+
332
+/*
333
+** Return true if the named file contains an unresolved merge marker line.
334
+*/
335
+int file_contains_merge_marker(const char *zFullpath){
336
+ Blob file;
337
+ int rc;
338
+ blob_read_from_file(&file, zFullpath);
339
+ rc = contains_merge_marker(&file);
340
+ blob_reset(&file);
341
+ return rc;
342
+}
306343
307344
/*
308345
** COMMAND: test-3-way-merge
309346
**
310347
** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
311348
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133 i += 3;
134 }
135 return i;
136 }
137
 
 
 
 
 
 
 
 
 
 
138
139
140 /*
141 ** Do a three-way merge. Initialize pOut to contain the result.
142 **
@@ -154,18 +164,10 @@
154 int *aC2; /* Changes from pPivot to pV2 */
155 int i1, i2; /* Index into aC1[] and aC2[] */
156 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
157 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
158 int nConflict = 0; /* Number of merge conflicts seen so far */
159 static const char zBegin[] =
160 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n";
161 static const char zMid1[] =
162 "======= COMMON ANCESTOR content follows ============================\n";
163 static const char zMid2[] =
164 "======= MERGED IN content follows ==================================\n";
165 static const char zEnd[] =
166 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n";
167
168 blob_zero(pOut); /* Merge results stored in pOut */
169
170 /* Compute the edits that occur from pPivot => pV1 (into aC1)
171 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
266 nConflict++;
267 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
268 sz++;
269 }
270 DEBUG( printf("CONFLICT %d\n", sz); )
271 blob_appendf(pOut, zBegin);
272 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
273 blob_appendf(pOut, zMid1);
274 blob_copy_lines(pOut, pPivot, sz);
275 blob_appendf(pOut, zMid2);
276 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
277 blob_appendf(pOut, zEnd);
278 }
279
280 /* If we are finished with an edit triple, advance to the next
281 ** triple.
282 */
@@ -301,10 +303,45 @@
301
302 free(aC1);
303 free(aC2);
304 return nConflict;
305 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
307 /*
308 ** COMMAND: test-3-way-merge
309 **
310 ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
311
--- src/merge3.c
+++ src/merge3.c
@@ -133,10 +133,20 @@
133 i += 3;
134 }
135 return i;
136 }
137
138 /*
139 ** Text of boundary markers for merge conflicts.
140 */
141 static char const * const mergeMarker[] = {
142 /*123456789 123456789 123456789 123456789 123456789 123456789 123456789*/
143 "<<<<<<< BEGIN MERGE CONFLICT: local copy shown first <<<<<<<<<<<<<<<\n",
144 "======= COMMON ANCESTOR content follows ============================\n",
145 "======= MERGED IN content follows ==================================\n",
146 ">>>>>>> END MERGE CONFLICT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
147 };
148
149
150 /*
151 ** Do a three-way merge. Initialize pOut to contain the result.
152 **
@@ -154,18 +164,10 @@
164 int *aC2; /* Changes from pPivot to pV2 */
165 int i1, i2; /* Index into aC1[] and aC2[] */
166 int nCpy, nDel, nIns; /* Number of lines to copy, delete, or insert */
167 int limit1, limit2; /* Sizes of aC1[] and aC2[] */
168 int nConflict = 0; /* Number of merge conflicts seen so far */
 
 
 
 
 
 
 
 
169
170 blob_zero(pOut); /* Merge results stored in pOut */
171
172 /* Compute the edits that occur from pPivot => pV1 (into aC1)
173 ** and pPivot => pV2 (into aC2). Each of the aC1 and aC2 arrays is
@@ -266,17 +268,17 @@
268 nConflict++;
269 while( !ends_at_CPY(&aC1[i1], sz) || !ends_at_CPY(&aC2[i2], sz) ){
270 sz++;
271 }
272 DEBUG( printf("CONFLICT %d\n", sz); )
273 blob_appendf(pOut, mergeMarker[0]);
274 i1 = output_one_side(pOut, pV1, aC1, i1, sz);
275 blob_appendf(pOut, mergeMarker[1]);
276 blob_copy_lines(pOut, pPivot, sz);
277 blob_appendf(pOut, mergeMarker[2]);
278 i2 = output_one_side(pOut, pV2, aC2, i2, sz);
279 blob_appendf(pOut, mergeMarker[3]);
280 }
281
282 /* If we are finished with an edit triple, advance to the next
283 ** triple.
284 */
@@ -301,10 +303,45 @@
303
304 free(aC1);
305 free(aC2);
306 return nConflict;
307 }
308
309 /*
310 ** Return true if the input string contains a merge marker on a line by
311 ** itself.
312 */
313 int contains_merge_marker(Blob *p){
314 int i, j;
315 int len = (int)strlen(mergeMarker[0]);
316 const char *z = blob_buffer(p);
317 int n = blob_size(p) - len + 1;
318 assert( len==(int)strlen(mergeMarker[1]) );
319 assert( len==(int)strlen(mergeMarker[2]) );
320 assert( len==(int)strlen(mergeMarker[3]) );
321 assert( sizeof(mergeMarker)/sizeof(mergeMarker[0])==4 );
322 for(i=0; i<n; ){
323 for(j=0; j<4; j++){
324 if( memcmp(&z[i], mergeMarker[j], len)==0 ) return 1;
325 }
326 while( i<n && z[i]!='\n' ){ i++; }
327 while( i<n && z[i]=='\n' ){ i++; }
328 }
329 return 0;
330 }
331
332 /*
333 ** Return true if the named file contains an unresolved merge marker line.
334 */
335 int file_contains_merge_marker(const char *zFullpath){
336 Blob file;
337 int rc;
338 blob_read_from_file(&file, zFullpath);
339 rc = contains_merge_marker(&file);
340 blob_reset(&file);
341 return rc;
342 }
343
344 /*
345 ** COMMAND: test-3-way-merge
346 **
347 ** Usage: %fossil test-3-way-merge PIVOT V1 V2 MERGED
348
+8 -8
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -217,11 +217,11 @@
217217
struct TclContext *tclContext = (struct TclContext *)ctx;
218218
tcl_NotifyProc *xNotifyProc;
219219
220220
if ( !tclContext ){
221221
Th_ErrorMessage(interp,
222
- "Invalid Tcl context", (const char *)"", 0);
222
+ "invalid Tcl context", (const char *)"", 0);
223223
return TH_ERROR;
224224
}
225225
xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
226226
if ( xNotifyProc ){
227227
rc = xNotifyProc(bIsPost ?
@@ -397,11 +397,11 @@
397397
Tcl_DecrRefCount(objPtr);
398398
Tcl_Release((ClientData)tclInterp);
399399
return TH_ERROR;
400400
}
401401
if( !cmdInfo.objProc ){
402
- Th_ErrorMessage(interp, "Cannot invoke Tcl command:", argv[1], argl[1]);
402
+ Th_ErrorMessage(interp, "cannot invoke Tcl command:", argv[1], argl[1]);
403403
Tcl_DecrRefCount(objPtr);
404404
Tcl_Release((ClientData)tclInterp);
405405
return TH_ERROR;
406406
}
407407
Tcl_DecrRefCount(objPtr);
@@ -533,11 +533,11 @@
533533
#if defined(USE_TCL_STUBS)
534534
char fileName[] = TCL_LIBRARY_NAME;
535535
#endif
536536
if( !pLibrary || !pxFindExecutable || !pxCreateInterp ){
537537
Th_ErrorMessage(interp,
538
- "Invalid Tcl loader argument(s)", (const char *)"", 0);
538
+ "invalid Tcl loader argument(s)", (const char *)"", 0);
539539
return TH_ERROR;
540540
}
541541
#if defined(USE_TCL_STUBS)
542542
do {
543543
void *library = dlopen(fileName, RTLD_NOW | RTLD_GLOBAL);
@@ -549,11 +549,11 @@
549549
if( !xFindExecutable ){
550550
xFindExecutable = (tcl_FindExecutableProc *)dlsym(library, procName);
551551
}
552552
if( !xFindExecutable ){
553553
Th_ErrorMessage(interp,
554
- "Could not locate Tcl_FindExecutable", (const char *)"", 0);
554
+ "could not locate Tcl_FindExecutable", (const char *)"", 0);
555555
dlclose(library);
556556
return TH_ERROR;
557557
}
558558
procName = TCL_CREATEINTERP_NAME;
559559
xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName + 1);
@@ -560,11 +560,11 @@
560560
if( !xCreateInterp ){
561561
xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName);
562562
}
563563
if( !xCreateInterp ){
564564
Th_ErrorMessage(interp,
565
- "Could not locate Tcl_CreateInterp", (const char *)"", 0);
565
+ "could not locate Tcl_CreateInterp", (const char *)"", 0);
566566
dlclose(library);
567567
return TH_ERROR;
568568
}
569569
*pLibrary = library;
570570
*pxFindExecutable = xFindExecutable;
@@ -571,11 +571,11 @@
571571
*pxCreateInterp = xCreateInterp;
572572
return TH_OK;
573573
}
574574
} while( --fileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
575575
Th_ErrorMessage(interp,
576
- "Could not load Tcl shared library \"" TCL_LIBRARY_NAME "\"",
576
+ "could not load Tcl shared library \"" TCL_LIBRARY_NAME "\"",
577577
(const char *)"", 0);
578578
return TH_ERROR;
579579
#else
580580
*pLibrary = 0;
581581
*pxFindExecutable = Tcl_FindExecutable;
@@ -656,11 +656,11 @@
656656
Tcl_Interp *tclInterp;
657657
char *setup;
658658
659659
if ( !tclContext ){
660660
Th_ErrorMessage(interp,
661
- "Invalid Tcl context", (const char *)"", 0);
661
+ "invalid Tcl context", (const char *)"", 0);
662662
return TH_ERROR;
663663
}
664664
if ( tclContext->interp ){
665665
return TH_OK;
666666
}
@@ -679,11 +679,11 @@
679679
#if defined(USE_TCL_STUBS)
680680
!Tcl_InitStubs(tclInterp, "8.4", 0) ||
681681
#endif
682682
Tcl_InterpDeleted(tclInterp) ){
683683
Th_ErrorMessage(interp,
684
- "Could not create Tcl interpreter", (const char *)"", 0);
684
+ "could not create Tcl interpreter", (const char *)"", 0);
685685
return TH_ERROR;
686686
}
687687
tclContext->interp = tclInterp;
688688
if( Tcl_Init(tclInterp)!=TCL_OK ){
689689
Th_ErrorMessage(interp,
690690
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -217,11 +217,11 @@
217 struct TclContext *tclContext = (struct TclContext *)ctx;
218 tcl_NotifyProc *xNotifyProc;
219
220 if ( !tclContext ){
221 Th_ErrorMessage(interp,
222 "Invalid Tcl context", (const char *)"", 0);
223 return TH_ERROR;
224 }
225 xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
226 if ( xNotifyProc ){
227 rc = xNotifyProc(bIsPost ?
@@ -397,11 +397,11 @@
397 Tcl_DecrRefCount(objPtr);
398 Tcl_Release((ClientData)tclInterp);
399 return TH_ERROR;
400 }
401 if( !cmdInfo.objProc ){
402 Th_ErrorMessage(interp, "Cannot invoke Tcl command:", argv[1], argl[1]);
403 Tcl_DecrRefCount(objPtr);
404 Tcl_Release((ClientData)tclInterp);
405 return TH_ERROR;
406 }
407 Tcl_DecrRefCount(objPtr);
@@ -533,11 +533,11 @@
533 #if defined(USE_TCL_STUBS)
534 char fileName[] = TCL_LIBRARY_NAME;
535 #endif
536 if( !pLibrary || !pxFindExecutable || !pxCreateInterp ){
537 Th_ErrorMessage(interp,
538 "Invalid Tcl loader argument(s)", (const char *)"", 0);
539 return TH_ERROR;
540 }
541 #if defined(USE_TCL_STUBS)
542 do {
543 void *library = dlopen(fileName, RTLD_NOW | RTLD_GLOBAL);
@@ -549,11 +549,11 @@
549 if( !xFindExecutable ){
550 xFindExecutable = (tcl_FindExecutableProc *)dlsym(library, procName);
551 }
552 if( !xFindExecutable ){
553 Th_ErrorMessage(interp,
554 "Could not locate Tcl_FindExecutable", (const char *)"", 0);
555 dlclose(library);
556 return TH_ERROR;
557 }
558 procName = TCL_CREATEINTERP_NAME;
559 xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName + 1);
@@ -560,11 +560,11 @@
560 if( !xCreateInterp ){
561 xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName);
562 }
563 if( !xCreateInterp ){
564 Th_ErrorMessage(interp,
565 "Could not locate Tcl_CreateInterp", (const char *)"", 0);
566 dlclose(library);
567 return TH_ERROR;
568 }
569 *pLibrary = library;
570 *pxFindExecutable = xFindExecutable;
@@ -571,11 +571,11 @@
571 *pxCreateInterp = xCreateInterp;
572 return TH_OK;
573 }
574 } while( --fileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
575 Th_ErrorMessage(interp,
576 "Could not load Tcl shared library \"" TCL_LIBRARY_NAME "\"",
577 (const char *)"", 0);
578 return TH_ERROR;
579 #else
580 *pLibrary = 0;
581 *pxFindExecutable = Tcl_FindExecutable;
@@ -656,11 +656,11 @@
656 Tcl_Interp *tclInterp;
657 char *setup;
658
659 if ( !tclContext ){
660 Th_ErrorMessage(interp,
661 "Invalid Tcl context", (const char *)"", 0);
662 return TH_ERROR;
663 }
664 if ( tclContext->interp ){
665 return TH_OK;
666 }
@@ -679,11 +679,11 @@
679 #if defined(USE_TCL_STUBS)
680 !Tcl_InitStubs(tclInterp, "8.4", 0) ||
681 #endif
682 Tcl_InterpDeleted(tclInterp) ){
683 Th_ErrorMessage(interp,
684 "Could not create Tcl interpreter", (const char *)"", 0);
685 return TH_ERROR;
686 }
687 tclContext->interp = tclInterp;
688 if( Tcl_Init(tclInterp)!=TCL_OK ){
689 Th_ErrorMessage(interp,
690
--- src/th_tcl.c
+++ src/th_tcl.c
@@ -217,11 +217,11 @@
217 struct TclContext *tclContext = (struct TclContext *)ctx;
218 tcl_NotifyProc *xNotifyProc;
219
220 if ( !tclContext ){
221 Th_ErrorMessage(interp,
222 "invalid Tcl context", (const char *)"", 0);
223 return TH_ERROR;
224 }
225 xNotifyProc = bIsPost ? tclContext->xPostEval : tclContext->xPreEval;
226 if ( xNotifyProc ){
227 rc = xNotifyProc(bIsPost ?
@@ -397,11 +397,11 @@
397 Tcl_DecrRefCount(objPtr);
398 Tcl_Release((ClientData)tclInterp);
399 return TH_ERROR;
400 }
401 if( !cmdInfo.objProc ){
402 Th_ErrorMessage(interp, "cannot invoke Tcl command:", argv[1], argl[1]);
403 Tcl_DecrRefCount(objPtr);
404 Tcl_Release((ClientData)tclInterp);
405 return TH_ERROR;
406 }
407 Tcl_DecrRefCount(objPtr);
@@ -533,11 +533,11 @@
533 #if defined(USE_TCL_STUBS)
534 char fileName[] = TCL_LIBRARY_NAME;
535 #endif
536 if( !pLibrary || !pxFindExecutable || !pxCreateInterp ){
537 Th_ErrorMessage(interp,
538 "invalid Tcl loader argument(s)", (const char *)"", 0);
539 return TH_ERROR;
540 }
541 #if defined(USE_TCL_STUBS)
542 do {
543 void *library = dlopen(fileName, RTLD_NOW | RTLD_GLOBAL);
@@ -549,11 +549,11 @@
549 if( !xFindExecutable ){
550 xFindExecutable = (tcl_FindExecutableProc *)dlsym(library, procName);
551 }
552 if( !xFindExecutable ){
553 Th_ErrorMessage(interp,
554 "could not locate Tcl_FindExecutable", (const char *)"", 0);
555 dlclose(library);
556 return TH_ERROR;
557 }
558 procName = TCL_CREATEINTERP_NAME;
559 xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName + 1);
@@ -560,11 +560,11 @@
560 if( !xCreateInterp ){
561 xCreateInterp = (tcl_CreateInterpProc *)dlsym(library, procName);
562 }
563 if( !xCreateInterp ){
564 Th_ErrorMessage(interp,
565 "could not locate Tcl_CreateInterp", (const char *)"", 0);
566 dlclose(library);
567 return TH_ERROR;
568 }
569 *pLibrary = library;
570 *pxFindExecutable = xFindExecutable;
@@ -571,11 +571,11 @@
571 *pxCreateInterp = xCreateInterp;
572 return TH_OK;
573 }
574 } while( --fileName[TCL_MINOR_OFFSET]>'3' ); /* Tcl 8.4+ */
575 Th_ErrorMessage(interp,
576 "could not load Tcl shared library \"" TCL_LIBRARY_NAME "\"",
577 (const char *)"", 0);
578 return TH_ERROR;
579 #else
580 *pLibrary = 0;
581 *pxFindExecutable = Tcl_FindExecutable;
@@ -656,11 +656,11 @@
656 Tcl_Interp *tclInterp;
657 char *setup;
658
659 if ( !tclContext ){
660 Th_ErrorMessage(interp,
661 "invalid Tcl context", (const char *)"", 0);
662 return TH_ERROR;
663 }
664 if ( tclContext->interp ){
665 return TH_OK;
666 }
@@ -679,11 +679,11 @@
679 #if defined(USE_TCL_STUBS)
680 !Tcl_InitStubs(tclInterp, "8.4", 0) ||
681 #endif
682 Tcl_InterpDeleted(tclInterp) ){
683 Th_ErrorMessage(interp,
684 "could not create Tcl interpreter", (const char *)"", 0);
685 return TH_ERROR;
686 }
687 tclContext->interp = tclInterp;
688 if( Tcl_Init(tclInterp)!=TCL_OK ){
689 Th_ErrorMessage(interp,
690
+1
--- src/tkt.c
+++ src/tkt.c
@@ -446,10 +446,11 @@
446446
free(zDate);
447447
for(i=0; i<nField; i++){
448448
if( azAppend[i] ){
449449
blob_appendf(&tktchng, "J +%s %z\n", azField[i],
450450
fossilize(azAppend[i], -1));
451
+ ++nJ;
451452
}
452453
}
453454
for(i=0; i<nField; i++){
454455
const char *zValue;
455456
int nValue;
456457
--- src/tkt.c
+++ src/tkt.c
@@ -446,10 +446,11 @@
446 free(zDate);
447 for(i=0; i<nField; i++){
448 if( azAppend[i] ){
449 blob_appendf(&tktchng, "J +%s %z\n", azField[i],
450 fossilize(azAppend[i], -1));
 
451 }
452 }
453 for(i=0; i<nField; i++){
454 const char *zValue;
455 int nValue;
456
--- src/tkt.c
+++ src/tkt.c
@@ -446,10 +446,11 @@
446 free(zDate);
447 for(i=0; i<nField; i++){
448 if( azAppend[i] ){
449 blob_appendf(&tktchng, "J +%s %z\n", azField[i],
450 fossilize(azAppend[i], -1));
451 ++nJ;
452 }
453 }
454 for(i=0; i<nField; i++){
455 const char *zValue;
456 int nValue;
457
+78 -17
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -27,10 +27,11 @@
2727
*/
2828
#define WIKI_NOFOLLOW 0x001
2929
#define WIKI_HTML 0x002
3030
#define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */
3131
#define WIKI_NOBLOCK 0x008 /* No block markup of any kind */
32
+#define WIKI_BUTTONS 0x010 /* Allow sub-menu buttons */
3233
#endif
3334
3435
3536
/*
3637
** These are the only markup attributes allowed.
@@ -378,19 +379,19 @@
378379
#define TOKEN_INDENT 9 /* " " */
379380
#define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
380381
#define TOKEN_TEXT 11 /* None of the above */
381382
382383
/*
383
-** State flags
384
+** State flags. Save the lower 16 bits for the WIKI_* flags.
384385
*/
385
-#define AT_NEWLINE 0x001 /* At start of a line */
386
-#define AT_PARAGRAPH 0x002 /* At start of a paragraph */
387
-#define ALLOW_WIKI 0x004 /* Allow wiki markup */
388
-#define FONT_MARKUP_ONLY 0x008 /* Only allow MUTYPE_FONT markup */
389
-#define INLINE_MARKUP_ONLY 0x010 /* Allow only "inline" markup */
390
-#define IN_LIST 0x020 /* Within wiki <ul> or <ol> */
391
-#define WIKI_USE_HTML 0x040 /* wiki-use-html option = on */
386
+#define AT_NEWLINE 0x0010000 /* At start of a line */
387
+#define AT_PARAGRAPH 0x0020000 /* At start of a paragraph */
388
+#define ALLOW_WIKI 0x0040000 /* Allow wiki markup */
389
+#define FONT_MARKUP_ONLY 0x0080000 /* Only allow MUTYPE_FONT markup */
390
+#define INLINE_MARKUP_ONLY 0x0100000 /* Allow only "inline" markup */
391
+#define IN_LIST 0x0200000 /* Within wiki <ul> or <ol> */
392
+#define WIKI_USE_HTML 0x0400000 /* wiki-use-html option = on */
392393
393394
/*
394395
** Current state of the rendering engine
395396
*/
396397
typedef struct Renderer Renderer;
@@ -825,22 +826,72 @@
825826
z[n] = p->aAttr[i].cTerm;
826827
}
827828
}
828829
829830
/*
830
-** Return the ID attribute for markup. Return NULL if there is no
831
+** Return the value of attribute attrId. Return NULL if there is no
831832
** ID attribute.
832833
*/
833
-static const char *markupId(ParsedMarkup *p){
834
+static const char *attributeValue(ParsedMarkup *p, int attrId){
834835
int i;
835836
for(i=0; i<p->nAttr; i++){
836
- if( p->aAttr[i].iACode==ATTR_ID ){
837
+ if( p->aAttr[i].iACode==attrId ){
837838
return p->aAttr[i].zValue;
838839
}
839840
}
840841
return 0;
841842
}
843
+
844
+/*
845
+** Return the ID attribute for markup. Return NULL if there is no
846
+** ID attribute.
847
+*/
848
+static const char *markupId(ParsedMarkup *p){
849
+ return attributeValue(p, ATTR_ID);
850
+}
851
+
852
+/*
853
+** Check markup pMarkup to see if it is a hyperlink with class "button"
854
+** that is follows by simple text and an </a> only. Example:
855
+**
856
+** <a class="button" href="../index.wiki">Index</a>
857
+**
858
+** If the markup matches this pattern, and if the WIKI_BUTTONS flag was
859
+** passed to wiki_convert(), then transform this link into a submenu
860
+** button, skip the text, and set *pN equal to the total length of the
861
+** text through the end of </a> and return true. If the markup does
862
+** not match or if WIKI_BUTTONS is not set, then make no changes to *pN
863
+** and return false.
864
+*/
865
+static int isButtonHyperlink(
866
+ Renderer *p, /* Renderer state */
867
+ ParsedMarkup *pMarkup, /* Potential button markup */
868
+ const char *z, /* Complete text of Wiki */
869
+ int *pN /* Characters of z[] consumed */
870
+){
871
+ const char *zClass;
872
+ const char *zHref;
873
+ char *zTag;
874
+ int i, j;
875
+ if( (p->state & WIKI_BUTTONS)==0 ) return 0;
876
+ zClass = attributeValue(pMarkup, ATTR_CLASS);
877
+ if( zClass==0 ) return 0;
878
+ if( fossil_strcmp(zClass, "button")!=0 ) return 0;
879
+ zHref = attributeValue(pMarkup, ATTR_HREF);
880
+ if( zHref==0 ) return 0;
881
+ i = *pN;
882
+ while( z[i] && z[i]!='<' ){ i++; }
883
+ if( fossil_strnicmp(&z[i], "</a>",4)!=0 ) return 0;
884
+ for(j=*pN; fossil_isspace(z[j]); j++){}
885
+ zTag = mprintf("%.*s", i-j, &z[j]);
886
+ j = (int)strlen(zTag);
887
+ while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; }
888
+ if( j==0 ) return 0;
889
+ style_submenu_element(zTag, zTag, "%s", zHref);
890
+ *pN = i+4;
891
+ return 1;
892
+}
842893
843894
/*
844895
** Pop a single element off of the stack. As the element is popped,
845896
** output its end tag if it is not a </div> tag.
846897
*/
@@ -1453,14 +1504,16 @@
14531504
pushStack(p, markup.iCode);
14541505
renderMarkup(p->pOut, &markup);
14551506
}
14561507
}else
14571508
if( markup.iType==MUTYPE_HYPERLINK ){
1458
- popStackToTag(p, markup.iCode);
1459
- startAutoParagraph(p);
1460
- renderMarkup(p->pOut, &markup);
1461
- pushStack(p, markup.iCode);
1509
+ if( !isButtonHyperlink(p, &markup, z, &n) ){
1510
+ popStackToTag(p, markup.iCode);
1511
+ startAutoParagraph(p);
1512
+ renderMarkup(p->pOut, &markup);
1513
+ pushStack(p, markup.iCode);
1514
+ }
14621515
}else
14631516
{
14641517
if( markup.iType==MUTYPE_FONT ){
14651518
startAutoParagraph(p);
14661519
}else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){
@@ -1508,11 +1561,11 @@
15081561
void wiki_convert(Blob *pIn, Blob *pOut, int flags){
15091562
char *z;
15101563
Renderer renderer;
15111564
15121565
memset(&renderer, 0, sizeof(renderer));
1513
- renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
1566
+ renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH|flags;
15141567
if( flags & WIKI_NOBLOCK ){
15151568
renderer.state |= INLINE_MARKUP_ONLY;
15161569
}
15171570
if( flags & WIKI_INLINE ){
15181571
renderer.wantAutoParagraph = 0;
@@ -1538,17 +1591,25 @@
15381591
free(renderer.aStack);
15391592
}
15401593
15411594
/*
15421595
** COMMAND: test-wiki-render
1596
+**
1597
+** %fossil test-wiki-render FILE [OPTIONS]
1598
+**
1599
+** Options:
1600
+** --buttons Set the WIKI_BUTTONS flag
15431601
*/
15441602
void test_wiki_render(void){
15451603
Blob in, out;
1604
+ int flags = 0;
1605
+ if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
1606
+ verify_all_options();
15461607
if( g.argc!=3 ) usage("FILE");
15471608
blob_zero(&out);
15481609
blob_read_from_file(&in, g.argv[2]);
1549
- wiki_convert(&in, &out, 0);
1610
+ wiki_convert(&in, &out, flags);
15501611
blob_write_to_file(&out, "-");
15511612
}
15521613
15531614
/*
15541615
** Search for a <title>...</title> at the beginning of a wiki page.
15551616
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -27,10 +27,11 @@
27 */
28 #define WIKI_NOFOLLOW 0x001
29 #define WIKI_HTML 0x002
30 #define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */
31 #define WIKI_NOBLOCK 0x008 /* No block markup of any kind */
 
32 #endif
33
34
35 /*
36 ** These are the only markup attributes allowed.
@@ -378,19 +379,19 @@
378 #define TOKEN_INDENT 9 /* " " */
379 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
380 #define TOKEN_TEXT 11 /* None of the above */
381
382 /*
383 ** State flags
384 */
385 #define AT_NEWLINE 0x001 /* At start of a line */
386 #define AT_PARAGRAPH 0x002 /* At start of a paragraph */
387 #define ALLOW_WIKI 0x004 /* Allow wiki markup */
388 #define FONT_MARKUP_ONLY 0x008 /* Only allow MUTYPE_FONT markup */
389 #define INLINE_MARKUP_ONLY 0x010 /* Allow only "inline" markup */
390 #define IN_LIST 0x020 /* Within wiki <ul> or <ol> */
391 #define WIKI_USE_HTML 0x040 /* wiki-use-html option = on */
392
393 /*
394 ** Current state of the rendering engine
395 */
396 typedef struct Renderer Renderer;
@@ -825,22 +826,72 @@
825 z[n] = p->aAttr[i].cTerm;
826 }
827 }
828
829 /*
830 ** Return the ID attribute for markup. Return NULL if there is no
831 ** ID attribute.
832 */
833 static const char *markupId(ParsedMarkup *p){
834 int i;
835 for(i=0; i<p->nAttr; i++){
836 if( p->aAttr[i].iACode==ATTR_ID ){
837 return p->aAttr[i].zValue;
838 }
839 }
840 return 0;
841 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842
843 /*
844 ** Pop a single element off of the stack. As the element is popped,
845 ** output its end tag if it is not a </div> tag.
846 */
@@ -1453,14 +1504,16 @@
1453 pushStack(p, markup.iCode);
1454 renderMarkup(p->pOut, &markup);
1455 }
1456 }else
1457 if( markup.iType==MUTYPE_HYPERLINK ){
1458 popStackToTag(p, markup.iCode);
1459 startAutoParagraph(p);
1460 renderMarkup(p->pOut, &markup);
1461 pushStack(p, markup.iCode);
 
 
1462 }else
1463 {
1464 if( markup.iType==MUTYPE_FONT ){
1465 startAutoParagraph(p);
1466 }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){
@@ -1508,11 +1561,11 @@
1508 void wiki_convert(Blob *pIn, Blob *pOut, int flags){
1509 char *z;
1510 Renderer renderer;
1511
1512 memset(&renderer, 0, sizeof(renderer));
1513 renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH;
1514 if( flags & WIKI_NOBLOCK ){
1515 renderer.state |= INLINE_MARKUP_ONLY;
1516 }
1517 if( flags & WIKI_INLINE ){
1518 renderer.wantAutoParagraph = 0;
@@ -1538,17 +1591,25 @@
1538 free(renderer.aStack);
1539 }
1540
1541 /*
1542 ** COMMAND: test-wiki-render
 
 
 
 
 
1543 */
1544 void test_wiki_render(void){
1545 Blob in, out;
 
 
 
1546 if( g.argc!=3 ) usage("FILE");
1547 blob_zero(&out);
1548 blob_read_from_file(&in, g.argv[2]);
1549 wiki_convert(&in, &out, 0);
1550 blob_write_to_file(&out, "-");
1551 }
1552
1553 /*
1554 ** Search for a <title>...</title> at the beginning of a wiki page.
1555
--- src/wikiformat.c
+++ src/wikiformat.c
@@ -27,10 +27,11 @@
27 */
28 #define WIKI_NOFOLLOW 0x001
29 #define WIKI_HTML 0x002
30 #define WIKI_INLINE 0x004 /* Do not surround with <p>..</p> */
31 #define WIKI_NOBLOCK 0x008 /* No block markup of any kind */
32 #define WIKI_BUTTONS 0x010 /* Allow sub-menu buttons */
33 #endif
34
35
36 /*
37 ** These are the only markup attributes allowed.
@@ -378,19 +379,19 @@
379 #define TOKEN_INDENT 9 /* " " */
380 #define TOKEN_RAW 10 /* Output exactly (used when wiki-use-html==1) */
381 #define TOKEN_TEXT 11 /* None of the above */
382
383 /*
384 ** State flags. Save the lower 16 bits for the WIKI_* flags.
385 */
386 #define AT_NEWLINE 0x0010000 /* At start of a line */
387 #define AT_PARAGRAPH 0x0020000 /* At start of a paragraph */
388 #define ALLOW_WIKI 0x0040000 /* Allow wiki markup */
389 #define FONT_MARKUP_ONLY 0x0080000 /* Only allow MUTYPE_FONT markup */
390 #define INLINE_MARKUP_ONLY 0x0100000 /* Allow only "inline" markup */
391 #define IN_LIST 0x0200000 /* Within wiki <ul> or <ol> */
392 #define WIKI_USE_HTML 0x0400000 /* wiki-use-html option = on */
393
394 /*
395 ** Current state of the rendering engine
396 */
397 typedef struct Renderer Renderer;
@@ -825,22 +826,72 @@
826 z[n] = p->aAttr[i].cTerm;
827 }
828 }
829
830 /*
831 ** Return the value of attribute attrId. Return NULL if there is no
832 ** ID attribute.
833 */
834 static const char *attributeValue(ParsedMarkup *p, int attrId){
835 int i;
836 for(i=0; i<p->nAttr; i++){
837 if( p->aAttr[i].iACode==attrId ){
838 return p->aAttr[i].zValue;
839 }
840 }
841 return 0;
842 }
843
844 /*
845 ** Return the ID attribute for markup. Return NULL if there is no
846 ** ID attribute.
847 */
848 static const char *markupId(ParsedMarkup *p){
849 return attributeValue(p, ATTR_ID);
850 }
851
852 /*
853 ** Check markup pMarkup to see if it is a hyperlink with class "button"
854 ** that is follows by simple text and an </a> only. Example:
855 **
856 ** <a class="button" href="../index.wiki">Index</a>
857 **
858 ** If the markup matches this pattern, and if the WIKI_BUTTONS flag was
859 ** passed to wiki_convert(), then transform this link into a submenu
860 ** button, skip the text, and set *pN equal to the total length of the
861 ** text through the end of </a> and return true. If the markup does
862 ** not match or if WIKI_BUTTONS is not set, then make no changes to *pN
863 ** and return false.
864 */
865 static int isButtonHyperlink(
866 Renderer *p, /* Renderer state */
867 ParsedMarkup *pMarkup, /* Potential button markup */
868 const char *z, /* Complete text of Wiki */
869 int *pN /* Characters of z[] consumed */
870 ){
871 const char *zClass;
872 const char *zHref;
873 char *zTag;
874 int i, j;
875 if( (p->state & WIKI_BUTTONS)==0 ) return 0;
876 zClass = attributeValue(pMarkup, ATTR_CLASS);
877 if( zClass==0 ) return 0;
878 if( fossil_strcmp(zClass, "button")!=0 ) return 0;
879 zHref = attributeValue(pMarkup, ATTR_HREF);
880 if( zHref==0 ) return 0;
881 i = *pN;
882 while( z[i] && z[i]!='<' ){ i++; }
883 if( fossil_strnicmp(&z[i], "</a>",4)!=0 ) return 0;
884 for(j=*pN; fossil_isspace(z[j]); j++){}
885 zTag = mprintf("%.*s", i-j, &z[j]);
886 j = (int)strlen(zTag);
887 while( j>0 && fossil_isspace(zTag[j-1]) ){ j--; }
888 if( j==0 ) return 0;
889 style_submenu_element(zTag, zTag, "%s", zHref);
890 *pN = i+4;
891 return 1;
892 }
893
894 /*
895 ** Pop a single element off of the stack. As the element is popped,
896 ** output its end tag if it is not a </div> tag.
897 */
@@ -1453,14 +1504,16 @@
1504 pushStack(p, markup.iCode);
1505 renderMarkup(p->pOut, &markup);
1506 }
1507 }else
1508 if( markup.iType==MUTYPE_HYPERLINK ){
1509 if( !isButtonHyperlink(p, &markup, z, &n) ){
1510 popStackToTag(p, markup.iCode);
1511 startAutoParagraph(p);
1512 renderMarkup(p->pOut, &markup);
1513 pushStack(p, markup.iCode);
1514 }
1515 }else
1516 {
1517 if( markup.iType==MUTYPE_FONT ){
1518 startAutoParagraph(p);
1519 }else if( markup.iType==MUTYPE_BLOCK || markup.iType==MUTYPE_LIST ){
@@ -1508,11 +1561,11 @@
1561 void wiki_convert(Blob *pIn, Blob *pOut, int flags){
1562 char *z;
1563 Renderer renderer;
1564
1565 memset(&renderer, 0, sizeof(renderer));
1566 renderer.state = ALLOW_WIKI|AT_NEWLINE|AT_PARAGRAPH|flags;
1567 if( flags & WIKI_NOBLOCK ){
1568 renderer.state |= INLINE_MARKUP_ONLY;
1569 }
1570 if( flags & WIKI_INLINE ){
1571 renderer.wantAutoParagraph = 0;
@@ -1538,17 +1591,25 @@
1591 free(renderer.aStack);
1592 }
1593
1594 /*
1595 ** COMMAND: test-wiki-render
1596 **
1597 ** %fossil test-wiki-render FILE [OPTIONS]
1598 **
1599 ** Options:
1600 ** --buttons Set the WIKI_BUTTONS flag
1601 */
1602 void test_wiki_render(void){
1603 Blob in, out;
1604 int flags = 0;
1605 if( find_option("buttons",0,0)!=0 ) flags |= WIKI_BUTTONS;
1606 verify_all_options();
1607 if( g.argc!=3 ) usage("FILE");
1608 blob_zero(&out);
1609 blob_read_from_file(&in, g.argv[2]);
1610 wiki_convert(&in, &out, flags);
1611 blob_write_to_file(&out, "-");
1612 }
1613
1614 /*
1615 ** Search for a <title>...</title> at the beginning of a wiki page.
1616
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,76 @@
11
<title>Change Log</title>
2
+
3
+<h2>Changes For Version 1.24 (2012-10-22)</h2>
4
+ * Added support for WYSIWYG editing of wiki pages. WYSIWYG is turned off
5
+ by default and can be turned on by setting a configuration option.
6
+ * Allow style= attribute to occur in HTML markup on wiki pages.
7
+ * Added the --tk option to the "fossi diff" and "fossil stash diff"
8
+ commands, causing color-coded diff output to be displayed in a Tcl/Tk
9
+ GUI window. This option only works if Tcl/Tk is installed on the
10
+ host.
11
+ * On windows, make the "gdiff" command default to use WinDiff.exe.
12
+ * Update the "fossil stash" command so that it always prompts for a
13
+ comment if the -m option is omitted.
14
+ * Enhance the timeline webpages so that a=, b=, c=, d=, p=, and dp=
15
+ query parameters (and others) can all accept any valid checkin name
16
+ (such as branch names or labels) instead of just SHA1 hashes.
17
+ * Added the "fossil stash show" command.
18
+ * Added the "fileage" webpage with links to this page from the check-in
19
+ information page and from the file browser.
20
+ * Added --age and -t options to the "fossil ls" command.
21
+ * Added the --setmtime option to "fossil update". When used, the mtime
22
+ of all mananged files is set to the time when the most recent version of
23
+ the file was checked in.
24
+ * Changed the "vdiff" webpage to show the complete text of files that
25
+ were added or removed (the equivelent of using the -N or --newfile
26
+ options with the "fossil diff" command-line.)
27
+ * Added the --temp option to "fossil clean" and "fossil extra", causing
28
+ those commands to only look at temporary files generated by Fossil,
29
+ such as merge-conflict reports or aborted check-in messages.
30
+ * Enhance the raw page download so that it can guess the mimetype of
31
+ attachments based on the filename.
32
+ * Change the behavior of the from= and to= query parameters on the
33
+ timeline page so that by default the path between the two specified
34
+ check-ins avoids merges.
35
+ * Add the --baseurl option to "fossil server" and "fossil http" commands,
36
+ so that those commands can be used with reverse proxies.
37
+ * If unable to determine the command-line user, do not guess. Instead
38
+ issue an error message. This helps prevent check-ins from accidentally
39
+ occurring under the wrong username.
40
+ * Include branch information in the output of file change listings
41
+ (the "finfo" webpage).
42
+ * Make the simplified view of file history, rather than the full view,
43
+ the default.
44
+ * In the "fossil configuration" command, allow the "css" option for
45
+ synchronizing, importing, or exporting just the CSS file. This makes
46
+ it easier to share CSS files across repositories by exporting from
47
+ one and importing to another.
48
+ * Add the (unsupported) "fossil test-orphans" command.
49
+ * Add the --template option to the "fossil init" command, to facilitate
50
+ creating new repositories based on a template repository.
51
+ * Add the diff-binary setting, which if enabled causes binary files to
52
+ be passed to the "gdiff" command for it to deal with, rather than simply
53
+ printing a "cannot diff binary files" error.
54
+ * Add the --unified option to the "fossil diff" command to force a unified
55
+ diff even if the --tk option (which normally implies a side-by-side diff)
56
+ is used.
57
+ * Present a choice of nearby branches and versions to diff against on the
58
+ check-in information page.
59
+ * Add the --force option to the "fossil merge" command that will force the
60
+ merge to occur even if it would be a no-op. This is sometimes useful for
61
+ documentation purposes.
62
+ * Add another built-in skin: "Enhanced Default". Other minor tweaks to
63
+ the existing skins.
64
+ * Add the "urllist" webpage, showing a list of URLs by which a server
65
+ instance of Fossil has been accessed. Requires "Administrator" privileges.
66
+ A link is on the "Setup" main page.
67
+ * Enable dynamic loading of the Tcl runtime for installations that want
68
+ to use Tcl as part of their configuration. This reduces the size of
69
+ the Fossil binary and allows any version of Tcl 8.4 or later to be used.
70
+ * Merge the latest SQLite changes from upstream.
71
+ * Lots of minor bug fixes.
272
373
<h2>Changes For Version 1.23 (2012-08-08)</h2>
474
* The default checkout database name is now ".fslckout" instead of
575
"_FOSSIL_" on unix. Both names continue to work.
676
* Added the "fossil all changes" command
777
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,76 @@
1 <title>Change Log</title>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
3 <h2>Changes For Version 1.23 (2012-08-08)</h2>
4 * The default checkout database name is now ".fslckout" instead of
5 "_FOSSIL_" on unix. Both names continue to work.
6 * Added the "fossil all changes" command
7
--- www/changes.wiki
+++ www/changes.wiki
@@ -1,6 +1,76 @@
1 <title>Change Log</title>
2
3 <h2>Changes For Version 1.24 (2012-10-22)</h2>
4 * Added support for WYSIWYG editing of wiki pages. WYSIWYG is turned off
5 by default and can be turned on by setting a configuration option.
6 * Allow style= attribute to occur in HTML markup on wiki pages.
7 * Added the --tk option to the "fossi diff" and "fossil stash diff"
8 commands, causing color-coded diff output to be displayed in a Tcl/Tk
9 GUI window. This option only works if Tcl/Tk is installed on the
10 host.
11 * On windows, make the "gdiff" command default to use WinDiff.exe.
12 * Update the "fossil stash" command so that it always prompts for a
13 comment if the -m option is omitted.
14 * Enhance the timeline webpages so that a=, b=, c=, d=, p=, and dp=
15 query parameters (and others) can all accept any valid checkin name
16 (such as branch names or labels) instead of just SHA1 hashes.
17 * Added the "fossil stash show" command.
18 * Added the "fileage" webpage with links to this page from the check-in
19 information page and from the file browser.
20 * Added --age and -t options to the "fossil ls" command.
21 * Added the --setmtime option to "fossil update". When used, the mtime
22 of all mananged files is set to the time when the most recent version of
23 the file was checked in.
24 * Changed the "vdiff" webpage to show the complete text of files that
25 were added or removed (the equivelent of using the -N or --newfile
26 options with the "fossil diff" command-line.)
27 * Added the --temp option to "fossil clean" and "fossil extra", causing
28 those commands to only look at temporary files generated by Fossil,
29 such as merge-conflict reports or aborted check-in messages.
30 * Enhance the raw page download so that it can guess the mimetype of
31 attachments based on the filename.
32 * Change the behavior of the from= and to= query parameters on the
33 timeline page so that by default the path between the two specified
34 check-ins avoids merges.
35 * Add the --baseurl option to "fossil server" and "fossil http" commands,
36 so that those commands can be used with reverse proxies.
37 * If unable to determine the command-line user, do not guess. Instead
38 issue an error message. This helps prevent check-ins from accidentally
39 occurring under the wrong username.
40 * Include branch information in the output of file change listings
41 (the "finfo" webpage).
42 * Make the simplified view of file history, rather than the full view,
43 the default.
44 * In the "fossil configuration" command, allow the "css" option for
45 synchronizing, importing, or exporting just the CSS file. This makes
46 it easier to share CSS files across repositories by exporting from
47 one and importing to another.
48 * Add the (unsupported) "fossil test-orphans" command.
49 * Add the --template option to the "fossil init" command, to facilitate
50 creating new repositories based on a template repository.
51 * Add the diff-binary setting, which if enabled causes binary files to
52 be passed to the "gdiff" command for it to deal with, rather than simply
53 printing a "cannot diff binary files" error.
54 * Add the --unified option to the "fossil diff" command to force a unified
55 diff even if the --tk option (which normally implies a side-by-side diff)
56 is used.
57 * Present a choice of nearby branches and versions to diff against on the
58 check-in information page.
59 * Add the --force option to the "fossil merge" command that will force the
60 merge to occur even if it would be a no-op. This is sometimes useful for
61 documentation purposes.
62 * Add another built-in skin: "Enhanced Default". Other minor tweaks to
63 the existing skins.
64 * Add the "urllist" webpage, showing a list of URLs by which a server
65 instance of Fossil has been accessed. Requires "Administrator" privileges.
66 A link is on the "Setup" main page.
67 * Enable dynamic loading of the Tcl runtime for installations that want
68 to use Tcl as part of their configuration. This reduces the size of
69 the Fossil binary and allows any version of Tcl 8.4 or later to be used.
70 * Merge the latest SQLite changes from upstream.
71 * Lots of minor bug fixes.
72
73 <h2>Changes For Version 1.23 (2012-08-08)</h2>
74 * The default checkout database name is now ".fslckout" instead of
75 "_FOSSIL_" on unix. Both names continue to work.
76 * Added the "fossil all changes" command
77
+1 -1
--- www/style.wiki
+++ www/style.wiki
@@ -23,11 +23,11 @@
2323
16. All C-code conforms to ANSI C-89.
2424
2525
17. All comments and identifiers are in English.
2626
2727
18. The program is single-threaded. Do not use threads.
28
- (One except to this is the HTTP server implementation for windows,
28
+ (One exception to this is the HTTP server implementation for windows,
2929
which we do not know how to implement without the use of threads.)
3030
3131
3232
<b>C preprocessor macros</b>:
3333
3434
--- www/style.wiki
+++ www/style.wiki
@@ -23,11 +23,11 @@
23 16. All C-code conforms to ANSI C-89.
24
25 17. All comments and identifiers are in English.
26
27 18. The program is single-threaded. Do not use threads.
28 (One except to this is the HTTP server implementation for windows,
29 which we do not know how to implement without the use of threads.)
30
31
32 <b>C preprocessor macros</b>:
33
34
--- www/style.wiki
+++ www/style.wiki
@@ -23,11 +23,11 @@
23 16. All C-code conforms to ANSI C-89.
24
25 17. All comments and identifiers are in English.
26
27 18. The program is single-threaded. Do not use threads.
28 (One exception to this is the HTTP server implementation for windows,
29 which we do not know how to implement without the use of threads.)
30
31
32 <b>C preprocessor macros</b>:
33
34

Keyboard Shortcuts

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