Changeset - 5e2470ebdbc6
[Not reviewed]
default
0 7 0
Marcin Kuzminski - 16 years ago 2010-04-26 00:38:53
marcin@python-works.com
Added repo switcher, in base and long term caching for this.
7 files changed with 59 insertions and 12 deletions:
0 comments (0 inline, 0 general)
development.ini
Show inline comments
 
################################################################################
 
################################################################################
 
# pylons_app - Pylons environment configuration                                #
 
#                                                                              # 
 
# The %(here)s variable will be replaced with the parent directory of this file#
 
################################################################################
 

	
 
[DEFAULT]
 
debug = true
 
############################################
 
## Uncomment and replace with the address ##
 
## which should receive any error reports ##
 
############################################
 
#email_to = marcin.kuzminski@etelko.pl
 
#smtp_server = mail.etelko.pl
 
#error_email_from = paste_error@localhost
 
#smtp_username = 
 
#smtp_password = 
 
#error_message = 'mercurial crash !'
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before
 
threadpool_max_requests = 2
 

	
 
##option to use threads of process
 
use_threadpool = true
 

	
 
use = egg:Paste#http
 
host = 127.0.0.1
 
port = 5000
 

	
 
[app:main]
 
use = egg:pylons_app
 
full_stack = true
 
static_files = true
 
lang=en
 
cache_dir = %(here)s/data
 
repos_name = Python-works
 

	
 
####################################
 
###         BEAKER CACHE        ####
 
####################################
 
beaker.cache.data_dir=/tmp/cache/data
 
beaker.cache.lock_dir=/tmp/cache/lock
 
beaker.cache.regions=short_term
 
beaker.cache.regions=short_term,long_term
 
beaker.cache.short_term.type=file
 
beaker.cache.short_term.expire=3600
 
beaker.cache.short_term.type=memory
 
beaker.cache.short_term.expire=60
 
    
 

	
 
################################################################################
 
## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*  ##
 
## Debug mode will enable the interactive debugging tool, allowing ANYONE to  ##
 
## execute malicious code after an exception is raised.                       ##
 
################################################################################
 
#set debug = false
 

	
 
##################################
 
###       LOGVIEW CONFIG       ###
 
##################################
 
logview.sqlalchemy = #faa
 
logview.pylons.templating = #bfb
 
logview.pylons.util = #eee
 

	
 
#########################################################
 
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 
#########################################################
 
sqlalchemy.db1.url = sqlite:///%(here)s/hg_app.db
 
#sqlalchemy.db1.echo = False
 
#sqlalchemy.db1.pool_recycle = 3600
 
sqlalchemy.convert_unicode = true
 

	
 
################################
 
### LOGGING CONFIGURATION   ####
 
################################
 
[loggers]
 
keys = root, routes, pylons_app, sqlalchemy
 

	
 
[handlers]
 
keys = console
 

	
 
[formatters]
 
keys = generic
 

	
 
#############
 
## LOGGERS ##
 
#############
 
[logger_root]
 
level = NOTSET
 
handlers = console
 

	
 
[logger_routes]
 
level = DEBUG
 
handlers = console
 
qualname = routes.middleware
 
# "level = DEBUG" logs the route matched and routing variables.
 

	
 
[logger_pylons_app]
 
level = DEBUG
 
handlers = console
 
qualname = pylons_app
 

	
 

	
 
[logger_sqlalchemy]
 
level = INFO
 
handlers = console
 
qualname = sqlalchemy.engine
 
propagate = 0
 

	
 
##############
 
## HANDLERS ##
 
##############
 

	
 
[handler_console]
 
class = StreamHandler
 
args = (sys.stderr,)
 
level = NOTSET
 
formatter = generic
 

	
 
################
 
## FORMATTERS ##
 
################
 

	
 
[formatter_generic]
 
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 
datefmt = %Y-%m-%d %H:%M:%S
 

	
production.ini
Show inline comments
 
################################################################################
 
################################################################################
 
# pylons_app - Pylons environment configuration                                #
 
#                                                                              # 
 
# The %(here)s variable will be replaced with the parent directory of this file#
 
################################################################################
 

	
 
[DEFAULT]
 
debug = true
 
############################################
 
## Uncomment and replace with the address ##
 
## which should receive any error reports ##
 
############################################
 
#email_to = marcin.kuzminski@etelko.pl
 
#smtp_server = mail.etelko.pl
 
#error_email_from = paste_error@localhost
 
#smtp_username = 
 
#smtp_password = 
 
#error_message = 'mercurial crash !'
 

	
 
[server:main]
 
##nr of threads to spawn
 
threadpool_workers = 5
 

	
 
##max request before
 
threadpool_max_requests = 2
 

	
 
##option to use threads of process
 
use_threadpool = true
 

	
 
use = egg:Paste#http
 
host = 127.0.0.1
 
port = 8001
 

	
 
[app:main]
 
use = egg:pylons_app
 
full_stack = true
 
static_files = true
 
lang=en
 
cache_dir = %(here)s/data
 
repos_name = Python-works
 

	
 
####################################
 
###         BEAKER CACHE        ####
 
####################################
 
beaker.cache.data_dir=/tmp/cache/data
 
beaker.cache.lock_dir=/tmp/cache/lock
 
beaker.cache.regions=short_term
 
beaker.cache.regions=short_term,long_term
 
beaker.cache.short_term.type=file
 
beaker.cache.short_term.expire=3600
 
beaker.cache.short_term.type=memory
 
beaker.cache.short_term.expire=3600
 
beaker.cache.short_term.expire=60
 
    
 
################################################################################
 
## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*  ##
 
## Debug mode will enable the interactive debugging tool, allowing ANYONE to  ##
 
## execute malicious code after an exception is raised.                       ##
 
################################################################################
 
set debug = false
 

	
 
##################################
 
###       LOGVIEW CONFIG       ###
 
##################################
 
logview.sqlalchemy = #faa
 
logview.pylons.templating = #bfb
 
logview.pylons.util = #eee
 

	
 
#########################################################
 
### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG    ###
 
#########################################################
 
sqlalchemy.db1.url = sqlite:///%(here)s/hg_app.db
 
#sqlalchemy.db1.echo = True
 
#sqlalchemy.db1.pool_recycle = 3600
 
sqlalchemy.convert_unicode = true
 

	
 
################################
 
### LOGGING CONFIGURATION   ####
 
################################
 
[loggers]
 
keys = root, routes, pylons_app, sqlalchemy
 

	
 
[handlers]
 
keys = console
 

	
 
[formatters]
 
keys = generic
 

	
 
#############
 
## LOGGERS ##
 
#############
 
[logger_root]
 
level = INFO
 
handlers = console
 

	
 
[logger_routes]
 
level = INFO
 
handlers = console
 
qualname = routes.middleware
 
# "level = DEBUG" logs the route matched and routing variables.
 

	
 
[logger_pylons_app]
 
level = DEBUG
 
handlers = console
 
qualname = pylons_app
 

	
 

	
 
[logger_sqlalchemy]
 
level = DEBUG
 
handlers = console
 
qualname = sqlalchemy.engine
 

	
 
##############
 
## HANDLERS ##
 
##############
 

	
 
[handler_console]
 
class = StreamHandler
 
args = (sys.stderr,)
 
level = NOTSET
 
formatter = generic
 

	
 
################
 
## FORMATTERS ##
 
################
 

	
 
[formatter_generic]
 
format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 
datefmt = %Y-%m-%d %H:%M:%S
 

	
pylons_app/config/environment.py
Show inline comments
 
"""Pylons environment configuration"""
 
import logging
 
import os
 

	
 
from mako.lookup import TemplateLookup
 
from pylons.configuration import PylonsConfig
 
from pylons.error import handle_mako_error
 
from sqlalchemy import engine_from_config
 

	
 
import pylons_app.lib.app_globals as app_globals
 
import pylons_app.lib.helpers
 
from pylons_app.config.routing import make_map
 
from pylons_app.model import init_model
 

	
 
log = logging.getLogger(__name__)
 

	
 
def load_environment(global_conf, app_conf):
 
    """Configure the Pylons environment via the ``pylons.config``
 
    object
 
    """
 
    config = PylonsConfig()
 
    
 
    # Pylons paths
 
    root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
    paths = dict(root=root,
 
                 controllers=os.path.join(root, 'controllers'),
 
                 static_files=os.path.join(root, 'public'),
 
                 templates=[os.path.join(root, 'templates')])
 

	
 
    # Initialize config with the basic options
 
    config.init_app(global_conf, app_conf, package='pylons_app', paths=paths)
 

	
 
    config['routes.map'] = make_map(config)
 
    config['pylons.app_globals'] = app_globals.Globals(config)
 
    config['pylons.h'] = pylons_app.lib.helpers
 
    
 
    # Setup cache object as early as possible
 
    import pylons
 
    pylons.cache._push_object(config['pylons.app_globals'].cache)
 
    
 

	
 
    # Create the Mako TemplateLookup, with the default auto-escaping
 
    config['pylons.app_globals'].mako_lookup = TemplateLookup(
 
        directories=paths['templates'],
 
        error_handler=handle_mako_error,
 
        module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
 
        input_encoding='utf-8', default_filters=['escape'],
 
        imports=['from webhelpers.html import escape'])
 

	
 
    #sets the c attribute access when don't existing attribute ar accessed
 
    config['pylons.strict_tmpl_context'] = False
 
    config['pylons.strict_tmpl_context'] = True
 
    
 
    #MULTIPLE DB configs
 
    # Setup the SQLAlchemy database engine
 
    if config['debug']:
 
        #use query time debugging.
 
        from pylons_app.lib.timerproxy import TimerProxy
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
 
                                                            proxy=TimerProxy())
 
    else:
 
        sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
 

	
 
    init_model(sa_engine_db1)
 

	
 
    # CONFIGURATION OPTIONS HERE (note: all config options will override
 
    # any Pylons config options)
 
    
 
    return config
pylons_app/controllers/summary.py
Show inline comments
 
import logging
 

	
 
from pylons import tmpl_context as c, app_globals as g, session, request, config, url
 
from pylons.controllers.util import abort, redirect
 

	
 
from pylons_app.lib.base import BaseController, render
 
from pylons_app.lib.utils import get_repo_slug
 
from pylons_app.model.hg_model import HgModel
 
log = logging.getLogger(__name__)
 

	
 
class SummaryController(BaseController):
 
    def __before__(self):
 
        c.repos_prefix = config['repos_name']
 
        
 
        c.repo_name = get_repo_slug(request)
 
        
 
    def index(self):
 
        hg_model = HgModel()
 
        c.repo_info = hg_model.get_repo(c.repo_name)
 
        c.repo_changesets = c.repo_info.get_changesets(10)
 
        
 
        e = request.environ
 
        uri = r'%(protocol)s://%(user)s@%(host)s/%(repo_name)s' % {
 
                                                'protocol': e.get('wsgi.url_scheme'),
 
                                                'user':e.get('REMOTE_USER'),
 
                                                'host':e.get('HTTP_HOST'),
 
                                                'repo_name':c.repo_name,
 
                                                }
 
        c.clone_repo_url = url(uri)
 
        #c.repo_tags = c.repo_info.get_tags(limit=10)
 
        #c.repo_branches = c.repo_info.get_branches(limit=10)
 
        c.repo_tags = []#c.repo_info.get_tags(limit=10)
 
        c.repo_branches = []#c.repo_info.get_branches(limit=10)
 
        return render('/summary.html')
pylons_app/lib/base.py
Show inline comments
 
"""The base Controller API
 

	
 
Provides the BaseController class for subclassing.
 
"""
 
from pylons.controllers import WSGIController
 
from pylons.templating import render_mako as render
 
from pylons_app.model import meta
 
from beaker.cache import cache_region
 
from pylons import tmpl_context as c
 
from pylons_app.model.hg_model import HgModel
 

	
 
class BaseController(WSGIController):
 

	
 
    def _load_repos(self):
 
                
 
        @cache_region('long_term', 'repo_list_2')
 
        def _get_repos():
 
            return [rep['name'] for rep in HgModel().get_repos()]
 
        
 
        c.repo_list = _get_repos()
 
        
 
    def __call__(self, environ, start_response):
 
        """Invoke the Controller"""
 
        # WSGIController.__call__ dispatches to the Controller method
 
        # the request is routed to. This routing information is
 
        # available in environ['pylons.routes_dict']
 
        self._load_repos()
 
        try:
 
            return WSGIController.__call__(self, environ, start_response)
 
        finally:
 
            meta.Session.remove()
pylons_app/public/css/monoblue_custom.css
Show inline comments
 
/*** Initial Settings ***/
 
* {
 
  margin: 0;
 
  padding: 0;
 
  font-weight: normal;
 
  font-style: normal;
 
}
 

	
 
html {
 
  font-size: 100%;
 
  font-family: sans-serif;
 
}
 

	
 
body {
 
  font-size: 77%;
 
  margin: 15px 50px;
 
  background: #DBD4C6;
 
}
 

	
 
a {
 
  color:#0000cc;
 
  text-decoration: none;
 
}
 
/*** end of Initial Settings ***/
 

	
 

	
 
/** common settings **/
 
div#main{
 
padding:5px;
 
}
 
div#container {
 
  background: #FFFFFF;
 
  position: relative;
 
  color: #666;
 
}
 

	
 
div.page-header {
 
  padding: 50px 20px 0;
 
  background: #556cb5 top left repeat-x;
 
  position: relative;
 
}
 
  div.page-header h1 {
 
    margin: 10px 0 30px;
 
    font-size: 1.8em;
 
    font-weight: bold;
 
    font-family: osaka,'MS P Gothic', Georgia, serif;
 
    font-family: sans-serif;
 
    letter-spacing: 1px;
 
    color: #DDD;
 
  }
 
  div.page-header h1 a {
 
    font-weight: bold;
 
    color: #FFF;
 
  }
 
  div.page-header a {
 
    text-decoration: none;
 
  }
 

	
 
  div.page-header form {
 
    position: absolute;
 
    margin-bottom: 2px;
 
    bottom: 0;
 
    right: 20px;
 
  }
 
  div.page-header form label {
 
    color: #DDD;
 
  }
 
  div.page-header form input {
 
    padding: 2px;
 
    border: solid 1px #DDD;
 
  }
 
  div.page-header form dl {
 
    overflow: hidden;
 
  }
 
  div.page-header form dl dt {
 
    font-size: 1.2em;
 
  }
 
  div.page-header form dl dt,
 
  div.page-header form dl dd {
 
    margin: 0 0 0 5px;
 
    float: left;
 
    height: 24px;
 
    line-height: 20px;
 
  }
 

	
 
  ul.page-nav {
 
    margin: 10px 0 0 0;
 
    list-style-type: none;
 
    overflow: hidden;
 
    width: 800px;
 
  }
 
    ul.page-nav li {
 
      margin: 0 2px 0 0;
 
      float: left;
 
      width: 80px;
 
      height: 24px;
 
      font-size: 1.1em;
 
      line-height: 24px;
 
      text-align: center;
 
      text-align: center;    
 
    }
 
    ul.page-nav li.current {
 
      background: #FFF;
 
      padding-right:5px;
 
      padding-left:5px;
 
    }
 
    ul.page-nav li a {
 
      height: 24px;
 
      color: #666;
 
      padding-right:5px;
 
      padding-left:5px;        
 
      background: #DDD;
 
      display: block;
 
      text-decoration: none;
 
    }
 
    ul.page-nav li a:hover {
 
      color:#333;
 
      background: #FFF;
 
    }
 

	
 
ul.submenu {
 
  margin: 10px 0 -10px 20px;
 
  list-style-type: none;
 
}
 
ul.submenu li {
 
  margin: 0 10px 0 0;
 
  font-size: 1.2em;
 
  display: inline;
 
}
 

	
 
h2 {
 
  margin: 20px 0 10px;
 
  height: 30px;
 
  line-height: 30px;
 
  text-indent: 20px;
 
  background: #FFF;
 
  font-size: 1.2em;
 
  border-top: dotted 1px #D5E1E6;
 
  font-weight: bold;
 
}
 
h2.no-link {
 
  color:#006699;
 
}
 
h2.no-border {
 
  color: #FFF;
 
  background: #006699;
 
  border: 0;
 
}
 
h2 a {
 
  font-weight:bold;
 
  color:#006699;
 
}
 

	
 
div.page-path {
 
  text-align: right;
 
  padding: 20px 30px 10px 0;
 
  border:solid #d9d8d1;
 
  border-width:0px 0px 1px;
 
  font-size: 1.2em;
 
}
 

	
 
div.page-footer {
 
  margin: 50px 0 0;
 
  position: relative;
 
}
 
  div.page-footer p {
 
    position: relative;
 
    left: 20px;
 
    bottom: 5px;
 
    font-size: 1.2em;
 
  }
 

	
 
  ul.rss-logo {
 
    position: absolute;
 
    top: -10px;
 
    right: 20px;
 
    height: 20px;
 
    list-style-type: none;
 
  }
 
  ul.rss-logo li {
 
    display: inline;
 
  }
 
  ul.rss-logo li a {
 
    padding: 3px 6px;
 
    line-height: 10px;
 
    border:1px solid;
 
    border-color:#fcc7a5 #7d3302 #3e1a01 #ff954e;
 
    color:#ffffff;
 
    background-color:#ff6600;
 
    font-weight:bold;
 
    font-family:sans-serif;
 
    font-size:10px;
 
    text-align:center;
 
    text-decoration:none;
 
  }
 
  div.rss-logo li a:hover {
 
    background-color:#ee5500;
 
  }
 

	
 
p.normal {
 
  margin: 20px 0 20px 30px;
 
  font-size: 1.2em;
 
}
 

	
 
table {
 
  margin: 0 0 0 0;  
 
  border-collapse: collapse;
 
}
 
/*
 
table tr td {
 
  font-size: 1.1em;
 
}
 
table tr td.nowrap {
 
  white-space: nowrap;
 
}
 
*/
 
table tr.parity0:hover,table tr.parity1:hover {
 
  background: #D5E1E6;
 
}
 

	
 
table tr.parity0 {
 
  background: #EAEAE9;
 
}
 
table tr.parity1 {
 
  background: #FFFFFF;
 
}
 
table tr td {
 
  padding: 3px 3px;
 
}
 
table.annotated tr td {
 
  padding: 0px 3px;
 
}
 

	
 
span.logtags span {
 
  padding: 2px 6px;
 
  font-weight: normal;
 
  font-size: 11px;
 
  border: 1px solid;
 
  background-color: #ffaaff;
 
  border-color: #ffccff #ff00ee #ff00ee #ffccff;
 
}
 
span.logtags span.tagtag {
 
  background-color: #ffffaa;
 
  border-color: #ffffcc #ffee00 #ffee00 #ffffcc;
 
}
 
span.logtags span.branchtag {
 
  background-color: #aaffaa;
 
  border-color: #ccffcc #00cc33 #00cc33 #ccffcc;
 
}
 
span.logtags span.inbranchtag {
 
  background-color: #d5dde6;
 
  border-color: #e3ecf4 #9398f4 #9398f4 #e3ecf4;
 
}
 

	
 
div.diff pre {
 
  margin: 10px 0 0 0;
 
}
 
div.diff pre span {
 
  font-family: monospace;
 
  white-space: pre;
 
  font-size: 1.2em;
 
  padding: 3px 0;
 
}
 
td.source {
 
  white-space: pre;
 
  font-family: monospace;
 
  margin: 10px 30px 0;
 
  font-size: 1.2em;
 
  font-family: monospace;
 
}
 
  div.source div.parity0,
 
  div.source div.parity1 {
 
    padding: 1px;
 
    font-size: 1.2em;
 
  }
 
  div.source div.parity0 {
 
    background: #F1F6F7;
 
  }
 
  div.source div.parity1 {
 
    background: #FFFFFF;
 
  }
 
div.parity0:hover,
 
div.parity1:hover {
 
  background: #D5E1E6;
 
}
 
.linenr {
 
  color: #999;
 
  text-align: right;
 
}
 
.lineno {
 
  text-align: right;
 
}
 
.lineno a {
 
  color: #999;
 
}
 
td.linenr {
 
  width: 60px;
 
}
 

	
 
div#powered-by {
 
  position: absolute;
 
  width: 75px;
 
  top: 15px;
pylons_app/templates/base/base.html
Show inline comments
 
## -*- coding: utf-8 -*-
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml">
 
<head>
 
    <link rel="icon" href="/images/hgicon.png" type="image/png" />
 
    <meta name="robots" content="index, nofollow"/>
 
    <title>${next.title()}</title>
 
    ${self.css()}
 
    ${self.js()}
 
</head>
 

	
 
<body>
 
<div id="container">
 
    <div class="page-header">
 
        <h1>
 
            ${next.breadcrumbs()}
 
        </h1>
 
        <ul class="page-nav">
 
            ${self.page_nav()}
 
        </ul>
 
    </div>
 
    <div id="main">
 
    	${next.main()}
 
    </div>
 
    <div class="page-footer">
 
        Mercurial App &copy; 2010
 
    </div>   
 

	
 
    <div id="powered-by">
 
        <p>
 
        <a href="http://mercurial.selenic.com/" title="Mercurial">
 
            <img src="/images/hglogo.png" width="75" height="90" alt="mercurial"/></a>
 
        </p>
 
    </div>
 

	
 
    <div id="corner-top-left"></div>
 
    <div id="corner-top-right"></div>
 
    <div id="corner-bottom-left"></div>
 
    <div id="corner-bottom-right"></div>
 

	
 
</div>
 
</body>
 
</html>
 

	
 
<%def name="page_nav()">
 

	
 
	${self.menu()}
 

	
 
</%def>
 

	
 

	
 
<%def name="menu(current)">
 
        <ul class="page-nav">
 

	
 
        	<script>
 
        	YAHOO.util.Event.onDOMReady(function(){
 
				YAHOO.util.Event.addListener('repo_switcher','click',function(){
 
					if(YAHOO.util.Dom.hasClass('repo_switcher','selected')){
 
						YAHOO.util.Dom.setStyle('switch_repos','display','none');
 
						YAHOO.util.Dom.removeClass('repo_switcher','selected');
 
					}
 
					else{
 
						YAHOO.util.Dom.setStyle('switch_repos','display','');
 
						YAHOO.util.Dom.addClass('repo_switcher','selected');
 
					}
 
					});
 
				YAHOO.util.Event.addListener('repos_list','change',function(e){
 
		            var wa = YAHOO.util.Dom.get('repos_list').value;
 
		        	
 
		            var url = "${h.url('summary_home',repo_name='__REPLACE__')}".replace('__REPLACE__',wa);
 
			        window.location = url;
 
				})
 
            });
 
        	</script>
 
			<li>
 
				<a id="repo_switcher" title="${_('Switch repository')}" href="#">&darr;</a>
 
				<div id="switch_repos" style="display:none;position: absolute;width: 150px;height: 25px;background-color: #DDDDDD">
 
					<select id="repos_list">
 
					%for repo in c.repo_list:
 
						<option value="${repo}">${repo}</option>
 
					%endfor
 
					</select>
 
				</div>			
 
			</li>
 
            <li 
 
            %if current=='summary':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='summary',_('summary'),h.url('summary_home',repo_name=c.repo_name))}</li>
 
            <li 
 
            %if current=='changelog':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='changelog',_('changelog'),h.url('changelog_home',repo_name=c.repo_name))}</li>
 
            <li 
 
            %if current=='branches':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='branches',_('branches'),h.url('branches_home',repo_name=c.repo_name))}</li>
 
            <li 
 
            %if current=='tags':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='tags',_('tags'),h.url('tags_home',repo_name=c.repo_name))}</li>
 
            <li 
 
            %if current=='graph':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='graph',_('graph'),h.url('graph_home',repo_name=c.repo_name))}</li>
 
            <li 
 
            %if current=='files':
 
            	class='current' 
 
            %endif
 
            >${h.link_to_unless(current=='files',_('files'),h.url('files_home',repo_name=c.repo_name))}</li>
 
        </ul>
 
</%def>
 

	
 
<%def name="css()">
 
<link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
 
</%def>
 

	
 
<%def name="js()">
 
<script type="text/javascript" src="/js/yui/utilities/utilities.js"></script>
 
</%def>
 
\ No newline at end of file
0 comments (0 inline, 0 general)