Fossil SCM

Started refactoring some of the timeline/artifact components into reusable parts.

stephan 2011-10-01 06:45 UTC json-multitag-test
Commit b1f9257213c4447b0a072e73f7845b43e85074cd
+1 -1
--- ajax/index.html
+++ ajax/index.html
@@ -220,11 +220,11 @@
220220
<input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
221221
<input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
222222
<input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{page:"Fossil"})' />
223223
<input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
224224
<input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
225
-<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=trunk")' />
225
+<input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
226226
227227
<!--
228228
<input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
229229
<input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
230230
<input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' />
231231
--- ajax/index.html
+++ ajax/index.html
@@ -220,11 +220,11 @@
220 <input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
221 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
222 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{page:"Fossil"})' />
223 <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
224 <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
225 <input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=trunk")' />
226
227 <!--
228 <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
229 <input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
230 <input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' />
231
--- ajax/index.html
+++ ajax/index.html
@@ -220,11 +220,11 @@
220 <input type='button' value='timeline/ticket' onclick='TheApp.cgi.sendCommand("/json/timeline/ticket")' />
221 <input type='button' value='wiki/list' onclick='TheApp.cgi.sendCommand("/json/wiki/list")' />
222 <input type='button' value='wiki/get Fossil' onclick='TheApp.cgi.sendCommand("/json/wiki/get",{page:"Fossil"})' />
223 <input type='button' value='user/list' onclick='TheApp.cgi.sendCommand("/json/user/list")' />
224 <input type='button' value='user/get' onclick='TheApp.cgi.sendCommand("/json/user/get?name=anonymous")' />
225 <input type='button' value='artifact/XYZ' onclick='TheApp.cgi.sendCommand("/json/artifact?uuid=json")' />
226
227 <!--
228 <input type='button' value='get whiki' onclick='TheApp.cgi.getPages("whiki")' />
229 <input type='button' value='get more' onclick='TheApp.cgi.getPages("HelloWorld/WhikiNews")' />
230 <input type='button' value='get client data' onclick='TheApp.cgi.getPageClientData("HelloWorld/whiki/WhikiCommands")' />
231
+33 -5
--- src/json.c
+++ src/json.c
@@ -827,14 +827,13 @@
827827
return rc;
828828
}
829829
830830
/*
831831
** Wrapper around json_string_split(), taking the same first 3
832
-** parameters as this function, but returns the results as
833
-** a JSON Array (if splitting produced tokens)
834
-** OR a JSON null value (if splitting produced no tokens)
835
-** OR NULL (if splitting failed in any way).
832
+** parameters as this function, but returns the results as a JSON
833
+** Array (if splitting produced tokens) or NULL (if splitting failed
834
+** in any way or produced no tokens).
836835
**
837836
** The returned value is owned by the caller. If not NULL then it
838837
** _will_ have a JSON type of Array or Null.
839838
*/
840839
cson_value * json_string_split2( char const * zStr,
@@ -843,17 +842,18 @@
843842
cson_value * v = cson_value_new_array();
844843
cson_array * a = cson_value_get_array(v);
845844
int rc = json_string_split( zStr, separator, doDeHttp, a );
846845
if( 0 == rc ){
847846
cson_value_free(v);
848
- v = cson_value_null();
847
+ v = NULL;
849848
}else if(rc<0){
850849
cson_value_free(v);
851850
v = NULL;
852851
}
853852
return v;
854853
}
854
+
855855
856856
/*
857857
** Performs some common initialization of JSON-related state. Must be
858858
** called by the json_page_top() and json_cmd_top() dispatching
859859
** functions to set up the JSON stat used by the dispatched functions.
@@ -1322,10 +1322,38 @@
13221322
if(warnMsg){
13231323
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg );
13241324
}
13251325
return v;
13261326
}
1327
+
1328
+
1329
+/*
1330
+** If the given rid has any tags associated with it, this function
1331
+** returns a JSON Array containing the tag names, else it returns
1332
+** NULL.
1333
+*/
1334
+cson_value * json_tags_for_rid(int rid){
1335
+ cson_value * v = NULL;
1336
+ Stmt q;
1337
+ assert((rid>0) && "rid is invalid");
1338
+ db_prepare(&q,"SELECT group_concat(substr(tagname,5), ',')"
1339
+ " FROM tag t, tagxref x "
1340
+ " WHERE x.rid=%d "
1341
+ " AND tagname GLOB 'sym-*' "
1342
+ " AND t.tagid=x.tagid AND x.tagtype>0",
1343
+ rid);
1344
+ if( (SQLITE_ROW==db_step(&q)) ){
1345
+ char const * tags;
1346
+ tags = db_column_text(&q,0);
1347
+ if(tags && *tags){
1348
+ v = json_string_split2(tags,',',0);
1349
+ }
1350
+ }
1351
+ db_finalize(&q);
1352
+ return v;
1353
+}
1354
+
13271355
13281356
/*
13291357
** /json/version implementation.
13301358
**
13311359
** Returns the payload object (owned by the caller).
13321360
--- src/json.c
+++ src/json.c
@@ -827,14 +827,13 @@
827 return rc;
828 }
829
830 /*
831 ** Wrapper around json_string_split(), taking the same first 3
832 ** parameters as this function, but returns the results as
833 ** a JSON Array (if splitting produced tokens)
834 ** OR a JSON null value (if splitting produced no tokens)
835 ** OR NULL (if splitting failed in any way).
836 **
837 ** The returned value is owned by the caller. If not NULL then it
838 ** _will_ have a JSON type of Array or Null.
839 */
840 cson_value * json_string_split2( char const * zStr,
@@ -843,17 +842,18 @@
843 cson_value * v = cson_value_new_array();
844 cson_array * a = cson_value_get_array(v);
845 int rc = json_string_split( zStr, separator, doDeHttp, a );
846 if( 0 == rc ){
847 cson_value_free(v);
848 v = cson_value_null();
849 }else if(rc<0){
850 cson_value_free(v);
851 v = NULL;
852 }
853 return v;
854 }
 
855
856 /*
857 ** Performs some common initialization of JSON-related state. Must be
858 ** called by the json_page_top() and json_cmd_top() dispatching
859 ** functions to set up the JSON stat used by the dispatched functions.
@@ -1322,10 +1322,38 @@
1322 if(warnMsg){
1323 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg );
1324 }
1325 return v;
1326 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1327
1328 /*
1329 ** /json/version implementation.
1330 **
1331 ** Returns the payload object (owned by the caller).
1332
--- src/json.c
+++ src/json.c
@@ -827,14 +827,13 @@
827 return rc;
828 }
829
830 /*
831 ** Wrapper around json_string_split(), taking the same first 3
832 ** parameters as this function, but returns the results as a JSON
833 ** Array (if splitting produced tokens) or NULL (if splitting failed
834 ** in any way or produced no tokens).
 
835 **
836 ** The returned value is owned by the caller. If not NULL then it
837 ** _will_ have a JSON type of Array or Null.
838 */
839 cson_value * json_string_split2( char const * zStr,
@@ -843,17 +842,18 @@
842 cson_value * v = cson_value_new_array();
843 cson_array * a = cson_value_get_array(v);
844 int rc = json_string_split( zStr, separator, doDeHttp, a );
845 if( 0 == rc ){
846 cson_value_free(v);
847 v = NULL;
848 }else if(rc<0){
849 cson_value_free(v);
850 v = NULL;
851 }
852 return v;
853 }
854
855
856 /*
857 ** Performs some common initialization of JSON-related state. Must be
858 ** called by the json_page_top() and json_cmd_top() dispatching
859 ** functions to set up the JSON stat used by the dispatched functions.
@@ -1322,10 +1322,38 @@
1322 if(warnMsg){
1323 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED, warnMsg );
1324 }
1325 return v;
1326 }
1327
1328
1329 /*
1330 ** If the given rid has any tags associated with it, this function
1331 ** returns a JSON Array containing the tag names, else it returns
1332 ** NULL.
1333 */
1334 cson_value * json_tags_for_rid(int rid){
1335 cson_value * v = NULL;
1336 Stmt q;
1337 assert((rid>0) && "rid is invalid");
1338 db_prepare(&q,"SELECT group_concat(substr(tagname,5), ',')"
1339 " FROM tag t, tagxref x "
1340 " WHERE x.rid=%d "
1341 " AND tagname GLOB 'sym-*' "
1342 " AND t.tagid=x.tagid AND x.tagtype>0",
1343 rid);
1344 if( (SQLITE_ROW==db_step(&q)) ){
1345 char const * tags;
1346 tags = db_column_text(&q,0);
1347 if(tags && *tags){
1348 v = json_string_split2(tags,',',0);
1349 }
1350 }
1351 db_finalize(&q);
1352 return v;
1353 }
1354
1355
1356 /*
1357 ** /json/version implementation.
1358 **
1359 ** Returns the payload object (owned by the caller).
1360
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -33,21 +33,17 @@
3333
3434
/*
3535
** Generates an artifact Object for the given rid/zUuid. rid
3636
** must refer to a Checkin.
3737
**
38
-**
39
-** TODO: consolidate the result structure (and its generation) with
40
-** /json/timeline/ci.
38
+** Returned value is NULL or an Object owned by the caller.
4139
*/
42
-static cson_value * json_artifact_ci( int rid, char const * zUuid ){
43
- cson_value * v = cson_value_new_object();
44
- cson_object * o = cson_value_get_object(v);
40
+cson_value * json_artifact_for_ci( int rid, char const * zUuid, char showFiles ){
4541
char const * zParent = NULL;
42
+ cson_value * v = NULL;
4643
Stmt q;
4744
assert( NULL != zUuid );
48
- cson_object_set(o,"isLeaf", cson_value_new_bool(is_a_leaf(rid)));
4945
zParent = db_text(0,
5046
"SELECT uuid FROM plink, blob"
5147
" WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
5248
rid
5349
);
@@ -59,18 +55,22 @@
5955
" WHERE blob.rid=%d"
6056
" AND event.objid=%d",
6157
rid, rid
6258
);
6359
if( db_step(&q)==SQLITE_ROW ){
60
+ cson_object * o;
61
+ cson_value * tmpV = NULL;
62
+ v = cson_value_new_object();
63
+ o = cson_value_get_object(v);
6464
/*const char *zUuid = db_column_text(&q, 0);*/
6565
char * zTmp;
6666
const char *zUser;
6767
const char *zComment;
6868
char * zEUser, * zEComment;
6969
int mtime, omtime;
70
- cson_value * fileList = NULL;
7170
#define SET(K,V) cson_object_set(o,(K), (V))
71
+ SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));
7272
SET("uuid",json_new_string(zUuid));
7373
zUser = db_column_text(&q,2);
7474
SET("user",json_new_string(zUser));
7575
zEUser = db_text(0,
7676
"SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
@@ -99,23 +99,34 @@
9999
100100
if(zParent){
101101
SET("parentUuid", json_new_string(zParent));
102102
}
103103
104
- fileList = json_timeline_get_changed_files(rid);
105
- if(fileList){
106
- SET("files",fileList);
104
+ if( showFiles ){
105
+ cson_value * fileList = json_timeline_get_changed_files(rid);
106
+ if(fileList){
107
+ SET("files",fileList);
108
+ }
109
+ }
110
+
111
+ tmpV = json_tags_for_rid(rid);
112
+ if(tmpV){
113
+ SET("tags",tmpV);
107114
}
108115
109116
#undef SET
110
- }else{
111
- cson_value_free(v);
112
- v = NULL;
113117
}
114118
db_finalize(&q);
115119
return v;
116120
}
121
+
122
+/*
123
+** Sub-impl of /json/artifact for checkins.
124
+*/
125
+static cson_value * json_artifact_ci( int rid, char const * zUuid ){
126
+ return json_artifact_for_ci(rid, zUuid, 1);
127
+}
117128
118129
static char perms_can_read(){
119130
return g.perm.Read ? 1 : 0;
120131
}
121132
122133
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -33,21 +33,17 @@
33
34 /*
35 ** Generates an artifact Object for the given rid/zUuid. rid
36 ** must refer to a Checkin.
37 **
38 **
39 ** TODO: consolidate the result structure (and its generation) with
40 ** /json/timeline/ci.
41 */
42 static cson_value * json_artifact_ci( int rid, char const * zUuid ){
43 cson_value * v = cson_value_new_object();
44 cson_object * o = cson_value_get_object(v);
45 char const * zParent = NULL;
 
46 Stmt q;
47 assert( NULL != zUuid );
48 cson_object_set(o,"isLeaf", cson_value_new_bool(is_a_leaf(rid)));
49 zParent = db_text(0,
50 "SELECT uuid FROM plink, blob"
51 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
52 rid
53 );
@@ -59,18 +55,22 @@
59 " WHERE blob.rid=%d"
60 " AND event.objid=%d",
61 rid, rid
62 );
63 if( db_step(&q)==SQLITE_ROW ){
 
 
 
 
64 /*const char *zUuid = db_column_text(&q, 0);*/
65 char * zTmp;
66 const char *zUser;
67 const char *zComment;
68 char * zEUser, * zEComment;
69 int mtime, omtime;
70 cson_value * fileList = NULL;
71 #define SET(K,V) cson_object_set(o,(K), (V))
 
72 SET("uuid",json_new_string(zUuid));
73 zUser = db_column_text(&q,2);
74 SET("user",json_new_string(zUser));
75 zEUser = db_text(0,
76 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
@@ -99,23 +99,34 @@
99
100 if(zParent){
101 SET("parentUuid", json_new_string(zParent));
102 }
103
104 fileList = json_timeline_get_changed_files(rid);
105 if(fileList){
106 SET("files",fileList);
 
 
 
 
 
 
 
107 }
108
109 #undef SET
110 }else{
111 cson_value_free(v);
112 v = NULL;
113 }
114 db_finalize(&q);
115 return v;
116 }
 
 
 
 
 
 
 
117
118 static char perms_can_read(){
119 return g.perm.Read ? 1 : 0;
120 }
121
122
--- src/json_artifact.c
+++ src/json_artifact.c
@@ -33,21 +33,17 @@
33
34 /*
35 ** Generates an artifact Object for the given rid/zUuid. rid
36 ** must refer to a Checkin.
37 **
38 ** Returned value is NULL or an Object owned by the caller.
 
 
39 */
40 cson_value * json_artifact_for_ci( int rid, char const * zUuid, char showFiles ){
 
 
41 char const * zParent = NULL;
42 cson_value * v = NULL;
43 Stmt q;
44 assert( NULL != zUuid );
 
45 zParent = db_text(0,
46 "SELECT uuid FROM plink, blob"
47 " WHERE plink.cid=%d AND blob.rid=plink.pid AND plink.isprim",
48 rid
49 );
@@ -59,18 +55,22 @@
55 " WHERE blob.rid=%d"
56 " AND event.objid=%d",
57 rid, rid
58 );
59 if( db_step(&q)==SQLITE_ROW ){
60 cson_object * o;
61 cson_value * tmpV = NULL;
62 v = cson_value_new_object();
63 o = cson_value_get_object(v);
64 /*const char *zUuid = db_column_text(&q, 0);*/
65 char * zTmp;
66 const char *zUser;
67 const char *zComment;
68 char * zEUser, * zEComment;
69 int mtime, omtime;
 
70 #define SET(K,V) cson_object_set(o,(K), (V))
71 SET("isLeaf", cson_value_new_bool(is_a_leaf(rid)));
72 SET("uuid",json_new_string(zUuid));
73 zUser = db_column_text(&q,2);
74 SET("user",json_new_string(zUser));
75 zEUser = db_text(0,
76 "SELECT value FROM tagxref WHERE tagid=%d AND rid=%d",
@@ -99,23 +99,34 @@
99
100 if(zParent){
101 SET("parentUuid", json_new_string(zParent));
102 }
103
104 if( showFiles ){
105 cson_value * fileList = json_timeline_get_changed_files(rid);
106 if(fileList){
107 SET("files",fileList);
108 }
109 }
110
111 tmpV = json_tags_for_rid(rid);
112 if(tmpV){
113 SET("tags",tmpV);
114 }
115
116 #undef SET
 
 
 
117 }
118 db_finalize(&q);
119 return v;
120 }
121
122 /*
123 ** Sub-impl of /json/artifact for checkins.
124 */
125 static cson_value * json_artifact_ci( int rid, char const * zUuid ){
126 return json_artifact_for_ci(rid, zUuid, 1);
127 }
128
129 static char perms_can_read(){
130 return g.perm.Read ? 1 : 0;
131 }
132
133
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -320,35 +320,22 @@
320320
while( (SQLITE_ROW == db_step(&q) )){
321321
/* convert each row into a JSON object...*/
322322
int const rid = db_column_int(&q,0);
323323
cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
324324
cson_object * row = cson_value_get_object(rowV);
325
- cson_string const * tagsStr = NULL;
325
+ cson_value * tagList = NULL;
326326
if(!row && !warnRowToJsonFailed){
327327
warnRowToJsonFailed = 1;
328328
json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
329329
"Could not convert at least one timeline result row to JSON." );
330330
continue;
331331
}
332332
/* Split tags string field into JSON Array... */
333333
cson_array_append(list, rowV);
334
- tagsStr = cson_value_get_string(cson_object_get(row,"tags"));
335
- if(tagsStr){
336
- cson_value * tags = json_string_split2( cson_string_cstr(tagsStr),
337
- ',', 0);
338
- if( tags ){
339
- if(0 != cson_object_set(row,"tags",tags)){
340
- cson_value_free(tags);
341
- }else{
342
- /*replaced/deleted old tags value, invalidating tagsStr*/;
343
- tagsStr = NULL;
344
- }
345
- }else if(!warnStringToArrayFailed){
346
- warnStringToArrayFailed = 1;
347
- json_warn(FSL_JSON_W_STRING_TO_ARRAY_FAILED,
348
- "Could not convert tags string to array.");
349
- }
334
+ tmp = json_tags_for_rid(rid);
335
+ if(tmp){
336
+ cson_object_set(row,"tags",tmp);
350337
}
351338
352339
/* replace isLeaf int w/ JSON bool */
353340
tmp = cson_object_get(row,"isLeaf");
354341
if(tmp && cson_value_is_integer(tmp)){
355342
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -320,35 +320,22 @@
320 while( (SQLITE_ROW == db_step(&q) )){
321 /* convert each row into a JSON object...*/
322 int const rid = db_column_int(&q,0);
323 cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
324 cson_object * row = cson_value_get_object(rowV);
325 cson_string const * tagsStr = NULL;
326 if(!row && !warnRowToJsonFailed){
327 warnRowToJsonFailed = 1;
328 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
329 "Could not convert at least one timeline result row to JSON." );
330 continue;
331 }
332 /* Split tags string field into JSON Array... */
333 cson_array_append(list, rowV);
334 tagsStr = cson_value_get_string(cson_object_get(row,"tags"));
335 if(tagsStr){
336 cson_value * tags = json_string_split2( cson_string_cstr(tagsStr),
337 ',', 0);
338 if( tags ){
339 if(0 != cson_object_set(row,"tags",tags)){
340 cson_value_free(tags);
341 }else{
342 /*replaced/deleted old tags value, invalidating tagsStr*/;
343 tagsStr = NULL;
344 }
345 }else if(!warnStringToArrayFailed){
346 warnStringToArrayFailed = 1;
347 json_warn(FSL_JSON_W_STRING_TO_ARRAY_FAILED,
348 "Could not convert tags string to array.");
349 }
350 }
351
352 /* replace isLeaf int w/ JSON bool */
353 tmp = cson_object_get(row,"isLeaf");
354 if(tmp && cson_value_is_integer(tmp)){
355
--- src/json_timeline.c
+++ src/json_timeline.c
@@ -320,35 +320,22 @@
320 while( (SQLITE_ROW == db_step(&q) )){
321 /* convert each row into a JSON object...*/
322 int const rid = db_column_int(&q,0);
323 cson_value * rowV = cson_sqlite3_row_to_object(q.pStmt);
324 cson_object * row = cson_value_get_object(rowV);
325 cson_value * tagList = NULL;
326 if(!row && !warnRowToJsonFailed){
327 warnRowToJsonFailed = 1;
328 json_warn( FSL_JSON_W_ROW_TO_JSON_FAILED,
329 "Could not convert at least one timeline result row to JSON." );
330 continue;
331 }
332 /* Split tags string field into JSON Array... */
333 cson_array_append(list, rowV);
334 tmp = json_tags_for_rid(rid);
335 if(tmp){
336 cson_object_set(row,"tags",tmp);
 
 
 
 
 
 
 
 
 
 
 
 
 
337 }
338
339 /* replace isLeaf int w/ JSON bool */
340 tmp = cson_object_get(row,"isLeaf");
341 if(tmp && cson_value_is_integer(tmp)){
342

Keyboard Shortcuts

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