Fossil SCM

Much better detection of changes to tags. Prevent commit with no changes.

baruch 2015-01-18 14:10 svn-import
Commit bb020aed6259245580adad127978a71ca1772cf9
1 file changed +75 -42
+75 -42
--- src/import.c
+++ src/import.c
@@ -935,38 +935,63 @@
935935
int branchId = db_column_int(&getChanges, 0);
936936
const char *zBranch = db_column_text(&getChanges, 1);
937937
int branchType = db_column_int(&getChanges, 2);
938938
int parentRid = db_column_int(&getChanges, 3);
939939
int mergeRid = parentRid;
940
- int rid;
941
- if( branchType!=SVN_TAG ){
942
- if( gsvn.zComment ){
943
- blob_appendf(&manifest, "C %F\n", gsvn.zComment);
944
- }else{
945
- blob_append(&manifest, "C (no\\scomment)\n", 16);
946
- }
947
- blob_appendf(&manifest, "D %s\n", gsvn.zDate);
948
- db_bind_int(&getFiles, ":branch", branchId);
949
- while( db_step(&getFiles)==SQLITE_ROW ){
950
- const char *zFile = db_column_text(&getFiles, 0);
951
- const char *zUuid = db_column_text(&getFiles, 1);
952
- const char *zPerm = db_column_text(&getFiles, 2);
953
- blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
954
- }
955
- db_reset(&getFiles);
956
- if( !bag_find(&gsvn.newBranches, branchId) ){
957
- parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
958
- " WHERE trev<%d AND tbranch=%d",
959
- gsvn.rev, branchId);
960
- }
940
+ Manifest *pParentManifest = 0;
941
+ ManifestFile *pParentFile = 0;
942
+ int sameAsParent = 1;
943
+ int parentBranch = 0;
944
+ if( !bag_find(&gsvn.newBranches, branchId) ){
945
+ parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
946
+ " WHERE trev<%d AND tbranch=%d",
947
+ gsvn.rev, branchId);
948
+ }
949
+ if( parentRid>0 ){
950
+ pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
951
+ pParentFile = manifest_file_next(pParentManifest, 0);
952
+ parentBranch = db_int(0, "SELECT tbranch FROM xrevisions WHERE trid=%d",
953
+ parentRid);
954
+ if( parentBranch!=branchId && branchType!=SVN_TAG ){
955
+ sameAsParent = 0;
956
+ }
957
+ }
958
+ if( gsvn.zComment ){
959
+ blob_appendf(&manifest, "C %F\n", gsvn.zComment);
960
+ }else{
961
+ blob_append(&manifest, "C (no\\scomment)\n", 16);
962
+ }
963
+ blob_appendf(&manifest, "D %s\n", gsvn.zDate);
964
+ db_bind_int(&getFiles, ":branch", branchId);
965
+ while( db_step(&getFiles)==SQLITE_ROW ){
966
+ const char *zFile = db_column_text(&getFiles, 0);
967
+ const char *zUuid = db_column_text(&getFiles, 1);
968
+ const char *zPerm = db_column_text(&getFiles, 2);
969
+ blob_appendf(&manifest, "F %F %s%s\n", zFile, zUuid, zPerm);
970
+ if( sameAsParent ){
971
+ if( !pParentFile
972
+ || fossil_strcmp(pParentFile->zName,zFile)!=0
973
+ || fossil_strcmp(pParentFile->zUuid,zUuid)!=0
974
+ || fossil_strcmp(pParentFile->zPerm,zPerm)!=0
975
+ ){
976
+ sameAsParent = 0;
977
+ }else{
978
+ pParentFile = manifest_file_next(pParentManifest, 0);
979
+ }
980
+ }
981
+ }
982
+ if( pParentFile ){
983
+ sameAsParent = 0;
984
+ }
985
+ db_reset(&getFiles);
986
+ if( !sameAsParent ){
961987
if( parentRid>0 ){
962988
char *zParentUuid = rid_to_uuid(parentRid);
963989
if( parentRid==mergeRid || mergeRid==0){
964990
char *zParentBranch =
965
- db_text(0, "SELECT tname FROM xbranches WHERE tid="
966
- " (SELECT tbranch FROM xrevisions WHERE trid=%d)",
967
- parentRid
991
+ db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
992
+ parentBranch
968993
);
969994
blob_appendf(&manifest, "P %s\n", zParentUuid);
970995
blob_appendf(&manifest, "T *branch * %F\n", zBranch);
971996
blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
972997
blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
@@ -982,12 +1007,13 @@
9821007
}else{
9831008
blob_appendf(&manifest, "T *branch * %F\n", zBranch);
9841009
blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
9851010
blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
9861011
}
987
- }else{
1012
+ }else if( branchType==SVN_TAG ){
9881013
char *zParentUuid = rid_to_uuid(parentRid);
1014
+ blob_reset(&manifest);
9891015
blob_appendf(&manifest, "D %s\n", gsvn.zDate);
9901016
blob_appendf(&manifest, "T +sym-%F %s\n", zBranch, zParentUuid);
9911017
fossil_free(zParentUuid);
9921018
}
9931019
if( gsvn.zUser ){
@@ -997,16 +1023,28 @@
9971023
blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
9981024
}
9991025
md5sum_blob(&manifest, &mcksum);
10001026
blob_appendf(&manifest, "Z %b\n", &mcksum);
10011027
blob_reset(&mcksum);
1002
- rid = content_put(&manifest);
1003
- db_bind_int(&setRid, ":branch", branchId);
1004
- db_bind_int(&setRid, ":rid", rid);
1005
- db_step(&setRid);
1006
- db_reset(&setRid);
1028
+ if( !sameAsParent ){
1029
+ int rid = content_put(&manifest);
1030
+ db_bind_int(&setRid, ":branch", branchId);
1031
+ db_bind_int(&setRid, ":rid", rid);
1032
+ db_step(&setRid);
1033
+ db_reset(&setRid);
1034
+ }else if( branchType==SVN_TAG ){
1035
+ content_put(&manifest);
1036
+ db_bind_int(&setRid, ":branch", branchId);
1037
+ db_bind_int(&setRid, ":rid", parentRid);
1038
+ db_step(&setRid);
1039
+ db_reset(&setRid);
1040
+ }else{
1041
+ db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1042
+ branchId, gsvn.rev);
1043
+ }
10071044
blob_reset(&manifest);
1045
+ manifest_destroy(pParentManifest);
10081046
}
10091047
db_reset(&getChanges);
10101048
db_finalize(&setRid);
10111049
}
10121050
@@ -1210,11 +1248,11 @@
12101248
char *zFile;
12111249
int branchType;
12121250
int branchId = svn_parse_path(zTemp, &zFile, &branchType);
12131251
char *zAction = svn_find_header(rec, "Node-action");
12141252
char *zKind = svn_find_header(rec, "Node-kind");
1215
- char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1253
+ char *zPerm = svn_find_prop(rec, "svn:executable") ? " x" : 0;
12161254
int deltaFlag = 0;
12171255
int srcRev = 0;
12181256
if( branchId==0 ){
12191257
svn_free_rec(&rec);
12201258
continue;
@@ -1250,19 +1288,13 @@
12501288
}
12511289
srcBranch = svn_parse_path(zSrcPath, &zSrcFile, &branchType);
12521290
if( srcBranch==0 ){
12531291
fossil_fatal("Copy from path outside the import paths");
12541292
}
1255
- if( branchType!=SVN_TAG ){
1256
- srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1257
- " WHERE trev<=%d AND tbranch=%d",
1258
- srcRev, srcBranch);
1259
- }else{
1260
- srcRid = db_int(0, "SELECT tparent, max(trev) FROM xrevisions"
1261
- " WHERE trev<=%d AND tbranch=%d",
1262
- srcRev, srcBranch);
1263
- }
1293
+ srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1294
+ " WHERE trev<=%d AND tbranch=%d",
1295
+ srcRev, srcBranch);
12641296
if( srcRid>0 && srcBranch!=branchId ){
12651297
db_bind_int(&addRev, ":branch", branchId);
12661298
db_step(&addRev);
12671299
db_reset(&addRev);
12681300
db_bind_int(&revSrc, ":parent", srcRid);
@@ -1273,11 +1305,11 @@
12731305
}
12741306
}
12751307
if( zKind==0 ){
12761308
fossil_fatal("Missing Node-kind");
12771309
}else if( strncmp(zKind, "dir", 3)==0 ){
1278
- if( zSrcPath && branchType!=SVN_TAG ){
1310
+ if( zSrcPath ){
12791311
if( srcRid>0 ){
12801312
if( zSrcFile[0]==0 ){
12811313
db_bind_text(&cpyRoot, ":path", zFile);
12821314
db_bind_int(&cpyRoot, ":branch", branchId);
12831315
db_bind_int(&cpyRoot, ":rid", srcRid);
@@ -1484,12 +1516,13 @@
14841516
}else
14851517
if( strncmp(g.argv[2], "svn", 3)==0 ){
14861518
db_multi_exec(
14871519
"CREATE TEMP TABLE xrevisions("
14881520
" trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1489
- " UNIQUE(tbranch, trev), UNIQUE(trid)"
1521
+ " UNIQUE(tbranch, trev)"
14901522
");"
1523
+ "CREATE INDEX temp.i_xrevisions ON xrevisions(trid);"
14911524
"CREATE TEMP TABLE xfiles("
14921525
" tpath TEXT, tbranch INT, tuuid TEXT, tperm TEXT,"
14931526
" UNIQUE (tbranch, tpath) ON CONFLICT REPLACE"
14941527
");"
14951528
"CREATE TEMP TABLE xbranches("
14961529
--- src/import.c
+++ src/import.c
@@ -935,38 +935,63 @@
935 int branchId = db_column_int(&getChanges, 0);
936 const char *zBranch = db_column_text(&getChanges, 1);
937 int branchType = db_column_int(&getChanges, 2);
938 int parentRid = db_column_int(&getChanges, 3);
939 int mergeRid = parentRid;
940 int rid;
941 if( branchType!=SVN_TAG ){
942 if( gsvn.zComment ){
943 blob_appendf(&manifest, "C %F\n", gsvn.zComment);
944 }else{
945 blob_append(&manifest, "C (no\\scomment)\n", 16);
946 }
947 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
948 db_bind_int(&getFiles, ":branch", branchId);
949 while( db_step(&getFiles)==SQLITE_ROW ){
950 const char *zFile = db_column_text(&getFiles, 0);
951 const char *zUuid = db_column_text(&getFiles, 1);
952 const char *zPerm = db_column_text(&getFiles, 2);
953 blob_appendf(&manifest, "F %F %s %s\n", zFile, zUuid, zPerm);
954 }
955 db_reset(&getFiles);
956 if( !bag_find(&gsvn.newBranches, branchId) ){
957 parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
958 " WHERE trev<%d AND tbranch=%d",
959 gsvn.rev, branchId);
960 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
961 if( parentRid>0 ){
962 char *zParentUuid = rid_to_uuid(parentRid);
963 if( parentRid==mergeRid || mergeRid==0){
964 char *zParentBranch =
965 db_text(0, "SELECT tname FROM xbranches WHERE tid="
966 " (SELECT tbranch FROM xrevisions WHERE trid=%d)",
967 parentRid
968 );
969 blob_appendf(&manifest, "P %s\n", zParentUuid);
970 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
971 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
972 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
@@ -982,12 +1007,13 @@
982 }else{
983 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
984 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
985 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
986 }
987 }else{
988 char *zParentUuid = rid_to_uuid(parentRid);
 
989 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
990 blob_appendf(&manifest, "T +sym-%F %s\n", zBranch, zParentUuid);
991 fossil_free(zParentUuid);
992 }
993 if( gsvn.zUser ){
@@ -997,16 +1023,28 @@
997 blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
998 }
999 md5sum_blob(&manifest, &mcksum);
1000 blob_appendf(&manifest, "Z %b\n", &mcksum);
1001 blob_reset(&mcksum);
1002 rid = content_put(&manifest);
1003 db_bind_int(&setRid, ":branch", branchId);
1004 db_bind_int(&setRid, ":rid", rid);
1005 db_step(&setRid);
1006 db_reset(&setRid);
 
 
 
 
 
 
 
 
 
 
 
1007 blob_reset(&manifest);
 
1008 }
1009 db_reset(&getChanges);
1010 db_finalize(&setRid);
1011 }
1012
@@ -1210,11 +1248,11 @@
1210 char *zFile;
1211 int branchType;
1212 int branchId = svn_parse_path(zTemp, &zFile, &branchType);
1213 char *zAction = svn_find_header(rec, "Node-action");
1214 char *zKind = svn_find_header(rec, "Node-kind");
1215 char *zPerm = svn_find_prop(rec, "svn:executable") ? "x" : 0;
1216 int deltaFlag = 0;
1217 int srcRev = 0;
1218 if( branchId==0 ){
1219 svn_free_rec(&rec);
1220 continue;
@@ -1250,19 +1288,13 @@
1250 }
1251 srcBranch = svn_parse_path(zSrcPath, &zSrcFile, &branchType);
1252 if( srcBranch==0 ){
1253 fossil_fatal("Copy from path outside the import paths");
1254 }
1255 if( branchType!=SVN_TAG ){
1256 srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1257 " WHERE trev<=%d AND tbranch=%d",
1258 srcRev, srcBranch);
1259 }else{
1260 srcRid = db_int(0, "SELECT tparent, max(trev) FROM xrevisions"
1261 " WHERE trev<=%d AND tbranch=%d",
1262 srcRev, srcBranch);
1263 }
1264 if( srcRid>0 && srcBranch!=branchId ){
1265 db_bind_int(&addRev, ":branch", branchId);
1266 db_step(&addRev);
1267 db_reset(&addRev);
1268 db_bind_int(&revSrc, ":parent", srcRid);
@@ -1273,11 +1305,11 @@
1273 }
1274 }
1275 if( zKind==0 ){
1276 fossil_fatal("Missing Node-kind");
1277 }else if( strncmp(zKind, "dir", 3)==0 ){
1278 if( zSrcPath && branchType!=SVN_TAG ){
1279 if( srcRid>0 ){
1280 if( zSrcFile[0]==0 ){
1281 db_bind_text(&cpyRoot, ":path", zFile);
1282 db_bind_int(&cpyRoot, ":branch", branchId);
1283 db_bind_int(&cpyRoot, ":rid", srcRid);
@@ -1484,12 +1516,13 @@
1484 }else
1485 if( strncmp(g.argv[2], "svn", 3)==0 ){
1486 db_multi_exec(
1487 "CREATE TEMP TABLE xrevisions("
1488 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1489 " UNIQUE(tbranch, trev), UNIQUE(trid)"
1490 ");"
 
1491 "CREATE TEMP TABLE xfiles("
1492 " tpath TEXT, tbranch INT, tuuid TEXT, tperm TEXT,"
1493 " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE"
1494 ");"
1495 "CREATE TEMP TABLE xbranches("
1496
--- src/import.c
+++ src/import.c
@@ -935,38 +935,63 @@
935 int branchId = db_column_int(&getChanges, 0);
936 const char *zBranch = db_column_text(&getChanges, 1);
937 int branchType = db_column_int(&getChanges, 2);
938 int parentRid = db_column_int(&getChanges, 3);
939 int mergeRid = parentRid;
940 Manifest *pParentManifest = 0;
941 ManifestFile *pParentFile = 0;
942 int sameAsParent = 1;
943 int parentBranch = 0;
944 if( !bag_find(&gsvn.newBranches, branchId) ){
945 parentRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
946 " WHERE trev<%d AND tbranch=%d",
947 gsvn.rev, branchId);
948 }
949 if( parentRid>0 ){
950 pParentManifest = manifest_get(parentRid, CFTYPE_MANIFEST, 0);
951 pParentFile = manifest_file_next(pParentManifest, 0);
952 parentBranch = db_int(0, "SELECT tbranch FROM xrevisions WHERE trid=%d",
953 parentRid);
954 if( parentBranch!=branchId && branchType!=SVN_TAG ){
955 sameAsParent = 0;
956 }
957 }
958 if( gsvn.zComment ){
959 blob_appendf(&manifest, "C %F\n", gsvn.zComment);
960 }else{
961 blob_append(&manifest, "C (no\\scomment)\n", 16);
962 }
963 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
964 db_bind_int(&getFiles, ":branch", branchId);
965 while( db_step(&getFiles)==SQLITE_ROW ){
966 const char *zFile = db_column_text(&getFiles, 0);
967 const char *zUuid = db_column_text(&getFiles, 1);
968 const char *zPerm = db_column_text(&getFiles, 2);
969 blob_appendf(&manifest, "F %F %s%s\n", zFile, zUuid, zPerm);
970 if( sameAsParent ){
971 if( !pParentFile
972 || fossil_strcmp(pParentFile->zName,zFile)!=0
973 || fossil_strcmp(pParentFile->zUuid,zUuid)!=0
974 || fossil_strcmp(pParentFile->zPerm,zPerm)!=0
975 ){
976 sameAsParent = 0;
977 }else{
978 pParentFile = manifest_file_next(pParentManifest, 0);
979 }
980 }
981 }
982 if( pParentFile ){
983 sameAsParent = 0;
984 }
985 db_reset(&getFiles);
986 if( !sameAsParent ){
987 if( parentRid>0 ){
988 char *zParentUuid = rid_to_uuid(parentRid);
989 if( parentRid==mergeRid || mergeRid==0){
990 char *zParentBranch =
991 db_text(0, "SELECT tname FROM xbranches WHERE tid=%d",
992 parentBranch
 
993 );
994 blob_appendf(&manifest, "P %s\n", zParentUuid);
995 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
996 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
997 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
@@ -982,12 +1007,13 @@
1007 }else{
1008 blob_appendf(&manifest, "T *branch * %F\n", zBranch);
1009 blob_appendf(&manifest, "T *sym-%F *\n", zBranch);
1010 blob_appendf(&manifest, "T +sym-svn-rev-%d *\n", gsvn.rev);
1011 }
1012 }else if( branchType==SVN_TAG ){
1013 char *zParentUuid = rid_to_uuid(parentRid);
1014 blob_reset(&manifest);
1015 blob_appendf(&manifest, "D %s\n", gsvn.zDate);
1016 blob_appendf(&manifest, "T +sym-%F %s\n", zBranch, zParentUuid);
1017 fossil_free(zParentUuid);
1018 }
1019 if( gsvn.zUser ){
@@ -997,16 +1023,28 @@
1023 blob_appendf(&manifest, "U %F\n", zUserOvrd ? zUserOvrd : login_name());
1024 }
1025 md5sum_blob(&manifest, &mcksum);
1026 blob_appendf(&manifest, "Z %b\n", &mcksum);
1027 blob_reset(&mcksum);
1028 if( !sameAsParent ){
1029 int rid = content_put(&manifest);
1030 db_bind_int(&setRid, ":branch", branchId);
1031 db_bind_int(&setRid, ":rid", rid);
1032 db_step(&setRid);
1033 db_reset(&setRid);
1034 }else if( branchType==SVN_TAG ){
1035 content_put(&manifest);
1036 db_bind_int(&setRid, ":branch", branchId);
1037 db_bind_int(&setRid, ":rid", parentRid);
1038 db_step(&setRid);
1039 db_reset(&setRid);
1040 }else{
1041 db_multi_exec("DELETE FROM xrevisions WHERE tbranch=%d AND trev=%d",
1042 branchId, gsvn.rev);
1043 }
1044 blob_reset(&manifest);
1045 manifest_destroy(pParentManifest);
1046 }
1047 db_reset(&getChanges);
1048 db_finalize(&setRid);
1049 }
1050
@@ -1210,11 +1248,11 @@
1248 char *zFile;
1249 int branchType;
1250 int branchId = svn_parse_path(zTemp, &zFile, &branchType);
1251 char *zAction = svn_find_header(rec, "Node-action");
1252 char *zKind = svn_find_header(rec, "Node-kind");
1253 char *zPerm = svn_find_prop(rec, "svn:executable") ? " x" : 0;
1254 int deltaFlag = 0;
1255 int srcRev = 0;
1256 if( branchId==0 ){
1257 svn_free_rec(&rec);
1258 continue;
@@ -1250,19 +1288,13 @@
1288 }
1289 srcBranch = svn_parse_path(zSrcPath, &zSrcFile, &branchType);
1290 if( srcBranch==0 ){
1291 fossil_fatal("Copy from path outside the import paths");
1292 }
1293 srcRid = db_int(0, "SELECT trid, max(trev) FROM xrevisions"
1294 " WHERE trev<=%d AND tbranch=%d",
1295 srcRev, srcBranch);
 
 
 
 
 
 
1296 if( srcRid>0 && srcBranch!=branchId ){
1297 db_bind_int(&addRev, ":branch", branchId);
1298 db_step(&addRev);
1299 db_reset(&addRev);
1300 db_bind_int(&revSrc, ":parent", srcRid);
@@ -1273,11 +1305,11 @@
1305 }
1306 }
1307 if( zKind==0 ){
1308 fossil_fatal("Missing Node-kind");
1309 }else if( strncmp(zKind, "dir", 3)==0 ){
1310 if( zSrcPath ){
1311 if( srcRid>0 ){
1312 if( zSrcFile[0]==0 ){
1313 db_bind_text(&cpyRoot, ":path", zFile);
1314 db_bind_int(&cpyRoot, ":branch", branchId);
1315 db_bind_int(&cpyRoot, ":rid", srcRid);
@@ -1484,12 +1516,13 @@
1516 }else
1517 if( strncmp(g.argv[2], "svn", 3)==0 ){
1518 db_multi_exec(
1519 "CREATE TEMP TABLE xrevisions("
1520 " trev INTEGER, tbranch INT, trid INT, tparent INT DEFAULT 0,"
1521 " UNIQUE(tbranch, trev)"
1522 ");"
1523 "CREATE INDEX temp.i_xrevisions ON xrevisions(trid);"
1524 "CREATE TEMP TABLE xfiles("
1525 " tpath TEXT, tbranch INT, tuuid TEXT, tperm TEXT,"
1526 " UNIQUE (tbranch, tpath) ON CONFLICT REPLACE"
1527 ");"
1528 "CREATE TEMP TABLE xbranches("
1529

Keyboard Shortcuts

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