Fossil

Check-in [a3be0b80]
Login

Check-in [a3be0b80]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge documentation typo fixes by BrickViking.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: a3be0b80cebcbeccfc53a8412ab935910ac42312c81b2d715a90761bda75c43c
User & Date: drh 2024-10-30 10:39:11
Context
2024-10-30
21:25
Merge from bv-corrections01 ... (check-in: c0654b13 user: brickviking tags: trunk)
13:21
Add ability to sign check-ins with ssh. ... (check-in: bbed5d8d user: danield tags: ssh-signing)
10:39
Merge documentation typo fixes by BrickViking. ... (check-in: a3be0b80 user: drh tags: trunk)
2024-10-29
23:50
Changes for the following files: www/json-api/api-checkout.md www/json-api/api-finfo.md www/json-api/api-query.md www/json-api/api-tag.md ... (check-in: d1251174 user: brickviking tags: bv-corrections01)
2024-10-28
19:17
Fix an issue with "fossil patch pull" on Windows when multiple files are being deleted by the patch. ... (check-in: 8beffa1e user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to www/caps/index.md.

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
defeated because your user has [**Setup**][s] capability on both sides
of the sync. Be aware that those file checks do still matter, however:
Fossil requires write access to a repo DB while cloning from it, so you
can’t clone from a read-only repo DB file over a local file path.

Even more surprising to you may be the fact that user caps do not affect
cloning and syncing over SSH! (Not unless you go [out of your way][sshfc]
patch around it, at any rate.) When you make a change to such a
repository, the stock Fossil behavior is that the change first goes to the
local repo clone where file system
permissions are all that matter, but then upon sync, the situation is
effectively the same as when the parent repo is on the local file
system. The reason behind this is that if you can log into the remote
system over SSH and that user has the necessary file system permissions
on that remote repo DB file to allow clone and sync operations, then







|







292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
defeated because your user has [**Setup**][s] capability on both sides
of the sync. Be aware that those file checks do still matter, however:
Fossil requires write access to a repo DB while cloning from it, so you
can’t clone from a read-only repo DB file over a local file path.

Even more surprising to you may be the fact that user caps do not affect
cloning and syncing over SSH! (Not unless you go [out of your way][sshfc]
to patch around it, at any rate.) When you make a change to such a
repository, the stock Fossil behavior is that the change first goes to the
local repo clone where file system
permissions are all that matter, but then upon sync, the situation is
effectively the same as when the parent repo is on the local file
system. The reason behind this is that if you can log into the remote
system over SSH and that user has the necessary file system permissions
on that remote repo DB file to allow clone and sync operations, then

Changes to www/custom_ticket.wiki.

80
81
82
83
84
85
86

87
88
89
90
91
92

93
94
95
96
97
98
99

<h2>Modify the 'view ticket' page</h2>

Look for the text "Contact:" (about halfway through).  Then insert these lines
after the closing tr tag and before the "enable_output" line:

<verbatim>

<td align="right">Assigned to:</td><td bgcolor="#d0d0d0">
  $<assigned_to>
</td>
<td align="right">Opened by:</td><td bgcolor="#d0d0d0">
  $<opened_by>
</td>

</verbatim>

This will add a row which displays these two fields, in the event the user has
<a href="./caps/ref.html#w">ticket "edit" capability</a>.

<h2>Modify the 'edit ticket' page</h2>








>
|
|
|
|
|
|
>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

<h2>Modify the 'view ticket' page</h2>

Look for the text "Contact:" (about halfway through).  Then insert these lines
after the closing tr tag and before the "enable_output" line:

<verbatim>
<tr>
  <td align="right">Assigned to:</td><td bgcolor="#d0d0d0">
    $<assigned_to>
  </td>
  <td align="right">Opened by:</td><td bgcolor="#d0d0d0">
    $<opened_by>
  </td>
</tr>
</verbatim>

This will add a row which displays these two fields, in the event the user has
<a href="./caps/ref.html#w">ticket "edit" capability</a>.

<h2>Modify the 'edit ticket' page</h2>

Changes to www/json-api/api-artifact.md.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

<a id="file"></a>
# File Artifacts

Fetches information about file artifacts.

**FIXME:** the content type guessing is currently very primitive, and
may (but i haven't seen this) mis-diagnose some non-binary files as
binary. Fossil doesn't yet have a mechanism for mime-type mappings.

**Status:** implemented 20111020

**Required permissions:** "o"

**Request:** `/json/artifact/FILE_HASH`







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

<a id="file"></a>
# File Artifacts

Fetches information about file artifacts.

**FIXME:** the content type guessing is currently very primitive, and
may (but I haven't seen this) mis-diagnose some non-binary files as
binary. Fossil doesn't yet have a mechanism for mime-type mappings.

**Status:** implemented 20111020

**Required permissions:** "o"

**Request:** `/json/artifact/FILE_HASH`

Changes to www/json-api/api-auth.md.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
the top-level POST request envelope) to prove to fossil that they are
authorized to access the requested resources. For most intents and
purposes, the "auth token" and the "login cookie" are the same thing (or
serve the same purpose), and the auth token is in fact just the value
part of the login cookie (which has a project-specific key).

Note that fossil has two conventional user names which can show up in
various response but do not refer to specific people: nobody and
anonymous. The nobody user is anyone who is not logged in. The anonymous
user is logged in but has no persistent user data (no associated user
name, email address, or similar). Normally the guest (nobody) user has
more access restrictions. The distinction between the two is largely
historical - it is a mechanism to keep bots from following the
multitudes of links generated by the HTML interface (especially the ZIP
files), while allowing interested users to do so by logging in as the







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
the top-level POST request envelope) to prove to fossil that they are
authorized to access the requested resources. For most intents and
purposes, the "auth token" and the "login cookie" are the same thing (or
serve the same purpose), and the auth token is in fact just the value
part of the login cookie (which has a project-specific key).

Note that fossil has two conventional user names which can show up in
various responses but do not refer to specific people: nobody and
anonymous. The nobody user is anyone who is not logged in. The anonymous
user is logged in but has no persistent user data (no associated user
name, email address, or similar). Normally the guest (nobody) user has
more access restrictions. The distinction between the two is largely
historical - it is a mechanism to keep bots from following the
multitudes of links generated by the HTML interface (especially the ZIP
files), while allowing interested users to do so by logging in as the
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
request envelope or as a GET parameter, and it *must* be given if the
request requires restricted access to a resource. e.g. if reading
tickets is disabled for the guest user then all non-guest users must
send authentication info in their requests in order to be able to fetch
ticket info.

Cookie-aware clients should send the login-generated cookie with each
request, in which case they do not need explicitly include the
`authToken` in the JSON envelope/GET arguments. If submitted, the
`authToken` is used, otherwise the cookie, if set, is used. Note that
fossil uses a project-dependent cookie name in order to help thwart
attacks, so there is no simple mapping of cookie *name* to auth
token. That said, the cookie's *value* is also the auth token's value.

> Special case: when accessing fossil over a local server instance







|







156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
request envelope or as a GET parameter, and it *must* be given if the
request requires restricted access to a resource. e.g. if reading
tickets is disabled for the guest user then all non-guest users must
send authentication info in their requests in order to be able to fetch
ticket info.

Cookie-aware clients should send the login-generated cookie with each
request, in which case they do not need to explicitly include the
`authToken` in the JSON envelope/GET arguments. If submitted, the
`authToken` is used, otherwise the cookie, if set, is used. Note that
fossil uses a project-dependent cookie name in order to help thwart
attacks, so there is no simple mapping of cookie *name* to auth
token. That said, the cookie's *value* is also the auth token's value.

> Special case: when accessing fossil over a local server instance
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
non-anonymous login except that extra "anonymousSeed" property is
required.

The password value *may* be time-limited, and *may* eventually become
invalidated due to old age. This is unspecified.

***Potential***** (low-probability) bug regarding the seed value:** from
what i hear, some unusual JSON platforms don't support full 32-bit
precision. If absolutely necessary we could chop off a bit or two from
the seed value (*if* it ever becomes a problem and if DRH blesses it).
Or we could just make it a double.


<a id="logout"></a>
# Logout







|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
non-anonymous login except that extra "anonymousSeed" property is
required.

The password value *may* be time-limited, and *may* eventually become
invalidated due to old age. This is unspecified.

***Potential***** (low-probability) bug regarding the seed value:** from
what I hear, some unusual JSON platforms don't support full 32-bit
precision. If absolutely necessary we could chop off a bit or two from
the seed value (*if* it ever becomes a problem and if DRH blesses it).
Or we could just make it a double.


<a id="logout"></a>
# Logout

Changes to www/json-api/api-checkout.md.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# JSON API: /status
([&#x2b11;JSON API Index](index.md))

# Status of Local Checkout

**Status:** implemented 20130223

**Required permissions:** n/a (local access only)

**Request:** `/json/status`

This command requires a local checkout and is analog to the "fossil
status" command.

**Request Options:** currently none.

Payload example:

```json











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# JSON API: /status
([&#x2b11;JSON API Index](index.md))

# Status of Local Checkout

**Status:** implemented 20130223

**Required permissions:** n/a (local access only)

**Request:** `/json/status`

This command requires a local checkout and is the analog to the "fossil
status" command.

**Request Options:** currently none.

Payload example:

```json

Changes to www/json-api/api-finfo.md.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    CLI mode: `--name` or positional argument.
-   `checkin=string`. Only return info related to this specific checkin,
    as opposed to listing all checkins. If set, neither "before" nor
    "after" have any effect.\  
    CLI mode: `--checkin|-ci`
-   `before=DATETIME` only lists checkins from on or before this time.\  
    CLI mode: `--before|-b`
-   `after=DATETIME` only lists checkins from on or before this time.
    Using this option swaps the sort order, to provide reasonable
    behaviour in conjunction with the limit option.\  
    Only one of "before" and "after" may be specified, and if both are
    specified then which one takes precedence is unspecified.\  
    CLI mode: `--after|-a`
-   `limit=integer` limits the output to (at most) the given number of
    associated checkins.\  







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
    CLI mode: `--name` or positional argument.
-   `checkin=string`. Only return info related to this specific checkin,
    as opposed to listing all checkins. If set, neither "before" nor
    "after" have any effect.\  
    CLI mode: `--checkin|-ci`
-   `before=DATETIME` only lists checkins from on or before this time.\  
    CLI mode: `--before|-b`
-   `after=DATETIME` only lists checkins from on or after this time.
    Using this option swaps the sort order, to provide reasonable
    behaviour in conjunction with the limit option.\  
    Only one of "before" and "after" may be specified, and if both are
    specified then which one takes precedence is unspecified.\  
    CLI mode: `--after|-a`
-   `limit=integer` limits the output to (at most) the given number of
    associated checkins.\  

Changes to www/json-api/api-query.md.

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    "mtime":1303870798,
   },
  …
  ]
}
```

The column names are provided in a separate field is because their order
is guaranteed to match the order of the query columns, whereas object
key/value pairs might get reordered (typically sorted by key) when
travelling through different JSON implementations. In this manner,
clients can e.g. be sure to render the columns in the proper
(query-specified) order.

When in "array" mode the "rows" results will be an array of arrays. For
example, the above "rows" property would instead look like:

`[ [1, "drh", "All Tickets", 1303870798, … ], … ]`

Note the column *names* are never *guaranteed* to be exactly as they
appear in the SQL *unless* they are qualified with an AS, e.g. `SELECT
foo AS foo...`. When generating reports which need fixed column names, it
is highly recommended to use an AS qualifier for every column, even if
they use the same name as the column. This is the only way to guaranty
that the result column names will be stable. (FYI: that behaviour comes
from sqlite3, not the JSON bits, and this behaviour *has* been known to
change between sqlite3 versions (so this is not just an idle threat of
*potential* future incompatibility).)







|















|




58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    "mtime":1303870798,
   },
  …
  ]
}
```

The column names are provided in a separate field because their order
is guaranteed to match the order of the query columns, whereas object
key/value pairs might get reordered (typically sorted by key) when
travelling through different JSON implementations. In this manner,
clients can e.g. be sure to render the columns in the proper
(query-specified) order.

When in "array" mode the "rows" results will be an array of arrays. For
example, the above "rows" property would instead look like:

`[ [1, "drh", "All Tickets", 1303870798, … ], … ]`

Note the column *names* are never *guaranteed* to be exactly as they
appear in the SQL *unless* they are qualified with an AS, e.g. `SELECT
foo AS foo...`. When generating reports which need fixed column names, it
is highly recommended to use an AS qualifier for every column, even if
they use the same name as the column. This is the only way to guarantee
that the result column names will be stable. (FYI: that behaviour comes
from sqlite3, not the JSON bits, and this behaviour *has* been known to
change between sqlite3 versions (so this is not just an idle threat of
*potential* future incompatibility).)

Changes to www/json-api/api-tag.md.

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

-   `name=string` The tag name to search for. Can optionally be the 3rd
    path element.
-   `limit=int` (defalt=0) Limits the number of results (0=no limit).
    Since they are ordered from oldest to newest, the newest N results
    will be returned.
-   `type=string` (default=`*`) Searches only for the given type of
    artifact (using fossil's conventional type naming: ci, e, t, w.
-   `raw=bool` (=false) If enabled, the response is an array of hashes
    of the requested artifact type; otherwise,
    it is an array of higher-level objects. If this is
    true, the "name" property is interpretted as-is. If it is false, the
    name is automatically prepended with "sym-" (meaning a branch).
    (FIXME: the current semantics are confusing and hard to remember.
    Re-do them.)

**Response payload example, in RAW mode: (expect this format to change
at some point!)**








|



|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

-   `name=string` The tag name to search for. Can optionally be the 3rd
    path element.
-   `limit=int` (defalt=0) Limits the number of results (0=no limit).
    Since they are ordered from oldest to newest, the newest N results
    will be returned.
-   `type=string` (default=`*`) Searches only for the given type of
    artifact (using fossil's conventional type naming: ci, e, t, w.)
-   `raw=bool` (=false) If enabled, the response is an array of hashes
    of the requested artifact type; otherwise,
    it is an array of higher-level objects. If this is
    true, the "name" property is interpreted as-is. If it is false, the
    name is automatically prepended with "sym-" (meaning a branch).
    (FIXME: the current semantics are confusing and hard to remember.
    Re-do them.)

**Response payload example, in RAW mode: (expect this format to change
at some point!)**

Changes to www/json-api/conventions.md.

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  using the given name. e.g. if `jsonp=foo` then the result would look like:\  
`foo( {...the response envelope...} )`

The API allows most of those (normally all but the payload) to come in
as either GET parameters or properties of the top-level POSTed request
JSON envelope, with GET taking priority over POST. (Reminder to self: we
could potentially also use values from cookies. Fossil currently only
uses 1 cookie (the login token), and i'd prefer to keep it that way.)

POST requests without such an envelope will be rejected, generating a
Fossil/JSON error response (as opposed to an HTTP error response). GET
requests, by definition, never have an envelope.

POSTed client requests *must* send a Content-Type header of either
`application/json` , `application/javascript`, or `text/plain`, or the







|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  using the given name. e.g. if `jsonp=foo` then the result would look like:\  
`foo( {...the response envelope...} )`

The API allows most of those (normally all but the payload) to come in
as either GET parameters or properties of the top-level POSTed request
JSON envelope, with GET taking priority over POST. (Reminder to self: we
could potentially also use values from cookies. Fossil currently only
uses 1 cookie (the login token), and I'd prefer to keep it that way.)

POST requests without such an envelope will be rejected, generating a
Fossil/JSON error response (as opposed to an HTTP error response). GET
requests, by definition, never have an envelope.

POSTed client requests *must* send a Content-Type header of either
`application/json` , `application/javascript`, or `text/plain`, or the
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
conversions behave.

No higher-level constructs, e.g. JSON **arrays** or **objects**, are
accepted in string form. Such parameters must be set in the POST
envelope or payload, as specified by the specific API.

This API does not currently use any **floating-point** parameters, but
does return floating-point results in a couple places.

For **integer** parameters we use a conventional string-to-int algorithm
and assume base 10 (analog to atoi(3)). The API may err on the side of
usability when given technically invalid values. e.g. "123abc" will
likely be interpreted as the integer 123. No APIs currently rely on
integer parameters with more than 32 bits (signedness is call-dependent
but few, if any, use negative values).







|







167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
conversions behave.

No higher-level constructs, e.g. JSON **arrays** or **objects**, are
accepted in string form. Such parameters must be set in the POST
envelope or payload, as specified by the specific API.

This API does not currently use any **floating-point** parameters, but
does return floating-point results in a couple of places.

For **integer** parameters we use a conventional string-to-int algorithm
and assume base 10 (analog to atoi(3)). The API may err on the side of
usability when given technically invalid values. e.g. "123abc" will
likely be interpreted as the integer 123. No APIs currently rely on
integer parameters with more than 32 bits (signedness is call-dependent
but few, if any, use negative values).
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
TODO: consider changing the GET-value-to-bool semantics to match the JS
semantics, for consistency (within the JSON API at least, but that might
cause inconsistencies vis-a-vis the HTML interface).

<a id="response-envelope"></a>
# Response Envelope

Every response comes in the form of a HTTP response or (in CLI mode)
JSON sent to stdout. The body of the response is a JSON object following
a common envelope format. The envelope has the following properties:


- `fossil`: Fossil server version string. This property is basically
  "the official response envelope marker" - if it is set, clients can
  "probably safely assume" that the object indeed came from one of the
  Fossil/JSON APIs. This API never creates responses which do not
  contain this property.
- `requestId`: Only set if the request contained it, and then it is
  echoed back to the caller as-is. This can be use to determine
  (client-side) which request a given response is coming in for
  (assuming multiple asynchronous requests are pending). In practice
  this generally isn’t needed because response handling tends to be
  done by closures associated with the original request object (at
  least in JavaScript code). In languages without closures it might
  have some use. It may be any legal JSON value - it need not be
  confined to a string or number.
- `resultCode`: Standardized result code string in the form
  `FOSSIL-####`. Only error responses contain a `resultCode`.
- `resultText`: Possibly a descriptive string, possibly
  empty. Supplements the resultCode, but can also be set on success
  responses (but normally isn't). Clients must not rely on any
  specific values being set here.
- `payload`: Request-specific response payload (data type/structure is
  request-specific).  The payload is never set for error responses,
  only for success responses (and only those which actually have a
  payload - not all do).
- `timestamp`: Response timestamp (GMT Unix Epoch). We use seconds
  precision because i did not know at the time that Fossil actually
  records millisecond precision.
- `payloadVersion`: Not initially needed, but reserved for future use
  in maintaining version compatibility when the format of a given
  response type's payload changes. If needed, the "first version"
  value is assumed to be 0, for semantic [near-]compatibility with the
  undefined value clients see when this property is not set.
- `command`: Normalized form of the command being run. It consists of







|










|


















|







203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
TODO: consider changing the GET-value-to-bool semantics to match the JS
semantics, for consistency (within the JSON API at least, but that might
cause inconsistencies vis-a-vis the HTML interface).

<a id="response-envelope"></a>
# Response Envelope

Every response comes in the form of an HTTP response or (in CLI mode)
JSON sent to stdout. The body of the response is a JSON object following
a common envelope format. The envelope has the following properties:


- `fossil`: Fossil server version string. This property is basically
  "the official response envelope marker" - if it is set, clients can
  "probably safely assume" that the object indeed came from one of the
  Fossil/JSON APIs. This API never creates responses which do not
  contain this property.
- `requestId`: Only set if the request contained it, and then it is
  echoed back to the caller as-is. This can be used to determine
  (client-side) which request a given response is coming in for
  (assuming multiple asynchronous requests are pending). In practice
  this generally isn’t needed because response handling tends to be
  done by closures associated with the original request object (at
  least in JavaScript code). In languages without closures it might
  have some use. It may be any legal JSON value - it need not be
  confined to a string or number.
- `resultCode`: Standardized result code string in the form
  `FOSSIL-####`. Only error responses contain a `resultCode`.
- `resultText`: Possibly a descriptive string, possibly
  empty. Supplements the resultCode, but can also be set on success
  responses (but normally isn't). Clients must not rely on any
  specific values being set here.
- `payload`: Request-specific response payload (data type/structure is
  request-specific).  The payload is never set for error responses,
  only for success responses (and only those which actually have a
  payload - not all do).
- `timestamp`: Response timestamp (GMT Unix Epoch). We use seconds
  precision because I did not know at the time that Fossil actually
  records millisecond precision.
- `payloadVersion`: Not initially needed, but reserved for future use
  in maintaining version compatibility when the format of a given
  response type's payload changes. If needed, the "first version"
  value is assumed to be 0, for semantic [near-]compatibility with the
  undefined value clients see when this property is not set.
- `command`: Normalized form of the command being run. It consists of
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
can filter the output to globally replace ASCII 9dec (TAB) with ASCII
32dec (space). Because JSON string values *never* contain hard tabs
(they are represented by `\t`) there is no chance that such a global
replacement will corrupt JSON string contents - only the formatting will
be affected.

Potential TODO: because extraneous indention "could potentially" be used
as a form DoS, the option *might* be subject to later removed from HTTP
mode (in CLI it's fine).

In HTTP mode no trailing newline is added to the output, whereas in CLI
mode one is normally appended (exception: in JSONP mode no newline is
appended, to (rather pedantically and arbitraily) allow the client to
add a semicolon at the end if he likes). There is currently no option to
control the newline behaviour, but the underlying JSON code supports







|







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
can filter the output to globally replace ASCII 9dec (TAB) with ASCII
32dec (space). Because JSON string values *never* contain hard tabs
(they are represented by `\t`) there is no chance that such a global
replacement will corrupt JSON string contents - only the formatting will
be affected.

Potential TODO: because extraneous indention "could potentially" be used
as a form of DoS, the option *might* be subject to later removal from HTTP
mode (in CLI it's fine).

In HTTP mode no trailing newline is added to the output, whereas in CLI
mode one is normally appended (exception: in JSONP mode no newline is
appended, to (rather pedantically and arbitraily) allow the client to
add a semicolon at the end if he likes). There is currently no option to
control the newline behaviour, but the underlying JSON code supports
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    admins consider error messages to be security-relevant and like to
    "dumb them down" on their way to the client, whereas developers
    normally want to see very specific error codes when tracking down a
    problem. We can offer a configuration option to "dumb down" error
    codes to their generic category by simply doing a modulo 100
    (or 1000) against the native error code number. e.g. FOSSIL-1271
    could (via a simple modulo) be reduced to FOSSIL-1200 or
    FOSSIL-1000, depending on the paranoia level of the sysadmin. i have
    tried to order the result code numbers so that a dumb-down level of
    2 provides reasonably usable results without giving away too much
    detail to malicious clients.\
    (**TODO:** `g.json.errorDetailParanoia` is used to set the
    default dumb-down level, but it is currently set at compile-time.
    It needs to be moved to a config option. We have a chicken/egg scenario
    with error reporting and db access there (where the config is







|







480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
    admins consider error messages to be security-relevant and like to
    "dumb them down" on their way to the client, whereas developers
    normally want to see very specific error codes when tracking down a
    problem. We can offer a configuration option to "dumb down" error
    codes to their generic category by simply doing a modulo 100
    (or 1000) against the native error code number. e.g. FOSSIL-1271
    could (via a simple modulo) be reduced to FOSSIL-1200 or
    FOSSIL-1000, depending on the paranoia level of the sysadmin. I have
    tried to order the result code numbers so that a dumb-down level of
    2 provides reasonably usable results without giving away too much
    detail to malicious clients.\
    (**TODO:** `g.json.errorDetailParanoia` is used to set the
    default dumb-down level, but it is currently set at compile-time.
    It needs to be moved to a config option. We have a chicken/egg scenario
    with error reporting and db access there (where the config is
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
- `FOSSIL-1104`: RE-USE
- `FOSSIL-1105`: A server-side timeout was reached. (i’m not sure we
  can actually implement this one, though.)
- `FOSSIL-1106`: Assertion failed (or would have had we
  continued). Note: if an `assert()` fails in CGI/server modes, the HTTP
  response will be code 500 (Internal Server Error). We want to avoid
  that and return a JSON response instead. All of that said - there seems
  to be little reason to implementi this, since assertions are "truly
  serious" errors.
- `FOSSIL-1107`: Allocation/out of memory error. This cannot be reasonably
  reported because fossil aborts if an allocation fails.
- `FOSSIL-1108`: Requested API is not yet implemented.
- `FOSSIL-1109`: Panic! Fossil's `fossil_panic()` or `cgi_panic()` was
  called. In non-JSON HTML mode this produces an HTTP 500
  error. Clients "should" report this as a potential bug, as it







|







531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
- `FOSSIL-1104`: RE-USE
- `FOSSIL-1105`: A server-side timeout was reached. (i’m not sure we
  can actually implement this one, though.)
- `FOSSIL-1106`: Assertion failed (or would have had we
  continued). Note: if an `assert()` fails in CGI/server modes, the HTTP
  response will be code 500 (Internal Server Error). We want to avoid
  that and return a JSON response instead. All of that said - there seems
  to be little reason to implement this, since assertions are "truly
  serious" errors.
- `FOSSIL-1107`: Allocation/out of memory error. This cannot be reasonably
  reported because fossil aborts if an allocation fails.
- `FOSSIL-1108`: Requested API is not yet implemented.
- `FOSSIL-1109`: Panic! Fossil's `fossil_panic()` or `cgi_panic()` was
  called. In non-JSON HTML mode this produces an HTTP 500
  error. Clients "should" report this as a potential bug, as it

Changes to www/json-api/hacking.md.

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
foregoes fossil's conventional command/path dispatching mechanism. Only
the top-most "json" command/path is dispatched directly by fossil's
core. The disadvantages of this are that we lose fossil's conventional
help text mechanism (which is based on code comments in the
command/path's dispatcher impl) and the ability to write abbreviated
command names in CLI mode ("json" itself may be abbreviated, but not the
subcommands). The advantages are that we can handle CLI/HTTP modes
almost identically (there are a couple minor differences) by unifying
them under the same callback functions much more easily.

The top-level "json" command/path uses its own dispatching mechanism
which uses either the path (in HTTP mode) or CLI positional arguments to
dispatch commands (stopping at the first "flag option" (e.g. -foo) in
CLI mode). The command handlers are simply callback functions which
return a cson\_value pointer (the C representation of an arbitrary JSON







|







77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
foregoes fossil's conventional command/path dispatching mechanism. Only
the top-most "json" command/path is dispatched directly by fossil's
core. The disadvantages of this are that we lose fossil's conventional
help text mechanism (which is based on code comments in the
command/path's dispatcher impl) and the ability to write abbreviated
command names in CLI mode ("json" itself may be abbreviated, but not the
subcommands). The advantages are that we can handle CLI/HTTP modes
almost identically (there are a couple of minor differences) by unifying
them under the same callback functions much more easily.

The top-level "json" command/path uses its own dispatching mechanism
which uses either the path (in HTTP mode) or CLI positional arguments to
dispatch commands (stopping at the first "flag option" (e.g. -foo) in
CLI mode). The command handlers are simply callback functions which
return a cson\_value pointer (the C representation of an arbitrary JSON
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
they will exit differently. Because of this, it is perfectly fine for a
command handler to exit via one of fossil's conventional mechanisms
(e.g. `db_prepare()` can be fatal, and callbacks may call `fossil_panic()`
if they really want to). One exception is `fossil_exit()`, which does
_not_ generate any extra output and will `exit()` the app. In the JSON
API, as a rule of thumb, `fossil_exit()` is only used when we *want* a
failed request to cause an HTTP 500 error, and it is reserved for
allocation errors and similar truly catostrophic failures. That said...
libcson has been hacked to use `fossil_alloc()` and friends for memory
management, and those routines exit on error, so alloc error handling in
the JSON command handler code can afford to be a little lax (the
majority of *potential* errors clients get from the cson API have
allocation failure as their root cause).

As a side-note: the vast majority (if not all) of the cson API calls are







|







123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
they will exit differently. Because of this, it is perfectly fine for a
command handler to exit via one of fossil's conventional mechanisms
(e.g. `db_prepare()` can be fatal, and callbacks may call `fossil_panic()`
if they really want to). One exception is `fossil_exit()`, which does
_not_ generate any extra output and will `exit()` the app. In the JSON
API, as a rule of thumb, `fossil_exit()` is only used when we *want* a
failed request to cause an HTTP 500 error, and it is reserved for
allocation errors and similar truly catastrophic failures. That said...
libcson has been hacked to use `fossil_alloc()` and friends for memory
management, and those routines exit on error, so alloc error handling in
the JSON command handler code can afford to be a little lax (the
majority of *potential* errors clients get from the cson API have
allocation failure as their root cause).

As a side-note: the vast majority (if not all) of the cson API calls are
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
functions which behave ever so slightly differently. A summary:

-   `json_getenv()` and `json_getenv_TYPE()` search the so-called "JSON
    environment," which is a superset of the GET/POST/`POST.payload` (if
    `POST.payload` is-a Object).
-   `json_find_option_TYPE()`: searches the CLI args (only when in CLI
    mode) and the JSON environment.
-   The use of fossil's `P()` and `PD()` macros is discourages in JSON
    callbacks because they can only handle String data from the CLI or
    GET parameters (not POST/`POST.payload`). (Note that `P()` and `PD()`
    *normally* also handle POSTed keys, but they only "see" values
    posted as form-urlencoded fields, and not JSON format.)
-   `find_option()` (from `src/main.c`) "should" also be avoided in
    JSON API handlers because it removes flag from the g.argv
    arguments list. That said, the JSON API does use `find_option()` in
    several of its option-finding convenience wrappers.

For example code: the existing command callbacks demonstrate all kinds
of uses and the various styles of parameter/option inspection. Check out
any of the functions named `json_page_SOMETHING()`.

<a href="creating-json"></a>
# Creating JSON Data

<a href="creating-json-values"></a>
## Creating JSON Values

cson has a fairly rich API for creating and manipulating the various
JSON-defined value types. For a detailed overview and demonstration i
recommend reading:

[](https://fossil.wanderinghorse.net/wikis/cson/?page=HowTo)

That said, the Fossil/JSON API has several convenience wrappers to save
a few bytes of typing:








|




















|







257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
functions which behave ever so slightly differently. A summary:

-   `json_getenv()` and `json_getenv_TYPE()` search the so-called "JSON
    environment," which is a superset of the GET/POST/`POST.payload` (if
    `POST.payload` is-a Object).
-   `json_find_option_TYPE()`: searches the CLI args (only when in CLI
    mode) and the JSON environment.
-   The use of fossil's `P()` and `PD()` macros is discouraged in JSON
    callbacks because they can only handle String data from the CLI or
    GET parameters (not POST/`POST.payload`). (Note that `P()` and `PD()`
    *normally* also handle POSTed keys, but they only "see" values
    posted as form-urlencoded fields, and not JSON format.)
-   `find_option()` (from `src/main.c`) "should" also be avoided in
    JSON API handlers because it removes flag from the g.argv
    arguments list. That said, the JSON API does use `find_option()` in
    several of its option-finding convenience wrappers.

For example code: the existing command callbacks demonstrate all kinds
of uses and the various styles of parameter/option inspection. Check out
any of the functions named `json_page_SOMETHING()`.

<a href="creating-json"></a>
# Creating JSON Data

<a href="creating-json-values"></a>
## Creating JSON Values

cson has a fairly rich API for creating and manipulating the various
JSON-defined value types. For a detailed overview and demonstration I
recommend reading:

[](https://fossil.wanderinghorse.net/wikis/cson/?page=HowTo)

That said, the Fossil/JSON API has several convenience wrappers to save
a few bytes of typing:

308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

The `cson_sqlite3_xxx()` family of functions convert `sqlite3_stmt` rows
to Arrays or Objects, or convert single columns to a JSON-compatible
form. See `json_stmt_to_array_of_obj()`,
`json_stmt_to_array_of_array()` (both in `src/json.c`), and
`cson_sqlite3_column_to_value()` and friends (in
`extsrc/cson_amalgamation.h`). They work in an intuitive way for numeric
types, but they optimistically/natively *assume* that any fields of type
TEXT or BLOB are actually UTF8 data, and treat them as such. cson's
string class only handles UTF8 data and it is semantically illegal to
feed them anything but UTF8. Violating this will likely result in
down-stream errors (e.g. when emiting the JSON string output). **The
moral of this story is:** *do not use these APIs to fetch binary data*.
JSON doesn't do binary and the `cson_string` class does not
protect itself against clients feeding it non-UTF8 data.

Here's a basic example of using these features:

```c







|



|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326

The `cson_sqlite3_xxx()` family of functions convert `sqlite3_stmt` rows
to Arrays or Objects, or convert single columns to a JSON-compatible
form. See `json_stmt_to_array_of_obj()`,
`json_stmt_to_array_of_array()` (both in `src/json.c`), and
`cson_sqlite3_column_to_value()` and friends (in
`extsrc/cson_amalgamation.h`). They work in an intuitive way for numeric
types, but they optimistically/naively *assume* that any fields of type
TEXT or BLOB are actually UTF8 data, and treat them as such. cson's
string class only handles UTF8 data and it is semantically illegal to
feed them anything but UTF8. Violating this will likely result in
down-stream errors (e.g. when emitting the JSON string output). **The
moral of this story is:** *do not use these APIs to fetch binary data*.
JSON doesn't do binary and the `cson_string` class does not
protect itself against clients feeding it non-UTF8 data.

Here's a basic example of using these features:

```c
345
346
347
348
349
350
351
352
353
than they appear in the query (this is documented behaviour of sqlite3).
Because the JSON API needs to return stable field names, we need to use
AS clauses to be guaranteed that the db driver will return the column
names we want. Note that the AS clause is often used to translate column
names into something more JSON-conventional or user-friendly, e.g.
"SELECT cap AS capabilities...". Alternately, we can convert the
individual `sqlite3_stmt` column values to JSON using
`cson_sqlite3_column_to_value()`, without refering directly to the
db-reported column name.







|

345
346
347
348
349
350
351
352
353
than they appear in the query (this is documented behaviour of sqlite3).
Because the JSON API needs to return stable field names, we need to use
AS clauses to be guaranteed that the db driver will return the column
names we want. Note that the AS clause is often used to translate column
names into something more JSON-conventional or user-friendly, e.g.
"SELECT cap AS capabilities...". Alternately, we can convert the
individual `sqlite3_stmt` column values to JSON using
`cson_sqlite3_column_to_value()`, without referring directly to the
db-reported column name.

Changes to www/mdtest/test1.md.

1
2
3
4
5
6
7
8
9
10
# Markdown Link-test

This document exist solely as a test for some of the hyperlinking
capabilities of Markdown as implemented by Fossil.

## Relative-Path Links

  *   The index: [](../index.wiki)

  *   Load management: [](../loadmgmt.md)


|







1
2
3
4
5
6
7
8
9
10
# Markdown Link-test

This document exists solely as a test for some of the hyperlinking
capabilities of Markdown as implemented by Fossil.

## Relative-Path Links

  *   The index: [](../index.wiki)

  *   Load management: [](../loadmgmt.md)

Changes to www/server/debian/service.md.

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

Note the change of configuration directory from the `~/.local` directory
to the system level. We need to start this socket listener at the root
level because of the low-numbered TCP port restriction we brought up
above.

This configuration says more or less the same thing as the socket part
of an `inted` entry [exemplified elsewhere in this
documentation](../any/inetd.md).

Next, create the service definition file in that same directory as
`fossil@.service`:

```dosini
[Unit]







|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

Note the change of configuration directory from the `~/.local` directory
to the system level. We need to start this socket listener at the root
level because of the low-numbered TCP port restriction we brought up
above.

This configuration says more or less the same thing as the socket part
of an `inetd` entry [exemplified elsewhere in this
documentation](../any/inetd.md).

Next, create the service definition file in that same directory as
`fossil@.service`:

```dosini
[Unit]

Changes to www/server/openbsd/fastcgi.md.

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
files larger than this limit as unversioned content, you need to raise
the limit as we’ve done above with the “`connection max request body`”
setting, raising the limit to 100 MiB.

[dlim]: https://man.openbsd.org/httpd.conf.5#connection
[uv]:   ../../unvers.wiki

**NOTE:** If not already in possession of a HTTPS certificate, comment
out the `https` server block and proceed to securing a free
[Let's Encrypt Certificate](#letsencrypt); otherwise skip to
[Start `httpd`](#starthttpd).


## <a id="letsencrypt"></a>Let's Encrypt Certificate








|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
files larger than this limit as unversioned content, you need to raise
the limit as we’ve done above with the “`connection max request body`”
setting, raising the limit to 100 MiB.

[dlim]: https://man.openbsd.org/httpd.conf.5#connection
[uv]:   ../../unvers.wiki

**NOTE:** If not already in possession of an HTTPS certificate, comment
out the `https` server block and proceed to securing a free
[Let's Encrypt Certificate](#letsencrypt); otherwise skip to
[Start `httpd`](#starthttpd).


## <a id="letsencrypt"></a>Let's Encrypt Certificate

Changes to www/server/windows/service.md.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
```

This will create a windows service named 'Fossil-DSCM' running under the local
system account and accessible on port 8080 by default.  `fossil winsrv` can also
start, stop, and delete the service.  For all available options, please execute
`fossil help winsrv` on a windows install of Fossil.

If you wish to server a directory of repositories, the `fossil winsrv` command
requires a slightly different set of options vs. `fossil server`:

```
fossil winsrv create --repository D:/Path/to/Repos --repolist
```

### Choice of Directory Considerations







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
```

This will create a windows service named 'Fossil-DSCM' running under the local
system account and accessible on port 8080 by default.  `fossil winsrv` can also
start, stop, and delete the service.  For all available options, please execute
`fossil help winsrv` on a windows install of Fossil.

If you wish to serve a directory of repositories, the `fossil winsrv` command
requires a slightly different set of options vs. `fossil server`:

```
fossil winsrv create --repository D:/Path/to/Repos --repolist
```

### Choice of Directory Considerations

Changes to www/th1.md.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
TH1 is a string-processing language.  All values are strings.  Any numerical
operations are accomplished by converting from string to numeric, performing
the computation, then converting the result back into a string.  (This might
seem inefficient, but it is faster than people imagine, and numeric
computations do not come up very often for the kinds of work that TH1 does,
so it has never been a factor.)

A TH1 script consist of a sequence of commands.
Each command is terminated by the first *unescaped* newline or ";" character.
The text of the command (excluding the newline or semicolon terminator)
is broken into space-separated tokens.  The first token is the command
name and subsequent tokens are the arguments.  In this sense, TH1 syntax
is similar to the familiar command-line shell syntax.

A token is any sequence of characters other than whitespace and semicolons.







|







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
TH1 is a string-processing language.  All values are strings.  Any numerical
operations are accomplished by converting from string to numeric, performing
the computation, then converting the result back into a string.  (This might
seem inefficient, but it is faster than people imagine, and numeric
computations do not come up very often for the kinds of work that TH1 does,
so it has never been a factor.)

A TH1 script consists of a sequence of commands.
Each command is terminated by the first *unescaped* newline or ";" character.
The text of the command (excluding the newline or semicolon terminator)
is broken into space-separated tokens.  The first token is the command
name and subsequent tokens are the arguments.  In this sense, TH1 syntax
is similar to the familiar command-line shell syntax.

A token is any sequence of characters other than whitespace and semicolons.
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  *  capexpr CAPABILITY-EXPR

The capability expression is a list. Each term of the list is a
cluster of [capability letters](./caps/ref.html). 
The overall expression is true if any
one term is true. A single term is true if all letters within that
term are true. Or, if the term begins with "!", then the term is true
if none of the terms or true. Or, if the term begins with "@" then
the term is true if all of the capability letters in that term are
available to the "anonymous" user. Or, if the term is "*" then it is
always true.

Examples:

```







|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
  *  capexpr CAPABILITY-EXPR

The capability expression is a list. Each term of the list is a
cluster of [capability letters](./caps/ref.html). 
The overall expression is true if any
one term is true. A single term is true if all letters within that
term are true. Or, if the term begins with "!", then the term is true
if none of the terms are true. Or, if the term begins with "@" then
the term is true if all of the capability letters in that term are
available to the "anonymous" user. Or, if the term is "*" then it is
always true.

Examples:

```
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
             compile-time by `FOSSIL_HASH_DIGITS_URL`, defaults to 16).

<a id="date"></a>TH1 date Command
-----------------------------------

  *  date ?-local?

Return a strings which is the current time and date.  If the -local
option is used, the date appears using localtime instead of UTC.

<a id="decorate"></a>TH1 decorate Command
-------------------------------------------

  *  decorate STRING








|







381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
             compile-time by `FOSSIL_HASH_DIGITS_URL`, defaults to 16).

<a id="date"></a>TH1 date Command
-----------------------------------

  *  date ?-local?

Return a string which is the current time and date.  If the -local
option is used, the date appears using localtime instead of UTC.

<a id="decorate"></a>TH1 decorate Command
-------------------------------------------

  *  decorate STRING

568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
as a hidden element of the form.

<a id="linecount"></a>TH1 linecount Command
---------------------------------------------

  *  linecount STRING MAX MIN

Returns one more than the number of \n characters in STRING.  But
never returns less than MIN or more than MAX.

<a id="markdown"></a>TH1 markdown Command
-------------------------------------------

  *  markdown STRING








|







568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
as a hidden element of the form.

<a id="linecount"></a>TH1 linecount Command
---------------------------------------------

  *  linecount STRING MAX MIN

Returns one more than the number of `\n` characters in STRING.  But
never returns less than MIN or more than MAX.

<a id="markdown"></a>TH1 markdown Command
-------------------------------------------

  *  markdown STRING

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854

<a id="verifyCsrf"></a>TH1 verifyCsrf Command
-----------------------------------------------

  *  verifyCsrf

Before using the results of a form, first call this command to verify
that this Anti-CSRF token is present and is valid.  If the Anti-CSRF token
is missing or is incorrect, that indicates a cross-site scripting attack.
If the event of an attack is detected, an error message is generated and
all further processing is aborted.

<a id="verifyLogin"></a>TH1 verifyLogin Command
-------------------------------------------------








|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854

<a id="verifyCsrf"></a>TH1 verifyCsrf Command
-----------------------------------------------

  *  verifyCsrf

Before using the results of a form, first call this command to verify
that the Anti-CSRF token is present and is valid.  If the Anti-CSRF token
is missing or is incorrect, that indicates a cross-site scripting attack.
If the event of an attack is detected, an error message is generated and
all further processing is aborted.

<a id="verifyLogin"></a>TH1 verifyLogin Command
-------------------------------------------------

Changes to www/theory1.wiki.

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
the Fossil implementation is enhanced, and the content is recomputed from
the unchanging bag of artifacts.  The local relational database is an
implementation detail which currently happens to use SQLite.

Another way to think of the relational tables in a Fossil repository is
as an index for the artifacts.  Without the relational tables,
to generate a report like a timeline would require scanning every artifact -
the equivalent of a full table scan.  The relational tables hold pointers
the relevant artifacts in presorted order so that generating a timeline
is much more efficient.  So like an index in a relational database, the
relational tables in an Fossil repository do not add any new information,
they merely make the information in the artifacts faster and easier to
look up.

Fossil is not "based" on SQLite.  Fossil simply exploits SQLite as
a powerful tool to make the implementation easier.
And Fossil doesn't use a distributed
NoSQL database because Fossil is a distributed NoSQL database.  That answers







|


|







71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
the Fossil implementation is enhanced, and the content is recomputed from
the unchanging bag of artifacts.  The local relational database is an
implementation detail which currently happens to use SQLite.

Another way to think of the relational tables in a Fossil repository is
as an index for the artifacts.  Without the relational tables,
to generate a report like a timeline would require scanning every artifact -
the equivalent of a full table scan.  The relational tables hold pointers to
the relevant artifacts in presorted order so that generating a timeline
is much more efficient.  So like an index in a relational database, the
relational tables in a Fossil repository do not add any new information,
they merely make the information in the artifacts faster and easier to
look up.

Fossil is not "based" on SQLite.  Fossil simply exploits SQLite as
a powerful tool to make the implementation easier.
And Fossil doesn't use a distributed
NoSQL database because Fossil is a distributed NoSQL database.  That answers

Changes to www/tickets.wiki.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
implement the change.  The key corresponds to a field of the ticket
that is modified.  The value may either replace the earlier value for
that key, or the value may be appended to the prior value.

<h2>2.0 Ticket Tables</h2>

The low-level artifact format for ticket content is tedious and
cumbersome to access in real time.  To facility reporting and display
of tickets, the low-level artifact information is collected and
summarized in a pair of SQL tables in each local repository.  Display
and reporting of tickets is accomplished by querying these two tables.

Note that only the low-level ticket change artifacts are synced.  The
content of the two ticket tables can always be reconstructed from the
ticket change artifacts.  And, indeed, the reconstruction of the ticket







|







25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
implement the change.  The key corresponds to a field of the ticket
that is modified.  The value may either replace the earlier value for
that key, or the value may be appended to the prior value.

<h2>2.0 Ticket Tables</h2>

The low-level artifact format for ticket content is tedious and
cumbersome to access in real time.  To facilitate reporting and display
of tickets, the low-level artifact information is collected and
summarized in a pair of SQL tables in each local repository.  Display
and reporting of tickets is accomplished by querying these two tables.

Note that only the low-level ticket change artifacts are synced.  The
content of the two ticket tables can always be reconstructed from the
ticket change artifacts.  And, indeed, the reconstruction of the ticket
189
190
191
192
193
194
195
196
197
198
199
to be in HTML and others to be plaintext.  Some site administrators wanted the
ability to mix plaintext, wiki, and HTML comments and display each
comment according to its chosen format.  Hence, Fossil was enhanced to
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its on mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in time stamp order.







|



189
190
191
192
193
194
195
196
197
198
199
to be in HTML and others to be plaintext.  Some site administrators wanted the
ability to mix plaintext, wiki, and HTML comments and display each
comment according to its chosen format.  Hence, Fossil was enhanced to
support the "new-style" tickets.

The TICKETCHNG table was added to support new-style tickets.  In the new
style, comment text is stored with the "icomment" (for "Incremental Comment")
key and appears separately, and with its own mimetype, in multiple rows
of the TICKETCHNG table.  It then falls to the TH1 script code on the
View Ticket Page to query the TICKETCHNG table and extract and format
the various comments in time stamp order.

Changes to www/unvers.wiki.

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

Notice that the "-u" option does not work on
[/help?cmd=push|fossil push] or [/help?cmd=pull|fossil pull].
The "-u" option is only available on "sync" and "clone".
A rough equivalent of an unversioned pull would be the
[/help?cmd=unversioned|fossil unversioned revert] command.  The
"unversioned revert"
command causes the unversioned content on the local repository to overwritten
by the unversioned content found on the remote repository.

Beware that because unversioned file sync is an uncommonly dangerous
capability — there being no history to revert to in the case of human
error — even the all-powerful Fossil "setup" user does not get
unversioned file sync capability by default.  See
[./caps/admin-v-setup.md#dcap | this] for the full details, but the
short-and-sweet takeaway is that a user needs the "y" capability on the







|
|







51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

Notice that the "-u" option does not work on
[/help?cmd=push|fossil push] or [/help?cmd=pull|fossil pull].
The "-u" option is only available on "sync" and "clone".
A rough equivalent of an unversioned pull would be the
[/help?cmd=unversioned|fossil unversioned revert] command.  The
"unversioned revert"
command causes the unversioned content on the local repository to be
overwritten by the unversioned content found on the remote repository.

Beware that because unversioned file sync is an uncommonly dangerous
capability — there being no history to revert to in the case of human
error — even the all-powerful Fossil "setup" user does not get
unversioned file sync capability by default.  See
[./caps/admin-v-setup.md#dcap | this] for the full details, but the
short-and-sweet takeaway is that a user needs the "y" capability on the

Changes to www/userlinks.wiki.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  *  The [./selfcheck.wiki | automatic self-check] mechanism
     helps insure project integrity.
  *  Fossil contains a [./wikitheory.wiki | built-in wiki].
  *  An [./event.wiki | Event] is a special kind of wiki page associated
     with a point in time rather than a name.
  *  [./settings.wiki | Settings] control the behaviour of Fossil.
  *  [./ssl.wiki | Use SSL] to encrypt communication with the server.
  *  The [https://fossil-scm.org/forum|Fossil forum] is, as of mid-2018,
     the project's central communication channel. The
     [https://www.mail-archive.com/fossil-users@lists.fossil-scm.org
     | read-only mailing list archives] house discussions spanning Fossil's
     first decade.
  *  [./stats.wiki | Performance statistics] taken from real-world projects
     hosted on Fossil.
  *  How to [./shunning.wiki | delete content] from a Fossil repository.







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  *  The [./selfcheck.wiki | automatic self-check] mechanism
     helps insure project integrity.
  *  Fossil contains a [./wikitheory.wiki | built-in wiki].
  *  An [./event.wiki | Event] is a special kind of wiki page associated
     with a point in time rather than a name.
  *  [./settings.wiki | Settings] control the behaviour of Fossil.
  *  [./ssl.wiki | Use SSL] to encrypt communication with the server.
  *  The [https://fossil-scm.org/forum|Fossil forum] is, as of late-2024,
     the project's central communication channel. The
     [https://www.mail-archive.com/fossil-users@lists.fossil-scm.org
     | read-only mailing list archives] house discussions spanning Fossil's
     first decade.
  *  [./stats.wiki | Performance statistics] taken from real-world projects
     hosted on Fossil.
  *  How to [./shunning.wiki | delete content] from a Fossil repository.

Changes to www/webui.wiki.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
on with separate sub-teams within your project team.

The "Files" link on the menu allows you to browse through the <b>file
hierarchy</b> of the project and to view complete changes histories on
individual files, with hyperlinks to the check-ins that made those
changes, and with diffs and annotated diffs between versions.

The web interface supports [./embeddeddoc.wiki | embedded documentation].
Embedded documentation is documentation files (usually in wiki format)
that are checked into project as part of the source tree.  Such files
can be viewed as if they were ordinary web pages.  This document that
you are now reading is an example of embedded documentation.

<h2>Customizing The Web Interface Appearance</h2>

Users with appropriate permissions can customize the look and feel of
the web interface using the "Admin" link on the main menu of the web
interface.  Templates
for the header and footer of each page can be edited, as can the CSS







|
|
|
|
|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
on with separate sub-teams within your project team.

The "Files" link on the menu allows you to browse through the <b>file
hierarchy</b> of the project and to view complete changes histories on
individual files, with hyperlinks to the check-ins that made those
changes, and with diffs and annotated diffs between versions.

The web interface supports [./embeddeddoc.wiki | embedded documentation]
files (usually in wiki format) that are checked into the project as
part of the source tree.  Such files can be viewed as if they were
ordinary web pages.  This document that you are now reading is an
example of embedded documentation.

<h2>Customizing The Web Interface Appearance</h2>

Users with appropriate permissions can customize the look and feel of
the web interface using the "Admin" link on the main menu of the web
interface.  Templates
for the header and footer of each page can be edited, as can the CSS

Changes to www/wikitheory.wiki.

82
83
84
85
86
87
88
89
90
   *  [/timeline?r=graph-test-branch] shows the text of the
      [/wiki?name=branch/graph-test-branch&p|branch/graph-test-branch]
      wiki page at the top of the timeline
   *  [/info/19c60b7fc9e2] shows the text of the
      [/wiki?name=checkin/19c60b7fc9e2400e56a6f938bbad0e34ca746ca2eabdecac10945539f1f5e8c6&p|checkin/19c60b7fc9e2...]
      wiki page in the "About" section.

This special wiki pages are very useful for recording historical
notes.







|

82
83
84
85
86
87
88
89
90
   *  [/timeline?r=graph-test-branch] shows the text of the
      [/wiki?name=branch/graph-test-branch&p|branch/graph-test-branch]
      wiki page at the top of the timeline
   *  [/info/19c60b7fc9e2] shows the text of the
      [/wiki?name=checkin/19c60b7fc9e2400e56a6f938bbad0e34ca746ca2eabdecac10945539f1f5e8c6&p|checkin/19c60b7fc9e2...]
      wiki page in the "About" section.

These special wiki pages are very useful for recording historical
notes.