##// END OF EJS Templates
fixes few bugs...
marcink -
r671:bee56f20 rhodecode-0.0.1.0.1 default
parent child Browse files
Show More
@@ -3,6 +3,16 b''
3 Changelog
3 Changelog
4 =========
4 =========
5
5
6
7 1.0.1 (**2010-11-10**)
8 ----------------------
9
10 - fixed #53 python2.5 incompatible enumerate calls
11 - fixed #52 disable mercurial extension for web
12 - fixed #51 deleting repositories don't delete it's dependent objects
13 - small css updated
14
15
6 1.0.0 (**2010-11-02**)
16 1.0.0 (**2010-11-02**)
7 ----------------------
17 ----------------------
8
18
@@ -5,12 +5,12 b' Installation'
5
5
6 ``RhodeCode`` is written entirely in Python, but in order to use it's full
6 ``RhodeCode`` is written entirely in Python, but in order to use it's full
7 potential there are some third-party requirements. When RhodeCode is used
7 potential there are some third-party requirements. When RhodeCode is used
8 together with celery You have to install some kind of message broker,
8 together with celery_ You have to install some kind of message broker,
9 recommended one is rabbitmq_ to make the async tasks work.
9 recommended one is rabbitmq_ to make the async tasks work.
10
10
11 Of course RhodeCode works in sync mode also, then You don't have to install
11 Of course RhodeCode works in sync mode also, then You don't have to install
12 any third party apps. Celery_ will give You large speed improvement when using
12 any third party apps. Celery_ will give You large speed improvement when using
13 many big repositories. If You plan to use it for 2 or 3 small repositories, it
13 many big repositories. If You plan to use it for 5 or 10 small repositories, it
14 will work just fine without celery running.
14 will work just fine without celery running.
15
15
16 After You decide to Run it with celery make sure You run celeryd and
16 After You decide to Run it with celery make sure You run celeryd and
@@ -33,7 +33,7 b' Install from Cheese Shop'
33
33
34 Easiest way to install ``rhodecode`` is to run::
34 Easiest way to install ``rhodecode`` is to run::
35
35
36 easy_install rhodecode
36 easy_install rhodecode
37
37
38 Or::
38 Or::
39
39
@@ -42,15 +42,16 b' Or::'
42 If you prefer to install manually simply grab latest release from
42 If you prefer to install manually simply grab latest release from
43 http://pypi.python.org/pypi/rhodecode, decompres archive and run::
43 http://pypi.python.org/pypi/rhodecode, decompres archive and run::
44
44
45 python setup.py install
45 python setup.py install
46
46
47
47
48 Step by step installation example
48 Step by step installation example
49 ---------------------------------
49 ---------------------------------
50
50
51
51
52 - Assuming You have installed virtualenv_ create one using. The `--no-site-packages`
52 - Assuming You have installed virtualenv_ create one using.
53 will make sure non of Your system libs are linked with this virtualenv_
53 The `--no-site-packages` will make sure non of Your system libs are linked
54 with this virtualenv_
54
55
55 ::
56 ::
56
57
@@ -40,6 +40,18 b' Setting up the application'
40 - Default permissions on each repository is read, and owner is admin. So
40 - Default permissions on each repository is read, and owner is admin. So
41 remember to update these if needed.
41 remember to update these if needed.
42
42
43 Note
44 ----
45
46 RhodeCode when running without the celery it's running all it's task in sync
47 mode, for first few times when visiting summary page You can notice few
48 slow downs, this is due the statistics building it's cache. After all changesets
49 are parsed it'll take the stats from cache and run much faster. Each summary
50 page display parse at most 250 changesets in order to not stress the cpu, so
51 the full stats are going to be loaded after total_number_of_changesets/250
52 summary page visits.
53
54
43
55
44 Setting up Whoosh
56 Setting up Whoosh
45 -----------------
57 -----------------
@@ -53,9 +65,9 b' Setting up Whoosh'
53 When using incremental mode whoosh will check last modification date of each file
65 When using incremental mode whoosh will check last modification date of each file
54 and add it to reindex if newer file is available. Also indexing daemon checks
66 and add it to reindex if newer file is available. Also indexing daemon checks
55 for removed files and removes them from index. Sometime You might want to rebuild
67 for removed files and removes them from index. Sometime You might want to rebuild
56 index from scrach, in admin pannel You can check `build from scratch` flag
68 index from scratch, in admin panel You can check `build from scratch` flag
57 and in standalone daemon You can pass `full` instead on incremental to build
69 and in standalone daemon You can pass `full` instead on incremental to build
58 remove previos index and build new one.
70 remove previous index and build new one.
59
71
60 Nginx virtual host example
72 Nginx virtual host example
61 --------------------------
73 --------------------------
@@ -24,7 +24,7 b' versioning implementation: http://semver'
24 @author: marcink
24 @author: marcink
25 """
25 """
26
26
27 VERSION = (1, 0, 0,)
27 VERSION = (1, 0, 1,)
28
28
29 __version__ = '.'.join((str(each) for each in VERSION[:4]))
29 __version__ = '.'.join((str(each) for each in VERSION[:4]))
30
30
@@ -64,20 +64,20 b" def recursive_replace(str, replace=' '):"
64 return str
64 return str
65 else:
65 else:
66 str = str.replace(replace * 2, replace)
66 str = str.replace(replace * 2, replace)
67 return recursive_replace(str, replace)
67 return recursive_replace(str, replace)
68
68
69 class _ToolTip(object):
69 class _ToolTip(object):
70
70
71 def __call__(self, tooltip_title, trim_at=50):
71 def __call__(self, tooltip_title, trim_at=50):
72 """
72 """
73 Special function just to wrap our text into nice formatted autowrapped
73 Special function just to wrap our text into nice formatted autowrapped
74 text
74 text
75 :param tooltip_title:
75 :param tooltip_title:
76 """
76 """
77
77
78 return wrap_paragraphs(escape(tooltip_title), trim_at)\
78 return wrap_paragraphs(escape(tooltip_title), trim_at)\
79 .replace('\n', '<br/>')
79 .replace('\n', '<br/>')
80
80
81 def activate(self):
81 def activate(self):
82 """
82 """
83 Adds tooltip mechanism to the given Html all tooltips have to have
83 Adds tooltip mechanism to the given Html all tooltips have to have
@@ -85,7 +85,7 b' class _ToolTip(object):'
85 Then a tooltip will be generated based on that
85 Then a tooltip will be generated based on that
86 All with yui js tooltip
86 All with yui js tooltip
87 """
87 """
88
88
89 js = '''
89 js = '''
90 YAHOO.util.Event.onDOMReady(function(){
90 YAHOO.util.Event.onDOMReady(function(){
91 function toolTipsId(){
91 function toolTipsId(){
@@ -190,25 +190,25 b' class _ToolTip(object):'
190
190
191 });
191 });
192 });
192 });
193 '''
193 '''
194 return literal(js)
194 return literal(js)
195
195
196 tooltip = _ToolTip()
196 tooltip = _ToolTip()
197
197
198 class _FilesBreadCrumbs(object):
198 class _FilesBreadCrumbs(object):
199
199
200 def __call__(self, repo_name, rev, paths):
200 def __call__(self, repo_name, rev, paths):
201 url_l = [link_to(repo_name, url('files_home',
201 url_l = [link_to(repo_name, url('files_home',
202 repo_name=repo_name,
202 repo_name=repo_name,
203 revision=rev, f_path=''))]
203 revision=rev, f_path=''))]
204 paths_l = paths.split('/')
204 paths_l = paths.split('/')
205
205
206 for cnt, p in enumerate(paths_l, 1):
206 for cnt, p in enumerate(paths_l):
207 if p != '':
207 if p != '':
208 url_l.append(link_to(p, url('files_home',
208 url_l.append(link_to(p, url('files_home',
209 repo_name=repo_name,
209 repo_name=repo_name,
210 revision=rev,
210 revision=rev,
211 f_path='/'.join(paths_l[:cnt]))))
211 f_path='/'.join(paths_l[:cnt + 1]))))
212
212
213 return literal('/'.join(url_l))
213 return literal('/'.join(url_l))
214
214
@@ -219,9 +219,9 b' class CodeHtmlFormatter(HtmlFormatter):'
219 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
219 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
220
220
221 def _wrap_code(self, source):
221 def _wrap_code(self, source):
222 for cnt, it in enumerate(source, 1):
222 for cnt, it in enumerate(source):
223 i, t = it
223 i, t = it
224 t = '<div id="#S-%s">%s</div>' % (cnt, t)
224 t = '<div id="#S-%s">%s</div>' % (cnt + 1, t)
225 yield i, t
225 yield i, t
226 def pygmentize(filenode, **kwargs):
226 def pygmentize(filenode, **kwargs):
227 """
227 """
@@ -236,12 +236,12 b' def pygmentize_annotation(filenode, **kw'
236 pygmentize function for annotation
236 pygmentize function for annotation
237 :param filenode:
237 :param filenode:
238 """
238 """
239
239
240 color_dict = {}
240 color_dict = {}
241 def gen_color():
241 def gen_color():
242 """generator for getting 10k of evenly distibuted colors using hsv color
242 """generator for getting 10k of evenly distibuted colors using hsv color
243 and golden ratio.
243 and golden ratio.
244 """
244 """
245 import colorsys
245 import colorsys
246 n = 10000
246 n = 10000
247 golden_ratio = 0.618033988749895
247 golden_ratio = 0.618033988749895
@@ -252,21 +252,21 b' def pygmentize_annotation(filenode, **kw'
252 h %= 1
252 h %= 1
253 HSV_tuple = [h, 0.95, 0.95]
253 HSV_tuple = [h, 0.95, 0.95]
254 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
254 RGB_tuple = colorsys.hsv_to_rgb(*HSV_tuple)
255 yield map(lambda x:str(int(x * 256)), RGB_tuple)
255 yield map(lambda x:str(int(x * 256)), RGB_tuple)
256
256
257 cgenerator = gen_color()
257 cgenerator = gen_color()
258
258
259 def get_color_string(cs):
259 def get_color_string(cs):
260 if color_dict.has_key(cs):
260 if color_dict.has_key(cs):
261 col = color_dict[cs]
261 col = color_dict[cs]
262 else:
262 else:
263 col = color_dict[cs] = cgenerator.next()
263 col = color_dict[cs] = cgenerator.next()
264 return "color: rgb(%s)! important;" % (', '.join(col))
264 return "color: rgb(%s)! important;" % (', '.join(col))
265
265
266 def url_func(changeset):
266 def url_func(changeset):
267 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
267 tooltip_html = "<div style='font-size:0.8em'><b>Author:</b>" + \
268 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
268 " %s<br/><b>Date:</b> %s</b><br/><b>Message:</b> %s<br/></div>"
269
269
270 tooltip_html = tooltip_html % (changeset.author,
270 tooltip_html = tooltip_html % (changeset.author,
271 changeset.date,
271 changeset.date,
272 tooltip(changeset.message))
272 tooltip(changeset.message))
@@ -280,11 +280,11 b' def pygmentize_annotation(filenode, **kw'
280 class_='tooltip',
280 class_='tooltip',
281 tooltip_title=tooltip_html
281 tooltip_title=tooltip_html
282 )
282 )
283
283
284 uri += '\n'
284 uri += '\n'
285 return uri
285 return uri
286 return literal(annotate_highlight(filenode, url_func, **kwargs))
286 return literal(annotate_highlight(filenode, url_func, **kwargs))
287
287
288 def repo_name_slug(value):
288 def repo_name_slug(value):
289 """Return slug of name of repository
289 """Return slug of name of repository
290 This function is called on each creation/modification
290 This function is called on each creation/modification
@@ -292,7 +292,7 b' def repo_name_slug(value):'
292 """
292 """
293 slug = remove_formatting(value)
293 slug = remove_formatting(value)
294 slug = strip_tags(slug)
294 slug = strip_tags(slug)
295
295
296 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
296 for c in """=[]\;'"<>,/~!@#$%^&*()+{}|: """:
297 slug = slug.replace(c, '-')
297 slug = slug.replace(c, '-')
298 slug = recursive_replace(slug, '-')
298 slug = recursive_replace(slug, '-')
@@ -305,7 +305,7 b' def get_changeset_safe(repo, rev):'
305 if not isinstance(repo, BaseRepository):
305 if not isinstance(repo, BaseRepository):
306 raise Exception('You must pass an Repository '
306 raise Exception('You must pass an Repository '
307 'object as first argument got %s', type(repo))
307 'object as first argument got %s', type(repo))
308
308
309 try:
309 try:
310 cs = repo.get_changeset(rev)
310 cs = repo.get_changeset(rev)
311 except RepositoryError:
311 except RepositoryError:
@@ -358,8 +358,8 b' def gravatar_url(email_address, size=30)'
358 baseurl_nossl = "http://www.gravatar.com/avatar/"
358 baseurl_nossl = "http://www.gravatar.com/avatar/"
359 baseurl_ssl = "https://secure.gravatar.com/avatar/"
359 baseurl_ssl = "https://secure.gravatar.com/avatar/"
360 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
360 baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl
361
361
362
362
363 # construct the url
363 # construct the url
364 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
364 gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?"
365 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
365 gravatar_url += urllib.urlencode({'d':default, 's':str(size)})
@@ -370,7 +370,7 b' def safe_unicode(str):'
370 """safe unicode function. In case of UnicodeDecode error we try to return
370 """safe unicode function. In case of UnicodeDecode error we try to return
371 unicode with errors replace, if this failes we return unicode with
371 unicode with errors replace, if this failes we return unicode with
372 string_escape decoding """
372 string_escape decoding """
373
373
374 try:
374 try:
375 u_str = unicode(str)
375 u_str = unicode(str)
376 except UnicodeDecodeError:
376 except UnicodeDecodeError:
@@ -379,5 +379,5 b' def safe_unicode(str):'
379 except UnicodeDecodeError:
379 except UnicodeDecodeError:
380 #incase we have a decode error just represent as byte string
380 #incase we have a decode error just represent as byte string
381 u_str = unicode(str(str).encode('string_escape'))
381 u_str = unicode(str(str).encode('string_escape'))
382
382
383 return u_str
383 return u_str
@@ -221,6 +221,11 b" def make_ui(read_from='file', path=None,"
221 for k, v in cfg.items(section):
221 for k, v in cfg.items(section):
222 baseui.setconfig(section, k, v)
222 baseui.setconfig(section, k, v)
223 log.debug('settings ui from file[%s]%s:%s', section, k, v)
223 log.debug('settings ui from file[%s]%s:%s', section, k, v)
224
225 for k, v in baseui.configitems('extensions'):
226 baseui.setconfig('extensions', k, '0')
227 #just enable mq
228 baseui.setconfig('extensions', 'mq', '1')
224 if checkpaths:check_repo_dir(cfg.items('paths'))
229 if checkpaths:check_repo_dir(cfg.items('paths'))
225
230
226
231
@@ -22,9 +22,9 b' class RhodeCodeUi(Base):'
22 ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
22 ui_key = Column("ui_key", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
23 ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
23 ui_value = Column("ui_value", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
24 ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
24 ui_active = Column("ui_active", BOOLEAN(), nullable=True, unique=None, default=True)
25
25
26
26
27 class User(Base):
27 class User(Base):
28 __tablename__ = 'users'
28 __tablename__ = 'users'
29 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
29 __table_args__ = (UniqueConstraint('username'), UniqueConstraint('email'), {'useexisting':True})
30 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
30 user_id = Column("user_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
@@ -36,21 +36,21 b' class User(Base):'
36 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
36 lastname = Column("lastname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
37 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
37 email = Column("email", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
38 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
38 last_login = Column("last_login", DATETIME(timezone=False), nullable=True, unique=None, default=None)
39
39
40 user_log = relation('UserLog')
40 user_log = relation('UserLog')
41 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id")
41 user_perms = relation('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id")
42
42
43 @LazyProperty
43 @LazyProperty
44 def full_contact(self):
44 def full_contact(self):
45 return '%s %s <%s>' % (self.name, self.lastname, self.email)
45 return '%s %s <%s>' % (self.name, self.lastname, self.email)
46
46
47 def __repr__(self):
47 def __repr__(self):
48 return "<User('id:%s:%s')>" % (self.user_id, self.username)
48 return "<User('id:%s:%s')>" % (self.user_id, self.username)
49
49
50 def update_lastlogin(self):
50 def update_lastlogin(self):
51 """Update user lastlogin"""
51 """Update user lastlogin"""
52 import datetime
52 import datetime
53
53
54 try:
54 try:
55 session = Session.object_session(self)
55 session = Session.object_session(self)
56 self.last_login = datetime.datetime.now()
56 self.last_login = datetime.datetime.now()
@@ -58,24 +58,24 b' class User(Base):'
58 session.commit()
58 session.commit()
59 log.debug('updated user %s lastlogin', self.username)
59 log.debug('updated user %s lastlogin', self.username)
60 except Exception:
60 except Exception:
61 session.rollback()
61 session.rollback()
62
62
63
63
64 class UserLog(Base):
64 class UserLog(Base):
65 __tablename__ = 'user_logs'
65 __tablename__ = 'user_logs'
66 __table_args__ = {'useexisting':True}
66 __table_args__ = {'useexisting':True}
67 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
67 user_log_id = Column("user_log_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
68 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
68 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
69 repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
69 repository_id = Column("repository_id", INTEGER(length=None, convert_unicode=False, assert_unicode=None), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
70 repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
70 repository_name = Column("repository_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
71 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
71 user_ip = Column("user_ip", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
72 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
72 action = Column("action", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
73 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
73 action_date = Column("action_date", DATETIME(timezone=False), nullable=True, unique=None, default=None)
74 revision = Column('revision', TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
74 revision = Column('revision', TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
75
75
76 user = relation('User')
76 user = relation('User')
77 repository = relation('Repository')
77 repository = relation('Repository')
78
78
79 class Repository(Base):
79 class Repository(Base):
80 __tablename__ = 'repositories'
80 __tablename__ = 'repositories'
81 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
81 __table_args__ = (UniqueConstraint('repo_name'), {'useexisting':True},)
@@ -85,21 +85,23 b' class Repository(Base):'
85 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
85 private = Column("private", BOOLEAN(), nullable=True, unique=None, default=None)
86 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
86 description = Column("description", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
87 fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
87 fork_id = Column("fork_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=True, unique=False, default=None)
88
88
89 user = relation('User')
89 user = relation('User')
90 fork = relation('Repository', remote_side=repo_id)
90 fork = relation('Repository', remote_side=repo_id)
91 repo_to_perm = relation('RepoToPerm', cascade='all')
91 repo_to_perm = relation('RepoToPerm', cascade='all')
92
92 stats = relation('Statistics', cascade='all')
93
94
93 def __repr__(self):
95 def __repr__(self):
94 return "<Repository('id:%s:%s')>" % (self.repo_id, self.repo_name)
96 return "<Repository('id:%s:%s')>" % (self.repo_id, self.repo_name)
95
97
96 class Permission(Base):
98 class Permission(Base):
97 __tablename__ = 'permissions'
99 __tablename__ = 'permissions'
98 __table_args__ = {'useexisting':True}
100 __table_args__ = {'useexisting':True}
99 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
101 permission_id = Column("permission_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
100 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
102 permission_name = Column("permission_name", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
101 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
103 permission_longname = Column("permission_longname", TEXT(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
102
104
103 def __repr__(self):
105 def __repr__(self):
104 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
106 return "<Permission('%s:%s')>" % (self.permission_id, self.permission_name)
105
107
@@ -109,8 +111,8 b' class RepoToPerm(Base):'
109 repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
111 repo_to_perm_id = Column("repo_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
110 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
112 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
111 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
113 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
112 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
114 repository_id = Column("repository_id", INTEGER(), ForeignKey(u'repositories.repo_id'), nullable=False, unique=None, default=None)
113
115
114 user = relation('User')
116 user = relation('User')
115 permission = relation('Permission')
117 permission = relation('Permission')
116 repository = relation('Repository')
118 repository = relation('Repository')
@@ -121,7 +123,7 b' class UserToPerm(Base):'
121 user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
123 user_to_perm_id = Column("user_to_perm_id", INTEGER(), nullable=False, unique=True, default=None, primary_key=True)
122 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
124 user_id = Column("user_id", INTEGER(), ForeignKey(u'users.user_id'), nullable=False, unique=None, default=None)
123 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
125 permission_id = Column("permission_id", INTEGER(), ForeignKey(u'permissions.permission_id'), nullable=False, unique=None, default=None)
124
126
125 user = relation('User')
127 user = relation('User')
126 permission = relation('Permission')
128 permission = relation('Permission')
127
129
@@ -134,6 +136,6 b' class Statistics(Base):'
134 commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
136 commit_activity = Column("commit_activity", BLOB(), nullable=False)#JSON data
135 commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
137 commit_activity_combined = Column("commit_activity_combined", BLOB(), nullable=False)#JSON data
136 languages = Column("languages", BLOB(), nullable=False)#JSON data
138 languages = Column("languages", BLOB(), nullable=False)#JSON data
137
138 repository = relation('Repository')
139
139
140 repository = relation('Repository', single_parent=True)
141
@@ -270,7 +270,7 b' text-decoration:none;'
270 }
270 }
271
271
272 #header #header-inner #logo a:hover {
272 #header #header-inner #logo a:hover {
273 color:#dabf29;
273 color:#bfe3ff;
274 }
274 }
275
275
276 #header #header-inner #quick,#header #header-inner #quick ul {
276 #header #header-inner #quick,#header #header-inner #quick ul {
@@ -419,7 +419,7 b' padding:12px 9px 7px 24px;'
419 }
419 }
420
420
421 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
421 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover {
422 background:url("../images/icons/folder_edit.png") no-repeat scroll 4px 9px #FFF;
422 background:url("../images/icons/database_edit.png") no-repeat scroll 4px 9px #FFF;
423 width:167px;
423 width:167px;
424 margin:0;
424 margin:0;
425 padding:12px 9px 7px 24px;
425 padding:12px 9px 7px 24px;
@@ -1010,7 +1010,7 b' padding:0;'
1010 #content div.box table th {
1010 #content div.box table th {
1011 background:#eee;
1011 background:#eee;
1012 border-bottom:1px solid #ddd;
1012 border-bottom:1px solid #ddd;
1013 padding:10px;
1013 padding:5px 0px 5px 5px;
1014 }
1014 }
1015
1015
1016 #content div.box table th.left {
1016 #content div.box table th.left {
@@ -1393,7 +1393,6 b' background-color:#003367;'
1393 color:#FFF;
1393 color:#FFF;
1394 display:block;
1394 display:block;
1395 min-width:20px;
1395 min-width:20px;
1396 max-width:400px;
1397 text-decoration:none;
1396 text-decoration:none;
1398 height:12px;
1397 height:12px;
1399 margin-bottom:4px;
1398 margin-bottom:4px;
@@ -1542,7 +1541,7 b' background:#F88;'
1542
1541
1543 .right .merge {
1542 .right .merge {
1544 vertical-align:top;
1543 vertical-align:top;
1545 font-size:60%;
1544 font-size:0.75em;
1546 font-weight:700;
1545 font-weight:700;
1547 }
1546 }
1548
1547
@@ -1554,13 +1553,15 b' font-family:monospace;'
1554 .right .logtags .branchtag {
1553 .right .logtags .branchtag {
1555 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1554 background:#FFF url("../images/icons/arrow_branch.png") no-repeat right 6px;
1556 display:block;
1555 display:block;
1557 padding:8px 16px 0 0;
1556 font-size:0.8em;
1557 padding:11px 16px 0 0;
1558 }
1558 }
1559
1559
1560 .right .logtags .tagtag {
1560 .right .logtags .tagtag {
1561 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1561 background:#FFF url("../images/icons/tag_blue.png") no-repeat right 6px;
1562 display:block;
1562 display:block;
1563 padding:6px 18px 0 0;
1563 font-size:0.8em;
1564 padding:11px 16px 0 0;
1564 }
1565 }
1565
1566
1566 div.browserblock {
1567 div.browserblock {
@@ -1701,6 +1702,7 b' font:100% sans-serif;'
1701 width:auto;
1702 width:auto;
1702 opacity:1px;
1703 opacity:1px;
1703 padding:8px;
1704 padding:8px;
1705 white-space: pre;
1704 }
1706 }
1705
1707
1706 .ac {
1708 .ac {
@@ -2024,7 +2026,6 b' display:block;'
2024 }
2026 }
2025
2027
2026 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2028 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a {
2027 background:url("../../images/title_tab_selected.png") no-repeat bottom center;
2028 color:#bfe3ff;
2029 color:#bfe3ff;
2029 }
2030 }
2030
2031
@@ -43,8 +43,8 b''
43 </tr>
43 </tr>
44 %endif
44 %endif
45
45
46 %for cnt,node in enumerate(c.files_list,1):
46 %for cnt,node in enumerate(c.files_list):
47 <tr class="parity${cnt%2}">
47 <tr class="parity${(cnt+1)%2}">
48 <td>
48 <td>
49 ${h.link_to(node.name,h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=node.path),class_=file_class(node))}
49 ${h.link_to(node.name,h.url('files_home',repo_name=c.repo_name,revision=c.cur_rev,f_path=node.path),class_=file_class(node))}
50 </td>
50 </td>
@@ -59,19 +59,19 b''
59 %endif
59 %endif
60 </td>
60 </td>
61 <td>
61 <td>
62 %if node.is_file():
62 %if node.is_file():
63 ${node.last_changeset.revision}
63 ${node.last_changeset.revision}
64 %endif
64 %endif
65 </td>
65 </td>
66 <td>
66 <td>
67 %if node.is_file():
67 %if node.is_file():
68 ${h.age(node.last_changeset._ctx.date())} - ${node.last_changeset.date}
68 ${h.age(node.last_changeset._ctx.date())} - ${node.last_changeset.date}
69 %endif
69 %endif
70 </td>
70 </td>
71 <td>
71 <td>
72 %if node.is_file():
72 %if node.is_file():
73 ${node.last_changeset.author}
73 ${node.last_changeset.author}
74 %endif
74 %endif
75 </td>
75 </td>
76 </tr>
76 </tr>
77 %endfor
77 %endfor
@@ -131,11 +131,13 b' E.onDOMReady(function(e){'
131 var value = data[k];
131 var value = data[k];
132 var td1 = document.createElement('td');
132 var td1 = document.createElement('td');
133 td1.width=150;
133 td1.width=150;
134
134 var trending_language_label = document.createElement('div');
135 var trending_language_label = document.createElement('div');
135 trending_language_label.innerHTML = k;
136 trending_language_label.innerHTML = k;
136 td1.appendChild(trending_language_label);
137 td1.appendChild(trending_language_label);
137
138
138 var td2 = document.createElement('td');
139 var td2 = document.createElement('td');
140 td2.setAttribute('style','padding-right: 12px ! important;');
139 var trending_language = document.createElement('div');
141 var trending_language = document.createElement('div');
140 trending_language.title = k;
142 trending_language.title = k;
141 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
143 trending_language.innerHTML = "<b>"+percentage+"% "+value+" ${_('files')}</b>";
General Comments 0
You need to be logged in to leave comments. Login now