Fossil SCM
Added /json/tag/add.
Commit
bd9d7ce2f6873871c06f75a074d466600830d19c
Parent
1088cf2107afaac…
2 files changed
+2
+84
-9
+2
| --- ajax/index.html | ||
| +++ ajax/index.html | ||
| @@ -235,10 +235,12 @@ | ||
| 235 | 235 | <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' /> |
| 236 | 236 | <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' /> |
| 237 | 237 | <input type='button' value='resultCodes' onclick='TheApp.cgi.sendCommand("/json/resultCodes")' /> |
| 238 | 238 | <input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' /> |
| 239 | 239 | <input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' /> |
| 240 | +<input type='button' value='tag/add' | |
| 241 | +onclick='TheApp.cgi.sendCommand("/json/tag/add",{name:"json-add-tag-test",checkin:"json",value:"tag test",propagate:false,raw:false})' /> | |
| 240 | 242 | <!-- not yet ready... |
| 241 | 243 | <input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' /> |
| 242 | 244 | --> |
| 243 | 245 | |
| 244 | 246 | <!-- |
| 245 | 247 |
| --- ajax/index.html | |
| +++ ajax/index.html | |
| @@ -235,10 +235,12 @@ | |
| 235 | <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' /> |
| 236 | <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' /> |
| 237 | <input type='button' value='resultCodes' onclick='TheApp.cgi.sendCommand("/json/resultCodes")' /> |
| 238 | <input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' /> |
| 239 | <input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' /> |
| 240 | <!-- not yet ready... |
| 241 | <input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' /> |
| 242 | --> |
| 243 | |
| 244 | <!-- |
| 245 |
| --- ajax/index.html | |
| +++ ajax/index.html | |
| @@ -235,10 +235,12 @@ | |
| 235 | <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' /> |
| 236 | <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' /> |
| 237 | <input type='button' value='resultCodes' onclick='TheApp.cgi.sendCommand("/json/resultCodes")' /> |
| 238 | <input type='button' value='tag/list' onclick='TheApp.cgi.sendCommand("/json/tag/list?includeTickets=false&raw=false")' /> |
| 239 | <input type='button' value='tag/list/json' onclick='TheApp.cgi.sendCommand("/json/tag/list/json?raw=false")' /> |
| 240 | <input type='button' value='tag/add' |
| 241 | onclick='TheApp.cgi.sendCommand("/json/tag/add",{name:"json-add-tag-test",checkin:"json",value:"tag test",propagate:false,raw:false})' /> |
| 242 | <!-- not yet ready... |
| 243 | <input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' /> |
| 244 | --> |
| 245 | |
| 246 | <!-- |
| 247 |
+84
-9
| --- src/json_tag.c | ||
| +++ src/json_tag.c | ||
| @@ -54,14 +54,85 @@ | ||
| 54 | 54 | static cson_value * json_tag_add(){ |
| 55 | 55 | cson_value * payV = NULL; |
| 56 | 56 | cson_object * pay = NULL; |
| 57 | 57 | char const * zName = NULL; |
| 58 | 58 | char const * zCheckin = NULL; |
| 59 | - char propagate = 0; | |
| 60 | - char raw = 0; | |
| 61 | - char const * zPrefix = NULL; /* raw ? "" : "sym-" */ | |
| 62 | - g.json.resultCode = FSL_JSON_E_NYI; | |
| 59 | + char fRaw = 0; | |
| 60 | + char fPropagate = 0; | |
| 61 | + char const * zValue = NULL; | |
| 62 | + const char *zPrefix = NULL; | |
| 63 | + | |
| 64 | + if( !g.perm.Write ){ | |
| 65 | + json_set_err(FSL_JSON_E_DENIED, | |
| 66 | + "Requires 'i' permissions."); | |
| 67 | + return NULL; | |
| 68 | + } | |
| 69 | + fRaw = json_find_option_bool("raw",NULL,NULL,0); | |
| 70 | + fPropagate = json_find_option_bool("propagate",NULL,NULL,0); | |
| 71 | + zName = json_find_option_cstr("name",NULL,NULL); | |
| 72 | + zPrefix = fRaw ? "" : "sym-"; | |
| 73 | + if(!zName || !*zName){ | |
| 74 | + if(!fossil_is_json()){ | |
| 75 | + zName = json_command_arg(3); | |
| 76 | + } | |
| 77 | + if(!zName || !*zName){ | |
| 78 | + json_set_err(FSL_JSON_E_MISSING_ARGS, | |
| 79 | + "'name' parameter is missing."); | |
| 80 | + return NULL; | |
| 81 | + } | |
| 82 | + } | |
| 83 | + | |
| 84 | + zCheckin = json_find_option_cstr("checkin",NULL,NULL); | |
| 85 | + if( !zCheckin ){ | |
| 86 | + if(!fossil_is_json()){ | |
| 87 | + zCheckin = json_command_arg(4); | |
| 88 | + } | |
| 89 | + if(!zCheckin || !*zCheckin){ | |
| 90 | + json_set_err(FSL_JSON_E_MISSING_ARGS, | |
| 91 | + "'checkin' parameter is missing."); | |
| 92 | + return NULL; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 96 | + | |
| 97 | + zValue = json_find_option_cstr("value",NULL,NULL); | |
| 98 | + if(!zValue && !fossil_is_json()){ | |
| 99 | + zValue = json_command_arg(5); | |
| 100 | + } | |
| 101 | + | |
| 102 | + db_begin_transaction(); | |
| 103 | + tag_add_artifact(zPrefix, zName, zCheckin, zValue, | |
| 104 | + 1+fPropagate,NULL/*DateOvrd*/,NULL/*UserOvrd*/); | |
| 105 | + db_end_transaction(0); | |
| 106 | + | |
| 107 | + payV = cson_value_new_object(); | |
| 108 | + pay = cson_value_get_object(payV); | |
| 109 | + cson_object_set(pay, "name", json_new_string(zName) ); | |
| 110 | + cson_object_set(pay, "value", (zValue&&*zValue) | |
| 111 | + ? json_new_string(zValue) | |
| 112 | + : cson_value_null()); | |
| 113 | + cson_object_set(pay, "propagate", cson_value_new_bool(fPropagate)); | |
| 114 | + cson_object_set(pay, "raw", cson_value_new_bool(fRaw)); | |
| 115 | + { | |
| 116 | + Blob uu = empty_blob; | |
| 117 | + blob_append(&uu, zName, -1); | |
| 118 | + int const rc = name_to_uuid(&uu, 9, "*"); | |
| 119 | + if(0!=rc){ | |
| 120 | + json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!"); | |
| 121 | + blob_reset(&uu); | |
| 122 | + goto error; | |
| 123 | + } | |
| 124 | + cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu))); | |
| 125 | + blob_reset(&uu); | |
| 126 | + } | |
| 127 | + | |
| 128 | + goto ok; | |
| 129 | + error: | |
| 130 | + assert( 0 != g.json.resultCode ); | |
| 131 | + cson_value_free(payV); | |
| 132 | + payV = NULL; | |
| 133 | + ok: | |
| 63 | 134 | return payV; |
| 64 | 135 | } |
| 65 | 136 | |
| 66 | 137 | |
| 67 | 138 | /* |
| @@ -176,16 +247,23 @@ | ||
| 176 | 247 | }else{/* all tags */ |
| 177 | 248 | /* Output format: |
| 178 | 249 | |
| 179 | 250 | RAW mode: |
| 180 | 251 | |
| 181 | - ["sym-tagname", "sym-tagname2",...] | |
| 252 | + ["tagname", "sym-tagname2",...] | |
| 182 | 253 | |
| 183 | 254 | Non-raw: |
| 184 | 255 | |
| 185 | 256 | ["tagname", "tagname2",...] |
| 186 | 257 | |
| 258 | + i don't really like the discrepancy in the format but this list | |
| 259 | + can get really long and (A) most tags don't have values, (B) i | |
| 260 | + don't want to bloat it more, and (C) cson_object_set() is O(N) | |
| 261 | + (N=current number of properties) because it uses an unsorted list | |
| 262 | + internally (for memory reasons), so this can slow down appreciably | |
| 263 | + on a long list. The culprit is really tkt- tags, as there is one | |
| 264 | + for each ticket (941 in the main fossil repo as of this writing). | |
| 187 | 265 | */ |
| 188 | 266 | Blob sql = empty_blob; |
| 189 | 267 | cson_value * arV = NULL; |
| 190 | 268 | cson_array * ar = NULL; |
| 191 | 269 | blob_append(&sql, |
| @@ -206,24 +284,21 @@ | ||
| 206 | 284 | while( SQLITE_ROW == db_step(&q) ){ |
| 207 | 285 | const char *zName = db_column_text(&q, 0); |
| 208 | 286 | if(NULL==arV){ |
| 209 | 287 | arV = cson_value_new_array(); |
| 210 | 288 | ar = cson_value_get_array(arV); |
| 211 | - tagsVal = arV; | |
| 212 | 289 | cson_object_set(pay, "tags", arV); |
| 290 | + tagsVal = arV; | |
| 213 | 291 | } |
| 214 | 292 | if(!fTicket && (0==strncmp(zName, "tkt-", 4))) continue; |
| 215 | 293 | else if( !fRaw && (0==strncmp(zName, "sym-", 4))){ |
| 216 | 294 | zName += 4; |
| 217 | 295 | assert( *zName ); |
| 218 | 296 | } |
| 219 | 297 | cson_array_append(ar, json_new_string(zName)); |
| 220 | 298 | } |
| 221 | 299 | db_finalize(&q); |
| 222 | - if( ! arV ){ | |
| 223 | - arV = cson_value_null(); | |
| 224 | - } | |
| 225 | 300 | } |
| 226 | 301 | |
| 227 | 302 | goto end; |
| 228 | 303 | error: |
| 229 | 304 | assert(0 != g.json.resultCode); |
| 230 | 305 |
| --- src/json_tag.c | |
| +++ src/json_tag.c | |
| @@ -54,14 +54,85 @@ | |
| 54 | static cson_value * json_tag_add(){ |
| 55 | cson_value * payV = NULL; |
| 56 | cson_object * pay = NULL; |
| 57 | char const * zName = NULL; |
| 58 | char const * zCheckin = NULL; |
| 59 | char propagate = 0; |
| 60 | char raw = 0; |
| 61 | char const * zPrefix = NULL; /* raw ? "" : "sym-" */ |
| 62 | g.json.resultCode = FSL_JSON_E_NYI; |
| 63 | return payV; |
| 64 | } |
| 65 | |
| 66 | |
| 67 | /* |
| @@ -176,16 +247,23 @@ | |
| 176 | }else{/* all tags */ |
| 177 | /* Output format: |
| 178 | |
| 179 | RAW mode: |
| 180 | |
| 181 | ["sym-tagname", "sym-tagname2",...] |
| 182 | |
| 183 | Non-raw: |
| 184 | |
| 185 | ["tagname", "tagname2",...] |
| 186 | |
| 187 | */ |
| 188 | Blob sql = empty_blob; |
| 189 | cson_value * arV = NULL; |
| 190 | cson_array * ar = NULL; |
| 191 | blob_append(&sql, |
| @@ -206,24 +284,21 @@ | |
| 206 | while( SQLITE_ROW == db_step(&q) ){ |
| 207 | const char *zName = db_column_text(&q, 0); |
| 208 | if(NULL==arV){ |
| 209 | arV = cson_value_new_array(); |
| 210 | ar = cson_value_get_array(arV); |
| 211 | tagsVal = arV; |
| 212 | cson_object_set(pay, "tags", arV); |
| 213 | } |
| 214 | if(!fTicket && (0==strncmp(zName, "tkt-", 4))) continue; |
| 215 | else if( !fRaw && (0==strncmp(zName, "sym-", 4))){ |
| 216 | zName += 4; |
| 217 | assert( *zName ); |
| 218 | } |
| 219 | cson_array_append(ar, json_new_string(zName)); |
| 220 | } |
| 221 | db_finalize(&q); |
| 222 | if( ! arV ){ |
| 223 | arV = cson_value_null(); |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | goto end; |
| 228 | error: |
| 229 | assert(0 != g.json.resultCode); |
| 230 |
| --- src/json_tag.c | |
| +++ src/json_tag.c | |
| @@ -54,14 +54,85 @@ | |
| 54 | static cson_value * json_tag_add(){ |
| 55 | cson_value * payV = NULL; |
| 56 | cson_object * pay = NULL; |
| 57 | char const * zName = NULL; |
| 58 | char const * zCheckin = NULL; |
| 59 | char fRaw = 0; |
| 60 | char fPropagate = 0; |
| 61 | char const * zValue = NULL; |
| 62 | const char *zPrefix = NULL; |
| 63 | |
| 64 | if( !g.perm.Write ){ |
| 65 | json_set_err(FSL_JSON_E_DENIED, |
| 66 | "Requires 'i' permissions."); |
| 67 | return NULL; |
| 68 | } |
| 69 | fRaw = json_find_option_bool("raw",NULL,NULL,0); |
| 70 | fPropagate = json_find_option_bool("propagate",NULL,NULL,0); |
| 71 | zName = json_find_option_cstr("name",NULL,NULL); |
| 72 | zPrefix = fRaw ? "" : "sym-"; |
| 73 | if(!zName || !*zName){ |
| 74 | if(!fossil_is_json()){ |
| 75 | zName = json_command_arg(3); |
| 76 | } |
| 77 | if(!zName || !*zName){ |
| 78 | json_set_err(FSL_JSON_E_MISSING_ARGS, |
| 79 | "'name' parameter is missing."); |
| 80 | return NULL; |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | zCheckin = json_find_option_cstr("checkin",NULL,NULL); |
| 85 | if( !zCheckin ){ |
| 86 | if(!fossil_is_json()){ |
| 87 | zCheckin = json_command_arg(4); |
| 88 | } |
| 89 | if(!zCheckin || !*zCheckin){ |
| 90 | json_set_err(FSL_JSON_E_MISSING_ARGS, |
| 91 | "'checkin' parameter is missing."); |
| 92 | return NULL; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | |
| 97 | zValue = json_find_option_cstr("value",NULL,NULL); |
| 98 | if(!zValue && !fossil_is_json()){ |
| 99 | zValue = json_command_arg(5); |
| 100 | } |
| 101 | |
| 102 | db_begin_transaction(); |
| 103 | tag_add_artifact(zPrefix, zName, zCheckin, zValue, |
| 104 | 1+fPropagate,NULL/*DateOvrd*/,NULL/*UserOvrd*/); |
| 105 | db_end_transaction(0); |
| 106 | |
| 107 | payV = cson_value_new_object(); |
| 108 | pay = cson_value_get_object(payV); |
| 109 | cson_object_set(pay, "name", json_new_string(zName) ); |
| 110 | cson_object_set(pay, "value", (zValue&&*zValue) |
| 111 | ? json_new_string(zValue) |
| 112 | : cson_value_null()); |
| 113 | cson_object_set(pay, "propagate", cson_value_new_bool(fPropagate)); |
| 114 | cson_object_set(pay, "raw", cson_value_new_bool(fRaw)); |
| 115 | { |
| 116 | Blob uu = empty_blob; |
| 117 | blob_append(&uu, zName, -1); |
| 118 | int const rc = name_to_uuid(&uu, 9, "*"); |
| 119 | if(0!=rc){ |
| 120 | json_set_err(FSL_JSON_E_UNKNOWN,"Could not convert name back to UUID!"); |
| 121 | blob_reset(&uu); |
| 122 | goto error; |
| 123 | } |
| 124 | cson_object_set(pay, "appliedTo", json_new_string(blob_buffer(&uu))); |
| 125 | blob_reset(&uu); |
| 126 | } |
| 127 | |
| 128 | goto ok; |
| 129 | error: |
| 130 | assert( 0 != g.json.resultCode ); |
| 131 | cson_value_free(payV); |
| 132 | payV = NULL; |
| 133 | ok: |
| 134 | return payV; |
| 135 | } |
| 136 | |
| 137 | |
| 138 | /* |
| @@ -176,16 +247,23 @@ | |
| 247 | }else{/* all tags */ |
| 248 | /* Output format: |
| 249 | |
| 250 | RAW mode: |
| 251 | |
| 252 | ["tagname", "sym-tagname2",...] |
| 253 | |
| 254 | Non-raw: |
| 255 | |
| 256 | ["tagname", "tagname2",...] |
| 257 | |
| 258 | i don't really like the discrepancy in the format but this list |
| 259 | can get really long and (A) most tags don't have values, (B) i |
| 260 | don't want to bloat it more, and (C) cson_object_set() is O(N) |
| 261 | (N=current number of properties) because it uses an unsorted list |
| 262 | internally (for memory reasons), so this can slow down appreciably |
| 263 | on a long list. The culprit is really tkt- tags, as there is one |
| 264 | for each ticket (941 in the main fossil repo as of this writing). |
| 265 | */ |
| 266 | Blob sql = empty_blob; |
| 267 | cson_value * arV = NULL; |
| 268 | cson_array * ar = NULL; |
| 269 | blob_append(&sql, |
| @@ -206,24 +284,21 @@ | |
| 284 | while( SQLITE_ROW == db_step(&q) ){ |
| 285 | const char *zName = db_column_text(&q, 0); |
| 286 | if(NULL==arV){ |
| 287 | arV = cson_value_new_array(); |
| 288 | ar = cson_value_get_array(arV); |
| 289 | cson_object_set(pay, "tags", arV); |
| 290 | tagsVal = arV; |
| 291 | } |
| 292 | if(!fTicket && (0==strncmp(zName, "tkt-", 4))) continue; |
| 293 | else if( !fRaw && (0==strncmp(zName, "sym-", 4))){ |
| 294 | zName += 4; |
| 295 | assert( *zName ); |
| 296 | } |
| 297 | cson_array_append(ar, json_new_string(zName)); |
| 298 | } |
| 299 | db_finalize(&q); |
| 300 | } |
| 301 | |
| 302 | goto end; |
| 303 | error: |
| 304 | assert(0 != g.json.resultCode); |
| 305 |