@@ -29,15 +29,35 @@
#include "config.h"
#include "timeline.h"
/*
+** Shorten a UUID so that is the minimum length needed to contain
+** at least one digit in the range 'a'..'f'. The minimum length is 10.
+*/
+static void shorten_uuid(char *zDest, const char *zSrc){
+ int i;
+ for(i=0; i<10 && zSrc[i]<='9'; i++){}
+ memcpy(zDest, zSrc, 10);
+ if( i==10 ){
+ do{
+ zDest[i] = zSrc[i];
+ i++;
+ }while( zSrc[i-1]<='9' );
+ }else{
+ i = 10;
+ }
+ zDest[i] = 0;
+}
+
+
+/*
** Generate a hyperlink to a version.
*/
void hyperlink_to_uuid(const char *zUuid){
char zShortUuid[UUID_SIZE+1];
- sprintf(zShortUuid, "%.10s", zUuid);
+ shorten_uuid(zShortUuid, zUuid);
if( g.okHistory ){
- @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">[%s(zShortUuid)]</a>
+ @ <a href="%s(g.zBaseURL)/info/%s(zShortUuid)">[%s(zShortUuid)]</a>
}else{
@ <b>[%s(zShortUuid)]</b>
}
}
@@ -52,12 +72,12 @@
const char *zOut, /* Javascript proc for mouseout */
int id /* Argument to javascript procs */
){
char zShortUuid[UUID_SIZE+1];
- sprintf(zShortUuid, "%.10s", zUuid);
+ shorten_uuid(zShortUuid, zUuid);
if( g.okHistory ){
@ <a onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'
- @ href="%s(g.zBaseURL)/vinfo/%s(zUuid)">[%s(zShortUuid)]</a>
+ @ href="%s(g.zBaseURL)/vinfo/%s(zShortUuid)">[%s(zShortUuid)]</a>
}else{
@ <b onmouseover='%s(zIn)("m%d(id)")' onmouseout='%s(zOut)("m%d(id)")'>
@ [%s(zShortUuid)]</b>
}
@@ -398,8 +418,9 @@
** d=RID artifact RID and up to COUNT descendants
** t=TAGID show only check-ins with the given tagid
** u=USER only if belonging to this user
** y=TYPE 'ci', 'w', 't'
+** s=TEXT string search (comment and brief)
**
** p= and d= can appear individually or together. If either p= or d=
** appear, then u=, y=, a=, and b= are ignored.
**
@@ -420,8 +441,9 @@
const char *zAfter = P("a"); /* Events after this time */
const char *zBefore = P("b"); /* Events before this time */
const char *zCirca = P("c"); /* Events near this time */
const char *zTagName = P("t"); /* Show events with this tag */
+ const char *zString = P("s"); /* String text search of comment and brief */
HQuery url; /* URL for various branch links */
int tagid; /* Tag ID */
int tmFlags; /* Timeline flags */
@@ -465,11 +487,11 @@
nd = 0;
if( d_rid ){
compute_descendants(d_rid, nEntry+1);
nd = db_int(0, "SELECT count(*)-1 FROM ok");
- if( nd>0 ){
+ if( nd>=0 ){
db_multi_exec("%s", blob_str(&sql));
- blob_appendf(&desc, "%d descendants", nd);
+ blob_appendf(&desc, "%d descendant%s", nd,(1==nd)?"":"s");
}
timeline_add_dividers(
db_text("1","SELECT datetime(mtime,'localtime') FROM event"
" WHERE objid=%d", d_rid)
@@ -524,8 +546,13 @@
}
if( zUser ){
blob_appendf(&sql, " AND event.user=%Q", zUser);
url_add_parameter(&url, "u", zUser);
+ }
+ if ( zString ){
+ blob_appendf(&sql, " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
+ zString, zString);
+ url_add_parameter(&url, "s", zString);
}
if( zAfter ){
while( isspace(zAfter[0]) ){ zAfter++; }
if( zAfter[0] ){
@@ -828,29 +855,8 @@
return zBaseSql;
}
/*
-** Equivalent to timeline_query_for_tty(), except that:
-**
-** a) accepts a the -type=XX flag to set the event type to filter on.
-** The values of XX are the same as supported by the /timeline page.
-**
-** b) The returned string must be freed using free().
-*/
-char * timeline_query_for_tty_m(void){
- Blob bl;
- char const * zType = 0;
- blob_zero(&bl);
- blob_append( &bl, timeline_query_for_tty(), -1 );
- zType = find_option( "type", "t", 1 );
- if( zType && *zType )
- {
- blob_appendf( &bl, " AND event.type=%Q", zType );
- }
- return blob_buffer(&bl);
-}
-
-/*
** Return true if the input string is a date in the ISO 8601 format:
** YYYY-MM-DD.
*/
static int isIsoDate(const char *z){
@@ -895,9 +901,9 @@
const char *zCount;
const char *zType;
char *zOrigin;
char *zDate;
- char *zSQL;
+ Blob sql;
int objid = 0;
Blob uuid;
int mode = 0 ; /* 0:none 1: before 2:after 3:children 4:parents */
db_find_and_open_repository(1);
@@ -962,29 +968,31 @@
}
zDate = mprintf("(SELECT julianday(%Q%s, 'utc'))", zOrigin, zShift);
}
if( mode==0 ) mode = 1;
- zSQL = mprintf("%z AND event.mtime %s %s",
- timeline_query_for_tty_m(),
+ blob_zero(&sql);
+ blob_append(&sql, timeline_query_for_tty(), -1);
+ blob_appendf(&sql, " AND event.mtime %s %s",
(mode==1 || mode==4) ? "<=" : ">=",
zDate
);
+
if( mode==3 || mode==4 ){
db_multi_exec("CREATE TEMP TABLE ok(rid INTEGER PRIMARY KEY)");
if( mode==3 ){
compute_descendants(objid, n);
}else{
compute_ancestors(objid, n);
}
- zSQL = mprintf("%z AND blob.rid IN ok", zSQL);
+ blob_appendf(&sql, " AND blob.rid IN ok");
}
if( zType && (zType[0]!='a') ){
- zSQL = mprintf( "%z AND event.type=%Q ", zSQL, zType);
+ blob_appendf(&sql, " AND event.type=%Q ", zType);
}
- zSQL = mprintf("%z ORDER BY event.mtime DESC", zSQL);
- db_prepare(&q, zSQL);
- free( zSQL );
+ blob_appendf(&sql, " ORDER BY event.mtime DESC");
+ db_prepare(&q, blob_str(&sql));
+ blob_reset(&sql);
print_timeline(&q, n);
db_finalize(&q);
}