Index: src/tkt.c
==================================================================
--- src/tkt.c
+++ src/tkt.c
@@ -30,22 +30,27 @@
static int nField = 0;
static struct tktFieldInfo {
char *zName; /* Name of the database field */
char *zValue; /* Value to store */
char *zAppend; /* Value to append */
+ char *zBsln; /* "baseline for $zName" if that field exists*/
unsigned mUsed; /* 01: TICKET 02: TICKETCHNG */
} *aField;
#define USEDBY_TICKET 01
#define USEDBY_TICKETCHNG 02
#define USEDBY_BOTH 03
+#define JCARD_ASSIGN ('=')
+#define JCARD_APPEND ('+')
+#define JCARD_PRIVATE ('p')
static u8 haveTicket = 0; /* True if the TICKET table exists */
static u8 haveTicketCTime = 0; /* True if TICKET.TKT_CTIME exists */
static u8 haveTicketChng = 0; /* True if the TICKETCHNG table exists */
static u8 haveTicketChngRid = 0; /* True if TICKETCHNG.TKT_RID exists */
static u8 haveTicketChngUser = 0;/* True if TICKETCHNG.TKT_USER exists */
static u8 useTicketGenMt = 0; /* use generated TICKET.MIMETYPE */
static u8 useTicketChngGenMt = 0;/* use generated TICKETCHNG.MIMETYPE */
+static int nTicketBslns = 0; /* number of valid "baseline for ..." */
/*
** Compare two entries in aField[] for sorting purposes
*/
@@ -73,31 +78,56 @@
** The haveTicket and haveTicketChng variables are set to 1 if the TICKET and
** TICKETCHANGE tables exist, respectively.
*/
static void getAllTicketFields(void){
Stmt q;
- int i, noRegularMimetype;
+ int i, noRegularMimetype, nBaselines;
static int once = 0;
if( once ) return;
once = 1;
+ nBaselines = 0;
db_prepare(&q, "PRAGMA table_info(ticket)");
while( db_step(&q)==SQLITE_ROW ){
const char *zFieldName = db_column_text(&q, 1);
haveTicket = 1;
if( memcmp(zFieldName,"tkt_",4)==0 ){
if( strcmp(zFieldName, "tkt_ctime")==0 ) haveTicketCTime = 1;
continue;
+ }
+ if( memcmp(zFieldName,"baseline for ",13)==0 ){
+ if( strcmp(db_column_text(&q,2),"INTEGER")==0 ){
+ nBaselines++;
+ }
+ continue;
}
if( strchr(zFieldName,' ')!=0 ) continue;
if( nField%10==0 ){
aField = fossil_realloc(aField, sizeof(aField[0])*(nField+10) );
}
+ aField[nField].zBsln = 0;
aField[nField].zName = mprintf("%s", zFieldName);
aField[nField].mUsed = USEDBY_TICKET;
nField++;
}
db_finalize(&q);
+ if( nBaselines ){
+ db_prepare(&q, "SELECT 1 FROM pragma_table_info('ticket') "
+ "WHERE type = 'INTEGER' AND name = :n");
+ for(i=0; inField; i++){
const char * const zName = p->aField[i].zName;
const char * const zBaseName = zName[0]=='+' ? zName+1 : zName;
j = fieldId(zBaseName);
if( j<0 ) continue;
@@ -244,12 +274,16 @@
aUsed[j] = 1;
if( aField[j].mUsed & USEDBY_TICKET ){
if( zName[0]=='+' ){
blob_append_sql(&sql1,", \"%w\"=coalesce(\"%w\",'') || %Q",
zBaseName, zBaseName, p->aField[i].zValue);
+ /* when appending keep "baseline for ..." unchanged */
}else{
blob_append_sql(&sql1,", \"%w\"=%Q", zBaseName, p->aField[i].zValue);
+ if( aField[j].zBsln ){
+ blob_append_sql(&sql1,", \"%w\"=%d", aField[j].zBsln, rid);
+ }
}
}
if( aField[j].mUsed & USEDBY_TICKETCHNG ){
blob_append_sql(&sql2, ",\"%w\"", zBaseName);
blob_append_sql(&sql3, ",%Q", p->aField[i].zValue);
@@ -742,19 +776,35 @@
** Write a ticket into the repository.
*/
static int ticket_put(
Blob *pTicket, /* The text of the ticket change record */
const char *zTktId, /* The ticket to which this change is applied */
+ const char *aUsed, /* Indicators for fields' modifications */
int needMod /* True if moderation is needed */
){
int result;
int rid;
manifest_crosslink_begin();
rid = content_put_ex(pTicket, 0, 0, 0, needMod);
if( rid==0 ){
fossil_fatal("trouble committing ticket: %s", g.zErrMsg);
}
+ if( nTicketBslns ){
+ int i, s, buf[8], nSrc=0, *aSrc=&(buf[0]);
+ if( nTicketBslns > count(buf) ){
+ aSrc = (int*)fossil_malloc(sizeof(int)*nTicketBslns);
+ }
+ for(i=0; i 0 ) aSrc[nSrc++] = s;
+ }
+ }
+ if( nSrc ) content_deltify(rid, aSrc, nSrc, 0);
+ if( aSrc!=&(buf[0]) ) fossil_free( aSrc );
+ }
if( needMod ){
moderation_table_create();
db_multi_exec(
"INSERT INTO modreq(objid, tktid) VALUES(%d,%Q)",
rid, zTktId
@@ -787,14 +837,14 @@
void *pUuid,
int argc,
const char **argv,
int *argl
){
- char *zDate;
+ char *zDate, *aUsed;
const char *zUuid;
int i;
- int nJ = 0;
+ int nJ = 0, rc = TH_OK;
Blob tktchng, cksum;
int needMod;
login_verify_csrf_secret();
if( !captcha_is_correct(0) ){
@@ -804,15 +854,17 @@
zUuid = (const char *)pUuid;
blob_zero(&tktchng);
zDate = date_in_standard_format("now");
blob_appendf(&tktchng, "D %s\n", zDate);
free(zDate);
+ aUsed = fossil_malloc_zero( nField );
for(i=0; iTicket artifact that would have been submitted:
@ %h(blob_str(&tktchng))
@ Moderation would be %h(zNeedMod).
@
@
- return TH_OK;
}else{
if( g.thTrace ){
Th_Trace("submit_ticket {\n\n%h\n
\n"
"}
\n",
blob_str(&tktchng));
}
- ticket_put(&tktchng, zUuid, needMod);
+ ticket_put(&tktchng, zUuid, aUsed, needMod);
+ rc = ticket_change(zUuid);
}
- return ticket_change(zUuid);
+ finish:
+ fossil_free( aUsed );
+ return rc;
}
/*
** WEBPAGE: tktnew
@@ -1460,10 +1516,11 @@
}else{
/* add a new ticket or update an existing ticket */
enum { set,add,history,err } eCmd = err;
int i = 0;
Blob tktchng, cksum;
+ char *aUsed;
/* get command type (set/add) and get uuid, if needed for set */
if( strncmp(g.argv[2],"set",n)==0 || strncmp(g.argv[2],"change",n)==0 ||
strncmp(g.argv[2],"history",n)==0 ){
if( strncmp(g.argv[2],"history",n)==0 ){
@@ -1602,10 +1659,11 @@
}else{
aField[j].zValue = zFValue;
}
}
}
+ aUsed = fossil_malloc_zero( nField );
/* now add the needed artifacts to the repository */
blob_zero(&tktchng);
/* add the time to the ticket manifest */
blob_appendf(&tktchng, "D %s\n", zDate);
@@ -1615,34 +1673,39 @@
char *zPfx;
if( aField[i].zAppend && aField[i].zAppend[0] ){
zPfx = " +";
zValue = aField[i].zAppend;
+ aUsed[i] = JCARD_APPEND;
}else if( aField[i].zValue && aField[i].zValue[0] ){
zPfx = " ";
zValue = aField[i].zValue;
+ aUsed[i] = JCARD_ASSIGN;
}else{
continue;
}
if( memcmp(aField[i].zName, "private_", 8)==0 ){
zValue = db_conceal(zValue, strlen(zValue));
blob_appendf(&tktchng, "J%s%s %s\n", zPfx, aField[i].zName, zValue);
+ aUsed[i] = JCARD_PRIVATE;
}else{
blob_appendf(&tktchng, "J%s%s %#F\n", zPfx,
aField[i].zName, strlen(zValue), zValue);
}
}
blob_appendf(&tktchng, "K %s\n", zTktUuid);
blob_appendf(&tktchng, "U %F\n", zUser);
md5sum_blob(&tktchng, &cksum);
blob_appendf(&tktchng, "Z %b\n", &cksum);
- if( ticket_put(&tktchng, zTktUuid, ticket_need_moderation(1))==0 ){
+ if( ticket_put(&tktchng, zTktUuid, aUsed,
+ ticket_need_moderation(1) )==0 ){
fossil_fatal("%s", g.zErrMsg);
}else{
fossil_print("ticket %s succeeded for %s\n",
(eCmd==set?"set":"add"),zTktUuid);
}
+ fossil_free( aUsed );
}
}
}