Edgewall Software

Project classifiers (aka labels)

Consider merging this page with Multi-Project Support for Trac

In order to provide an structured solution so as not to limit the possible ways of grouping projects it is convenient to introduce the concept of project labels. Main goals are the following :

  • Offer a structured mechanism to identify a group of projects no matter what hierarchy is involved .
  • Encapsulate these details at the API level while determining (multi)project context.

Considering the reference example, in spite of searching for tickets in Family A and Family B but not in Tools and 3rdParty when needed, a label containing both projects has to be created (either explicitly or implicitly, see below) .

This document also suggests alternatives and approaches to implement some features defined in Multi-Project Support for Trac. Some content may actually overlap aforementioned specification.

URL space for different projects

A constraint should be imposed in order to simplify dispatching strategy so as to map projects to URLs. Project short name MUST be unique in the context of an environment.

  • host mapping: the name of the (virtual) host used to access the Trac environment is taken to be the name of the project. A given host can be configured to be an alias for the default, top-level project. Label names are not allowed to be used this way.
  • prefix mapping: if the PATH_INFO starts with /p/<project name>/ prefix, name of a project will be taken to be <project_name> . Otherwise if it starts with /l/<label_name>/ then the request is addressed to the set of projects included in label <label_name>. In general this is less ambiguous than the mapping suggested in original proposal. Explanation and implementation details provided below.

The Data Model and the API

Labels may be considered as resources bound to the environment rather than to particular projects (e.g. like Changeset and Source which belong to a given repository - see MultiRepos). Hence only an additional labels table is also needed, and it can take the form of a resource table specialization from the GenericTrac. Project labels should have at least short name (and maybe description) field. Project labels can be linked explicitly to projects and labels (if using nested labels). These connections can take the form of relations from Trac Relations.

I think it is vital that labels be first-class objects with history (like tickets, not milestones). Say I have a .../l/Label1 link somewhere in a wiki page or ticket description or something. Today Label1 points to ProjectA, ProjectB, and ProjectC but for whatever administrative reason, ProjectC gets reclassified or cancelled or something. I might click through my link and wonder where all the ProjectC stuff went. If labels have history, I can go look and see, "Oh, Bob cancelled Project C yesterday. He said, 'Customer Foo cancelled their order.'" — Chris Nelson, 4 Jan 2012

URL prefix mapping explained

Project-specific URLs will start with /p/<project name> prefix. Requests involving multiple projects will be made available on a per-label basis at URLs starting with /l/<label name> prefix. Remaining path after this will be used to select what instance of IRequestHandler should process the request. Examples below illustrate some use cases. In all cases multi-project environment root URL is http://server.com/path/to/trac/ and it will contain the reference project hierarchy used throughout this document :

URL Target projects Comments
http://server.com/path/to/trac/ top-level project (i.e. '' )
http://server.com/path/to/trac/roadmap top-level project (i.e. '' ) Top-level milestone view. This may be used to show top-level (e.g. product, current year, …) milestones.
http://server.com/path/to/trac/p/FamilyB/roadmap project FamilyB FamilyB project-specific milestones.
http://server.com/path/to/trac/p/product_c/roadmap project product_c product c project-specific milestones.
http://server.com/path/to/trac/l/javascript/roadmap all projects in label javascript display milestones for javascript projects.

By doing things this way request dispatch may be implemented as a combination of two existing architectural features , namely request filters and request handlers. First of all by supporting multi-project specifications the context associated to the request has to contain information about target project(s) . One component acting as a request filter intercepts the request before match is performed. If any multiproject prefix (i.e. /p/<project name> or /l/<label name>) is detected then project resolution takes place. Single-project requests only need to add corresponding internal project resource to context. In the case of labels the context should contain label name as well as a list of resources identifying target projects . In the case of more complex project selector expressions the context should contain the expression itself, the instance of IProjectLabelManager matching label name, and the list of resource objects identifying target projects . If this advanced feature will be supported, it may be considered as a generic way to encapsulate multi-project context in spite of having flexibility and uniformity, considering the fact that first two variants are just particular cases. Aforementioned data may be retrieved right away at dispatch time or loaded on demand.

Immediately after multi-project context resolution, the request filter rewrites PATH_INFO by removing project selection prefix. The request is then matched as usual so as to determine the handler responsible for processing it (e.g. wiki, ticket, …). The target instance of IRequestHandler will rely on request context so as to determine target projects involved and build the response accordingly.

Advanced labels features

Subsequent sub-sections deal with some advanced features that may be useful under certain circumstances but may also over-complicate core design . Nonetheless I mention them here for the sake of could not find the right word.

Project alias

A label related to a single project may be considered a project alias. This scenario may happen when two or more projects are merged and previous project name is to be kept so as not to break external references, for instance.

Nested labels

It might be convenient as well to provide a way to specify a hierarchy of labels (rather than projects). In order to illustrate this with a particular example which might be very common in practice, let's consider we have the sample hierarchy of projects and still need to group them according to programming languages and frameworks used to build them (let them be explicit project dependencies or not). In that case it will be useful to have some labels like javascript, python, c#, vb.net, f#, ruby, php and so on. Let's also consider a similar situation and project classification also includes frameworks, so there are further tags like e.g. trac, wcf, jquery, mootools, wpf, django, dojo, … Nonetheless :

  • It may be useful to know which projects are related to .NET framework.
  • It may be useful to ease the process by tagging projects using a single label identifying a framework and having them auto-magically included in the label for the corresponding programming language .

In order to do that the following label hierarchy might help :

 +-- python
 | +-- trac
 | +-- django
 +-- ruby
 +-- javascript
 | +-- jquery
 | +-- dojo
 | +-- mootools
 +-- .net
 | +-- .net languages
 | | +-- c#
 | | +-- vb.net
 | | +-- f#
 | +-- .net technologies
 | | +-- wpf
 | | +-- wcf
 | | +-- wwf
 +-- php
 

For instance , Trac-Hacks website may be one such example where there's a flat one-level project hierarchy and labels to group hacks. In Apendix B it is possible to see sample label hierarchy based on hack classifiers available at present. Idea is , for instance, that if somebody tags a project using macro label then it also belongs auto-magically in plugins label.

There's another precision that needs to be mentioned up to this point and it is whether it is more convenient to define label relationships using graphs rather than a tree . Considering the same case mentioned above , labels like iron_python , iron_ruby would be hard to classify considering aforementioned hierarchy as they may be related to both .net and (python | ruby) (same reasoning for e.g. jpype , jython for python & java; rython , unholy for python & ruby … and it's possible to find more examples even in totally different business domains).

Project context extensions

It may be useful to be able to specify special project groups like :

These are just a few examples. In order to prepare the system for flexibilty and maybe allow the definition of other project selector expressions (e.g. in plugins) it is convenient to introduce a new interface (namely IProjectLabelManager) used to determine which projects belong in a given label, provided its name. Selection should work using a chain of responsibilty similar to the one already used for IRequestHandler. All instances of IProjectLabelManager are requested to expand a project selector expression. This will consist of returning a list of project names matching a given label name (aka project selector expression ⇐ this seems to be more generic ;) , or None if such match is not found. In the later case the next instance of IProjectLabelManager is considered and so on … until either a match is found (and subsequent request handling takes place) or all options are exhausted (and error handling occurs e.g. HTTP 404 Not Found returned to the client) .

User interface

Considering everything mentioned up to this point , the following variants of project selector GUI control are suggested.

Project selector (drop-down menu)

The use of labels makes possible to present a flat drop-down menu to the user in order to select a set of projects like shown below. This may be considered more appropriate than always having to display a hierarchy.

PS: Create new label … option should be visible only if user can create labels. If the user can modify labels (i.e. classify projects in categories) then it may be useful to include shortcut links to update projects membership. In both cases a dialog (see picture below) should be displayed.

Create new label


Select projects
  • Top-level
    • Family A
      • product a
      • product b
    • Family B
      • product c
      • product d
    • Tools
    • 3rdParty

Project selector (tree view)

Another option is to provide a more ellaborate version of the box suggested in Multi-Project Support specification. One of the benefits is that it will be possible to select either projects or labels. It should look like this

Project Selector
  • Top-level
    • Family A
      • product a
      • product b
    • Family B
      • product c
      • product d
    • Tools
    • 3rdParty
  • Product familiesEdit
  • ProductsEdit
  • All except product bEdit

Once label is selected then target projects should be highlighted like above.

Ideally it should be possible to drag a project & drop it on an item representing a label in order to add that project to that label (a confirmation box may be shown so as to detect mistakes).

Label membership editor dialog box may be displayed as well so as to edit a label if user clicks on Edit link.

Appendix A : Other systems supporting labels

Other similar examples of the use of labels in other products are :

  • Google+ circles which allow to group people,
  • GMail contact groups which serve to a similar purpose
  • GMail labels which allow to mark e-mails

Other instances of similar label hierarchies :

  • GMail nested labels.

Appendix B : Proposed label hierarchy for Trac-Hacks

This section considers just a subset of Trac-Hacks classifiers.

 +-- supported-version
 | +-- 0.1
 | +-- 0.10
 | +-- 0.10.4
 | +-- 0.11
 | +-- 0.11.5
 | +-- 0.11.6
 | +-- 0.12
 | +-- 0.12-compatible
 | +-- 0.12dev
 | +-- 0.13
 | +-- 0.3.4
 | +-- 0.4
 | +-- 0.5
 | +-- 0.5dev
 | +-- 0.8
 | +-- 0.9
 | +-- 0.9.1
 | +-- 0.9.2
 | +-- 0.9.6
 | +-- 1.1dev
 | +-- trunk
 | +-- anyrelease
 +-- db
 | +-- sql
 | +-- sqlalchemy
 | +-- sqlite
 | | +-- sqlite3
 | +-- postgresql 
 | +-- mysql
 +-- plugin
 | +-- macro
 | +-- theme
 +-- scripts
 +-- patch
 +-- integration
 +-- translation
 +-- workflow

Last modified 12 years ago Last modified on Jan 4, 2012, 3:36:34 PM
Note: See TracWiki for help on using the wiki.