Fossil SCM
Allow filtering by filename, tag or wiki page as well as by ticket UUID. Better handling of invalid values (they now generate empty RSS feeds rather than appending the HTML footer...).
Commit
d244452bda788c3f940a0a8b616827bd03ca5359
Parent
21da639fee8f1c1…
1 file changed
+43
-10
+43
-10
| --- src/rss.c | ||
| +++ src/rss.c | ||
| @@ -22,29 +22,37 @@ | ||
| 22 | 22 | #include "rss.h" |
| 23 | 23 | #include <assert.h> |
| 24 | 24 | |
| 25 | 25 | /* |
| 26 | 26 | ** WEBPAGE: timeline.rss |
| 27 | -** URL: /timeline.rss/y=TYPE&n=LIMIT&tkt=UUID | |
| 27 | +** URL: /timeline.rss/y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME | |
| 28 | 28 | ** |
| 29 | 29 | ** Produce an RSS feed of the timeline. |
| 30 | 30 | ** |
| 31 | 31 | ** TYPE may be: all, ci (show checkins only), t (show tickets only), |
| 32 | 32 | ** w (show wiki only). LIMIT is the number of items to show. |
| 33 | 33 | ** |
| 34 | -** If UUID is specified, then only changes for the specified ticket will | |
| 35 | -** be shown. It probably only makes sense to use y=t if you're doing this. | |
| 34 | +** tkt=UUID filters for only those events for the specified ticket. tag=TAG | |
| 35 | +** filters for a tag, and wiki=NAME for a wiki page. Only one may be used. | |
| 36 | +** | |
| 37 | +** In addition, name=FILENAME filters for a specific file. This may be | |
| 38 | +** combined with one of the other filters (useful for looking at a specific | |
| 39 | +** branch). | |
| 36 | 40 | */ |
| 37 | 41 | |
| 38 | 42 | void page_timeline_rss(void){ |
| 39 | 43 | Stmt q; |
| 40 | 44 | int nLine=0; |
| 41 | 45 | char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0; |
| 42 | 46 | Blob bSQL; |
| 43 | 47 | const char *zType = PD("y","all"); /* Type of events. All if NULL */ |
| 44 | 48 | const char *zTicketUuid = PD("tkt",NULL); |
| 49 | + const char *zTag = PD("tag",NULL); | |
| 50 | + const char *zFilename = PD("name",NULL); | |
| 51 | + const char *zWiki = PD("wiki",NULL); | |
| 45 | 52 | int nLimit = atoi(PD("n","20")); |
| 53 | + int nTagId; | |
| 46 | 54 | const char zSQL1[] = |
| 47 | 55 | @ SELECT |
| 48 | 56 | @ blob.rid, |
| 49 | 57 | @ uuid, |
| 50 | 58 | @ event.mtime, |
| @@ -89,19 +97,44 @@ | ||
| 89 | 97 | assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki ); |
| 90 | 98 | blob_append(&bSQL, " AND event.type!='t'", -1); |
| 91 | 99 | } |
| 92 | 100 | } |
| 93 | 101 | |
| 94 | - if ( zTicketUuid ){ | |
| 95 | - int nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", | |
| 102 | + if( zTicketUuid ){ | |
| 103 | + nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", | |
| 96 | 104 | zTicketUuid); |
| 97 | - if ( nTagId == 0 ){ | |
| 98 | - @ No such ticket: %h(zTicketUuid) | |
| 99 | - style_footer(); | |
| 100 | - return; | |
| 105 | + if ( nTagId==0 ){ | |
| 106 | + nTagId = -1; | |
| 107 | + } | |
| 108 | + }else if( zTag ){ | |
| 109 | + nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'", | |
| 110 | + zTag); | |
| 111 | + if ( nTagId==0 ){ | |
| 112 | + nTagId = -1; | |
| 113 | + } | |
| 114 | + }else if( zWiki ){ | |
| 115 | + nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'", | |
| 116 | + zWiki); | |
| 117 | + if ( nTagId==0 ){ | |
| 118 | + nTagId = -1; | |
| 101 | 119 | } |
| 102 | - blob_appendf(&bSQL, " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", nTagId); | |
| 120 | + }else{ | |
| 121 | + nTagId = 0; | |
| 122 | + } | |
| 123 | + | |
| 124 | + if( nTagId==-1 ){ | |
| 125 | + blob_appendf(&bSQL, " AND 0"); | |
| 126 | + }else if( nTagId!=0 ){ | |
| 127 | + blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref" | |
| 128 | + " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId); | |
| 129 | + } | |
| 130 | + | |
| 131 | + if( zFilename ){ | |
| 132 | + blob_appendf(&bSQL, | |
| 133 | + " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)", | |
| 134 | + zFilename, filename_collation() | |
| 135 | + ); | |
| 103 | 136 | } |
| 104 | 137 | |
| 105 | 138 | blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 ); |
| 106 | 139 | |
| 107 | 140 | cgi_set_content_type("application/rss+xml"); |
| 108 | 141 |
| --- src/rss.c | |
| +++ src/rss.c | |
| @@ -22,29 +22,37 @@ | |
| 22 | #include "rss.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | /* |
| 26 | ** WEBPAGE: timeline.rss |
| 27 | ** URL: /timeline.rss/y=TYPE&n=LIMIT&tkt=UUID |
| 28 | ** |
| 29 | ** Produce an RSS feed of the timeline. |
| 30 | ** |
| 31 | ** TYPE may be: all, ci (show checkins only), t (show tickets only), |
| 32 | ** w (show wiki only). LIMIT is the number of items to show. |
| 33 | ** |
| 34 | ** If UUID is specified, then only changes for the specified ticket will |
| 35 | ** be shown. It probably only makes sense to use y=t if you're doing this. |
| 36 | */ |
| 37 | |
| 38 | void page_timeline_rss(void){ |
| 39 | Stmt q; |
| 40 | int nLine=0; |
| 41 | char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0; |
| 42 | Blob bSQL; |
| 43 | const char *zType = PD("y","all"); /* Type of events. All if NULL */ |
| 44 | const char *zTicketUuid = PD("tkt",NULL); |
| 45 | int nLimit = atoi(PD("n","20")); |
| 46 | const char zSQL1[] = |
| 47 | @ SELECT |
| 48 | @ blob.rid, |
| 49 | @ uuid, |
| 50 | @ event.mtime, |
| @@ -89,19 +97,44 @@ | |
| 89 | assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki ); |
| 90 | blob_append(&bSQL, " AND event.type!='t'", -1); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | if ( zTicketUuid ){ |
| 95 | int nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", |
| 96 | zTicketUuid); |
| 97 | if ( nTagId == 0 ){ |
| 98 | @ No such ticket: %h(zTicketUuid) |
| 99 | style_footer(); |
| 100 | return; |
| 101 | } |
| 102 | blob_appendf(&bSQL, " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", nTagId); |
| 103 | } |
| 104 | |
| 105 | blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 ); |
| 106 | |
| 107 | cgi_set_content_type("application/rss+xml"); |
| 108 |
| --- src/rss.c | |
| +++ src/rss.c | |
| @@ -22,29 +22,37 @@ | |
| 22 | #include "rss.h" |
| 23 | #include <assert.h> |
| 24 | |
| 25 | /* |
| 26 | ** WEBPAGE: timeline.rss |
| 27 | ** URL: /timeline.rss/y=TYPE&n=LIMIT&tkt=UUID&tag=TAG&wiki=NAME&name=FILENAME |
| 28 | ** |
| 29 | ** Produce an RSS feed of the timeline. |
| 30 | ** |
| 31 | ** TYPE may be: all, ci (show checkins only), t (show tickets only), |
| 32 | ** w (show wiki only). LIMIT is the number of items to show. |
| 33 | ** |
| 34 | ** tkt=UUID filters for only those events for the specified ticket. tag=TAG |
| 35 | ** filters for a tag, and wiki=NAME for a wiki page. Only one may be used. |
| 36 | ** |
| 37 | ** In addition, name=FILENAME filters for a specific file. This may be |
| 38 | ** combined with one of the other filters (useful for looking at a specific |
| 39 | ** branch). |
| 40 | */ |
| 41 | |
| 42 | void page_timeline_rss(void){ |
| 43 | Stmt q; |
| 44 | int nLine=0; |
| 45 | char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0; |
| 46 | Blob bSQL; |
| 47 | const char *zType = PD("y","all"); /* Type of events. All if NULL */ |
| 48 | const char *zTicketUuid = PD("tkt",NULL); |
| 49 | const char *zTag = PD("tag",NULL); |
| 50 | const char *zFilename = PD("name",NULL); |
| 51 | const char *zWiki = PD("wiki",NULL); |
| 52 | int nLimit = atoi(PD("n","20")); |
| 53 | int nTagId; |
| 54 | const char zSQL1[] = |
| 55 | @ SELECT |
| 56 | @ blob.rid, |
| 57 | @ uuid, |
| 58 | @ event.mtime, |
| @@ -89,19 +97,44 @@ | |
| 97 | assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki ); |
| 98 | blob_append(&bSQL, " AND event.type!='t'", -1); |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | if( zTicketUuid ){ |
| 103 | nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'tkt-%q*'", |
| 104 | zTicketUuid); |
| 105 | if ( nTagId==0 ){ |
| 106 | nTagId = -1; |
| 107 | } |
| 108 | }else if( zTag ){ |
| 109 | nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'sym-%q*'", |
| 110 | zTag); |
| 111 | if ( nTagId==0 ){ |
| 112 | nTagId = -1; |
| 113 | } |
| 114 | }else if( zWiki ){ |
| 115 | nTagId = db_int(0, "SELECT tagid FROM tag WHERE tagname GLOB 'wiki-%q*'", |
| 116 | zWiki); |
| 117 | if ( nTagId==0 ){ |
| 118 | nTagId = -1; |
| 119 | } |
| 120 | }else{ |
| 121 | nTagId = 0; |
| 122 | } |
| 123 | |
| 124 | if( nTagId==-1 ){ |
| 125 | blob_appendf(&bSQL, " AND 0"); |
| 126 | }else if( nTagId!=0 ){ |
| 127 | blob_appendf(&bSQL, " AND (EXISTS(SELECT 1 FROM tagxref" |
| 128 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid))", nTagId); |
| 129 | } |
| 130 | |
| 131 | if( zFilename ){ |
| 132 | blob_appendf(&bSQL, |
| 133 | " AND (SELECT mlink.fnid FROM mlink WHERE event.objid=mlink.mid) IN (SELECT fnid FROM filename WHERE name=%Q %s)", |
| 134 | zFilename, filename_collation() |
| 135 | ); |
| 136 | } |
| 137 | |
| 138 | blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 ); |
| 139 | |
| 140 | cgi_set_content_type("application/rss+xml"); |
| 141 |