Fossil SCM

Change the format of the A-card for attachments again. Add the ATTACHMENT table to the repository. Insert attachment information into the ATTACHMENT table when processing attachment artifacts.

drh 2010-03-16 16:52 trunk
Commit 615a52f0ba072ae9a1116b0a8d92e621687d3ce3
+24 -9
--- src/manifest.c
+++ src/manifest.c
@@ -166,39 +166,40 @@
166166
cPrevType = z[0];
167167
seenHeader = 1;
168168
if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
169169
switch( z[0] ){
170170
/*
171
- ** A (+|-)<filename> target source
171
+ ** A <filename> <target> ?<source>?
172172
**
173173
** Identifies an attachment to either a wiki page or a ticket.
174
- ** <uuid> is the artifact that is the attachment.
174
+ ** <source> is the artifact that is the attachment. <source>
175
+ ** is omitted to delete an attachment. <target> is the name of
176
+ ** a wiki page or ticket to which that attachment is connected.
175177
*/
176178
case 'A': {
177179
char *zName, *zTarget, *zSrc;
178180
md5sum_step_text(blob_buffer(&line), blob_size(&line));
179181
if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
180182
if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
181
- if( blob_token(&line, &a3)==0 ) goto manifest_syntax_error;
182183
if( p->zAttachName!=0 ) goto manifest_syntax_error;
183184
zName = blob_terminate(&a1);
184185
zTarget = blob_terminate(&a2);
186
+ blob_token(&line, &a3);
185187
zSrc = blob_terminate(&a3);
186188
defossilize(zName);
187
- if( zName[0]!='+' && zName[0]!='-' ){
188
- goto manifest_syntax_error;
189
- }
190
- if( !file_is_simple_pathname(&zName[1]) ){
189
+ if( !file_is_simple_pathname(zName) ){
191190
goto manifest_syntax_error;
192191
}
193192
defossilize(zTarget);
194193
if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
195194
&& !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
196195
goto manifest_syntax_error;
197196
}
198
- if( blob_size(&a3)!=UUID_SIZE ) goto manifest_syntax_error;
199
- if( !validate16(zSrc, UUID_SIZE) ) goto manifest_syntax_error;
197
+ if( blob_size(&a3)>0
198
+ && (blob_size(&a3)!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){
199
+ goto manifest_syntax_error;
200
+ }
200201
p->zAttachName = zName;
201202
p->zAttachSrc = zSrc;
202203
p->zAttachTarget = zTarget;
203204
break;
204205
}
@@ -622,10 +623,11 @@
622623
}else if( p->zAttachName ){
623624
if( p->nCChild>0 ) goto manifest_syntax_error;
624625
if( p->rDate==0.0 ) goto manifest_syntax_error;
625626
if( p->zTicketUuid ) goto manifest_syntax_error;
626627
if( p->zWikiTitle ) goto manifest_syntax_error;
628
+ if( !seenZ ) goto manifest_syntax_error;
627629
p->type = CFTYPE_ATTACHMENT;
628630
}else{
629631
if( p->nCChild>0 ) goto manifest_syntax_error;
630632
if( p->rDate<=0.0 ) goto manifest_syntax_error;
631633
if( p->nParent>0 ) goto manifest_syntax_error;
@@ -1114,10 +1116,23 @@
11141116
zTag = mprintf("tkt-%s", m.zTicketUuid);
11151117
tag_insert(zTag, 1, 0, rid, m.rDate, rid);
11161118
free(zTag);
11171119
db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
11181120
m.zTicketUuid);
1121
+ }
1122
+ if( m.type==CFTYPE_ATTACHMENT ){
1123
+ db_multi_exec(
1124
+ "INSERT OR IGNORE INTO attachment(mtime, target, filename)"
1125
+ "VALUES(0.0,%Q,%Q)",
1126
+ m.zAttachTarget, m.zAttachName
1127
+ );
1128
+ db_multi_exec(
1129
+ "UPDATE attachment SET mtime=%.17g, src=%Q, comment=%Q, user=%Q"
1130
+ " WHERE mtime<%.17g AND target=%Q AND filename=%Q",
1131
+ m.rDate, m.zAttachSrc, m.zComment, m.zUser,
1132
+ m.rDate, m.zAttachTarget, m.zAttachName
1133
+ );
11191134
}
11201135
db_end_transaction(0);
11211136
manifest_clear(&m);
11221137
return 1;
11231138
}
11241139
--- src/manifest.c
+++ src/manifest.c
@@ -166,39 +166,40 @@
166 cPrevType = z[0];
167 seenHeader = 1;
168 if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
169 switch( z[0] ){
170 /*
171 ** A (+|-)<filename> target source
172 **
173 ** Identifies an attachment to either a wiki page or a ticket.
174 ** <uuid> is the artifact that is the attachment.
 
 
175 */
176 case 'A': {
177 char *zName, *zTarget, *zSrc;
178 md5sum_step_text(blob_buffer(&line), blob_size(&line));
179 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
180 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
181 if( blob_token(&line, &a3)==0 ) goto manifest_syntax_error;
182 if( p->zAttachName!=0 ) goto manifest_syntax_error;
183 zName = blob_terminate(&a1);
184 zTarget = blob_terminate(&a2);
 
185 zSrc = blob_terminate(&a3);
186 defossilize(zName);
187 if( zName[0]!='+' && zName[0]!='-' ){
188 goto manifest_syntax_error;
189 }
190 if( !file_is_simple_pathname(&zName[1]) ){
191 goto manifest_syntax_error;
192 }
193 defossilize(zTarget);
194 if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
195 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
196 goto manifest_syntax_error;
197 }
198 if( blob_size(&a3)!=UUID_SIZE ) goto manifest_syntax_error;
199 if( !validate16(zSrc, UUID_SIZE) ) goto manifest_syntax_error;
 
 
200 p->zAttachName = zName;
201 p->zAttachSrc = zSrc;
202 p->zAttachTarget = zTarget;
203 break;
204 }
@@ -622,10 +623,11 @@
622 }else if( p->zAttachName ){
623 if( p->nCChild>0 ) goto manifest_syntax_error;
624 if( p->rDate==0.0 ) goto manifest_syntax_error;
625 if( p->zTicketUuid ) goto manifest_syntax_error;
626 if( p->zWikiTitle ) goto manifest_syntax_error;
 
627 p->type = CFTYPE_ATTACHMENT;
628 }else{
629 if( p->nCChild>0 ) goto manifest_syntax_error;
630 if( p->rDate<=0.0 ) goto manifest_syntax_error;
631 if( p->nParent>0 ) goto manifest_syntax_error;
@@ -1114,10 +1116,23 @@
1114 zTag = mprintf("tkt-%s", m.zTicketUuid);
1115 tag_insert(zTag, 1, 0, rid, m.rDate, rid);
1116 free(zTag);
1117 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
1118 m.zTicketUuid);
 
 
 
 
 
 
 
 
 
 
 
 
 
1119 }
1120 db_end_transaction(0);
1121 manifest_clear(&m);
1122 return 1;
1123 }
1124
--- src/manifest.c
+++ src/manifest.c
@@ -166,39 +166,40 @@
166 cPrevType = z[0];
167 seenHeader = 1;
168 if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error;
169 switch( z[0] ){
170 /*
171 ** A <filename> <target> ?<source>?
172 **
173 ** Identifies an attachment to either a wiki page or a ticket.
174 ** <source> is the artifact that is the attachment. <source>
175 ** is omitted to delete an attachment. <target> is the name of
176 ** a wiki page or ticket to which that attachment is connected.
177 */
178 case 'A': {
179 char *zName, *zTarget, *zSrc;
180 md5sum_step_text(blob_buffer(&line), blob_size(&line));
181 if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error;
182 if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error;
 
183 if( p->zAttachName!=0 ) goto manifest_syntax_error;
184 zName = blob_terminate(&a1);
185 zTarget = blob_terminate(&a2);
186 blob_token(&line, &a3);
187 zSrc = blob_terminate(&a3);
188 defossilize(zName);
189 if( !file_is_simple_pathname(zName) ){
 
 
 
190 goto manifest_syntax_error;
191 }
192 defossilize(zTarget);
193 if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE))
194 && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){
195 goto manifest_syntax_error;
196 }
197 if( blob_size(&a3)>0
198 && (blob_size(&a3)!=UUID_SIZE || !validate16(zSrc, UUID_SIZE)) ){
199 goto manifest_syntax_error;
200 }
201 p->zAttachName = zName;
202 p->zAttachSrc = zSrc;
203 p->zAttachTarget = zTarget;
204 break;
205 }
@@ -622,10 +623,11 @@
623 }else if( p->zAttachName ){
624 if( p->nCChild>0 ) goto manifest_syntax_error;
625 if( p->rDate==0.0 ) goto manifest_syntax_error;
626 if( p->zTicketUuid ) goto manifest_syntax_error;
627 if( p->zWikiTitle ) goto manifest_syntax_error;
628 if( !seenZ ) goto manifest_syntax_error;
629 p->type = CFTYPE_ATTACHMENT;
630 }else{
631 if( p->nCChild>0 ) goto manifest_syntax_error;
632 if( p->rDate<=0.0 ) goto manifest_syntax_error;
633 if( p->nParent>0 ) goto manifest_syntax_error;
@@ -1114,10 +1116,23 @@
1116 zTag = mprintf("tkt-%s", m.zTicketUuid);
1117 tag_insert(zTag, 1, 0, rid, m.rDate, rid);
1118 free(zTag);
1119 db_multi_exec("INSERT OR IGNORE INTO pending_tkt VALUES(%Q)",
1120 m.zTicketUuid);
1121 }
1122 if( m.type==CFTYPE_ATTACHMENT ){
1123 db_multi_exec(
1124 "INSERT OR IGNORE INTO attachment(mtime, target, filename)"
1125 "VALUES(0.0,%Q,%Q)",
1126 m.zAttachTarget, m.zAttachName
1127 );
1128 db_multi_exec(
1129 "UPDATE attachment SET mtime=%.17g, src=%Q, comment=%Q, user=%Q"
1130 " WHERE mtime<%.17g AND target=%Q AND filename=%Q",
1131 m.rDate, m.zAttachSrc, m.zComment, m.zUser,
1132 m.rDate, m.zAttachTarget, m.zAttachName
1133 );
1134 }
1135 db_end_transaction(0);
1136 manifest_clear(&m);
1137 return 1;
1138 }
1139
+13
--- src/schema.c
+++ src/schema.c
@@ -322,10 +322,23 @@
322322
@ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
323323
@ mtime TIMESTAMP, -- time that the hyperlink was added
324324
@ UNIQUE(target, srctype, srcid)
325325
@ );
326326
@ CREATE INDEX backlink_src ON backlink(srcid, srctype);
327
+@
328
+@ -- Each attachment is an entry in the following table. Only
329
+@ -- the most recent attachment (identified by the D card) is saved.
330
+@ --
331
+@ CREATE TABLE attachment(
332
+@ mtime TIMESTAMP, -- Time when attachment last changed
333
+@ src TEXT, -- UUID of the attachment. NULL to delete
334
+@ target TEXT, -- Object attached to
335
+@ filename TEXT, -- Filename for the attachment
336
+@ comment TEXT, -- Comment associated with this attachment
337
+@ user TEXT, -- Name of user adding attachment
338
+@ PRIMARY KEY(target, filename)
339
+@ );
327340
@
328341
@ -- Template for the TICKET table
329342
@ --
330343
@ -- NB: when changing the schema of the TICKET table here, also make the
331344
@ -- same change in tktsetup.c.
332345
--- src/schema.c
+++ src/schema.c
@@ -322,10 +322,23 @@
322 @ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
323 @ mtime TIMESTAMP, -- time that the hyperlink was added
324 @ UNIQUE(target, srctype, srcid)
325 @ );
326 @ CREATE INDEX backlink_src ON backlink(srcid, srctype);
 
 
 
 
 
 
 
 
 
 
 
 
 
327 @
328 @ -- Template for the TICKET table
329 @ --
330 @ -- NB: when changing the schema of the TICKET table here, also make the
331 @ -- same change in tktsetup.c.
332
--- src/schema.c
+++ src/schema.c
@@ -322,10 +322,23 @@
322 @ srcid INT, -- rid for checkin or wiki. tkt_id for ticket.
323 @ mtime TIMESTAMP, -- time that the hyperlink was added
324 @ UNIQUE(target, srctype, srcid)
325 @ );
326 @ CREATE INDEX backlink_src ON backlink(srcid, srctype);
327 @
328 @ -- Each attachment is an entry in the following table. Only
329 @ -- the most recent attachment (identified by the D card) is saved.
330 @ --
331 @ CREATE TABLE attachment(
332 @ mtime TIMESTAMP, -- Time when attachment last changed
333 @ src TEXT, -- UUID of the attachment. NULL to delete
334 @ target TEXT, -- Object attached to
335 @ filename TEXT, -- Filename for the attachment
336 @ comment TEXT, -- Comment associated with this attachment
337 @ user TEXT, -- Name of user adding attachment
338 @ PRIMARY KEY(target, filename)
339 @ );
340 @
341 @ -- Template for the TICKET table
342 @ --
343 @ -- NB: when changing the schema of the TICKET table here, also make the
344 @ -- same change in tktsetup.c.
345
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -380,23 +380,23 @@
380380
attachment (the source artifact) with a ticket or wiki page to which
381381
the attachment is connected (the target artifact).
382382
The following cards are allowed on an attachment artifact:
383383
384384
<blockquote>
385
-<b>A</b> (<b>+</b>|<b>-</b>)<i>filename target source</i>
385
+<b>A</b> <i>filename target</i> ?<i>source</i>?
386386
<b>C</b> <i>comment</i><br>
387387
<b>D</b> <i>time-and-date-stamp</i><br />
388388
<b>U</b> <i>user-name</i><br />
389389
<b>Z</b> <i>checksum</i>
390390
</blockquote>
391391
392392
The A card specifies a filename for the attachment in its first argument.
393
-The filename is preceeded by "+" to add the attachment or "-" to
394
-remove the attachment. The second argument to the A card is the name
393
+The second argument to the A card is the name
395394
of the wiki page or ticket to which the attachment is connected. The
396
-third argument is is the 40-character artifact ID of the attachment
397
-itself. Every attachment artifact must have exactly one A card.
395
+third argument is either missing or else it is the 40-character artifact
396
+ID of the attachment itself. A missing third argument means that the
397
+attachment should be deleted.
398398
399399
The C card is an optional comment describing what the attachment is about.
400400
The C card is optional, but there can only be one.
401401
402402
A single D card is required to give the date and time when the attachment
@@ -426,11 +426,11 @@
426426
<th>Wiki</th>
427427
<th>Ticket</th>
428428
<th>Attachment</th>
429429
</tr>
430430
<tr>
431
-<td><b>A</b> (<b>+</b>|<b>-</b>)<i>filename target source</i></td>
431
+<td><b>A</b> <i>filename target source</i></td>
432432
<td>&nbsp;</td>
433433
<td>&nbsp;</td>
434434
<td>&nbsp;</td>
435435
<td>&nbsp;</td>
436436
<td>&nbsp;</td>
437437
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -380,23 +380,23 @@
380 attachment (the source artifact) with a ticket or wiki page to which
381 the attachment is connected (the target artifact).
382 The following cards are allowed on an attachment artifact:
383
384 <blockquote>
385 <b>A</b> (<b>+</b>|<b>-</b>)<i>filename target source</i>
386 <b>C</b> <i>comment</i><br>
387 <b>D</b> <i>time-and-date-stamp</i><br />
388 <b>U</b> <i>user-name</i><br />
389 <b>Z</b> <i>checksum</i>
390 </blockquote>
391
392 The A card specifies a filename for the attachment in its first argument.
393 The filename is preceeded by "+" to add the attachment or "-" to
394 remove the attachment. The second argument to the A card is the name
395 of the wiki page or ticket to which the attachment is connected. The
396 third argument is is the 40-character artifact ID of the attachment
397 itself. Every attachment artifact must have exactly one A card.
 
398
399 The C card is an optional comment describing what the attachment is about.
400 The C card is optional, but there can only be one.
401
402 A single D card is required to give the date and time when the attachment
@@ -426,11 +426,11 @@
426 <th>Wiki</th>
427 <th>Ticket</th>
428 <th>Attachment</th>
429 </tr>
430 <tr>
431 <td><b>A</b> (<b>+</b>|<b>-</b>)<i>filename target source</i></td>
432 <td>&nbsp;</td>
433 <td>&nbsp;</td>
434 <td>&nbsp;</td>
435 <td>&nbsp;</td>
436 <td>&nbsp;</td>
437
--- www/fileformat.wiki
+++ www/fileformat.wiki
@@ -380,23 +380,23 @@
380 attachment (the source artifact) with a ticket or wiki page to which
381 the attachment is connected (the target artifact).
382 The following cards are allowed on an attachment artifact:
383
384 <blockquote>
385 <b>A</b> <i>filename target</i> ?<i>source</i>?
386 <b>C</b> <i>comment</i><br>
387 <b>D</b> <i>time-and-date-stamp</i><br />
388 <b>U</b> <i>user-name</i><br />
389 <b>Z</b> <i>checksum</i>
390 </blockquote>
391
392 The A card specifies a filename for the attachment in its first argument.
393 The second argument to the A card is the name
 
394 of the wiki page or ticket to which the attachment is connected. The
395 third argument is either missing or else it is the 40-character artifact
396 ID of the attachment itself. A missing third argument means that the
397 attachment should be deleted.
398
399 The C card is an optional comment describing what the attachment is about.
400 The C card is optional, but there can only be one.
401
402 A single D card is required to give the date and time when the attachment
@@ -426,11 +426,11 @@
426 <th>Wiki</th>
427 <th>Ticket</th>
428 <th>Attachment</th>
429 </tr>
430 <tr>
431 <td><b>A</b> <i>filename target source</i></td>
432 <td>&nbsp;</td>
433 <td>&nbsp;</td>
434 <td>&nbsp;</td>
435 <td>&nbsp;</td>
436 <td>&nbsp;</td>
437

Keyboard Shortcuts

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