Fossil SCM
Improved file format documentation. Added information on the attachment artifact. Redefine the A-card (which has not previously been used). Update the Manifest object to store attachment artifacts.
Commit
d5a4e41c81280c86e9922785713294ef78083065
Parent
ef80cbf52f4b565…
2 files changed
+57
-92
+237
-85
+57
-92
| --- src/manifest.c | ||
| +++ src/manifest.c | ||
| @@ -37,67 +37,56 @@ | ||
| 37 | 37 | #define CFTYPE_MANIFEST 1 |
| 38 | 38 | #define CFTYPE_CLUSTER 2 |
| 39 | 39 | #define CFTYPE_CONTROL 3 |
| 40 | 40 | #define CFTYPE_WIKI 4 |
| 41 | 41 | #define CFTYPE_TICKET 5 |
| 42 | - | |
| 43 | -/* | |
| 44 | -** Mode parameter values | |
| 45 | -*/ | |
| 46 | -#define CFMODE_READ 1 | |
| 47 | -#define CFMODE_APPEND 2 | |
| 48 | -#define CFMODE_WRITE 3 | |
| 42 | +#define CFTYPE_ATTACHMENT 6 | |
| 49 | 43 | |
| 50 | 44 | /* |
| 51 | 45 | ** A parsed manifest or cluster. |
| 52 | 46 | */ |
| 53 | 47 | struct Manifest { |
| 54 | 48 | Blob content; /* The original content blob */ |
| 55 | - int type; /* Type of file */ | |
| 56 | - int mode; /* Access mode */ | |
| 57 | - char *zComment; /* Decoded comment */ | |
| 58 | - double rDate; /* Time in the "D" line */ | |
| 59 | - char *zUser; /* Name of the user */ | |
| 60 | - char *zRepoCksum; /* MD5 checksum of the baseline content */ | |
| 61 | - char *zWiki; /* Text of the wiki page */ | |
| 62 | - char *zWikiTitle; /* Name of the wiki page */ | |
| 63 | - char *zTicketUuid; /* UUID for a ticket */ | |
| 64 | - int nFile; /* Number of F lines */ | |
| 49 | + int type; /* Type of artifact. One of CFTYPE_xxxxx */ | |
| 50 | + char *zComment; /* Decoded comment. The C card. */ | |
| 51 | + double rDate; /* Date and time from D card. 0.0 if no D card. */ | |
| 52 | + char *zUser; /* Name of the user from the U card. */ | |
| 53 | + char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ | |
| 54 | + char *zWiki; /* Text of the wiki page. W card. */ | |
| 55 | + char *zWikiTitle; /* Name of the wiki page. L card. */ | |
| 56 | + char *zTicketUuid; /* UUID for a ticket. K card. */ | |
| 57 | + char *zAttachName; /* Filename of an attachment. A card. */ | |
| 58 | + char *zAttachSrc; /* UUID of document being attached. A card. */ | |
| 59 | + char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ | |
| 60 | + int nFile; /* Number of F cards */ | |
| 65 | 61 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 66 | 62 | struct { |
| 67 | 63 | char *zName; /* Name of a file */ |
| 68 | 64 | char *zUuid; /* UUID of the file */ |
| 69 | 65 | char *zPerm; /* File permissions */ |
| 70 | 66 | char *zPrior; /* Prior name if the name was changed */ |
| 71 | 67 | int iRename; /* index of renamed name in prior/next manifest */ |
| 72 | - } *aFile; | |
| 73 | - int nParent; /* Number of parents */ | |
| 68 | + } *aFile; /* One entry for each F card */ | |
| 69 | + int nParent; /* Number of parents. */ | |
| 74 | 70 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 75 | - char **azParent; /* UUIDs of parents */ | |
| 71 | + char **azParent; /* UUIDs of parents. One for each P card argument */ | |
| 76 | 72 | int nCChild; /* Number of cluster children */ |
| 77 | 73 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 78 | - char **azCChild; /* UUIDs of referenced objects in a cluster */ | |
| 79 | - int nTag; /* Number of T lines */ | |
| 74 | + char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */ | |
| 75 | + int nTag; /* Number of T Cards */ | |
| 80 | 76 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 81 | 77 | struct { |
| 82 | 78 | char *zName; /* Name of the tag */ |
| 83 | 79 | char *zUuid; /* UUID that the tag is applied to */ |
| 84 | 80 | char *zValue; /* Value if the tag is really a property */ |
| 85 | - } *aTag; | |
| 86 | - int nField; /* Number of J lines */ | |
| 81 | + } *aTag; /* One for each T card */ | |
| 82 | + int nField; /* Number of J cards */ | |
| 87 | 83 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 88 | 84 | struct { |
| 89 | 85 | char *zName; /* Key or field name */ |
| 90 | 86 | char *zValue; /* Value of the field */ |
| 91 | - } *aField; | |
| 92 | - int nAttach; /* Number of A lines */ | |
| 93 | - int nAttachAlloc; /* Slots allocated in aAttach[] */ | |
| 94 | - struct { | |
| 95 | - char *zUuid; /* UUID of the attachment */ | |
| 96 | - char *zName; /* Name of the attachment */ | |
| 97 | - char *zDesc; /* Description of the attachment */ | |
| 98 | - } *aAttach; | |
| 87 | + } *aField; /* One for each J card */ | |
| 99 | 88 | }; |
| 100 | 89 | #endif |
| 101 | 90 | |
| 102 | 91 | |
| 103 | 92 | /* |
| @@ -108,11 +97,10 @@ | ||
| 108 | 97 | free(p->aFile); |
| 109 | 98 | free(p->azParent); |
| 110 | 99 | free(p->azCChild); |
| 111 | 100 | free(p->aTag); |
| 112 | 101 | free(p->aField); |
| 113 | - free(p->aAttach); | |
| 114 | 102 | memset(p, 0, sizeof(*p)); |
| 115 | 103 | } |
| 116 | 104 | |
| 117 | 105 | /* |
| 118 | 106 | ** Parse a blob into a Manifest object. The Manifest object |
| @@ -178,44 +166,42 @@ | ||
| 178 | 166 | cPrevType = z[0]; |
| 179 | 167 | seenHeader = 1; |
| 180 | 168 | if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error; |
| 181 | 169 | switch( z[0] ){ |
| 182 | 170 | /* |
| 183 | - ** A <uuid> <filename> <description> | |
| 171 | + ** A (+|-)<filename> target source | |
| 184 | 172 | ** |
| 185 | 173 | ** Identifies an attachment to either a wiki page or a ticket. |
| 186 | 174 | ** <uuid> is the artifact that is the attachment. |
| 187 | 175 | */ |
| 188 | 176 | case 'A': { |
| 189 | - char *zName, *zUuid, *zDesc; | |
| 177 | + char *zName, *zTarget, *zSrc; | |
| 190 | 178 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 191 | 179 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 192 | 180 | if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; |
| 193 | 181 | if( blob_token(&line, &a3)==0 ) goto manifest_syntax_error; |
| 194 | - zUuid = blob_terminate(&a1); | |
| 195 | - zName = blob_terminate(&a2); | |
| 196 | - zDesc = blob_terminate(&a3); | |
| 197 | - if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error; | |
| 198 | - if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; | |
| 182 | + if( p->zAttachName!=0 ) goto manifest_syntax_error; | |
| 183 | + zName = blob_terminate(&a1); | |
| 184 | + zTarget = blob_terminate(&a2); | |
| 185 | + zSrc = blob_terminate(&a3); | |
| 199 | 186 | defossilize(zName); |
| 200 | - if( !file_is_simple_pathname(zName) ){ | |
| 201 | - goto manifest_syntax_error; | |
| 202 | - } | |
| 203 | - defossilize(zDesc); | |
| 204 | - if( p->nAttach>=p->nAttachAlloc ){ | |
| 205 | - p->nAttachAlloc = p->nAttachAlloc*2 + 10; | |
| 206 | - p->aAttach = realloc(p->aAttach, | |
| 207 | - p->nAttachAlloc*sizeof(p->aAttach[0]) ); | |
| 208 | - if( p->aAttach==0 ) fossil_panic("out of memory"); | |
| 209 | - } | |
| 210 | - i = p->nAttach++; | |
| 211 | - p->aAttach[i].zUuid = zUuid; | |
| 212 | - p->aAttach[i].zName = zName; | |
| 213 | - p->aAttach[i].zDesc = zDesc; | |
| 214 | - if( i>0 && strcmp(p->aAttach[i-1].zUuid, zUuid)>=0 ){ | |
| 215 | - goto manifest_syntax_error; | |
| 216 | - } | |
| 187 | + if( zName[0]!='+' && zName[0]!='-' ){ | |
| 188 | + goto manifest_syntax_error; | |
| 189 | + } | |
| 190 | + if( !file_is_simple_pathname(&zName[1]) ){ | |
| 191 | + goto manifest_syntax_error; | |
| 192 | + } | |
| 193 | + defossilize(zTarget); | |
| 194 | + if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) | |
| 195 | + && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ | |
| 196 | + goto manifest_syntax_error; | |
| 197 | + } | |
| 198 | + if( blob_size(&a3)!=UUID_SIZE ) goto manifest_syntax_error; | |
| 199 | + if( !validate16(zSrc, UUID_SIZE) ) goto manifest_syntax_error; | |
| 200 | + p->zAttachName = zName; | |
| 201 | + p->zAttachSrc = zSrc; | |
| 202 | + p->zAttachTarget = zTarget; | |
| 217 | 203 | break; |
| 218 | 204 | } |
| 219 | 205 | |
| 220 | 206 | /* |
| 221 | 207 | ** C <comment> |
| @@ -247,33 +233,10 @@ | ||
| 247 | 233 | if( p->rDate!=0.0 ) goto manifest_syntax_error; |
| 248 | 234 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 249 | 235 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 250 | 236 | zDate = blob_terminate(&a1); |
| 251 | 237 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 252 | - break; | |
| 253 | - } | |
| 254 | - | |
| 255 | - /* | |
| 256 | - ** E <mode> | |
| 257 | - ** | |
| 258 | - ** Access mode. <mode> can be one of "read", "append", | |
| 259 | - ** or "write". | |
| 260 | - */ | |
| 261 | - case 'E': { | |
| 262 | - md5sum_step_text(blob_buffer(&line), blob_size(&line)); | |
| 263 | - if( p->mode!=0 ) goto manifest_syntax_error; | |
| 264 | - if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; | |
| 265 | - if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; | |
| 266 | - if( blob_eq(&a1, "write") ){ | |
| 267 | - p->mode = CFMODE_WRITE; | |
| 268 | - }else if( blob_eq(&a1, "append") ){ | |
| 269 | - p->mode = CFMODE_APPEND; | |
| 270 | - }else if( blob_eq(&a1, "read") ){ | |
| 271 | - p->mode = CFMODE_READ; | |
| 272 | - }else{ | |
| 273 | - goto manifest_syntax_error; | |
| 274 | - } | |
| 275 | 238 | break; |
| 276 | 239 | } |
| 277 | 240 | |
| 278 | 241 | /* |
| 279 | 242 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| @@ -608,72 +571,74 @@ | ||
| 608 | 571 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 609 | 572 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 610 | 573 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 611 | 574 | if( p->nField>0 ) goto manifest_syntax_error; |
| 612 | 575 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 613 | - if( p->nAttach>0 ) goto manifest_syntax_error; | |
| 614 | 576 | if( p->zWiki ) goto manifest_syntax_error; |
| 615 | 577 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 616 | 578 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 579 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 617 | 580 | p->type = CFTYPE_MANIFEST; |
| 618 | 581 | }else if( p->nCChild>0 ){ |
| 619 | 582 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| 620 | 583 | if( p->zComment!=0 ) goto manifest_syntax_error; |
| 621 | 584 | if( p->zUser!=0 ) goto manifest_syntax_error; |
| 622 | 585 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 623 | 586 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 624 | - if( p->zRepoCksum!=0 ) goto manifest_syntax_error; | |
| 625 | 587 | if( p->nField>0 ) goto manifest_syntax_error; |
| 626 | 588 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 627 | - if( p->nAttach>0 ) goto manifest_syntax_error; | |
| 628 | 589 | if( p->zWiki ) goto manifest_syntax_error; |
| 629 | 590 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 591 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 630 | 592 | if( !seenZ ) goto manifest_syntax_error; |
| 631 | 593 | p->type = CFTYPE_CLUSTER; |
| 632 | 594 | }else if( p->nField>0 ){ |
| 633 | 595 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 634 | - if( p->zRepoCksum!=0 ) goto manifest_syntax_error; | |
| 635 | 596 | if( p->zWiki ) goto manifest_syntax_error; |
| 636 | 597 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 637 | 598 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 638 | 599 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 639 | 600 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 640 | 601 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 602 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 641 | 603 | if( !seenZ ) goto manifest_syntax_error; |
| 642 | 604 | p->type = CFTYPE_TICKET; |
| 643 | 605 | }else if( p->zWiki!=0 ){ |
| 644 | 606 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 645 | - if( p->zRepoCksum!=0 ) goto manifest_syntax_error; | |
| 646 | 607 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 647 | 608 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 648 | 609 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 649 | 610 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 611 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 650 | 612 | if( !seenZ ) goto manifest_syntax_error; |
| 651 | 613 | p->type = CFTYPE_WIKI; |
| 652 | 614 | }else if( p->nTag>0 ){ |
| 653 | 615 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 654 | - if( p->zRepoCksum!=0 ) goto manifest_syntax_error; | |
| 655 | 616 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 656 | - if( p->nAttach>0 ) goto manifest_syntax_error; | |
| 657 | - if( p->nField>0 ) goto manifest_syntax_error; | |
| 658 | - if( p->zWiki ) goto manifest_syntax_error; | |
| 659 | 617 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 660 | 618 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 619 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 661 | 620 | if( !seenZ ) goto manifest_syntax_error; |
| 662 | 621 | p->type = CFTYPE_CONTROL; |
| 663 | - }else{ | |
| 622 | + }else if( p->zAttachName ){ | |
| 664 | 623 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 665 | 624 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 625 | + if( p->zTicketUuid ) goto manifest_syntax_error; | |
| 626 | + if( p->zWikiTitle ) goto manifest_syntax_error; | |
| 627 | + p->type = CFTYPE_ATTACHMENT; | |
| 628 | + }else{ | |
| 629 | + if( p->nCChild>0 ) goto manifest_syntax_error; | |
| 630 | + if( p->rDate<=0.0 ) goto manifest_syntax_error; | |
| 631 | + if( p->nParent>0 ) goto manifest_syntax_error; | |
| 666 | 632 | if( p->nField>0 ) goto manifest_syntax_error; |
| 667 | 633 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 668 | - if( p->nAttach>0 ) goto manifest_syntax_error; | |
| 669 | 634 | if( p->zWiki ) goto manifest_syntax_error; |
| 670 | 635 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 671 | 636 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 637 | + if( p->zAttachName ) goto manifest_syntax_error; | |
| 672 | 638 | p->type = CFTYPE_MANIFEST; |
| 673 | 639 | } |
| 674 | - | |
| 675 | 640 | md5sum_init(); |
| 676 | 641 | return 1; |
| 677 | 642 | |
| 678 | 643 | manifest_syntax_error: |
| 679 | 644 | /*fprintf(stderr, "Manifest error on line %i\n", lineNo);fflush(stderr);*/ |
| 680 | 645 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -37,67 +37,56 @@ | |
| 37 | #define CFTYPE_MANIFEST 1 |
| 38 | #define CFTYPE_CLUSTER 2 |
| 39 | #define CFTYPE_CONTROL 3 |
| 40 | #define CFTYPE_WIKI 4 |
| 41 | #define CFTYPE_TICKET 5 |
| 42 | |
| 43 | /* |
| 44 | ** Mode parameter values |
| 45 | */ |
| 46 | #define CFMODE_READ 1 |
| 47 | #define CFMODE_APPEND 2 |
| 48 | #define CFMODE_WRITE 3 |
| 49 | |
| 50 | /* |
| 51 | ** A parsed manifest or cluster. |
| 52 | */ |
| 53 | struct Manifest { |
| 54 | Blob content; /* The original content blob */ |
| 55 | int type; /* Type of file */ |
| 56 | int mode; /* Access mode */ |
| 57 | char *zComment; /* Decoded comment */ |
| 58 | double rDate; /* Time in the "D" line */ |
| 59 | char *zUser; /* Name of the user */ |
| 60 | char *zRepoCksum; /* MD5 checksum of the baseline content */ |
| 61 | char *zWiki; /* Text of the wiki page */ |
| 62 | char *zWikiTitle; /* Name of the wiki page */ |
| 63 | char *zTicketUuid; /* UUID for a ticket */ |
| 64 | int nFile; /* Number of F lines */ |
| 65 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 66 | struct { |
| 67 | char *zName; /* Name of a file */ |
| 68 | char *zUuid; /* UUID of the file */ |
| 69 | char *zPerm; /* File permissions */ |
| 70 | char *zPrior; /* Prior name if the name was changed */ |
| 71 | int iRename; /* index of renamed name in prior/next manifest */ |
| 72 | } *aFile; |
| 73 | int nParent; /* Number of parents */ |
| 74 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 75 | char **azParent; /* UUIDs of parents */ |
| 76 | int nCChild; /* Number of cluster children */ |
| 77 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 78 | char **azCChild; /* UUIDs of referenced objects in a cluster */ |
| 79 | int nTag; /* Number of T lines */ |
| 80 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 81 | struct { |
| 82 | char *zName; /* Name of the tag */ |
| 83 | char *zUuid; /* UUID that the tag is applied to */ |
| 84 | char *zValue; /* Value if the tag is really a property */ |
| 85 | } *aTag; |
| 86 | int nField; /* Number of J lines */ |
| 87 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 88 | struct { |
| 89 | char *zName; /* Key or field name */ |
| 90 | char *zValue; /* Value of the field */ |
| 91 | } *aField; |
| 92 | int nAttach; /* Number of A lines */ |
| 93 | int nAttachAlloc; /* Slots allocated in aAttach[] */ |
| 94 | struct { |
| 95 | char *zUuid; /* UUID of the attachment */ |
| 96 | char *zName; /* Name of the attachment */ |
| 97 | char *zDesc; /* Description of the attachment */ |
| 98 | } *aAttach; |
| 99 | }; |
| 100 | #endif |
| 101 | |
| 102 | |
| 103 | /* |
| @@ -108,11 +97,10 @@ | |
| 108 | free(p->aFile); |
| 109 | free(p->azParent); |
| 110 | free(p->azCChild); |
| 111 | free(p->aTag); |
| 112 | free(p->aField); |
| 113 | free(p->aAttach); |
| 114 | memset(p, 0, sizeof(*p)); |
| 115 | } |
| 116 | |
| 117 | /* |
| 118 | ** Parse a blob into a Manifest object. The Manifest object |
| @@ -178,44 +166,42 @@ | |
| 178 | cPrevType = z[0]; |
| 179 | seenHeader = 1; |
| 180 | if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error; |
| 181 | switch( z[0] ){ |
| 182 | /* |
| 183 | ** A <uuid> <filename> <description> |
| 184 | ** |
| 185 | ** Identifies an attachment to either a wiki page or a ticket. |
| 186 | ** <uuid> is the artifact that is the attachment. |
| 187 | */ |
| 188 | case 'A': { |
| 189 | char *zName, *zUuid, *zDesc; |
| 190 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 191 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 192 | if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; |
| 193 | if( blob_token(&line, &a3)==0 ) goto manifest_syntax_error; |
| 194 | zUuid = blob_terminate(&a1); |
| 195 | zName = blob_terminate(&a2); |
| 196 | zDesc = blob_terminate(&a3); |
| 197 | if( blob_size(&a1)!=UUID_SIZE ) goto manifest_syntax_error; |
| 198 | if( !validate16(zUuid, UUID_SIZE) ) goto manifest_syntax_error; |
| 199 | defossilize(zName); |
| 200 | if( !file_is_simple_pathname(zName) ){ |
| 201 | goto manifest_syntax_error; |
| 202 | } |
| 203 | defossilize(zDesc); |
| 204 | if( p->nAttach>=p->nAttachAlloc ){ |
| 205 | p->nAttachAlloc = p->nAttachAlloc*2 + 10; |
| 206 | p->aAttach = realloc(p->aAttach, |
| 207 | p->nAttachAlloc*sizeof(p->aAttach[0]) ); |
| 208 | if( p->aAttach==0 ) fossil_panic("out of memory"); |
| 209 | } |
| 210 | i = p->nAttach++; |
| 211 | p->aAttach[i].zUuid = zUuid; |
| 212 | p->aAttach[i].zName = zName; |
| 213 | p->aAttach[i].zDesc = zDesc; |
| 214 | if( i>0 && strcmp(p->aAttach[i-1].zUuid, zUuid)>=0 ){ |
| 215 | goto manifest_syntax_error; |
| 216 | } |
| 217 | break; |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | ** C <comment> |
| @@ -247,33 +233,10 @@ | |
| 247 | if( p->rDate!=0.0 ) goto manifest_syntax_error; |
| 248 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 249 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 250 | zDate = blob_terminate(&a1); |
| 251 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 252 | break; |
| 253 | } |
| 254 | |
| 255 | /* |
| 256 | ** E <mode> |
| 257 | ** |
| 258 | ** Access mode. <mode> can be one of "read", "append", |
| 259 | ** or "write". |
| 260 | */ |
| 261 | case 'E': { |
| 262 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 263 | if( p->mode!=0 ) goto manifest_syntax_error; |
| 264 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 265 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 266 | if( blob_eq(&a1, "write") ){ |
| 267 | p->mode = CFMODE_WRITE; |
| 268 | }else if( blob_eq(&a1, "append") ){ |
| 269 | p->mode = CFMODE_APPEND; |
| 270 | }else if( blob_eq(&a1, "read") ){ |
| 271 | p->mode = CFMODE_READ; |
| 272 | }else{ |
| 273 | goto manifest_syntax_error; |
| 274 | } |
| 275 | break; |
| 276 | } |
| 277 | |
| 278 | /* |
| 279 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| @@ -608,72 +571,74 @@ | |
| 608 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 609 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 610 | if( p->rDate==0.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->nAttach>0 ) goto manifest_syntax_error; |
| 614 | if( p->zWiki ) goto manifest_syntax_error; |
| 615 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 616 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 617 | p->type = CFTYPE_MANIFEST; |
| 618 | }else if( p->nCChild>0 ){ |
| 619 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| 620 | if( p->zComment!=0 ) goto manifest_syntax_error; |
| 621 | if( p->zUser!=0 ) goto manifest_syntax_error; |
| 622 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 623 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 624 | if( p->zRepoCksum!=0 ) goto manifest_syntax_error; |
| 625 | if( p->nField>0 ) goto manifest_syntax_error; |
| 626 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 627 | if( p->nAttach>0 ) goto manifest_syntax_error; |
| 628 | if( p->zWiki ) goto manifest_syntax_error; |
| 629 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 630 | if( !seenZ ) goto manifest_syntax_error; |
| 631 | p->type = CFTYPE_CLUSTER; |
| 632 | }else if( p->nField>0 ){ |
| 633 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 634 | if( p->zRepoCksum!=0 ) goto manifest_syntax_error; |
| 635 | if( p->zWiki ) goto manifest_syntax_error; |
| 636 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 637 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 638 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 639 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 640 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 641 | if( !seenZ ) goto manifest_syntax_error; |
| 642 | p->type = CFTYPE_TICKET; |
| 643 | }else if( p->zWiki!=0 ){ |
| 644 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 645 | if( p->zRepoCksum!=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( !seenZ ) goto manifest_syntax_error; |
| 651 | p->type = CFTYPE_WIKI; |
| 652 | }else if( p->nTag>0 ){ |
| 653 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 654 | if( p->zRepoCksum!=0 ) goto manifest_syntax_error; |
| 655 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 656 | if( p->nAttach>0 ) goto manifest_syntax_error; |
| 657 | if( p->nField>0 ) goto manifest_syntax_error; |
| 658 | if( p->zWiki ) goto manifest_syntax_error; |
| 659 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 660 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 661 | if( !seenZ ) goto manifest_syntax_error; |
| 662 | p->type = CFTYPE_CONTROL; |
| 663 | }else{ |
| 664 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 665 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 666 | if( p->nField>0 ) goto manifest_syntax_error; |
| 667 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 668 | if( p->nAttach>0 ) goto manifest_syntax_error; |
| 669 | if( p->zWiki ) goto manifest_syntax_error; |
| 670 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 671 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 672 | p->type = CFTYPE_MANIFEST; |
| 673 | } |
| 674 | |
| 675 | md5sum_init(); |
| 676 | return 1; |
| 677 | |
| 678 | manifest_syntax_error: |
| 679 | /*fprintf(stderr, "Manifest error on line %i\n", lineNo);fflush(stderr);*/ |
| 680 |
| --- src/manifest.c | |
| +++ src/manifest.c | |
| @@ -37,67 +37,56 @@ | |
| 37 | #define CFTYPE_MANIFEST 1 |
| 38 | #define CFTYPE_CLUSTER 2 |
| 39 | #define CFTYPE_CONTROL 3 |
| 40 | #define CFTYPE_WIKI 4 |
| 41 | #define CFTYPE_TICKET 5 |
| 42 | #define CFTYPE_ATTACHMENT 6 |
| 43 | |
| 44 | /* |
| 45 | ** A parsed manifest or cluster. |
| 46 | */ |
| 47 | struct Manifest { |
| 48 | Blob content; /* The original content blob */ |
| 49 | int type; /* Type of artifact. One of CFTYPE_xxxxx */ |
| 50 | char *zComment; /* Decoded comment. The C card. */ |
| 51 | double rDate; /* Date and time from D card. 0.0 if no D card. */ |
| 52 | char *zUser; /* Name of the user from the U card. */ |
| 53 | char *zRepoCksum; /* MD5 checksum of the baseline content. R card. */ |
| 54 | char *zWiki; /* Text of the wiki page. W card. */ |
| 55 | char *zWikiTitle; /* Name of the wiki page. L card. */ |
| 56 | char *zTicketUuid; /* UUID for a ticket. K card. */ |
| 57 | char *zAttachName; /* Filename of an attachment. A card. */ |
| 58 | char *zAttachSrc; /* UUID of document being attached. A card. */ |
| 59 | char *zAttachTarget; /* Ticket or wiki that attachment applies to. A card */ |
| 60 | int nFile; /* Number of F cards */ |
| 61 | int nFileAlloc; /* Slots allocated in aFile[] */ |
| 62 | struct { |
| 63 | char *zName; /* Name of a file */ |
| 64 | char *zUuid; /* UUID of the file */ |
| 65 | char *zPerm; /* File permissions */ |
| 66 | char *zPrior; /* Prior name if the name was changed */ |
| 67 | int iRename; /* index of renamed name in prior/next manifest */ |
| 68 | } *aFile; /* One entry for each F card */ |
| 69 | int nParent; /* Number of parents. */ |
| 70 | int nParentAlloc; /* Slots allocated in azParent[] */ |
| 71 | char **azParent; /* UUIDs of parents. One for each P card argument */ |
| 72 | int nCChild; /* Number of cluster children */ |
| 73 | int nCChildAlloc; /* Number of closts allocated in azCChild[] */ |
| 74 | char **azCChild; /* UUIDs of referenced objects in a cluster. M cards */ |
| 75 | int nTag; /* Number of T Cards */ |
| 76 | int nTagAlloc; /* Slots allocated in aTag[] */ |
| 77 | struct { |
| 78 | char *zName; /* Name of the tag */ |
| 79 | char *zUuid; /* UUID that the tag is applied to */ |
| 80 | char *zValue; /* Value if the tag is really a property */ |
| 81 | } *aTag; /* One for each T card */ |
| 82 | int nField; /* Number of J cards */ |
| 83 | int nFieldAlloc; /* Slots allocated in aField[] */ |
| 84 | struct { |
| 85 | char *zName; /* Key or field name */ |
| 86 | char *zValue; /* Value of the field */ |
| 87 | } *aField; /* One for each J card */ |
| 88 | }; |
| 89 | #endif |
| 90 | |
| 91 | |
| 92 | /* |
| @@ -108,11 +97,10 @@ | |
| 97 | free(p->aFile); |
| 98 | free(p->azParent); |
| 99 | free(p->azCChild); |
| 100 | free(p->aTag); |
| 101 | free(p->aField); |
| 102 | memset(p, 0, sizeof(*p)); |
| 103 | } |
| 104 | |
| 105 | /* |
| 106 | ** Parse a blob into a Manifest object. The Manifest object |
| @@ -178,44 +166,42 @@ | |
| 166 | cPrevType = z[0]; |
| 167 | seenHeader = 1; |
| 168 | if( blob_token(&line, &token)!=1 ) goto manifest_syntax_error; |
| 169 | switch( z[0] ){ |
| 170 | /* |
| 171 | ** A (+|-)<filename> target source |
| 172 | ** |
| 173 | ** Identifies an attachment to either a wiki page or a ticket. |
| 174 | ** <uuid> is the artifact that is the attachment. |
| 175 | */ |
| 176 | case 'A': { |
| 177 | char *zName, *zTarget, *zSrc; |
| 178 | md5sum_step_text(blob_buffer(&line), blob_size(&line)); |
| 179 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 180 | if( blob_token(&line, &a2)==0 ) goto manifest_syntax_error; |
| 181 | if( blob_token(&line, &a3)==0 ) goto manifest_syntax_error; |
| 182 | if( p->zAttachName!=0 ) goto manifest_syntax_error; |
| 183 | zName = blob_terminate(&a1); |
| 184 | zTarget = blob_terminate(&a2); |
| 185 | zSrc = blob_terminate(&a3); |
| 186 | defossilize(zName); |
| 187 | if( zName[0]!='+' && zName[0]!='-' ){ |
| 188 | goto manifest_syntax_error; |
| 189 | } |
| 190 | if( !file_is_simple_pathname(&zName[1]) ){ |
| 191 | goto manifest_syntax_error; |
| 192 | } |
| 193 | defossilize(zTarget); |
| 194 | if( (blob_size(&a2)!=UUID_SIZE || !validate16(zTarget, UUID_SIZE)) |
| 195 | && !wiki_name_is_wellformed((const unsigned char *)zTarget) ){ |
| 196 | goto manifest_syntax_error; |
| 197 | } |
| 198 | if( blob_size(&a3)!=UUID_SIZE ) goto manifest_syntax_error; |
| 199 | if( !validate16(zSrc, UUID_SIZE) ) goto manifest_syntax_error; |
| 200 | p->zAttachName = zName; |
| 201 | p->zAttachSrc = zSrc; |
| 202 | p->zAttachTarget = zTarget; |
| 203 | break; |
| 204 | } |
| 205 | |
| 206 | /* |
| 207 | ** C <comment> |
| @@ -247,33 +233,10 @@ | |
| 233 | if( p->rDate!=0.0 ) goto manifest_syntax_error; |
| 234 | if( blob_token(&line, &a1)==0 ) goto manifest_syntax_error; |
| 235 | if( blob_token(&line, &a2)!=0 ) goto manifest_syntax_error; |
| 236 | zDate = blob_terminate(&a1); |
| 237 | p->rDate = db_double(0.0, "SELECT julianday(%Q)", zDate); |
| 238 | break; |
| 239 | } |
| 240 | |
| 241 | /* |
| 242 | ** F <filename> <uuid> ?<permissions>? ?<old-name>? |
| @@ -608,72 +571,74 @@ | |
| 571 | if( p->nFile>0 || p->zRepoCksum!=0 ){ |
| 572 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 573 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 574 | if( p->nField>0 ) goto manifest_syntax_error; |
| 575 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 576 | if( p->zWiki ) goto manifest_syntax_error; |
| 577 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 578 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 579 | if( p->zAttachName ) goto manifest_syntax_error; |
| 580 | p->type = CFTYPE_MANIFEST; |
| 581 | }else if( p->nCChild>0 ){ |
| 582 | if( p->rDate>0.0 ) goto manifest_syntax_error; |
| 583 | if( p->zComment!=0 ) goto manifest_syntax_error; |
| 584 | if( p->zUser!=0 ) goto manifest_syntax_error; |
| 585 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 586 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 587 | if( p->nField>0 ) goto manifest_syntax_error; |
| 588 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 589 | if( p->zWiki ) goto manifest_syntax_error; |
| 590 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 591 | if( p->zAttachName ) goto manifest_syntax_error; |
| 592 | if( !seenZ ) goto manifest_syntax_error; |
| 593 | p->type = CFTYPE_CLUSTER; |
| 594 | }else if( p->nField>0 ){ |
| 595 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 596 | if( p->zWiki ) goto manifest_syntax_error; |
| 597 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 598 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 599 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 600 | if( p->zTicketUuid==0 ) goto manifest_syntax_error; |
| 601 | if( p->zUser==0 ) goto manifest_syntax_error; |
| 602 | if( p->zAttachName ) goto manifest_syntax_error; |
| 603 | if( !seenZ ) goto manifest_syntax_error; |
| 604 | p->type = CFTYPE_TICKET; |
| 605 | }else if( p->zWiki!=0 ){ |
| 606 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 607 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 608 | if( p->nTag>0 ) goto manifest_syntax_error; |
| 609 | if( p->zTicketUuid!=0 ) goto manifest_syntax_error; |
| 610 | if( p->zWikiTitle==0 ) goto manifest_syntax_error; |
| 611 | if( p->zAttachName ) goto manifest_syntax_error; |
| 612 | if( !seenZ ) goto manifest_syntax_error; |
| 613 | p->type = CFTYPE_WIKI; |
| 614 | }else if( p->nTag>0 ){ |
| 615 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 616 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 617 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 618 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 619 | if( p->zAttachName ) goto manifest_syntax_error; |
| 620 | if( !seenZ ) goto manifest_syntax_error; |
| 621 | p->type = CFTYPE_CONTROL; |
| 622 | }else if( p->zAttachName ){ |
| 623 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 624 | if( p->rDate==0.0 ) goto manifest_syntax_error; |
| 625 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 626 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 627 | p->type = CFTYPE_ATTACHMENT; |
| 628 | }else{ |
| 629 | if( p->nCChild>0 ) goto manifest_syntax_error; |
| 630 | if( p->rDate<=0.0 ) goto manifest_syntax_error; |
| 631 | if( p->nParent>0 ) goto manifest_syntax_error; |
| 632 | if( p->nField>0 ) goto manifest_syntax_error; |
| 633 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 634 | if( p->zWiki ) goto manifest_syntax_error; |
| 635 | if( p->zWikiTitle ) goto manifest_syntax_error; |
| 636 | if( p->zTicketUuid ) goto manifest_syntax_error; |
| 637 | if( p->zAttachName ) goto manifest_syntax_error; |
| 638 | p->type = CFTYPE_MANIFEST; |
| 639 | } |
| 640 | md5sum_init(); |
| 641 | return 1; |
| 642 | |
| 643 | manifest_syntax_error: |
| 644 | /*fprintf(stderr, "Manifest error on line %i\n", lineNo);fflush(stderr);*/ |
| 645 |
+237
-85
| --- www/fileformat.wiki | ||
| +++ www/fileformat.wiki | ||
| @@ -1,26 +1,23 @@ | ||
| 1 | 1 | <title>Fossil File Formats</title> |
| 2 | 2 | <h1 align="center"> |
| 3 | 3 | Fossil File Formats |
| 4 | 4 | </h1> |
| 5 | 5 | |
| 6 | -<p>The global state of a fossil repository is kept simple so that it can | |
| 6 | +The global state of a fossil repository is kept simple so that it can | |
| 7 | 7 | endure in useful form for decades or centuries. |
| 8 | 8 | A fossil repository is intended to be readable, |
| 9 | -searchable, and extensible by people not yet born.</p> | |
| 9 | +searchable, and extensible by people not yet born. | |
| 10 | 10 | |
| 11 | -<p> | |
| 12 | 11 | The global state of a fossil repository is an unordered |
| 13 | 12 | set of <i>artifacts</i>. |
| 14 | 13 | An artifact might be a source code file, the text of a wiki page, |
| 15 | 14 | part of a trouble ticket, or one of several special control artifacts |
| 16 | 15 | used to show the relationships between other artifacts within the |
| 17 | 16 | project. Each artifact is normally represented on disk as a separate |
| 18 | 17 | file. Artifacts can be text or binary. |
| 19 | -</p> | |
| 20 | 18 | |
| 21 | -<p> | |
| 22 | 19 | In addition to the global state, |
| 23 | 20 | each fossil repository also contains local state. |
| 24 | 21 | The local state consists of web-page formatting |
| 25 | 22 | preferences, authorized users, ticket display and reporting formats, |
| 26 | 23 | and so forth. The global state is shared in common among all |
| @@ -29,82 +26,73 @@ | ||
| 29 | 26 | The local state is not versioned and is not synchronized |
| 30 | 27 | with the global state. |
| 31 | 28 | The local state is not composed of artifacts and is not intended to be enduring. |
| 32 | 29 | This document is concerned with global state only. Local state is only |
| 33 | 30 | mentioned here in order to distinguish it from global state. |
| 34 | -</p> | |
| 35 | 31 | |
| 36 | -<p> | |
| 37 | 32 | Each artifact in the repository is named by its SHA1 hash. |
| 38 | 33 | No prefixes or meta information is added to a artifact before |
| 39 | 34 | its hash is computed. The name of a artifact in the repository |
| 40 | 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 41 | 36 | on the file as it exists in your source tree.</p> |
| 42 | 37 | |
| 43 | -<p> | |
| 44 | 38 | Some artifacts have a particular format which gives them special |
| 45 | -meaning to fossil. Fossil recognizes:</p> | |
| 39 | +meaning to fossil. Fossil recognizes: | |
| 46 | 40 | |
| 47 | 41 | <ul> |
| 48 | -<li> Manifests </li> | |
| 49 | -<li> Clusters </li> | |
| 50 | -<li> Control Artifacts </li> | |
| 51 | -<li> Wiki Pages </li> | |
| 52 | -<li> Ticket Changes </li> | |
| 42 | +<li> [#manifest | Manifests] </li> | |
| 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> [#artifact | Artifacts] </li> | |
| 53 | 48 | </ul> |
| 54 | 49 | |
| 55 | -<p>These five artifact types are described in the sequel.</p> | |
| 50 | +These five artifact types are described in the sequel. | |
| 56 | 51 | |
| 57 | -<p>In the current implementation (as of 2009-01-25) the artifacts that | |
| 52 | +In the current implementation (as of 2009-01-25) the artifacts that | |
| 58 | 53 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 59 | 54 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 60 | 55 | is an implementation detail and might change in a future release. For |
| 61 | 56 | the purpose of this article "file format" means the format of the artifacts, |
| 62 | 57 | not how the artifacts are stored on disk. It is the artifact format that |
| 63 | 58 | is intended to be enduring. The specifics of how artifacts are stored on |
| 64 | 59 | disk, though stable, is not intended to live as long as the |
| 65 | -artifact format.</p> | |
| 60 | +artifact format. | |
| 66 | 61 | |
| 62 | +<a name="manifest"></a> | |
| 67 | 63 | <h2>1.0 The Manifest</h2> |
| 68 | 64 | |
| 69 | -<p>A manifest defines a check-in or version of the project | |
| 65 | +A manifest defines a check-in or version of the project | |
| 70 | 66 | source tree. The manifest contains a list of artifacts for |
| 71 | 67 | each file in the project and the corresponding filenames, as |
| 72 | 68 | well as information such as parent check-ins, the name of the |
| 73 | 69 | programmer who created the check-in, the date and time when |
| 74 | 70 | the check-in was created, and any check-in comments associated |
| 75 | -with the check-in.</p> | |
| 71 | +with the check-in. | |
| 76 | 72 | |
| 77 | -<p> | |
| 78 | 73 | Any artifact in the repository that follows the syntactic rules |
| 79 | 74 | of a manifest is a manifest. Note that a manifest can |
| 80 | 75 | be both a real manifest and also a content file, though this |
| 81 | 76 | is rare. |
| 82 | -</p> | |
| 83 | 77 | |
| 84 | -<p> | |
| 85 | 78 | A manifest is a text file. Newline characters |
| 86 | 79 | (ASCII 0x0a) separate the file into "cards". |
| 87 | 80 | Each card begins with a single |
| 88 | 81 | character "card type". Zero or more arguments may follow |
| 89 | 82 | the card type. All arguments are separated from each other |
| 90 | 83 | and from the card-type character by a single space |
| 91 | 84 | character. There is no surplus white space between arguments |
| 92 | 85 | and no leading or trailing whitespace except for the newline |
| 93 | 86 | character that acts as the card separator. |
| 94 | -</p> | |
| 95 | 87 | |
| 96 | -<p> | |
| 97 | 88 | All cards of the manifest occur in strict sorted lexicographical order. |
| 98 | 89 | No card may be duplicated. |
| 99 | 90 | The entire manifest may be PGP clear-signed, but otherwise it |
| 100 | 91 | may contain no additional text or data beyond what is described here. |
| 101 | -</p> | |
| 102 | 92 | |
| 103 | -<p> | |
| 104 | 93 | Allowed cards in the manifest are as follows: |
| 105 | -</p> | |
| 106 | 94 | |
| 107 | 95 | <blockquote> |
| 108 | 96 | <b>C</b> <i>checkin-comment</i><br> |
| 109 | 97 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 110 | 98 | <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> |
| @@ -113,11 +101,10 @@ | ||
| 113 | 101 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> |
| 114 | 102 | <b>U</b> <i>user-login</i><br> |
| 115 | 103 | <b>Z</b> <i>manifest-checksum</i> |
| 116 | 104 | </blockquote> |
| 117 | 105 | |
| 118 | -<p> | |
| 119 | 106 | A manifest must have exactly one C-card. The sole argument to |
| 120 | 107 | the C-card is a check-in comment that describes the check-in that |
| 121 | 108 | the manifest defines. The check-in comment is text. The following |
| 122 | 109 | escape sequences are applied to the text: |
| 123 | 110 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| @@ -124,24 +111,20 @@ | ||
| 124 | 111 | newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash |
| 125 | 112 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 126 | 113 | space and newline, no other whitespace characters are allowed in |
| 127 | 114 | the check-in comment. Nor are any unprintable characters allowed |
| 128 | 115 | in the comment. |
| 129 | -</p> | |
| 130 | 116 | |
| 131 | -<p> | |
| 132 | 117 | A manifest must have exactly one D-card. The sole argument to |
| 133 | 118 | the D-card is a date-time stamp in the ISO8601 format. The |
| 134 | 119 | date and time should be in coordinated universal time (UTC). |
| 135 | 120 | The format is: |
| 136 | -</p> | |
| 137 | 121 | |
| 138 | 122 | <blockquote> |
| 139 | 123 | <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> |
| 140 | 124 | </blockquote> |
| 141 | 125 | |
| 142 | -<p> | |
| 143 | 126 | A manifest has zero or more F-cards. Each F-card defines a file |
| 144 | 127 | (other than the manifest itself) which is part of the check-in that |
| 145 | 128 | the manifest defines. There are two, three, or four arguments. |
| 146 | 129 | The first argument |
| 147 | 130 | is the pathname of the file in the check-in relative to the root |
| @@ -157,13 +140,11 @@ | ||
| 157 | 140 | always readable and writable. This can be expressed by "w" permission |
| 158 | 141 | if desired but is optional. |
| 159 | 142 | The optional 4th argument is the name of the same file as it existed in |
| 160 | 143 | the parent check-in. If the name of the file is unchanged from its |
| 161 | 144 | parent, then the 4th argument is omitted. |
| 162 | -</p> | |
| 163 | 145 | |
| 164 | -<p> | |
| 165 | 146 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 166 | 147 | The P-card has a varying number of arguments that |
| 167 | 148 | defines other manifests from which the current manifest |
| 168 | 149 | is derived. Each argument is an 40-character lowercase |
| 169 | 150 | hexadecimal SHA1 of the predecessor manifest. All arguments |
| @@ -171,13 +152,11 @@ | ||
| 171 | 152 | The first predecessor is the direct ancestor of the manifest. |
| 172 | 153 | Other arguments define manifests with which the first was |
| 173 | 154 | merged to yield the current manifest. Most manifests have |
| 174 | 155 | a P-card with a single argument. The first manifest in the |
| 175 | 156 | project has no ancestors and thus has no P-card. |
| 176 | -</p> | |
| 177 | 157 | |
| 178 | -<p> | |
| 179 | 158 | A manifest may optionally have a single R-card. The R-card has |
| 180 | 159 | a single argument which is the MD5 checksum of all files in |
| 181 | 160 | the check-in except the manifest itself. The checksum is expressed |
| 182 | 161 | as 32-characters of lowercase hexadecimal. The checksum is |
| 183 | 162 | computed as follows: For each file in the check-in (except for |
| @@ -185,13 +164,11 @@ | ||
| 185 | 164 | take the pathname of the file relative to the root of the |
| 186 | 165 | repository, append a single space (ASCII 0x20), the |
| 187 | 166 | size of the file in ASCII decimal, a single newline |
| 188 | 167 | character (ASCII 0x0A), and the complete text of the file. |
| 189 | 168 | Compute the MD5 checksum of the the result. |
| 190 | -</p> | |
| 191 | 169 | |
| 192 | -<p> | |
| 193 | 170 | A manifest might contain one or more T-cards used to set tags or |
| 194 | 171 | properties on the check-in. The format of the T-card is the same as |
| 195 | 172 | described in <i>Control Artifacts</i> section below, except that the |
| 196 | 173 | second argument is the single characcter "<b>*</b>" instead of an |
| 197 | 174 | artifact ID. The <b>*</b> in place of the artifact ID indicates that |
| @@ -199,42 +176,35 @@ | ||
| 199 | 176 | possible to encode the current artifact ID as part of an artifact, |
| 200 | 177 | since the act of inserting the artifact ID would change the artifact ID, |
| 201 | 178 | hence a <b>*</b> is used to represent "self". T-cards are typically |
| 202 | 179 | added to manifests in order to set the <b>branch</b> property and a |
| 203 | 180 | symbolic name when the check-in is intended to start a new branch. |
| 204 | -</p> | |
| 205 | 181 | |
| 206 | -<p> | |
| 207 | 182 | Each manifest has a single U-card. The argument to the U-card is |
| 208 | 183 | the login of the user who created the manifest. The login name |
| 209 | 184 | is encoded using the same character escapes as is used for the |
| 210 | 185 | check-in comment argument to the C-card. |
| 211 | -</p> | |
| 212 | 186 | |
| 213 | -<p> | |
| 214 | 187 | A manifest has an option Z-card as its last line. The argument |
| 215 | 188 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 216 | 189 | of all prior lines of the manifest up to and including the newline |
| 217 | 190 | character that immediately precedes the "Z". The Z-card is just |
| 218 | 191 | a sanity check to prove that the manifest is well-formed and |
| 219 | 192 | consistent. |
| 220 | -</p> | |
| 221 | 193 | |
| 222 | -<p>A sample manifest from Fossil itself can be seen | |
| 194 | +A sample manifest from Fossil itself can be seen | |
| 223 | 195 | [/artifact/28987096ac | here]. |
| 224 | 196 | |
| 197 | +<a name="cluster"></a> | |
| 225 | 198 | <h2>2.0 Clusters</h2> |
| 226 | 199 | |
| 227 | -<p> | |
| 228 | 200 | A cluster is a artifact that declares the existence of other artifacts. |
| 229 | 201 | Clusters are used during repository synchronization to help |
| 230 | 202 | reduce network traffic. As such, clusters are an optimization and |
| 231 | 203 | may be removed from a repository without loss or damage to the |
| 232 | 204 | underlying project code. |
| 233 | -</p> | |
| 234 | 205 | |
| 235 | -<p> | |
| 236 | 206 | Clusters follow a syntax that is very similar to manifests. |
| 237 | 207 | A Cluster is a line-oriented text file. Newline characters |
| 238 | 208 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 239 | 209 | character "card type". Zero or more arguments may follow |
| 240 | 210 | the card type. All arguments are separated from each other |
| @@ -245,67 +215,58 @@ | ||
| 245 | 215 | All cards of a cluster occur in strict sorted lexicographical order. |
| 246 | 216 | No card may be duplicated. |
| 247 | 217 | The cluster may not contain additional text or data beyond |
| 248 | 218 | what is described here. |
| 249 | 219 | Unlike manifests, clusters are never PGP signed. |
| 250 | -</p> | |
| 251 | 220 | |
| 252 | -<p> | |
| 253 | 221 | Allowed cards in the cluster are as follows: |
| 254 | -</p> | |
| 255 | 222 | |
| 256 | 223 | <blockquote> |
| 257 | 224 | <b>M</b> <i>artifact-id</i><br /> |
| 258 | 225 | <b>Z</b> <i>checksum</i> |
| 259 | 226 | </blockquote> |
| 260 | 227 | |
| 261 | -<p> | |
| 262 | 228 | A cluster contains one or more "M" cards followed by a single "Z" |
| 263 | 229 | line. Each M card has a single argument which is the artifact ID of |
| 264 | 230 | another artifact in the repository. The Z card work exactly like |
| 265 | 231 | the Z card of a manifest. The argument to the Z card is the |
| 266 | 232 | lower-case hexadecimal representation of the MD5 checksum of all |
| 267 | 233 | prior cards in the cluster. Note that the Z card is required |
| 268 | 234 | on a cluster. |
| 269 | -</p> | |
| 270 | 235 | |
| 271 | -<p>An example cluster from Fossil can be seen | |
| 272 | -[/artifact/d03dbdd73a2a8 | here].</p> | |
| 236 | +An example cluster from Fossil can be seen | |
| 237 | +[/artifact/d03dbdd73a2a8 | here]. | |
| 273 | 238 | |
| 274 | - | |
| 239 | +<a name="ctrl"></a> | |
| 275 | 240 | <h2>3.0 Control Artifacts</h2> |
| 276 | 241 | |
| 277 | -<p> | |
| 278 | 242 | Control artifacts are used to assign properties to other artifacts |
| 279 | 243 | within the repository. The basic format of a control artifact is |
| 280 | 244 | the same as a manifest or cluster. A control artifact is a text |
| 281 | 245 | files divided into cards by newline characters. Each card has a |
| 282 | 246 | single-character card type followed by arguments. Spaces separate |
| 283 | 247 | the card type and the arguments. No surplus whitespace is allowed. |
| 284 | 248 | All cards must occur in strict lexigraphical order. |
| 285 | -</p> | |
| 286 | 249 | |
| 287 | -<p> | |
| 288 | 250 | Allowed cards in a control artifact are as follows: |
| 289 | -</p> | |
| 290 | 251 | |
| 291 | 252 | <blockquote> |
| 292 | 253 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 293 | 254 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name artifact-id ?value?</i><br /> |
| 255 | +<b>U</b> <i>user-name</i><br /> | |
| 294 | 256 | <b>Z</b> <i>checksum</i><br /> |
| 295 | 257 | </blockquote> |
| 296 | 258 | |
| 297 | -<p> | |
| 298 | 259 | A control artifact must have one D card and one Z card and |
| 299 | 260 | one or more T cards. No other cards or other text is |
| 300 | 261 | allowed in a control artifact. Control artifacts might be PGP |
| 301 | -clearsigned.</p> | |
| 262 | +clearsigned. | |
| 302 | 263 | |
| 303 | -<p>The D card and the Z card of a control artifact are the same | |
| 304 | -as in a manifest.</p> | |
| 264 | +The D card and the Z card of a control artifact are the same | |
| 265 | +as in a manifest. | |
| 305 | 266 | |
| 306 | -<p>The T card represents a "tag" or property that is applied to | |
| 267 | +The T card represents a "tag" or property that is applied to | |
| 307 | 268 | some other artifact. The T card has two or three values. The |
| 308 | 269 | second argument is the 40 character lowercase artifact ID of the artifact |
| 309 | 270 | to which the tag is to be applied. The |
| 310 | 271 | first value is the tag name. The first character of the tag |
| 311 | 272 | is either "+", "-", or "*". A "+" means the tag should be added |
| @@ -313,28 +274,37 @@ | ||
| 313 | 274 | The "*" character means the tag should be added to the artifact |
| 314 | 275 | and all direct descendants (but not branches) of the artifact down |
| 315 | 276 | to but not including the first descendant that contains a |
| 316 | 277 | more recent "-" tag with the same name. |
| 317 | 278 | The optional third argument is the value of the tag. A tag |
| 318 | -without a value is a boolean.</p> | |
| 279 | +without a value is a boolean. | |
| 319 | 280 | |
| 320 | -<p>When two or more tags with the same name are applied to the | |
| 281 | +When two or more tags with the same name are applied to the | |
| 321 | 282 | same artifact, the tag with the latest (most recent) date is |
| 322 | -used.</p> | |
| 283 | +used. | |
| 323 | 284 | |
| 324 | -<p>Some tags have special meaning. The "comment" tag when applied | |
| 285 | +Some tags have special meaning. The "comment" tag when applied | |
| 325 | 286 | to a check-in will override the check-in comment of that check-in |
| 326 | -for display purposes.</p> | |
| 287 | +for display purposes. The "user" tag overrides the name of the | |
| 288 | +check-in user. The "date" tag overrides the check-in date. | |
| 289 | +The "branch" tag sets the name of the branch that at check-in | |
| 290 | +belongs to. Symbolic tags begin with the "sym-" prefix. | |
| 291 | + | |
| 292 | +The U card is the name of the user that created the control | |
| 293 | +artifact. The Z card is the usual artifact checksum. | |
| 294 | + | |
| 295 | +An example control artifacts can be seen [/info/9d302ccda8 | here]. | |
| 296 | + | |
| 327 | 297 | |
| 328 | 298 | <a name="wikichng"></a> |
| 329 | 299 | <h2>4.0 Wiki Pages</h2> |
| 330 | 300 | |
| 331 | -<p>A wiki page is an artifact with a format similar to manifests, | |
| 301 | +A wiki page is an artifact with a format similar to manifests, | |
| 332 | 302 | clusters, and control artifacts. The artifact is divided into |
| 333 | 303 | cards by newline characters. The format of each card is as in |
| 334 | 304 | manifests, clusters, and control artifacts. Wiki artifacts accept |
| 335 | -the following card types:</p> | |
| 305 | +the following card types: | |
| 336 | 306 | |
| 337 | 307 | <blockquote> |
| 338 | 308 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 339 | 309 | <b>L</b> <i>wiki-title</i><br /> |
| 340 | 310 | <b>P</b> <i>parent-artifact-id</i>+<br /> |
| @@ -341,63 +311,245 @@ | ||
| 341 | 311 | <b>U</b> <i>user-name</i><br /> |
| 342 | 312 | <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> |
| 343 | 313 | <b>Z</b> <i>checksum</i> |
| 344 | 314 | </blockquote> |
| 345 | 315 | |
| 346 | -<p>The D card is the date and time when the wiki page was edited. | |
| 316 | +The D card is the date and time when the wiki page was edited. | |
| 347 | 317 | The P card specifies the parent wiki pages, if any. The L card |
| 348 | 318 | gives the name of the wiki page. The U card specifies the login |
| 349 | 319 | of the user who made this edit to the wiki page. The Z card is |
| 350 | -the usual checksum over the either artifact.</p> | |
| 320 | +the usual checksum over the either artifact. | |
| 351 | 321 | |
| 352 | -<p>The W card is used to specify the text of the wiki page. The | |
| 322 | +The W card is used to specify the text of the wiki page. The | |
| 353 | 323 | argument to the W card is an integer which is the number of bytes |
| 354 | 324 | of text in the wiki page. That text follows the newline character |
| 355 | 325 | that terminates the W card. The wiki text is always followed by one |
| 356 | -extra newline.</p> | |
| 326 | +extra newline. | |
| 327 | + | |
| 328 | +An example wiki artifact can be seen | |
| 329 | +[/artifact/7b2f5fd0e0 | here]. | |
| 357 | 330 | |
| 358 | 331 | <a name="tktchng"></a> |
| 359 | 332 | <h2>5.0 Ticket Changes</h2> |
| 360 | 333 | |
| 361 | -<p>A ticket-change artifact represents a change to a trouble ticket. | |
| 362 | -The following cards are allowed on a ticket change artifact:</p> | |
| 334 | +A ticket-change artifact represents a change to a trouble ticket. | |
| 335 | +The following cards are allowed on a ticket change artifact: | |
| 363 | 336 | |
| 364 | 337 | <blockquote> |
| 365 | 338 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 366 | 339 | <b>J</b> ?<b>+</b>?<i>name</i> ?<i>value</i>?<br /> |
| 367 | 340 | <b>K</b> <i>ticket-id</i><br /> |
| 368 | 341 | <b>U</b> <i>user-name</i><br /> |
| 369 | 342 | <b>Z</b> <i>checksum</i> |
| 370 | 343 | </blockquote> |
| 371 | 344 | |
| 372 | -<p> | |
| 373 | 345 | The D card is the usual date and time stamp and represents the point |
| 374 | 346 | in time when the change was entered. The U card is the login of the |
| 375 | 347 | programmer who entered this change. The Z card is the checksum over |
| 376 | -the entire artifact.</p> | |
| 348 | +the entire artifact. | |
| 377 | 349 | |
| 378 | -<p> | |
| 379 | 350 | Every ticket has a unique ID. The ticket to which this change is applied |
| 380 | 351 | is specified by the K card. A ticket exists if it contains one or |
| 381 | 352 | more changes. The first "change" to a ticket is what brings the |
| 382 | -ticket into existence.</p> | |
| 353 | +ticket into existence. | |
| 383 | 354 | |
| 384 | -<p> | |
| 385 | 355 | J cards specify changes to the "value" of "fields" in the ticket. |
| 386 | 356 | If the <i>value</i> parameter of the J card is omitted, then the |
| 387 | 357 | field is set to an empty string. |
| 388 | 358 | Each fossil server has a ticket configuration which specifies the fields its |
| 389 | 359 | understands. The ticket configuration is part of the local state for |
| 390 | 360 | the repository and thus can vary from one repository to another. |
| 391 | 361 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 392 | 362 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 393 | 363 | is not in the local configuration, then that J card |
| 394 | -is simply ignored.</p> | |
| 364 | +is simply ignored. | |
| 395 | 365 | |
| 396 | -<p> | |
| 397 | 366 | The first argument of the J card is the field name. The second |
| 398 | 367 | value is the field value. If the field name begins with "+" then |
| 399 | 368 | the value is appended to the prior value. Otherwise, the value |
| 400 | 369 | on the J card replaces any previous value of the field. |
| 401 | 370 | The field name and value are both encoded using the character |
| 402 | 371 | escapes defined for the C card of a manifest. |
| 403 | -</p> | |
| 372 | + | |
| 373 | +An example ticket-change artifact can be seen | |
| 374 | +[/artifact/91f1ec6af053 | here]. | |
| 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> (<b>+</b>|<b>-</b>)<i>filename target source</i> | |
| 386 | +<b>C</b> <i>comment</i><br> | |
| 387 | +<b>D</b> <i>time-and-date-stamp</i><br /> | |
| 388 | +<b>U</b> <i>user-name</i><br /> | |
| 389 | +<b>Z</b> <i>checksum</i> | |
| 390 | +</blockquote> | |
| 391 | + | |
| 392 | +The A card specifies a filename for the attachment in its first argument. | |
| 393 | +The filename is preceeded by "+" to add the attachment or "-" to | |
| 394 | +remove the attachment. The second argument to the A card is the name | |
| 395 | +of the wiki page or ticket to which the attachment is connected. The | |
| 396 | +third argument is is the 40-character artifact ID of the attachment | |
| 397 | +itself. Every attachment artifact must have exactly one A card. | |
| 398 | + | |
| 399 | +The C card is an optional comment describing what the attachment is about. | |
| 400 | +The C card is optional, but there can only be one. | |
| 401 | + | |
| 402 | +A single D card is required to give the date and time when the attachment | |
| 403 | +was applied. | |
| 404 | + | |
| 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> (<b>+</b>|<b>-</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 | +<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> | |
| 465 | +</tr> | |
| 466 | +<tr> | |
| 467 | +<td><b>J</b> <i>name value</i></td> | |
| 468 | +<td align=center> </td> | |
| 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 | +<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> | |
| 502 | +<tr> | |
| 503 | +<td><b>P</b> <i>uuid ...</i></td> | |
| 504 | +<td align=center><b>X</b></td> | |
| 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> | |
| 519 | +<tr> | |
| 520 | +<td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname uuid value</i></td> | |
| 521 | +<td align=center><b>X</b></td> | |
| 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> | |
| 537 | +<tr> | |
| 538 | +<td><b>W</b> <i>size</i></td> | |
| 539 | +<td align=center> </td> | |
| 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> | |
| 404 | 556 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -1,26 +1,23 @@ | |
| 1 | <title>Fossil File Formats</title> |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | <p>The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born.</p> |
| 10 | |
| 11 | <p> |
| 12 | The global state of a fossil repository is an unordered |
| 13 | set of <i>artifacts</i>. |
| 14 | An artifact might be a source code file, the text of a wiki page, |
| 15 | part of a trouble ticket, or one of several special control artifacts |
| 16 | used to show the relationships between other artifacts within the |
| 17 | project. Each artifact is normally represented on disk as a separate |
| 18 | file. Artifacts can be text or binary. |
| 19 | </p> |
| 20 | |
| 21 | <p> |
| 22 | In addition to the global state, |
| 23 | each fossil repository also contains local state. |
| 24 | The local state consists of web-page formatting |
| 25 | preferences, authorized users, ticket display and reporting formats, |
| 26 | and so forth. The global state is shared in common among all |
| @@ -29,82 +26,73 @@ | |
| 29 | The local state is not versioned and is not synchronized |
| 30 | with the global state. |
| 31 | The local state is not composed of artifacts and is not intended to be enduring. |
| 32 | This document is concerned with global state only. Local state is only |
| 33 | mentioned here in order to distinguish it from global state. |
| 34 | </p> |
| 35 | |
| 36 | <p> |
| 37 | Each artifact in the repository is named by its SHA1 hash. |
| 38 | No prefixes or meta information is added to a artifact before |
| 39 | its hash is computed. The name of a artifact in the repository |
| 40 | is exactly the same SHA1 hash that is computed by sha1sum |
| 41 | on the file as it exists in your source tree.</p> |
| 42 | |
| 43 | <p> |
| 44 | Some artifacts have a particular format which gives them special |
| 45 | meaning to fossil. Fossil recognizes:</p> |
| 46 | |
| 47 | <ul> |
| 48 | <li> Manifests </li> |
| 49 | <li> Clusters </li> |
| 50 | <li> Control Artifacts </li> |
| 51 | <li> Wiki Pages </li> |
| 52 | <li> Ticket Changes </li> |
| 53 | </ul> |
| 54 | |
| 55 | <p>These five artifact types are described in the sequel.</p> |
| 56 | |
| 57 | <p>In the current implementation (as of 2009-01-25) the artifacts that |
| 58 | make up a fossil repository are stored in in as delta- and zlib-compressed |
| 59 | blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This |
| 60 | is an implementation detail and might change in a future release. For |
| 61 | the purpose of this article "file format" means the format of the artifacts, |
| 62 | not how the artifacts are stored on disk. It is the artifact format that |
| 63 | is intended to be enduring. The specifics of how artifacts are stored on |
| 64 | disk, though stable, is not intended to live as long as the |
| 65 | artifact format.</p> |
| 66 | |
| 67 | <h2>1.0 The Manifest</h2> |
| 68 | |
| 69 | <p>A manifest defines a check-in or version of the project |
| 70 | source tree. The manifest contains a list of artifacts for |
| 71 | each file in the project and the corresponding filenames, as |
| 72 | well as information such as parent check-ins, the name of the |
| 73 | programmer who created the check-in, the date and time when |
| 74 | the check-in was created, and any check-in comments associated |
| 75 | with the check-in.</p> |
| 76 | |
| 77 | <p> |
| 78 | Any artifact in the repository that follows the syntactic rules |
| 79 | of a manifest is a manifest. Note that a manifest can |
| 80 | be both a real manifest and also a content file, though this |
| 81 | is rare. |
| 82 | </p> |
| 83 | |
| 84 | <p> |
| 85 | A manifest is a text file. Newline characters |
| 86 | (ASCII 0x0a) separate the file into "cards". |
| 87 | Each card begins with a single |
| 88 | character "card type". Zero or more arguments may follow |
| 89 | the card type. All arguments are separated from each other |
| 90 | and from the card-type character by a single space |
| 91 | character. There is no surplus white space between arguments |
| 92 | and no leading or trailing whitespace except for the newline |
| 93 | character that acts as the card separator. |
| 94 | </p> |
| 95 | |
| 96 | <p> |
| 97 | All cards of the manifest occur in strict sorted lexicographical order. |
| 98 | No card may be duplicated. |
| 99 | The entire manifest may be PGP clear-signed, but otherwise it |
| 100 | may contain no additional text or data beyond what is described here. |
| 101 | </p> |
| 102 | |
| 103 | <p> |
| 104 | Allowed cards in the manifest are as follows: |
| 105 | </p> |
| 106 | |
| 107 | <blockquote> |
| 108 | <b>C</b> <i>checkin-comment</i><br> |
| 109 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 110 | <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> |
| @@ -113,11 +101,10 @@ | |
| 113 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> |
| 114 | <b>U</b> <i>user-login</i><br> |
| 115 | <b>Z</b> <i>manifest-checksum</i> |
| 116 | </blockquote> |
| 117 | |
| 118 | <p> |
| 119 | A manifest must have exactly one C-card. The sole argument to |
| 120 | the C-card is a check-in comment that describes the check-in that |
| 121 | the manifest defines. The check-in comment is text. The following |
| 122 | escape sequences are applied to the text: |
| 123 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| @@ -124,24 +111,20 @@ | |
| 124 | newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash |
| 125 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 126 | space and newline, no other whitespace characters are allowed in |
| 127 | the check-in comment. Nor are any unprintable characters allowed |
| 128 | in the comment. |
| 129 | </p> |
| 130 | |
| 131 | <p> |
| 132 | A manifest must have exactly one D-card. The sole argument to |
| 133 | the D-card is a date-time stamp in the ISO8601 format. The |
| 134 | date and time should be in coordinated universal time (UTC). |
| 135 | The format is: |
| 136 | </p> |
| 137 | |
| 138 | <blockquote> |
| 139 | <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> |
| 140 | </blockquote> |
| 141 | |
| 142 | <p> |
| 143 | A manifest has zero or more F-cards. Each F-card defines a file |
| 144 | (other than the manifest itself) which is part of the check-in that |
| 145 | the manifest defines. There are two, three, or four arguments. |
| 146 | The first argument |
| 147 | is the pathname of the file in the check-in relative to the root |
| @@ -157,13 +140,11 @@ | |
| 157 | always readable and writable. This can be expressed by "w" permission |
| 158 | if desired but is optional. |
| 159 | The optional 4th argument is the name of the same file as it existed in |
| 160 | the parent check-in. If the name of the file is unchanged from its |
| 161 | parent, then the 4th argument is omitted. |
| 162 | </p> |
| 163 | |
| 164 | <p> |
| 165 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 166 | The P-card has a varying number of arguments that |
| 167 | defines other manifests from which the current manifest |
| 168 | is derived. Each argument is an 40-character lowercase |
| 169 | hexadecimal SHA1 of the predecessor manifest. All arguments |
| @@ -171,13 +152,11 @@ | |
| 171 | The first predecessor is the direct ancestor of the manifest. |
| 172 | Other arguments define manifests with which the first was |
| 173 | merged to yield the current manifest. Most manifests have |
| 174 | a P-card with a single argument. The first manifest in the |
| 175 | project has no ancestors and thus has no P-card. |
| 176 | </p> |
| 177 | |
| 178 | <p> |
| 179 | A manifest may optionally have a single R-card. The R-card has |
| 180 | a single argument which is the MD5 checksum of all files in |
| 181 | the check-in except the manifest itself. The checksum is expressed |
| 182 | as 32-characters of lowercase hexadecimal. The checksum is |
| 183 | computed as follows: For each file in the check-in (except for |
| @@ -185,13 +164,11 @@ | |
| 185 | take the pathname of the file relative to the root of the |
| 186 | repository, append a single space (ASCII 0x20), the |
| 187 | size of the file in ASCII decimal, a single newline |
| 188 | character (ASCII 0x0A), and the complete text of the file. |
| 189 | Compute the MD5 checksum of the the result. |
| 190 | </p> |
| 191 | |
| 192 | <p> |
| 193 | A manifest might contain one or more T-cards used to set tags or |
| 194 | properties on the check-in. The format of the T-card is the same as |
| 195 | described in <i>Control Artifacts</i> section below, except that the |
| 196 | second argument is the single characcter "<b>*</b>" instead of an |
| 197 | artifact ID. The <b>*</b> in place of the artifact ID indicates that |
| @@ -199,42 +176,35 @@ | |
| 199 | possible to encode the current artifact ID as part of an artifact, |
| 200 | since the act of inserting the artifact ID would change the artifact ID, |
| 201 | hence a <b>*</b> is used to represent "self". T-cards are typically |
| 202 | added to manifests in order to set the <b>branch</b> property and a |
| 203 | symbolic name when the check-in is intended to start a new branch. |
| 204 | </p> |
| 205 | |
| 206 | <p> |
| 207 | Each manifest has a single U-card. The argument to the U-card is |
| 208 | the login of the user who created the manifest. The login name |
| 209 | is encoded using the same character escapes as is used for the |
| 210 | check-in comment argument to the C-card. |
| 211 | </p> |
| 212 | |
| 213 | <p> |
| 214 | A manifest has an option Z-card as its last line. The argument |
| 215 | to the Z-card is a 32-character lowercase hexadecimal MD5 hash |
| 216 | of all prior lines of the manifest up to and including the newline |
| 217 | character that immediately precedes the "Z". The Z-card is just |
| 218 | a sanity check to prove that the manifest is well-formed and |
| 219 | consistent. |
| 220 | </p> |
| 221 | |
| 222 | <p>A sample manifest from Fossil itself can be seen |
| 223 | [/artifact/28987096ac | here]. |
| 224 | |
| 225 | <h2>2.0 Clusters</h2> |
| 226 | |
| 227 | <p> |
| 228 | A cluster is a artifact that declares the existence of other artifacts. |
| 229 | Clusters are used during repository synchronization to help |
| 230 | reduce network traffic. As such, clusters are an optimization and |
| 231 | may be removed from a repository without loss or damage to the |
| 232 | underlying project code. |
| 233 | </p> |
| 234 | |
| 235 | <p> |
| 236 | Clusters follow a syntax that is very similar to manifests. |
| 237 | A Cluster is a line-oriented text file. Newline characters |
| 238 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 239 | character "card type". Zero or more arguments may follow |
| 240 | the card type. All arguments are separated from each other |
| @@ -245,67 +215,58 @@ | |
| 245 | All cards of a cluster occur in strict sorted lexicographical order. |
| 246 | No card may be duplicated. |
| 247 | The cluster may not contain additional text or data beyond |
| 248 | what is described here. |
| 249 | Unlike manifests, clusters are never PGP signed. |
| 250 | </p> |
| 251 | |
| 252 | <p> |
| 253 | Allowed cards in the cluster are as follows: |
| 254 | </p> |
| 255 | |
| 256 | <blockquote> |
| 257 | <b>M</b> <i>artifact-id</i><br /> |
| 258 | <b>Z</b> <i>checksum</i> |
| 259 | </blockquote> |
| 260 | |
| 261 | <p> |
| 262 | A cluster contains one or more "M" cards followed by a single "Z" |
| 263 | line. Each M card has a single argument which is the artifact ID of |
| 264 | another artifact in the repository. The Z card work exactly like |
| 265 | the Z card of a manifest. The argument to the Z card is the |
| 266 | lower-case hexadecimal representation of the MD5 checksum of all |
| 267 | prior cards in the cluster. Note that the Z card is required |
| 268 | on a cluster. |
| 269 | </p> |
| 270 | |
| 271 | <p>An example cluster from Fossil can be seen |
| 272 | [/artifact/d03dbdd73a2a8 | here].</p> |
| 273 | |
| 274 | |
| 275 | <h2>3.0 Control Artifacts</h2> |
| 276 | |
| 277 | <p> |
| 278 | Control artifacts are used to assign properties to other artifacts |
| 279 | within the repository. The basic format of a control artifact is |
| 280 | the same as a manifest or cluster. A control artifact is a text |
| 281 | files divided into cards by newline characters. Each card has a |
| 282 | single-character card type followed by arguments. Spaces separate |
| 283 | the card type and the arguments. No surplus whitespace is allowed. |
| 284 | All cards must occur in strict lexigraphical order. |
| 285 | </p> |
| 286 | |
| 287 | <p> |
| 288 | Allowed cards in a control artifact are as follows: |
| 289 | </p> |
| 290 | |
| 291 | <blockquote> |
| 292 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 293 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name artifact-id ?value?</i><br /> |
| 294 | <b>Z</b> <i>checksum</i><br /> |
| 295 | </blockquote> |
| 296 | |
| 297 | <p> |
| 298 | A control artifact must have one D card and one Z card and |
| 299 | one or more T cards. No other cards or other text is |
| 300 | allowed in a control artifact. Control artifacts might be PGP |
| 301 | clearsigned.</p> |
| 302 | |
| 303 | <p>The D card and the Z card of a control artifact are the same |
| 304 | as in a manifest.</p> |
| 305 | |
| 306 | <p>The T card represents a "tag" or property that is applied to |
| 307 | some other artifact. The T card has two or three values. The |
| 308 | second argument is the 40 character lowercase artifact ID of the artifact |
| 309 | to which the tag is to be applied. The |
| 310 | first value is the tag name. The first character of the tag |
| 311 | is either "+", "-", or "*". A "+" means the tag should be added |
| @@ -313,28 +274,37 @@ | |
| 313 | The "*" character means the tag should be added to the artifact |
| 314 | and all direct descendants (but not branches) of the artifact down |
| 315 | to but not including the first descendant that contains a |
| 316 | more recent "-" tag with the same name. |
| 317 | The optional third argument is the value of the tag. A tag |
| 318 | without a value is a boolean.</p> |
| 319 | |
| 320 | <p>When two or more tags with the same name are applied to the |
| 321 | same artifact, the tag with the latest (most recent) date is |
| 322 | used.</p> |
| 323 | |
| 324 | <p>Some tags have special meaning. The "comment" tag when applied |
| 325 | to a check-in will override the check-in comment of that check-in |
| 326 | for display purposes.</p> |
| 327 | |
| 328 | <a name="wikichng"></a> |
| 329 | <h2>4.0 Wiki Pages</h2> |
| 330 | |
| 331 | <p>A wiki page is an artifact with a format similar to manifests, |
| 332 | clusters, and control artifacts. The artifact is divided into |
| 333 | cards by newline characters. The format of each card is as in |
| 334 | manifests, clusters, and control artifacts. Wiki artifacts accept |
| 335 | the following card types:</p> |
| 336 | |
| 337 | <blockquote> |
| 338 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 339 | <b>L</b> <i>wiki-title</i><br /> |
| 340 | <b>P</b> <i>parent-artifact-id</i>+<br /> |
| @@ -341,63 +311,245 @@ | |
| 341 | <b>U</b> <i>user-name</i><br /> |
| 342 | <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> |
| 343 | <b>Z</b> <i>checksum</i> |
| 344 | </blockquote> |
| 345 | |
| 346 | <p>The D card is the date and time when the wiki page was edited. |
| 347 | The P card specifies the parent wiki pages, if any. The L card |
| 348 | gives the name of the wiki page. The U card specifies the login |
| 349 | of the user who made this edit to the wiki page. The Z card is |
| 350 | the usual checksum over the either artifact.</p> |
| 351 | |
| 352 | <p>The W card is used to specify the text of the wiki page. The |
| 353 | argument to the W card is an integer which is the number of bytes |
| 354 | of text in the wiki page. That text follows the newline character |
| 355 | that terminates the W card. The wiki text is always followed by one |
| 356 | extra newline.</p> |
| 357 | |
| 358 | <a name="tktchng"></a> |
| 359 | <h2>5.0 Ticket Changes</h2> |
| 360 | |
| 361 | <p>A ticket-change artifact represents a change to a trouble ticket. |
| 362 | The following cards are allowed on a ticket change artifact:</p> |
| 363 | |
| 364 | <blockquote> |
| 365 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 366 | <b>J</b> ?<b>+</b>?<i>name</i> ?<i>value</i>?<br /> |
| 367 | <b>K</b> <i>ticket-id</i><br /> |
| 368 | <b>U</b> <i>user-name</i><br /> |
| 369 | <b>Z</b> <i>checksum</i> |
| 370 | </blockquote> |
| 371 | |
| 372 | <p> |
| 373 | The D card is the usual date and time stamp and represents the point |
| 374 | in time when the change was entered. The U card is the login of the |
| 375 | programmer who entered this change. The Z card is the checksum over |
| 376 | the entire artifact.</p> |
| 377 | |
| 378 | <p> |
| 379 | Every ticket has a unique ID. The ticket to which this change is applied |
| 380 | is specified by the K card. A ticket exists if it contains one or |
| 381 | more changes. The first "change" to a ticket is what brings the |
| 382 | ticket into existence.</p> |
| 383 | |
| 384 | <p> |
| 385 | J cards specify changes to the "value" of "fields" in the ticket. |
| 386 | If the <i>value</i> parameter of the J card is omitted, then the |
| 387 | field is set to an empty string. |
| 388 | Each fossil server has a ticket configuration which specifies the fields its |
| 389 | understands. The ticket configuration is part of the local state for |
| 390 | the repository and thus can vary from one repository to another. |
| 391 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 392 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 393 | is not in the local configuration, then that J card |
| 394 | is simply ignored.</p> |
| 395 | |
| 396 | <p> |
| 397 | The first argument of the J card is the field name. The second |
| 398 | value is the field value. If the field name begins with "+" then |
| 399 | the value is appended to the prior value. Otherwise, the value |
| 400 | on the J card replaces any previous value of the field. |
| 401 | The field name and value are both encoded using the character |
| 402 | escapes defined for the C card of a manifest. |
| 403 | </p> |
| 404 |
| --- www/fileformat.wiki | |
| +++ www/fileformat.wiki | |
| @@ -1,26 +1,23 @@ | |
| 1 | <title>Fossil File Formats</title> |
| 2 | <h1 align="center"> |
| 3 | Fossil File Formats |
| 4 | </h1> |
| 5 | |
| 6 | The global state of a fossil repository is kept simple so that it can |
| 7 | endure in useful form for decades or centuries. |
| 8 | A fossil repository is intended to be readable, |
| 9 | searchable, and extensible by people not yet born. |
| 10 | |
| 11 | The global state of a fossil repository is an unordered |
| 12 | set of <i>artifacts</i>. |
| 13 | An artifact might be a source code file, the text of a wiki page, |
| 14 | part of a trouble ticket, or one of several special control artifacts |
| 15 | used to show the relationships between other artifacts within the |
| 16 | project. Each artifact is normally represented on disk as a separate |
| 17 | file. Artifacts can be text or binary. |
| 18 | |
| 19 | In addition to the global state, |
| 20 | each fossil repository also contains local state. |
| 21 | The local state consists of web-page formatting |
| 22 | preferences, authorized users, ticket display and reporting formats, |
| 23 | and so forth. The global state is shared in common among all |
| @@ -29,82 +26,73 @@ | |
| 26 | The local state is not versioned and is not synchronized |
| 27 | with the global state. |
| 28 | The local state is not composed of artifacts and is not intended to be enduring. |
| 29 | This document is concerned with global state only. Local state is only |
| 30 | mentioned here in order to distinguish it from global state. |
| 31 | |
| 32 | Each artifact in the repository is named by its SHA1 hash. |
| 33 | No prefixes or meta information is added to a artifact before |
| 34 | its hash is computed. The name of a artifact in the repository |
| 35 | is exactly the same SHA1 hash that is computed by sha1sum |
| 36 | on the file as it exists in your source tree.</p> |
| 37 | |
| 38 | Some artifacts have a particular format which gives them special |
| 39 | meaning to fossil. Fossil recognizes: |
| 40 | |
| 41 | <ul> |
| 42 | <li> [#manifest | Manifests] </li> |
| 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> [#artifact | Artifacts] </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 | 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 |
| 66 | source tree. The manifest contains a list of artifacts for |
| 67 | each file in the project and the corresponding filenames, as |
| 68 | well as information such as parent check-ins, the name of the |
| 69 | programmer who created the check-in, the date and time when |
| 70 | the check-in was created, and any check-in comments associated |
| 71 | with the check-in. |
| 72 | |
| 73 | Any artifact in the repository that follows the syntactic rules |
| 74 | of a manifest is a manifest. Note that a manifest can |
| 75 | be both a real manifest and also a content file, though this |
| 76 | is rare. |
| 77 | |
| 78 | A manifest is a text file. Newline characters |
| 79 | (ASCII 0x0a) separate the file into "cards". |
| 80 | Each card begins with a single |
| 81 | character "card type". Zero or more arguments may follow |
| 82 | the card type. All arguments are separated from each other |
| 83 | and from the card-type character by a single space |
| 84 | character. There is no surplus white space between arguments |
| 85 | and no leading or trailing whitespace except for the newline |
| 86 | character that acts as the card separator. |
| 87 | |
| 88 | All cards of the manifest occur in strict sorted lexicographical order. |
| 89 | No card may be duplicated. |
| 90 | The entire manifest may be PGP clear-signed, but otherwise it |
| 91 | may contain no additional text or data beyond what is described here. |
| 92 | |
| 93 | Allowed cards in the manifest are as follows: |
| 94 | |
| 95 | <blockquote> |
| 96 | <b>C</b> <i>checkin-comment</i><br> |
| 97 | <b>D</b> <i>time-and-date-stamp</i><br> |
| 98 | <b>F</b> <i>filename</i> <i>SHA1-hash</i> <i>permissions</i> <i>old-name</i><br> |
| @@ -113,11 +101,10 @@ | |
| 101 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name <b>*</b> ?value?</i><br> |
| 102 | <b>U</b> <i>user-login</i><br> |
| 103 | <b>Z</b> <i>manifest-checksum</i> |
| 104 | </blockquote> |
| 105 | |
| 106 | A manifest must have exactly one C-card. The sole argument to |
| 107 | the C-card is a check-in comment that describes the check-in that |
| 108 | the manifest defines. The check-in comment is text. The following |
| 109 | escape sequences are applied to the text: |
| 110 | A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A |
| @@ -124,24 +111,20 @@ | |
| 111 | newline (ASCII 0x0a) is "\n" (ASCII 0x6C, x6E). A backslash |
| 112 | (ASCII 0x5C) is represented as two backslashes "\\". Apart from |
| 113 | space and newline, no other whitespace characters are allowed in |
| 114 | the check-in comment. Nor are any unprintable characters allowed |
| 115 | in the comment. |
| 116 | |
| 117 | A manifest must have exactly one D-card. The sole argument to |
| 118 | the D-card is a date-time stamp in the ISO8601 format. The |
| 119 | date and time should be in coordinated universal time (UTC). |
| 120 | The format is: |
| 121 | |
| 122 | <blockquote> |
| 123 | <i>YYYY</i><b>-</b><i>MM</i><b>-</b><i>DD</i><b>T</b><i>HH</i><b>:</b><i>MM</i><b>:</b><i>SS</i> |
| 124 | </blockquote> |
| 125 | |
| 126 | A manifest has zero or more F-cards. Each F-card defines a file |
| 127 | (other than the manifest itself) which is part of the check-in that |
| 128 | the manifest defines. There are two, three, or four arguments. |
| 129 | The first argument |
| 130 | is the pathname of the file in the check-in relative to the root |
| @@ -157,13 +140,11 @@ | |
| 140 | always readable and writable. This can be expressed by "w" permission |
| 141 | if desired but is optional. |
| 142 | The optional 4th argument is the name of the same file as it existed in |
| 143 | the parent check-in. If the name of the file is unchanged from its |
| 144 | parent, then the 4th argument is omitted. |
| 145 | |
| 146 | A manifest has zero or one P-cards. Most manifests have one P-card. |
| 147 | The P-card has a varying number of arguments that |
| 148 | defines other manifests from which the current manifest |
| 149 | is derived. Each argument is an 40-character lowercase |
| 150 | hexadecimal SHA1 of the predecessor manifest. All arguments |
| @@ -171,13 +152,11 @@ | |
| 152 | The first predecessor is the direct ancestor of the manifest. |
| 153 | Other arguments define manifests with which the first was |
| 154 | merged to yield the current manifest. Most manifests have |
| 155 | a P-card with a single argument. The first manifest in the |
| 156 | project has no ancestors and thus has no P-card. |
| 157 | |
| 158 | A manifest may optionally have a single R-card. The R-card has |
| 159 | a single argument which is the MD5 checksum of all files in |
| 160 | the check-in except the manifest itself. The checksum is expressed |
| 161 | as 32-characters of lowercase hexadecimal. The checksum is |
| 162 | computed as follows: For each file in the check-in (except for |
| @@ -185,13 +164,11 @@ | |
| 164 | take the pathname of the file relative to the root of the |
| 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 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 |
| @@ -199,42 +176,35 @@ | |
| 176 | possible to encode the current artifact ID as part of an artifact, |
| 177 | since the act of inserting the artifact ID would change the artifact ID, |
| 178 | hence a <b>*</b> is used to represent "self". T-cards are typically |
| 179 | added to manifests in order to set the <b>branch</b> property and a |
| 180 | symbolic name when the check-in is intended to start a new branch. |
| 181 | |
| 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. |
| 193 | |
| 194 | A sample manifest from Fossil itself can be seen |
| 195 | [/artifact/28987096ac | here]. |
| 196 | |
| 197 | <a name="cluster"></a> |
| 198 | <h2>2.0 Clusters</h2> |
| 199 | |
| 200 | A cluster is a artifact that declares the existence of other artifacts. |
| 201 | Clusters are used during repository synchronization to help |
| 202 | reduce network traffic. As such, clusters are an optimization and |
| 203 | may be removed from a repository without loss or damage to the |
| 204 | underlying project code. |
| 205 | |
| 206 | Clusters follow a syntax that is very similar to manifests. |
| 207 | A Cluster is a line-oriented text file. Newline characters |
| 208 | (ASCII 0x0a) separate the artifact into cards. Each card begins with a single |
| 209 | character "card type". Zero or more arguments may follow |
| 210 | the card type. All arguments are separated from each other |
| @@ -245,67 +215,58 @@ | |
| 215 | All cards of a cluster occur in strict sorted lexicographical order. |
| 216 | No card may be duplicated. |
| 217 | The cluster may not contain additional text or data beyond |
| 218 | what is described here. |
| 219 | Unlike manifests, clusters are never PGP signed. |
| 220 | |
| 221 | Allowed cards in the cluster are as follows: |
| 222 | |
| 223 | <blockquote> |
| 224 | <b>M</b> <i>artifact-id</i><br /> |
| 225 | <b>Z</b> <i>checksum</i> |
| 226 | </blockquote> |
| 227 | |
| 228 | A cluster contains one or more "M" cards followed by a single "Z" |
| 229 | line. Each M card has a single argument which is the artifact ID of |
| 230 | another artifact in the repository. The Z card work exactly like |
| 231 | the Z card of a manifest. The argument to the Z card is the |
| 232 | lower-case hexadecimal representation of the MD5 checksum of all |
| 233 | prior cards in the cluster. Note that the Z card is required |
| 234 | on a cluster. |
| 235 | |
| 236 | An example cluster from Fossil can be seen |
| 237 | [/artifact/d03dbdd73a2a8 | here]. |
| 238 | |
| 239 | <a name="ctrl"></a> |
| 240 | <h2>3.0 Control Artifacts</h2> |
| 241 | |
| 242 | Control artifacts are used to assign properties to other artifacts |
| 243 | within the repository. The basic format of a control artifact is |
| 244 | the same as a manifest or cluster. A control artifact is a text |
| 245 | files divided into cards by newline characters. Each card has a |
| 246 | single-character card type followed by arguments. Spaces separate |
| 247 | the card type and the arguments. No surplus whitespace is allowed. |
| 248 | All cards must occur in strict lexigraphical order. |
| 249 | |
| 250 | Allowed cards in a control artifact are as follows: |
| 251 | |
| 252 | <blockquote> |
| 253 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 254 | <b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name artifact-id ?value?</i><br /> |
| 255 | <b>U</b> <i>user-name</i><br /> |
| 256 | <b>Z</b> <i>checksum</i><br /> |
| 257 | </blockquote> |
| 258 | |
| 259 | A control artifact must have one D card and one Z card and |
| 260 | one or more T cards. No other cards or other text is |
| 261 | allowed in a control artifact. Control artifacts might be PGP |
| 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 |
| @@ -313,28 +274,37 @@ | |
| 274 | The "*" character means the tag should be added to the artifact |
| 275 | and all direct descendants (but not branches) of the artifact down |
| 276 | to but not including the first descendant that contains a |
| 277 | more recent "-" tag with the same name. |
| 278 | The optional third argument is the value of the tag. A tag |
| 279 | without a value is a boolean. |
| 280 | |
| 281 | When two or more tags with the same name are applied to the |
| 282 | same artifact, the tag with the latest (most recent) date is |
| 283 | used. |
| 284 | |
| 285 | Some tags have special meaning. The "comment" tag when applied |
| 286 | to a check-in will override the check-in comment of that check-in |
| 287 | for display purposes. The "user" tag overrides the name of the |
| 288 | check-in user. The "date" tag overrides the check-in date. |
| 289 | The "branch" tag sets the name of the branch that at check-in |
| 290 | belongs to. Symbolic tags begin with the "sym-" prefix. |
| 291 | |
| 292 | The U card is the name of the user that created the control |
| 293 | artifact. The Z card is the usual artifact checksum. |
| 294 | |
| 295 | An example control artifacts can be seen [/info/9d302ccda8 | here]. |
| 296 | |
| 297 | |
| 298 | <a name="wikichng"></a> |
| 299 | <h2>4.0 Wiki Pages</h2> |
| 300 | |
| 301 | A wiki page is an artifact with a format similar to manifests, |
| 302 | clusters, and control artifacts. The artifact is divided into |
| 303 | cards by newline characters. The format of each card is as in |
| 304 | manifests, clusters, and control artifacts. Wiki artifacts accept |
| 305 | the following card types: |
| 306 | |
| 307 | <blockquote> |
| 308 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 309 | <b>L</b> <i>wiki-title</i><br /> |
| 310 | <b>P</b> <i>parent-artifact-id</i>+<br /> |
| @@ -341,63 +311,245 @@ | |
| 311 | <b>U</b> <i>user-name</i><br /> |
| 312 | <b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> |
| 313 | <b>Z</b> <i>checksum</i> |
| 314 | </blockquote> |
| 315 | |
| 316 | The D card is the date and time when the wiki page was edited. |
| 317 | The P card specifies the parent wiki pages, if any. The L card |
| 318 | gives the name of the wiki page. The U card specifies the login |
| 319 | of the user who made this edit to the wiki page. The Z card is |
| 320 | the usual checksum over the either artifact. |
| 321 | |
| 322 | The W card is used to specify the text of the wiki page. The |
| 323 | argument to the W card is an integer which is the number of bytes |
| 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. |
| 335 | The following cards are allowed on a ticket change artifact: |
| 336 | |
| 337 | <blockquote> |
| 338 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 339 | <b>J</b> ?<b>+</b>?<i>name</i> ?<i>value</i>?<br /> |
| 340 | <b>K</b> <i>ticket-id</i><br /> |
| 341 | <b>U</b> <i>user-name</i><br /> |
| 342 | <b>Z</b> <i>checksum</i> |
| 343 | </blockquote> |
| 344 | |
| 345 | The D card is the usual date and time stamp and represents the point |
| 346 | in time when the change was entered. The U card is the login of the |
| 347 | programmer who entered this change. The Z card is the checksum over |
| 348 | the entire artifact. |
| 349 | |
| 350 | Every ticket has a unique ID. The ticket to which this change is applied |
| 351 | is specified by the K card. A ticket exists if it contains one or |
| 352 | more changes. The first "change" to a ticket is what brings the |
| 353 | ticket into existence. |
| 354 | |
| 355 | J cards specify changes to the "value" of "fields" in the ticket. |
| 356 | If the <i>value</i> parameter of the J card is omitted, then the |
| 357 | field is set to an empty string. |
| 358 | Each fossil server has a ticket configuration which specifies the fields its |
| 359 | understands. The ticket configuration is part of the local state for |
| 360 | the repository and thus can vary from one repository to another. |
| 361 | Hence a J card might specify a <i>field</i> that do not exist in the |
| 362 | local ticket configuration. If a J card specifies a <i>field</i> that |
| 363 | is not in the local configuration, then that J card |
| 364 | is simply ignored. |
| 365 | |
| 366 | The first argument of the J card is the field name. The second |
| 367 | value is the field value. If the field name begins with "+" then |
| 368 | the value is appended to the prior value. Otherwise, the value |
| 369 | on the J card replaces any previous value of the field. |
| 370 | The field name and value are both encoded using the character |
| 371 | escapes defined for the C card of a manifest. |
| 372 | |
| 373 | An example ticket-change artifact can be seen |
| 374 | [/artifact/91f1ec6af053 | here]. |
| 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> (<b>+</b>|<b>-</b>)<i>filename target source</i> |
| 386 | <b>C</b> <i>comment</i><br> |
| 387 | <b>D</b> <i>time-and-date-stamp</i><br /> |
| 388 | <b>U</b> <i>user-name</i><br /> |
| 389 | <b>Z</b> <i>checksum</i> |
| 390 | </blockquote> |
| 391 | |
| 392 | The A card specifies a filename for the attachment in its first argument. |
| 393 | The filename is preceeded by "+" to add the attachment or "-" to |
| 394 | remove the attachment. The second argument to the A card is the name |
| 395 | of the wiki page or ticket to which the attachment is connected. The |
| 396 | third argument is is the 40-character artifact ID of the attachment |
| 397 | itself. Every attachment artifact must have exactly one A card. |
| 398 | |
| 399 | The C card is an optional comment describing what the attachment is about. |
| 400 | The C card is optional, but there can only be one. |
| 401 | |
| 402 | A single D card is required to give the date and time when the attachment |
| 403 | was applied. |
| 404 | |
| 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> (<b>+</b>|<b>-</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 | <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> |
| 465 | </tr> |
| 466 | <tr> |
| 467 | <td><b>J</b> <i>name value</i></td> |
| 468 | <td align=center> </td> |
| 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 | <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> |
| 502 | <tr> |
| 503 | <td><b>P</b> <i>uuid ...</i></td> |
| 504 | <td align=center><b>X</b></td> |
| 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> |
| 519 | <tr> |
| 520 | <td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname uuid value</i></td> |
| 521 | <td align=center><b>X</b></td> |
| 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> |
| 537 | <tr> |
| 538 | <td><b>W</b> <i>size</i></td> |
| 539 | <td align=center> </td> |
| 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 |