Fossil SCM
integrated wiki-keep-mimetype branch.
Commit
52d242a73be2d7d68f8cf5693481a95976995faf
Parent
f6d3b815136fc0f…
4 files changed
+5
-5
+11
-7
+42
-20
+42
-20
+5
-5
| --- src/json_artifact.c | ||
| +++ src/json_artifact.c | ||
| @@ -245,29 +245,29 @@ | ||
| 245 | 245 | ** If the "format" (CLI: -f) flag is set function returns the same as |
| 246 | 246 | ** json_wiki_get_content_format_flag(), else it returns true (non-0) |
| 247 | 247 | ** if either the includeContent (HTTP) or -content|-c boolean flags |
| 248 | 248 | ** (CLI) are set. |
| 249 | 249 | */ |
| 250 | -static char json_artifact_get_content_format_flag(){ | |
| 250 | +static int json_artifact_get_content_format_flag(){ | |
| 251 | 251 | enum { MagicValue = -9 }; |
| 252 | - char contentFormat = json_wiki_get_content_format_flag(MagicValue); | |
| 252 | + int contentFormat = json_wiki_get_content_format_flag(MagicValue); | |
| 253 | 253 | if(MagicValue == contentFormat){ |
| 254 | 254 | contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0; |
| 255 | 255 | } |
| 256 | 256 | return contentFormat; |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | -extern char json_wiki_get_content_format_flag( char defaultValue ) /* json_wiki.c */; | |
| 259 | +extern int json_wiki_get_content_format_flag( int defaultValue ) /* json_wiki.c */; | |
| 260 | 260 | |
| 261 | 261 | cson_value * json_artifact_wiki(cson_object * zParent, int rid){ |
| 262 | 262 | if( ! g.perm.RdWiki ){ |
| 263 | 263 | json_set_err(FSL_JSON_E_DENIED, |
| 264 | 264 | "Requires 'j' privileges."); |
| 265 | 265 | return NULL; |
| 266 | 266 | }else{ |
| 267 | 267 | enum { MagicValue = -9 }; |
| 268 | - char const contentFormat = json_artifact_get_content_format_flag(); | |
| 268 | + int const contentFormat = json_artifact_get_content_format_flag(); | |
| 269 | 269 | return json_get_wiki_page_by_rid(rid, contentFormat); |
| 270 | 270 | } |
| 271 | 271 | } |
| 272 | 272 | |
| 273 | 273 | /* |
| @@ -289,11 +289,11 @@ | ||
| 289 | 289 | |
| 290 | 290 | cson_value * json_artifact_file(cson_object * zParent, int rid){ |
| 291 | 291 | cson_object * pay = NULL; |
| 292 | 292 | Stmt q = empty_Stmt; |
| 293 | 293 | cson_array * checkin_arr = NULL; |
| 294 | - char contentFormat; | |
| 294 | + int contentFormat; | |
| 295 | 295 | i64 contentSize = -1; |
| 296 | 296 | char * parentUuid; |
| 297 | 297 | if( ! g.perm.Read ){ |
| 298 | 298 | json_set_err(FSL_JSON_E_DENIED, |
| 299 | 299 | "Requires 'o' privileges."); |
| 300 | 300 |
| --- src/json_artifact.c | |
| +++ src/json_artifact.c | |
| @@ -245,29 +245,29 @@ | |
| 245 | ** If the "format" (CLI: -f) flag is set function returns the same as |
| 246 | ** json_wiki_get_content_format_flag(), else it returns true (non-0) |
| 247 | ** if either the includeContent (HTTP) or -content|-c boolean flags |
| 248 | ** (CLI) are set. |
| 249 | */ |
| 250 | static char json_artifact_get_content_format_flag(){ |
| 251 | enum { MagicValue = -9 }; |
| 252 | char contentFormat = json_wiki_get_content_format_flag(MagicValue); |
| 253 | if(MagicValue == contentFormat){ |
| 254 | contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0; |
| 255 | } |
| 256 | return contentFormat; |
| 257 | } |
| 258 | |
| 259 | extern char json_wiki_get_content_format_flag( char defaultValue ) /* json_wiki.c */; |
| 260 | |
| 261 | cson_value * json_artifact_wiki(cson_object * zParent, int rid){ |
| 262 | if( ! g.perm.RdWiki ){ |
| 263 | json_set_err(FSL_JSON_E_DENIED, |
| 264 | "Requires 'j' privileges."); |
| 265 | return NULL; |
| 266 | }else{ |
| 267 | enum { MagicValue = -9 }; |
| 268 | char const contentFormat = json_artifact_get_content_format_flag(); |
| 269 | return json_get_wiki_page_by_rid(rid, contentFormat); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | /* |
| @@ -289,11 +289,11 @@ | |
| 289 | |
| 290 | cson_value * json_artifact_file(cson_object * zParent, int rid){ |
| 291 | cson_object * pay = NULL; |
| 292 | Stmt q = empty_Stmt; |
| 293 | cson_array * checkin_arr = NULL; |
| 294 | char contentFormat; |
| 295 | i64 contentSize = -1; |
| 296 | char * parentUuid; |
| 297 | if( ! g.perm.Read ){ |
| 298 | json_set_err(FSL_JSON_E_DENIED, |
| 299 | "Requires 'o' privileges."); |
| 300 |
| --- src/json_artifact.c | |
| +++ src/json_artifact.c | |
| @@ -245,29 +245,29 @@ | |
| 245 | ** If the "format" (CLI: -f) flag is set function returns the same as |
| 246 | ** json_wiki_get_content_format_flag(), else it returns true (non-0) |
| 247 | ** if either the includeContent (HTTP) or -content|-c boolean flags |
| 248 | ** (CLI) are set. |
| 249 | */ |
| 250 | static int json_artifact_get_content_format_flag(){ |
| 251 | enum { MagicValue = -9 }; |
| 252 | int contentFormat = json_wiki_get_content_format_flag(MagicValue); |
| 253 | if(MagicValue == contentFormat){ |
| 254 | contentFormat = json_find_option_bool("includeContent","content","c",0) /* deprecated */ ? -1 : 0; |
| 255 | } |
| 256 | return contentFormat; |
| 257 | } |
| 258 | |
| 259 | extern int json_wiki_get_content_format_flag( int defaultValue ) /* json_wiki.c */; |
| 260 | |
| 261 | cson_value * json_artifact_wiki(cson_object * zParent, int rid){ |
| 262 | if( ! g.perm.RdWiki ){ |
| 263 | json_set_err(FSL_JSON_E_DENIED, |
| 264 | "Requires 'j' privileges."); |
| 265 | return NULL; |
| 266 | }else{ |
| 267 | enum { MagicValue = -9 }; |
| 268 | int const contentFormat = json_artifact_get_content_format_flag(); |
| 269 | return json_get_wiki_page_by_rid(rid, contentFormat); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | /* |
| @@ -289,11 +289,11 @@ | |
| 289 | |
| 290 | cson_value * json_artifact_file(cson_object * zParent, int rid){ |
| 291 | cson_object * pay = NULL; |
| 292 | Stmt q = empty_Stmt; |
| 293 | cson_array * checkin_arr = NULL; |
| 294 | int contentFormat; |
| 295 | i64 contentSize = -1; |
| 296 | char * parentUuid; |
| 297 | if( ! g.perm.Read ){ |
| 298 | json_set_err(FSL_JSON_E_DENIED, |
| 299 | "Requires 'o' privileges."); |
| 300 |
+11
-7
| --- src/json_wiki.c | ||
| +++ src/json_wiki.c | ||
| @@ -80,11 +80,11 @@ | ||
| 80 | 80 | ** the page. |
| 81 | 81 | ** |
| 82 | 82 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 83 | 83 | ** caller. If it returns NULL then it may set g.json's error state. |
| 84 | 84 | */ |
| 85 | -cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ | |
| 85 | +cson_value * json_get_wiki_page_by_rid(int rid, int contentFormat){ | |
| 86 | 86 | Manifest * pWiki = NULL; |
| 87 | 87 | if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){ |
| 88 | 88 | json_set_err( FSL_JSON_E_UNKNOWN, |
| 89 | 89 | "Error reading wiki page from manifest (rid=%d).", |
| 90 | 90 | rid ); |
| @@ -145,11 +145,11 @@ | ||
| 145 | 145 | /* |
| 146 | 146 | ** Searches for the latest version of a wiki page with the given |
| 147 | 147 | ** name. If found it behaves like json_get_wiki_page_by_rid(theRid, |
| 148 | 148 | ** contentFormat), else it returns NULL. |
| 149 | 149 | */ |
| 150 | -cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){ | |
| 150 | +cson_value * json_get_wiki_page_by_name(char const * zPageName, int contentFormat){ | |
| 151 | 151 | int rid; |
| 152 | 152 | rid = db_int(0, |
| 153 | 153 | "SELECT x.rid FROM tag t, tagxref x, blob b" |
| 154 | 154 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' " |
| 155 | 155 | " AND b.rid=x.rid" |
| @@ -175,12 +175,12 @@ | ||
| 175 | 175 | ** [r]aw = -1 |
| 176 | 176 | ** |
| 177 | 177 | ** The return value is intended for use with |
| 178 | 178 | ** json_get_wiki_page_by_rid() and friends. |
| 179 | 179 | */ |
| 180 | -char json_wiki_get_content_format_flag( char defaultValue ){ | |
| 181 | - char contentFormat = defaultValue; | |
| 180 | +int json_wiki_get_content_format_flag( int defaultValue ){ | |
| 181 | + int contentFormat = defaultValue; | |
| 182 | 182 | char const * zFormat = json_find_option_cstr("format",NULL,"f"); |
| 183 | 183 | if( !zFormat || !*zFormat ){ |
| 184 | 184 | return contentFormat; |
| 185 | 185 | } |
| 186 | 186 | else if('r'==*zFormat){ |
| @@ -203,11 +203,11 @@ | ||
| 203 | 203 | ** json_get_wiki_page_by_name() will be returned (owned by the |
| 204 | 204 | ** caller). On error g.json's error state is set and NULL is returned. |
| 205 | 205 | */ |
| 206 | 206 | static cson_value * json_wiki_get_by_name_or_symname(char const * zPageName, |
| 207 | 207 | char const * zSymname, |
| 208 | - char contentFormat ){ | |
| 208 | + int contentFormat ){ | |
| 209 | 209 | if(!zSymname || !*zSymname){ |
| 210 | 210 | return json_get_wiki_page_by_name(zPageName, contentFormat); |
| 211 | 211 | }else{ |
| 212 | 212 | int rid = symbolic_name_to_rid( zSymname ? zSymname : zPageName, "w" ); |
| 213 | 213 | if(rid<0){ |
| @@ -229,11 +229,11 @@ | ||
| 229 | 229 | ** |
| 230 | 230 | */ |
| 231 | 231 | static cson_value * json_wiki_get(){ |
| 232 | 232 | char const * zPageName; |
| 233 | 233 | char const * zSymName = NULL; |
| 234 | - char contentFormat = -1; | |
| 234 | + int contentFormat = -1; | |
| 235 | 235 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 236 | 236 | json_set_err(FSL_JSON_E_DENIED, |
| 237 | 237 | "Requires 'o' or 'j' access."); |
| 238 | 238 | return NULL; |
| 239 | 239 | } |
| @@ -308,10 +308,11 @@ | ||
| 308 | 308 | char const * zPageName; /* cstr form of page name */ |
| 309 | 309 | cson_value * contentV; /* passed-in content */ |
| 310 | 310 | cson_value * emptyContent = NULL; /* placeholder for empty content. */ |
| 311 | 311 | cson_value * payV = NULL; /* payload/return value */ |
| 312 | 312 | cson_string const * jstr = NULL; /* temp for cson_value-to-cson_string conversions. */ |
| 313 | + char const * zMimeType = 0; | |
| 313 | 314 | unsigned int contentLen = 0; |
| 314 | 315 | int rid; |
| 315 | 316 | if( (createMode && !g.perm.NewWiki) |
| 316 | 317 | || (!createMode && !g.perm.WrWiki)){ |
| 317 | 318 | json_set_err(FSL_JSON_E_DENIED, |
| @@ -371,11 +372,14 @@ | ||
| 371 | 372 | jstr = cson_value_get_string(contentV); |
| 372 | 373 | contentLen = (int)cson_string_length_bytes(jstr); |
| 373 | 374 | if(contentLen){ |
| 374 | 375 | blob_append(&content, cson_string_cstr(jstr),contentLen); |
| 375 | 376 | } |
| 376 | - wiki_cmd_commit(zPageName, 0==rid, &content); | |
| 377 | + | |
| 378 | + zMimeType = json_find_option_cstr("mimetype","mimetype","M"); | |
| 379 | + | |
| 380 | + wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType); | |
| 377 | 381 | blob_reset(&content); |
| 378 | 382 | /* |
| 379 | 383 | Our return value here has a race condition: if this operation |
| 380 | 384 | is called concurrently for the same wiki page via two requests, |
| 381 | 385 | payV could reflect the results of the other save operation. |
| 382 | 386 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -80,11 +80,11 @@ | |
| 80 | ** the page. |
| 81 | ** |
| 82 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 83 | ** caller. If it returns NULL then it may set g.json's error state. |
| 84 | */ |
| 85 | cson_value * json_get_wiki_page_by_rid(int rid, char contentFormat){ |
| 86 | Manifest * pWiki = NULL; |
| 87 | if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){ |
| 88 | json_set_err( FSL_JSON_E_UNKNOWN, |
| 89 | "Error reading wiki page from manifest (rid=%d).", |
| 90 | rid ); |
| @@ -145,11 +145,11 @@ | |
| 145 | /* |
| 146 | ** Searches for the latest version of a wiki page with the given |
| 147 | ** name. If found it behaves like json_get_wiki_page_by_rid(theRid, |
| 148 | ** contentFormat), else it returns NULL. |
| 149 | */ |
| 150 | cson_value * json_get_wiki_page_by_name(char const * zPageName, char contentFormat){ |
| 151 | int rid; |
| 152 | rid = db_int(0, |
| 153 | "SELECT x.rid FROM tag t, tagxref x, blob b" |
| 154 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' " |
| 155 | " AND b.rid=x.rid" |
| @@ -175,12 +175,12 @@ | |
| 175 | ** [r]aw = -1 |
| 176 | ** |
| 177 | ** The return value is intended for use with |
| 178 | ** json_get_wiki_page_by_rid() and friends. |
| 179 | */ |
| 180 | char json_wiki_get_content_format_flag( char defaultValue ){ |
| 181 | char contentFormat = defaultValue; |
| 182 | char const * zFormat = json_find_option_cstr("format",NULL,"f"); |
| 183 | if( !zFormat || !*zFormat ){ |
| 184 | return contentFormat; |
| 185 | } |
| 186 | else if('r'==*zFormat){ |
| @@ -203,11 +203,11 @@ | |
| 203 | ** json_get_wiki_page_by_name() will be returned (owned by the |
| 204 | ** caller). On error g.json's error state is set and NULL is returned. |
| 205 | */ |
| 206 | static cson_value * json_wiki_get_by_name_or_symname(char const * zPageName, |
| 207 | char const * zSymname, |
| 208 | char contentFormat ){ |
| 209 | if(!zSymname || !*zSymname){ |
| 210 | return json_get_wiki_page_by_name(zPageName, contentFormat); |
| 211 | }else{ |
| 212 | int rid = symbolic_name_to_rid( zSymname ? zSymname : zPageName, "w" ); |
| 213 | if(rid<0){ |
| @@ -229,11 +229,11 @@ | |
| 229 | ** |
| 230 | */ |
| 231 | static cson_value * json_wiki_get(){ |
| 232 | char const * zPageName; |
| 233 | char const * zSymName = NULL; |
| 234 | char contentFormat = -1; |
| 235 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 236 | json_set_err(FSL_JSON_E_DENIED, |
| 237 | "Requires 'o' or 'j' access."); |
| 238 | return NULL; |
| 239 | } |
| @@ -308,10 +308,11 @@ | |
| 308 | char const * zPageName; /* cstr form of page name */ |
| 309 | cson_value * contentV; /* passed-in content */ |
| 310 | cson_value * emptyContent = NULL; /* placeholder for empty content. */ |
| 311 | cson_value * payV = NULL; /* payload/return value */ |
| 312 | cson_string const * jstr = NULL; /* temp for cson_value-to-cson_string conversions. */ |
| 313 | unsigned int contentLen = 0; |
| 314 | int rid; |
| 315 | if( (createMode && !g.perm.NewWiki) |
| 316 | || (!createMode && !g.perm.WrWiki)){ |
| 317 | json_set_err(FSL_JSON_E_DENIED, |
| @@ -371,11 +372,14 @@ | |
| 371 | jstr = cson_value_get_string(contentV); |
| 372 | contentLen = (int)cson_string_length_bytes(jstr); |
| 373 | if(contentLen){ |
| 374 | blob_append(&content, cson_string_cstr(jstr),contentLen); |
| 375 | } |
| 376 | wiki_cmd_commit(zPageName, 0==rid, &content); |
| 377 | blob_reset(&content); |
| 378 | /* |
| 379 | Our return value here has a race condition: if this operation |
| 380 | is called concurrently for the same wiki page via two requests, |
| 381 | payV could reflect the results of the other save operation. |
| 382 |
| --- src/json_wiki.c | |
| +++ src/json_wiki.c | |
| @@ -80,11 +80,11 @@ | |
| 80 | ** the page. |
| 81 | ** |
| 82 | ** The returned value, if not NULL, is-a JSON Object owned by the |
| 83 | ** caller. If it returns NULL then it may set g.json's error state. |
| 84 | */ |
| 85 | cson_value * json_get_wiki_page_by_rid(int rid, int contentFormat){ |
| 86 | Manifest * pWiki = NULL; |
| 87 | if( NULL == (pWiki = manifest_get(rid, CFTYPE_WIKI, 0)) ){ |
| 88 | json_set_err( FSL_JSON_E_UNKNOWN, |
| 89 | "Error reading wiki page from manifest (rid=%d).", |
| 90 | rid ); |
| @@ -145,11 +145,11 @@ | |
| 145 | /* |
| 146 | ** Searches for the latest version of a wiki page with the given |
| 147 | ** name. If found it behaves like json_get_wiki_page_by_rid(theRid, |
| 148 | ** contentFormat), else it returns NULL. |
| 149 | */ |
| 150 | cson_value * json_get_wiki_page_by_name(char const * zPageName, int contentFormat){ |
| 151 | int rid; |
| 152 | rid = db_int(0, |
| 153 | "SELECT x.rid FROM tag t, tagxref x, blob b" |
| 154 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q' " |
| 155 | " AND b.rid=x.rid" |
| @@ -175,12 +175,12 @@ | |
| 175 | ** [r]aw = -1 |
| 176 | ** |
| 177 | ** The return value is intended for use with |
| 178 | ** json_get_wiki_page_by_rid() and friends. |
| 179 | */ |
| 180 | int json_wiki_get_content_format_flag( int defaultValue ){ |
| 181 | int contentFormat = defaultValue; |
| 182 | char const * zFormat = json_find_option_cstr("format",NULL,"f"); |
| 183 | if( !zFormat || !*zFormat ){ |
| 184 | return contentFormat; |
| 185 | } |
| 186 | else if('r'==*zFormat){ |
| @@ -203,11 +203,11 @@ | |
| 203 | ** json_get_wiki_page_by_name() will be returned (owned by the |
| 204 | ** caller). On error g.json's error state is set and NULL is returned. |
| 205 | */ |
| 206 | static cson_value * json_wiki_get_by_name_or_symname(char const * zPageName, |
| 207 | char const * zSymname, |
| 208 | int contentFormat ){ |
| 209 | if(!zSymname || !*zSymname){ |
| 210 | return json_get_wiki_page_by_name(zPageName, contentFormat); |
| 211 | }else{ |
| 212 | int rid = symbolic_name_to_rid( zSymname ? zSymname : zPageName, "w" ); |
| 213 | if(rid<0){ |
| @@ -229,11 +229,11 @@ | |
| 229 | ** |
| 230 | */ |
| 231 | static cson_value * json_wiki_get(){ |
| 232 | char const * zPageName; |
| 233 | char const * zSymName = NULL; |
| 234 | int contentFormat = -1; |
| 235 | if( !g.perm.RdWiki && !g.perm.Read ){ |
| 236 | json_set_err(FSL_JSON_E_DENIED, |
| 237 | "Requires 'o' or 'j' access."); |
| 238 | return NULL; |
| 239 | } |
| @@ -308,10 +308,11 @@ | |
| 308 | char const * zPageName; /* cstr form of page name */ |
| 309 | cson_value * contentV; /* passed-in content */ |
| 310 | cson_value * emptyContent = NULL; /* placeholder for empty content. */ |
| 311 | cson_value * payV = NULL; /* payload/return value */ |
| 312 | cson_string const * jstr = NULL; /* temp for cson_value-to-cson_string conversions. */ |
| 313 | char const * zMimeType = 0; |
| 314 | unsigned int contentLen = 0; |
| 315 | int rid; |
| 316 | if( (createMode && !g.perm.NewWiki) |
| 317 | || (!createMode && !g.perm.WrWiki)){ |
| 318 | json_set_err(FSL_JSON_E_DENIED, |
| @@ -371,11 +372,14 @@ | |
| 372 | jstr = cson_value_get_string(contentV); |
| 373 | contentLen = (int)cson_string_length_bytes(jstr); |
| 374 | if(contentLen){ |
| 375 | blob_append(&content, cson_string_cstr(jstr),contentLen); |
| 376 | } |
| 377 | |
| 378 | zMimeType = json_find_option_cstr("mimetype","mimetype","M"); |
| 379 | |
| 380 | wiki_cmd_commit(zPageName, 0==rid, &content, zMimeType); |
| 381 | blob_reset(&content); |
| 382 | /* |
| 383 | Our return value here has a race condition: if this operation |
| 384 | is called concurrently for the same wiki page via two requests, |
| 385 | payV could reflect the results of the other save operation. |
| 386 |
+42
-20
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -955,18 +955,23 @@ | ||
| 955 | 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | 957 | ** and isNew is false, then this routine throws an error. |
| 958 | 958 | ** |
| 959 | 959 | ** The content of the new page is given by the blob pContent. |
| 960 | +** | |
| 961 | +** zMimeType specifies the N-card for the wiki page. If it is 0, | |
| 962 | +** empty, or "text/x-fossil-wiki" (the default format) then it is | |
| 963 | +** ignored. | |
| 960 | 964 | */ |
| 961 | -int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent){ | |
| 965 | +int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent, | |
| 966 | + char const * zMimeType){ | |
| 962 | 967 | Blob wiki; /* Wiki page content */ |
| 963 | 968 | Blob cksum; /* wiki checksum */ |
| 964 | 969 | int rid; /* artifact ID of parent page */ |
| 965 | 970 | char *zDate; /* timestamp */ |
| 966 | 971 | char *zUuid; /* uuid for rid */ |
| 967 | - | |
| 972 | + | |
| 968 | 973 | rid = db_int(0, |
| 969 | 974 | "SELECT x.rid FROM tag t, tagxref x" |
| 970 | 975 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 971 | 976 | " ORDER BY x.mtime DESC LIMIT 1", |
| 972 | 977 | zPageName |
| @@ -987,10 +992,14 @@ | ||
| 987 | 992 | blob_zero(&wiki); |
| 988 | 993 | zDate = date_in_standard_format("now"); |
| 989 | 994 | blob_appendf(&wiki, "D %s\n", zDate); |
| 990 | 995 | free(zDate); |
| 991 | 996 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 997 | + if( zMimeType && *zMimeType | |
| 998 | + && 0!=fossil_strcmp(zMimeType,"text/x-fossil-wiki") ){ | |
| 999 | + blob_appendf(&wiki, "N %F\n", zMimeType); | |
| 1000 | + } | |
| 992 | 1001 | if( rid ){ |
| 993 | 1002 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 994 | 1003 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 995 | 1004 | free(zUuid); |
| 996 | 1005 | } |
| @@ -1019,16 +1028,18 @@ | ||
| 1019 | 1028 | ** %fossil wiki export PAGENAME ?FILE? |
| 1020 | 1029 | ** |
| 1021 | 1030 | ** Sends the latest version of the PAGENAME wiki |
| 1022 | 1031 | ** entry to the given file or standard output. |
| 1023 | 1032 | ** |
| 1024 | -** %fossil wiki commit PAGENAME ?FILE? | |
| 1033 | +** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT] | |
| 1025 | 1034 | ** |
| 1026 | 1035 | ** Commit changes to a wiki page from FILE or from standard |
| 1027 | -** input. | |
| 1036 | +** input. The -mimetype (-M) flag specifies the mime type, | |
| 1037 | +** defaulting to the type used by the previous version of | |
| 1038 | +** the page or (for new pages) text/x-fossil-wiki. | |
| 1028 | 1039 | ** |
| 1029 | -** %fossil wiki create PAGENAME ?FILE? | |
| 1040 | +** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT] | |
| 1030 | 1041 | ** |
| 1031 | 1042 | ** Create a new wiki page with initial content taken from |
| 1032 | 1043 | ** FILE or from standard input. |
| 1033 | 1044 | ** |
| 1034 | 1045 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | ||
| 1054 | 1065 | int rid; /* Artifact ID of the wiki page */ |
| 1055 | 1066 | int i; /* Loop counter */ |
| 1056 | 1067 | char *zBody = 0; /* Wiki page content */ |
| 1057 | 1068 | Blob body; /* Wiki page content */ |
| 1058 | 1069 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1059 | - | |
| 1060 | 1070 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1061 | 1071 | usage("export PAGENAME ?FILE?"); |
| 1062 | 1072 | } |
| 1063 | 1073 | zPageName = g.argv[3]; |
| 1064 | 1074 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | ||
| 1079 | 1089 | blob_append(&body, "\n", 1); |
| 1080 | 1090 | blob_write_to_file(&body, zFile); |
| 1081 | 1091 | blob_reset(&body); |
| 1082 | 1092 | manifest_destroy(pWiki); |
| 1083 | 1093 | return; |
| 1084 | - }else | |
| 1085 | - if( strncmp(g.argv[2],"commit",n)==0 | |
| 1086 | - || strncmp(g.argv[2],"create",n)==0 ){ | |
| 1087 | - char *zPageName; | |
| 1088 | - Blob content; | |
| 1094 | + }else if( strncmp(g.argv[2],"commit",n)==0 | |
| 1095 | + || strncmp(g.argv[2],"create",n)==0 ){ | |
| 1096 | + char const *zPageName; /* page name */ | |
| 1097 | + Blob content; /* Input content */ | |
| 1098 | + int rid; | |
| 1099 | + Manifest *pWiki = 0; /* Parsed wiki page content */ | |
| 1100 | + char const * zMimeType = find_option("mimetype", "M", 1); | |
| 1089 | 1101 | if( g.argc!=4 && g.argc!=5 ){ |
| 1090 | - usage("commit PAGENAME ?FILE?"); | |
| 1102 | + usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]"); | |
| 1091 | 1103 | } |
| 1092 | 1104 | zPageName = g.argv[3]; |
| 1093 | 1105 | if( g.argc==4 ){ |
| 1094 | 1106 | blob_read_from_channel(&content, stdin, -1); |
| 1095 | 1107 | }else{ |
| 1096 | 1108 | blob_read_from_file(&content, g.argv[4]); |
| 1109 | + } | |
| 1110 | + if(!zMimeType || !*zMimeType){ | |
| 1111 | + /* Try to deduce the mime type based on the prior version. */ | |
| 1112 | + rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" | |
| 1113 | + " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" | |
| 1114 | + " ORDER BY x.mtime DESC LIMIT 1", | |
| 1115 | + zPageName | |
| 1116 | + ); | |
| 1117 | + if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 | |
| 1118 | + && (pWiki->zMimetype && *pWiki->zMimetype)){ | |
| 1119 | + zMimeType = pWiki->zMimetype; | |
| 1120 | + } | |
| 1097 | 1121 | } |
| 1098 | 1122 | if( g.argv[2][1]=='r' ){ |
| 1099 | - wiki_cmd_commit(zPageName, 1, &content); | |
| 1123 | + wiki_cmd_commit(zPageName, 1, &content, zMimeType); | |
| 1100 | 1124 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1101 | 1125 | }else{ |
| 1102 | - wiki_cmd_commit(zPageName, 0, &content); | |
| 1126 | + wiki_cmd_commit(zPageName, 0, &content, zMimeType); | |
| 1103 | 1127 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1104 | 1128 | } |
| 1129 | + manifest_destroy(pWiki); | |
| 1105 | 1130 | blob_reset(&content); |
| 1106 | - }else | |
| 1107 | - if( strncmp(g.argv[2],"delete",n)==0 ){ | |
| 1131 | + }else if( strncmp(g.argv[2],"delete",n)==0 ){ | |
| 1108 | 1132 | if( g.argc!=5 ){ |
| 1109 | 1133 | usage("delete PAGENAME"); |
| 1110 | 1134 | } |
| 1111 | 1135 | fossil_fatal("delete not yet implemented."); |
| 1112 | - }else | |
| 1113 | - if( strncmp(g.argv[2],"list",n)==0 ){ | |
| 1136 | + }else if( strncmp(g.argv[2],"list",n)==0 ){ | |
| 1114 | 1137 | Stmt q; |
| 1115 | 1138 | db_prepare(&q, |
| 1116 | 1139 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1117 | 1140 | " ORDER BY lower(tagname) /*sort*/" |
| 1118 | 1141 | ); |
| @@ -1119,14 +1142,13 @@ | ||
| 1119 | 1142 | while( db_step(&q)==SQLITE_ROW ){ |
| 1120 | 1143 | const char *zName = db_column_text(&q, 0); |
| 1121 | 1144 | fossil_print( "%s\n",zName); |
| 1122 | 1145 | } |
| 1123 | 1146 | db_finalize(&q); |
| 1124 | - }else | |
| 1125 | - { | |
| 1147 | + }else{ | |
| 1126 | 1148 | goto wiki_cmd_usage; |
| 1127 | 1149 | } |
| 1128 | 1150 | return; |
| 1129 | 1151 | |
| 1130 | 1152 | wiki_cmd_usage: |
| 1131 | 1153 | usage("export|create|commit|list ..."); |
| 1132 | 1154 | } |
| 1133 | 1155 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -955,18 +955,23 @@ | |
| 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | ** and isNew is false, then this routine throws an error. |
| 958 | ** |
| 959 | ** The content of the new page is given by the blob pContent. |
| 960 | */ |
| 961 | int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent){ |
| 962 | Blob wiki; /* Wiki page content */ |
| 963 | Blob cksum; /* wiki checksum */ |
| 964 | int rid; /* artifact ID of parent page */ |
| 965 | char *zDate; /* timestamp */ |
| 966 | char *zUuid; /* uuid for rid */ |
| 967 | |
| 968 | rid = db_int(0, |
| 969 | "SELECT x.rid FROM tag t, tagxref x" |
| 970 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 971 | " ORDER BY x.mtime DESC LIMIT 1", |
| 972 | zPageName |
| @@ -987,10 +992,14 @@ | |
| 987 | blob_zero(&wiki); |
| 988 | zDate = date_in_standard_format("now"); |
| 989 | blob_appendf(&wiki, "D %s\n", zDate); |
| 990 | free(zDate); |
| 991 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 992 | if( rid ){ |
| 993 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 994 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 995 | free(zUuid); |
| 996 | } |
| @@ -1019,16 +1028,18 @@ | |
| 1019 | ** %fossil wiki export PAGENAME ?FILE? |
| 1020 | ** |
| 1021 | ** Sends the latest version of the PAGENAME wiki |
| 1022 | ** entry to the given file or standard output. |
| 1023 | ** |
| 1024 | ** %fossil wiki commit PAGENAME ?FILE? |
| 1025 | ** |
| 1026 | ** Commit changes to a wiki page from FILE or from standard |
| 1027 | ** input. |
| 1028 | ** |
| 1029 | ** %fossil wiki create PAGENAME ?FILE? |
| 1030 | ** |
| 1031 | ** Create a new wiki page with initial content taken from |
| 1032 | ** FILE or from standard input. |
| 1033 | ** |
| 1034 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | |
| 1054 | int rid; /* Artifact ID of the wiki page */ |
| 1055 | int i; /* Loop counter */ |
| 1056 | char *zBody = 0; /* Wiki page content */ |
| 1057 | Blob body; /* Wiki page content */ |
| 1058 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1059 | |
| 1060 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1061 | usage("export PAGENAME ?FILE?"); |
| 1062 | } |
| 1063 | zPageName = g.argv[3]; |
| 1064 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | |
| 1079 | blob_append(&body, "\n", 1); |
| 1080 | blob_write_to_file(&body, zFile); |
| 1081 | blob_reset(&body); |
| 1082 | manifest_destroy(pWiki); |
| 1083 | return; |
| 1084 | }else |
| 1085 | if( strncmp(g.argv[2],"commit",n)==0 |
| 1086 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1087 | char *zPageName; |
| 1088 | Blob content; |
| 1089 | if( g.argc!=4 && g.argc!=5 ){ |
| 1090 | usage("commit PAGENAME ?FILE?"); |
| 1091 | } |
| 1092 | zPageName = g.argv[3]; |
| 1093 | if( g.argc==4 ){ |
| 1094 | blob_read_from_channel(&content, stdin, -1); |
| 1095 | }else{ |
| 1096 | blob_read_from_file(&content, g.argv[4]); |
| 1097 | } |
| 1098 | if( g.argv[2][1]=='r' ){ |
| 1099 | wiki_cmd_commit(zPageName, 1, &content); |
| 1100 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1101 | }else{ |
| 1102 | wiki_cmd_commit(zPageName, 0, &content); |
| 1103 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1104 | } |
| 1105 | blob_reset(&content); |
| 1106 | }else |
| 1107 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 1108 | if( g.argc!=5 ){ |
| 1109 | usage("delete PAGENAME"); |
| 1110 | } |
| 1111 | fossil_fatal("delete not yet implemented."); |
| 1112 | }else |
| 1113 | if( strncmp(g.argv[2],"list",n)==0 ){ |
| 1114 | Stmt q; |
| 1115 | db_prepare(&q, |
| 1116 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1117 | " ORDER BY lower(tagname) /*sort*/" |
| 1118 | ); |
| @@ -1119,14 +1142,13 @@ | |
| 1119 | while( db_step(&q)==SQLITE_ROW ){ |
| 1120 | const char *zName = db_column_text(&q, 0); |
| 1121 | fossil_print( "%s\n",zName); |
| 1122 | } |
| 1123 | db_finalize(&q); |
| 1124 | }else |
| 1125 | { |
| 1126 | goto wiki_cmd_usage; |
| 1127 | } |
| 1128 | return; |
| 1129 | |
| 1130 | wiki_cmd_usage: |
| 1131 | usage("export|create|commit|list ..."); |
| 1132 | } |
| 1133 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -955,18 +955,23 @@ | |
| 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | ** and isNew is false, then this routine throws an error. |
| 958 | ** |
| 959 | ** The content of the new page is given by the blob pContent. |
| 960 | ** |
| 961 | ** zMimeType specifies the N-card for the wiki page. If it is 0, |
| 962 | ** empty, or "text/x-fossil-wiki" (the default format) then it is |
| 963 | ** ignored. |
| 964 | */ |
| 965 | int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent, |
| 966 | char const * zMimeType){ |
| 967 | Blob wiki; /* Wiki page content */ |
| 968 | Blob cksum; /* wiki checksum */ |
| 969 | int rid; /* artifact ID of parent page */ |
| 970 | char *zDate; /* timestamp */ |
| 971 | char *zUuid; /* uuid for rid */ |
| 972 | |
| 973 | rid = db_int(0, |
| 974 | "SELECT x.rid FROM tag t, tagxref x" |
| 975 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 976 | " ORDER BY x.mtime DESC LIMIT 1", |
| 977 | zPageName |
| @@ -987,10 +992,14 @@ | |
| 992 | blob_zero(&wiki); |
| 993 | zDate = date_in_standard_format("now"); |
| 994 | blob_appendf(&wiki, "D %s\n", zDate); |
| 995 | free(zDate); |
| 996 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 997 | if( zMimeType && *zMimeType |
| 998 | && 0!=fossil_strcmp(zMimeType,"text/x-fossil-wiki") ){ |
| 999 | blob_appendf(&wiki, "N %F\n", zMimeType); |
| 1000 | } |
| 1001 | if( rid ){ |
| 1002 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1003 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 1004 | free(zUuid); |
| 1005 | } |
| @@ -1019,16 +1028,18 @@ | |
| 1028 | ** %fossil wiki export PAGENAME ?FILE? |
| 1029 | ** |
| 1030 | ** Sends the latest version of the PAGENAME wiki |
| 1031 | ** entry to the given file or standard output. |
| 1032 | ** |
| 1033 | ** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT] |
| 1034 | ** |
| 1035 | ** Commit changes to a wiki page from FILE or from standard |
| 1036 | ** input. The -mimetype (-M) flag specifies the mime type, |
| 1037 | ** defaulting to the type used by the previous version of |
| 1038 | ** the page or (for new pages) text/x-fossil-wiki. |
| 1039 | ** |
| 1040 | ** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT] |
| 1041 | ** |
| 1042 | ** Create a new wiki page with initial content taken from |
| 1043 | ** FILE or from standard input. |
| 1044 | ** |
| 1045 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | |
| 1065 | int rid; /* Artifact ID of the wiki page */ |
| 1066 | int i; /* Loop counter */ |
| 1067 | char *zBody = 0; /* Wiki page content */ |
| 1068 | Blob body; /* Wiki page content */ |
| 1069 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1070 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1071 | usage("export PAGENAME ?FILE?"); |
| 1072 | } |
| 1073 | zPageName = g.argv[3]; |
| 1074 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | |
| 1089 | blob_append(&body, "\n", 1); |
| 1090 | blob_write_to_file(&body, zFile); |
| 1091 | blob_reset(&body); |
| 1092 | manifest_destroy(pWiki); |
| 1093 | return; |
| 1094 | }else if( strncmp(g.argv[2],"commit",n)==0 |
| 1095 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1096 | char const *zPageName; /* page name */ |
| 1097 | Blob content; /* Input content */ |
| 1098 | int rid; |
| 1099 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1100 | char const * zMimeType = find_option("mimetype", "M", 1); |
| 1101 | if( g.argc!=4 && g.argc!=5 ){ |
| 1102 | usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]"); |
| 1103 | } |
| 1104 | zPageName = g.argv[3]; |
| 1105 | if( g.argc==4 ){ |
| 1106 | blob_read_from_channel(&content, stdin, -1); |
| 1107 | }else{ |
| 1108 | blob_read_from_file(&content, g.argv[4]); |
| 1109 | } |
| 1110 | if(!zMimeType || !*zMimeType){ |
| 1111 | /* Try to deduce the mime type based on the prior version. */ |
| 1112 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 1113 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 1114 | " ORDER BY x.mtime DESC LIMIT 1", |
| 1115 | zPageName |
| 1116 | ); |
| 1117 | if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 |
| 1118 | && (pWiki->zMimetype && *pWiki->zMimetype)){ |
| 1119 | zMimeType = pWiki->zMimetype; |
| 1120 | } |
| 1121 | } |
| 1122 | if( g.argv[2][1]=='r' ){ |
| 1123 | wiki_cmd_commit(zPageName, 1, &content, zMimeType); |
| 1124 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1125 | }else{ |
| 1126 | wiki_cmd_commit(zPageName, 0, &content, zMimeType); |
| 1127 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1128 | } |
| 1129 | manifest_destroy(pWiki); |
| 1130 | blob_reset(&content); |
| 1131 | }else if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 1132 | if( g.argc!=5 ){ |
| 1133 | usage("delete PAGENAME"); |
| 1134 | } |
| 1135 | fossil_fatal("delete not yet implemented."); |
| 1136 | }else if( strncmp(g.argv[2],"list",n)==0 ){ |
| 1137 | Stmt q; |
| 1138 | db_prepare(&q, |
| 1139 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1140 | " ORDER BY lower(tagname) /*sort*/" |
| 1141 | ); |
| @@ -1119,14 +1142,13 @@ | |
| 1142 | while( db_step(&q)==SQLITE_ROW ){ |
| 1143 | const char *zName = db_column_text(&q, 0); |
| 1144 | fossil_print( "%s\n",zName); |
| 1145 | } |
| 1146 | db_finalize(&q); |
| 1147 | }else{ |
| 1148 | goto wiki_cmd_usage; |
| 1149 | } |
| 1150 | return; |
| 1151 | |
| 1152 | wiki_cmd_usage: |
| 1153 | usage("export|create|commit|list ..."); |
| 1154 | } |
| 1155 |
+42
-20
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -955,18 +955,23 @@ | ||
| 955 | 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | 957 | ** and isNew is false, then this routine throws an error. |
| 958 | 958 | ** |
| 959 | 959 | ** The content of the new page is given by the blob pContent. |
| 960 | +** | |
| 961 | +** zMimeType specifies the N-card for the wiki page. If it is 0, | |
| 962 | +** empty, or "text/x-fossil-wiki" (the default format) then it is | |
| 963 | +** ignored. | |
| 960 | 964 | */ |
| 961 | -int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent){ | |
| 965 | +int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent, | |
| 966 | + char const * zMimeType){ | |
| 962 | 967 | Blob wiki; /* Wiki page content */ |
| 963 | 968 | Blob cksum; /* wiki checksum */ |
| 964 | 969 | int rid; /* artifact ID of parent page */ |
| 965 | 970 | char *zDate; /* timestamp */ |
| 966 | 971 | char *zUuid; /* uuid for rid */ |
| 967 | - | |
| 972 | + | |
| 968 | 973 | rid = db_int(0, |
| 969 | 974 | "SELECT x.rid FROM tag t, tagxref x" |
| 970 | 975 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 971 | 976 | " ORDER BY x.mtime DESC LIMIT 1", |
| 972 | 977 | zPageName |
| @@ -987,10 +992,14 @@ | ||
| 987 | 992 | blob_zero(&wiki); |
| 988 | 993 | zDate = date_in_standard_format("now"); |
| 989 | 994 | blob_appendf(&wiki, "D %s\n", zDate); |
| 990 | 995 | free(zDate); |
| 991 | 996 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 997 | + if( zMimeType && *zMimeType | |
| 998 | + && 0!=fossil_strcmp(zMimeType,"text/x-fossil-wiki") ){ | |
| 999 | + blob_appendf(&wiki, "N %F\n", zMimeType); | |
| 1000 | + } | |
| 992 | 1001 | if( rid ){ |
| 993 | 1002 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 994 | 1003 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 995 | 1004 | free(zUuid); |
| 996 | 1005 | } |
| @@ -1019,16 +1028,18 @@ | ||
| 1019 | 1028 | ** %fossil wiki export PAGENAME ?FILE? |
| 1020 | 1029 | ** |
| 1021 | 1030 | ** Sends the latest version of the PAGENAME wiki |
| 1022 | 1031 | ** entry to the given file or standard output. |
| 1023 | 1032 | ** |
| 1024 | -** %fossil wiki commit PAGENAME ?FILE? | |
| 1033 | +** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT] | |
| 1025 | 1034 | ** |
| 1026 | 1035 | ** Commit changes to a wiki page from FILE or from standard |
| 1027 | -** input. | |
| 1036 | +** input. The -mimetype (-M) flag specifies the mime type, | |
| 1037 | +** defaulting to the type used by the previous version of | |
| 1038 | +** the page or (for new pages) text/x-fossil-wiki. | |
| 1028 | 1039 | ** |
| 1029 | -** %fossil wiki create PAGENAME ?FILE? | |
| 1040 | +** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT] | |
| 1030 | 1041 | ** |
| 1031 | 1042 | ** Create a new wiki page with initial content taken from |
| 1032 | 1043 | ** FILE or from standard input. |
| 1033 | 1044 | ** |
| 1034 | 1045 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | ||
| 1054 | 1065 | int rid; /* Artifact ID of the wiki page */ |
| 1055 | 1066 | int i; /* Loop counter */ |
| 1056 | 1067 | char *zBody = 0; /* Wiki page content */ |
| 1057 | 1068 | Blob body; /* Wiki page content */ |
| 1058 | 1069 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1059 | - | |
| 1060 | 1070 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1061 | 1071 | usage("export PAGENAME ?FILE?"); |
| 1062 | 1072 | } |
| 1063 | 1073 | zPageName = g.argv[3]; |
| 1064 | 1074 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | ||
| 1079 | 1089 | blob_append(&body, "\n", 1); |
| 1080 | 1090 | blob_write_to_file(&body, zFile); |
| 1081 | 1091 | blob_reset(&body); |
| 1082 | 1092 | manifest_destroy(pWiki); |
| 1083 | 1093 | return; |
| 1084 | - }else | |
| 1085 | - if( strncmp(g.argv[2],"commit",n)==0 | |
| 1086 | - || strncmp(g.argv[2],"create",n)==0 ){ | |
| 1087 | - char *zPageName; | |
| 1088 | - Blob content; | |
| 1094 | + }else if( strncmp(g.argv[2],"commit",n)==0 | |
| 1095 | + || strncmp(g.argv[2],"create",n)==0 ){ | |
| 1096 | + char const *zPageName; /* page name */ | |
| 1097 | + Blob content; /* Input content */ | |
| 1098 | + int rid; | |
| 1099 | + Manifest *pWiki = 0; /* Parsed wiki page content */ | |
| 1100 | + char const * zMimeType = find_option("mimetype", "M", 1); | |
| 1089 | 1101 | if( g.argc!=4 && g.argc!=5 ){ |
| 1090 | - usage("commit PAGENAME ?FILE?"); | |
| 1102 | + usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]"); | |
| 1091 | 1103 | } |
| 1092 | 1104 | zPageName = g.argv[3]; |
| 1093 | 1105 | if( g.argc==4 ){ |
| 1094 | 1106 | blob_read_from_channel(&content, stdin, -1); |
| 1095 | 1107 | }else{ |
| 1096 | 1108 | blob_read_from_file(&content, g.argv[4]); |
| 1109 | + } | |
| 1110 | + if(!zMimeType || !*zMimeType){ | |
| 1111 | + /* Try to deduce the mime type based on the prior version. */ | |
| 1112 | + rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" | |
| 1113 | + " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" | |
| 1114 | + " ORDER BY x.mtime DESC LIMIT 1", | |
| 1115 | + zPageName | |
| 1116 | + ); | |
| 1117 | + if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 | |
| 1118 | + && (pWiki->zMimetype && *pWiki->zMimetype)){ | |
| 1119 | + zMimeType = pWiki->zMimetype; | |
| 1120 | + } | |
| 1097 | 1121 | } |
| 1098 | 1122 | if( g.argv[2][1]=='r' ){ |
| 1099 | - wiki_cmd_commit(zPageName, 1, &content); | |
| 1123 | + wiki_cmd_commit(zPageName, 1, &content, zMimeType); | |
| 1100 | 1124 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1101 | 1125 | }else{ |
| 1102 | - wiki_cmd_commit(zPageName, 0, &content); | |
| 1126 | + wiki_cmd_commit(zPageName, 0, &content, zMimeType); | |
| 1103 | 1127 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1104 | 1128 | } |
| 1129 | + manifest_destroy(pWiki); | |
| 1105 | 1130 | blob_reset(&content); |
| 1106 | - }else | |
| 1107 | - if( strncmp(g.argv[2],"delete",n)==0 ){ | |
| 1131 | + }else if( strncmp(g.argv[2],"delete",n)==0 ){ | |
| 1108 | 1132 | if( g.argc!=5 ){ |
| 1109 | 1133 | usage("delete PAGENAME"); |
| 1110 | 1134 | } |
| 1111 | 1135 | fossil_fatal("delete not yet implemented."); |
| 1112 | - }else | |
| 1113 | - if( strncmp(g.argv[2],"list",n)==0 ){ | |
| 1136 | + }else if( strncmp(g.argv[2],"list",n)==0 ){ | |
| 1114 | 1137 | Stmt q; |
| 1115 | 1138 | db_prepare(&q, |
| 1116 | 1139 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1117 | 1140 | " ORDER BY lower(tagname) /*sort*/" |
| 1118 | 1141 | ); |
| @@ -1119,14 +1142,13 @@ | ||
| 1119 | 1142 | while( db_step(&q)==SQLITE_ROW ){ |
| 1120 | 1143 | const char *zName = db_column_text(&q, 0); |
| 1121 | 1144 | fossil_print( "%s\n",zName); |
| 1122 | 1145 | } |
| 1123 | 1146 | db_finalize(&q); |
| 1124 | - }else | |
| 1125 | - { | |
| 1147 | + }else{ | |
| 1126 | 1148 | goto wiki_cmd_usage; |
| 1127 | 1149 | } |
| 1128 | 1150 | return; |
| 1129 | 1151 | |
| 1130 | 1152 | wiki_cmd_usage: |
| 1131 | 1153 | usage("export|create|commit|list ..."); |
| 1132 | 1154 | } |
| 1133 | 1155 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -955,18 +955,23 @@ | |
| 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | ** and isNew is false, then this routine throws an error. |
| 958 | ** |
| 959 | ** The content of the new page is given by the blob pContent. |
| 960 | */ |
| 961 | int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent){ |
| 962 | Blob wiki; /* Wiki page content */ |
| 963 | Blob cksum; /* wiki checksum */ |
| 964 | int rid; /* artifact ID of parent page */ |
| 965 | char *zDate; /* timestamp */ |
| 966 | char *zUuid; /* uuid for rid */ |
| 967 | |
| 968 | rid = db_int(0, |
| 969 | "SELECT x.rid FROM tag t, tagxref x" |
| 970 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 971 | " ORDER BY x.mtime DESC LIMIT 1", |
| 972 | zPageName |
| @@ -987,10 +992,14 @@ | |
| 987 | blob_zero(&wiki); |
| 988 | zDate = date_in_standard_format("now"); |
| 989 | blob_appendf(&wiki, "D %s\n", zDate); |
| 990 | free(zDate); |
| 991 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 992 | if( rid ){ |
| 993 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 994 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 995 | free(zUuid); |
| 996 | } |
| @@ -1019,16 +1028,18 @@ | |
| 1019 | ** %fossil wiki export PAGENAME ?FILE? |
| 1020 | ** |
| 1021 | ** Sends the latest version of the PAGENAME wiki |
| 1022 | ** entry to the given file or standard output. |
| 1023 | ** |
| 1024 | ** %fossil wiki commit PAGENAME ?FILE? |
| 1025 | ** |
| 1026 | ** Commit changes to a wiki page from FILE or from standard |
| 1027 | ** input. |
| 1028 | ** |
| 1029 | ** %fossil wiki create PAGENAME ?FILE? |
| 1030 | ** |
| 1031 | ** Create a new wiki page with initial content taken from |
| 1032 | ** FILE or from standard input. |
| 1033 | ** |
| 1034 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | |
| 1054 | int rid; /* Artifact ID of the wiki page */ |
| 1055 | int i; /* Loop counter */ |
| 1056 | char *zBody = 0; /* Wiki page content */ |
| 1057 | Blob body; /* Wiki page content */ |
| 1058 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1059 | |
| 1060 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1061 | usage("export PAGENAME ?FILE?"); |
| 1062 | } |
| 1063 | zPageName = g.argv[3]; |
| 1064 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | |
| 1079 | blob_append(&body, "\n", 1); |
| 1080 | blob_write_to_file(&body, zFile); |
| 1081 | blob_reset(&body); |
| 1082 | manifest_destroy(pWiki); |
| 1083 | return; |
| 1084 | }else |
| 1085 | if( strncmp(g.argv[2],"commit",n)==0 |
| 1086 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1087 | char *zPageName; |
| 1088 | Blob content; |
| 1089 | if( g.argc!=4 && g.argc!=5 ){ |
| 1090 | usage("commit PAGENAME ?FILE?"); |
| 1091 | } |
| 1092 | zPageName = g.argv[3]; |
| 1093 | if( g.argc==4 ){ |
| 1094 | blob_read_from_channel(&content, stdin, -1); |
| 1095 | }else{ |
| 1096 | blob_read_from_file(&content, g.argv[4]); |
| 1097 | } |
| 1098 | if( g.argv[2][1]=='r' ){ |
| 1099 | wiki_cmd_commit(zPageName, 1, &content); |
| 1100 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1101 | }else{ |
| 1102 | wiki_cmd_commit(zPageName, 0, &content); |
| 1103 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1104 | } |
| 1105 | blob_reset(&content); |
| 1106 | }else |
| 1107 | if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 1108 | if( g.argc!=5 ){ |
| 1109 | usage("delete PAGENAME"); |
| 1110 | } |
| 1111 | fossil_fatal("delete not yet implemented."); |
| 1112 | }else |
| 1113 | if( strncmp(g.argv[2],"list",n)==0 ){ |
| 1114 | Stmt q; |
| 1115 | db_prepare(&q, |
| 1116 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1117 | " ORDER BY lower(tagname) /*sort*/" |
| 1118 | ); |
| @@ -1119,14 +1142,13 @@ | |
| 1119 | while( db_step(&q)==SQLITE_ROW ){ |
| 1120 | const char *zName = db_column_text(&q, 0); |
| 1121 | fossil_print( "%s\n",zName); |
| 1122 | } |
| 1123 | db_finalize(&q); |
| 1124 | }else |
| 1125 | { |
| 1126 | goto wiki_cmd_usage; |
| 1127 | } |
| 1128 | return; |
| 1129 | |
| 1130 | wiki_cmd_usage: |
| 1131 | usage("export|create|commit|list ..."); |
| 1132 | } |
| 1133 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -955,18 +955,23 @@ | |
| 955 | ** given by the zPageName parameter. isNew must be true to create |
| 956 | ** a new page. If no previous page with the name zPageName exists |
| 957 | ** and isNew is false, then this routine throws an error. |
| 958 | ** |
| 959 | ** The content of the new page is given by the blob pContent. |
| 960 | ** |
| 961 | ** zMimeType specifies the N-card for the wiki page. If it is 0, |
| 962 | ** empty, or "text/x-fossil-wiki" (the default format) then it is |
| 963 | ** ignored. |
| 964 | */ |
| 965 | int wiki_cmd_commit(char const * zPageName, int isNew, Blob *pContent, |
| 966 | char const * zMimeType){ |
| 967 | Blob wiki; /* Wiki page content */ |
| 968 | Blob cksum; /* wiki checksum */ |
| 969 | int rid; /* artifact ID of parent page */ |
| 970 | char *zDate; /* timestamp */ |
| 971 | char *zUuid; /* uuid for rid */ |
| 972 | |
| 973 | rid = db_int(0, |
| 974 | "SELECT x.rid FROM tag t, tagxref x" |
| 975 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 976 | " ORDER BY x.mtime DESC LIMIT 1", |
| 977 | zPageName |
| @@ -987,10 +992,14 @@ | |
| 992 | blob_zero(&wiki); |
| 993 | zDate = date_in_standard_format("now"); |
| 994 | blob_appendf(&wiki, "D %s\n", zDate); |
| 995 | free(zDate); |
| 996 | blob_appendf(&wiki, "L %F\n", zPageName ); |
| 997 | if( zMimeType && *zMimeType |
| 998 | && 0!=fossil_strcmp(zMimeType,"text/x-fossil-wiki") ){ |
| 999 | blob_appendf(&wiki, "N %F\n", zMimeType); |
| 1000 | } |
| 1001 | if( rid ){ |
| 1002 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| 1003 | blob_appendf(&wiki, "P %s\n", zUuid); |
| 1004 | free(zUuid); |
| 1005 | } |
| @@ -1019,16 +1028,18 @@ | |
| 1028 | ** %fossil wiki export PAGENAME ?FILE? |
| 1029 | ** |
| 1030 | ** Sends the latest version of the PAGENAME wiki |
| 1031 | ** entry to the given file or standard output. |
| 1032 | ** |
| 1033 | ** %fossil wiki commit PAGENAME ?FILE? [-mimetype TEXT-FORMAT] |
| 1034 | ** |
| 1035 | ** Commit changes to a wiki page from FILE or from standard |
| 1036 | ** input. The -mimetype (-M) flag specifies the mime type, |
| 1037 | ** defaulting to the type used by the previous version of |
| 1038 | ** the page or (for new pages) text/x-fossil-wiki. |
| 1039 | ** |
| 1040 | ** %fossil wiki create PAGENAME ?FILE? [-mimetype TEXT-FORMAT] |
| 1041 | ** |
| 1042 | ** Create a new wiki page with initial content taken from |
| 1043 | ** FILE or from standard input. |
| 1044 | ** |
| 1045 | ** %fossil wiki list |
| @@ -1054,11 +1065,10 @@ | |
| 1065 | int rid; /* Artifact ID of the wiki page */ |
| 1066 | int i; /* Loop counter */ |
| 1067 | char *zBody = 0; /* Wiki page content */ |
| 1068 | Blob body; /* Wiki page content */ |
| 1069 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1070 | if( (g.argc!=4) && (g.argc!=5) ){ |
| 1071 | usage("export PAGENAME ?FILE?"); |
| 1072 | } |
| 1073 | zPageName = g.argv[3]; |
| 1074 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| @@ -1079,40 +1089,53 @@ | |
| 1089 | blob_append(&body, "\n", 1); |
| 1090 | blob_write_to_file(&body, zFile); |
| 1091 | blob_reset(&body); |
| 1092 | manifest_destroy(pWiki); |
| 1093 | return; |
| 1094 | }else if( strncmp(g.argv[2],"commit",n)==0 |
| 1095 | || strncmp(g.argv[2],"create",n)==0 ){ |
| 1096 | char const *zPageName; /* page name */ |
| 1097 | Blob content; /* Input content */ |
| 1098 | int rid; |
| 1099 | Manifest *pWiki = 0; /* Parsed wiki page content */ |
| 1100 | char const * zMimeType = find_option("mimetype", "M", 1); |
| 1101 | if( g.argc!=4 && g.argc!=5 ){ |
| 1102 | usage("commit|create PAGENAME ?FILE? [-mimetype TEXT-FORMAT]"); |
| 1103 | } |
| 1104 | zPageName = g.argv[3]; |
| 1105 | if( g.argc==4 ){ |
| 1106 | blob_read_from_channel(&content, stdin, -1); |
| 1107 | }else{ |
| 1108 | blob_read_from_file(&content, g.argv[4]); |
| 1109 | } |
| 1110 | if(!zMimeType || !*zMimeType){ |
| 1111 | /* Try to deduce the mime type based on the prior version. */ |
| 1112 | rid = db_int(0, "SELECT x.rid FROM tag t, tagxref x" |
| 1113 | " WHERE x.tagid=t.tagid AND t.tagname='wiki-%q'" |
| 1114 | " ORDER BY x.mtime DESC LIMIT 1", |
| 1115 | zPageName |
| 1116 | ); |
| 1117 | if(rid>0 && (pWiki = manifest_get(rid, CFTYPE_WIKI, 0))!=0 |
| 1118 | && (pWiki->zMimetype && *pWiki->zMimetype)){ |
| 1119 | zMimeType = pWiki->zMimetype; |
| 1120 | } |
| 1121 | } |
| 1122 | if( g.argv[2][1]=='r' ){ |
| 1123 | wiki_cmd_commit(zPageName, 1, &content, zMimeType); |
| 1124 | fossil_print("Created new wiki page %s.\n", zPageName); |
| 1125 | }else{ |
| 1126 | wiki_cmd_commit(zPageName, 0, &content, zMimeType); |
| 1127 | fossil_print("Updated wiki page %s.\n", zPageName); |
| 1128 | } |
| 1129 | manifest_destroy(pWiki); |
| 1130 | blob_reset(&content); |
| 1131 | }else if( strncmp(g.argv[2],"delete",n)==0 ){ |
| 1132 | if( g.argc!=5 ){ |
| 1133 | usage("delete PAGENAME"); |
| 1134 | } |
| 1135 | fossil_fatal("delete not yet implemented."); |
| 1136 | }else if( strncmp(g.argv[2],"list",n)==0 ){ |
| 1137 | Stmt q; |
| 1138 | db_prepare(&q, |
| 1139 | "SELECT substr(tagname, 6) FROM tag WHERE tagname GLOB 'wiki-*'" |
| 1140 | " ORDER BY lower(tagname) /*sort*/" |
| 1141 | ); |
| @@ -1119,14 +1142,13 @@ | |
| 1142 | while( db_step(&q)==SQLITE_ROW ){ |
| 1143 | const char *zName = db_column_text(&q, 0); |
| 1144 | fossil_print( "%s\n",zName); |
| 1145 | } |
| 1146 | db_finalize(&q); |
| 1147 | }else{ |
| 1148 | goto wiki_cmd_usage; |
| 1149 | } |
| 1150 | return; |
| 1151 | |
| 1152 | wiki_cmd_usage: |
| 1153 | usage("export|create|commit|list ..."); |
| 1154 | } |
| 1155 |