Fossil SCM
Initial prototype of the /json/settings/get command/page, per discussion in [forum:04b7159d63d4abe4|forum post 04b7159d63d4abe4].
Commit
29e5bb008c83265847953816d21df3896578c019f02726b9c18356b611cbc6ac
Parent
c76b00197f5e0fc…
2 files changed
+1
+107
-5
+1
| --- src/json.c | ||
| +++ src/json.c | ||
| @@ -2247,10 +2247,11 @@ | ||
| 2247 | 2247 | {"logout",json_page_logout,0}, |
| 2248 | 2248 | {"query",json_page_query,0}, |
| 2249 | 2249 | {"rebuild",json_page_rebuild,0}, |
| 2250 | 2250 | {"report", json_page_report, 0}, |
| 2251 | 2251 | {"resultCodes", json_page_resultCodes,0}, |
| 2252 | +{"settings",json_page_settings,0}, | |
| 2252 | 2253 | {"stat",json_page_stat,0}, |
| 2253 | 2254 | {"status", json_page_status, 0}, |
| 2254 | 2255 | {"tag", json_page_tag,0}, |
| 2255 | 2256 | /*{"ticket", json_page_nyi,0},*/ |
| 2256 | 2257 | {"timeline", json_page_timeline,0}, |
| 2257 | 2258 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -2247,10 +2247,11 @@ | |
| 2247 | {"logout",json_page_logout,0}, |
| 2248 | {"query",json_page_query,0}, |
| 2249 | {"rebuild",json_page_rebuild,0}, |
| 2250 | {"report", json_page_report, 0}, |
| 2251 | {"resultCodes", json_page_resultCodes,0}, |
| 2252 | {"stat",json_page_stat,0}, |
| 2253 | {"status", json_page_status, 0}, |
| 2254 | {"tag", json_page_tag,0}, |
| 2255 | /*{"ticket", json_page_nyi,0},*/ |
| 2256 | {"timeline", json_page_timeline,0}, |
| 2257 |
| --- src/json.c | |
| +++ src/json.c | |
| @@ -2247,10 +2247,11 @@ | |
| 2247 | {"logout",json_page_logout,0}, |
| 2248 | {"query",json_page_query,0}, |
| 2249 | {"rebuild",json_page_rebuild,0}, |
| 2250 | {"report", json_page_report, 0}, |
| 2251 | {"resultCodes", json_page_resultCodes,0}, |
| 2252 | {"settings",json_page_settings,0}, |
| 2253 | {"stat",json_page_stat,0}, |
| 2254 | {"status", json_page_status, 0}, |
| 2255 | {"tag", json_page_tag,0}, |
| 2256 | /*{"ticket", json_page_nyi,0},*/ |
| 2257 | {"timeline", json_page_timeline,0}, |
| 2258 |
+107
-5
| --- src/json_config.c | ||
| +++ src/json_config.c | ||
| @@ -21,12 +21,12 @@ | ||
| 21 | 21 | |
| 22 | 22 | #if INTERFACE |
| 23 | 23 | #include "json_detail.h" |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | -static cson_value * json_config_get(); | |
| 27 | -static cson_value * json_config_save(); | |
| 26 | +static cson_value * json_config_get(void); | |
| 27 | +static cson_value * json_config_save(void); | |
| 28 | 28 | |
| 29 | 29 | /* |
| 30 | 30 | ** Mapping of /json/config/XXX commands/paths to callbacks. |
| 31 | 31 | */ |
| 32 | 32 | static const JsonPageDef JsonPageDefs_Config[] = { |
| @@ -34,18 +34,36 @@ | ||
| 34 | 34 | {"save", json_config_save, 0}, |
| 35 | 35 | /* Last entry MUST have a NULL name. */ |
| 36 | 36 | {NULL,NULL,0} |
| 37 | 37 | }; |
| 38 | 38 | |
| 39 | +static cson_value * json_settings_get(void); | |
| 40 | +/* | |
| 41 | +** Mapping of /json/settings/XXX commands/paths to callbacks. | |
| 42 | +*/ | |
| 43 | +static const JsonPageDef JsonPageDefs_Settings[] = { | |
| 44 | +{"get", json_settings_get, 0}, | |
| 45 | +/* Last entry MUST have a NULL name. */ | |
| 46 | +{NULL,NULL,0} | |
| 47 | +}; | |
| 48 | + | |
| 39 | 49 | |
| 40 | 50 | /* |
| 41 | 51 | ** Implements the /json/config family of pages/commands. |
| 42 | 52 | ** |
| 43 | 53 | */ |
| 44 | -cson_value * json_page_config(){ | |
| 54 | +cson_value * json_page_config(void){ | |
| 45 | 55 | return json_page_dispatch_helper(&JsonPageDefs_Config[0]); |
| 46 | 56 | } |
| 57 | + | |
| 58 | +/* | |
| 59 | +** Implements the /json/settings family of pages/commands. | |
| 60 | +** | |
| 61 | +*/ | |
| 62 | +cson_value * json_page_settings(void){ | |
| 63 | + return json_page_dispatch_helper(&JsonPageDefs_Settings[0]); | |
| 64 | +} | |
| 47 | 65 | |
| 48 | 66 | |
| 49 | 67 | /* |
| 50 | 68 | ** JSON-internal mapping of config options to config groups. This is |
| 51 | 69 | ** mostly a copy of the config options in configure.c, but that data |
| @@ -105,11 +123,11 @@ | ||
| 105 | 123 | |
| 106 | 124 | /* |
| 107 | 125 | ** Impl of /json/config/get. Requires setup rights. |
| 108 | 126 | ** |
| 109 | 127 | */ |
| 110 | -static cson_value * json_config_get(){ | |
| 128 | +static cson_value * json_config_get(void){ | |
| 111 | 129 | cson_object * pay = NULL; |
| 112 | 130 | Stmt q = empty_Stmt; |
| 113 | 131 | Blob sql = empty_blob; |
| 114 | 132 | char const * zName = NULL; |
| 115 | 133 | int confMask = 0; |
| @@ -181,10 +199,94 @@ | ||
| 181 | 199 | /* |
| 182 | 200 | ** Impl of /json/config/save. |
| 183 | 201 | ** |
| 184 | 202 | ** TODOs: |
| 185 | 203 | */ |
| 186 | -static cson_value * json_config_save(){ | |
| 204 | +static cson_value * json_config_save(void){ | |
| 187 | 205 | json_set_err(FSL_JSON_E_NYI, NULL); |
| 188 | 206 | return NULL; |
| 189 | 207 | } |
| 208 | + | |
| 209 | +/* | |
| 210 | +** Impl of /json/settings/get. | |
| 211 | +*/ | |
| 212 | +static cson_value * json_settings_get(void){ | |
| 213 | + cson_array * pay = cson_new_array(); | |
| 214 | + int nSetting, i; | |
| 215 | + const Setting *aSetting = setting_info(&nSetting); | |
| 216 | + Stmt q = empty_Stmt; | |
| 217 | + | |
| 218 | + if( !g.perm.Read ){ | |
| 219 | + json_set_err( FSL_JSON_E_DENIED, "Fetching settings requires 'o' access." ); | |
| 220 | + return NULL; | |
| 221 | + } | |
| 222 | + if( g.localOpen ){ | |
| 223 | + db_prepare(&q, | |
| 224 | + "SELECT 'checkout', value FROM vvar WHERE name=:name" | |
| 225 | + " UNION ALL " | |
| 226 | + "SELECT 'repo', value FROM config WHERE name=:name" | |
| 227 | + ); | |
| 228 | + }else{ | |
| 229 | + db_prepare(&q, | |
| 230 | + "SELECT 'repo', value FROM config WHERE name=:name" | |
| 231 | + ); | |
| 232 | + } | |
| 233 | + for(i=0; i<nSetting; ++i){ | |
| 234 | + const Setting *pSet = &aSetting[i]; | |
| 235 | + cson_object * jSet; | |
| 236 | + cson_value * pVal = 0, * pSrc = 0; | |
| 237 | + if( pSet->sensitive && !g.perm.Setup ){ | |
| 238 | + continue; | |
| 239 | + } | |
| 240 | + jSet = cson_new_object(); | |
| 241 | + cson_array_append(pay, cson_object_value(jSet)); | |
| 242 | + cson_object_set(jSet, "name", json_new_string(pSet->name)); | |
| 243 | + cson_object_set(jSet, "versionable", cson_value_new_bool(pSet->versionable)); | |
| 244 | + cson_object_set(jSet, "sensitive", cson_value_new_bool(pSet->sensitive)); | |
| 245 | + cson_object_set(jSet, "defaultValue", (pSet->def && pSet->def[0]) | |
| 246 | + ? json_new_string(pSet->def) | |
| 247 | + : cson_value_null()); | |
| 248 | + if( pSet->versionable ){ | |
| 249 | + /* Check to see if this is overridden by a versionable settings file */ | |
| 250 | + if( g.localOpen ){ | |
| 251 | + /* Pull value from a local .fossil-settings/X file, if one exists. */ | |
| 252 | + Blob versionedPathname; | |
| 253 | + blob_zero(&versionedPathname); | |
| 254 | + blob_appendf(&versionedPathname, "%s.fossil-settings/%s", | |
| 255 | + g.zLocalRoot, pSet->name); | |
| 256 | + if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ | |
| 257 | + Blob content; | |
| 258 | + blob_zero(&content); | |
| 259 | + blob_read_from_file(&content, blob_str(&versionedPathname), ExtFILE); | |
| 260 | + pSrc = json_new_string("versioned"); | |
| 261 | + pVal = json_new_string(blob_str(&content)); | |
| 262 | + blob_reset(&content); | |
| 263 | + } | |
| 264 | + blob_reset(&versionedPathname); | |
| 265 | + } | |
| 266 | + if( 0==pSrc ){ | |
| 267 | + /* | |
| 268 | + ** TODO? No checkout-local versioned setting found. We could | |
| 269 | + ** fish the file out of the repository but we'd need to make | |
| 270 | + ** an assumption about which branch to pull it from or require | |
| 271 | + ** the user to pass in a version. | |
| 272 | + */ | |
| 273 | + } | |
| 274 | + } | |
| 275 | + if( 0==pSrc ){ | |
| 276 | + /* We had no checkout-local value, so use the value from | |
| 277 | + ** repo.config. */ | |
| 278 | + db_bind_text(&q, ":name", pSet->name); | |
| 279 | + if( SQLITE_ROW==db_step(&q) ){ | |
| 280 | + pSrc = json_new_string(db_column_text(&q, 0)); | |
| 281 | + pVal = json_new_string(db_column_text(&q, 1)); | |
| 282 | + } | |
| 283 | + db_reset(&q); | |
| 284 | + } | |
| 285 | + cson_object_set(jSet, "valueSource", pSrc ? pSrc : cson_value_null()); | |
| 286 | + cson_object_set(jSet, "value", pVal ? pVal : cson_value_null()); | |
| 287 | + } | |
| 288 | + db_finalize(&q); | |
| 289 | + return cson_array_value(pay); | |
| 290 | +} | |
| 291 | + | |
| 190 | 292 | #endif /* FOSSIL_ENABLE_JSON */ |
| 191 | 293 |
| --- src/json_config.c | |
| +++ src/json_config.c | |
| @@ -21,12 +21,12 @@ | |
| 21 | |
| 22 | #if INTERFACE |
| 23 | #include "json_detail.h" |
| 24 | #endif |
| 25 | |
| 26 | static cson_value * json_config_get(); |
| 27 | static cson_value * json_config_save(); |
| 28 | |
| 29 | /* |
| 30 | ** Mapping of /json/config/XXX commands/paths to callbacks. |
| 31 | */ |
| 32 | static const JsonPageDef JsonPageDefs_Config[] = { |
| @@ -34,18 +34,36 @@ | |
| 34 | {"save", json_config_save, 0}, |
| 35 | /* Last entry MUST have a NULL name. */ |
| 36 | {NULL,NULL,0} |
| 37 | }; |
| 38 | |
| 39 | |
| 40 | /* |
| 41 | ** Implements the /json/config family of pages/commands. |
| 42 | ** |
| 43 | */ |
| 44 | cson_value * json_page_config(){ |
| 45 | return json_page_dispatch_helper(&JsonPageDefs_Config[0]); |
| 46 | } |
| 47 | |
| 48 | |
| 49 | /* |
| 50 | ** JSON-internal mapping of config options to config groups. This is |
| 51 | ** mostly a copy of the config options in configure.c, but that data |
| @@ -105,11 +123,11 @@ | |
| 105 | |
| 106 | /* |
| 107 | ** Impl of /json/config/get. Requires setup rights. |
| 108 | ** |
| 109 | */ |
| 110 | static cson_value * json_config_get(){ |
| 111 | cson_object * pay = NULL; |
| 112 | Stmt q = empty_Stmt; |
| 113 | Blob sql = empty_blob; |
| 114 | char const * zName = NULL; |
| 115 | int confMask = 0; |
| @@ -181,10 +199,94 @@ | |
| 181 | /* |
| 182 | ** Impl of /json/config/save. |
| 183 | ** |
| 184 | ** TODOs: |
| 185 | */ |
| 186 | static cson_value * json_config_save(){ |
| 187 | json_set_err(FSL_JSON_E_NYI, NULL); |
| 188 | return NULL; |
| 189 | } |
| 190 | #endif /* FOSSIL_ENABLE_JSON */ |
| 191 |
| --- src/json_config.c | |
| +++ src/json_config.c | |
| @@ -21,12 +21,12 @@ | |
| 21 | |
| 22 | #if INTERFACE |
| 23 | #include "json_detail.h" |
| 24 | #endif |
| 25 | |
| 26 | static cson_value * json_config_get(void); |
| 27 | static cson_value * json_config_save(void); |
| 28 | |
| 29 | /* |
| 30 | ** Mapping of /json/config/XXX commands/paths to callbacks. |
| 31 | */ |
| 32 | static const JsonPageDef JsonPageDefs_Config[] = { |
| @@ -34,18 +34,36 @@ | |
| 34 | {"save", json_config_save, 0}, |
| 35 | /* Last entry MUST have a NULL name. */ |
| 36 | {NULL,NULL,0} |
| 37 | }; |
| 38 | |
| 39 | static cson_value * json_settings_get(void); |
| 40 | /* |
| 41 | ** Mapping of /json/settings/XXX commands/paths to callbacks. |
| 42 | */ |
| 43 | static const JsonPageDef JsonPageDefs_Settings[] = { |
| 44 | {"get", json_settings_get, 0}, |
| 45 | /* Last entry MUST have a NULL name. */ |
| 46 | {NULL,NULL,0} |
| 47 | }; |
| 48 | |
| 49 | |
| 50 | /* |
| 51 | ** Implements the /json/config family of pages/commands. |
| 52 | ** |
| 53 | */ |
| 54 | cson_value * json_page_config(void){ |
| 55 | return json_page_dispatch_helper(&JsonPageDefs_Config[0]); |
| 56 | } |
| 57 | |
| 58 | /* |
| 59 | ** Implements the /json/settings family of pages/commands. |
| 60 | ** |
| 61 | */ |
| 62 | cson_value * json_page_settings(void){ |
| 63 | return json_page_dispatch_helper(&JsonPageDefs_Settings[0]); |
| 64 | } |
| 65 | |
| 66 | |
| 67 | /* |
| 68 | ** JSON-internal mapping of config options to config groups. This is |
| 69 | ** mostly a copy of the config options in configure.c, but that data |
| @@ -105,11 +123,11 @@ | |
| 123 | |
| 124 | /* |
| 125 | ** Impl of /json/config/get. Requires setup rights. |
| 126 | ** |
| 127 | */ |
| 128 | static cson_value * json_config_get(void){ |
| 129 | cson_object * pay = NULL; |
| 130 | Stmt q = empty_Stmt; |
| 131 | Blob sql = empty_blob; |
| 132 | char const * zName = NULL; |
| 133 | int confMask = 0; |
| @@ -181,10 +199,94 @@ | |
| 199 | /* |
| 200 | ** Impl of /json/config/save. |
| 201 | ** |
| 202 | ** TODOs: |
| 203 | */ |
| 204 | static cson_value * json_config_save(void){ |
| 205 | json_set_err(FSL_JSON_E_NYI, NULL); |
| 206 | return NULL; |
| 207 | } |
| 208 | |
| 209 | /* |
| 210 | ** Impl of /json/settings/get. |
| 211 | */ |
| 212 | static cson_value * json_settings_get(void){ |
| 213 | cson_array * pay = cson_new_array(); |
| 214 | int nSetting, i; |
| 215 | const Setting *aSetting = setting_info(&nSetting); |
| 216 | Stmt q = empty_Stmt; |
| 217 | |
| 218 | if( !g.perm.Read ){ |
| 219 | json_set_err( FSL_JSON_E_DENIED, "Fetching settings requires 'o' access." ); |
| 220 | return NULL; |
| 221 | } |
| 222 | if( g.localOpen ){ |
| 223 | db_prepare(&q, |
| 224 | "SELECT 'checkout', value FROM vvar WHERE name=:name" |
| 225 | " UNION ALL " |
| 226 | "SELECT 'repo', value FROM config WHERE name=:name" |
| 227 | ); |
| 228 | }else{ |
| 229 | db_prepare(&q, |
| 230 | "SELECT 'repo', value FROM config WHERE name=:name" |
| 231 | ); |
| 232 | } |
| 233 | for(i=0; i<nSetting; ++i){ |
| 234 | const Setting *pSet = &aSetting[i]; |
| 235 | cson_object * jSet; |
| 236 | cson_value * pVal = 0, * pSrc = 0; |
| 237 | if( pSet->sensitive && !g.perm.Setup ){ |
| 238 | continue; |
| 239 | } |
| 240 | jSet = cson_new_object(); |
| 241 | cson_array_append(pay, cson_object_value(jSet)); |
| 242 | cson_object_set(jSet, "name", json_new_string(pSet->name)); |
| 243 | cson_object_set(jSet, "versionable", cson_value_new_bool(pSet->versionable)); |
| 244 | cson_object_set(jSet, "sensitive", cson_value_new_bool(pSet->sensitive)); |
| 245 | cson_object_set(jSet, "defaultValue", (pSet->def && pSet->def[0]) |
| 246 | ? json_new_string(pSet->def) |
| 247 | : cson_value_null()); |
| 248 | if( pSet->versionable ){ |
| 249 | /* Check to see if this is overridden by a versionable settings file */ |
| 250 | if( g.localOpen ){ |
| 251 | /* Pull value from a local .fossil-settings/X file, if one exists. */ |
| 252 | Blob versionedPathname; |
| 253 | blob_zero(&versionedPathname); |
| 254 | blob_appendf(&versionedPathname, "%s.fossil-settings/%s", |
| 255 | g.zLocalRoot, pSet->name); |
| 256 | if( file_size(blob_str(&versionedPathname), ExtFILE)>=0 ){ |
| 257 | Blob content; |
| 258 | blob_zero(&content); |
| 259 | blob_read_from_file(&content, blob_str(&versionedPathname), ExtFILE); |
| 260 | pSrc = json_new_string("versioned"); |
| 261 | pVal = json_new_string(blob_str(&content)); |
| 262 | blob_reset(&content); |
| 263 | } |
| 264 | blob_reset(&versionedPathname); |
| 265 | } |
| 266 | if( 0==pSrc ){ |
| 267 | /* |
| 268 | ** TODO? No checkout-local versioned setting found. We could |
| 269 | ** fish the file out of the repository but we'd need to make |
| 270 | ** an assumption about which branch to pull it from or require |
| 271 | ** the user to pass in a version. |
| 272 | */ |
| 273 | } |
| 274 | } |
| 275 | if( 0==pSrc ){ |
| 276 | /* We had no checkout-local value, so use the value from |
| 277 | ** repo.config. */ |
| 278 | db_bind_text(&q, ":name", pSet->name); |
| 279 | if( SQLITE_ROW==db_step(&q) ){ |
| 280 | pSrc = json_new_string(db_column_text(&q, 0)); |
| 281 | pVal = json_new_string(db_column_text(&q, 1)); |
| 282 | } |
| 283 | db_reset(&q); |
| 284 | } |
| 285 | cson_object_set(jSet, "valueSource", pSrc ? pSrc : cson_value_null()); |
| 286 | cson_object_set(jSet, "value", pVal ? pVal : cson_value_null()); |
| 287 | } |
| 288 | db_finalize(&q); |
| 289 | return cson_array_value(pay); |
| 290 | } |
| 291 | |
| 292 | #endif /* FOSSIL_ENABLE_JSON */ |
| 293 |