Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch timeline-rss-ticket Excluding Merge-Ins
This is equivalent to a diff from fab09a1710 to 1c46835e4c
2013-02-18
| ||
21:45 | /info/TICKET_UUID now only shows the ticket title if the ticket db has a title field. Leaf check-in: 1c46835e4c user: stephan tags: timeline-rss-ticket | |
2013-02-12
| ||
16:57 | Update src/rss.c with latest version from dg-misc branch (original at [01e85ec4]). check-in: a10282407c user: dg tags: timeline-rss-ticket | |
11:53 | Replaced a call to realloc() with cson_realloc() (which, in turn, uses the fossil realloc). check-in: a1d2cd84b8 user: stephan tags: trunk | |
10:08 | timeline.rss with single-ticket support, based on David Given's patch. check-in: 1bc09124bd user: stephan tags: timeline-rss-ticket | |
2013-02-11
| ||
19:30 | Merging from trunk. I still have merge conflicts since my previous merge. check-in: bdeb633a6c user: viriketo tags: annotate_links | |
2013-02-08
| ||
09:37 | Eliminate use of starts_with_utf16(be|le)_bom functions, starts_with_utf16_bom should be enough. External code will typically call "starts_with_utf16_bom" first, and if it returns true call "blob_to_utf8_no_bom" converting it to utf-8. There is no reason any more then for external code to know wheter the BOM was le or be. check-in: fab09a1710 user: jan.nijtmans tags: trunk | |
08:55 | Addendum to previous commit: Allow the user to decide whether the "fossil knows nothing about" warning should abort the commit or not. check-in: c31bbd4084 user: jan.nijtmans tags: trunk | |
Changes to src/db.c.
1870 1870 } 1871 1871 int db_lget_int(const char *zName, int dflt){ 1872 1872 return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName); 1873 1873 } 1874 1874 void db_lset_int(const char *zName, int value){ 1875 1875 db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value); 1876 1876 } 1877 + 1878 +/* 1879 +** Returns non-0 if the database (which must be open) table identified 1880 +** by zTableName has a column named zColName (case-sensitive), else 1881 +** returns 0. 1882 +*/ 1883 +int db_table_has_column( char const *zTableName, char const *zColName ){ 1884 + Stmt q = empty_Stmt; 1885 + int rc = 0; 1886 + db_prepare( &q, "PRAGMA table_info(%Q)", zTableName ); 1887 + while(SQLITE_ROW == db_step(&q)){ 1888 + /* Columns: (cid, name, type, notnull, dflt_value, pk) */ 1889 + char const * zCol = db_column_text(&q, 1); 1890 + if(0==fossil_strcmp(zColName, zCol)){ 1891 + rc = 1; 1892 + break; 1893 + } 1894 + } 1895 + db_finalize(&q); 1896 + return rc; 1897 +} 1877 1898 1878 1899 /* 1879 1900 ** Record the name of a local repository in the global_config() database. 1880 1901 ** The repository filename %s is recorded as an entry with a "name" field 1881 1902 ** of the following form: 1882 1903 ** 1883 1904 ** repo:%s
Changes to src/info.c.
1721 1721 int rid; 1722 1722 char *zDate; 1723 1723 const char *zUuid; 1724 1724 char zTktName[UUID_SIZE+1]; 1725 1725 Manifest *pTktChng; 1726 1726 int modPending; 1727 1727 const char *zModAction; 1728 - 1728 + char *zTktTitle; 1729 1729 login_check_credentials(); 1730 1730 if( !g.perm.RdTkt ){ login_needed(); return; } 1731 1731 rid = name_to_rid_www("name"); 1732 1732 if( rid==0 ){ fossil_redirect_home(); } 1733 1733 zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid); 1734 1734 if( g.perm.Admin ){ 1735 1735 if( db_exists("SELECT 1 FROM shun WHERE uuid='%s'", zUuid) ){ ................................................................................ 1750 1750 cgi_redirectf("%R/tktview/%s", zTktName); 1751 1751 /*NOTREACHED*/ 1752 1752 } 1753 1753 if( strcmp(zModAction,"approve")==0 ){ 1754 1754 moderation_approve(rid); 1755 1755 } 1756 1756 } 1757 + zTktTitle = db_table_has_column( "ticket", "title" ) 1758 + ? db_text("(No title)", "SELECT title FROM ticket WHERE tkt_uuid=%Q", zTktName) 1759 + : 0; 1757 1760 style_header("Ticket Change Details"); 1758 1761 style_submenu_element("Raw", "Raw", "%R/artifact/%S", zUuid); 1759 1762 style_submenu_element("History", "History", "%R/tkthistory/%s", zTktName); 1760 1763 style_submenu_element("Page", "Page", "%R/tktview/%t", zTktName); 1761 1764 style_submenu_element("Timeline", "Timeline", "%R/tkttimeline/%t", zTktName); 1762 1765 if( P("plaintext") ){ 1763 1766 style_submenu_element("Formatted", "Formatted", "%R/info/%S", zUuid); ................................................................................ 1774 1777 @ (%d(rid)) 1775 1778 } 1776 1779 modPending = moderation_pending(rid); 1777 1780 if( modPending ){ 1778 1781 @ <span class="modpending">*** Awaiting Moderator Approval ***</span> 1779 1782 } 1780 1783 @ <tr><th>Ticket:</th> 1781 - @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></td></tr> 1784 + @ <td>%z(href("%R/tktview/%s",zTktName))%s(zTktName)</a> 1785 + if(zTktTitle){ 1786 + @<br>%h(zTktTitle) 1787 + } 1788 + @</td></tr> 1782 1789 @ <tr><th>Date:</th><td> 1783 1790 hyperlink_to_date(zDate, "</td></tr>"); 1784 1791 @ <tr><th>User:</th><td> 1785 1792 hyperlink_to_user(pTktChng->zUser, zDate, "</td></tr>"); 1786 1793 @ </table> 1787 1794 free(zDate); 1795 + free(zTktTitle); 1788 1796 1789 1797 if( g.perm.ModTkt && modPending ){ 1790 1798 @ <div class="section">Moderation</div> 1791 1799 @ <blockquote> 1792 1800 @ <form method="POST" action="%R/tinfo/%s(zUuid)"> 1793 1801 @ <label><input type="radio" name="modaction" value="delete"> 1794 1802 @ Delete this change</label><br />
Changes to src/rss.c.
20 20 #include "config.h" 21 21 #include <time.h> 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&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). 27 40 */ 41 + 28 42 void page_timeline_rss(void){ 29 43 Stmt q; 30 44 int nLine=0; 31 45 char *zPubDate, *zProjectName, *zProjectDescr, *zFreeProjectName=0; 32 46 Blob bSQL; 33 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); 34 52 int nLimit = atoi(PD("n","20")); 53 + int nTagId; 35 54 const char zSQL1[] = 36 55 @ SELECT 37 56 @ blob.rid, 38 57 @ uuid, 39 58 @ event.mtime, 40 59 @ coalesce(ecomment,comment), 41 60 @ coalesce(euser,user), ................................................................................ 60 79 blob_appendf(&bSQL, " AND event.type=%Q", zType); 61 80 }else{ 62 81 if( !g.perm.Read ){ 63 82 if( g.perm.RdTkt && g.perm.RdWiki ){ 64 83 blob_append(&bSQL, " AND event.type!='ci'", -1); 65 84 }else if( g.perm.RdTkt ){ 66 85 blob_append(&bSQL, " AND event.type=='t'", -1); 86 + 67 87 }else{ 68 88 blob_append(&bSQL, " AND event.type=='w'", -1); 69 89 } 70 90 }else if( !g.perm.RdWiki ){ 71 91 if( g.perm.RdTkt ){ 72 92 blob_append(&bSQL, " AND event.type!='w'", -1); 73 93 }else{ ................................................................................ 74 94 blob_append(&bSQL, " AND event.type=='ci'", -1); 75 95 } 76 96 }else if( !g.perm.RdTkt ){ 77 97 assert( !g.perm.RdTkt &&& g.perm.Read && g.perm.RdWiki ); 78 98 blob_append(&bSQL, " AND event.type!='t'", -1); 79 99 } 80 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 + } 81 137 82 138 blob_append( &bSQL, " ORDER BY event.mtime DESC", -1 ); 83 139 84 140 cgi_set_content_type("application/rss+xml"); 85 141 86 142 zProjectName = db_get("project-name", 0); 87 143 if( zProjectName==0 ){