14 | | The tight and coherent integration of these features is achieved by several means: |
15 | | * tracking of a single software repository |
16 | | * using a simple relational database to store all the informations |
17 | | about tickets, milestones, changesets and wiki pages. |
18 | | * using a unified ''language'' to talk about objects in the system, |
19 | | by the way of a wiki syntax (TacLinks) which can be used nearly everywhere: |
20 | | * in Subversion commit log messages |
21 | | * in Ticket descriptions and comments |
22 | | * in Wiki pages and change descriptions |
23 | | * in attachments descriptions |
24 | | * ... |
25 | | This unique approach enables a powerful structuring of the information |
26 | | in the system, yet this can be achieved in a very flexible and informal way |
27 | | thanks to that feature. |
| 11 | The tight and coherent integration of its features is achieved by several means, |
| 12 | but most notably by the consistent use of a unified ''language'' to talk about |
| 13 | objects in the system (the TracLinks). |
| 14 | |
| 15 | This unique approach enables a powerful structuring of the information |
| 16 | in the system, yet this can be achieved in a very flexible and informal way. |
33 | | '''In the following, I'll try to show how those Trac ''objects'' are variations on a same theme, both from the data point of view and from the behavioral point of view.''' |
| 22 | === Trac Object Model === |
| 23 | |
| 24 | In the following, I'll try to show that Trac is a manager for typed pieces |
| 25 | of informations: the Trac ''objects''. |
| 26 | |
| 27 | There are many advantages to gain by refactoring the internals of Trac |
| 28 | to acknowledge this reality: |
| 29 | * more consitency, less redundancy, code simplication |
| 30 | * spreading the features available for one object to the other objects |
| 31 | |
| 32 | This updated revision is made in light of the experience gathered |
| 33 | while working on the #1242 patch. |
| 34 | |
63 | | * It would have a unique identity in the system |
64 | | * It would have some wiki syntax to describe it |
65 | | (a ''canonical'' form and also a ''shortcut'' form if possible) |
66 | | * There would be obviously a Wiki description of it |
67 | | * There would be some properties attached to it: |
68 | | * Some would be universal: |
69 | | * an author |
70 | | * a time of creation |
| 66 | * It would have a unique identity in the system -- {{{id}}} |
| 67 | * It would have some wiki syntax to describe it |
| 68 | * {{{shortcut_regexp()}}} |
| 69 | * {{{canonical_regexp()}}} |
| 70 | * It would be displayed in several ways: |
| 71 | * a ''canonical'' form -- {{{canonical_name()}}} |
| 72 | * a ''shortcut'' form -- {{{name()}}} |
| 73 | * There could be one or several Wiki text attached to the object. |
| 74 | Each would be a '''facet''' of this object. |
| 75 | Some facets are: |
| 76 | * '''content''', appropriate for a !WikiPage and a Changeset |
| 77 | * '''description''', appropriate for a Ticket, a Report and a Milestone |
| 78 | * '''comment:n''' for the n^th^ comment |
| 79 | * '''attachment:file''' for the attachment name ''file'' |
| 80 | * There would be some fields attached to it. |
73 | | * One would want to be able to attach files to that object |
74 | | * After the main wiki content, there could be a change history, |
75 | | a sequence of summary of commented property changes (or just comments) |
76 | | * The Wiki content of the object could be modified, so there |
77 | | would be an history of changes, the possibility to make |
78 | | diffs between revisions of wiki (see also TighterSubversionIntegration) |
| 83 | * One would want to be able to attach files to any object |
| 84 | * One would want to be able to comment on any object, just like for a Ticket |
| 85 | * One would want to see the history of the modification of the object |
| 86 | * the edit history of the main facet (see also TighterSubversionIntegration) |
| 87 | * the change history of the value of the fields |
87 | | * The Wiki description would be actually the content of the Wiki page itself. |
88 | | * Only a few properties are relevant: |
89 | | * The universal properties (author and creation time) are there, |
90 | | * There's no need for specific properties for a !WikiPage |
91 | | (except maybe a ''readonly'' attribute?) |
92 | | * ''custom'' properties could make sense, but as usual with ''custom'' |
93 | | properties, their presence and pertinence would be site-dependant. |
| 96 | -- currently present in source:trunk/trac/WikiFormatter.py |
| 97 | {{{r"(?P<wikihref>!?(^|(?<=[^A-Za-z]))[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[A-Za-z0-9]+)?(?=\Z|\s|[.,;:!?\)}\]]))"}}} |
| 98 | and in source:trunk/trac/Search.py {{{r = "((^|(?<=[^A-Za-z]))[!]?[A-Z][a-z/]+(?:[A-Z][a-z/]+)+)"}}} |
| 99 | * The main facet would be ''content'', i.e. the content of the Wiki page itself. |
| 100 | * The relevant fields: |
| 101 | * author and creation time |
| 102 | * a ''readonly'' boolean field |
101 | | * The unique identity is the revision number |
102 | | * The wiki syntax is {{{changeset:XYZ}}} or {{{[XYZ]}}} |
103 | | * The Wiki description is the original commit log entered in Subversion. |
104 | | This is normally not meant to change, though it can sometimes be |
105 | | handy to fix a typo (therefore the occasional use of the |
106 | | {{{svnadmin setlog}}} command). There are 3 possibilities: |
107 | | * Keep it as it is (read-only) |
108 | | * Enable ''trac-only'' modifications |
109 | | * Provide the functionality of {{{svnadmin setlog}}} |
| 109 | * The unique identity is the revision number -- {{{s/rev/id}}} |
| 110 | * The wiki syntax is {{{r"(?P<changesethref>!?(\[\d+\]|\br\d+\b))"}}} |
| 111 | * The main facet is 'content', which is the original commit log entered in Subversion. |
| 112 | See #781. |
125 | | * A change history for a Changeset, wouldn't be that extreme? |
126 | | Actually, the contributed comments could be used for code reviews, |
127 | | another long standing request (#YYY TODO) |
128 | | * Wiki history and diffs would be usefull if the changelog is to be modified |
| 125 | * A change history for a Changeset, wouldn't that be cool? |
| 126 | Actually, the contributed comments could be used for code reviews |
| 127 | The history and diffs for the commit log are useful once the |
| 128 | changelog becomes modifiable |
132 | | Introducing an object hierarchy was indeed the initial motivator for this proposal. |
133 | | While thinking about request for ''MasterTicket''s (#886), it struck me |
134 | | that ''Milestone''s could be seen as a kind of tickets. |
135 | | |
136 | | (I explained elsewhere (#919) the reasons why I think a categorization of tickets |
137 | | can be important. However, the approach taken in that proposed patch, is, |
138 | | well, just a patch.) |
139 | | |
140 | | A hierarchy of ticket classes would better serve the purpose of a categorization. |
141 | | It can achieve a better repartition of the specific properties. |
142 | | The relationships between these categories could also be done in a modular way. |
143 | | |
144 | | First I'll describe the generic ticket as I did above for the other Trac objects, |
145 | | then I will describe a hierarchy of tickets. |
146 | | |
147 | | * The unique identity for a ticket is its number |
148 | | * The wiki syntax is {{{ticket:XYZ}}} or #XYZ |
149 | | * The Wiki description for that object is the Ticket description |
150 | | * The ticket properties: |
151 | | * The universal properties (author and creation time) also apply here |
152 | | * The specific properties would be: |
153 | | * The short summary |
154 | | * The keywords |
155 | | * An optional due time |
156 | | * Assigned to... |
157 | | * Cc field |
| 132 | * The unique identity for a ticket is its number -- {{{id}}} |
| 133 | * The wiki shortcut syntax is {{{r"(?P<tickethref>!?#\d+)"}}} |
| 134 | * The main facet is ''description'' |
| 135 | * The ticket fields: |
| 136 | * author and creation time |
| 137 | * milestone and component |
| 138 | * The short summary |
| 139 | * The keywords |
| 140 | * An optional due time |
| 141 | * Assigned to... |
| 142 | * Cc field |
167 | | Then, I would propose the following subclasses: |
168 | | * a !TaskTicket: ''something to be done about something'' |
169 | | * Additional specific properties: |
170 | | * Severity: ''what is the impact of this task?'' |
171 | | * Priority: ''what's the most urgent task among the urgent tasks?'' |
172 | | * Milestone: ''to what Milestone'' object does it relate? |
173 | | * The related component(s) ''(well, a Component could also be a Trac object...)'' |
174 | | * Status (opened/closed) |
175 | | * Resolution: ''in which way the task has been completed'' |
176 | | * !ProblemReportTicket would be a simple subclass of !TaskTicket |
177 | | * !EnhancementRequestTicket would be a simple subclass of !TaskTicket |
178 | | * !MilestoneTicket: ''a collection of Tasks that will happen sometime (due time either set or opened)'' |
| 149 | ==== Source ==== |
180 | | Other possible Ticket types: |
181 | | * Information: ''just to pass some news around (its due time is present)'' |
182 | | * Deployment: ''a specific build has been made available'' |
183 | | |
184 | | ==== Attachment ==== |
185 | | |
186 | | * The unique identifier for an attachment would be its filename, |
187 | | plus the unique identifier of the object it is attached to. |
188 | | * There's currently no wiki syntax associated to an attachment, |
189 | | though in #944, I propose the {{{attachment:filename}}}. |
190 | | This currently works only from the Wiki of the parent object, |
191 | | the one to which the file is attached. What would be needed would be: |
192 | | {{{attachment:<TracLink>:filename}}}, where !TracLink would specify |
193 | | the parent object. |
194 | | * The Wiki content would be the optional file description |
195 | | * Properties: |
196 | | * The universal properties also apply for attachment |
197 | | * The specific properties would be: |
198 | | * The size |
199 | | * The mime-type |
200 | | * Ok, attachments for attachments. Now ''that'' does not make sense... |
201 | | * Change history would probably be overkill |
202 | | * Wiki history and diff would probably be overkill here too |
203 | | |
204 | | But have a look to the TighterSubversionIntegration proposal |
205 | | to see that those last features would in some cases prove usefull... |
206 | | |
207 | | ==== Component ==== |
208 | | |
209 | | This would be a subtype of a !WikiPage. |
210 | | Therefore it would share most of what has been said for !WikiPage. |
211 | | |
212 | | In addition, there would be specific fields, |
213 | | like a list of repository paths describing the component |
214 | | in term of software artifacts. |
215 | | |
216 | | This would allow the following features: |
217 | | * automatically relate a Changeset to the affected components. |
218 | | * filter the Changesets in the Timeline to those belonging |
219 | | to a component |
220 | | |
221 | | This is just an example of a new type of Trac object. |
222 | | It may or may not sounds like a good idea, but by the way of the |
223 | | object model, its implementation would essentially focus |
224 | | about how it would interact with the Changeset and Timeline modules. |
225 | | |
226 | | See also TracReleaselist for the Release object... |
227 | | |
228 | | |
229 | | === Summary === |
230 | | |
231 | | The above correspond to the following hierarchy: |
232 | | * !TracObject |
233 | | * !WikiPage |
234 | | * Component |
235 | | * Changeset |
236 | | * Ticket |
237 | | * Task |
238 | | * !ProblemReport |
239 | | * !EnhancementRequest |
240 | | * Milestone |
241 | | * Information ''*'' |
242 | | * Deployment ''*'' |
243 | | * Attachment/File |
| 151 | * The identifier for a file or directory is its path |
| 152 | * There's no facet attached to a source |
| 153 | * Fields |
| 154 | * author, creation date |
| 155 | * The size |
| 156 | * The mime-type |
| 157 | * dynamical svn properties |
| 158 | * attachments for files... Why not? One could already do it with |
| 159 | Subversion anyway ({{{svn pset prop -F attachment source}}}) |
255 | | * Module (much of the current Ticket code would be moved here) |
256 | | * Wiki |
257 | | * Component |
258 | | * Changeset |
259 | | * Ticket |
260 | | * Task |
261 | | * !ProblemReport |
262 | | * !EnhancementRequest |
263 | | * Milestone |
264 | | * Attachment/File (see TighterSubversionIntegration) |
265 | | |
266 | | But not only that, the Trac object hierarchy will also correspond to a specific |
267 | | object model for the schema in the database. |
268 | | |
269 | | There is essentially two approaches for the object-relational mapping: |
270 | | * For a class, have multiple tables, one for each level in the |
271 | | hierarchy, and join them on the shared identifier. |
272 | | The root level contains also the type of the object. |
273 | | * Have a table for each class, with common column names |
274 | | |
275 | | Each solution has its pros and cons. I will adopt the first approach here, |
276 | | to get things started. |
277 | | |
278 | | Common to all the Trac Objects, there would be a main table |
279 | | and some auxilliary tables: |
280 | | |
281 | | {{{ |
282 | | #!sql |
283 | | |
284 | | -- TracObject |
285 | | ------------- |
286 | | |
287 | | CREATE TABLE trac_object ( |
288 | | id text PRIMARY KEY, |
289 | | type text, |
290 | | time integer, -- the time it was created |
291 | | author text, |
292 | | description text, |
293 | | ); |
294 | | |
295 | | -- for the change history of any TracObject |
296 | | ------------------------------------------- |
297 | | |
298 | | CREATE TABLE object_change ( |
299 | | id text, |
300 | | time integer, |
301 | | author text, |
302 | | field text, |
303 | | oldvalue text, |
304 | | newvalue text, |
305 | | UNIQUE(id, time, field) |
306 | | ); |
307 | | |
308 | | -- for the custom fields associated to any TracObject |
309 | | ----------------------------------------------------- |
310 | | |
311 | | CREATE TABLE object_custom ( |
312 | | id integer, |
313 | | name text, |
314 | | value text, |
315 | | UNIQUE(id,name) |
316 | | ); |
317 | | |
318 | | CREATE TABLE object_custom_multi ( |
319 | | id integer, |
320 | | name text, |
321 | | value text |
322 | | ); |
323 | | }}} |
324 | | |
325 | | Each Trac object would eventually have an extension table, |
326 | | to represent its specific fields: |
327 | | |
328 | | {{{ |
329 | | #!sql |
330 | | |
331 | | -- Ticket (or Milestone) |
332 | | ------------------------ |
333 | | |
334 | | CREATE TABLE ticket ( |
335 | | id text, |
336 | | summary text, |
337 | | keywords text, |
338 | | duetime integer, |
339 | | owner text -- who is this ticket assigned to |
340 | | ); |
341 | | |
342 | | -- Task (or PR/ER) |
343 | | ------------------ |
344 | | |
345 | | CREATE TABLE task ( |
346 | | id text, |
347 | | severity text, |
348 | | priority text, |
349 | | milestone text |
350 | | ); |
351 | | |
352 | | -- Report |
353 | | --------- |
354 | | |
355 | | CREATE TABLE report ( |
356 | | id text, |
357 | | title text, |
358 | | sql text |
359 | | ); |
360 | | |
361 | | -- WikiPage |
362 | | ----------- |
363 | | |
364 | | CREATE TABLE wiki ( |
365 | | id text, |
366 | | readonly char(1) |
367 | | ); |
368 | | |
369 | | }}} |
370 | | |
371 | | Note: the Changeset doesn't need anything in addition to the TracObject fields. |
372 | | |
373 | | |
374 | | Finally, there would be auxilliary tables for some objects: |
375 | | |
376 | | {{{ |
377 | | #!sql |
378 | | |
379 | | -- For Changeset |
380 | | ---------------- |
381 | | |
382 | | CREATE TABLE changeset_node_change ( |
383 | | id text, |
384 | | path text, |
385 | | change char(1) |
386 | | ); |
387 | | |
388 | | -- For Component |
389 | | ---------------- |
390 | | |
391 | | CREATE TABLE component_path ( |
392 | | id text, |
393 | | path text |
394 | | ); |
395 | | }}} |
396 | | |
397 | | |
398 | | == Summary == |
399 | | |
400 | | This proposal aims both at a simplification of the current Trac implementation, |
401 | | which contains a different data representation for each Trac object, and at |
402 | | enhanced functionalities, because the rich functionality that is currently |
403 | | available for Ticket (attachments, change history, custom fields) |
404 | | would be also available for !WikiPage, Report, Changeset, Attachment/File and of course, |
405 | | subtypes of Tickets, like Task and Milestone. |
406 | | |
407 | | This does not mean that all these objects are interchangeable, or that any |
408 | | specific functionality would be lost in the process. Quite to the contrary, |
409 | | each module could focus on what makes it unique, and in which ways it |
410 | | can interact with the other modules, leaving to the generic {{{Module}}} |
411 | | all the shared functionality. |