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