##// END OF EJS Templates
Cleaned the way cache keys are invalidated...
marcink -
r3020:00498b3e beta
parent child Browse files
Show More
@@ -1,714 +1,716 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.lib.utils
3 rhodecode.lib.utils
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Utilities library for RhodeCode
6 Utilities library for RhodeCode
7
7
8 :created_on: Apr 18, 2010
8 :created_on: Apr 18, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import re
27 import re
28 import logging
28 import logging
29 import datetime
29 import datetime
30 import traceback
30 import traceback
31 import paste
31 import paste
32 import beaker
32 import beaker
33 import tarfile
33 import tarfile
34 import shutil
34 import shutil
35 from os.path import abspath
35 from os.path import abspath
36 from os.path import dirname as dn, join as jn
36 from os.path import dirname as dn, join as jn
37
37
38 from paste.script.command import Command, BadCommand
38 from paste.script.command import Command, BadCommand
39
39
40 from mercurial import ui, config
40 from mercurial import ui, config
41
41
42 from webhelpers.text import collapse, remove_formatting, strip_tags
42 from webhelpers.text import collapse, remove_formatting, strip_tags
43
43
44 from rhodecode.lib.vcs import get_backend
44 from rhodecode.lib.vcs import get_backend
45 from rhodecode.lib.vcs.backends.base import BaseChangeset
45 from rhodecode.lib.vcs.backends.base import BaseChangeset
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
47 from rhodecode.lib.vcs.utils.helpers import get_scm
47 from rhodecode.lib.vcs.utils.helpers import get_scm
48 from rhodecode.lib.vcs.exceptions import VCSError
48 from rhodecode.lib.vcs.exceptions import VCSError
49
49
50 from rhodecode.lib.caching_query import FromCache
50 from rhodecode.lib.caching_query import FromCache
51
51
52 from rhodecode.model import meta
52 from rhodecode.model import meta
53 from rhodecode.model.db import Repository, User, RhodeCodeUi, \
53 from rhodecode.model.db import Repository, User, RhodeCodeUi, \
54 UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation
54 UserLog, RepoGroup, RhodeCodeSetting, CacheInvalidation
55 from rhodecode.model.meta import Session
55 from rhodecode.model.meta import Session
56 from rhodecode.model.repos_group import ReposGroupModel
56 from rhodecode.model.repos_group import ReposGroupModel
57 from rhodecode.lib.utils2 import safe_str, safe_unicode
57 from rhodecode.lib.utils2 import safe_str, safe_unicode
58 from rhodecode.lib.vcs.utils.fakemod import create_module
58 from rhodecode.lib.vcs.utils.fakemod import create_module
59
59
60 log = logging.getLogger(__name__)
60 log = logging.getLogger(__name__)
61
61
62 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
62 REMOVED_REPO_PAT = re.compile(r'rm__\d{8}_\d{6}_\d{6}__.*')
63
63
64
64
65 def recursive_replace(str_, replace=' '):
65 def recursive_replace(str_, replace=' '):
66 """
66 """
67 Recursive replace of given sign to just one instance
67 Recursive replace of given sign to just one instance
68
68
69 :param str_: given string
69 :param str_: given string
70 :param replace: char to find and replace multiple instances
70 :param replace: char to find and replace multiple instances
71
71
72 Examples::
72 Examples::
73 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
73 >>> recursive_replace("Mighty---Mighty-Bo--sstones",'-')
74 'Mighty-Mighty-Bo-sstones'
74 'Mighty-Mighty-Bo-sstones'
75 """
75 """
76
76
77 if str_.find(replace * 2) == -1:
77 if str_.find(replace * 2) == -1:
78 return str_
78 return str_
79 else:
79 else:
80 str_ = str_.replace(replace * 2, replace)
80 str_ = str_.replace(replace * 2, replace)
81 return recursive_replace(str_, replace)
81 return recursive_replace(str_, replace)
82
82
83
83
84 def repo_name_slug(value):
84 def repo_name_slug(value):
85 """
85 """
86 Return slug of name of repository
86 Return slug of name of repository
87 This function is called on each creation/modification
87 This function is called on each creation/modification
88 of repository to prevent bad names in repo
88 of repository to prevent bad names in repo
89 """
89 """
90
90
91 slug = remove_formatting(value)
91 slug = remove_formatting(value)
92 slug = strip_tags(slug)
92 slug = strip_tags(slug)
93
93
94 for c in """`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
94 for c in """`?=[]\;'"<>,/~!@#$%^&*()+{}|: """:
95 slug = slug.replace(c, '-')
95 slug = slug.replace(c, '-')
96 slug = recursive_replace(slug, '-')
96 slug = recursive_replace(slug, '-')
97 slug = collapse(slug, '-')
97 slug = collapse(slug, '-')
98 return slug
98 return slug
99
99
100
100
101 def get_repo_slug(request):
101 def get_repo_slug(request):
102 _repo = request.environ['pylons.routes_dict'].get('repo_name')
102 _repo = request.environ['pylons.routes_dict'].get('repo_name')
103 if _repo:
103 if _repo:
104 _repo = _repo.rstrip('/')
104 _repo = _repo.rstrip('/')
105 return _repo
105 return _repo
106
106
107
107
108 def get_repos_group_slug(request):
108 def get_repos_group_slug(request):
109 _group = request.environ['pylons.routes_dict'].get('group_name')
109 _group = request.environ['pylons.routes_dict'].get('group_name')
110 if _group:
110 if _group:
111 _group = _group.rstrip('/')
111 _group = _group.rstrip('/')
112 return _group
112 return _group
113
113
114
114
115 def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
115 def action_logger(user, action, repo, ipaddr='', sa=None, commit=False):
116 """
116 """
117 Action logger for various actions made by users
117 Action logger for various actions made by users
118
118
119 :param user: user that made this action, can be a unique username string or
119 :param user: user that made this action, can be a unique username string or
120 object containing user_id attribute
120 object containing user_id attribute
121 :param action: action to log, should be on of predefined unique actions for
121 :param action: action to log, should be on of predefined unique actions for
122 easy translations
122 easy translations
123 :param repo: string name of repository or object containing repo_id,
123 :param repo: string name of repository or object containing repo_id,
124 that action was made on
124 that action was made on
125 :param ipaddr: optional ip address from what the action was made
125 :param ipaddr: optional ip address from what the action was made
126 :param sa: optional sqlalchemy session
126 :param sa: optional sqlalchemy session
127
127
128 """
128 """
129
129
130 if not sa:
130 if not sa:
131 sa = meta.Session()
131 sa = meta.Session()
132
132
133 try:
133 try:
134 if hasattr(user, 'user_id'):
134 if hasattr(user, 'user_id'):
135 user_obj = user
135 user_obj = user
136 elif isinstance(user, basestring):
136 elif isinstance(user, basestring):
137 user_obj = User.get_by_username(user)
137 user_obj = User.get_by_username(user)
138 else:
138 else:
139 raise Exception('You have to provide a user object or a username')
139 raise Exception('You have to provide a user object or a username')
140
140
141 if hasattr(repo, 'repo_id'):
141 if hasattr(repo, 'repo_id'):
142 repo_obj = Repository.get(repo.repo_id)
142 repo_obj = Repository.get(repo.repo_id)
143 repo_name = repo_obj.repo_name
143 repo_name = repo_obj.repo_name
144 elif isinstance(repo, basestring):
144 elif isinstance(repo, basestring):
145 repo_name = repo.lstrip('/')
145 repo_name = repo.lstrip('/')
146 repo_obj = Repository.get_by_repo_name(repo_name)
146 repo_obj = Repository.get_by_repo_name(repo_name)
147 else:
147 else:
148 repo_obj = None
148 repo_obj = None
149 repo_name = ''
149 repo_name = ''
150
150
151 user_log = UserLog()
151 user_log = UserLog()
152 user_log.user_id = user_obj.user_id
152 user_log.user_id = user_obj.user_id
153 user_log.action = safe_unicode(action)
153 user_log.action = safe_unicode(action)
154
154
155 user_log.repository = repo_obj
155 user_log.repository = repo_obj
156 user_log.repository_name = repo_name
156 user_log.repository_name = repo_name
157
157
158 user_log.action_date = datetime.datetime.now()
158 user_log.action_date = datetime.datetime.now()
159 user_log.user_ip = ipaddr
159 user_log.user_ip = ipaddr
160 sa.add(user_log)
160 sa.add(user_log)
161
161
162 log.info(
162 log.info(
163 'Adding user %s, action %s on %s' % (user_obj, action,
163 'Adding user %s, action %s on %s' % (user_obj, action,
164 safe_unicode(repo))
164 safe_unicode(repo))
165 )
165 )
166 if commit:
166 if commit:
167 sa.commit()
167 sa.commit()
168 except:
168 except:
169 log.error(traceback.format_exc())
169 log.error(traceback.format_exc())
170 raise
170 raise
171
171
172
172
173 def get_repos(path, recursive=False):
173 def get_repos(path, recursive=False):
174 """
174 """
175 Scans given path for repos and return (name,(type,path)) tuple
175 Scans given path for repos and return (name,(type,path)) tuple
176
176
177 :param path: path to scan for repositories
177 :param path: path to scan for repositories
178 :param recursive: recursive search and return names with subdirs in front
178 :param recursive: recursive search and return names with subdirs in front
179 """
179 """
180
180
181 # remove ending slash for better results
181 # remove ending slash for better results
182 path = path.rstrip(os.sep)
182 path = path.rstrip(os.sep)
183
183
184 def _get_repos(p):
184 def _get_repos(p):
185 if not os.access(p, os.W_OK):
185 if not os.access(p, os.W_OK):
186 return
186 return
187 for dirpath in os.listdir(p):
187 for dirpath in os.listdir(p):
188 if os.path.isfile(os.path.join(p, dirpath)):
188 if os.path.isfile(os.path.join(p, dirpath)):
189 continue
189 continue
190 cur_path = os.path.join(p, dirpath)
190 cur_path = os.path.join(p, dirpath)
191 try:
191 try:
192 scm_info = get_scm(cur_path)
192 scm_info = get_scm(cur_path)
193 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
193 yield scm_info[1].split(path, 1)[-1].lstrip(os.sep), scm_info
194 except VCSError:
194 except VCSError:
195 if not recursive:
195 if not recursive:
196 continue
196 continue
197 #check if this dir containts other repos for recursive scan
197 #check if this dir containts other repos for recursive scan
198 rec_path = os.path.join(p, dirpath)
198 rec_path = os.path.join(p, dirpath)
199 if os.path.isdir(rec_path):
199 if os.path.isdir(rec_path):
200 for inner_scm in _get_repos(rec_path):
200 for inner_scm in _get_repos(rec_path):
201 yield inner_scm
201 yield inner_scm
202
202
203 return _get_repos(path)
203 return _get_repos(path)
204
204
205
205
206 def is_valid_repo(repo_name, base_path, scm=None):
206 def is_valid_repo(repo_name, base_path, scm=None):
207 """
207 """
208 Returns True if given path is a valid repository False otherwise.
208 Returns True if given path is a valid repository False otherwise.
209 If scm param is given also compare if given scm is the same as expected
209 If scm param is given also compare if given scm is the same as expected
210 from scm parameter
210 from scm parameter
211
211
212 :param repo_name:
212 :param repo_name:
213 :param base_path:
213 :param base_path:
214 :param scm:
214 :param scm:
215
215
216 :return True: if given path is a valid repository
216 :return True: if given path is a valid repository
217 """
217 """
218 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
218 full_path = os.path.join(safe_str(base_path), safe_str(repo_name))
219
219
220 try:
220 try:
221 scm_ = get_scm(full_path)
221 scm_ = get_scm(full_path)
222 if scm:
222 if scm:
223 return scm_[0] == scm
223 return scm_[0] == scm
224 return True
224 return True
225 except VCSError:
225 except VCSError:
226 return False
226 return False
227
227
228
228
229 def is_valid_repos_group(repos_group_name, base_path):
229 def is_valid_repos_group(repos_group_name, base_path):
230 """
230 """
231 Returns True if given path is a repos group False otherwise
231 Returns True if given path is a repos group False otherwise
232
232
233 :param repo_name:
233 :param repo_name:
234 :param base_path:
234 :param base_path:
235 """
235 """
236 full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name))
236 full_path = os.path.join(safe_str(base_path), safe_str(repos_group_name))
237
237
238 # check if it's not a repo
238 # check if it's not a repo
239 if is_valid_repo(repos_group_name, base_path):
239 if is_valid_repo(repos_group_name, base_path):
240 return False
240 return False
241
241
242 try:
242 try:
243 # we need to check bare git repos at higher level
243 # we need to check bare git repos at higher level
244 # since we might match branches/hooks/info/objects or possible
244 # since we might match branches/hooks/info/objects or possible
245 # other things inside bare git repo
245 # other things inside bare git repo
246 get_scm(os.path.dirname(full_path))
246 get_scm(os.path.dirname(full_path))
247 return False
247 return False
248 except VCSError:
248 except VCSError:
249 pass
249 pass
250
250
251 # check if it's a valid path
251 # check if it's a valid path
252 if os.path.isdir(full_path):
252 if os.path.isdir(full_path):
253 return True
253 return True
254
254
255 return False
255 return False
256
256
257
257
258 def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
258 def ask_ok(prompt, retries=4, complaint='Yes or no please!'):
259 while True:
259 while True:
260 ok = raw_input(prompt)
260 ok = raw_input(prompt)
261 if ok in ('y', 'ye', 'yes'):
261 if ok in ('y', 'ye', 'yes'):
262 return True
262 return True
263 if ok in ('n', 'no', 'nop', 'nope'):
263 if ok in ('n', 'no', 'nop', 'nope'):
264 return False
264 return False
265 retries = retries - 1
265 retries = retries - 1
266 if retries < 0:
266 if retries < 0:
267 raise IOError
267 raise IOError
268 print complaint
268 print complaint
269
269
270 #propagated from mercurial documentation
270 #propagated from mercurial documentation
271 ui_sections = ['alias', 'auth',
271 ui_sections = ['alias', 'auth',
272 'decode/encode', 'defaults',
272 'decode/encode', 'defaults',
273 'diff', 'email',
273 'diff', 'email',
274 'extensions', 'format',
274 'extensions', 'format',
275 'merge-patterns', 'merge-tools',
275 'merge-patterns', 'merge-tools',
276 'hooks', 'http_proxy',
276 'hooks', 'http_proxy',
277 'smtp', 'patch',
277 'smtp', 'patch',
278 'paths', 'profiling',
278 'paths', 'profiling',
279 'server', 'trusted',
279 'server', 'trusted',
280 'ui', 'web', ]
280 'ui', 'web', ]
281
281
282
282
283 def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
283 def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
284 """
284 """
285 A function that will read python rc files or database
285 A function that will read python rc files or database
286 and make an mercurial ui object from read options
286 and make an mercurial ui object from read options
287
287
288 :param path: path to mercurial config file
288 :param path: path to mercurial config file
289 :param checkpaths: check the path
289 :param checkpaths: check the path
290 :param read_from: read from 'file' or 'db'
290 :param read_from: read from 'file' or 'db'
291 """
291 """
292
292
293 baseui = ui.ui()
293 baseui = ui.ui()
294
294
295 # clean the baseui object
295 # clean the baseui object
296 baseui._ocfg = config.config()
296 baseui._ocfg = config.config()
297 baseui._ucfg = config.config()
297 baseui._ucfg = config.config()
298 baseui._tcfg = config.config()
298 baseui._tcfg = config.config()
299
299
300 if read_from == 'file':
300 if read_from == 'file':
301 if not os.path.isfile(path):
301 if not os.path.isfile(path):
302 log.debug('hgrc file is not present at %s, skipping...' % path)
302 log.debug('hgrc file is not present at %s, skipping...' % path)
303 return False
303 return False
304 log.debug('reading hgrc from %s' % path)
304 log.debug('reading hgrc from %s' % path)
305 cfg = config.config()
305 cfg = config.config()
306 cfg.read(path)
306 cfg.read(path)
307 for section in ui_sections:
307 for section in ui_sections:
308 for k, v in cfg.items(section):
308 for k, v in cfg.items(section):
309 log.debug('settings ui from file[%s]%s:%s' % (section, k, v))
309 log.debug('settings ui from file[%s]%s:%s' % (section, k, v))
310 baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))
310 baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))
311
311
312 elif read_from == 'db':
312 elif read_from == 'db':
313 sa = meta.Session()
313 sa = meta.Session()
314 ret = sa.query(RhodeCodeUi)\
314 ret = sa.query(RhodeCodeUi)\
315 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
315 .options(FromCache("sql_cache_short", "get_hg_ui_settings"))\
316 .all()
316 .all()
317
317
318 hg_ui = ret
318 hg_ui = ret
319 for ui_ in hg_ui:
319 for ui_ in hg_ui:
320 if ui_.ui_active:
320 if ui_.ui_active:
321 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
321 log.debug('settings ui from db[%s]%s:%s', ui_.ui_section,
322 ui_.ui_key, ui_.ui_value)
322 ui_.ui_key, ui_.ui_value)
323 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
323 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
324 safe_str(ui_.ui_value))
324 safe_str(ui_.ui_value))
325 if ui_.ui_key == 'push_ssl':
325 if ui_.ui_key == 'push_ssl':
326 # force set push_ssl requirement to False, rhodecode
326 # force set push_ssl requirement to False, rhodecode
327 # handles that
327 # handles that
328 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
328 baseui.setconfig(safe_str(ui_.ui_section), safe_str(ui_.ui_key),
329 False)
329 False)
330 if clear_session:
330 if clear_session:
331 meta.Session.remove()
331 meta.Session.remove()
332 return baseui
332 return baseui
333
333
334
334
335 def set_rhodecode_config(config):
335 def set_rhodecode_config(config):
336 """
336 """
337 Updates pylons config with new settings from database
337 Updates pylons config with new settings from database
338
338
339 :param config:
339 :param config:
340 """
340 """
341 hgsettings = RhodeCodeSetting.get_app_settings()
341 hgsettings = RhodeCodeSetting.get_app_settings()
342
342
343 for k, v in hgsettings.items():
343 for k, v in hgsettings.items():
344 config[k] = v
344 config[k] = v
345
345
346
346
347 def invalidate_cache(cache_key, *args):
347 def invalidate_cache(cache_key, *args):
348 """
348 """
349 Puts cache invalidation task into db for
349 Puts cache invalidation task into db for
350 further global cache invalidation
350 further global cache invalidation
351 """
351 """
352
352
353 from rhodecode.model.scm import ScmModel
353 from rhodecode.model.scm import ScmModel
354
354
355 if cache_key.startswith('get_repo_cached_'):
355 if cache_key.startswith('get_repo_cached_'):
356 name = cache_key.split('get_repo_cached_')[-1]
356 name = cache_key.split('get_repo_cached_')[-1]
357 ScmModel().mark_for_invalidation(name)
357 ScmModel().mark_for_invalidation(name)
358
358
359
359
360 def map_groups(path):
360 def map_groups(path):
361 """
361 """
362 Given a full path to a repository, create all nested groups that this
362 Given a full path to a repository, create all nested groups that this
363 repo is inside. This function creates parent-child relationships between
363 repo is inside. This function creates parent-child relationships between
364 groups and creates default perms for all new groups.
364 groups and creates default perms for all new groups.
365
365
366 :param paths: full path to repository
366 :param paths: full path to repository
367 """
367 """
368 sa = meta.Session()
368 sa = meta.Session()
369 groups = path.split(Repository.url_sep())
369 groups = path.split(Repository.url_sep())
370 parent = None
370 parent = None
371 group = None
371 group = None
372
372
373 # last element is repo in nested groups structure
373 # last element is repo in nested groups structure
374 groups = groups[:-1]
374 groups = groups[:-1]
375 rgm = ReposGroupModel(sa)
375 rgm = ReposGroupModel(sa)
376 for lvl, group_name in enumerate(groups):
376 for lvl, group_name in enumerate(groups):
377 group_name = '/'.join(groups[:lvl] + [group_name])
377 group_name = '/'.join(groups[:lvl] + [group_name])
378 group = RepoGroup.get_by_group_name(group_name)
378 group = RepoGroup.get_by_group_name(group_name)
379 desc = '%s group' % group_name
379 desc = '%s group' % group_name
380
380
381 # skip folders that are now removed repos
381 # skip folders that are now removed repos
382 if REMOVED_REPO_PAT.match(group_name):
382 if REMOVED_REPO_PAT.match(group_name):
383 break
383 break
384
384
385 if group is None:
385 if group is None:
386 log.debug('creating group level: %s group_name: %s' % (lvl,
386 log.debug('creating group level: %s group_name: %s' % (lvl,
387 group_name))
387 group_name))
388 group = RepoGroup(group_name, parent)
388 group = RepoGroup(group_name, parent)
389 group.group_description = desc
389 group.group_description = desc
390 sa.add(group)
390 sa.add(group)
391 rgm._create_default_perms(group)
391 rgm._create_default_perms(group)
392 sa.flush()
392 sa.flush()
393 parent = group
393 parent = group
394 return group
394 return group
395
395
396
396
397 def repo2db_mapper(initial_repo_list, remove_obsolete=False,
397 def repo2db_mapper(initial_repo_list, remove_obsolete=False,
398 install_git_hook=False):
398 install_git_hook=False):
399 """
399 """
400 maps all repos given in initial_repo_list, non existing repositories
400 maps all repos given in initial_repo_list, non existing repositories
401 are created, if remove_obsolete is True it also check for db entries
401 are created, if remove_obsolete is True it also check for db entries
402 that are not in initial_repo_list and removes them.
402 that are not in initial_repo_list and removes them.
403
403
404 :param initial_repo_list: list of repositories found by scanning methods
404 :param initial_repo_list: list of repositories found by scanning methods
405 :param remove_obsolete: check for obsolete entries in database
405 :param remove_obsolete: check for obsolete entries in database
406 :param install_git_hook: if this is True, also check and install githook
406 :param install_git_hook: if this is True, also check and install githook
407 for a repo if missing
407 for a repo if missing
408 """
408 """
409 from rhodecode.model.repo import RepoModel
409 from rhodecode.model.repo import RepoModel
410 from rhodecode.model.scm import ScmModel
410 from rhodecode.model.scm import ScmModel
411 sa = meta.Session()
411 sa = meta.Session()
412 rm = RepoModel()
412 rm = RepoModel()
413 user = sa.query(User).filter(User.admin == True).first()
413 user = sa.query(User).filter(User.admin == True).first()
414 if user is None:
414 if user is None:
415 raise Exception('Missing administrative account!')
415 raise Exception('Missing administrative account!')
416 added = []
416 added = []
417
417
418 # # clear cache keys
418 # # clear cache keys
419 # log.debug("Clearing cache keys now...")
419 # log.debug("Clearing cache keys now...")
420 # CacheInvalidation.clear_cache()
420 # CacheInvalidation.clear_cache()
421 # sa.commit()
421 # sa.commit()
422
422
423 for name, repo in initial_repo_list.items():
423 for name, repo in initial_repo_list.items():
424 group = map_groups(name)
424 group = map_groups(name)
425 db_repo = rm.get_by_repo_name(name)
425 db_repo = rm.get_by_repo_name(name)
426 # found repo that is on filesystem not in RhodeCode database
426 # found repo that is on filesystem not in RhodeCode database
427 if not db_repo:
427 if not db_repo:
428 log.info('repository %s not found, creating now' % name)
428 log.info('repository %s not found, creating now' % name)
429 added.append(name)
429 added.append(name)
430 desc = (repo.description
430 desc = (repo.description
431 if repo.description != 'unknown'
431 if repo.description != 'unknown'
432 else '%s repository' % name)
432 else '%s repository' % name)
433 new_repo = rm.create_repo(
433 new_repo = rm.create_repo(
434 repo_name=name,
434 repo_name=name,
435 repo_type=repo.alias,
435 repo_type=repo.alias,
436 description=desc,
436 description=desc,
437 repos_group=getattr(group, 'group_id', None),
437 repos_group=getattr(group, 'group_id', None),
438 owner=user,
438 owner=user,
439 just_db=True
439 just_db=True
440 )
440 )
441 # we added that repo just now, and make sure it has githook
441 # we added that repo just now, and make sure it has githook
442 # installed
442 # installed
443 if new_repo.repo_type == 'git':
443 if new_repo.repo_type == 'git':
444 ScmModel().install_git_hook(new_repo.scm_instance)
444 ScmModel().install_git_hook(new_repo.scm_instance)
445 elif install_git_hook:
445 elif install_git_hook:
446 if db_repo.repo_type == 'git':
446 if db_repo.repo_type == 'git':
447 ScmModel().install_git_hook(db_repo.scm_instance)
447 ScmModel().install_git_hook(db_repo.scm_instance)
448 # during starting install all cache keys for all repositories in the
448 # during starting install all cache keys for all repositories in the
449 # system, this will register all repos and multiple instances
449 # system, this will register all repos and multiple instances
450 key, _prefix, _org_key = CacheInvalidation._get_key(name)
450 key, _prefix, _org_key = CacheInvalidation._get_key(name)
451 log.debug("Creating a cache key for %s instance_id:`%s`" % (name, _prefix))
451 CacheInvalidation.invalidate(name)
452 CacheInvalidation._get_or_create_key(key, _prefix, _org_key, commit=False)
452 log.debug("Creating a cache key for %s instance_id=>`%s`"
453 % (name, _prefix or '-'))
454
453 sa.commit()
455 sa.commit()
454 removed = []
456 removed = []
455 if remove_obsolete:
457 if remove_obsolete:
456 # remove from database those repositories that are not in the filesystem
458 # remove from database those repositories that are not in the filesystem
457 for repo in sa.query(Repository).all():
459 for repo in sa.query(Repository).all():
458 if repo.repo_name not in initial_repo_list.keys():
460 if repo.repo_name not in initial_repo_list.keys():
459 log.debug("Removing non-existing repository found in db `%s`" %
461 log.debug("Removing non-existing repository found in db `%s`" %
460 repo.repo_name)
462 repo.repo_name)
461 try:
463 try:
462 sa.delete(repo)
464 sa.delete(repo)
463 sa.commit()
465 sa.commit()
464 removed.append(repo.repo_name)
466 removed.append(repo.repo_name)
465 except:
467 except:
466 #don't hold further removals on error
468 #don't hold further removals on error
467 log.error(traceback.format_exc())
469 log.error(traceback.format_exc())
468 sa.rollback()
470 sa.rollback()
469
471
470 return added, removed
472 return added, removed
471
473
472
474
473 # set cache regions for beaker so celery can utilise it
475 # set cache regions for beaker so celery can utilise it
474 def add_cache(settings):
476 def add_cache(settings):
475 cache_settings = {'regions': None}
477 cache_settings = {'regions': None}
476 for key in settings.keys():
478 for key in settings.keys():
477 for prefix in ['beaker.cache.', 'cache.']:
479 for prefix in ['beaker.cache.', 'cache.']:
478 if key.startswith(prefix):
480 if key.startswith(prefix):
479 name = key.split(prefix)[1].strip()
481 name = key.split(prefix)[1].strip()
480 cache_settings[name] = settings[key].strip()
482 cache_settings[name] = settings[key].strip()
481 if cache_settings['regions']:
483 if cache_settings['regions']:
482 for region in cache_settings['regions'].split(','):
484 for region in cache_settings['regions'].split(','):
483 region = region.strip()
485 region = region.strip()
484 region_settings = {}
486 region_settings = {}
485 for key, value in cache_settings.items():
487 for key, value in cache_settings.items():
486 if key.startswith(region):
488 if key.startswith(region):
487 region_settings[key.split('.')[1]] = value
489 region_settings[key.split('.')[1]] = value
488 region_settings['expire'] = int(region_settings.get('expire',
490 region_settings['expire'] = int(region_settings.get('expire',
489 60))
491 60))
490 region_settings.setdefault('lock_dir',
492 region_settings.setdefault('lock_dir',
491 cache_settings.get('lock_dir'))
493 cache_settings.get('lock_dir'))
492 region_settings.setdefault('data_dir',
494 region_settings.setdefault('data_dir',
493 cache_settings.get('data_dir'))
495 cache_settings.get('data_dir'))
494
496
495 if 'type' not in region_settings:
497 if 'type' not in region_settings:
496 region_settings['type'] = cache_settings.get('type',
498 region_settings['type'] = cache_settings.get('type',
497 'memory')
499 'memory')
498 beaker.cache.cache_regions[region] = region_settings
500 beaker.cache.cache_regions[region] = region_settings
499
501
500
502
501 def load_rcextensions(root_path):
503 def load_rcextensions(root_path):
502 import rhodecode
504 import rhodecode
503 from rhodecode.config import conf
505 from rhodecode.config import conf
504
506
505 path = os.path.join(root_path, 'rcextensions', '__init__.py')
507 path = os.path.join(root_path, 'rcextensions', '__init__.py')
506 if os.path.isfile(path):
508 if os.path.isfile(path):
507 rcext = create_module('rc', path)
509 rcext = create_module('rc', path)
508 EXT = rhodecode.EXTENSIONS = rcext
510 EXT = rhodecode.EXTENSIONS = rcext
509 log.debug('Found rcextensions now loading %s...' % rcext)
511 log.debug('Found rcextensions now loading %s...' % rcext)
510
512
511 # Additional mappings that are not present in the pygments lexers
513 # Additional mappings that are not present in the pygments lexers
512 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
514 conf.LANGUAGES_EXTENSIONS_MAP.update(getattr(EXT, 'EXTRA_MAPPINGS', {}))
513
515
514 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
516 #OVERRIDE OUR EXTENSIONS FROM RC-EXTENSIONS (if present)
515
517
516 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
518 if getattr(EXT, 'INDEX_EXTENSIONS', []) != []:
517 log.debug('settings custom INDEX_EXTENSIONS')
519 log.debug('settings custom INDEX_EXTENSIONS')
518 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
520 conf.INDEX_EXTENSIONS = getattr(EXT, 'INDEX_EXTENSIONS', [])
519
521
520 #ADDITIONAL MAPPINGS
522 #ADDITIONAL MAPPINGS
521 log.debug('adding extra into INDEX_EXTENSIONS')
523 log.debug('adding extra into INDEX_EXTENSIONS')
522 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
524 conf.INDEX_EXTENSIONS.extend(getattr(EXT, 'EXTRA_INDEX_EXTENSIONS', []))
523
525
524
526
525 #==============================================================================
527 #==============================================================================
526 # TEST FUNCTIONS AND CREATORS
528 # TEST FUNCTIONS AND CREATORS
527 #==============================================================================
529 #==============================================================================
528 def create_test_index(repo_location, config, full_index):
530 def create_test_index(repo_location, config, full_index):
529 """
531 """
530 Makes default test index
532 Makes default test index
531
533
532 :param config: test config
534 :param config: test config
533 :param full_index:
535 :param full_index:
534 """
536 """
535
537
536 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
538 from rhodecode.lib.indexers.daemon import WhooshIndexingDaemon
537 from rhodecode.lib.pidlock import DaemonLock, LockHeld
539 from rhodecode.lib.pidlock import DaemonLock, LockHeld
538
540
539 repo_location = repo_location
541 repo_location = repo_location
540
542
541 index_location = os.path.join(config['app_conf']['index_dir'])
543 index_location = os.path.join(config['app_conf']['index_dir'])
542 if not os.path.exists(index_location):
544 if not os.path.exists(index_location):
543 os.makedirs(index_location)
545 os.makedirs(index_location)
544
546
545 try:
547 try:
546 l = DaemonLock(file_=jn(dn(index_location), 'make_index.lock'))
548 l = DaemonLock(file_=jn(dn(index_location), 'make_index.lock'))
547 WhooshIndexingDaemon(index_location=index_location,
549 WhooshIndexingDaemon(index_location=index_location,
548 repo_location=repo_location)\
550 repo_location=repo_location)\
549 .run(full_index=full_index)
551 .run(full_index=full_index)
550 l.release()
552 l.release()
551 except LockHeld:
553 except LockHeld:
552 pass
554 pass
553
555
554
556
555 def create_test_env(repos_test_path, config):
557 def create_test_env(repos_test_path, config):
556 """
558 """
557 Makes a fresh database and
559 Makes a fresh database and
558 install test repository into tmp dir
560 install test repository into tmp dir
559 """
561 """
560 from rhodecode.lib.db_manage import DbManage
562 from rhodecode.lib.db_manage import DbManage
561 from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
563 from rhodecode.tests import HG_REPO, GIT_REPO, TESTS_TMP_PATH
562
564
563 # PART ONE create db
565 # PART ONE create db
564 dbconf = config['sqlalchemy.db1.url']
566 dbconf = config['sqlalchemy.db1.url']
565 log.debug('making test db %s' % dbconf)
567 log.debug('making test db %s' % dbconf)
566
568
567 # create test dir if it doesn't exist
569 # create test dir if it doesn't exist
568 if not os.path.isdir(repos_test_path):
570 if not os.path.isdir(repos_test_path):
569 log.debug('Creating testdir %s' % repos_test_path)
571 log.debug('Creating testdir %s' % repos_test_path)
570 os.makedirs(repos_test_path)
572 os.makedirs(repos_test_path)
571
573
572 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
574 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=config['here'],
573 tests=True)
575 tests=True)
574 dbmanage.create_tables(override=True)
576 dbmanage.create_tables(override=True)
575 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
577 dbmanage.create_settings(dbmanage.config_prompt(repos_test_path))
576 dbmanage.create_default_user()
578 dbmanage.create_default_user()
577 dbmanage.admin_prompt()
579 dbmanage.admin_prompt()
578 dbmanage.create_permissions()
580 dbmanage.create_permissions()
579 dbmanage.populate_default_permissions()
581 dbmanage.populate_default_permissions()
580 Session().commit()
582 Session().commit()
581 # PART TWO make test repo
583 # PART TWO make test repo
582 log.debug('making test vcs repositories')
584 log.debug('making test vcs repositories')
583
585
584 idx_path = config['app_conf']['index_dir']
586 idx_path = config['app_conf']['index_dir']
585 data_path = config['app_conf']['cache_dir']
587 data_path = config['app_conf']['cache_dir']
586
588
587 #clean index and data
589 #clean index and data
588 if idx_path and os.path.exists(idx_path):
590 if idx_path and os.path.exists(idx_path):
589 log.debug('remove %s' % idx_path)
591 log.debug('remove %s' % idx_path)
590 shutil.rmtree(idx_path)
592 shutil.rmtree(idx_path)
591
593
592 if data_path and os.path.exists(data_path):
594 if data_path and os.path.exists(data_path):
593 log.debug('remove %s' % data_path)
595 log.debug('remove %s' % data_path)
594 shutil.rmtree(data_path)
596 shutil.rmtree(data_path)
595
597
596 #CREATE DEFAULT TEST REPOS
598 #CREATE DEFAULT TEST REPOS
597 cur_dir = dn(dn(abspath(__file__)))
599 cur_dir = dn(dn(abspath(__file__)))
598 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
600 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_hg.tar.gz"))
599 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
601 tar.extractall(jn(TESTS_TMP_PATH, HG_REPO))
600 tar.close()
602 tar.close()
601
603
602 cur_dir = dn(dn(abspath(__file__)))
604 cur_dir = dn(dn(abspath(__file__)))
603 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_git.tar.gz"))
605 tar = tarfile.open(jn(cur_dir, 'tests', "vcs_test_git.tar.gz"))
604 tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO))
606 tar.extractall(jn(TESTS_TMP_PATH, GIT_REPO))
605 tar.close()
607 tar.close()
606
608
607 #LOAD VCS test stuff
609 #LOAD VCS test stuff
608 from rhodecode.tests.vcs import setup_package
610 from rhodecode.tests.vcs import setup_package
609 setup_package()
611 setup_package()
610
612
611
613
612 #==============================================================================
614 #==============================================================================
613 # PASTER COMMANDS
615 # PASTER COMMANDS
614 #==============================================================================
616 #==============================================================================
615 class BasePasterCommand(Command):
617 class BasePasterCommand(Command):
616 """
618 """
617 Abstract Base Class for paster commands.
619 Abstract Base Class for paster commands.
618
620
619 The celery commands are somewhat aggressive about loading
621 The celery commands are somewhat aggressive about loading
620 celery.conf, and since our module sets the `CELERY_LOADER`
622 celery.conf, and since our module sets the `CELERY_LOADER`
621 environment variable to our loader, we have to bootstrap a bit and
623 environment variable to our loader, we have to bootstrap a bit and
622 make sure we've had a chance to load the pylons config off of the
624 make sure we've had a chance to load the pylons config off of the
623 command line, otherwise everything fails.
625 command line, otherwise everything fails.
624 """
626 """
625 min_args = 1
627 min_args = 1
626 min_args_error = "Please provide a paster config file as an argument."
628 min_args_error = "Please provide a paster config file as an argument."
627 takes_config_file = 1
629 takes_config_file = 1
628 requires_config_file = True
630 requires_config_file = True
629
631
630 def notify_msg(self, msg, log=False):
632 def notify_msg(self, msg, log=False):
631 """Make a notification to user, additionally if logger is passed
633 """Make a notification to user, additionally if logger is passed
632 it logs this action using given logger
634 it logs this action using given logger
633
635
634 :param msg: message that will be printed to user
636 :param msg: message that will be printed to user
635 :param log: logging instance, to use to additionally log this message
637 :param log: logging instance, to use to additionally log this message
636
638
637 """
639 """
638 if log and isinstance(log, logging):
640 if log and isinstance(log, logging):
639 log(msg)
641 log(msg)
640
642
641 def run(self, args):
643 def run(self, args):
642 """
644 """
643 Overrides Command.run
645 Overrides Command.run
644
646
645 Checks for a config file argument and loads it.
647 Checks for a config file argument and loads it.
646 """
648 """
647 if len(args) < self.min_args:
649 if len(args) < self.min_args:
648 raise BadCommand(
650 raise BadCommand(
649 self.min_args_error % {'min_args': self.min_args,
651 self.min_args_error % {'min_args': self.min_args,
650 'actual_args': len(args)})
652 'actual_args': len(args)})
651
653
652 # Decrement because we're going to lob off the first argument.
654 # Decrement because we're going to lob off the first argument.
653 # @@ This is hacky
655 # @@ This is hacky
654 self.min_args -= 1
656 self.min_args -= 1
655 self.bootstrap_config(args[0])
657 self.bootstrap_config(args[0])
656 self.update_parser()
658 self.update_parser()
657 return super(BasePasterCommand, self).run(args[1:])
659 return super(BasePasterCommand, self).run(args[1:])
658
660
659 def update_parser(self):
661 def update_parser(self):
660 """
662 """
661 Abstract method. Allows for the class's parser to be updated
663 Abstract method. Allows for the class's parser to be updated
662 before the superclass's `run` method is called. Necessary to
664 before the superclass's `run` method is called. Necessary to
663 allow options/arguments to be passed through to the underlying
665 allow options/arguments to be passed through to the underlying
664 celery command.
666 celery command.
665 """
667 """
666 raise NotImplementedError("Abstract Method.")
668 raise NotImplementedError("Abstract Method.")
667
669
668 def bootstrap_config(self, conf):
670 def bootstrap_config(self, conf):
669 """
671 """
670 Loads the pylons configuration.
672 Loads the pylons configuration.
671 """
673 """
672 from pylons import config as pylonsconfig
674 from pylons import config as pylonsconfig
673
675
674 self.path_to_ini_file = os.path.realpath(conf)
676 self.path_to_ini_file = os.path.realpath(conf)
675 conf = paste.deploy.appconfig('config:' + self.path_to_ini_file)
677 conf = paste.deploy.appconfig('config:' + self.path_to_ini_file)
676 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
678 pylonsconfig.init_app(conf.global_conf, conf.local_conf)
677
679
678
680
679 def check_git_version():
681 def check_git_version():
680 """
682 """
681 Checks what version of git is installed in system, and issues a warning
683 Checks what version of git is installed in system, and issues a warning
682 if it's too old for RhodeCode to properly work.
684 if it's too old for RhodeCode to properly work.
683 """
685 """
684 import subprocess
686 import subprocess
685 from distutils.version import StrictVersion
687 from distutils.version import StrictVersion
686 from rhodecode import BACKENDS
688 from rhodecode import BACKENDS
687
689
688 p = subprocess.Popen('git --version', shell=True,
690 p = subprocess.Popen('git --version', shell=True,
689 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
691 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
690 stdout, stderr = p.communicate()
692 stdout, stderr = p.communicate()
691 ver = (stdout.split(' ')[-1] or '').strip() or '0.0.0'
693 ver = (stdout.split(' ')[-1] or '').strip() or '0.0.0'
692 if len(ver.split('.')) > 3:
694 if len(ver.split('.')) > 3:
693 #StrictVersion needs to be only 3 element type
695 #StrictVersion needs to be only 3 element type
694 ver = '.'.join(ver.split('.')[:3])
696 ver = '.'.join(ver.split('.')[:3])
695 try:
697 try:
696 _ver = StrictVersion(ver)
698 _ver = StrictVersion(ver)
697 except:
699 except:
698 _ver = StrictVersion('0.0.0')
700 _ver = StrictVersion('0.0.0')
699 stderr = traceback.format_exc()
701 stderr = traceback.format_exc()
700
702
701 req_ver = '1.7.4'
703 req_ver = '1.7.4'
702 to_old_git = False
704 to_old_git = False
703 if _ver < StrictVersion(req_ver):
705 if _ver < StrictVersion(req_ver):
704 to_old_git = True
706 to_old_git = True
705
707
706 if 'git' in BACKENDS:
708 if 'git' in BACKENDS:
707 log.debug('GIT version detected: %s' % stdout)
709 log.debug('GIT version detected: %s' % stdout)
708 if stderr:
710 if stderr:
709 log.warning('Unable to detect git version org error was:%r' % stderr)
711 log.warning('Unable to detect git version org error was:%r' % stderr)
710 elif to_old_git:
712 elif to_old_git:
711 log.warning('RhodeCode detected git version %s, which is too old '
713 log.warning('RhodeCode detected git version %s, which is too old '
712 'for the system to function properly. Make sure '
714 'for the system to function properly. Make sure '
713 'its version is at least %s' % (ver, req_ver))
715 'its version is at least %s' % (ver, req_ver))
714 return _ver
716 return _ver
@@ -1,1802 +1,1812 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.db
3 rhodecode.model.db
4 ~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~
5
5
6 Database Models for RhodeCode
6 Database Models for RhodeCode
7
7
8 :created_on: Apr 08, 2010
8 :created_on: Apr 08, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25
25
26 import os
26 import os
27 import logging
27 import logging
28 import datetime
28 import datetime
29 import traceback
29 import traceback
30 import hashlib
30 import hashlib
31 import time
31 import time
32 from collections import defaultdict
32 from collections import defaultdict
33
33
34 from sqlalchemy import *
34 from sqlalchemy import *
35 from sqlalchemy.ext.hybrid import hybrid_property
35 from sqlalchemy.ext.hybrid import hybrid_property
36 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
36 from sqlalchemy.orm import relationship, joinedload, class_mapper, validates
37 from sqlalchemy.exc import DatabaseError
37 from sqlalchemy.exc import DatabaseError
38 from beaker.cache import cache_region, region_invalidate
38 from beaker.cache import cache_region, region_invalidate
39 from webob.exc import HTTPNotFound
39 from webob.exc import HTTPNotFound
40
40
41 from pylons.i18n.translation import lazy_ugettext as _
41 from pylons.i18n.translation import lazy_ugettext as _
42
42
43 from rhodecode.lib.vcs import get_backend
43 from rhodecode.lib.vcs import get_backend
44 from rhodecode.lib.vcs.utils.helpers import get_scm
44 from rhodecode.lib.vcs.utils.helpers import get_scm
45 from rhodecode.lib.vcs.exceptions import VCSError
45 from rhodecode.lib.vcs.exceptions import VCSError
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
46 from rhodecode.lib.vcs.utils.lazy import LazyProperty
47
47
48 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
48 from rhodecode.lib.utils2 import str2bool, safe_str, get_changeset_safe, \
49 safe_unicode, remove_suffix
49 safe_unicode, remove_suffix
50 from rhodecode.lib.compat import json
50 from rhodecode.lib.compat import json
51 from rhodecode.lib.caching_query import FromCache
51 from rhodecode.lib.caching_query import FromCache
52
52
53 from rhodecode.model.meta import Base, Session
53 from rhodecode.model.meta import Base, Session
54
54
55 URL_SEP = '/'
55 URL_SEP = '/'
56 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
57
57
58 #==============================================================================
58 #==============================================================================
59 # BASE CLASSES
59 # BASE CLASSES
60 #==============================================================================
60 #==============================================================================
61
61
62 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
62 _hash_key = lambda k: hashlib.md5(safe_str(k)).hexdigest()
63
63
64
64
65 class BaseModel(object):
65 class BaseModel(object):
66 """
66 """
67 Base Model for all classess
67 Base Model for all classess
68 """
68 """
69
69
70 @classmethod
70 @classmethod
71 def _get_keys(cls):
71 def _get_keys(cls):
72 """return column names for this model """
72 """return column names for this model """
73 return class_mapper(cls).c.keys()
73 return class_mapper(cls).c.keys()
74
74
75 def get_dict(self):
75 def get_dict(self):
76 """
76 """
77 return dict with keys and values corresponding
77 return dict with keys and values corresponding
78 to this model data """
78 to this model data """
79
79
80 d = {}
80 d = {}
81 for k in self._get_keys():
81 for k in self._get_keys():
82 d[k] = getattr(self, k)
82 d[k] = getattr(self, k)
83
83
84 # also use __json__() if present to get additional fields
84 # also use __json__() if present to get additional fields
85 _json_attr = getattr(self, '__json__', None)
85 _json_attr = getattr(self, '__json__', None)
86 if _json_attr:
86 if _json_attr:
87 # update with attributes from __json__
87 # update with attributes from __json__
88 if callable(_json_attr):
88 if callable(_json_attr):
89 _json_attr = _json_attr()
89 _json_attr = _json_attr()
90 for k, val in _json_attr.iteritems():
90 for k, val in _json_attr.iteritems():
91 d[k] = val
91 d[k] = val
92 return d
92 return d
93
93
94 def get_appstruct(self):
94 def get_appstruct(self):
95 """return list with keys and values tupples corresponding
95 """return list with keys and values tupples corresponding
96 to this model data """
96 to this model data """
97
97
98 l = []
98 l = []
99 for k in self._get_keys():
99 for k in self._get_keys():
100 l.append((k, getattr(self, k),))
100 l.append((k, getattr(self, k),))
101 return l
101 return l
102
102
103 def populate_obj(self, populate_dict):
103 def populate_obj(self, populate_dict):
104 """populate model with data from given populate_dict"""
104 """populate model with data from given populate_dict"""
105
105
106 for k in self._get_keys():
106 for k in self._get_keys():
107 if k in populate_dict:
107 if k in populate_dict:
108 setattr(self, k, populate_dict[k])
108 setattr(self, k, populate_dict[k])
109
109
110 @classmethod
110 @classmethod
111 def query(cls):
111 def query(cls):
112 return Session().query(cls)
112 return Session().query(cls)
113
113
114 @classmethod
114 @classmethod
115 def get(cls, id_):
115 def get(cls, id_):
116 if id_:
116 if id_:
117 return cls.query().get(id_)
117 return cls.query().get(id_)
118
118
119 @classmethod
119 @classmethod
120 def get_or_404(cls, id_):
120 def get_or_404(cls, id_):
121 try:
121 try:
122 id_ = int(id_)
122 id_ = int(id_)
123 except (TypeError, ValueError):
123 except (TypeError, ValueError):
124 raise HTTPNotFound
124 raise HTTPNotFound
125
125
126 res = cls.query().get(id_)
126 res = cls.query().get(id_)
127 if not res:
127 if not res:
128 raise HTTPNotFound
128 raise HTTPNotFound
129 return res
129 return res
130
130
131 @classmethod
131 @classmethod
132 def getAll(cls):
132 def getAll(cls):
133 return cls.query().all()
133 return cls.query().all()
134
134
135 @classmethod
135 @classmethod
136 def delete(cls, id_):
136 def delete(cls, id_):
137 obj = cls.query().get(id_)
137 obj = cls.query().get(id_)
138 Session().delete(obj)
138 Session().delete(obj)
139
139
140 def __repr__(self):
140 def __repr__(self):
141 if hasattr(self, '__unicode__'):
141 if hasattr(self, '__unicode__'):
142 # python repr needs to return str
142 # python repr needs to return str
143 return safe_str(self.__unicode__())
143 return safe_str(self.__unicode__())
144 return '<DB:%s>' % (self.__class__.__name__)
144 return '<DB:%s>' % (self.__class__.__name__)
145
145
146
146
147 class RhodeCodeSetting(Base, BaseModel):
147 class RhodeCodeSetting(Base, BaseModel):
148 __tablename__ = 'rhodecode_settings'
148 __tablename__ = 'rhodecode_settings'
149 __table_args__ = (
149 __table_args__ = (
150 UniqueConstraint('app_settings_name'),
150 UniqueConstraint('app_settings_name'),
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
151 {'extend_existing': True, 'mysql_engine': 'InnoDB',
152 'mysql_charset': 'utf8'}
152 'mysql_charset': 'utf8'}
153 )
153 )
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
154 app_settings_id = Column("app_settings_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
155 app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
155 app_settings_name = Column("app_settings_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
156 _app_settings_value = Column("app_settings_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
157
157
158 def __init__(self, k='', v=''):
158 def __init__(self, k='', v=''):
159 self.app_settings_name = k
159 self.app_settings_name = k
160 self.app_settings_value = v
160 self.app_settings_value = v
161
161
162 @validates('_app_settings_value')
162 @validates('_app_settings_value')
163 def validate_settings_value(self, key, val):
163 def validate_settings_value(self, key, val):
164 assert type(val) == unicode
164 assert type(val) == unicode
165 return val
165 return val
166
166
167 @hybrid_property
167 @hybrid_property
168 def app_settings_value(self):
168 def app_settings_value(self):
169 v = self._app_settings_value
169 v = self._app_settings_value
170 if self.app_settings_name == 'ldap_active':
170 if self.app_settings_name == 'ldap_active':
171 v = str2bool(v)
171 v = str2bool(v)
172 return v
172 return v
173
173
174 @app_settings_value.setter
174 @app_settings_value.setter
175 def app_settings_value(self, val):
175 def app_settings_value(self, val):
176 """
176 """
177 Setter that will always make sure we use unicode in app_settings_value
177 Setter that will always make sure we use unicode in app_settings_value
178
178
179 :param val:
179 :param val:
180 """
180 """
181 self._app_settings_value = safe_unicode(val)
181 self._app_settings_value = safe_unicode(val)
182
182
183 def __unicode__(self):
183 def __unicode__(self):
184 return u"<%s('%s:%s')>" % (
184 return u"<%s('%s:%s')>" % (
185 self.__class__.__name__,
185 self.__class__.__name__,
186 self.app_settings_name, self.app_settings_value
186 self.app_settings_name, self.app_settings_value
187 )
187 )
188
188
189 @classmethod
189 @classmethod
190 def get_by_name(cls, key):
190 def get_by_name(cls, key):
191 return cls.query()\
191 return cls.query()\
192 .filter(cls.app_settings_name == key).scalar()
192 .filter(cls.app_settings_name == key).scalar()
193
193
194 @classmethod
194 @classmethod
195 def get_by_name_or_create(cls, key):
195 def get_by_name_or_create(cls, key):
196 res = cls.get_by_name(key)
196 res = cls.get_by_name(key)
197 if not res:
197 if not res:
198 res = cls(key)
198 res = cls(key)
199 return res
199 return res
200
200
201 @classmethod
201 @classmethod
202 def get_app_settings(cls, cache=False):
202 def get_app_settings(cls, cache=False):
203
203
204 ret = cls.query()
204 ret = cls.query()
205
205
206 if cache:
206 if cache:
207 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
207 ret = ret.options(FromCache("sql_cache_short", "get_hg_settings"))
208
208
209 if not ret:
209 if not ret:
210 raise Exception('Could not get application settings !')
210 raise Exception('Could not get application settings !')
211 settings = {}
211 settings = {}
212 for each in ret:
212 for each in ret:
213 settings['rhodecode_' + each.app_settings_name] = \
213 settings['rhodecode_' + each.app_settings_name] = \
214 each.app_settings_value
214 each.app_settings_value
215
215
216 return settings
216 return settings
217
217
218 @classmethod
218 @classmethod
219 def get_ldap_settings(cls, cache=False):
219 def get_ldap_settings(cls, cache=False):
220 ret = cls.query()\
220 ret = cls.query()\
221 .filter(cls.app_settings_name.startswith('ldap_')).all()
221 .filter(cls.app_settings_name.startswith('ldap_')).all()
222 fd = {}
222 fd = {}
223 for row in ret:
223 for row in ret:
224 fd.update({row.app_settings_name: row.app_settings_value})
224 fd.update({row.app_settings_name: row.app_settings_value})
225
225
226 return fd
226 return fd
227
227
228
228
229 class RhodeCodeUi(Base, BaseModel):
229 class RhodeCodeUi(Base, BaseModel):
230 __tablename__ = 'rhodecode_ui'
230 __tablename__ = 'rhodecode_ui'
231 __table_args__ = (
231 __table_args__ = (
232 UniqueConstraint('ui_key'),
232 UniqueConstraint('ui_key'),
233 {'extend_existing': True, 'mysql_engine': 'InnoDB',
233 {'extend_existing': True, 'mysql_engine': 'InnoDB',
234 'mysql_charset': 'utf8'}
234 'mysql_charset': 'utf8'}
235 )
235 )
236
236
237 HOOK_UPDATE = 'changegroup.update'
237 HOOK_UPDATE = 'changegroup.update'
238 HOOK_REPO_SIZE = 'changegroup.repo_size'
238 HOOK_REPO_SIZE = 'changegroup.repo_size'
239 HOOK_PUSH = 'changegroup.push_logger'
239 HOOK_PUSH = 'changegroup.push_logger'
240 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
240 HOOK_PRE_PUSH = 'prechangegroup.pre_push'
241 HOOK_PULL = 'outgoing.pull_logger'
241 HOOK_PULL = 'outgoing.pull_logger'
242 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
242 HOOK_PRE_PULL = 'preoutgoing.pre_pull'
243
243
244 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
244 ui_id = Column("ui_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
245 ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
245 ui_section = Column("ui_section", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
246 ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
246 ui_key = Column("ui_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
247 ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
247 ui_value = Column("ui_value", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
248 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
248 ui_active = Column("ui_active", Boolean(), nullable=True, unique=None, default=True)
249
249
250 @classmethod
250 @classmethod
251 def get_by_key(cls, key):
251 def get_by_key(cls, key):
252 return cls.query().filter(cls.ui_key == key).scalar()
252 return cls.query().filter(cls.ui_key == key).scalar()
253
253
254 @classmethod
254 @classmethod
255 def get_builtin_hooks(cls):
255 def get_builtin_hooks(cls):
256 q = cls.query()
256 q = cls.query()
257 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
257 q = q.filter(cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
258 cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
258 cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
259 cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
259 cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
260 return q.all()
260 return q.all()
261
261
262 @classmethod
262 @classmethod
263 def get_custom_hooks(cls):
263 def get_custom_hooks(cls):
264 q = cls.query()
264 q = cls.query()
265 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
265 q = q.filter(~cls.ui_key.in_([cls.HOOK_UPDATE, cls.HOOK_REPO_SIZE,
266 cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
266 cls.HOOK_PUSH, cls.HOOK_PRE_PUSH,
267 cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
267 cls.HOOK_PULL, cls.HOOK_PRE_PULL]))
268 q = q.filter(cls.ui_section == 'hooks')
268 q = q.filter(cls.ui_section == 'hooks')
269 return q.all()
269 return q.all()
270
270
271 @classmethod
271 @classmethod
272 def get_repos_location(cls):
272 def get_repos_location(cls):
273 return cls.get_by_key('/').ui_value
273 return cls.get_by_key('/').ui_value
274
274
275 @classmethod
275 @classmethod
276 def create_or_update_hook(cls, key, val):
276 def create_or_update_hook(cls, key, val):
277 new_ui = cls.get_by_key(key) or cls()
277 new_ui = cls.get_by_key(key) or cls()
278 new_ui.ui_section = 'hooks'
278 new_ui.ui_section = 'hooks'
279 new_ui.ui_active = True
279 new_ui.ui_active = True
280 new_ui.ui_key = key
280 new_ui.ui_key = key
281 new_ui.ui_value = val
281 new_ui.ui_value = val
282
282
283 Session().add(new_ui)
283 Session().add(new_ui)
284
284
285 def __repr__(self):
285 def __repr__(self):
286 return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
286 return '<DB:%s[%s:%s]>' % (self.__class__.__name__, self.ui_key,
287 self.ui_value)
287 self.ui_value)
288
288
289
289
290 class User(Base, BaseModel):
290 class User(Base, BaseModel):
291 __tablename__ = 'users'
291 __tablename__ = 'users'
292 __table_args__ = (
292 __table_args__ = (
293 UniqueConstraint('username'), UniqueConstraint('email'),
293 UniqueConstraint('username'), UniqueConstraint('email'),
294 Index('u_username_idx', 'username'),
294 Index('u_username_idx', 'username'),
295 Index('u_email_idx', 'email'),
295 Index('u_email_idx', 'email'),
296 {'extend_existing': True, 'mysql_engine': 'InnoDB',
296 {'extend_existing': True, 'mysql_engine': 'InnoDB',
297 'mysql_charset': 'utf8'}
297 'mysql_charset': 'utf8'}
298 )
298 )
299 DEFAULT_USER = 'default'
299 DEFAULT_USER = 'default'
300 DEFAULT_PERMISSIONS = [
300 DEFAULT_PERMISSIONS = [
301 'hg.register.manual_activate', 'hg.create.repository',
301 'hg.register.manual_activate', 'hg.create.repository',
302 'hg.fork.repository', 'repository.read'
302 'hg.fork.repository', 'repository.read'
303 ]
303 ]
304 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
304 user_id = Column("user_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
305 username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
305 username = Column("username", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
306 password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
306 password = Column("password", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
307 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
307 active = Column("active", Boolean(), nullable=True, unique=None, default=True)
308 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
308 admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
309 name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
309 name = Column("firstname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
310 lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
310 lastname = Column("lastname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
311 _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
311 _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
312 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
312 last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
313 ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
313 ldap_dn = Column("ldap_dn", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
314 api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
314 api_key = Column("api_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
315 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
315 inherit_default_permissions = Column("inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
316
316
317 user_log = relationship('UserLog', cascade='all')
317 user_log = relationship('UserLog', cascade='all')
318 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
318 user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
319
319
320 repositories = relationship('Repository')
320 repositories = relationship('Repository')
321 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
321 user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
322 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
322 repo_to_perm = relationship('UserRepoToPerm', primaryjoin='UserRepoToPerm.user_id==User.user_id', cascade='all')
323 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
323 repo_group_to_perm = relationship('UserRepoGroupToPerm', primaryjoin='UserRepoGroupToPerm.user_id==User.user_id', cascade='all')
324
324
325 group_member = relationship('UsersGroupMember', cascade='all')
325 group_member = relationship('UsersGroupMember', cascade='all')
326
326
327 notifications = relationship('UserNotification', cascade='all')
327 notifications = relationship('UserNotification', cascade='all')
328 # notifications assigned to this user
328 # notifications assigned to this user
329 user_created_notifications = relationship('Notification', cascade='all')
329 user_created_notifications = relationship('Notification', cascade='all')
330 # comments created by this user
330 # comments created by this user
331 user_comments = relationship('ChangesetComment', cascade='all')
331 user_comments = relationship('ChangesetComment', cascade='all')
332 #extra emails for this user
332 #extra emails for this user
333 user_emails = relationship('UserEmailMap', cascade='all')
333 user_emails = relationship('UserEmailMap', cascade='all')
334
334
335 @hybrid_property
335 @hybrid_property
336 def email(self):
336 def email(self):
337 return self._email
337 return self._email
338
338
339 @email.setter
339 @email.setter
340 def email(self, val):
340 def email(self, val):
341 self._email = val.lower() if val else None
341 self._email = val.lower() if val else None
342
342
343 @property
343 @property
344 def firstname(self):
344 def firstname(self):
345 # alias for future
345 # alias for future
346 return self.name
346 return self.name
347
347
348 @property
348 @property
349 def emails(self):
349 def emails(self):
350 other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
350 other = UserEmailMap.query().filter(UserEmailMap.user==self).all()
351 return [self.email] + [x.email for x in other]
351 return [self.email] + [x.email for x in other]
352
352
353 @property
353 @property
354 def username_and_name(self):
354 def username_and_name(self):
355 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
355 return '%s (%s %s)' % (self.username, self.firstname, self.lastname)
356
356
357 @property
357 @property
358 def full_name(self):
358 def full_name(self):
359 return '%s %s' % (self.firstname, self.lastname)
359 return '%s %s' % (self.firstname, self.lastname)
360
360
361 @property
361 @property
362 def full_name_or_username(self):
362 def full_name_or_username(self):
363 return ('%s %s' % (self.firstname, self.lastname)
363 return ('%s %s' % (self.firstname, self.lastname)
364 if (self.firstname and self.lastname) else self.username)
364 if (self.firstname and self.lastname) else self.username)
365
365
366 @property
366 @property
367 def full_contact(self):
367 def full_contact(self):
368 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
368 return '%s %s <%s>' % (self.firstname, self.lastname, self.email)
369
369
370 @property
370 @property
371 def short_contact(self):
371 def short_contact(self):
372 return '%s %s' % (self.firstname, self.lastname)
372 return '%s %s' % (self.firstname, self.lastname)
373
373
374 @property
374 @property
375 def is_admin(self):
375 def is_admin(self):
376 return self.admin
376 return self.admin
377
377
378 def __unicode__(self):
378 def __unicode__(self):
379 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
379 return u"<%s('id:%s:%s')>" % (self.__class__.__name__,
380 self.user_id, self.username)
380 self.user_id, self.username)
381
381
382 @classmethod
382 @classmethod
383 def get_by_username(cls, username, case_insensitive=False, cache=False):
383 def get_by_username(cls, username, case_insensitive=False, cache=False):
384 if case_insensitive:
384 if case_insensitive:
385 q = cls.query().filter(cls.username.ilike(username))
385 q = cls.query().filter(cls.username.ilike(username))
386 else:
386 else:
387 q = cls.query().filter(cls.username == username)
387 q = cls.query().filter(cls.username == username)
388
388
389 if cache:
389 if cache:
390 q = q.options(FromCache(
390 q = q.options(FromCache(
391 "sql_cache_short",
391 "sql_cache_short",
392 "get_user_%s" % _hash_key(username)
392 "get_user_%s" % _hash_key(username)
393 )
393 )
394 )
394 )
395 return q.scalar()
395 return q.scalar()
396
396
397 @classmethod
397 @classmethod
398 def get_by_api_key(cls, api_key, cache=False):
398 def get_by_api_key(cls, api_key, cache=False):
399 q = cls.query().filter(cls.api_key == api_key)
399 q = cls.query().filter(cls.api_key == api_key)
400
400
401 if cache:
401 if cache:
402 q = q.options(FromCache("sql_cache_short",
402 q = q.options(FromCache("sql_cache_short",
403 "get_api_key_%s" % api_key))
403 "get_api_key_%s" % api_key))
404 return q.scalar()
404 return q.scalar()
405
405
406 @classmethod
406 @classmethod
407 def get_by_email(cls, email, case_insensitive=False, cache=False):
407 def get_by_email(cls, email, case_insensitive=False, cache=False):
408 if case_insensitive:
408 if case_insensitive:
409 q = cls.query().filter(cls.email.ilike(email))
409 q = cls.query().filter(cls.email.ilike(email))
410 else:
410 else:
411 q = cls.query().filter(cls.email == email)
411 q = cls.query().filter(cls.email == email)
412
412
413 if cache:
413 if cache:
414 q = q.options(FromCache("sql_cache_short",
414 q = q.options(FromCache("sql_cache_short",
415 "get_email_key_%s" % email))
415 "get_email_key_%s" % email))
416
416
417 ret = q.scalar()
417 ret = q.scalar()
418 if ret is None:
418 if ret is None:
419 q = UserEmailMap.query()
419 q = UserEmailMap.query()
420 # try fetching in alternate email map
420 # try fetching in alternate email map
421 if case_insensitive:
421 if case_insensitive:
422 q = q.filter(UserEmailMap.email.ilike(email))
422 q = q.filter(UserEmailMap.email.ilike(email))
423 else:
423 else:
424 q = q.filter(UserEmailMap.email == email)
424 q = q.filter(UserEmailMap.email == email)
425 q = q.options(joinedload(UserEmailMap.user))
425 q = q.options(joinedload(UserEmailMap.user))
426 if cache:
426 if cache:
427 q = q.options(FromCache("sql_cache_short",
427 q = q.options(FromCache("sql_cache_short",
428 "get_email_map_key_%s" % email))
428 "get_email_map_key_%s" % email))
429 ret = getattr(q.scalar(), 'user', None)
429 ret = getattr(q.scalar(), 'user', None)
430
430
431 return ret
431 return ret
432
432
433 def update_lastlogin(self):
433 def update_lastlogin(self):
434 """Update user lastlogin"""
434 """Update user lastlogin"""
435 self.last_login = datetime.datetime.now()
435 self.last_login = datetime.datetime.now()
436 Session().add(self)
436 Session().add(self)
437 log.debug('updated user %s lastlogin' % self.username)
437 log.debug('updated user %s lastlogin' % self.username)
438
438
439 def get_api_data(self):
439 def get_api_data(self):
440 """
440 """
441 Common function for generating user related data for API
441 Common function for generating user related data for API
442 """
442 """
443 user = self
443 user = self
444 data = dict(
444 data = dict(
445 user_id=user.user_id,
445 user_id=user.user_id,
446 username=user.username,
446 username=user.username,
447 firstname=user.name,
447 firstname=user.name,
448 lastname=user.lastname,
448 lastname=user.lastname,
449 email=user.email,
449 email=user.email,
450 emails=user.emails,
450 emails=user.emails,
451 api_key=user.api_key,
451 api_key=user.api_key,
452 active=user.active,
452 active=user.active,
453 admin=user.admin,
453 admin=user.admin,
454 ldap_dn=user.ldap_dn,
454 ldap_dn=user.ldap_dn,
455 last_login=user.last_login,
455 last_login=user.last_login,
456 )
456 )
457 return data
457 return data
458
458
459 def __json__(self):
459 def __json__(self):
460 data = dict(
460 data = dict(
461 full_name=self.full_name,
461 full_name=self.full_name,
462 full_name_or_username=self.full_name_or_username,
462 full_name_or_username=self.full_name_or_username,
463 short_contact=self.short_contact,
463 short_contact=self.short_contact,
464 full_contact=self.full_contact
464 full_contact=self.full_contact
465 )
465 )
466 data.update(self.get_api_data())
466 data.update(self.get_api_data())
467 return data
467 return data
468
468
469
469
470 class UserEmailMap(Base, BaseModel):
470 class UserEmailMap(Base, BaseModel):
471 __tablename__ = 'user_email_map'
471 __tablename__ = 'user_email_map'
472 __table_args__ = (
472 __table_args__ = (
473 Index('uem_email_idx', 'email'),
473 Index('uem_email_idx', 'email'),
474 UniqueConstraint('email'),
474 UniqueConstraint('email'),
475 {'extend_existing': True, 'mysql_engine': 'InnoDB',
475 {'extend_existing': True, 'mysql_engine': 'InnoDB',
476 'mysql_charset': 'utf8'}
476 'mysql_charset': 'utf8'}
477 )
477 )
478 __mapper_args__ = {}
478 __mapper_args__ = {}
479
479
480 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
480 email_id = Column("email_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
481 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
481 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
482 _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
482 _email = Column("email", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
483 user = relationship('User', lazy='joined')
483 user = relationship('User', lazy='joined')
484
484
485 @validates('_email')
485 @validates('_email')
486 def validate_email(self, key, email):
486 def validate_email(self, key, email):
487 # check if this email is not main one
487 # check if this email is not main one
488 main_email = Session().query(User).filter(User.email == email).scalar()
488 main_email = Session().query(User).filter(User.email == email).scalar()
489 if main_email is not None:
489 if main_email is not None:
490 raise AttributeError('email %s is present is user table' % email)
490 raise AttributeError('email %s is present is user table' % email)
491 return email
491 return email
492
492
493 @hybrid_property
493 @hybrid_property
494 def email(self):
494 def email(self):
495 return self._email
495 return self._email
496
496
497 @email.setter
497 @email.setter
498 def email(self, val):
498 def email(self, val):
499 self._email = val.lower() if val else None
499 self._email = val.lower() if val else None
500
500
501
501
502 class UserLog(Base, BaseModel):
502 class UserLog(Base, BaseModel):
503 __tablename__ = 'user_logs'
503 __tablename__ = 'user_logs'
504 __table_args__ = (
504 __table_args__ = (
505 {'extend_existing': True, 'mysql_engine': 'InnoDB',
505 {'extend_existing': True, 'mysql_engine': 'InnoDB',
506 'mysql_charset': 'utf8'},
506 'mysql_charset': 'utf8'},
507 )
507 )
508 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
508 user_log_id = Column("user_log_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
509 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
509 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
510 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
510 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True)
511 repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
511 repository_name = Column("repository_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
512 user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
512 user_ip = Column("user_ip", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
513 action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
513 action = Column("action", UnicodeText(1200000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
514 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
514 action_date = Column("action_date", DateTime(timezone=False), nullable=True, unique=None, default=None)
515
515
516 @property
516 @property
517 def action_as_day(self):
517 def action_as_day(self):
518 return datetime.date(*self.action_date.timetuple()[:3])
518 return datetime.date(*self.action_date.timetuple()[:3])
519
519
520 user = relationship('User')
520 user = relationship('User')
521 repository = relationship('Repository', cascade='')
521 repository = relationship('Repository', cascade='')
522
522
523
523
524 class UsersGroup(Base, BaseModel):
524 class UsersGroup(Base, BaseModel):
525 __tablename__ = 'users_groups'
525 __tablename__ = 'users_groups'
526 __table_args__ = (
526 __table_args__ = (
527 {'extend_existing': True, 'mysql_engine': 'InnoDB',
527 {'extend_existing': True, 'mysql_engine': 'InnoDB',
528 'mysql_charset': 'utf8'},
528 'mysql_charset': 'utf8'},
529 )
529 )
530
530
531 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
531 users_group_id = Column("users_group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
532 users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
532 users_group_name = Column("users_group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
533 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
533 users_group_active = Column("users_group_active", Boolean(), nullable=True, unique=None, default=None)
534 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
534 inherit_default_permissions = Column("users_group_inherit_default_permissions", Boolean(), nullable=False, unique=None, default=True)
535
535
536 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
536 members = relationship('UsersGroupMember', cascade="all, delete, delete-orphan", lazy="joined")
537 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
537 users_group_to_perm = relationship('UsersGroupToPerm', cascade='all')
538 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
538 users_group_repo_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
539
539
540 def __unicode__(self):
540 def __unicode__(self):
541 return u'<userGroup(%s)>' % (self.users_group_name)
541 return u'<userGroup(%s)>' % (self.users_group_name)
542
542
543 @classmethod
543 @classmethod
544 def get_by_group_name(cls, group_name, cache=False,
544 def get_by_group_name(cls, group_name, cache=False,
545 case_insensitive=False):
545 case_insensitive=False):
546 if case_insensitive:
546 if case_insensitive:
547 q = cls.query().filter(cls.users_group_name.ilike(group_name))
547 q = cls.query().filter(cls.users_group_name.ilike(group_name))
548 else:
548 else:
549 q = cls.query().filter(cls.users_group_name == group_name)
549 q = cls.query().filter(cls.users_group_name == group_name)
550 if cache:
550 if cache:
551 q = q.options(FromCache(
551 q = q.options(FromCache(
552 "sql_cache_short",
552 "sql_cache_short",
553 "get_user_%s" % _hash_key(group_name)
553 "get_user_%s" % _hash_key(group_name)
554 )
554 )
555 )
555 )
556 return q.scalar()
556 return q.scalar()
557
557
558 @classmethod
558 @classmethod
559 def get(cls, users_group_id, cache=False):
559 def get(cls, users_group_id, cache=False):
560 users_group = cls.query()
560 users_group = cls.query()
561 if cache:
561 if cache:
562 users_group = users_group.options(FromCache("sql_cache_short",
562 users_group = users_group.options(FromCache("sql_cache_short",
563 "get_users_group_%s" % users_group_id))
563 "get_users_group_%s" % users_group_id))
564 return users_group.get(users_group_id)
564 return users_group.get(users_group_id)
565
565
566 def get_api_data(self):
566 def get_api_data(self):
567 users_group = self
567 users_group = self
568
568
569 data = dict(
569 data = dict(
570 users_group_id=users_group.users_group_id,
570 users_group_id=users_group.users_group_id,
571 group_name=users_group.users_group_name,
571 group_name=users_group.users_group_name,
572 active=users_group.users_group_active,
572 active=users_group.users_group_active,
573 )
573 )
574
574
575 return data
575 return data
576
576
577
577
578 class UsersGroupMember(Base, BaseModel):
578 class UsersGroupMember(Base, BaseModel):
579 __tablename__ = 'users_groups_members'
579 __tablename__ = 'users_groups_members'
580 __table_args__ = (
580 __table_args__ = (
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
581 {'extend_existing': True, 'mysql_engine': 'InnoDB',
582 'mysql_charset': 'utf8'},
582 'mysql_charset': 'utf8'},
583 )
583 )
584
584
585 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
585 users_group_member_id = Column("users_group_member_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
586 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
586 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
587 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
587 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
588
588
589 user = relationship('User', lazy='joined')
589 user = relationship('User', lazy='joined')
590 users_group = relationship('UsersGroup')
590 users_group = relationship('UsersGroup')
591
591
592 def __init__(self, gr_id='', u_id=''):
592 def __init__(self, gr_id='', u_id=''):
593 self.users_group_id = gr_id
593 self.users_group_id = gr_id
594 self.user_id = u_id
594 self.user_id = u_id
595
595
596
596
597 class Repository(Base, BaseModel):
597 class Repository(Base, BaseModel):
598 __tablename__ = 'repositories'
598 __tablename__ = 'repositories'
599 __table_args__ = (
599 __table_args__ = (
600 UniqueConstraint('repo_name'),
600 UniqueConstraint('repo_name'),
601 Index('r_repo_name_idx', 'repo_name'),
601 Index('r_repo_name_idx', 'repo_name'),
602 {'extend_existing': True, 'mysql_engine': 'InnoDB',
602 {'extend_existing': True, 'mysql_engine': 'InnoDB',
603 'mysql_charset': 'utf8'},
603 'mysql_charset': 'utf8'},
604 )
604 )
605
605
606 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
606 repo_id = Column("repo_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
607 repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
607 repo_name = Column("repo_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
608 clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
608 clone_uri = Column("clone_uri", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
609 repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
609 repo_type = Column("repo_type", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
610 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
610 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
611 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
611 private = Column("private", Boolean(), nullable=True, unique=None, default=None)
612 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
612 enable_statistics = Column("statistics", Boolean(), nullable=True, unique=None, default=True)
613 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
613 enable_downloads = Column("downloads", Boolean(), nullable=True, unique=None, default=True)
614 description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
614 description = Column("description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
615 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
615 created_on = Column('created_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
616 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
616 updated_on = Column('updated_on', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
617 landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
617 landing_rev = Column("landing_revision", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=False, default=None)
618 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
618 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
619 _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
619 _locked = Column("locked", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=False, default=None)
620
620
621 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
621 fork_id = Column("fork_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=False, default=None)
622 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
622 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=False, default=None)
623
623
624 user = relationship('User')
624 user = relationship('User')
625 fork = relationship('Repository', remote_side=repo_id)
625 fork = relationship('Repository', remote_side=repo_id)
626 group = relationship('RepoGroup')
626 group = relationship('RepoGroup')
627 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
627 repo_to_perm = relationship('UserRepoToPerm', cascade='all', order_by='UserRepoToPerm.repo_to_perm_id')
628 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
628 users_group_to_perm = relationship('UsersGroupRepoToPerm', cascade='all')
629 stats = relationship('Statistics', cascade='all', uselist=False)
629 stats = relationship('Statistics', cascade='all', uselist=False)
630
630
631 followers = relationship('UserFollowing',
631 followers = relationship('UserFollowing',
632 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
632 primaryjoin='UserFollowing.follows_repo_id==Repository.repo_id',
633 cascade='all')
633 cascade='all')
634
634
635 logs = relationship('UserLog')
635 logs = relationship('UserLog')
636 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
636 comments = relationship('ChangesetComment', cascade="all, delete, delete-orphan")
637
637
638 pull_requests_org = relationship('PullRequest',
638 pull_requests_org = relationship('PullRequest',
639 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
639 primaryjoin='PullRequest.org_repo_id==Repository.repo_id',
640 cascade="all, delete, delete-orphan")
640 cascade="all, delete, delete-orphan")
641
641
642 pull_requests_other = relationship('PullRequest',
642 pull_requests_other = relationship('PullRequest',
643 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
643 primaryjoin='PullRequest.other_repo_id==Repository.repo_id',
644 cascade="all, delete, delete-orphan")
644 cascade="all, delete, delete-orphan")
645
645
646 def __unicode__(self):
646 def __unicode__(self):
647 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
647 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.repo_id,
648 self.repo_name)
648 self.repo_name)
649
649
650 @hybrid_property
650 @hybrid_property
651 def locked(self):
651 def locked(self):
652 # always should return [user_id, timelocked]
652 # always should return [user_id, timelocked]
653 if self._locked:
653 if self._locked:
654 _lock_info = self._locked.split(':')
654 _lock_info = self._locked.split(':')
655 return int(_lock_info[0]), _lock_info[1]
655 return int(_lock_info[0]), _lock_info[1]
656 return [None, None]
656 return [None, None]
657
657
658 @locked.setter
658 @locked.setter
659 def locked(self, val):
659 def locked(self, val):
660 if val and isinstance(val, (list, tuple)):
660 if val and isinstance(val, (list, tuple)):
661 self._locked = ':'.join(map(str, val))
661 self._locked = ':'.join(map(str, val))
662 else:
662 else:
663 self._locked = None
663 self._locked = None
664
664
665 @classmethod
665 @classmethod
666 def url_sep(cls):
666 def url_sep(cls):
667 return URL_SEP
667 return URL_SEP
668
668
669 @classmethod
669 @classmethod
670 def get_by_repo_name(cls, repo_name):
670 def get_by_repo_name(cls, repo_name):
671 q = Session().query(cls).filter(cls.repo_name == repo_name)
671 q = Session().query(cls).filter(cls.repo_name == repo_name)
672 q = q.options(joinedload(Repository.fork))\
672 q = q.options(joinedload(Repository.fork))\
673 .options(joinedload(Repository.user))\
673 .options(joinedload(Repository.user))\
674 .options(joinedload(Repository.group))
674 .options(joinedload(Repository.group))
675 return q.scalar()
675 return q.scalar()
676
676
677 @classmethod
677 @classmethod
678 def get_by_full_path(cls, repo_full_path):
678 def get_by_full_path(cls, repo_full_path):
679 repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
679 repo_name = repo_full_path.split(cls.base_path(), 1)[-1]
680 return cls.get_by_repo_name(repo_name.strip(URL_SEP))
680 return cls.get_by_repo_name(repo_name.strip(URL_SEP))
681
681
682 @classmethod
682 @classmethod
683 def get_repo_forks(cls, repo_id):
683 def get_repo_forks(cls, repo_id):
684 return cls.query().filter(Repository.fork_id == repo_id)
684 return cls.query().filter(Repository.fork_id == repo_id)
685
685
686 @classmethod
686 @classmethod
687 def base_path(cls):
687 def base_path(cls):
688 """
688 """
689 Returns base path when all repos are stored
689 Returns base path when all repos are stored
690
690
691 :param cls:
691 :param cls:
692 """
692 """
693 q = Session().query(RhodeCodeUi)\
693 q = Session().query(RhodeCodeUi)\
694 .filter(RhodeCodeUi.ui_key == cls.url_sep())
694 .filter(RhodeCodeUi.ui_key == cls.url_sep())
695 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
695 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
696 return q.one().ui_value
696 return q.one().ui_value
697
697
698 @property
698 @property
699 def forks(self):
699 def forks(self):
700 """
700 """
701 Return forks of this repo
701 Return forks of this repo
702 """
702 """
703 return Repository.get_repo_forks(self.repo_id)
703 return Repository.get_repo_forks(self.repo_id)
704
704
705 @property
705 @property
706 def parent(self):
706 def parent(self):
707 """
707 """
708 Returns fork parent
708 Returns fork parent
709 """
709 """
710 return self.fork
710 return self.fork
711
711
712 @property
712 @property
713 def just_name(self):
713 def just_name(self):
714 return self.repo_name.split(Repository.url_sep())[-1]
714 return self.repo_name.split(Repository.url_sep())[-1]
715
715
716 @property
716 @property
717 def groups_with_parents(self):
717 def groups_with_parents(self):
718 groups = []
718 groups = []
719 if self.group is None:
719 if self.group is None:
720 return groups
720 return groups
721
721
722 cur_gr = self.group
722 cur_gr = self.group
723 groups.insert(0, cur_gr)
723 groups.insert(0, cur_gr)
724 while 1:
724 while 1:
725 gr = getattr(cur_gr, 'parent_group', None)
725 gr = getattr(cur_gr, 'parent_group', None)
726 cur_gr = cur_gr.parent_group
726 cur_gr = cur_gr.parent_group
727 if gr is None:
727 if gr is None:
728 break
728 break
729 groups.insert(0, gr)
729 groups.insert(0, gr)
730
730
731 return groups
731 return groups
732
732
733 @property
733 @property
734 def groups_and_repo(self):
734 def groups_and_repo(self):
735 return self.groups_with_parents, self.just_name
735 return self.groups_with_parents, self.just_name
736
736
737 @LazyProperty
737 @LazyProperty
738 def repo_path(self):
738 def repo_path(self):
739 """
739 """
740 Returns base full path for that repository means where it actually
740 Returns base full path for that repository means where it actually
741 exists on a filesystem
741 exists on a filesystem
742 """
742 """
743 q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
743 q = Session().query(RhodeCodeUi).filter(RhodeCodeUi.ui_key ==
744 Repository.url_sep())
744 Repository.url_sep())
745 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
745 q = q.options(FromCache("sql_cache_short", "repository_repo_path"))
746 return q.one().ui_value
746 return q.one().ui_value
747
747
748 @property
748 @property
749 def repo_full_path(self):
749 def repo_full_path(self):
750 p = [self.repo_path]
750 p = [self.repo_path]
751 # we need to split the name by / since this is how we store the
751 # we need to split the name by / since this is how we store the
752 # names in the database, but that eventually needs to be converted
752 # names in the database, but that eventually needs to be converted
753 # into a valid system path
753 # into a valid system path
754 p += self.repo_name.split(Repository.url_sep())
754 p += self.repo_name.split(Repository.url_sep())
755 return os.path.join(*p)
755 return os.path.join(*p)
756
756
757 @property
757 @property
758 def cache_keys(self):
758 def cache_keys(self):
759 """
759 """
760 Returns associated cache keys for that repo
760 Returns associated cache keys for that repo
761 """
761 """
762 return CacheInvalidation.query()\
762 return CacheInvalidation.query()\
763 .filter(CacheInvalidation.cache_args == self.repo_name)\
763 .filter(CacheInvalidation.cache_args == self.repo_name)\
764 .order_by(CacheInvalidation.cache_key)\
764 .order_by(CacheInvalidation.cache_key)\
765 .all()
765 .all()
766
766
767 def get_new_name(self, repo_name):
767 def get_new_name(self, repo_name):
768 """
768 """
769 returns new full repository name based on assigned group and new new
769 returns new full repository name based on assigned group and new new
770
770
771 :param group_name:
771 :param group_name:
772 """
772 """
773 path_prefix = self.group.full_path_splitted if self.group else []
773 path_prefix = self.group.full_path_splitted if self.group else []
774 return Repository.url_sep().join(path_prefix + [repo_name])
774 return Repository.url_sep().join(path_prefix + [repo_name])
775
775
776 @property
776 @property
777 def _ui(self):
777 def _ui(self):
778 """
778 """
779 Creates an db based ui object for this repository
779 Creates an db based ui object for this repository
780 """
780 """
781 from rhodecode.lib.utils import make_ui
781 from rhodecode.lib.utils import make_ui
782 return make_ui('db', clear_session=False)
782 return make_ui('db', clear_session=False)
783
783
784 @classmethod
784 @classmethod
785 def inject_ui(cls, repo, extras={}):
785 def inject_ui(cls, repo, extras={}):
786 from rhodecode.lib.vcs.backends.hg import MercurialRepository
786 from rhodecode.lib.vcs.backends.hg import MercurialRepository
787 from rhodecode.lib.vcs.backends.git import GitRepository
787 from rhodecode.lib.vcs.backends.git import GitRepository
788 required = (MercurialRepository, GitRepository)
788 required = (MercurialRepository, GitRepository)
789 if not isinstance(repo, required):
789 if not isinstance(repo, required):
790 raise Exception('repo must be instance of %s' % required)
790 raise Exception('repo must be instance of %s' % required)
791
791
792 # inject ui extra param to log this action via push logger
792 # inject ui extra param to log this action via push logger
793 for k, v in extras.items():
793 for k, v in extras.items():
794 repo._repo.ui.setconfig('rhodecode_extras', k, v)
794 repo._repo.ui.setconfig('rhodecode_extras', k, v)
795
795
796 @classmethod
796 @classmethod
797 def is_valid(cls, repo_name):
797 def is_valid(cls, repo_name):
798 """
798 """
799 returns True if given repo name is a valid filesystem repository
799 returns True if given repo name is a valid filesystem repository
800
800
801 :param cls:
801 :param cls:
802 :param repo_name:
802 :param repo_name:
803 """
803 """
804 from rhodecode.lib.utils import is_valid_repo
804 from rhodecode.lib.utils import is_valid_repo
805
805
806 return is_valid_repo(repo_name, cls.base_path())
806 return is_valid_repo(repo_name, cls.base_path())
807
807
808 def get_api_data(self):
808 def get_api_data(self):
809 """
809 """
810 Common function for generating repo api data
810 Common function for generating repo api data
811
811
812 """
812 """
813 repo = self
813 repo = self
814 data = dict(
814 data = dict(
815 repo_id=repo.repo_id,
815 repo_id=repo.repo_id,
816 repo_name=repo.repo_name,
816 repo_name=repo.repo_name,
817 repo_type=repo.repo_type,
817 repo_type=repo.repo_type,
818 clone_uri=repo.clone_uri,
818 clone_uri=repo.clone_uri,
819 private=repo.private,
819 private=repo.private,
820 created_on=repo.created_on,
820 created_on=repo.created_on,
821 description=repo.description,
821 description=repo.description,
822 landing_rev=repo.landing_rev,
822 landing_rev=repo.landing_rev,
823 owner=repo.user.username,
823 owner=repo.user.username,
824 fork_of=repo.fork.repo_name if repo.fork else None
824 fork_of=repo.fork.repo_name if repo.fork else None
825 )
825 )
826
826
827 return data
827 return data
828
828
829 @classmethod
829 @classmethod
830 def lock(cls, repo, user_id):
830 def lock(cls, repo, user_id):
831 repo.locked = [user_id, time.time()]
831 repo.locked = [user_id, time.time()]
832 Session().add(repo)
832 Session().add(repo)
833 Session().commit()
833 Session().commit()
834
834
835 @classmethod
835 @classmethod
836 def unlock(cls, repo):
836 def unlock(cls, repo):
837 repo.locked = None
837 repo.locked = None
838 Session().add(repo)
838 Session().add(repo)
839 Session().commit()
839 Session().commit()
840
840
841 @property
841 @property
842 def last_db_change(self):
842 def last_db_change(self):
843 return self.updated_on
843 return self.updated_on
844
844
845 #==========================================================================
845 #==========================================================================
846 # SCM PROPERTIES
846 # SCM PROPERTIES
847 #==========================================================================
847 #==========================================================================
848
848
849 def get_changeset(self, rev=None):
849 def get_changeset(self, rev=None):
850 return get_changeset_safe(self.scm_instance, rev)
850 return get_changeset_safe(self.scm_instance, rev)
851
851
852 def get_landing_changeset(self):
852 def get_landing_changeset(self):
853 """
853 """
854 Returns landing changeset, or if that doesn't exist returns the tip
854 Returns landing changeset, or if that doesn't exist returns the tip
855 """
855 """
856 cs = self.get_changeset(self.landing_rev) or self.get_changeset()
856 cs = self.get_changeset(self.landing_rev) or self.get_changeset()
857 return cs
857 return cs
858
858
859 def update_last_change(self, last_change=None):
859 def update_last_change(self, last_change=None):
860 if last_change is None:
860 if last_change is None:
861 last_change = datetime.datetime.now()
861 last_change = datetime.datetime.now()
862 if self.updated_on is None or self.updated_on != last_change:
862 if self.updated_on is None or self.updated_on != last_change:
863 log.debug('updated repo %s with new date %s' % (self, last_change))
863 log.debug('updated repo %s with new date %s' % (self, last_change))
864 self.updated_on = last_change
864 self.updated_on = last_change
865 Session().add(self)
865 Session().add(self)
866 Session().commit()
866 Session().commit()
867
867
868 @property
868 @property
869 def tip(self):
869 def tip(self):
870 return self.get_changeset('tip')
870 return self.get_changeset('tip')
871
871
872 @property
872 @property
873 def author(self):
873 def author(self):
874 return self.tip.author
874 return self.tip.author
875
875
876 @property
876 @property
877 def last_change(self):
877 def last_change(self):
878 return self.scm_instance.last_change
878 return self.scm_instance.last_change
879
879
880 def get_comments(self, revisions=None):
880 def get_comments(self, revisions=None):
881 """
881 """
882 Returns comments for this repository grouped by revisions
882 Returns comments for this repository grouped by revisions
883
883
884 :param revisions: filter query by revisions only
884 :param revisions: filter query by revisions only
885 """
885 """
886 cmts = ChangesetComment.query()\
886 cmts = ChangesetComment.query()\
887 .filter(ChangesetComment.repo == self)
887 .filter(ChangesetComment.repo == self)
888 if revisions:
888 if revisions:
889 cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
889 cmts = cmts.filter(ChangesetComment.revision.in_(revisions))
890 grouped = defaultdict(list)
890 grouped = defaultdict(list)
891 for cmt in cmts.all():
891 for cmt in cmts.all():
892 grouped[cmt.revision].append(cmt)
892 grouped[cmt.revision].append(cmt)
893 return grouped
893 return grouped
894
894
895 def statuses(self, revisions=None):
895 def statuses(self, revisions=None):
896 """
896 """
897 Returns statuses for this repository
897 Returns statuses for this repository
898
898
899 :param revisions: list of revisions to get statuses for
899 :param revisions: list of revisions to get statuses for
900 :type revisions: list
900 :type revisions: list
901 """
901 """
902
902
903 statuses = ChangesetStatus.query()\
903 statuses = ChangesetStatus.query()\
904 .filter(ChangesetStatus.repo == self)\
904 .filter(ChangesetStatus.repo == self)\
905 .filter(ChangesetStatus.version == 0)
905 .filter(ChangesetStatus.version == 0)
906 if revisions:
906 if revisions:
907 statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
907 statuses = statuses.filter(ChangesetStatus.revision.in_(revisions))
908 grouped = {}
908 grouped = {}
909
909
910 #maybe we have open new pullrequest without a status ?
910 #maybe we have open new pullrequest without a status ?
911 stat = ChangesetStatus.STATUS_UNDER_REVIEW
911 stat = ChangesetStatus.STATUS_UNDER_REVIEW
912 status_lbl = ChangesetStatus.get_status_lbl(stat)
912 status_lbl = ChangesetStatus.get_status_lbl(stat)
913 for pr in PullRequest.query().filter(PullRequest.org_repo == self).all():
913 for pr in PullRequest.query().filter(PullRequest.org_repo == self).all():
914 for rev in pr.revisions:
914 for rev in pr.revisions:
915 pr_id = pr.pull_request_id
915 pr_id = pr.pull_request_id
916 pr_repo = pr.other_repo.repo_name
916 pr_repo = pr.other_repo.repo_name
917 grouped[rev] = [stat, status_lbl, pr_id, pr_repo]
917 grouped[rev] = [stat, status_lbl, pr_id, pr_repo]
918
918
919 for stat in statuses.all():
919 for stat in statuses.all():
920 pr_id = pr_repo = None
920 pr_id = pr_repo = None
921 if stat.pull_request:
921 if stat.pull_request:
922 pr_id = stat.pull_request.pull_request_id
922 pr_id = stat.pull_request.pull_request_id
923 pr_repo = stat.pull_request.other_repo.repo_name
923 pr_repo = stat.pull_request.other_repo.repo_name
924 grouped[stat.revision] = [str(stat.status), stat.status_lbl,
924 grouped[stat.revision] = [str(stat.status), stat.status_lbl,
925 pr_id, pr_repo]
925 pr_id, pr_repo]
926 return grouped
926 return grouped
927
927
928 #==========================================================================
928 #==========================================================================
929 # SCM CACHE INSTANCE
929 # SCM CACHE INSTANCE
930 #==========================================================================
930 #==========================================================================
931
931
932 @property
932 @property
933 def invalidate(self):
933 def invalidate(self):
934 return CacheInvalidation.invalidate(self.repo_name)
934 return CacheInvalidation.invalidate(self.repo_name)
935
935
936 def set_invalidate(self):
936 def set_invalidate(self):
937 """
937 """
938 set a cache for invalidation for this instance
938 set a cache for invalidation for this instance
939 """
939 """
940 CacheInvalidation.set_invalidate(self.repo_name)
940 CacheInvalidation.set_invalidate(repo_name=self.repo_name)
941
941
942 @LazyProperty
942 @LazyProperty
943 def scm_instance(self):
943 def scm_instance(self):
944 return self.scm_instance_cached()
944 return self.scm_instance_cached()
945 return self.__get_instance()
945 return self.__get_instance()
946
946
947 def scm_instance_cached(self, cache_map=None):
947 def scm_instance_cached(self, cache_map=None):
948 @cache_region('long_term')
948 @cache_region('long_term')
949 def _c(repo_name):
949 def _c(repo_name):
950 return self.__get_instance()
950 return self.__get_instance()
951 rn = self.repo_name
951 rn = self.repo_name
952 log.debug('Getting cached instance of repo')
952 log.debug('Getting cached instance of repo')
953
953
954 if cache_map:
954 if cache_map:
955 # get using prefilled cache_map
955 # get using prefilled cache_map
956 invalidate_repo = cache_map[self.repo_name]
956 invalidate_repo = cache_map[self.repo_name]
957 if invalidate_repo:
957 if invalidate_repo:
958 invalidate_repo = (None if invalidate_repo.cache_active
958 invalidate_repo = (None if invalidate_repo.cache_active
959 else invalidate_repo)
959 else invalidate_repo)
960 else:
960 else:
961 # get from invalidate
961 # get from invalidate
962 invalidate_repo = self.invalidate
962 invalidate_repo = self.invalidate
963
963
964 if invalidate_repo is not None:
964 if invalidate_repo is not None:
965 region_invalidate(_c, None, rn)
965 region_invalidate(_c, None, rn)
966 # update our cache
966 # update our cache
967 CacheInvalidation.set_valid(invalidate_repo.cache_key)
967 CacheInvalidation.set_valid(invalidate_repo.cache_key)
968 return _c(rn)
968 return _c(rn)
969
969
970 def __get_instance(self):
970 def __get_instance(self):
971 repo_full_path = self.repo_full_path
971 repo_full_path = self.repo_full_path
972 try:
972 try:
973 alias = get_scm(repo_full_path)[0]
973 alias = get_scm(repo_full_path)[0]
974 log.debug('Creating instance of %s repository' % alias)
974 log.debug('Creating instance of %s repository' % alias)
975 backend = get_backend(alias)
975 backend = get_backend(alias)
976 except VCSError:
976 except VCSError:
977 log.error(traceback.format_exc())
977 log.error(traceback.format_exc())
978 log.error('Perhaps this repository is in db and not in '
978 log.error('Perhaps this repository is in db and not in '
979 'filesystem run rescan repositories with '
979 'filesystem run rescan repositories with '
980 '"destroy old data " option from admin panel')
980 '"destroy old data " option from admin panel')
981 return
981 return
982
982
983 if alias == 'hg':
983 if alias == 'hg':
984
984
985 repo = backend(safe_str(repo_full_path), create=False,
985 repo = backend(safe_str(repo_full_path), create=False,
986 baseui=self._ui)
986 baseui=self._ui)
987 # skip hidden web repository
987 # skip hidden web repository
988 if repo._get_hidden():
988 if repo._get_hidden():
989 return
989 return
990 else:
990 else:
991 repo = backend(repo_full_path, create=False)
991 repo = backend(repo_full_path, create=False)
992
992
993 return repo
993 return repo
994
994
995
995
996 class RepoGroup(Base, BaseModel):
996 class RepoGroup(Base, BaseModel):
997 __tablename__ = 'groups'
997 __tablename__ = 'groups'
998 __table_args__ = (
998 __table_args__ = (
999 UniqueConstraint('group_name', 'group_parent_id'),
999 UniqueConstraint('group_name', 'group_parent_id'),
1000 CheckConstraint('group_id != group_parent_id'),
1000 CheckConstraint('group_id != group_parent_id'),
1001 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1001 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1002 'mysql_charset': 'utf8'},
1002 'mysql_charset': 'utf8'},
1003 )
1003 )
1004 __mapper_args__ = {'order_by': 'group_name'}
1004 __mapper_args__ = {'order_by': 'group_name'}
1005
1005
1006 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1006 group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1007 group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
1007 group_name = Column("group_name", String(255, convert_unicode=False, assert_unicode=None), nullable=False, unique=True, default=None)
1008 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
1008 group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
1009 group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1009 group_description = Column("group_description", String(10000, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1010 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1010 enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
1011
1011
1012 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1012 repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
1013 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1013 users_group_to_perm = relationship('UsersGroupRepoGroupToPerm', cascade='all')
1014
1014
1015 parent_group = relationship('RepoGroup', remote_side=group_id)
1015 parent_group = relationship('RepoGroup', remote_side=group_id)
1016
1016
1017 def __init__(self, group_name='', parent_group=None):
1017 def __init__(self, group_name='', parent_group=None):
1018 self.group_name = group_name
1018 self.group_name = group_name
1019 self.parent_group = parent_group
1019 self.parent_group = parent_group
1020
1020
1021 def __unicode__(self):
1021 def __unicode__(self):
1022 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
1022 return u"<%s('%s:%s')>" % (self.__class__.__name__, self.group_id,
1023 self.group_name)
1023 self.group_name)
1024
1024
1025 @classmethod
1025 @classmethod
1026 def groups_choices(cls, check_perms=False):
1026 def groups_choices(cls, check_perms=False):
1027 from webhelpers.html import literal as _literal
1027 from webhelpers.html import literal as _literal
1028 from rhodecode.model.scm import ScmModel
1028 from rhodecode.model.scm import ScmModel
1029 groups = cls.query().all()
1029 groups = cls.query().all()
1030 if check_perms:
1030 if check_perms:
1031 #filter group user have access to, it's done
1031 #filter group user have access to, it's done
1032 #magically inside ScmModel based on current user
1032 #magically inside ScmModel based on current user
1033 groups = ScmModel().get_repos_groups(groups)
1033 groups = ScmModel().get_repos_groups(groups)
1034 repo_groups = [('', '')]
1034 repo_groups = [('', '')]
1035 sep = ' &raquo; '
1035 sep = ' &raquo; '
1036 _name = lambda k: _literal(sep.join(k))
1036 _name = lambda k: _literal(sep.join(k))
1037
1037
1038 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
1038 repo_groups.extend([(x.group_id, _name(x.full_path_splitted))
1039 for x in groups])
1039 for x in groups])
1040
1040
1041 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
1041 repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0])
1042 return repo_groups
1042 return repo_groups
1043
1043
1044 @classmethod
1044 @classmethod
1045 def url_sep(cls):
1045 def url_sep(cls):
1046 return URL_SEP
1046 return URL_SEP
1047
1047
1048 @classmethod
1048 @classmethod
1049 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
1049 def get_by_group_name(cls, group_name, cache=False, case_insensitive=False):
1050 if case_insensitive:
1050 if case_insensitive:
1051 gr = cls.query()\
1051 gr = cls.query()\
1052 .filter(cls.group_name.ilike(group_name))
1052 .filter(cls.group_name.ilike(group_name))
1053 else:
1053 else:
1054 gr = cls.query()\
1054 gr = cls.query()\
1055 .filter(cls.group_name == group_name)
1055 .filter(cls.group_name == group_name)
1056 if cache:
1056 if cache:
1057 gr = gr.options(FromCache(
1057 gr = gr.options(FromCache(
1058 "sql_cache_short",
1058 "sql_cache_short",
1059 "get_group_%s" % _hash_key(group_name)
1059 "get_group_%s" % _hash_key(group_name)
1060 )
1060 )
1061 )
1061 )
1062 return gr.scalar()
1062 return gr.scalar()
1063
1063
1064 @property
1064 @property
1065 def parents(self):
1065 def parents(self):
1066 parents_recursion_limit = 5
1066 parents_recursion_limit = 5
1067 groups = []
1067 groups = []
1068 if self.parent_group is None:
1068 if self.parent_group is None:
1069 return groups
1069 return groups
1070 cur_gr = self.parent_group
1070 cur_gr = self.parent_group
1071 groups.insert(0, cur_gr)
1071 groups.insert(0, cur_gr)
1072 cnt = 0
1072 cnt = 0
1073 while 1:
1073 while 1:
1074 cnt += 1
1074 cnt += 1
1075 gr = getattr(cur_gr, 'parent_group', None)
1075 gr = getattr(cur_gr, 'parent_group', None)
1076 cur_gr = cur_gr.parent_group
1076 cur_gr = cur_gr.parent_group
1077 if gr is None:
1077 if gr is None:
1078 break
1078 break
1079 if cnt == parents_recursion_limit:
1079 if cnt == parents_recursion_limit:
1080 # this will prevent accidental infinit loops
1080 # this will prevent accidental infinit loops
1081 log.error('group nested more than %s' %
1081 log.error('group nested more than %s' %
1082 parents_recursion_limit)
1082 parents_recursion_limit)
1083 break
1083 break
1084
1084
1085 groups.insert(0, gr)
1085 groups.insert(0, gr)
1086 return groups
1086 return groups
1087
1087
1088 @property
1088 @property
1089 def children(self):
1089 def children(self):
1090 return RepoGroup.query().filter(RepoGroup.parent_group == self)
1090 return RepoGroup.query().filter(RepoGroup.parent_group == self)
1091
1091
1092 @property
1092 @property
1093 def name(self):
1093 def name(self):
1094 return self.group_name.split(RepoGroup.url_sep())[-1]
1094 return self.group_name.split(RepoGroup.url_sep())[-1]
1095
1095
1096 @property
1096 @property
1097 def full_path(self):
1097 def full_path(self):
1098 return self.group_name
1098 return self.group_name
1099
1099
1100 @property
1100 @property
1101 def full_path_splitted(self):
1101 def full_path_splitted(self):
1102 return self.group_name.split(RepoGroup.url_sep())
1102 return self.group_name.split(RepoGroup.url_sep())
1103
1103
1104 @property
1104 @property
1105 def repositories(self):
1105 def repositories(self):
1106 return Repository.query()\
1106 return Repository.query()\
1107 .filter(Repository.group == self)\
1107 .filter(Repository.group == self)\
1108 .order_by(Repository.repo_name)
1108 .order_by(Repository.repo_name)
1109
1109
1110 @property
1110 @property
1111 def repositories_recursive_count(self):
1111 def repositories_recursive_count(self):
1112 cnt = self.repositories.count()
1112 cnt = self.repositories.count()
1113
1113
1114 def children_count(group):
1114 def children_count(group):
1115 cnt = 0
1115 cnt = 0
1116 for child in group.children:
1116 for child in group.children:
1117 cnt += child.repositories.count()
1117 cnt += child.repositories.count()
1118 cnt += children_count(child)
1118 cnt += children_count(child)
1119 return cnt
1119 return cnt
1120
1120
1121 return cnt + children_count(self)
1121 return cnt + children_count(self)
1122
1122
1123 def recursive_groups_and_repos(self):
1123 def recursive_groups_and_repos(self):
1124 """
1124 """
1125 Recursive return all groups, with repositories in those groups
1125 Recursive return all groups, with repositories in those groups
1126 """
1126 """
1127 all_ = []
1127 all_ = []
1128
1128
1129 def _get_members(root_gr):
1129 def _get_members(root_gr):
1130 for r in root_gr.repositories:
1130 for r in root_gr.repositories:
1131 all_.append(r)
1131 all_.append(r)
1132 childs = root_gr.children.all()
1132 childs = root_gr.children.all()
1133 if childs:
1133 if childs:
1134 for gr in childs:
1134 for gr in childs:
1135 all_.append(gr)
1135 all_.append(gr)
1136 _get_members(gr)
1136 _get_members(gr)
1137
1137
1138 _get_members(self)
1138 _get_members(self)
1139 return [self] + all_
1139 return [self] + all_
1140
1140
1141 def get_new_name(self, group_name):
1141 def get_new_name(self, group_name):
1142 """
1142 """
1143 returns new full group name based on parent and new name
1143 returns new full group name based on parent and new name
1144
1144
1145 :param group_name:
1145 :param group_name:
1146 """
1146 """
1147 path_prefix = (self.parent_group.full_path_splitted if
1147 path_prefix = (self.parent_group.full_path_splitted if
1148 self.parent_group else [])
1148 self.parent_group else [])
1149 return RepoGroup.url_sep().join(path_prefix + [group_name])
1149 return RepoGroup.url_sep().join(path_prefix + [group_name])
1150
1150
1151
1151
1152 class Permission(Base, BaseModel):
1152 class Permission(Base, BaseModel):
1153 __tablename__ = 'permissions'
1153 __tablename__ = 'permissions'
1154 __table_args__ = (
1154 __table_args__ = (
1155 Index('p_perm_name_idx', 'permission_name'),
1155 Index('p_perm_name_idx', 'permission_name'),
1156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1156 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1157 'mysql_charset': 'utf8'},
1157 'mysql_charset': 'utf8'},
1158 )
1158 )
1159 PERMS = [
1159 PERMS = [
1160 ('repository.none', _('Repository no access')),
1160 ('repository.none', _('Repository no access')),
1161 ('repository.read', _('Repository read access')),
1161 ('repository.read', _('Repository read access')),
1162 ('repository.write', _('Repository write access')),
1162 ('repository.write', _('Repository write access')),
1163 ('repository.admin', _('Repository admin access')),
1163 ('repository.admin', _('Repository admin access')),
1164
1164
1165 ('group.none', _('Repositories Group no access')),
1165 ('group.none', _('Repositories Group no access')),
1166 ('group.read', _('Repositories Group read access')),
1166 ('group.read', _('Repositories Group read access')),
1167 ('group.write', _('Repositories Group write access')),
1167 ('group.write', _('Repositories Group write access')),
1168 ('group.admin', _('Repositories Group admin access')),
1168 ('group.admin', _('Repositories Group admin access')),
1169
1169
1170 ('hg.admin', _('RhodeCode Administrator')),
1170 ('hg.admin', _('RhodeCode Administrator')),
1171 ('hg.create.none', _('Repository creation disabled')),
1171 ('hg.create.none', _('Repository creation disabled')),
1172 ('hg.create.repository', _('Repository creation enabled')),
1172 ('hg.create.repository', _('Repository creation enabled')),
1173 ('hg.fork.none', _('Repository forking disabled')),
1173 ('hg.fork.none', _('Repository forking disabled')),
1174 ('hg.fork.repository', _('Repository forking enabled')),
1174 ('hg.fork.repository', _('Repository forking enabled')),
1175 ('hg.register.none', _('Register disabled')),
1175 ('hg.register.none', _('Register disabled')),
1176 ('hg.register.manual_activate', _('Register new user with RhodeCode '
1176 ('hg.register.manual_activate', _('Register new user with RhodeCode '
1177 'with manual activation')),
1177 'with manual activation')),
1178
1178
1179 ('hg.register.auto_activate', _('Register new user with RhodeCode '
1179 ('hg.register.auto_activate', _('Register new user with RhodeCode '
1180 'with auto activation')),
1180 'with auto activation')),
1181 ]
1181 ]
1182
1182
1183 # defines which permissions are more important higher the more important
1183 # defines which permissions are more important higher the more important
1184 PERM_WEIGHTS = {
1184 PERM_WEIGHTS = {
1185 'repository.none': 0,
1185 'repository.none': 0,
1186 'repository.read': 1,
1186 'repository.read': 1,
1187 'repository.write': 3,
1187 'repository.write': 3,
1188 'repository.admin': 4,
1188 'repository.admin': 4,
1189
1189
1190 'group.none': 0,
1190 'group.none': 0,
1191 'group.read': 1,
1191 'group.read': 1,
1192 'group.write': 3,
1192 'group.write': 3,
1193 'group.admin': 4,
1193 'group.admin': 4,
1194
1194
1195 'hg.fork.none': 0,
1195 'hg.fork.none': 0,
1196 'hg.fork.repository': 1,
1196 'hg.fork.repository': 1,
1197 'hg.create.none': 0,
1197 'hg.create.none': 0,
1198 'hg.create.repository':1
1198 'hg.create.repository':1
1199 }
1199 }
1200
1200
1201 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1201 permission_id = Column("permission_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1202 permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1202 permission_name = Column("permission_name", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1203 permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1203 permission_longname = Column("permission_longname", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1204
1204
1205 def __unicode__(self):
1205 def __unicode__(self):
1206 return u"<%s('%s:%s')>" % (
1206 return u"<%s('%s:%s')>" % (
1207 self.__class__.__name__, self.permission_id, self.permission_name
1207 self.__class__.__name__, self.permission_id, self.permission_name
1208 )
1208 )
1209
1209
1210 @classmethod
1210 @classmethod
1211 def get_by_key(cls, key):
1211 def get_by_key(cls, key):
1212 return cls.query().filter(cls.permission_name == key).scalar()
1212 return cls.query().filter(cls.permission_name == key).scalar()
1213
1213
1214 @classmethod
1214 @classmethod
1215 def get_default_perms(cls, default_user_id):
1215 def get_default_perms(cls, default_user_id):
1216 q = Session().query(UserRepoToPerm, Repository, cls)\
1216 q = Session().query(UserRepoToPerm, Repository, cls)\
1217 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
1217 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
1218 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
1218 .join((cls, UserRepoToPerm.permission_id == cls.permission_id))\
1219 .filter(UserRepoToPerm.user_id == default_user_id)
1219 .filter(UserRepoToPerm.user_id == default_user_id)
1220
1220
1221 return q.all()
1221 return q.all()
1222
1222
1223 @classmethod
1223 @classmethod
1224 def get_default_group_perms(cls, default_user_id):
1224 def get_default_group_perms(cls, default_user_id):
1225 q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
1225 q = Session().query(UserRepoGroupToPerm, RepoGroup, cls)\
1226 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
1226 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
1227 .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
1227 .join((cls, UserRepoGroupToPerm.permission_id == cls.permission_id))\
1228 .filter(UserRepoGroupToPerm.user_id == default_user_id)
1228 .filter(UserRepoGroupToPerm.user_id == default_user_id)
1229
1229
1230 return q.all()
1230 return q.all()
1231
1231
1232
1232
1233 class UserRepoToPerm(Base, BaseModel):
1233 class UserRepoToPerm(Base, BaseModel):
1234 __tablename__ = 'repo_to_perm'
1234 __tablename__ = 'repo_to_perm'
1235 __table_args__ = (
1235 __table_args__ = (
1236 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
1236 UniqueConstraint('user_id', 'repository_id', 'permission_id'),
1237 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1237 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1238 'mysql_charset': 'utf8'}
1238 'mysql_charset': 'utf8'}
1239 )
1239 )
1240 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1240 repo_to_perm_id = Column("repo_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1241 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1241 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1242 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1242 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1243 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1243 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1244
1244
1245 user = relationship('User')
1245 user = relationship('User')
1246 repository = relationship('Repository')
1246 repository = relationship('Repository')
1247 permission = relationship('Permission')
1247 permission = relationship('Permission')
1248
1248
1249 @classmethod
1249 @classmethod
1250 def create(cls, user, repository, permission):
1250 def create(cls, user, repository, permission):
1251 n = cls()
1251 n = cls()
1252 n.user = user
1252 n.user = user
1253 n.repository = repository
1253 n.repository = repository
1254 n.permission = permission
1254 n.permission = permission
1255 Session().add(n)
1255 Session().add(n)
1256 return n
1256 return n
1257
1257
1258 def __unicode__(self):
1258 def __unicode__(self):
1259 return u'<user:%s => %s >' % (self.user, self.repository)
1259 return u'<user:%s => %s >' % (self.user, self.repository)
1260
1260
1261
1261
1262 class UserToPerm(Base, BaseModel):
1262 class UserToPerm(Base, BaseModel):
1263 __tablename__ = 'user_to_perm'
1263 __tablename__ = 'user_to_perm'
1264 __table_args__ = (
1264 __table_args__ = (
1265 UniqueConstraint('user_id', 'permission_id'),
1265 UniqueConstraint('user_id', 'permission_id'),
1266 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1266 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1267 'mysql_charset': 'utf8'}
1267 'mysql_charset': 'utf8'}
1268 )
1268 )
1269 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1269 user_to_perm_id = Column("user_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1270 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1270 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1271 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1271 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1272
1272
1273 user = relationship('User')
1273 user = relationship('User')
1274 permission = relationship('Permission', lazy='joined')
1274 permission = relationship('Permission', lazy='joined')
1275
1275
1276
1276
1277 class UsersGroupRepoToPerm(Base, BaseModel):
1277 class UsersGroupRepoToPerm(Base, BaseModel):
1278 __tablename__ = 'users_group_repo_to_perm'
1278 __tablename__ = 'users_group_repo_to_perm'
1279 __table_args__ = (
1279 __table_args__ = (
1280 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1280 UniqueConstraint('repository_id', 'users_group_id', 'permission_id'),
1281 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1281 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1282 'mysql_charset': 'utf8'}
1282 'mysql_charset': 'utf8'}
1283 )
1283 )
1284 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1284 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1285 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1285 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1286 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1286 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1287 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1287 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=None, default=None)
1288
1288
1289 users_group = relationship('UsersGroup')
1289 users_group = relationship('UsersGroup')
1290 permission = relationship('Permission')
1290 permission = relationship('Permission')
1291 repository = relationship('Repository')
1291 repository = relationship('Repository')
1292
1292
1293 @classmethod
1293 @classmethod
1294 def create(cls, users_group, repository, permission):
1294 def create(cls, users_group, repository, permission):
1295 n = cls()
1295 n = cls()
1296 n.users_group = users_group
1296 n.users_group = users_group
1297 n.repository = repository
1297 n.repository = repository
1298 n.permission = permission
1298 n.permission = permission
1299 Session().add(n)
1299 Session().add(n)
1300 return n
1300 return n
1301
1301
1302 def __unicode__(self):
1302 def __unicode__(self):
1303 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1303 return u'<userGroup:%s => %s >' % (self.users_group, self.repository)
1304
1304
1305
1305
1306 class UsersGroupToPerm(Base, BaseModel):
1306 class UsersGroupToPerm(Base, BaseModel):
1307 __tablename__ = 'users_group_to_perm'
1307 __tablename__ = 'users_group_to_perm'
1308 __table_args__ = (
1308 __table_args__ = (
1309 UniqueConstraint('users_group_id', 'permission_id',),
1309 UniqueConstraint('users_group_id', 'permission_id',),
1310 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1310 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1311 'mysql_charset': 'utf8'}
1311 'mysql_charset': 'utf8'}
1312 )
1312 )
1313 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1313 users_group_to_perm_id = Column("users_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1314 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1314 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1315 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1315 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1316
1316
1317 users_group = relationship('UsersGroup')
1317 users_group = relationship('UsersGroup')
1318 permission = relationship('Permission')
1318 permission = relationship('Permission')
1319
1319
1320
1320
1321 class UserRepoGroupToPerm(Base, BaseModel):
1321 class UserRepoGroupToPerm(Base, BaseModel):
1322 __tablename__ = 'user_repo_group_to_perm'
1322 __tablename__ = 'user_repo_group_to_perm'
1323 __table_args__ = (
1323 __table_args__ = (
1324 UniqueConstraint('user_id', 'group_id', 'permission_id'),
1324 UniqueConstraint('user_id', 'group_id', 'permission_id'),
1325 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1325 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1326 'mysql_charset': 'utf8'}
1326 'mysql_charset': 'utf8'}
1327 )
1327 )
1328
1328
1329 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1329 group_to_perm_id = Column("group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1330 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1330 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1331 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1331 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1332 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1332 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1333
1333
1334 user = relationship('User')
1334 user = relationship('User')
1335 group = relationship('RepoGroup')
1335 group = relationship('RepoGroup')
1336 permission = relationship('Permission')
1336 permission = relationship('Permission')
1337
1337
1338
1338
1339 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1339 class UsersGroupRepoGroupToPerm(Base, BaseModel):
1340 __tablename__ = 'users_group_repo_group_to_perm'
1340 __tablename__ = 'users_group_repo_group_to_perm'
1341 __table_args__ = (
1341 __table_args__ = (
1342 UniqueConstraint('users_group_id', 'group_id'),
1342 UniqueConstraint('users_group_id', 'group_id'),
1343 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1343 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1344 'mysql_charset': 'utf8'}
1344 'mysql_charset': 'utf8'}
1345 )
1345 )
1346
1346
1347 users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1347 users_group_repo_group_to_perm_id = Column("users_group_repo_group_to_perm_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1348 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1348 users_group_id = Column("users_group_id", Integer(), ForeignKey('users_groups.users_group_id'), nullable=False, unique=None, default=None)
1349 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1349 group_id = Column("group_id", Integer(), ForeignKey('groups.group_id'), nullable=False, unique=None, default=None)
1350 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1350 permission_id = Column("permission_id", Integer(), ForeignKey('permissions.permission_id'), nullable=False, unique=None, default=None)
1351
1351
1352 users_group = relationship('UsersGroup')
1352 users_group = relationship('UsersGroup')
1353 permission = relationship('Permission')
1353 permission = relationship('Permission')
1354 group = relationship('RepoGroup')
1354 group = relationship('RepoGroup')
1355
1355
1356
1356
1357 class Statistics(Base, BaseModel):
1357 class Statistics(Base, BaseModel):
1358 __tablename__ = 'statistics'
1358 __tablename__ = 'statistics'
1359 __table_args__ = (
1359 __table_args__ = (
1360 UniqueConstraint('repository_id'),
1360 UniqueConstraint('repository_id'),
1361 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1361 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1362 'mysql_charset': 'utf8'}
1362 'mysql_charset': 'utf8'}
1363 )
1363 )
1364 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1364 stat_id = Column("stat_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1365 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1365 repository_id = Column("repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=False, unique=True, default=None)
1366 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1366 stat_on_revision = Column("stat_on_revision", Integer(), nullable=False)
1367 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1367 commit_activity = Column("commit_activity", LargeBinary(1000000), nullable=False)#JSON data
1368 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1368 commit_activity_combined = Column("commit_activity_combined", LargeBinary(), nullable=False)#JSON data
1369 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1369 languages = Column("languages", LargeBinary(1000000), nullable=False)#JSON data
1370
1370
1371 repository = relationship('Repository', single_parent=True)
1371 repository = relationship('Repository', single_parent=True)
1372
1372
1373
1373
1374 class UserFollowing(Base, BaseModel):
1374 class UserFollowing(Base, BaseModel):
1375 __tablename__ = 'user_followings'
1375 __tablename__ = 'user_followings'
1376 __table_args__ = (
1376 __table_args__ = (
1377 UniqueConstraint('user_id', 'follows_repository_id'),
1377 UniqueConstraint('user_id', 'follows_repository_id'),
1378 UniqueConstraint('user_id', 'follows_user_id'),
1378 UniqueConstraint('user_id', 'follows_user_id'),
1379 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1379 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1380 'mysql_charset': 'utf8'}
1380 'mysql_charset': 'utf8'}
1381 )
1381 )
1382
1382
1383 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1383 user_following_id = Column("user_following_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1384 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1384 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None, default=None)
1385 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1385 follows_repo_id = Column("follows_repository_id", Integer(), ForeignKey('repositories.repo_id'), nullable=True, unique=None, default=None)
1386 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1386 follows_user_id = Column("follows_user_id", Integer(), ForeignKey('users.user_id'), nullable=True, unique=None, default=None)
1387 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1387 follows_from = Column('follows_from', DateTime(timezone=False), nullable=True, unique=None, default=datetime.datetime.now)
1388
1388
1389 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1389 user = relationship('User', primaryjoin='User.user_id==UserFollowing.user_id')
1390
1390
1391 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1391 follows_user = relationship('User', primaryjoin='User.user_id==UserFollowing.follows_user_id')
1392 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1392 follows_repository = relationship('Repository', order_by='Repository.repo_name')
1393
1393
1394 @classmethod
1394 @classmethod
1395 def get_repo_followers(cls, repo_id):
1395 def get_repo_followers(cls, repo_id):
1396 return cls.query().filter(cls.follows_repo_id == repo_id)
1396 return cls.query().filter(cls.follows_repo_id == repo_id)
1397
1397
1398
1398
1399 class CacheInvalidation(Base, BaseModel):
1399 class CacheInvalidation(Base, BaseModel):
1400 __tablename__ = 'cache_invalidation'
1400 __tablename__ = 'cache_invalidation'
1401 __table_args__ = (
1401 __table_args__ = (
1402 UniqueConstraint('cache_key'),
1402 UniqueConstraint('cache_key'),
1403 Index('key_idx', 'cache_key'),
1403 Index('key_idx', 'cache_key'),
1404 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1404 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1405 'mysql_charset': 'utf8'},
1405 'mysql_charset': 'utf8'},
1406 )
1406 )
1407 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1407 cache_id = Column("cache_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
1408 cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1408 cache_key = Column("cache_key", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1409 cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1409 cache_args = Column("cache_args", String(255, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
1410 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1410 cache_active = Column("cache_active", Boolean(), nullable=True, unique=None, default=False)
1411
1411
1412 def __init__(self, cache_key, cache_args=''):
1412 def __init__(self, cache_key, cache_args=''):
1413 self.cache_key = cache_key
1413 self.cache_key = cache_key
1414 self.cache_args = cache_args
1414 self.cache_args = cache_args
1415 self.cache_active = False
1415 self.cache_active = False
1416
1416
1417 def __unicode__(self):
1417 def __unicode__(self):
1418 return u"<%s('%s:%s')>" % (self.__class__.__name__,
1418 return u"<%s('%s:%s')>" % (self.__class__.__name__,
1419 self.cache_id, self.cache_key)
1419 self.cache_id, self.cache_key)
1420
1420
1421 @property
1421 @property
1422 def prefix(self):
1422 def prefix(self):
1423 _split = self.cache_key.split(self.cache_args, 1)
1423 _split = self.cache_key.split(self.cache_args, 1)
1424 if _split and len(_split) == 2:
1424 if _split and len(_split) == 2:
1425 return _split[0]
1425 return _split[0]
1426 return ''
1426 return ''
1427
1427
1428 @classmethod
1428 @classmethod
1429 def clear_cache(cls):
1429 def clear_cache(cls):
1430 cls.query().delete()
1430 cls.query().delete()
1431
1431
1432 @classmethod
1432 @classmethod
1433 def _get_key(cls, key):
1433 def _get_key(cls, key):
1434 """
1434 """
1435 Wrapper for generating a key, together with a prefix
1435 Wrapper for generating a key, together with a prefix
1436
1436
1437 :param key:
1437 :param key:
1438 """
1438 """
1439 import rhodecode
1439 import rhodecode
1440 prefix = ''
1440 prefix = ''
1441 org_key = key
1441 iid = rhodecode.CONFIG.get('instance_id')
1442 iid = rhodecode.CONFIG.get('instance_id')
1442 if iid:
1443 if iid:
1443 prefix = iid
1444 prefix = iid
1444 #remove specific suffixes like _README or _RSS
1445
1445 key = remove_suffix(key, '_README')
1446 return "%s%s" % (prefix, key), prefix, org_key
1446 key = remove_suffix(key, '_RSS')
1447 key = remove_suffix(key, '_ATOM')
1448 return "%s%s" % (prefix, key), prefix, key
1449
1447
1450 @classmethod
1448 @classmethod
1451 def get_by_key(cls, key):
1449 def get_by_key(cls, key):
1452 return cls.query().filter(cls.cache_key == key).scalar()
1450 return cls.query().filter(cls.cache_key == key).scalar()
1453
1451
1454 @classmethod
1452 @classmethod
1455 def _get_or_create_key(cls, key, prefix, org_key, commit=True):
1453 def get_by_repo_name(cls, repo_name):
1454 return cls.query().filter(cls.cache_args == repo_name).all()
1455
1456 @classmethod
1457 def _get_or_create_key(cls, key, repo_name, commit=True):
1456 inv_obj = Session().query(cls).filter(cls.cache_key == key).scalar()
1458 inv_obj = Session().query(cls).filter(cls.cache_key == key).scalar()
1457 if not inv_obj:
1459 if not inv_obj:
1458 try:
1460 try:
1459 inv_obj = CacheInvalidation(key, org_key)
1461 inv_obj = CacheInvalidation(key, repo_name)
1460 Session().add(inv_obj)
1462 Session().add(inv_obj)
1461 if commit:
1463 if commit:
1462 Session().commit()
1464 Session().commit()
1463 except Exception:
1465 except Exception:
1464 log.error(traceback.format_exc())
1466 log.error(traceback.format_exc())
1465 Session().rollback()
1467 Session().rollback()
1466 return inv_obj
1468 return inv_obj
1467
1469
1468 @classmethod
1470 @classmethod
1469 def invalidate(cls, key):
1471 def invalidate(cls, key):
1470 """
1472 """
1471 Returns Invalidation object if this given key should be invalidated
1473 Returns Invalidation object if this given key should be invalidated
1472 None otherwise. `cache_active = False` means that this cache
1474 None otherwise. `cache_active = False` means that this cache
1473 state is not valid and needs to be invalidated
1475 state is not valid and needs to be invalidated
1474
1476
1475 :param key:
1477 :param key:
1476 """
1478 """
1479 repo_name = key
1480 repo_name = remove_suffix(repo_name, '_README')
1481 repo_name = remove_suffix(repo_name, '_RSS')
1482 repo_name = remove_suffix(repo_name, '_ATOM')
1477
1483
1484 # adds instance prefix
1478 key, _prefix, _org_key = cls._get_key(key)
1485 key, _prefix, _org_key = cls._get_key(key)
1479 inv = cls._get_or_create_key(key, _prefix, _org_key)
1486 inv = cls._get_or_create_key(key, repo_name)
1480
1487
1481 if inv and inv.cache_active is False:
1488 if inv and inv.cache_active is False:
1482 return inv
1489 return inv
1483
1490
1484 @classmethod
1491 @classmethod
1485 def set_invalidate(cls, key):
1492 def set_invalidate(cls, key=None, repo_name=None):
1486 """
1493 """
1487 Mark this Cache key for invalidation
1494 Mark this Cache key for invalidation, either by key or whole
1495 cache sets based on repo_name
1488
1496
1489 :param key:
1497 :param key:
1490 """
1498 """
1491
1499 if key:
1492 key, _prefix, _org_key = cls._get_key(key)
1500 key, _prefix, _org_key = cls._get_key(key)
1493 inv_objs = Session().query(cls).filter(cls.cache_args == _org_key).all()
1501 inv_objs = Session().query(cls).filter(cls.cache_key == key).all()
1494 log.debug('marking %s key[s] %s for invalidation' % (len(inv_objs),
1502 elif repo_name:
1495 _org_key))
1503 inv_objs = Session().query(cls).filter(cls.cache_args == repo_name).all()
1504
1505 log.debug('marking %s key[s] for invalidation based on key=%s,repo_name=%s'
1506 % (len(inv_objs), key, repo_name))
1496 try:
1507 try:
1497 for inv_obj in inv_objs:
1508 for inv_obj in inv_objs:
1498 if inv_obj:
1509 print inv_obj
1499 inv_obj.cache_active = False
1510 inv_obj.cache_active = False
1500
1501 Session().add(inv_obj)
1511 Session().add(inv_obj)
1502 Session().commit()
1512 Session().commit()
1503 except Exception:
1513 except Exception:
1504 log.error(traceback.format_exc())
1514 log.error(traceback.format_exc())
1505 Session().rollback()
1515 Session().rollback()
1506
1516
1507 @classmethod
1517 @classmethod
1508 def set_valid(cls, key):
1518 def set_valid(cls, key):
1509 """
1519 """
1510 Mark this cache key as active and currently cached
1520 Mark this cache key as active and currently cached
1511
1521
1512 :param key:
1522 :param key:
1513 """
1523 """
1514 inv_obj = cls.get_by_key(key)
1524 inv_obj = cls.get_by_key(key)
1515 inv_obj.cache_active = True
1525 inv_obj.cache_active = True
1516 Session().add(inv_obj)
1526 Session().add(inv_obj)
1517 Session().commit()
1527 Session().commit()
1518
1528
1519 @classmethod
1529 @classmethod
1520 def get_cache_map(cls):
1530 def get_cache_map(cls):
1521
1531
1522 class cachemapdict(dict):
1532 class cachemapdict(dict):
1523
1533
1524 def __init__(self, *args, **kwargs):
1534 def __init__(self, *args, **kwargs):
1525 fixkey = kwargs.get('fixkey')
1535 fixkey = kwargs.get('fixkey')
1526 if fixkey:
1536 if fixkey:
1527 del kwargs['fixkey']
1537 del kwargs['fixkey']
1528 self.fixkey = fixkey
1538 self.fixkey = fixkey
1529 super(cachemapdict, self).__init__(*args, **kwargs)
1539 super(cachemapdict, self).__init__(*args, **kwargs)
1530
1540
1531 def __getattr__(self, name):
1541 def __getattr__(self, name):
1532 key = name
1542 key = name
1533 if self.fixkey:
1543 if self.fixkey:
1534 key, _prefix, _org_key = cls._get_key(key)
1544 key, _prefix, _org_key = cls._get_key(key)
1535 if key in self.__dict__:
1545 if key in self.__dict__:
1536 return self.__dict__[key]
1546 return self.__dict__[key]
1537 else:
1547 else:
1538 return self[key]
1548 return self[key]
1539
1549
1540 def __getitem__(self, key):
1550 def __getitem__(self, key):
1541 if self.fixkey:
1551 if self.fixkey:
1542 key, _prefix, _org_key = cls._get_key(key)
1552 key, _prefix, _org_key = cls._get_key(key)
1543 try:
1553 try:
1544 return super(cachemapdict, self).__getitem__(key)
1554 return super(cachemapdict, self).__getitem__(key)
1545 except KeyError:
1555 except KeyError:
1546 return
1556 return
1547
1557
1548 cache_map = cachemapdict(fixkey=True)
1558 cache_map = cachemapdict(fixkey=True)
1549 for obj in cls.query().all():
1559 for obj in cls.query().all():
1550 cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
1560 cache_map[obj.cache_key] = cachemapdict(obj.get_dict())
1551 return cache_map
1561 return cache_map
1552
1562
1553
1563
1554 class ChangesetComment(Base, BaseModel):
1564 class ChangesetComment(Base, BaseModel):
1555 __tablename__ = 'changeset_comments'
1565 __tablename__ = 'changeset_comments'
1556 __table_args__ = (
1566 __table_args__ = (
1557 Index('cc_revision_idx', 'revision'),
1567 Index('cc_revision_idx', 'revision'),
1558 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1568 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1559 'mysql_charset': 'utf8'},
1569 'mysql_charset': 'utf8'},
1560 )
1570 )
1561 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1571 comment_id = Column('comment_id', Integer(), nullable=False, primary_key=True)
1562 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1572 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1563 revision = Column('revision', String(40), nullable=True)
1573 revision = Column('revision', String(40), nullable=True)
1564 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1574 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1565 line_no = Column('line_no', Unicode(10), nullable=True)
1575 line_no = Column('line_no', Unicode(10), nullable=True)
1566 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1576 hl_lines = Column('hl_lines', Unicode(512), nullable=True)
1567 f_path = Column('f_path', Unicode(1000), nullable=True)
1577 f_path = Column('f_path', Unicode(1000), nullable=True)
1568 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1578 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), nullable=False)
1569 text = Column('text', UnicodeText(25000), nullable=False)
1579 text = Column('text', UnicodeText(25000), nullable=False)
1570 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1580 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1571 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1581 modified_at = Column('modified_at', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1572
1582
1573 author = relationship('User', lazy='joined')
1583 author = relationship('User', lazy='joined')
1574 repo = relationship('Repository')
1584 repo = relationship('Repository')
1575 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1585 status_change = relationship('ChangesetStatus', cascade="all, delete, delete-orphan")
1576 pull_request = relationship('PullRequest', lazy='joined')
1586 pull_request = relationship('PullRequest', lazy='joined')
1577
1587
1578 @classmethod
1588 @classmethod
1579 def get_users(cls, revision=None, pull_request_id=None):
1589 def get_users(cls, revision=None, pull_request_id=None):
1580 """
1590 """
1581 Returns user associated with this ChangesetComment. ie those
1591 Returns user associated with this ChangesetComment. ie those
1582 who actually commented
1592 who actually commented
1583
1593
1584 :param cls:
1594 :param cls:
1585 :param revision:
1595 :param revision:
1586 """
1596 """
1587 q = Session().query(User)\
1597 q = Session().query(User)\
1588 .join(ChangesetComment.author)
1598 .join(ChangesetComment.author)
1589 if revision:
1599 if revision:
1590 q = q.filter(cls.revision == revision)
1600 q = q.filter(cls.revision == revision)
1591 elif pull_request_id:
1601 elif pull_request_id:
1592 q = q.filter(cls.pull_request_id == pull_request_id)
1602 q = q.filter(cls.pull_request_id == pull_request_id)
1593 return q.all()
1603 return q.all()
1594
1604
1595
1605
1596 class ChangesetStatus(Base, BaseModel):
1606 class ChangesetStatus(Base, BaseModel):
1597 __tablename__ = 'changeset_statuses'
1607 __tablename__ = 'changeset_statuses'
1598 __table_args__ = (
1608 __table_args__ = (
1599 Index('cs_revision_idx', 'revision'),
1609 Index('cs_revision_idx', 'revision'),
1600 Index('cs_version_idx', 'version'),
1610 Index('cs_version_idx', 'version'),
1601 UniqueConstraint('repo_id', 'revision', 'version'),
1611 UniqueConstraint('repo_id', 'revision', 'version'),
1602 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1612 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1603 'mysql_charset': 'utf8'}
1613 'mysql_charset': 'utf8'}
1604 )
1614 )
1605 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1615 STATUS_NOT_REVIEWED = DEFAULT = 'not_reviewed'
1606 STATUS_APPROVED = 'approved'
1616 STATUS_APPROVED = 'approved'
1607 STATUS_REJECTED = 'rejected'
1617 STATUS_REJECTED = 'rejected'
1608 STATUS_UNDER_REVIEW = 'under_review'
1618 STATUS_UNDER_REVIEW = 'under_review'
1609
1619
1610 STATUSES = [
1620 STATUSES = [
1611 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1621 (STATUS_NOT_REVIEWED, _("Not Reviewed")), # (no icon) and default
1612 (STATUS_APPROVED, _("Approved")),
1622 (STATUS_APPROVED, _("Approved")),
1613 (STATUS_REJECTED, _("Rejected")),
1623 (STATUS_REJECTED, _("Rejected")),
1614 (STATUS_UNDER_REVIEW, _("Under Review")),
1624 (STATUS_UNDER_REVIEW, _("Under Review")),
1615 ]
1625 ]
1616
1626
1617 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1627 changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
1618 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1628 repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1619 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1629 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1620 revision = Column('revision', String(40), nullable=False)
1630 revision = Column('revision', String(40), nullable=False)
1621 status = Column('status', String(128), nullable=False, default=DEFAULT)
1631 status = Column('status', String(128), nullable=False, default=DEFAULT)
1622 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1632 changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
1623 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1633 modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
1624 version = Column('version', Integer(), nullable=False, default=0)
1634 version = Column('version', Integer(), nullable=False, default=0)
1625 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1635 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
1626
1636
1627 author = relationship('User', lazy='joined')
1637 author = relationship('User', lazy='joined')
1628 repo = relationship('Repository')
1638 repo = relationship('Repository')
1629 comment = relationship('ChangesetComment', lazy='joined')
1639 comment = relationship('ChangesetComment', lazy='joined')
1630 pull_request = relationship('PullRequest', lazy='joined')
1640 pull_request = relationship('PullRequest', lazy='joined')
1631
1641
1632 def __unicode__(self):
1642 def __unicode__(self):
1633 return u"<%s('%s:%s')>" % (
1643 return u"<%s('%s:%s')>" % (
1634 self.__class__.__name__,
1644 self.__class__.__name__,
1635 self.status, self.author
1645 self.status, self.author
1636 )
1646 )
1637
1647
1638 @classmethod
1648 @classmethod
1639 def get_status_lbl(cls, value):
1649 def get_status_lbl(cls, value):
1640 return dict(cls.STATUSES).get(value)
1650 return dict(cls.STATUSES).get(value)
1641
1651
1642 @property
1652 @property
1643 def status_lbl(self):
1653 def status_lbl(self):
1644 return ChangesetStatus.get_status_lbl(self.status)
1654 return ChangesetStatus.get_status_lbl(self.status)
1645
1655
1646
1656
1647 class PullRequest(Base, BaseModel):
1657 class PullRequest(Base, BaseModel):
1648 __tablename__ = 'pull_requests'
1658 __tablename__ = 'pull_requests'
1649 __table_args__ = (
1659 __table_args__ = (
1650 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1660 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1651 'mysql_charset': 'utf8'},
1661 'mysql_charset': 'utf8'},
1652 )
1662 )
1653
1663
1654 STATUS_NEW = u'new'
1664 STATUS_NEW = u'new'
1655 STATUS_OPEN = u'open'
1665 STATUS_OPEN = u'open'
1656 STATUS_CLOSED = u'closed'
1666 STATUS_CLOSED = u'closed'
1657
1667
1658 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1668 pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
1659 title = Column('title', Unicode(256), nullable=True)
1669 title = Column('title', Unicode(256), nullable=True)
1660 description = Column('description', UnicodeText(10240), nullable=True)
1670 description = Column('description', UnicodeText(10240), nullable=True)
1661 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1671 status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW)
1662 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1672 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1663 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1673 updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1664 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1674 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
1665 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1675 _revisions = Column('revisions', UnicodeText(20500)) # 500 revisions max
1666 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1676 org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1667 org_ref = Column('org_ref', Unicode(256), nullable=False)
1677 org_ref = Column('org_ref', Unicode(256), nullable=False)
1668 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1678 other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
1669 other_ref = Column('other_ref', Unicode(256), nullable=False)
1679 other_ref = Column('other_ref', Unicode(256), nullable=False)
1670
1680
1671 @hybrid_property
1681 @hybrid_property
1672 def revisions(self):
1682 def revisions(self):
1673 return self._revisions.split(':')
1683 return self._revisions.split(':')
1674
1684
1675 @revisions.setter
1685 @revisions.setter
1676 def revisions(self, val):
1686 def revisions(self, val):
1677 self._revisions = ':'.join(val)
1687 self._revisions = ':'.join(val)
1678
1688
1679 author = relationship('User', lazy='joined')
1689 author = relationship('User', lazy='joined')
1680 reviewers = relationship('PullRequestReviewers',
1690 reviewers = relationship('PullRequestReviewers',
1681 cascade="all, delete, delete-orphan")
1691 cascade="all, delete, delete-orphan")
1682 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1692 org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
1683 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1693 other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
1684 statuses = relationship('ChangesetStatus')
1694 statuses = relationship('ChangesetStatus')
1685 comments = relationship('ChangesetComment',
1695 comments = relationship('ChangesetComment',
1686 cascade="all, delete, delete-orphan")
1696 cascade="all, delete, delete-orphan")
1687
1697
1688 def is_closed(self):
1698 def is_closed(self):
1689 return self.status == self.STATUS_CLOSED
1699 return self.status == self.STATUS_CLOSED
1690
1700
1691 def __json__(self):
1701 def __json__(self):
1692 return dict(
1702 return dict(
1693 revisions=self.revisions
1703 revisions=self.revisions
1694 )
1704 )
1695
1705
1696
1706
1697 class PullRequestReviewers(Base, BaseModel):
1707 class PullRequestReviewers(Base, BaseModel):
1698 __tablename__ = 'pull_request_reviewers'
1708 __tablename__ = 'pull_request_reviewers'
1699 __table_args__ = (
1709 __table_args__ = (
1700 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1710 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1701 'mysql_charset': 'utf8'},
1711 'mysql_charset': 'utf8'},
1702 )
1712 )
1703
1713
1704 def __init__(self, user=None, pull_request=None):
1714 def __init__(self, user=None, pull_request=None):
1705 self.user = user
1715 self.user = user
1706 self.pull_request = pull_request
1716 self.pull_request = pull_request
1707
1717
1708 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1718 pull_requests_reviewers_id = Column('pull_requests_reviewers_id', Integer(), nullable=False, primary_key=True)
1709 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1719 pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=False)
1710 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1720 user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=True)
1711
1721
1712 user = relationship('User')
1722 user = relationship('User')
1713 pull_request = relationship('PullRequest')
1723 pull_request = relationship('PullRequest')
1714
1724
1715
1725
1716 class Notification(Base, BaseModel):
1726 class Notification(Base, BaseModel):
1717 __tablename__ = 'notifications'
1727 __tablename__ = 'notifications'
1718 __table_args__ = (
1728 __table_args__ = (
1719 Index('notification_type_idx', 'type'),
1729 Index('notification_type_idx', 'type'),
1720 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1730 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1721 'mysql_charset': 'utf8'},
1731 'mysql_charset': 'utf8'},
1722 )
1732 )
1723
1733
1724 TYPE_CHANGESET_COMMENT = u'cs_comment'
1734 TYPE_CHANGESET_COMMENT = u'cs_comment'
1725 TYPE_MESSAGE = u'message'
1735 TYPE_MESSAGE = u'message'
1726 TYPE_MENTION = u'mention'
1736 TYPE_MENTION = u'mention'
1727 TYPE_REGISTRATION = u'registration'
1737 TYPE_REGISTRATION = u'registration'
1728 TYPE_PULL_REQUEST = u'pull_request'
1738 TYPE_PULL_REQUEST = u'pull_request'
1729 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1739 TYPE_PULL_REQUEST_COMMENT = u'pull_request_comment'
1730
1740
1731 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1741 notification_id = Column('notification_id', Integer(), nullable=False, primary_key=True)
1732 subject = Column('subject', Unicode(512), nullable=True)
1742 subject = Column('subject', Unicode(512), nullable=True)
1733 body = Column('body', UnicodeText(50000), nullable=True)
1743 body = Column('body', UnicodeText(50000), nullable=True)
1734 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1744 created_by = Column("created_by", Integer(), ForeignKey('users.user_id'), nullable=True)
1735 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1745 created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
1736 type_ = Column('type', Unicode(256))
1746 type_ = Column('type', Unicode(256))
1737
1747
1738 created_by_user = relationship('User')
1748 created_by_user = relationship('User')
1739 notifications_to_users = relationship('UserNotification', lazy='joined',
1749 notifications_to_users = relationship('UserNotification', lazy='joined',
1740 cascade="all, delete, delete-orphan")
1750 cascade="all, delete, delete-orphan")
1741
1751
1742 @property
1752 @property
1743 def recipients(self):
1753 def recipients(self):
1744 return [x.user for x in UserNotification.query()\
1754 return [x.user for x in UserNotification.query()\
1745 .filter(UserNotification.notification == self)\
1755 .filter(UserNotification.notification == self)\
1746 .order_by(UserNotification.user_id.asc()).all()]
1756 .order_by(UserNotification.user_id.asc()).all()]
1747
1757
1748 @classmethod
1758 @classmethod
1749 def create(cls, created_by, subject, body, recipients, type_=None):
1759 def create(cls, created_by, subject, body, recipients, type_=None):
1750 if type_ is None:
1760 if type_ is None:
1751 type_ = Notification.TYPE_MESSAGE
1761 type_ = Notification.TYPE_MESSAGE
1752
1762
1753 notification = cls()
1763 notification = cls()
1754 notification.created_by_user = created_by
1764 notification.created_by_user = created_by
1755 notification.subject = subject
1765 notification.subject = subject
1756 notification.body = body
1766 notification.body = body
1757 notification.type_ = type_
1767 notification.type_ = type_
1758 notification.created_on = datetime.datetime.now()
1768 notification.created_on = datetime.datetime.now()
1759
1769
1760 for u in recipients:
1770 for u in recipients:
1761 assoc = UserNotification()
1771 assoc = UserNotification()
1762 assoc.notification = notification
1772 assoc.notification = notification
1763 u.notifications.append(assoc)
1773 u.notifications.append(assoc)
1764 Session().add(notification)
1774 Session().add(notification)
1765 return notification
1775 return notification
1766
1776
1767 @property
1777 @property
1768 def description(self):
1778 def description(self):
1769 from rhodecode.model.notification import NotificationModel
1779 from rhodecode.model.notification import NotificationModel
1770 return NotificationModel().make_description(self)
1780 return NotificationModel().make_description(self)
1771
1781
1772
1782
1773 class UserNotification(Base, BaseModel):
1783 class UserNotification(Base, BaseModel):
1774 __tablename__ = 'user_to_notification'
1784 __tablename__ = 'user_to_notification'
1775 __table_args__ = (
1785 __table_args__ = (
1776 UniqueConstraint('user_id', 'notification_id'),
1786 UniqueConstraint('user_id', 'notification_id'),
1777 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1787 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1778 'mysql_charset': 'utf8'}
1788 'mysql_charset': 'utf8'}
1779 )
1789 )
1780 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1790 user_id = Column('user_id', Integer(), ForeignKey('users.user_id'), primary_key=True)
1781 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1791 notification_id = Column("notification_id", Integer(), ForeignKey('notifications.notification_id'), primary_key=True)
1782 read = Column('read', Boolean, default=False)
1792 read = Column('read', Boolean, default=False)
1783 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1793 sent_on = Column('sent_on', DateTime(timezone=False), nullable=True, unique=None)
1784
1794
1785 user = relationship('User', lazy="joined")
1795 user = relationship('User', lazy="joined")
1786 notification = relationship('Notification', lazy="joined",
1796 notification = relationship('Notification', lazy="joined",
1787 order_by=lambda: Notification.created_on.desc(),)
1797 order_by=lambda: Notification.created_on.desc(),)
1788
1798
1789 def mark_as_read(self):
1799 def mark_as_read(self):
1790 self.read = True
1800 self.read = True
1791 Session().add(self)
1801 Session().add(self)
1792
1802
1793
1803
1794 class DbMigrateVersion(Base, BaseModel):
1804 class DbMigrateVersion(Base, BaseModel):
1795 __tablename__ = 'db_migrate_version'
1805 __tablename__ = 'db_migrate_version'
1796 __table_args__ = (
1806 __table_args__ = (
1797 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1807 {'extend_existing': True, 'mysql_engine': 'InnoDB',
1798 'mysql_charset': 'utf8'},
1808 'mysql_charset': 'utf8'},
1799 )
1809 )
1800 repository_id = Column('repository_id', String(250), primary_key=True)
1810 repository_id = Column('repository_id', String(250), primary_key=True)
1801 repository_path = Column('repository_path', Text)
1811 repository_path = Column('repository_path', Text)
1802 version = Column('version', Integer)
1812 version = Column('version', Integer)
@@ -1,618 +1,618 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.scm
3 rhodecode.model.scm
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Scm model for RhodeCode
6 Scm model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 from __future__ import with_statement
25 from __future__ import with_statement
26 import os
26 import os
27 import re
27 import re
28 import time
28 import time
29 import traceback
29 import traceback
30 import logging
30 import logging
31 import cStringIO
31 import cStringIO
32 import pkg_resources
32 import pkg_resources
33 from os.path import dirname as dn, join as jn
33 from os.path import dirname as dn, join as jn
34
34
35 from sqlalchemy import func
35 from sqlalchemy import func
36 from pylons.i18n.translation import _
36 from pylons.i18n.translation import _
37
37
38 import rhodecode
38 import rhodecode
39 from rhodecode.lib.vcs import get_backend
39 from rhodecode.lib.vcs import get_backend
40 from rhodecode.lib.vcs.exceptions import RepositoryError
40 from rhodecode.lib.vcs.exceptions import RepositoryError
41 from rhodecode.lib.vcs.utils.lazy import LazyProperty
41 from rhodecode.lib.vcs.utils.lazy import LazyProperty
42 from rhodecode.lib.vcs.nodes import FileNode
42 from rhodecode.lib.vcs.nodes import FileNode
43 from rhodecode.lib.vcs.backends.base import EmptyChangeset
43 from rhodecode.lib.vcs.backends.base import EmptyChangeset
44
44
45 from rhodecode import BACKENDS
45 from rhodecode import BACKENDS
46 from rhodecode.lib import helpers as h
46 from rhodecode.lib import helpers as h
47 from rhodecode.lib.utils2 import safe_str, safe_unicode
47 from rhodecode.lib.utils2 import safe_str, safe_unicode
48 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
48 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
49 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
49 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
50 action_logger, REMOVED_REPO_PAT
50 action_logger, REMOVED_REPO_PAT
51 from rhodecode.model import BaseModel
51 from rhodecode.model import BaseModel
52 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
52 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
53 UserFollowing, UserLog, User, RepoGroup, PullRequest
53 UserFollowing, UserLog, User, RepoGroup, PullRequest
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class UserTemp(object):
58 class UserTemp(object):
59 def __init__(self, user_id):
59 def __init__(self, user_id):
60 self.user_id = user_id
60 self.user_id = user_id
61
61
62 def __repr__(self):
62 def __repr__(self):
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
63 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
64
64
65
65
66 class RepoTemp(object):
66 class RepoTemp(object):
67 def __init__(self, repo_id):
67 def __init__(self, repo_id):
68 self.repo_id = repo_id
68 self.repo_id = repo_id
69
69
70 def __repr__(self):
70 def __repr__(self):
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
71 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
72
72
73
73
74 class CachedRepoList(object):
74 class CachedRepoList(object):
75 """
75 """
76 Cached repo list, uses in-memory cache after initialization, that is
76 Cached repo list, uses in-memory cache after initialization, that is
77 super fast
77 super fast
78 """
78 """
79
79
80 def __init__(self, db_repo_list, repos_path, order_by=None):
80 def __init__(self, db_repo_list, repos_path, order_by=None):
81 self.db_repo_list = db_repo_list
81 self.db_repo_list = db_repo_list
82 self.repos_path = repos_path
82 self.repos_path = repos_path
83 self.order_by = order_by
83 self.order_by = order_by
84 self.reversed = (order_by or '').startswith('-')
84 self.reversed = (order_by or '').startswith('-')
85
85
86 def __len__(self):
86 def __len__(self):
87 return len(self.db_repo_list)
87 return len(self.db_repo_list)
88
88
89 def __repr__(self):
89 def __repr__(self):
90 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
90 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
91
91
92 def __iter__(self):
92 def __iter__(self):
93 # pre-propagated cache_map to save executing select statements
93 # pre-propagated cache_map to save executing select statements
94 # for each repo
94 # for each repo
95 cache_map = CacheInvalidation.get_cache_map()
95 cache_map = CacheInvalidation.get_cache_map()
96
96
97 for dbr in self.db_repo_list:
97 for dbr in self.db_repo_list:
98 scmr = dbr.scm_instance_cached(cache_map)
98 scmr = dbr.scm_instance_cached(cache_map)
99 # check permission at this level
99 # check permission at this level
100 if not HasRepoPermissionAny(
100 if not HasRepoPermissionAny(
101 'repository.read', 'repository.write', 'repository.admin'
101 'repository.read', 'repository.write', 'repository.admin'
102 )(dbr.repo_name, 'get repo check'):
102 )(dbr.repo_name, 'get repo check'):
103 continue
103 continue
104
104
105 if scmr is None:
105 if scmr is None:
106 log.error(
106 log.error(
107 '%s this repository is present in database but it '
107 '%s this repository is present in database but it '
108 'cannot be created as an scm instance' % dbr.repo_name
108 'cannot be created as an scm instance' % dbr.repo_name
109 )
109 )
110 continue
110 continue
111
111
112 last_change = scmr.last_change
112 last_change = scmr.last_change
113 tip = h.get_changeset_safe(scmr, 'tip')
113 tip = h.get_changeset_safe(scmr, 'tip')
114
114
115 tmp_d = {}
115 tmp_d = {}
116 tmp_d['name'] = dbr.repo_name
116 tmp_d['name'] = dbr.repo_name
117 tmp_d['name_sort'] = tmp_d['name'].lower()
117 tmp_d['name_sort'] = tmp_d['name'].lower()
118 tmp_d['raw_name'] = tmp_d['name'].lower()
118 tmp_d['raw_name'] = tmp_d['name'].lower()
119 tmp_d['description'] = dbr.description
119 tmp_d['description'] = dbr.description
120 tmp_d['description_sort'] = tmp_d['description'].lower()
120 tmp_d['description_sort'] = tmp_d['description'].lower()
121 tmp_d['last_change'] = last_change
121 tmp_d['last_change'] = last_change
122 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
122 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
123 tmp_d['tip'] = tip.raw_id
123 tmp_d['tip'] = tip.raw_id
124 tmp_d['tip_sort'] = tip.revision
124 tmp_d['tip_sort'] = tip.revision
125 tmp_d['rev'] = tip.revision
125 tmp_d['rev'] = tip.revision
126 tmp_d['contact'] = dbr.user.full_contact
126 tmp_d['contact'] = dbr.user.full_contact
127 tmp_d['contact_sort'] = tmp_d['contact']
127 tmp_d['contact_sort'] = tmp_d['contact']
128 tmp_d['owner_sort'] = tmp_d['contact']
128 tmp_d['owner_sort'] = tmp_d['contact']
129 tmp_d['repo_archives'] = list(scmr._get_archives())
129 tmp_d['repo_archives'] = list(scmr._get_archives())
130 tmp_d['last_msg'] = tip.message
130 tmp_d['last_msg'] = tip.message
131 tmp_d['author'] = tip.author
131 tmp_d['author'] = tip.author
132 tmp_d['dbrepo'] = dbr.get_dict()
132 tmp_d['dbrepo'] = dbr.get_dict()
133 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
133 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
134 yield tmp_d
134 yield tmp_d
135
135
136
136
137 class SimpleCachedRepoList(CachedRepoList):
137 class SimpleCachedRepoList(CachedRepoList):
138 """
138 """
139 Lighter version of CachedRepoList without the scm initialisation
139 Lighter version of CachedRepoList without the scm initialisation
140 """
140 """
141
141
142 def __iter__(self):
142 def __iter__(self):
143 for dbr in self.db_repo_list:
143 for dbr in self.db_repo_list:
144 # check permission at this level
144 # check permission at this level
145 if not HasRepoPermissionAny(
145 if not HasRepoPermissionAny(
146 'repository.read', 'repository.write', 'repository.admin'
146 'repository.read', 'repository.write', 'repository.admin'
147 )(dbr.repo_name, 'get repo check'):
147 )(dbr.repo_name, 'get repo check'):
148 continue
148 continue
149
149
150 tmp_d = {}
150 tmp_d = {}
151 tmp_d['name'] = dbr.repo_name
151 tmp_d['name'] = dbr.repo_name
152 tmp_d['name_sort'] = tmp_d['name'].lower()
152 tmp_d['name_sort'] = tmp_d['name'].lower()
153 tmp_d['raw_name'] = tmp_d['name'].lower()
153 tmp_d['raw_name'] = tmp_d['name'].lower()
154 tmp_d['description'] = dbr.description
154 tmp_d['description'] = dbr.description
155 tmp_d['description_sort'] = tmp_d['description'].lower()
155 tmp_d['description_sort'] = tmp_d['description'].lower()
156 tmp_d['dbrepo'] = dbr.get_dict()
156 tmp_d['dbrepo'] = dbr.get_dict()
157 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
157 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
158 yield tmp_d
158 yield tmp_d
159
159
160
160
161 class GroupList(object):
161 class GroupList(object):
162
162
163 def __init__(self, db_repo_group_list):
163 def __init__(self, db_repo_group_list):
164 self.db_repo_group_list = db_repo_group_list
164 self.db_repo_group_list = db_repo_group_list
165
165
166 def __len__(self):
166 def __len__(self):
167 return len(self.db_repo_group_list)
167 return len(self.db_repo_group_list)
168
168
169 def __repr__(self):
169 def __repr__(self):
170 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
170 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
171
171
172 def __iter__(self):
172 def __iter__(self):
173 for dbgr in self.db_repo_group_list:
173 for dbgr in self.db_repo_group_list:
174 # check permission at this level
174 # check permission at this level
175 if not HasReposGroupPermissionAny(
175 if not HasReposGroupPermissionAny(
176 'group.read', 'group.write', 'group.admin'
176 'group.read', 'group.write', 'group.admin'
177 )(dbgr.group_name, 'get group repo check'):
177 )(dbgr.group_name, 'get group repo check'):
178 continue
178 continue
179
179
180 yield dbgr
180 yield dbgr
181
181
182
182
183 class ScmModel(BaseModel):
183 class ScmModel(BaseModel):
184 """
184 """
185 Generic Scm Model
185 Generic Scm Model
186 """
186 """
187
187
188 def __get_repo(self, instance):
188 def __get_repo(self, instance):
189 cls = Repository
189 cls = Repository
190 if isinstance(instance, cls):
190 if isinstance(instance, cls):
191 return instance
191 return instance
192 elif isinstance(instance, int) or safe_str(instance).isdigit():
192 elif isinstance(instance, int) or safe_str(instance).isdigit():
193 return cls.get(instance)
193 return cls.get(instance)
194 elif isinstance(instance, basestring):
194 elif isinstance(instance, basestring):
195 return cls.get_by_repo_name(instance)
195 return cls.get_by_repo_name(instance)
196 elif instance:
196 elif instance:
197 raise Exception('given object must be int, basestr or Instance'
197 raise Exception('given object must be int, basestr or Instance'
198 ' of %s got %s' % (type(cls), type(instance)))
198 ' of %s got %s' % (type(cls), type(instance)))
199
199
200 @LazyProperty
200 @LazyProperty
201 def repos_path(self):
201 def repos_path(self):
202 """
202 """
203 Get's the repositories root path from database
203 Get's the repositories root path from database
204 """
204 """
205
205
206 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
206 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
207
207
208 return q.ui_value
208 return q.ui_value
209
209
210 def repo_scan(self, repos_path=None):
210 def repo_scan(self, repos_path=None):
211 """
211 """
212 Listing of repositories in given path. This path should not be a
212 Listing of repositories in given path. This path should not be a
213 repository itself. Return a dictionary of repository objects
213 repository itself. Return a dictionary of repository objects
214
214
215 :param repos_path: path to directory containing repositories
215 :param repos_path: path to directory containing repositories
216 """
216 """
217
217
218 if repos_path is None:
218 if repos_path is None:
219 repos_path = self.repos_path
219 repos_path = self.repos_path
220
220
221 log.info('scanning for repositories in %s' % repos_path)
221 log.info('scanning for repositories in %s' % repos_path)
222
222
223 baseui = make_ui('db')
223 baseui = make_ui('db')
224 repos = {}
224 repos = {}
225
225
226 for name, path in get_filesystem_repos(repos_path, recursive=True):
226 for name, path in get_filesystem_repos(repos_path, recursive=True):
227 # skip removed repos
227 # skip removed repos
228 if REMOVED_REPO_PAT.match(name):
228 if REMOVED_REPO_PAT.match(name):
229 continue
229 continue
230
230
231 # name need to be decomposed and put back together using the /
231 # name need to be decomposed and put back together using the /
232 # since this is internal storage separator for rhodecode
232 # since this is internal storage separator for rhodecode
233 name = Repository.url_sep().join(name.split(os.sep))
233 name = Repository.url_sep().join(name.split(os.sep))
234
234
235 try:
235 try:
236 if name in repos:
236 if name in repos:
237 raise RepositoryError('Duplicate repository name %s '
237 raise RepositoryError('Duplicate repository name %s '
238 'found in %s' % (name, path))
238 'found in %s' % (name, path))
239 else:
239 else:
240
240
241 klass = get_backend(path[0])
241 klass = get_backend(path[0])
242
242
243 if path[0] == 'hg' and path[0] in BACKENDS.keys():
243 if path[0] == 'hg' and path[0] in BACKENDS.keys():
244 repos[name] = klass(safe_str(path[1]), baseui=baseui)
244 repos[name] = klass(safe_str(path[1]), baseui=baseui)
245
245
246 if path[0] == 'git' and path[0] in BACKENDS.keys():
246 if path[0] == 'git' and path[0] in BACKENDS.keys():
247 repos[name] = klass(path[1])
247 repos[name] = klass(path[1])
248 except OSError:
248 except OSError:
249 continue
249 continue
250
250
251 return repos
251 return repos
252
252
253 def get_repos(self, all_repos=None, sort_key=None, simple=False):
253 def get_repos(self, all_repos=None, sort_key=None, simple=False):
254 """
254 """
255 Get all repos from db and for each repo create it's
255 Get all repos from db and for each repo create it's
256 backend instance and fill that backed with information from database
256 backend instance and fill that backed with information from database
257
257
258 :param all_repos: list of repository names as strings
258 :param all_repos: list of repository names as strings
259 give specific repositories list, good for filtering
259 give specific repositories list, good for filtering
260
260
261 :param sort_key: initial sorting of repos
261 :param sort_key: initial sorting of repos
262 :param simple: use SimpleCachedList - one without the SCM info
262 :param simple: use SimpleCachedList - one without the SCM info
263 """
263 """
264 if all_repos is None:
264 if all_repos is None:
265 all_repos = self.sa.query(Repository)\
265 all_repos = self.sa.query(Repository)\
266 .filter(Repository.group_id == None)\
266 .filter(Repository.group_id == None)\
267 .order_by(func.lower(Repository.repo_name)).all()
267 .order_by(func.lower(Repository.repo_name)).all()
268 if simple:
268 if simple:
269 repo_iter = SimpleCachedRepoList(all_repos,
269 repo_iter = SimpleCachedRepoList(all_repos,
270 repos_path=self.repos_path,
270 repos_path=self.repos_path,
271 order_by=sort_key)
271 order_by=sort_key)
272 else:
272 else:
273 repo_iter = CachedRepoList(all_repos,
273 repo_iter = CachedRepoList(all_repos,
274 repos_path=self.repos_path,
274 repos_path=self.repos_path,
275 order_by=sort_key)
275 order_by=sort_key)
276
276
277 return repo_iter
277 return repo_iter
278
278
279 def get_repos_groups(self, all_groups=None):
279 def get_repos_groups(self, all_groups=None):
280 if all_groups is None:
280 if all_groups is None:
281 all_groups = RepoGroup.query()\
281 all_groups = RepoGroup.query()\
282 .filter(RepoGroup.group_parent_id == None).all()
282 .filter(RepoGroup.group_parent_id == None).all()
283 group_iter = GroupList(all_groups)
283 group_iter = GroupList(all_groups)
284
284
285 return group_iter
285 return group_iter
286
286
287 def mark_for_invalidation(self, repo_name):
287 def mark_for_invalidation(self, repo_name):
288 """
288 """
289 Puts cache invalidation task into db for
289 Puts cache invalidation task into db for
290 further global cache invalidation
290 further global cache invalidation
291
291
292 :param repo_name: this repo that should invalidation take place
292 :param repo_name: this repo that should invalidation take place
293 """
293 """
294 CacheInvalidation.set_invalidate(repo_name)
294 CacheInvalidation.set_invalidate(repo_name=repo_name)
295
295
296 def toggle_following_repo(self, follow_repo_id, user_id):
296 def toggle_following_repo(self, follow_repo_id, user_id):
297
297
298 f = self.sa.query(UserFollowing)\
298 f = self.sa.query(UserFollowing)\
299 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
299 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
300 .filter(UserFollowing.user_id == user_id).scalar()
300 .filter(UserFollowing.user_id == user_id).scalar()
301
301
302 if f is not None:
302 if f is not None:
303 try:
303 try:
304 self.sa.delete(f)
304 self.sa.delete(f)
305 action_logger(UserTemp(user_id),
305 action_logger(UserTemp(user_id),
306 'stopped_following_repo',
306 'stopped_following_repo',
307 RepoTemp(follow_repo_id))
307 RepoTemp(follow_repo_id))
308 return
308 return
309 except:
309 except:
310 log.error(traceback.format_exc())
310 log.error(traceback.format_exc())
311 raise
311 raise
312
312
313 try:
313 try:
314 f = UserFollowing()
314 f = UserFollowing()
315 f.user_id = user_id
315 f.user_id = user_id
316 f.follows_repo_id = follow_repo_id
316 f.follows_repo_id = follow_repo_id
317 self.sa.add(f)
317 self.sa.add(f)
318
318
319 action_logger(UserTemp(user_id),
319 action_logger(UserTemp(user_id),
320 'started_following_repo',
320 'started_following_repo',
321 RepoTemp(follow_repo_id))
321 RepoTemp(follow_repo_id))
322 except:
322 except:
323 log.error(traceback.format_exc())
323 log.error(traceback.format_exc())
324 raise
324 raise
325
325
326 def toggle_following_user(self, follow_user_id, user_id):
326 def toggle_following_user(self, follow_user_id, user_id):
327 f = self.sa.query(UserFollowing)\
327 f = self.sa.query(UserFollowing)\
328 .filter(UserFollowing.follows_user_id == follow_user_id)\
328 .filter(UserFollowing.follows_user_id == follow_user_id)\
329 .filter(UserFollowing.user_id == user_id).scalar()
329 .filter(UserFollowing.user_id == user_id).scalar()
330
330
331 if f is not None:
331 if f is not None:
332 try:
332 try:
333 self.sa.delete(f)
333 self.sa.delete(f)
334 return
334 return
335 except:
335 except:
336 log.error(traceback.format_exc())
336 log.error(traceback.format_exc())
337 raise
337 raise
338
338
339 try:
339 try:
340 f = UserFollowing()
340 f = UserFollowing()
341 f.user_id = user_id
341 f.user_id = user_id
342 f.follows_user_id = follow_user_id
342 f.follows_user_id = follow_user_id
343 self.sa.add(f)
343 self.sa.add(f)
344 except:
344 except:
345 log.error(traceback.format_exc())
345 log.error(traceback.format_exc())
346 raise
346 raise
347
347
348 def is_following_repo(self, repo_name, user_id, cache=False):
348 def is_following_repo(self, repo_name, user_id, cache=False):
349 r = self.sa.query(Repository)\
349 r = self.sa.query(Repository)\
350 .filter(Repository.repo_name == repo_name).scalar()
350 .filter(Repository.repo_name == repo_name).scalar()
351
351
352 f = self.sa.query(UserFollowing)\
352 f = self.sa.query(UserFollowing)\
353 .filter(UserFollowing.follows_repository == r)\
353 .filter(UserFollowing.follows_repository == r)\
354 .filter(UserFollowing.user_id == user_id).scalar()
354 .filter(UserFollowing.user_id == user_id).scalar()
355
355
356 return f is not None
356 return f is not None
357
357
358 def is_following_user(self, username, user_id, cache=False):
358 def is_following_user(self, username, user_id, cache=False):
359 u = User.get_by_username(username)
359 u = User.get_by_username(username)
360
360
361 f = self.sa.query(UserFollowing)\
361 f = self.sa.query(UserFollowing)\
362 .filter(UserFollowing.follows_user == u)\
362 .filter(UserFollowing.follows_user == u)\
363 .filter(UserFollowing.user_id == user_id).scalar()
363 .filter(UserFollowing.user_id == user_id).scalar()
364
364
365 return f is not None
365 return f is not None
366
366
367 def get_followers(self, repo):
367 def get_followers(self, repo):
368 repo = self._get_repo(repo)
368 repo = self._get_repo(repo)
369
369
370 return self.sa.query(UserFollowing)\
370 return self.sa.query(UserFollowing)\
371 .filter(UserFollowing.follows_repository == repo).count()
371 .filter(UserFollowing.follows_repository == repo).count()
372
372
373 def get_forks(self, repo):
373 def get_forks(self, repo):
374 repo = self._get_repo(repo)
374 repo = self._get_repo(repo)
375 return self.sa.query(Repository)\
375 return self.sa.query(Repository)\
376 .filter(Repository.fork == repo).count()
376 .filter(Repository.fork == repo).count()
377
377
378 def get_pull_requests(self, repo):
378 def get_pull_requests(self, repo):
379 repo = self._get_repo(repo)
379 repo = self._get_repo(repo)
380 return self.sa.query(PullRequest)\
380 return self.sa.query(PullRequest)\
381 .filter(PullRequest.other_repo == repo).count()
381 .filter(PullRequest.other_repo == repo).count()
382
382
383 def mark_as_fork(self, repo, fork, user):
383 def mark_as_fork(self, repo, fork, user):
384 repo = self.__get_repo(repo)
384 repo = self.__get_repo(repo)
385 fork = self.__get_repo(fork)
385 fork = self.__get_repo(fork)
386 if fork and repo.repo_id == fork.repo_id:
386 if fork and repo.repo_id == fork.repo_id:
387 raise Exception("Cannot set repository as fork of itself")
387 raise Exception("Cannot set repository as fork of itself")
388 repo.fork = fork
388 repo.fork = fork
389 self.sa.add(repo)
389 self.sa.add(repo)
390 return repo
390 return repo
391
391
392 def pull_changes(self, repo, username):
392 def pull_changes(self, repo, username):
393 dbrepo = self.__get_repo(repo)
393 dbrepo = self.__get_repo(repo)
394 clone_uri = dbrepo.clone_uri
394 clone_uri = dbrepo.clone_uri
395 if not clone_uri:
395 if not clone_uri:
396 raise Exception("This repository doesn't have a clone uri")
396 raise Exception("This repository doesn't have a clone uri")
397
397
398 repo = dbrepo.scm_instance
398 repo = dbrepo.scm_instance
399 from rhodecode import CONFIG
399 from rhodecode import CONFIG
400 try:
400 try:
401 extras = {
401 extras = {
402 'ip': '',
402 'ip': '',
403 'username': username,
403 'username': username,
404 'action': 'push_remote',
404 'action': 'push_remote',
405 'repository': dbrepo.repo_name,
405 'repository': dbrepo.repo_name,
406 'scm': repo.alias,
406 'scm': repo.alias,
407 'config': CONFIG['__file__'],
407 'config': CONFIG['__file__'],
408 'make_lock': None,
408 'make_lock': None,
409 'locked_by': [None, None]
409 'locked_by': [None, None]
410 }
410 }
411
411
412 Repository.inject_ui(repo, extras=extras)
412 Repository.inject_ui(repo, extras=extras)
413
413
414 if repo.alias == 'git':
414 if repo.alias == 'git':
415 repo.fetch(clone_uri)
415 repo.fetch(clone_uri)
416 else:
416 else:
417 repo.pull(clone_uri)
417 repo.pull(clone_uri)
418 self.mark_for_invalidation(dbrepo.repo_name)
418 self.mark_for_invalidation(dbrepo.repo_name)
419 except:
419 except:
420 log.error(traceback.format_exc())
420 log.error(traceback.format_exc())
421 raise
421 raise
422
422
423 def commit_change(self, repo, repo_name, cs, user, author, message,
423 def commit_change(self, repo, repo_name, cs, user, author, message,
424 content, f_path):
424 content, f_path):
425 """
425 """
426 Commits changes
426 Commits changes
427
427
428 :param repo: SCM instance
428 :param repo: SCM instance
429
429
430 """
430 """
431
431
432 if repo.alias == 'hg':
432 if repo.alias == 'hg':
433 from rhodecode.lib.vcs.backends.hg import \
433 from rhodecode.lib.vcs.backends.hg import \
434 MercurialInMemoryChangeset as IMC
434 MercurialInMemoryChangeset as IMC
435 elif repo.alias == 'git':
435 elif repo.alias == 'git':
436 from rhodecode.lib.vcs.backends.git import \
436 from rhodecode.lib.vcs.backends.git import \
437 GitInMemoryChangeset as IMC
437 GitInMemoryChangeset as IMC
438
438
439 # decoding here will force that we have proper encoded values
439 # decoding here will force that we have proper encoded values
440 # in any other case this will throw exceptions and deny commit
440 # in any other case this will throw exceptions and deny commit
441 content = safe_str(content)
441 content = safe_str(content)
442 path = safe_str(f_path)
442 path = safe_str(f_path)
443 # message and author needs to be unicode
443 # message and author needs to be unicode
444 # proper backend should then translate that into required type
444 # proper backend should then translate that into required type
445 message = safe_unicode(message)
445 message = safe_unicode(message)
446 author = safe_unicode(author)
446 author = safe_unicode(author)
447 m = IMC(repo)
447 m = IMC(repo)
448 m.change(FileNode(path, content))
448 m.change(FileNode(path, content))
449 tip = m.commit(message=message,
449 tip = m.commit(message=message,
450 author=author,
450 author=author,
451 parents=[cs], branch=cs.branch)
451 parents=[cs], branch=cs.branch)
452
452
453 action = 'push_local:%s' % tip.raw_id
453 action = 'push_local:%s' % tip.raw_id
454 action_logger(user, action, repo_name)
454 action_logger(user, action, repo_name)
455 self.mark_for_invalidation(repo_name)
455 self.mark_for_invalidation(repo_name)
456 return tip
456 return tip
457
457
458 def create_node(self, repo, repo_name, cs, user, author, message, content,
458 def create_node(self, repo, repo_name, cs, user, author, message, content,
459 f_path):
459 f_path):
460 if repo.alias == 'hg':
460 if repo.alias == 'hg':
461 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
461 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
462 elif repo.alias == 'git':
462 elif repo.alias == 'git':
463 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
463 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
464 # decoding here will force that we have proper encoded values
464 # decoding here will force that we have proper encoded values
465 # in any other case this will throw exceptions and deny commit
465 # in any other case this will throw exceptions and deny commit
466
466
467 if isinstance(content, (basestring,)):
467 if isinstance(content, (basestring,)):
468 content = safe_str(content)
468 content = safe_str(content)
469 elif isinstance(content, (file, cStringIO.OutputType,)):
469 elif isinstance(content, (file, cStringIO.OutputType,)):
470 content = content.read()
470 content = content.read()
471 else:
471 else:
472 raise Exception('Content is of unrecognized type %s' % (
472 raise Exception('Content is of unrecognized type %s' % (
473 type(content)
473 type(content)
474 ))
474 ))
475
475
476 message = safe_unicode(message)
476 message = safe_unicode(message)
477 author = safe_unicode(author)
477 author = safe_unicode(author)
478 path = safe_str(f_path)
478 path = safe_str(f_path)
479 m = IMC(repo)
479 m = IMC(repo)
480
480
481 if isinstance(cs, EmptyChangeset):
481 if isinstance(cs, EmptyChangeset):
482 # EmptyChangeset means we we're editing empty repository
482 # EmptyChangeset means we we're editing empty repository
483 parents = None
483 parents = None
484 else:
484 else:
485 parents = [cs]
485 parents = [cs]
486
486
487 m.add(FileNode(path, content=content))
487 m.add(FileNode(path, content=content))
488 tip = m.commit(message=message,
488 tip = m.commit(message=message,
489 author=author,
489 author=author,
490 parents=parents, branch=cs.branch)
490 parents=parents, branch=cs.branch)
491
491
492 action = 'push_local:%s' % tip.raw_id
492 action = 'push_local:%s' % tip.raw_id
493 action_logger(user, action, repo_name)
493 action_logger(user, action, repo_name)
494 self.mark_for_invalidation(repo_name)
494 self.mark_for_invalidation(repo_name)
495 return tip
495 return tip
496
496
497 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
497 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
498 """
498 """
499 recursive walk in root dir and return a set of all path in that dir
499 recursive walk in root dir and return a set of all path in that dir
500 based on repository walk function
500 based on repository walk function
501
501
502 :param repo_name: name of repository
502 :param repo_name: name of repository
503 :param revision: revision for which to list nodes
503 :param revision: revision for which to list nodes
504 :param root_path: root path to list
504 :param root_path: root path to list
505 :param flat: return as a list, if False returns a dict with decription
505 :param flat: return as a list, if False returns a dict with decription
506
506
507 """
507 """
508 _files = list()
508 _files = list()
509 _dirs = list()
509 _dirs = list()
510 try:
510 try:
511 _repo = self.__get_repo(repo_name)
511 _repo = self.__get_repo(repo_name)
512 changeset = _repo.scm_instance.get_changeset(revision)
512 changeset = _repo.scm_instance.get_changeset(revision)
513 root_path = root_path.lstrip('/')
513 root_path = root_path.lstrip('/')
514 for topnode, dirs, files in changeset.walk(root_path):
514 for topnode, dirs, files in changeset.walk(root_path):
515 for f in files:
515 for f in files:
516 _files.append(f.path if flat else {"name": f.path,
516 _files.append(f.path if flat else {"name": f.path,
517 "type": "file"})
517 "type": "file"})
518 for d in dirs:
518 for d in dirs:
519 _dirs.append(d.path if flat else {"name": d.path,
519 _dirs.append(d.path if flat else {"name": d.path,
520 "type": "dir"})
520 "type": "dir"})
521 except RepositoryError:
521 except RepositoryError:
522 log.debug(traceback.format_exc())
522 log.debug(traceback.format_exc())
523 raise
523 raise
524
524
525 return _dirs, _files
525 return _dirs, _files
526
526
527 def get_unread_journal(self):
527 def get_unread_journal(self):
528 return self.sa.query(UserLog).count()
528 return self.sa.query(UserLog).count()
529
529
530 def get_repo_landing_revs(self, repo=None):
530 def get_repo_landing_revs(self, repo=None):
531 """
531 """
532 Generates select option with tags branches and bookmarks (for hg only)
532 Generates select option with tags branches and bookmarks (for hg only)
533 grouped by type
533 grouped by type
534
534
535 :param repo:
535 :param repo:
536 :type repo:
536 :type repo:
537 """
537 """
538
538
539 hist_l = []
539 hist_l = []
540 choices = []
540 choices = []
541 repo = self.__get_repo(repo)
541 repo = self.__get_repo(repo)
542 hist_l.append(['tip', _('latest tip')])
542 hist_l.append(['tip', _('latest tip')])
543 choices.append('tip')
543 choices.append('tip')
544 if not repo:
544 if not repo:
545 return choices, hist_l
545 return choices, hist_l
546
546
547 repo = repo.scm_instance
547 repo = repo.scm_instance
548
548
549 branches_group = ([(k, k) for k, v in
549 branches_group = ([(k, k) for k, v in
550 repo.branches.iteritems()], _("Branches"))
550 repo.branches.iteritems()], _("Branches"))
551 hist_l.append(branches_group)
551 hist_l.append(branches_group)
552 choices.extend([x[0] for x in branches_group[0]])
552 choices.extend([x[0] for x in branches_group[0]])
553
553
554 if repo.alias == 'hg':
554 if repo.alias == 'hg':
555 bookmarks_group = ([(k, k) for k, v in
555 bookmarks_group = ([(k, k) for k, v in
556 repo.bookmarks.iteritems()], _("Bookmarks"))
556 repo.bookmarks.iteritems()], _("Bookmarks"))
557 hist_l.append(bookmarks_group)
557 hist_l.append(bookmarks_group)
558 choices.extend([x[0] for x in bookmarks_group[0]])
558 choices.extend([x[0] for x in bookmarks_group[0]])
559
559
560 tags_group = ([(k, k) for k, v in
560 tags_group = ([(k, k) for k, v in
561 repo.tags.iteritems()], _("Tags"))
561 repo.tags.iteritems()], _("Tags"))
562 hist_l.append(tags_group)
562 hist_l.append(tags_group)
563 choices.extend([x[0] for x in tags_group[0]])
563 choices.extend([x[0] for x in tags_group[0]])
564
564
565 return choices, hist_l
565 return choices, hist_l
566
566
567 def install_git_hook(self, repo, force_create=False):
567 def install_git_hook(self, repo, force_create=False):
568 """
568 """
569 Creates a rhodecode hook inside a git repository
569 Creates a rhodecode hook inside a git repository
570
570
571 :param repo: Instance of VCS repo
571 :param repo: Instance of VCS repo
572 :param force_create: Create even if same name hook exists
572 :param force_create: Create even if same name hook exists
573 """
573 """
574
574
575 loc = jn(repo.path, 'hooks')
575 loc = jn(repo.path, 'hooks')
576 if not repo.bare:
576 if not repo.bare:
577 loc = jn(repo.path, '.git', 'hooks')
577 loc = jn(repo.path, '.git', 'hooks')
578 if not os.path.isdir(loc):
578 if not os.path.isdir(loc):
579 os.makedirs(loc)
579 os.makedirs(loc)
580
580
581 tmpl_post = pkg_resources.resource_string(
581 tmpl_post = pkg_resources.resource_string(
582 'rhodecode', jn('config', 'post_receive_tmpl.py')
582 'rhodecode', jn('config', 'post_receive_tmpl.py')
583 )
583 )
584 tmpl_pre = pkg_resources.resource_string(
584 tmpl_pre = pkg_resources.resource_string(
585 'rhodecode', jn('config', 'pre_receive_tmpl.py')
585 'rhodecode', jn('config', 'pre_receive_tmpl.py')
586 )
586 )
587
587
588 for h_type, tmpl in [('pre', tmpl_pre), ('post', tmpl_post)]:
588 for h_type, tmpl in [('pre', tmpl_pre), ('post', tmpl_post)]:
589 _hook_file = jn(loc, '%s-receive' % h_type)
589 _hook_file = jn(loc, '%s-receive' % h_type)
590 _rhodecode_hook = False
590 _rhodecode_hook = False
591 log.debug('Installing git hook in repo %s' % repo)
591 log.debug('Installing git hook in repo %s' % repo)
592 if os.path.exists(_hook_file):
592 if os.path.exists(_hook_file):
593 # let's take a look at this hook, maybe it's rhodecode ?
593 # let's take a look at this hook, maybe it's rhodecode ?
594 log.debug('hook exists, checking if it is from rhodecode')
594 log.debug('hook exists, checking if it is from rhodecode')
595 _HOOK_VER_PAT = re.compile(r'^RC_HOOK_VER')
595 _HOOK_VER_PAT = re.compile(r'^RC_HOOK_VER')
596 with open(_hook_file, 'rb') as f:
596 with open(_hook_file, 'rb') as f:
597 data = f.read()
597 data = f.read()
598 matches = re.compile(r'(?:%s)\s*=\s*(.*)'
598 matches = re.compile(r'(?:%s)\s*=\s*(.*)'
599 % 'RC_HOOK_VER').search(data)
599 % 'RC_HOOK_VER').search(data)
600 if matches:
600 if matches:
601 try:
601 try:
602 ver = matches.groups()[0]
602 ver = matches.groups()[0]
603 log.debug('got %s it is rhodecode' % (ver))
603 log.debug('got %s it is rhodecode' % (ver))
604 _rhodecode_hook = True
604 _rhodecode_hook = True
605 except:
605 except:
606 log.error(traceback.format_exc())
606 log.error(traceback.format_exc())
607 else:
607 else:
608 # there is no hook in this dir, so we want to create one
608 # there is no hook in this dir, so we want to create one
609 _rhodecode_hook = True
609 _rhodecode_hook = True
610
610
611 if _rhodecode_hook or force_create:
611 if _rhodecode_hook or force_create:
612 log.debug('writing %s hook file !' % h_type)
612 log.debug('writing %s hook file !' % h_type)
613 with open(_hook_file, 'wb') as f:
613 with open(_hook_file, 'wb') as f:
614 tmpl = tmpl.replace('_TMPL_', rhodecode.__version__)
614 tmpl = tmpl.replace('_TMPL_', rhodecode.__version__)
615 f.write(tmpl)
615 f.write(tmpl)
616 os.chmod(_hook_file, 0755)
616 os.chmod(_hook_file, 0755)
617 else:
617 else:
618 log.debug('skipping writing hook file')
618 log.debug('skipping writing hook file')
@@ -1,4759 +1,4760 b''
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td
1 html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td
2 {
2 {
3 border: 0;
3 border: 0;
4 outline: 0;
4 outline: 0;
5 font-size: 100%;
5 font-size: 100%;
6 vertical-align: baseline;
6 vertical-align: baseline;
7 background: transparent;
7 background: transparent;
8 margin: 0;
8 margin: 0;
9 padding: 0;
9 padding: 0;
10 }
10 }
11
11
12 body {
12 body {
13 line-height: 1;
13 line-height: 1;
14 height: 100%;
14 height: 100%;
15 background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
15 background: url("../images/background.png") repeat scroll 0 0 #B0B0B0;
16 font-family: Lucida Grande, Verdana, Lucida Sans Regular,
16 font-family: Lucida Grande, Verdana, Lucida Sans Regular,
17 Lucida Sans Unicode, Arial, sans-serif; font-size : 12px;
17 Lucida Sans Unicode, Arial, sans-serif; font-size : 12px;
18 color: #000;
18 color: #000;
19 margin: 0;
19 margin: 0;
20 padding: 0;
20 padding: 0;
21 font-size: 12px;
21 font-size: 12px;
22 }
22 }
23
23
24 ol,ul {
24 ol,ul {
25 list-style: none;
25 list-style: none;
26 }
26 }
27
27
28 blockquote,q {
28 blockquote,q {
29 quotes: none;
29 quotes: none;
30 }
30 }
31
31
32 blockquote:before,blockquote:after,q:before,q:after {
32 blockquote:before,blockquote:after,q:before,q:after {
33 content: none;
33 content: none;
34 }
34 }
35
35
36 :focus {
36 :focus {
37 outline: 0;
37 outline: 0;
38 }
38 }
39
39
40 del {
40 del {
41 text-decoration: line-through;
41 text-decoration: line-through;
42 }
42 }
43
43
44 table {
44 table {
45 border-collapse: collapse;
45 border-collapse: collapse;
46 border-spacing: 0;
46 border-spacing: 0;
47 }
47 }
48
48
49 html {
49 html {
50 height: 100%;
50 height: 100%;
51 }
51 }
52
52
53 a {
53 a {
54 color: #003367;
54 color: #003367;
55 text-decoration: none;
55 text-decoration: none;
56 cursor: pointer;
56 cursor: pointer;
57 }
57 }
58
58
59 a:hover {
59 a:hover {
60 color: #316293;
60 color: #316293;
61 text-decoration: underline;
61 text-decoration: underline;
62 }
62 }
63
63
64 h1,h2,h3,h4,h5,h6,
64 h1,h2,h3,h4,h5,h6,
65 div.h1,div.h2,div.h3,div.h4,div.h5,div.h6 {
65 div.h1,div.h2,div.h3,div.h4,div.h5,div.h6 {
66 color: #292929;
66 color: #292929;
67 font-weight: 700;
67 font-weight: 700;
68 }
68 }
69
69
70 h1,div.h1 {
70 h1,div.h1 {
71 font-size: 22px;
71 font-size: 22px;
72 }
72 }
73
73
74 h2,div.h2 {
74 h2,div.h2 {
75 font-size: 20px;
75 font-size: 20px;
76 }
76 }
77
77
78 h3,div.h3 {
78 h3,div.h3 {
79 font-size: 18px;
79 font-size: 18px;
80 }
80 }
81
81
82 h4,div.h4 {
82 h4,div.h4 {
83 font-size: 16px;
83 font-size: 16px;
84 }
84 }
85
85
86 h5,div.h5 {
86 h5,div.h5 {
87 font-size: 14px;
87 font-size: 14px;
88 }
88 }
89
89
90 h6,div.h6 {
90 h6,div.h6 {
91 font-size: 11px;
91 font-size: 11px;
92 }
92 }
93
93
94 ul.circle {
94 ul.circle {
95 list-style-type: circle;
95 list-style-type: circle;
96 }
96 }
97
97
98 ul.disc {
98 ul.disc {
99 list-style-type: disc;
99 list-style-type: disc;
100 }
100 }
101
101
102 ul.square {
102 ul.square {
103 list-style-type: square;
103 list-style-type: square;
104 }
104 }
105
105
106 ol.lower-roman {
106 ol.lower-roman {
107 list-style-type: lower-roman;
107 list-style-type: lower-roman;
108 }
108 }
109
109
110 ol.upper-roman {
110 ol.upper-roman {
111 list-style-type: upper-roman;
111 list-style-type: upper-roman;
112 }
112 }
113
113
114 ol.lower-alpha {
114 ol.lower-alpha {
115 list-style-type: lower-alpha;
115 list-style-type: lower-alpha;
116 }
116 }
117
117
118 ol.upper-alpha {
118 ol.upper-alpha {
119 list-style-type: upper-alpha;
119 list-style-type: upper-alpha;
120 }
120 }
121
121
122 ol.decimal {
122 ol.decimal {
123 list-style-type: decimal;
123 list-style-type: decimal;
124 }
124 }
125
125
126 div.color {
126 div.color {
127 clear: both;
127 clear: both;
128 overflow: hidden;
128 overflow: hidden;
129 position: absolute;
129 position: absolute;
130 background: #FFF;
130 background: #FFF;
131 margin: 7px 0 0 60px;
131 margin: 7px 0 0 60px;
132 padding: 1px 1px 1px 0;
132 padding: 1px 1px 1px 0;
133 }
133 }
134
134
135 div.color a {
135 div.color a {
136 width: 15px;
136 width: 15px;
137 height: 15px;
137 height: 15px;
138 display: block;
138 display: block;
139 float: left;
139 float: left;
140 margin: 0 0 0 1px;
140 margin: 0 0 0 1px;
141 padding: 0;
141 padding: 0;
142 }
142 }
143
143
144 div.options {
144 div.options {
145 clear: both;
145 clear: both;
146 overflow: hidden;
146 overflow: hidden;
147 position: absolute;
147 position: absolute;
148 background: #FFF;
148 background: #FFF;
149 margin: 7px 0 0 162px;
149 margin: 7px 0 0 162px;
150 padding: 0;
150 padding: 0;
151 }
151 }
152
152
153 div.options a {
153 div.options a {
154 height: 1%;
154 height: 1%;
155 display: block;
155 display: block;
156 text-decoration: none;
156 text-decoration: none;
157 margin: 0;
157 margin: 0;
158 padding: 3px 8px;
158 padding: 3px 8px;
159 }
159 }
160
160
161 .top-left-rounded-corner {
161 .top-left-rounded-corner {
162 -webkit-border-top-left-radius: 8px;
162 -webkit-border-top-left-radius: 8px;
163 -khtml-border-radius-topleft: 8px;
163 -khtml-border-radius-topleft: 8px;
164 -moz-border-radius-topleft: 8px;
164 -moz-border-radius-topleft: 8px;
165 border-top-left-radius: 8px;
165 border-top-left-radius: 8px;
166 }
166 }
167
167
168 .top-right-rounded-corner {
168 .top-right-rounded-corner {
169 -webkit-border-top-right-radius: 8px;
169 -webkit-border-top-right-radius: 8px;
170 -khtml-border-radius-topright: 8px;
170 -khtml-border-radius-topright: 8px;
171 -moz-border-radius-topright: 8px;
171 -moz-border-radius-topright: 8px;
172 border-top-right-radius: 8px;
172 border-top-right-radius: 8px;
173 }
173 }
174
174
175 .bottom-left-rounded-corner {
175 .bottom-left-rounded-corner {
176 -webkit-border-bottom-left-radius: 8px;
176 -webkit-border-bottom-left-radius: 8px;
177 -khtml-border-radius-bottomleft: 8px;
177 -khtml-border-radius-bottomleft: 8px;
178 -moz-border-radius-bottomleft: 8px;
178 -moz-border-radius-bottomleft: 8px;
179 border-bottom-left-radius: 8px;
179 border-bottom-left-radius: 8px;
180 }
180 }
181
181
182 .bottom-right-rounded-corner {
182 .bottom-right-rounded-corner {
183 -webkit-border-bottom-right-radius: 8px;
183 -webkit-border-bottom-right-radius: 8px;
184 -khtml-border-radius-bottomright: 8px;
184 -khtml-border-radius-bottomright: 8px;
185 -moz-border-radius-bottomright: 8px;
185 -moz-border-radius-bottomright: 8px;
186 border-bottom-right-radius: 8px;
186 border-bottom-right-radius: 8px;
187 }
187 }
188
188
189 .top-left-rounded-corner-mid {
189 .top-left-rounded-corner-mid {
190 -webkit-border-top-left-radius: 4px;
190 -webkit-border-top-left-radius: 4px;
191 -khtml-border-radius-topleft: 4px;
191 -khtml-border-radius-topleft: 4px;
192 -moz-border-radius-topleft: 4px;
192 -moz-border-radius-topleft: 4px;
193 border-top-left-radius: 4px;
193 border-top-left-radius: 4px;
194 }
194 }
195
195
196 .top-right-rounded-corner-mid {
196 .top-right-rounded-corner-mid {
197 -webkit-border-top-right-radius: 4px;
197 -webkit-border-top-right-radius: 4px;
198 -khtml-border-radius-topright: 4px;
198 -khtml-border-radius-topright: 4px;
199 -moz-border-radius-topright: 4px;
199 -moz-border-radius-topright: 4px;
200 border-top-right-radius: 4px;
200 border-top-right-radius: 4px;
201 }
201 }
202
202
203 .bottom-left-rounded-corner-mid {
203 .bottom-left-rounded-corner-mid {
204 -webkit-border-bottom-left-radius: 4px;
204 -webkit-border-bottom-left-radius: 4px;
205 -khtml-border-radius-bottomleft: 4px;
205 -khtml-border-radius-bottomleft: 4px;
206 -moz-border-radius-bottomleft: 4px;
206 -moz-border-radius-bottomleft: 4px;
207 border-bottom-left-radius: 4px;
207 border-bottom-left-radius: 4px;
208 }
208 }
209
209
210 .bottom-right-rounded-corner-mid {
210 .bottom-right-rounded-corner-mid {
211 -webkit-border-bottom-right-radius: 4px;
211 -webkit-border-bottom-right-radius: 4px;
212 -khtml-border-radius-bottomright: 4px;
212 -khtml-border-radius-bottomright: 4px;
213 -moz-border-radius-bottomright: 4px;
213 -moz-border-radius-bottomright: 4px;
214 border-bottom-right-radius: 4px;
214 border-bottom-right-radius: 4px;
215 }
215 }
216
216
217 .help-block {
217 .help-block {
218 color: #999999;
218 color: #999999;
219 display: block;
219 display: block;
220 margin-bottom: 0;
220 margin-bottom: 0;
221 margin-top: 5px;
221 margin-top: 5px;
222 }
222 }
223
223
224 .empty_data{
224 .empty_data{
225 color:#B9B9B9;
225 color:#B9B9B9;
226 }
226 }
227
227
228 a.permalink{
228 a.permalink{
229 visibility: hidden;
229 visibility: hidden;
230 }
230 }
231
231
232 a.permalink:hover{
232 a.permalink:hover{
233 text-decoration: none;
233 text-decoration: none;
234 }
234 }
235
235
236 h1:hover > a.permalink,
236 h1:hover > a.permalink,
237 h2:hover > a.permalink,
237 h2:hover > a.permalink,
238 h3:hover > a.permalink,
238 h3:hover > a.permalink,
239 h4:hover > a.permalink,
239 h4:hover > a.permalink,
240 h5:hover > a.permalink,
240 h5:hover > a.permalink,
241 h6:hover > a.permalink,
241 h6:hover > a.permalink,
242 div:hover > a.permalink {
242 div:hover > a.permalink {
243 visibility: visible;
243 visibility: visible;
244 }
244 }
245
245
246 #header {
246 #header {
247 margin: 0;
247 margin: 0;
248 padding: 0 10px;
248 padding: 0 10px;
249 }
249 }
250
250
251 #header ul#logged-user {
251 #header ul#logged-user {
252 margin-bottom: 5px !important;
252 margin-bottom: 5px !important;
253 -webkit-border-radius: 0px 0px 8px 8px;
253 -webkit-border-radius: 0px 0px 8px 8px;
254 -khtml-border-radius: 0px 0px 8px 8px;
254 -khtml-border-radius: 0px 0px 8px 8px;
255 -moz-border-radius: 0px 0px 8px 8px;
255 -moz-border-radius: 0px 0px 8px 8px;
256 border-radius: 0px 0px 8px 8px;
256 border-radius: 0px 0px 8px 8px;
257 height: 37px;
257 height: 37px;
258 background-color: #003B76;
258 background-color: #003B76;
259 background-repeat: repeat-x;
259 background-repeat: repeat-x;
260 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
260 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
261 background-image: -moz-linear-gradient(top, #003b76, #00376e);
261 background-image: -moz-linear-gradient(top, #003b76, #00376e);
262 background-image: -ms-linear-gradient(top, #003b76, #00376e);
262 background-image: -ms-linear-gradient(top, #003b76, #00376e);
263 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
263 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
264 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
264 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
265 background-image: -o-linear-gradient(top, #003b76, #00376e);
265 background-image: -o-linear-gradient(top, #003b76, #00376e);
266 background-image: linear-gradient(top, #003b76, #00376e);
266 background-image: linear-gradient(top, #003b76, #00376e);
267 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
267 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
268 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
268 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
269 }
269 }
270
270
271 #header ul#logged-user li {
271 #header ul#logged-user li {
272 list-style: none;
272 list-style: none;
273 float: left;
273 float: left;
274 margin: 8px 0 0;
274 margin: 8px 0 0;
275 padding: 4px 12px;
275 padding: 4px 12px;
276 border-left: 1px solid #316293;
276 border-left: 1px solid #316293;
277 }
277 }
278
278
279 #header ul#logged-user li.first {
279 #header ul#logged-user li.first {
280 border-left: none;
280 border-left: none;
281 margin: 4px;
281 margin: 4px;
282 }
282 }
283
283
284 #header ul#logged-user li.first div.gravatar {
284 #header ul#logged-user li.first div.gravatar {
285 margin-top: -2px;
285 margin-top: -2px;
286 }
286 }
287
287
288 #header ul#logged-user li.first div.account {
288 #header ul#logged-user li.first div.account {
289 padding-top: 4px;
289 padding-top: 4px;
290 float: left;
290 float: left;
291 }
291 }
292
292
293 #header ul#logged-user li.last {
293 #header ul#logged-user li.last {
294 border-right: none;
294 border-right: none;
295 }
295 }
296
296
297 #header ul#logged-user li a {
297 #header ul#logged-user li a {
298 color: #fff;
298 color: #fff;
299 font-weight: 700;
299 font-weight: 700;
300 text-decoration: none;
300 text-decoration: none;
301 }
301 }
302
302
303 #header ul#logged-user li a:hover {
303 #header ul#logged-user li a:hover {
304 text-decoration: underline;
304 text-decoration: underline;
305 }
305 }
306
306
307 #header ul#logged-user li.highlight a {
307 #header ul#logged-user li.highlight a {
308 color: #fff;
308 color: #fff;
309 }
309 }
310
310
311 #header ul#logged-user li.highlight a:hover {
311 #header ul#logged-user li.highlight a:hover {
312 color: #FFF;
312 color: #FFF;
313 }
313 }
314
314
315 #header #header-inner {
315 #header #header-inner {
316 min-height: 44px;
316 min-height: 44px;
317 clear: both;
317 clear: both;
318 position: relative;
318 position: relative;
319 background-color: #003B76;
319 background-color: #003B76;
320 background-repeat: repeat-x;
320 background-repeat: repeat-x;
321 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
321 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
322 background-image: -moz-linear-gradient(top, #003b76, #00376e);
322 background-image: -moz-linear-gradient(top, #003b76, #00376e);
323 background-image: -ms-linear-gradient(top, #003b76, #00376e);
323 background-image: -ms-linear-gradient(top, #003b76, #00376e);
324 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) );
324 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) );
325 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
325 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
326 background-image: -o-linear-gradient(top, #003b76, #00376e);
326 background-image: -o-linear-gradient(top, #003b76, #00376e);
327 background-image: linear-gradient(top, #003b76, #00376e);
327 background-image: linear-gradient(top, #003b76, #00376e);
328 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
328 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 );
329 margin: 0;
329 margin: 0;
330 padding: 0;
330 padding: 0;
331 display: block;
331 display: block;
332 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
332 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
333 -webkit-border-radius: 4px 4px 4px 4px;
333 -webkit-border-radius: 4px 4px 4px 4px;
334 -khtml-border-radius: 4px 4px 4px 4px;
334 -khtml-border-radius: 4px 4px 4px 4px;
335 -moz-border-radius: 4px 4px 4px 4px;
335 -moz-border-radius: 4px 4px 4px 4px;
336 border-radius: 4px 4px 4px 4px;
336 border-radius: 4px 4px 4px 4px;
337 }
337 }
338 #header #header-inner.hover{
338 #header #header-inner.hover{
339 position: fixed !important;
339 position: fixed !important;
340 width: 100% !important;
340 width: 100% !important;
341 margin-left: -10px !important;
341 margin-left: -10px !important;
342 z-index: 10000;
342 z-index: 10000;
343 -webkit-border-radius: 0px 0px 0px 0px;
343 -webkit-border-radius: 0px 0px 0px 0px;
344 -khtml-border-radius: 0px 0px 0px 0px;
344 -khtml-border-radius: 0px 0px 0px 0px;
345 -moz-border-radius: 0px 0px 0px 0px;
345 -moz-border-radius: 0px 0px 0px 0px;
346 border-radius: 0px 0px 0px 0px;
346 border-radius: 0px 0px 0px 0px;
347 }
347 }
348
348
349 .ie7 #header #header-inner.hover,
349 .ie7 #header #header-inner.hover,
350 .ie8 #header #header-inner.hover,
350 .ie8 #header #header-inner.hover,
351 .ie9 #header #header-inner.hover
351 .ie9 #header #header-inner.hover
352 {
352 {
353 z-index: auto !important;
353 z-index: auto !important;
354 }
354 }
355
355
356 .header-pos-fix, .anchor{
356 .header-pos-fix, .anchor{
357 margin-top: -46px;
357 margin-top: -46px;
358 padding-top: 46px;
358 padding-top: 46px;
359 }
359 }
360
360
361 #header #header-inner #home a {
361 #header #header-inner #home a {
362 height: 40px;
362 height: 40px;
363 width: 46px;
363 width: 46px;
364 display: block;
364 display: block;
365 background: url("../images/button_home.png");
365 background: url("../images/button_home.png");
366 background-position: 0 0;
366 background-position: 0 0;
367 margin: 0;
367 margin: 0;
368 padding: 0;
368 padding: 0;
369 }
369 }
370
370
371 #header #header-inner #home a:hover {
371 #header #header-inner #home a:hover {
372 background-position: 0 -40px;
372 background-position: 0 -40px;
373 }
373 }
374
374
375 #header #header-inner #logo {
375 #header #header-inner #logo {
376 float: left;
376 float: left;
377 position: absolute;
377 position: absolute;
378 }
378 }
379
379
380 #header #header-inner #logo h1 {
380 #header #header-inner #logo h1 {
381 color: #FFF;
381 color: #FFF;
382 font-size: 20px;
382 font-size: 20px;
383 margin: 12px 0 0 13px;
383 margin: 12px 0 0 13px;
384 padding: 0;
384 padding: 0;
385 }
385 }
386
386
387 #header #header-inner #logo a {
387 #header #header-inner #logo a {
388 color: #fff;
388 color: #fff;
389 text-decoration: none;
389 text-decoration: none;
390 }
390 }
391
391
392 #header #header-inner #logo a:hover {
392 #header #header-inner #logo a:hover {
393 color: #bfe3ff;
393 color: #bfe3ff;
394 }
394 }
395
395
396 #header #header-inner #quick,#header #header-inner #quick ul {
396 #header #header-inner #quick,#header #header-inner #quick ul {
397 position: relative;
397 position: relative;
398 float: right;
398 float: right;
399 list-style-type: none;
399 list-style-type: none;
400 list-style-position: outside;
400 list-style-position: outside;
401 margin: 8px 8px 0 0;
401 margin: 8px 8px 0 0;
402 padding: 0;
402 padding: 0;
403 }
403 }
404
404
405 #header #header-inner #quick li {
405 #header #header-inner #quick li {
406 position: relative;
406 position: relative;
407 float: left;
407 float: left;
408 margin: 0 5px 0 0;
408 margin: 0 5px 0 0;
409 padding: 0;
409 padding: 0;
410 }
410 }
411
411
412 #header #header-inner #quick li a.menu_link {
412 #header #header-inner #quick li a.menu_link {
413 top: 0;
413 top: 0;
414 left: 0;
414 left: 0;
415 height: 1%;
415 height: 1%;
416 display: block;
416 display: block;
417 clear: both;
417 clear: both;
418 overflow: hidden;
418 overflow: hidden;
419 color: #FFF;
419 color: #FFF;
420 font-weight: 700;
420 font-weight: 700;
421 text-decoration: none;
421 text-decoration: none;
422 background: #369;
422 background: #369;
423 padding: 0;
423 padding: 0;
424 -webkit-border-radius: 4px 4px 4px 4px;
424 -webkit-border-radius: 4px 4px 4px 4px;
425 -khtml-border-radius: 4px 4px 4px 4px;
425 -khtml-border-radius: 4px 4px 4px 4px;
426 -moz-border-radius: 4px 4px 4px 4px;
426 -moz-border-radius: 4px 4px 4px 4px;
427 border-radius: 4px 4px 4px 4px;
427 border-radius: 4px 4px 4px 4px;
428 }
428 }
429
429
430 #header #header-inner #quick li span.short {
430 #header #header-inner #quick li span.short {
431 padding: 9px 6px 8px 6px;
431 padding: 9px 6px 8px 6px;
432 }
432 }
433
433
434 #header #header-inner #quick li span {
434 #header #header-inner #quick li span {
435 top: 0;
435 top: 0;
436 right: 0;
436 right: 0;
437 height: 1%;
437 height: 1%;
438 display: block;
438 display: block;
439 float: left;
439 float: left;
440 border-left: 1px solid #3f6f9f;
440 border-left: 1px solid #3f6f9f;
441 margin: 0;
441 margin: 0;
442 padding: 10px 12px 8px 10px;
442 padding: 10px 12px 8px 10px;
443 }
443 }
444
444
445 #header #header-inner #quick li span.normal {
445 #header #header-inner #quick li span.normal {
446 border: none;
446 border: none;
447 padding: 10px 12px 8px;
447 padding: 10px 12px 8px;
448 }
448 }
449
449
450 #header #header-inner #quick li span.icon {
450 #header #header-inner #quick li span.icon {
451 top: 0;
451 top: 0;
452 left: 0;
452 left: 0;
453 border-left: none;
453 border-left: none;
454 border-right: 1px solid #2e5c89;
454 border-right: 1px solid #2e5c89;
455 padding: 8px 6px 4px;
455 padding: 8px 6px 4px;
456 }
456 }
457
457
458 #header #header-inner #quick li span.icon_short {
458 #header #header-inner #quick li span.icon_short {
459 top: 0;
459 top: 0;
460 left: 0;
460 left: 0;
461 border-left: none;
461 border-left: none;
462 border-right: 1px solid #2e5c89;
462 border-right: 1px solid #2e5c89;
463 padding: 8px 6px 4px;
463 padding: 8px 6px 4px;
464 }
464 }
465
465
466 #header #header-inner #quick li span.icon img,#header #header-inner #quick li span.icon_short img
466 #header #header-inner #quick li span.icon img,#header #header-inner #quick li span.icon_short img
467 {
467 {
468 margin: 0px -2px 0px 0px;
468 margin: 0px -2px 0px 0px;
469 }
469 }
470
470
471 #header #header-inner #quick li a:hover {
471 #header #header-inner #quick li a:hover {
472 background: #4e4e4e no-repeat top left;
472 background: #4e4e4e no-repeat top left;
473 }
473 }
474
474
475 #header #header-inner #quick li a:hover span {
475 #header #header-inner #quick li a:hover span {
476 border-left: 1px solid #545454;
476 border-left: 1px solid #545454;
477 }
477 }
478
478
479 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short
479 #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short
480 {
480 {
481 border-left: none;
481 border-left: none;
482 border-right: 1px solid #464646;
482 border-right: 1px solid #464646;
483 }
483 }
484
484
485 #header #header-inner #quick ul {
485 #header #header-inner #quick ul {
486 top: 29px;
486 top: 29px;
487 right: 0;
487 right: 0;
488 min-width: 200px;
488 min-width: 200px;
489 display: none;
489 display: none;
490 position: absolute;
490 position: absolute;
491 background: #FFF;
491 background: #FFF;
492 border: 1px solid #666;
492 border: 1px solid #666;
493 border-top: 1px solid #003367;
493 border-top: 1px solid #003367;
494 z-index: 100;
494 z-index: 100;
495 margin: 0px 0px 0px 0px;
495 margin: 0px 0px 0px 0px;
496 padding: 0;
496 padding: 0;
497 }
497 }
498
498
499 #header #header-inner #quick ul.repo_switcher {
499 #header #header-inner #quick ul.repo_switcher {
500 max-height: 275px;
500 max-height: 275px;
501 overflow-x: hidden;
501 overflow-x: hidden;
502 overflow-y: auto;
502 overflow-y: auto;
503 }
503 }
504
504
505 #header #header-inner #quick ul.repo_switcher li.qfilter_rs {
505 #header #header-inner #quick ul.repo_switcher li.qfilter_rs {
506 float: none;
506 float: none;
507 margin: 0;
507 margin: 0;
508 border-bottom: 2px solid #003367;
508 border-bottom: 2px solid #003367;
509 }
509 }
510
510
511 #header #header-inner #quick .repo_switcher_type {
511 #header #header-inner #quick .repo_switcher_type {
512 position: absolute;
512 position: absolute;
513 left: 0;
513 left: 0;
514 top: 9px;
514 top: 9px;
515 }
515 }
516
516
517 #header #header-inner #quick li ul li {
517 #header #header-inner #quick li ul li {
518 border-bottom: 1px solid #ddd;
518 border-bottom: 1px solid #ddd;
519 }
519 }
520
520
521 #header #header-inner #quick li ul li a {
521 #header #header-inner #quick li ul li a {
522 width: 182px;
522 width: 182px;
523 height: auto;
523 height: auto;
524 display: block;
524 display: block;
525 float: left;
525 float: left;
526 background: #FFF;
526 background: #FFF;
527 color: #003367;
527 color: #003367;
528 font-weight: 400;
528 font-weight: 400;
529 margin: 0;
529 margin: 0;
530 padding: 7px 9px;
530 padding: 7px 9px;
531 }
531 }
532
532
533 #header #header-inner #quick li ul li a:hover {
533 #header #header-inner #quick li ul li a:hover {
534 color: #000;
534 color: #000;
535 background: #FFF;
535 background: #FFF;
536 }
536 }
537
537
538 #header #header-inner #quick ul ul {
538 #header #header-inner #quick ul ul {
539 top: auto;
539 top: auto;
540 }
540 }
541
541
542 #header #header-inner #quick li ul ul {
542 #header #header-inner #quick li ul ul {
543 right: 200px;
543 right: 200px;
544 max-height: 275px;
544 max-height: 275px;
545 overflow: auto;
545 overflow: auto;
546 overflow-x: hidden;
546 overflow-x: hidden;
547 white-space: normal;
547 white-space: normal;
548 }
548 }
549
549
550 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover
550 #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover
551 {
551 {
552 background: url("../images/icons/book.png") no-repeat scroll 4px 9px
552 background: url("../images/icons/book.png") no-repeat scroll 4px 9px
553 #FFF;
553 #FFF;
554 width: 167px;
554 width: 167px;
555 margin: 0;
555 margin: 0;
556 padding: 12px 9px 7px 24px;
556 padding: 12px 9px 7px 24px;
557 }
557 }
558
558
559 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover
559 #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover
560 {
560 {
561 background: url("../images/icons/lock.png") no-repeat scroll 4px 9px
561 background: url("../images/icons/lock.png") no-repeat scroll 4px 9px
562 #FFF;
562 #FFF;
563 min-width: 167px;
563 min-width: 167px;
564 margin: 0;
564 margin: 0;
565 padding: 12px 9px 7px 24px;
565 padding: 12px 9px 7px 24px;
566 }
566 }
567
567
568 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover
568 #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover
569 {
569 {
570 background: url("../images/icons/lock_open.png") no-repeat scroll 4px
570 background: url("../images/icons/lock_open.png") no-repeat scroll 4px
571 9px #FFF;
571 9px #FFF;
572 min-width: 167px;
572 min-width: 167px;
573 margin: 0;
573 margin: 0;
574 padding: 12px 9px 7px 24px;
574 padding: 12px 9px 7px 24px;
575 }
575 }
576
576
577 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover
577 #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover
578 {
578 {
579 background: url("../images/icons/hgicon.png") no-repeat scroll 4px 9px
579 background: url("../images/icons/hgicon.png") no-repeat scroll 4px 9px
580 #FFF;
580 #FFF;
581 min-width: 167px;
581 min-width: 167px;
582 margin: 0 0 0 14px;
582 margin: 0 0 0 14px;
583 padding: 12px 9px 7px 24px;
583 padding: 12px 9px 7px 24px;
584 }
584 }
585
585
586 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover
586 #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover
587 {
587 {
588 background: url("../images/icons/giticon.png") no-repeat scroll 4px 9px
588 background: url("../images/icons/giticon.png") no-repeat scroll 4px 9px
589 #FFF;
589 #FFF;
590 min-width: 167px;
590 min-width: 167px;
591 margin: 0 0 0 14px;
591 margin: 0 0 0 14px;
592 padding: 12px 9px 7px 24px;
592 padding: 12px 9px 7px 24px;
593 }
593 }
594
594
595 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover
595 #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover
596 {
596 {
597 background: url("../images/icons/database_edit.png") no-repeat scroll
597 background: url("../images/icons/database_edit.png") no-repeat scroll
598 4px 9px #FFF;
598 4px 9px #FFF;
599 width: 167px;
599 width: 167px;
600 margin: 0;
600 margin: 0;
601 padding: 12px 9px 7px 24px;
601 padding: 12px 9px 7px 24px;
602 }
602 }
603
603
604 #header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover
604 #header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover
605 {
605 {
606 background: url("../images/icons/database_link.png") no-repeat scroll
606 background: url("../images/icons/database_link.png") no-repeat scroll
607 4px 9px #FFF;
607 4px 9px #FFF;
608 width: 167px;
608 width: 167px;
609 margin: 0;
609 margin: 0;
610 padding: 12px 9px 7px 24px;
610 padding: 12px 9px 7px 24px;
611 }
611 }
612
612
613 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover
613 #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover
614 {
614 {
615 background: #FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
615 background: #FFF url("../images/icons/user_edit.png") no-repeat 4px 9px;
616 width: 167px;
616 width: 167px;
617 margin: 0;
617 margin: 0;
618 padding: 12px 9px 7px 24px;
618 padding: 12px 9px 7px 24px;
619 }
619 }
620
620
621 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover
621 #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover
622 {
622 {
623 background: #FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
623 background: #FFF url("../images/icons/group_edit.png") no-repeat 4px 9px;
624 width: 167px;
624 width: 167px;
625 margin: 0;
625 margin: 0;
626 padding: 12px 9px 7px 24px;
626 padding: 12px 9px 7px 24px;
627 }
627 }
628
628
629 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover
629 #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover
630 {
630 {
631 background: #FFF url("../images/icons/cog.png") no-repeat 4px 9px;
631 background: #FFF url("../images/icons/cog.png") no-repeat 4px 9px;
632 width: 167px;
632 width: 167px;
633 margin: 0;
633 margin: 0;
634 padding: 12px 9px 7px 24px;
634 padding: 12px 9px 7px 24px;
635 }
635 }
636
636
637 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover
637 #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover
638 {
638 {
639 background: #FFF url("../images/icons/key.png") no-repeat 4px 9px;
639 background: #FFF url("../images/icons/key.png") no-repeat 4px 9px;
640 width: 167px;
640 width: 167px;
641 margin: 0;
641 margin: 0;
642 padding: 12px 9px 7px 24px;
642 padding: 12px 9px 7px 24px;
643 }
643 }
644
644
645 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover
645 #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover
646 {
646 {
647 background: #FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
647 background: #FFF url("../images/icons/server_key.png") no-repeat 4px 9px;
648 width: 167px;
648 width: 167px;
649 margin: 0;
649 margin: 0;
650 padding: 12px 9px 7px 24px;
650 padding: 12px 9px 7px 24px;
651 }
651 }
652
652
653 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover
653 #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover
654 {
654 {
655 background: #FFF url("../images/icons/arrow_divide.png") no-repeat 4px
655 background: #FFF url("../images/icons/arrow_divide.png") no-repeat 4px
656 9px;
656 9px;
657 width: 167px;
657 width: 167px;
658 margin: 0;
658 margin: 0;
659 padding: 12px 9px 7px 24px;
659 padding: 12px 9px 7px 24px;
660 }
660 }
661
661
662 #header #header-inner #quick li ul li a.locking_add,#header #header-inner #quick li ul li a.locking_add:hover
662 #header #header-inner #quick li ul li a.locking_add,#header #header-inner #quick li ul li a.locking_add:hover
663 {
663 {
664 background: #FFF url("../images/icons/lock_add.png") no-repeat 4px
664 background: #FFF url("../images/icons/lock_add.png") no-repeat 4px
665 9px;
665 9px;
666 width: 167px;
666 width: 167px;
667 margin: 0;
667 margin: 0;
668 padding: 12px 9px 7px 24px;
668 padding: 12px 9px 7px 24px;
669 }
669 }
670
670
671 #header #header-inner #quick li ul li a.locking_del,#header #header-inner #quick li ul li a.locking_del:hover
671 #header #header-inner #quick li ul li a.locking_del,#header #header-inner #quick li ul li a.locking_del:hover
672 {
672 {
673 background: #FFF url("../images/icons/lock_delete.png") no-repeat 4px
673 background: #FFF url("../images/icons/lock_delete.png") no-repeat 4px
674 9px;
674 9px;
675 width: 167px;
675 width: 167px;
676 margin: 0;
676 margin: 0;
677 padding: 12px 9px 7px 24px;
677 padding: 12px 9px 7px 24px;
678 }
678 }
679
679
680 #header #header-inner #quick li ul li a.pull_request,#header #header-inner #quick li ul li a.pull_request:hover
680 #header #header-inner #quick li ul li a.pull_request,#header #header-inner #quick li ul li a.pull_request:hover
681 {
681 {
682 background: #FFF url("../images/icons/arrow_join.png") no-repeat 4px
682 background: #FFF url("../images/icons/arrow_join.png") no-repeat 4px
683 9px;
683 9px;
684 width: 167px;
684 width: 167px;
685 margin: 0;
685 margin: 0;
686 padding: 12px 9px 7px 24px;
686 padding: 12px 9px 7px 24px;
687 }
687 }
688
688
689 #header #header-inner #quick li ul li a.compare_request,#header #header-inner #quick li ul li a.compare_request:hover
689 #header #header-inner #quick li ul li a.compare_request,#header #header-inner #quick li ul li a.compare_request:hover
690 {
690 {
691 background: #FFF url("../images/icons/arrow_inout.png") no-repeat 4px
691 background: #FFF url("../images/icons/arrow_inout.png") no-repeat 4px
692 9px;
692 9px;
693 width: 167px;
693 width: 167px;
694 margin: 0;
694 margin: 0;
695 padding: 12px 9px 7px 24px;
695 padding: 12px 9px 7px 24px;
696 }
696 }
697
697
698 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover
698 #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover
699 {
699 {
700 background: #FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
700 background: #FFF url("../images/icons/search_16.png") no-repeat 4px 9px;
701 width: 167px;
701 width: 167px;
702 margin: 0;
702 margin: 0;
703 padding: 12px 9px 7px 24px;
703 padding: 12px 9px 7px 24px;
704 }
704 }
705
705
706 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover
706 #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover
707 {
707 {
708 background: #FFF url("../images/icons/delete.png") no-repeat 4px 9px;
708 background: #FFF url("../images/icons/delete.png") no-repeat 4px 9px;
709 width: 167px;
709 width: 167px;
710 margin: 0;
710 margin: 0;
711 padding: 12px 9px 7px 24px;
711 padding: 12px 9px 7px 24px;
712 }
712 }
713
713
714 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover
714 #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover
715 {
715 {
716 background: #FFF url("../images/icons/arrow_branch.png") no-repeat 4px
716 background: #FFF url("../images/icons/arrow_branch.png") no-repeat 4px
717 9px;
717 9px;
718 width: 167px;
718 width: 167px;
719 margin: 0;
719 margin: 0;
720 padding: 12px 9px 7px 24px;
720 padding: 12px 9px 7px 24px;
721 }
721 }
722
722
723 #header #header-inner #quick li ul li a.tags,
723 #header #header-inner #quick li ul li a.tags,
724 #header #header-inner #quick li ul li a.tags:hover{
724 #header #header-inner #quick li ul li a.tags:hover{
725 background: #FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
725 background: #FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px;
726 width: 167px;
726 width: 167px;
727 margin: 0;
727 margin: 0;
728 padding: 12px 9px 7px 24px;
728 padding: 12px 9px 7px 24px;
729 }
729 }
730
730
731 #header #header-inner #quick li ul li a.bookmarks,
731 #header #header-inner #quick li ul li a.bookmarks,
732 #header #header-inner #quick li ul li a.bookmarks:hover{
732 #header #header-inner #quick li ul li a.bookmarks:hover{
733 background: #FFF url("../images/icons/tag_green.png") no-repeat 4px 9px;
733 background: #FFF url("../images/icons/tag_green.png") no-repeat 4px 9px;
734 width: 167px;
734 width: 167px;
735 margin: 0;
735 margin: 0;
736 padding: 12px 9px 7px 24px;
736 padding: 12px 9px 7px 24px;
737 }
737 }
738
738
739 #header #header-inner #quick li ul li a.admin,
739 #header #header-inner #quick li ul li a.admin,
740 #header #header-inner #quick li ul li a.admin:hover{
740 #header #header-inner #quick li ul li a.admin:hover{
741 background: #FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
741 background: #FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px;
742 width: 167px;
742 width: 167px;
743 margin: 0;
743 margin: 0;
744 padding: 12px 9px 7px 24px;
744 padding: 12px 9px 7px 24px;
745 }
745 }
746
746
747 .groups_breadcrumbs a {
747 .groups_breadcrumbs a {
748 color: #fff;
748 color: #fff;
749 }
749 }
750
750
751 .groups_breadcrumbs a:hover {
751 .groups_breadcrumbs a:hover {
752 color: #bfe3ff;
752 color: #bfe3ff;
753 text-decoration: none;
753 text-decoration: none;
754 }
754 }
755
755
756 td.quick_repo_menu {
756 td.quick_repo_menu {
757 background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important;
757 background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important;
758 cursor: pointer;
758 cursor: pointer;
759 width: 8px;
759 width: 8px;
760 border: 1px solid transparent;
760 border: 1px solid transparent;
761 }
761 }
762
762
763 td.quick_repo_menu.active {
763 td.quick_repo_menu.active {
764 background: url("../images/dt-arrow-dn.png") no-repeat scroll 5px 50% #FFFFFF !important;
764 background: url("../images/dt-arrow-dn.png") no-repeat scroll 5px 50% #FFFFFF !important;
765 border: 1px solid #003367;
765 border: 1px solid #003367;
766 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
766 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
767 cursor: pointer;
767 cursor: pointer;
768 }
768 }
769
769
770 td.quick_repo_menu .menu_items {
770 td.quick_repo_menu .menu_items {
771 margin-top: 10px;
771 margin-top: 10px;
772 margin-left:-6px;
772 margin-left:-6px;
773 width: 150px;
773 width: 150px;
774 position: absolute;
774 position: absolute;
775 background-color: #FFF;
775 background-color: #FFF;
776 background: none repeat scroll 0 0 #FFFFFF;
776 background: none repeat scroll 0 0 #FFFFFF;
777 border-color: #003367 #666666 #666666;
777 border-color: #003367 #666666 #666666;
778 border-right: 1px solid #666666;
778 border-right: 1px solid #666666;
779 border-style: solid;
779 border-style: solid;
780 border-width: 1px;
780 border-width: 1px;
781 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
781 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
782 border-top-style: none;
782 border-top-style: none;
783 }
783 }
784
784
785 td.quick_repo_menu .menu_items li {
785 td.quick_repo_menu .menu_items li {
786 padding: 0 !important;
786 padding: 0 !important;
787 }
787 }
788
788
789 td.quick_repo_menu .menu_items a {
789 td.quick_repo_menu .menu_items a {
790 display: block;
790 display: block;
791 padding: 4px 12px 4px 8px;
791 padding: 4px 12px 4px 8px;
792 }
792 }
793
793
794 td.quick_repo_menu .menu_items a:hover {
794 td.quick_repo_menu .menu_items a:hover {
795 background-color: #EEE;
795 background-color: #EEE;
796 text-decoration: none;
796 text-decoration: none;
797 }
797 }
798
798
799 td.quick_repo_menu .menu_items .icon img {
799 td.quick_repo_menu .menu_items .icon img {
800 margin-bottom: -2px;
800 margin-bottom: -2px;
801 }
801 }
802
802
803 td.quick_repo_menu .menu_items.hidden {
803 td.quick_repo_menu .menu_items.hidden {
804 display: none;
804 display: none;
805 }
805 }
806
806
807 .yui-dt-first th {
807 .yui-dt-first th {
808 text-align: left;
808 text-align: left;
809 }
809 }
810
810
811 /*
811 /*
812 Copyright (c) 2011, Yahoo! Inc. All rights reserved.
812 Copyright (c) 2011, Yahoo! Inc. All rights reserved.
813 Code licensed under the BSD License:
813 Code licensed under the BSD License:
814 http://developer.yahoo.com/yui/license.html
814 http://developer.yahoo.com/yui/license.html
815 version: 2.9.0
815 version: 2.9.0
816 */
816 */
817 .yui-skin-sam .yui-dt-mask {
817 .yui-skin-sam .yui-dt-mask {
818 position: absolute;
818 position: absolute;
819 z-index: 9500;
819 z-index: 9500;
820 }
820 }
821 .yui-dt-tmp {
821 .yui-dt-tmp {
822 position: absolute;
822 position: absolute;
823 left: -9000px;
823 left: -9000px;
824 }
824 }
825 .yui-dt-scrollable .yui-dt-bd { overflow: auto }
825 .yui-dt-scrollable .yui-dt-bd { overflow: auto }
826 .yui-dt-scrollable .yui-dt-hd {
826 .yui-dt-scrollable .yui-dt-hd {
827 overflow: hidden;
827 overflow: hidden;
828 position: relative;
828 position: relative;
829 }
829 }
830 .yui-dt-scrollable .yui-dt-bd thead tr,
830 .yui-dt-scrollable .yui-dt-bd thead tr,
831 .yui-dt-scrollable .yui-dt-bd thead th {
831 .yui-dt-scrollable .yui-dt-bd thead th {
832 position: absolute;
832 position: absolute;
833 left: -1500px;
833 left: -1500px;
834 }
834 }
835 .yui-dt-scrollable tbody { -moz-outline: 0 }
835 .yui-dt-scrollable tbody { -moz-outline: 0 }
836 .yui-skin-sam thead .yui-dt-sortable { cursor: pointer }
836 .yui-skin-sam thead .yui-dt-sortable { cursor: pointer }
837 .yui-skin-sam thead .yui-dt-draggable { cursor: move }
837 .yui-skin-sam thead .yui-dt-draggable { cursor: move }
838 .yui-dt-coltarget {
838 .yui-dt-coltarget {
839 position: absolute;
839 position: absolute;
840 z-index: 999;
840 z-index: 999;
841 }
841 }
842 .yui-dt-hd { zoom: 1 }
842 .yui-dt-hd { zoom: 1 }
843 th.yui-dt-resizeable .yui-dt-resizerliner { position: relative }
843 th.yui-dt-resizeable .yui-dt-resizerliner { position: relative }
844 .yui-dt-resizer {
844 .yui-dt-resizer {
845 position: absolute;
845 position: absolute;
846 right: 0;
846 right: 0;
847 bottom: 0;
847 bottom: 0;
848 height: 100%;
848 height: 100%;
849 cursor: e-resize;
849 cursor: e-resize;
850 cursor: col-resize;
850 cursor: col-resize;
851 background-color: #CCC;
851 background-color: #CCC;
852 opacity: 0;
852 opacity: 0;
853 filter: alpha(opacity=0);
853 filter: alpha(opacity=0);
854 }
854 }
855 .yui-dt-resizerproxy {
855 .yui-dt-resizerproxy {
856 visibility: hidden;
856 visibility: hidden;
857 position: absolute;
857 position: absolute;
858 z-index: 9000;
858 z-index: 9000;
859 background-color: #CCC;
859 background-color: #CCC;
860 opacity: 0;
860 opacity: 0;
861 filter: alpha(opacity=0);
861 filter: alpha(opacity=0);
862 }
862 }
863 th.yui-dt-hidden .yui-dt-liner,
863 th.yui-dt-hidden .yui-dt-liner,
864 td.yui-dt-hidden .yui-dt-liner,
864 td.yui-dt-hidden .yui-dt-liner,
865 th.yui-dt-hidden .yui-dt-resizer { display: none }
865 th.yui-dt-hidden .yui-dt-resizer { display: none }
866 .yui-dt-editor,
866 .yui-dt-editor,
867 .yui-dt-editor-shim {
867 .yui-dt-editor-shim {
868 position: absolute;
868 position: absolute;
869 z-index: 9000;
869 z-index: 9000;
870 }
870 }
871 .yui-skin-sam .yui-dt table {
871 .yui-skin-sam .yui-dt table {
872 margin: 0;
872 margin: 0;
873 padding: 0;
873 padding: 0;
874 font-family: arial;
874 font-family: arial;
875 font-size: inherit;
875 font-size: inherit;
876 border-collapse: separate;
876 border-collapse: separate;
877 *border-collapse: collapse;
877 *border-collapse: collapse;
878 border-spacing: 0;
878 border-spacing: 0;
879 border: 1px solid #7f7f7f;
879 border: 1px solid #7f7f7f;
880 }
880 }
881 .yui-skin-sam .yui-dt thead { border-spacing: 0 }
881 .yui-skin-sam .yui-dt thead { border-spacing: 0 }
882 .yui-skin-sam .yui-dt caption {
882 .yui-skin-sam .yui-dt caption {
883 color: #000;
883 color: #000;
884 font-size: 85%;
884 font-size: 85%;
885 font-weight: normal;
885 font-weight: normal;
886 font-style: italic;
886 font-style: italic;
887 line-height: 1;
887 line-height: 1;
888 padding: 1em 0;
888 padding: 1em 0;
889 text-align: center;
889 text-align: center;
890 }
890 }
891 .yui-skin-sam .yui-dt th { background: #d8d8da url(../images/sprite.png) repeat-x 0 0 }
891 .yui-skin-sam .yui-dt th { background: #d8d8da url(../images/sprite.png) repeat-x 0 0 }
892 .yui-skin-sam .yui-dt th,
892 .yui-skin-sam .yui-dt th,
893 .yui-skin-sam .yui-dt th a {
893 .yui-skin-sam .yui-dt th a {
894 font-weight: normal;
894 font-weight: normal;
895 text-decoration: none;
895 text-decoration: none;
896 color: #000;
896 color: #000;
897 vertical-align: bottom;
897 vertical-align: bottom;
898 }
898 }
899 .yui-skin-sam .yui-dt th {
899 .yui-skin-sam .yui-dt th {
900 margin: 0;
900 margin: 0;
901 padding: 0;
901 padding: 0;
902 border: 0;
902 border: 0;
903 border-right: 1px solid #cbcbcb;
903 border-right: 1px solid #cbcbcb;
904 }
904 }
905 .yui-skin-sam .yui-dt tr.yui-dt-first td { border-top: 1px solid #7f7f7f }
905 .yui-skin-sam .yui-dt tr.yui-dt-first td { border-top: 1px solid #7f7f7f }
906 .yui-skin-sam .yui-dt th .yui-dt-liner { white-space: nowrap }
906 .yui-skin-sam .yui-dt th .yui-dt-liner { white-space: nowrap }
907 .yui-skin-sam .yui-dt-liner {
907 .yui-skin-sam .yui-dt-liner {
908 margin: 0;
908 margin: 0;
909 padding: 0;
909 padding: 0;
910 }
910 }
911 .yui-skin-sam .yui-dt-coltarget {
911 .yui-skin-sam .yui-dt-coltarget {
912 width: 5px;
912 width: 5px;
913 background-color: red;
913 background-color: red;
914 }
914 }
915 .yui-skin-sam .yui-dt td {
915 .yui-skin-sam .yui-dt td {
916 margin: 0;
916 margin: 0;
917 padding: 0;
917 padding: 0;
918 border: 0;
918 border: 0;
919 border-right: 1px solid #cbcbcb;
919 border-right: 1px solid #cbcbcb;
920 text-align: left;
920 text-align: left;
921 }
921 }
922 .yui-skin-sam .yui-dt-list td { border-right: 0 }
922 .yui-skin-sam .yui-dt-list td { border-right: 0 }
923 .yui-skin-sam .yui-dt-resizer { width: 6px }
923 .yui-skin-sam .yui-dt-resizer { width: 6px }
924 .yui-skin-sam .yui-dt-mask {
924 .yui-skin-sam .yui-dt-mask {
925 background-color: #000;
925 background-color: #000;
926 opacity: .25;
926 opacity: .25;
927 filter: alpha(opacity=25);
927 filter: alpha(opacity=25);
928 }
928 }
929 .yui-skin-sam .yui-dt-message { background-color: #FFF }
929 .yui-skin-sam .yui-dt-message { background-color: #FFF }
930 .yui-skin-sam .yui-dt-scrollable table { border: 0 }
930 .yui-skin-sam .yui-dt-scrollable table { border: 0 }
931 .yui-skin-sam .yui-dt-scrollable .yui-dt-hd {
931 .yui-skin-sam .yui-dt-scrollable .yui-dt-hd {
932 border-left: 1px solid #7f7f7f;
932 border-left: 1px solid #7f7f7f;
933 border-top: 1px solid #7f7f7f;
933 border-top: 1px solid #7f7f7f;
934 border-right: 1px solid #7f7f7f;
934 border-right: 1px solid #7f7f7f;
935 }
935 }
936 .yui-skin-sam .yui-dt-scrollable .yui-dt-bd {
936 .yui-skin-sam .yui-dt-scrollable .yui-dt-bd {
937 border-left: 1px solid #7f7f7f;
937 border-left: 1px solid #7f7f7f;
938 border-bottom: 1px solid #7f7f7f;
938 border-bottom: 1px solid #7f7f7f;
939 border-right: 1px solid #7f7f7f;
939 border-right: 1px solid #7f7f7f;
940 background-color: #FFF;
940 background-color: #FFF;
941 }
941 }
942 .yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td { border-bottom: 1px solid #7f7f7f }
942 .yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td { border-bottom: 1px solid #7f7f7f }
943 .yui-skin-sam th.yui-dt-asc,
943 .yui-skin-sam th.yui-dt-asc,
944 .yui-skin-sam th.yui-dt-desc { background: url(../images/sprite.png) repeat-x 0 -100px }
944 .yui-skin-sam th.yui-dt-desc { background: url(../images/sprite.png) repeat-x 0 -100px }
945 .yui-skin-sam th.yui-dt-sortable .yui-dt-label { margin-right: 10px }
945 .yui-skin-sam th.yui-dt-sortable .yui-dt-label { margin-right: 10px }
946 .yui-skin-sam th.yui-dt-asc .yui-dt-liner { background: url(../images/dt-arrow-up.png) no-repeat right }
946 .yui-skin-sam th.yui-dt-asc .yui-dt-liner { background: url(../images/dt-arrow-up.png) no-repeat right }
947 .yui-skin-sam th.yui-dt-desc .yui-dt-liner { background: url(../images/dt-arrow-dn.png) no-repeat right }
947 .yui-skin-sam th.yui-dt-desc .yui-dt-liner { background: url(../images/dt-arrow-dn.png) no-repeat right }
948 tbody .yui-dt-editable { cursor: pointer }
948 tbody .yui-dt-editable { cursor: pointer }
949 .yui-dt-editor {
949 .yui-dt-editor {
950 text-align: left;
950 text-align: left;
951 background-color: #f2f2f2;
951 background-color: #f2f2f2;
952 border: 1px solid #808080;
952 border: 1px solid #808080;
953 padding: 6px;
953 padding: 6px;
954 }
954 }
955 .yui-dt-editor label {
955 .yui-dt-editor label {
956 padding-left: 4px;
956 padding-left: 4px;
957 padding-right: 6px;
957 padding-right: 6px;
958 }
958 }
959 .yui-dt-editor .yui-dt-button {
959 .yui-dt-editor .yui-dt-button {
960 padding-top: 6px;
960 padding-top: 6px;
961 text-align: right;
961 text-align: right;
962 }
962 }
963 .yui-dt-editor .yui-dt-button button {
963 .yui-dt-editor .yui-dt-button button {
964 background: url(../images/sprite.png) repeat-x 0 0;
964 background: url(../images/sprite.png) repeat-x 0 0;
965 border: 1px solid #999;
965 border: 1px solid #999;
966 width: 4em;
966 width: 4em;
967 height: 1.8em;
967 height: 1.8em;
968 margin-left: 6px;
968 margin-left: 6px;
969 }
969 }
970 .yui-dt-editor .yui-dt-button button.yui-dt-default {
970 .yui-dt-editor .yui-dt-button button.yui-dt-default {
971 background: url(../images/sprite.png) repeat-x 0 -1400px;
971 background: url(../images/sprite.png) repeat-x 0 -1400px;
972 background-color: #5584e0;
972 background-color: #5584e0;
973 border: 1px solid #304369;
973 border: 1px solid #304369;
974 color: #FFF;
974 color: #FFF;
975 }
975 }
976 .yui-dt-editor .yui-dt-button button:hover {
976 .yui-dt-editor .yui-dt-button button:hover {
977 background: url(../images/sprite.png) repeat-x 0 -1300px;
977 background: url(../images/sprite.png) repeat-x 0 -1300px;
978 color: #000;
978 color: #000;
979 }
979 }
980 .yui-dt-editor .yui-dt-button button:active {
980 .yui-dt-editor .yui-dt-button button:active {
981 background: url(../images/sprite.png) repeat-x 0 -1700px;
981 background: url(../images/sprite.png) repeat-x 0 -1700px;
982 color: #000;
982 color: #000;
983 }
983 }
984 .yui-skin-sam tr.yui-dt-even { background-color: #FFF }
984 .yui-skin-sam tr.yui-dt-even { background-color: #FFF }
985 .yui-skin-sam tr.yui-dt-odd { background-color: #edf5ff }
985 .yui-skin-sam tr.yui-dt-odd { background-color: #edf5ff }
986 .yui-skin-sam tr.yui-dt-even td.yui-dt-asc,
986 .yui-skin-sam tr.yui-dt-even td.yui-dt-asc,
987 .yui-skin-sam tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
987 .yui-skin-sam tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
988 .yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,
988 .yui-skin-sam tr.yui-dt-odd td.yui-dt-asc,
989 .yui-skin-sam tr.yui-dt-odd td.yui-dt-desc { background-color: #dbeaff }
989 .yui-skin-sam tr.yui-dt-odd td.yui-dt-desc { background-color: #dbeaff }
990 .yui-skin-sam .yui-dt-list tr.yui-dt-even { background-color: #FFF }
990 .yui-skin-sam .yui-dt-list tr.yui-dt-even { background-color: #FFF }
991 .yui-skin-sam .yui-dt-list tr.yui-dt-odd { background-color: #FFF }
991 .yui-skin-sam .yui-dt-list tr.yui-dt-odd { background-color: #FFF }
992 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,
992 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc,
993 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
993 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff }
994 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,
994 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc,
995 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc { background-color: #edf5ff }
995 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc { background-color: #edf5ff }
996 .yui-skin-sam th.yui-dt-highlighted,
996 .yui-skin-sam th.yui-dt-highlighted,
997 .yui-skin-sam th.yui-dt-highlighted a { background-color: #b2d2ff }
997 .yui-skin-sam th.yui-dt-highlighted a { background-color: #b2d2ff }
998 .yui-skin-sam tr.yui-dt-highlighted,
998 .yui-skin-sam tr.yui-dt-highlighted,
999 .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,
999 .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc,
1000 .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,
1000 .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc,
1001 .yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,
1001 .yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted,
1002 .yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted {
1002 .yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted {
1003 cursor: pointer;
1003 cursor: pointer;
1004 background-color: #b2d2ff;
1004 background-color: #b2d2ff;
1005 }
1005 }
1006 .yui-skin-sam .yui-dt-list th.yui-dt-highlighted,
1006 .yui-skin-sam .yui-dt-list th.yui-dt-highlighted,
1007 .yui-skin-sam .yui-dt-list th.yui-dt-highlighted a { background-color: #b2d2ff }
1007 .yui-skin-sam .yui-dt-list th.yui-dt-highlighted a { background-color: #b2d2ff }
1008 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,
1008 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted,
1009 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,
1009 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc,
1010 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,
1010 .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc,
1011 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,
1011 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted,
1012 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted {
1012 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted {
1013 cursor: pointer;
1013 cursor: pointer;
1014 background-color: #b2d2ff;
1014 background-color: #b2d2ff;
1015 }
1015 }
1016 .yui-skin-sam th.yui-dt-selected,
1016 .yui-skin-sam th.yui-dt-selected,
1017 .yui-skin-sam th.yui-dt-selected a { background-color: #446cd7 }
1017 .yui-skin-sam th.yui-dt-selected a { background-color: #446cd7 }
1018 .yui-skin-sam tr.yui-dt-selected td,
1018 .yui-skin-sam tr.yui-dt-selected td,
1019 .yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,
1019 .yui-skin-sam tr.yui-dt-selected td.yui-dt-asc,
1020 .yui-skin-sam tr.yui-dt-selected td.yui-dt-desc {
1020 .yui-skin-sam tr.yui-dt-selected td.yui-dt-desc {
1021 background-color: #426fd9;
1021 background-color: #426fd9;
1022 color: #FFF;
1022 color: #FFF;
1023 }
1023 }
1024 .yui-skin-sam tr.yui-dt-even td.yui-dt-selected,
1024 .yui-skin-sam tr.yui-dt-even td.yui-dt-selected,
1025 .yui-skin-sam tr.yui-dt-odd td.yui-dt-selected {
1025 .yui-skin-sam tr.yui-dt-odd td.yui-dt-selected {
1026 background-color: #446cd7;
1026 background-color: #446cd7;
1027 color: #FFF;
1027 color: #FFF;
1028 }
1028 }
1029 .yui-skin-sam .yui-dt-list th.yui-dt-selected,
1029 .yui-skin-sam .yui-dt-list th.yui-dt-selected,
1030 .yui-skin-sam .yui-dt-list th.yui-dt-selected a { background-color: #446cd7 }
1030 .yui-skin-sam .yui-dt-list th.yui-dt-selected a { background-color: #446cd7 }
1031 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td,
1031 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td,
1032 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,
1032 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc,
1033 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc {
1033 .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc {
1034 background-color: #426fd9;
1034 background-color: #426fd9;
1035 color: #FFF;
1035 color: #FFF;
1036 }
1036 }
1037 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,
1037 .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected,
1038 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected {
1038 .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected {
1039 background-color: #446cd7;
1039 background-color: #446cd7;
1040 color: #FFF;
1040 color: #FFF;
1041 }
1041 }
1042 .yui-skin-sam .yui-dt-paginator {
1042 .yui-skin-sam .yui-dt-paginator {
1043 display: block;
1043 display: block;
1044 margin: 6px 0;
1044 margin: 6px 0;
1045 white-space: nowrap;
1045 white-space: nowrap;
1046 }
1046 }
1047 .yui-skin-sam .yui-dt-paginator .yui-dt-first,
1047 .yui-skin-sam .yui-dt-paginator .yui-dt-first,
1048 .yui-skin-sam .yui-dt-paginator .yui-dt-last,
1048 .yui-skin-sam .yui-dt-paginator .yui-dt-last,
1049 .yui-skin-sam .yui-dt-paginator .yui-dt-selected { padding: 2px 6px }
1049 .yui-skin-sam .yui-dt-paginator .yui-dt-selected { padding: 2px 6px }
1050 .yui-skin-sam .yui-dt-paginator a.yui-dt-first,
1050 .yui-skin-sam .yui-dt-paginator a.yui-dt-first,
1051 .yui-skin-sam .yui-dt-paginator a.yui-dt-last { text-decoration: none }
1051 .yui-skin-sam .yui-dt-paginator a.yui-dt-last { text-decoration: none }
1052 .yui-skin-sam .yui-dt-paginator .yui-dt-previous,
1052 .yui-skin-sam .yui-dt-paginator .yui-dt-previous,
1053 .yui-skin-sam .yui-dt-paginator .yui-dt-next { display: none }
1053 .yui-skin-sam .yui-dt-paginator .yui-dt-next { display: none }
1054 .yui-skin-sam a.yui-dt-page {
1054 .yui-skin-sam a.yui-dt-page {
1055 border: 1px solid #cbcbcb;
1055 border: 1px solid #cbcbcb;
1056 padding: 2px 6px;
1056 padding: 2px 6px;
1057 text-decoration: none;
1057 text-decoration: none;
1058 background-color: #fff;
1058 background-color: #fff;
1059 }
1059 }
1060 .yui-skin-sam .yui-dt-selected {
1060 .yui-skin-sam .yui-dt-selected {
1061 border: 1px solid #fff;
1061 border: 1px solid #fff;
1062 background-color: #fff;
1062 background-color: #fff;
1063 }
1063 }
1064
1064
1065 #content #left {
1065 #content #left {
1066 left: 0;
1066 left: 0;
1067 width: 280px;
1067 width: 280px;
1068 position: absolute;
1068 position: absolute;
1069 }
1069 }
1070
1070
1071 #content #right {
1071 #content #right {
1072 margin: 0 60px 10px 290px;
1072 margin: 0 60px 10px 290px;
1073 }
1073 }
1074
1074
1075 #content div.box {
1075 #content div.box {
1076 clear: both;
1076 clear: both;
1077 overflow: hidden;
1077 overflow: hidden;
1078 background: #fff;
1078 background: #fff;
1079 margin: 0 0 10px;
1079 margin: 0 0 10px;
1080 padding: 0 0 10px;
1080 padding: 0 0 10px;
1081 -webkit-border-radius: 4px 4px 4px 4px;
1081 -webkit-border-radius: 4px 4px 4px 4px;
1082 -khtml-border-radius: 4px 4px 4px 4px;
1082 -khtml-border-radius: 4px 4px 4px 4px;
1083 -moz-border-radius: 4px 4px 4px 4px;
1083 -moz-border-radius: 4px 4px 4px 4px;
1084 border-radius: 4px 4px 4px 4px;
1084 border-radius: 4px 4px 4px 4px;
1085 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1085 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1086 }
1086 }
1087
1087
1088 #content div.box-left {
1088 #content div.box-left {
1089 width: 49%;
1089 width: 49%;
1090 clear: none;
1090 clear: none;
1091 float: left;
1091 float: left;
1092 margin: 0 0 10px;
1092 margin: 0 0 10px;
1093 }
1093 }
1094
1094
1095 #content div.box-right {
1095 #content div.box-right {
1096 width: 49%;
1096 width: 49%;
1097 clear: none;
1097 clear: none;
1098 float: right;
1098 float: right;
1099 margin: 0 0 10px;
1099 margin: 0 0 10px;
1100 }
1100 }
1101
1101
1102 #content div.box div.title {
1102 #content div.box div.title {
1103 clear: both;
1103 clear: both;
1104 overflow: hidden;
1104 overflow: hidden;
1105 background-color: #003B76;
1105 background-color: #003B76;
1106 background-repeat: repeat-x;
1106 background-repeat: repeat-x;
1107 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
1107 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
1108 background-image: -moz-linear-gradient(top, #003b76, #00376e);
1108 background-image: -moz-linear-gradient(top, #003b76, #00376e);
1109 background-image: -ms-linear-gradient(top, #003b76, #00376e);
1109 background-image: -ms-linear-gradient(top, #003b76, #00376e);
1110 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
1110 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
1111 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
1111 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
1112 background-image: -o-linear-gradient(top, #003b76, #00376e);
1112 background-image: -o-linear-gradient(top, #003b76, #00376e);
1113 background-image: linear-gradient(top, #003b76, #00376e);
1113 background-image: linear-gradient(top, #003b76, #00376e);
1114 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
1114 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
1115 margin: 0 0 20px;
1115 margin: 0 0 20px;
1116 padding: 0;
1116 padding: 0;
1117 }
1117 }
1118
1118
1119 #content div.box div.title h5 {
1119 #content div.box div.title h5 {
1120 float: left;
1120 float: left;
1121 border: none;
1121 border: none;
1122 color: #fff;
1122 color: #fff;
1123 text-transform: uppercase;
1123 text-transform: uppercase;
1124 margin: 0;
1124 margin: 0;
1125 padding: 11px 0 11px 10px;
1125 padding: 11px 0 11px 10px;
1126 }
1126 }
1127
1127
1128 #content div.box div.title .link-white{
1128 #content div.box div.title .link-white{
1129 color: #FFFFFF;
1129 color: #FFFFFF;
1130 }
1130 }
1131
1131
1132 #content div.box div.title .link-white.current{
1132 #content div.box div.title .link-white.current{
1133 color: #BFE3FF;
1133 color: #BFE3FF;
1134 }
1134 }
1135
1135
1136 #content div.box div.title ul.links li {
1136 #content div.box div.title ul.links li {
1137 list-style: none;
1137 list-style: none;
1138 float: left;
1138 float: left;
1139 margin: 0;
1139 margin: 0;
1140 padding: 0;
1140 padding: 0;
1141 }
1141 }
1142
1142
1143 #content div.box div.title ul.links li a {
1143 #content div.box div.title ul.links li a {
1144 border-left: 1px solid #316293;
1144 border-left: 1px solid #316293;
1145 color: #FFFFFF;
1145 color: #FFFFFF;
1146 display: block;
1146 display: block;
1147 float: left;
1147 float: left;
1148 font-size: 13px;
1148 font-size: 13px;
1149 font-weight: 700;
1149 font-weight: 700;
1150 height: 1%;
1150 height: 1%;
1151 margin: 0;
1151 margin: 0;
1152 padding: 11px 22px 12px;
1152 padding: 11px 22px 12px;
1153 text-decoration: none;
1153 text-decoration: none;
1154 }
1154 }
1155
1155
1156 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6,
1156 #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6,
1157 #content div.box div.h1,#content div.box div.h2,#content div.box div.h3,#content div.box div.h4,#content div.box div.h5,#content div.box div.h6
1157 #content div.box div.h1,#content div.box div.h2,#content div.box div.h3,#content div.box div.h4,#content div.box div.h5,#content div.box div.h6
1158
1158
1159 {
1159 {
1160 clear: both;
1160 clear: both;
1161 overflow: hidden;
1161 overflow: hidden;
1162 border-bottom: 1px solid #DDD;
1162 border-bottom: 1px solid #DDD;
1163 margin: 10px 20px;
1163 margin: 10px 20px;
1164 padding: 0 0 15px;
1164 padding: 0 0 15px;
1165 }
1165 }
1166
1166
1167 #content div.box p {
1167 #content div.box p {
1168 color: #5f5f5f;
1168 color: #5f5f5f;
1169 font-size: 12px;
1169 font-size: 12px;
1170 line-height: 150%;
1170 line-height: 150%;
1171 margin: 0 24px 10px;
1171 margin: 0 24px 10px;
1172 padding: 0;
1172 padding: 0;
1173 }
1173 }
1174
1174
1175 #content div.box blockquote {
1175 #content div.box blockquote {
1176 border-left: 4px solid #DDD;
1176 border-left: 4px solid #DDD;
1177 color: #5f5f5f;
1177 color: #5f5f5f;
1178 font-size: 11px;
1178 font-size: 11px;
1179 line-height: 150%;
1179 line-height: 150%;
1180 margin: 0 34px;
1180 margin: 0 34px;
1181 padding: 0 0 0 14px;
1181 padding: 0 0 0 14px;
1182 }
1182 }
1183
1183
1184 #content div.box blockquote p {
1184 #content div.box blockquote p {
1185 margin: 10px 0;
1185 margin: 10px 0;
1186 padding: 0;
1186 padding: 0;
1187 }
1187 }
1188
1188
1189 #content div.box dl {
1189 #content div.box dl {
1190 margin: 10px 0px;
1190 margin: 10px 0px;
1191 }
1191 }
1192
1192
1193 #content div.box dt {
1193 #content div.box dt {
1194 font-size: 12px;
1194 font-size: 12px;
1195 margin: 0;
1195 margin: 0;
1196 }
1196 }
1197
1197
1198 #content div.box dd {
1198 #content div.box dd {
1199 font-size: 12px;
1199 font-size: 12px;
1200 margin: 0;
1200 margin: 0;
1201 padding: 8px 0 8px 15px;
1201 padding: 8px 0 8px 15px;
1202 }
1202 }
1203
1203
1204 #content div.box li {
1204 #content div.box li {
1205 font-size: 12px;
1205 font-size: 12px;
1206 padding: 4px 0;
1206 padding: 4px 0;
1207 }
1207 }
1208
1208
1209 #content div.box ul.disc,#content div.box ul.circle {
1209 #content div.box ul.disc,#content div.box ul.circle {
1210 margin: 10px 24px 10px 38px;
1210 margin: 10px 24px 10px 38px;
1211 }
1211 }
1212
1212
1213 #content div.box ul.square {
1213 #content div.box ul.square {
1214 margin: 10px 24px 10px 40px;
1214 margin: 10px 24px 10px 40px;
1215 }
1215 }
1216
1216
1217 #content div.box img.left {
1217 #content div.box img.left {
1218 border: none;
1218 border: none;
1219 float: left;
1219 float: left;
1220 margin: 10px 10px 10px 0;
1220 margin: 10px 10px 10px 0;
1221 }
1221 }
1222
1222
1223 #content div.box img.right {
1223 #content div.box img.right {
1224 border: none;
1224 border: none;
1225 float: right;
1225 float: right;
1226 margin: 10px 0 10px 10px;
1226 margin: 10px 0 10px 10px;
1227 }
1227 }
1228
1228
1229 #content div.box div.messages {
1229 #content div.box div.messages {
1230 clear: both;
1230 clear: both;
1231 overflow: hidden;
1231 overflow: hidden;
1232 margin: 0 20px;
1232 margin: 0 20px;
1233 padding: 0;
1233 padding: 0;
1234 }
1234 }
1235
1235
1236 #content div.box div.message {
1236 #content div.box div.message {
1237 clear: both;
1237 clear: both;
1238 overflow: hidden;
1238 overflow: hidden;
1239 margin: 0;
1239 margin: 0;
1240 padding: 5px 0;
1240 padding: 5px 0;
1241 white-space: pre-wrap;
1241 white-space: pre-wrap;
1242 }
1242 }
1243 #content div.box div.expand {
1243 #content div.box div.expand {
1244 width: 110%;
1244 width: 110%;
1245 height:14px;
1245 height:14px;
1246 font-size:10px;
1246 font-size:10px;
1247 text-align:center;
1247 text-align:center;
1248 cursor: pointer;
1248 cursor: pointer;
1249 color:#666;
1249 color:#666;
1250
1250
1251 background:-webkit-gradient(linear,0% 50%,100% 50%,color-stop(0%,rgba(255,255,255,0)),color-stop(100%,rgba(64,96,128,0.1)));
1251 background:-webkit-gradient(linear,0% 50%,100% 50%,color-stop(0%,rgba(255,255,255,0)),color-stop(100%,rgba(64,96,128,0.1)));
1252 background:-webkit-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1252 background:-webkit-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1253 background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1253 background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1254 background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1254 background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1255 background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1255 background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1256 background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1256 background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1));
1257
1257
1258 display: none;
1258 display: none;
1259 }
1259 }
1260 #content div.box div.expand .expandtext {
1260 #content div.box div.expand .expandtext {
1261 background-color: #ffffff;
1261 background-color: #ffffff;
1262 padding: 2px;
1262 padding: 2px;
1263 border-radius: 2px;
1263 border-radius: 2px;
1264 }
1264 }
1265
1265
1266 #content div.box div.message a {
1266 #content div.box div.message a {
1267 font-weight: 400 !important;
1267 font-weight: 400 !important;
1268 }
1268 }
1269
1269
1270 #content div.box div.message div.image {
1270 #content div.box div.message div.image {
1271 float: left;
1271 float: left;
1272 margin: 9px 0 0 5px;
1272 margin: 9px 0 0 5px;
1273 padding: 6px;
1273 padding: 6px;
1274 }
1274 }
1275
1275
1276 #content div.box div.message div.image img {
1276 #content div.box div.message div.image img {
1277 vertical-align: middle;
1277 vertical-align: middle;
1278 margin: 0;
1278 margin: 0;
1279 }
1279 }
1280
1280
1281 #content div.box div.message div.text {
1281 #content div.box div.message div.text {
1282 float: left;
1282 float: left;
1283 margin: 0;
1283 margin: 0;
1284 padding: 9px 6px;
1284 padding: 9px 6px;
1285 }
1285 }
1286
1286
1287 #content div.box div.message div.dismiss a {
1287 #content div.box div.message div.dismiss a {
1288 height: 16px;
1288 height: 16px;
1289 width: 16px;
1289 width: 16px;
1290 display: block;
1290 display: block;
1291 background: url("../images/icons/cross.png") no-repeat;
1291 background: url("../images/icons/cross.png") no-repeat;
1292 margin: 15px 14px 0 0;
1292 margin: 15px 14px 0 0;
1293 padding: 0;
1293 padding: 0;
1294 }
1294 }
1295
1295
1296 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6
1296 #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6
1297 {
1297 {
1298 border: none;
1298 border: none;
1299 margin: 0;
1299 margin: 0;
1300 padding: 0;
1300 padding: 0;
1301 }
1301 }
1302
1302
1303 #content div.box div.message div.text span {
1303 #content div.box div.message div.text span {
1304 height: 1%;
1304 height: 1%;
1305 display: block;
1305 display: block;
1306 margin: 0;
1306 margin: 0;
1307 padding: 5px 0 0;
1307 padding: 5px 0 0;
1308 }
1308 }
1309
1309
1310 #content div.box div.message-error {
1310 #content div.box div.message-error {
1311 height: 1%;
1311 height: 1%;
1312 clear: both;
1312 clear: both;
1313 overflow: hidden;
1313 overflow: hidden;
1314 background: #FBE3E4;
1314 background: #FBE3E4;
1315 border: 1px solid #FBC2C4;
1315 border: 1px solid #FBC2C4;
1316 color: #860006;
1316 color: #860006;
1317 }
1317 }
1318
1318
1319 #content div.box div.message-error h6 {
1319 #content div.box div.message-error h6 {
1320 color: #860006;
1320 color: #860006;
1321 }
1321 }
1322
1322
1323 #content div.box div.message-warning {
1323 #content div.box div.message-warning {
1324 height: 1%;
1324 height: 1%;
1325 clear: both;
1325 clear: both;
1326 overflow: hidden;
1326 overflow: hidden;
1327 background: #FFF6BF;
1327 background: #FFF6BF;
1328 border: 1px solid #FFD324;
1328 border: 1px solid #FFD324;
1329 color: #5f5200;
1329 color: #5f5200;
1330 }
1330 }
1331
1331
1332 #content div.box div.message-warning h6 {
1332 #content div.box div.message-warning h6 {
1333 color: #5f5200;
1333 color: #5f5200;
1334 }
1334 }
1335
1335
1336 #content div.box div.message-notice {
1336 #content div.box div.message-notice {
1337 height: 1%;
1337 height: 1%;
1338 clear: both;
1338 clear: both;
1339 overflow: hidden;
1339 overflow: hidden;
1340 background: #8FBDE0;
1340 background: #8FBDE0;
1341 border: 1px solid #6BACDE;
1341 border: 1px solid #6BACDE;
1342 color: #003863;
1342 color: #003863;
1343 }
1343 }
1344
1344
1345 #content div.box div.message-notice h6 {
1345 #content div.box div.message-notice h6 {
1346 color: #003863;
1346 color: #003863;
1347 }
1347 }
1348
1348
1349 #content div.box div.message-success {
1349 #content div.box div.message-success {
1350 height: 1%;
1350 height: 1%;
1351 clear: both;
1351 clear: both;
1352 overflow: hidden;
1352 overflow: hidden;
1353 background: #E6EFC2;
1353 background: #E6EFC2;
1354 border: 1px solid #C6D880;
1354 border: 1px solid #C6D880;
1355 color: #4e6100;
1355 color: #4e6100;
1356 }
1356 }
1357
1357
1358 #content div.box div.message-success h6 {
1358 #content div.box div.message-success h6 {
1359 color: #4e6100;
1359 color: #4e6100;
1360 }
1360 }
1361
1361
1362 #content div.box div.form div.fields div.field {
1362 #content div.box div.form div.fields div.field {
1363 height: 1%;
1363 height: 1%;
1364 border-bottom: 1px solid #DDD;
1364 border-bottom: 1px solid #DDD;
1365 clear: both;
1365 clear: both;
1366 margin: 0;
1366 margin: 0;
1367 padding: 10px 0;
1367 padding: 10px 0;
1368 }
1368 }
1369
1369
1370 #content div.box div.form div.fields div.field-first {
1370 #content div.box div.form div.fields div.field-first {
1371 padding: 0 0 10px;
1371 padding: 0 0 10px;
1372 }
1372 }
1373
1373
1374 #content div.box div.form div.fields div.field-noborder {
1374 #content div.box div.form div.fields div.field-noborder {
1375 border-bottom: 0 !important;
1375 border-bottom: 0 !important;
1376 }
1376 }
1377
1377
1378 #content div.box div.form div.fields div.field span.error-message {
1378 #content div.box div.form div.fields div.field span.error-message {
1379 height: 1%;
1379 height: 1%;
1380 display: inline-block;
1380 display: inline-block;
1381 color: red;
1381 color: red;
1382 margin: 8px 0 0 4px;
1382 margin: 8px 0 0 4px;
1383 padding: 0;
1383 padding: 0;
1384 }
1384 }
1385
1385
1386 #content div.box div.form div.fields div.field span.success {
1386 #content div.box div.form div.fields div.field span.success {
1387 height: 1%;
1387 height: 1%;
1388 display: block;
1388 display: block;
1389 color: #316309;
1389 color: #316309;
1390 margin: 8px 0 0;
1390 margin: 8px 0 0;
1391 padding: 0;
1391 padding: 0;
1392 }
1392 }
1393
1393
1394 #content div.box div.form div.fields div.field div.label {
1394 #content div.box div.form div.fields div.field div.label {
1395 left: 70px;
1395 left: 70px;
1396 width: 155px;
1396 width: 155px;
1397 position: absolute;
1397 position: absolute;
1398 margin: 0;
1398 margin: 0;
1399 padding: 5px 0 0 0px;
1399 padding: 5px 0 0 0px;
1400 }
1400 }
1401
1401
1402 #content div.box div.form div.fields div.field div.label-summary {
1402 #content div.box div.form div.fields div.field div.label-summary {
1403 left: 30px;
1403 left: 30px;
1404 width: 155px;
1404 width: 155px;
1405 position: absolute;
1405 position: absolute;
1406 margin: 0;
1406 margin: 0;
1407 padding: 0px 0 0 0px;
1407 padding: 0px 0 0 0px;
1408 }
1408 }
1409
1409
1410 #content div.box-left div.form div.fields div.field div.label,
1410 #content div.box-left div.form div.fields div.field div.label,
1411 #content div.box-right div.form div.fields div.field div.label,
1411 #content div.box-right div.form div.fields div.field div.label,
1412 #content div.box-left div.form div.fields div.field div.label,
1412 #content div.box-left div.form div.fields div.field div.label,
1413 #content div.box-left div.form div.fields div.field div.label-summary,
1413 #content div.box-left div.form div.fields div.field div.label-summary,
1414 #content div.box-right div.form div.fields div.field div.label-summary,
1414 #content div.box-right div.form div.fields div.field div.label-summary,
1415 #content div.box-left div.form div.fields div.field div.label-summary
1415 #content div.box-left div.form div.fields div.field div.label-summary
1416 {
1416 {
1417 clear: both;
1417 clear: both;
1418 overflow: hidden;
1418 overflow: hidden;
1419 left: 0;
1419 left: 0;
1420 width: auto;
1420 width: auto;
1421 position: relative;
1421 position: relative;
1422 margin: 0;
1422 margin: 0;
1423 padding: 0 0 8px;
1423 padding: 0 0 8px;
1424 }
1424 }
1425
1425
1426 #content div.box div.form div.fields div.field div.label-select {
1426 #content div.box div.form div.fields div.field div.label-select {
1427 padding: 5px 0 0 5px;
1427 padding: 5px 0 0 5px;
1428 }
1428 }
1429
1429
1430 #content div.box-left div.form div.fields div.field div.label-select,
1430 #content div.box-left div.form div.fields div.field div.label-select,
1431 #content div.box-right div.form div.fields div.field div.label-select
1431 #content div.box-right div.form div.fields div.field div.label-select
1432 {
1432 {
1433 padding: 0 0 8px;
1433 padding: 0 0 8px;
1434 }
1434 }
1435
1435
1436 #content div.box-left div.form div.fields div.field div.label-textarea,
1436 #content div.box-left div.form div.fields div.field div.label-textarea,
1437 #content div.box-right div.form div.fields div.field div.label-textarea
1437 #content div.box-right div.form div.fields div.field div.label-textarea
1438 {
1438 {
1439 padding: 0 0 8px !important;
1439 padding: 0 0 8px !important;
1440 }
1440 }
1441
1441
1442 #content div.box div.form div.fields div.field div.label label,div.label label
1442 #content div.box div.form div.fields div.field div.label label,div.label label
1443 {
1443 {
1444 color: #393939;
1444 color: #393939;
1445 font-weight: 700;
1445 font-weight: 700;
1446 }
1446 }
1447 #content div.box div.form div.fields div.field div.label label,div.label-summary label
1447 #content div.box div.form div.fields div.field div.label label,div.label-summary label
1448 {
1448 {
1449 color: #393939;
1449 color: #393939;
1450 font-weight: 700;
1450 font-weight: 700;
1451 }
1451 }
1452 #content div.box div.form div.fields div.field div.input {
1452 #content div.box div.form div.fields div.field div.input {
1453 margin: 0 0 0 200px;
1453 margin: 0 0 0 200px;
1454 }
1454 }
1455
1455
1456 #content div.box div.form div.fields div.field div.input.summary {
1456 #content div.box div.form div.fields div.field div.input.summary {
1457 margin: 0 0 0 110px;
1457 margin: 0 0 0 110px;
1458 }
1458 }
1459 #content div.box div.form div.fields div.field div.input.summary-short {
1459 #content div.box div.form div.fields div.field div.input.summary-short {
1460 margin: 0 0 0 110px;
1460 margin: 0 0 0 110px;
1461 }
1461 }
1462 #content div.box div.form div.fields div.field div.file {
1462 #content div.box div.form div.fields div.field div.file {
1463 margin: 0 0 0 200px;
1463 margin: 0 0 0 200px;
1464 }
1464 }
1465
1465
1466 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input
1466 #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input
1467 {
1467 {
1468 margin: 0 0 0 0px;
1468 margin: 0 0 0 0px;
1469 }
1469 }
1470
1470
1471 #content div.box div.form div.fields div.field div.input input,
1471 #content div.box div.form div.fields div.field div.input input,
1472 .reviewer_ac input {
1472 .reviewer_ac input {
1473 background: #FFF;
1473 background: #FFF;
1474 border-top: 1px solid #b3b3b3;
1474 border-top: 1px solid #b3b3b3;
1475 border-left: 1px solid #b3b3b3;
1475 border-left: 1px solid #b3b3b3;
1476 border-right: 1px solid #eaeaea;
1476 border-right: 1px solid #eaeaea;
1477 border-bottom: 1px solid #eaeaea;
1477 border-bottom: 1px solid #eaeaea;
1478 color: #000;
1478 color: #000;
1479 font-size: 11px;
1479 font-size: 11px;
1480 margin: 0;
1480 margin: 0;
1481 padding: 7px 7px 6px;
1481 padding: 7px 7px 6px;
1482 }
1482 }
1483
1483
1484 #content div.box div.form div.fields div.field div.input input#clone_url,
1484 #content div.box div.form div.fields div.field div.input input#clone_url,
1485 #content div.box div.form div.fields div.field div.input input#clone_url_id
1485 #content div.box div.form div.fields div.field div.input input#clone_url_id
1486 {
1486 {
1487 font-size: 16px;
1487 font-size: 16px;
1488 padding: 2px;
1488 padding: 2px;
1489 }
1489 }
1490
1490
1491 #content div.box div.form div.fields div.field div.file input {
1491 #content div.box div.form div.fields div.field div.file input {
1492 background: none repeat scroll 0 0 #FFFFFF;
1492 background: none repeat scroll 0 0 #FFFFFF;
1493 border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
1493 border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3;
1494 border-style: solid;
1494 border-style: solid;
1495 border-width: 1px;
1495 border-width: 1px;
1496 color: #000000;
1496 color: #000000;
1497 font-size: 11px;
1497 font-size: 11px;
1498 margin: 0;
1498 margin: 0;
1499 padding: 7px 7px 6px;
1499 padding: 7px 7px 6px;
1500 }
1500 }
1501
1501
1502 input.disabled {
1502 input.disabled {
1503 background-color: #F5F5F5 !important;
1503 background-color: #F5F5F5 !important;
1504 }
1504 }
1505 #content div.box div.form div.fields div.field div.input input.small {
1505 #content div.box div.form div.fields div.field div.input input.small {
1506 width: 30%;
1506 width: 30%;
1507 }
1507 }
1508
1508
1509 #content div.box div.form div.fields div.field div.input input.medium {
1509 #content div.box div.form div.fields div.field div.input input.medium {
1510 width: 55%;
1510 width: 55%;
1511 }
1511 }
1512
1512
1513 #content div.box div.form div.fields div.field div.input input.large {
1513 #content div.box div.form div.fields div.field div.input input.large {
1514 width: 85%;
1514 width: 85%;
1515 }
1515 }
1516
1516
1517 #content div.box div.form div.fields div.field div.input input.date {
1517 #content div.box div.form div.fields div.field div.input input.date {
1518 width: 177px;
1518 width: 177px;
1519 }
1519 }
1520
1520
1521 #content div.box div.form div.fields div.field div.input input.button {
1521 #content div.box div.form div.fields div.field div.input input.button {
1522 background: #D4D0C8;
1522 background: #D4D0C8;
1523 border-top: 1px solid #FFF;
1523 border-top: 1px solid #FFF;
1524 border-left: 1px solid #FFF;
1524 border-left: 1px solid #FFF;
1525 border-right: 1px solid #404040;
1525 border-right: 1px solid #404040;
1526 border-bottom: 1px solid #404040;
1526 border-bottom: 1px solid #404040;
1527 color: #000;
1527 color: #000;
1528 margin: 0;
1528 margin: 0;
1529 padding: 4px 8px;
1529 padding: 4px 8px;
1530 }
1530 }
1531
1531
1532 #content div.box div.form div.fields div.field div.textarea {
1532 #content div.box div.form div.fields div.field div.textarea {
1533 border-top: 1px solid #b3b3b3;
1533 border-top: 1px solid #b3b3b3;
1534 border-left: 1px solid #b3b3b3;
1534 border-left: 1px solid #b3b3b3;
1535 border-right: 1px solid #eaeaea;
1535 border-right: 1px solid #eaeaea;
1536 border-bottom: 1px solid #eaeaea;
1536 border-bottom: 1px solid #eaeaea;
1537 margin: 0 0 0 200px;
1537 margin: 0 0 0 200px;
1538 padding: 10px;
1538 padding: 10px;
1539 }
1539 }
1540
1540
1541 #content div.box div.form div.fields div.field div.textarea-editor {
1541 #content div.box div.form div.fields div.field div.textarea-editor {
1542 border: 1px solid #ddd;
1542 border: 1px solid #ddd;
1543 padding: 0;
1543 padding: 0;
1544 }
1544 }
1545
1545
1546 #content div.box div.form div.fields div.field div.textarea textarea {
1546 #content div.box div.form div.fields div.field div.textarea textarea {
1547 width: 100%;
1547 width: 100%;
1548 height: 220px;
1548 height: 220px;
1549 overflow: hidden;
1549 overflow: hidden;
1550 background: #FFF;
1550 background: #FFF;
1551 color: #000;
1551 color: #000;
1552 font-size: 11px;
1552 font-size: 11px;
1553 outline: none;
1553 outline: none;
1554 border-width: 0;
1554 border-width: 0;
1555 margin: 0;
1555 margin: 0;
1556 padding: 0;
1556 padding: 0;
1557 }
1557 }
1558
1558
1559 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea
1559 #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea
1560 {
1560 {
1561 width: 100%;
1561 width: 100%;
1562 height: 100px;
1562 height: 100px;
1563 }
1563 }
1564
1564
1565 #content div.box div.form div.fields div.field div.textarea table {
1565 #content div.box div.form div.fields div.field div.textarea table {
1566 width: 100%;
1566 width: 100%;
1567 border: none;
1567 border: none;
1568 margin: 0;
1568 margin: 0;
1569 padding: 0;
1569 padding: 0;
1570 }
1570 }
1571
1571
1572 #content div.box div.form div.fields div.field div.textarea table td {
1572 #content div.box div.form div.fields div.field div.textarea table td {
1573 background: #DDD;
1573 background: #DDD;
1574 border: none;
1574 border: none;
1575 padding: 0;
1575 padding: 0;
1576 }
1576 }
1577
1577
1578 #content div.box div.form div.fields div.field div.textarea table td table
1578 #content div.box div.form div.fields div.field div.textarea table td table
1579 {
1579 {
1580 width: auto;
1580 width: auto;
1581 border: none;
1581 border: none;
1582 margin: 0;
1582 margin: 0;
1583 padding: 0;
1583 padding: 0;
1584 }
1584 }
1585
1585
1586 #content div.box div.form div.fields div.field div.textarea table td table td
1586 #content div.box div.form div.fields div.field div.textarea table td table td
1587 {
1587 {
1588 font-size: 11px;
1588 font-size: 11px;
1589 padding: 5px 5px 5px 0;
1589 padding: 5px 5px 5px 0;
1590 }
1590 }
1591
1591
1592 #content div.box div.form div.fields div.field input[type=text]:focus,
1592 #content div.box div.form div.fields div.field input[type=text]:focus,
1593 #content div.box div.form div.fields div.field input[type=password]:focus,
1593 #content div.box div.form div.fields div.field input[type=password]:focus,
1594 #content div.box div.form div.fields div.field input[type=file]:focus,
1594 #content div.box div.form div.fields div.field input[type=file]:focus,
1595 #content div.box div.form div.fields div.field textarea:focus,
1595 #content div.box div.form div.fields div.field textarea:focus,
1596 #content div.box div.form div.fields div.field select:focus,
1596 #content div.box div.form div.fields div.field select:focus,
1597 .reviewer_ac input:focus
1597 .reviewer_ac input:focus
1598 {
1598 {
1599 background: #f6f6f6;
1599 background: #f6f6f6;
1600 border-color: #666;
1600 border-color: #666;
1601 }
1601 }
1602
1602
1603 .reviewer_ac {
1603 .reviewer_ac {
1604 padding:10px
1604 padding:10px
1605 }
1605 }
1606
1606
1607 div.form div.fields div.field div.button {
1607 div.form div.fields div.field div.button {
1608 margin: 0;
1608 margin: 0;
1609 padding: 0 0 0 8px;
1609 padding: 0 0 0 8px;
1610 }
1610 }
1611 #content div.box table.noborder {
1611 #content div.box table.noborder {
1612 border: 1px solid transparent;
1612 border: 1px solid transparent;
1613 }
1613 }
1614
1614
1615 #content div.box table {
1615 #content div.box table {
1616 width: 100%;
1616 width: 100%;
1617 border-collapse: separate;
1617 border-collapse: separate;
1618 margin: 0;
1618 margin: 0;
1619 padding: 0;
1619 padding: 0;
1620 border: 1px solid #eee;
1620 border: 1px solid #eee;
1621 -webkit-border-radius: 4px;
1621 -webkit-border-radius: 4px;
1622 -moz-border-radius: 4px;
1622 -moz-border-radius: 4px;
1623 border-radius: 4px;
1623 border-radius: 4px;
1624 }
1624 }
1625
1625
1626 #content div.box table th {
1626 #content div.box table th {
1627 background: #eee;
1627 background: #eee;
1628 border-bottom: 1px solid #ddd;
1628 border-bottom: 1px solid #ddd;
1629 padding: 5px 0px 5px 5px;
1629 padding: 5px 0px 5px 5px;
1630 text-align: left;
1630 }
1631 }
1631
1632
1632 #content div.box table th.left {
1633 #content div.box table th.left {
1633 text-align: left;
1634 text-align: left;
1634 }
1635 }
1635
1636
1636 #content div.box table th.right {
1637 #content div.box table th.right {
1637 text-align: right;
1638 text-align: right;
1638 }
1639 }
1639
1640
1640 #content div.box table th.center {
1641 #content div.box table th.center {
1641 text-align: center;
1642 text-align: center;
1642 }
1643 }
1643
1644
1644 #content div.box table th.selected {
1645 #content div.box table th.selected {
1645 vertical-align: middle;
1646 vertical-align: middle;
1646 padding: 0;
1647 padding: 0;
1647 }
1648 }
1648
1649
1649 #content div.box table td {
1650 #content div.box table td {
1650 background: #fff;
1651 background: #fff;
1651 border-bottom: 1px solid #cdcdcd;
1652 border-bottom: 1px solid #cdcdcd;
1652 vertical-align: middle;
1653 vertical-align: middle;
1653 padding: 5px;
1654 padding: 5px;
1654 }
1655 }
1655
1656
1656 #content div.box table tr.selected td {
1657 #content div.box table tr.selected td {
1657 background: #FFC;
1658 background: #FFC;
1658 }
1659 }
1659
1660
1660 #content div.box table td.selected {
1661 #content div.box table td.selected {
1661 width: 3%;
1662 width: 3%;
1662 text-align: center;
1663 text-align: center;
1663 vertical-align: middle;
1664 vertical-align: middle;
1664 padding: 0;
1665 padding: 0;
1665 }
1666 }
1666
1667
1667 #content div.box table td.action {
1668 #content div.box table td.action {
1668 width: 45%;
1669 width: 45%;
1669 text-align: left;
1670 text-align: left;
1670 }
1671 }
1671
1672
1672 #content div.box table td.date {
1673 #content div.box table td.date {
1673 width: 33%;
1674 width: 33%;
1674 text-align: center;
1675 text-align: center;
1675 }
1676 }
1676
1677
1677 #content div.box div.action {
1678 #content div.box div.action {
1678 float: right;
1679 float: right;
1679 background: #FFF;
1680 background: #FFF;
1680 text-align: right;
1681 text-align: right;
1681 margin: 10px 0 0;
1682 margin: 10px 0 0;
1682 padding: 0;
1683 padding: 0;
1683 }
1684 }
1684
1685
1685 #content div.box div.action select {
1686 #content div.box div.action select {
1686 font-size: 11px;
1687 font-size: 11px;
1687 margin: 0;
1688 margin: 0;
1688 }
1689 }
1689
1690
1690 #content div.box div.action .ui-selectmenu {
1691 #content div.box div.action .ui-selectmenu {
1691 margin: 0;
1692 margin: 0;
1692 padding: 0;
1693 padding: 0;
1693 }
1694 }
1694
1695
1695 #content div.box div.pagination {
1696 #content div.box div.pagination {
1696 height: 1%;
1697 height: 1%;
1697 clear: both;
1698 clear: both;
1698 overflow: hidden;
1699 overflow: hidden;
1699 margin: 10px 0 0;
1700 margin: 10px 0 0;
1700 padding: 0;
1701 padding: 0;
1701 }
1702 }
1702
1703
1703 #content div.box div.pagination ul.pager {
1704 #content div.box div.pagination ul.pager {
1704 float: right;
1705 float: right;
1705 text-align: right;
1706 text-align: right;
1706 margin: 0;
1707 margin: 0;
1707 padding: 0;
1708 padding: 0;
1708 }
1709 }
1709
1710
1710 #content div.box div.pagination ul.pager li {
1711 #content div.box div.pagination ul.pager li {
1711 height: 1%;
1712 height: 1%;
1712 float: left;
1713 float: left;
1713 list-style: none;
1714 list-style: none;
1714 background: #ebebeb url("../images/pager.png") repeat-x;
1715 background: #ebebeb url("../images/pager.png") repeat-x;
1715 border-top: 1px solid #dedede;
1716 border-top: 1px solid #dedede;
1716 border-left: 1px solid #cfcfcf;
1717 border-left: 1px solid #cfcfcf;
1717 border-right: 1px solid #c4c4c4;
1718 border-right: 1px solid #c4c4c4;
1718 border-bottom: 1px solid #c4c4c4;
1719 border-bottom: 1px solid #c4c4c4;
1719 color: #4A4A4A;
1720 color: #4A4A4A;
1720 font-weight: 700;
1721 font-weight: 700;
1721 margin: 0 0 0 4px;
1722 margin: 0 0 0 4px;
1722 padding: 0;
1723 padding: 0;
1723 }
1724 }
1724
1725
1725 #content div.box div.pagination ul.pager li.separator {
1726 #content div.box div.pagination ul.pager li.separator {
1726 padding: 6px;
1727 padding: 6px;
1727 }
1728 }
1728
1729
1729 #content div.box div.pagination ul.pager li.current {
1730 #content div.box div.pagination ul.pager li.current {
1730 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1731 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1731 border-top: 1px solid #ccc;
1732 border-top: 1px solid #ccc;
1732 border-left: 1px solid #bebebe;
1733 border-left: 1px solid #bebebe;
1733 border-right: 1px solid #b1b1b1;
1734 border-right: 1px solid #b1b1b1;
1734 border-bottom: 1px solid #afafaf;
1735 border-bottom: 1px solid #afafaf;
1735 color: #515151;
1736 color: #515151;
1736 padding: 6px;
1737 padding: 6px;
1737 }
1738 }
1738
1739
1739 #content div.box div.pagination ul.pager li a {
1740 #content div.box div.pagination ul.pager li a {
1740 height: 1%;
1741 height: 1%;
1741 display: block;
1742 display: block;
1742 float: left;
1743 float: left;
1743 color: #515151;
1744 color: #515151;
1744 text-decoration: none;
1745 text-decoration: none;
1745 margin: 0;
1746 margin: 0;
1746 padding: 6px;
1747 padding: 6px;
1747 }
1748 }
1748
1749
1749 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active
1750 #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active
1750 {
1751 {
1751 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1752 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1752 border-top: 1px solid #ccc;
1753 border-top: 1px solid #ccc;
1753 border-left: 1px solid #bebebe;
1754 border-left: 1px solid #bebebe;
1754 border-right: 1px solid #b1b1b1;
1755 border-right: 1px solid #b1b1b1;
1755 border-bottom: 1px solid #afafaf;
1756 border-bottom: 1px solid #afafaf;
1756 margin: -1px;
1757 margin: -1px;
1757 }
1758 }
1758
1759
1759 #content div.box div.pagination-wh {
1760 #content div.box div.pagination-wh {
1760 height: 1%;
1761 height: 1%;
1761 clear: both;
1762 clear: both;
1762 overflow: hidden;
1763 overflow: hidden;
1763 text-align: right;
1764 text-align: right;
1764 margin: 10px 0 0;
1765 margin: 10px 0 0;
1765 padding: 0;
1766 padding: 0;
1766 }
1767 }
1767
1768
1768 #content div.box div.pagination-right {
1769 #content div.box div.pagination-right {
1769 float: right;
1770 float: right;
1770 }
1771 }
1771
1772
1772 #content div.box div.pagination-wh a,
1773 #content div.box div.pagination-wh a,
1773 #content div.box div.pagination-wh span.pager_dotdot,
1774 #content div.box div.pagination-wh span.pager_dotdot,
1774 #content div.box div.pagination-wh span.yui-pg-previous,
1775 #content div.box div.pagination-wh span.yui-pg-previous,
1775 #content div.box div.pagination-wh span.yui-pg-last,
1776 #content div.box div.pagination-wh span.yui-pg-last,
1776 #content div.box div.pagination-wh span.yui-pg-next,
1777 #content div.box div.pagination-wh span.yui-pg-next,
1777 #content div.box div.pagination-wh span.yui-pg-first
1778 #content div.box div.pagination-wh span.yui-pg-first
1778 {
1779 {
1779 height: 1%;
1780 height: 1%;
1780 float: left;
1781 float: left;
1781 background: #ebebeb url("../images/pager.png") repeat-x;
1782 background: #ebebeb url("../images/pager.png") repeat-x;
1782 border-top: 1px solid #dedede;
1783 border-top: 1px solid #dedede;
1783 border-left: 1px solid #cfcfcf;
1784 border-left: 1px solid #cfcfcf;
1784 border-right: 1px solid #c4c4c4;
1785 border-right: 1px solid #c4c4c4;
1785 border-bottom: 1px solid #c4c4c4;
1786 border-bottom: 1px solid #c4c4c4;
1786 color: #4A4A4A;
1787 color: #4A4A4A;
1787 font-weight: 700;
1788 font-weight: 700;
1788 margin: 0 0 0 4px;
1789 margin: 0 0 0 4px;
1789 padding: 6px;
1790 padding: 6px;
1790 }
1791 }
1791
1792
1792 #content div.box div.pagination-wh span.pager_curpage {
1793 #content div.box div.pagination-wh span.pager_curpage {
1793 height: 1%;
1794 height: 1%;
1794 float: left;
1795 float: left;
1795 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1796 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1796 border-top: 1px solid #ccc;
1797 border-top: 1px solid #ccc;
1797 border-left: 1px solid #bebebe;
1798 border-left: 1px solid #bebebe;
1798 border-right: 1px solid #b1b1b1;
1799 border-right: 1px solid #b1b1b1;
1799 border-bottom: 1px solid #afafaf;
1800 border-bottom: 1px solid #afafaf;
1800 color: #515151;
1801 color: #515151;
1801 font-weight: 700;
1802 font-weight: 700;
1802 margin: 0 0 0 4px;
1803 margin: 0 0 0 4px;
1803 padding: 6px;
1804 padding: 6px;
1804 }
1805 }
1805
1806
1806 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active
1807 #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active
1807 {
1808 {
1808 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1809 background: #b4b4b4 url("../images/pager_selected.png") repeat-x;
1809 border-top: 1px solid #ccc;
1810 border-top: 1px solid #ccc;
1810 border-left: 1px solid #bebebe;
1811 border-left: 1px solid #bebebe;
1811 border-right: 1px solid #b1b1b1;
1812 border-right: 1px solid #b1b1b1;
1812 border-bottom: 1px solid #afafaf;
1813 border-bottom: 1px solid #afafaf;
1813 text-decoration: none;
1814 text-decoration: none;
1814 }
1815 }
1815
1816
1816 #content div.box div.traffic div.legend {
1817 #content div.box div.traffic div.legend {
1817 clear: both;
1818 clear: both;
1818 overflow: hidden;
1819 overflow: hidden;
1819 border-bottom: 1px solid #ddd;
1820 border-bottom: 1px solid #ddd;
1820 margin: 0 0 10px;
1821 margin: 0 0 10px;
1821 padding: 0 0 10px;
1822 padding: 0 0 10px;
1822 }
1823 }
1823
1824
1824 #content div.box div.traffic div.legend h6 {
1825 #content div.box div.traffic div.legend h6 {
1825 float: left;
1826 float: left;
1826 border: none;
1827 border: none;
1827 margin: 0;
1828 margin: 0;
1828 padding: 0;
1829 padding: 0;
1829 }
1830 }
1830
1831
1831 #content div.box div.traffic div.legend li {
1832 #content div.box div.traffic div.legend li {
1832 list-style: none;
1833 list-style: none;
1833 float: left;
1834 float: left;
1834 font-size: 11px;
1835 font-size: 11px;
1835 margin: 0;
1836 margin: 0;
1836 padding: 0 8px 0 4px;
1837 padding: 0 8px 0 4px;
1837 }
1838 }
1838
1839
1839 #content div.box div.traffic div.legend li.visits {
1840 #content div.box div.traffic div.legend li.visits {
1840 border-left: 12px solid #edc240;
1841 border-left: 12px solid #edc240;
1841 }
1842 }
1842
1843
1843 #content div.box div.traffic div.legend li.pageviews {
1844 #content div.box div.traffic div.legend li.pageviews {
1844 border-left: 12px solid #afd8f8;
1845 border-left: 12px solid #afd8f8;
1845 }
1846 }
1846
1847
1847 #content div.box div.traffic table {
1848 #content div.box div.traffic table {
1848 width: auto;
1849 width: auto;
1849 }
1850 }
1850
1851
1851 #content div.box div.traffic table td {
1852 #content div.box div.traffic table td {
1852 background: transparent;
1853 background: transparent;
1853 border: none;
1854 border: none;
1854 padding: 2px 3px 3px;
1855 padding: 2px 3px 3px;
1855 }
1856 }
1856
1857
1857 #content div.box div.traffic table td.legendLabel {
1858 #content div.box div.traffic table td.legendLabel {
1858 padding: 0 3px 2px;
1859 padding: 0 3px 2px;
1859 }
1860 }
1860
1861
1861 #summary {
1862 #summary {
1862
1863
1863 }
1864 }
1864
1865
1865 #summary .metatag {
1866 #summary .metatag {
1866 display: inline-block;
1867 display: inline-block;
1867 padding: 3px 5px;
1868 padding: 3px 5px;
1868 margin-bottom: 3px;
1869 margin-bottom: 3px;
1869 margin-right: 1px;
1870 margin-right: 1px;
1870 border-radius: 5px;
1871 border-radius: 5px;
1871 }
1872 }
1872
1873
1873 #content div.box #summary p {
1874 #content div.box #summary p {
1874 margin-bottom: -5px;
1875 margin-bottom: -5px;
1875 width: 600px;
1876 width: 600px;
1876 white-space: pre-wrap;
1877 white-space: pre-wrap;
1877 }
1878 }
1878
1879
1879 #content div.box #summary p:last-child {
1880 #content div.box #summary p:last-child {
1880 margin-bottom: 9px;
1881 margin-bottom: 9px;
1881 }
1882 }
1882
1883
1883 #content div.box #summary p:first-of-type {
1884 #content div.box #summary p:first-of-type {
1884 margin-top: 9px;
1885 margin-top: 9px;
1885 }
1886 }
1886
1887
1887 .metatag {
1888 .metatag {
1888 display: inline-block;
1889 display: inline-block;
1889 margin-right: 1px;
1890 margin-right: 1px;
1890 -webkit-border-radius: 4px 4px 4px 4px;
1891 -webkit-border-radius: 4px 4px 4px 4px;
1891 -khtml-border-radius: 4px 4px 4px 4px;
1892 -khtml-border-radius: 4px 4px 4px 4px;
1892 -moz-border-radius: 4px 4px 4px 4px;
1893 -moz-border-radius: 4px 4px 4px 4px;
1893 border-radius: 4px 4px 4px 4px;
1894 border-radius: 4px 4px 4px 4px;
1894
1895
1895 border: solid 1px #9CF;
1896 border: solid 1px #9CF;
1896 padding: 2px 3px 2px 3px !important;
1897 padding: 2px 3px 2px 3px !important;
1897 background-color: #DEF;
1898 background-color: #DEF;
1898 }
1899 }
1899
1900
1900 .metatag[tag="dead"] {
1901 .metatag[tag="dead"] {
1901 background-color: #E44;
1902 background-color: #E44;
1902 }
1903 }
1903
1904
1904 .metatag[tag="stale"] {
1905 .metatag[tag="stale"] {
1905 background-color: #EA4;
1906 background-color: #EA4;
1906 }
1907 }
1907
1908
1908 .metatag[tag="featured"] {
1909 .metatag[tag="featured"] {
1909 background-color: #AEA;
1910 background-color: #AEA;
1910 }
1911 }
1911
1912
1912 .metatag[tag="requires"] {
1913 .metatag[tag="requires"] {
1913 background-color: #9CF;
1914 background-color: #9CF;
1914 }
1915 }
1915
1916
1916 .metatag[tag="recommends"] {
1917 .metatag[tag="recommends"] {
1917 background-color: #BDF;
1918 background-color: #BDF;
1918 }
1919 }
1919
1920
1920 .metatag[tag="lang"] {
1921 .metatag[tag="lang"] {
1921 background-color: #FAF474;
1922 background-color: #FAF474;
1922 }
1923 }
1923
1924
1924 .metatag[tag="license"] {
1925 .metatag[tag="license"] {
1925 border: solid 1px #9CF;
1926 border: solid 1px #9CF;
1926 background-color: #DEF;
1927 background-color: #DEF;
1927 target-new: tab !important;
1928 target-new: tab !important;
1928 }
1929 }
1929 .metatag[tag="see"] {
1930 .metatag[tag="see"] {
1930 border: solid 1px #CBD;
1931 border: solid 1px #CBD;
1931 background-color: #EDF;
1932 background-color: #EDF;
1932 }
1933 }
1933
1934
1934 a.metatag[tag="license"]:hover {
1935 a.metatag[tag="license"]:hover {
1935 background-color: #003367;
1936 background-color: #003367;
1936 color: #FFF;
1937 color: #FFF;
1937 text-decoration: none;
1938 text-decoration: none;
1938 }
1939 }
1939
1940
1940 #summary .desc {
1941 #summary .desc {
1941 white-space: pre;
1942 white-space: pre;
1942 width: 100%;
1943 width: 100%;
1943 }
1944 }
1944
1945
1945 #summary .repo_name {
1946 #summary .repo_name {
1946 font-size: 1.6em;
1947 font-size: 1.6em;
1947 font-weight: bold;
1948 font-weight: bold;
1948 vertical-align: baseline;
1949 vertical-align: baseline;
1949 clear: right
1950 clear: right
1950 }
1951 }
1951
1952
1952 #footer {
1953 #footer {
1953 clear: both;
1954 clear: both;
1954 overflow: hidden;
1955 overflow: hidden;
1955 text-align: right;
1956 text-align: right;
1956 margin: 0;
1957 margin: 0;
1957 padding: 0 10px 4px;
1958 padding: 0 10px 4px;
1958 margin: -10px 0 0;
1959 margin: -10px 0 0;
1959 }
1960 }
1960
1961
1961 #footer div#footer-inner {
1962 #footer div#footer-inner {
1962 background-color: #003B76;
1963 background-color: #003B76;
1963 background-repeat : repeat-x;
1964 background-repeat : repeat-x;
1964 background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
1965 background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
1965 background-image : -moz-linear-gradient(top, #003b76, #00376e);
1966 background-image : -moz-linear-gradient(top, #003b76, #00376e);
1966 background-image : -ms-linear-gradient( top, #003b76, #00376e);
1967 background-image : -ms-linear-gradient( top, #003b76, #00376e);
1967 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
1968 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
1968 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
1969 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
1969 background-image : -o-linear-gradient( top, #003b76, #00376e));
1970 background-image : -o-linear-gradient( top, #003b76, #00376e));
1970 background-image : linear-gradient( top, #003b76, #00376e);
1971 background-image : linear-gradient( top, #003b76, #00376e);
1971 filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
1972 filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
1972 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1973 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
1973 -webkit-border-radius: 4px 4px 4px 4px;
1974 -webkit-border-radius: 4px 4px 4px 4px;
1974 -khtml-border-radius: 4px 4px 4px 4px;
1975 -khtml-border-radius: 4px 4px 4px 4px;
1975 -moz-border-radius: 4px 4px 4px 4px;
1976 -moz-border-radius: 4px 4px 4px 4px;
1976 border-radius: 4px 4px 4px 4px;
1977 border-radius: 4px 4px 4px 4px;
1977 }
1978 }
1978
1979
1979 #footer div#footer-inner p {
1980 #footer div#footer-inner p {
1980 padding: 15px 25px 15px 0;
1981 padding: 15px 25px 15px 0;
1981 color: #FFF;
1982 color: #FFF;
1982 font-weight: 700;
1983 font-weight: 700;
1983 }
1984 }
1984
1985
1985 #footer div#footer-inner .footer-link {
1986 #footer div#footer-inner .footer-link {
1986 float: left;
1987 float: left;
1987 padding-left: 10px;
1988 padding-left: 10px;
1988 }
1989 }
1989
1990
1990 #footer div#footer-inner .footer-link a,#footer div#footer-inner .footer-link-right a
1991 #footer div#footer-inner .footer-link a,#footer div#footer-inner .footer-link-right a
1991 {
1992 {
1992 color: #FFF;
1993 color: #FFF;
1993 }
1994 }
1994
1995
1995 #login div.title {
1996 #login div.title {
1996 width: 420px;
1997 width: 420px;
1997 clear: both;
1998 clear: both;
1998 overflow: hidden;
1999 overflow: hidden;
1999 position: relative;
2000 position: relative;
2000 background-color: #003B76;
2001 background-color: #003B76;
2001 background-repeat : repeat-x;
2002 background-repeat : repeat-x;
2002 background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
2003 background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E));
2003 background-image : -moz-linear-gradient( top, #003b76, #00376e);
2004 background-image : -moz-linear-gradient( top, #003b76, #00376e);
2004 background-image : -ms-linear-gradient( top, #003b76, #00376e);
2005 background-image : -ms-linear-gradient( top, #003b76, #00376e);
2005 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2006 background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e));
2006 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2007 background-image : -webkit-linear-gradient( top, #003b76, #00376e));
2007 background-image : -o-linear-gradient( top, #003b76, #00376e));
2008 background-image : -o-linear-gradient( top, #003b76, #00376e));
2008 background-image : linear-gradient( top, #003b76, #00376e);
2009 background-image : linear-gradient( top, #003b76, #00376e);
2009 filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2010 filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0);
2010 margin: 0 auto;
2011 margin: 0 auto;
2011 padding: 0;
2012 padding: 0;
2012 }
2013 }
2013
2014
2014 #login div.inner {
2015 #login div.inner {
2015 width: 380px;
2016 width: 380px;
2016 background: #FFF url("../images/login.png") no-repeat top left;
2017 background: #FFF url("../images/login.png") no-repeat top left;
2017 border-top: none;
2018 border-top: none;
2018 border-bottom: none;
2019 border-bottom: none;
2019 margin: 0 auto;
2020 margin: 0 auto;
2020 padding: 20px;
2021 padding: 20px;
2021 }
2022 }
2022
2023
2023 #login div.form div.fields div.field div.label {
2024 #login div.form div.fields div.field div.label {
2024 width: 173px;
2025 width: 173px;
2025 float: left;
2026 float: left;
2026 text-align: right;
2027 text-align: right;
2027 margin: 2px 10px 0 0;
2028 margin: 2px 10px 0 0;
2028 padding: 5px 0 0 5px;
2029 padding: 5px 0 0 5px;
2029 }
2030 }
2030
2031
2031 #login div.form div.fields div.field div.input input {
2032 #login div.form div.fields div.field div.input input {
2032 width: 176px;
2033 width: 176px;
2033 background: #FFF;
2034 background: #FFF;
2034 border-top: 1px solid #b3b3b3;
2035 border-top: 1px solid #b3b3b3;
2035 border-left: 1px solid #b3b3b3;
2036 border-left: 1px solid #b3b3b3;
2036 border-right: 1px solid #eaeaea;
2037 border-right: 1px solid #eaeaea;
2037 border-bottom: 1px solid #eaeaea;
2038 border-bottom: 1px solid #eaeaea;
2038 color: #000;
2039 color: #000;
2039 font-size: 11px;
2040 font-size: 11px;
2040 margin: 0;
2041 margin: 0;
2041 padding: 7px 7px 6px;
2042 padding: 7px 7px 6px;
2042 }
2043 }
2043
2044
2044 #login div.form div.fields div.buttons {
2045 #login div.form div.fields div.buttons {
2045 clear: both;
2046 clear: both;
2046 overflow: hidden;
2047 overflow: hidden;
2047 border-top: 1px solid #DDD;
2048 border-top: 1px solid #DDD;
2048 text-align: right;
2049 text-align: right;
2049 margin: 0;
2050 margin: 0;
2050 padding: 10px 0 0;
2051 padding: 10px 0 0;
2051 }
2052 }
2052
2053
2053 #login div.form div.links {
2054 #login div.form div.links {
2054 clear: both;
2055 clear: both;
2055 overflow: hidden;
2056 overflow: hidden;
2056 margin: 10px 0 0;
2057 margin: 10px 0 0;
2057 padding: 0 0 2px;
2058 padding: 0 0 2px;
2058 }
2059 }
2059
2060
2060 .user-menu{
2061 .user-menu{
2061 margin: 0px !important;
2062 margin: 0px !important;
2062 float: left;
2063 float: left;
2063 }
2064 }
2064
2065
2065 .user-menu .container{
2066 .user-menu .container{
2066 padding:0px 4px 0px 4px;
2067 padding:0px 4px 0px 4px;
2067 margin: 0px 0px 0px 0px;
2068 margin: 0px 0px 0px 0px;
2068 }
2069 }
2069
2070
2070 .user-menu .gravatar{
2071 .user-menu .gravatar{
2071 margin: 0px 0px 0px 0px;
2072 margin: 0px 0px 0px 0px;
2072 cursor: pointer;
2073 cursor: pointer;
2073 }
2074 }
2074 .user-menu .gravatar.enabled{
2075 .user-menu .gravatar.enabled{
2075 background-color: #FDF784 !important;
2076 background-color: #FDF784 !important;
2076 }
2077 }
2077 .user-menu .gravatar:hover{
2078 .user-menu .gravatar:hover{
2078 background-color: #FDF784 !important;
2079 background-color: #FDF784 !important;
2079 }
2080 }
2080 #quick_login{
2081 #quick_login{
2081 min-height: 80px;
2082 min-height: 80px;
2082 margin: 37px 0 0 -251px;
2083 margin: 37px 0 0 -251px;
2083 padding: 4px;
2084 padding: 4px;
2084 position: absolute;
2085 position: absolute;
2085 width: 278px;
2086 width: 278px;
2086 background-color: #003B76;
2087 background-color: #003B76;
2087 background-repeat: repeat-x;
2088 background-repeat: repeat-x;
2088 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
2089 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
2089 background-image: -moz-linear-gradient(top, #003b76, #00376e);
2090 background-image: -moz-linear-gradient(top, #003b76, #00376e);
2090 background-image: -ms-linear-gradient(top, #003b76, #00376e);
2091 background-image: -ms-linear-gradient(top, #003b76, #00376e);
2091 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2092 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2092 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2093 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2093 background-image: -o-linear-gradient(top, #003b76, #00376e);
2094 background-image: -o-linear-gradient(top, #003b76, #00376e);
2094 background-image: linear-gradient(top, #003b76, #00376e);
2095 background-image: linear-gradient(top, #003b76, #00376e);
2095 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
2096 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 );
2096
2097
2097 z-index: 999;
2098 z-index: 999;
2098 -webkit-border-radius: 0px 0px 4px 4px;
2099 -webkit-border-radius: 0px 0px 4px 4px;
2099 -khtml-border-radius: 0px 0px 4px 4px;
2100 -khtml-border-radius: 0px 0px 4px 4px;
2100 -moz-border-radius: 0px 0px 4px 4px;
2101 -moz-border-radius: 0px 0px 4px 4px;
2101 border-radius: 0px 0px 4px 4px;
2102 border-radius: 0px 0px 4px 4px;
2102 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2103 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
2103 }
2104 }
2104 #quick_login h4{
2105 #quick_login h4{
2105 color: #fff;
2106 color: #fff;
2106 padding: 5px 0px 5px 14px;
2107 padding: 5px 0px 5px 14px;
2107 }
2108 }
2108
2109
2109 #quick_login .password_forgoten {
2110 #quick_login .password_forgoten {
2110 padding-right: 10px;
2111 padding-right: 10px;
2111 padding-top: 0px;
2112 padding-top: 0px;
2112 text-align: left;
2113 text-align: left;
2113 }
2114 }
2114
2115
2115 #quick_login .password_forgoten a {
2116 #quick_login .password_forgoten a {
2116 font-size: 10px;
2117 font-size: 10px;
2117 color: #fff;
2118 color: #fff;
2118 }
2119 }
2119
2120
2120 #quick_login .register {
2121 #quick_login .register {
2121 padding-right: 10px;
2122 padding-right: 10px;
2122 padding-top: 5px;
2123 padding-top: 5px;
2123 text-align: left;
2124 text-align: left;
2124 }
2125 }
2125
2126
2126 #quick_login .register a {
2127 #quick_login .register a {
2127 font-size: 10px;
2128 font-size: 10px;
2128 color: #fff;
2129 color: #fff;
2129 }
2130 }
2130
2131
2131 #quick_login .submit {
2132 #quick_login .submit {
2132 margin: -20px 0 0 0px;
2133 margin: -20px 0 0 0px;
2133 position: absolute;
2134 position: absolute;
2134 right: 15px;
2135 right: 15px;
2135 }
2136 }
2136
2137
2137 #quick_login .links_left{
2138 #quick_login .links_left{
2138 float: left;
2139 float: left;
2139 }
2140 }
2140 #quick_login .links_right{
2141 #quick_login .links_right{
2141 float: right;
2142 float: right;
2142 }
2143 }
2143 #quick_login .full_name{
2144 #quick_login .full_name{
2144 color: #FFFFFF;
2145 color: #FFFFFF;
2145 font-weight: bold;
2146 font-weight: bold;
2146 padding: 3px;
2147 padding: 3px;
2147 }
2148 }
2148 #quick_login .big_gravatar{
2149 #quick_login .big_gravatar{
2149 padding:4px 0px 0px 6px;
2150 padding:4px 0px 0px 6px;
2150 }
2151 }
2151 #quick_login .inbox{
2152 #quick_login .inbox{
2152 padding:4px 0px 0px 6px;
2153 padding:4px 0px 0px 6px;
2153 color: #FFFFFF;
2154 color: #FFFFFF;
2154 font-weight: bold;
2155 font-weight: bold;
2155 }
2156 }
2156 #quick_login .inbox a{
2157 #quick_login .inbox a{
2157 color: #FFFFFF;
2158 color: #FFFFFF;
2158 }
2159 }
2159 #quick_login .email,#quick_login .email a{
2160 #quick_login .email,#quick_login .email a{
2160 color: #FFFFFF;
2161 color: #FFFFFF;
2161 padding: 3px;
2162 padding: 3px;
2162
2163
2163 }
2164 }
2164 #quick_login .links .logout{
2165 #quick_login .links .logout{
2165
2166
2166 }
2167 }
2167
2168
2168 #quick_login div.form div.fields {
2169 #quick_login div.form div.fields {
2169 padding-top: 2px;
2170 padding-top: 2px;
2170 padding-left: 10px;
2171 padding-left: 10px;
2171 }
2172 }
2172
2173
2173 #quick_login div.form div.fields div.field {
2174 #quick_login div.form div.fields div.field {
2174 padding: 5px;
2175 padding: 5px;
2175 }
2176 }
2176
2177
2177 #quick_login div.form div.fields div.field div.label label {
2178 #quick_login div.form div.fields div.field div.label label {
2178 color: #fff;
2179 color: #fff;
2179 padding-bottom: 3px;
2180 padding-bottom: 3px;
2180 }
2181 }
2181
2182
2182 #quick_login div.form div.fields div.field div.input input {
2183 #quick_login div.form div.fields div.field div.input input {
2183 width: 236px;
2184 width: 236px;
2184 background: #FFF;
2185 background: #FFF;
2185 border-top: 1px solid #b3b3b3;
2186 border-top: 1px solid #b3b3b3;
2186 border-left: 1px solid #b3b3b3;
2187 border-left: 1px solid #b3b3b3;
2187 border-right: 1px solid #eaeaea;
2188 border-right: 1px solid #eaeaea;
2188 border-bottom: 1px solid #eaeaea;
2189 border-bottom: 1px solid #eaeaea;
2189 color: #000;
2190 color: #000;
2190 font-size: 11px;
2191 font-size: 11px;
2191 margin: 0;
2192 margin: 0;
2192 padding: 5px 7px 4px;
2193 padding: 5px 7px 4px;
2193 }
2194 }
2194
2195
2195 #quick_login div.form div.fields div.buttons {
2196 #quick_login div.form div.fields div.buttons {
2196 clear: both;
2197 clear: both;
2197 overflow: hidden;
2198 overflow: hidden;
2198 text-align: right;
2199 text-align: right;
2199 margin: 0;
2200 margin: 0;
2200 padding: 5px 14px 0px 5px;
2201 padding: 5px 14px 0px 5px;
2201 }
2202 }
2202
2203
2203 #quick_login div.form div.links {
2204 #quick_login div.form div.links {
2204 clear: both;
2205 clear: both;
2205 overflow: hidden;
2206 overflow: hidden;
2206 margin: 10px 0 0;
2207 margin: 10px 0 0;
2207 padding: 0 0 2px;
2208 padding: 0 0 2px;
2208 }
2209 }
2209
2210
2210 #quick_login ol.links{
2211 #quick_login ol.links{
2211 display: block;
2212 display: block;
2212 font-weight: bold;
2213 font-weight: bold;
2213 list-style: none outside none;
2214 list-style: none outside none;
2214 text-align: right;
2215 text-align: right;
2215 }
2216 }
2216 #quick_login ol.links li{
2217 #quick_login ol.links li{
2217 line-height: 27px;
2218 line-height: 27px;
2218 margin: 0;
2219 margin: 0;
2219 padding: 0;
2220 padding: 0;
2220 color: #fff;
2221 color: #fff;
2221 display: block;
2222 display: block;
2222 float:none !important;
2223 float:none !important;
2223 }
2224 }
2224
2225
2225 #quick_login ol.links li a{
2226 #quick_login ol.links li a{
2226 color: #fff;
2227 color: #fff;
2227 display: block;
2228 display: block;
2228 padding: 2px;
2229 padding: 2px;
2229 }
2230 }
2230 #quick_login ol.links li a:HOVER{
2231 #quick_login ol.links li a:HOVER{
2231 background-color: inherit !important;
2232 background-color: inherit !important;
2232 }
2233 }
2233
2234
2234 #register div.title {
2235 #register div.title {
2235 clear: both;
2236 clear: both;
2236 overflow: hidden;
2237 overflow: hidden;
2237 position: relative;
2238 position: relative;
2238 background-color: #003B76;
2239 background-color: #003B76;
2239 background-repeat: repeat-x;
2240 background-repeat: repeat-x;
2240 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
2241 background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) );
2241 background-image: -moz-linear-gradient(top, #003b76, #00376e);
2242 background-image: -moz-linear-gradient(top, #003b76, #00376e);
2242 background-image: -ms-linear-gradient(top, #003b76, #00376e);
2243 background-image: -ms-linear-gradient(top, #003b76, #00376e);
2243 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2244 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) );
2244 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2245 background-image: -webkit-linear-gradient(top, #003b76, #00376e);
2245 background-image: -o-linear-gradient(top, #003b76, #00376e);
2246 background-image: -o-linear-gradient(top, #003b76, #00376e);
2246 background-image: linear-gradient(top, #003b76, #00376e);
2247 background-image: linear-gradient(top, #003b76, #00376e);
2247 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',
2248 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',
2248 endColorstr='#00376e', GradientType=0 );
2249 endColorstr='#00376e', GradientType=0 );
2249 margin: 0 auto;
2250 margin: 0 auto;
2250 padding: 0;
2251 padding: 0;
2251 }
2252 }
2252
2253
2253 #register div.inner {
2254 #register div.inner {
2254 background: #FFF;
2255 background: #FFF;
2255 border-top: none;
2256 border-top: none;
2256 border-bottom: none;
2257 border-bottom: none;
2257 margin: 0 auto;
2258 margin: 0 auto;
2258 padding: 20px;
2259 padding: 20px;
2259 }
2260 }
2260
2261
2261 #register div.form div.fields div.field div.label {
2262 #register div.form div.fields div.field div.label {
2262 width: 135px;
2263 width: 135px;
2263 float: left;
2264 float: left;
2264 text-align: right;
2265 text-align: right;
2265 margin: 2px 10px 0 0;
2266 margin: 2px 10px 0 0;
2266 padding: 5px 0 0 5px;
2267 padding: 5px 0 0 5px;
2267 }
2268 }
2268
2269
2269 #register div.form div.fields div.field div.input input {
2270 #register div.form div.fields div.field div.input input {
2270 width: 300px;
2271 width: 300px;
2271 background: #FFF;
2272 background: #FFF;
2272 border-top: 1px solid #b3b3b3;
2273 border-top: 1px solid #b3b3b3;
2273 border-left: 1px solid #b3b3b3;
2274 border-left: 1px solid #b3b3b3;
2274 border-right: 1px solid #eaeaea;
2275 border-right: 1px solid #eaeaea;
2275 border-bottom: 1px solid #eaeaea;
2276 border-bottom: 1px solid #eaeaea;
2276 color: #000;
2277 color: #000;
2277 font-size: 11px;
2278 font-size: 11px;
2278 margin: 0;
2279 margin: 0;
2279 padding: 7px 7px 6px;
2280 padding: 7px 7px 6px;
2280 }
2281 }
2281
2282
2282 #register div.form div.fields div.buttons {
2283 #register div.form div.fields div.buttons {
2283 clear: both;
2284 clear: both;
2284 overflow: hidden;
2285 overflow: hidden;
2285 border-top: 1px solid #DDD;
2286 border-top: 1px solid #DDD;
2286 text-align: left;
2287 text-align: left;
2287 margin: 0;
2288 margin: 0;
2288 padding: 10px 0 0 150px;
2289 padding: 10px 0 0 150px;
2289 }
2290 }
2290
2291
2291 #register div.form div.activation_msg {
2292 #register div.form div.activation_msg {
2292 padding-top: 4px;
2293 padding-top: 4px;
2293 padding-bottom: 4px;
2294 padding-bottom: 4px;
2294 }
2295 }
2295
2296
2296 #journal .journal_day {
2297 #journal .journal_day {
2297 font-size: 20px;
2298 font-size: 20px;
2298 padding: 10px 0px;
2299 padding: 10px 0px;
2299 border-bottom: 2px solid #DDD;
2300 border-bottom: 2px solid #DDD;
2300 margin-left: 10px;
2301 margin-left: 10px;
2301 margin-right: 10px;
2302 margin-right: 10px;
2302 }
2303 }
2303
2304
2304 #journal .journal_container {
2305 #journal .journal_container {
2305 padding: 5px;
2306 padding: 5px;
2306 clear: both;
2307 clear: both;
2307 margin: 0px 5px 0px 10px;
2308 margin: 0px 5px 0px 10px;
2308 }
2309 }
2309
2310
2310 #journal .journal_action_container {
2311 #journal .journal_action_container {
2311 padding-left: 38px;
2312 padding-left: 38px;
2312 }
2313 }
2313
2314
2314 #journal .journal_user {
2315 #journal .journal_user {
2315 color: #747474;
2316 color: #747474;
2316 font-size: 14px;
2317 font-size: 14px;
2317 font-weight: bold;
2318 font-weight: bold;
2318 height: 30px;
2319 height: 30px;
2319 }
2320 }
2320
2321
2321 #journal .journal_icon {
2322 #journal .journal_icon {
2322 clear: both;
2323 clear: both;
2323 float: left;
2324 float: left;
2324 padding-right: 4px;
2325 padding-right: 4px;
2325 padding-top: 3px;
2326 padding-top: 3px;
2326 }
2327 }
2327
2328
2328 #journal .journal_action {
2329 #journal .journal_action {
2329 padding-top: 4px;
2330 padding-top: 4px;
2330 min-height: 2px;
2331 min-height: 2px;
2331 float: left
2332 float: left
2332 }
2333 }
2333
2334
2334 #journal .journal_action_params {
2335 #journal .journal_action_params {
2335 clear: left;
2336 clear: left;
2336 padding-left: 22px;
2337 padding-left: 22px;
2337 }
2338 }
2338
2339
2339 #journal .journal_repo {
2340 #journal .journal_repo {
2340 float: left;
2341 float: left;
2341 margin-left: 6px;
2342 margin-left: 6px;
2342 padding-top: 3px;
2343 padding-top: 3px;
2343 }
2344 }
2344
2345
2345 #journal .date {
2346 #journal .date {
2346 clear: both;
2347 clear: both;
2347 color: #777777;
2348 color: #777777;
2348 font-size: 11px;
2349 font-size: 11px;
2349 padding-left: 22px;
2350 padding-left: 22px;
2350 }
2351 }
2351
2352
2352 #journal .journal_repo .journal_repo_name {
2353 #journal .journal_repo .journal_repo_name {
2353 font-weight: bold;
2354 font-weight: bold;
2354 font-size: 1.1em;
2355 font-size: 1.1em;
2355 }
2356 }
2356
2357
2357 #journal .compare_view {
2358 #journal .compare_view {
2358 padding: 5px 0px 5px 0px;
2359 padding: 5px 0px 5px 0px;
2359 width: 95px;
2360 width: 95px;
2360 }
2361 }
2361
2362
2362 .journal_highlight {
2363 .journal_highlight {
2363 font-weight: bold;
2364 font-weight: bold;
2364 padding: 0 2px;
2365 padding: 0 2px;
2365 vertical-align: bottom;
2366 vertical-align: bottom;
2366 }
2367 }
2367
2368
2368 .trending_language_tbl,.trending_language_tbl td {
2369 .trending_language_tbl,.trending_language_tbl td {
2369 border: 0 !important;
2370 border: 0 !important;
2370 margin: 0 !important;
2371 margin: 0 !important;
2371 padding: 0 !important;
2372 padding: 0 !important;
2372 }
2373 }
2373
2374
2374 .trending_language_tbl,.trending_language_tbl tr {
2375 .trending_language_tbl,.trending_language_tbl tr {
2375 border-spacing: 1px;
2376 border-spacing: 1px;
2376 }
2377 }
2377
2378
2378 .trending_language {
2379 .trending_language {
2379 background-color: #003367;
2380 background-color: #003367;
2380 color: #FFF;
2381 color: #FFF;
2381 display: block;
2382 display: block;
2382 min-width: 20px;
2383 min-width: 20px;
2383 text-decoration: none;
2384 text-decoration: none;
2384 height: 12px;
2385 height: 12px;
2385 margin-bottom: 0px;
2386 margin-bottom: 0px;
2386 margin-left: 5px;
2387 margin-left: 5px;
2387 white-space: pre;
2388 white-space: pre;
2388 padding: 3px;
2389 padding: 3px;
2389 }
2390 }
2390
2391
2391 h3.files_location {
2392 h3.files_location {
2392 font-size: 1.8em;
2393 font-size: 1.8em;
2393 font-weight: 700;
2394 font-weight: 700;
2394 border-bottom: none !important;
2395 border-bottom: none !important;
2395 margin: 10px 0 !important;
2396 margin: 10px 0 !important;
2396 }
2397 }
2397
2398
2398 #files_data dl dt {
2399 #files_data dl dt {
2399 float: left;
2400 float: left;
2400 width: 60px;
2401 width: 60px;
2401 margin: 0 !important;
2402 margin: 0 !important;
2402 padding: 5px;
2403 padding: 5px;
2403 }
2404 }
2404
2405
2405 #files_data dl dd {
2406 #files_data dl dd {
2406 margin: 0 !important;
2407 margin: 0 !important;
2407 padding: 5px !important;
2408 padding: 5px !important;
2408 }
2409 }
2409
2410
2410 .file_history{
2411 .file_history{
2411 padding-top:10px;
2412 padding-top:10px;
2412 font-size:16px;
2413 font-size:16px;
2413 }
2414 }
2414 .file_author{
2415 .file_author{
2415 float: left;
2416 float: left;
2416 }
2417 }
2417
2418
2418 .file_author .item{
2419 .file_author .item{
2419 float:left;
2420 float:left;
2420 padding:5px;
2421 padding:5px;
2421 color: #888;
2422 color: #888;
2422 }
2423 }
2423
2424
2424 .tablerow0 {
2425 .tablerow0 {
2425 background-color: #F8F8F8;
2426 background-color: #F8F8F8;
2426 }
2427 }
2427
2428
2428 .tablerow1 {
2429 .tablerow1 {
2429 background-color: #FFFFFF;
2430 background-color: #FFFFFF;
2430 }
2431 }
2431
2432
2432 .changeset_id {
2433 .changeset_id {
2433 font-family: monospace;
2434 font-family: monospace;
2434 color: #666666;
2435 color: #666666;
2435 }
2436 }
2436
2437
2437 .changeset_hash {
2438 .changeset_hash {
2438 color: #000000;
2439 color: #000000;
2439 }
2440 }
2440
2441
2441 #changeset_content {
2442 #changeset_content {
2442 border-left: 1px solid #CCC;
2443 border-left: 1px solid #CCC;
2443 border-right: 1px solid #CCC;
2444 border-right: 1px solid #CCC;
2444 border-bottom: 1px solid #CCC;
2445 border-bottom: 1px solid #CCC;
2445 padding: 5px;
2446 padding: 5px;
2446 }
2447 }
2447
2448
2448 #changeset_compare_view_content {
2449 #changeset_compare_view_content {
2449 border: 1px solid #CCC;
2450 border: 1px solid #CCC;
2450 padding: 5px;
2451 padding: 5px;
2451 }
2452 }
2452
2453
2453 #changeset_content .container {
2454 #changeset_content .container {
2454 min-height: 100px;
2455 min-height: 100px;
2455 font-size: 1.2em;
2456 font-size: 1.2em;
2456 overflow: hidden;
2457 overflow: hidden;
2457 }
2458 }
2458
2459
2459 #changeset_compare_view_content .compare_view_commits {
2460 #changeset_compare_view_content .compare_view_commits {
2460 width: auto !important;
2461 width: auto !important;
2461 }
2462 }
2462
2463
2463 #changeset_compare_view_content .compare_view_commits td {
2464 #changeset_compare_view_content .compare_view_commits td {
2464 padding: 0px 0px 0px 12px !important;
2465 padding: 0px 0px 0px 12px !important;
2465 }
2466 }
2466
2467
2467 #changeset_content .container .right {
2468 #changeset_content .container .right {
2468 float: right;
2469 float: right;
2469 width: 20%;
2470 width: 20%;
2470 text-align: right;
2471 text-align: right;
2471 }
2472 }
2472
2473
2473 #changeset_content .container .left .message {
2474 #changeset_content .container .left .message {
2474 white-space: pre-wrap;
2475 white-space: pre-wrap;
2475 }
2476 }
2476 #changeset_content .container .left .message a:hover {
2477 #changeset_content .container .left .message a:hover {
2477 text-decoration: none;
2478 text-decoration: none;
2478 }
2479 }
2479 .cs_files .cur_cs {
2480 .cs_files .cur_cs {
2480 margin: 10px 2px;
2481 margin: 10px 2px;
2481 font-weight: bold;
2482 font-weight: bold;
2482 }
2483 }
2483
2484
2484 .cs_files .node {
2485 .cs_files .node {
2485 float: left;
2486 float: left;
2486 }
2487 }
2487
2488
2488 .cs_files .changes {
2489 .cs_files .changes {
2489 float: right;
2490 float: right;
2490 color:#003367;
2491 color:#003367;
2491
2492
2492 }
2493 }
2493
2494
2494 .cs_files .changes .added {
2495 .cs_files .changes .added {
2495 background-color: #BBFFBB;
2496 background-color: #BBFFBB;
2496 float: left;
2497 float: left;
2497 text-align: center;
2498 text-align: center;
2498 font-size: 9px;
2499 font-size: 9px;
2499 padding: 2px 0px 2px 0px;
2500 padding: 2px 0px 2px 0px;
2500 }
2501 }
2501
2502
2502 .cs_files .changes .deleted {
2503 .cs_files .changes .deleted {
2503 background-color: #FF8888;
2504 background-color: #FF8888;
2504 float: left;
2505 float: left;
2505 text-align: center;
2506 text-align: center;
2506 font-size: 9px;
2507 font-size: 9px;
2507 padding: 2px 0px 2px 0px;
2508 padding: 2px 0px 2px 0px;
2508 }
2509 }
2509 /*new binary*/
2510 /*new binary*/
2510 .cs_files .changes .bin1 {
2511 .cs_files .changes .bin1 {
2511 background-color: #BBFFBB;
2512 background-color: #BBFFBB;
2512 float: left;
2513 float: left;
2513 text-align: center;
2514 text-align: center;
2514 font-size: 9px;
2515 font-size: 9px;
2515 padding: 2px 0px 2px 0px;
2516 padding: 2px 0px 2px 0px;
2516 }
2517 }
2517
2518
2518 /*deleted binary*/
2519 /*deleted binary*/
2519 .cs_files .changes .bin2 {
2520 .cs_files .changes .bin2 {
2520 background-color: #FF8888;
2521 background-color: #FF8888;
2521 float: left;
2522 float: left;
2522 text-align: center;
2523 text-align: center;
2523 font-size: 9px;
2524 font-size: 9px;
2524 padding: 2px 0px 2px 0px;
2525 padding: 2px 0px 2px 0px;
2525 }
2526 }
2526
2527
2527 /*mod binary*/
2528 /*mod binary*/
2528 .cs_files .changes .bin3 {
2529 .cs_files .changes .bin3 {
2529 background-color: #DDDDDD;
2530 background-color: #DDDDDD;
2530 float: left;
2531 float: left;
2531 text-align: center;
2532 text-align: center;
2532 font-size: 9px;
2533 font-size: 9px;
2533 padding: 2px 0px 2px 0px;
2534 padding: 2px 0px 2px 0px;
2534 }
2535 }
2535
2536
2536 /*rename file*/
2537 /*rename file*/
2537 .cs_files .changes .bin4 {
2538 .cs_files .changes .bin4 {
2538 background-color: #6D99FF;
2539 background-color: #6D99FF;
2539 float: left;
2540 float: left;
2540 text-align: center;
2541 text-align: center;
2541 font-size: 9px;
2542 font-size: 9px;
2542 padding: 2px 0px 2px 0px;
2543 padding: 2px 0px 2px 0px;
2543 }
2544 }
2544
2545
2545
2546
2546 .cs_files .cs_added,.cs_files .cs_A {
2547 .cs_files .cs_added,.cs_files .cs_A {
2547 background: url("../images/icons/page_white_add.png") no-repeat scroll
2548 background: url("../images/icons/page_white_add.png") no-repeat scroll
2548 3px;
2549 3px;
2549 height: 16px;
2550 height: 16px;
2550 padding-left: 20px;
2551 padding-left: 20px;
2551 margin-top: 7px;
2552 margin-top: 7px;
2552 text-align: left;
2553 text-align: left;
2553 }
2554 }
2554
2555
2555 .cs_files .cs_changed,.cs_files .cs_M {
2556 .cs_files .cs_changed,.cs_files .cs_M {
2556 background: url("../images/icons/page_white_edit.png") no-repeat scroll
2557 background: url("../images/icons/page_white_edit.png") no-repeat scroll
2557 3px;
2558 3px;
2558 height: 16px;
2559 height: 16px;
2559 padding-left: 20px;
2560 padding-left: 20px;
2560 margin-top: 7px;
2561 margin-top: 7px;
2561 text-align: left;
2562 text-align: left;
2562 }
2563 }
2563
2564
2564 .cs_files .cs_removed,.cs_files .cs_D {
2565 .cs_files .cs_removed,.cs_files .cs_D {
2565 background: url("../images/icons/page_white_delete.png") no-repeat
2566 background: url("../images/icons/page_white_delete.png") no-repeat
2566 scroll 3px;
2567 scroll 3px;
2567 height: 16px;
2568 height: 16px;
2568 padding-left: 20px;
2569 padding-left: 20px;
2569 margin-top: 7px;
2570 margin-top: 7px;
2570 text-align: left;
2571 text-align: left;
2571 }
2572 }
2572
2573
2573 #graph {
2574 #graph {
2574 overflow: hidden;
2575 overflow: hidden;
2575 }
2576 }
2576
2577
2577 #graph_nodes {
2578 #graph_nodes {
2578 float: left;
2579 float: left;
2579 margin-right: 0px;
2580 margin-right: 0px;
2580 margin-top: 0px;
2581 margin-top: 0px;
2581 }
2582 }
2582
2583
2583 #graph_content {
2584 #graph_content {
2584 width: 80%;
2585 width: 80%;
2585 float: left;
2586 float: left;
2586 }
2587 }
2587
2588
2588 #graph_content .container_header {
2589 #graph_content .container_header {
2589 border-bottom: 1px solid #DDD;
2590 border-bottom: 1px solid #DDD;
2590 padding: 10px;
2591 padding: 10px;
2591 height: 25px;
2592 height: 25px;
2592 }
2593 }
2593
2594
2594 #graph_content #rev_range_container {
2595 #graph_content #rev_range_container {
2595 float: left;
2596 float: left;
2596 margin: 0px 0px 0px 3px;
2597 margin: 0px 0px 0px 3px;
2597 }
2598 }
2598
2599
2599 #graph_content #rev_range_clear {
2600 #graph_content #rev_range_clear {
2600 float: left;
2601 float: left;
2601 margin: 0px 0px 0px 3px;
2602 margin: 0px 0px 0px 3px;
2602 }
2603 }
2603
2604
2604 #graph_content .container {
2605 #graph_content .container {
2605 border-bottom: 1px solid #DDD;
2606 border-bottom: 1px solid #DDD;
2606 height: 56px;
2607 height: 56px;
2607 overflow: hidden;
2608 overflow: hidden;
2608 }
2609 }
2609
2610
2610 #graph_content .container .right {
2611 #graph_content .container .right {
2611 float: right;
2612 float: right;
2612 width: 23%;
2613 width: 23%;
2613 text-align: right;
2614 text-align: right;
2614 }
2615 }
2615
2616
2616 #graph_content .container .left {
2617 #graph_content .container .left {
2617 float: left;
2618 float: left;
2618 width: 25%;
2619 width: 25%;
2619 padding-left: 5px;
2620 padding-left: 5px;
2620 }
2621 }
2621
2622
2622 #graph_content .container .mid {
2623 #graph_content .container .mid {
2623 float: left;
2624 float: left;
2624 width: 49%;
2625 width: 49%;
2625 }
2626 }
2626
2627
2627
2628
2628 #graph_content .container .left .date {
2629 #graph_content .container .left .date {
2629 color: #666;
2630 color: #666;
2630 padding-left: 22px;
2631 padding-left: 22px;
2631 font-size: 10px;
2632 font-size: 10px;
2632 }
2633 }
2633
2634
2634 #graph_content .container .left .author {
2635 #graph_content .container .left .author {
2635 height: 22px;
2636 height: 22px;
2636 }
2637 }
2637
2638
2638 #graph_content .container .left .author .user {
2639 #graph_content .container .left .author .user {
2639 color: #444444;
2640 color: #444444;
2640 float: left;
2641 float: left;
2641 margin-left: -4px;
2642 margin-left: -4px;
2642 margin-top: 4px;
2643 margin-top: 4px;
2643 }
2644 }
2644
2645
2645 #graph_content .container .mid .message {
2646 #graph_content .container .mid .message {
2646 white-space: pre-wrap;
2647 white-space: pre-wrap;
2647 }
2648 }
2648
2649
2649 #graph_content .container .mid .message a:hover{
2650 #graph_content .container .mid .message a:hover{
2650 text-decoration: none;
2651 text-decoration: none;
2651 }
2652 }
2652 #content #graph_content .message .revision-link,
2653 #content #graph_content .message .revision-link,
2653 #changeset_content .container .message .revision-link
2654 #changeset_content .container .message .revision-link
2654 {
2655 {
2655 color:#3F6F9F;
2656 color:#3F6F9F;
2656 font-weight: bold !important;
2657 font-weight: bold !important;
2657 }
2658 }
2658
2659
2659 #content #graph_content .message .issue-tracker-link,
2660 #content #graph_content .message .issue-tracker-link,
2660 #changeset_content .container .message .issue-tracker-link{
2661 #changeset_content .container .message .issue-tracker-link{
2661 color:#3F6F9F;
2662 color:#3F6F9F;
2662 font-weight: bold !important;
2663 font-weight: bold !important;
2663 }
2664 }
2664
2665
2665 .changeset-status-container{
2666 .changeset-status-container{
2666 padding-right: 5px;
2667 padding-right: 5px;
2667 margin-top:1px;
2668 margin-top:1px;
2668 float:right;
2669 float:right;
2669 height:14px;
2670 height:14px;
2670 }
2671 }
2671 .code-header .changeset-status-container{
2672 .code-header .changeset-status-container{
2672 float:left;
2673 float:left;
2673 padding:2px 0px 0px 2px;
2674 padding:2px 0px 0px 2px;
2674 }
2675 }
2675 .changeset-status-container .changeset-status-lbl{
2676 .changeset-status-container .changeset-status-lbl{
2676 color: rgb(136, 136, 136);
2677 color: rgb(136, 136, 136);
2677 float: left;
2678 float: left;
2678 padding: 3px 4px 0px 0px
2679 padding: 3px 4px 0px 0px
2679 }
2680 }
2680 .code-header .changeset-status-container .changeset-status-lbl{
2681 .code-header .changeset-status-container .changeset-status-lbl{
2681 float: left;
2682 float: left;
2682 padding: 0px 4px 0px 0px;
2683 padding: 0px 4px 0px 0px;
2683 }
2684 }
2684 .changeset-status-container .changeset-status-ico{
2685 .changeset-status-container .changeset-status-ico{
2685 float: left;
2686 float: left;
2686 }
2687 }
2687 .code-header .changeset-status-container .changeset-status-ico, .container .changeset-status-ico{
2688 .code-header .changeset-status-container .changeset-status-ico, .container .changeset-status-ico{
2688 float: left;
2689 float: left;
2689 }
2690 }
2690 .right .comments-container{
2691 .right .comments-container{
2691 padding-right: 5px;
2692 padding-right: 5px;
2692 margin-top:1px;
2693 margin-top:1px;
2693 float:right;
2694 float:right;
2694 height:14px;
2695 height:14px;
2695 }
2696 }
2696
2697
2697 .right .comments-cnt{
2698 .right .comments-cnt{
2698 float: left;
2699 float: left;
2699 color: rgb(136, 136, 136);
2700 color: rgb(136, 136, 136);
2700 padding-right: 2px;
2701 padding-right: 2px;
2701 }
2702 }
2702
2703
2703 .right .changes{
2704 .right .changes{
2704 clear: both;
2705 clear: both;
2705 }
2706 }
2706
2707
2707 .right .changes .changed_total {
2708 .right .changes .changed_total {
2708 display: block;
2709 display: block;
2709 float: right;
2710 float: right;
2710 text-align: center;
2711 text-align: center;
2711 min-width: 45px;
2712 min-width: 45px;
2712 cursor: pointer;
2713 cursor: pointer;
2713 color: #444444;
2714 color: #444444;
2714 background: #FEA;
2715 background: #FEA;
2715 -webkit-border-radius: 0px 0px 0px 6px;
2716 -webkit-border-radius: 0px 0px 0px 6px;
2716 -moz-border-radius: 0px 0px 0px 6px;
2717 -moz-border-radius: 0px 0px 0px 6px;
2717 border-radius: 0px 0px 0px 6px;
2718 border-radius: 0px 0px 0px 6px;
2718 padding: 1px;
2719 padding: 1px;
2719 }
2720 }
2720
2721
2721 .right .changes .added,.changed,.removed {
2722 .right .changes .added,.changed,.removed {
2722 display: block;
2723 display: block;
2723 padding: 1px;
2724 padding: 1px;
2724 color: #444444;
2725 color: #444444;
2725 float: right;
2726 float: right;
2726 text-align: center;
2727 text-align: center;
2727 min-width: 15px;
2728 min-width: 15px;
2728 }
2729 }
2729
2730
2730 .right .changes .added {
2731 .right .changes .added {
2731 background: #CFC;
2732 background: #CFC;
2732 }
2733 }
2733
2734
2734 .right .changes .changed {
2735 .right .changes .changed {
2735 background: #FEA;
2736 background: #FEA;
2736 }
2737 }
2737
2738
2738 .right .changes .removed {
2739 .right .changes .removed {
2739 background: #FAA;
2740 background: #FAA;
2740 }
2741 }
2741
2742
2742 .right .merge {
2743 .right .merge {
2743 padding: 1px 3px 1px 3px;
2744 padding: 1px 3px 1px 3px;
2744 background-color: #fca062;
2745 background-color: #fca062;
2745 font-size: 10px;
2746 font-size: 10px;
2746 font-weight: bold;
2747 font-weight: bold;
2747 color: #ffffff;
2748 color: #ffffff;
2748 text-transform: uppercase;
2749 text-transform: uppercase;
2749 white-space: nowrap;
2750 white-space: nowrap;
2750 -webkit-border-radius: 3px;
2751 -webkit-border-radius: 3px;
2751 -moz-border-radius: 3px;
2752 -moz-border-radius: 3px;
2752 border-radius: 3px;
2753 border-radius: 3px;
2753 margin-right: 2px;
2754 margin-right: 2px;
2754 }
2755 }
2755
2756
2756 .right .parent {
2757 .right .parent {
2757 color: #666666;
2758 color: #666666;
2758 clear:both;
2759 clear:both;
2759 }
2760 }
2760 .right .logtags{
2761 .right .logtags{
2761 padding: 2px 2px 2px 2px;
2762 padding: 2px 2px 2px 2px;
2762 }
2763 }
2763 .right .logtags .branchtag,.right .logtags .tagtag,.right .logtags .booktag{
2764 .right .logtags .branchtag,.right .logtags .tagtag,.right .logtags .booktag{
2764 margin: 0px 2px;
2765 margin: 0px 2px;
2765 }
2766 }
2766
2767
2767 .right .logtags .branchtag,.logtags .branchtag {
2768 .right .logtags .branchtag,.logtags .branchtag {
2768 padding: 1px 3px 1px 3px;
2769 padding: 1px 3px 1px 3px;
2769 background-color: #bfbfbf;
2770 background-color: #bfbfbf;
2770 font-size: 10px;
2771 font-size: 10px;
2771 font-weight: bold;
2772 font-weight: bold;
2772 color: #ffffff;
2773 color: #ffffff;
2773 text-transform: uppercase;
2774 text-transform: uppercase;
2774 white-space: nowrap;
2775 white-space: nowrap;
2775 -webkit-border-radius: 3px;
2776 -webkit-border-radius: 3px;
2776 -moz-border-radius: 3px;
2777 -moz-border-radius: 3px;
2777 border-radius: 3px;
2778 border-radius: 3px;
2778 }
2779 }
2779 .right .logtags .branchtag a:hover,.logtags .branchtag a{
2780 .right .logtags .branchtag a:hover,.logtags .branchtag a{
2780 color: #ffffff;
2781 color: #ffffff;
2781 }
2782 }
2782 .right .logtags .branchtag a:hover,.logtags .branchtag a:hover{
2783 .right .logtags .branchtag a:hover,.logtags .branchtag a:hover{
2783 text-decoration: none;
2784 text-decoration: none;
2784 color: #ffffff;
2785 color: #ffffff;
2785 }
2786 }
2786 .right .logtags .tagtag,.logtags .tagtag {
2787 .right .logtags .tagtag,.logtags .tagtag {
2787 padding: 1px 3px 1px 3px;
2788 padding: 1px 3px 1px 3px;
2788 background-color: #62cffc;
2789 background-color: #62cffc;
2789 font-size: 10px;
2790 font-size: 10px;
2790 font-weight: bold;
2791 font-weight: bold;
2791 color: #ffffff;
2792 color: #ffffff;
2792 text-transform: uppercase;
2793 text-transform: uppercase;
2793 white-space: nowrap;
2794 white-space: nowrap;
2794 -webkit-border-radius: 3px;
2795 -webkit-border-radius: 3px;
2795 -moz-border-radius: 3px;
2796 -moz-border-radius: 3px;
2796 border-radius: 3px;
2797 border-radius: 3px;
2797 }
2798 }
2798 .right .logtags .tagtag a:hover,.logtags .tagtag a{
2799 .right .logtags .tagtag a:hover,.logtags .tagtag a{
2799 color: #ffffff;
2800 color: #ffffff;
2800 }
2801 }
2801 .right .logtags .tagtag a:hover,.logtags .tagtag a:hover{
2802 .right .logtags .tagtag a:hover,.logtags .tagtag a:hover{
2802 text-decoration: none;
2803 text-decoration: none;
2803 color: #ffffff;
2804 color: #ffffff;
2804 }
2805 }
2805 .right .logbooks .bookbook,.logbooks .bookbook,.right .logtags .bookbook,.logtags .bookbook {
2806 .right .logbooks .bookbook,.logbooks .bookbook,.right .logtags .bookbook,.logtags .bookbook {
2806 padding: 1px 3px 1px 3px;
2807 padding: 1px 3px 1px 3px;
2807 background-color: #46A546;
2808 background-color: #46A546;
2808 font-size: 10px;
2809 font-size: 10px;
2809 font-weight: bold;
2810 font-weight: bold;
2810 color: #ffffff;
2811 color: #ffffff;
2811 text-transform: uppercase;
2812 text-transform: uppercase;
2812 white-space: nowrap;
2813 white-space: nowrap;
2813 -webkit-border-radius: 3px;
2814 -webkit-border-radius: 3px;
2814 -moz-border-radius: 3px;
2815 -moz-border-radius: 3px;
2815 border-radius: 3px;
2816 border-radius: 3px;
2816 }
2817 }
2817 .right .logbooks .bookbook,.logbooks .bookbook a,.right .logtags .bookbook,.logtags .bookbook a{
2818 .right .logbooks .bookbook,.logbooks .bookbook a,.right .logtags .bookbook,.logtags .bookbook a{
2818 color: #ffffff;
2819 color: #ffffff;
2819 }
2820 }
2820 .right .logbooks .bookbook,.logbooks .bookbook a:hover,.right .logtags .bookbook,.logtags .bookbook a:hover{
2821 .right .logbooks .bookbook,.logbooks .bookbook a:hover,.right .logtags .bookbook,.logtags .bookbook a:hover{
2821 text-decoration: none;
2822 text-decoration: none;
2822 color: #ffffff;
2823 color: #ffffff;
2823 }
2824 }
2824 div.browserblock {
2825 div.browserblock {
2825 overflow: hidden;
2826 overflow: hidden;
2826 border: 1px solid #ccc;
2827 border: 1px solid #ccc;
2827 background: #f8f8f8;
2828 background: #f8f8f8;
2828 font-size: 100%;
2829 font-size: 100%;
2829 line-height: 125%;
2830 line-height: 125%;
2830 padding: 0;
2831 padding: 0;
2831 -webkit-border-radius: 6px 6px 0px 0px;
2832 -webkit-border-radius: 6px 6px 0px 0px;
2832 -moz-border-radius: 6px 6px 0px 0px;
2833 -moz-border-radius: 6px 6px 0px 0px;
2833 border-radius: 6px 6px 0px 0px;
2834 border-radius: 6px 6px 0px 0px;
2834 }
2835 }
2835
2836
2836 div.browserblock .browser-header {
2837 div.browserblock .browser-header {
2837 background: #FFF;
2838 background: #FFF;
2838 padding: 10px 0px 15px 0px;
2839 padding: 10px 0px 15px 0px;
2839 width: 100%;
2840 width: 100%;
2840 }
2841 }
2841
2842
2842 div.browserblock .browser-nav {
2843 div.browserblock .browser-nav {
2843 float: left
2844 float: left
2844 }
2845 }
2845
2846
2846 div.browserblock .browser-branch {
2847 div.browserblock .browser-branch {
2847 float: left;
2848 float: left;
2848 }
2849 }
2849
2850
2850 div.browserblock .browser-branch label {
2851 div.browserblock .browser-branch label {
2851 color: #4A4A4A;
2852 color: #4A4A4A;
2852 vertical-align: text-top;
2853 vertical-align: text-top;
2853 }
2854 }
2854
2855
2855 div.browserblock .browser-header span {
2856 div.browserblock .browser-header span {
2856 margin-left: 5px;
2857 margin-left: 5px;
2857 font-weight: 700;
2858 font-weight: 700;
2858 }
2859 }
2859
2860
2860 div.browserblock .browser-search {
2861 div.browserblock .browser-search {
2861 clear: both;
2862 clear: both;
2862 padding: 8px 8px 0px 5px;
2863 padding: 8px 8px 0px 5px;
2863 height: 20px;
2864 height: 20px;
2864 }
2865 }
2865
2866
2866 div.browserblock #node_filter_box {
2867 div.browserblock #node_filter_box {
2867
2868
2868 }
2869 }
2869
2870
2870 div.browserblock .search_activate {
2871 div.browserblock .search_activate {
2871 float: left
2872 float: left
2872 }
2873 }
2873
2874
2874 div.browserblock .add_node {
2875 div.browserblock .add_node {
2875 float: left;
2876 float: left;
2876 padding-left: 5px;
2877 padding-left: 5px;
2877 }
2878 }
2878
2879
2879 div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover
2880 div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover
2880 {
2881 {
2881 text-decoration: none !important;
2882 text-decoration: none !important;
2882 }
2883 }
2883
2884
2884 div.browserblock .browser-body {
2885 div.browserblock .browser-body {
2885 background: #EEE;
2886 background: #EEE;
2886 border-top: 1px solid #CCC;
2887 border-top: 1px solid #CCC;
2887 }
2888 }
2888
2889
2889 table.code-browser {
2890 table.code-browser {
2890 border-collapse: collapse;
2891 border-collapse: collapse;
2891 width: 100%;
2892 width: 100%;
2892 }
2893 }
2893
2894
2894 table.code-browser tr {
2895 table.code-browser tr {
2895 margin: 3px;
2896 margin: 3px;
2896 }
2897 }
2897
2898
2898 table.code-browser thead th {
2899 table.code-browser thead th {
2899 background-color: #EEE;
2900 background-color: #EEE;
2900 height: 20px;
2901 height: 20px;
2901 font-size: 1.1em;
2902 font-size: 1.1em;
2902 font-weight: 700;
2903 font-weight: 700;
2903 text-align: left;
2904 text-align: left;
2904 padding-left: 10px;
2905 padding-left: 10px;
2905 }
2906 }
2906
2907
2907 table.code-browser tbody td {
2908 table.code-browser tbody td {
2908 padding-left: 10px;
2909 padding-left: 10px;
2909 height: 20px;
2910 height: 20px;
2910 }
2911 }
2911
2912
2912 table.code-browser .browser-file {
2913 table.code-browser .browser-file {
2913 background: url("../images/icons/document_16.png") no-repeat scroll 3px;
2914 background: url("../images/icons/document_16.png") no-repeat scroll 3px;
2914 height: 16px;
2915 height: 16px;
2915 padding-left: 20px;
2916 padding-left: 20px;
2916 text-align: left;
2917 text-align: left;
2917 }
2918 }
2918 .diffblock .changeset_header {
2919 .diffblock .changeset_header {
2919 height: 16px;
2920 height: 16px;
2920 }
2921 }
2921 .diffblock .changeset_file {
2922 .diffblock .changeset_file {
2922 background: url("../images/icons/file.png") no-repeat scroll 3px;
2923 background: url("../images/icons/file.png") no-repeat scroll 3px;
2923 text-align: left;
2924 text-align: left;
2924 float: left;
2925 float: left;
2925 padding: 2px 0px 2px 22px;
2926 padding: 2px 0px 2px 22px;
2926 }
2927 }
2927 .diffblock .diff-menu-wrapper{
2928 .diffblock .diff-menu-wrapper{
2928 float: left;
2929 float: left;
2929 }
2930 }
2930
2931
2931 .diffblock .diff-menu{
2932 .diffblock .diff-menu{
2932 position: absolute;
2933 position: absolute;
2933 background: none repeat scroll 0 0 #FFFFFF;
2934 background: none repeat scroll 0 0 #FFFFFF;
2934 border-color: #003367 #666666 #666666;
2935 border-color: #003367 #666666 #666666;
2935 border-right: 1px solid #666666;
2936 border-right: 1px solid #666666;
2936 border-style: solid solid solid;
2937 border-style: solid solid solid;
2937 border-width: 1px;
2938 border-width: 1px;
2938 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
2939 box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2);
2939 margin-top:5px;
2940 margin-top:5px;
2940 margin-left:1px;
2941 margin-left:1px;
2941
2942
2942 }
2943 }
2943 .diffblock .diff-actions {
2944 .diffblock .diff-actions {
2944 padding: 2px 0px 0px 2px;
2945 padding: 2px 0px 0px 2px;
2945 float: left;
2946 float: left;
2946 }
2947 }
2947 .diffblock .diff-menu ul li {
2948 .diffblock .diff-menu ul li {
2948 padding: 0px 0px 0px 0px !important;
2949 padding: 0px 0px 0px 0px !important;
2949 }
2950 }
2950 .diffblock .diff-menu ul li a{
2951 .diffblock .diff-menu ul li a{
2951 display: block;
2952 display: block;
2952 padding: 3px 8px 3px 8px !important;
2953 padding: 3px 8px 3px 8px !important;
2953 }
2954 }
2954 .diffblock .diff-menu ul li a:hover{
2955 .diffblock .diff-menu ul li a:hover{
2955 text-decoration: none;
2956 text-decoration: none;
2956 background-color: #EEEEEE;
2957 background-color: #EEEEEE;
2957 }
2958 }
2958 table.code-browser .browser-dir {
2959 table.code-browser .browser-dir {
2959 background: url("../images/icons/folder_16.png") no-repeat scroll 3px;
2960 background: url("../images/icons/folder_16.png") no-repeat scroll 3px;
2960 height: 16px;
2961 height: 16px;
2961 padding-left: 20px;
2962 padding-left: 20px;
2962 text-align: left;
2963 text-align: left;
2963 }
2964 }
2964
2965
2965 table.code-browser .submodule-dir {
2966 table.code-browser .submodule-dir {
2966 background: url("../images/icons/disconnect.png") no-repeat scroll 3px;
2967 background: url("../images/icons/disconnect.png") no-repeat scroll 3px;
2967 height: 16px;
2968 height: 16px;
2968 padding-left: 20px;
2969 padding-left: 20px;
2969 text-align: left;
2970 text-align: left;
2970 }
2971 }
2971
2972
2972
2973
2973 .box .search {
2974 .box .search {
2974 clear: both;
2975 clear: both;
2975 overflow: hidden;
2976 overflow: hidden;
2976 margin: 0;
2977 margin: 0;
2977 padding: 0 20px 10px;
2978 padding: 0 20px 10px;
2978 }
2979 }
2979
2980
2980 .box .search div.search_path {
2981 .box .search div.search_path {
2981 background: none repeat scroll 0 0 #EEE;
2982 background: none repeat scroll 0 0 #EEE;
2982 border: 1px solid #CCC;
2983 border: 1px solid #CCC;
2983 color: blue;
2984 color: blue;
2984 margin-bottom: 10px;
2985 margin-bottom: 10px;
2985 padding: 10px 0;
2986 padding: 10px 0;
2986 }
2987 }
2987
2988
2988 .box .search div.search_path div.link {
2989 .box .search div.search_path div.link {
2989 font-weight: 700;
2990 font-weight: 700;
2990 margin-left: 25px;
2991 margin-left: 25px;
2991 }
2992 }
2992
2993
2993 .box .search div.search_path div.link a {
2994 .box .search div.search_path div.link a {
2994 color: #003367;
2995 color: #003367;
2995 cursor: pointer;
2996 cursor: pointer;
2996 text-decoration: none;
2997 text-decoration: none;
2997 }
2998 }
2998
2999
2999 #path_unlock {
3000 #path_unlock {
3000 color: red;
3001 color: red;
3001 font-size: 1.2em;
3002 font-size: 1.2em;
3002 padding-left: 4px;
3003 padding-left: 4px;
3003 }
3004 }
3004
3005
3005 .info_box span {
3006 .info_box span {
3006 margin-left: 3px;
3007 margin-left: 3px;
3007 margin-right: 3px;
3008 margin-right: 3px;
3008 }
3009 }
3009
3010
3010 .info_box .rev {
3011 .info_box .rev {
3011 color: #003367;
3012 color: #003367;
3012 font-size: 1.6em;
3013 font-size: 1.6em;
3013 font-weight: bold;
3014 font-weight: bold;
3014 vertical-align: sub;
3015 vertical-align: sub;
3015 }
3016 }
3016
3017
3017 .info_box input#at_rev,.info_box input#size {
3018 .info_box input#at_rev,.info_box input#size {
3018 background: #FFF;
3019 background: #FFF;
3019 border-top: 1px solid #b3b3b3;
3020 border-top: 1px solid #b3b3b3;
3020 border-left: 1px solid #b3b3b3;
3021 border-left: 1px solid #b3b3b3;
3021 border-right: 1px solid #eaeaea;
3022 border-right: 1px solid #eaeaea;
3022 border-bottom: 1px solid #eaeaea;
3023 border-bottom: 1px solid #eaeaea;
3023 color: #000;
3024 color: #000;
3024 font-size: 12px;
3025 font-size: 12px;
3025 margin: 0;
3026 margin: 0;
3026 padding: 1px 5px 1px;
3027 padding: 1px 5px 1px;
3027 }
3028 }
3028
3029
3029 .info_box input#view {
3030 .info_box input#view {
3030 text-align: center;
3031 text-align: center;
3031 padding: 4px 3px 2px 2px;
3032 padding: 4px 3px 2px 2px;
3032 }
3033 }
3033
3034
3034 .yui-overlay,.yui-panel-container {
3035 .yui-overlay,.yui-panel-container {
3035 visibility: hidden;
3036 visibility: hidden;
3036 position: absolute;
3037 position: absolute;
3037 z-index: 2;
3038 z-index: 2;
3038 }
3039 }
3039
3040
3040 #tip-box {
3041 #tip-box {
3041 position: absolute;
3042 position: absolute;
3042
3043
3043 background-color: #FFF;
3044 background-color: #FFF;
3044 border: 2px solid #003367;
3045 border: 2px solid #003367;
3045 font: 100% sans-serif;
3046 font: 100% sans-serif;
3046 width: auto;
3047 width: auto;
3047 opacity: 1px;
3048 opacity: 1px;
3048 padding: 8px;
3049 padding: 8px;
3049
3050
3050 white-space: pre-wrap;
3051 white-space: pre-wrap;
3051 -webkit-border-radius: 8px 8px 8px 8px;
3052 -webkit-border-radius: 8px 8px 8px 8px;
3052 -khtml-border-radius: 8px 8px 8px 8px;
3053 -khtml-border-radius: 8px 8px 8px 8px;
3053 -moz-border-radius: 8px 8px 8px 8px;
3054 -moz-border-radius: 8px 8px 8px 8px;
3054 border-radius: 8px 8px 8px 8px;
3055 border-radius: 8px 8px 8px 8px;
3055 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3056 box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3056 -moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3057 -moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3057 -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3058 -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6);
3058 }
3059 }
3059
3060
3060 .mentions-container{
3061 .mentions-container{
3061 width: 90% !important;
3062 width: 90% !important;
3062 }
3063 }
3063 .mentions-container .yui-ac-content{
3064 .mentions-container .yui-ac-content{
3064 width: 100% !important;
3065 width: 100% !important;
3065 }
3066 }
3066
3067
3067 .ac {
3068 .ac {
3068 vertical-align: top;
3069 vertical-align: top;
3069 }
3070 }
3070
3071
3071 .ac .yui-ac {
3072 .ac .yui-ac {
3072 position: inherit;
3073 position: inherit;
3073 font-size: 100%;
3074 font-size: 100%;
3074 }
3075 }
3075
3076
3076 .ac .perm_ac {
3077 .ac .perm_ac {
3077 width: 20em;
3078 width: 20em;
3078 }
3079 }
3079
3080
3080 .ac .yui-ac-input {
3081 .ac .yui-ac-input {
3081 width: 100%;
3082 width: 100%;
3082 }
3083 }
3083
3084
3084 .ac .yui-ac-container {
3085 .ac .yui-ac-container {
3085 position: absolute;
3086 position: absolute;
3086 top: 1.6em;
3087 top: 1.6em;
3087 width: auto;
3088 width: auto;
3088 }
3089 }
3089
3090
3090 .ac .yui-ac-content {
3091 .ac .yui-ac-content {
3091 position: absolute;
3092 position: absolute;
3092 border: 1px solid gray;
3093 border: 1px solid gray;
3093 background: #fff;
3094 background: #fff;
3094 z-index: 9050;
3095 z-index: 9050;
3095
3096
3096 }
3097 }
3097
3098
3098 .ac .yui-ac-shadow {
3099 .ac .yui-ac-shadow {
3099 position: absolute;
3100 position: absolute;
3100 width: 100%;
3101 width: 100%;
3101 background: #000;
3102 background: #000;
3102 -moz-opacity: 0.1px;
3103 -moz-opacity: 0.1px;
3103 opacity: .10;
3104 opacity: .10;
3104 filter: alpha(opacity = 10);
3105 filter: alpha(opacity = 10);
3105 z-index: 9049;
3106 z-index: 9049;
3106 margin: .3em;
3107 margin: .3em;
3107 }
3108 }
3108
3109
3109 .ac .yui-ac-content ul {
3110 .ac .yui-ac-content ul {
3110 width: 100%;
3111 width: 100%;
3111 margin: 0;
3112 margin: 0;
3112 padding: 0;
3113 padding: 0;
3113 z-index: 9050;
3114 z-index: 9050;
3114 }
3115 }
3115
3116
3116 .ac .yui-ac-content li {
3117 .ac .yui-ac-content li {
3117 cursor: default;
3118 cursor: default;
3118 white-space: nowrap;
3119 white-space: nowrap;
3119 margin: 0;
3120 margin: 0;
3120 padding: 2px 5px;
3121 padding: 2px 5px;
3121 height: 18px;
3122 height: 18px;
3122 z-index: 9050;
3123 z-index: 9050;
3123 display: block;
3124 display: block;
3124 width: auto !important;
3125 width: auto !important;
3125 }
3126 }
3126
3127
3127 .ac .yui-ac-content li .ac-container-wrap{
3128 .ac .yui-ac-content li .ac-container-wrap{
3128 width: auto;
3129 width: auto;
3129 }
3130 }
3130
3131
3131 .ac .yui-ac-content li.yui-ac-prehighlight {
3132 .ac .yui-ac-content li.yui-ac-prehighlight {
3132 background: #B3D4FF;
3133 background: #B3D4FF;
3133 z-index: 9050;
3134 z-index: 9050;
3134 }
3135 }
3135
3136
3136 .ac .yui-ac-content li.yui-ac-highlight {
3137 .ac .yui-ac-content li.yui-ac-highlight {
3137 background: #556CB5;
3138 background: #556CB5;
3138 color: #FFF;
3139 color: #FFF;
3139 z-index: 9050;
3140 z-index: 9050;
3140 }
3141 }
3141 .ac .yui-ac-bd{
3142 .ac .yui-ac-bd{
3142 z-index: 9050;
3143 z-index: 9050;
3143 }
3144 }
3144
3145
3145 .follow {
3146 .follow {
3146 background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
3147 background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
3147 height: 16px;
3148 height: 16px;
3148 width: 20px;
3149 width: 20px;
3149 cursor: pointer;
3150 cursor: pointer;
3150 display: block;
3151 display: block;
3151 float: right;
3152 float: right;
3152 margin-top: 2px;
3153 margin-top: 2px;
3153 }
3154 }
3154
3155
3155 .following {
3156 .following {
3156 background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
3157 background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
3157 height: 16px;
3158 height: 16px;
3158 width: 20px;
3159 width: 20px;
3159 cursor: pointer;
3160 cursor: pointer;
3160 display: block;
3161 display: block;
3161 float: right;
3162 float: right;
3162 margin-top: 2px;
3163 margin-top: 2px;
3163 }
3164 }
3164
3165
3165 .locking_locked{
3166 .locking_locked{
3166 background: #FFF url("../images/icons/block_16.png") no-repeat scroll 3px;
3167 background: #FFF url("../images/icons/block_16.png") no-repeat scroll 3px;
3167 height: 16px;
3168 height: 16px;
3168 width: 20px;
3169 width: 20px;
3169 cursor: pointer;
3170 cursor: pointer;
3170 display: block;
3171 display: block;
3171 float: right;
3172 float: right;
3172 margin-top: 2px;
3173 margin-top: 2px;
3173 }
3174 }
3174
3175
3175 .locking_unlocked{
3176 .locking_unlocked{
3176 background: #FFF url("../images/icons/accept.png") no-repeat scroll 3px;
3177 background: #FFF url("../images/icons/accept.png") no-repeat scroll 3px;
3177 height: 16px;
3178 height: 16px;
3178 width: 20px;
3179 width: 20px;
3179 cursor: pointer;
3180 cursor: pointer;
3180 display: block;
3181 display: block;
3181 float: right;
3182 float: right;
3182 margin-top: 2px;
3183 margin-top: 2px;
3183 }
3184 }
3184
3185
3185 .currently_following {
3186 .currently_following {
3186 padding-left: 10px;
3187 padding-left: 10px;
3187 padding-bottom: 5px;
3188 padding-bottom: 5px;
3188 }
3189 }
3189
3190
3190 .add_icon {
3191 .add_icon {
3191 background: url("../images/icons/add.png") no-repeat scroll 3px;
3192 background: url("../images/icons/add.png") no-repeat scroll 3px;
3192 padding-left: 20px;
3193 padding-left: 20px;
3193 padding-top: 0px;
3194 padding-top: 0px;
3194 text-align: left;
3195 text-align: left;
3195 }
3196 }
3196
3197
3197 .accept_icon {
3198 .accept_icon {
3198 background: url("../images/icons/accept.png") no-repeat scroll 3px;
3199 background: url("../images/icons/accept.png") no-repeat scroll 3px;
3199 padding-left: 20px;
3200 padding-left: 20px;
3200 padding-top: 0px;
3201 padding-top: 0px;
3201 text-align: left;
3202 text-align: left;
3202 }
3203 }
3203
3204
3204 .edit_icon {
3205 .edit_icon {
3205 background: url("../images/icons/folder_edit.png") no-repeat scroll 3px;
3206 background: url("../images/icons/folder_edit.png") no-repeat scroll 3px;
3206 padding-left: 20px;
3207 padding-left: 20px;
3207 padding-top: 0px;
3208 padding-top: 0px;
3208 text-align: left;
3209 text-align: left;
3209 }
3210 }
3210
3211
3211 .delete_icon {
3212 .delete_icon {
3212 background: url("../images/icons/delete.png") no-repeat scroll 3px;
3213 background: url("../images/icons/delete.png") no-repeat scroll 3px;
3213 padding-left: 20px;
3214 padding-left: 20px;
3214 padding-top: 0px;
3215 padding-top: 0px;
3215 text-align: left;
3216 text-align: left;
3216 }
3217 }
3217
3218
3218 .refresh_icon {
3219 .refresh_icon {
3219 background: url("../images/icons/arrow_refresh.png") no-repeat scroll
3220 background: url("../images/icons/arrow_refresh.png") no-repeat scroll
3220 3px;
3221 3px;
3221 padding-left: 20px;
3222 padding-left: 20px;
3222 padding-top: 0px;
3223 padding-top: 0px;
3223 text-align: left;
3224 text-align: left;
3224 }
3225 }
3225
3226
3226 .pull_icon {
3227 .pull_icon {
3227 background: url("../images/icons/connect.png") no-repeat scroll 3px;
3228 background: url("../images/icons/connect.png") no-repeat scroll 3px;
3228 padding-left: 20px;
3229 padding-left: 20px;
3229 padding-top: 0px;
3230 padding-top: 0px;
3230 text-align: left;
3231 text-align: left;
3231 }
3232 }
3232
3233
3233 .rss_icon {
3234 .rss_icon {
3234 background: url("../images/icons/rss_16.png") no-repeat scroll 3px;
3235 background: url("../images/icons/rss_16.png") no-repeat scroll 3px;
3235 padding-left: 20px;
3236 padding-left: 20px;
3236 padding-top: 4px;
3237 padding-top: 4px;
3237 text-align: left;
3238 text-align: left;
3238 font-size: 8px
3239 font-size: 8px
3239 }
3240 }
3240
3241
3241 .atom_icon {
3242 .atom_icon {
3242 background: url("../images/icons/atom.png") no-repeat scroll 3px;
3243 background: url("../images/icons/atom.png") no-repeat scroll 3px;
3243 padding-left: 20px;
3244 padding-left: 20px;
3244 padding-top: 4px;
3245 padding-top: 4px;
3245 text-align: left;
3246 text-align: left;
3246 font-size: 8px
3247 font-size: 8px
3247 }
3248 }
3248
3249
3249 .archive_icon {
3250 .archive_icon {
3250 background: url("../images/icons/compress.png") no-repeat scroll 3px;
3251 background: url("../images/icons/compress.png") no-repeat scroll 3px;
3251 padding-left: 20px;
3252 padding-left: 20px;
3252 text-align: left;
3253 text-align: left;
3253 padding-top: 1px;
3254 padding-top: 1px;
3254 }
3255 }
3255
3256
3256 .start_following_icon {
3257 .start_following_icon {
3257 background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
3258 background: url("../images/icons/heart_add.png") no-repeat scroll 3px;
3258 padding-left: 20px;
3259 padding-left: 20px;
3259 text-align: left;
3260 text-align: left;
3260 padding-top: 0px;
3261 padding-top: 0px;
3261 }
3262 }
3262
3263
3263 .stop_following_icon {
3264 .stop_following_icon {
3264 background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
3265 background: url("../images/icons/heart_delete.png") no-repeat scroll 3px;
3265 padding-left: 20px;
3266 padding-left: 20px;
3266 text-align: left;
3267 text-align: left;
3267 padding-top: 0px;
3268 padding-top: 0px;
3268 }
3269 }
3269
3270
3270 .action_button {
3271 .action_button {
3271 border: 0;
3272 border: 0;
3272 display: inline;
3273 display: inline;
3273 }
3274 }
3274
3275
3275 .action_button:hover {
3276 .action_button:hover {
3276 border: 0;
3277 border: 0;
3277 text-decoration: underline;
3278 text-decoration: underline;
3278 cursor: pointer;
3279 cursor: pointer;
3279 }
3280 }
3280
3281
3281 #switch_repos {
3282 #switch_repos {
3282 position: absolute;
3283 position: absolute;
3283 height: 25px;
3284 height: 25px;
3284 z-index: 1;
3285 z-index: 1;
3285 }
3286 }
3286
3287
3287 #switch_repos select {
3288 #switch_repos select {
3288 min-width: 150px;
3289 min-width: 150px;
3289 max-height: 250px;
3290 max-height: 250px;
3290 z-index: 1;
3291 z-index: 1;
3291 }
3292 }
3292
3293
3293 .breadcrumbs {
3294 .breadcrumbs {
3294 border: medium none;
3295 border: medium none;
3295 color: #FFF;
3296 color: #FFF;
3296 float: left;
3297 float: left;
3297 text-transform: uppercase;
3298 text-transform: uppercase;
3298 font-weight: 700;
3299 font-weight: 700;
3299 font-size: 14px;
3300 font-size: 14px;
3300 margin: 0;
3301 margin: 0;
3301 padding: 11px 0 11px 10px;
3302 padding: 11px 0 11px 10px;
3302 }
3303 }
3303
3304
3304 .breadcrumbs .hash {
3305 .breadcrumbs .hash {
3305 text-transform: none;
3306 text-transform: none;
3306 color: #fff;
3307 color: #fff;
3307 }
3308 }
3308
3309
3309 .breadcrumbs a {
3310 .breadcrumbs a {
3310 color: #FFF;
3311 color: #FFF;
3311 }
3312 }
3312
3313
3313 .flash_msg {
3314 .flash_msg {
3314
3315
3315 }
3316 }
3316
3317
3317 .flash_msg ul {
3318 .flash_msg ul {
3318
3319
3319 }
3320 }
3320
3321
3321 .error_red {
3322 .error_red {
3322 color:red;
3323 color:red;
3323 }
3324 }
3324
3325
3325 .error_msg {
3326 .error_msg {
3326 background-color: #c43c35;
3327 background-color: #c43c35;
3327 background-repeat: repeat-x;
3328 background-repeat: repeat-x;
3328 background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) );
3329 background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) );
3329 background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
3330 background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
3330 background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
3331 background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
3331 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
3332 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) );
3332 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3333 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3333 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3334 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3334 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3335 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3335 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
3336 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 );
3336 border-color: #c43c35 #c43c35 #882a25;
3337 border-color: #c43c35 #c43c35 #882a25;
3337 }
3338 }
3338
3339
3339 .warning_msg {
3340 .warning_msg {
3340 color: #404040 !important;
3341 color: #404040 !important;
3341 background-color: #eedc94;
3342 background-color: #eedc94;
3342 background-repeat: repeat-x;
3343 background-repeat: repeat-x;
3343 background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94) );
3344 background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94) );
3344 background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
3345 background-image: -moz-linear-gradient(top, #fceec1, #eedc94);
3345 background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
3346 background-image: -ms-linear-gradient(top, #fceec1, #eedc94);
3346 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
3347 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) );
3347 background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
3348 background-image: -webkit-linear-gradient(top, #fceec1, #eedc94);
3348 background-image: -o-linear-gradient(top, #fceec1, #eedc94);
3349 background-image: -o-linear-gradient(top, #fceec1, #eedc94);
3349 background-image: linear-gradient(top, #fceec1, #eedc94);
3350 background-image: linear-gradient(top, #fceec1, #eedc94);
3350 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
3351 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 );
3351 border-color: #eedc94 #eedc94 #e4c652;
3352 border-color: #eedc94 #eedc94 #e4c652;
3352 }
3353 }
3353
3354
3354 .success_msg {
3355 .success_msg {
3355 background-color: #57a957;
3356 background-color: #57a957;
3356 background-repeat: repeat-x !important;
3357 background-repeat: repeat-x !important;
3357 background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) );
3358 background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) );
3358 background-image: -moz-linear-gradient(top, #62c462, #57a957);
3359 background-image: -moz-linear-gradient(top, #62c462, #57a957);
3359 background-image: -ms-linear-gradient(top, #62c462, #57a957);
3360 background-image: -ms-linear-gradient(top, #62c462, #57a957);
3360 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
3361 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) );
3361 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3362 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3362 background-image: -o-linear-gradient(top, #62c462, #57a957);
3363 background-image: -o-linear-gradient(top, #62c462, #57a957);
3363 background-image: linear-gradient(top, #62c462, #57a957);
3364 background-image: linear-gradient(top, #62c462, #57a957);
3364 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
3365 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 );
3365 border-color: #57a957 #57a957 #3d773d;
3366 border-color: #57a957 #57a957 #3d773d;
3366 }
3367 }
3367
3368
3368 .notice_msg {
3369 .notice_msg {
3369 background-color: #339bb9;
3370 background-color: #339bb9;
3370 background-repeat: repeat-x;
3371 background-repeat: repeat-x;
3371 background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) );
3372 background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) );
3372 background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
3373 background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
3373 background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
3374 background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
3374 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
3375 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) );
3375 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3376 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3376 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3377 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3377 background-image: linear-gradient(top, #5bc0de, #339bb9);
3378 background-image: linear-gradient(top, #5bc0de, #339bb9);
3378 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
3379 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 );
3379 border-color: #339bb9 #339bb9 #22697d;
3380 border-color: #339bb9 #339bb9 #22697d;
3380 }
3381 }
3381
3382
3382 .success_msg,.error_msg,.notice_msg,.warning_msg {
3383 .success_msg,.error_msg,.notice_msg,.warning_msg {
3383 font-size: 12px;
3384 font-size: 12px;
3384 font-weight: 700;
3385 font-weight: 700;
3385 min-height: 14px;
3386 min-height: 14px;
3386 line-height: 14px;
3387 line-height: 14px;
3387 margin-bottom: 10px;
3388 margin-bottom: 10px;
3388 margin-top: 0;
3389 margin-top: 0;
3389 display: block;
3390 display: block;
3390 overflow: auto;
3391 overflow: auto;
3391 padding: 6px 10px 6px 10px;
3392 padding: 6px 10px 6px 10px;
3392 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3393 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3393 position: relative;
3394 position: relative;
3394 color: #FFF;
3395 color: #FFF;
3395 border-width: 1px;
3396 border-width: 1px;
3396 border-style: solid;
3397 border-style: solid;
3397 -webkit-border-radius: 4px;
3398 -webkit-border-radius: 4px;
3398 -moz-border-radius: 4px;
3399 -moz-border-radius: 4px;
3399 border-radius: 4px;
3400 border-radius: 4px;
3400 -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3401 -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3401 -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3402 -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3402 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3403 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
3403 }
3404 }
3404
3405
3405 #msg_close {
3406 #msg_close {
3406 background: transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
3407 background: transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0;
3407 cursor: pointer;
3408 cursor: pointer;
3408 height: 16px;
3409 height: 16px;
3409 position: absolute;
3410 position: absolute;
3410 right: 5px;
3411 right: 5px;
3411 top: 5px;
3412 top: 5px;
3412 width: 16px;
3413 width: 16px;
3413 }
3414 }
3414 div#legend_data{
3415 div#legend_data{
3415 padding-left:10px;
3416 padding-left:10px;
3416 }
3417 }
3417 div#legend_container table{
3418 div#legend_container table{
3418 border: none !important;
3419 border: none !important;
3419 }
3420 }
3420 div#legend_container table,div#legend_choices table {
3421 div#legend_container table,div#legend_choices table {
3421 width: auto !important;
3422 width: auto !important;
3422 }
3423 }
3423
3424
3424 table#permissions_manage {
3425 table#permissions_manage {
3425 width: 0 !important;
3426 width: 0 !important;
3426 }
3427 }
3427
3428
3428 table#permissions_manage span.private_repo_msg {
3429 table#permissions_manage span.private_repo_msg {
3429 font-size: 0.8em;
3430 font-size: 0.8em;
3430 opacity: 0.6px;
3431 opacity: 0.6px;
3431 }
3432 }
3432
3433
3433 table#permissions_manage td.private_repo_msg {
3434 table#permissions_manage td.private_repo_msg {
3434 font-size: 0.8em;
3435 font-size: 0.8em;
3435 }
3436 }
3436
3437
3437 table#permissions_manage tr#add_perm_input td {
3438 table#permissions_manage tr#add_perm_input td {
3438 vertical-align: middle;
3439 vertical-align: middle;
3439 }
3440 }
3440
3441
3441 div.gravatar {
3442 div.gravatar {
3442 background-color: #FFF;
3443 background-color: #FFF;
3443 float: left;
3444 float: left;
3444 margin-right: 0.7em;
3445 margin-right: 0.7em;
3445 padding: 1px 1px 1px 1px;
3446 padding: 1px 1px 1px 1px;
3446 line-height:0;
3447 line-height:0;
3447 -webkit-border-radius: 3px;
3448 -webkit-border-radius: 3px;
3448 -khtml-border-radius: 3px;
3449 -khtml-border-radius: 3px;
3449 -moz-border-radius: 3px;
3450 -moz-border-radius: 3px;
3450 border-radius: 3px;
3451 border-radius: 3px;
3451 }
3452 }
3452
3453
3453 div.gravatar img {
3454 div.gravatar img {
3454 -webkit-border-radius: 2px;
3455 -webkit-border-radius: 2px;
3455 -khtml-border-radius: 2px;
3456 -khtml-border-radius: 2px;
3456 -moz-border-radius: 2px;
3457 -moz-border-radius: 2px;
3457 border-radius: 2px;
3458 border-radius: 2px;
3458 }
3459 }
3459
3460
3460 #header,#content,#footer {
3461 #header,#content,#footer {
3461 min-width: 978px;
3462 min-width: 978px;
3462 }
3463 }
3463
3464
3464 #content {
3465 #content {
3465 clear: both;
3466 clear: both;
3466 overflow: hidden;
3467 overflow: hidden;
3467 padding: 54px 10px 14px 10px;
3468 padding: 54px 10px 14px 10px;
3468 }
3469 }
3469
3470
3470 #content div.box div.title div.search {
3471 #content div.box div.title div.search {
3471
3472
3472 border-left: 1px solid #316293;
3473 border-left: 1px solid #316293;
3473 }
3474 }
3474
3475
3475 #content div.box div.title div.search div.input input {
3476 #content div.box div.title div.search div.input input {
3476 border: 1px solid #316293;
3477 border: 1px solid #316293;
3477 }
3478 }
3478
3479
3479 .ui-btn{
3480 .ui-btn{
3480 color: #515151;
3481 color: #515151;
3481 background-color: #DADADA;
3482 background-color: #DADADA;
3482 background-repeat: repeat-x;
3483 background-repeat: repeat-x;
3483 background-image: -khtml-gradient(linear, left top, left bottom, from(#F4F4F4),to(#DADADA) );
3484 background-image: -khtml-gradient(linear, left top, left bottom, from(#F4F4F4),to(#DADADA) );
3484 background-image: -moz-linear-gradient(top, #F4F4F4, #DADADA);
3485 background-image: -moz-linear-gradient(top, #F4F4F4, #DADADA);
3485 background-image: -ms-linear-gradient(top, #F4F4F4, #DADADA);
3486 background-image: -ms-linear-gradient(top, #F4F4F4, #DADADA);
3486 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) );
3487 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) );
3487 background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) );
3488 background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) );
3488 background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) );
3489 background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) );
3489 background-image: linear-gradient(top, #F4F4F4, #DADADA);
3490 background-image: linear-gradient(top, #F4F4F4, #DADADA);
3490 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0);
3491 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0);
3491
3492
3492 border-top: 1px solid #DDD;
3493 border-top: 1px solid #DDD;
3493 border-left: 1px solid #c6c6c6;
3494 border-left: 1px solid #c6c6c6;
3494 border-right: 1px solid #DDD;
3495 border-right: 1px solid #DDD;
3495 border-bottom: 1px solid #c6c6c6;
3496 border-bottom: 1px solid #c6c6c6;
3496 color: #515151;
3497 color: #515151;
3497 outline: none;
3498 outline: none;
3498 margin: 0px 3px 3px 0px;
3499 margin: 0px 3px 3px 0px;
3499 -webkit-border-radius: 4px 4px 4px 4px !important;
3500 -webkit-border-radius: 4px 4px 4px 4px !important;
3500 -khtml-border-radius: 4px 4px 4px 4px !important;
3501 -khtml-border-radius: 4px 4px 4px 4px !important;
3501 -moz-border-radius: 4px 4px 4px 4px !important;
3502 -moz-border-radius: 4px 4px 4px 4px !important;
3502 border-radius: 4px 4px 4px 4px !important;
3503 border-radius: 4px 4px 4px 4px !important;
3503 cursor: pointer !important;
3504 cursor: pointer !important;
3504 padding: 3px 3px 3px 3px;
3505 padding: 3px 3px 3px 3px;
3505 background-position: 0 -15px;
3506 background-position: 0 -15px;
3506
3507
3507 }
3508 }
3508 .ui-btn.xsmall{
3509 .ui-btn.xsmall{
3509 padding: 1px 2px 1px 1px;
3510 padding: 1px 2px 1px 1px;
3510 }
3511 }
3511
3512
3512 .ui-btn.large{
3513 .ui-btn.large{
3513 padding: 6px 12px;
3514 padding: 6px 12px;
3514 }
3515 }
3515
3516
3516 .ui-btn.clone{
3517 .ui-btn.clone{
3517 padding: 5px 2px 6px 1px;
3518 padding: 5px 2px 6px 1px;
3518 margin: 0px -4px 3px 0px;
3519 margin: 0px -4px 3px 0px;
3519 -webkit-border-radius: 4px 0px 0px 4px !important;
3520 -webkit-border-radius: 4px 0px 0px 4px !important;
3520 -khtml-border-radius: 4px 0px 0px 4px !important;
3521 -khtml-border-radius: 4px 0px 0px 4px !important;
3521 -moz-border-radius: 4px 0px 0px 4px !important;
3522 -moz-border-radius: 4px 0px 0px 4px !important;
3522 border-radius: 4px 0px 0px 4px !important;
3523 border-radius: 4px 0px 0px 4px !important;
3523 width: 100px;
3524 width: 100px;
3524 text-align: center;
3525 text-align: center;
3525 float: left;
3526 float: left;
3526 position: absolute;
3527 position: absolute;
3527 }
3528 }
3528 .ui-btn:focus {
3529 .ui-btn:focus {
3529 outline: none;
3530 outline: none;
3530 }
3531 }
3531 .ui-btn:hover{
3532 .ui-btn:hover{
3532 background-position: 0 0px;
3533 background-position: 0 0px;
3533 text-decoration: none;
3534 text-decoration: none;
3534 color: #515151;
3535 color: #515151;
3535 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
3536 box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important;
3536 }
3537 }
3537
3538
3538 .ui-btn.red{
3539 .ui-btn.red{
3539 color:#fff;
3540 color:#fff;
3540 background-color: #c43c35;
3541 background-color: #c43c35;
3541 background-repeat: repeat-x;
3542 background-repeat: repeat-x;
3542 background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
3543 background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));
3543 background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
3544 background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35);
3544 background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
3545 background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35);
3545 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
3546 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));
3546 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3547 background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35);
3547 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3548 background-image: -o-linear-gradient(top, #ee5f5b, #c43c35);
3548 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3549 background-image: linear-gradient(top, #ee5f5b, #c43c35);
3549 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
3550 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);
3550 border-color: #c43c35 #c43c35 #882a25;
3551 border-color: #c43c35 #c43c35 #882a25;
3551 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3552 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3552 }
3553 }
3553
3554
3554
3555
3555 .ui-btn.blue{
3556 .ui-btn.blue{
3556 color:#fff;
3557 color:#fff;
3557 background-color: #339bb9;
3558 background-color: #339bb9;
3558 background-repeat: repeat-x;
3559 background-repeat: repeat-x;
3559 background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
3560 background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));
3560 background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
3561 background-image: -moz-linear-gradient(top, #5bc0de, #339bb9);
3561 background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
3562 background-image: -ms-linear-gradient(top, #5bc0de, #339bb9);
3562 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
3563 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));
3563 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3564 background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9);
3564 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3565 background-image: -o-linear-gradient(top, #5bc0de, #339bb9);
3565 background-image: linear-gradient(top, #5bc0de, #339bb9);
3566 background-image: linear-gradient(top, #5bc0de, #339bb9);
3566 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
3567 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);
3567 border-color: #339bb9 #339bb9 #22697d;
3568 border-color: #339bb9 #339bb9 #22697d;
3568 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3569 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3569 }
3570 }
3570
3571
3571 .ui-btn.green{
3572 .ui-btn.green{
3572 background-color: #57a957;
3573 background-color: #57a957;
3573 background-repeat: repeat-x;
3574 background-repeat: repeat-x;
3574 background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
3575 background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));
3575 background-image: -moz-linear-gradient(top, #62c462, #57a957);
3576 background-image: -moz-linear-gradient(top, #62c462, #57a957);
3576 background-image: -ms-linear-gradient(top, #62c462, #57a957);
3577 background-image: -ms-linear-gradient(top, #62c462, #57a957);
3577 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
3578 background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));
3578 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3579 background-image: -webkit-linear-gradient(top, #62c462, #57a957);
3579 background-image: -o-linear-gradient(top, #62c462, #57a957);
3580 background-image: -o-linear-gradient(top, #62c462, #57a957);
3580 background-image: linear-gradient(top, #62c462, #57a957);
3581 background-image: linear-gradient(top, #62c462, #57a957);
3581 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
3582 filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);
3582 border-color: #57a957 #57a957 #3d773d;
3583 border-color: #57a957 #57a957 #3d773d;
3583 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3584 border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
3584 }
3585 }
3585
3586
3586 .ui-btn.active{
3587 .ui-btn.active{
3587 font-weight: bold;
3588 font-weight: bold;
3588 }
3589 }
3589
3590
3590 ins,div.options a:hover {
3591 ins,div.options a:hover {
3591 text-decoration: none;
3592 text-decoration: none;
3592 }
3593 }
3593
3594
3594 img,
3595 img,
3595 #header #header-inner #quick li a:hover span.normal,
3596 #header #header-inner #quick li a:hover span.normal,
3596 #header #header-inner #quick li ul li.last,
3597 #header #header-inner #quick li ul li.last,
3597 #content div.box div.form div.fields div.field div.textarea table td table td a,
3598 #content div.box div.form div.fields div.field div.textarea table td table td a,
3598 #clone_url,
3599 #clone_url,
3599 #clone_url_id
3600 #clone_url_id
3600 {
3601 {
3601 border: none;
3602 border: none;
3602 }
3603 }
3603
3604
3604 img.icon,.right .merge img {
3605 img.icon,.right .merge img {
3605 vertical-align: bottom;
3606 vertical-align: bottom;
3606 }
3607 }
3607
3608
3608 #header ul#logged-user,#content div.box div.title ul.links,
3609 #header ul#logged-user,#content div.box div.title ul.links,
3609 #content div.box div.message div.dismiss,
3610 #content div.box div.message div.dismiss,
3610 #content div.box div.traffic div.legend ul
3611 #content div.box div.traffic div.legend ul
3611 {
3612 {
3612 float: right;
3613 float: right;
3613 margin: 0;
3614 margin: 0;
3614 padding: 0;
3615 padding: 0;
3615 }
3616 }
3616
3617
3617 #header #header-inner #home,#header #header-inner #logo,
3618 #header #header-inner #home,#header #header-inner #logo,
3618 #content div.box ul.left,#content div.box ol.left,
3619 #content div.box ul.left,#content div.box ol.left,
3619 #content div.box div.pagination-left,div#commit_history,
3620 #content div.box div.pagination-left,div#commit_history,
3620 div#legend_data,div#legend_container,div#legend_choices
3621 div#legend_data,div#legend_container,div#legend_choices
3621 {
3622 {
3622 float: left;
3623 float: left;
3623 }
3624 }
3624
3625
3625 #header #header-inner #quick li:hover ul ul,
3626 #header #header-inner #quick li:hover ul ul,
3626 #header #header-inner #quick li:hover ul ul ul,
3627 #header #header-inner #quick li:hover ul ul ul,
3627 #header #header-inner #quick li:hover ul ul ul ul,
3628 #header #header-inner #quick li:hover ul ul ul ul,
3628 #content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow
3629 #content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow
3629 {
3630 {
3630 display: none;
3631 display: none;
3631 }
3632 }
3632
3633
3633 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded
3634 #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded
3634 {
3635 {
3635 display: block;
3636 display: block;
3636 }
3637 }
3637
3638
3638 #content div.graph {
3639 #content div.graph {
3639 padding: 0 10px 10px;
3640 padding: 0 10px 10px;
3640 }
3641 }
3641
3642
3642 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a
3643 #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a
3643 {
3644 {
3644 color: #bfe3ff;
3645 color: #bfe3ff;
3645 }
3646 }
3646
3647
3647 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal
3648 #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal
3648 {
3649 {
3649 margin: 10px 24px 10px 44px;
3650 margin: 10px 24px 10px 44px;
3650 }
3651 }
3651
3652
3652 #content div.box div.form,#content div.box div.table,#content div.box div.traffic
3653 #content div.box div.form,#content div.box div.table,#content div.box div.traffic
3653 {
3654 {
3654 clear: both;
3655 clear: both;
3655 overflow: hidden;
3656 overflow: hidden;
3656 margin: 0;
3657 margin: 0;
3657 padding: 0 20px 10px;
3658 padding: 0 20px 10px;
3658 }
3659 }
3659
3660
3660 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields
3661 #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields
3661 {
3662 {
3662 clear: both;
3663 clear: both;
3663 overflow: hidden;
3664 overflow: hidden;
3664 margin: 0;
3665 margin: 0;
3665 padding: 0;
3666 padding: 0;
3666 }
3667 }
3667
3668
3668 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span
3669 #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span
3669 {
3670 {
3670 height: 1%;
3671 height: 1%;
3671 display: block;
3672 display: block;
3672 color: #363636;
3673 color: #363636;
3673 margin: 0;
3674 margin: 0;
3674 padding: 2px 0 0;
3675 padding: 2px 0 0;
3675 }
3676 }
3676
3677
3677 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error
3678 #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error
3678 {
3679 {
3679 background: #FBE3E4;
3680 background: #FBE3E4;
3680 border-top: 1px solid #e1b2b3;
3681 border-top: 1px solid #e1b2b3;
3681 border-left: 1px solid #e1b2b3;
3682 border-left: 1px solid #e1b2b3;
3682 border-right: 1px solid #FBC2C4;
3683 border-right: 1px solid #FBC2C4;
3683 border-bottom: 1px solid #FBC2C4;
3684 border-bottom: 1px solid #FBC2C4;
3684 }
3685 }
3685
3686
3686 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success
3687 #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success
3687 {
3688 {
3688 background: #E6EFC2;
3689 background: #E6EFC2;
3689 border-top: 1px solid #cebb98;
3690 border-top: 1px solid #cebb98;
3690 border-left: 1px solid #cebb98;
3691 border-left: 1px solid #cebb98;
3691 border-right: 1px solid #c6d880;
3692 border-right: 1px solid #c6d880;
3692 border-bottom: 1px solid #c6d880;
3693 border-bottom: 1px solid #c6d880;
3693 }
3694 }
3694
3695
3695 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input
3696 #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input
3696 {
3697 {
3697 margin: 0;
3698 margin: 0;
3698 }
3699 }
3699
3700
3700 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios
3701 #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios
3701 {
3702 {
3702 margin: 0 0 0 0px !important;
3703 margin: 0 0 0 0px !important;
3703 padding: 0;
3704 padding: 0;
3704 }
3705 }
3705
3706
3706 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios
3707 #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios
3707 {
3708 {
3708 margin: 0 0 0 200px;
3709 margin: 0 0 0 200px;
3709 padding: 0;
3710 padding: 0;
3710 }
3711 }
3711
3712
3712 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover
3713 #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover
3713 {
3714 {
3714 color: #000;
3715 color: #000;
3715 text-decoration: none;
3716 text-decoration: none;
3716 }
3717 }
3717
3718
3718 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus
3719 #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus
3719 {
3720 {
3720 border: 1px solid #666;
3721 border: 1px solid #666;
3721 }
3722 }
3722
3723
3723 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio
3724 #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio
3724 {
3725 {
3725 clear: both;
3726 clear: both;
3726 overflow: hidden;
3727 overflow: hidden;
3727 margin: 0;
3728 margin: 0;
3728 padding: 8px 0 2px;
3729 padding: 8px 0 2px;
3729 }
3730 }
3730
3731
3731 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input
3732 #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input
3732 {
3733 {
3733 float: left;
3734 float: left;
3734 margin: 0;
3735 margin: 0;
3735 }
3736 }
3736
3737
3737 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label
3738 #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label
3738 {
3739 {
3739 height: 1%;
3740 height: 1%;
3740 display: block;
3741 display: block;
3741 float: left;
3742 float: left;
3742 margin: 2px 0 0 4px;
3743 margin: 2px 0 0 4px;
3743 }
3744 }
3744
3745
3745 div.form div.fields div.field div.button input,
3746 div.form div.fields div.field div.button input,
3746 #content div.box div.form div.fields div.buttons input
3747 #content div.box div.form div.fields div.buttons input
3747 div.form div.fields div.buttons input,
3748 div.form div.fields div.buttons input,
3748 #content div.box div.action div.button input {
3749 #content div.box div.action div.button input {
3749 /*color: #000;*/
3750 /*color: #000;*/
3750 font-size: 11px;
3751 font-size: 11px;
3751 font-weight: 700;
3752 font-weight: 700;
3752 margin: 0;
3753 margin: 0;
3753 }
3754 }
3754
3755
3755 input.ui-button {
3756 input.ui-button {
3756 background: #e5e3e3 url("../images/button.png") repeat-x;
3757 background: #e5e3e3 url("../images/button.png") repeat-x;
3757 border-top: 1px solid #DDD;
3758 border-top: 1px solid #DDD;
3758 border-left: 1px solid #c6c6c6;
3759 border-left: 1px solid #c6c6c6;
3759 border-right: 1px solid #DDD;
3760 border-right: 1px solid #DDD;
3760 border-bottom: 1px solid #c6c6c6;
3761 border-bottom: 1px solid #c6c6c6;
3761 color: #515151 !important;
3762 color: #515151 !important;
3762 outline: none;
3763 outline: none;
3763 margin: 0;
3764 margin: 0;
3764 padding: 6px 12px;
3765 padding: 6px 12px;
3765 -webkit-border-radius: 4px 4px 4px 4px;
3766 -webkit-border-radius: 4px 4px 4px 4px;
3766 -khtml-border-radius: 4px 4px 4px 4px;
3767 -khtml-border-radius: 4px 4px 4px 4px;
3767 -moz-border-radius: 4px 4px 4px 4px;
3768 -moz-border-radius: 4px 4px 4px 4px;
3768 border-radius: 4px 4px 4px 4px;
3769 border-radius: 4px 4px 4px 4px;
3769 box-shadow: 0 1px 0 #ececec;
3770 box-shadow: 0 1px 0 #ececec;
3770 cursor: pointer;
3771 cursor: pointer;
3771 }
3772 }
3772
3773
3773 input.ui-button:hover {
3774 input.ui-button:hover {
3774 background: #b4b4b4 url("../images/button_selected.png") repeat-x;
3775 background: #b4b4b4 url("../images/button_selected.png") repeat-x;
3775 border-top: 1px solid #ccc;
3776 border-top: 1px solid #ccc;
3776 border-left: 1px solid #bebebe;
3777 border-left: 1px solid #bebebe;
3777 border-right: 1px solid #b1b1b1;
3778 border-right: 1px solid #b1b1b1;
3778 border-bottom: 1px solid #afafaf;
3779 border-bottom: 1px solid #afafaf;
3779 }
3780 }
3780
3781
3781 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight
3782 div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight
3782 {
3783 {
3783 display: inline;
3784 display: inline;
3784 }
3785 }
3785
3786
3786 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons
3787 #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons
3787 {
3788 {
3788 margin: 10px 0 0 200px;
3789 margin: 10px 0 0 200px;
3789 padding: 0;
3790 padding: 0;
3790 }
3791 }
3791
3792
3792 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons
3793 #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons
3793 {
3794 {
3794 margin: 10px 0 0;
3795 margin: 10px 0 0;
3795 }
3796 }
3796
3797
3797 #content div.box table td.user,#content div.box table td.address {
3798 #content div.box table td.user,#content div.box table td.address {
3798 width: 10%;
3799 width: 10%;
3799 text-align: center;
3800 text-align: center;
3800 }
3801 }
3801
3802
3802 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link
3803 #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link
3803 {
3804 {
3804 text-align: right;
3805 text-align: right;
3805 margin: 6px 0 0;
3806 margin: 6px 0 0;
3806 padding: 0;
3807 padding: 0;
3807 }
3808 }
3808
3809
3809 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover
3810 #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover
3810 {
3811 {
3811 background: #b4b4b4 url("../images/button_selected.png") repeat-x;
3812 background: #b4b4b4 url("../images/button_selected.png") repeat-x;
3812 border-top: 1px solid #ccc;
3813 border-top: 1px solid #ccc;
3813 border-left: 1px solid #bebebe;
3814 border-left: 1px solid #bebebe;
3814 border-right: 1px solid #b1b1b1;
3815 border-right: 1px solid #b1b1b1;
3815 border-bottom: 1px solid #afafaf;
3816 border-bottom: 1px solid #afafaf;
3816 color: #515151;
3817 color: #515151;
3817 margin: 0;
3818 margin: 0;
3818 padding: 6px 12px;
3819 padding: 6px 12px;
3819 }
3820 }
3820
3821
3821 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results
3822 #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results
3822 {
3823 {
3823 text-align: left;
3824 text-align: left;
3824 float: left;
3825 float: left;
3825 margin: 0;
3826 margin: 0;
3826 padding: 0;
3827 padding: 0;
3827 }
3828 }
3828
3829
3829 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span
3830 #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span
3830 {
3831 {
3831 height: 1%;
3832 height: 1%;
3832 display: block;
3833 display: block;
3833 float: left;
3834 float: left;
3834 background: #ebebeb url("../images/pager.png") repeat-x;
3835 background: #ebebeb url("../images/pager.png") repeat-x;
3835 border-top: 1px solid #dedede;
3836 border-top: 1px solid #dedede;
3836 border-left: 1px solid #cfcfcf;
3837 border-left: 1px solid #cfcfcf;
3837 border-right: 1px solid #c4c4c4;
3838 border-right: 1px solid #c4c4c4;
3838 border-bottom: 1px solid #c4c4c4;
3839 border-bottom: 1px solid #c4c4c4;
3839 color: #4A4A4A;
3840 color: #4A4A4A;
3840 font-weight: 700;
3841 font-weight: 700;
3841 margin: 0;
3842 margin: 0;
3842 padding: 6px 8px;
3843 padding: 6px 8px;
3843 }
3844 }
3844
3845
3845 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled
3846 #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled
3846 {
3847 {
3847 color: #B4B4B4;
3848 color: #B4B4B4;
3848 padding: 6px;
3849 padding: 6px;
3849 }
3850 }
3850
3851
3851 #login,#register {
3852 #login,#register {
3852 width: 520px;
3853 width: 520px;
3853 margin: 10% auto 0;
3854 margin: 10% auto 0;
3854 padding: 0;
3855 padding: 0;
3855 }
3856 }
3856
3857
3857 #login div.color,#register div.color {
3858 #login div.color,#register div.color {
3858 clear: both;
3859 clear: both;
3859 overflow: hidden;
3860 overflow: hidden;
3860 background: #FFF;
3861 background: #FFF;
3861 margin: 10px auto 0;
3862 margin: 10px auto 0;
3862 padding: 3px 3px 3px 0;
3863 padding: 3px 3px 3px 0;
3863 }
3864 }
3864
3865
3865 #login div.color a,#register div.color a {
3866 #login div.color a,#register div.color a {
3866 width: 20px;
3867 width: 20px;
3867 height: 20px;
3868 height: 20px;
3868 display: block;
3869 display: block;
3869 float: left;
3870 float: left;
3870 margin: 0 0 0 3px;
3871 margin: 0 0 0 3px;
3871 padding: 0;
3872 padding: 0;
3872 }
3873 }
3873
3874
3874 #login div.title h5,#register div.title h5 {
3875 #login div.title h5,#register div.title h5 {
3875 color: #fff;
3876 color: #fff;
3876 margin: 10px;
3877 margin: 10px;
3877 padding: 0;
3878 padding: 0;
3878 }
3879 }
3879
3880
3880 #login div.form div.fields div.field,#register div.form div.fields div.field
3881 #login div.form div.fields div.field,#register div.form div.fields div.field
3881 {
3882 {
3882 clear: both;
3883 clear: both;
3883 overflow: hidden;
3884 overflow: hidden;
3884 margin: 0;
3885 margin: 0;
3885 padding: 0 0 10px;
3886 padding: 0 0 10px;
3886 }
3887 }
3887
3888
3888 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message
3889 #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message
3889 {
3890 {
3890 height: 1%;
3891 height: 1%;
3891 display: block;
3892 display: block;
3892 color: red;
3893 color: red;
3893 margin: 8px 0 0;
3894 margin: 8px 0 0;
3894 padding: 0;
3895 padding: 0;
3895 max-width: 320px;
3896 max-width: 320px;
3896 }
3897 }
3897
3898
3898 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label
3899 #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label
3899 {
3900 {
3900 color: #000;
3901 color: #000;
3901 font-weight: 700;
3902 font-weight: 700;
3902 }
3903 }
3903
3904
3904 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input
3905 #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input
3905 {
3906 {
3906 float: left;
3907 float: left;
3907 margin: 0;
3908 margin: 0;
3908 padding: 0;
3909 padding: 0;
3909 }
3910 }
3910
3911
3911 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox
3912 #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox
3912 {
3913 {
3913 margin: 0 0 0 184px;
3914 margin: 0 0 0 184px;
3914 padding: 0;
3915 padding: 0;
3915 }
3916 }
3916
3917
3917 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label
3918 #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label
3918 {
3919 {
3919 color: #565656;
3920 color: #565656;
3920 font-weight: 700;
3921 font-weight: 700;
3921 }
3922 }
3922
3923
3923 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input
3924 #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input
3924 {
3925 {
3925 color: #000;
3926 color: #000;
3926 font-size: 1em;
3927 font-size: 1em;
3927 font-weight: 700;
3928 font-weight: 700;
3928 margin: 0;
3929 margin: 0;
3929 }
3930 }
3930
3931
3931 #changeset_content .container .wrapper,#graph_content .container .wrapper
3932 #changeset_content .container .wrapper,#graph_content .container .wrapper
3932 {
3933 {
3933 width: 600px;
3934 width: 600px;
3934 }
3935 }
3935
3936
3936 #changeset_content .container .left {
3937 #changeset_content .container .left {
3937 float: left;
3938 float: left;
3938 width: 75%;
3939 width: 75%;
3939 padding-left: 5px;
3940 padding-left: 5px;
3940 }
3941 }
3941
3942
3942 #changeset_content .container .left .date,.ac .match {
3943 #changeset_content .container .left .date,.ac .match {
3943 font-weight: 700;
3944 font-weight: 700;
3944 padding-top: 5px;
3945 padding-top: 5px;
3945 padding-bottom: 5px;
3946 padding-bottom: 5px;
3946 }
3947 }
3947
3948
3948 div#legend_container table td,div#legend_choices table td {
3949 div#legend_container table td,div#legend_choices table td {
3949 border: none !important;
3950 border: none !important;
3950 height: 20px !important;
3951 height: 20px !important;
3951 padding: 0 !important;
3952 padding: 0 !important;
3952 }
3953 }
3953
3954
3954 .q_filter_box {
3955 .q_filter_box {
3955 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
3956 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
3956 -webkit-border-radius: 4px;
3957 -webkit-border-radius: 4px;
3957 -moz-border-radius: 4px;
3958 -moz-border-radius: 4px;
3958 border-radius: 4px;
3959 border-radius: 4px;
3959 border: 0 none;
3960 border: 0 none;
3960 color: #AAAAAA;
3961 color: #AAAAAA;
3961 margin-bottom: -4px;
3962 margin-bottom: -4px;
3962 margin-top: -4px;
3963 margin-top: -4px;
3963 padding-left: 3px;
3964 padding-left: 3px;
3964 }
3965 }
3965
3966
3966 #node_filter {
3967 #node_filter {
3967 border: 0px solid #545454;
3968 border: 0px solid #545454;
3968 color: #AAAAAA;
3969 color: #AAAAAA;
3969 padding-left: 3px;
3970 padding-left: 3px;
3970 }
3971 }
3971
3972
3972
3973
3973 .group_members_wrap{
3974 .group_members_wrap{
3974 min-height: 85px;
3975 min-height: 85px;
3975 padding-left: 20px;
3976 padding-left: 20px;
3976 }
3977 }
3977
3978
3978 .group_members .group_member{
3979 .group_members .group_member{
3979 height: 30px;
3980 height: 30px;
3980 padding:0px 0px 0px 0px;
3981 padding:0px 0px 0px 0px;
3981 }
3982 }
3982
3983
3983 .reviewers_member{
3984 .reviewers_member{
3984 height: 15px;
3985 height: 15px;
3985 padding:0px 0px 0px 10px;
3986 padding:0px 0px 0px 10px;
3986 }
3987 }
3987
3988
3988 .emails_wrap{
3989 .emails_wrap{
3989 padding: 0px 20px;
3990 padding: 0px 20px;
3990 }
3991 }
3991
3992
3992 .emails_wrap .email_entry{
3993 .emails_wrap .email_entry{
3993 height: 30px;
3994 height: 30px;
3994 padding:0px 0px 0px 10px;
3995 padding:0px 0px 0px 10px;
3995 }
3996 }
3996 .emails_wrap .email_entry .email{
3997 .emails_wrap .email_entry .email{
3997 float: left
3998 float: left
3998 }
3999 }
3999 .emails_wrap .email_entry .email_action{
4000 .emails_wrap .email_entry .email_action{
4000 float: left
4001 float: left
4001 }
4002 }
4002
4003
4003 /*README STYLE*/
4004 /*README STYLE*/
4004
4005
4005 div.readme {
4006 div.readme {
4006 padding:0px;
4007 padding:0px;
4007 }
4008 }
4008
4009
4009 div.readme h2 {
4010 div.readme h2 {
4010 font-weight: normal;
4011 font-weight: normal;
4011 }
4012 }
4012
4013
4013 div.readme .readme_box {
4014 div.readme .readme_box {
4014 background-color: #fafafa;
4015 background-color: #fafafa;
4015 }
4016 }
4016
4017
4017 div.readme .readme_box {
4018 div.readme .readme_box {
4018 clear:both;
4019 clear:both;
4019 overflow:hidden;
4020 overflow:hidden;
4020 margin:0;
4021 margin:0;
4021 padding:0 20px 10px;
4022 padding:0 20px 10px;
4022 }
4023 }
4023
4024
4024 div.readme .readme_box h1, div.readme .readme_box h2, div.readme .readme_box h3, div.readme .readme_box h4, div.readme .readme_box h5, div.readme .readme_box h6 {
4025 div.readme .readme_box h1, div.readme .readme_box h2, div.readme .readme_box h3, div.readme .readme_box h4, div.readme .readme_box h5, div.readme .readme_box h6 {
4025 border-bottom: 0 !important;
4026 border-bottom: 0 !important;
4026 margin: 0 !important;
4027 margin: 0 !important;
4027 padding: 0 !important;
4028 padding: 0 !important;
4028 line-height: 1.5em !important;
4029 line-height: 1.5em !important;
4029 }
4030 }
4030
4031
4031
4032
4032 div.readme .readme_box h1:first-child {
4033 div.readme .readme_box h1:first-child {
4033 padding-top: .25em !important;
4034 padding-top: .25em !important;
4034 }
4035 }
4035
4036
4036 div.readme .readme_box h2, div.readme .readme_box h3 {
4037 div.readme .readme_box h2, div.readme .readme_box h3 {
4037 margin: 1em 0 !important;
4038 margin: 1em 0 !important;
4038 }
4039 }
4039
4040
4040 div.readme .readme_box h2 {
4041 div.readme .readme_box h2 {
4041 margin-top: 1.5em !important;
4042 margin-top: 1.5em !important;
4042 border-top: 4px solid #e0e0e0 !important;
4043 border-top: 4px solid #e0e0e0 !important;
4043 padding-top: .5em !important;
4044 padding-top: .5em !important;
4044 }
4045 }
4045
4046
4046 div.readme .readme_box p {
4047 div.readme .readme_box p {
4047 color: black !important;
4048 color: black !important;
4048 margin: 1em 0 !important;
4049 margin: 1em 0 !important;
4049 line-height: 1.5em !important;
4050 line-height: 1.5em !important;
4050 }
4051 }
4051
4052
4052 div.readme .readme_box ul {
4053 div.readme .readme_box ul {
4053 list-style: disc !important;
4054 list-style: disc !important;
4054 margin: 1em 0 1em 2em !important;
4055 margin: 1em 0 1em 2em !important;
4055 }
4056 }
4056
4057
4057 div.readme .readme_box ol {
4058 div.readme .readme_box ol {
4058 list-style: decimal;
4059 list-style: decimal;
4059 margin: 1em 0 1em 2em !important;
4060 margin: 1em 0 1em 2em !important;
4060 }
4061 }
4061
4062
4062 div.readme .readme_box pre, code {
4063 div.readme .readme_box pre, code {
4063 font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
4064 font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
4064 }
4065 }
4065
4066
4066 div.readme .readme_box code {
4067 div.readme .readme_box code {
4067 font-size: 12px !important;
4068 font-size: 12px !important;
4068 background-color: ghostWhite !important;
4069 background-color: ghostWhite !important;
4069 color: #444 !important;
4070 color: #444 !important;
4070 padding: 0 .2em !important;
4071 padding: 0 .2em !important;
4071 border: 1px solid #dedede !important;
4072 border: 1px solid #dedede !important;
4072 }
4073 }
4073
4074
4074 div.readme .readme_box pre code {
4075 div.readme .readme_box pre code {
4075 padding: 0 !important;
4076 padding: 0 !important;
4076 font-size: 12px !important;
4077 font-size: 12px !important;
4077 background-color: #eee !important;
4078 background-color: #eee !important;
4078 border: none !important;
4079 border: none !important;
4079 }
4080 }
4080
4081
4081 div.readme .readme_box pre {
4082 div.readme .readme_box pre {
4082 margin: 1em 0;
4083 margin: 1em 0;
4083 font-size: 12px;
4084 font-size: 12px;
4084 background-color: #eee;
4085 background-color: #eee;
4085 border: 1px solid #ddd;
4086 border: 1px solid #ddd;
4086 padding: 5px;
4087 padding: 5px;
4087 color: #444;
4088 color: #444;
4088 overflow: auto;
4089 overflow: auto;
4089 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4090 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4090 -webkit-border-radius: 3px;
4091 -webkit-border-radius: 3px;
4091 -moz-border-radius: 3px;
4092 -moz-border-radius: 3px;
4092 border-radius: 3px;
4093 border-radius: 3px;
4093 }
4094 }
4094
4095
4095 div.readme .readme_box table {
4096 div.readme .readme_box table {
4096 display: table;
4097 display: table;
4097 border-collapse: separate;
4098 border-collapse: separate;
4098 border-spacing: 2px;
4099 border-spacing: 2px;
4099 border-color: gray;
4100 border-color: gray;
4100 width: auto !important;
4101 width: auto !important;
4101 }
4102 }
4102
4103
4103
4104
4104 /** RST STYLE **/
4105 /** RST STYLE **/
4105
4106
4106
4107
4107 div.rst-block {
4108 div.rst-block {
4108 padding:0px;
4109 padding:0px;
4109 }
4110 }
4110
4111
4111 div.rst-block h2 {
4112 div.rst-block h2 {
4112 font-weight: normal;
4113 font-weight: normal;
4113 }
4114 }
4114
4115
4115 div.rst-block {
4116 div.rst-block {
4116 background-color: #fafafa;
4117 background-color: #fafafa;
4117 }
4118 }
4118
4119
4119 div.rst-block {
4120 div.rst-block {
4120 clear:both;
4121 clear:both;
4121 overflow:hidden;
4122 overflow:hidden;
4122 margin:0;
4123 margin:0;
4123 padding:0 20px 10px;
4124 padding:0 20px 10px;
4124 }
4125 }
4125
4126
4126 div.rst-block h1, div.rst-block h2, div.rst-block h3, div.rst-block h4, div.rst-block h5, div.rst-block h6 {
4127 div.rst-block h1, div.rst-block h2, div.rst-block h3, div.rst-block h4, div.rst-block h5, div.rst-block h6 {
4127 border-bottom: 0 !important;
4128 border-bottom: 0 !important;
4128 margin: 0 !important;
4129 margin: 0 !important;
4129 padding: 0 !important;
4130 padding: 0 !important;
4130 line-height: 1.5em !important;
4131 line-height: 1.5em !important;
4131 }
4132 }
4132
4133
4133
4134
4134 div.rst-block h1:first-child {
4135 div.rst-block h1:first-child {
4135 padding-top: .25em !important;
4136 padding-top: .25em !important;
4136 }
4137 }
4137
4138
4138 div.rst-block h2, div.rst-block h3 {
4139 div.rst-block h2, div.rst-block h3 {
4139 margin: 1em 0 !important;
4140 margin: 1em 0 !important;
4140 }
4141 }
4141
4142
4142 div.rst-block h2 {
4143 div.rst-block h2 {
4143 margin-top: 1.5em !important;
4144 margin-top: 1.5em !important;
4144 border-top: 4px solid #e0e0e0 !important;
4145 border-top: 4px solid #e0e0e0 !important;
4145 padding-top: .5em !important;
4146 padding-top: .5em !important;
4146 }
4147 }
4147
4148
4148 div.rst-block p {
4149 div.rst-block p {
4149 color: black !important;
4150 color: black !important;
4150 margin: 1em 0 !important;
4151 margin: 1em 0 !important;
4151 line-height: 1.5em !important;
4152 line-height: 1.5em !important;
4152 }
4153 }
4153
4154
4154 div.rst-block ul {
4155 div.rst-block ul {
4155 list-style: disc !important;
4156 list-style: disc !important;
4156 margin: 1em 0 1em 2em !important;
4157 margin: 1em 0 1em 2em !important;
4157 }
4158 }
4158
4159
4159 div.rst-block ol {
4160 div.rst-block ol {
4160 list-style: decimal;
4161 list-style: decimal;
4161 margin: 1em 0 1em 2em !important;
4162 margin: 1em 0 1em 2em !important;
4162 }
4163 }
4163
4164
4164 div.rst-block pre, code {
4165 div.rst-block pre, code {
4165 font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
4166 font: 12px "Bitstream Vera Sans Mono","Courier",monospace;
4166 }
4167 }
4167
4168
4168 div.rst-block code {
4169 div.rst-block code {
4169 font-size: 12px !important;
4170 font-size: 12px !important;
4170 background-color: ghostWhite !important;
4171 background-color: ghostWhite !important;
4171 color: #444 !important;
4172 color: #444 !important;
4172 padding: 0 .2em !important;
4173 padding: 0 .2em !important;
4173 border: 1px solid #dedede !important;
4174 border: 1px solid #dedede !important;
4174 }
4175 }
4175
4176
4176 div.rst-block pre code {
4177 div.rst-block pre code {
4177 padding: 0 !important;
4178 padding: 0 !important;
4178 font-size: 12px !important;
4179 font-size: 12px !important;
4179 background-color: #eee !important;
4180 background-color: #eee !important;
4180 border: none !important;
4181 border: none !important;
4181 }
4182 }
4182
4183
4183 div.rst-block pre {
4184 div.rst-block pre {
4184 margin: 1em 0;
4185 margin: 1em 0;
4185 font-size: 12px;
4186 font-size: 12px;
4186 background-color: #eee;
4187 background-color: #eee;
4187 border: 1px solid #ddd;
4188 border: 1px solid #ddd;
4188 padding: 5px;
4189 padding: 5px;
4189 color: #444;
4190 color: #444;
4190 overflow: auto;
4191 overflow: auto;
4191 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4192 -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset;
4192 -webkit-border-radius: 3px;
4193 -webkit-border-radius: 3px;
4193 -moz-border-radius: 3px;
4194 -moz-border-radius: 3px;
4194 border-radius: 3px;
4195 border-radius: 3px;
4195 }
4196 }
4196
4197
4197
4198
4198 /** comment main **/
4199 /** comment main **/
4199 .comments {
4200 .comments {
4200 padding:10px 20px;
4201 padding:10px 20px;
4201 }
4202 }
4202
4203
4203 .comments .comment {
4204 .comments .comment {
4204 border: 1px solid #ddd;
4205 border: 1px solid #ddd;
4205 margin-top: 10px;
4206 margin-top: 10px;
4206 -webkit-border-radius: 4px;
4207 -webkit-border-radius: 4px;
4207 -moz-border-radius: 4px;
4208 -moz-border-radius: 4px;
4208 border-radius: 4px;
4209 border-radius: 4px;
4209 }
4210 }
4210
4211
4211 .comments .comment .meta {
4212 .comments .comment .meta {
4212 background: #f8f8f8;
4213 background: #f8f8f8;
4213 padding: 4px;
4214 padding: 4px;
4214 border-bottom: 1px solid #ddd;
4215 border-bottom: 1px solid #ddd;
4215 height: 18px;
4216 height: 18px;
4216 }
4217 }
4217
4218
4218 .comments .comment .meta img {
4219 .comments .comment .meta img {
4219 vertical-align: middle;
4220 vertical-align: middle;
4220 }
4221 }
4221
4222
4222 .comments .comment .meta .user {
4223 .comments .comment .meta .user {
4223 font-weight: bold;
4224 font-weight: bold;
4224 float: left;
4225 float: left;
4225 padding: 4px 2px 2px 2px;
4226 padding: 4px 2px 2px 2px;
4226 }
4227 }
4227
4228
4228 .comments .comment .meta .date {
4229 .comments .comment .meta .date {
4229 float: left;
4230 float: left;
4230 padding:4px 4px 0px 4px;
4231 padding:4px 4px 0px 4px;
4231 }
4232 }
4232
4233
4233 .comments .comment .text {
4234 .comments .comment .text {
4234 background-color: #FAFAFA;
4235 background-color: #FAFAFA;
4235 }
4236 }
4236 .comment .text div.rst-block p {
4237 .comment .text div.rst-block p {
4237 margin: 0.5em 0px !important;
4238 margin: 0.5em 0px !important;
4238 }
4239 }
4239
4240
4240 .comments .comments-number{
4241 .comments .comments-number{
4241 padding:0px 0px 10px 0px;
4242 padding:0px 0px 10px 0px;
4242 font-weight: bold;
4243 font-weight: bold;
4243 color: #666;
4244 color: #666;
4244 font-size: 16px;
4245 font-size: 16px;
4245 }
4246 }
4246
4247
4247 /** comment form **/
4248 /** comment form **/
4248
4249
4249 .status-block{
4250 .status-block{
4250 height:80px;
4251 height:80px;
4251 clear:both
4252 clear:both
4252 }
4253 }
4253
4254
4254 .comment-form .clearfix{
4255 .comment-form .clearfix{
4255 background: #EEE;
4256 background: #EEE;
4256 -webkit-border-radius: 4px;
4257 -webkit-border-radius: 4px;
4257 -moz-border-radius: 4px;
4258 -moz-border-radius: 4px;
4258 border-radius: 4px;
4259 border-radius: 4px;
4259 padding: 10px;
4260 padding: 10px;
4260 }
4261 }
4261
4262
4262 div.comment-form {
4263 div.comment-form {
4263 margin-top: 20px;
4264 margin-top: 20px;
4264 }
4265 }
4265
4266
4266 .comment-form strong {
4267 .comment-form strong {
4267 display: block;
4268 display: block;
4268 margin-bottom: 15px;
4269 margin-bottom: 15px;
4269 }
4270 }
4270
4271
4271 .comment-form textarea {
4272 .comment-form textarea {
4272 width: 100%;
4273 width: 100%;
4273 height: 100px;
4274 height: 100px;
4274 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
4275 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
4275 }
4276 }
4276
4277
4277 form.comment-form {
4278 form.comment-form {
4278 margin-top: 10px;
4279 margin-top: 10px;
4279 margin-left: 10px;
4280 margin-left: 10px;
4280 }
4281 }
4281
4282
4282 .comment-form-submit {
4283 .comment-form-submit {
4283 margin-top: 5px;
4284 margin-top: 5px;
4284 margin-left: 525px;
4285 margin-left: 525px;
4285 }
4286 }
4286
4287
4287 .file-comments {
4288 .file-comments {
4288 display: none;
4289 display: none;
4289 }
4290 }
4290
4291
4291 .comment-form .comment {
4292 .comment-form .comment {
4292 margin-left: 10px;
4293 margin-left: 10px;
4293 }
4294 }
4294
4295
4295 .comment-form .comment-help{
4296 .comment-form .comment-help{
4296 padding: 0px 0px 5px 0px;
4297 padding: 0px 0px 5px 0px;
4297 color: #666;
4298 color: #666;
4298 }
4299 }
4299
4300
4300 .comment-form .comment-button{
4301 .comment-form .comment-button{
4301 padding-top:5px;
4302 padding-top:5px;
4302 }
4303 }
4303
4304
4304 .add-another-button {
4305 .add-another-button {
4305 margin-left: 10px;
4306 margin-left: 10px;
4306 margin-top: 10px;
4307 margin-top: 10px;
4307 margin-bottom: 10px;
4308 margin-bottom: 10px;
4308 }
4309 }
4309
4310
4310 .comment .buttons {
4311 .comment .buttons {
4311 float: right;
4312 float: right;
4312 padding:2px 2px 0px 0px;
4313 padding:2px 2px 0px 0px;
4313 }
4314 }
4314
4315
4315
4316
4316 .show-inline-comments{
4317 .show-inline-comments{
4317 position: relative;
4318 position: relative;
4318 top:1px
4319 top:1px
4319 }
4320 }
4320
4321
4321 /** comment inline form **/
4322 /** comment inline form **/
4322 .comment-inline-form .overlay{
4323 .comment-inline-form .overlay{
4323 display: none;
4324 display: none;
4324 }
4325 }
4325 .comment-inline-form .overlay.submitting{
4326 .comment-inline-form .overlay.submitting{
4326 display:block;
4327 display:block;
4327 background: none repeat scroll 0 0 white;
4328 background: none repeat scroll 0 0 white;
4328 font-size: 16px;
4329 font-size: 16px;
4329 opacity: 0.5;
4330 opacity: 0.5;
4330 position: absolute;
4331 position: absolute;
4331 text-align: center;
4332 text-align: center;
4332 vertical-align: top;
4333 vertical-align: top;
4333
4334
4334 }
4335 }
4335 .comment-inline-form .overlay.submitting .overlay-text{
4336 .comment-inline-form .overlay.submitting .overlay-text{
4336 width:100%;
4337 width:100%;
4337 margin-top:5%;
4338 margin-top:5%;
4338 }
4339 }
4339
4340
4340 .comment-inline-form .clearfix{
4341 .comment-inline-form .clearfix{
4341 background: #EEE;
4342 background: #EEE;
4342 -webkit-border-radius: 4px;
4343 -webkit-border-radius: 4px;
4343 -moz-border-radius: 4px;
4344 -moz-border-radius: 4px;
4344 border-radius: 4px;
4345 border-radius: 4px;
4345 padding: 5px;
4346 padding: 5px;
4346 }
4347 }
4347
4348
4348 div.comment-inline-form {
4349 div.comment-inline-form {
4349 padding:4px 0px 6px 0px;
4350 padding:4px 0px 6px 0px;
4350 }
4351 }
4351
4352
4352
4353
4353 tr.hl-comment{
4354 tr.hl-comment{
4354 /*
4355 /*
4355 background-color: #FFFFCC !important;
4356 background-color: #FFFFCC !important;
4356 */
4357 */
4357 }
4358 }
4358
4359
4359 /*
4360 /*
4360 tr.hl-comment pre {
4361 tr.hl-comment pre {
4361 border-top: 2px solid #FFEE33;
4362 border-top: 2px solid #FFEE33;
4362 border-left: 2px solid #FFEE33;
4363 border-left: 2px solid #FFEE33;
4363 border-right: 2px solid #FFEE33;
4364 border-right: 2px solid #FFEE33;
4364 }
4365 }
4365 */
4366 */
4366
4367
4367 .comment-inline-form strong {
4368 .comment-inline-form strong {
4368 display: block;
4369 display: block;
4369 margin-bottom: 15px;
4370 margin-bottom: 15px;
4370 }
4371 }
4371
4372
4372 .comment-inline-form textarea {
4373 .comment-inline-form textarea {
4373 width: 100%;
4374 width: 100%;
4374 height: 100px;
4375 height: 100px;
4375 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
4376 font-family: 'Monaco', 'Courier', 'Courier New', monospace;
4376 }
4377 }
4377
4378
4378 form.comment-inline-form {
4379 form.comment-inline-form {
4379 margin-top: 10px;
4380 margin-top: 10px;
4380 margin-left: 10px;
4381 margin-left: 10px;
4381 }
4382 }
4382
4383
4383 .comment-inline-form-submit {
4384 .comment-inline-form-submit {
4384 margin-top: 5px;
4385 margin-top: 5px;
4385 margin-left: 525px;
4386 margin-left: 525px;
4386 }
4387 }
4387
4388
4388 .file-comments {
4389 .file-comments {
4389 display: none;
4390 display: none;
4390 }
4391 }
4391
4392
4392 .comment-inline-form .comment {
4393 .comment-inline-form .comment {
4393 margin-left: 10px;
4394 margin-left: 10px;
4394 }
4395 }
4395
4396
4396 .comment-inline-form .comment-help{
4397 .comment-inline-form .comment-help{
4397 padding: 0px 0px 2px 0px;
4398 padding: 0px 0px 2px 0px;
4398 color: #666666;
4399 color: #666666;
4399 font-size: 10px;
4400 font-size: 10px;
4400 }
4401 }
4401
4402
4402 .comment-inline-form .comment-button{
4403 .comment-inline-form .comment-button{
4403 padding-top:5px;
4404 padding-top:5px;
4404 }
4405 }
4405
4406
4406 /** comment inline **/
4407 /** comment inline **/
4407 .inline-comments {
4408 .inline-comments {
4408 padding:10px 20px;
4409 padding:10px 20px;
4409 }
4410 }
4410
4411
4411 .inline-comments div.rst-block {
4412 .inline-comments div.rst-block {
4412 clear:both;
4413 clear:both;
4413 overflow:hidden;
4414 overflow:hidden;
4414 margin:0;
4415 margin:0;
4415 padding:0 20px 0px;
4416 padding:0 20px 0px;
4416 }
4417 }
4417 .inline-comments .comment {
4418 .inline-comments .comment {
4418 border: 1px solid #ddd;
4419 border: 1px solid #ddd;
4419 -webkit-border-radius: 4px;
4420 -webkit-border-radius: 4px;
4420 -moz-border-radius: 4px;
4421 -moz-border-radius: 4px;
4421 border-radius: 4px;
4422 border-radius: 4px;
4422 margin: 3px 3px 5px 5px;
4423 margin: 3px 3px 5px 5px;
4423 background-color: #FAFAFA;
4424 background-color: #FAFAFA;
4424 }
4425 }
4425 .inline-comments .add-comment {
4426 .inline-comments .add-comment {
4426 padding: 2px 4px 8px 5px;
4427 padding: 2px 4px 8px 5px;
4427 }
4428 }
4428
4429
4429 .inline-comments .comment-wrapp{
4430 .inline-comments .comment-wrapp{
4430 padding:1px;
4431 padding:1px;
4431 }
4432 }
4432 .inline-comments .comment .meta {
4433 .inline-comments .comment .meta {
4433 background: #f8f8f8;
4434 background: #f8f8f8;
4434 padding: 4px;
4435 padding: 4px;
4435 border-bottom: 1px solid #ddd;
4436 border-bottom: 1px solid #ddd;
4436 height: 20px;
4437 height: 20px;
4437 }
4438 }
4438
4439
4439 .inline-comments .comment .meta img {
4440 .inline-comments .comment .meta img {
4440 vertical-align: middle;
4441 vertical-align: middle;
4441 }
4442 }
4442
4443
4443 .inline-comments .comment .meta .user {
4444 .inline-comments .comment .meta .user {
4444 font-weight: bold;
4445 font-weight: bold;
4445 float:left;
4446 float:left;
4446 padding: 3px;
4447 padding: 3px;
4447 }
4448 }
4448
4449
4449 .inline-comments .comment .meta .date {
4450 .inline-comments .comment .meta .date {
4450 float:left;
4451 float:left;
4451 padding: 3px;
4452 padding: 3px;
4452 }
4453 }
4453
4454
4454 .inline-comments .comment .text {
4455 .inline-comments .comment .text {
4455 background-color: #FAFAFA;
4456 background-color: #FAFAFA;
4456 }
4457 }
4457
4458
4458 .inline-comments .comments-number{
4459 .inline-comments .comments-number{
4459 padding:0px 0px 10px 0px;
4460 padding:0px 0px 10px 0px;
4460 font-weight: bold;
4461 font-weight: bold;
4461 color: #666;
4462 color: #666;
4462 font-size: 16px;
4463 font-size: 16px;
4463 }
4464 }
4464 .inline-comments-button .add-comment{
4465 .inline-comments-button .add-comment{
4465 margin:2px 0px 8px 5px !important
4466 margin:2px 0px 8px 5px !important
4466 }
4467 }
4467
4468
4468
4469
4469 .notification-paginator{
4470 .notification-paginator{
4470 padding: 0px 0px 4px 16px;
4471 padding: 0px 0px 4px 16px;
4471 float: left;
4472 float: left;
4472 }
4473 }
4473
4474
4474 .notifications{
4475 .notifications{
4475 border-radius: 4px 4px 4px 4px;
4476 border-radius: 4px 4px 4px 4px;
4476 -webkit-border-radius: 4px;
4477 -webkit-border-radius: 4px;
4477 -moz-border-radius: 4px;
4478 -moz-border-radius: 4px;
4478 float: right;
4479 float: right;
4479 margin: 20px 0px 0px 0px;
4480 margin: 20px 0px 0px 0px;
4480 position: absolute;
4481 position: absolute;
4481 text-align: center;
4482 text-align: center;
4482 width: 26px;
4483 width: 26px;
4483 z-index: 1000;
4484 z-index: 1000;
4484 }
4485 }
4485 .notifications a{
4486 .notifications a{
4486 color:#888 !important;
4487 color:#888 !important;
4487 display: block;
4488 display: block;
4488 font-size: 10px;
4489 font-size: 10px;
4489 background-color: #DEDEDE !important;
4490 background-color: #DEDEDE !important;
4490 border-radius: 2px !important;
4491 border-radius: 2px !important;
4491 -webkit-border-radius: 2px !important;
4492 -webkit-border-radius: 2px !important;
4492 -moz-border-radius: 2px !important;
4493 -moz-border-radius: 2px !important;
4493 }
4494 }
4494 .notifications a:hover{
4495 .notifications a:hover{
4495 text-decoration: none !important;
4496 text-decoration: none !important;
4496 background-color: #EEEFFF !important;
4497 background-color: #EEEFFF !important;
4497 }
4498 }
4498 .notification-header{
4499 .notification-header{
4499 padding-top:6px;
4500 padding-top:6px;
4500 }
4501 }
4501 .notification-header .desc{
4502 .notification-header .desc{
4502 font-size: 16px;
4503 font-size: 16px;
4503 height: 24px;
4504 height: 24px;
4504 float: left
4505 float: left
4505 }
4506 }
4506 .notification-list .container.unread{
4507 .notification-list .container.unread{
4507 background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
4508 background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6);
4508 }
4509 }
4509 .notification-header .gravatar{
4510 .notification-header .gravatar{
4510 background: none repeat scroll 0 0 transparent;
4511 background: none repeat scroll 0 0 transparent;
4511 padding: 0px 0px 0px 8px;
4512 padding: 0px 0px 0px 8px;
4512 }
4513 }
4513 .notification-list .container .notification-header .desc{
4514 .notification-list .container .notification-header .desc{
4514 font-weight: bold;
4515 font-weight: bold;
4515 font-size: 17px;
4516 font-size: 17px;
4516 }
4517 }
4517 .notification-table{
4518 .notification-table{
4518 border: 1px solid #ccc;
4519 border: 1px solid #ccc;
4519 -webkit-border-radius: 6px 6px 6px 6px;
4520 -webkit-border-radius: 6px 6px 6px 6px;
4520 -moz-border-radius: 6px 6px 6px 6px;
4521 -moz-border-radius: 6px 6px 6px 6px;
4521 border-radius: 6px 6px 6px 6px;
4522 border-radius: 6px 6px 6px 6px;
4522 clear: both;
4523 clear: both;
4523 margin: 0px 20px 0px 20px;
4524 margin: 0px 20px 0px 20px;
4524 }
4525 }
4525 .notification-header .delete-notifications{
4526 .notification-header .delete-notifications{
4526 float: right;
4527 float: right;
4527 padding-top: 8px;
4528 padding-top: 8px;
4528 cursor: pointer;
4529 cursor: pointer;
4529 }
4530 }
4530 .notification-header .read-notifications{
4531 .notification-header .read-notifications{
4531 float: right;
4532 float: right;
4532 padding-top: 8px;
4533 padding-top: 8px;
4533 cursor: pointer;
4534 cursor: pointer;
4534 }
4535 }
4535 .notification-subject{
4536 .notification-subject{
4536 clear:both;
4537 clear:both;
4537 border-bottom: 1px solid #eee;
4538 border-bottom: 1px solid #eee;
4538 padding:5px 0px 5px 38px;
4539 padding:5px 0px 5px 38px;
4539 }
4540 }
4540
4541
4541 .notification-body{
4542 .notification-body{
4542 clear:both;
4543 clear:both;
4543 margin: 34px 2px 2px 8px
4544 margin: 34px 2px 2px 8px
4544 }
4545 }
4545
4546
4546 /****
4547 /****
4547 PULL REQUESTS
4548 PULL REQUESTS
4548 *****/
4549 *****/
4549 .pullrequests_section_head {
4550 .pullrequests_section_head {
4550 padding:10px 10px 10px 0px;
4551 padding:10px 10px 10px 0px;
4551 font-size:16px;
4552 font-size:16px;
4552 font-weight: bold;
4553 font-weight: bold;
4553 }
4554 }
4554
4555
4555 /****
4556 /****
4556 PERMS
4557 PERMS
4557 *****/
4558 *****/
4558 #perms .perms_section_head {
4559 #perms .perms_section_head {
4559 padding:10px 10px 10px 0px;
4560 padding:10px 10px 10px 0px;
4560 font-size:16px;
4561 font-size:16px;
4561 font-weight: bold;
4562 font-weight: bold;
4562 }
4563 }
4563
4564
4564 #perms .perm_tag{
4565 #perms .perm_tag{
4565 padding: 1px 3px 1px 3px;
4566 padding: 1px 3px 1px 3px;
4566 font-size: 10px;
4567 font-size: 10px;
4567 font-weight: bold;
4568 font-weight: bold;
4568 text-transform: uppercase;
4569 text-transform: uppercase;
4569 white-space: nowrap;
4570 white-space: nowrap;
4570 -webkit-border-radius: 3px;
4571 -webkit-border-radius: 3px;
4571 -moz-border-radius: 3px;
4572 -moz-border-radius: 3px;
4572 border-radius: 3px;
4573 border-radius: 3px;
4573 }
4574 }
4574
4575
4575 #perms .perm_tag.admin{
4576 #perms .perm_tag.admin{
4576 background-color: #B94A48;
4577 background-color: #B94A48;
4577 color: #ffffff;
4578 color: #ffffff;
4578 }
4579 }
4579
4580
4580 #perms .perm_tag.write{
4581 #perms .perm_tag.write{
4581 background-color: #B94A48;
4582 background-color: #B94A48;
4582 color: #ffffff;
4583 color: #ffffff;
4583 }
4584 }
4584
4585
4585 #perms .perm_tag.read{
4586 #perms .perm_tag.read{
4586 background-color: #468847;
4587 background-color: #468847;
4587 color: #ffffff;
4588 color: #ffffff;
4588 }
4589 }
4589
4590
4590 #perms .perm_tag.none{
4591 #perms .perm_tag.none{
4591 background-color: #bfbfbf;
4592 background-color: #bfbfbf;
4592 color: #ffffff;
4593 color: #ffffff;
4593 }
4594 }
4594
4595
4595 .perm-gravatar{
4596 .perm-gravatar{
4596 vertical-align:middle;
4597 vertical-align:middle;
4597 padding:2px;
4598 padding:2px;
4598 }
4599 }
4599 .perm-gravatar-ac{
4600 .perm-gravatar-ac{
4600 vertical-align:middle;
4601 vertical-align:middle;
4601 padding:2px;
4602 padding:2px;
4602 width: 14px;
4603 width: 14px;
4603 height: 14px;
4604 height: 14px;
4604 }
4605 }
4605
4606
4606 /*****************************************************************************
4607 /*****************************************************************************
4607 DIFFS CSS
4608 DIFFS CSS
4608 ******************************************************************************/
4609 ******************************************************************************/
4609
4610
4610 div.diffblock {
4611 div.diffblock {
4611 overflow: auto;
4612 overflow: auto;
4612 padding: 0px;
4613 padding: 0px;
4613 border: 1px solid #ccc;
4614 border: 1px solid #ccc;
4614 background: #f8f8f8;
4615 background: #f8f8f8;
4615 font-size: 100%;
4616 font-size: 100%;
4616 line-height: 100%;
4617 line-height: 100%;
4617 /* new */
4618 /* new */
4618 line-height: 125%;
4619 line-height: 125%;
4619 -webkit-border-radius: 6px 6px 0px 0px;
4620 -webkit-border-radius: 6px 6px 0px 0px;
4620 -moz-border-radius: 6px 6px 0px 0px;
4621 -moz-border-radius: 6px 6px 0px 0px;
4621 border-radius: 6px 6px 0px 0px;
4622 border-radius: 6px 6px 0px 0px;
4622 }
4623 }
4623 div.diffblock.margined{
4624 div.diffblock.margined{
4624 margin: 0px 20px 0px 20px;
4625 margin: 0px 20px 0px 20px;
4625 }
4626 }
4626 div.diffblock .code-header{
4627 div.diffblock .code-header{
4627 border-bottom: 1px solid #CCCCCC;
4628 border-bottom: 1px solid #CCCCCC;
4628 background: #EEEEEE;
4629 background: #EEEEEE;
4629 padding:10px 0 10px 0;
4630 padding:10px 0 10px 0;
4630 height: 14px;
4631 height: 14px;
4631 }
4632 }
4632 div.diffblock .code-header.cv{
4633 div.diffblock .code-header.cv{
4633 height: 34px;
4634 height: 34px;
4634 }
4635 }
4635 div.diffblock .code-header-title{
4636 div.diffblock .code-header-title{
4636 padding: 0px 0px 10px 5px !important;
4637 padding: 0px 0px 10px 5px !important;
4637 margin: 0 !important;
4638 margin: 0 !important;
4638 }
4639 }
4639 div.diffblock .code-header .hash{
4640 div.diffblock .code-header .hash{
4640 float: left;
4641 float: left;
4641 padding: 2px 0 0 2px;
4642 padding: 2px 0 0 2px;
4642 }
4643 }
4643 div.diffblock .code-header .date{
4644 div.diffblock .code-header .date{
4644 float:left;
4645 float:left;
4645 text-transform: uppercase;
4646 text-transform: uppercase;
4646 padding: 2px 0px 0px 2px;
4647 padding: 2px 0px 0px 2px;
4647 }
4648 }
4648 div.diffblock .code-header div{
4649 div.diffblock .code-header div{
4649 margin-left:4px;
4650 margin-left:4px;
4650 font-weight: bold;
4651 font-weight: bold;
4651 font-size: 14px;
4652 font-size: 14px;
4652 }
4653 }
4653 div.diffblock .code-body{
4654 div.diffblock .code-body{
4654 background: #FFFFFF;
4655 background: #FFFFFF;
4655 }
4656 }
4656 div.diffblock pre.raw{
4657 div.diffblock pre.raw{
4657 background: #FFFFFF;
4658 background: #FFFFFF;
4658 color:#000000;
4659 color:#000000;
4659 }
4660 }
4660 table.code-difftable{
4661 table.code-difftable{
4661 border-collapse: collapse;
4662 border-collapse: collapse;
4662 width: 99%;
4663 width: 99%;
4663 }
4664 }
4664 table.code-difftable td {
4665 table.code-difftable td {
4665 padding: 0 !important;
4666 padding: 0 !important;
4666 background: none !important;
4667 background: none !important;
4667 border:0 !important;
4668 border:0 !important;
4668 vertical-align: none !important;
4669 vertical-align: none !important;
4669 }
4670 }
4670 table.code-difftable .context{
4671 table.code-difftable .context{
4671 background:none repeat scroll 0 0 #DDE7EF;
4672 background:none repeat scroll 0 0 #DDE7EF;
4672 }
4673 }
4673 table.code-difftable .add{
4674 table.code-difftable .add{
4674 background:none repeat scroll 0 0 #DDFFDD;
4675 background:none repeat scroll 0 0 #DDFFDD;
4675 }
4676 }
4676 table.code-difftable .add ins{
4677 table.code-difftable .add ins{
4677 background:none repeat scroll 0 0 #AAFFAA;
4678 background:none repeat scroll 0 0 #AAFFAA;
4678 text-decoration:none;
4679 text-decoration:none;
4679 }
4680 }
4680 table.code-difftable .del{
4681 table.code-difftable .del{
4681 background:none repeat scroll 0 0 #FFDDDD;
4682 background:none repeat scroll 0 0 #FFDDDD;
4682 }
4683 }
4683 table.code-difftable .del del{
4684 table.code-difftable .del del{
4684 background:none repeat scroll 0 0 #FFAAAA;
4685 background:none repeat scroll 0 0 #FFAAAA;
4685 text-decoration:none;
4686 text-decoration:none;
4686 }
4687 }
4687
4688
4688 /** LINE NUMBERS **/
4689 /** LINE NUMBERS **/
4689 table.code-difftable .lineno{
4690 table.code-difftable .lineno{
4690
4691
4691 padding-left:2px;
4692 padding-left:2px;
4692 padding-right:2px;
4693 padding-right:2px;
4693 text-align:right;
4694 text-align:right;
4694 width:32px;
4695 width:32px;
4695 -moz-user-select:none;
4696 -moz-user-select:none;
4696 -webkit-user-select: none;
4697 -webkit-user-select: none;
4697 border-right: 1px solid #CCC !important;
4698 border-right: 1px solid #CCC !important;
4698 border-left: 0px solid #CCC !important;
4699 border-left: 0px solid #CCC !important;
4699 border-top: 0px solid #CCC !important;
4700 border-top: 0px solid #CCC !important;
4700 border-bottom: none !important;
4701 border-bottom: none !important;
4701 vertical-align: middle !important;
4702 vertical-align: middle !important;
4702
4703
4703 }
4704 }
4704 table.code-difftable .lineno.new {
4705 table.code-difftable .lineno.new {
4705 }
4706 }
4706 table.code-difftable .lineno.old {
4707 table.code-difftable .lineno.old {
4707 }
4708 }
4708 table.code-difftable .lineno a{
4709 table.code-difftable .lineno a{
4709 color:#747474 !important;
4710 color:#747474 !important;
4710 font:11px "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace !important;
4711 font:11px "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace !important;
4711 letter-spacing:-1px;
4712 letter-spacing:-1px;
4712 text-align:right;
4713 text-align:right;
4713 padding-right: 2px;
4714 padding-right: 2px;
4714 cursor: pointer;
4715 cursor: pointer;
4715 display: block;
4716 display: block;
4716 width: 32px;
4717 width: 32px;
4717 }
4718 }
4718
4719
4719 table.code-difftable .lineno-inline{
4720 table.code-difftable .lineno-inline{
4720 background:none repeat scroll 0 0 #FFF !important;
4721 background:none repeat scroll 0 0 #FFF !important;
4721 padding-left:2px;
4722 padding-left:2px;
4722 padding-right:2px;
4723 padding-right:2px;
4723 text-align:right;
4724 text-align:right;
4724 width:30px;
4725 width:30px;
4725 -moz-user-select:none;
4726 -moz-user-select:none;
4726 -webkit-user-select: none;
4727 -webkit-user-select: none;
4727 }
4728 }
4728
4729
4729 /** CODE **/
4730 /** CODE **/
4730 table.code-difftable .code {
4731 table.code-difftable .code {
4731 display: block;
4732 display: block;
4732 width: 100%;
4733 width: 100%;
4733 }
4734 }
4734 table.code-difftable .code td{
4735 table.code-difftable .code td{
4735 margin:0;
4736 margin:0;
4736 padding:0;
4737 padding:0;
4737 }
4738 }
4738 table.code-difftable .code pre{
4739 table.code-difftable .code pre{
4739 margin:0;
4740 margin:0;
4740 padding:0;
4741 padding:0;
4741 height: 17px;
4742 height: 17px;
4742 line-height: 17px;
4743 line-height: 17px;
4743 }
4744 }
4744
4745
4745
4746
4746 .diffblock.margined.comm .line .code:hover{
4747 .diffblock.margined.comm .line .code:hover{
4747 background-color:#FFFFCC !important;
4748 background-color:#FFFFCC !important;
4748 cursor: pointer !important;
4749 cursor: pointer !important;
4749 background-image:url("../images/icons/comment_add.png") !important;
4750 background-image:url("../images/icons/comment_add.png") !important;
4750 background-repeat:no-repeat !important;
4751 background-repeat:no-repeat !important;
4751 background-position: right !important;
4752 background-position: right !important;
4752 background-position: 0% 50% !important;
4753 background-position: 0% 50% !important;
4753 }
4754 }
4754 .diffblock.margined.comm .line .code.no-comment:hover{
4755 .diffblock.margined.comm .line .code.no-comment:hover{
4755 background-image: none !important;
4756 background-image: none !important;
4756 cursor: auto !important;
4757 cursor: auto !important;
4757 background-color: inherit !important;
4758 background-color: inherit !important;
4758
4759
4759 }
4760 }
@@ -1,282 +1,291 b''
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <%inherit file="/base/base.html"/>
2 <%inherit file="/base/base.html"/>
3
3
4 <%def name="title()">
4 <%def name="title()">
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
5 ${_('Edit repository')} ${c.repo_info.repo_name} - ${c.rhodecode_name}
6 </%def>
6 </%def>
7
7
8 <%def name="breadcrumbs_links()">
8 <%def name="breadcrumbs_links()">
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
9 ${h.link_to(_('Admin'),h.url('admin_home'))}
10 &raquo;
10 &raquo;
11 ${h.link_to(_('Repositories'),h.url('repos'))}
11 ${h.link_to(_('Repositories'),h.url('repos'))}
12 &raquo;
12 &raquo;
13 ${_('edit')} &raquo; ${h.link_to(c.repo_info.just_name,h.url('summary_home',repo_name=c.repo_name))}
13 ${_('edit')} &raquo; ${h.link_to(c.repo_info.just_name,h.url('summary_home',repo_name=c.repo_name))}
14 </%def>
14 </%def>
15
15
16 <%def name="page_nav()">
16 <%def name="page_nav()">
17 ${self.menu('admin')}
17 ${self.menu('admin')}
18 </%def>
18 </%def>
19
19
20 <%def name="main()">
20 <%def name="main()">
21 <div class="box box-left">
21 <div class="box box-left">
22 <!-- box / title -->
22 <!-- box / title -->
23 <div class="title">
23 <div class="title">
24 ${self.breadcrumbs()}
24 ${self.breadcrumbs()}
25 </div>
25 </div>
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
26 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='put')}
27 <div class="form">
27 <div class="form">
28 <!-- fields -->
28 <!-- fields -->
29 <div class="fields">
29 <div class="fields">
30 <div class="field">
30 <div class="field">
31 <div class="label">
31 <div class="label">
32 <label for="repo_name">${_('Name')}:</label>
32 <label for="repo_name">${_('Name')}:</label>
33 </div>
33 </div>
34 <div class="input">
34 <div class="input">
35 ${h.text('repo_name',class_="medium")}
35 ${h.text('repo_name',class_="medium")}
36 </div>
36 </div>
37 </div>
37 </div>
38 <div class="field">
38 <div class="field">
39 <div class="label">
39 <div class="label">
40 <label for="clone_uri">${_('Clone uri')}:</label>
40 <label for="clone_uri">${_('Clone uri')}:</label>
41 </div>
41 </div>
42 <div class="input">
42 <div class="input">
43 ${h.text('clone_uri',class_="medium")}
43 ${h.text('clone_uri',class_="medium")}
44 <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span>
44 <span class="help-block">${_('Optional http[s] url from which repository should be cloned.')}</span>
45 </div>
45 </div>
46 </div>
46 </div>
47 <div class="field">
47 <div class="field">
48 <div class="label">
48 <div class="label">
49 <label for="repo_group">${_('Repository group')}:</label>
49 <label for="repo_group">${_('Repository group')}:</label>
50 </div>
50 </div>
51 <div class="input">
51 <div class="input">
52 ${h.select('repo_group','',c.repo_groups,class_="medium")}
52 ${h.select('repo_group','',c.repo_groups,class_="medium")}
53 <span class="help-block">${_('Optional select a group to put this repository into.')}</span>
53 <span class="help-block">${_('Optional select a group to put this repository into.')}</span>
54 </div>
54 </div>
55 </div>
55 </div>
56 <div class="field">
56 <div class="field">
57 <div class="label">
57 <div class="label">
58 <label for="repo_type">${_('Type')}:</label>
58 <label for="repo_type">${_('Type')}:</label>
59 </div>
59 </div>
60 <div class="input">
60 <div class="input">
61 ${h.select('repo_type','hg',c.backends,class_="medium")}
61 ${h.select('repo_type','hg',c.backends,class_="medium")}
62 </div>
62 </div>
63 </div>
63 </div>
64 <div class="field">
64 <div class="field">
65 <div class="label">
65 <div class="label">
66 <label for="landing_rev">${_('Landing revision')}:</label>
66 <label for="landing_rev">${_('Landing revision')}:</label>
67 </div>
67 </div>
68 <div class="input">
68 <div class="input">
69 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
69 ${h.select('landing_rev','',c.landing_revs,class_="medium")}
70 <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span>
70 <span class="help-block">${_('Default revision for files page, downloads, whoosh and readme')}</span>
71 </div>
71 </div>
72 </div>
72 </div>
73 <div class="field">
73 <div class="field">
74 <div class="label label-textarea">
74 <div class="label label-textarea">
75 <label for="description">${_('Description')}:</label>
75 <label for="description">${_('Description')}:</label>
76 </div>
76 </div>
77 <div class="textarea text-area editor">
77 <div class="textarea text-area editor">
78 ${h.textarea('description')}
78 ${h.textarea('description')}
79 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
79 <span class="help-block">${_('Keep it short and to the point. Use a README file for longer descriptions.')}</span>
80 </div>
80 </div>
81 </div>
81 </div>
82
82
83 <div class="field">
83 <div class="field">
84 <div class="label label-checkbox">
84 <div class="label label-checkbox">
85 <label for="private">${_('Private repository')}:</label>
85 <label for="private">${_('Private repository')}:</label>
86 </div>
86 </div>
87 <div class="checkboxes">
87 <div class="checkboxes">
88 ${h.checkbox('private',value="True")}
88 ${h.checkbox('private',value="True")}
89 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
89 <span class="help-block">${_('Private repositories are only visible to people explicitly added as collaborators.')}</span>
90 </div>
90 </div>
91 </div>
91 </div>
92 <div class="field">
92 <div class="field">
93 <div class="label label-checkbox">
93 <div class="label label-checkbox">
94 <label for="enable_statistics">${_('Enable statistics')}:</label>
94 <label for="enable_statistics">${_('Enable statistics')}:</label>
95 </div>
95 </div>
96 <div class="checkboxes">
96 <div class="checkboxes">
97 ${h.checkbox('enable_statistics',value="True")}
97 ${h.checkbox('enable_statistics',value="True")}
98 <span class="help-block">${_('Enable statistics window on summary page.')}</span>
98 <span class="help-block">${_('Enable statistics window on summary page.')}</span>
99 </div>
99 </div>
100 </div>
100 </div>
101 <div class="field">
101 <div class="field">
102 <div class="label label-checkbox">
102 <div class="label label-checkbox">
103 <label for="enable_downloads">${_('Enable downloads')}:</label>
103 <label for="enable_downloads">${_('Enable downloads')}:</label>
104 </div>
104 </div>
105 <div class="checkboxes">
105 <div class="checkboxes">
106 ${h.checkbox('enable_downloads',value="True")}
106 ${h.checkbox('enable_downloads',value="True")}
107 <span class="help-block">${_('Enable download menu on summary page.')}</span>
107 <span class="help-block">${_('Enable download menu on summary page.')}</span>
108 </div>
108 </div>
109 </div>
109 </div>
110 <div class="field">
110 <div class="field">
111 <div class="label label-checkbox">
111 <div class="label label-checkbox">
112 <label for="enable_locking">${_('Enable locking')}:</label>
112 <label for="enable_locking">${_('Enable locking')}:</label>
113 </div>
113 </div>
114 <div class="checkboxes">
114 <div class="checkboxes">
115 ${h.checkbox('enable_locking',value="True")}
115 ${h.checkbox('enable_locking',value="True")}
116 <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span>
116 <span class="help-block">${_('Enable lock-by-pulling on repository.')}</span>
117 </div>
117 </div>
118 </div>
118 </div>
119 <div class="field">
119 <div class="field">
120 <div class="label">
120 <div class="label">
121 <label for="user">${_('Owner')}:</label>
121 <label for="user">${_('Owner')}:</label>
122 </div>
122 </div>
123 <div class="input input-medium ac">
123 <div class="input input-medium ac">
124 <div class="perm_ac">
124 <div class="perm_ac">
125 ${h.text('user',class_='yui-ac-input')}
125 ${h.text('user',class_='yui-ac-input')}
126 <span class="help-block">${_('Change owner of this repository.')}</span>
126 <span class="help-block">${_('Change owner of this repository.')}</span>
127 <div id="owner_container"></div>
127 <div id="owner_container"></div>
128 </div>
128 </div>
129 </div>
129 </div>
130 </div>
130 </div>
131
131
132 <div class="field">
132 <div class="field">
133 <div class="label">
133 <div class="label">
134 <label for="input">${_('Permissions')}:</label>
134 <label for="input">${_('Permissions')}:</label>
135 </div>
135 </div>
136 <div class="input">
136 <div class="input">
137 <%include file="repo_edit_perms.html"/>
137 <%include file="repo_edit_perms.html"/>
138 </div>
138 </div>
139
139
140 <div class="buttons">
140 <div class="buttons">
141 ${h.submit('save',_('Save'),class_="ui-btn large")}
141 ${h.submit('save',_('Save'),class_="ui-btn large")}
142 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
142 ${h.reset('reset',_('Reset'),class_="ui-btn large")}
143 </div>
143 </div>
144 </div>
144 </div>
145 </div>
145 </div>
146 </div>
146 </div>
147 ${h.end_form()}
147 ${h.end_form()}
148 </div>
148 </div>
149
149
150 <div class="box box-right">
150 <div class="box box-right">
151 <div class="title">
151 <div class="title">
152 <h5>${_('Administration')}</h5>
152 <h5>${_('Administration')}</h5>
153 </div>
153 </div>
154
154
155 <h3>${_('Statistics')}</h3>
155 <h3>${_('Statistics')}</h3>
156 ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
156 ${h.form(url('repo_stats', repo_name=c.repo_info.repo_name),method='delete')}
157 <div class="form">
157 <div class="form">
158 <div class="fields">
158 <div class="fields">
159 ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="ui-btn",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")}
159 ${h.submit('reset_stats_%s' % c.repo_info.repo_name,_('Reset current statistics'),class_="ui-btn",onclick="return confirm('"+_('Confirm to remove current statistics')+"');")}
160 <div class="field" style="border:none;color:#888">
160 <div class="field" style="border:none;color:#888">
161 <ul>
161 <ul>
162 <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
162 <li>${_('Fetched to rev')}: ${c.stats_revision}/${c.repo_last_rev}</li>
163 <li>${_('Stats gathered')}: ${c.stats_percentage}%</li>
163 <li>${_('Stats gathered')}: ${c.stats_percentage}%</li>
164 </ul>
164 </ul>
165 </div>
165 </div>
166 </div>
166 </div>
167 </div>
167 </div>
168 ${h.end_form()}
168 ${h.end_form()}
169
169
170 %if c.repo_info.clone_uri:
170 %if c.repo_info.clone_uri:
171 <h3>${_('Remote')}</h3>
171 <h3>${_('Remote')}</h3>
172 ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')}
172 ${h.form(url('repo_pull', repo_name=c.repo_info.repo_name),method='put')}
173 <div class="form">
173 <div class="form">
174 <div class="fields">
174 <div class="fields">
175 ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="ui-btn",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
175 ${h.submit('remote_pull_%s' % c.repo_info.repo_name,_('Pull changes from remote location'),class_="ui-btn",onclick="return confirm('"+_('Confirm to pull changes from remote side')+"');")}
176 <div class="field" style="border:none">
176 <div class="field" style="border:none">
177 <ul>
177 <ul>
178 <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li>
178 <li><a href="${c.repo_info.clone_uri}">${c.repo_info.clone_uri}</a></li>
179 </ul>
179 </ul>
180 </div>
180 </div>
181 </div>
181 </div>
182 </div>
182 </div>
183 ${h.end_form()}
183 ${h.end_form()}
184 %endif
184 %endif
185
185
186 <h3>${_('Cache')}</h3>
186 <h3>${_('Cache')}</h3>
187 ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
187 ${h.form(url('repo_cache', repo_name=c.repo_info.repo_name),method='delete')}
188 <div class="form">
188 <div class="form">
189 <div class="fields">
189 <div class="fields">
190 ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="ui-btn",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")}
190 ${h.submit('reset_cache_%s' % c.repo_info.repo_name,_('Invalidate repository cache'),class_="ui-btn",onclick="return confirm('"+_('Confirm to invalidate repository cache')+"');")}
191 <div class="field" style="border:none;color:#888">
191 <div class="field" style="border:none;color:#888">
192 <ul>
192 <ul>
193 <li>${_('Manually invalidate cache for this repository. On first access repository will be cached again')}
193 <li>${_('Manually invalidate cache for this repository. On first access repository will be cached again')}
194 </li>
194 </li>
195 </ul>
195 </ul>
196 </div>
196 </div>
197 <div class="field" style="border:none;">
197 <div class="field" style="border:none;">
198 ${_('List of cached values')}
198 ${_('List of cached values')}
199 <ul>
199 <table>
200 <tr>
201 <th>${_('Prefix')}</th>
202 <th>${_('Key')}</th>
203 <th>${_('Active')}</th>
204 </tr>
200 %for cache in c.repo_info.cache_keys:
205 %for cache in c.repo_info.cache_keys:
201 <li>INSTANCE ID:${cache.prefix or '-'} ${cache.cache_args} CACHED: ${h.bool2icon(cache.cache_active)}</li>
206 <tr>
207 <td>${cache.prefix or '-'}</td>
208 <td>${cache.cache_key}</td>
209 <td>${h.bool2icon(cache.cache_active)}</td>
210 </tr>
202 %endfor
211 %endfor
203 </ul>
212 </table>
204 </div>
213 </div>
205 </div>
214 </div>
206 </div>
215 </div>
207 ${h.end_form()}
216 ${h.end_form()}
208
217
209 <h3>${_('Public journal')}</h3>
218 <h3>${_('Public journal')}</h3>
210 ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
219 ${h.form(url('repo_public_journal', repo_name=c.repo_info.repo_name),method='put')}
211 <div class="form">
220 <div class="form">
212 ${h.hidden('auth_token',str(h.get_token()))}
221 ${h.hidden('auth_token',str(h.get_token()))}
213 <div class="field">
222 <div class="field">
214 %if c.in_public_journal:
223 %if c.in_public_journal:
215 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="ui-btn")}
224 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Remove from public journal'),class_="ui-btn")}
216 %else:
225 %else:
217 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="ui-btn")}
226 ${h.submit('set_public_%s' % c.repo_info.repo_name,_('Add to public journal'),class_="ui-btn")}
218 %endif
227 %endif
219 </div>
228 </div>
220 <div class="field" style="border:none;color:#888">
229 <div class="field" style="border:none;color:#888">
221 <ul>
230 <ul>
222 <li>${_('All actions made on this repository will be accessible to everyone in public journal')}
231 <li>${_('All actions made on this repository will be accessible to everyone in public journal')}
223 </li>
232 </li>
224 </ul>
233 </ul>
225 </div>
234 </div>
226 </div>
235 </div>
227 ${h.end_form()}
236 ${h.end_form()}
228
237
229 <h3>${_('Locking')}</h3>
238 <h3>${_('Locking')}</h3>
230 ${h.form(url('repo_locking', repo_name=c.repo_info.repo_name),method='put')}
239 ${h.form(url('repo_locking', repo_name=c.repo_info.repo_name),method='put')}
231 <div class="form">
240 <div class="form">
232 <div class="fields">
241 <div class="fields">
233 %if c.repo_info.locked[0]:
242 %if c.repo_info.locked[0]:
234 ${h.submit('set_unlock' ,_('Unlock locked repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to unlock repository')+"');")}
243 ${h.submit('set_unlock' ,_('Unlock locked repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to unlock repository')+"');")}
235 ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))}
244 ${'Locked by %s on %s' % (h.person_by_id(c.repo_info.locked[0]),h.fmt_date(h.time_to_datetime(c.repo_info.locked[1])))}
236 %else:
245 %else:
237 ${h.submit('set_lock',_('lock repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to lock repository')+"');")}
246 ${h.submit('set_lock',_('lock repo'),class_="ui-btn",onclick="return confirm('"+_('Confirm to lock repository')+"');")}
238 ${_('Repository is not locked')}
247 ${_('Repository is not locked')}
239 %endif
248 %endif
240 </div>
249 </div>
241 <div class="field" style="border:none;color:#888">
250 <div class="field" style="border:none;color:#888">
242 <ul>
251 <ul>
243 <li>${_('Force locking on repository. Works only when anonymous access is disabled')}
252 <li>${_('Force locking on repository. Works only when anonymous access is disabled')}
244 </li>
253 </li>
245 </ul>
254 </ul>
246 </div>
255 </div>
247 </div>
256 </div>
248 ${h.end_form()}
257 ${h.end_form()}
249
258
250 <h3>${_('Set as fork of')}</h3>
259 <h3>${_('Set as fork of')}</h3>
251 ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')}
260 ${h.form(url('repo_as_fork', repo_name=c.repo_info.repo_name),method='put')}
252 <div class="form">
261 <div class="form">
253 <div class="fields">
262 <div class="fields">
254 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
263 ${h.select('id_fork_of','',c.repos_list,class_="medium")}
255 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('set'),class_="ui-btn",)}
264 ${h.submit('set_as_fork_%s' % c.repo_info.repo_name,_('set'),class_="ui-btn",)}
256 </div>
265 </div>
257 <div class="field" style="border:none;color:#888">
266 <div class="field" style="border:none;color:#888">
258 <ul>
267 <ul>
259 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
268 <li>${_('''Manually set this repository as a fork of another from the list''')}</li>
260 </ul>
269 </ul>
261 </div>
270 </div>
262 </div>
271 </div>
263 ${h.end_form()}
272 ${h.end_form()}
264
273
265 <h3>${_('Delete')}</h3>
274 <h3>${_('Delete')}</h3>
266 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
275 ${h.form(url('repo', repo_name=c.repo_info.repo_name),method='delete')}
267 <div class="form">
276 <div class="form">
268 <div class="fields">
277 <div class="fields">
269 ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="ui-btn red",onclick="return confirm('"+_('Confirm to delete this repository')+"');")}
278 ${h.submit('remove_%s' % c.repo_info.repo_name,_('Remove this repository'),class_="ui-btn red",onclick="return confirm('"+_('Confirm to delete this repository')+"');")}
270 </div>
279 </div>
271 <div class="field" style="border:none;color:#888">
280 <div class="field" style="border:none;color:#888">
272 <ul>
281 <ul>
273 <li>${_('''This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems.
282 <li>${_('''This repository will be renamed in a special way in order to be unaccesible for RhodeCode and VCS systems.
274 If you need fully delete it from filesystem please do it manually''')}
283 If you need fully delete it from filesystem please do it manually''')}
275 </li>
284 </li>
276 </ul>
285 </ul>
277 </div>
286 </div>
278 </div>
287 </div>
279 ${h.end_form()}
288 ${h.end_form()}
280 </div>
289 </div>
281
290
282 </%def>
291 </%def>
General Comments 0
You need to be logged in to leave comments. Login now