Fossil SCM

experimental CLI version of rss feed, per ML request.

stephan 2014-01-18 08:33 UTC trunk
Commit e28a5765faf5aeac7e40ffea2ab96d8f0d548b8d
1 file changed +170
+170
--- src/rss.c
+++ src/rss.c
@@ -196,10 +196,180 @@
196196
}
197197
198198
db_finalize(&q);
199199
@ </channel>
200200
@ </rss>
201
+
202
+ if( zFreeProjectName != 0 ){
203
+ free( zFreeProjectName );
204
+ }
205
+}
206
+
207
+/*
208
+** COMMAND: rss
209
+**
210
+** The CLI variant of the /timeline.rss page.
211
+*/
212
+void cmd_timeline_rss(void){
213
+ Stmt q;
214
+ int nLine=0;
215
+ char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
216
+ Blob bSQL;
217
+ const char *zType = find_option("y",NULL,1); /* Type of events. All if NULL */
218
+ const char *zTicketUuid = find_option("tkt",NULL,1);
219
+ const char *zTag = find_option("tag",NULL,1);
220
+ const char *zFilename = find_option("name",NULL,1);
221
+ const char *zWiki = find_option("wiki",NULL,1);
222
+ const char *zLimit = find_option("limit", "n",1);
223
+ int nLimit = atoi( (zLimit && *zLimit) ? zLimit : "20" );
224
+ int nTagId;
225
+ const char zSQL1[] =
226
+ @ SELECT
227
+ @ blob.rid,
228
+ @ uuid,
229
+ @ event.mtime,
230
+ @ coalesce(ecomment,comment),
231
+ @ coalesce(euser,user),
232
+ @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
233
+ @ (SELECT count(*) FROM plink WHERE cid=blob.rid)
234
+ @ FROM event, blob
235
+ @ WHERE blob.rid=event.objid
236
+ ;
237
+ if(!zType || !*zType){
238
+ zType = "all";
239
+ }
240
+
241
+ db_find_and_open_repository(0, 0);
242
+
243
+ blob_zero(&bSQL);
244
+ blob_append( &bSQL, zSQL1, -1 );
245
+
246
+ if( zType[0]!='a' ){
247
+ if( zType[0]=='c' && !g.perm.Read ) zType = "x";
248
+ if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
249
+ if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
250
+ blob_appendf(&bSQL, " AND event.type=%Q", zType);
251
+ }else{
252
+ if( !g.perm.Read ){
253
+ if( g.perm.RdTkt && g.perm.RdWiki ){
254
+ blob_append(&bSQL, " AND event.type!='ci'", -1);
255
+ }else if( g.perm.RdTkt ){
256
+ blob_append(&bSQL, " AND event.type=='t'", -1);
257
+
258
+ }else{
259
+ blob_append(&bSQL, " AND event.type=='w'", -1);
260
+ }
261
+ }else if( !g.perm.RdWiki ){
262
+ if( g.perm.RdTkt ){
263
+ blob_append(&bSQL, " AND event.type!='w'", -1);
264
+ }else{
265
+ blob_append(&bSQL, " AND event.type=='ci'", -1);
266
+ }
267
+ }else if( !g.perm.RdTkt ){
268
+ assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
269
+ blob_append(&bSQL, " AND event.type!='t'", -1);
270
+ }
271
+ }
272
+
273
+ if( zTicketUuid ){
274
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
275
+ zTicketUuid);
276
+ if ( nTagId==0 ){
277
+ nTagId = -1;
278
+ }
279
+ }else if( zTag ){
280
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'",
281
+ zTag);
282
+ if ( nTagId==0 ){
283
+ nTagId = -1;
284
+ }
285
+ }else if( zWiki ){
286
+ nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'",
287
+ zWiki);
288
+ if ( nTagId==0 ){
289
+ nTagId = -1;
290
+ }
291
+ }else{
292
+ nTagId = 0;
293
+ }
294
+
295
+ if( nTagId==-1 ){
296
+ blob_appendf(&bSQL, " AND 0");
297
+ }else if( nTagId!=0 ){
298
+ blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
299
+ " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
300
+ }
301
+
302
+ if( zFilename ){
303
+ blob_appendf(&bSQL,
304
+ " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
305
+ zFilename, filename_collation()
306
+ );
307
+ }
308
+
309
+ blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
310
+
311
+ zProjectName = db_get("project-name", 0);
312
+ if( zProjectName==0 ){
313
+ zFreeProjectName = zProjectName = mprintf("Fossil source repository for: %s",
314
+ g.zBaseURL);
315
+ }
316
+ zProjectDescr = db_get("project-description", 0);
317
+ if( zProjectDescr==0 ){
318
+ zProjectDescr = zProjectName;
319
+ }
320
+
321
+ zPubDate = cgi_rfc822_datestamp(time(NULL));
322
+
323
+ fossil_print("<?xml version=\"1.0\"?>");
324
+ fossil_print("<rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" version=\"2.0\">");
325
+ fossil_print("<channel>\n");
326
+ fossil_print("<title>%h</title>\n", zProjectName);
327
+ fossil_print("<link>%s</link>\n", g.zBaseURL);
328
+ fossil_print("<description>%h</description>\n", zProjectDescr);
329
+ fossil_print("<pubDate>%s</pubDate>\n", zPubDate);
330
+ fossil_print("<generator>Fossil version %s %s</generator>\n",
331
+ MANIFEST_VERSION, MANIFEST_DATE);
332
+ free(zPubDate);
333
+ db_prepare(&q, blob_str(&bSQL));
334
+ blob_reset( &bSQL );
335
+ while( db_step(&q)==SQLITE_ROW && nLine<=nLimit ){
336
+ const char *zId = db_column_text(&q, 1);
337
+ const char *zCom = db_column_text(&q, 3);
338
+ const char *zAuthor = db_column_text(&q, 4);
339
+ char *zPrefix = "";
340
+ char *zDate;
341
+ int nChild = db_column_int(&q, 5);
342
+ int nParent = db_column_int(&q, 6);
343
+ time_t ts;
344
+
345
+ ts = (time_t)((db_column_double(&q,2) - 2440587.5)*86400.0);
346
+ zDate = cgi_rfc822_datestamp(ts);
347
+
348
+ if( nParent>1 && nChild>1 ){
349
+ zPrefix = "*MERGE/FORK* ";
350
+ }else if( nParent>1 ){
351
+ zPrefix = "*MERGE* ";
352
+ }else if( nChild>1 ){
353
+ zPrefix = "*FORK* ";
354
+ }
355
+
356
+ fossil_print("<item>");
357
+ fossil_print("<title>%s%h</title>\n", zPrefix, zCom);
358
+ fossil_print("<link>%s/info/%s</link>\n", g.zBaseURL, zId);
359
+ fossil_print("<description>%s%h</description>\n", zPrefix, zCom);
360
+ fossil_print("<pubDate>%s</pubDate>\n", zDate);
361
+ fossil_print("<dc:creator>%h</dc:creator>\n", zAuthor);
362
+ fossil_print("<guid>%s/info/%s</guid>\n", g.zBaseURL, zId);
363
+ fossil_print("</item>\n");
364
+ free(zDate);
365
+ nLine++;
366
+ }
367
+
368
+ db_finalize(&q);
369
+ fossil_print("</channel>\n");
370
+ fossil_print("</rss>\n");
201371
202372
if( zFreeProjectName != 0 ){
203373
free( zFreeProjectName );
204374
}
205375
}
206376
--- src/rss.c
+++ src/rss.c
@@ -196,10 +196,180 @@
196 }
197
198 db_finalize(&q);
199 @ </channel>
200 @ </rss>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
202 if( zFreeProjectName != 0 ){
203 free( zFreeProjectName );
204 }
205 }
206
--- src/rss.c
+++ src/rss.c
@@ -196,10 +196,180 @@
196 }
197
198 db_finalize(&q);
199 @ </channel>
200 @ </rss>
201
202 if( zFreeProjectName != 0 ){
203 free( zFreeProjectName );
204 }
205 }
206
207 /*
208 ** COMMAND: rss
209 **
210 ** The CLI variant of the /timeline.rss page.
211 */
212 void cmd_timeline_rss(void){
213 Stmt q;
214 int nLine=0;
215 char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0;
216 Blob bSQL;
217 const char *zType = find_option("y",NULL,1); /* Type of events. All if NULL */
218 const char *zTicketUuid = find_option("tkt",NULL,1);
219 const char *zTag = find_option("tag",NULL,1);
220 const char *zFilename = find_option("name",NULL,1);
221 const char *zWiki = find_option("wiki",NULL,1);
222 const char *zLimit = find_option("limit", "n",1);
223 int nLimit = atoi( (zLimit && *zLimit) ? zLimit : "20" );
224 int nTagId;
225 const char zSQL1[] =
226 @ SELECT
227 @ blob.rid,
228 @ uuid,
229 @ event.mtime,
230 @ coalesce(ecomment,comment),
231 @ coalesce(euser,user),
232 @ (SELECT count(*) FROM plink WHERE pid=blob.rid AND isprim),
233 @ (SELECT count(*) FROM plink WHERE cid=blob.rid)
234 @ FROM event, blob
235 @ WHERE blob.rid=event.objid
236 ;
237 if(!zType || !*zType){
238 zType = "all";
239 }
240
241 db_find_and_open_repository(0, 0);
242
243 blob_zero(&bSQL);
244 blob_append( &bSQL, zSQL1, -1 );
245
246 if( zType[0]!='a' ){
247 if( zType[0]=='c' && !g.perm.Read ) zType = "x";
248 if( zType[0]=='w' && !g.perm.RdWiki ) zType = "x";
249 if( zType[0]=='t' && !g.perm.RdTkt ) zType = "x";
250 blob_appendf(&bSQL, " AND event.type=%Q", zType);
251 }else{
252 if( !g.perm.Read ){
253 if( g.perm.RdTkt && g.perm.RdWiki ){
254 blob_append(&bSQL, " AND event.type!='ci'", -1);
255 }else if( g.perm.RdTkt ){
256 blob_append(&bSQL, " AND event.type=='t'", -1);
257
258 }else{
259 blob_append(&bSQL, " AND event.type=='w'", -1);
260 }
261 }else if( !g.perm.RdWiki ){
262 if( g.perm.RdTkt ){
263 blob_append(&bSQL, " AND event.type!='w'", -1);
264 }else{
265 blob_append(&bSQL, " AND event.type=='ci'", -1);
266 }
267 }else if( !g.perm.RdTkt ){
268 assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki );
269 blob_append(&bSQL, " AND event.type!='t'", -1);
270 }
271 }
272
273 if( zTicketUuid ){
274 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'",
275 zTicketUuid);
276 if ( nTagId==0 ){
277 nTagId = -1;
278 }
279 }else if( zTag ){
280 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'",
281 zTag);
282 if ( nTagId==0 ){
283 nTagId = -1;
284 }
285 }else if( zWiki ){
286 nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'",
287 zWiki);
288 if ( nTagId==0 ){
289 nTagId = -1;
290 }
291 }else{
292 nTagId = 0;
293 }
294
295 if( nTagId==-1 ){
296 blob_appendf(&bSQL, " AND 0");
297 }else if( nTagId!=0 ){
298 blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref"
299 " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId);
300 }
301
302 if( zFilename ){
303 blob_appendf(&bSQL,
304 " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)",
305 zFilename, filename_collation()
306 );
307 }
308
309 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 );
310
311 zProjectName = db_get("project-name", 0);
312 if( zProjectName==0 ){
313 zFreeProjectName = zProjectName = mprintf("Fossil source repository for: %s",
314 g.zBaseURL);
315 }
316 zProjectDescr = db_get("project-description", 0);
317 if( zProjectDescr==0 ){
318 zProjectDescr = zProjectName;
319 }
320
321 zPubDate = cgi_rfc822_datestamp(time(NULL));
322
323 fossil_print("<?xml version=\"1.0\"?>");
324 fossil_print("<rss xmlns:dc=\"http://purl.org/dc/elements/1.1/\" version=\"2.0\">");
325 fossil_print("<channel>\n");
326 fossil_print("<title>%h</title>\n", zProjectName);
327 fossil_print("<link>%s</link>\n", g.zBaseURL);
328 fossil_print("<description>%h</description>\n", zProjectDescr);
329 fossil_print("<pubDate>%s</pubDate>\n", zPubDate);
330 fossil_print("<generator>Fossil version %s %s</generator>\n",
331 MANIFEST_VERSION, MANIFEST_DATE);
332 free(zPubDate);
333 db_prepare(&q, blob_str(&bSQL));
334 blob_reset( &bSQL );
335 while( db_step(&q)==SQLITE_ROW && nLine<=nLimit ){
336 const char *zId = db_column_text(&q, 1);
337 const char *zCom = db_column_text(&q, 3);
338 const char *zAuthor = db_column_text(&q, 4);
339 char *zPrefix = "";
340 char *zDate;
341 int nChild = db_column_int(&q, 5);
342 int nParent = db_column_int(&q, 6);
343 time_t ts;
344
345 ts = (time_t)((db_column_double(&q,2) - 2440587.5)*86400.0);
346 zDate = cgi_rfc822_datestamp(ts);
347
348 if( nParent>1 && nChild>1 ){
349 zPrefix = "*MERGE/FORK* ";
350 }else if( nParent>1 ){
351 zPrefix = "*MERGE* ";
352 }else if( nChild>1 ){
353 zPrefix = "*FORK* ";
354 }
355
356 fossil_print("<item>");
357 fossil_print("<title>%s%h</title>\n", zPrefix, zCom);
358 fossil_print("<link>%s/info/%s</link>\n", g.zBaseURL, zId);
359 fossil_print("<description>%s%h</description>\n", zPrefix, zCom);
360 fossil_print("<pubDate>%s</pubDate>\n", zDate);
361 fossil_print("<dc:creator>%h</dc:creator>\n", zAuthor);
362 fossil_print("<guid>%s/info/%s</guid>\n", g.zBaseURL, zId);
363 fossil_print("</item>\n");
364 free(zDate);
365 nLine++;
366 }
367
368 db_finalize(&q);
369 fossil_print("</channel>\n");
370 fossil_print("</rss>\n");
371
372 if( zFreeProjectName != 0 ){
373 free( zFreeProjectName );
374 }
375 }
376

Keyboard Shortcuts

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