##// END OF EJS Templates
added permission functions to webhelpers, updated dbmanage permissions
marcink -
r307:504feff5 default
parent child Browse files
Show More
@@ -1,142 +1,143 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # database managment for hg app
3 # database managment for hg app
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5
5
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20
20
21 """
21 """
22 Created on April 10, 2010
22 Created on April 10, 2010
23 database managment and creation for hg app
23 database managment and creation for hg app
24 @author: marcink
24 @author: marcink
25 """
25 """
26
26
27 from os.path import dirname as dn, join as jn
27 from os.path import dirname as dn, join as jn
28 import os
28 import os
29 import sys
29 import sys
30 ROOT = dn(dn(dn(os.path.realpath(__file__))))
30 ROOT = dn(dn(dn(os.path.realpath(__file__))))
31 sys.path.append(ROOT)
31 sys.path.append(ROOT)
32
32
33 from pylons_app.lib.auth import get_crypt_password
33 from pylons_app.lib.auth import get_crypt_password
34 from pylons_app.model import init_model
34 from pylons_app.model import init_model
35 from pylons_app.model.db import User, Permission
35 from pylons_app.model.db import User, Permission
36 from pylons_app.model.meta import Session, Base
36 from pylons_app.model.meta import Session, Base
37 from sqlalchemy.engine import create_engine
37 from sqlalchemy.engine import create_engine
38 import logging
38 import logging
39
39
40 log = logging.getLogger('db manage')
40 log = logging.getLogger('db manage')
41 log.setLevel(logging.DEBUG)
41 log.setLevel(logging.DEBUG)
42 console_handler = logging.StreamHandler()
42 console_handler = logging.StreamHandler()
43 console_handler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)03d"
43 console_handler.setFormatter(logging.Formatter("%(asctime)s.%(msecs)03d"
44 " %(levelname)-5.5s [%(name)s] %(message)s"))
44 " %(levelname)-5.5s [%(name)s] %(message)s"))
45 log.addHandler(console_handler)
45 log.addHandler(console_handler)
46
46
47 class DbManage(object):
47 class DbManage(object):
48 def __init__(self, log_sql):
48 def __init__(self, log_sql):
49 self.dbname = 'hg_app.db'
49 self.dbname = 'hg_app.db'
50 dburi = 'sqlite:////%s' % jn(ROOT, self.dbname)
50 dburi = 'sqlite:////%s' % jn(ROOT, self.dbname)
51 engine = create_engine(dburi, echo=log_sql)
51 engine = create_engine(dburi, echo=log_sql)
52 init_model(engine)
52 init_model(engine)
53 self.sa = Session()
53 self.sa = Session()
54 self.db_exists = False
54 self.db_exists = False
55
55
56 def check_for_db(self, override):
56 def check_for_db(self, override):
57 log.info('checking for exisiting db')
57 log.info('checking for exisiting db')
58 if os.path.isfile(jn(ROOT, self.dbname)):
58 if os.path.isfile(jn(ROOT, self.dbname)):
59 self.db_exists = True
59 self.db_exists = True
60 log.info('database exisist')
60 log.info('database exisist')
61 if not override:
61 if not override:
62 raise Exception('database already exists')
62 raise Exception('database already exists')
63
63
64 def create_tables(self, override=False):
64 def create_tables(self, override=False):
65 """
65 """
66 Create a auth database
66 Create a auth database
67 """
67 """
68 self.check_for_db(override)
68 self.check_for_db(override)
69 if override:
69 if override:
70 log.info("database exisist and it's going to be destroyed")
70 log.info("database exisist and it's going to be destroyed")
71 if self.db_exists:
71 if self.db_exists:
72 os.remove(jn(ROOT, self.dbname))
72 os.remove(jn(ROOT, self.dbname))
73 Base.metadata.create_all(checkfirst=override)
73 Base.metadata.create_all(checkfirst=override)
74 log.info('Created tables for %s', self.dbname)
74 log.info('Created tables for %s', self.dbname)
75
75
76 def admin_prompt(self):
76 def admin_prompt(self):
77 import getpass
77 import getpass
78 username = raw_input('Specify admin username:')
78 username = raw_input('Specify admin username:')
79 password = getpass.getpass('Specify admin password:')
79 password = getpass.getpass('Specify admin password:')
80 self.create_user(username, password, True)
80 self.create_user(username, password, True)
81
81
82 def create_user(self, username, password, admin=False):
82 def create_user(self, username, password, admin=False):
83
83
84 log.info('creating default user')
84 log.info('creating default user')
85 #create default user for handling default permissions.
85 #create default user for handling default permissions.
86 def_user = User()
86 def_user = User()
87 def_user.username = 'default'
87 def_user.username = 'default'
88 def_user.password = 'default'
88 def_user.password = 'default'
89 def_user.name = 'default'
89 def_user.name = 'default'
90 def_user.lastname = 'default'
90 def_user.lastname = 'default'
91 def_user.email = 'default@default'
91 def_user.email = 'default@default'
92 def_user.admin = False
92 def_user.admin = False
93 def_user.active = False
93 def_user.active = False
94
94
95 self.sa.add(def_user)
95 self.sa.add(def_user)
96
96
97 log.info('creating administrator user %s', username)
97 log.info('creating administrator user %s', username)
98 new_user = User()
98 new_user = User()
99 new_user.username = username
99 new_user.username = username
100 new_user.password = get_crypt_password(password)
100 new_user.password = get_crypt_password(password)
101 new_user.name = 'Hg'
101 new_user.name = 'Hg'
102 new_user.lastname = 'Admin'
102 new_user.lastname = 'Admin'
103 new_user.email = 'admin@localhost'
103 new_user.email = 'admin@localhost'
104 new_user.admin = admin
104 new_user.admin = admin
105 new_user.active = True
105 new_user.active = True
106
106
107 try:
107 try:
108 self.sa.add(new_user)
108 self.sa.add(new_user)
109 self.sa.commit()
109 self.sa.commit()
110 except:
110 except:
111 self.sa.rollback()
111 self.sa.rollback()
112 raise
112 raise
113
113
114 def create_permissions(self):
114 def create_permissions(self):
115 #module.(access|create|change|delete)_[name]
115 #module.(access|create|change|delete)_[name]
116 #module.(read|write|owner)
116 #module.(read|write|owner)
117 perms = [('repository.none', 'Repository no access'),
117 perms = [('repository.none', 'Repository no access'),
118 ('repository.read', 'Repository read access'),
118 ('repository.read', 'Repository read access'),
119 ('repository.write', 'Repository write access'),
119 ('repository.write', 'Repository write access'),
120 ('repository.admin', 'Repository admin access'),
120 ('repository.admin', 'Repository admin access'),
121 ('hg.admin', 'Hg Administrator'),
121 ]
122 ]
122
123
123 for p in perms:
124 for p in perms:
124 new_perm = Permission()
125 new_perm = Permission()
125 new_perm.permission_name = p[0]
126 new_perm.permission_name = p[0]
126 new_perm.permission_longname = p[1]
127 new_perm.permission_longname = p[1]
127 try:
128 try:
128 self.sa.add(new_perm)
129 self.sa.add(new_perm)
129 self.sa.commit()
130 self.sa.commit()
130 except:
131 except:
131 self.sa.rollback()
132 self.sa.rollback()
132 raise
133 raise
133
134
134
135
135
136
136 if __name__ == '__main__':
137 if __name__ == '__main__':
137 dbmanage = DbManage(log_sql=True)
138 dbmanage = DbManage(log_sql=True)
138 dbmanage.create_tables(override=True)
139 dbmanage.create_tables(override=True)
139 dbmanage.admin_prompt()
140 dbmanage.admin_prompt()
140 dbmanage.create_permissions()
141 dbmanage.create_permissions()
141
142
142
143
@@ -1,300 +1,305 b''
1 """Helper functions
1 """Helper functions
2
2
3 Consists of functions to typically be used within templates, but also
3 Consists of functions to typically be used within templates, but also
4 available to Controllers. This module is available to both as 'h'.
4 available to Controllers. This module is available to both as 'h'.
5 """
5 """
6 from pygments.formatters import HtmlFormatter
6 from pygments.formatters import HtmlFormatter
7 from pygments import highlight as code_highlight
7 from pygments import highlight as code_highlight
8 from pylons import url, app_globals as g
8 from pylons import url, app_globals as g
9 from pylons.i18n.translation import _, ungettext
9 from pylons.i18n.translation import _, ungettext
10 from vcs.utils.annotate import annotate_highlight
10 from vcs.utils.annotate import annotate_highlight
11 from webhelpers.html import literal, HTML, escape
11 from webhelpers.html import literal, HTML, escape
12 from webhelpers.html.tools import *
12 from webhelpers.html.tools import *
13 from webhelpers.html.builder import make_tag
13 from webhelpers.html.builder import make_tag
14 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
14 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
15 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
15 end_form, file, form, hidden, image, javascript_link, link_to, link_to_if, \
16 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
16 link_to_unless, ol, required_legend, select, stylesheet_link, submit, text, \
17 password, textarea, title, ul, xml_declaration, radio
17 password, textarea, title, ul, xml_declaration, radio
18 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
18 from webhelpers.html.tools import auto_link, button_to, highlight, js_obfuscate, \
19 mail_to, strip_links, strip_tags, tag_re
19 mail_to, strip_links, strip_tags, tag_re
20 from webhelpers.number import format_byte_size, format_bit_size
20 from webhelpers.number import format_byte_size, format_bit_size
21 from webhelpers.pylonslib import Flash as _Flash
21 from webhelpers.pylonslib import Flash as _Flash
22 from webhelpers.pylonslib.secure_form import secure_form
22 from webhelpers.pylonslib.secure_form import secure_form
23 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
23 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
24 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
24 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
25 replace_whitespace, urlify, truncate, wrap_paragraphs
25 replace_whitespace, urlify, truncate, wrap_paragraphs
26
26
27
27
28 #Custom helpers here :)
28 #Custom helpers here :)
29 class _Link(object):
29 class _Link(object):
30 '''
30 '''
31 Make a url based on label and url with help of url_for
31 Make a url based on label and url with help of url_for
32 @param label:name of link if not defined url is used
32 @param label:name of link if not defined url is used
33 @param url: the url for link
33 @param url: the url for link
34 '''
34 '''
35
35
36 def __call__(self, label='', *url_, **urlargs):
36 def __call__(self, label='', *url_, **urlargs):
37 if label is None or '':
37 if label is None or '':
38 label = url
38 label = url
39 link_fn = link_to(label, url(*url_, **urlargs))
39 link_fn = link_to(label, url(*url_, **urlargs))
40 return link_fn
40 return link_fn
41
41
42 link = _Link()
42 link = _Link()
43
43
44 class _GetError(object):
44 class _GetError(object):
45
45
46 def __call__(self, field_name, form_errors):
46 def __call__(self, field_name, form_errors):
47 tmpl = """<span class="error_msg">%s</span>"""
47 tmpl = """<span class="error_msg">%s</span>"""
48 if form_errors and form_errors.has_key(field_name):
48 if form_errors and form_errors.has_key(field_name):
49 return literal(tmpl % form_errors.get(field_name))
49 return literal(tmpl % form_errors.get(field_name))
50
50
51 get_error = _GetError()
51 get_error = _GetError()
52
52
53 def recursive_replace(str, replace=' '):
53 def recursive_replace(str, replace=' '):
54 """
54 """
55 Recursive replace of given sign to just one instance
55 Recursive replace of given sign to just one instance
56 @param str: given string
56 @param str: given string
57 @param replace:char to find and replace multiple instances
57 @param replace:char to find and replace multiple instances
58
58
59 Examples::
59 Examples::
60 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
60 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
61 'Mighty-Mighty-Bo-sstones'
61 'Mighty-Mighty-Bo-sstones'
62 """
62 """
63
63
64 if str.find(replace * 2) == -1:
64 if str.find(replace * 2) == -1:
65 return str
65 return str
66 else:
66 else:
67 str = str.replace(replace * 2, replace)
67 str = str.replace(replace * 2, replace)
68 return recursive_replace(str, replace)
68 return recursive_replace(str, replace)
69
69
70 class _ToolTip(object):
70 class _ToolTip(object):
71
71
72 def __call__(self, tooltip_title, trim_at=50):
72 def __call__(self, tooltip_title, trim_at=50):
73 """
73 """
74 Special function just to wrap our text into nice formatted autowrapped
74 Special function just to wrap our text into nice formatted autowrapped
75 text
75 text
76 @param tooltip_title:
76 @param tooltip_title:
77 """
77 """
78
78
79 return literal(wrap_paragraphs(tooltip_title, trim_at)\
79 return literal(wrap_paragraphs(tooltip_title, trim_at)\
80 .replace('\n', '<br/>'))
80 .replace('\n', '<br/>'))
81
81
82 def activate(self):
82 def activate(self):
83 """
83 """
84 Adds tooltip mechanism to the given Html all tooltips have to have
84 Adds tooltip mechanism to the given Html all tooltips have to have
85 set class tooltip and set attribute tooltip_title.
85 set class tooltip and set attribute tooltip_title.
86 Then a tooltip will be generated based on that
86 Then a tooltip will be generated based on that
87 All with yui js tooltip
87 All with yui js tooltip
88 """
88 """
89
89
90 js = '''
90 js = '''
91 YAHOO.util.Event.onDOMReady(function(){
91 YAHOO.util.Event.onDOMReady(function(){
92 function toolTipsId(){
92 function toolTipsId(){
93 var ids = [];
93 var ids = [];
94 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
94 var tts = YAHOO.util.Dom.getElementsByClassName('tooltip');
95
95
96 for (var i = 0; i < tts.length; i++) {
96 for (var i = 0; i < tts.length; i++) {
97 //if element doesn not have and id autgenerate one for tooltip
97 //if element doesn not have and id autgenerate one for tooltip
98
98
99 if (!tts[i].id){
99 if (!tts[i].id){
100 tts[i].id='tt'+i*100;
100 tts[i].id='tt'+i*100;
101 }
101 }
102 ids.push(tts[i].id);
102 ids.push(tts[i].id);
103 }
103 }
104 return ids
104 return ids
105 };
105 };
106 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
106 var myToolTips = new YAHOO.widget.Tooltip("tooltip", {
107 context: toolTipsId(),
107 context: toolTipsId(),
108 monitorresize:false,
108 monitorresize:false,
109 xyoffset :[0,0],
109 xyoffset :[0,0],
110 autodismissdelay:300000,
110 autodismissdelay:300000,
111 hidedelay:5,
111 hidedelay:5,
112 showdelay:20,
112 showdelay:20,
113 });
113 });
114
114
115 //Mouse Over event disabled for new repositories since they dont
115 //Mouse Over event disabled for new repositories since they dont
116 //have last commit message
116 //have last commit message
117 myToolTips.contextMouseOverEvent.subscribe(
117 myToolTips.contextMouseOverEvent.subscribe(
118 function(type, args) {
118 function(type, args) {
119 var context = args[0];
119 var context = args[0];
120 var txt = context.getAttribute('tooltip_title');
120 var txt = context.getAttribute('tooltip_title');
121 if(txt){
121 if(txt){
122 return true;
122 return true;
123 }
123 }
124 else{
124 else{
125 return false;
125 return false;
126 }
126 }
127 });
127 });
128
128
129
129
130 // Set the text for the tooltip just before we display it. Lazy method
130 // Set the text for the tooltip just before we display it. Lazy method
131 myToolTips.contextTriggerEvent.subscribe(
131 myToolTips.contextTriggerEvent.subscribe(
132 function(type, args) {
132 function(type, args) {
133
133
134
134
135 var context = args[0];
135 var context = args[0];
136
136
137 var txt = context.getAttribute('tooltip_title');
137 var txt = context.getAttribute('tooltip_title');
138 this.cfg.setProperty("text", txt);
138 this.cfg.setProperty("text", txt);
139
139
140
140
141 // positioning of tooltip
141 // positioning of tooltip
142 var tt_w = this.element.clientWidth;
142 var tt_w = this.element.clientWidth;
143 var tt_h = this.element.clientHeight;
143 var tt_h = this.element.clientHeight;
144
144
145 var context_w = context.offsetWidth;
145 var context_w = context.offsetWidth;
146 var context_h = context.offsetHeight;
146 var context_h = context.offsetHeight;
147
147
148 var pos_x = YAHOO.util.Dom.getX(context);
148 var pos_x = YAHOO.util.Dom.getX(context);
149 var pos_y = YAHOO.util.Dom.getY(context);
149 var pos_y = YAHOO.util.Dom.getY(context);
150
150
151 var display_strategy = 'top';
151 var display_strategy = 'top';
152 var xy_pos = [0,0];
152 var xy_pos = [0,0];
153 switch (display_strategy){
153 switch (display_strategy){
154
154
155 case 'top':
155 case 'top':
156 var cur_x = (pos_x+context_w/2)-(tt_w/2);
156 var cur_x = (pos_x+context_w/2)-(tt_w/2);
157 var cur_y = pos_y-tt_h-4;
157 var cur_y = pos_y-tt_h-4;
158 xy_pos = [cur_x,cur_y];
158 xy_pos = [cur_x,cur_y];
159 break;
159 break;
160 case 'bottom':
160 case 'bottom':
161 var cur_x = (pos_x+context_w/2)-(tt_w/2);
161 var cur_x = (pos_x+context_w/2)-(tt_w/2);
162 var cur_y = pos_y+context_h+4;
162 var cur_y = pos_y+context_h+4;
163 xy_pos = [cur_x,cur_y];
163 xy_pos = [cur_x,cur_y];
164 break;
164 break;
165 case 'left':
165 case 'left':
166 var cur_x = (pos_x-tt_w-4);
166 var cur_x = (pos_x-tt_w-4);
167 var cur_y = pos_y-((tt_h/2)-context_h/2);
167 var cur_y = pos_y-((tt_h/2)-context_h/2);
168 xy_pos = [cur_x,cur_y];
168 xy_pos = [cur_x,cur_y];
169 break;
169 break;
170 case 'right':
170 case 'right':
171 var cur_x = (pos_x+context_w+4);
171 var cur_x = (pos_x+context_w+4);
172 var cur_y = pos_y-((tt_h/2)-context_h/2);
172 var cur_y = pos_y-((tt_h/2)-context_h/2);
173 xy_pos = [cur_x,cur_y];
173 xy_pos = [cur_x,cur_y];
174 break;
174 break;
175 default:
175 default:
176 var cur_x = (pos_x+context_w/2)-(tt_w/2);
176 var cur_x = (pos_x+context_w/2)-(tt_w/2);
177 var cur_y = pos_y-tt_h-4;
177 var cur_y = pos_y-tt_h-4;
178 xy_pos = [cur_x,cur_y];
178 xy_pos = [cur_x,cur_y];
179 break;
179 break;
180
180
181 }
181 }
182
182
183 this.cfg.setProperty("xy",xy_pos);
183 this.cfg.setProperty("xy",xy_pos);
184
184
185 });
185 });
186
186
187 //Mouse out
187 //Mouse out
188 myToolTips.contextMouseOutEvent.subscribe(
188 myToolTips.contextMouseOutEvent.subscribe(
189 function(type, args) {
189 function(type, args) {
190 var context = args[0];
190 var context = args[0];
191
191
192 });
192 });
193 });
193 });
194 '''
194 '''
195 return literal(js)
195 return literal(js)
196
196
197 tooltip = _ToolTip()
197 tooltip = _ToolTip()
198
198
199 class _FilesBreadCrumbs(object):
199 class _FilesBreadCrumbs(object):
200
200
201 def __call__(self, repo_name, rev, paths):
201 def __call__(self, repo_name, rev, paths):
202 url_l = [link_to(repo_name, url('files_home',
202 url_l = [link_to(repo_name, url('files_home',
203 repo_name=repo_name,
203 repo_name=repo_name,
204 revision=rev, f_path=''))]
204 revision=rev, f_path=''))]
205 paths_l = paths.split('/')
205 paths_l = paths.split('/')
206
206
207 for cnt, p in enumerate(paths_l, 1):
207 for cnt, p in enumerate(paths_l, 1):
208 if p != '':
208 if p != '':
209 url_l.append(link_to(p, url('files_home',
209 url_l.append(link_to(p, url('files_home',
210 repo_name=repo_name,
210 repo_name=repo_name,
211 revision=rev,
211 revision=rev,
212 f_path='/'.join(paths_l[:cnt]))))
212 f_path='/'.join(paths_l[:cnt]))))
213
213
214 return literal(' / '.join(url_l))
214 return literal(' / '.join(url_l))
215
215
216 files_breadcrumbs = _FilesBreadCrumbs()
216 files_breadcrumbs = _FilesBreadCrumbs()
217
217
218 def pygmentize(filenode, **kwargs):
218 def pygmentize(filenode, **kwargs):
219 """
219 """
220 pygmentize function using pygments
220 pygmentize function using pygments
221 @param filenode:
221 @param filenode:
222 """
222 """
223 return literal(code_highlight(filenode.content, filenode.lexer, HtmlFormatter(**kwargs)))
223 return literal(code_highlight(filenode.content, filenode.lexer, HtmlFormatter(**kwargs)))
224
224
225 def pygmentize_annotation(filenode, **kwargs):
225 def pygmentize_annotation(filenode, **kwargs):
226 """
226 """
227 pygmentize function for annotation
227 pygmentize function for annotation
228 @param filenode:
228 @param filenode:
229 """
229 """
230
230
231 color_dict = g.changeset_annotation_colors
231 color_dict = g.changeset_annotation_colors
232 def gen_color():
232 def gen_color():
233 import random
233 import random
234 return [str(random.randrange(10, 235)) for _ in xrange(3)]
234 return [str(random.randrange(10, 235)) for _ in xrange(3)]
235 def get_color_string(cs):
235 def get_color_string(cs):
236 if color_dict.has_key(cs):
236 if color_dict.has_key(cs):
237 col = color_dict[cs]
237 col = color_dict[cs]
238 else:
238 else:
239 color_dict[cs] = gen_color()
239 color_dict[cs] = gen_color()
240 col = color_dict[cs]
240 col = color_dict[cs]
241 return "color: rgb(%s) ! important;" % (', '.join(col))
241 return "color: rgb(%s) ! important;" % (', '.join(col))
242
242
243 def url_func(changeset):
243 def url_func(changeset):
244 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b> %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
244 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b> %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
245
245
246 tooltip_html = tooltip_html % (changeset.author,
246 tooltip_html = tooltip_html % (changeset.author,
247 changeset.date,
247 changeset.date,
248 tooltip(changeset.message))
248 tooltip(changeset.message))
249 lnk_format = 'r%s:%s' % (changeset.revision,
249 lnk_format = 'r%s:%s' % (changeset.revision,
250 changeset.raw_id)
250 changeset.raw_id)
251 uri = link_to(
251 uri = link_to(
252 lnk_format,
252 lnk_format,
253 url('changeset_home', repo_name='test',
253 url('changeset_home', repo_name='test',
254 revision=changeset.raw_id),
254 revision=changeset.raw_id),
255 style=get_color_string(changeset.raw_id),
255 style=get_color_string(changeset.raw_id),
256 class_='tooltip',
256 class_='tooltip',
257 tooltip_title=tooltip_html
257 tooltip_title=tooltip_html
258 )
258 )
259
259
260 uri += '\n'
260 uri += '\n'
261 return uri
261 return uri
262 return literal(annotate_highlight(filenode, url_func, **kwargs))
262 return literal(annotate_highlight(filenode, url_func, **kwargs))
263
263
264 def repo_name_slug(value):
264 def repo_name_slug(value):
265 """
265 """
266 Return slug of name of repository
266 Return slug of name of repository
267 """
267 """
268 slug = urlify(value)
268 slug = urlify(value)
269 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|:""":
269 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|:""":
270 slug = slug.replace(c, '-')
270 slug = slug.replace(c, '-')
271 slug = recursive_replace(slug, '-')
271 slug = recursive_replace(slug, '-')
272 return slug
272 return slug
273
273
274 flash = _Flash()
274 flash = _Flash()
275
275
276
276
277 #===============================================================================
277 #===============================================================================
278 # MERCURIAL FILTERS available via h.
278 # MERCURIAL FILTERS available via h.
279 #===============================================================================
279 #===============================================================================
280
280
281
281
282 from mercurial import util
282 from mercurial import util
283 from mercurial.templatefilters import age as _age, person as _person
283 from mercurial.templatefilters import age as _age, person as _person
284
284
285 age = lambda x:_age(x)
285 age = lambda x:_age(x)
286 capitalize = lambda x: x.capitalize()
286 capitalize = lambda x: x.capitalize()
287 date = lambda x: util.datestr(x)
287 date = lambda x: util.datestr(x)
288 email = util.email
288 email = util.email
289 person = lambda x: _person(x)
289 person = lambda x: _person(x)
290 hgdate = lambda x: "%d %d" % x
290 hgdate = lambda x: "%d %d" % x
291 isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
291 isodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M %1%2')
292 isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
292 isodatesec = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2')
293 localdate = lambda x: (x[0], util.makedate()[1])
293 localdate = lambda x: (x[0], util.makedate()[1])
294 rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
294 rfc822date = lambda x: util.datestr(x, "%a, %d %b %Y %H:%M:%S %1%2")
295 rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
295 rfc3339date = lambda x: util.datestr(x, "%Y-%m-%dT%H:%M:%S%1:%2")
296 time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
296 time_ago = lambda x: util.datestr(_age(x), "%a, %d %b %Y %H:%M:%S %1%2")
297
297
298
298
299 #===============================================================================
300 # PERMS
301 #===============================================================================
302 from pylons_app.lib.auth import HasPermissionAny, HasPermissionAll, \
303 HasRepoPermissionAny, HasRepoPermissionAll
299
304
300
305
General Comments 0
You need to be logged in to leave comments. Login now