Fossil SCM

Add new commands: test-var-list, test-var-get, and test-var-set. The original motivation was to make it easier to insert "css", "header", and "footer" values that people send in, but these commands seem useful for other kinds of experimentation. The are "test-*" commands because they are not intended to be accessed by ordinary users.

drh 2015-01-23 17:13 trunk
Commit 1e21dacecad2117f0b5286736e2045895704b340
1 file changed +191
--- src/configure.c
+++ src/configure.c
@@ -989,5 +989,196 @@
989989
fossil_fatal("METHOD should be one of:"
990990
" export import merge pull push reset");
991991
}
992992
configure_rebuild();
993993
}
994
+
995
+
996
+/*
997
+** COMMAND: test-var-list
998
+**
999
+** Usage: %fossil test-var-list ?PATTERN? ?--unset? ?--mtime?
1000
+**
1001
+** Show the content of the CONFIG table in a repository. If PATTERN is
1002
+** specified, then only show the entries that match that glob pattern.
1003
+** Last modification time is shown if the --mtime option is present.
1004
+**
1005
+** If the --unset option is included, then entries are deleted rather than
1006
+** being displayed. WARNING! This cannot be undone. Be sure you know what
1007
+** you are doing! The --unset option only works if there is a PATTERN.
1008
+** Probably you should run the command once without --unset to make sure
1009
+** you know exactly what is being deleted.
1010
+**
1011
+** If not in an open check-out, use the -R REPO option to specify a
1012
+** a repository.
1013
+*/
1014
+void test_var_list_cmd(void){
1015
+ Stmt q;
1016
+ int i, j;
1017
+ const char *zPattern = 0;
1018
+ int doUnset;
1019
+ int showMtime;
1020
+ Blob sql;
1021
+ Blob ans;
1022
+ unsigned char zTrans[1000];
1023
+
1024
+ doUnset = find_option("unset",0,0)!=0;
1025
+ showMtime = find_option("mtime",0,0)!=0;
1026
+ db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1027
+ verify_all_options();
1028
+ if( g.argc>=3 ){
1029
+ zPattern = g.argv[2];
1030
+ }
1031
+ blob_init(&sql,0,0);
1032
+ blob_appendf(&sql, "SELECT name, value, datetime(mtime,'unixepoch')"
1033
+ " FROM config");
1034
+ if( zPattern ){
1035
+ blob_appendf(&sql, " WHERE name GLOB %Q", zPattern);
1036
+ }
1037
+ if( showMtime ){
1038
+ blob_appendf(&sql, " ORDER BY mtime, name");
1039
+ }else{
1040
+ blob_appendf(&sql, " ORDER BY name");
1041
+ }
1042
+ db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/);
1043
+ blob_reset(&sql);
1044
+#define MX_VAL 40
1045
+#define MX_NM 28
1046
+#define MX_LONGNM 60
1047
+ while( db_step(&q)==SQLITE_ROW ){
1048
+ const char *zName = db_column_text(&q,0);
1049
+ int nName = db_column_bytes(&q,0);
1050
+ const char *zValue = db_column_text(&q,1);
1051
+ int szValue = db_column_bytes(&q,1);
1052
+ const char *zMTime = db_column_text(&q,2);
1053
+ for(i=j=0; j<MX_VAL && zValue[i]; i++){
1054
+ unsigned char c = (unsigned char)zValue[i];
1055
+ if( c>=' ' && c<='~' ){
1056
+ zTrans[j++] = c;
1057
+ }else{
1058
+ zTrans[j++] = '\\';
1059
+ if( c=='\n' ){
1060
+ zTrans[j++] = 'n';
1061
+ }else if( c=='\r' ){
1062
+ zTrans[j++] = 'r';
1063
+ }else if( c=='\t' ){
1064
+ zTrans[j++] = 't';
1065
+ }else{
1066
+ zTrans[j++] = '0' + ((c>>6)&7);
1067
+ zTrans[j++] = '0' + ((c>>3)&7);
1068
+ zTrans[j++] = '0' + (c&7);
1069
+ }
1070
+ }
1071
+ }
1072
+ zTrans[j] = 0;
1073
+ if( i<szValue ){
1074
+ sqlite3_snprintf(sizeof(zTrans)-j, (char*)zTrans+j, "...+%d", szValue-i);
1075
+ j += (int)strlen((char*)zTrans+j);
1076
+ }
1077
+ if( showMtime ){
1078
+ fossil_print("%s:%*s%s\n", zName, 58-nName, "", zMTime);
1079
+ }else if( nName<MX_NM-2 ){
1080
+ fossil_print("%s:%*s%s\n", zName, MX_NM-1-nName, "", zTrans);
1081
+ }else if( nName<MX_LONGNM-2 && j<10 ){
1082
+ fossil_print("%s:%*s%s\n", zName, MX_LONGNM-1-nName, "", zTrans);
1083
+ }else{
1084
+ fossil_print("%s:\n%*s%s\n", zName, MX_NM, "", zTrans);
1085
+ }
1086
+ }
1087
+ db_finalize(&q);
1088
+ if( zPattern && doUnset ){
1089
+ prompt_user("Delete all of the above? (y/N)? ", &ans);
1090
+ if( blob_str(&ans)[0]=='y' || blob_str(&ans)[0]=='Y' ){
1091
+ db_multi_exec("DELETE FROM config WHERE name GLOB %Q", zPattern);
1092
+ }
1093
+ blob_reset(&ans);
1094
+ }
1095
+}
1096
+
1097
+/*
1098
+** COMMAND: test-var-get
1099
+**
1100
+** Usage: %fossil test-var-get VAR ?FILE?
1101
+**
1102
+** Write the text of the VAR variable into FILE. If FILE is "-"
1103
+** or is omitted then output goes to standard output. VAR can be a
1104
+** GLOB pattern.
1105
+**
1106
+** If not in an open check-out, use the -R REPO option to specify a
1107
+** a repository.
1108
+*/
1109
+void test_var_get_cmd(void){
1110
+ const char *zVar;
1111
+ const char *zFile;
1112
+ int n;
1113
+ Blob x;
1114
+ db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1115
+ verify_all_options();
1116
+ if( g.argc<3 ){
1117
+ usage("VAR ?FILE?");
1118
+ }
1119
+ zVar = g.argv[2];
1120
+ zFile = g.argc>=4 ? g.argv[3] : "-";
1121
+ n = db_int(0, "SELECT count(*) FROM config WHERE name GLOB %Q", zVar);
1122
+ if( n==0 ){
1123
+ fossil_fatal("no match for %Q", zVar);
1124
+ }
1125
+ if( n>1 ){
1126
+ fossil_fatal("multiple matches: %s",
1127
+ db_text(0, "SELECT group_concat(quote(name),', ') FROM ("
1128
+ " SELECT name FROM config WHERE name GLOB %Q ORDER BY 1)",
1129
+ zVar));
1130
+ }
1131
+ blob_init(&x,0,0);
1132
+ db_blob(&x, "SELECT value FROM config WHERE name GLOB %Q", zVar);
1133
+ blob_write_to_file(&x, zFile);
1134
+}
1135
+
1136
+/*
1137
+** COMMAND: test-var-set
1138
+**
1139
+** Usage: %fossil test-var-set VAR ?VALUE? ?--file FILE?
1140
+**
1141
+** Store VALUE or the content of FILE (exactly one of which must be
1142
+** supplied) into variable VAR. Use a FILE of "-" to read from
1143
+** standard input.
1144
+**
1145
+** WARNING: changing the value of a variable can interfere with the
1146
+** operation of Fossil. Be sure you know what you are doing.
1147
+**
1148
+** Use "--blob FILE" instead of "--file FILE" to load a binary blob
1149
+** such as a GIF.
1150
+*/
1151
+void test_var_set_cmd(void){
1152
+ const char *zVar;
1153
+ const char *zFile;
1154
+ const char *zBlob;
1155
+ Blob x;
1156
+ Stmt ins;
1157
+ zFile = find_option("file",0,1);
1158
+ zBlob = find_option("blob",0,1);
1159
+ db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1160
+ verify_all_options();
1161
+ if( g.argc<3 || (zFile==0 && zBlob==0 && g.argc<4) ){
1162
+ usage("VAR ?VALUE? ?--file FILE?");
1163
+ }
1164
+ zVar = g.argv[2];
1165
+ if( zFile ){
1166
+ if( zBlob ) fossil_fatal("cannot do both --file or --blob");
1167
+ blob_read_from_file(&x, zFile);
1168
+ }else if( zBlob ){
1169
+ blob_read_from_file(&x, zBlob);
1170
+ }else{
1171
+ blob_init(&x,g.argv[3],-1);
1172
+ }
1173
+ db_prepare(&ins,
1174
+ "REPLACE INTO config(name,value,mtime)"
1175
+ "VALUES(%Q,:val,now())", zVar);
1176
+ if( zBlob ){
1177
+ db_bind_blob(&ins, ":val", &x);
1178
+ }else{
1179
+ db_bind_text(&ins, ":val", blob_str(&x));
1180
+ }
1181
+ db_step(&ins);
1182
+ db_finalize(&ins);
1183
+ blob_reset(&x);
1184
+}
9941185
--- src/configure.c
+++ src/configure.c
@@ -989,5 +989,196 @@
989 fossil_fatal("METHOD should be one of:"
990 " export import merge pull push reset");
991 }
992 configure_rebuild();
993 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
994
--- src/configure.c
+++ src/configure.c
@@ -989,5 +989,196 @@
989 fossil_fatal("METHOD should be one of:"
990 " export import merge pull push reset");
991 }
992 configure_rebuild();
993 }
994
995
996 /*
997 ** COMMAND: test-var-list
998 **
999 ** Usage: %fossil test-var-list ?PATTERN? ?--unset? ?--mtime?
1000 **
1001 ** Show the content of the CONFIG table in a repository. If PATTERN is
1002 ** specified, then only show the entries that match that glob pattern.
1003 ** Last modification time is shown if the --mtime option is present.
1004 **
1005 ** If the --unset option is included, then entries are deleted rather than
1006 ** being displayed. WARNING! This cannot be undone. Be sure you know what
1007 ** you are doing! The --unset option only works if there is a PATTERN.
1008 ** Probably you should run the command once without --unset to make sure
1009 ** you know exactly what is being deleted.
1010 **
1011 ** If not in an open check-out, use the -R REPO option to specify a
1012 ** a repository.
1013 */
1014 void test_var_list_cmd(void){
1015 Stmt q;
1016 int i, j;
1017 const char *zPattern = 0;
1018 int doUnset;
1019 int showMtime;
1020 Blob sql;
1021 Blob ans;
1022 unsigned char zTrans[1000];
1023
1024 doUnset = find_option("unset",0,0)!=0;
1025 showMtime = find_option("mtime",0,0)!=0;
1026 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1027 verify_all_options();
1028 if( g.argc>=3 ){
1029 zPattern = g.argv[2];
1030 }
1031 blob_init(&sql,0,0);
1032 blob_appendf(&sql, "SELECT name, value, datetime(mtime,'unixepoch')"
1033 " FROM config");
1034 if( zPattern ){
1035 blob_appendf(&sql, " WHERE name GLOB %Q", zPattern);
1036 }
1037 if( showMtime ){
1038 blob_appendf(&sql, " ORDER BY mtime, name");
1039 }else{
1040 blob_appendf(&sql, " ORDER BY name");
1041 }
1042 db_prepare(&q, "%s", blob_str(&sql)/*safe-for-%s*/);
1043 blob_reset(&sql);
1044 #define MX_VAL 40
1045 #define MX_NM 28
1046 #define MX_LONGNM 60
1047 while( db_step(&q)==SQLITE_ROW ){
1048 const char *zName = db_column_text(&q,0);
1049 int nName = db_column_bytes(&q,0);
1050 const char *zValue = db_column_text(&q,1);
1051 int szValue = db_column_bytes(&q,1);
1052 const char *zMTime = db_column_text(&q,2);
1053 for(i=j=0; j<MX_VAL && zValue[i]; i++){
1054 unsigned char c = (unsigned char)zValue[i];
1055 if( c>=' ' && c<='~' ){
1056 zTrans[j++] = c;
1057 }else{
1058 zTrans[j++] = '\\';
1059 if( c=='\n' ){
1060 zTrans[j++] = 'n';
1061 }else if( c=='\r' ){
1062 zTrans[j++] = 'r';
1063 }else if( c=='\t' ){
1064 zTrans[j++] = 't';
1065 }else{
1066 zTrans[j++] = '0' + ((c>>6)&7);
1067 zTrans[j++] = '0' + ((c>>3)&7);
1068 zTrans[j++] = '0' + (c&7);
1069 }
1070 }
1071 }
1072 zTrans[j] = 0;
1073 if( i<szValue ){
1074 sqlite3_snprintf(sizeof(zTrans)-j, (char*)zTrans+j, "...+%d", szValue-i);
1075 j += (int)strlen((char*)zTrans+j);
1076 }
1077 if( showMtime ){
1078 fossil_print("%s:%*s%s\n", zName, 58-nName, "", zMTime);
1079 }else if( nName<MX_NM-2 ){
1080 fossil_print("%s:%*s%s\n", zName, MX_NM-1-nName, "", zTrans);
1081 }else if( nName<MX_LONGNM-2 && j<10 ){
1082 fossil_print("%s:%*s%s\n", zName, MX_LONGNM-1-nName, "", zTrans);
1083 }else{
1084 fossil_print("%s:\n%*s%s\n", zName, MX_NM, "", zTrans);
1085 }
1086 }
1087 db_finalize(&q);
1088 if( zPattern && doUnset ){
1089 prompt_user("Delete all of the above? (y/N)? ", &ans);
1090 if( blob_str(&ans)[0]=='y' || blob_str(&ans)[0]=='Y' ){
1091 db_multi_exec("DELETE FROM config WHERE name GLOB %Q", zPattern);
1092 }
1093 blob_reset(&ans);
1094 }
1095 }
1096
1097 /*
1098 ** COMMAND: test-var-get
1099 **
1100 ** Usage: %fossil test-var-get VAR ?FILE?
1101 **
1102 ** Write the text of the VAR variable into FILE. If FILE is "-"
1103 ** or is omitted then output goes to standard output. VAR can be a
1104 ** GLOB pattern.
1105 **
1106 ** If not in an open check-out, use the -R REPO option to specify a
1107 ** a repository.
1108 */
1109 void test_var_get_cmd(void){
1110 const char *zVar;
1111 const char *zFile;
1112 int n;
1113 Blob x;
1114 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1115 verify_all_options();
1116 if( g.argc<3 ){
1117 usage("VAR ?FILE?");
1118 }
1119 zVar = g.argv[2];
1120 zFile = g.argc>=4 ? g.argv[3] : "-";
1121 n = db_int(0, "SELECT count(*) FROM config WHERE name GLOB %Q", zVar);
1122 if( n==0 ){
1123 fossil_fatal("no match for %Q", zVar);
1124 }
1125 if( n>1 ){
1126 fossil_fatal("multiple matches: %s",
1127 db_text(0, "SELECT group_concat(quote(name),', ') FROM ("
1128 " SELECT name FROM config WHERE name GLOB %Q ORDER BY 1)",
1129 zVar));
1130 }
1131 blob_init(&x,0,0);
1132 db_blob(&x, "SELECT value FROM config WHERE name GLOB %Q", zVar);
1133 blob_write_to_file(&x, zFile);
1134 }
1135
1136 /*
1137 ** COMMAND: test-var-set
1138 **
1139 ** Usage: %fossil test-var-set VAR ?VALUE? ?--file FILE?
1140 **
1141 ** Store VALUE or the content of FILE (exactly one of which must be
1142 ** supplied) into variable VAR. Use a FILE of "-" to read from
1143 ** standard input.
1144 **
1145 ** WARNING: changing the value of a variable can interfere with the
1146 ** operation of Fossil. Be sure you know what you are doing.
1147 **
1148 ** Use "--blob FILE" instead of "--file FILE" to load a binary blob
1149 ** such as a GIF.
1150 */
1151 void test_var_set_cmd(void){
1152 const char *zVar;
1153 const char *zFile;
1154 const char *zBlob;
1155 Blob x;
1156 Stmt ins;
1157 zFile = find_option("file",0,1);
1158 zBlob = find_option("blob",0,1);
1159 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
1160 verify_all_options();
1161 if( g.argc<3 || (zFile==0 && zBlob==0 && g.argc<4) ){
1162 usage("VAR ?VALUE? ?--file FILE?");
1163 }
1164 zVar = g.argv[2];
1165 if( zFile ){
1166 if( zBlob ) fossil_fatal("cannot do both --file or --blob");
1167 blob_read_from_file(&x, zFile);
1168 }else if( zBlob ){
1169 blob_read_from_file(&x, zBlob);
1170 }else{
1171 blob_init(&x,g.argv[3],-1);
1172 }
1173 db_prepare(&ins,
1174 "REPLACE INTO config(name,value,mtime)"
1175 "VALUES(%Q,:val,now())", zVar);
1176 if( zBlob ){
1177 db_bind_blob(&ins, ":val", &x);
1178 }else{
1179 db_bind_text(&ins, ":val", blob_str(&x));
1180 }
1181 db_step(&ins);
1182 db_finalize(&ins);
1183 blob_reset(&x);
1184 }
1185

Keyboard Shortcuts

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