Fossil SCM
Merge the experimental "Event" changes into the trunk.
Commit
d96c4a42f051c9d1078a91495cb2640314f69375
Parent
b8f134bbbb23f68…
20 files changed
+1
-1
+1
-1
+2
+89
-66
+12
-2
+1
+99
-7
+99
-7
+3
-3
+1
-1
+16
-8
+3
-1
+7
-3
+7
-3
+1
-1
+1
+35
+106
-13
+5
-2
+1
~
src/attach.c
~
src/blob.c
~
src/event.c
~
src/info.c
~
src/main.mk
~
src/makemake.tcl
~
src/manifest.c
~
src/manifest.c
~
src/printf.c
~
src/style.c
~
src/timeline.c
~
src/tkt.c
~
src/wiki.c
~
src/wiki.c
~
win/Makefile.PellesCGMake
~
www/branching.wiki
~
www/event.wiki
~
www/fileformat.wiki
~
www/index.wiki
~
www/wikitheory.wiki
+1
-1
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -351,11 +351,11 @@ | ||
| 351 | 351 | cgi_redirect(zFrom); |
| 352 | 352 | } |
| 353 | 353 | style_header("Delete Attachment"); |
| 354 | 354 | @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div> |
| 355 | 355 | @ <p>Confirm that you want to delete the attachment named |
| 356 | - @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /> | |
| 356 | + @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /></p> | |
| 357 | 357 | if( zTkt ){ |
| 358 | 358 | @ <input type="hidden" name="tkt" value="%h(zTkt)" /> |
| 359 | 359 | }else{ |
| 360 | 360 | @ <input type="hidden" name="page" value="%h(zPage)" /> |
| 361 | 361 | } |
| 362 | 362 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -351,11 +351,11 @@ | |
| 351 | cgi_redirect(zFrom); |
| 352 | } |
| 353 | style_header("Delete Attachment"); |
| 354 | @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div> |
| 355 | @ <p>Confirm that you want to delete the attachment named |
| 356 | @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /> |
| 357 | if( zTkt ){ |
| 358 | @ <input type="hidden" name="tkt" value="%h(zTkt)" /> |
| 359 | }else{ |
| 360 | @ <input type="hidden" name="page" value="%h(zPage)" /> |
| 361 | } |
| 362 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -351,11 +351,11 @@ | |
| 351 | cgi_redirect(zFrom); |
| 352 | } |
| 353 | style_header("Delete Attachment"); |
| 354 | @ <form action="%s(g.zBaseURL)/attachdelete" method="post"><div> |
| 355 | @ <p>Confirm that you want to delete the attachment named |
| 356 | @ "%h(zFile)" on %s(zTkt?"ticket":"wiki page") %h(zTarget):<br /></p> |
| 357 | if( zTkt ){ |
| 358 | @ <input type="hidden" name="tkt" value="%h(zTkt)" /> |
| 359 | }else{ |
| 360 | @ <input type="hidden" name="page" value="%h(zPage)" /> |
| 361 | } |
| 362 |
+1
-1
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -72,11 +72,11 @@ | ||
| 72 | 72 | |
| 73 | 73 | /* |
| 74 | 74 | ** We find that the built-in isspace() function does not work for |
| 75 | 75 | ** some international character sets. So here is a substitute. |
| 76 | 76 | */ |
| 77 | -static int blob_isspace(char c){ | |
| 77 | +int blob_isspace(char c){ | |
| 78 | 78 | return c==' ' || (c<='\r' && c>='\t'); |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | /* |
| 82 | 82 | ** COMMAND: test-isspace |
| 83 | 83 | |
| 84 | 84 | ADDED src/event.c |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -72,11 +72,11 @@ | |
| 72 | |
| 73 | /* |
| 74 | ** We find that the built-in isspace() function does not work for |
| 75 | ** some international character sets. So here is a substitute. |
| 76 | */ |
| 77 | static int blob_isspace(char c){ |
| 78 | return c==' ' || (c<='\r' && c>='\t'); |
| 79 | } |
| 80 | |
| 81 | /* |
| 82 | ** COMMAND: test-isspace |
| 83 | |
| 84 | DDED src/event.c |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -72,11 +72,11 @@ | |
| 72 | |
| 73 | /* |
| 74 | ** We find that the built-in isspace() function does not work for |
| 75 | ** some international character sets. So here is a substitute. |
| 76 | */ |
| 77 | int blob_isspace(char c){ |
| 78 | return c==' ' || (c<='\r' && c>='\t'); |
| 79 | } |
| 80 | |
| 81 | /* |
| 82 | ** COMMAND: test-isspace |
| 83 | |
| 84 | DDED src/event.c |
+2
| --- a/src/event.c | ||
| +++ b/src/event.c | ||
| @@ -0,0 +1,2 @@ | ||
| 1 | +mParsedblobblobmParsed?name=EVENTID&de='event-%q(); | |
| 2 | +} |
| --- a/src/event.c | |
| +++ b/src/event.c | |
| @@ -0,0 +1,2 @@ | |
| --- a/src/event.c | |
| +++ b/src/event.c | |
| @@ -0,0 +1,2 @@ | |
| 1 | mParsedblobblobmParsed?name=EVENTID&de='event-%q(); |
| 2 | } |
+89
-66
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -779,11 +779,11 @@ | ||
| 779 | 779 | } |
| 780 | 780 | } |
| 781 | 781 | db_finalize(&q); |
| 782 | 782 | if( nWiki==0 ){ |
| 783 | 783 | db_prepare(&q, |
| 784 | - "SELECT datetime(mtime), user, comment, type, uuid" | |
| 784 | + "SELECT datetime(mtime), user, comment, type, uuid, tagid" | |
| 785 | 785 | " FROM event, blob" |
| 786 | 786 | " WHERE event.objid=%d" |
| 787 | 787 | " AND blob.rid=%d", |
| 788 | 788 | rid, rid |
| 789 | 789 | ); |
| @@ -800,14 +800,19 @@ | ||
| 800 | 800 | @ Wiki edit |
| 801 | 801 | }else if( zType[0]=='t' ){ |
| 802 | 802 | @ Ticket change |
| 803 | 803 | }else if( zType[0]=='c' ){ |
| 804 | 804 | @ Manifest of check-in |
| 805 | + }else if( zType[0]=='e' ){ | |
| 806 | + @ Instance of event | |
| 807 | + hyperlink_to_event_tagid(db_column_int(&q, 5)); | |
| 805 | 808 | }else{ |
| 806 | 809 | @ Control file referencing |
| 807 | 810 | } |
| 808 | - hyperlink_to_uuid(zUuid); | |
| 811 | + if( zType[0]!='e' ){ | |
| 812 | + hyperlink_to_uuid(zUuid); | |
| 813 | + } | |
| 809 | 814 | @ - %w(zCom) by |
| 810 | 815 | hyperlink_to_user(zUser,zDate," on"); |
| 811 | 816 | hyperlink_to_date(zDate, "."); |
| 812 | 817 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 813 | 818 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| @@ -1260,10 +1265,90 @@ | ||
| 1260 | 1265 | }else |
| 1261 | 1266 | { |
| 1262 | 1267 | artifact_page(); |
| 1263 | 1268 | } |
| 1264 | 1269 | } |
| 1270 | + | |
| 1271 | +/* | |
| 1272 | +** Generate HTML that will present the user with a selection of | |
| 1273 | +** potential background colors for timeline entries. | |
| 1274 | +*/ | |
| 1275 | +void render_color_chooser( | |
| 1276 | + int fPropagate, /* Default value for propagation */ | |
| 1277 | + const char *zDefaultColor, /* The current default color */ | |
| 1278 | + const char *zIdPropagate, /* ID of form element checkbox. NULL for none */ | |
| 1279 | + const char *zId, /* The ID of the form element */ | |
| 1280 | + const char *zIdCustom /* ID of text box for custom color */ | |
| 1281 | +){ | |
| 1282 | + static const struct SampleColors { | |
| 1283 | + const char *zCName; | |
| 1284 | + const char *zColor; | |
| 1285 | + } aColor[] = { | |
| 1286 | + { "(none)", "" }, | |
| 1287 | + { "#f2dcdc", "#f2dcdc" }, | |
| 1288 | + { "#f0ffc0", "#f0ffc0" }, | |
| 1289 | + { "#bde5d6", "#bde5d6" }, | |
| 1290 | + { "#c0ffc0", "#c0ffc0" }, | |
| 1291 | + { "#c0fff0", "#c0fff0" }, | |
| 1292 | + { "#c0f0ff", "#c0f0ff" }, | |
| 1293 | + { "#d0c0ff", "#d0c0ff" }, | |
| 1294 | + { "#ffc0ff", "#ffc0ff" }, | |
| 1295 | + { "#ffc0d0", "#ffc0d0" }, | |
| 1296 | + { "#fff0c0", "#fff0c0" }, | |
| 1297 | + { "#c0c0c0", "#c0c0c0" }, | |
| 1298 | + { "custom", "##" }, | |
| 1299 | + }; | |
| 1300 | + int nColor = sizeof(aColor)/sizeof(aColor[0])-1; | |
| 1301 | + int stdClrFound = 0; | |
| 1302 | + int i; | |
| 1303 | + | |
| 1304 | + @ <table border="0" cellpadding="0" cellspacing="1"> | |
| 1305 | + if( zIdPropagate ){ | |
| 1306 | + @ <tr><td colspan="6" align="left"> | |
| 1307 | + if( fPropagate ){ | |
| 1308 | + @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" /> | |
| 1309 | + }else{ | |
| 1310 | + @ <input type="checkbox" name="%s(zIdPropagate)" /> | |
| 1311 | + } | |
| 1312 | + @ Propagate color to descendants</td></tr> | |
| 1313 | + } | |
| 1314 | + @ <tr> | |
| 1315 | + for(i=0; i<nColor; i++){ | |
| 1316 | + if( aColor[i].zColor[0] ){ | |
| 1317 | + @ <td style="background-color: %h(aColor[i].zColor);"> | |
| 1318 | + }else{ | |
| 1319 | + @ <td> | |
| 1320 | + } | |
| 1321 | + if( strcmp(zDefaultColor, aColor[i].zColor)==0 ){ | |
| 1322 | + @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" | |
| 1323 | + @ checked="checked" /> | |
| 1324 | + stdClrFound=1; | |
| 1325 | + }else{ | |
| 1326 | + @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" /> | |
| 1327 | + } | |
| 1328 | + @ %h(aColor[i].zCName)</td> | |
| 1329 | + if( (i%6)==5 && i+1<nColor ){ | |
| 1330 | + @ </tr><tr> | |
| 1331 | + } | |
| 1332 | + } | |
| 1333 | + @ </tr><tr> | |
| 1334 | + if (stdClrFound){ | |
| 1335 | + @ <td colspan="6"> | |
| 1336 | + @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" /> | |
| 1337 | + }else{ | |
| 1338 | + @ <td style="background-color: %h(zDefaultColor);" colspan="6"> | |
| 1339 | + @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" | |
| 1340 | + @ checked="checked" /> | |
| 1341 | + } | |
| 1342 | + @ %h(aColor[i].zCName) | |
| 1343 | + @ <input type="text" name="%s(zIdCustom)" | |
| 1344 | + @ id="%s(zIdCustom)" class="checkinUserColor" | |
| 1345 | + @ value="%h(stdClrFound?"":zDefaultColor)" /> | |
| 1346 | + @ </td> | |
| 1347 | + @ </tr> | |
| 1348 | + @ </table> | |
| 1349 | +} | |
| 1265 | 1350 | |
| 1266 | 1351 | /* |
| 1267 | 1352 | ** WEBPAGE: ci_edit |
| 1268 | 1353 | ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER |
| 1269 | 1354 | ** |
| @@ -1290,31 +1375,10 @@ | ||
| 1290 | 1375 | const char *zCloseFlag; |
| 1291 | 1376 | int fPropagateColor; |
| 1292 | 1377 | char *zUuid; |
| 1293 | 1378 | Blob comment; |
| 1294 | 1379 | Stmt q; |
| 1295 | - static const struct SampleColors { | |
| 1296 | - const char *zCName; | |
| 1297 | - const char *zColor; | |
| 1298 | - } aColor[] = { | |
| 1299 | - { "(none)", "" }, | |
| 1300 | - { "#f2dcdc", "#f2dcdc" }, | |
| 1301 | - { "#f0ffc0", "#f0ffc0" }, | |
| 1302 | - { "#bde5d6", "#bde5d6" }, | |
| 1303 | - { "#c0ffc0", "#c0ffc0" }, | |
| 1304 | - { "#c0fff0", "#c0fff0" }, | |
| 1305 | - { "#c0f0ff", "#c0f0ff" }, | |
| 1306 | - { "#d0c0ff", "#d0c0ff" }, | |
| 1307 | - { "#ffc0ff", "#ffc0ff" }, | |
| 1308 | - { "#ffc0d0", "#ffc0d0" }, | |
| 1309 | - { "#fff0c0", "#fff0c0" }, | |
| 1310 | - { "#c0c0c0", "#c0c0c0" }, | |
| 1311 | - { "custom", "##" }, | |
| 1312 | - }; | |
| 1313 | - int nColor = sizeof(aColor)/sizeof(aColor[0])-1; | |
| 1314 | - int stdClrFound; | |
| 1315 | - int i; | |
| 1316 | 1380 | |
| 1317 | 1381 | login_check_credentials(); |
| 1318 | 1382 | if( !g.okWrite ){ login_needed(); return; } |
| 1319 | 1383 | rid = name_to_rid(P("r")); |
| 1320 | 1384 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -1334,11 +1398,11 @@ | ||
| 1334 | 1398 | if( zDate==0 ) fossil_redirect_home(); |
| 1335 | 1399 | zNewDate = PD("dt",zDate); |
| 1336 | 1400 | zColor = db_text("", "SELECT bgcolor" |
| 1337 | 1401 | " FROM event WHERE objid=%d", rid); |
| 1338 | 1402 | zNewColor = PD("clr",zColor); |
| 1339 | - if( strcmp(zNewColor,aColor[nColor].zColor)==0 ){ | |
| 1403 | + if( strcmp(zNewColor,"##")==0 ){ | |
| 1340 | 1404 | zNewColor = P("clrcust"); |
| 1341 | 1405 | } |
| 1342 | 1406 | fPropagateColor = P("pclr")!=0; |
| 1343 | 1407 | zNewTagFlag = P("newtag") ? " checked" : ""; |
| 1344 | 1408 | zNewTag = PD("tagname",""); |
| @@ -1501,52 +1565,11 @@ | ||
| 1501 | 1565 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 1502 | 1566 | @ </td></tr> |
| 1503 | 1567 | |
| 1504 | 1568 | @ <tr><td align="right" valign="top"><b>Background Color:</b></td> |
| 1505 | 1569 | @ <td valign="top"> |
| 1506 | - @ <table border="0" cellpadding="0" cellspacing="1"> | |
| 1507 | - @ <tr><td colspan="6" align="left"> | |
| 1508 | - if( fPropagateColor ){ | |
| 1509 | - @ <input type="checkbox" name="pclr" checked="checked" /> | |
| 1510 | - }else{ | |
| 1511 | - @ <input type="checkbox" name="pclr" /> | |
| 1512 | - } | |
| 1513 | - @ Propagate color to descendants</td></tr> | |
| 1514 | - @ <tr> | |
| 1515 | - for(i=0,stdClrFound=0; i<nColor; i++){ | |
| 1516 | - if( aColor[i].zColor[0] ){ | |
| 1517 | - @ <td style="background-color: %h(aColor[i].zColor);"> | |
| 1518 | - }else{ | |
| 1519 | - @ <td> | |
| 1520 | - } | |
| 1521 | - if( strcmp(zNewColor, aColor[i].zColor)==0 ){ | |
| 1522 | - @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" | |
| 1523 | - @ checked="checked" /> | |
| 1524 | - stdClrFound=1; | |
| 1525 | - }else{ | |
| 1526 | - @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" /> | |
| 1527 | - } | |
| 1528 | - @ %h(aColor[i].zCName)</td> | |
| 1529 | - if( (i%6)==5 && i+1<nColor ){ | |
| 1530 | - @ </tr><tr> | |
| 1531 | - } | |
| 1532 | - } | |
| 1533 | - @ </tr><tr> | |
| 1534 | - if (stdClrFound){ | |
| 1535 | - @ <td colspan="6"> | |
| 1536 | - @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" /> | |
| 1537 | - }else{ | |
| 1538 | - @ <td style="background-color: %h(zNewColor);" colspan="6"> | |
| 1539 | - @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" | |
| 1540 | - @ checked="checked" /> | |
| 1541 | - } | |
| 1542 | - @ %h(aColor[i].zCName) | |
| 1543 | - @ <input type="text" name="clrcust" id="clrcust" class="checkinUserColor" | |
| 1544 | - @ value="%h(stdClrFound?"":zNewColor)" /> | |
| 1545 | - @ </td> | |
| 1546 | - @ </tr> | |
| 1547 | - @ </table> | |
| 1570 | + render_color_chooser(fPropagateColor, zNewColor, "pclr", "clr", "clrcust"); | |
| 1548 | 1571 | @ </td></tr> |
| 1549 | 1572 | |
| 1550 | 1573 | @ <tr><td align="right" valign="top"><b>Tags:</b></td> |
| 1551 | 1574 | @ <td valign="top"> |
| 1552 | 1575 | @ <input type="checkbox" name="newtag"%s(zNewTagFlag) /> |
| 1553 | 1576 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -779,11 +779,11 @@ | |
| 779 | } |
| 780 | } |
| 781 | db_finalize(&q); |
| 782 | if( nWiki==0 ){ |
| 783 | db_prepare(&q, |
| 784 | "SELECT datetime(mtime), user, comment, type, uuid" |
| 785 | " FROM event, blob" |
| 786 | " WHERE event.objid=%d" |
| 787 | " AND blob.rid=%d", |
| 788 | rid, rid |
| 789 | ); |
| @@ -800,14 +800,19 @@ | |
| 800 | @ Wiki edit |
| 801 | }else if( zType[0]=='t' ){ |
| 802 | @ Ticket change |
| 803 | }else if( zType[0]=='c' ){ |
| 804 | @ Manifest of check-in |
| 805 | }else{ |
| 806 | @ Control file referencing |
| 807 | } |
| 808 | hyperlink_to_uuid(zUuid); |
| 809 | @ - %w(zCom) by |
| 810 | hyperlink_to_user(zUser,zDate," on"); |
| 811 | hyperlink_to_date(zDate, "."); |
| 812 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 813 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| @@ -1260,10 +1265,90 @@ | |
| 1260 | }else |
| 1261 | { |
| 1262 | artifact_page(); |
| 1263 | } |
| 1264 | } |
| 1265 | |
| 1266 | /* |
| 1267 | ** WEBPAGE: ci_edit |
| 1268 | ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER |
| 1269 | ** |
| @@ -1290,31 +1375,10 @@ | |
| 1290 | const char *zCloseFlag; |
| 1291 | int fPropagateColor; |
| 1292 | char *zUuid; |
| 1293 | Blob comment; |
| 1294 | Stmt q; |
| 1295 | static const struct SampleColors { |
| 1296 | const char *zCName; |
| 1297 | const char *zColor; |
| 1298 | } aColor[] = { |
| 1299 | { "(none)", "" }, |
| 1300 | { "#f2dcdc", "#f2dcdc" }, |
| 1301 | { "#f0ffc0", "#f0ffc0" }, |
| 1302 | { "#bde5d6", "#bde5d6" }, |
| 1303 | { "#c0ffc0", "#c0ffc0" }, |
| 1304 | { "#c0fff0", "#c0fff0" }, |
| 1305 | { "#c0f0ff", "#c0f0ff" }, |
| 1306 | { "#d0c0ff", "#d0c0ff" }, |
| 1307 | { "#ffc0ff", "#ffc0ff" }, |
| 1308 | { "#ffc0d0", "#ffc0d0" }, |
| 1309 | { "#fff0c0", "#fff0c0" }, |
| 1310 | { "#c0c0c0", "#c0c0c0" }, |
| 1311 | { "custom", "##" }, |
| 1312 | }; |
| 1313 | int nColor = sizeof(aColor)/sizeof(aColor[0])-1; |
| 1314 | int stdClrFound; |
| 1315 | int i; |
| 1316 | |
| 1317 | login_check_credentials(); |
| 1318 | if( !g.okWrite ){ login_needed(); return; } |
| 1319 | rid = name_to_rid(P("r")); |
| 1320 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -1334,11 +1398,11 @@ | |
| 1334 | if( zDate==0 ) fossil_redirect_home(); |
| 1335 | zNewDate = PD("dt",zDate); |
| 1336 | zColor = db_text("", "SELECT bgcolor" |
| 1337 | " FROM event WHERE objid=%d", rid); |
| 1338 | zNewColor = PD("clr",zColor); |
| 1339 | if( strcmp(zNewColor,aColor[nColor].zColor)==0 ){ |
| 1340 | zNewColor = P("clrcust"); |
| 1341 | } |
| 1342 | fPropagateColor = P("pclr")!=0; |
| 1343 | zNewTagFlag = P("newtag") ? " checked" : ""; |
| 1344 | zNewTag = PD("tagname",""); |
| @@ -1501,52 +1565,11 @@ | |
| 1501 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 1502 | @ </td></tr> |
| 1503 | |
| 1504 | @ <tr><td align="right" valign="top"><b>Background Color:</b></td> |
| 1505 | @ <td valign="top"> |
| 1506 | @ <table border="0" cellpadding="0" cellspacing="1"> |
| 1507 | @ <tr><td colspan="6" align="left"> |
| 1508 | if( fPropagateColor ){ |
| 1509 | @ <input type="checkbox" name="pclr" checked="checked" /> |
| 1510 | }else{ |
| 1511 | @ <input type="checkbox" name="pclr" /> |
| 1512 | } |
| 1513 | @ Propagate color to descendants</td></tr> |
| 1514 | @ <tr> |
| 1515 | for(i=0,stdClrFound=0; i<nColor; i++){ |
| 1516 | if( aColor[i].zColor[0] ){ |
| 1517 | @ <td style="background-color: %h(aColor[i].zColor);"> |
| 1518 | }else{ |
| 1519 | @ <td> |
| 1520 | } |
| 1521 | if( strcmp(zNewColor, aColor[i].zColor)==0 ){ |
| 1522 | @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" |
| 1523 | @ checked="checked" /> |
| 1524 | stdClrFound=1; |
| 1525 | }else{ |
| 1526 | @ <input type="radio" name="clr" value="%h(aColor[i].zColor)" /> |
| 1527 | } |
| 1528 | @ %h(aColor[i].zCName)</td> |
| 1529 | if( (i%6)==5 && i+1<nColor ){ |
| 1530 | @ </tr><tr> |
| 1531 | } |
| 1532 | } |
| 1533 | @ </tr><tr> |
| 1534 | if (stdClrFound){ |
| 1535 | @ <td colspan="6"> |
| 1536 | @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" /> |
| 1537 | }else{ |
| 1538 | @ <td style="background-color: %h(zNewColor);" colspan="6"> |
| 1539 | @ <input type="radio" name="clr" value="%h(aColor[nColor].zColor)" |
| 1540 | @ checked="checked" /> |
| 1541 | } |
| 1542 | @ %h(aColor[i].zCName) |
| 1543 | @ <input type="text" name="clrcust" id="clrcust" class="checkinUserColor" |
| 1544 | @ value="%h(stdClrFound?"":zNewColor)" /> |
| 1545 | @ </td> |
| 1546 | @ </tr> |
| 1547 | @ </table> |
| 1548 | @ </td></tr> |
| 1549 | |
| 1550 | @ <tr><td align="right" valign="top"><b>Tags:</b></td> |
| 1551 | @ <td valign="top"> |
| 1552 | @ <input type="checkbox" name="newtag"%s(zNewTagFlag) /> |
| 1553 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -779,11 +779,11 @@ | |
| 779 | } |
| 780 | } |
| 781 | db_finalize(&q); |
| 782 | if( nWiki==0 ){ |
| 783 | db_prepare(&q, |
| 784 | "SELECT datetime(mtime), user, comment, type, uuid, tagid" |
| 785 | " FROM event, blob" |
| 786 | " WHERE event.objid=%d" |
| 787 | " AND blob.rid=%d", |
| 788 | rid, rid |
| 789 | ); |
| @@ -800,14 +800,19 @@ | |
| 800 | @ Wiki edit |
| 801 | }else if( zType[0]=='t' ){ |
| 802 | @ Ticket change |
| 803 | }else if( zType[0]=='c' ){ |
| 804 | @ Manifest of check-in |
| 805 | }else if( zType[0]=='e' ){ |
| 806 | @ Instance of event |
| 807 | hyperlink_to_event_tagid(db_column_int(&q, 5)); |
| 808 | }else{ |
| 809 | @ Control file referencing |
| 810 | } |
| 811 | if( zType[0]!='e' ){ |
| 812 | hyperlink_to_uuid(zUuid); |
| 813 | } |
| 814 | @ - %w(zCom) by |
| 815 | hyperlink_to_user(zUser,zDate," on"); |
| 816 | hyperlink_to_date(zDate, "."); |
| 817 | if( pDownloadName && blob_size(pDownloadName)==0 ){ |
| 818 | blob_appendf(pDownloadName, "%.10s.txt", zUuid); |
| @@ -1260,10 +1265,90 @@ | |
| 1265 | }else |
| 1266 | { |
| 1267 | artifact_page(); |
| 1268 | } |
| 1269 | } |
| 1270 | |
| 1271 | /* |
| 1272 | ** Generate HTML that will present the user with a selection of |
| 1273 | ** potential background colors for timeline entries. |
| 1274 | */ |
| 1275 | void render_color_chooser( |
| 1276 | int fPropagate, /* Default value for propagation */ |
| 1277 | const char *zDefaultColor, /* The current default color */ |
| 1278 | const char *zIdPropagate, /* ID of form element checkbox. NULL for none */ |
| 1279 | const char *zId, /* The ID of the form element */ |
| 1280 | const char *zIdCustom /* ID of text box for custom color */ |
| 1281 | ){ |
| 1282 | static const struct SampleColors { |
| 1283 | const char *zCName; |
| 1284 | const char *zColor; |
| 1285 | } aColor[] = { |
| 1286 | { "(none)", "" }, |
| 1287 | { "#f2dcdc", "#f2dcdc" }, |
| 1288 | { "#f0ffc0", "#f0ffc0" }, |
| 1289 | { "#bde5d6", "#bde5d6" }, |
| 1290 | { "#c0ffc0", "#c0ffc0" }, |
| 1291 | { "#c0fff0", "#c0fff0" }, |
| 1292 | { "#c0f0ff", "#c0f0ff" }, |
| 1293 | { "#d0c0ff", "#d0c0ff" }, |
| 1294 | { "#ffc0ff", "#ffc0ff" }, |
| 1295 | { "#ffc0d0", "#ffc0d0" }, |
| 1296 | { "#fff0c0", "#fff0c0" }, |
| 1297 | { "#c0c0c0", "#c0c0c0" }, |
| 1298 | { "custom", "##" }, |
| 1299 | }; |
| 1300 | int nColor = sizeof(aColor)/sizeof(aColor[0])-1; |
| 1301 | int stdClrFound = 0; |
| 1302 | int i; |
| 1303 | |
| 1304 | @ <table border="0" cellpadding="0" cellspacing="1"> |
| 1305 | if( zIdPropagate ){ |
| 1306 | @ <tr><td colspan="6" align="left"> |
| 1307 | if( fPropagate ){ |
| 1308 | @ <input type="checkbox" name="%s(zIdPropagate)" checked="checked" /> |
| 1309 | }else{ |
| 1310 | @ <input type="checkbox" name="%s(zIdPropagate)" /> |
| 1311 | } |
| 1312 | @ Propagate color to descendants</td></tr> |
| 1313 | } |
| 1314 | @ <tr> |
| 1315 | for(i=0; i<nColor; i++){ |
| 1316 | if( aColor[i].zColor[0] ){ |
| 1317 | @ <td style="background-color: %h(aColor[i].zColor);"> |
| 1318 | }else{ |
| 1319 | @ <td> |
| 1320 | } |
| 1321 | if( strcmp(zDefaultColor, aColor[i].zColor)==0 ){ |
| 1322 | @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" |
| 1323 | @ checked="checked" /> |
| 1324 | stdClrFound=1; |
| 1325 | }else{ |
| 1326 | @ <input type="radio" name="%s(zId)" value="%h(aColor[i].zColor)" /> |
| 1327 | } |
| 1328 | @ %h(aColor[i].zCName)</td> |
| 1329 | if( (i%6)==5 && i+1<nColor ){ |
| 1330 | @ </tr><tr> |
| 1331 | } |
| 1332 | } |
| 1333 | @ </tr><tr> |
| 1334 | if (stdClrFound){ |
| 1335 | @ <td colspan="6"> |
| 1336 | @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" /> |
| 1337 | }else{ |
| 1338 | @ <td style="background-color: %h(zDefaultColor);" colspan="6"> |
| 1339 | @ <input type="radio" name="%s(zId)" value="%h(aColor[nColor].zColor)" |
| 1340 | @ checked="checked" /> |
| 1341 | } |
| 1342 | @ %h(aColor[i].zCName) |
| 1343 | @ <input type="text" name="%s(zIdCustom)" |
| 1344 | @ id="%s(zIdCustom)" class="checkinUserColor" |
| 1345 | @ value="%h(stdClrFound?"":zDefaultColor)" /> |
| 1346 | @ </td> |
| 1347 | @ </tr> |
| 1348 | @ </table> |
| 1349 | } |
| 1350 | |
| 1351 | /* |
| 1352 | ** WEBPAGE: ci_edit |
| 1353 | ** URL: ci_edit?r=RID&c=NEWCOMMENT&u=NEWUSER |
| 1354 | ** |
| @@ -1290,31 +1375,10 @@ | |
| 1375 | const char *zCloseFlag; |
| 1376 | int fPropagateColor; |
| 1377 | char *zUuid; |
| 1378 | Blob comment; |
| 1379 | Stmt q; |
| 1380 | |
| 1381 | login_check_credentials(); |
| 1382 | if( !g.okWrite ){ login_needed(); return; } |
| 1383 | rid = name_to_rid(P("r")); |
| 1384 | zUuid = db_text(0, "SELECT uuid FROM blob WHERE rid=%d", rid); |
| @@ -1334,11 +1398,11 @@ | |
| 1398 | if( zDate==0 ) fossil_redirect_home(); |
| 1399 | zNewDate = PD("dt",zDate); |
| 1400 | zColor = db_text("", "SELECT bgcolor" |
| 1401 | " FROM event WHERE objid=%d", rid); |
| 1402 | zNewColor = PD("clr",zColor); |
| 1403 | if( strcmp(zNewColor,"##")==0 ){ |
| 1404 | zNewColor = P("clrcust"); |
| 1405 | } |
| 1406 | fPropagateColor = P("pclr")!=0; |
| 1407 | zNewTagFlag = P("newtag") ? " checked" : ""; |
| 1408 | zNewTag = PD("tagname",""); |
| @@ -1501,52 +1565,11 @@ | |
| 1565 | @ <input type="text" name="dt" size="20" value="%h(zNewDate)" /> |
| 1566 | @ </td></tr> |
| 1567 | |
| 1568 | @ <tr><td align="right" valign="top"><b>Background Color:</b></td> |
| 1569 | @ <td valign="top"> |
| 1570 | render_color_chooser(fPropagateColor, zNewColor, "pclr", "clr", "clrcust"); |
| 1571 | @ </td></tr> |
| 1572 | |
| 1573 | @ <tr><td align="right" valign="top"><b>Tags:</b></td> |
| 1574 | @ <td valign="top"> |
| 1575 | @ <input type="checkbox" name="newtag"%s(zNewTagFlag) /> |
| 1576 |
+12
-2
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -35,10 +35,11 @@ | ||
| 35 | 35 | $(SRCDIR)/descendants.c \ |
| 36 | 36 | $(SRCDIR)/diff.c \ |
| 37 | 37 | $(SRCDIR)/diffcmd.c \ |
| 38 | 38 | $(SRCDIR)/doc.c \ |
| 39 | 39 | $(SRCDIR)/encode.c \ |
| 40 | + $(SRCDIR)/event.c \ | |
| 40 | 41 | $(SRCDIR)/file.c \ |
| 41 | 42 | $(SRCDIR)/finfo.c \ |
| 42 | 43 | $(SRCDIR)/graph.c \ |
| 43 | 44 | $(SRCDIR)/http.c \ |
| 44 | 45 | $(SRCDIR)/http_socket.c \ |
| @@ -108,10 +109,11 @@ | ||
| 108 | 109 | descendants_.c \ |
| 109 | 110 | diff_.c \ |
| 110 | 111 | diffcmd_.c \ |
| 111 | 112 | doc_.c \ |
| 112 | 113 | encode_.c \ |
| 114 | + event_.c \ | |
| 113 | 115 | file_.c \ |
| 114 | 116 | finfo_.c \ |
| 115 | 117 | graph_.c \ |
| 116 | 118 | http_.c \ |
| 117 | 119 | http_socket_.c \ |
| @@ -181,10 +183,11 @@ | ||
| 181 | 183 | $(OBJDIR)/descendants.o \ |
| 182 | 184 | $(OBJDIR)/diff.o \ |
| 183 | 185 | $(OBJDIR)/diffcmd.o \ |
| 184 | 186 | $(OBJDIR)/doc.o \ |
| 185 | 187 | $(OBJDIR)/encode.o \ |
| 188 | + $(OBJDIR)/event.o \ | |
| 186 | 189 | $(OBJDIR)/file.o \ |
| 187 | 190 | $(OBJDIR)/finfo.o \ |
| 188 | 191 | $(OBJDIR)/graph.o \ |
| 189 | 192 | $(OBJDIR)/http.o \ |
| 190 | 193 | $(OBJDIR)/http_socket.o \ |
| @@ -273,16 +276,16 @@ | ||
| 273 | 276 | # noop |
| 274 | 277 | |
| 275 | 278 | clean: |
| 276 | 279 | rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h |
| 277 | 280 | rm -f translate makeheaders mkindex page_index.h headers |
| 278 | - rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h | |
| 281 | + rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h event.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h | |
| 279 | 282 | |
| 280 | 283 | page_index.h: $(TRANS_SRC) mkindex |
| 281 | 284 | ./mkindex $(TRANS_SRC) >$@ |
| 282 | 285 | headers: page_index.h makeheaders VERSION.h |
| 283 | - ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h | |
| 286 | + ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h | |
| 284 | 287 | touch headers |
| 285 | 288 | headers: Makefile |
| 286 | 289 | Makefile: |
| 287 | 290 | add_.c: $(SRCDIR)/add.c translate |
| 288 | 291 | ./translate $(SRCDIR)/add.c >add_.c |
| @@ -450,10 +453,17 @@ | ||
| 450 | 453 | |
| 451 | 454 | $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h |
| 452 | 455 | $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c |
| 453 | 456 | |
| 454 | 457 | encode.h: headers |
| 458 | +event_.c: $(SRCDIR)/event.c translate | |
| 459 | + ./translate $(SRCDIR)/event.c >event_.c | |
| 460 | + | |
| 461 | +$(OBJDIR)/event.o: event_.c event.h $(SRCDIR)/config.h | |
| 462 | + $(XTCC) -o $(OBJDIR)/event.o -c event_.c | |
| 463 | + | |
| 464 | +event.h: headers | |
| 455 | 465 | file_.c: $(SRCDIR)/file.c translate |
| 456 | 466 | ./translate $(SRCDIR)/file.c >file_.c |
| 457 | 467 | |
| 458 | 468 | $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h |
| 459 | 469 | $(XTCC) -o $(OBJDIR)/file.o -c file_.c |
| 460 | 470 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -35,10 +35,11 @@ | |
| 35 | $(SRCDIR)/descendants.c \ |
| 36 | $(SRCDIR)/diff.c \ |
| 37 | $(SRCDIR)/diffcmd.c \ |
| 38 | $(SRCDIR)/doc.c \ |
| 39 | $(SRCDIR)/encode.c \ |
| 40 | $(SRCDIR)/file.c \ |
| 41 | $(SRCDIR)/finfo.c \ |
| 42 | $(SRCDIR)/graph.c \ |
| 43 | $(SRCDIR)/http.c \ |
| 44 | $(SRCDIR)/http_socket.c \ |
| @@ -108,10 +109,11 @@ | |
| 108 | descendants_.c \ |
| 109 | diff_.c \ |
| 110 | diffcmd_.c \ |
| 111 | doc_.c \ |
| 112 | encode_.c \ |
| 113 | file_.c \ |
| 114 | finfo_.c \ |
| 115 | graph_.c \ |
| 116 | http_.c \ |
| 117 | http_socket_.c \ |
| @@ -181,10 +183,11 @@ | |
| 181 | $(OBJDIR)/descendants.o \ |
| 182 | $(OBJDIR)/diff.o \ |
| 183 | $(OBJDIR)/diffcmd.o \ |
| 184 | $(OBJDIR)/doc.o \ |
| 185 | $(OBJDIR)/encode.o \ |
| 186 | $(OBJDIR)/file.o \ |
| 187 | $(OBJDIR)/finfo.o \ |
| 188 | $(OBJDIR)/graph.o \ |
| 189 | $(OBJDIR)/http.o \ |
| 190 | $(OBJDIR)/http_socket.o \ |
| @@ -273,16 +276,16 @@ | |
| 273 | # noop |
| 274 | |
| 275 | clean: |
| 276 | rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h |
| 277 | rm -f translate makeheaders mkindex page_index.h headers |
| 278 | rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h |
| 279 | |
| 280 | page_index.h: $(TRANS_SRC) mkindex |
| 281 | ./mkindex $(TRANS_SRC) >$@ |
| 282 | headers: page_index.h makeheaders VERSION.h |
| 283 | ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h |
| 284 | touch headers |
| 285 | headers: Makefile |
| 286 | Makefile: |
| 287 | add_.c: $(SRCDIR)/add.c translate |
| 288 | ./translate $(SRCDIR)/add.c >add_.c |
| @@ -450,10 +453,17 @@ | |
| 450 | |
| 451 | $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h |
| 452 | $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c |
| 453 | |
| 454 | encode.h: headers |
| 455 | file_.c: $(SRCDIR)/file.c translate |
| 456 | ./translate $(SRCDIR)/file.c >file_.c |
| 457 | |
| 458 | $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h |
| 459 | $(XTCC) -o $(OBJDIR)/file.o -c file_.c |
| 460 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -35,10 +35,11 @@ | |
| 35 | $(SRCDIR)/descendants.c \ |
| 36 | $(SRCDIR)/diff.c \ |
| 37 | $(SRCDIR)/diffcmd.c \ |
| 38 | $(SRCDIR)/doc.c \ |
| 39 | $(SRCDIR)/encode.c \ |
| 40 | $(SRCDIR)/event.c \ |
| 41 | $(SRCDIR)/file.c \ |
| 42 | $(SRCDIR)/finfo.c \ |
| 43 | $(SRCDIR)/graph.c \ |
| 44 | $(SRCDIR)/http.c \ |
| 45 | $(SRCDIR)/http_socket.c \ |
| @@ -108,10 +109,11 @@ | |
| 109 | descendants_.c \ |
| 110 | diff_.c \ |
| 111 | diffcmd_.c \ |
| 112 | doc_.c \ |
| 113 | encode_.c \ |
| 114 | event_.c \ |
| 115 | file_.c \ |
| 116 | finfo_.c \ |
| 117 | graph_.c \ |
| 118 | http_.c \ |
| 119 | http_socket_.c \ |
| @@ -181,10 +183,11 @@ | |
| 183 | $(OBJDIR)/descendants.o \ |
| 184 | $(OBJDIR)/diff.o \ |
| 185 | $(OBJDIR)/diffcmd.o \ |
| 186 | $(OBJDIR)/doc.o \ |
| 187 | $(OBJDIR)/encode.o \ |
| 188 | $(OBJDIR)/event.o \ |
| 189 | $(OBJDIR)/file.o \ |
| 190 | $(OBJDIR)/finfo.o \ |
| 191 | $(OBJDIR)/graph.o \ |
| 192 | $(OBJDIR)/http.o \ |
| 193 | $(OBJDIR)/http_socket.o \ |
| @@ -273,16 +276,16 @@ | |
| 276 | # noop |
| 277 | |
| 278 | clean: |
| 279 | rm -f $(OBJDIR)/*.o *_.c $(APPNAME) VERSION.h |
| 280 | rm -f translate makeheaders mkindex page_index.h headers |
| 281 | rm -f add.h allrepo.h attach.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h event.h file.h finfo.h graph.h http.h http_socket.h http_ssl.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h popen.h pqueue.h printf.h rebuild.h report.h rss.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h |
| 282 | |
| 283 | page_index.h: $(TRANS_SRC) mkindex |
| 284 | ./mkindex $(TRANS_SRC) >$@ |
| 285 | headers: page_index.h makeheaders VERSION.h |
| 286 | ./makeheaders add_.c:add.h allrepo_.c:allrepo.h attach_.c:attach.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h event_.c:event.h file_.c:file.h finfo_.c:finfo.h graph_.c:graph.h http_.c:http.h http_socket_.c:http_socket.h http_ssl_.c:http_ssl.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h popen_.c:popen.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h |
| 287 | touch headers |
| 288 | headers: Makefile |
| 289 | Makefile: |
| 290 | add_.c: $(SRCDIR)/add.c translate |
| 291 | ./translate $(SRCDIR)/add.c >add_.c |
| @@ -450,10 +453,17 @@ | |
| 453 | |
| 454 | $(OBJDIR)/encode.o: encode_.c encode.h $(SRCDIR)/config.h |
| 455 | $(XTCC) -o $(OBJDIR)/encode.o -c encode_.c |
| 456 | |
| 457 | encode.h: headers |
| 458 | event_.c: $(SRCDIR)/event.c translate |
| 459 | ./translate $(SRCDIR)/event.c >event_.c |
| 460 | |
| 461 | $(OBJDIR)/event.o: event_.c event.h $(SRCDIR)/config.h |
| 462 | $(XTCC) -o $(OBJDIR)/event.o -c event_.c |
| 463 | |
| 464 | event.h: headers |
| 465 | file_.c: $(SRCDIR)/file.c translate |
| 466 | ./translate $(SRCDIR)/file.c >file_.c |
| 467 | |
| 468 | $(OBJDIR)/file.o: file_.c file.h $(SRCDIR)/config.h |
| 469 | $(XTCC) -o $(OBJDIR)/file.o -c file_.c |
| 470 |
+1
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -29,10 +29,11 @@ | ||
| 29 | 29 | descendants |
| 30 | 30 | diff |
| 31 | 31 | diffcmd |
| 32 | 32 | doc |
| 33 | 33 | encode |
| 34 | + event | |
| 34 | 35 | file |
| 35 | 36 | finfo |
| 36 | 37 | graph |
| 37 | 38 | http |
| 38 | 39 | http_socket |
| 39 | 40 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -29,10 +29,11 @@ | |
| 29 | descendants |
| 30 | diff |
| 31 | diffcmd |
| 32 | doc |
| 33 | encode |
| 34 | file |
| 35 | finfo |
| 36 | graph |
| 37 | http |
| 38 | http_socket |
| 39 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -29,10 +29,11 @@ | |
| 29 | descendants |
| 30 | diff |
| 31 | diffcmd |
| 32 | doc |
| 33 | encode |
| 34 | event |
| 35 | file |
| 36 | finfo |
| 37 | graph |
| 38 | http |
| 39 | http_socket |
| 40 |
+99
-7
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -32,10 +32,11 @@ | ||
| 32 | 32 | #define CFTYPE_CLUSTER 2 |
| 33 | 33 | #define CFTYPE_CONTROL 3 |
| 34 | 34 | #define CFTYPE_WIKI 4 |
| 35 | 35 | #define CFTYPE_TICKET 5 |
| 36 | 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | +#define CFTYPE_EVENT 7 | |
| 37 | 38 | |
| 38 | 39 | /* |
| 39 | 40 | ** A parsed manifest or cluster. |
| 40 | 41 | */ |
| 41 | 42 | struct Manifest { |
| @@ -45,10 +46,12 @@ | ||
| 45 | 46 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 46 | 47 | char *zUser; /* Name of the user from the U card. */ |
| 47 | 48 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 48 | 49 | char *zWiki; /* Text of the wiki page. W card. */ |
| 49 | 50 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 51 | + double rEventDate; /* Date of an event. E card. */ | |
| 52 | + char *zEventId; /* UUID for an event. E card. */ | |
| 50 | 53 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 51 | 54 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 52 | 55 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 53 | 56 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 54 | 57 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | ||
| 230 | 233 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 231 | 234 | zDate = blob_terminate(&a1); |
| 232 | 235 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 233 | 236 | break; |
| 234 | 237 | } |
| 238 | + | |
| 239 | + /* | |
| 240 | + ** E <timestamp> <uuid> | |
| 241 | + ** | |
| 242 | + ** An "event" card that contains the timestamp of the event in the | |
| 243 | + ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event. | |
| 244 | + ** The event timestamp is distinct from the D timestamp. The D | |
| 245 | + ** timestamp is when the artifact was created whereas the E timestamp | |
| 246 | + ** is when the specific event is said to occur. | |
| 247 | + */ | |
| 248 | + case 'E': { | |
| 249 | + char *zEDate; | |
| 250 | + md5sum_step_text(blob_buffer(&line), blob_size(&line)); | |
| 251 | + if( p->rEventDate!=0.0 ) goto manifest_syntax_error; | |
| 252 | + if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; | |
| 253 | + if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; | |
| 254 | + if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error; | |
| 255 | + zEDate = blob_terminate(&a1); | |
| 256 | + p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate); | |
| 257 | + if( p->rEventDate<=0.0 ) goto manifest_syntax_error; | |
| 258 | + if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error; | |
| 259 | + p->zEventId = blob_terminate(&a2); | |
| 260 | + if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error; | |
| 261 | + break; | |
| 262 | + } | |
| 235 | 263 | |
| 236 | 264 | /* |
| 237 | 265 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 238 | 266 | ** |
| 239 | 267 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | ||
| 563 | 591 | } |
| 564 | 592 | if( !seenHeader ) goto manifest_syntax_error; |
| 565 | 593 | |
| 566 | 594 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 567 | 595 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 568 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 596 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 569 | 597 | if( p->nField>0 ) goto manifest_syntax_error; |
| 570 | 598 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 571 | 599 | if( p->zWiki ) goto manifest_syntax_error; |
| 572 | 600 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 601 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 573 | 602 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 574 | 603 | if( p->zAttachName ) goto manifest_syntax_error; |
| 575 | 604 | p->type = CFTYPE_MANIFEST; |
| 576 | 605 | }else if( p->nCChild>0 ){ |
| 577 | 606 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | ||
| 581 | 610 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 582 | 611 | if( p->nField>0 ) goto manifest_syntax_error; |
| 583 | 612 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 584 | 613 | if( p->zWiki ) goto manifest_syntax_error; |
| 585 | 614 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 615 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 586 | 616 | if( p->zAttachName ) goto manifest_syntax_error; |
| 587 | 617 | if( !seenZ ) goto manifest_syntax_error; |
| 588 | 618 | p->type = CFTYPE_CLUSTER; |
| 589 | 619 | }else if( p->nField>0 ){ |
| 590 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 620 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 591 | 621 | if( p->zWiki ) goto manifest_syntax_error; |
| 592 | 622 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 623 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 593 | 624 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 594 | 625 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 595 | 626 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 596 | 627 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 597 | 628 | if( p->zAttachName ) goto manifest_syntax_error; |
| 598 | 629 | if( !seenZ ) goto manifest_syntax_error; |
| 599 | 630 | p->type = CFTYPE_TICKET; |
| 631 | + }else if( p->zEventId ){ | |
| 632 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 633 | + if( p->nCChild>0 ) goto manifest_syntax_error; | |
| 634 | + if( p->zTicketUuid!=0 ) goto manifest_syntax_error; | |
| 635 | + if( p->zWikiTitle!=0 ) goto manifest_syntax_error; | |
| 636 | + if( p->zWiki==0 ) goto manifest_syntax_error; | |
| 637 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 638 | + for(i=0; i<p->nTag; i++){ | |
| 639 | + if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error; | |
| 640 | + if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error; | |
| 641 | + } | |
| 642 | + if( !seenZ ) goto manifest_syntax_error; | |
| 643 | + p->type = CFTYPE_EVENT; | |
| 600 | 644 | }else if( p->zWiki!=0 ){ |
| 601 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 645 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 602 | 646 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 603 | 647 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 604 | 648 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 605 | 649 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 606 | 650 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | ||
| 614 | 658 | if( p->zAttachName ) goto manifest_syntax_error; |
| 615 | 659 | if( !seenZ ) goto manifest_syntax_error; |
| 616 | 660 | p->type = CFTYPE_CONTROL; |
| 617 | 661 | }else if( p->zAttachName ){ |
| 618 | 662 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 619 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 663 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 620 | 664 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 621 | 665 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 622 | 666 | if( !seenZ ) goto manifest_syntax_error; |
| 623 | 667 | p->type = CFTYPE_ATTACHMENT; |
| 624 | 668 | }else{ |
| @@ -625,14 +669,12 @@ | ||
| 625 | 669 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 626 | 670 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 627 | 671 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 628 | 672 | if( p->nField>0 ) goto manifest_syntax_error; |
| 629 | 673 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 630 | - if( p->zWiki ) goto manifest_syntax_error; | |
| 631 | 674 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 632 | 675 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 633 | - if( p->zAttachName ) goto manifest_syntax_error; | |
| 634 | 676 | p->type = CFTYPE_MANIFEST; |
| 635 | 677 | } |
| 636 | 678 | md5sum_init(); |
| 637 | 679 | return 1; |
| 638 | 680 | |
| @@ -964,10 +1006,12 @@ | ||
| 964 | 1006 | ** * Manifest |
| 965 | 1007 | ** * Control |
| 966 | 1008 | ** * Wiki Page |
| 967 | 1009 | ** * Ticket Change |
| 968 | 1010 | ** * Cluster |
| 1011 | +** * Attachment | |
| 1012 | +** * Event | |
| 969 | 1013 | ** |
| 970 | 1014 | ** If the input is a control artifact, then make appropriate entries |
| 971 | 1015 | ** in the auxiliary tables of the database in order to crosslink the |
| 972 | 1016 | ** artifact. |
| 973 | 1017 | ** |
| @@ -1043,11 +1087,14 @@ | ||
| 1043 | 1087 | if( mid>0 ){ |
| 1044 | 1088 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1045 | 1089 | } |
| 1046 | 1090 | } |
| 1047 | 1091 | } |
| 1048 | - if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ | |
| 1092 | + if( m.type==CFTYPE_CONTROL | |
| 1093 | + || m.type==CFTYPE_MANIFEST | |
| 1094 | + || m.type==CFTYPE_EVENT | |
| 1095 | + ){ | |
| 1049 | 1096 | for(i=0; i<m.nTag; i++){ |
| 1050 | 1097 | int tid; |
| 1051 | 1098 | int type; |
| 1052 | 1099 | if( m.aTag[i].zUuid ){ |
| 1053 | 1100 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | ||
| 1109 | 1156 | TAG_BGCOLOR, rid, |
| 1110 | 1157 | TAG_USER, rid, |
| 1111 | 1158 | TAG_COMMENT, rid |
| 1112 | 1159 | ); |
| 1113 | 1160 | free(zComment); |
| 1161 | + } | |
| 1162 | + if( m.type==CFTYPE_EVENT ){ | |
| 1163 | + char *zTag = mprintf("event-%s", m.zEventId); | |
| 1164 | + int tagid = tag_findid(zTag, 1); | |
| 1165 | + int prior, subsequent; | |
| 1166 | + int nWiki; | |
| 1167 | + char zLength[40]; | |
| 1168 | + while( isspace(m.zWiki[0]) ) m.zWiki++; | |
| 1169 | + nWiki = strlen(m.zWiki); | |
| 1170 | + sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); | |
| 1171 | + tag_insert(zTag, 1, zLength, rid, m.rDate, rid); | |
| 1172 | + free(zTag); | |
| 1173 | + prior = db_int(0, | |
| 1174 | + "SELECT rid FROM tagxref" | |
| 1175 | + " WHERE tagid=%d AND mtime<%.17g" | |
| 1176 | + " ORDER BY mtime DESC", | |
| 1177 | + tagid, m.rDate | |
| 1178 | + ); | |
| 1179 | + if( prior ){ | |
| 1180 | + content_deltify(prior, rid, 0); | |
| 1181 | + db_multi_exec( | |
| 1182 | + "DELETE FROM event" | |
| 1183 | + " WHERE type='e'" | |
| 1184 | + " AND tagid=%d" | |
| 1185 | + " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", | |
| 1186 | + tagid, tagid | |
| 1187 | + ); | |
| 1188 | + } | |
| 1189 | + subsequent = db_int(0, | |
| 1190 | + "SELECT rid FROM tagxref" | |
| 1191 | + " WHERE tagid=%d AND mtime>%.17g" | |
| 1192 | + " ORDER BY mtime", | |
| 1193 | + tagid, m.rDate | |
| 1194 | + ); | |
| 1195 | + if( subsequent ){ | |
| 1196 | + content_deltify(rid, subsequent, 0); | |
| 1197 | + }else{ | |
| 1198 | + db_multi_exec( | |
| 1199 | + "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)" | |
| 1200 | + "VALUES('e',%.17g,%d,%d,%Q,%Q," | |
| 1201 | + " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", | |
| 1202 | + m.rEventDate, rid, tagid, m.zUser, m.zComment, | |
| 1203 | + TAG_BGCOLOR, rid | |
| 1204 | + ); | |
| 1205 | + } | |
| 1114 | 1206 | } |
| 1115 | 1207 | if( m.type==CFTYPE_TICKET ){ |
| 1116 | 1208 | char *zTag; |
| 1117 | 1209 | |
| 1118 | 1210 | assert( manifest_crosslink_busy==1 ); |
| 1119 | 1211 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -32,10 +32,11 @@ | |
| 32 | #define CFTYPE_CLUSTER 2 |
| 33 | #define CFTYPE_CONTROL 3 |
| 34 | #define CFTYPE_WIKI 4 |
| 35 | #define CFTYPE_TICKET 5 |
| 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | |
| 38 | /* |
| 39 | ** A parsed manifest or cluster. |
| 40 | */ |
| 41 | struct Manifest { |
| @@ -45,10 +46,12 @@ | |
| 45 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 46 | char *zUser; /* Name of the user from the U card. */ |
| 47 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 48 | char *zWiki; /* Text of the wiki page. W card. */ |
| 49 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 50 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 51 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 52 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 53 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 54 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | |
| 230 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 231 | zDate = blob_terminate(&a1); |
| 232 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 233 | break; |
| 234 | } |
| 235 | |
| 236 | /* |
| 237 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 238 | ** |
| 239 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | |
| 563 | } |
| 564 | if( !seenHeader ) goto manifest_syntax_error; |
| 565 | |
| 566 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 567 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 568 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 569 | if( p->nField>0 ) goto manifest_syntax_error; |
| 570 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 571 | if( p->zWiki ) goto manifest_syntax_error; |
| 572 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 573 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 574 | if( p->zAttachName ) goto manifest_syntax_error; |
| 575 | p->type = CFTYPE_MANIFEST; |
| 576 | }else if( p->nCChild>0 ){ |
| 577 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | |
| 581 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 582 | if( p->nField>0 ) goto manifest_syntax_error; |
| 583 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 584 | if( p->zWiki ) goto manifest_syntax_error; |
| 585 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 586 | if( p->zAttachName ) goto manifest_syntax_error; |
| 587 | if( !seenZ ) goto manifest_syntax_error; |
| 588 | p->type = CFTYPE_CLUSTER; |
| 589 | }else if( p->nField>0 ){ |
| 590 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 591 | if( p->zWiki ) goto manifest_syntax_error; |
| 592 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 593 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 594 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 595 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 596 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 597 | if( p->zAttachName ) goto manifest_syntax_error; |
| 598 | if( !seenZ ) goto manifest_syntax_error; |
| 599 | p->type = CFTYPE_TICKET; |
| 600 | }else if( p->zWiki!=0 ){ |
| 601 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 602 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 603 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 604 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 605 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 606 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | |
| 614 | if( p->zAttachName ) goto manifest_syntax_error; |
| 615 | if( !seenZ ) goto manifest_syntax_error; |
| 616 | p->type = CFTYPE_CONTROL; |
| 617 | }else if( p->zAttachName ){ |
| 618 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 619 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 620 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 621 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 622 | if( !seenZ ) goto manifest_syntax_error; |
| 623 | p->type = CFTYPE_ATTACHMENT; |
| 624 | }else{ |
| @@ -625,14 +669,12 @@ | |
| 625 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 626 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 627 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 628 | if( p->nField>0 ) goto manifest_syntax_error; |
| 629 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 630 | if( p->zWiki ) goto manifest_syntax_error; |
| 631 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 632 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 633 | if( p->zAttachName ) goto manifest_syntax_error; |
| 634 | p->type = CFTYPE_MANIFEST; |
| 635 | } |
| 636 | md5sum_init(); |
| 637 | return 1; |
| 638 | |
| @@ -964,10 +1006,12 @@ | |
| 964 | ** * Manifest |
| 965 | ** * Control |
| 966 | ** * Wiki Page |
| 967 | ** * Ticket Change |
| 968 | ** * Cluster |
| 969 | ** |
| 970 | ** If the input is a control artifact, then make appropriate entries |
| 971 | ** in the auxiliary tables of the database in order to crosslink the |
| 972 | ** artifact. |
| 973 | ** |
| @@ -1043,11 +1087,14 @@ | |
| 1043 | if( mid>0 ){ |
| 1044 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1045 | } |
| 1046 | } |
| 1047 | } |
| 1048 | if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ |
| 1049 | for(i=0; i<m.nTag; i++){ |
| 1050 | int tid; |
| 1051 | int type; |
| 1052 | if( m.aTag[i].zUuid ){ |
| 1053 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | |
| 1109 | TAG_BGCOLOR, rid, |
| 1110 | TAG_USER, rid, |
| 1111 | TAG_COMMENT, rid |
| 1112 | ); |
| 1113 | free(zComment); |
| 1114 | } |
| 1115 | if( m.type==CFTYPE_TICKET ){ |
| 1116 | char *zTag; |
| 1117 | |
| 1118 | assert( manifest_crosslink_busy==1 ); |
| 1119 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -32,10 +32,11 @@ | |
| 32 | #define CFTYPE_CLUSTER 2 |
| 33 | #define CFTYPE_CONTROL 3 |
| 34 | #define CFTYPE_WIKI 4 |
| 35 | #define CFTYPE_TICKET 5 |
| 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | #define CFTYPE_EVENT 7 |
| 38 | |
| 39 | /* |
| 40 | ** A parsed manifest or cluster. |
| 41 | */ |
| 42 | struct Manifest { |
| @@ -45,10 +46,12 @@ | |
| 46 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 47 | char *zUser; /* Name of the user from the U card. */ |
| 48 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 49 | char *zWiki; /* Text of the wiki page. W card. */ |
| 50 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 51 | double rEventDate; /* Date of an event. E card. */ |
| 52 | char *zEventId; /* UUID for an event. E card. */ |
| 53 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 54 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 55 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 56 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 57 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | |
| 233 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 234 | zDate = blob_terminate(&a1); |
| 235 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 236 | break; |
| 237 | } |
| 238 | |
| 239 | /* |
| 240 | ** E <timestamp> <uuid> |
| 241 | ** |
| 242 | ** An "event" card that contains the timestamp of the event in the |
| 243 | ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event. |
| 244 | ** The event timestamp is distinct from the D timestamp. The D |
| 245 | ** timestamp is when the artifact was created whereas the E timestamp |
| 246 | ** is when the specific event is said to occur. |
| 247 | */ |
| 248 | case 'E': { |
| 249 | char *zEDate; |
| 250 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 251 | if( p->rEventDate!=0.0 ) goto manifest_syntax_error; |
| 252 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 253 | if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; |
| 254 | if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error; |
| 255 | zEDate = blob_terminate(&a1); |
| 256 | p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate); |
| 257 | if( p->rEventDate<=0.0 ) goto manifest_syntax_error; |
| 258 | if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error; |
| 259 | p->zEventId = blob_terminate(&a2); |
| 260 | if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error; |
| 261 | break; |
| 262 | } |
| 263 | |
| 264 | /* |
| 265 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 266 | ** |
| 267 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | |
| 591 | } |
| 592 | if( !seenHeader ) goto manifest_syntax_error; |
| 593 | |
| 594 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 595 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 596 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 597 | if( p->nField>0 ) goto manifest_syntax_error; |
| 598 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 599 | if( p->zWiki ) goto manifest_syntax_error; |
| 600 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 601 | if( p->zEventId ) goto manifest_syntax_error; |
| 602 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 603 | if( p->zAttachName ) goto manifest_syntax_error; |
| 604 | p->type = CFTYPE_MANIFEST; |
| 605 | }else if( p->nCChild>0 ){ |
| 606 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | |
| 610 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 611 | if( p->nField>0 ) goto manifest_syntax_error; |
| 612 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 613 | if( p->zWiki ) goto manifest_syntax_error; |
| 614 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 615 | if( p->zEventId ) goto manifest_syntax_error; |
| 616 | if( p->zAttachName ) goto manifest_syntax_error; |
| 617 | if( !seenZ ) goto manifest_syntax_error; |
| 618 | p->type = CFTYPE_CLUSTER; |
| 619 | }else if( p->nField>0 ){ |
| 620 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 621 | if( p->zWiki ) goto manifest_syntax_error; |
| 622 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 623 | if( p->zEventId ) goto manifest_syntax_error; |
| 624 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 625 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 626 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 627 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 628 | if( p->zAttachName ) goto manifest_syntax_error; |
| 629 | if( !seenZ ) goto manifest_syntax_error; |
| 630 | p->type = CFTYPE_TICKET; |
| 631 | }else if( p->zEventId ){ |
| 632 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 633 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 634 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 635 | if( p->zWikiTitle!=0 ) goto manifest_syntax_error; |
| 636 | if( p->zWiki==0 ) goto manifest_syntax_error; |
| 637 | if( p->zAttachName ) goto manifest_syntax_error; |
| 638 | for(i=0; i<p->nTag; i++){ |
| 639 | if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error; |
| 640 | if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error; |
| 641 | } |
| 642 | if( !seenZ ) goto manifest_syntax_error; |
| 643 | p->type = CFTYPE_EVENT; |
| 644 | }else if( p->zWiki!=0 ){ |
| 645 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 646 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 647 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 648 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 649 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 650 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | |
| 658 | if( p->zAttachName ) goto manifest_syntax_error; |
| 659 | if( !seenZ ) goto manifest_syntax_error; |
| 660 | p->type = CFTYPE_CONTROL; |
| 661 | }else if( p->zAttachName ){ |
| 662 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 663 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 664 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 665 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 666 | if( !seenZ ) goto manifest_syntax_error; |
| 667 | p->type = CFTYPE_ATTACHMENT; |
| 668 | }else{ |
| @@ -625,14 +669,12 @@ | |
| 669 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 670 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 671 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 672 | if( p->nField>0 ) goto manifest_syntax_error; |
| 673 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 674 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 675 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 676 | p->type = CFTYPE_MANIFEST; |
| 677 | } |
| 678 | md5sum_init(); |
| 679 | return 1; |
| 680 | |
| @@ -964,10 +1006,12 @@ | |
| 1006 | ** * Manifest |
| 1007 | ** * Control |
| 1008 | ** * Wiki Page |
| 1009 | ** * Ticket Change |
| 1010 | ** * Cluster |
| 1011 | ** * Attachment |
| 1012 | ** * Event |
| 1013 | ** |
| 1014 | ** If the input is a control artifact, then make appropriate entries |
| 1015 | ** in the auxiliary tables of the database in order to crosslink the |
| 1016 | ** artifact. |
| 1017 | ** |
| @@ -1043,11 +1087,14 @@ | |
| 1087 | if( mid>0 ){ |
| 1088 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1089 | } |
| 1090 | } |
| 1091 | } |
| 1092 | if( m.type==CFTYPE_CONTROL |
| 1093 | || m.type==CFTYPE_MANIFEST |
| 1094 | || m.type==CFTYPE_EVENT |
| 1095 | ){ |
| 1096 | for(i=0; i<m.nTag; i++){ |
| 1097 | int tid; |
| 1098 | int type; |
| 1099 | if( m.aTag[i].zUuid ){ |
| 1100 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | |
| 1156 | TAG_BGCOLOR, rid, |
| 1157 | TAG_USER, rid, |
| 1158 | TAG_COMMENT, rid |
| 1159 | ); |
| 1160 | free(zComment); |
| 1161 | } |
| 1162 | if( m.type==CFTYPE_EVENT ){ |
| 1163 | char *zTag = mprintf("event-%s", m.zEventId); |
| 1164 | int tagid = tag_findid(zTag, 1); |
| 1165 | int prior, subsequent; |
| 1166 | int nWiki; |
| 1167 | char zLength[40]; |
| 1168 | while( isspace(m.zWiki[0]) ) m.zWiki++; |
| 1169 | nWiki = strlen(m.zWiki); |
| 1170 | sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); |
| 1171 | tag_insert(zTag, 1, zLength, rid, m.rDate, rid); |
| 1172 | free(zTag); |
| 1173 | prior = db_int(0, |
| 1174 | "SELECT rid FROM tagxref" |
| 1175 | " WHERE tagid=%d AND mtime<%.17g" |
| 1176 | " ORDER BY mtime DESC", |
| 1177 | tagid, m.rDate |
| 1178 | ); |
| 1179 | if( prior ){ |
| 1180 | content_deltify(prior, rid, 0); |
| 1181 | db_multi_exec( |
| 1182 | "DELETE FROM event" |
| 1183 | " WHERE type='e'" |
| 1184 | " AND tagid=%d" |
| 1185 | " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", |
| 1186 | tagid, tagid |
| 1187 | ); |
| 1188 | } |
| 1189 | subsequent = db_int(0, |
| 1190 | "SELECT rid FROM tagxref" |
| 1191 | " WHERE tagid=%d AND mtime>%.17g" |
| 1192 | " ORDER BY mtime", |
| 1193 | tagid, m.rDate |
| 1194 | ); |
| 1195 | if( subsequent ){ |
| 1196 | content_deltify(rid, subsequent, 0); |
| 1197 | }else{ |
| 1198 | db_multi_exec( |
| 1199 | "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)" |
| 1200 | "VALUES('e',%.17g,%d,%d,%Q,%Q," |
| 1201 | " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", |
| 1202 | m.rEventDate, rid, tagid, m.zUser, m.zComment, |
| 1203 | TAG_BGCOLOR, rid |
| 1204 | ); |
| 1205 | } |
| 1206 | } |
| 1207 | if( m.type==CFTYPE_TICKET ){ |
| 1208 | char *zTag; |
| 1209 | |
| 1210 | assert( manifest_crosslink_busy==1 ); |
| 1211 |
+99
-7
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -32,10 +32,11 @@ | ||
| 32 | 32 | #define CFTYPE_CLUSTER 2 |
| 33 | 33 | #define CFTYPE_CONTROL 3 |
| 34 | 34 | #define CFTYPE_WIKI 4 |
| 35 | 35 | #define CFTYPE_TICKET 5 |
| 36 | 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | +#define CFTYPE_EVENT 7 | |
| 37 | 38 | |
| 38 | 39 | /* |
| 39 | 40 | ** A parsed manifest or cluster. |
| 40 | 41 | */ |
| 41 | 42 | struct Manifest { |
| @@ -45,10 +46,12 @@ | ||
| 45 | 46 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 46 | 47 | char *zUser; /* Name of the user from the U card. */ |
| 47 | 48 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 48 | 49 | char *zWiki; /* Text of the wiki page. W card. */ |
| 49 | 50 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 51 | + double rEventDate; /* Date of an event. E card. */ | |
| 52 | + char *zEventId; /* UUID for an event. E card. */ | |
| 50 | 53 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 51 | 54 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 52 | 55 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 53 | 56 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 54 | 57 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | ||
| 230 | 233 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 231 | 234 | zDate = blob_terminate(&a1); |
| 232 | 235 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 233 | 236 | break; |
| 234 | 237 | } |
| 238 | + | |
| 239 | + /* | |
| 240 | + ** E <timestamp> <uuid> | |
| 241 | + ** | |
| 242 | + ** An "event" card that contains the timestamp of the event in the | |
| 243 | + ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event. | |
| 244 | + ** The event timestamp is distinct from the D timestamp. The D | |
| 245 | + ** timestamp is when the artifact was created whereas the E timestamp | |
| 246 | + ** is when the specific event is said to occur. | |
| 247 | + */ | |
| 248 | + case 'E': { | |
| 249 | + char *zEDate; | |
| 250 | + md5sum_step_text(blob_buffer(&line), blob_size(&line)); | |
| 251 | + if( p->rEventDate!=0.0 ) goto manifest_syntax_error; | |
| 252 | + if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; | |
| 253 | + if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; | |
| 254 | + if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error; | |
| 255 | + zEDate = blob_terminate(&a1); | |
| 256 | + p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate); | |
| 257 | + if( p->rEventDate<=0.0 ) goto manifest_syntax_error; | |
| 258 | + if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error; | |
| 259 | + p->zEventId = blob_terminate(&a2); | |
| 260 | + if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error; | |
| 261 | + break; | |
| 262 | + } | |
| 235 | 263 | |
| 236 | 264 | /* |
| 237 | 265 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 238 | 266 | ** |
| 239 | 267 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | ||
| 563 | 591 | } |
| 564 | 592 | if( !seenHeader ) goto manifest_syntax_error; |
| 565 | 593 | |
| 566 | 594 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 567 | 595 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 568 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 596 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 569 | 597 | if( p->nField>0 ) goto manifest_syntax_error; |
| 570 | 598 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 571 | 599 | if( p->zWiki ) goto manifest_syntax_error; |
| 572 | 600 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 601 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 573 | 602 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 574 | 603 | if( p->zAttachName ) goto manifest_syntax_error; |
| 575 | 604 | p->type = CFTYPE_MANIFEST; |
| 576 | 605 | }else if( p->nCChild>0 ){ |
| 577 | 606 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | ||
| 581 | 610 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 582 | 611 | if( p->nField>0 ) goto manifest_syntax_error; |
| 583 | 612 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 584 | 613 | if( p->zWiki ) goto manifest_syntax_error; |
| 585 | 614 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 615 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 586 | 616 | if( p->zAttachName ) goto manifest_syntax_error; |
| 587 | 617 | if( !seenZ ) goto manifest_syntax_error; |
| 588 | 618 | p->type = CFTYPE_CLUSTER; |
| 589 | 619 | }else if( p->nField>0 ){ |
| 590 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 620 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 591 | 621 | if( p->zWiki ) goto manifest_syntax_error; |
| 592 | 622 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 623 | + if( p->zEventId ) goto manifest_syntax_error; | |
| 593 | 624 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 594 | 625 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 595 | 626 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 596 | 627 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 597 | 628 | if( p->zAttachName ) goto manifest_syntax_error; |
| 598 | 629 | if( !seenZ ) goto manifest_syntax_error; |
| 599 | 630 | p->type = CFTYPE_TICKET; |
| 631 | + }else if( p->zEventId ){ | |
| 632 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 633 | + if( p->nCChild>0 ) goto manifest_syntax_error; | |
| 634 | + if( p->zTicketUuid!=0 ) goto manifest_syntax_error; | |
| 635 | + if( p->zWikiTitle!=0 ) goto manifest_syntax_error; | |
| 636 | + if( p->zWiki==0 ) goto manifest_syntax_error; | |
| 637 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 638 | + for(i=0; i<p->nTag; i++){ | |
| 639 | + if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error; | |
| 640 | + if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error; | |
| 641 | + } | |
| 642 | + if( !seenZ ) goto manifest_syntax_error; | |
| 643 | + p->type = CFTYPE_EVENT; | |
| 600 | 644 | }else if( p->zWiki!=0 ){ |
| 601 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 645 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 602 | 646 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 603 | 647 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 604 | 648 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 605 | 649 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 606 | 650 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | ||
| 614 | 658 | if( p->zAttachName ) goto manifest_syntax_error; |
| 615 | 659 | if( !seenZ ) goto manifest_syntax_error; |
| 616 | 660 | p->type = CFTYPE_CONTROL; |
| 617 | 661 | }else if( p->zAttachName ){ |
| 618 | 662 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 619 | - if( p->rDate==0.0 ) goto manifest_syntax_error; | |
| 663 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 620 | 664 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 621 | 665 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 622 | 666 | if( !seenZ ) goto manifest_syntax_error; |
| 623 | 667 | p->type = CFTYPE_ATTACHMENT; |
| 624 | 668 | }else{ |
| @@ -625,14 +669,12 @@ | ||
| 625 | 669 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 626 | 670 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 627 | 671 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 628 | 672 | if( p->nField>0 ) goto manifest_syntax_error; |
| 629 | 673 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 630 | - if( p->zWiki ) goto manifest_syntax_error; | |
| 631 | 674 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 632 | 675 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 633 | - if( p->zAttachName ) goto manifest_syntax_error; | |
| 634 | 676 | p->type = CFTYPE_MANIFEST; |
| 635 | 677 | } |
| 636 | 678 | md5sum_init(); |
| 637 | 679 | return 1; |
| 638 | 680 | |
| @@ -964,10 +1006,12 @@ | ||
| 964 | 1006 | ** * Manifest |
| 965 | 1007 | ** * Control |
| 966 | 1008 | ** * Wiki Page |
| 967 | 1009 | ** * Ticket Change |
| 968 | 1010 | ** * Cluster |
| 1011 | +** * Attachment | |
| 1012 | +** * Event | |
| 969 | 1013 | ** |
| 970 | 1014 | ** If the input is a control artifact, then make appropriate entries |
| 971 | 1015 | ** in the auxiliary tables of the database in order to crosslink the |
| 972 | 1016 | ** artifact. |
| 973 | 1017 | ** |
| @@ -1043,11 +1087,14 @@ | ||
| 1043 | 1087 | if( mid>0 ){ |
| 1044 | 1088 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1045 | 1089 | } |
| 1046 | 1090 | } |
| 1047 | 1091 | } |
| 1048 | - if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ | |
| 1092 | + if( m.type==CFTYPE_CONTROL | |
| 1093 | + || m.type==CFTYPE_MANIFEST | |
| 1094 | + || m.type==CFTYPE_EVENT | |
| 1095 | + ){ | |
| 1049 | 1096 | for(i=0; i<m.nTag; i++){ |
| 1050 | 1097 | int tid; |
| 1051 | 1098 | int type; |
| 1052 | 1099 | if( m.aTag[i].zUuid ){ |
| 1053 | 1100 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | ||
| 1109 | 1156 | TAG_BGCOLOR, rid, |
| 1110 | 1157 | TAG_USER, rid, |
| 1111 | 1158 | TAG_COMMENT, rid |
| 1112 | 1159 | ); |
| 1113 | 1160 | free(zComment); |
| 1161 | + } | |
| 1162 | + if( m.type==CFTYPE_EVENT ){ | |
| 1163 | + char *zTag = mprintf("event-%s", m.zEventId); | |
| 1164 | + int tagid = tag_findid(zTag, 1); | |
| 1165 | + int prior, subsequent; | |
| 1166 | + int nWiki; | |
| 1167 | + char zLength[40]; | |
| 1168 | + while( isspace(m.zWiki[0]) ) m.zWiki++; | |
| 1169 | + nWiki = strlen(m.zWiki); | |
| 1170 | + sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); | |
| 1171 | + tag_insert(zTag, 1, zLength, rid, m.rDate, rid); | |
| 1172 | + free(zTag); | |
| 1173 | + prior = db_int(0, | |
| 1174 | + "SELECT rid FROM tagxref" | |
| 1175 | + " WHERE tagid=%d AND mtime<%.17g" | |
| 1176 | + " ORDER BY mtime DESC", | |
| 1177 | + tagid, m.rDate | |
| 1178 | + ); | |
| 1179 | + if( prior ){ | |
| 1180 | + content_deltify(prior, rid, 0); | |
| 1181 | + db_multi_exec( | |
| 1182 | + "DELETE FROM event" | |
| 1183 | + " WHERE type='e'" | |
| 1184 | + " AND tagid=%d" | |
| 1185 | + " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", | |
| 1186 | + tagid, tagid | |
| 1187 | + ); | |
| 1188 | + } | |
| 1189 | + subsequent = db_int(0, | |
| 1190 | + "SELECT rid FROM tagxref" | |
| 1191 | + " WHERE tagid=%d AND mtime>%.17g" | |
| 1192 | + " ORDER BY mtime", | |
| 1193 | + tagid, m.rDate | |
| 1194 | + ); | |
| 1195 | + if( subsequent ){ | |
| 1196 | + content_deltify(rid, subsequent, 0); | |
| 1197 | + }else{ | |
| 1198 | + db_multi_exec( | |
| 1199 | + "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)" | |
| 1200 | + "VALUES('e',%.17g,%d,%d,%Q,%Q," | |
| 1201 | + " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", | |
| 1202 | + m.rEventDate, rid, tagid, m.zUser, m.zComment, | |
| 1203 | + TAG_BGCOLOR, rid | |
| 1204 | + ); | |
| 1205 | + } | |
| 1114 | 1206 | } |
| 1115 | 1207 | if( m.type==CFTYPE_TICKET ){ |
| 1116 | 1208 | char *zTag; |
| 1117 | 1209 | |
| 1118 | 1210 | assert( manifest_crosslink_busy==1 ); |
| 1119 | 1211 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -32,10 +32,11 @@ | |
| 32 | #define CFTYPE_CLUSTER 2 |
| 33 | #define CFTYPE_CONTROL 3 |
| 34 | #define CFTYPE_WIKI 4 |
| 35 | #define CFTYPE_TICKET 5 |
| 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | |
| 38 | /* |
| 39 | ** A parsed manifest or cluster. |
| 40 | */ |
| 41 | struct Manifest { |
| @@ -45,10 +46,12 @@ | |
| 45 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 46 | char *zUser; /* Name of the user from the U card. */ |
| 47 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 48 | char *zWiki; /* Text of the wiki page. W card. */ |
| 49 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 50 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 51 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 52 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 53 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 54 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | |
| 230 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 231 | zDate = blob_terminate(&a1); |
| 232 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 233 | break; |
| 234 | } |
| 235 | |
| 236 | /* |
| 237 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 238 | ** |
| 239 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | |
| 563 | } |
| 564 | if( !seenHeader ) goto manifest_syntax_error; |
| 565 | |
| 566 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 567 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 568 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 569 | if( p->nField>0 ) goto manifest_syntax_error; |
| 570 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 571 | if( p->zWiki ) goto manifest_syntax_error; |
| 572 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 573 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 574 | if( p->zAttachName ) goto manifest_syntax_error; |
| 575 | p->type = CFTYPE_MANIFEST; |
| 576 | }else if( p->nCChild>0 ){ |
| 577 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | |
| 581 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 582 | if( p->nField>0 ) goto manifest_syntax_error; |
| 583 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 584 | if( p->zWiki ) goto manifest_syntax_error; |
| 585 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 586 | if( p->zAttachName ) goto manifest_syntax_error; |
| 587 | if( !seenZ ) goto manifest_syntax_error; |
| 588 | p->type = CFTYPE_CLUSTER; |
| 589 | }else if( p->nField>0 ){ |
| 590 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 591 | if( p->zWiki ) goto manifest_syntax_error; |
| 592 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 593 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 594 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 595 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 596 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 597 | if( p->zAttachName ) goto manifest_syntax_error; |
| 598 | if( !seenZ ) goto manifest_syntax_error; |
| 599 | p->type = CFTYPE_TICKET; |
| 600 | }else if( p->zWiki!=0 ){ |
| 601 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 602 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 603 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 604 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 605 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 606 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | |
| 614 | if( p->zAttachName ) goto manifest_syntax_error; |
| 615 | if( !seenZ ) goto manifest_syntax_error; |
| 616 | p->type = CFTYPE_CONTROL; |
| 617 | }else if( p->zAttachName ){ |
| 618 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 619 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 620 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 621 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 622 | if( !seenZ ) goto manifest_syntax_error; |
| 623 | p->type = CFTYPE_ATTACHMENT; |
| 624 | }else{ |
| @@ -625,14 +669,12 @@ | |
| 625 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 626 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 627 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 628 | if( p->nField>0 ) goto manifest_syntax_error; |
| 629 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 630 | if( p->zWiki ) goto manifest_syntax_error; |
| 631 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 632 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 633 | if( p->zAttachName ) goto manifest_syntax_error; |
| 634 | p->type = CFTYPE_MANIFEST; |
| 635 | } |
| 636 | md5sum_init(); |
| 637 | return 1; |
| 638 | |
| @@ -964,10 +1006,12 @@ | |
| 964 | ** * Manifest |
| 965 | ** * Control |
| 966 | ** * Wiki Page |
| 967 | ** * Ticket Change |
| 968 | ** * Cluster |
| 969 | ** |
| 970 | ** If the input is a control artifact, then make appropriate entries |
| 971 | ** in the auxiliary tables of the database in order to crosslink the |
| 972 | ** artifact. |
| 973 | ** |
| @@ -1043,11 +1087,14 @@ | |
| 1043 | if( mid>0 ){ |
| 1044 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1045 | } |
| 1046 | } |
| 1047 | } |
| 1048 | if( m.type==CFTYPE_CONTROL || m.type==CFTYPE_MANIFEST ){ |
| 1049 | for(i=0; i<m.nTag; i++){ |
| 1050 | int tid; |
| 1051 | int type; |
| 1052 | if( m.aTag[i].zUuid ){ |
| 1053 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | |
| 1109 | TAG_BGCOLOR, rid, |
| 1110 | TAG_USER, rid, |
| 1111 | TAG_COMMENT, rid |
| 1112 | ); |
| 1113 | free(zComment); |
| 1114 | } |
| 1115 | if( m.type==CFTYPE_TICKET ){ |
| 1116 | char *zTag; |
| 1117 | |
| 1118 | assert( manifest_crosslink_busy==1 ); |
| 1119 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -32,10 +32,11 @@ | |
| 32 | #define CFTYPE_CLUSTER 2 |
| 33 | #define CFTYPE_CONTROL 3 |
| 34 | #define CFTYPE_WIKI 4 |
| 35 | #define CFTYPE_TICKET 5 |
| 36 | #define CFTYPE_ATTACHMENT 6 |
| 37 | #define CFTYPE_EVENT 7 |
| 38 | |
| 39 | /* |
| 40 | ** A parsed manifest or cluster. |
| 41 | */ |
| 42 | struct Manifest { |
| @@ -45,10 +46,12 @@ | |
| 46 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 47 | char *zUser; /* Name of the user from the U card. */ |
| 48 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 49 | char *zWiki; /* Text of the wiki page. W card. */ |
| 50 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 51 | double rEventDate; /* Date of an event. E card. */ |
| 52 | char *zEventId; /* UUID for an event. E card. */ |
| 53 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 54 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 55 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 56 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 57 | int nFile; /* Number of F cards */ |
| @@ -230,10 +233,35 @@ | |
| 233 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 234 | zDate = blob_terminate(&a1); |
| 235 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 236 | break; |
| 237 | } |
| 238 | |
| 239 | /* |
| 240 | ** E <timestamp> <uuid> |
| 241 | ** |
| 242 | ** An "event" card that contains the timestamp of the event in the |
| 243 | ** format YYYY-MM-DDtHH:MM:SS and a unique identifier for the event. |
| 244 | ** The event timestamp is distinct from the D timestamp. The D |
| 245 | ** timestamp is when the artifact was created whereas the E timestamp |
| 246 | ** is when the specific event is said to occur. |
| 247 | */ |
| 248 | case 'E': { |
| 249 | char *zEDate; |
| 250 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 251 | if( p->rEventDate!=0.0 ) goto manifest_syntax_error; |
| 252 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 253 | if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; |
| 254 | if( blob_token(&line, &a3)!=0 ) goto manifest_syntax_error; |
| 255 | zEDate = blob_terminate(&a1); |
| 256 | p->rEventDate = db_double(0.0, "SELECT julianday(%Q)", zEDate); |
| 257 | if( p->rEventDate<=0.0 ) goto manifest_syntax_error; |
| 258 | if( blob_size(&a2)!=UUID_SIZE ) goto manifest_syntax_error; |
| 259 | p->zEventId = blob_terminate(&a2); |
| 260 | if( !validate16(p->zEventId, UUID_SIZE) ) goto manifest_syntax_error; |
| 261 | break; |
| 262 | } |
| 263 | |
| 264 | /* |
| 265 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| 266 | ** |
| 267 | ** Identifies a file in a manifest. Multiple F lines are |
| @@ -563,15 +591,16 @@ | |
| 591 | } |
| 592 | if( !seenHeader ) goto manifest_syntax_error; |
| 593 | |
| 594 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 595 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 596 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 597 | if( p->nField>0 ) goto manifest_syntax_error; |
| 598 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 599 | if( p->zWiki ) goto manifest_syntax_error; |
| 600 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 601 | if( p->zEventId ) goto manifest_syntax_error; |
| 602 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 603 | if( p->zAttachName ) goto manifest_syntax_error; |
| 604 | p->type = CFTYPE_MANIFEST; |
| 605 | }else if( p->nCChild>0 ){ |
| 606 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| @@ -581,26 +610,41 @@ | |
| 610 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 611 | if( p->nField>0 ) goto manifest_syntax_error; |
| 612 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 613 | if( p->zWiki ) goto manifest_syntax_error; |
| 614 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 615 | if( p->zEventId ) goto manifest_syntax_error; |
| 616 | if( p->zAttachName ) goto manifest_syntax_error; |
| 617 | if( !seenZ ) goto manifest_syntax_error; |
| 618 | p->type = CFTYPE_CLUSTER; |
| 619 | }else if( p->nField>0 ){ |
| 620 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 621 | if( p->zWiki ) goto manifest_syntax_error; |
| 622 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 623 | if( p->zEventId ) goto manifest_syntax_error; |
| 624 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 625 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 626 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 627 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 628 | if( p->zAttachName ) goto manifest_syntax_error; |
| 629 | if( !seenZ ) goto manifest_syntax_error; |
| 630 | p->type = CFTYPE_TICKET; |
| 631 | }else if( p->zEventId ){ |
| 632 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 633 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 634 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 635 | if( p->zWikiTitle!=0 ) goto manifest_syntax_error; |
| 636 | if( p->zWiki==0 ) goto manifest_syntax_error; |
| 637 | if( p->zAttachName ) goto manifest_syntax_error; |
| 638 | for(i=0; i<p->nTag; i++){ |
| 639 | if( p->aTag[i].zName[0]!='+' ) goto manifest_syntax_error; |
| 640 | if( p->aTag[i].zUuid!=0 ) goto manifest_syntax_error; |
| 641 | } |
| 642 | if( !seenZ ) goto manifest_syntax_error; |
| 643 | p->type = CFTYPE_EVENT; |
| 644 | }else if( p->zWiki!=0 ){ |
| 645 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 646 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 647 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 648 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 649 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 650 | if( p->zAttachName ) goto manifest_syntax_error; |
| @@ -614,11 +658,11 @@ | |
| 658 | if( p->zAttachName ) goto manifest_syntax_error; |
| 659 | if( !seenZ ) goto manifest_syntax_error; |
| 660 | p->type = CFTYPE_CONTROL; |
| 661 | }else if( p->zAttachName ){ |
| 662 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 663 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 664 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 665 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 666 | if( !seenZ ) goto manifest_syntax_error; |
| 667 | p->type = CFTYPE_ATTACHMENT; |
| 668 | }else{ |
| @@ -625,14 +669,12 @@ | |
| 669 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 670 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 671 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 672 | if( p->nField>0 ) goto manifest_syntax_error; |
| 673 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 674 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 675 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 676 | p->type = CFTYPE_MANIFEST; |
| 677 | } |
| 678 | md5sum_init(); |
| 679 | return 1; |
| 680 | |
| @@ -964,10 +1006,12 @@ | |
| 1006 | ** * Manifest |
| 1007 | ** * Control |
| 1008 | ** * Wiki Page |
| 1009 | ** * Ticket Change |
| 1010 | ** * Cluster |
| 1011 | ** * Attachment |
| 1012 | ** * Event |
| 1013 | ** |
| 1014 | ** If the input is a control artifact, then make appropriate entries |
| 1015 | ** in the auxiliary tables of the database in order to crosslink the |
| 1016 | ** artifact. |
| 1017 | ** |
| @@ -1043,11 +1087,14 @@ | |
| 1087 | if( mid>0 ){ |
| 1088 | db_multi_exec("DELETE FROM unclustered WHERE rid=%d", mid); |
| 1089 | } |
| 1090 | } |
| 1091 | } |
| 1092 | if( m.type==CFTYPE_CONTROL |
| 1093 | || m.type==CFTYPE_MANIFEST |
| 1094 | || m.type==CFTYPE_EVENT |
| 1095 | ){ |
| 1096 | for(i=0; i<m.nTag; i++){ |
| 1097 | int tid; |
| 1098 | int type; |
| 1099 | if( m.aTag[i].zUuid ){ |
| 1100 | tid = uuid_to_rid(m.aTag[i].zUuid, 1); |
| @@ -1109,10 +1156,55 @@ | |
| 1156 | TAG_BGCOLOR, rid, |
| 1157 | TAG_USER, rid, |
| 1158 | TAG_COMMENT, rid |
| 1159 | ); |
| 1160 | free(zComment); |
| 1161 | } |
| 1162 | if( m.type==CFTYPE_EVENT ){ |
| 1163 | char *zTag = mprintf("event-%s", m.zEventId); |
| 1164 | int tagid = tag_findid(zTag, 1); |
| 1165 | int prior, subsequent; |
| 1166 | int nWiki; |
| 1167 | char zLength[40]; |
| 1168 | while( isspace(m.zWiki[0]) ) m.zWiki++; |
| 1169 | nWiki = strlen(m.zWiki); |
| 1170 | sqlite3_snprintf(sizeof(zLength), zLength, "%d", nWiki); |
| 1171 | tag_insert(zTag, 1, zLength, rid, m.rDate, rid); |
| 1172 | free(zTag); |
| 1173 | prior = db_int(0, |
| 1174 | "SELECT rid FROM tagxref" |
| 1175 | " WHERE tagid=%d AND mtime<%.17g" |
| 1176 | " ORDER BY mtime DESC", |
| 1177 | tagid, m.rDate |
| 1178 | ); |
| 1179 | if( prior ){ |
| 1180 | content_deltify(prior, rid, 0); |
| 1181 | db_multi_exec( |
| 1182 | "DELETE FROM event" |
| 1183 | " WHERE type='e'" |
| 1184 | " AND tagid=%d" |
| 1185 | " AND objid IN (SELECT rid FROM tagxref WHERE tagid=%d)", |
| 1186 | tagid, tagid |
| 1187 | ); |
| 1188 | } |
| 1189 | subsequent = db_int(0, |
| 1190 | "SELECT rid FROM tagxref" |
| 1191 | " WHERE tagid=%d AND mtime>%.17g" |
| 1192 | " ORDER BY mtime", |
| 1193 | tagid, m.rDate |
| 1194 | ); |
| 1195 | if( subsequent ){ |
| 1196 | content_deltify(rid, subsequent, 0); |
| 1197 | }else{ |
| 1198 | db_multi_exec( |
| 1199 | "REPLACE INTO event(type,mtime,objid,tagid,user,comment,bgcolor)" |
| 1200 | "VALUES('e',%.17g,%d,%d,%Q,%Q," |
| 1201 | " (SELECT value FROM tagxref WHERE tagid=%d AND rid=%d));", |
| 1202 | m.rEventDate, rid, tagid, m.zUser, m.zComment, |
| 1203 | TAG_BGCOLOR, rid |
| 1204 | ); |
| 1205 | } |
| 1206 | } |
| 1207 | if( m.type==CFTYPE_TICKET ){ |
| 1208 | char *zTag; |
| 1209 | |
| 1210 | assert( manifest_crosslink_busy==1 ); |
| 1211 |
+3
-3
| --- src/printf.c | ||
| +++ src/printf.c | ||
| @@ -44,13 +44,13 @@ | ||
| 44 | 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | 48 | #define etPATH 20 /* Path type */ |
| 49 | -#define etWIKISTR 21 /* Wiki text rendered from a char* */ | |
| 50 | -#define etWIKIBLOB 22 /* Wiki text rendered from a Blob* */ | |
| 51 | -#define etSTRINGID 23 /* String with length limit for a UUID prefix */ | |
| 49 | +#define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ | |
| 50 | +#define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ | |
| 51 | +#define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ | |
| 52 | 52 | |
| 53 | 53 | |
| 54 | 54 | /* |
| 55 | 55 | ** An "etByte" is an 8-bit unsigned value. |
| 56 | 56 | */ |
| 57 | 57 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -44,13 +44,13 @@ | |
| 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Wiki text rendered from a char* */ |
| 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob* */ |
| 51 | #define etSTRINGID 23 /* String with length limit for a UUID prefix */ |
| 52 | |
| 53 | |
| 54 | /* |
| 55 | ** An "etByte" is an 8-bit unsigned value. |
| 56 | */ |
| 57 |
| --- src/printf.c | |
| +++ src/printf.c | |
| @@ -44,13 +44,13 @@ | |
| 44 | #define etHTMLIZE 16 /* Make text safe for HTML */ |
| 45 | #define etHTTPIZE 17 /* Make text safe for HTTP. "/" encoded as %2f */ |
| 46 | #define etURLIZE 18 /* Make text safe for HTTP. "/" not encoded */ |
| 47 | #define etFOSSILIZE 19 /* The fossil header encoding format. */ |
| 48 | #define etPATH 20 /* Path type */ |
| 49 | #define etWIKISTR 21 /* Wiki text rendered from a char*: %w */ |
| 50 | #define etWIKIBLOB 22 /* Wiki text rendered from a Blob*: %W */ |
| 51 | #define etSTRINGID 23 /* String with length limit for a UUID prefix: %S */ |
| 52 | |
| 53 | |
| 54 | /* |
| 55 | ** An "etByte" is an 8-bit unsigned value. |
| 56 | */ |
| 57 |
+1
-1
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -198,11 +198,11 @@ | ||
| 198 | 198 | @ media="screen" /> |
| 199 | 199 | @ </head> |
| 200 | 200 | @ <body> |
| 201 | 201 | @ <div class="header"> |
| 202 | 202 | @ <div class="logo"> |
| 203 | -@ <img src="$baseurl/logo" alt="logo"> | |
| 203 | +@ <img src="$baseurl/logo" alt="logo" /> | |
| 204 | 204 | @ </div> |
| 205 | 205 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 206 | 206 | @ <div class="status"><th1> |
| 207 | 207 | @ if {[info exists login]} { |
| 208 | 208 | @ puts "Logged in as $login" |
| 209 | 209 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -198,11 +198,11 @@ | |
| 198 | @ media="screen" /> |
| 199 | @ </head> |
| 200 | @ <body> |
| 201 | @ <div class="header"> |
| 202 | @ <div class="logo"> |
| 203 | @ <img src="$baseurl/logo" alt="logo"> |
| 204 | @ </div> |
| 205 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 206 | @ <div class="status"><th1> |
| 207 | @ if {[info exists login]} { |
| 208 | @ puts "Logged in as $login" |
| 209 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -198,11 +198,11 @@ | |
| 198 | @ media="screen" /> |
| 199 | @ </head> |
| 200 | @ <body> |
| 201 | @ <div class="header"> |
| 202 | @ <div class="logo"> |
| 203 | @ <img src="$baseurl/logo" alt="logo" /> |
| 204 | @ </div> |
| 205 | @ <div class="title"><small>$<project_name></small><br />$<title></div> |
| 206 | @ <div class="status"><th1> |
| 207 | @ if {[info exists login]} { |
| 208 | @ puts "Logged in as $login" |
| 209 |
+16
-8
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -165,11 +165,11 @@ | ||
| 165 | 165 | ** 4. User |
| 166 | 166 | ** 5. True if is a leaf |
| 167 | 167 | ** 6. background color |
| 168 | 168 | ** 7. type ("ci", "w", "t") |
| 169 | 169 | ** 8. list of symbolic tags. |
| 170 | -** 9. tagid for ticket or wiki | |
| 170 | +** 9. tagid for ticket or wiki or event | |
| 171 | 171 | ** 10. Short comment to user for repeated tickets and wiki |
| 172 | 172 | */ |
| 173 | 173 | void www_print_timeline( |
| 174 | 174 | Stmt *pQuery, /* Query to implement the timeline */ |
| 175 | 175 | int tmFlags, /* Flags controlling display behavior */ |
| @@ -288,10 +288,12 @@ | ||
| 288 | 288 | @ <span class="timelineLeaf">Closed-Leaf:</span> |
| 289 | 289 | }else{ |
| 290 | 290 | @ <span class="timelineLeaf">Leaf:</span> |
| 291 | 291 | } |
| 292 | 292 | } |
| 293 | + }else if( zType[0]=='e' && tagid ){ | |
| 294 | + hyperlink_to_event_tagid(tagid); | |
| 293 | 295 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 294 | 296 | hyperlink_to_uuid(zUuid); |
| 295 | 297 | } |
| 296 | 298 | db_column_blob(pQuery, commentColumn, &comment); |
| 297 | 299 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| @@ -639,11 +641,11 @@ | ||
| 639 | 641 | ** p=RID artifact RID and up to COUNT parents and ancestors |
| 640 | 642 | ** d=RID artifact RID and up to COUNT descendants |
| 641 | 643 | ** t=TAGID show only check-ins with the given tagid |
| 642 | 644 | ** r=TAGID show check-ins related to tagid |
| 643 | 645 | ** u=USER only if belonging to this user |
| 644 | -** y=TYPE 'ci', 'w', 't' | |
| 646 | +** y=TYPE 'ci', 'w', 't', 'e' | |
| 645 | 647 | ** s=TEXT string search (comment and brief) |
| 646 | 648 | ** ng Suppress the graph if present |
| 647 | 649 | ** |
| 648 | 650 | ** p= and d= can appear individually or together. If either p= or d= |
| 649 | 651 | ** appear, then u=, y=, a=, and b= are ignored. |
| @@ -749,22 +751,22 @@ | ||
| 749 | 751 | }else{ |
| 750 | 752 | blob_appendf(&desc, " of check-in [%.10s]", zUuid); |
| 751 | 753 | } |
| 752 | 754 | }else{ |
| 753 | 755 | int n; |
| 754 | - const char *zEType = "event"; | |
| 756 | + const char *zEType = "timeline item"; | |
| 755 | 757 | char *zDate; |
| 756 | 758 | char *zNEntry = mprintf("%d", nEntry); |
| 757 | 759 | url_initialize(&url, "timeline"); |
| 758 | 760 | url_add_parameter(&url, "n", zNEntry); |
| 759 | 761 | if( tagid>0 ){ |
| 760 | - zType = "ci"; | |
| 762 | + if( zType[0]!='e' ) zType = "ci"; | |
| 761 | 763 | blob_appendf(&sql, |
| 762 | 764 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 763 | 765 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 764 | 766 | |
| 765 | - if( zBrName ){ | |
| 767 | + if( zBrName && zType[0]=='c' ){ | |
| 766 | 768 | /* The next two blob_appendf() calls add SQL that causes checkins that |
| 767 | 769 | ** are not part of the branch which are parents or childen of the branch |
| 768 | 770 | ** to be included in the report. This related check-ins are useful |
| 769 | 771 | ** in helping to visualize what has happened on a quiescent branch |
| 770 | 772 | ** that is infrequently merged with a much more activate branch. |
| @@ -781,10 +783,11 @@ | ||
| 781 | 783 | } |
| 782 | 784 | blob_appendf(&sql, ")"); |
| 783 | 785 | } |
| 784 | 786 | if( (zType[0]=='w' && !g.okRdWiki) |
| 785 | 787 | || (zType[0]=='t' && !g.okRdTkt) |
| 788 | + || (zType[0]=='e' && !g.okRdWiki) | |
| 786 | 789 | || (zType[0]=='c' && !g.okRead) |
| 787 | 790 | ){ |
| 788 | 791 | zType = "all"; |
| 789 | 792 | } |
| 790 | 793 | if( zType[0]=='a' ){ |
| @@ -794,11 +797,11 @@ | ||
| 794 | 797 | if( g.okRead ){ |
| 795 | 798 | blob_appendf(&sql, "%c'ci'", cSep); |
| 796 | 799 | cSep = ','; |
| 797 | 800 | } |
| 798 | 801 | if( g.okRdWiki ){ |
| 799 | - blob_appendf(&sql, "%c'w'", cSep); | |
| 802 | + blob_appendf(&sql, "%c'w','e'", cSep); | |
| 800 | 803 | cSep = ','; |
| 801 | 804 | } |
| 802 | 805 | if( g.okRdTkt ){ |
| 803 | 806 | blob_appendf(&sql, "%c't'", cSep); |
| 804 | 807 | cSep = ','; |
| @@ -812,10 +815,12 @@ | ||
| 812 | 815 | zEType = "checkin"; |
| 813 | 816 | }else if( zType[0]=='w' ){ |
| 814 | 817 | zEType = "wiki edit"; |
| 815 | 818 | }else if( zType[0]=='t' ){ |
| 816 | 819 | zEType = "ticket change"; |
| 820 | + }else if( zType[0]=='e' ){ | |
| 821 | + zEType = "event"; | |
| 817 | 822 | } |
| 818 | 823 | } |
| 819 | 824 | if( zUser ){ |
| 820 | 825 | blob_appendf(&sql, " AND event.user=%Q", zUser); |
| 821 | 826 | url_add_parameter(&url, "u", zUser); |
| @@ -926,16 +931,19 @@ | ||
| 926 | 931 | timeline_submenu(&url, "Checkins Only", "y", "ci", 0); |
| 927 | 932 | } |
| 928 | 933 | if( zType[0]!='t' && g.okRdTkt ){ |
| 929 | 934 | timeline_submenu(&url, "Tickets Only", "y", "t", 0); |
| 930 | 935 | } |
| 936 | + if( zType[0]!='e' && g.okRdWiki ){ | |
| 937 | + timeline_submenu(&url, "Events Only", "y", "e", 0); | |
| 938 | + } | |
| 931 | 939 | } |
| 932 | 940 | if( nEntry>20 ){ |
| 933 | - timeline_submenu(&url, "20 Events", "n", "20", 0); | |
| 941 | + timeline_submenu(&url, "20 Entries", "n", "20", 0); | |
| 934 | 942 | } |
| 935 | 943 | if( nEntry<200 ){ |
| 936 | - timeline_submenu(&url, "200 Events", "n", "200", 0); | |
| 944 | + timeline_submenu(&url, "200 Entries", "n", "200", 0); | |
| 937 | 945 | } |
| 938 | 946 | } |
| 939 | 947 | } |
| 940 | 948 | blob_zero(&sql); |
| 941 | 949 | db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/"); |
| 942 | 950 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -165,11 +165,11 @@ | |
| 165 | ** 4. User |
| 166 | ** 5. True if is a leaf |
| 167 | ** 6. background color |
| 168 | ** 7. type ("ci", "w", "t") |
| 169 | ** 8. list of symbolic tags. |
| 170 | ** 9. tagid for ticket or wiki |
| 171 | ** 10. Short comment to user for repeated tickets and wiki |
| 172 | */ |
| 173 | void www_print_timeline( |
| 174 | Stmt *pQuery, /* Query to implement the timeline */ |
| 175 | int tmFlags, /* Flags controlling display behavior */ |
| @@ -288,10 +288,12 @@ | |
| 288 | @ <span class="timelineLeaf">Closed-Leaf:</span> |
| 289 | }else{ |
| 290 | @ <span class="timelineLeaf">Leaf:</span> |
| 291 | } |
| 292 | } |
| 293 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 294 | hyperlink_to_uuid(zUuid); |
| 295 | } |
| 296 | db_column_blob(pQuery, commentColumn, &comment); |
| 297 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| @@ -639,11 +641,11 @@ | |
| 639 | ** p=RID artifact RID and up to COUNT parents and ancestors |
| 640 | ** d=RID artifact RID and up to COUNT descendants |
| 641 | ** t=TAGID show only check-ins with the given tagid |
| 642 | ** r=TAGID show check-ins related to tagid |
| 643 | ** u=USER only if belonging to this user |
| 644 | ** y=TYPE 'ci', 'w', 't' |
| 645 | ** s=TEXT string search (comment and brief) |
| 646 | ** ng Suppress the graph if present |
| 647 | ** |
| 648 | ** p= and d= can appear individually or together. If either p= or d= |
| 649 | ** appear, then u=, y=, a=, and b= are ignored. |
| @@ -749,22 +751,22 @@ | |
| 749 | }else{ |
| 750 | blob_appendf(&desc, " of check-in [%.10s]", zUuid); |
| 751 | } |
| 752 | }else{ |
| 753 | int n; |
| 754 | const char *zEType = "event"; |
| 755 | char *zDate; |
| 756 | char *zNEntry = mprintf("%d", nEntry); |
| 757 | url_initialize(&url, "timeline"); |
| 758 | url_add_parameter(&url, "n", zNEntry); |
| 759 | if( tagid>0 ){ |
| 760 | zType = "ci"; |
| 761 | blob_appendf(&sql, |
| 762 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 763 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 764 | |
| 765 | if( zBrName ){ |
| 766 | /* The next two blob_appendf() calls add SQL that causes checkins that |
| 767 | ** are not part of the branch which are parents or childen of the branch |
| 768 | ** to be included in the report. This related check-ins are useful |
| 769 | ** in helping to visualize what has happened on a quiescent branch |
| 770 | ** that is infrequently merged with a much more activate branch. |
| @@ -781,10 +783,11 @@ | |
| 781 | } |
| 782 | blob_appendf(&sql, ")"); |
| 783 | } |
| 784 | if( (zType[0]=='w' && !g.okRdWiki) |
| 785 | || (zType[0]=='t' && !g.okRdTkt) |
| 786 | || (zType[0]=='c' && !g.okRead) |
| 787 | ){ |
| 788 | zType = "all"; |
| 789 | } |
| 790 | if( zType[0]=='a' ){ |
| @@ -794,11 +797,11 @@ | |
| 794 | if( g.okRead ){ |
| 795 | blob_appendf(&sql, "%c'ci'", cSep); |
| 796 | cSep = ','; |
| 797 | } |
| 798 | if( g.okRdWiki ){ |
| 799 | blob_appendf(&sql, "%c'w'", cSep); |
| 800 | cSep = ','; |
| 801 | } |
| 802 | if( g.okRdTkt ){ |
| 803 | blob_appendf(&sql, "%c't'", cSep); |
| 804 | cSep = ','; |
| @@ -812,10 +815,12 @@ | |
| 812 | zEType = "checkin"; |
| 813 | }else if( zType[0]=='w' ){ |
| 814 | zEType = "wiki edit"; |
| 815 | }else if( zType[0]=='t' ){ |
| 816 | zEType = "ticket change"; |
| 817 | } |
| 818 | } |
| 819 | if( zUser ){ |
| 820 | blob_appendf(&sql, " AND event.user=%Q", zUser); |
| 821 | url_add_parameter(&url, "u", zUser); |
| @@ -926,16 +931,19 @@ | |
| 926 | timeline_submenu(&url, "Checkins Only", "y", "ci", 0); |
| 927 | } |
| 928 | if( zType[0]!='t' && g.okRdTkt ){ |
| 929 | timeline_submenu(&url, "Tickets Only", "y", "t", 0); |
| 930 | } |
| 931 | } |
| 932 | if( nEntry>20 ){ |
| 933 | timeline_submenu(&url, "20 Events", "n", "20", 0); |
| 934 | } |
| 935 | if( nEntry<200 ){ |
| 936 | timeline_submenu(&url, "200 Events", "n", "200", 0); |
| 937 | } |
| 938 | } |
| 939 | } |
| 940 | blob_zero(&sql); |
| 941 | db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/"); |
| 942 |
| --- src/timeline.c | |
| +++ src/timeline.c | |
| @@ -165,11 +165,11 @@ | |
| 165 | ** 4. User |
| 166 | ** 5. True if is a leaf |
| 167 | ** 6. background color |
| 168 | ** 7. type ("ci", "w", "t") |
| 169 | ** 8. list of symbolic tags. |
| 170 | ** 9. tagid for ticket or wiki or event |
| 171 | ** 10. Short comment to user for repeated tickets and wiki |
| 172 | */ |
| 173 | void www_print_timeline( |
| 174 | Stmt *pQuery, /* Query to implement the timeline */ |
| 175 | int tmFlags, /* Flags controlling display behavior */ |
| @@ -288,10 +288,12 @@ | |
| 288 | @ <span class="timelineLeaf">Closed-Leaf:</span> |
| 289 | }else{ |
| 290 | @ <span class="timelineLeaf">Leaf:</span> |
| 291 | } |
| 292 | } |
| 293 | }else if( zType[0]=='e' && tagid ){ |
| 294 | hyperlink_to_event_tagid(tagid); |
| 295 | }else if( (tmFlags & TIMELINE_ARTID)!=0 ){ |
| 296 | hyperlink_to_uuid(zUuid); |
| 297 | } |
| 298 | db_column_blob(pQuery, commentColumn, &comment); |
| 299 | if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){ |
| @@ -639,11 +641,11 @@ | |
| 641 | ** p=RID artifact RID and up to COUNT parents and ancestors |
| 642 | ** d=RID artifact RID and up to COUNT descendants |
| 643 | ** t=TAGID show only check-ins with the given tagid |
| 644 | ** r=TAGID show check-ins related to tagid |
| 645 | ** u=USER only if belonging to this user |
| 646 | ** y=TYPE 'ci', 'w', 't', 'e' |
| 647 | ** s=TEXT string search (comment and brief) |
| 648 | ** ng Suppress the graph if present |
| 649 | ** |
| 650 | ** p= and d= can appear individually or together. If either p= or d= |
| 651 | ** appear, then u=, y=, a=, and b= are ignored. |
| @@ -749,22 +751,22 @@ | |
| 751 | }else{ |
| 752 | blob_appendf(&desc, " of check-in [%.10s]", zUuid); |
| 753 | } |
| 754 | }else{ |
| 755 | int n; |
| 756 | const char *zEType = "timeline item"; |
| 757 | char *zDate; |
| 758 | char *zNEntry = mprintf("%d", nEntry); |
| 759 | url_initialize(&url, "timeline"); |
| 760 | url_add_parameter(&url, "n", zNEntry); |
| 761 | if( tagid>0 ){ |
| 762 | if( zType[0]!='e' ) zType = "ci"; |
| 763 | blob_appendf(&sql, |
| 764 | "AND (EXISTS(SELECT 1 FROM tagxref" |
| 765 | " WHERE tagid=%d AND tagtype>0 AND rid=blob.rid)", tagid); |
| 766 | |
| 767 | if( zBrName && zType[0]=='c' ){ |
| 768 | /* The next two blob_appendf() calls add SQL that causes checkins that |
| 769 | ** are not part of the branch which are parents or childen of the branch |
| 770 | ** to be included in the report. This related check-ins are useful |
| 771 | ** in helping to visualize what has happened on a quiescent branch |
| 772 | ** that is infrequently merged with a much more activate branch. |
| @@ -781,10 +783,11 @@ | |
| 783 | } |
| 784 | blob_appendf(&sql, ")"); |
| 785 | } |
| 786 | if( (zType[0]=='w' && !g.okRdWiki) |
| 787 | || (zType[0]=='t' && !g.okRdTkt) |
| 788 | || (zType[0]=='e' && !g.okRdWiki) |
| 789 | || (zType[0]=='c' && !g.okRead) |
| 790 | ){ |
| 791 | zType = "all"; |
| 792 | } |
| 793 | if( zType[0]=='a' ){ |
| @@ -794,11 +797,11 @@ | |
| 797 | if( g.okRead ){ |
| 798 | blob_appendf(&sql, "%c'ci'", cSep); |
| 799 | cSep = ','; |
| 800 | } |
| 801 | if( g.okRdWiki ){ |
| 802 | blob_appendf(&sql, "%c'w','e'", cSep); |
| 803 | cSep = ','; |
| 804 | } |
| 805 | if( g.okRdTkt ){ |
| 806 | blob_appendf(&sql, "%c't'", cSep); |
| 807 | cSep = ','; |
| @@ -812,10 +815,12 @@ | |
| 815 | zEType = "checkin"; |
| 816 | }else if( zType[0]=='w' ){ |
| 817 | zEType = "wiki edit"; |
| 818 | }else if( zType[0]=='t' ){ |
| 819 | zEType = "ticket change"; |
| 820 | }else if( zType[0]=='e' ){ |
| 821 | zEType = "event"; |
| 822 | } |
| 823 | } |
| 824 | if( zUser ){ |
| 825 | blob_appendf(&sql, " AND event.user=%Q", zUser); |
| 826 | url_add_parameter(&url, "u", zUser); |
| @@ -926,16 +931,19 @@ | |
| 931 | timeline_submenu(&url, "Checkins Only", "y", "ci", 0); |
| 932 | } |
| 933 | if( zType[0]!='t' && g.okRdTkt ){ |
| 934 | timeline_submenu(&url, "Tickets Only", "y", "t", 0); |
| 935 | } |
| 936 | if( zType[0]!='e' && g.okRdWiki ){ |
| 937 | timeline_submenu(&url, "Events Only", "y", "e", 0); |
| 938 | } |
| 939 | } |
| 940 | if( nEntry>20 ){ |
| 941 | timeline_submenu(&url, "20 Entries", "n", "20", 0); |
| 942 | } |
| 943 | if( nEntry<200 ){ |
| 944 | timeline_submenu(&url, "200 Entries", "n", "200", 0); |
| 945 | } |
| 946 | } |
| 947 | } |
| 948 | blob_zero(&sql); |
| 949 | db_prepare(&q, "SELECT * FROM timeline ORDER BY timestamp DESC /*scan*/"); |
| 950 |
+3
-1
| --- src/tkt.c | ||
| +++ src/tkt.c | ||
| @@ -346,21 +346,23 @@ | ||
| 346 | 346 | if( cnt==0 ){ |
| 347 | 347 | @ <hr /><h2>Attachments:</h2> |
| 348 | 348 | @ <ul> |
| 349 | 349 | } |
| 350 | 350 | cnt++; |
| 351 | + @ <li> | |
| 351 | 352 | if( g.okRead && g.okHistory ){ |
| 352 | - @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> | |
| 353 | + @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> | |
| 353 | 354 | @ %h(zFile)</a> |
| 354 | 355 | }else{ |
| 355 | 356 | @ %h(zFile) |
| 356 | 357 | } |
| 357 | 358 | @ added by %h(zUser) on |
| 358 | 359 | hyperlink_to_date(zDate, "."); |
| 359 | 360 | if( g.okWrTkt && g.okAttach ){ |
| 360 | 361 | @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] |
| 361 | 362 | } |
| 363 | + @ </li> | |
| 362 | 364 | } |
| 363 | 365 | if( cnt ){ |
| 364 | 366 | @ </ul> |
| 365 | 367 | } |
| 366 | 368 | db_finalize(&q); |
| 367 | 369 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -346,21 +346,23 @@ | |
| 346 | if( cnt==0 ){ |
| 347 | @ <hr /><h2>Attachments:</h2> |
| 348 | @ <ul> |
| 349 | } |
| 350 | cnt++; |
| 351 | if( g.okRead && g.okHistory ){ |
| 352 | @ <li><a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> |
| 353 | @ %h(zFile)</a> |
| 354 | }else{ |
| 355 | @ %h(zFile) |
| 356 | } |
| 357 | @ added by %h(zUser) on |
| 358 | hyperlink_to_date(zDate, "."); |
| 359 | if( g.okWrTkt && g.okAttach ){ |
| 360 | @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] |
| 361 | } |
| 362 | } |
| 363 | if( cnt ){ |
| 364 | @ </ul> |
| 365 | } |
| 366 | db_finalize(&q); |
| 367 |
| --- src/tkt.c | |
| +++ src/tkt.c | |
| @@ -346,21 +346,23 @@ | |
| 346 | if( cnt==0 ){ |
| 347 | @ <hr /><h2>Attachments:</h2> |
| 348 | @ <ul> |
| 349 | } |
| 350 | cnt++; |
| 351 | @ <li> |
| 352 | if( g.okRead && g.okHistory ){ |
| 353 | @ <a href="%s(g.zTop)/attachview?tkt=%s(zFullName)&file=%t(zFile)"> |
| 354 | @ %h(zFile)</a> |
| 355 | }else{ |
| 356 | @ %h(zFile) |
| 357 | } |
| 358 | @ added by %h(zUser) on |
| 359 | hyperlink_to_date(zDate, "."); |
| 360 | if( g.okWrTkt && g.okAttach ){ |
| 361 | @ [<a href="%s(g.zTop)/attachdelete?tkt=%s(zFullName)&file=%t(zFile)&from=%s(g.zTop)/tktview%%3fname=%s(zFullName)">delete</a>] |
| 362 | } |
| 363 | @ </li> |
| 364 | } |
| 365 | if( cnt ){ |
| 366 | @ </ul> |
| 367 | } |
| 368 | db_finalize(&q); |
| 369 |
+7
-3
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -106,11 +106,11 @@ | ||
| 106 | 106 | @ <p>This is a stub home-page for the project. |
| 107 | 107 | @ To fill in this page, first go to |
| 108 | 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | 109 | @ and establish a "Project Name". Then create a |
| 110 | 110 | @ wiki page with that name. The content of that wiki page |
| 111 | - @ will be displayed in place of this message. | |
| 111 | + @ will be displayed in place of this message.</p> | |
| 112 | 112 | style_footer(); |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | /* |
| 116 | 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | ||
| 153 | 153 | @ wiki.</li> |
| 154 | 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | 155 | @ to experiment.</li> |
| 156 | 156 | if( g.okNewWiki ){ |
| 157 | 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | + if( g.okWrite ){ | |
| 159 | + @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> | |
| 160 | + } | |
| 158 | 161 | } |
| 159 | 162 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 160 | 163 | @ available on this server.</li> |
| 161 | 164 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 162 | 165 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | ||
| 223 | 226 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | 227 | const char *zDate = db_column_text(&q, 0); |
| 225 | 228 | const char *zFile = db_column_text(&q, 1); |
| 226 | 229 | const char *zUser = db_column_text(&q, 2); |
| 227 | 230 | if( cnt==0 ){ |
| 228 | - @ <hr><h2>Attachments:</h2> | |
| 231 | + @ <hr /><h2>Attachments:</h2> | |
| 229 | 232 | @ <ul> |
| 230 | 233 | } |
| 231 | 234 | cnt++; |
| 235 | + @ <li> | |
| 232 | 236 | if( g.okHistory && g.okRead ){ |
| 233 | - @ <li> | |
| 234 | 237 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 235 | 238 | @ %h(zFile)</a> |
| 236 | 239 | }else{ |
| 237 | 240 | @ <li>%h(zFile) |
| 238 | 241 | } |
| @@ -239,10 +242,11 @@ | ||
| 239 | 242 | @ added by %h(zUser) on |
| 240 | 243 | hyperlink_to_date(zDate, "."); |
| 241 | 244 | if( g.okWrWiki && g.okAttach ){ |
| 242 | 245 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 243 | 246 | } |
| 247 | + @ </li> | |
| 244 | 248 | } |
| 245 | 249 | if( cnt ){ |
| 246 | 250 | @ </ul> |
| 247 | 251 | } |
| 248 | 252 | db_finalize(&q); |
| 249 | 253 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -106,11 +106,11 @@ | |
| 106 | @ <p>This is a stub home-page for the project. |
| 107 | @ To fill in this page, first go to |
| 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | @ and establish a "Project Name". Then create a |
| 110 | @ wiki page with that name. The content of that wiki page |
| 111 | @ will be displayed in place of this message. |
| 112 | style_footer(); |
| 113 | } |
| 114 | |
| 115 | /* |
| 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | |
| 153 | @ wiki.</li> |
| 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | @ to experiment.</li> |
| 156 | if( g.okNewWiki ){ |
| 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | } |
| 159 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 160 | @ available on this server.</li> |
| 161 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 162 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | |
| 223 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | const char *zDate = db_column_text(&q, 0); |
| 225 | const char *zFile = db_column_text(&q, 1); |
| 226 | const char *zUser = db_column_text(&q, 2); |
| 227 | if( cnt==0 ){ |
| 228 | @ <hr><h2>Attachments:</h2> |
| 229 | @ <ul> |
| 230 | } |
| 231 | cnt++; |
| 232 | if( g.okHistory && g.okRead ){ |
| 233 | @ <li> |
| 234 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 235 | @ %h(zFile)</a> |
| 236 | }else{ |
| 237 | @ <li>%h(zFile) |
| 238 | } |
| @@ -239,10 +242,11 @@ | |
| 239 | @ added by %h(zUser) on |
| 240 | hyperlink_to_date(zDate, "."); |
| 241 | if( g.okWrWiki && g.okAttach ){ |
| 242 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 243 | } |
| 244 | } |
| 245 | if( cnt ){ |
| 246 | @ </ul> |
| 247 | } |
| 248 | db_finalize(&q); |
| 249 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -106,11 +106,11 @@ | |
| 106 | @ <p>This is a stub home-page for the project. |
| 107 | @ To fill in this page, first go to |
| 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | @ and establish a "Project Name". Then create a |
| 110 | @ wiki page with that name. The content of that wiki page |
| 111 | @ will be displayed in place of this message.</p> |
| 112 | style_footer(); |
| 113 | } |
| 114 | |
| 115 | /* |
| 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | |
| 153 | @ wiki.</li> |
| 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | @ to experiment.</li> |
| 156 | if( g.okNewWiki ){ |
| 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | if( g.okWrite ){ |
| 159 | @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> |
| 160 | } |
| 161 | } |
| 162 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 163 | @ available on this server.</li> |
| 164 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 165 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | |
| 226 | while( db_step(&q)==SQLITE_ROW ){ |
| 227 | const char *zDate = db_column_text(&q, 0); |
| 228 | const char *zFile = db_column_text(&q, 1); |
| 229 | const char *zUser = db_column_text(&q, 2); |
| 230 | if( cnt==0 ){ |
| 231 | @ <hr /><h2>Attachments:</h2> |
| 232 | @ <ul> |
| 233 | } |
| 234 | cnt++; |
| 235 | @ <li> |
| 236 | if( g.okHistory && g.okRead ){ |
| 237 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 238 | @ %h(zFile)</a> |
| 239 | }else{ |
| 240 | @ <li>%h(zFile) |
| 241 | } |
| @@ -239,10 +242,11 @@ | |
| 242 | @ added by %h(zUser) on |
| 243 | hyperlink_to_date(zDate, "."); |
| 244 | if( g.okWrWiki && g.okAttach ){ |
| 245 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 246 | } |
| 247 | @ </li> |
| 248 | } |
| 249 | if( cnt ){ |
| 250 | @ </ul> |
| 251 | } |
| 252 | db_finalize(&q); |
| 253 |
+7
-3
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -106,11 +106,11 @@ | ||
| 106 | 106 | @ <p>This is a stub home-page for the project. |
| 107 | 107 | @ To fill in this page, first go to |
| 108 | 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | 109 | @ and establish a "Project Name". Then create a |
| 110 | 110 | @ wiki page with that name. The content of that wiki page |
| 111 | - @ will be displayed in place of this message. | |
| 111 | + @ will be displayed in place of this message.</p> | |
| 112 | 112 | style_footer(); |
| 113 | 113 | } |
| 114 | 114 | |
| 115 | 115 | /* |
| 116 | 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | ||
| 153 | 153 | @ wiki.</li> |
| 154 | 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | 155 | @ to experiment.</li> |
| 156 | 156 | if( g.okNewWiki ){ |
| 157 | 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | + if( g.okWrite ){ | |
| 159 | + @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> | |
| 160 | + } | |
| 158 | 161 | } |
| 159 | 162 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 160 | 163 | @ available on this server.</li> |
| 161 | 164 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 162 | 165 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | ||
| 223 | 226 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | 227 | const char *zDate = db_column_text(&q, 0); |
| 225 | 228 | const char *zFile = db_column_text(&q, 1); |
| 226 | 229 | const char *zUser = db_column_text(&q, 2); |
| 227 | 230 | if( cnt==0 ){ |
| 228 | - @ <hr><h2>Attachments:</h2> | |
| 231 | + @ <hr /><h2>Attachments:</h2> | |
| 229 | 232 | @ <ul> |
| 230 | 233 | } |
| 231 | 234 | cnt++; |
| 235 | + @ <li> | |
| 232 | 236 | if( g.okHistory && g.okRead ){ |
| 233 | - @ <li> | |
| 234 | 237 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 235 | 238 | @ %h(zFile)</a> |
| 236 | 239 | }else{ |
| 237 | 240 | @ <li>%h(zFile) |
| 238 | 241 | } |
| @@ -239,10 +242,11 @@ | ||
| 239 | 242 | @ added by %h(zUser) on |
| 240 | 243 | hyperlink_to_date(zDate, "."); |
| 241 | 244 | if( g.okWrWiki && g.okAttach ){ |
| 242 | 245 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 243 | 246 | } |
| 247 | + @ </li> | |
| 244 | 248 | } |
| 245 | 249 | if( cnt ){ |
| 246 | 250 | @ </ul> |
| 247 | 251 | } |
| 248 | 252 | db_finalize(&q); |
| 249 | 253 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -106,11 +106,11 @@ | |
| 106 | @ <p>This is a stub home-page for the project. |
| 107 | @ To fill in this page, first go to |
| 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | @ and establish a "Project Name". Then create a |
| 110 | @ wiki page with that name. The content of that wiki page |
| 111 | @ will be displayed in place of this message. |
| 112 | style_footer(); |
| 113 | } |
| 114 | |
| 115 | /* |
| 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | |
| 153 | @ wiki.</li> |
| 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | @ to experiment.</li> |
| 156 | if( g.okNewWiki ){ |
| 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | } |
| 159 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 160 | @ available on this server.</li> |
| 161 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 162 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | |
| 223 | while( db_step(&q)==SQLITE_ROW ){ |
| 224 | const char *zDate = db_column_text(&q, 0); |
| 225 | const char *zFile = db_column_text(&q, 1); |
| 226 | const char *zUser = db_column_text(&q, 2); |
| 227 | if( cnt==0 ){ |
| 228 | @ <hr><h2>Attachments:</h2> |
| 229 | @ <ul> |
| 230 | } |
| 231 | cnt++; |
| 232 | if( g.okHistory && g.okRead ){ |
| 233 | @ <li> |
| 234 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 235 | @ %h(zFile)</a> |
| 236 | }else{ |
| 237 | @ <li>%h(zFile) |
| 238 | } |
| @@ -239,10 +242,11 @@ | |
| 239 | @ added by %h(zUser) on |
| 240 | hyperlink_to_date(zDate, "."); |
| 241 | if( g.okWrWiki && g.okAttach ){ |
| 242 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 243 | } |
| 244 | } |
| 245 | if( cnt ){ |
| 246 | @ </ul> |
| 247 | } |
| 248 | db_finalize(&q); |
| 249 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -106,11 +106,11 @@ | |
| 106 | @ <p>This is a stub home-page for the project. |
| 107 | @ To fill in this page, first go to |
| 108 | @ <a href="%s(g.zBaseURL)/setup_config">setup/config</a> |
| 109 | @ and establish a "Project Name". Then create a |
| 110 | @ wiki page with that name. The content of that wiki page |
| 111 | @ will be displayed in place of this message.</p> |
| 112 | style_footer(); |
| 113 | } |
| 114 | |
| 115 | /* |
| 116 | ** Return true if the given pagename is the name of the sandbox |
| @@ -153,10 +153,13 @@ | |
| 153 | @ wiki.</li> |
| 154 | @ <li> Use the <a href="%s(g.zBaseURL)/wiki?name=Sandbox">Sandbox</a> |
| 155 | @ to experiment.</li> |
| 156 | if( g.okNewWiki ){ |
| 157 | @ <li> Create a <a href="%s(g.zBaseURL)/wikinew">new wiki page</a>.</li> |
| 158 | if( g.okWrite ){ |
| 159 | @ <li> Create a <a href="%s(g.zTop)/eventedit">new event</a>.</li> |
| 160 | } |
| 161 | } |
| 162 | @ <li> <a href="%s(g.zBaseURL)/wcontent">List of All Wiki Pages</a> |
| 163 | @ available on this server.</li> |
| 164 | @ <li> <form method="get" action="%s(g.zBaseURL)/wfind"><div> |
| 165 | @ Search wiki titles: <input type="text" name="title"/> |
| @@ -223,16 +226,16 @@ | |
| 226 | while( db_step(&q)==SQLITE_ROW ){ |
| 227 | const char *zDate = db_column_text(&q, 0); |
| 228 | const char *zFile = db_column_text(&q, 1); |
| 229 | const char *zUser = db_column_text(&q, 2); |
| 230 | if( cnt==0 ){ |
| 231 | @ <hr /><h2>Attachments:</h2> |
| 232 | @ <ul> |
| 233 | } |
| 234 | cnt++; |
| 235 | @ <li> |
| 236 | if( g.okHistory && g.okRead ){ |
| 237 | @ <a href="%s(g.zTop)/attachview?page=%s(zPageName)&file=%t(zFile)"> |
| 238 | @ %h(zFile)</a> |
| 239 | }else{ |
| 240 | @ <li>%h(zFile) |
| 241 | } |
| @@ -239,10 +242,11 @@ | |
| 242 | @ added by %h(zUser) on |
| 243 | hyperlink_to_date(zDate, "."); |
| 244 | if( g.okWrWiki && g.okAttach ){ |
| 245 | @ [<a href="%s(g.zTop)/attachdelete?page=%s(zPageName)&file=%t(zFile)&from=%s(g.zTop)/wiki%%3fname=%s(zPageName)">delete</a>] |
| 246 | } |
| 247 | @ </li> |
| 248 | } |
| 249 | if( cnt ){ |
| 250 | @ </ul> |
| 251 | } |
| 252 | db_finalize(&q); |
| 253 |
+1
-1
| --- win/Makefile.PellesCGMake | ||
| +++ win/Makefile.PellesCGMake | ||
| @@ -60,11 +60,11 @@ | ||
| 60 | 60 | INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) |
| 61 | 61 | |
| 62 | 62 | UTILS=translate.exe mkindex.exe makeheaders.exe |
| 63 | 63 | UTILS_OBJ=$(UTILS:.exe=.obj) |
| 64 | 64 | |
| 65 | -SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c | |
| 65 | +SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c event.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c | |
| 66 | 66 | ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf)) |
| 67 | 67 | TRANSLATEDSRC=$(SRC:.c=_.c) |
| 68 | 68 | TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj) |
| 69 | 69 | |
| 70 | 70 | SQLITESRC=sqlite3.c |
| 71 | 71 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -60,11 +60,11 @@ | |
| 60 | INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) |
| 61 | |
| 62 | UTILS=translate.exe mkindex.exe makeheaders.exe |
| 63 | UTILS_OBJ=$(UTILS:.exe=.obj) |
| 64 | |
| 65 | SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c |
| 66 | ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf)) |
| 67 | TRANSLATEDSRC=$(SRC:.c=_.c) |
| 68 | TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj) |
| 69 | |
| 70 | SQLITESRC=sqlite3.c |
| 71 |
| --- win/Makefile.PellesCGMake | |
| +++ win/Makefile.PellesCGMake | |
| @@ -60,11 +60,11 @@ | |
| 60 | INCLUDE=/I $(PellesCDir)\Include\Win /I $(PellesCDir)\Include /I $(ZLIBSRCDIR) /I $(SRCDIR) |
| 61 | |
| 62 | UTILS=translate.exe mkindex.exe makeheaders.exe |
| 63 | UTILS_OBJ=$(UTILS:.exe=.obj) |
| 64 | |
| 65 | SRC=add.c allrepo.c attach.c bag.c blob.c branch.c browse.c captcha.c cgi.c checkin.c checkout.c clearsign.c clone.c comformat.c configure.c content.c db.c delta.c deltacmd.c descendants.c diff.c diffcmd.c doc.c encode.c event.c file.c finfo.c graph.c http.c http_socket.c http_ssl.c http_transport.c info.c login.c main.c manifest.c md5.c merge.c merge3.c name.c pivot.c popen.c pqueue.c printf.c rebuild.c report.c rss.c schema.c search.c setup.c sha1.c shun.c skins.c stat.c style.c sync.c tag.c th_main.c timeline.c tkt.c tktsetup.c undo.c update.c url.c user.c verify.c vfile.c wiki.c wikiformat.c winhttp.c xfer.c zip.c |
| 66 | ORIGSRC=$(foreach sf,$(SRC),$(SRCDIR)$(sf)) |
| 67 | TRANSLATEDSRC=$(SRC:.c=_.c) |
| 68 | TRANSLATEDOBJ=$(TRANSLATEDSRC:.c=.obj) |
| 69 | |
| 70 | SQLITESRC=sqlite3.c |
| 71 |
+1
| --- www/branching.wiki | ||
| +++ www/branching.wiki | ||
| @@ -155,10 +155,11 @@ | ||
| 155 | 155 | accident that stems from concurrent development. In figure 4, giving |
| 156 | 156 | check-in 2 multiple children is a deliberate act. So, to a good |
| 157 | 157 | approximation, we define forking to be by accident and branching to |
| 158 | 158 | be by intent. Apart from that, they are the same. |
| 159 | 159 | |
| 160 | +<a name="tags"></a> | |
| 160 | 161 | <h2>Tags And Properties</h2> |
| 161 | 162 | |
| 162 | 163 | Tags and properties are used in fossil to help express the intent, and |
| 163 | 164 | thus to distinguish between forks and branches. Figure 5 shows the |
| 164 | 165 | same scenario as figure 4 but with tags and properties added: |
| 165 | 166 | |
| 166 | 167 | ADDED www/event.wiki |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -155,10 +155,11 @@ | |
| 155 | accident that stems from concurrent development. In figure 4, giving |
| 156 | check-in 2 multiple children is a deliberate act. So, to a good |
| 157 | approximation, we define forking to be by accident and branching to |
| 158 | be by intent. Apart from that, they are the same. |
| 159 | |
| 160 | <h2>Tags And Properties</h2> |
| 161 | |
| 162 | Tags and properties are used in fossil to help express the intent, and |
| 163 | thus to distinguish between forks and branches. Figure 5 shows the |
| 164 | same scenario as figure 4 but with tags and properties added: |
| 165 | |
| 166 | DDED www/event.wiki |
| --- www/branching.wiki | |
| +++ www/branching.wiki | |
| @@ -155,10 +155,11 @@ | |
| 155 | accident that stems from concurrent development. In figure 4, giving |
| 156 | check-in 2 multiple children is a deliberate act. So, to a good |
| 157 | approximation, we define forking to be by accident and branching to |
| 158 | be by intent. Apart from that, they are the same. |
| 159 | |
| 160 | <a name="tags"></a> |
| 161 | <h2>Tags And Properties</h2> |
| 162 | |
| 163 | Tags and properties are used in fossil to help express the intent, and |
| 164 | thus to distinguish between forks and branches. Figure 5 shows the |
| 165 | same scenario as figure 4 but with tags and properties added: |
| 166 | |
| 167 | DDED www/event.wiki |
+35
| --- a/www/event.wiki | ||
| +++ b/www/event.wiki | ||
| @@ -0,0 +1,35 @@ | ||
| 1 | +<title>Eventes</title> | |
| 2 | + | |
| 3 | +<h2>What Is A "Event"?</h2>e?y=<titl | |
| 4 | +Possible uses for technotes include: | |
| 5 | + | |
| 6 | + * <b>Milestones</b>. Project milestones, such as releases or beta-test | |
| 7 | + cycles, can be recorded as technotes. The timeline entry for the technote | |
| 8 | + can be something simple like "Version 1.2.3" perhaps with a bright | |
| 9 | + color background to draw attention to the entry and the wiki content | |
| 10 | + can contain release notes, for example. | |
| 11 | + | |
| 12 | + * <b>Blog Entries</b>. Blog entries from developers describing the current | |
| 13 | + state of a project, or rational for v arious design decisions, or | |
| 14 | + roadmaps for future development, can be entered as technotes. | |
| 15 | + | |
| 16 | + * <b>Process Checkpoints</b>. For projects that have a formal process, | |
| 17 | + technotes can be used to record the completion or the initiation of | |
| 18 | + various process steps. For example, a technote can be used to record | |
| 19 | + the successful completion of a long-running test, perhaps w[./wikitheory.wiki | wiki page] | |
| 20 | +that is associated with a point in time rather thaevent causes a si [/timelinhyperlink ofTimeline Page]entry cause a jump to the wiThe wiki content, the timeline entry text, the | |
| 21 | +time of the eventTechnical Notes</title> | |
| 22 | + | |
| 23 | +<h2>What Is A "Technote"?</h2> | |
| 24 | + | |
| 25 | +In Fossil, a "technical note" or "technoteventerly called an "event") | |
| 26 | +is a speeventiki page] | |
| 27 | +that is associated with a point in time rather than having a page name. | |
| 28 | +eventaving a page name. | |
| 29 | +Each technote causes a single entry to appear on the | |
| 30 | +[/timeline?y=<titl | |
| 31 | +Possible uses for technotes include: | |
| 32 | + | |
| 33 | + * <b>Milestones</b>. Project milestones, such as releases or beta-test | |
| 34 | + cycles, can be recorded as technotes. The timeline entry for the technote | |
| 35 | + can be something simple like "V |
| --- a/www/event.wiki | |
| +++ b/www/event.wiki | |
| @@ -0,0 +1,35 @@ | |
| --- a/www/event.wiki | |
| +++ b/www/event.wiki | |
| @@ -0,0 +1,35 @@ | |
| 1 | <title>Eventes</title> |
| 2 | |
| 3 | <h2>What Is A "Event"?</h2>e?y=<titl |
| 4 | Possible uses for technotes include: |
| 5 | |
| 6 | * <b>Milestones</b>. Project milestones, such as releases or beta-test |
| 7 | cycles, can be recorded as technotes. The timeline entry for the technote |
| 8 | can be something simple like "Version 1.2.3" perhaps with a bright |
| 9 | color background to draw attention to the entry and the wiki content |
| 10 | can contain release notes, for example. |
| 11 | |
| 12 | * <b>Blog Entries</b>. Blog entries from developers describing the current |
| 13 | state of a project, or rational for v arious design decisions, or |
| 14 | roadmaps for future development, can be entered as technotes. |
| 15 | |
| 16 | * <b>Process Checkpoints</b>. For projects that have a formal process, |
| 17 | technotes can be used to record the completion or the initiation of |
| 18 | various process steps. For example, a technote can be used to record |
| 19 | the successful completion of a long-running test, perhaps w[./wikitheory.wiki | wiki page] |
| 20 | that is associated with a point in time rather thaevent causes a si [/timelinhyperlink ofTimeline Page]entry cause a jump to the wiThe wiki content, the timeline entry text, the |
| 21 | time of the eventTechnical Notes</title> |
| 22 | |
| 23 | <h2>What Is A "Technote"?</h2> |
| 24 | |
| 25 | In Fossil, a "technical note" or "technoteventerly called an "event") |
| 26 | is a speeventiki page] |
| 27 | that is associated with a point in time rather than having a page name. |
| 28 | eventaving a page name. |
| 29 | Each technote causes a single entry to appear on the |
| 30 | [/timeline?y=<titl |
| 31 | Possible uses for technotes include: |
| 32 | |
| 33 | * <b>Milestones</b>. Project milestones, such as releases or beta-test |
| 34 | cycles, can be recorded as technotes. The timeline entry for the technote |
| 35 | can be something simple like "V |
+106
-13
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -43,13 +43,14 @@ | ||
| 43 | 43 | <li> [#cluster | Clusters] </li> |
| 44 | 44 | <li> [#ctrl | Control Artifacts] </li> |
| 45 | 45 | <li> [#wikichng | Wiki Pages] </li> |
| 46 | 46 | <li> [#tktchng | Ticket Changes] </li> |
| 47 | 47 | <li> [#attachment | Attachments] </li> |
| 48 | +<li> [#event | Events] </li> | |
| 48 | 49 | </ul> |
| 49 | 50 | |
| 50 | -These five artifact types are described in the sequel. | |
| 51 | +These seven artifact types are described in the sequel. | |
| 51 | 52 | |
| 52 | 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 53 | 54 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 54 | 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 55 | 56 | is an implementation detail and might change in a future release. For |
| @@ -56,10 +57,13 @@ | ||
| 56 | 57 | the purpose of this article "file format" means the format of the artifacts, |
| 57 | 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 58 | 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| 59 | 60 | disk, though stable, is not intended to live as long as the |
| 60 | 61 | artifact format. |
| 62 | + | |
| 63 | +All of the artifacts can be extracted from a Fossil repository using | |
| 64 | +the "fossil deconstruct" command. | |
| 61 | 65 | |
| 62 | 66 | <a name="manifest"></a> |
| 63 | 67 | <h2>1.0 The Manifest</h2> |
| 64 | 68 | |
| 65 | 69 | A manifest defines a check-in or version of the project |
| @@ -165,12 +169,13 @@ | ||
| 165 | 169 | repository, append a single space (ASCII 0x20), the |
| 166 | 170 | size of the file in ASCII decimal, a single newline |
| 167 | 171 | character (ASCII 0x0A), and the complete text of the file. |
| 168 | 172 | Compute the MD5 checksum of the result. |
| 169 | 173 | |
| 170 | -A manifest might contain one or more T-cards used to set tags or | |
| 171 | -properties on the check-in. The format of the T-card is the same as | |
| 174 | +A manifest might contain one or more T-cards used to set | |
| 175 | +[./branching.wiki#tags | tags or properties] | |
| 176 | +on the check-in. The format of the T-card is the same as | |
| 172 | 177 | described in <i>Control Artifacts</i> section below, except that the |
| 173 | 178 | second argument is the single characcter "<b>*</b>" instead of an |
| 174 | 179 | artifact ID. The <b>*</b> in place of the artifact ID indicates that |
| 175 | 180 | the tag or property applies to the current artifact. It is not |
| 176 | 181 | possible to encode the current artifact ID as part of an artifact, |
| @@ -182,11 +187,11 @@ | ||
| 182 | 187 | Each manifest has a single U-card. The argument to the U-card is |
| 183 | 188 | the login of the user who created the manifest. The login name |
| 184 | 189 | is encoded using the same character escapes as is used for the |
| 185 | 190 | check-in comment argument to the C-card. |
| 186 | 191 | |
| 187 | -A manifest has an option Z-card as its last line. The argument | |
| 192 | +A manifest has an optional Z-card as its last line. The argument | |
| 188 | 193 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 189 | 194 | of all prior lines of the manifest up to and including the newline |
| 190 | 195 | character that immediately precedes the "Z". The Z-card is just |
| 191 | 196 | a sanity check to prove that the manifest is well-formed and |
| 192 | 197 | consistent. |
| @@ -262,11 +267,12 @@ | ||
| 262 | 267 | clearsigned. |
| 263 | 268 | |
| 264 | 269 | The D card and the Z card of a control artifact are the same |
| 265 | 270 | as in a manifest. |
| 266 | 271 | |
| 267 | -The T card represents a "tag" or property that is applied to | |
| 272 | +The T card represents a [./branching.wiki#tags | tag or property] | |
| 273 | +that is applied to | |
| 268 | 274 | some other artifact. The T card has two or three values. The |
| 269 | 275 | second argument is the 40 character lowercase artifact ID of the artifact |
| 270 | 276 | to which the tag is to be applied. The |
| 271 | 277 | first value is the tag name. The first character of the tag |
| 272 | 278 | is either "+", "-", or "*". A "+" means the tag should be added |
| @@ -324,11 +330,11 @@ | ||
| 324 | 330 | of text in the wiki page. That text follows the newline character |
| 325 | 331 | that terminates the W card. The wiki text is always followed by one |
| 326 | 332 | extra newline. |
| 327 | 333 | |
| 328 | 334 | An example wiki artifact can be seen |
| 329 | -[/artifact/7b2f5fd0e0 | here]. | |
| 335 | +[/artifact?name=7b2f5fd0e0&txt=1 | here]. | |
| 330 | 336 | |
| 331 | 337 | <a name="tktchng"></a> |
| 332 | 338 | <h2>5.0 Ticket Changes</h2> |
| 333 | 339 | |
| 334 | 340 | A ticket-change artifact represents a change to a trouble ticket. |
| @@ -375,25 +381,25 @@ | ||
| 375 | 381 | |
| 376 | 382 | <a name="attachment"></a> |
| 377 | 383 | <h2>6.0 Attachments</h2> |
| 378 | 384 | |
| 379 | 385 | An attachment artifact associates some other artifact that is the |
| 380 | -attachment (the source artifact) with a ticket or wiki page to which | |
| 386 | +attachment (the source artifact) with a ticket or wiki page or event to which | |
| 381 | 387 | the attachment is connected (the target artifact). |
| 382 | 388 | The following cards are allowed on an attachment artifact: |
| 383 | 389 | |
| 384 | 390 | <blockquote> |
| 385 | -<b>A</b> <i>filename target</i> ?<i>source</i>? | |
| 386 | -<b>C</b> <i>comment</i><br> | |
| 391 | +<b>A</b> <i>filename target</i> ?<i>source</i>?<br /> | |
| 392 | +<b>C</b> <i>comment</i><br /> | |
| 387 | 393 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 388 | 394 | <b>U</b> <i>user-name</i><br /> |
| 389 | 395 | <b>Z</b> <i>checksum</i> |
| 390 | 396 | </blockquote> |
| 391 | 397 | |
| 392 | 398 | The A card specifies a filename for the attachment in its first argument. |
| 393 | 399 | The second argument to the A card is the name |
| 394 | -of the wiki page or ticket to which the attachment is connected. The | |
| 400 | +of the wiki page or ticket or event to which the attachment is connected. The | |
| 395 | 401 | third argument is either missing or else it is the 40-character artifact |
| 396 | 402 | ID of the attachment itself. A missing third argument means that the |
| 397 | 403 | attachment should be deleted. |
| 398 | 404 | |
| 399 | 405 | The C card is an optional comment describing what the attachment is about. |
| @@ -405,46 +411,111 @@ | ||
| 405 | 411 | A single U card gives the name of the user to added the attachment. |
| 406 | 412 | If an attachment is added anonymously, then the U card may be omitted. |
| 407 | 413 | |
| 408 | 414 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 409 | 415 | |
| 416 | + | |
| 417 | +<a name="event"></a> | |
| 418 | +<h2>7.0 Events</h2> | |
| 419 | + | |
| 420 | +An event artifact associates a timeline comment and a page of text | |
| 421 | +(similar to a wiki page) with a point in time. Events can be used | |
| 422 | +to record project milestones, release notes, blog entries, process | |
| 423 | +checkpoints, or news articles. | |
| 424 | +The following cards are allowed on an event artifact: | |
| 425 | + | |
| 426 | +<blockquote> | |
| 427 | +<b>C</b> <i>comment</i><br> | |
| 428 | +<b>D</b> <i>time-and-date-stamp</i><br /> | |
| 429 | +<b>E</b> <i>event-time</i> <i>event-id</i><br /> | |
| 430 | +<b>P</b> <i>parent-artifact-id</i>+<br /> | |
| 431 | +<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br /> | |
| 432 | +<b>U</b> <i>user-name</i><br /> | |
| 433 | +<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> | |
| 434 | +<b>Z</b> <i>checksum</i> | |
| 435 | +</blockquote> | |
| 436 | + | |
| 437 | +The C card contains text that is displayed on the timeline for the | |
| 438 | +event. Exactly one C card is required on an event artifact. | |
| 439 | + | |
| 440 | +A single D card is required to give the date and time when the | |
| 441 | +event artifact was created. This is different from the time at which | |
| 442 | +the event occurs. | |
| 443 | + | |
| 444 | +A single E card gives the time of the event (the point on the timeline | |
| 445 | +where the event is displayed) and a unique identifier for the event. | |
| 446 | +When there are multiple artifacts with the same event-id, the one with | |
| 447 | +the most recent D card is the only one used. The event-id must be a | |
| 448 | +40-character lower-case hexadecimal string. | |
| 449 | + | |
| 450 | +The option P card specifies a prior event with the same event-id from | |
| 451 | +which the current event is an edit. The P card is a hint to the system | |
| 452 | +that it might be space efficient to store one event as a delta of the | |
| 453 | +other. | |
| 454 | + | |
| 455 | +An event might contain one or more T-cards used to set | |
| 456 | +[./branching.wiki#tags | tags or properties] | |
| 457 | +on the event. The format of the T-card is the same as | |
| 458 | +described in [#ctrl | Control Artifacts] section above, except that the | |
| 459 | +second argument is the single characcter "<b>*</b>" instead of an | |
| 460 | +artifact ID and the name is always prefaced by "<b>+</b>". | |
| 461 | +The <b>*</b> in place of the artifact ID indicates that | |
| 462 | +the tag or property applies to the current artifact. It is not | |
| 463 | +possible to encode the current artifact ID as part of an artifact, | |
| 464 | +since the act of inserting the artifact ID would change the artifact ID, | |
| 465 | +hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the | |
| 466 | +name means that tags can only be add and they can only be non-propagating | |
| 467 | +tags. A an event, T cards are normally used to set the background | |
| 468 | +display color for timelines. | |
| 469 | + | |
| 470 | +The optional U card gives name of the user who entered the event. | |
| 471 | + | |
| 472 | +A single W card provides wiki text for the document associated with the | |
| 473 | +event. The format of the W card is exactly the same as for a | |
| 474 | +[#wikichng | wiki artifact]. | |
| 475 | + | |
| 476 | +The Z card is the usual checksum over the rest of the attachment artifact. | |
| 477 | + | |
| 410 | 478 | |
| 411 | 479 | <a name="summary"></a> |
| 412 | -<h2>7.0 Card Summary</h2> | |
| 480 | +<h2>8.0 Card Summary</h2> | |
| 413 | 481 | |
| 414 | 482 | The following table summaries the various kinds of cards that |
| 415 | 483 | appear on Fossil artifacts: |
| 416 | 484 | |
| 417 | 485 | <table border=1 width="100%"> |
| 418 | 486 | <tr> |
| 419 | 487 | <th rowspan=2 valign=bottom>Card Format</th> |
| 420 | -<th colspan=6>Used By</th> | |
| 488 | +<th colspan=7>Used By</th> | |
| 421 | 489 | </tr> |
| 422 | 490 | <tr> |
| 423 | 491 | <th>Manifest</th> |
| 424 | 492 | <th>Cluster</th> |
| 425 | 493 | <th>Control</th> |
| 426 | 494 | <th>Wiki</th> |
| 427 | 495 | <th>Ticket</th> |
| 428 | 496 | <th>Attachment</th> |
| 497 | +<th>Event</th> | |
| 429 | 498 | </tr> |
| 430 | 499 | <tr> |
| 431 | 500 | <td><b>A</b> <i>filename target source</i></td> |
| 432 | 501 | <td> </td> |
| 433 | 502 | <td> </td> |
| 434 | 503 | <td> </td> |
| 435 | 504 | <td> </td> |
| 436 | 505 | <td> </td> |
| 437 | 506 | <td align=center><b>X</b></td> |
| 507 | +<td> </td> | |
| 438 | 508 | </tr> |
| 439 | 509 | <tr> |
| 440 | -<td><b>C</b> <i>coment-text</i></td> | |
| 510 | +<td><b>C</b> <i>comment-text</i></td> | |
| 441 | 511 | <td align=center><b>X</b></td> |
| 442 | 512 | <td> </td> |
| 443 | 513 | <td> </td> |
| 444 | 514 | <td> </td> |
| 445 | 515 | <td> </td> |
| 516 | +<td align=center><b>X</b></td> | |
| 446 | 517 | <td align=center><b>X</b></td> |
| 447 | 518 | </tr> |
| 448 | 519 | <tr> |
| 449 | 520 | <td><b>D</b> <i>date-time-stamp</i></td> |
| 450 | 521 | <td align=center><b>X</b></td> |
| @@ -451,14 +522,26 @@ | ||
| 451 | 522 | <td align=center> </td> |
| 452 | 523 | <td align=center><b>X</b></td> |
| 453 | 524 | <td align=center><b>X</b></td> |
| 454 | 525 | <td align=center><b>X</b></td> |
| 455 | 526 | <td align=center><b>X</b></td> |
| 527 | +<td align=center><b>X</b></td> | |
| 528 | +</tr> | |
| 529 | +<tr> | |
| 530 | +<td><b>E</b> <i>event-time event-id</i></td> | |
| 531 | +<td align=center> </td> | |
| 532 | +<td align=center> </td> | |
| 533 | +<td align=center> </td> | |
| 534 | +<td align=center> </td> | |
| 535 | +<td align=center> </td> | |
| 536 | +<td align=center> </td> | |
| 537 | +<td align=center><b>X</b></td> | |
| 456 | 538 | </tr> |
| 457 | 539 | <tr> |
| 458 | 540 | <td><b>F</b> <i>filename uuid permissions oldname</i></td> |
| 459 | 541 | <td align=center><b>X</b></td> |
| 542 | +<td align=center> </td> | |
| 460 | 543 | <td align=center> </td> |
| 461 | 544 | <td align=center> </td> |
| 462 | 545 | <td align=center> </td> |
| 463 | 546 | <td align=center> </td> |
| 464 | 547 | <td align=center> </td> |
| @@ -469,18 +552,20 @@ | ||
| 469 | 552 | <td align=center> </td> |
| 470 | 553 | <td align=center> </td> |
| 471 | 554 | <td align=center> </td> |
| 472 | 555 | <td align=center><b>X</b></td> |
| 473 | 556 | <td align=center> </td> |
| 557 | +<td align=center> </td> | |
| 474 | 558 | </tr> |
| 475 | 559 | <tr> |
| 476 | 560 | <td><b>K</b> <i>ticket-uuid</i></td> |
| 477 | 561 | <td align=center> </td> |
| 478 | 562 | <td align=center> </td> |
| 479 | 563 | <td align=center> </td> |
| 480 | 564 | <td align=center> </td> |
| 481 | 565 | <td align=center><b>X</b></td> |
| 566 | +<td align=center> </td> | |
| 482 | 567 | <td align=center> </td> |
| 483 | 568 | </tr> |
| 484 | 569 | <tr> |
| 485 | 570 | <td><b>L</b> <i>wiki-title</i></td> |
| 486 | 571 | <td align=center> </td> |
| @@ -487,15 +572,17 @@ | ||
| 487 | 572 | <td align=center> </td> |
| 488 | 573 | <td align=center> </td> |
| 489 | 574 | <td align=center><b>X</b></td> |
| 490 | 575 | <td align=center> </td> |
| 491 | 576 | <td align=center> </td> |
| 577 | +<td align=center> </td> | |
| 492 | 578 | </tr> |
| 493 | 579 | <tr> |
| 494 | 580 | <td><b>M</b> <i>uuid</i></td> |
| 495 | 581 | <td align=center> </td> |
| 496 | 582 | <td align=center><b>X</b></td> |
| 583 | +<td align=center> </td> | |
| 497 | 584 | <td align=center> </td> |
| 498 | 585 | <td align=center> </td> |
| 499 | 586 | <td align=center> </td> |
| 500 | 587 | <td align=center> </td> |
| 501 | 588 | </tr> |
| @@ -505,14 +592,16 @@ | ||
| 505 | 592 | <td align=center> </td> |
| 506 | 593 | <td align=center> </td> |
| 507 | 594 | <td align=center><b>X</b></td> |
| 508 | 595 | <td align=center> </td> |
| 509 | 596 | <td align=center> </td> |
| 597 | +<td align=center> </td> | |
| 510 | 598 | </tr> |
| 511 | 599 | <tr> |
| 512 | 600 | <td><b>R</b> <i>md5sum</i></td> |
| 513 | 601 | <td align=center><b>X</b></td> |
| 602 | +<td align=center> </td> | |
| 514 | 603 | <td align=center> </td> |
| 515 | 604 | <td align=center> </td> |
| 516 | 605 | <td align=center> </td> |
| 517 | 606 | <td align=center> </td> |
| 518 | 607 | <td align=center> </td> |
| @@ -522,15 +611,17 @@ | ||
| 522 | 611 | <td align=center> </td> |
| 523 | 612 | <td align=center><b>X</b></td> |
| 524 | 613 | <td align=center> </td> |
| 525 | 614 | <td align=center> </td> |
| 526 | 615 | <td align=center> </td> |
| 616 | +<td align=center><b>X</b></td> | |
| 527 | 617 | </tr> |
| 528 | 618 | <tr> |
| 529 | 619 | <td><b>U</b> <i>username</i></td> |
| 530 | 620 | <td align=center><b>X</b></td> |
| 531 | 621 | <td align=center> </td> |
| 622 | +<td align=center><b>X</b></td> | |
| 532 | 623 | <td align=center><b>X</b></td> |
| 533 | 624 | <td align=center><b>X</b></td> |
| 534 | 625 | <td align=center><b>X</b></td> |
| 535 | 626 | <td align=center><b>X</b></td> |
| 536 | 627 | </tr> |
| @@ -540,16 +631,18 @@ | ||
| 540 | 631 | <td align=center> </td> |
| 541 | 632 | <td align=center> </td> |
| 542 | 633 | <td align=center><b>X</b></td> |
| 543 | 634 | <td align=center> </td> |
| 544 | 635 | <td align=center> </td> |
| 636 | +<td align=center><b>X</b></td> | |
| 545 | 637 | </tr> |
| 546 | 638 | <tr> |
| 547 | 639 | <td><b>Z</b> <i>md5sum</i></td> |
| 640 | +<td align=center><b>X</b></td> | |
| 548 | 641 | <td align=center><b>X</b></td> |
| 549 | 642 | <td align=center><b>X</b></td> |
| 550 | 643 | <td align=center><b>X</b></td> |
| 551 | 644 | <td align=center><b>X</b></td> |
| 552 | 645 | <td align=center><b>X</b></td> |
| 553 | 646 | <td align=center><b>X</b></td> |
| 554 | 647 | </tr> |
| 555 | 648 | </table> |
| 556 | 649 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -43,13 +43,14 @@ | |
| 43 | <li> [#cluster | Clusters] </li> |
| 44 | <li> [#ctrl | Control Artifacts] </li> |
| 45 | <li> [#wikichng | Wiki Pages] </li> |
| 46 | <li> [#tktchng | Ticket Changes] </li> |
| 47 | <li> [#attachment | Attachments] </li> |
| 48 | </ul> |
| 49 | |
| 50 | These five artifact types are described in the sequel. |
| 51 | |
| 52 | In the current implementation (as of 2009-01-25) the artifacts that |
| 53 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 54 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 55 | is an implementation detail and might change in a future release. For |
| @@ -56,10 +57,13 @@ | |
| 56 | the purpose of this article "file format" means the format of the artifacts, |
| 57 | not how the artifacts are stored on disk. It is the artifact format that |
| 58 | is intended to be enduring. The specifics of how artifacts are stored on |
| 59 | disk, though stable, is not intended to live as long as the |
| 60 | artifact format. |
| 61 | |
| 62 | <a name="manifest"></a> |
| 63 | <h2>1.0 The Manifest</h2> |
| 64 | |
| 65 | A manifest defines a check-in or version of the project |
| @@ -165,12 +169,13 @@ | |
| 165 | repository, append a single space (ASCII 0x20), the |
| 166 | size of the file in ASCII decimal, a single newline |
| 167 | character (ASCII 0x0A), and the complete text of the file. |
| 168 | Compute the MD5 checksum of the result. |
| 169 | |
| 170 | A manifest might contain one or more T-cards used to set tags or |
| 171 | properties on the check-in. The format of the T-card is the same as |
| 172 | described in <i>Control Artifacts</i> section below, except that the |
| 173 | second argument is the single characcter "<b>*</b>" instead of an |
| 174 | artifact ID. The <b>*</b> in place of the artifact ID indicates that |
| 175 | the tag or property applies to the current artifact. It is not |
| 176 | possible to encode the current artifact ID as part of an artifact, |
| @@ -182,11 +187,11 @@ | |
| 182 | Each manifest has a single U-card. The argument to the U-card is |
| 183 | the login of the user who created the manifest. The login name |
| 184 | is encoded using the same character escapes as is used for the |
| 185 | check-in comment argument to the C-card. |
| 186 | |
| 187 | A manifest has an option Z-card as its last line. The argument |
| 188 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 189 | of all prior lines of the manifest up to and including the newline |
| 190 | character that immediately precedes the "Z". The Z-card is just |
| 191 | a sanity check to prove that the manifest is well-formed and |
| 192 | consistent. |
| @@ -262,11 +267,12 @@ | |
| 262 | clearsigned. |
| 263 | |
| 264 | The D card and the Z card of a control artifact are the same |
| 265 | as in a manifest. |
| 266 | |
| 267 | The T card represents a "tag" or property that is applied to |
| 268 | some other artifact. The T card has two or three values. The |
| 269 | second argument is the 40 character lowercase artifact ID of the artifact |
| 270 | to which the tag is to be applied. The |
| 271 | first value is the tag name. The first character of the tag |
| 272 | is either "+", "-", or "*". A "+" means the tag should be added |
| @@ -324,11 +330,11 @@ | |
| 324 | of text in the wiki page. That text follows the newline character |
| 325 | that terminates the W card. The wiki text is always followed by one |
| 326 | extra newline. |
| 327 | |
| 328 | An example wiki artifact can be seen |
| 329 | [/artifact/7b2f5fd0e0 | here]. |
| 330 | |
| 331 | <a name="tktchng"></a> |
| 332 | <h2>5.0 Ticket Changes</h2> |
| 333 | |
| 334 | A ticket-change artifact represents a change to a trouble ticket. |
| @@ -375,25 +381,25 @@ | |
| 375 | |
| 376 | <a name="attachment"></a> |
| 377 | <h2>6.0 Attachments</h2> |
| 378 | |
| 379 | An attachment artifact associates some other artifact that is the |
| 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. |
| @@ -405,46 +411,111 @@ | |
| 405 | A single U card gives the name of the user to added the attachment. |
| 406 | If an attachment is added anonymously, then the U card may be omitted. |
| 407 | |
| 408 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 409 | |
| 410 | |
| 411 | <a name="summary"></a> |
| 412 | <h2>7.0 Card Summary</h2> |
| 413 | |
| 414 | The following table summaries the various kinds of cards that |
| 415 | appear on Fossil artifacts: |
| 416 | |
| 417 | <table border=1 width="100%"> |
| 418 | <tr> |
| 419 | <th rowspan=2 valign=bottom>Card Format</th> |
| 420 | <th colspan=6>Used By</th> |
| 421 | </tr> |
| 422 | <tr> |
| 423 | <th>Manifest</th> |
| 424 | <th>Cluster</th> |
| 425 | <th>Control</th> |
| 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> </td> |
| 433 | <td> </td> |
| 434 | <td> </td> |
| 435 | <td> </td> |
| 436 | <td> </td> |
| 437 | <td align=center><b>X</b></td> |
| 438 | </tr> |
| 439 | <tr> |
| 440 | <td><b>C</b> <i>coment-text</i></td> |
| 441 | <td align=center><b>X</b></td> |
| 442 | <td> </td> |
| 443 | <td> </td> |
| 444 | <td> </td> |
| 445 | <td> </td> |
| 446 | <td align=center><b>X</b></td> |
| 447 | </tr> |
| 448 | <tr> |
| 449 | <td><b>D</b> <i>date-time-stamp</i></td> |
| 450 | <td align=center><b>X</b></td> |
| @@ -451,14 +522,26 @@ | |
| 451 | <td align=center> </td> |
| 452 | <td align=center><b>X</b></td> |
| 453 | <td align=center><b>X</b></td> |
| 454 | <td align=center><b>X</b></td> |
| 455 | <td align=center><b>X</b></td> |
| 456 | </tr> |
| 457 | <tr> |
| 458 | <td><b>F</b> <i>filename uuid permissions oldname</i></td> |
| 459 | <td align=center><b>X</b></td> |
| 460 | <td align=center> </td> |
| 461 | <td align=center> </td> |
| 462 | <td align=center> </td> |
| 463 | <td align=center> </td> |
| 464 | <td align=center> </td> |
| @@ -469,18 +552,20 @@ | |
| 469 | <td align=center> </td> |
| 470 | <td align=center> </td> |
| 471 | <td align=center> </td> |
| 472 | <td align=center><b>X</b></td> |
| 473 | <td align=center> </td> |
| 474 | </tr> |
| 475 | <tr> |
| 476 | <td><b>K</b> <i>ticket-uuid</i></td> |
| 477 | <td align=center> </td> |
| 478 | <td align=center> </td> |
| 479 | <td align=center> </td> |
| 480 | <td align=center> </td> |
| 481 | <td align=center><b>X</b></td> |
| 482 | <td align=center> </td> |
| 483 | </tr> |
| 484 | <tr> |
| 485 | <td><b>L</b> <i>wiki-title</i></td> |
| 486 | <td align=center> </td> |
| @@ -487,15 +572,17 @@ | |
| 487 | <td align=center> </td> |
| 488 | <td align=center> </td> |
| 489 | <td align=center><b>X</b></td> |
| 490 | <td align=center> </td> |
| 491 | <td align=center> </td> |
| 492 | </tr> |
| 493 | <tr> |
| 494 | <td><b>M</b> <i>uuid</i></td> |
| 495 | <td align=center> </td> |
| 496 | <td align=center><b>X</b></td> |
| 497 | <td align=center> </td> |
| 498 | <td align=center> </td> |
| 499 | <td align=center> </td> |
| 500 | <td align=center> </td> |
| 501 | </tr> |
| @@ -505,14 +592,16 @@ | |
| 505 | <td align=center> </td> |
| 506 | <td align=center> </td> |
| 507 | <td align=center><b>X</b></td> |
| 508 | <td align=center> </td> |
| 509 | <td align=center> </td> |
| 510 | </tr> |
| 511 | <tr> |
| 512 | <td><b>R</b> <i>md5sum</i></td> |
| 513 | <td align=center><b>X</b></td> |
| 514 | <td align=center> </td> |
| 515 | <td align=center> </td> |
| 516 | <td align=center> </td> |
| 517 | <td align=center> </td> |
| 518 | <td align=center> </td> |
| @@ -522,15 +611,17 @@ | |
| 522 | <td align=center> </td> |
| 523 | <td align=center><b>X</b></td> |
| 524 | <td align=center> </td> |
| 525 | <td align=center> </td> |
| 526 | <td align=center> </td> |
| 527 | </tr> |
| 528 | <tr> |
| 529 | <td><b>U</b> <i>username</i></td> |
| 530 | <td align=center><b>X</b></td> |
| 531 | <td align=center> </td> |
| 532 | <td align=center><b>X</b></td> |
| 533 | <td align=center><b>X</b></td> |
| 534 | <td align=center><b>X</b></td> |
| 535 | <td align=center><b>X</b></td> |
| 536 | </tr> |
| @@ -540,16 +631,18 @@ | |
| 540 | <td align=center> </td> |
| 541 | <td align=center> </td> |
| 542 | <td align=center><b>X</b></td> |
| 543 | <td align=center> </td> |
| 544 | <td align=center> </td> |
| 545 | </tr> |
| 546 | <tr> |
| 547 | <td><b>Z</b> <i>md5sum</i></td> |
| 548 | <td align=center><b>X</b></td> |
| 549 | <td align=center><b>X</b></td> |
| 550 | <td align=center><b>X</b></td> |
| 551 | <td align=center><b>X</b></td> |
| 552 | <td align=center><b>X</b></td> |
| 553 | <td align=center><b>X</b></td> |
| 554 | </tr> |
| 555 | </table> |
| 556 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -43,13 +43,14 @@ | |
| 43 | <li> [#cluster | Clusters] </li> |
| 44 | <li> [#ctrl | Control Artifacts] </li> |
| 45 | <li> [#wikichng | Wiki Pages] </li> |
| 46 | <li> [#tktchng | Ticket Changes] </li> |
| 47 | <li> [#attachment | Attachments] </li> |
| 48 | <li> [#event | Events] </li> |
| 49 | </ul> |
| 50 | |
| 51 | These seven artifact types are described in the sequel. |
| 52 | |
| 53 | In the current implementation (as of 2009-01-25) the artifacts that |
| 54 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 55 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 56 | is an implementation detail and might change in a future release. For |
| @@ -56,10 +57,13 @@ | |
| 57 | the purpose of this article "file format" means the format of the artifacts, |
| 58 | not how the artifacts are stored on disk. It is the artifact format that |
| 59 | is intended to be enduring. The specifics of how artifacts are stored on |
| 60 | disk, though stable, is not intended to live as long as the |
| 61 | artifact format. |
| 62 | |
| 63 | All of the artifacts can be extracted from a Fossil repository using |
| 64 | the "fossil deconstruct" command. |
| 65 | |
| 66 | <a name="manifest"></a> |
| 67 | <h2>1.0 The Manifest</h2> |
| 68 | |
| 69 | A manifest defines a check-in or version of the project |
| @@ -165,12 +169,13 @@ | |
| 169 | repository, append a single space (ASCII 0x20), the |
| 170 | size of the file in ASCII decimal, a single newline |
| 171 | character (ASCII 0x0A), and the complete text of the file. |
| 172 | Compute the MD5 checksum of the result. |
| 173 | |
| 174 | A manifest might contain one or more T-cards used to set |
| 175 | [./branching.wiki#tags | tags or properties] |
| 176 | on the check-in. The format of the T-card is the same as |
| 177 | described in <i>Control Artifacts</i> section below, except that the |
| 178 | second argument is the single characcter "<b>*</b>" instead of an |
| 179 | artifact ID. The <b>*</b> in place of the artifact ID indicates that |
| 180 | the tag or property applies to the current artifact. It is not |
| 181 | possible to encode the current artifact ID as part of an artifact, |
| @@ -182,11 +187,11 @@ | |
| 187 | Each manifest has a single U-card. The argument to the U-card is |
| 188 | the login of the user who created the manifest. The login name |
| 189 | is encoded using the same character escapes as is used for the |
| 190 | check-in comment argument to the C-card. |
| 191 | |
| 192 | A manifest has an optional Z-card as its last line. The argument |
| 193 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 194 | of all prior lines of the manifest up to and including the newline |
| 195 | character that immediately precedes the "Z". The Z-card is just |
| 196 | a sanity check to prove that the manifest is well-formed and |
| 197 | consistent. |
| @@ -262,11 +267,12 @@ | |
| 267 | clearsigned. |
| 268 | |
| 269 | The D card and the Z card of a control artifact are the same |
| 270 | as in a manifest. |
| 271 | |
| 272 | The T card represents a [./branching.wiki#tags | tag or property] |
| 273 | that is applied to |
| 274 | some other artifact. The T card has two or three values. The |
| 275 | second argument is the 40 character lowercase artifact ID of the artifact |
| 276 | to which the tag is to be applied. The |
| 277 | first value is the tag name. The first character of the tag |
| 278 | is either "+", "-", or "*". A "+" means the tag should be added |
| @@ -324,11 +330,11 @@ | |
| 330 | of text in the wiki page. That text follows the newline character |
| 331 | that terminates the W card. The wiki text is always followed by one |
| 332 | extra newline. |
| 333 | |
| 334 | An example wiki artifact can be seen |
| 335 | [/artifact?name=7b2f5fd0e0&txt=1 | here]. |
| 336 | |
| 337 | <a name="tktchng"></a> |
| 338 | <h2>5.0 Ticket Changes</h2> |
| 339 | |
| 340 | A ticket-change artifact represents a change to a trouble ticket. |
| @@ -375,25 +381,25 @@ | |
| 381 | |
| 382 | <a name="attachment"></a> |
| 383 | <h2>6.0 Attachments</h2> |
| 384 | |
| 385 | An attachment artifact associates some other artifact that is the |
| 386 | attachment (the source artifact) with a ticket or wiki page or event to which |
| 387 | the attachment is connected (the target artifact). |
| 388 | The following cards are allowed on an attachment artifact: |
| 389 | |
| 390 | <blockquote> |
| 391 | <b>A</b> <i>filename target</i> ?<i>source</i>?<br /> |
| 392 | <b>C</b> <i>comment</i><br /> |
| 393 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 394 | <b>U</b> <i>user-name</i><br /> |
| 395 | <b>Z</b> <i>checksum</i> |
| 396 | </blockquote> |
| 397 | |
| 398 | The A card specifies a filename for the attachment in its first argument. |
| 399 | The second argument to the A card is the name |
| 400 | of the wiki page or ticket or event to which the attachment is connected. The |
| 401 | third argument is either missing or else it is the 40-character artifact |
| 402 | ID of the attachment itself. A missing third argument means that the |
| 403 | attachment should be deleted. |
| 404 | |
| 405 | The C card is an optional comment describing what the attachment is about. |
| @@ -405,46 +411,111 @@ | |
| 411 | A single U card gives the name of the user to added the attachment. |
| 412 | If an attachment is added anonymously, then the U card may be omitted. |
| 413 | |
| 414 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 415 | |
| 416 | |
| 417 | <a name="event"></a> |
| 418 | <h2>7.0 Events</h2> |
| 419 | |
| 420 | An event artifact associates a timeline comment and a page of text |
| 421 | (similar to a wiki page) with a point in time. Events can be used |
| 422 | to record project milestones, release notes, blog entries, process |
| 423 | checkpoints, or news articles. |
| 424 | The following cards are allowed on an event artifact: |
| 425 | |
| 426 | <blockquote> |
| 427 | <b>C</b> <i>comment</i><br> |
| 428 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 429 | <b>E</b> <i>event-time</i> <i>event-id</i><br /> |
| 430 | <b>P</b> <i>parent-artifact-id</i>+<br /> |
| 431 | <b>T</b> <b>+</b><i>tag-name</i> <b>*</b> <i>value</i><br /> |
| 432 | <b>U</b> <i>user-name</i><br /> |
| 433 | <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> |
| 434 | <b>Z</b> <i>checksum</i> |
| 435 | </blockquote> |
| 436 | |
| 437 | The C card contains text that is displayed on the timeline for the |
| 438 | event. Exactly one C card is required on an event artifact. |
| 439 | |
| 440 | A single D card is required to give the date and time when the |
| 441 | event artifact was created. This is different from the time at which |
| 442 | the event occurs. |
| 443 | |
| 444 | A single E card gives the time of the event (the point on the timeline |
| 445 | where the event is displayed) and a unique identifier for the event. |
| 446 | When there are multiple artifacts with the same event-id, the one with |
| 447 | the most recent D card is the only one used. The event-id must be a |
| 448 | 40-character lower-case hexadecimal string. |
| 449 | |
| 450 | The option P card specifies a prior event with the same event-id from |
| 451 | which the current event is an edit. The P card is a hint to the system |
| 452 | that it might be space efficient to store one event as a delta of the |
| 453 | other. |
| 454 | |
| 455 | An event might contain one or more T-cards used to set |
| 456 | [./branching.wiki#tags | tags or properties] |
| 457 | on the event. The format of the T-card is the same as |
| 458 | described in [#ctrl | Control Artifacts] section above, except that the |
| 459 | second argument is the single characcter "<b>*</b>" instead of an |
| 460 | artifact ID and the name is always prefaced by "<b>+</b>". |
| 461 | The <b>*</b> in place of the artifact ID indicates that |
| 462 | the tag or property applies to the current artifact. It is not |
| 463 | possible to encode the current artifact ID as part of an artifact, |
| 464 | since the act of inserting the artifact ID would change the artifact ID, |
| 465 | hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the |
| 466 | name means that tags can only be add and they can only be non-propagating |
| 467 | tags. A an event, T cards are normally used to set the background |
| 468 | display color for timelines. |
| 469 | |
| 470 | The optional U card gives name of the user who entered the event. |
| 471 | |
| 472 | A single W card provides wiki text for the document associated with the |
| 473 | event. The format of the W card is exactly the same as for a |
| 474 | [#wikichng | wiki artifact]. |
| 475 | |
| 476 | The Z card is the usual checksum over the rest of the attachment artifact. |
| 477 | |
| 478 | |
| 479 | <a name="summary"></a> |
| 480 | <h2>8.0 Card Summary</h2> |
| 481 | |
| 482 | The following table summaries the various kinds of cards that |
| 483 | appear on Fossil artifacts: |
| 484 | |
| 485 | <table border=1 width="100%"> |
| 486 | <tr> |
| 487 | <th rowspan=2 valign=bottom>Card Format</th> |
| 488 | <th colspan=7>Used By</th> |
| 489 | </tr> |
| 490 | <tr> |
| 491 | <th>Manifest</th> |
| 492 | <th>Cluster</th> |
| 493 | <th>Control</th> |
| 494 | <th>Wiki</th> |
| 495 | <th>Ticket</th> |
| 496 | <th>Attachment</th> |
| 497 | <th>Event</th> |
| 498 | </tr> |
| 499 | <tr> |
| 500 | <td><b>A</b> <i>filename target source</i></td> |
| 501 | <td> </td> |
| 502 | <td> </td> |
| 503 | <td> </td> |
| 504 | <td> </td> |
| 505 | <td> </td> |
| 506 | <td align=center><b>X</b></td> |
| 507 | <td> </td> |
| 508 | </tr> |
| 509 | <tr> |
| 510 | <td><b>C</b> <i>comment-text</i></td> |
| 511 | <td align=center><b>X</b></td> |
| 512 | <td> </td> |
| 513 | <td> </td> |
| 514 | <td> </td> |
| 515 | <td> </td> |
| 516 | <td align=center><b>X</b></td> |
| 517 | <td align=center><b>X</b></td> |
| 518 | </tr> |
| 519 | <tr> |
| 520 | <td><b>D</b> <i>date-time-stamp</i></td> |
| 521 | <td align=center><b>X</b></td> |
| @@ -451,14 +522,26 @@ | |
| 522 | <td align=center> </td> |
| 523 | <td align=center><b>X</b></td> |
| 524 | <td align=center><b>X</b></td> |
| 525 | <td align=center><b>X</b></td> |
| 526 | <td align=center><b>X</b></td> |
| 527 | <td align=center><b>X</b></td> |
| 528 | </tr> |
| 529 | <tr> |
| 530 | <td><b>E</b> <i>event-time event-id</i></td> |
| 531 | <td align=center> </td> |
| 532 | <td align=center> </td> |
| 533 | <td align=center> </td> |
| 534 | <td align=center> </td> |
| 535 | <td align=center> </td> |
| 536 | <td align=center> </td> |
| 537 | <td align=center><b>X</b></td> |
| 538 | </tr> |
| 539 | <tr> |
| 540 | <td><b>F</b> <i>filename uuid permissions oldname</i></td> |
| 541 | <td align=center><b>X</b></td> |
| 542 | <td align=center> </td> |
| 543 | <td align=center> </td> |
| 544 | <td align=center> </td> |
| 545 | <td align=center> </td> |
| 546 | <td align=center> </td> |
| 547 | <td align=center> </td> |
| @@ -469,18 +552,20 @@ | |
| 552 | <td align=center> </td> |
| 553 | <td align=center> </td> |
| 554 | <td align=center> </td> |
| 555 | <td align=center><b>X</b></td> |
| 556 | <td align=center> </td> |
| 557 | <td align=center> </td> |
| 558 | </tr> |
| 559 | <tr> |
| 560 | <td><b>K</b> <i>ticket-uuid</i></td> |
| 561 | <td align=center> </td> |
| 562 | <td align=center> </td> |
| 563 | <td align=center> </td> |
| 564 | <td align=center> </td> |
| 565 | <td align=center><b>X</b></td> |
| 566 | <td align=center> </td> |
| 567 | <td align=center> </td> |
| 568 | </tr> |
| 569 | <tr> |
| 570 | <td><b>L</b> <i>wiki-title</i></td> |
| 571 | <td align=center> </td> |
| @@ -487,15 +572,17 @@ | |
| 572 | <td align=center> </td> |
| 573 | <td align=center> </td> |
| 574 | <td align=center><b>X</b></td> |
| 575 | <td align=center> </td> |
| 576 | <td align=center> </td> |
| 577 | <td align=center> </td> |
| 578 | </tr> |
| 579 | <tr> |
| 580 | <td><b>M</b> <i>uuid</i></td> |
| 581 | <td align=center> </td> |
| 582 | <td align=center><b>X</b></td> |
| 583 | <td align=center> </td> |
| 584 | <td align=center> </td> |
| 585 | <td align=center> </td> |
| 586 | <td align=center> </td> |
| 587 | <td align=center> </td> |
| 588 | </tr> |
| @@ -505,14 +592,16 @@ | |
| 592 | <td align=center> </td> |
| 593 | <td align=center> </td> |
| 594 | <td align=center><b>X</b></td> |
| 595 | <td align=center> </td> |
| 596 | <td align=center> </td> |
| 597 | <td align=center> </td> |
| 598 | </tr> |
| 599 | <tr> |
| 600 | <td><b>R</b> <i>md5sum</i></td> |
| 601 | <td align=center><b>X</b></td> |
| 602 | <td align=center> </td> |
| 603 | <td align=center> </td> |
| 604 | <td align=center> </td> |
| 605 | <td align=center> </td> |
| 606 | <td align=center> </td> |
| 607 | <td align=center> </td> |
| @@ -522,15 +611,17 @@ | |
| 611 | <td align=center> </td> |
| 612 | <td align=center><b>X</b></td> |
| 613 | <td align=center> </td> |
| 614 | <td align=center> </td> |
| 615 | <td align=center> </td> |
| 616 | <td align=center><b>X</b></td> |
| 617 | </tr> |
| 618 | <tr> |
| 619 | <td><b>U</b> <i>username</i></td> |
| 620 | <td align=center><b>X</b></td> |
| 621 | <td align=center> </td> |
| 622 | <td align=center><b>X</b></td> |
| 623 | <td align=center><b>X</b></td> |
| 624 | <td align=center><b>X</b></td> |
| 625 | <td align=center><b>X</b></td> |
| 626 | <td align=center><b>X</b></td> |
| 627 | </tr> |
| @@ -540,16 +631,18 @@ | |
| 631 | <td align=center> </td> |
| 632 | <td align=center> </td> |
| 633 | <td align=center><b>X</b></td> |
| 634 | <td align=center> </td> |
| 635 | <td align=center> </td> |
| 636 | <td align=center><b>X</b></td> |
| 637 | </tr> |
| 638 | <tr> |
| 639 | <td><b>Z</b> <i>md5sum</i></td> |
| 640 | <td align=center><b>X</b></td> |
| 641 | <td align=center><b>X</b></td> |
| 642 | <td align=center><b>X</b></td> |
| 643 | <td align=center><b>X</b></td> |
| 644 | <td align=center><b>X</b></td> |
| 645 | <td align=center><b>X</b></td> |
| 646 | <td align=center><b>X</b></td> |
| 647 | </tr> |
| 648 | </table> |
| 649 |
+5
-2
| --- www/index.wiki | ||
| +++ www/index.wiki | ||
| @@ -40,12 +40,13 @@ | ||
| 40 | 40 | internet these days. What makes Fossil worthy of attention? |
| 41 | 41 | |
| 42 | 42 | 1. <b>Bug Tracking And Wiki</b> - |
| 43 | 43 | In addition to doing [./concepts.wiki | distributed version control] |
| 44 | 44 | like Git and Mercurial, |
| 45 | - Fossil also supports [./bugtheory.wiki | distributed bug tracking] and | |
| 46 | - [./wikitheory.wiki | distributed wiki] all in a single | |
| 45 | + Fossil also supports [./bugtheory.wiki | distributed bug tracking], | |
| 46 | + [./wikitheory.wiki | distributed wiki], and a | |
| 47 | + [./event.wiki | distributed blog] mechanism all in a single | |
| 47 | 48 | integrated package. |
| 48 | 49 | |
| 49 | 50 | 2. <b>Web Interface</b> - |
| 50 | 51 | Fossil has a built-in and easy-to-use [./webui.wiki | web interface] |
| 51 | 52 | that simplifies project tracking and promotes situational awareness. |
| @@ -111,10 +112,12 @@ | ||
| 111 | 112 | * A tutorial on [./branching.wiki | branching], what it means and how |
| 112 | 113 | to do it using fossil. |
| 113 | 114 | * The [./selfcheck.wiki | automatic self-check] mechanism |
| 114 | 115 | helps insure project integrity. |
| 115 | 116 | * Fossil contains a [./wikitheory.wiki | built-in wiki]. |
| 117 | + * An [./event.wiki | Event] is a special kind of wiki page associated | |
| 118 | + with a point in time rather than a name. | |
| 116 | 119 | * There is a |
| 117 | 120 | [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable |
| 118 | 121 | [http://www.mail-archive.com/[email protected] | archives] |
| 119 | 122 | available for discussing fossil issues. |
| 120 | 123 | * [./stats.wiki | Performance statistics] taken from real-world projects |
| 121 | 124 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -40,12 +40,13 @@ | |
| 40 | internet these days. What makes Fossil worthy of attention? |
| 41 | |
| 42 | 1. <b>Bug Tracking And Wiki</b> - |
| 43 | In addition to doing [./concepts.wiki | distributed version control] |
| 44 | like Git and Mercurial, |
| 45 | Fossil also supports [./bugtheory.wiki | distributed bug tracking] and |
| 46 | [./wikitheory.wiki | distributed wiki] all in a single |
| 47 | integrated package. |
| 48 | |
| 49 | 2. <b>Web Interface</b> - |
| 50 | Fossil has a built-in and easy-to-use [./webui.wiki | web interface] |
| 51 | that simplifies project tracking and promotes situational awareness. |
| @@ -111,10 +112,12 @@ | |
| 111 | * A tutorial on [./branching.wiki | branching], what it means and how |
| 112 | to do it using fossil. |
| 113 | * The [./selfcheck.wiki | automatic self-check] mechanism |
| 114 | helps insure project integrity. |
| 115 | * Fossil contains a [./wikitheory.wiki | built-in wiki]. |
| 116 | * There is a |
| 117 | [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable |
| 118 | [http://www.mail-archive.com/[email protected] | archives] |
| 119 | available for discussing fossil issues. |
| 120 | * [./stats.wiki | Performance statistics] taken from real-world projects |
| 121 |
| --- www/index.wiki | |
| +++ www/index.wiki | |
| @@ -40,12 +40,13 @@ | |
| 40 | internet these days. What makes Fossil worthy of attention? |
| 41 | |
| 42 | 1. <b>Bug Tracking And Wiki</b> - |
| 43 | In addition to doing [./concepts.wiki | distributed version control] |
| 44 | like Git and Mercurial, |
| 45 | Fossil also supports [./bugtheory.wiki | distributed bug tracking], |
| 46 | [./wikitheory.wiki | distributed wiki], and a |
| 47 | [./event.wiki | distributed blog] mechanism all in a single |
| 48 | integrated package. |
| 49 | |
| 50 | 2. <b>Web Interface</b> - |
| 51 | Fossil has a built-in and easy-to-use [./webui.wiki | web interface] |
| 52 | that simplifies project tracking and promotes situational awareness. |
| @@ -111,10 +112,12 @@ | |
| 112 | * A tutorial on [./branching.wiki | branching], what it means and how |
| 113 | to do it using fossil. |
| 114 | * The [./selfcheck.wiki | automatic self-check] mechanism |
| 115 | helps insure project integrity. |
| 116 | * Fossil contains a [./wikitheory.wiki | built-in wiki]. |
| 117 | * An [./event.wiki | Event] is a special kind of wiki page associated |
| 118 | with a point in time rather than a name. |
| 119 | * There is a |
| 120 | [http://lists.fossil-scm.org:8080/cgi-bin/mailman/listinfo/fossil-users | mailing list] (with publicly readable |
| 121 | [http://www.mail-archive.com/[email protected] | archives] |
| 122 | available for discussing fossil issues. |
| 123 | * [./stats.wiki | Performance statistics] taken from real-world projects |
| 124 |
+1
| --- www/wikitheory.wiki | ||
| +++ www/wikitheory.wiki | ||
| @@ -5,10 +5,11 @@ | ||
| 5 | 5 | * Stand-alone wiki pages. |
| 6 | 6 | * Description and comments in [./bugtheory.wiki | bug reports]. |
| 7 | 7 | * Check-in comments. |
| 8 | 8 | * [./embeddeddoc.wiki | Embedded documentation] files whose |
| 9 | 9 | name ends in "wiki". |
| 10 | + * [./event.wiki | Event descriptions]. | |
| 10 | 11 | |
| 11 | 12 | The [/wiki_rules | formatting rules] for fossil wiki |
| 12 | 13 | are designed to be simple and intuitive. The idea is that wiki provides |
| 13 | 14 | paragraph breaks, numbered and bulleted lists, and hyperlinking for |
| 14 | 15 | simple documents together with a safe subset of HTML for more complex |
| 15 | 16 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -5,10 +5,11 @@ | |
| 5 | * Stand-alone wiki pages. |
| 6 | * Description and comments in [./bugtheory.wiki | bug reports]. |
| 7 | * Check-in comments. |
| 8 | * [./embeddeddoc.wiki | Embedded documentation] files whose |
| 9 | name ends in "wiki". |
| 10 | |
| 11 | The [/wiki_rules | formatting rules] for fossil wiki |
| 12 | are designed to be simple and intuitive. The idea is that wiki provides |
| 13 | paragraph breaks, numbered and bulleted lists, and hyperlinking for |
| 14 | simple documents together with a safe subset of HTML for more complex |
| 15 |
| --- www/wikitheory.wiki | |
| +++ www/wikitheory.wiki | |
| @@ -5,10 +5,11 @@ | |
| 5 | * Stand-alone wiki pages. |
| 6 | * Description and comments in [./bugtheory.wiki | bug reports]. |
| 7 | * Check-in comments. |
| 8 | * [./embeddeddoc.wiki | Embedded documentation] files whose |
| 9 | name ends in "wiki". |
| 10 | * [./event.wiki | Event descriptions]. |
| 11 | |
| 12 | The [/wiki_rules | formatting rules] for fossil wiki |
| 13 | are designed to be simple and intuitive. The idea is that wiki provides |
| 14 | paragraph breaks, numbered and bulleted lists, and hyperlinking for |
| 15 | simple documents together with a safe subset of HTML for more complex |
| 16 |