Fossil SCM

Added first go at /json/wiki/diff. Not yet configurable but proves the concept.

stephan 2012-03-04 18:41 trunk
Commit c6c38a522faf1cca8622788f73a24b387d2926eb
1 file changed +119 -10
+119 -10
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -25,19 +25,20 @@
2525
2626
static cson_value * json_wiki_create();
2727
static cson_value * json_wiki_get();
2828
static cson_value * json_wiki_list();
2929
static cson_value * json_wiki_save();
30
-
30
+static cson_value * json_wiki_diff();
3131
/*
3232
** Mapping of /json/wiki/XXX commands/paths to callbacks.
3333
*/
3434
static const JsonPageDef JsonPageDefs_Wiki[] = {
35
-{"create", json_wiki_create, 1},
35
+{"create", json_wiki_create, 0},
36
+{"diff", json_wiki_diff, 0},
3637
{"get", json_wiki_get, 0},
3738
{"list", json_wiki_list, 0},
38
-{"save", json_wiki_save, 1},
39
+{"save", json_wiki_save, 0},
3940
{"timeline", json_timeline_wiki,0},
4041
/* Last entry MUST have a NULL name. */
4142
{NULL,NULL,0}
4243
};
4344
@@ -48,10 +49,20 @@
4849
*/
4950
cson_value * json_page_wiki(){
5051
return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
5152
}
5253
54
+char * json_wiki_get_uuid_for_rid( int rid )
55
+{
56
+ return db_text(NULL,
57
+ "SELECT b.uuid FROM tag t, tagxref x, blob b"
58
+ " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
59
+ " AND b.rid=x.rid AND b.rid=%d"
60
+ " ORDER BY x.mtime DESC LIMIT 1",
61
+ rid
62
+ );
63
+}
5364
5465
/*
5566
** Tries to load a wiki page from the given rid creates a JSON object
5667
** representation of it. If the page is not found then NULL is
5768
** returned. If contentFormat is positive then the page content
@@ -75,17 +86,11 @@
7586
/*char const * zFormat = NULL;*/
7687
unsigned int len = 0;
7788
cson_object * pay = cson_new_object();
7889
char const * zBody = pWiki->zWiki;
7990
char const * zFormat = NULL;
80
- char * zUuid = db_text(NULL,
81
- "SELECT b.uuid FROM tag t, tagxref x, blob b"
82
- " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
83
- " AND b.rid=x.rid AND b.rid=%d"
84
- " ORDER BY x.mtime DESC LIMIT 1",
85
- rid
86
- );
91
+ char * zUuid = json_wiki_get_uuid_for_rid(rid);
8792
cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
8893
cson_object_set(pay,"uuid",json_new_string(zUuid));
8994
free(zUuid);
9095
zUuid = NULL;
9196
if( pWiki->nParent > 0 ){
@@ -422,6 +427,110 @@
422427
listV = NULL;
423428
end:
424429
db_finalize(&q);
425430
return listV;
426431
}
432
+
433
+static cson_value * json_wiki_diff(){
434
+ char const * zV1 = NULL;
435
+ char const * zV2 = NULL;
436
+ char const * zContent = NULL;
437
+ cson_object * pay = NULL;
438
+ int argPos = g.json.dispatchDepth;
439
+ int r1 = 0, r2 = 0;
440
+ Manifest * pW1 = NULL, *pW2 = NULL;
441
+ Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
442
+ char const * zErrTag = NULL;
443
+ int diffFlags;
444
+ char * zUuid = NULL;
445
+ if( !g.perm.History ){
446
+ json_set_err(FSL_JSON_E_DENIED,
447
+ "Requires 'h' permissions.");
448
+ return NULL;
449
+ }
450
+
451
+
452
+ zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );
453
+ zV2 = json_find_option_cstr2( "v2",NULL, NULL, ++argPos );
454
+ if(!zV1 || !*zV1 || !zV2 || !*zV2) {
455
+ json_set_err(FSL_JSON_E_INVALID_ARGS,
456
+ "Requires both 'v1' and 'v2' arguments.");
457
+ return NULL;
458
+ }
459
+
460
+ r1 = symbolic_name_to_rid( zV1, "w" );
461
+ zErrTag = zV1;
462
+ if(r1<0){
463
+ goto invalid;
464
+ }else if(0==r1){
465
+ goto ambiguous;
466
+ }
467
+
468
+ r2 = symbolic_name_to_rid( zV2, "w" );
469
+ zErrTag = zV2;
470
+ if(r2<0){
471
+ goto invalid;
472
+ }else if(0==r2){
473
+ goto ambiguous;
474
+ }
475
+
476
+ zErrTag = zV1;
477
+ pW1 = manifest_get(r1, CFTYPE_WIKI);
478
+ if( pW1==0 ) {
479
+ goto manifest;
480
+ }
481
+ zErrTag = zV2;
482
+ pW2 = manifest_get(r2, CFTYPE_WIKI);
483
+ if( pW2==0 ) {
484
+ goto manifest;
485
+ }
486
+
487
+ blob_init(&w1, pW1->zWiki, -1);
488
+ blob_zero(&w2);
489
+ blob_init(&w2, pW2->zWiki, -1);
490
+ blob_zero(&d);
491
+ diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
492
+ text_diff(&w2, &w1, &d, diffFlags);
493
+ blob_reset(&w1);
494
+ blob_reset(&w2);
495
+
496
+ pay = cson_new_object();
497
+
498
+ zUuid = json_wiki_get_uuid_for_rid( pW1->rid );
499
+ cson_object_set(pay, "v1", json_new_string(zUuid) );
500
+ free(zUuid);
501
+ zUuid = json_wiki_get_uuid_for_rid( pW2->rid );
502
+ cson_object_set(pay, "v2", json_new_string(zUuid) );
503
+ free(zUuid);
504
+ zUuid = NULL;
505
+
506
+ manifest_destroy(pW1);
507
+ manifest_destroy(pW2);
508
+
509
+ cson_object_set(pay, "diff",
510
+ cson_value_new_string( blob_str(&d),
511
+ (unsigned int)blob_size(&d)));
512
+
513
+ return cson_object_value(pay);
514
+
515
+ manifest:
516
+ json_set_err(FSL_JSON_E_UNKNOWN,
517
+ "Could not load wiki manifest for UUID [%s].",
518
+ zErrTag);
519
+ goto end;
520
+
521
+ ambiguous:
522
+ json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
523
+ "UUID [%s] is ambiguous.", zErrTag);
524
+ goto end;
525
+
526
+ invalid:
527
+ json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
528
+ "UUID [%s] not found.", zErrTag);
529
+ goto end;
530
+
531
+ end:
532
+ cson_free_object(pay);
533
+ return NULL;
534
+}
535
+
427536
#endif /* FOSSIL_ENABLE_JSON */
428537
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -25,19 +25,20 @@
25
26 static cson_value * json_wiki_create();
27 static cson_value * json_wiki_get();
28 static cson_value * json_wiki_list();
29 static cson_value * json_wiki_save();
30
31 /*
32 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
33 */
34 static const JsonPageDef JsonPageDefs_Wiki[] = {
35 {"create", json_wiki_create, 1},
 
36 {"get", json_wiki_get, 0},
37 {"list", json_wiki_list, 0},
38 {"save", json_wiki_save, 1},
39 {"timeline", json_timeline_wiki,0},
40 /* Last entry MUST have a NULL name. */
41 {NULL,NULL,0}
42 };
43
@@ -48,10 +49,20 @@
48 */
49 cson_value * json_page_wiki(){
50 return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
51 }
52
 
 
 
 
 
 
 
 
 
 
53
54 /*
55 ** Tries to load a wiki page from the given rid creates a JSON object
56 ** representation of it. If the page is not found then NULL is
57 ** returned. If contentFormat is positive then the page content
@@ -75,17 +86,11 @@
75 /*char const * zFormat = NULL;*/
76 unsigned int len = 0;
77 cson_object * pay = cson_new_object();
78 char const * zBody = pWiki->zWiki;
79 char const * zFormat = NULL;
80 char * zUuid = db_text(NULL,
81 "SELECT b.uuid FROM tag t, tagxref x, blob b"
82 " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
83 " AND b.rid=x.rid AND b.rid=%d"
84 " ORDER BY x.mtime DESC LIMIT 1",
85 rid
86 );
87 cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
88 cson_object_set(pay,"uuid",json_new_string(zUuid));
89 free(zUuid);
90 zUuid = NULL;
91 if( pWiki->nParent > 0 ){
@@ -422,6 +427,110 @@
422 listV = NULL;
423 end:
424 db_finalize(&q);
425 return listV;
426 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427 #endif /* FOSSIL_ENABLE_JSON */
428
--- src/json_wiki.c
+++ src/json_wiki.c
@@ -25,19 +25,20 @@
25
26 static cson_value * json_wiki_create();
27 static cson_value * json_wiki_get();
28 static cson_value * json_wiki_list();
29 static cson_value * json_wiki_save();
30 static cson_value * json_wiki_diff();
31 /*
32 ** Mapping of /json/wiki/XXX commands/paths to callbacks.
33 */
34 static const JsonPageDef JsonPageDefs_Wiki[] = {
35 {"create", json_wiki_create, 0},
36 {"diff", json_wiki_diff, 0},
37 {"get", json_wiki_get, 0},
38 {"list", json_wiki_list, 0},
39 {"save", json_wiki_save, 0},
40 {"timeline", json_timeline_wiki,0},
41 /* Last entry MUST have a NULL name. */
42 {NULL,NULL,0}
43 };
44
@@ -48,10 +49,20 @@
49 */
50 cson_value * json_page_wiki(){
51 return json_page_dispatch_helper(&JsonPageDefs_Wiki[0]);
52 }
53
54 char * json_wiki_get_uuid_for_rid( int rid )
55 {
56 return db_text(NULL,
57 "SELECT b.uuid FROM tag t, tagxref x, blob b"
58 " WHERE x.tagid=t.tagid AND t.tagname GLOB 'wiki-*' "
59 " AND b.rid=x.rid AND b.rid=%d"
60 " ORDER BY x.mtime DESC LIMIT 1",
61 rid
62 );
63 }
64
65 /*
66 ** Tries to load a wiki page from the given rid creates a JSON object
67 ** representation of it. If the page is not found then NULL is
68 ** returned. If contentFormat is positive then the page content
@@ -75,17 +86,11 @@
86 /*char const * zFormat = NULL;*/
87 unsigned int len = 0;
88 cson_object * pay = cson_new_object();
89 char const * zBody = pWiki->zWiki;
90 char const * zFormat = NULL;
91 char * zUuid = json_wiki_get_uuid_for_rid(rid);
 
 
 
 
 
 
92 cson_object_set(pay,"name",json_new_string(pWiki->zWikiTitle));
93 cson_object_set(pay,"uuid",json_new_string(zUuid));
94 free(zUuid);
95 zUuid = NULL;
96 if( pWiki->nParent > 0 ){
@@ -422,6 +427,110 @@
427 listV = NULL;
428 end:
429 db_finalize(&q);
430 return listV;
431 }
432
433 static cson_value * json_wiki_diff(){
434 char const * zV1 = NULL;
435 char const * zV2 = NULL;
436 char const * zContent = NULL;
437 cson_object * pay = NULL;
438 int argPos = g.json.dispatchDepth;
439 int r1 = 0, r2 = 0;
440 Manifest * pW1 = NULL, *pW2 = NULL;
441 Blob w1 = empty_blob, w2 = empty_blob, d = empty_blob;
442 char const * zErrTag = NULL;
443 int diffFlags;
444 char * zUuid = NULL;
445 if( !g.perm.History ){
446 json_set_err(FSL_JSON_E_DENIED,
447 "Requires 'h' permissions.");
448 return NULL;
449 }
450
451
452 zV1 = json_find_option_cstr2( "v1",NULL, NULL, ++argPos );
453 zV2 = json_find_option_cstr2( "v2",NULL, NULL, ++argPos );
454 if(!zV1 || !*zV1 || !zV2 || !*zV2) {
455 json_set_err(FSL_JSON_E_INVALID_ARGS,
456 "Requires both 'v1' and 'v2' arguments.");
457 return NULL;
458 }
459
460 r1 = symbolic_name_to_rid( zV1, "w" );
461 zErrTag = zV1;
462 if(r1<0){
463 goto invalid;
464 }else if(0==r1){
465 goto ambiguous;
466 }
467
468 r2 = symbolic_name_to_rid( zV2, "w" );
469 zErrTag = zV2;
470 if(r2<0){
471 goto invalid;
472 }else if(0==r2){
473 goto ambiguous;
474 }
475
476 zErrTag = zV1;
477 pW1 = manifest_get(r1, CFTYPE_WIKI);
478 if( pW1==0 ) {
479 goto manifest;
480 }
481 zErrTag = zV2;
482 pW2 = manifest_get(r2, CFTYPE_WIKI);
483 if( pW2==0 ) {
484 goto manifest;
485 }
486
487 blob_init(&w1, pW1->zWiki, -1);
488 blob_zero(&w2);
489 blob_init(&w2, pW2->zWiki, -1);
490 blob_zero(&d);
491 diffFlags = DIFF_IGNORE_EOLWS | DIFF_INLINE;
492 text_diff(&w2, &w1, &d, diffFlags);
493 blob_reset(&w1);
494 blob_reset(&w2);
495
496 pay = cson_new_object();
497
498 zUuid = json_wiki_get_uuid_for_rid( pW1->rid );
499 cson_object_set(pay, "v1", json_new_string(zUuid) );
500 free(zUuid);
501 zUuid = json_wiki_get_uuid_for_rid( pW2->rid );
502 cson_object_set(pay, "v2", json_new_string(zUuid) );
503 free(zUuid);
504 zUuid = NULL;
505
506 manifest_destroy(pW1);
507 manifest_destroy(pW2);
508
509 cson_object_set(pay, "diff",
510 cson_value_new_string( blob_str(&d),
511 (unsigned int)blob_size(&d)));
512
513 return cson_object_value(pay);
514
515 manifest:
516 json_set_err(FSL_JSON_E_UNKNOWN,
517 "Could not load wiki manifest for UUID [%s].",
518 zErrTag);
519 goto end;
520
521 ambiguous:
522 json_set_err(FSL_JSON_E_AMBIGUOUS_UUID,
523 "UUID [%s] is ambiguous.", zErrTag);
524 goto end;
525
526 invalid:
527 json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND,
528 "UUID [%s] not found.", zErrTag);
529 goto end;
530
531 end:
532 cson_free_object(pay);
533 return NULL;
534 }
535
536 #endif /* FOSSIL_ENABLE_JSON */
537

Keyboard Shortcuts

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