|
1
|
#ifdef FOSSIL_ENABLE_JSON |
|
2
|
/* |
|
3
|
** Copyright (c) 2011 D. Richard Hipp |
|
4
|
** |
|
5
|
** This program is free software; you can redistribute it and/or |
|
6
|
** modify it under the terms of the Simplified BSD License (also |
|
7
|
** known as the "2-Clause License" or "FreeBSD License".) |
|
8
|
** |
|
9
|
** This program is distributed in the hope that it will be useful, |
|
10
|
** but without any warranty; without even the implied warranty of |
|
11
|
** merchantability or fitness for a particular purpose. |
|
12
|
** |
|
13
|
** Author contact information: |
|
14
|
** [email protected] |
|
15
|
** http://www.hwaci.com/drh/ |
|
16
|
** |
|
17
|
*/ |
|
18
|
#include "VERSION.h" |
|
19
|
#include "config.h" |
|
20
|
#include "json_finfo.h" |
|
21
|
|
|
22
|
#if INTERFACE |
|
23
|
#include "json_detail.h" |
|
24
|
#endif |
|
25
|
|
|
26
|
/* |
|
27
|
** Implements the /json/finfo page/command. |
|
28
|
** |
|
29
|
*/ |
|
30
|
cson_value * json_page_finfo(void){ |
|
31
|
cson_object * pay = NULL; |
|
32
|
cson_array * checkins = NULL; |
|
33
|
char const * zFilename = NULL; |
|
34
|
Blob sql = empty_blob; |
|
35
|
Stmt q = empty_Stmt; |
|
36
|
char const * zAfter = NULL; |
|
37
|
char const * zBefore = NULL; |
|
38
|
int limit = -1; |
|
39
|
int currentRow = 0; |
|
40
|
char const * zCheckin = NULL; |
|
41
|
signed char sort = -1; |
|
42
|
if(!g.perm.Read){ |
|
43
|
json_set_err(FSL_JSON_E_DENIED,"Requires 'o' privileges."); |
|
44
|
return NULL; |
|
45
|
} |
|
46
|
json_warn( FSL_JSON_W_UNKNOWN, |
|
47
|
"Achtung: the output of the finfo command is up for change."); |
|
48
|
|
|
49
|
/* For the "name" argument we have to jump through some hoops to make sure |
|
50
|
that we don't get the fossil-internally-assigned "name" option. |
|
51
|
*/ |
|
52
|
zFilename = json_find_option_cstr2("name",NULL,NULL, g.json.dispatchDepth+1); |
|
53
|
if(!zFilename || !*zFilename){ |
|
54
|
json_set_err(FSL_JSON_E_MISSING_ARGS, "Missing 'name' parameter."); |
|
55
|
return NULL; |
|
56
|
} |
|
57
|
|
|
58
|
if(0==db_int(0,"SELECT 1 FROM filename WHERE name=%Q",zFilename)){ |
|
59
|
json_set_err(FSL_JSON_E_RESOURCE_NOT_FOUND, "File entry not found."); |
|
60
|
return NULL; |
|
61
|
} |
|
62
|
|
|
63
|
zBefore = json_find_option_cstr("before",NULL,"b"); |
|
64
|
zAfter = json_find_option_cstr("after",NULL,"a"); |
|
65
|
limit = json_find_option_int("limit",NULL,"n", -1); |
|
66
|
zCheckin = json_find_option_cstr("checkin",NULL,"ci"); |
|
67
|
|
|
68
|
blob_append_sql(&sql, |
|
69
|
/*0*/ "SELECT b.uuid," |
|
70
|
/*1*/ " ci.uuid," |
|
71
|
/*2*/ " (SELECT uuid FROM blob WHERE rid=mlink.fid),"/* Current file uuid */ |
|
72
|
/*3*/ " cast(strftime('%%s',event.mtime) AS INTEGER)," |
|
73
|
/*4*/ " coalesce(event.euser, event.user)," |
|
74
|
/*5*/ " coalesce(event.ecomment, event.comment)," |
|
75
|
/*6*/ " (SELECT uuid FROM blob WHERE rid=mlink.pid)," /* Parent file uuid */ |
|
76
|
/*7*/ " event.bgcolor," |
|
77
|
/*8*/ " b.size," |
|
78
|
/*9*/ " (mlink.pid==0) AS isNew," |
|
79
|
/*10*/ " (mlink.fid==0) AS isDel" |
|
80
|
" FROM mlink, blob b, event, blob ci, filename" |
|
81
|
" WHERE filename.name=%Q" |
|
82
|
" AND mlink.fnid=filename.fnid" |
|
83
|
" AND b.rid=mlink.fid" |
|
84
|
" AND event.objid=mlink.mid" |
|
85
|
" AND event.objid=ci.rid", |
|
86
|
zFilename |
|
87
|
); |
|
88
|
|
|
89
|
if( zCheckin && *zCheckin ){ |
|
90
|
char * zU = NULL; |
|
91
|
int rc = name_to_uuid2( zCheckin, "ci", &zU ); |
|
92
|
/*printf("zCheckin=[%s], zU=[%s]", zCheckin, zU);*/ |
|
93
|
if(rc<=0){ |
|
94
|
json_set_err((rc<0) ? FSL_JSON_E_AMBIGUOUS_UUID : |
|
95
|
FSL_JSON_E_RESOURCE_NOT_FOUND, |
|
96
|
"Check-in hash %s.", (rc<0) ? "is ambiguous" : "not found"); |
|
97
|
blob_reset(&sql); |
|
98
|
return NULL; |
|
99
|
} |
|
100
|
blob_append_sql(&sql, " AND ci.uuid='%q'", zU); |
|
101
|
free(zU); |
|
102
|
}else{ |
|
103
|
if( zAfter && *zAfter ){ |
|
104
|
blob_append_sql(&sql, " AND event.mtime>=julianday('%q')", zAfter); |
|
105
|
sort = 1; |
|
106
|
}else if( zBefore && *zBefore ){ |
|
107
|
blob_append_sql(&sql, " AND event.mtime<=julianday('%q')", zBefore); |
|
108
|
} |
|
109
|
} |
|
110
|
|
|
111
|
blob_append_sql(&sql," ORDER BY event.mtime %s /*sort*/", |
|
112
|
(sort>0 ? "ASC" : "DESC")); |
|
113
|
/*printf("SQL=\n%s\n",blob_str(&sql));*/ |
|
114
|
db_prepare(&q, "%s", blob_sql_text(&sql)); |
|
115
|
blob_reset(&sql); |
|
116
|
|
|
117
|
pay = cson_new_object(); |
|
118
|
cson_object_set(pay, "name", json_new_string(zFilename)); |
|
119
|
if( limit > 0 ){ |
|
120
|
cson_object_set(pay, "limit", json_new_int(limit)); |
|
121
|
} |
|
122
|
checkins = cson_new_array(); |
|
123
|
cson_object_set(pay, "checkins", cson_array_value(checkins)); |
|
124
|
while( db_step(&q)==SQLITE_ROW ){ |
|
125
|
cson_object * row = cson_new_object(); |
|
126
|
int const isNew = db_column_int(&q,9); |
|
127
|
int const isDel = db_column_int(&q,10); |
|
128
|
cson_array_append( checkins, cson_object_value(row) ); |
|
129
|
cson_object_set(row, "checkin", json_new_string( db_column_text(&q,1) )); |
|
130
|
cson_object_set(row, "uuid", json_new_string( db_column_text(&q,2) )); |
|
131
|
/*cson_object_set(row, "parentArtifact", |
|
132
|
json_new_string( db_column_text(&q,6) ));*/ |
|
133
|
cson_object_set(row, "timestamp", json_new_int( db_column_int64(&q,3) )); |
|
134
|
cson_object_set(row, "user", json_new_string( db_column_text(&q,4) )); |
|
135
|
cson_object_set(row, "comment", json_new_string( db_column_text(&q,5) )); |
|
136
|
/*cson_object_set(row, "bgColor", |
|
137
|
json_new_string( db_column_text(&q,7) ));*/ |
|
138
|
cson_object_set(row, "size", json_new_int( db_column_int64(&q,8) )); |
|
139
|
cson_object_set(row, "state", json_new_string( |
|
140
|
json_artifact_status_to_string(isNew, isDel))); |
|
141
|
if( (0 < limit) && (++currentRow >= limit) ){ |
|
142
|
break; |
|
143
|
} |
|
144
|
} |
|
145
|
db_finalize(&q); |
|
146
|
|
|
147
|
return pay ? cson_object_value(pay) : NULL; |
|
148
|
} |
|
149
|
|
|
150
|
|
|
151
|
|
|
152
|
#endif /* FOSSIL_ENABLE_JSON */ |
|
153
|
|