93 | | |
94 | | ''(Sorry, work in progress, hang on...)'' |
| 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}}} |
| 110 | * Changeset properties: |
| 111 | * The universal properties (author and creation time) are those |
| 112 | of the commit information. |
| 113 | * The properties specific to a Changeset could be the list of node changes |
| 114 | corresponding to that revision. |
| 115 | * Custom properties could be used for many things, as a way to |
| 116 | annotate the revision. Some ideas are: |
| 117 | * a boolean ''compilable'' flag (true by default, could be set to |
| 118 | false to indicate that this revision can't be built) |
| 119 | * a field indicating the % of successful test cases |
| 120 | * a QA status |
| 121 | * Attachments for a changeset also make sense: |
| 122 | * in case of a build failure, the corresponding errors from the compiler |
| 123 | could be attached. |
| 124 | * patches that applies to that revision |
| 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 |
| 129 | |
| 130 | ==== Ticket ==== |
| 131 | |
| 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 |
| 158 | * Custom properties as usual |
| 159 | * Attachments for tickets are there |
| 160 | * The change history is there |
| 161 | * The wiki history and diff would be usefull if the description is to be modified |
| 162 | |
| 163 | A generic event can be used to dispatch some information immediately, |
| 164 | or to indicate some future event (this needs to be coupled to |
| 165 | #ShowFutureEventsInTimeline -- oh, by the way, what about #TicketAliases ?) |
| 166 | |
| 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)'' |
| 179 | |
| 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 |
| 244 | |
| 245 | |
| 246 | == Implementing Trac Objects == |
| 247 | |
| 248 | For processing Trac objects and for the logic associated to them, |
| 249 | there would be a corresponding {{{Module}}} subclass |
| 250 | (see TracPluggableModules). |
| 251 | |
| 252 | Therefore, the Trac object hierarchy outlined above will closely corresponds to a |
| 253 | hierarchy of Python Module classes: |
| 254 | |
| 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. |
| 412 | |
| 413 | |