diff options
| author | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-09-04 09:05:24 +0200 |
| commit | 4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch) | |
| tree | c296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /www/fileformat.wiki | |
| download | relic-master.tar.gz | |
Diffstat (limited to 'www/fileformat.wiki')
| -rw-r--r-- | www/fileformat.wiki | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/www/fileformat.wiki b/www/fileformat.wiki new file mode 100644 index 0000000..3eaa3cc --- /dev/null +++ b/www/fileformat.wiki @@ -0,0 +1,995 @@ +<title>Fossil File Formats</title> + +The global state of a fossil repository is kept simple so that it can +endure in useful form for decades or centuries. +A fossil repository is intended to be readable, +searchable, and extensible by people not yet born. + +The global state of a fossil repository is an unordered +set of <i>artifacts</i>. +An artifact might be a source code file, the text of a wiki page, +part of a trouble ticket, a description of a check-in including all +the files in that check-in with the check-in comment and so forth. +Artifacts are broadly grouped into two types: content artifacts and +structural artifacts. Content artifacts are the raw project source-code +files that are checked into the repository. Structural artifacts have +special formatting rules and are used to show the relationships between +other artifacts in the repository. It is possible for an artifact to +be both a structure artifact and a content artifact, though this is +rare. Artifacts can be text or binary. + +In addition to the global state, +each fossil repository also contains local state. +The local state consists of web-page formatting +preferences, authorized users, ticket display and reporting formats, +and so forth. The global state is shared in common among all +repositories for the same project, whereas the local state is often +different in separate repositories. +The local state is not versioned and is not synchronized +with the global state. +The local state is not composed of artifacts and is not intended to be enduring. +This document is concerned with global state only. Local state is only +mentioned here in order to distinguish it from global state. + +<h2 id="names">1.0 Artifact Names</h2> + +Each artifact in the repository is named by a hash of its content. +No prefixes, suffixes, or other information is added to an artifact before +the hash is computed. The artifact name is just the (lower-case +hexadecimal) hash of the raw artifact. + +Fossil currently computes artifact names using either SHA1 or SHA3-256. It +is relatively easy to add new algorithms in the future, but there are no +plans to do so at this time. + +When referring to artifacts in using tty commands or webpage URLs, it is +sufficient to specify a unique prefix for the artifact name. If the input +prefix is not unique, Fossil will show an error. Within a structural +artifact, however, all references to other artifacts must be the complete +hash. + +Prior to Fossil version 2.0, all names were formed from the SHA1 hash of +the artifact. The key innovation in Fossil 2.0 was adding support for +alternative hash algorithms. + +<h2 id="structural">2.0 Structural Artifacts</h2> + +A structural artifact is an artifact with a particular format +that is used to define the relationships between other artifacts in the +repository. +Fossil recognizes the following kinds of structural +artifacts: + +<ul> +<li> [#manifest | Manifests] </li> +<li> [#cluster | Clusters] </li> +<li> [#ctrl | Control (a.k.a. Tag) Artifacts] </li> +<li> [#wikichng | Wiki Pages] </li> +<li> [#tktchng | Ticket Changes] </li> +<li> [#attachment | Attachments] </li> +<li> [#event | TechNotes] </li> +<li> [#forum | Forum Posts] </li> +</ul> + +These eight structural artifact types are described in subsections below. + +Structural artifacts are UTF-8 text. The artifact may be PGP clearsigned. +After removal of the PGP clearsign header and suffix (if any) a structural +artifact consists of one or more "cards" separated by a single newline +(ASCII: 0x0a) character. Each card begins with a single +character "card type". Zero or more arguments may follow +the card type. All arguments are separated from each other +and from the card-type character by a single space +character. There is no surplus white space between arguments +and no leading or trailing whitespace except for the newline +character that acts as the card separator. All cards must be in strict +lexicographical order (except for an +[./fileformat.wiki#outofordercards|historical bug compatibility]). +There may not be any duplicate cards. + +In the current implementation (as of 2017-02-27) the artifacts that +make up a fossil repository are stored as delta- and zlib-compressed +blobs in an <a href="http://www.sqlite.org/">SQLite</a> database. This +is an implementation detail and might change in a future release. For +the purpose of this article "file format" means the format of the artifacts, +not how the artifacts are stored on disk. It is the artifact format that +is intended to be enduring. The specifics of how artifacts are stored on +disk, though stable, is not intended to live as long as the +artifact format. + +<h3 id="manifest">2.1 The Manifest</h3> + +A manifest defines a check-in. +A manifest contains a list of artifacts for +each file in the project and the corresponding filenames, as +well as information such as parent check-ins, the username of the +programmer who created the check-in, the date and time when +the check-in was created, and any check-in comments associated +with the check-in. + +Allowed cards in the manifest are as follows: + +<div class="indent"> +<b>B</b> <i>baseline-manifest</i><br> +<b>C</b> <i>checkin-comment</i><br> +<b>D</b> <i>time-and-date-stamp</i><br> +<b>F</b> <i>filename</i> ?<i>hash</i>? ?<i>permissions</i>? ?<i>old-name</i>?<br> +<b>N</b> <i>mimetype</i><br> +<b>P</b> <i>artifact-hash</i>+<br> +<b>Q</b> (<b>+</b>|<b>-</b>)<i>artifact-hash</i> ?<i>artifact-hash</i>?<br> +<b>R</b> <i>repository-checksum</i><br> +<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <b>*</b> ?<i>value</i>?<br> +<b>U</b> <i>user-login</i><br> +<b>Z</b> <i>manifest-checksum</i> +</div> + +A manifest may optionally have a single <b>B</b> card. The <b>B</b> card specifies +another manifest that serves as the "baseline" for this manifest. A +manifest that has a <b>B</b> card is called a delta-manifest and a manifest +that omits the <b>B</b> card is a baseline-manifest. The other manifest +identified by the argument of the <b>B</b> card must be a baseline-manifest. +A baseline-manifest records the complete contents of a check-in. +A delta-manifest records only changes from its baseline. + +A manifest must have exactly one <b>C</b> card. The sole argument to +the <b>C</b> card is a check-in comment that describes the check-in that +the manifest defines. The check-in comment is text. The following +escape sequences are applied to the text: +A space (ASCII 0x20) is represented as "\s" (ASCII 0x5C, 0x73). A +newline (ASCII 0x0a) is "\n" (ASCII 0x5C, x6E). A backslash +(ASCII 0x5C) is represented as two backslashes "\\". Apart from +space and newline, no other whitespace characters are allowed in +the check-in comment. Nor are any unprintable characters allowed +in the comment. + +A manifest must have exactly one <b>D</b> card. The sole argument to +the <b>D</b> card is a date-time stamp in the ISO8601 format. The +date and time should be in coordinated universal time (UTC). +The format one of: + +<pre class="indent"><i>YYYY-MM-DD<b>T</b>HH:MM:SS +YYYY-MM-DD<b>T</b>HH:MM:SS.SSS</i></pre> + +A manifest has zero or more <b>F</b> cards. Each <b>F</b> card identifies a file +that is part of the check-in. There are one, two, three, or four +arguments. The first argument is the pathname of the file in the +check-in relative to the root of the project file hierarchy. No ".." +or "." directories are allowed within the filename. Space characters +are escaped as in <b>C</b> card comment text. Backslash characters and +newlines are not allowed within filenames. The directory separator +character is a forward slash (ASCII 0x2F). The second argument to the +<b>F</b> card is the lower-case hexadecimal artifact hash of +the content artifact. The second argument is required for baseline +manifests but is optional for delta manifests. When the second +argument to the <b>F</b> card is omitted, it means that the file has been +deleted relative to the baseline (files removed in baseline manifests +versions are <em>not</em> added as <b>F</b> cards). The optional 3rd argument +defines any special access permissions associated with the file. This +can be defined as "x" to mean that the file is executable or "l" +(small letter ell) to mean a symlink. All files are always readable +and writable. This can be expressed by "w" permission if desired but +is optional. The file format might be extended with new permission +letters in the future. The optional 4th argument is the name of the +same file as it existed in the parent check-in. If the name of the +file is unchanged from its parent, then the 4th argument is omitted. + +Sidebar: due to a minor bug in Fossil's early history (specifically +2008-08-11 to 2009-01-20), manifest parsers must be able to tolerate a +single space character after the UUID value even if no permissions +value is set. Normally the space would indicate that another token +is expected, but this one case requires leniency to allow +[/artifact/32b480faa3465591|a single known historical artifact] to parse. +For full details see +[https://claude.ai/code/artifact/c121be7a-5c6a-4a18-ab7f-63d086ac8071|this article]. + +A manifest has zero or one <b>N</b> cards. The <b>N</b> card specifies the mimetype for the +text in the comment of the <b>C</b> card. If the <b>N</b> card is omitted, a default mimetype +is used. Note that the <b>N</b> card has never actually been used by +any Fossil implementation. The implementation has always interpreted +check-in comments according to the [/wiki_rules|Fossil Wiki formatting rules]. +There are no current plans to ever change that. + +A manifest has zero or one <b>P</b> cards. Most manifests have one <b>P</b> card. +The <b>P</b> card has a varying number of arguments that +define other manifests from which the current manifest +is derived. Each argument is a lowercase +hexadecimal artifact hash of a predecessor manifest. All arguments +to the <b>P</b> card must be unique within that card. +The first argument is the artifact hash of the direct ancestor of the manifest. +Other arguments define manifests with which the first was +merged to yield the current manifest. Most manifests have +a <b>P</b> card with a single argument. The first manifest in the +project has no ancestors and thus has no <b>P</b> card or (depending +on the Fossil version) an empty <b>P</b> card (no arguments). + +A manifest has zero or more <b>Q</b> cards. A <b>Q</b> card is similar to a <b>P</b> card +in that it defines a predecessor to the current check-in. But +whereas a <b>P</b> card defines the immediate ancestor or a merge +ancestor, the <b>Q</b> card is used to identify a single check-in or a small +range of check-ins which were cherry-picked for inclusion in or +exclusion from the current manifest. The first argument of +the <b>Q</b> card is the artifact ID of another manifest (the "target") +which has had its changes included or excluded in the current manifest. +The target is preceded by "+" or "-" to show inclusion or +exclusion, respectively. The optional second argument to the +<b>Q</b> card is another manifest artifact ID which is the "baseline" +for the cherry-pick. If omitted, the baseline is the primary +parent of the target. The +changes included or excluded consist of all changes moving from +the baseline to the target. + +The <b>Q</b> card was added to the interface specification on 2011-02-26. +Older versions of Fossil will reject manifests that contain <b>Q</b> cards. + +A manifest may optionally have a single <b>R</b> card. The <b>R</b> card has +a single argument which is the MD5 checksum of all files in +the check-in except the manifest itself. The checksum is expressed +as 32 characters of lowercase hexadecimal. The checksum is +computed as follows: For each file in the check-in (except for +the manifest itself) in strict sorted lexicographical order, +take the pathname of the file relative to the root of the +repository, append a single space (ASCII 0x20), the +size of the file in ASCII decimal, a single newline +character (ASCII 0x0A), and the complete text of the file. +Compute the MD5 checksum of the result. + +A manifest might contain one or more <b>T</b> cards used to set +[./branching.wiki#tags | tags or properties] +on the check-in. The format of the <b>T</b> card is the same as +described in <i>Control Artifacts</i> section below, except that the +second argument is the single character "<b>*</b>" instead of an +artifact ID. The <b>*</b> in place of the artifact ID indicates that +the tag or property applies to the current artifact. It is not +possible to encode the current artifact ID as part of an artifact, +since the act of inserting the artifact ID would change the artifact ID, +hence a <b>*</b> is used to represent "self". <b>T</b> cards are typically +added to manifests in order to set the <b>branch</b> property and a +symbolic name when the check-in is intended to start a new branch. + +Each manifest has a single <b>U</b> card. The argument to the <b>U</b> card is +the login of the user who created the manifest. The login name +is encoded using the same character escapes as is used for the +check-in comment argument to the <b>C</b> card. + +A manifest must have a single <b>Z</b> card as its last line. The argument +to the <b>Z</b> card is a 32-character lowercase hexadecimal MD5 hash +of all prior lines of the manifest up to and including the newline +character that immediately precedes the "Z", excluding any PGP +clear-signing prefix. The <b>Z</b> card is +a sanity check to prove that the manifest is well-formed and +consistent. + +A sample manifest from Fossil itself can be seen +[/artifact/28987096ac | here]. + +<h3 id="cluster">2.2 Clusters</h3> + +A cluster is an artifact that declares the existence of other artifacts. +Clusters are used during repository synchronization to help +reduce network traffic. As such, clusters are an optimization and +may be removed from a repository without loss or damage to the +underlying project code. + +Allowed cards in the cluster are as follows: + +<div class="indent"> +<b>M</b> <i>artifact-id</i><br /> +<b>Z</b> <i>checksum</i> +</div> + +A cluster contains one or more <b>M</b> cards followed by a single <b>Z</b> card. +Each <b>M</b> card has a single argument which is the artifact ID of +another artifact in the repository. The <b>Z</b> card works exactly like +the <b>Z</b> card of a manifest. The argument to the <b>Z</b> card is the +lower-case hexadecimal representation of the MD5 checksum of all +prior cards in the cluster. The <b>Z</b> card is required. + +An example cluster from Fossil can be seen +[/artifact/d03dbdd73a2a8 | here]. + +<h3 id="ctrl">2.3 Control (a.k.a. Tag) Artifacts</h3> + +Control artifacts are used to assign properties to other artifacts +within the repository. Allowed cards in a control artifact are as +follows: + +<div class="indent"> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>T</b> (<b>+</b>|<b>-</b>|<b>*</b>)<i>tag-name</i> <i>artifact-id</i> ?<i>value</i>?<br /> +<b>U</b> <i>user-name</i><br /> +<b>Z</b> <i>checksum</i><br /> +</div> + +Control articles are also referred to as Tag artifacts, but tags can +also be applied via other artifact types, as described in +[#summary|the Card Summary table]. + +A control artifact must have one <b>D</b> card, one <b>U</b> card, one <b>Z</b> card and +one or more <b>T</b> cards. No other cards or other text is +allowed in a control artifact. Control artifacts might be PGP +clearsigned. + +The <b>D</b> card and the <b>Z</b> card of a control artifact are the same +as in a manifest. + +The <b>T</b> card represents a [./branching.wiki#tags | tag or property] +that is applied to +some other artifact. The <b>T</b> card has two or three values. The +second argument is the lowercase artifact ID of the artifact +to which the tag is to be applied. The +first value is the tag name. The first character of the tag +is either "+", "-", or "*". The "+" means the tag should be added +to the artifact. The "-" means the tag should be removed. +The "*" character means the tag should be added to the artifact +and all direct descendants (but not descendants through a merge) down +to but not including the first descendant that contains a +more recent "-", "*", or "+" tag with the same name. +The optional third argument is the value of the tag. A tag +without a value is a Boolean. + +When two or more tags with the same name are applied to the +same artifact, the tag with the latest (most recent) date is +used. + +Some tags have special meaning. The "comment" tag when applied +to a check-in will override the check-in comment of that check-in +for display purposes. The "user" tag overrides the name of the +check-in user. The "date" tag overrides the check-in date. +The "branch" tag sets the name of the branch that at check-in +belongs to. Symbolic tags begin with the "sym-" prefix. + +The <b>U</b> card is the name of the user that created the control +artifact. The <b>Z</b> card is the usual required artifact checksum. + +An example control artifact can be seen [/info/9d302ccda8 | here]. + + +<h3 id="wikichng">2.4 Wiki Pages</h3> + +A wiki artifact defines a single version of a +single wiki page. +Wiki artifacts accept +the following card types: + +<div class="indent"> +<b>C</b> <i>change-comment</i><br> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>L</b> <i>wiki-title</i><br /> +<b>N</b> <i>mimetype</i><br /> +<b>P</b> <i>parent-artifact-id</i>+<br /> +<b>U</b> <i>user-name</i><br /> +<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> +<b>Z</b> <i>checksum</i> +</div> + +The <b>D</b> card is the date and time when the wiki page was edited. +The <b>P</b> card specifies the parent wiki pages, if any. The <b>L</b> card +gives the name of the wiki page. The optional <b>N</b> card specifies +the mimetype of the wiki text. If the <b>N</b> card is omitted, the +mimetype is assumed to be text/x-fossil-wiki. +The <b>U</b> card specifies the login +of the user who made this edit to the wiki page. The <b>Z</b> card is +the usual checksum over the entire artifact and is required. + +The <b>W</b> card is used to specify the text of the wiki page. The +argument to the <b>W</b> card is an integer which is the number of bytes +of text in the wiki page. That text follows the newline character +that terminates the <b>W</b> card. The wiki text is always followed by one +extra newline. + +The <b>C</b> card on a wiki page is optional. The argument is a comment +that explains why the changes were made. The ability to have a <b>C</b> +card on a wiki page artifact was added on 2019-12-02 at the suggestion +of user George Krivov and is not currently used or generated by the +implementation. Older versions of Fossil will reject a wiki-page +artifact that includes a <b>C</b> card. + +An example wiki artifact can be seen +[/artifact?name=7b2f5fd0e0&txt=1 | here]. + +Historical note: though <b>U</b> cards are technically required for +wiki pages by this specification, Fossil has historically elided them +if the submitter is "nobody". Very few repositories enable "nobody" to +write to wiki pages, so relatively few wiki artifacts without U cards +exist, but they do exist. Implementations are recommended to accept a +missing U card as an alias for a U card with the value +<tt>nobody</tt>. + +<h3 id="tktchng">2.5 Ticket Changes</h3> + +A ticket-change artifact represents a change to a trouble ticket. +The following cards are allowed on a ticket change artifact: + +<div class="indent"> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>J</b> ?<b>+</b>?<i>name</i> ?<i>value</i>?<br /> +<b>K</b> <i>ticket-id</i><br /> +<b>U</b> <i>user-name</i><br /> +<b>Z</b> <i>checksum</i> +</div> + +The <b>D</b> card is the usual date and time stamp and represents the point +in time when the change was entered. The <b>U</b> card is the login of the +programmer who entered this change. The <b>Z</b> card is the required checksum over +the entire artifact. + +Every ticket has a distinct ticket-id: +40-character lower-case hexadecimal number. +The ticket-id is given in the <b>K</b> card. A ticket exists if it contains one or +more changes. The first "change" to a ticket is what brings the +ticket into existence. + +<b>J</b> cards specify changes to the "value" of "fields" in the ticket. +If the <i>value</i> parameter of the <b>J</b> card is omitted, then the +field is set to an empty string. +Each fossil server has a ticket configuration which specifies the fields it +understands. The ticket configuration is part of the local state for +the repository and thus can vary from one repository to another. +Hence a <b>J</b> card might specify a <i>field</i> that does not exist in the +local ticket configuration. If a <b>J</b> card specifies a <i>field</i> that +is not in the local configuration, then that <b>J</b> card +is simply ignored. + +The first argument of the <b>J</b> card is the field name. The second +value is the field value. If the field name begins with "+" then +the value is appended to the prior value. Otherwise, the value +on the <b>J</b> card replaces any previous value of the field. +The field name and value are both encoded using the character +escapes defined for the <b>C</b> card of a manifest. + +An example ticket-change artifact can be seen +[/artifact/91f1ec6af053 | here]. + +<h3 id="attachment">2.6 Attachments</h3> + +An attachment artifact associates some other artifact that is the +attachment (the source artifact) with a ticket, wiki page, technical +note, or forum post to which the attachment is connected (the target +artifact). The following cards are allowed on an attachment artifact: + +<div class="indent"> +<b>A</b> <i>filename target</i> ?<i>source</i>?<br /> +<b>C</b> <i>comment</i><br /> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>N</b> <i>mimetype</i><br /> +<b>U</b> <i>user-name</i><br /> +<b>Z</b> <i>checksum</i> +</div> + +The <b>A</b> card specifies a filename for the attachment in its first +argument. The second argument to the <b>A</b> card is the name of the +wiki page, ticket, technical note, or full hash of a forum post to +which the attachment is connected. The third argument is either +missing or else it is the lower-case artifact ID of the attachment +itself. A missing third argument means that the attachment should be +deleted. If <i>target</i> is a forum post, the hash provided should +generally be that of the first version of the post for reasons +[#forumpost-tag|explained elsewhere]. + +The <b>C</b> card is an optional comment describing what the attachment is about. +The <b>C</b> card is optional, but there can only be one. + +A single <b>D</b> card is required to give the date and time when the attachment +was applied. + +There may be zero or one <b>N</b> cards. The <b>N</b> card specifies the mimetype of the +comment text provided in the <b>C</b> card. If the <b>N</b> card is omitted, the <b>C</b> card +mimetype is taken to be text/plain. + +A single <b>U</b> card gives the name of the user who added the attachment. +If an attachment is added anonymously, then the <b>U</b> card may be omitted. + +The <b>Z</b> card is the usual checksum over the rest of the attachment artifact. +The <b>Z</b> card is required. + + +<h3 id="event">2.7 Technical Notes</h3> + +A technical note or "technote" artifact (formerly known as an "event" artifact) +associates a timeline comment and a page of text +(similar to a wiki page) with a point in time. Technotes can be used +to record project milestones, release notes, blog entries, process +checkpoints, or news articles. +The following cards are allowed on a technote artifact: + +<div class="indent"> +<b>C</b> <i>comment</i><br> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>E</b> <i>technote-time</i> <i>technote-id</i><br /> +<b>N</b> <i>mimetype</i><br /> +<b>P</b> <i>parent-artifact-id</i>+<br /> +<b>T</b> <b>+</b><i>tag-name</i> <b>*</b> ?<i>value</i>?<br /> +<b>U</b> <i>user-name</i><br /> +<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> +<b>Z</b> <i>checksum</i> +</div> + +The <b>C</b> card contains text that is displayed on the timeline for the +technote. The <b>C</b> card is optional, but there can only be one. + +A single <b>D</b> card is required to give the date and time when the +technote artifact was created. This is different from the time at which +the technote appears on the timeline. + +A single <b>E</b> card gives the time of the technote (the point on the timeline +where the technote is displayed) and a unique identifier for the technote. +When there are multiple artifacts with the same technote-id, the one with +the most recent <b>D</b> card is the only one used. The technote-id must be a +40-character lower-case hexadecimal string. + +The optional <b>N</b> card specifies the mimetype of the text of the technote +that is contained in the <b>W</b> card. If the <b>N</b> card is omitted, then the +<b>W</b> card text mimetype is assumed to be text/x-fossil-wiki, which is the +Fossil wiki format. + +The optional <b>P</b> card specifies a prior technote with the same technote-id +from which the current technote is an edit. The <b>P</b> card is a hint to the +system that it might be space efficient to store one technote as a delta of +the other. + +A technote might contain one or more <b>T</b> cards used to set +[./branching.wiki#tags | tags or properties] +on the technote. The format of the <b>T</b> card is the same as +described in [#ctrl | Control Artifacts] section above, except that the +second argument is the single character "<b>*</b>" instead of an +artifact ID and the name is always prefaced by "<b>+</b>". +The <b>*</b> in place of the artifact ID indicates that +the tag or property applies to the current artifact. It is not +possible to encode the current artifact ID as part of an artifact, +since the act of inserting the artifact ID would change the artifact ID, +hence a <b>*</b> is used to represent "self". The "<b>+</b>" on the +name means that tags can only be "add" and they can only be non-propagating +tags. In a technote, <b>T</b> cards are normally used to set the background +display color for timelines. + +The optional <b>U</b> card gives the name of the user who entered the technote. + +A single <b>W</b> card provides wiki text for the document associated with the +technote. The format of the <b>W</b> card is exactly the same as for a +[#wikichng | wiki artifact]. + +The <b>Z</b> card is the required checksum over the rest of the artifact. + +<h3 id="forum">2.8 Forum Posts</h3> + +Forum posts are intended as a mechanism for users and developers to +discuss a project. Forum posts are like messages on a mailing list. + +The following cards are allowed on an forum post artifact: + +<div class="indent"> +<b>D</b> <i>time-and-date-stamp</i><br /> +<b>G</b> <i>thread-root</i><br /> +<b>H</b> <i>thread-title</i><br /> +<b>I</b> <i>in-reply-to</i><br /> +<b>N</b> <i>mimetype</i><br /> +<b>P</b> <i>parent-artifact-id</i><br /> +<b>U</b> <i>user-name</i><br /> +<b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b><br /> +<b>Z</b> <i>checksum</i> +</div> + +Every forum post must have either one <b>I</b> card and one <b>G</b> card +or one <b>H</b> card. +Forum posts are organized into topic threads. The initial +post for a thread (the root post) has an <b>H</b> card giving the title or +subject for that thread. The argument to the <b>H</b> card is a string +in the same format as a comment string in a <b>C</b> card. +All follow-up posts have an <b>I</b> card that +indicates which prior post in the same thread the current forum +post is replying to, and a <b>G</b> card specifying the root post for +the entire thread. The argument to <b>G</b> and <b>I</b> cards is the +artifact hash for the prior forum post to which the card refers. + +In theory, it is sufficient for follow-up posts to have only an +<b>I</b> card, since the <b>G</b> card value could be computed by following a +chain of <b>I</b> cards. However, the <b>G</b> card is required in order to +associate the artifact with a forum thread in the case where an +intermediate artifact in the <b>I</b> card chain is shunned or otherwise +becomes unreadable. + +A single <b>D</b> card is required to give the date and time when the +forum post was created. + +The optional <b>N</b> card specifies the mimetype of the text of the technote +that is contained in the <b>W</b> card. If the <b>N</b> card is omitted, then the +<b>W</b> card text mimetype is assumed to be text/x-fossil-wiki, which is the +Fossil wiki format. + +The optional <b>P</b> card specifies a prior forum post for which this +forum post is an edit. For display purposes, only the child post +is shown, though the historical post is retained as a record. +If <b>P</b> cards are used and there exist multiple versions of the same +forum post, then <b>I</b> cards for other artifacts refer to whichever +version of the post was current at the time the reply was made, +but <b>G</b> cards refer to the initial, unedited root post for the thread. +Thus, following the chain of <b>I</b> cards back to the root of the thread +may land on a different post than the one given in the <b>G</b> card. +However, following the chain of <b>I</b> cards back to the thread root, +then following <b>P</b> cards back to the initial version of the thread +root must give the same artifact as is provided by the <b>G</b> card, +otherwise the artifact containing the <b>G</b> card is considered invalid +and should be ignored. + +In general, <b>P</b> cards may contain multiple arguments, indicating a +merge. But since forum posts cannot be merged, the +<b>P</b> card of a forum post may only contain a single argument. + +The <b>U</b> card gives name of the user who entered the forum post. + +A single <b>W</b> card provides wiki text for the forum post. +The format of the <b>W</b> card is exactly the same as for a +[#wikichng | wiki artifact]. + +The <b>Z</b> card is the required checksum over the rest of the artifact. + +<a name="forumpost-tag"></a> +<h4>2.8.1 Tags and Attachments on Forum Posts</h4> + +When adding [#ctrl|tags] or [#attachment|attachments] to [#forum|forum +posts] it is generally up to the application to tag, or attach to, +only the first version of any given post. For example, if post X has +two edits then a tag applied, or attachment added, by the user to post +X+2 should generally be applied to version X instead. Though this +complicates the app logic for applying tags, it simplifies the app's +location of tags for purposes of applying tag-/attachment-dependent +logic. As of this writing (May 2026), no current Fossil use cases +would be improved by tagging specific subsequent versions of posts, +e.g. the hypothetical X+1. + +Forum posts, because they have a P-card, support propagating tags. + + +<h2 id="summary">3.0 Card Summary</h2> + +The following table summarizes the various kinds of cards that appear +on Fossil artifacts. A blank entry means that combination of card and +artifact is not legal. A number or range of numbers indicates the number +of times a card may (or must) appear in the corresponding artifact type. +e.g. a value of 1 indicates a required unique card and 1+ indicates that one +or more such cards are required. + +<table> +<tr> +<th>⇩ Card Format / Used By ⇨</th> +<th>Manifest</th> +<th>Cluster</th> +<th>Control</th> +<th>Wiki</th> +<th>Ticket</th> +<th>Attachment</th> +<th>Technote</th> +<th>Forum</th> +</tr> +<tr> +<td><b>A</b> <i>filename</i> <i>target</i> ?<i>source</i>?</td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>B</b> <i>baseline</i></td> +<td align=center><b>0-1</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>C</b> <i>comment-text</i></td> +<td align=center><b>1</b></td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b></td> +<td> </td> +<td align=center><b>0-1</b></td> +<td align=center><b>0-1</b></td> +<td> </td> +</tr> +<tr> +<td><b>D</b> <i>date-time-stamp</i></td> +<td align=center><b>1</b></td> +<td> </td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +</tr> +<tr> +<td><b>E</b> <i>technote-time technote-id</i></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td> </td> +</tr> +<tr> +<td><b>F</b> <i>filename</i> ?<i>uuid</i>? ?<i>permissions</i>? ?<i>oldname</i>?</td> +<td align=center><b>0+</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>G</b> <i>thread-root</i></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b></td> +</tr> +<tr> +<td><b>H</b> <i>thread-title</i></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b><sup><nowiki>[4]</nowiki></sup></td> +</tr> +<tr> +<td><b>I</b> <i>in-reply-to</i></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b><sup><nowiki>[4]</nowiki></sup></td> +</tr> +<tr> +<td><b>J</b> <i>name</i> ?<i>value</i>?</td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1+</b></td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>K</b> <i>ticket-uuid</i></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>L</b> <i>wiki-title</i></td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>M</b> <i>uuid</i></td> +<td> </td> +<td align=center><b>1+</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>N</b> <i>mimetype</i></td> +<td align=center><b>0-1</b></td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b></td> +<td> </td> +<td align=center><b>0-1</b></td> +<td align=center><b>0-1</b></td> +<td align=center><b>0-1</b></td> +</tr> +<tr> +<td><b>P</b> <i>uuid ...</i></td> +<td align=center><b>0-1</b></td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b></td> +<td> </td> +<td> </td> +<td align=center><b>0-1</b></td> +<td align=center><b>0-1</b><sup><nowiki>[5]</nowiki></sup></td> +</tr> +<tr> +<td><b>Q</b> (<b>+</b>|<b>-</b>)<i>uuid</i> ?<i>uuid</i>?</td> +<td align=center><b>0+</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +</tr> +<tr> +<td><b>R</b> <i>md5sum</i></td> +<td align=center><b>0-1</b></td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<td> </td> +<tr> +<td><b>T</b> (<b>+</b>|<b>*</b>|<b>-</b>)<i>tagname</i> <i>uuid</i> ?<i>value</i>?<sup><nowiki>[1]</nowiki></sup></td> +<td align=center><b>0+</b></td> +<td> </td> +<td align=center><b>1+</b><sup><nowiki>[2]</nowiki></sup></td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>0+</b><sup><nowiki>[3]</nowiki></sup></td> +<td> </td> +</tr> +<tr> +<td><b>U</b> <i>username</i></td> +<td align=center><b>1</b></td> +<td> </td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>0-1</b></td> +<td align=center><b>0-1</b></td> +<td align=center><b>1</b></td> +</tr> +<tr> +<td><b>W</b> <i>size</i> <b>\n</b> <i>text</i> <b>\n</b></td> +<td> </td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td> </td> +<td> </td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +</tr> +<tr> +<td><b>Z</b> <i>md5sum</i></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +<td align=center><b>1</b></td> +</tr> +</table> + +Footnotes: + +1) T-card names may not be made up of only hexadecimal characters, as + they would be indistinguishable from a hash prefix. + +2) Tags in [#ctrl | Control Artifacts] may not be + self-referential. i.e. their target hash may not be <tt>*</tt>. + +3) Tags in [#event | Technotes] must be self-referential. i.e. their + target hash must be <tt>*</tt>. Similarly, technote tags may only + be non-propagating "add" tags. i.e. their name prefix must be + <tt>+</tt>. + +4) [#forum | Forum Posts] must have either one H-card or one + I-card, not both. + +5) [#forum | Forum Post] P-cards may have only a single parent + hash. i.e. they may not have merge parents. + +<h2 id="addenda">4.0 Addenda</h2> + +This section contains additional information which may be useful when +implementing algorithms described above. + +<h3 id="outofordercards">4.1 Relaxed Card Ordering Due To An Historical Bug</h3> + +All cards of a structural artifact should be in lexicographical order. +The Fossil implementation verifies this and rejects any structural +artifact which has out-of-order cards. Futhermore, when Fossil is +generating new structural artifacts, it runs the generated artifact +through the parser to confirm that all cards really are in the correct +order before committing the transaction. In this way, Fossil prevents +bugs in the code from accidentally inserting misformatted artifacts. +The test parse of newly created artifacts is part of the +[./selfcheck.wiki|self-check strategy] of Fossil. It takes a +few more CPU cycles to double check each artifact before inserting it. +The developers consider those CPU cycles well-spent. + +However, the card-order safety check was accidentally disabled due to +[15d04de574383d61|a bug]. +And while that bug was lurking undetected in the code, +[5e67a7f4041a36ad|another bug] caused the N cards of Technical Notes +to occur after the P card rather than before. +Thus for a span of several years, Technical Note artifacts were being +inserted into Fossil repositories that had their N and P cards in the +wrong order. + +Both bugs have now been fixed. However, to prevent historical +Technical Note artifacts that were inserted by users in good faith +from being rejected by newer Fossil builds, the card ordering +requirement is relaxed slightly. The actual implementation is this: + +<p class=blockquote> +"All cards must be in strict lexicographic order, except that the +N and P cards of a Technical Note artifact are allowed to be +interchanged." +</p> + +Future versions of Fossil might strengthen this slightly to only allow +the out of order N and P cards for Technical Notes entered before +a certain date. + +<h3>4.2 R-Card Hash Calculation</h3> + +Given a manifest file named <tt>MF</tt>, the following Bash shell code +demonstrates how to compute the value of the <b>R</b> card in that manifest. +This example uses manifest [28987096ac]. Lines starting with <tt>#</tt> are +shell input and other lines are output. This demonstration assumes that the +file versions represented by the input manifest are checked out +under the current directory. + +<nowiki><pre> +# head MF +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Make\sthe\s"clearsign"\sPGP\ssigning\sdefault\sto\soff. +D 2010-02-23T15:33:14 +F BUILD.txt 4f7988767e4e48b29f7eddd0e2cdea4555b9161c +F COPYRIGHT-GPL2.txt 06877624ea5c77efe3b7e39b0f909eda6e25a4ec +... + +# grep '^R ' MF +R c0788982781981c96a0d81465fec7192 + +# for i in $(awk '/^F /{print $2}' MF); do \ + echo $i $(stat -c '%s' $i); \ + cat $i; \ +done | md5sum +c0788982781981c96a0d81465fec7192 - +</pre></nowiki> + +Minor caveats: the above demonstration will work only when none of the +filenames in the manifest are "fossilized" (encoded) because they contain +spaces. In that case the shell-generated hash would differ because the +<tt>stat</tt> calls will fail to find such files (which are output in encoded +form here). That approach also won't work for delta manifests. Calculating +the <b>R</b> card for delta manifests requires traversing both the delta and its baseline in +lexical order of the files, preferring the delta's copy if both contain +a given file. |
