summaryrefslogtreecommitdiff
path: root/src/json_diff.c
blob: aec83f937c8ef62f8b9932d74ead3650969d932e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#ifdef FOSSIL_ENABLE_JSON
/*
** Copyright (c) 2011 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*/

#include "config.h"
#include "json_diff.h"

#if INTERFACE
#include "json_detail.h"
#endif



/*
** Generates a diff between two versions (zFrom and zTo), using nContext
** content lines in the output. On success, returns a new JSON String
** object. On error it sets g.json's error state and returns NULL.
**
** If fSbs is true (non-0) them side-by-side diffs are used.
**
** If fHtml is true then HTML markup is added to the diff.
*/
cson_value * json_generate_diff(const char *zFrom, const char *zTo,
                                int nContext, char fSbs,
                                char fHtml){
  int fromid;
  int toid;
  int outLen;
  DiffConfig DCfg;
  Blob from = empty_blob, to = empty_blob, out = empty_blob;
  cson_value * rc = NULL;
  int flags = (fSbs ? DIFF_SIDEBYSIDE : 0)
    | (fHtml ? DIFF_HTML : 0);
  fromid = name_to_typed_rid(zFrom, "*");
  if(fromid<=0){
      json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
                   "Could not resolve 'from' ID.");
      return NULL;
  }
  toid = name_to_typed_rid(zTo, "*");
  if(toid<=0){
      json_set_err(FSL_JSON_E_UNRESOLVED_UUID,
                   "Could not resolve 'to' ID.");
      return NULL;
  }
  content_get(fromid, &from);
  content_get(toid, &to);
  blob_zero(&out);
  diff_config_init(&DCfg, flags);
  text_diff(&from, &to, &out, &DCfg);
  blob_reset(&from);
  blob_reset(&to);
  outLen = blob_size(&out);
  if(outLen>=0){
    rc = cson_value_new_string(blob_buffer(&out),
                               (unsigned int)blob_size(&out));
  }
  blob_reset(&out);
  return rc;
}

/*
** Implementation of the /json/diff page.
**
** Arguments:
**
** v1=1st version to diff
** v2=2nd version to diff
**
** Can come from GET, POST.payload, CLI -v1/-v2 or as positional
** parameters following the command name (in HTTP and CLI modes).
**
*/
cson_value * json_page_diff(void){
  cson_object * pay = NULL;
  cson_value * v = NULL;
  char const * zFrom;
  char const * zTo;
  int nContext = 0;
  char doSBS;
  char doHtml;
  if(!g.perm.Read){
    json_set_err(FSL_JSON_E_DENIED,
                 "Requires 'o' permissions.");
    return NULL;
  }
  zFrom = json_find_option_cstr("v1",NULL,NULL);
  if(!zFrom){
    zFrom = json_command_arg(2);
  }
  if(!zFrom){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Required 'v1' parameter is missing.");
    return NULL;
  }
  zTo = json_find_option_cstr("v2",NULL,NULL);
  if(!zTo){
    zTo = json_command_arg(3);
  }
  if(!zTo){
    json_set_err(FSL_JSON_E_MISSING_ARGS,
                 "Required 'v2' parameter is missing.");
    return NULL;
  }
  nContext = json_find_option_int("context",NULL,"c",5);
  doSBS = json_find_option_bool("sbs",NULL,"y",0);
  doHtml = json_find_option_bool("html",NULL,"h",0);
  v = json_generate_diff(zFrom, zTo, nContext, doSBS, doHtml);
  if(!v){
    if(!g.json.resultCode){
      json_set_err(FSL_JSON_E_UNKNOWN,
                   "Generating diff failed for unknown reason.");
    }
    return NULL;
  }
  pay = cson_new_object();
  cson_object_set(pay, "from", json_new_string(zFrom));
  cson_object_set(pay, "to", json_new_string(zTo));
  cson_object_set(pay, "diff", v);
  v = 0;

  return pay ? cson_object_value(pay) : NULL;
}

#endif /* FOSSIL_ENABLE_JSON */