|
1
|
<title>Bug-Tracking In Fossil</title> |
|
2
|
<h2>Introduction</h2> |
|
3
|
|
|
4
|
A bug-report in fossil is called a "ticket". Tickets are tracked |
|
5
|
separately from code check-ins. |
|
6
|
|
|
7
|
Some other distributed bug-tracking systems store tickets as files within |
|
8
|
the source tree and thereby leverage the syncing and merging capabilities |
|
9
|
of the versioning system to sync and merge tickets. This approach is |
|
10
|
rejected in fossil for three reasons: |
|
11
|
|
|
12
|
1. Check-ins in fossil are immutable. So if |
|
13
|
tickets were part of the check-in, then there would be no way to add |
|
14
|
new tickets to a check-in as new bugs are discovered. |
|
15
|
|
|
16
|
2. Any project of reasonable size and complexity will generate thousands |
|
17
|
and thousands of tickets, and we do not want all those ticket files |
|
18
|
cluttering the source tree. |
|
19
|
|
|
20
|
3. We want tickets to be managed from the web interface and to have a |
|
21
|
permission system that is distinct from check-in permissions. |
|
22
|
In other words, we do not want to restrict the creation and editing |
|
23
|
of tickets to developers with check-in privileges and an installed |
|
24
|
copy of the fossil executable. Casual passers-by on the internet should |
|
25
|
be permitted to create tickets. |
|
26
|
|
|
27
|
Recall that a fossil repository consists of an |
|
28
|
unordered collection of <i>artifacts</i>. (See the |
|
29
|
<a href="fileformat.wiki">file format document</a> for details.) |
|
30
|
Some artifacts have a special format, and among those are |
|
31
|
<a href="fileformat.wiki#tktchng">Ticket Change Artifacts</a>. |
|
32
|
One or more ticket change artifacts are associated with each |
|
33
|
ticket. A ticket is created by a ticket change artifact. |
|
34
|
Each subsequent modification of the ticket is a separate artifact. |
|
35
|
|
|
36
|
The "push", "pull", and "sync" algorithms share ticket change artifacts |
|
37
|
between repositories in the same way as every other artifact. In fact, |
|
38
|
the sync algorithm has no knowledge of the meaning of the artifacts it |
|
39
|
is syncing. As far as the sync algorithm is concerned, all artifacts are |
|
40
|
alike. After the sync has occurs, the individual repositories must |
|
41
|
make sense of the meaning of the various artifacts for themselves. |
|
42
|
|
|
43
|
<h2>Interpretation Of Ticket Change Artifacts</h2> |
|
44
|
|
|
45
|
<i>Note: The following is implementation detail which can be safely ignored by |
|
46
|
casual users of fossil.</i> |
|
47
|
|
|
48
|
Every ticket change artifact contains (among other things) |
|
49
|
|
|
50
|
* a timestamp, |
|
51
|
* a ticket ID, and |
|
52
|
* one or more name/value pairs. |
|
53
|
|
|
54
|
The current state of a ticket is found by replaying all ticket |
|
55
|
change artifacts with the same ticket ID in timestamp order. |
|
56
|
For a given ticket, all values are initially NULL. As each |
|
57
|
ticket change artifact is encountered, values are either replaced |
|
58
|
or appended, according to a flag on the name/value pair. The current |
|
59
|
values for the fields of a ticket are the values that remain at the |
|
60
|
end of the replay process. |
|
61
|
|
|
62
|
To create a new ticket, one inserts a ticket change |
|
63
|
artifact with a new ID. The ticket ID |
|
64
|
is a random 40-character lower-case hexadecimal number. The "tktnew" |
|
65
|
page in the fossil web interface creates new ticket IDs |
|
66
|
using a good source of randomness to insure uniqueness. |
|
67
|
The name/value pairs on the initial ticket change |
|
68
|
artifact are the initial values for the fields in the ticket. |
|
69
|
|
|
70
|
Amending a ticket means simply creating a new artifact with the |
|
71
|
same ticket ID and with name/value pairs for those fields which |
|
72
|
are changing. Fields of the ticket which are not being modified |
|
73
|
should not appear as name/value pairs in the new artifact. |
|
74
|
|
|
75
|
This approach to storing ticket state means that independently entered |
|
76
|
changes are automatically merged together when artifacts are shared |
|
77
|
between repositories. Tickets do not branch. This approach also makes |
|
78
|
it trivial to track the historic progression of changes to a ticket. |
|
79
|
|
|
80
|
In order for this scheme to work, the system clocks on machines that |
|
81
|
add new ticket changes artifacts have to be set close to reality. |
|
82
|
It is OK for a ticket change artifact timestamp to be off by a few |
|
83
|
minutes or even a few hours. But if a timestamp on a ticket change |
|
84
|
artifact is off by months or years, it can seriously confuse the |
|
85
|
replay algorithm for determining the current ticket state. There |
|
86
|
are techniques available to cause rogue artifacts to be ignored |
|
87
|
by fossil. So if a ticket change artifact with a bad timestamp |
|
88
|
does get into a repository, it can be removed by an administrator. |
|
89
|
But the best approach is to take steps to insure that timestamps |
|
90
|
are approximately correct in the first place. |
|
91
|
|
|
92
|
<h2>Local Configuration</h2> |
|
93
|
|
|
94
|
The ticket change artifacts are part of the global state for a project. |
|
95
|
The global state is that which is shared between repositories during |
|
96
|
a sync. Each repository also has local state which is not (normally) |
|
97
|
shared. The name/value pairs for a ticket are part of global state, |
|
98
|
but the interpretation and display of that information is local state. |
|
99
|
Hence, each repository is free to set up its own ticket display and |
|
100
|
input formats and reporting rules according to its own particular needs. |
|
101
|
|
|
102
|
Each repository defines its own TICKET table in its database. There is |
|
103
|
one row in the TICKET table for each unique ticket ID. The |
|
104
|
names of columns in the TICKET table correspond to the names in |
|
105
|
the name/value pairs of ticket change artifacts. When running the replay |
|
106
|
algorithm, if a name/value pair is seen which has no corresponding column |
|
107
|
in the TICKET table, then that name/value pair is ignored. Columns can |
|
108
|
be added or removed from the TICKET table at any time. Whenever the |
|
109
|
TICKET table is modified, the replay algorithm automatically reruns |
|
110
|
to repopulate the table using the new column names. Note that the TICKET |
|
111
|
table schema and content is part of the local state of a repository |
|
112
|
and is not shared with other repositories during a sync, push, or pull. |
|
113
|
|
|
114
|
Each repository also defines scripts used to generate web pages for |
|
115
|
creating new tickets, viewing existing tickets, and modifying an |
|
116
|
existing ticket. These scripts consist of HTML with an embedded |
|
117
|
scripts written in a Tcl-like language called "[./th1.md|TH1]". Every |
|
118
|
new fossil repository is created with default scripts. Administrators |
|
119
|
wishing to customize their ticket entry, viewing, and editing screens |
|
120
|
should modify the default scripts to suit their needs. These screen |
|
121
|
generator scripts are part of the local state of a repository and are |
|
122
|
not shared with other repositories during a sync, push, or pull. |
|
123
|
|
|
124
|
<i>To be continued...</i> |
|
125
|
|