Changeset - 50a39f923f31
[Not reviewed]
default
0 4 2
Marcin Kuzminski - 15 years ago 2010-05-22 02:00:39
marcin@python-works.com
Added file annotation template. Bumped version to 0.6.8. Changelog and changeset are now cleaned with js, it's still very beta.
6 files changed with 146 insertions and 101 deletions:
0 comments (0 inline, 0 general)
pylons_app/__init__.py
Show inline comments
 
"""
 
Hg app, a web based mercurial repository managment based on pylons
 
"""
 

	
 
VERSION = (0, 6, 0, 'beta')
 
VERSION = (0, 6, 8, 'beta')
 

	
 
__version__ = '.'.join((str(each) for each in VERSION[:4]))
 

	
 
def get_version():
 
    """
 
    Returns shorter version (digit parts only) as string.
 
    """
 
    return '.'.join((str(each) for each in VERSION[:3]))
pylons_app/controllers/changeset.py
Show inline comments
 
import logging
 

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

	
 
from pylons_app.lib.auth import LoginRequired
 
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
 
import logging
 

	
 

	
 
log = logging.getLogger(__name__)
 

	
 
class ChangesetController(BaseController):
 
    
 
    @LoginRequired()
 
    def __before__(self):
 
        c.repos_prefix = config['repos_name']
 
        c.repo_name = get_repo_slug(request)
 
        super(ChangesetController, self).__before__()
 
        
 
    def index(self):
 
        # Return a rendered template
 
        #return render('/changeset.mako')
 
        # or, return a string
 
        return 'Hello World'
 
    def index(self, revision):
 
        hg_model = HgModel()
 
        c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
 
                          
 
        return render('changeset/changeset.html')
pylons_app/lib/utils.py
Show inline comments
 
@@ -8,97 +8,97 @@ log = logging.getLogger(__name__)
 
def get_repo_slug(request):
 
    path_info = request.environ.get('PATH_INFO')
 
    uri_lst = path_info.split('/')   
 
    repo_name = uri_lst[1]
 
    return repo_name
 

	
 
def is_mercurial(environ):
 
    """
 
    Returns True if request's target is mercurial server - header
 
    ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
 
    """
 
    http_accept = environ.get('HTTP_ACCEPT')
 
    if http_accept and http_accept.startswith('application/mercurial'):
 
        return True
 
    return False
 

	
 
def check_repo_dir(paths):
 
    repos_path = paths[0][1].split('/')
 
    if repos_path[-1] in ['*', '**']:
 
        repos_path = repos_path[:-1]
 
    if repos_path[0] != '/':
 
        repos_path[0] = '/'
 
    if not os.path.isdir(os.path.join(*repos_path)):
 
        raise Exception('Not a valid repository in %s' % paths[0][1])
 

	
 
def check_repo(repo_name, base_path):
 

	
 
    repo_path = os.path.join(base_path, repo_name)
 

	
 
    try:
 
        r = hg.repository(ui.ui(), repo_path)
 
        hg.verify(r)
 
        #here we hnow that repo exists it was verified
 
        log.info('%s repo is already created', repo_name)
 
        return False
 
        #raise Exception('Repo exists')
 
    except RepoError:
 
        log.info('%s repo is free for creation', repo_name)
 
        #it means that there is no valid repo there...
 
        return True
 
                
 
def make_ui(path='hgwebdir.config', checkpaths=True):        
 
    """
 
    A funcion that will read python rc files and make an ui from read options
 
    
 
    @param path: path to mercurial config file
 
    """
 
    if not os.path.isfile(path):
 
        log.error('Unable to read config file %s' % path)
 
        log.warning('Unable to read config file %s' % path)
 
        return False
 
    #propagated from mercurial documentation
 
    sections = [
 
                'alias',
 
                'auth',
 
                'decode/encode',
 
                'defaults',
 
                'diff',
 
                'email',
 
                'extensions',
 
                'format',
 
                'merge-patterns',
 
                'merge-tools',
 
                'hooks',
 
                'http_proxy',
 
                'smtp',
 
                'patch',
 
                'paths',
 
                'profiling',
 
                'server',
 
                'trusted',
 
                'ui',
 
                'web',
 
                ]
 

	
 
    baseui = ui.ui()
 
    cfg = config.config()
 
    cfg.read(path)
 
    if checkpaths:check_repo_dir(cfg.items('paths'))
 

	
 
    for section in sections:
 
        for k, v in cfg.items(section):
 
            baseui.setconfig(section, k, v)
 
    
 
    return baseui
 

	
 
def invalidate_cache(name, *args):
 
    from beaker.cache import region_invalidate
 
    log.info('INVALIDATING CACHE FOR %s', name)
 
    
 
    """propaget our arguments to make sure invalidation works. First
 
    argument has to be the name of cached func name give to cache decorator
 
    without that the invalidation would not work"""
 
    tmp = [name]
 
    tmp.extend(args)
 
    args = tuple(tmp)
 
    
 
    if name == 'cached_repo_list':
pylons_app/templates/changelog/changelog.html
Show inline comments
 
<%!
 
from pylons_app.lib import filters
 
%>
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Repository managment')}
 
    ${_('Changelog - %s') % c.repo_name}
 
</%def>
 
<%def name="breadcrumbs()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    / 
 
    ${h.link_to(c.repo_name,h.url('changelog_home',repo_name=c.repo_name))}
 
    /
 
    ${_('changelog')}
 
</%def>
 
<%def name="page_nav()">
 
        <form action="log">
 
            <dl class="search">
 
                <dt><label>Search: </label></dt>
 
                <dd><input type="text" name="rev" /></dd>
 
            </dl>
 
        </form>
 

	
 
		${self.menu('changelog')}     
 
	${self.menu('changelog')}     
 
</%def>
 

	
 
<%def name="main()">
 

	
 
    <h2 class="no-link no-border">${_('Changelog')} - ${_('showing ')} ${c.size} ${_('revisions')}</h2>
 
	<noscript>${_('The revision graph only works with JavaScript-enabled browsers.')}</noscript>
 
<div>
 
${h.form(h.url.current(),method='get')}
 
	${_('Show')}: ${h.text('size',size=5,value=c.size)} ${_('revisions')}
 
	${h.submit('','set')}
 
${h.end_form()}
 
</div>
 
<div id="wrapper"  style="height:${c.canvasheight}px">
 
	<div style="float:left;height:${c.canvasheight}px">
 
		<canvas id="graph" width="224" height="${c.canvasheight}"></canvas>
 
	</div>
 
	<div style="float:left;height:${c.canvasheight}px">
 
		<ul id="graphnodes"></ul>
 

	
 
<div id="graph">
 
	##<div id="graph_nodes" style="height:1000px">
 
	##	<canvas id="graph" width="160"></canvas>
 
	##</div>
 
	<div id="graph_content">
 
		<div class="container_header">
 
			${h.form(h.url.current(),method='get')}
 
				${_('Show')}: ${h.text('size',size=5,value=c.size)} ${_('revisions')}
 
				${h.submit('','set')}
 
			${h.end_form()}
 
		</div>
 
	%for cnt,cs in enumerate(c.pagination):
 
		<div class="container">
 
			<div class="left">
 
				<div class="date">${_('commit')} ${cs.revision}: ${cs.raw_id}@${cs.date}</div>
 
				<div class="author">${cs.author}</div>
 
				<div id="chg_${cnt}" class="message">
 
					${h.link_to(cs.message,
 
					h.url('changeset_home',repo_name=c.repo_name,revision=cs._short),
 
					title=cs.message)}
 
				</div>
 
					<span class="logtags">
 
						<span class="branchtag">${cs.branch}</span>
 
						%for tag in cs.tags:
 
							<span class="tagtag">${tag}</span>
 
						%endfor
 
					</span>
 
			</div>	
 
				<div class="right">
 
					<span class="removed" title="${_('removed')}">${len(cs.removed)}</span>
 
					<span class="changed" title="${_('changed')}">${len(cs.changed)}</span>
 
					<span class="added" title="${_('added')}">${len(cs.added)}</span>
 
				</div>
 
		</div>
 
		
 
	%endfor
 
	</div>
 
</div>
 

	
 
<script type="text/javascript" src="/js/graph.js"></script>
 
<script>
 
<!-- hide script content
 

	
 
var data = ${c.jsdata|n};
 
var graph = new Graph();
 
graph.scale(39);
 

	
 
graph.edge = function(x0, y0, x1, y1, color) {
 
	
 
	this.setColor(color, 0.0, 0.65);
 
	this.ctx.beginPath();
 
	this.ctx.moveTo(x0, y0);
 
	this.ctx.lineTo(x1, y1);
 
	this.ctx.stroke();
 
	
 
}
 

	
 
var revlink = '<li style="_STYLE"><span class="desc">';
 
revlink += '<a class="list" href="/${c.repo_name}/changeset/_NODEID" title="_NODEID"><b>_DESC</b></a>';
 
revlink += '</span> _TAGS';
 
revlink += '<span class="info">_DATE, by _USER</span></li>';
 
##<script type="text/javascript" src="/js/graph2.js"></script>
 
##<script type="text/javascript" src="http://bitbucket-assets.s3.amazonaws.com/js/lib/bundle.160310Mar.js"></script>
 
##
 
##<script>
 
##<!-- hide script content
 
##
 
##var jsdata = ${c.jsdata|n};
 
##var r = new BranchRenderer();
 
##r.render(jsdata); 
 

	
 
graph.vertex = function(x, y, color, parity, cur) {
 
	
 
	this.ctx.beginPath();
 
	color = this.setColor(color, 0.25, 0.75);
 
	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
 
	this.ctx.fill();
 
	
 
	var bg = '<li class="bg parity' + parity + '"></li>';
 
	var left = (this.columns + 1) * this.bg_height;
 
	var nstyle = 'padding-left: ' + left + 'px;';
 
	var item = revlink.replace(/_STYLE/, nstyle);
 
	item = item.replace(/_PARITY/, 'parity' + parity);
 
	item = item.replace(/_NODEID/, cur[0]);
 
	item = item.replace(/_NODEID/, cur[0]);
 
	item = item.replace(/_DESC/, cur[3]);
 
	item = item.replace(/_USER/, cur[4]);
 
	item = item.replace(/_DATE/, cur[5]);
 
	
 
	var tagspan = '';
 
	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
 
		tagspan = '<span class="logtags">';
 
		if (cur[6][1]) {
 
			tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
 
			tagspan += cur[6][0] + '</span> ';
 
		} else if (!cur[6][1] && cur[6][0] != 'default') {
 
			tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
 
			tagspan += cur[6][0] + '</span> ';
 
		}
 
		if (cur[7].length) {
 
			for (var t in cur[7]) {
 
				var tag = cur[7][t];
 
				tagspan += '<span class="tagtag">' + tag + '</span> ';
 
			}
 
		}
 
		tagspan += '</span>';
 
	}
 
	
 
	item = item.replace(/_TAGS/, tagspan);
 
	return [bg, item];
 
	
 
}
 
##// stop hiding script -->
 
##</script>
 

	
 
graph.render(data);
 

	
 
// stop hiding script -->
 
</script>
 
<div>
 
	<h2>${c.pagination.pager('$link_previous ~2~ $link_next')}</h2>
 
</div>	
 
</%def>    
 
\ No newline at end of file
pylons_app/templates/changeset/changeset.html
Show inline comments
 
new file 100644
 
<%!
 
from pylons_app.lib import filters
 
%>
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('Changeset')}
 
</%def>
 
<%def name="breadcrumbs()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    / 
 
    ${h.link_to(c.repo_name,h.url('changeset_home',repo_name=c.repo_name))}
 
    /
 
    ${_('changeset')}
 
</%def>
 
<%def name="page_nav()">
 
    ${self.menu('changelog')}     
 
</%def>
 

	
 
<%def name="main()">
 
    <h2 class="no-link no-border">${_('Changeset')}</h2>
 
    <div class="cs_files">
 
			%for filenode in c.changeset.added:
 
				<p class="cs_added">${filenode}</p>
 
			%endfor
 
			%for filenode in c.changeset.changed:
 
				<p class="cs_changed">${filenode}</p>
 
			%endfor
 
			%for filenode in c.changeset.removed:
 
				<p class="cs_removed">${filenode}</p>
 
			%endfor
 
	</div>			
 
</%def>    
 
\ No newline at end of file
pylons_app/templates/files/files_annotate.html
Show inline comments
 
new file 100644
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('File annotate')}
 
</%def>
 
<%def name="breadcrumbs()">
 
    ${h.link_to(u'Home',h.url('/'))}
 
    / 
 
    ${h.link_to(c.repo_name,h.url('files_home',repo_name=c.repo_name))}
 
    /
 
    ${_('files')}
 
</%def>
 
<%def name="page_nav()">
 
		${self.menu('files')}     
 
</%def>
 
<%def name="css()">
 
	<link rel="stylesheet" href="/css/monoblue_custom.css" type="text/css" />
 
	<link rel="stylesheet" href="/css/pygments.css" type="text/css" />
 
</%def>
 
<%def name="main()">
 
    <h2 class="no-link no-border">${_('Annotate')}</h2>
 
	<div id="files_data">
 
		<h2>${_('Location')}: ${h.files_breadcrumbs(c.repo_name,c.cur_rev,c.file.path)}</h2>
 
		<dl class="overview">
 
			<dt>${_('Revision')}</dt>
 
			<dd>r${c.file.last_changeset.revision}:${c.file.last_changeset._short}</dd>
 
			<dt>${_('Size')}</dt>
 
			<dd>${h.format_byte_size(c.file.size,binary=True)}</dd>
 
			<dt>${_('Options')}</dt>
 
			<dd>${h.link_to(_('source'),
 
			h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}  / ${h.link_to(_('raw'),
 
			h.url('files_raw_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=c.f_path))}</dd>				
 
		</dl>
 
		<div id="body" class="codeblock">
 
			<div class="code-header">
 
				<div class="revision">${c.file.name}@r${c.file.last_changeset.revision}:${c.file.last_changeset._short}</div>
 
				<div class="commit" style="font-size:70%">"${c.file_msg}"</div>
 
			</div>
 
			<div class="code-body">
 
				${h.pygmentize_annotation(c.annotate,c.repo_name)}
 
			</div>
 
		</div>
 
	</div>
 
</%def> 
 
\ No newline at end of file
0 comments (0 inline, 0 general)