Software List | Documentation | Demos | Articles |
Trac with SVN
Now we have our SVN repositories set up, our users can check-out, our developers even can check-in – so far so good. But to manage our projects, maybe we want more? With Trac, there is a very pleasant tool available to manage our projects. So why not make use of that?
OK, you are with me? So we are going to install and setup Trac now, even with some plugins for additional features. And, of course, we will initialize the setup for our public projects we already set up with SVN on the previous pages. In short, our Trac setup will provide us with the following features for each of our projects:
- A Wiki for documentation
- A Timeline presenting the users what's going on
- A Roadmap showing where we want to go
- One more possibility to browse our SVN repositories
- A Ticket system to track bugs and feature requests
- And - last but not least - we also add a PlugIn for the Administration of Trac, so we do not have to fiddle around with all the config files
This just should give you a raw idea. To explain all, this document would get far too long …
Contents
Installing Trac
As usual, all this starts with the installation of some packages. What we need
is Trac (at the time of writing this artice: v0.11.x) – unfortunaltely, there
is no up-to-date *.deb
package available. We'll get around this – and
dependencies are easier to solve now as they were with v0.10, luckily.
Pre-conditions and dependencies
- Ubuntu 8.04 "Hardy Heron" (for our example)
- Apache 2 (taken from the standard repositories)
- ModWSGI (to be found in the Repositories of IzzySoft, or taken from the project's homepage if not in the standard repos)
- Python2.5, python-support, python-clearsilver, python-pysqlite2, python-subversion, python-imaging aus den Standard-Repositories
- Genshi (installed via python-support)
- Trac (via SVN)
Installation
As web server, we again use Apache. Instead of
mod_python, for better performance go for mod_wsgi.
With the *.deb
package from the above mentioned IzzySoft repository (or the
official one if available), it is easily installed.
Ubuntu and Apache we assume already installed, ModWSGI was already dealt with – so we can go for the remaining dependencies:
#!/bin/bash # Trac Installation. Adapt this to your needs before running # Install dependencies sudo apt-get install python2.5 python-support python-clearsilver python-pysqlite2 python-subversion python-imaging sudo easy_install Genshi # this one needs the Repo of IzzySoft (http://apt.izzysoft.de/) sudo apt-get install apache2-mod-wsgi # some directory to place sources in - you may chose any cd /usr/local/src # checkout the latest stable Trac from SVN svn co http://svn.edgewall.org/repos/trac/branches/0.11-stable trac11-stable cd trac11-stable # obtain and apply a patch for better table-header formatting ( ||= HeaderCol1 =||= HeaderCol2 =|| ) wget http://trac.edgewall.org/raw-attachment/ticket/3347/3347_TableHeaders_NicerFormat.diff patch -p0 -i 3347_TableHeaders_NicerFormat.diff # and finally install Trac sudo easy_install . |
Configure Apache
Next we need to configure our web server. We need an additional block for our Trac installation. Put this either in your global configuration, or inside a virtual host – just as you like it to be placed. A detailed secription can be found here.
WSGIScriptAlias /trac /usr/local/trac-apache/trac.wsgi
<Directory /usr/local/trac>
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
</Directory>
# <Location "/trac/*/login">
# AuthType Basic
# AuthName "Trac Repositories"
# AuthUserFile /etc/apache2/.trac
# Require valid-user
# </Location>
You will note that there's half of the stuff commented out – namely those statements intended for the authentification. Well, that's intended: We will solve this with a plugin for Trac, so we usually won't need it configured in the web server. But just in case something fails at some time, we have it right here and just need to enable it.
In the location we configured above, we now also need to place WSGI script:
import sys
sys.stdout = sys.stderr
import os
os.environ['TRAC_ENV_PARENT_DIR'] = '/usr/local/trac'
os.environ['PYTHON_EGG_CACHE'] = '/usr/local/trac/.egg-cache'
import trac.web.main
application = trac.web.main.dispatch_request
Installing plugins
We never get enough, huh? So even before using Trac, we are going to extend it with a few plugins. Remember we installed Trac v0.11.x - so we have to take the compatible plugins. Simply comment out those you don't want. Essential are (and these you must not comment out) the AccountManager, and for sure the WebAdmin (though its already integrated with Trac 0.11, some plugins require it as a dependency):
#!/bin/bash # Install some useful Trac plugins (simply comment out those you don't want) # # The WebAdmin (is already integrated in 0.11+ - but some plugins need it) easy_install http://svn.edgewall.com/repos/trac/sandbox/webadmin/ # The AccountManager easy_install http://trac-hacks.org/svn/accountmanagerplugin/trunk/ # Not good enough? Make it nicer? easy_install http://trac-hacks.org/svn/usermanagerplugin/0.11/ # IniAdmin easy_install http://trac-hacks.org/svn/iniadminplugin/0.11/ # And we HATE SPAMMERS! easy_install http://svn.edgewall.com/repos/trac/sandbox/spam-filter/ # MediaWikiPluginMacro - turn your wiki to support MediaWiki syntax easy_install http://trac-hacks.org/svn/mediawikipluginmacro/ # TOC PlugIn (auto-generate table of contents) easy_install http://trac-hacks.org/svn/tocmacro/0.11/ # Acronyms support for the Wiki easy_install http://trac-hacks.org/svn/acronymsplugin/0.11/ # If you want to include external pages into your Wiki [Include(http://www.domain.com/page)] easy_install http://trac-hacks.org/svn/includemacro/0.11/ # MultiLang support - and nicer indexes (yes, it is 0.10 - but works on 0.11) easy_install http://trac-hacks.org/svn/tracwikinegotiatorplugin/0.10/ # TicketDelete PlugIn (get rid of spam tickets) easy_install http://trac-hacks.org/svn/ticketdeleteplugin/0.11/ # TracWysiwygPlugin - for better Wiki editing easy_install http://trac-hacks.org/svn/tracwysiwygplugin/0.11/ # Graphical Statistics Plugin easy_install http://trac-hacks.org/svn/stractisticsplugin/0.10/tags/0.4.2/ # Tags PlugIn (needed for ScreenshotsPlugin - and either useful itself) easy_install http://trac-hacks.org/svn/tagsplugin/trunk/ # ScreenshotsPlugin - Maintain and use screenshots easy_install http://trac-hacks.org/svn/screenshotsplugin/0.11/ # TracDownloaderPlugin to manage Downloads easy_install http://trac-hacks.org/svn/tracdownloaderplugin/0.11/ # Now, having quite a bunch of PlugIns installed, you may need to cleanup your navbar: easy_install http://trac-hacks.org/svn/navcontrolplugin/0.11/ |
Now the global setup is done, and we need to activate it by restarting the web server:
/etc/init.d/apache2 restart
Some of the plugins may require an upgrade of your projects after installation (or activation in the project) - see below for this.
Looking for more plugins? The longest lists you will find here:
Spam protection
We are already used to "our daily spam" in mailboxes – but the "bad guys" found
new challenges flooding forums and the like. So it will be just a matter of
time until they find our trac installation – and enter Viagra tickets for penis
enlargment requests. We can protect our installation using above
mentioned SpamFilter – but that one needs to be explicitely configured for
each project (so one day we may forget doing so for a new one – or we add a new
rule and have to do so 10 times). Another option is mod_security
installed with your Apache web server. This can save your day with some nice
rules – an example configuration file is attached below,
and you may just have to adjust the URI in each rule, if your projects absolute
URI is different from /trac/<Projektname>/
.
Unfortunately, today this is quite insufficient. But something powerful is ready for us: The Spam-Filter plugin. Initially, it will require some configuration to be taken for each of your Trac projects – but believe me: when spammers find your installation, you will find it's worth it!
Initializing projects
Personalize Trac
If you, amongst others, installed the NavControl plugin, you now can clean up the probably cluttered main navigation – moving items to the context navigation, or hide unwanted ones.
Define project defaults
Now we prepare the script to setup our projects. Download the script below and open it in your favorite editor. The most important part for you to check is the configuration section at the beginning of the script. While most settings should be correct (if you stayed with all the settings as we used them in this little tutorial, the path names etc. should be fine), there are some things you for sure need to change:
Let the HomePage
point to your home page (only the page, not the protocol).
As this is used in a regular expression, take care to escape characters where
necessary. For http://server.example.com/my/projects
, the definition must
look like this: HomePage="server.example.com\/my\/projects"
.
admin
is the web user having full access to your trac projects. This doesn't
mean there must be an OS user with the same name. But this user must have a
corresponding entry in the htpassword file defined above.
Besides, that's the place where your projects user/password information will be
stored - for all projects, i.e. all users defined here have access to all your
projects (you can of course define the permissions on a per-user base later
using the WebAdmin web interface).
projects
lists up the projects you want to use trac for. It is a space
separated list, one word for each project. You can spell them mixed case (as
you like their names to be displayed) – for directories etc. the lowercase
variant of this will be used. Their SVN repositories are expected to be
directly in the RepoParentPath
(the lowercase name appended), and their Trac
repositories will be created in TracEnvParentDir
(again, the lowercase name
appended).
That's basically all you need to check. Of course you can adapt the entire script
if you feel any need to do so, e.g. the permissions in function set_perms
or the default configuration add ons (mainly PlugIn activations) in
function conf_activate
.
Run the script
Now you are done with the preparations, and simply can run the script – it needs
no parameters to be invoked. Make sure all necessary files are in the same directory
(e.g. the tracwiki.tgz
) before doing so.
Final project configuration
When the script finished successfully, you can finalize your projects configuration. Using your web browser, go to the trac page of each project, log in as the admin, and select the "Admin" tab. Focus on the "General::Basic Settings" and "trac.ini::notification" (SMTP settings) which you really need to adjust. Some other things you probably also want to adjust are to be found in the "Ticket System" section: Components, Milestones, and Versions (the other three items will probably be fine). And maybe you also want to enable some logging - you can do so in the "General::Logging" section: simply set the "Type" to file, and better set the "Log Level" to something else than "DEBUG". Finally, you may look around what else you may find... And just to be on the safe side, we again restart the web server - this is at least needed if you changed something in the Logging settings.
Once logged in as admin, you should also click the "Settings" link (on top of the navigation bar) and enter your name and email, so you are able to receive notifications.
Troubleshooting
Internal Server Error
Oh yeah - this happens from time to time. Don't say it's not your fault - in most cases it is :-) So first place to check is the web servers error log. Most likely you will find some entry like
PythonHandler trac.web.modpython_frontend: TracError: The Trac Environment needs to be upgraded. Run trac-admin /usr/local/trac/project upgrade", referer: http://server.example.com/trac/project/
The reason, again in most cases, is that you installed a new plugin (or
activated it for this project). Ah well – the error message itself tells you
what to do: trac-admin /usr/local/trac/project upgrade
. Another possible
cause is something like this:
PythonHandler trac.web.modpython_frontend: IOError: zipimport: can not open file /usr/lib/python2.4/site-packages/TracProjectMenu-1.0-py2.4.egg, referer: http://server.example.com/trac/project/settings
This time it is the other way round: You removed some plugin, and Trac is
failing to find it. In this case, check your projects trac.ini
if you still
have the plugin enabled (see the [components] section) and remove it. If that's
done, you have to restart the web server: /etc/init.d/apache2 restart
. If
it's something else, and you don't know what to do, try a server restart as
well – the cases where that solves the problem are not that rare.
One more case:
PythonHandler trac.web.modpython_frontend: IOError: [Errno 13] Permission denied: u'/usr/local/trac/project/log/trac.log'
This usually happens whenever root runs trac-admin <Pfad> permission add …
–
at a time when there is not yet a log file, but the logging has just been
enabled for the project. In this case, the file will be created, and owned by
the creator – i.e. root. The web server cannot write access the file – and thus
the error.
The fix is quite easy: chmod -R www-data:www-data /usr/share/trac
.
Only Murphy knows what else here has the wrong owner – so we catch it all.
Everything below /usr/share/trac
should be owned by Trac, so what.
If you like, you can add that command to a Cron job, so this problem automatically
gets fixed every day (or hour, whatever you put ;)
Besides: By way of exception, this time we don't need to kick the Apache to restart …
Remove global plugins
It is quite easy to globally install a plugin with easy_install
.
But noone tells you how to undo that, right? So here it comes:
To not provoke some internal server error, first check all
your projects whether that plugin is still enabled. If you did not yet
uninstall the plugin, you still can use the WebAdmin plugin
for this. Alternatively, you can check the trac.ini
files as described
above.
Now change to the /usr/lib/python2.4/site-packages
directory (oh,
you have to be root, forgot to mention that), and look for a file named
easy-install.pth
. Open it with your favorite editor, and find the
line mentioning your plugin. Remember that name – then remove this line, save
the file, and remove the file with the name you just removed from the file.
Grrr… Understood?
One more place you should look is the cache directory, whether there are some
cache files for the plugin you just deleted. The cache directory is either
located in the home directory of the user running your web server – or in the
place you configured with SetEnv PYTHON_EGG_CACHE <directory>
in your Apache
configuration. If you find some cache directory for the plugin there, you can
remove it. Ah, and don't forget to restart the web server after that (Python
still kept the settings in some cache): /etc/init.d/apache2 restart
.
Scripts used here
Initializing the Trac environment
#!/bin/bash ############################################################################### # Setting up Trac projects (c) 2007 by Izzy and IzzySoft #------------------------------------------------------------------------------ # This script will help you to setup your trac projects without having to type # too much (or to fiddle around with the commands and their syntax). Check the # [ Configuration ] section first and adapt it to your settings and needs. You # may (or may not) want to change the permissions (found in function set_perms) # and/or the default configuration (in function conf_activate). Moreover, you # for sure want to check the default wiki pages in the tracwiki.tgz (in case # you don't want to stay with the default wikis shipped with trac). If you # don't want to have all the help wikis in each project, you can take this # replacement: Instead of installing them all everywhere, it replaces the links # in the templates to point to the trac project wiki directly. ############################################################################### #==========================================================[ Configuration ]=== # Where the trac shared files are TracShared=/usr/share/trac # Base directory for your Trac repositories TracEnvParentDir=/usr/local/trac # Where to link the logos to. Remember to escape slashes ("/" must be "\/") HomePage="www.example.com" # Who will be the admin (full access permissions) for the projects? admin=john # Space separated list of projects to establish. For path names etc., these will # be converted to lowercase. For display, they will be used as-is. Each project # name must be a single word projects="MyProject OtherProject" # DB to use for Trac DBFile="db/trac.db" TracDB="sqlite:$DBFile" # Repository Type RepoType=svn # Base Repository for your SVN repositories. Project name (lowercase) will be # added here, and the result should be the projects SVN Repo Path RepoParentPath=/usr/local/svn/public # Default Template path TracTemplatePath=$TracShared/templates # Replace default wiki pages by those from tracwiki.tgz ? WikiReplace=1 # Create default forums ("Help" and "Common Discussion")? You can change the # forums/descriptions in "function forum" below. ForumCreate=1 #-----------------------------------------------------------------[ Colors ]--- red='\e[0;31m' blue='\e[0;34m' NC='\e[0m' # No Color #==============================================================[ Functions ]=== #-------------------------------------------------------=[ Progress Output ]=-- function say { echo -e "${blue}$1${NC}" } function alert { echo -e "${red}$1${NC}" } #--------------------------------------------=[ Replace default Wiki pages ]=-- function wiki_default { if [ -e $TracShared/wiki-default.ori ]; then say "Looks like the default wiki pages already have been replaced - skipping this step." else say "Replacing default wiki pages..." mv $TracShared/wiki-default $TracShared/wiki-default.ori cp $TracShared/templates $TracShared/templates.ori mkdir $TracShared/wiki-default tar xzf tracwiki.tgz -C "$TracShared" fi } #-------------------------------------------------=[ Activate some PlugIns ]=-- function conf_activate { local project="$1" say "Updating trac.ini ..." local conffile=${TracEnvParentDir}/$project/conf/trac.ini cp $conffile ${conffile}.$$ cat ${conffile}.$$|sed "s/example\.org/$HomePage/g">${conffile} cat <<EndConf >>$conffile [components] acct_mgr.admin.accountmanageradminpage = enabled acct_mgr.api.accountmanager = enabled acct_mgr.htfile.htpasswdstore = enabled acct_mgr.web_ui.accountmodule = enabled acct_mgr.web_ui.loginmodule = enabled acct_mgr.web_ui.registrationmodule = enabled iniadmin.iniadmin.iniadminplugin = enabled trac.web.auth.loginmodule = disabled tracdiscussion.admin.discussionwebadmin = enabled tracdiscussion.core.discussioncore = enabled tracdiscussion.init.discussioninit = enabled tracdiscussion.search.discussionsearch = enabled tracdiscussion.wiki.discussionwiki = enabled tracemoticons.emoticonssupport = enabled webadmin.* = enabled [account-manager] password_file = /etc/httpd/.trac password_format = htpasswd EndConf } #-----------------------------------------------------=[ SetUp Permissions ]=-- function set_perms { local project="$1" say "Setting permissions ..." # The big boss aka admin trac-admin ${TracEnvParentDir}/${project} permission add ${admin} TRAC_ADMIN # SVN Repo trac-admin ${TracEnvParentDir}/${project} permission add visitor BROWSER_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor LOG_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor FILE_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor CHANGESET_VIEW # Tickets, MileStones, etc.: trac-admin ${TracEnvParentDir}/${project} permission add visitor TICKET_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor MILESTONE_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor ROADMAP_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor WIKI_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor TIMELINE_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor SEARCH_VIEW trac-admin ${TracEnvParentDir}/${project} permission add visitor REPORT_VIEW # Users who registered with our site get additional permissions: trac-admin ${TracEnvParentDir}/${project} permission add authenticated TICKET_CREATE trac-admin ${TracEnvParentDir}/${project} permission add authenticated TICKET_APPEND # Next comes a group for our testers, who inherit all from the r/o group: trac-admin ${TracEnvParentDir}/${project} permission add tester visitor trac-admin ${TracEnvParentDir}/${project} permission add tester WIKI_CREATE trac-admin ${TracEnvParentDir}/${project} permission add tester WIKI_MODIFY # Now for our developers (inheriting all from testers) trac-admin ${TracEnvParentDir}/${project} permission add developer tester trac-admin ${TracEnvParentDir}/${project} permission add developer TICKET_MODIFY # Forum trac-admin ${TracEnvParentDir}/${project} permission add visitor DISCUSSION_VIEW trac-admin ${TracEnvParentDir}/${project} permission add authenticated DISCUSSION_APPEND trac-admin ${TracEnvParentDir}/${project} permission add tester DISCUSSION_APPEND # Rewrite permissions for anonymous (not-logged-in) users trac-admin ${TracEnvParentDir}/${project} permission remove anonymous '*' trac-admin ${TracEnvParentDir}/${project} permission add anonymous visitor } #---------------------------------------------------------[ Forum creation ]--- function forum { local db=$1/$DBFile local project=$2 local now=`date +%s` say "Creating forums for $project in database $db..." # forum(id,name,create_timestamp,forum_group,author,moderators,subject,description) # Since no forum_group exists, leave that column to 0. sqlite3 $db <<EndSQL INSERT INTO forum VALUES(1,'Help',$now,0,'$admin','$admin','Help with $project','If you have problems with $project and need help, this is the right place to ask for'); INSERT INTO forum VALUES(2,'Common Discussion',$now,0,'$admin','$admin','All about $project','Feature requests, recent development...'); EndSQL } #====================================================[ Initialize projects ]=== [ $WikiReplace -eq 1 ] && wiki_default for pname in $projects; do say "Initializing Environment for $pname ..." proj=`echo $pname|tr [:upper:] [:lower:]` trac-admin $TracEnvParentDir/$proj initenv $pname $TracDB $RepoType $RepoParentPath/$proj $TracTemplatePath chown -R www-data:www-data $TracEnvParentDir/$proj conf_activate $proj set_perms $proj say "Upgrading environment..." trac-admin ${TracEnvParentDir}/$proj upgrade [ $ForumCreate -eq 1 ] && forum $TracEnvParentDir/$proj $pname done |
Spam protection with mod_security
############################################################################### # Protect TRAC against spammers # Track rules have id:7701xx # idea taken from http://madwifi.org/wiki/FightingTracSpam (where some comments # also refer to - e.g. "spam type x") ############################################################################### #==================================================================[ Rules ]=== #--------------------------------------------------------------[ Whitelist ]--- # allow all POST requests that are not directed to one of the handlers we take # into account below SecFilterSelective REQUEST_URI "!(/trac/.+/(wiki|newticket|ticket).*$)" "nolog,allow,id:770100" #---------------------------------------------[ Spam Type 1: #preview spam ]--- # block POSTs to /ticket/<number>#preview and /newticket#preview SecFilterSelective REQUEST_URI "^/trac/.+/(newticket|ticket/[0-9]+).*\#preview" "id:770101" #--------------------------------------------[ Spam Type 2: no cookie spam ]--- # block POSTs to /wiki, /ticket and /newticket from users who don't have a trac # cookie # # CAUTION: these rules likely cause false positives, as some users tend to turn # off cookie support in their browser. Don't activate them unless you're sure # that this won't offend your visitors, or at least warn visitors. #SecFilterSelective REQUEST_URI "^/trac/.+/(wiki/|newticket|ticket/).*$" "chain,id:770102" #SecFilterSelective HTTP_COOKIE "!(trac_auth|trac_session)" #---------------------------------------[ Spam Type 3: html processor spam ]--- # don't accept usage of HTML processor in tickets / ticket comments SecFilterSelective REQUEST_URI "^/trac/.+/(newticket|ticket/).*$" "chain,id:770103" SecFilterSelective "ARG_description|ARG_comment" "#!html" #-----------------------------------------------[ Spam Type 4: markup spam ]--- # block new ticket and ticket comment POSTs if they contain more than one URL SecFilterSelective "REQUEST_URI" "^/trac/.+/(newticket|ticket/).*$" "chain,id:770104" SecFilterSelective "ARGS" "http\:/.*http\:/" #--------------------------------------------------[ Spam Type 5: LED spam ]--- # block LED spammer; his spam is not blocked by the previous rule, since he only # includes only one URL to the spamvertised website last but not least SecFilterSelective REQUEST_URI "^/trac/.+/(newticket|ticket/).*$" "chain,id:770105" SecFilterSelective "ARG_description|ARG_comment" "www.tideled.com" #-------------------------------[ Spam Type 6: attachment description spam ]--- # block tickets or comments with an http://-URL in it, if user is not properly # authenticated; throw a 403 that allows to present users with a custom error # page which explains what is going on (see below) # this rule is used on tickets as well as attachment descriptions and therefore # also catches spam type 6 # Since this prevents all not-logged-in users from refering to any URL (even # if it is pointing to something needed in the context), you may want to # disable this rule #SecFilterSelective "REQUEST_URI" "/trac/.+/(newticket|ticket/|attachment/).*$" "chain,id:770106" #SecFilterSelective HTTP_COOKIE "!trac_auth" chain #SecFilterSelective HTTP_Authorization "!Basic" chain #SecFilterSelective "ARGS" "(http|https):/" "deny,log,status:403" #==============================================[ Customized Error Messages ]=== # See the article on http://madwifi.org/wiki/FightingTracSpam for more details #----------------------------------[ Error 402: "You have to pay for ads!" ]--- # Apache allows to present users with customized error pages, and we can make # use of that feature to let spammers know what we think of 'em. Tell Apache # what file to use as error page for 402, and let it know that requests to this # file should not be handled by Trac. # # Uncomment the following lines if you want to make use of this # feature (see also step 3 of the recipe): #ErrorDocument 402 /error402.html #<Location /error402.html> # SetHandler None #</Location> # #--------------------------[ Error 403: "URLs are not allowed in tickets!" ]--- # Another use for customized error pages is, as mentioned above, to let users # know why they are not allowed to give URLs in their tickets and what they # can do to circumvent this limitation. #ErrorDocument 403 /error403.html #<Location /error403.html> # XBitHack On # SetHandler None #</Location> |
Useful Trac resources
Manuals, tutorials and HowTos
URL | Description |
---|---|
Trac Home | The official Trac homepage |
Linux Subversion Server and Trac Server | YoLinux tutorial on configuration of a Linux Subversion Server and Trac server. |
Trac on Ubuntu | Other how-tos to get Trac on your Ubuntu machine (for multiple versions) |
Egg Cooking Tutorial | How to cook python eggs (e.g. to develop your own Trac plugin) |
Egg Cooking Tutorial for Trac 0.11+ | How to cook python eggs (e.g. to develop your own Trac plugin) |
PlugIns
URL | Description |
---|---|
Trac Hacks | Macros, patches, plugins … Track Hacks is the largest repository for these I found. Follow up to its HackIndex. |
Trac PluginList | A plugin list from the main site |